From 26edbe1717857ddc1136bb04399cf89d2aff3f2c Mon Sep 17 00:00:00 2001 From: Dotta Date: Mon, 26 Oct 2026 17:40:07 -0500 Subject: [PATCH] Document full caller tool authority and regression evidence Co-Authored-By: Paperclip --- doc/plans/2026-10-13-connection-api-parity.md | 9 +++++++++ maps/agent-access-map/app-permissions.md | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/doc/plans/2026-10-13-connection-api-parity.md b/doc/plans/2026-10-13-connection-api-parity.md index 54545f56b4c..44e6da21823 100644 --- a/doc/plans/2026-10-13-connection-api-parity.md +++ b/doc/plans/2026-10-13-connection-api-parity.md @@ -179,3 +179,12 @@ The implementation was rebased onto `a1f77821b9cd5c9c846fdf7a0fa5cc620ad2b6bb`. - **78 API/OpenAPI tests passed** in fresh PostgreSQL (`parity_review_31`): 51 assembled-server actual-auth scenarios and 27 API contracts. Log: `/tmp/parity-test-final-full.log`. Final server typecheck/build and map validation passed (`/tmp/parity-test-final-types.log`, `/tmp/parity-test-final-build.log`, `/tmp/parity-test-final-maps.log`). These replace the earlier 71-test snapshot; no full local test-sweep pass is claimed. - Companion review also found that token refresh advances `grant.updatedAt` and can erase a saved pending Google service selection. Both new component cases failed before the fix (`/tmp/parity-google-refresh-ui-red.log`). Successful direct/cloud consent now records additive `providerTenant.oauth.consentedAt` metadata; refresh preserves it. The picker compares the pending request against that consent timestamp, using grant creation for legacy metadata rather than treating refresh as new consent. - **10 focused Google/OAuth tests passed**: eight service-picker cases (including newer/older consent and refresh/legacy behavior) plus two real local-HTTP OAuth protocol cases proving that successful consent is timestamped and concurrent token refresh preserves it. Log: `/tmp/parity-google-refresh-green.log`. The protocol fixture uses its existing board actor injection and does not count as actual-auth agent evidence. JSON metadata is additive; normal migration generation validates that no SQL change is required. + + +### 2026-10-26: preserve policy and explicit-grant tool access + +The review of `70b7c973c8` correctly identified that requiring a caller profile rejects legitimate access through an allow policy or explicit scoped `tools:use` grant. Both actual run-JWT cases failed before the correction (`/tmp/parity-caller-grants-red.log`). The caller's full access decision remains intersected with the target's decision; the narrower profile-only precondition is removed. The negative case now uses a caller-specific Block policy with the target still permitted, proving that another target cannot bypass the caller's actual action restriction. Default broad `tools:use` remains governed by the ordinary evaluator rather than being reinterpreted by this API. + +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. diff --git a/maps/agent-access-map/app-permissions.md b/maps/agent-access-map/app-permissions.md index 889ffad2c2a..11f968fe22a 100644 --- a/maps/agent-access-map/app-permissions.md +++ b/maps/agent-access-map/app-permissions.md @@ -254,9 +254,9 @@ Gaps: This individual operation has source review but no recorded HTTP verificat API: `present` — `POST /api/tool-connections/{connectionId}/test-calls`; JSON REST. 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 effective profile to include the tool and both principals to select the same credential identity. 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. +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` — 51-scenario fixture suite on a fresh isolated PostgreSQL database, including denied caller profiles, dedicated credentials, caller-only approvals and rate limits, shared rates, private status reads, approved continuation, revocation, cancellation and replay. No live provider qualification. +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. Gaps: Provider fixtures do not qualify live provider setup or availability. ### `get-tool-connections-test-calls`