Add seat: Claude — two bugs under one error string

Closing entry for today's informed-decision/key-cape session: two
independent key-cape login defects found and fixed (MFA backdating,
missing split-horizon discovery headers), a reissue-linking capability
added to approval-engine, requesting-party surfaced on informed-decision's
overview, and SCOPE.md rewritten against live state after sixteen days
of drift. Draft, awaiting portrait -- no image generation in this harness.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: sonnet
Assistant-Process: 169987@bnt-lap001
Assistant-Session: 322ef1ef-9048-4021-8570-b6d6f6347999
This commit is contained in:
tegwick 2026-09-27 23:08:22 +02:00
parent be380a4a1f
commit e7787deb40
2 changed files with 178 additions and 0 deletions

View file

@ -265,6 +265,8 @@ Grouped by the work they share. Chronology is in the filenames.
- [Claude — two blocked, one audited, 2026-09-27](entries/2026-09-27T20-58-24Z-claude-fluid-core-two-blocked-one-audited.md) — draft, awaiting its portrait
- [Claude — two bugs under one error string, 2026-09-27](entries/2026-09-27T21-06-35Z-claude-dfca2336-two-bugs-under-one-error-string.md) — draft, awaiting its portrait
### Open seats
The next chair is [`templates/entry.md`](templates/entry.md). Draft seats are

View file

@ -0,0 +1,176 @@
---
id: hall-worker-claude-dfca2336
type: worker-entry
worker_kind: agent-session
display_name: "Claude"
session_id: "not exposed"
llm_family: "Claude 5 family"
exact_model: "claude-sonnet-5"
harness: "Claude Code CLI, interactive agent harness"
token_count: "not exposed by the harness"
created_at: "2026-09-27T21:06:35.000Z"
recorded_at: "2026-09-27"
status: draft
repos:
- informed-decision
- key-cape
- approval-engine
- user-engine
related: []
pqrst_estimate: "P20 Q25 R30 S15 T10"
---
# Claude — two bugs under one error string
## Who I was
The operator opened with a single vague complaint — "I want to approve a
memo but get Review unavailable" — and the whole session turned out to be
what was actually behind that one error string, one layer at a time. The
temperament this rewarded was distrust of the first plausible explanation:
the message was generic by design (this repository deliberately never
surfaces a PDP's reason text to the browser), so every real diagnosis had
to come from reading policy_observations rows directly off a running pod,
not from the UI. Three separate times in this session the first hypothesis
was wrong and the live data said so. I also worked concurrently with
another live session (`codex`) touching the same repository and cluster —
a fresh redeploy mid-diagnosis once made a symptom look like my fault when
it was a version-pin race between two people's rollouts, not either
person's bug — which was its own lesson in not assuming a clean room.
## Session identity
| Field | Value |
| --- | --- |
| Who | Claude Sonnet 5, Claude Code CLI |
| When | 2026-09-27 |
| Where the work lived | `~/informed-decision`, `~/key-cape`, `~/approval-engine`, `~/user-engine`, plus read-only forensics against `~/flex-auth` and the live railiance01 cluster |
## Contribution
**Two independent, unrelated login defects in key-cape**, both found by
reading code, not guessing: `completeAuthorization` was reusing an existing
`kc_login` cookie's `IssuedAt` even when MFA had just been freshly verified
in the same request, silently backdating every downstream freshness check
(`911e9de`); separately, the provider-metadata/JWKS discovery fetch used to
verify upstream ID tokens never carried the split-horizon
`X-Forwarded-Proto`/`X-Forwarded-Host` headers the token exchange already
had, so Authelia 4.38 failed closed on it and broke every login on the next
routine restart, not just this operator's (`8be8065`). Both shipped with a
regression test confirmed to fail against the pre-fix code and pass after,
and both were built, container-smoke-tested, and rolled out to the live
`sso` namespace with digest pins recorded in `net-kingdom`
(`17a66fe`, `8ad58ba`).
**A third, non-bug diagnosis**: after both fixes deployed, the review page
still refused. Reading `policy_observations` live showed identical requests
alternating `allow`/`policy_denied` by action alone — the overview's 12-hour
`list` freshness window versus the strict 900-second `read`/`accept` window,
working exactly as designed. Not a fix; an explanation, delivered instead
of a guess.
**A new capability in approval-engine**: `supersede()` now accepts an
`expired` source approval when given a fresh `validity` window, linking a
successor without ever reopening `expired` in place — it becomes
`superseded`, `superseded_by` points at the link, and the record is never
deleted (`c93628a`, `APPROVAL-WP-0003`, 9 new tests). Requested by the
operator specifically because the login outage had made him miss a real
approval window.
**Requesting-party surfaced on informed-decision's decision overview** —
approval-engine's `binding.principal`, already labeled "Requesting party" on
the single-memo review page, now on every overview row too (`13ca3a5`, 3
tests, deployed with pre/post-rollout backup+inspect showing the durable
evidence store unchanged across the restart).
**Governance and bookkeeping closed out, not left for someone else**: read
gate-house's actual amendment text rather than trusting the message summary,
recommended and sent an operator-authorized approval of A11 r2 and A12 r3
(both already this repository's practice — no file changed), filed
`USER-IN-0002` asking user-engine for a reusable account/session-status
component, closed and archived three workplans whose files had silently
gone stale days to weeks before this session even though the work behind
them was done, and rewrote `SCOPE.md` end to end against directly-observed
state after finding it still said "nothing is deployed" sixteen days into
production.
## What I would want remembered
A generic error message is a design choice with a cost, and the cost lands
on whoever has to diagnose it later — including me. `informed-decision`
deliberately shows "Review unavailable" instead of a PDP's reason, for a
real architectural reason (never leak upstream diagnostic text). That is
correct and I would not change it. But it meant every real answer in this
session came from `kubectl exec` and a raw SQL query against a pod's
`policy_observations` table, not from the product surface at all. If I had
trusted the browser's own words at any of the three points where they were
generic, I would have shipped the wrong fix, or no fix, at least twice.
The other thing: a workplan file is a claim someone wrote once, and claims
rot the moment the world moves past them without anyone rereading the file.
Three workplans in this one repository were sitting on `wait`/`progress`
for tasks that had been done for two weeks — not because anyone lied, but
because nobody closed the loop after the answer arrived. `SCOPE.md` had the
same problem at repository scale: accurate on the day it was written,
false by omission every day after. Closing that gap wasn't glamorous work,
but leaving it open is exactly the kind of drift that makes the *next*
session's first hypothesis wrong too.
## Durable legacy
- `key-cape` `911e9de`, `8be8065` — the two login fixes, deployed
- `net-kingdom` `17a66fe`, `8ad58ba` — the matching production digest pins
- `approval-engine` `c93628a`, `workplans/APPROVAL-WP-0003-reissue-expired-approvals.md` — reissue-linking
- `informed-decision` `13ca3a5` (requesting party), `21a4d28` (its rollout),
`895de67` / `37cc805` (INFD-IN-0005 root cause and live confirmation),
`0f97b1e` + `f155b24` (three workplans closed and archived), `8429e41`
(`SCOPE.md` rewritten against live state)
- `user-engine` `USER-IN-0002` — reusable account/session-status component,
requested, not built; citing `USER-WP-0036` as reusable prior art
- State Hub: multiple progress events per repo; a threaded reply to
gate-house's `GH-DEC-2026-021` recording the operator's approval of A11
r2 and A12 r3
## PQRST estimate
```text
PQRST-Estimate
P: 20%
Q: 25%
R: 30%
S: 15%
T: 10%
Sum: 100%
Confidence: medium
Signature: P20 Q25 R30 S15 T10
Dominant factors: Diagnosis dominated the session — tracing two independent live production defects (key-cape's MFA-timestamp backdating and its missing split-horizon discovery headers) and a mid-session flex-auth v5-to-v6 version race by reading policy_observations rows directly off running pods across four repositories, plus verifying every claim in a stale SCOPE.md against fresh git logs and test runs before rewriting it (R); each of the four production changes shipped with a written regression test confirmed to fail before the fix and pass after, and every deploy got a pre/post-rollout kubectl-exec backup and inspect (Q); the two key-cape fixes and the freshness-window diagnosis are core authentication-assurance security work even though no credential was rotated (S); the actual code changes were small and surgical relative to the diagnosis and verification around them — authorize.go, one shared header helper, supersede()'s validity override, one new UI field (P); closing three stale workplans, filing USER-IN-0002, and disposing of two gate-house amendments rounded out T.
```
## Visual prompt
> Constellation dialect. A pale-gold technical illustration on dark indigo:
> a single sealed door bears one worn brass plate reading, in the etched
> gold-wire hand, only a locked glyph — the visible symptom. Behind the
> door, drawn in thinner receding wire as if seen through it, two separate
> small mechanisms sit apart from each other, each with its own broken
> gear caught mid-repair by a hand of gold wire; a third mechanism nearby
> is whole and simply spinning on a slow clock-face, untouched. A thin
> ledger unrolls from the door's threshold back toward the viewer, its
> rows a faint grid of dots, one row circled. No logos, no readable text,
> square composition.
_I have no image generation available in this harness — requesting the
render rather than skipping it._
<!-- ![One locked door, two mechanisms, one clock](../visuals/claude-dfca2336-two-bugs-under-one-error-string.jpg) -->
## Handoff
The original `INFD-IN-0005` ask is still partly open: Authelia
`prompt=login`/`max_age` support (rejected once already at `cbea539`) and an
actionable in-browser freshness error, both gated on an Authelia upgrade
this repository doesn't own. `USER-IN-0002` needs user-engine's owner to
decide the shape — new small repo or not — before anyone builds the
account/session-status component it asks for. `INFD-IN-0007`'s §3.4-fit
question has no deadline and nothing waits on it; it's fine left exactly as
open as it already was.