Skip to content
Merged
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
3 changes: 3 additions & 0 deletions core/gate/approved_scripts.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,9 @@ func ReadApprovedScriptRegistry(path string) ([]schemagate.ApprovedScriptEntry,
var envelopeRaw map[string]json.RawMessage
if err := json.Unmarshal(content, &envelopeRaw); err == nil {
if rawEntries, ok := envelopeRaw["entries"]; ok {
if err := requireJSONArray(rawEntries, "entries"); err != nil {
return nil, fmt.Errorf("parse approved script registry: %w", err)
}
var envelope registryEnvelope
if err := json.Unmarshal(rawEntries, &envelope.Entries); err != nil {
return nil, fmt.Errorf("parse approved script registry: %w", err)
Expand Down
10 changes: 10 additions & 0 deletions core/gate/approved_scripts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,16 @@ func TestReadApprovedScriptRegistryVariants(t *testing.T) {
t.Fatalf("expected empty entries for empty envelope registry, got %#v", entries)
}

nullEnvelopePath := filepath.Join(t.TempDir(), "null_envelope.json")
if err := os.WriteFile(nullEnvelopePath, []byte(`{"entries":null}`), 0o600); err != nil {
t.Fatalf("write null envelope registry fixture: %v", err)
}
if _, err := ReadApprovedScriptRegistry(nullEnvelopePath); err == nil {
t.Fatalf("expected null entries envelope to fail")
} else if !strings.Contains(err.Error(), "entries must be an array") {
t.Fatalf("expected entries array validation error, got: %v", err)
}

nowUTC := time.Date(2026, time.February, 5, 0, 0, 0, 0, time.UTC)
legacyPath := filepath.Join(t.TempDir(), "legacy.json")
legacyJSON := []byte(`[
Expand Down
14 changes: 14 additions & 0 deletions core/gate/context_wrkr.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ func parseWrkrInventory(content []byte) (map[string]WrkrToolMetadata, error) {
var wrappedRaw map[string]json.RawMessage
if err := json.Unmarshal(content, &wrappedRaw); err == nil {
if rawItems, ok := wrappedRaw["items"]; ok {
if err := requireJSONArray(rawItems, "items"); err != nil {
return nil, fmt.Errorf("parse wrkr inventory: %w", err)
}
var wrapped envelope
if err := json.Unmarshal(rawItems, &wrapped.Items); err != nil {
return nil, fmt.Errorf("parse wrkr inventory: %w", err)
Expand Down Expand Up @@ -129,6 +132,17 @@ func parseWrkrInventory(content []byte) (map[string]WrkrToolMetadata, error) {
return tools, nil
}

func requireJSONArray(raw json.RawMessage, field string) error {
var parsed any
if err := json.Unmarshal(raw, &parsed); err != nil {
return err
}
if _, ok := parsed.([]any); !ok {
return fmt.Errorf("%s must be an array", field)
}
return nil
}

func ApplyWrkrContext(intent *schemagate.IntentRequest, toolName string, inventory map[string]WrkrToolMetadata) bool {
if intent == nil || len(inventory) == 0 {
return false
Expand Down
14 changes: 14 additions & 0 deletions core/gate/context_wrkr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,20 @@ func TestLoadWrkrInventoryAcceptsEmptyEnvelope(t *testing.T) {
}
}

func TestLoadWrkrInventoryRejectsNullItemsEnvelope(t *testing.T) {
workDir := t.TempDir()
path := filepath.Join(workDir, "wrkr_inventory.json")
mustWriteWrkrInventoryFile(t, path, `{"items":null}`)

_, err := LoadWrkrInventory(path)
if err == nil {
t.Fatalf("expected null items envelope to fail")
}
if !strings.Contains(err.Error(), "items must be an array") {
t.Fatalf("expected items array validation error, got: %v", err)
}
}

func TestApplyWrkrContextAddsMetadata(t *testing.T) {
intent := schemagate.IntentRequest{
Context: schemagate.IntentContext{},
Expand Down
Loading