Reassess SCOPE against the current revision
SCOPE.md declared itself reviewed against b989de4, 63 commits behind, with its
limits kept current by appending to bullets. That works until the header asserts
a review date that no longer describes what was reviewed -- the drift this file
exists to prevent, in the document whose only job is to be accurate.
Every claim was rechecked against source rather than carried forward: routes from
the mux registrations, subcommands from the dispatch, flags from the flag sets,
claim behaviour from token.go and userinfo.go. Three were false. Caller commands
omitted verify-client, the container was said to package only keycape (untrue
since KEY-WP-0026), and the issuer API row omitted /readyz. Capabilities that had
reached SCOPE only piecemeal are now in the capability table: the
authorization-code bindings, upstream token verification, readiness and drain, the
human tenant rules, authentication-time assurance, the shared verifier.
The substantive addition is a distinction SCOPE did not draw: source behaviour
and deployed behaviour are different claims with different evidence -- the test
suite and harness runs for one, committed receipts in docs/evidence/ for the
other. What is proven live is narrower and now stated exactly, including that the
issuer pin's pre-pin state did not match, so that risk was real rather than
hypothetical, and that the deployed image predates this revision so several
described behaviours are running nowhere yet.
That distinction is the fix for a repeated error: four times in two days a claim
about current state was written from a workplan paragraph or a partial view
instead of the authoritative artifact. A SCOPE that does not separate "the code
does this" from "this is running" invites the same mistake from the next reader.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NV9oijZukGyGbRQGGKnK4P
Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 713576@bnt-lap001
Assistant-Session: 384c511d-9bce-4cb8-a676-2aef6c0c8df6
This commit is contained in:
parent
7a73352368
commit
d6ecb2b7aa
3 changed files with 210 additions and 11 deletions
96
history/2026-09-09-scope-reassessment.md
Normal file
96
history/2026-09-09-scope-reassessment.md
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
# KeyCape scope reassessment — 2026-09-09
|
||||
|
||||
Source baseline: **5ae80d3**. Supersedes the
|
||||
[2026-09-05 assessment](2026-09-05-011726-scope-intent-assessment.md) against
|
||||
`b989de4`, which remains the record of the ten-gap backlog and its closures.
|
||||
|
||||
## Why now
|
||||
|
||||
SCOPE.md still declared itself reviewed against `b989de4`, 63 commits behind. Its
|
||||
limits section had been kept honest by appending to bullets, which works until the
|
||||
header asserts a review date that no longer describes what was reviewed. That is
|
||||
the drift this document exists to prevent, in the file whose only job is to say
|
||||
accurately what this repository does.
|
||||
|
||||
## Method
|
||||
|
||||
Every capability claim was checked against source at this revision rather than
|
||||
carried forward from the previous text: routes from the mux registrations in
|
||||
`cmd/keycape/main.go`, subcommands from the dispatch in `main.go` and
|
||||
`internal/authclient/cli.go`, flags from the flag sets, claim behaviour from
|
||||
`token.go` and `userinfo.go`. Live claims were checked against `docs/evidence/`.
|
||||
Where the existing prose and the code disagreed, the code won.
|
||||
|
||||
That method was chosen because the opposite failed repeatedly over the preceding
|
||||
two days: four times a statement about current state was written from a workplan
|
||||
paragraph, a partial `git status`, or an inference about what was admitted,
|
||||
without reading the authoritative artifact. Every one was wrong and every one was
|
||||
cheap to check.
|
||||
|
||||
## What changed since 2026-09-05
|
||||
|
||||
Gaps G01 through G09 are closed; G10 is external and remains open. The
|
||||
capabilities that reached SCOPE only piecemeal, now stated:
|
||||
|
||||
- the authorization-code grant binds the redirect URI, refuses clients not
|
||||
registered for it, authenticates confidential clients and consumes codes
|
||||
atomically; UserInfo checks algorithm, issuer and token purpose (G01);
|
||||
- upstream Authelia ID tokens are verified — signature, issuer, audience,
|
||||
validity window — failing closed and independently of transport, on an explicit
|
||||
operator decision not to police the transport instead (G01);
|
||||
- `/readyz` probes LLDAP by bind, plus Authelia and privacyIDEA, distinct from
|
||||
`/healthz`; `SIGTERM` drains for 15s (G08);
|
||||
- `keycape verify-client` checks a live registration's subject, tenant, roles,
|
||||
lifetime and scope refusals without emitting values;
|
||||
- a human tenant may be supplied by a client registration where the directory has
|
||||
placed the user nowhere, and issuance is refused when the two conflict;
|
||||
`assurance.at` is the authentication time rather than the mint time;
|
||||
- `internal/jose` is the single RS256/JWKS verifier behind both the caller path
|
||||
and upstream verification;
|
||||
- the container packages all five binaries, and the dev stack is bootstrappable
|
||||
from a clean checkout.
|
||||
|
||||
Three corrections to claims SCOPE previously made: caller commands omitted
|
||||
`verify-client`; the container was said to package only `keycape`, untrue since
|
||||
KEY-WP-0026; and the issuer API row omitted `/readyz`.
|
||||
|
||||
## The distinction this revision adds
|
||||
|
||||
SCOPE now states plainly that it describes **source**, and that source behaviour
|
||||
and deployed behaviour are different claims. The evidence for each is different
|
||||
too: 390 Go tests across 23 packages and the named harness runs for the first;
|
||||
committed receipts in `docs/evidence/` for the second.
|
||||
|
||||
What is actually proven live is narrower than what the source does, and worth
|
||||
stating exactly:
|
||||
|
||||
- the upstream issuer was probed and pinned in `sso/keycape-config`. The pre-pin
|
||||
state did not match, so the fail-closed login outage that risk described was
|
||||
real and was averted rather than hypothetical;
|
||||
- both approval service clients were verified in an attended owner process: JWKS
|
||||
signature verification, exact claims, excess-scope and wrong-secret denial at a
|
||||
900s lifetime, no credential values emitted.
|
||||
|
||||
Those receipts also decline what they did not test — no real predecessor rotation,
|
||||
no observed wall-clock expiry — and this document declines it with them.
|
||||
|
||||
The deployed image predates this revision, so the authorization-code bindings,
|
||||
upstream verification, readiness, graceful shutdown and both tenant-related
|
||||
changes are running nowhere yet. Two of them fail closed at startup, which is why
|
||||
they are listed in `docs/operations.md` under "Unreleased fail-closed startup
|
||||
changes" rather than only in a hub message.
|
||||
|
||||
## What remains
|
||||
|
||||
G10 is owner work: KEY-WP-0013-T05 waits on `informed-decision` for the approver
|
||||
client ID and deployed callback, and KEY-WP-0014-T04 has no admitted execution
|
||||
authority for a real predecessor rotation. Neither can be closed from this
|
||||
repository.
|
||||
|
||||
From G04, relying-party behaviour and MFA against a migrated realm are still
|
||||
unexercised, and credential and MFA migration is not supplied at all, so no
|
||||
harness can establish it. Complete profile conformance and drop-in Keycloak
|
||||
interchangeability remain unestablished — and the conformance suite found a
|
||||
concrete reason they are not the same question: stock Keycloak advertises the
|
||||
`implicit` and `password` grants this profile excludes, as server capabilities no
|
||||
realm configuration removes.
|
||||
Loading…
Add table
Add a link
Reference in a new issue