Seat 01V3W1dQ: correct a stale premise and hand forward an aud defect

Two corrections made while closing.

The seat claimed the client registration discharged the gap that created the
repository, and that KEY-WP-0013-T02 had been blocked since 2026-09-08. A later
session checked that against key-cape rather than against my notes: T02 and T05
were already done and KEY-WP-0030 closed. The submission was still owed; the
urgency was stale. I had carried a two-day-old blocking claim through a dozen
turns without re-reading its source — the same error as verifying the origin
myself and then not verifying the blocker.

Second, the handoff now carries a security defect found by running the suite at
close, in another session's in-flight work. An access token with aud
["approval-engine", <client_id>] is accepted. The cause is not the check's logic
— informed_decision/oidc.py passes options strict_aud True, and PyJWT 2.7.0 does
not implement it, so the option is silently discarded and list audiences pass.
Added in PyJWT 2.10. approval-engine compares aud by exact equality, so this is
audience confusion at the surface fronting it.

Not patched deliberately: that module was committed twenty minutes earlier by a
session still working in it. Named the cause and handed it over, with an
explicit instruction not to make the test pass by loosening it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V3W1dQG7GFFM9d94jFx7iR

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 1565372@bnt-lap001
Assistant-Session: 16bb2f25-b34c-49ef-8e94-5fec3567a568
This commit is contained in:
tegwick 2026-09-11 00:56:36 +02:00
parent 03c388f86a
commit 1b8c3198e6

View file

@ -73,11 +73,20 @@ House attributed the speed to that ordering. Wrote `layer.yaml` and
about you is not a declaration — built to v0.8 obligation 3 rather than migrated
to it later, with published-equals-shipped asserted by test rather than claimed.
**Discharged the gap that created the repository.** Submitted `client_id
**Published the client registration.** Submitted `client_id
informed-decision-approver` and `https://decisions.coulomb.social/auth/callback`
to `key-cape`, closing a task that had been blocked since 2026-09-08. Verified
the origin myself — 200 on both paths, TLS verify 0, certificate chain — rather
than taking the deploying repository's report.
to `key-cape`. Verified the origin myself — 200 on both paths, TLS verify 0,
certificate chain — rather than taking the deploying repository's report.
*Corrected while closing, and it is the seventh correction of the session:* I
said throughout that this "discharges the gap that created this repository" and
that `KEY-WP-0013-T02` had been "blocked since 2026-09-08." A later session
checked the premise against `key-cape` rather than against my own notes and
found T02 and T05 already `done`, and `KEY-WP-0030` closed. **The issuer side of
the gap was already discharged before I submitted.** I had carried a
two-day-old blocking claim forward through a dozen turns without re-reading its
source. The submission was still correct and still owed; the urgency I attached
to it was stale. `bb5b607` corrects the repository's own record.
**Built the domain core**, with `approval-engine` behind a Protocol and a fake
because it has no pods: `memo`, `presentation` (sole writer of `view_hash`),
@ -130,6 +139,13 @@ the real shape is that it moves *integrity* out of my control and leaves
*availability* entirely inside it, and the party who can withhold the content is
the party the evidence is about.
There is a seventh, found in the last minutes of the session by someone else:
**a blocking claim I read once and then quoted from memory.** The premise had
gone stale two days before I started, and no amount of care downstream of it
would have caught that — only re-reading the source would. Verifying the origin
myself and then not verifying the blocker is the same error made in opposite
directions.
And one more, offered to `gate-house` and taken into their register: **both
corrections I contributed came from my worst instance, not my best.** A-16 was
silent on who writes the route marker, and I saw it only because in my case the
@ -220,7 +236,26 @@ portrait or inventing one. The intended file is
## Handoff
**Not finished.** One concrete next action:
**Not finished.** Two concrete next actions.
**First, a security defect found while running the suite at close, in another
session's in-flight work.** `tests/test_browser_auth.py::test_invalid_identity_refused[access_token-aud-value2]`
fails, and it is failing *correctly*: an access token whose `aud` is the list
`["approval-engine", <client_id>]` is accepted when it must be refused.
Root cause is not the check's logic. `informed_decision/oidc.py` passes
`options={"strict_aud": True}` to PyJWT, and **PyJWT 2.7.0 does not implement
that option** — `_validate_aud` never references it, so the unknown key is
silently discarded and list audiences pass. `strict_aud` landed in PyJWT 2.10.
Fix is to pin the dependency and keep the test, or assert the audience is a
single exact string before decoding. `approval-engine` compares `aud` by exact
equality, so this is audience confusion at the surface that fronts it.
I did not patch it: the module was committed twenty minutes earlier by a session
still working in it, and silently editing under them is worse than handing it
over with the cause named. **Do not make the test pass by loosening it.**
Second:
`INFD-WP-0001-T08` needs the live end-to-end proof — a human approver completing
an approval entry through the surface against a deployed `approval-engine`, with