Add capability-gated tool registry and real project tool (#8) #27

Merged
lost-rob0t merged 12 commits from feature/issue-8-capability-tools into main 2026-08-12 11:37:48 +00:00
lost-rob0t commented 2026-08-12 11:33:04 +00:00 (Migrated from github.com)

Closes #8.

Capability boundary

  • add canonical capability terms for tools, context, models, graph, persistence, network, filesystem, process, MCP, and orchestration
  • normalize/deduplicate capability sets
  • add narrowing-only child capability derivation; requested child authority must be a strict subset/equal subset of the parent set
  • denied capability checks occur before handler invocation

Tool registry

  • add opaque in-process registry lifecycle
  • normalized tool schemas declare name, tool(Name) capability, argument schema, result schema, timeout, and output-byte ceiling
  • discovery returns schemas only, never trusted handlers
  • duplicate/unknown/stale registry conditions are structured
  • invocation validates authorization, arguments, timeout, result shape, and byte ceiling
  • per-call trace records tool name, authorization decision, status, output bytes, and elapsed time
  • call options may tighten but cannot widen registered limits

Typed-plan integration

  • tool_registry_runtime_tools/3 adapts trusted registered handlers into the existing closed typed-plan runtime
  • the plan validator still requires tool(Name) before execution
  • the registry independently rechecks capability at invocation time
  • successful plan tool values carry non-secret authorization/status metadata
  • plan transitions record tool(Name)

First real tool: project_read

  • read-only UTF-8 regular-file reader beneath one explicitly registered project root
  • rejects absolute paths, dot/parent traversal, backslash paths, NUL paths, and symlink components
  • bounds source file bytes, normalized output bytes, and wall time
  • grants only tool(project_read); no ambient filesystem/network/process authority

Deterministic coverage

Tests cover:

  • normalization/deduplication and narrowing/widening denial
  • registry/discovery without handler leakage
  • allowed real file read + authorization trace
  • denied handler call proving zero invocations
  • malformed arguments before handler execution
  • timeout
  • oversized output
  • root traversal rejection
  • typed-plan execution through the registry adapter
  • plan capability denial before a registered handler runs

The deterministic branch-head CI is green and statically loads both live plan definitions without credentials.

REAL OpenRouter integration

Trusted same-repository CI performs another actual OpenRouter inference using the production SWI provider. The routed model must produce a typed JSON plan selecting project_read; that plan then executes the actual registered file tool and verifies the fixture token.

Required live evidence is limited to non-secret fields such as provider/requested/selected model, HTTP 200, plan parsed, tool invoked, authorization allowed, status ok, file token seen, and transition count. Generated plan JSON, response text/reasoning, API keys, Authorization headers, and environment dumps are not intentionally logged.

Do not merge until deterministic CI and the REAL OpenRouter PR job are both green and the final credential/diff scan is clean.

Closes #8. ## Capability boundary - add canonical capability terms for tools, context, models, graph, persistence, network, filesystem, process, MCP, and orchestration - normalize/deduplicate capability sets - add narrowing-only child capability derivation; requested child authority must be a strict subset/equal subset of the parent set - denied capability checks occur before handler invocation ## Tool registry - add opaque in-process registry lifecycle - normalized tool schemas declare name, `tool(Name)` capability, argument schema, result schema, timeout, and output-byte ceiling - discovery returns schemas only, never trusted handlers - duplicate/unknown/stale registry conditions are structured - invocation validates authorization, arguments, timeout, result shape, and byte ceiling - per-call trace records tool name, authorization decision, status, output bytes, and elapsed time - call options may tighten but cannot widen registered limits ## Typed-plan integration - `tool_registry_runtime_tools/3` adapts trusted registered handlers into the existing closed typed-plan runtime - the plan validator still requires `tool(Name)` before execution - the registry independently rechecks capability at invocation time - successful plan tool values carry non-secret authorization/status metadata - plan transitions record `tool(Name)` ## First real tool: project_read - read-only UTF-8 regular-file reader beneath one explicitly registered project root - rejects absolute paths, dot/parent traversal, backslash paths, NUL paths, and symlink components - bounds source file bytes, normalized output bytes, and wall time - grants only `tool(project_read)`; no ambient filesystem/network/process authority ## Deterministic coverage Tests cover: - normalization/deduplication and narrowing/widening denial - registry/discovery without handler leakage - allowed real file read + authorization trace - denied handler call proving zero invocations - malformed arguments before handler execution - timeout - oversized output - root traversal rejection - typed-plan execution through the registry adapter - plan capability denial before a registered handler runs The deterministic branch-head CI is green and statically loads both live plan definitions without credentials. ## REAL OpenRouter integration Trusted same-repository CI performs another actual OpenRouter inference using the production SWI provider. The routed model must produce a typed JSON plan selecting `project_read`; that plan then executes the actual registered file tool and verifies the fixture token. Required live evidence is limited to non-secret fields such as provider/requested/selected model, HTTP 200, plan parsed, tool invoked, authorization allowed, status ok, file token seen, and transition count. Generated plan JSON, response text/reasoning, API keys, Authorization headers, and environment dumps are not intentionally logged. Do not merge until deterministic CI and the REAL OpenRouter PR job are both green and the final credential/diff scan is clean.
Sign in to join this conversation.
No description provided.