Found out of scope by the review of #90; the defect is in the merged conditional controller ownership (#84, b22b225). Being fixed on fix/claim-authority.
What happens
controllerKeeper.Claim asks AttachmentPolicy with the context it is called with. The keeper runs inside the plane's splice, which is driven by the runner's dial-back request, and that context carries no user identity. A policy adapter that inspects the identity (the hosted owner-or-admin shape) therefore answers denied, and the plane reports the claim as stale. Result: rainier attach --take and the in-session take-control key never obtain control on a hosted cell; the first attach still works because its authorization runs on the user's own request.
Self-hosted does not see it: ownerOrAdmin there answers the same for every identity. There is no controld-level test of the claim path, which is how it shipped.
Fix
Capture the authorizing identity when the keeper is built, inside AttachTerminal, where the context has the user, and authorize every later policy question (claim, and any renew/release that asks) against that identity rather than the request that happens to be running. Keep the question itself (AttachmentController, live per claim). Check every other policy call reachable from the splice for the same mistake.
Acceptance
A controld-level test: negotiated attach by a permitted principal, then a mid-attach claim under an identity-inspecting policy, which must succeed; it fails on main today. End-to-end proof that --take and the key work under such a policy. Ships in the same plane roll as controller ownership; nothing is deployed yet.
Found out of scope by the review of #90; the defect is in the merged conditional controller ownership (#84, b22b225). Being fixed on
fix/claim-authority.What happens
controllerKeeper.ClaimasksAttachmentPolicywith the context it is called with. The keeper runs inside the plane's splice, which is driven by the runner's dial-back request, and that context carries no user identity. A policy adapter that inspects the identity (the hosted owner-or-admin shape) therefore answers denied, and the plane reports the claim asstale. Result:rainier attach --takeand the in-session take-control key never obtain control on a hosted cell; the first attach still works because its authorization runs on the user's own request.Self-hosted does not see it:
ownerOrAdminthere answers the same for every identity. There is no controld-level test of the claim path, which is how it shipped.Fix
Capture the authorizing identity when the keeper is built, inside
AttachTerminal, where the context has the user, and authorize every later policy question (claim, and any renew/release that asks) against that identity rather than the request that happens to be running. Keep the question itself (AttachmentController, live per claim). Check every other policy call reachable from the splice for the same mistake.Acceptance
A controld-level test: negotiated attach by a permitted principal, then a mid-attach claim under an identity-inspecting policy, which must succeed; it fails on
maintoday. End-to-end proof that--takeand the key work under such a policy. Ships in the same plane roll as controller ownership; nothing is deployed yet.