From 8a52566fad9bc3fc6fa860b2497ee13d7d578a8c Mon Sep 17 00:00:00 2001 From: Dotta Date: Mon, 26 Oct 2026 17:48:02 -0500 Subject: [PATCH] Qualify bounded tool-connection activity reads Co-Authored-By: Paperclip --- doc/plans/2026-10-13-connection-api-parity.md | 9 +++++++++ maps/agent-access-map/app-permissions.md | 10 +++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/doc/plans/2026-10-13-connection-api-parity.md b/doc/plans/2026-10-13-connection-api-parity.md index 44e6da21823..76644564035 100644 --- a/doc/plans/2026-10-13-connection-api-parity.md +++ b/doc/plans/2026-10-13-connection-api-parity.md @@ -188,3 +188,12 @@ The review of `70b7c973c8` correctly identified that requiring a caller profile A further real-JWT regression found that the `authKind: none` shortcut could skip comparison of dedicated grant identities (`/tmp/parity-credential-kind-red.log`). Credential identity comparison now applies for every auth label. Both API-key and no-auth-labelled dedicated grants deny before provider invocation when their identities differ. The same responsible-user and target authority, approval, revocation, and rate checks remain in force. Implementation `52a87697f0` passed **81 API/OpenAPI tests** (54 assembled-server actual-auth scenarios plus 27 contracts) in fresh PostgreSQL `parity_review_33`, log `/tmp/parity-caller-grants-full-green.log`. The earlier profile-only version is superseded by this evidence; its failures and recovery remain above. Final server typecheck and build passed (`/tmp/parity-caller-grants-final-types.log`, `/tmp/parity-caller-grants-final-build.log`). The earlier 18-case focused run passed before adding the no-auth-label regression (`/tmp/parity-caller-grants-green.log`); the final full suite includes all 19 delegated-test cases. Google consent, GitHub UI, and Copilot code are unchanged by this correction. + + +### 2026-10-26: bounded tool-connection activity authorization + +Security review found that tool-connection activity repeated a full run capture per returned event, unlike the already corrected chat activity path. The actual run-JWT regression over 100 persisted events (half linked to an inaccessible private task) measured **100 capability decisions and 102 run captures** before the fix and failed (`/tmp/parity-tool-activity-red.log`). + +Implementation `e5b8070d2f` creates one management evaluator, shares decisions by task within the bounded page, and passes the current request's read context into each probe. The passing regression proves two capability decisions and at most two run captures, the same 50 visible events, no private event content, and a fresh 403 after revoking audit permission (`/tmp/parity-tool-activity-green.log`). No authority is cached across requests. + +**82 API/OpenAPI tests passed** in fresh PostgreSQL `parity_review_35`: 55 assembled-server actual-auth scenarios and 27 contracts (`/tmp/parity-tool-activity-full-green.log`). Server typecheck/build passed (`/tmp/parity-tool-activity-types.log`, `/tmp/parity-tool-activity-build.log`). The earlier red result is retained as the baseline; no full local sweep, live provider verification, or empirical model success claim is added. diff --git a/maps/agent-access-map/app-permissions.md b/maps/agent-access-map/app-permissions.md index 11f968fe22a..007bec9cb96 100644 --- a/maps/agent-access-map/app-permissions.md +++ b/maps/agent-access-map/app-permissions.md @@ -256,7 +256,7 @@ API: `present` — `POST /api/tool-connections/{connectionId}/test-calls`; JSON Agent access: `available` — agent REST and default native `search_api` / `call_api`. Policy: `tools:use`, responsible-user credential access and target-agent authority. Testing another agent also requires the caller’s full tool access decision (effective profiles, explicit grants, and action policies) and both principals to select the same credential identity, regardless of the connection’s auth label. Caller and target action policies apply before dispatch and after approval; either Ask first decision requires ordinary human approval. Shared rate buckets consume one slot per test. A successful yielded run may continue only while current user, agent, task, and grant authority remain valid. Evidence: `verified` — [assembled-server integration](../../server/src/__tests__/connection-management.integration.test.ts), actual bearer/session authentication, persisted PostgreSQL state, and deterministic local MCP/provider fixtures. -Verification: `passed` — 54-scenario fixture suite on a fresh isolated PostgreSQL database, including permitted policy/explicit grants without a caller profile, denied caller policies, dedicated credentials (including no-auth labels), caller-only approvals and rate limits, shared rates, private status reads, approved continuation, revocation, cancellation and replay. No live provider qualification. +Verification: `passed` — 55-scenario fixture suite on a fresh isolated PostgreSQL database, including permitted policy/explicit grants without a caller profile, denied caller policies, dedicated credentials (including no-auth labels), caller-only approvals and rate limits, shared rates, private status reads, approved continuation, revocation, cancellation and replay. No live provider qualification. Gaps: Provider fixtures do not qualify live provider setup or availability. ### `get-tool-connections-test-calls` @@ -493,7 +493,7 @@ Gaps: This individual operation has source review but no recorded HTTP verificat API: `present` — `GET /api/tool-connections/{connectionId}/activity`; JSON REST. Agent access: `available` — agent REST and default native `search_api` / `call_api`. -Policy: `tools:view_audit`; [shared management policy](../../doc/plans/2026-10-13-connection-api-parity.md#authorization-contract). Resolved resources and every affected target are checked; personal ownership remains the responsible user. -Evidence: `source-only` — [route](../../server/src/routes/tool-access.ts); reviewed in the working tree based on the source commit above. -Verification: `not-run` — individual operation not executed in this audit; shared authorization and representative family flows are exercised by the authenticated integration suite. Follow the route schema, inspect persistence/audit, and assert owner, scope and revoked-authority denial. -Gaps: This individual operation has source review but no recorded HTTP verification. Provider availability and live setup remain unqualified. +Policy: `tools:view_audit`, shared management authority, and linked-task visibility. Pages are capped at 100 events; each distinct task is authorized once and the request's run capture is reused. Decisions are not retained across requests. +Evidence: `verified` — [assembled-server integration](../../server/src/__tests__/connection-management.integration.test.ts), actual run JWT authentication and PostgreSQL event persistence. +Verification: `passed` — a 100-event page over two tasks returns its 50 visible events, with two capability decisions and at most two run captures (previously 100 and 102). Private events remain hidden; revoking audit permission makes the next request return 403. +Gaps: This internal audit-read proof does not qualify live provider setup or actions.