fix(cipher): the mint printed the credential twice, and the second copy wore no label - #2988
Merged
Merged
Conversation
Contributor
|
Important Review skippedAuto reviews are limited based on label configuration. 🏷️ Required labels (at least one) (1)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
POWERFULMOVES
force-pushed
the
fix/cipher-mint-single-emission
branch
from
September 8, 2026 08:47
b0753e2 to
af710b9
Compare
…py wore no label
`mint_cipher_token.py` builds the bearer as `token = f"cipher_{token_uuid.hex}"`
and stores that same `token_uuid`. Migration 20260728100000 declares
`token_uuid UUID PRIMARY KEY` with no hash column, and it is the ONLY cipher-token
migration, so nothing has superseded it: THE STORED ROW IS THE CREDENTIAL.
The insert is sent with `Prefer: return=representation`, so Supabase echoes that
row back -- and line 53 printed it verbatim, immediately above the labelled
`CIPHER_TOKEN=` line:
[{"token_uuid": "064cb5d4-3474-4faa-81f8-8c24f50bb776", ...}]
CIPHER_TOKEN=cipher_064cb5d434744faa81f88c24f50bb776
Same secret, two spellings. That is worse than a duplicate: redaction keys on the
label, so an operator or log scrubber removing `CIPHER_TOKEN=` takes away the copy
they can see and leaves the one they cannot -- and the transcript then LOOKS clean.
`.claude/PATTERNS.md` already warns never to run this target in an agent
transcript; this removes one of the two reasons why.
- the response body is no longer printed. It is still parsed, because "accepted
but stored no row" must be an error rather than a token the operator will try
to use.
- `_redact()` blanks both spellings in HTTPError detail before it reaches stderr.
A 23505 duplicate-key error quotes the offending value back, and that value is
token_uuid; server-controlled text is not a safe place to assume the credential
is absent.
Six tests, every one negative-controlled against the unfixed script. Two of them
were WRONG when first written and the control is what caught it:
* counting only the hex form PASSED against the broken code -- the echoed row
spells the uuid dashed, so the leak sailed past. Both forms are now counted.
* `ln is not line` is an identity check; splitlines() rebuilds the string, so it
fired on correct output. Now compared by value.
Scope: this is the cheap, self-contained half of the twice-expired
`docs/reclaim-cipher-token-model` lane (#2824, #2864 -- both merged, both
register-only, `6+ 0-`, no remediation ever written). Carrying it as one lane is
why it never shipped: the expensive half needs a schema change to a live auth
table plus operator sequencing, and it was gating a change that needs neither.
NOT fixed here, deliberately, and still unclaimed:
* the token is stored unhashed (needs a migration + fleet re-mint)
* `auth.ts:62-64` passes `uuidHex` to the PostgREST filter unvalidated when its
length is not 32 -- lives in the Pmoves-cipher submodule, so its own PR
* `auth.ts:49` bootstrap mode grants all six scopes under one shared identity,
which is the ACTIVE mode on Z890, and `Makefile:5727` defaults to those same
six scopes
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jxd5gryAFPXwhjaCMw9Qrx
POWERFULMOVES
force-pushed
the
fix/cipher-mint-single-emission
branch
from
September 8, 2026 08:59
af710b9 to
f1125fa
Compare
POWERFULMOVES
added a commit
that referenced
this pull request
Sep 11, 2026
…d-but-unreleased (#3007) Six expired-and-unreleased claims were each blocking a future claimant while nobody had said they were still on it. Five were already DELIVERED and simply never released; one was mine and was genuinely unfinished. MINE -- docs/reclaim-cipher-token-model, RELEASED with the real verdict: still needed, never started, now SPLIT. Claimed twice (#2824, #2864) and both PRs were REGISTER-ONLY -- #2864 was 6+ 0-, one file. Any audit keying on PR state reads two merged PRs as closure. It kept expiring because one claim held two lanes and the expensive half gated the cheap half. Cheap half landed as #2988; the expensive half (unhashed storage on a live auth table, auth.ts:62-64 in a submodule, bootstrap's six-scope shared identity) is named and left UNCLAIMED. FIVE BACKFILL ACKNOWLEDGEMENTS, not owner-signed closures -- B850 x3, HERMES x1, SPARK x1. Each carries filed-by: Z890-CLAUDE, merge SHA + timestamp, and states that the owner-authored RELEASE and signed ACK remain OWED. Attribution stays with the owner; only the signature is mine. That split is the point: AGENT_IDENTITY_PROPOSAL_2026-09-04.md section 4 names "written about and never writes" as the failure mode, so a backfill must not become another agent's ledger entry authored by me. CITATION CORRECTION. The precedent for this (#2960, the Mavis row) cites "AGENTS.md:L60-62, co-owner has no authority to close another owner's claim". That clause is not in AGENTS.md, and `git log -S` over AGENTS.md history returns EMPTY -- it has never been there. The practice is sound and is followed here; the phantom citation is not propagated. Grounded instead on the Village Rule that AGENTS.md does carry: claim -> work -> sign -> release, "on completion write a RELEASE row and a signed ACK block" -- which makes RELEASE the owner's act without inventing a clause. Verification: register is a strict byte prefix of origin/main plus 8589 appended bytes, 6 rows, NUL count 1 preserved, postdate clean. Expired-and-unreleased falls 6 -> 4. SPARK's three remaining expired lanes are deliberately NOT backfilled: each has an OPEN PR (#2946, #2959, #2943), so they are active work past TTL, not abandoned work. Claude-Session: https://claude.ai/code/session_01Jxd5gryAFPXwhjaCMw9Qrx Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: kiloclaw <kiloclaw@users.noreply.github.com>
POWERFULMOVES
added a commit
that referenced
this pull request
Sep 17, 2026
…ng correction I had backwards
OPERATOR CORRECTION, recorded at the top because it changes what the rest means:
the signing card is NOT an unlock or an authority gate. It is a LIVING DOC OF
PROVENANCE -- checkable, verifiable, current, deterministically maintained --
and the AGInTZ is ATTRIBUTED WITH THE RELEASE.
I spent this session building gates. The same code reads differently under the
right frame: when mint_cipher_token refuses an uncarded agent I read it as "you
lack authority"; under provenance it means THERE IS NOTHING TO ATTRIBUTE TO YET.
Not permission denied -- ledger absent.
The distinction decides the architecture. A permission model needs a gatekeeper
per act and cannot reach autonomy. A provenance model lets agents act and keeps
the record current, so attribution flows with the release. With self-improvement
near and the goal of all AGInTZ running autonomously round-trip, only one of
those scales.
LANES FILED:
fix/guard-names-vs-targets the Bash guard matches a protected path's
NAME, not a resolved target -- four refusals
for merely naming a file, including the
remedy its own error recommends
fix/skip-hides-absence a skipped test reports green; that is how
six of nine launchers stayed unwired under
a REQUIRED check on a protected branch
governance/identity-provenance- operator-owned; the vocabulary declarations
round-trip and the four real cards, with every
measurement on the ledger
A CORRECTION INSIDE THE THIRD: I reported NINE signatures that "cannot sign" as
though all nine were defects. Five are correctly uncarded -- minimax is
model_backend, the three botz-* are role templates, and powerfulmoves is the
Legendary/umbrella class whose signing facet IS darkxside, which HAS an active
card. The root of trust was never broken. Real gaps: 4.
AND ONE ON MY OWN MERGED WORK: commit #2988 states ".claude/PATTERNS.md already
warns never to run this target in an agent transcript". The warning is real but
lives in .claude/skills/pmoves-cipher-memory/SKILL.md:52. Right fact, wrong
file -- a phantom citation of the kind this register has corrected before, now
merged under my name. Recorded rather than quietly fixed, because the register's
own precedent is that a bad citation gets named and not propagated.
I did NOT run cipher-mint-token. The mint prints the bearer, and my 2026-08-28
row records leaking a bootstrap token exactly that way. A credential scattered
into a transcript is what breaks the provenance chain the card exists to keep
verifiable -- which is the whole point of the corrected frame.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
POWERFULMOVES
added a commit
that referenced
this pull request
Sep 18, 2026
…rged but not in effect Three RELEASE rows, each verified on main by CONTENT rather than by PR state — the distinction the docs/reclaim-cipher-token-model row warns about, where an audit keying on PR state reads merged-but-unremediated as closure. fix/nats-legacy-jetstream-volume #3077 (40198cc) fix/cipher-mint-single-emission #2988 (b0b193a) fix/cipher-skills-stale-blocker #3009 (bb6168c) THE NATS ROW CARRIES A DELIBERATE NON-CLOSURE. The compose fix is on main and verified there, but `pmoves-nats-1` has NOT been recreated, so the volume does not exist yet and JetStream is still writing to /tmp/nats/jetstream. The fix is merged and NOT in effect. The recreate briefly drops the bus 51 containers use and is an operator-sequenced act, so the row says so plainly instead of letting a merged PR imply a fixed node. THE TWO CIPHER ROWS ARE REFILED, and the reason is worth recording. They were first written earlier today onto a local branch that was never pushed. The rows existed, were committed, and still never reached main — so both lanes continued to read as OPEN. A register row on an unpushed branch is not a filed row. That is the same class as the defect they were closing: something that looks done from one angle and is invisible from the one that counts. Both are also LATE (7d and 5d past TTL), disclosed in the rows rather than smoothed over. Delivery was on time in both cases; only the release was missed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
POWERFULMOVES
added a commit
that referenced
this pull request
Sep 18, 2026
…ng correction I had backwards
OPERATOR CORRECTION, recorded at the top because it changes what the rest means:
the signing card is NOT an unlock or an authority gate. It is a LIVING DOC OF
PROVENANCE -- checkable, verifiable, current, deterministically maintained --
and the AGInTZ is ATTRIBUTED WITH THE RELEASE.
I spent this session building gates. The same code reads differently under the
right frame: when mint_cipher_token refuses an uncarded agent I read it as "you
lack authority"; under provenance it means THERE IS NOTHING TO ATTRIBUTE TO YET.
Not permission denied -- ledger absent.
The distinction decides the architecture. A permission model needs a gatekeeper
per act and cannot reach autonomy. A provenance model lets agents act and keeps
the record current, so attribution flows with the release. With self-improvement
near and the goal of all AGInTZ running autonomously round-trip, only one of
those scales.
LANES FILED:
fix/guard-names-vs-targets the Bash guard matches a protected path's
NAME, not a resolved target -- four refusals
for merely naming a file, including the
remedy its own error recommends
fix/skip-hides-absence a skipped test reports green; that is how
six of nine launchers stayed unwired under
a REQUIRED check on a protected branch
governance/identity-provenance- operator-owned; the vocabulary declarations
round-trip and the four real cards, with every
measurement on the ledger
A CORRECTION INSIDE THE THIRD: I reported NINE signatures that "cannot sign" as
though all nine were defects. Five are correctly uncarded -- minimax is
model_backend, the three botz-* are role templates, and powerfulmoves is the
Legendary/umbrella class whose signing facet IS darkxside, which HAS an active
card. The root of trust was never broken. Real gaps: 4.
AND ONE ON MY OWN MERGED WORK: commit #2988 states ".claude/PATTERNS.md already
warns never to run this target in an agent transcript". The warning is real but
lives in .claude/skills/pmoves-cipher-memory/SKILL.md:52. Right fact, wrong
file -- a phantom citation of the kind this register has corrected before, now
merged under my name. Recorded rather than quietly fixed, because the register's
own precedent is that a bad citation gets named and not propagated.
I did NOT run cipher-mint-token. The mint prints the bearer, and my 2026-08-28
row records leaking a bootstrap token exactly that way. A credential scattered
into a transcript is what breaks the provenance chain the card exists to keep
verifiable -- which is the whole point of the corrected frame.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The defect
mint_cipher_token.pybuilds the bearer astoken = f"cipher_{token_uuid.hex}"and stores that sametoken_uuid. Migration20260728100000declarestoken_uuid UUID PRIMARY KEY— no hash column — and it is the only cipher-token migration, so nothing superseded it. The stored row is the credential.The insert uses
Prefer: return=representation, so Supabase echoes that row back, and:53printed it verbatim directly above the labelled line:Same secret, two spellings — dashed in the row, hex in the token.
This is worse than a duplicate. Redaction keys on the label. An operator or scrubber removing
CIPHER_TOKEN=takes away the copy they can see and leaves the one they can't — and the transcript then looks clean..claude/PATTERNS.mdalready warns never to run this target in an agent transcript; this removes one of the two reasons why.The change
_redact()blanks both spellings inHTTPErrordetail before it reaches stderr. A23505duplicate-key error quotes the offending value back, and that value istoken_uuid; server-controlled text isn't a safe place to assume the credential is absent.Only consumer is
Makefile:5727, which runs the script and shows its output — nothing parsed the JSON that was removed.Tests: 6, every one negative-controlled
Two were wrong when first written, and the control is what caught them:
ln is not lineis an identity check;splitlines()rebuilds the string, so it fired on correct output. Now compared by value.The redaction test was verified by disabling
_redact()and watching it fail.Scope, and why this lane kept expiring
This is the cheap, self-contained half of the twice-expired
docs/reclaim-cipher-token-modellane. #2824 and #2864 both merged and were register-only (6+ 0-) — no remediation was ever written. Carried as one lane, the expensive half (schema change to a live auth table, operator sequencing) gated a change that needs neither.Not fixed here, deliberately, and still unclaimed:
auth.ts:62-64passesuuidHexto the PostgREST filter unvalidated when length ≠ 32 — lives in thePmoves-ciphersubmodule, so its own PRauth.ts:49bootstrap mode grants all six scopes under one shared identity — the active mode on Z890 — andMakefile:5727defaults to those same six scopesDisclosure
No local interpreter in this repo has
pytest_asyncioorpyyaml, so the rootconftest.pyfails to import and no pytest run underpmoves/works out of the box. I ran these in a throwawayuvvenv withpytest,pytest-asyncio,pyyaml. The 6 tests here are self-contained (network stubbed, no fixtures fromconftest), but I could not run the wider suite locally — CI is the check on that.Separately:
register-claimwrote 1 CRLF into an otherwise pure-LF register on Windows. Git normalized it (staged blob has 0 CRLF, verified), so this PR is clean, but it's a papercut inregister_append.🤖 Generated with Claude Code