@@ -1248,12 +1248,15 @@ function resolveGateAuthService(registry: StorageGateRegistry): RequestAuthServi
12481248 * KEY's answer, from the shared key-admission seam (`resolveApiKeyAdmission`)
12491249 * with the auth service's per-user posture computation: a key whose owner
12501250 * holds an `account`-scope posture answers that posture, and the door refuses
1251- * it with the session's `403`; an admitted key answers no posture, and the
1252- * session is NOT read for it — a cookie beside a key never answers for the
1253- * key. A key the seam does not recognise (`none`) leaves the session's own
1254- * gate to answer, exactly as the identity resolution falls through to the
1255- * session for it. Asked with the door's tenancy posture, so a key the posture
1256- * refuses is refused before its owner is asked, as on every other face.
1251+ * it with the session's `403`. Asked with the door's tenancy posture, so a key
1252+ * the posture refuses is refused before its owner is asked, as on every other
1253+ * face.
1254+ *
1255+ * [#24366] The family gate and the route judge the same credential: the gate
1256+ * judges every credential a route of this family can serve, so a session the
1257+ * policy holds is refused on every route whatever else the request carries.
1258+ * One door fronts every route, so the seam's answer about a key never stands
1259+ * in for the session's own posture.
12571260 */
12581261function buildAuthGateSessionReader (
12591262 registry : StorageGateRegistry ,
@@ -1284,12 +1287,12 @@ function buildAuthGateSessionReader(
12841287 await resolveAdmissionTenancyPosture ( registry ) ,
12851288 userAuthGateSourceOf ( auth ) ,
12861289 // [#23367] The API-key lifecycle policy, from the same service. A key
1287- // its own lifecycle refuses (`lifecycle`) carries no posture and is
1288- // left to the identity resolution below, which fails it closed.
1290+ // its own lifecycle refuses (`lifecycle`) carries no posture; the
1291+ // route that would serve it fails it closed.
12891292 apiKeyLifecyclePolicySourceOf ( auth ) ,
12901293 ) ;
12911294 if ( admission . outcome === 'held' ) return { authGate : admission . gate } ;
1292- if ( admission . outcome !== 'none' ) return undefined ;
1295+ // [#24366] Every other answer falls through to the session's own gate.
12931296 }
12941297 let session : SessionRead | null ;
12951298 try {
@@ -1468,11 +1471,12 @@ function buildFileReadAuthorizer(
14681471 // behind the family's door (`mountFamilyRoute` in
14691472 // `storage-routes.ts`), whose gate reader
14701473 // (`buildAuthGateSessionReader`) has already refused a held session
1471- // or a held owner's key on this request with the posture's `403`, and
1472- // both are bound by `composeStorageRoutes` from the same `auth`
1473- // service. The context the door hands on stays truthful (a held
1474- // principal carries the `authGate` decided off the read that admitted
1475- // it) without a second read: `'reread-when-active'` would read the
1474+ // or a held owner's key on this request with the posture's `403`,
1475+ // whatever else the request carries (#24366), and both are bound by
1476+ // `composeStorageRoutes` from the same `auth` service. The context
1477+ // the door hands on stays truthful (a held principal carries the
1478+ // `authGate` decided off the read that admitted it) without a second
1479+ // read: `'reread-when-active'` would read the
14761480 // session a third time on this request and add an outage arm no
14771481 // caller of this door ever had.
14781482 // - `credentials: 'api-key-and-session'`: the headers are the real
0 commit comments