Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions internal/guard/app/server/policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,6 @@ func (p staticPolicyConfigProvider) ActivePolicyConfig(context.Context) (guardpo
return p.config, nil
}

func NewRiskPolicyProvider() RiskPolicyProvider {
return NewRiskPolicyProviderWithJudge(nil)
}

func NewRiskPolicyProviderWithJudge(localJudge judge.Judge) RiskPolicyProvider {
return NewRiskPolicyProviderWithOptions(RiskPolicyProviderOptions{
Judge: localJudge,
})
}

func NewRiskPolicyProviderWithOptions(opts RiskPolicyProviderOptions) RiskPolicyProvider {
configProvider := opts.PolicyConfigProvider
if configProvider == nil {
Expand Down
19 changes: 0 additions & 19 deletions internal/guard/app/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,21 +93,6 @@ func NewServerWithOptions(store *sqlite.Store, opts Options) (*Server, error) {
}), policyStore, opts)
}

// NewServerWithPolicy creates a Guard server with an injected policy provider.
// A nil interface uses the default local risk policy; callers must not pass a
// typed-nil provider because it still satisfies the PolicyProvider interface.
func NewServerWithPolicy(store *sqlite.Store, policy PolicyProvider) (*Server, error) {
policyStore, err := openPolicyStoreForSQLite(store)
if err != nil {
return nil, err
}
return NewServerWithPolicyConfig(store, policy, policyStore)
}

func NewServerWithPolicyConfig(store *sqlite.Store, policy PolicyProvider, policyStore *policyconfig.Store) (*Server, error) {
return NewServerWithPolicyConfigAndOptions(store, policy, policyStore, Options{})
}

func NewServerWithPolicyConfigAndOptions(store *sqlite.Store, policy PolicyProvider, policyStore *policyconfig.Store, opts Options) (*Server, error) {
if policyStore == nil {
var err error
Expand Down Expand Up @@ -461,10 +446,6 @@ func openPolicyStoreForSQLite(store *sqlite.Store) (*policyconfig.Store, error)
return policyconfig.Open(filepath.Dir(store.Path()))
}

func OpenDefaultServer(dbPath string) (*Server, func() error, error) {
return OpenDefaultServerWithOptions(dbPath, Options{})
}

func OpenDefaultServerWithOptions(dbPath string, opts Options) (*Server, func() error, error) {
store, err := sqlite.OpenStore(dbPath)
if err != nil {
Expand Down
12 changes: 8 additions & 4 deletions internal/guard/app/server/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,22 @@ func newTestServer(t *testing.T, store *sqlite.Store) *Server {

func newTestServerWithPolicy(t *testing.T, store *sqlite.Store, policy PolicyProvider) *Server {
t.Helper()
server, err := NewServerWithPolicy(store, policy)
policyStore, err := openPolicyStoreForSQLite(store)
if err != nil {
t.Fatalf("NewServerWithPolicy() error = %v", err)
t.Fatalf("openPolicyStoreForSQLite() error = %v", err)
}
server, err := NewServerWithPolicyConfigAndOptions(store, policy, policyStore, Options{})
if err != nil {
t.Fatalf("NewServerWithPolicyConfigAndOptions() error = %v", err)
}
return server
}

func newTestServerWithPolicyConfig(t *testing.T, store *sqlite.Store, policyStore *policyconfig.Store) *Server {
t.Helper()
server, err := NewServerWithPolicyConfig(store, NewRiskPolicyProvider(), policyStore)
server, err := NewServerWithPolicyConfigAndOptions(store, nil, policyStore, Options{})
if err != nil {
t.Fatalf("NewServerWithPolicyConfig() error = %v", err)
t.Fatalf("NewServerWithPolicyConfigAndOptions() error = %v", err)
}
return server
}
Expand Down
12 changes: 7 additions & 5 deletions internal/guard/store/sqlite/ledger.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ func ledgerCursor(actions []LedgerRecord) (*LedgerCursor, error) {
if updatedAtKey == "" || actionID == "" {
return nil, nil
}
updatedAt, err := parseLedgerTimestamp(updatedAtKey)
updatedAt, err := ParseLedgerTimestamp(updatedAtKey)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -309,7 +309,7 @@ func normalizeLedgerRecord(record LedgerRecord) {
}

func normalizeLedgerTimeValue(column, value string, fallback time.Time) any {
if parsed, err := parseLedgerTimestamp(value); err == nil {
if parsed, err := ParseLedgerTimestamp(value); err == nil {
return parsed.UTC().Format(time.RFC3339Nano)
}
if isRequiredLedgerTimeColumn(column) {
Expand All @@ -321,7 +321,7 @@ func normalizeLedgerTimeValue(column, value string, fallback time.Time) any {
func ledgerRecordFallbackTime(record LedgerRecord) time.Time {
for _, column := range []string{"updated_at", "created_at"} {
value, _ := record[column].(string)
if parsed, err := parseLedgerTimestamp(value); err == nil {
if parsed, err := ParseLedgerTimestamp(value); err == nil {
return parsed.UTC()
}
}
Expand All @@ -347,7 +347,9 @@ func isRequiredLedgerTimeColumn(column string) bool {
return column == "created_at" || column == "updated_at"
}

func parseLedgerTimestamp(value string) (time.Time, error) {
// ParseLedgerTimestamp accepts the RFC3339Nano timestamps we write today plus
// the legacy layouts that may still exist in SQLite rows or persisted cursors.
func ParseLedgerTimestamp(value string) (time.Time, error) {
if parsed, err := time.Parse(time.RFC3339Nano, value); err == nil {
return parsed, nil
}
Expand All @@ -370,7 +372,7 @@ func ledgerTimestampCursorKeyFromTime(value time.Time) string {

func ledgerTimestampCursorKeyFromValues(values ...string) string {
for _, value := range values {
parsed, err := parseLedgerTimestamp(value)
parsed, err := ParseLedgerTimestamp(value)
if err == nil {
return ledgerTimestampCursorKeyFromTime(parsed)
}
Expand Down
14 changes: 9 additions & 5 deletions internal/hook/domain.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package hook

import "strings"
import (
"strings"

"github.com/kontext-security/kontext-cli/internal/guard/decision"
)

type HookName string

Expand Down Expand Up @@ -30,13 +34,13 @@ func (h HookName) CanBlock() bool {
return h == HookPreToolUse
}

type Decision string

const (
DecisionAllow Decision = "allow"
DecisionDeny Decision = "deny"
DecisionAllow = decision.Allow
DecisionDeny = decision.Deny
)

type Decision = decision.Decision

func NormalizeDecision(value string) (Decision, bool) {
switch strings.ToLower(strings.TrimSpace(value)) {
case string(DecisionAllow):
Expand Down
19 changes: 1 addition & 18 deletions internal/managedstream/stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ func Flush(ctx context.Context, opts Options) error {

var updatedAfter *time.Time
if state.UpdatedAfter != "" {
parsed, err := parseStateUpdatedAfter(state.UpdatedAfter)
parsed, err := sqlite.ParseLedgerTimestamp(state.UpdatedAfter)
if err != nil {
return fmt.Errorf("parse managed stream state: %w", err)
}
Expand Down Expand Up @@ -325,23 +325,6 @@ func saveCursor(statePath string, batch sqlite.LedgerBatch) error {
})
}

func parseStateUpdatedAfter(value string) (time.Time, error) {
if parsed, err := time.Parse(time.RFC3339Nano, value); err == nil {
return parsed, nil
}
for _, layout := range []string{
"2006-01-02T15:04:05.999999999",
"2006-01-02T15:04:05",
"2006-01-02 15:04:05.999999999",
"2006-01-02 15:04:05",
} {
if parsed, err := time.Parse(layout, value); err == nil {
return parsed, nil
}
}
return time.Time{}, fmt.Errorf("invalid timestamp %q", value)
}

func responseBodySummary(body io.Reader) string {
data, err := io.ReadAll(io.LimitReader(body, maxErrorBodyBytes+1))
if err != nil {
Expand Down
6 changes: 3 additions & 3 deletions internal/managedstream/stream_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -447,12 +447,12 @@ func TestParseStateUpdatedAfterAcceptsLegacyTimestampFormats(t *testing.T) {
"2026-06-08T12:20:07.853885",
"2026-06-08 12:20:07.853885",
} {
parsed, err := parseStateUpdatedAfter(value)
parsed, err := sqlite.ParseLedgerTimestamp(value)
if err != nil {
t.Fatalf("parseStateUpdatedAfter(%q) error = %v", value, err)
t.Fatalf("ParseLedgerTimestamp(%q) error = %v", value, err)
}
if got := parsed.UTC().Format(time.RFC3339Nano); got != "2026-06-08T12:20:07.853885Z" {
t.Fatalf("parseStateUpdatedAfter(%q) = %q", value, got)
t.Fatalf("ParseLedgerTimestamp(%q) = %q", value, got)
}
}
}
Expand Down
5 changes: 0 additions & 5 deletions internal/run/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,6 @@ type Options struct {
Args []string
}

// Start preserves the historical managed-session entry point.
func Start(ctx context.Context, opts Options) error {
return StartManaged(ctx, opts)
}

// StartManaged launches an agent with a hosted managed Kontext session.
func StartManaged(ctx context.Context, opts Options) error {
diagnostics := diagnostic.New(os.Stderr, opts.Verbose || diagnostic.EnabledFromEnv())
Expand Down
Loading