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
122 changes: 60 additions & 62 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ graph LR
classDef done fill:#1f7a1f,stroke:#0d3d0d,color:#ffffff;
classDef in_progress fill:#1f6feb,stroke:#0b3d91,color:#ffffff;
classDef todo fill:#6e7781,stroke:#3d4248,color:#ffffff;
class sandbox_isolation,scanner_v2,analytics_dashboard,scanner_simplification,schema_deferred done;
class ux_audit,action_log_transparency,agent_scope_hardening,token_bench,telemetry_identity,telemetry_v7_churn in_progress;
class sandbox_isolation,scanner_v2,analytics_dashboard,scanner_simplification,schema_deferred,agent_scope_hardening done;
class ux_audit,action_log_transparency,token_bench,telemetry_identity,telemetry_v7_churn in_progress;
class tpa_db,remote_access_tunnel,auto_routing_mode,tool_graph todo;
```

Expand Down Expand Up @@ -206,65 +206,6 @@ graph LR

</details>

<details>
<summary>🔵 Agent-token scope hardening: every MCP request authorized by its own scope (spec 105) — In progress · P1</summary>

> The Spec 104 cross-model review verified 'an agent token sees and uses only its granted servers, profile and tiers' against the code one surface at a time and found eight places where a legitimately narrow token could learn about or act on servers outside its grant: cached responses, set_profile and profile-URL responses, retrieve_tools metadata, direct-publication filtering, target-tier execution, aggregated prompts, per-server management ops, and refusal shapes. Spec 105 is the acceptance contract (19 astra rounds, ready-for-plan 2026-09-07). Five fix sessions ran in parallel from the review and MERGED 2026-09-08 (#1223 target tier, #1224 tail_log, #1225 set_profile, #1226 read_cache provenance, #1227 prompt owner + deleted-pin enumeration), each live-verified against a baseline binary and astra-reviewed to CLEAN. Each of those PR bodies carries a 'Follow-ups / Spec 105 gaps' checklist — the todo tasks below are those lists grouped by FR. Prerequisite for auto-routing-mode: Spec 104 FR-016 states the invariant these corrections make true.

Spec: [105-agent-scope-hardening](./specs/105-agent-scope-hardening/)

```mermaid
graph LR
scope_fix_target_tier["FR-009 (dispatch half): call_tool_* requires…"]
scope_fix_tail_log["FR-007 (name half): upstream_servers tail_log…"]
scope_fix_set_profile["FR-003: set_profile reports token ∩ profile,…"]
scope_fix_read_cache["FR-001: cached responses carry the producer's…"]
scope_fix_prompts_profile_url["FR-006 + FR-004 (deleted pin): aggregated pro…"]
scope_retrieve_tools["FR-005: retrieve_tools filters by scope BEFOR…"]
scope_direct_publication["FR-008: direct-surface definitions take owner…"]
scope_refusal_shapes["FR-010: scope-first refusal precedence; dispa…"]
scope_selectable_profile_predicate["FR-003/FR-004 remainder: selectable-profile p…"]
scope_cache_legacy_invalidation["FR-002 + FR-001 remainder: legacy/unstamped a…"]
scope_log_attribution["FR-007 remainder: per-record canonical log ow…"]
scope_target_identity_producers["FR-009 remainder: producer-side exact-name id…"]
scope_fix_stored_script_admin["FR-012: stored-script enumeration is administ…"]
scope_regression_suite["FR-011/FR-013/FR-014: two-fixture differentia…"]

scope_retrieve_tools --> scope_refusal_shapes
scope_fix_set_profile --> scope_selectable_profile_predicate
scope_fix_prompts_profile_url --> scope_selectable_profile_predicate
scope_fix_read_cache --> scope_cache_legacy_invalidation
scope_fix_tail_log --> scope_log_attribution
scope_fix_target_tier --> scope_target_identity_producers
scope_retrieve_tools --> scope_regression_suite
scope_direct_publication --> scope_regression_suite
scope_refusal_shapes --> scope_regression_suite

classDef done fill:#1f7a1f,stroke:#0d3d0d,color:#ffffff;
classDef todo fill:#6e7781,stroke:#3d4248,color:#ffffff;
class scope_fix_target_tier,scope_fix_tail_log,scope_fix_set_profile,scope_fix_read_cache,scope_fix_prompts_profile_url,scope_retrieve_tools,scope_direct_publication,scope_refusal_shapes,scope_selectable_profile_predicate,scope_cache_legacy_invalidation,scope_log_attribution,scope_target_identity_producers,scope_fix_stored_script_admin done;
class scope_regression_suite todo;
```

| Task | Status | Refs |
| --- | --- | --- |
| FR-009 (dispatch half): call_tool_* requires the TARGET tool's tier, fail closed on unresolved tiers; approval records keep exact ns:name identity | 🟢 Done | #1223 |
| FR-007 (name half): upstream_servers tail_log authorizes the server against effective scope before lookup, non-disclosing | 🟢 Done | #1224 |
| FR-003: set_profile reports token ∩ profile, selectable-profile predicate, non-selectable == nonexistent | 🟢 Done | #1225 |
| FR-001: cached responses carry the producer's authorization snapshot; read_cache and the REST cache branch refuse narrower readers | 🟢 Done | #1226 |
| FR-006 + FR-004 (deleted pin): aggregated prompts authorized by canonical registration owner; profile URL / set_profile stop enumerating on a deleted pin | 🟢 Done | #1227 |
| FR-005: retrieve_tools filters by scope BEFORE limiting; indexed counts, usage ranking, debug output and session risk computed over the authorized population only | 🟢 Done | #1325 |
| FR-008: direct-surface definitions take owner and tier from their own registration identity at every publication seam, both skew directions, full and deferred | 🟢 Done | #1326 |
| FR-010: scope-first refusal precedence; dispatch denials and 'available servers' never name hidden servers; describe_tool not-found and alias resolution computed over the authorized corpus | 🟢 Done | #1328 |
| FR-003/FR-004 remainder: selectable-profile predicate for UNPINNED tokens on /mcp/p/<slug>, /mcp/p, /mcp/p/ and set_profile; identical status+body across missing / deleted / not-selectable / pin-mismatch / no-profiles (#1225 + #1227 follow-up lists) | 🟢 Done | #1283 |
| FR-002 + FR-001 remainder: legacy/unstamped and internal (registry, guesser) cache entries refused for every caller and durably invalidated; monotone recursive provenance; existence-non-disclosing refusal on MCP and REST (#1226 follow-up list) | 🟢 Done | #1282 |
| FR-007 remainder: per-record canonical log ownership (a/b vs a_b share one file), filter-before-limit + authorized lines_returned, subject-bound OAuth-callback logging, canonical container ownership in Docker cleanup (#1224 follow-up list) | 🟢 Done | #1284 |
| FR-009 remainder: producer-side exact-name identity (checkToolApprovals / differential index collapse ns:erase to erase), direct-name dispatch + preflight share lookupToolApproval, unresolved/stale identity refuses scoped callers, full 54-cell acceptance tables (#1223 follow-up list) | 🟢 Done | #1279 |
| FR-012: stored-script enumeration is administrator-only (PR H0) | 🟢 Done | #1285 |
| FR-011/FR-013/FR-014: two-fixture differential oracle with sentinels across the applicability matrix, credential-authenticated HTTP matrix over every /mcp surface, admin p95 perf gate on the frozen 527-tool snapshot | ⚪ Todo | — |

</details>

<details>
<summary>🔵 Token-efficiency benchmark: measured savings, published results — In progress · P1</summary>

Expand Down Expand Up @@ -827,6 +768,63 @@ Spec: [102-schema-deferred](./specs/102-schema-deferred/) · PR: #1063

</details>

<details>
<summary>🟢 Agent-token scope hardening: every MCP request authorized by its own scope (spec 105) — Done · P1</summary>

> The Spec 104 cross-model review verified 'an agent token sees and uses only its granted servers, profile and tiers' against the code one surface at a time and found eight places where a legitimately narrow token could learn about or act on servers outside its grant: cached responses, set_profile and profile-URL responses, retrieve_tools metadata, direct-publication filtering, target-tier execution, aggregated prompts, per-server management ops, and refusal shapes. Spec 105 is the acceptance contract (19 astra rounds, ready-for-plan 2026-09-07). Five fix sessions ran in parallel from the review and MERGED 2026-09-08 (#1223 target tier, #1224 tail_log, #1225 set_profile, #1226 read_cache provenance, #1227 prompt owner + deleted-pin enumeration), each live-verified against a baseline binary and astra-reviewed to CLEAN. Each of those PR bodies carries a 'Follow-ups / Spec 105 gaps' checklist — the todo tasks below are those lists grouped by FR. Prerequisite for auto-routing-mode: Spec 104 FR-016 states the invariant these corrections make true.

Spec: [105-agent-scope-hardening](./specs/105-agent-scope-hardening/)

```mermaid
graph LR
scope_fix_target_tier["FR-009 (dispatch half): call_tool_* requires…"]
scope_fix_tail_log["FR-007 (name half): upstream_servers tail_log…"]
scope_fix_set_profile["FR-003: set_profile reports token ∩ profile,…"]
scope_fix_read_cache["FR-001: cached responses carry the producer's…"]
scope_fix_prompts_profile_url["FR-006 + FR-004 (deleted pin): aggregated pro…"]
scope_retrieve_tools["FR-005: retrieve_tools filters by scope BEFOR…"]
scope_direct_publication["FR-008: direct-surface definitions take owner…"]
scope_refusal_shapes["FR-010: scope-first refusal precedence; dispa…"]
scope_selectable_profile_predicate["FR-003/FR-004 remainder: selectable-profile p…"]
scope_cache_legacy_invalidation["FR-002 + FR-001 remainder: legacy/unstamped a…"]
scope_log_attribution["FR-007 remainder: per-record canonical log ow…"]
scope_target_identity_producers["FR-009 remainder: producer-side exact-name id…"]
scope_fix_stored_script_admin["FR-012: stored-script enumeration is administ…"]
scope_regression_suite["FR-011/FR-013/FR-014: two-fixture differentia…"]

scope_retrieve_tools --> scope_refusal_shapes
scope_fix_set_profile --> scope_selectable_profile_predicate
scope_fix_prompts_profile_url --> scope_selectable_profile_predicate
scope_fix_read_cache --> scope_cache_legacy_invalidation
scope_fix_tail_log --> scope_log_attribution
scope_fix_target_tier --> scope_target_identity_producers
scope_retrieve_tools --> scope_regression_suite
scope_direct_publication --> scope_regression_suite
scope_refusal_shapes --> scope_regression_suite

classDef done fill:#1f7a1f,stroke:#0d3d0d,color:#ffffff;
class scope_fix_target_tier,scope_fix_tail_log,scope_fix_set_profile,scope_fix_read_cache,scope_fix_prompts_profile_url,scope_retrieve_tools,scope_direct_publication,scope_refusal_shapes,scope_selectable_profile_predicate,scope_cache_legacy_invalidation,scope_log_attribution,scope_target_identity_producers,scope_fix_stored_script_admin,scope_regression_suite done;
```

| Task | Status | Refs |
| --- | --- | --- |
| FR-009 (dispatch half): call_tool_* requires the TARGET tool's tier, fail closed on unresolved tiers; approval records keep exact ns:name identity | 🟢 Done | #1223 |
| FR-007 (name half): upstream_servers tail_log authorizes the server against effective scope before lookup, non-disclosing | 🟢 Done | #1224 |
| FR-003: set_profile reports token ∩ profile, selectable-profile predicate, non-selectable == nonexistent | 🟢 Done | #1225 |
| FR-001: cached responses carry the producer's authorization snapshot; read_cache and the REST cache branch refuse narrower readers | 🟢 Done | #1226 |
| FR-006 + FR-004 (deleted pin): aggregated prompts authorized by canonical registration owner; profile URL / set_profile stop enumerating on a deleted pin | 🟢 Done | #1227 |
| FR-005: retrieve_tools filters by scope BEFORE limiting; indexed counts, usage ranking, debug output and session risk computed over the authorized population only | 🟢 Done | #1325 |
| FR-008: direct-surface definitions take owner and tier from their own registration identity at every publication seam, both skew directions, full and deferred | 🟢 Done | #1326 |
| FR-010: scope-first refusal precedence; dispatch denials and 'available servers' never name hidden servers; describe_tool not-found and alias resolution computed over the authorized corpus | 🟢 Done | #1328 |
| FR-003/FR-004 remainder: selectable-profile predicate for UNPINNED tokens on /mcp/p/<slug>, /mcp/p, /mcp/p/ and set_profile; identical status+body across missing / deleted / not-selectable / pin-mismatch / no-profiles (#1225 + #1227 follow-up lists) | 🟢 Done | #1283 |
| FR-002 + FR-001 remainder: legacy/unstamped and internal (registry, guesser) cache entries refused for every caller and durably invalidated; monotone recursive provenance; existence-non-disclosing refusal on MCP and REST (#1226 follow-up list) | 🟢 Done | #1282 |
| FR-007 remainder: per-record canonical log ownership (a/b vs a_b share one file), filter-before-limit + authorized lines_returned, subject-bound OAuth-callback logging, canonical container ownership in Docker cleanup (#1224 follow-up list) | 🟢 Done | #1284 |
| FR-009 remainder: producer-side exact-name identity (checkToolApprovals / differential index collapse ns:erase to erase), direct-name dispatch + preflight share lookupToolApproval, unresolved/stale identity refuses scoped callers, full 54-cell acceptance tables (#1223 follow-up list) | 🟢 Done | #1279 |
| FR-012: stored-script enumeration is administrator-only (PR H0) | 🟢 Done | #1285 |
| FR-011/FR-013/FR-014: two-fixture differential oracle with sentinels across the applicability matrix, credential-authenticated HTTP matrix over every /mcp surface, admin p95 perf gate on the frozen 527-tool snapshot | 🟢 Done | #1332 |

</details>

<details>
<summary>🟢 Tray↔core decoupling: socket/REST API only, no config-file reads — Done · P2</summary>

Expand Down Expand Up @@ -888,7 +886,6 @@ graph LR
| Web UI + macOS app UX audit | In progress | P0 | — | | |
| Release qualification gate (auto-QA matrix blocks the tag) | In progress | P0 | — | [081-release-qa-gate](./specs/081-release-qa-gate/) | |
| Action log / transparency — info at a glance | In progress | P1 | — | | |
| Agent-token scope hardening: every MCP request authorized by its own scope (spec 105) | In progress | P1 | 94/113 (83%) | [105-agent-scope-hardening](./specs/105-agent-scope-hardening/) | |
| Token-efficiency benchmark: measured savings, published results | In progress | P1 | 62/64 (97%) | [103-token-bench](./specs/103-token-bench/) | |
| Telemetry identity & data quality (machine_id + CI-filter hardening) | In progress | P1 | — | | |
| Telemetry v7: honest funnel + churn instrumentation | In progress | P1 | — | [080-telemetry-v7-churn](./specs/080-telemetry-v7-churn/) | |
Expand All @@ -913,6 +910,7 @@ graph LR
| Registries — easier search + add-server | Done | P1 | 21/24 (88%) | [070-registry-easy-upstream-add](./specs/070-registry-easy-upstream-add/) | |
| Scanner simplification (deterministic default, opt-in deep scan) | Done | P1 | 38/42 (90%) | [077-scanner-simplification](./specs/077-scanner-simplification/) | |
| Deferred-schema serialization for the direct tools/list surface (spec 102) | Done | P1 | 89/89 (100%) | [102-schema-deferred](./specs/102-schema-deferred/) | #1063 |
| Agent-token scope hardening: every MCP request authorized by its own scope (spec 105) | Done | P1 | 94/113 (83%) | [105-agent-scope-hardening](./specs/105-agent-scope-hardening/) | |
| Tray↔core decoupling: socket/REST API only, no config-file reads | Done | P2 | — | | |
| Spec 107 server edition SSO front door hardened for real IdPs | Done | P2 | 126/126 (100%) | [107-server-edition-sso-hardening](./specs/107-server-edition-sso-hardening/) | |

Expand Down
5 changes: 3 additions & 2 deletions roadmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ epics:

- id: agent-scope-hardening
title: "Agent-token scope hardening: every MCP request authorized by its own scope (spec 105)"
status: in_progress
status: done
priority: P1
spec: specs/105-agent-scope-hardening
depends_on: [schema-deferred]
Expand Down Expand Up @@ -477,8 +477,9 @@ epics:
depends_on: []
- id: scope-regression-suite
title: "FR-011/FR-013/FR-014: two-fixture differential oracle with sentinels across the applicability matrix, credential-authenticated HTTP matrix over every /mcp surface, admin p95 perf gate on the frozen 527-tool snapshot"
status: todo
status: done
priority: P2
pr: "#1332"
depends_on: [scope-retrieve-tools, scope-direct-publication, scope-refusal-shapes]

- id: auto-routing-mode
Expand Down
Loading