Skip to content

e2e: the profile layer refuses what it withholds, and what it withdrew - #236

Merged
dinstein merged 1 commit into
mainfrom
perm-e2e
Aug 7, 2026
Merged

e2e: the profile layer refuses what it withholds, and what it withdrew#236
dinstein merged 1 commit into
mainfrom
perm-e2e

Conversation

@dinstein

@dinstein dinstein commented Aug 7, 2026

Copy link
Copy Markdown
Owner

The call-side gap closed in #234 left two holes behind: profile tool allow
— one server's tools narrowed for one profile — still had no case that CALLED
what it withheld, and no verb that TAKES access away had one either.

Both matter for the same reason. Every layer intersects and none can widen, so
a narrowing that does not reach the execute path is not a smaller permission,
it is none at all worn as one — and a listing assertion cannot see the
difference. A revocation is where that is worst: it looks correct from every
angle an operator can see while the tool stays callable for anyone who kept
the name.

  • 1. profile tool allow refuses the call it withholds, and widening it gives the call back
  • 2. profile server rm and profile rm refuse the calls they withdrew, fail-closed

…ithdrew

Two holes were left after the gate-side cases landed. `profile tool allow` —
the third narrowing layer — still had no case that called what it withheld,
and no verb that takes access away had one at all: profile_test.go asserts
`profile server rm` and `profile rm` against tools/list, and its own comment
names the risk, that an rm which does not propagate is a tool the operator
believes they took away and did not.

The first case builds a fixture where only the profile can be the one
narrowing — no `server tool allow` exists and the downstream serves both
tools — then calls the withheld sibling and widens with --all. That widen is
the first anywhere in the suite for this layer; until now every profile tool
fixture only ever narrowed, which cannot be told from a server that never had
the tool.

The second revokes in two steps and asserts the gate each time: withdraw one
server from the profile, then delete the profile under the bound client. The
second step is the fail-closed rule at the execute path — a dangling binding
resolves to the empty set, and falling back to allow-all there would turn
deleting a narrowing profile into granting its client everything the profile
was keeping from it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@dinstein
dinstein merged commit b12c57b into main Aug 7, 2026
3 checks passed
@dinstein
dinstein deleted the perm-e2e branch August 7, 2026 09:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant