Skip to content

cli: Restore ms32 checksum as a separate generation command - #144

Open
BenWestgate wants to merge 1 commit into
codex/split146-contextfrom
claude/project-thread-ufnlez
Open

BenWestgate wants to merge 1 commit into
codex/split146-contextfrom
claude/project-thread-ufnlez

Conversation

@BenWestgate

@BenWestgate BenWestgate commented Oct 13, 2026 •

Copy link
Copy Markdown
Owner

Before: there is no way to checksum new Codex32 Book worksheet data. ms32 checksum and v0.6.1's Codex32String.from_unchecksummed_string were removed in 1a14000.

After: ms32 checksum checksums new Book worksheet data as a separate generation command from check and correct, following codex32 discussion #78. One private, generic helper builds the checksum, so a future GUI page (#153) reuses it instead of duplicating it.

API decision: private, not public. Ben (2026-10-21): "it can be private API, but we definitely don't need to duplicate it between CLI and GUI." The public complete_checksum() described in an earlier review reply is superseded. _from_unchecksummed_string() in bip93.py is not exported; it can become public later without a break if a real user needs it.

Stacked on #146 (base is its branch; retarget to reviewability-v1 once #146 merges). Two atomic commits, plus merges of #146's newer commits (7fcffa7, 96f6493):

  1. bip93: Add a private _from_unchecksummed_string: v0.6.1's operation for any HRP, now with header and ms payload validation and a full reparse. It is not exported. Invariant 1 names it; the malformed-input corpus covers it.
  2. cli: Restore ms32 checksum for Book worksheets: the command, help, tests, user guide and security model.

Flow

  1. Enter the worksheet's 32 non-pink bold squares.
  2. The terminal and scrollback clear where supported; re-enter them. A mismatch stops before anything is shown.
  3. The full completed string is shown; copy its 13 checksum characters into the pink squares and press Enter.
  4. The terminal clears; type back only the pink checksum squares.
  5. Only then does the completed string reach stdout.

Every entry must be ASCII and entirely uppercase or lowercase. --plain keeps the input's case; default output uses the usual uppercase card layout. Mismatch, EOF or interruption puts nothing on stdout (the preview has already appeared on stderr after step 3).

Misuse risks

A checksum makes any data look like a valid backup. From discussion #78:

  • Weak entropy: checksumming non-random data (raw dice rolls, seed words, a guessed string) and then funding an insecure wallet (Ben).
  • Re-checksumming a damaged backup: replacing a backup's checksum locks the damage in instead of correcting it (apoelstra).
  • Missing vs. wrong checksum: a damaged complete string can be as long as a longer unchecksummed payload, so a calculator can absorb the old checksum and produce valid but different wallet material (scgbckbone, Ben).
  • Conflation with repair: generation must be clearly distinct from validation, correction and completed shares (apoelstra, apoelstra).

How the CLI answers them:

  • ms32 only, interactive only, errors give no format hints.
  • Accepts only the Book worksheet's 32 non-pink squares with an ms HRP (checked on the decoded string, so a stray 1 cannot change it) and refuses every complete ms string length, pointing to 'ms32 check'. This narrows the missing-vs-wrong ambiguity but cannot remove it: a damaged backup that lost or gained characters can still reach the accepted length.
  • Warning and help forbid replacing an existing backup's checksum and entering raw dice, seed words, hex seeds or passwords.
  • Repeated entries catch typing errors; nothing can catch an error already on the worksheet or prove the data was generated well. The warning says so.

The helper itself has none of these safeguards; the security model says every façade that uses it must provide them.

Not included: GUI (#153 asks Book users to request it).

Security review: Ben's review of 8a04a42 found no vulnerabilities. Its one documentation note (the model said nothing is "computed" before the second entry, though only display is gated) is fixed in 1887cf6, alongside the rename from _complete_checksum and the commit-message wording. Ben's approach ACK of 7fcffa7 still requires a real-terminal worksheet ceremony and the security gate before merge.

Merges since the review: 7fcffa7's only conflict was the docs/developer/api.md boundary line, which takes #146's wording. 96f6493 brings in #146's flattened Codex32String, so the helper now builds the six-character header string and validates it with _header() (same threshold, identifier and index checks as before), returns Codex32String, and the CLI compares the pink squares against artifact.checksum. Invariant 1 now says construction validates and names the helper as one of the two builders.

Validation on 96f6493: 917 tests pass normally and under python -O; ruff, ruff format and mypy pass. A pseudo-terminal run with BIP-93 vector 1 completed the flow (lowercase and uppercase) and rejected a wrong pink square.

🤖 Generated with Claude Code

https://claude.ai/code/session_01C8Ur3dhqpcWU3gEYsweXNM

Copy link
Copy Markdown
Owner Author

@codex security-review

Focus: the input gate in _checksum (src/codex32/cli.py): refusal of complete-string lengths, the exact 32-square length check, ms-only and interactive-only, clear-screen re-entry, no format hints.


Generated by Claude Code

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-24T04:37:53.582106Z dff3bb8 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Copy link
Copy Markdown
Owner Author

@codex security review


Generated by Claude Code

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Nice work!

Reviewed commit: dcda141178

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@BenWestgate
BenWestgate marked this pull request as ready for review October 20, 2026 07:24

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dcda141178

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/codex32/cli.py Outdated
Comment on lines +580 to +584
hrp, body = bech32_decode(text)
# The Book's checksum worksheet has 32 non-pink squares.
if hrp != Profile.MS.value or len(text) + 13 != _ms_text_length(16):
raise ValueError
artifact = _from_parts(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Move checksum construction out of the CLI

Move this worksheet decoding and artifact construction into a dedicated domain helper or factory. The CLI now selects the profile and payload length, decodes Bech32 symbols, splits the header from the payload, and invokes the private _from_parts constructor itself; that duplicates domain logic at the presentation boundary and makes future checksum, profile-validation, or worksheet-format changes require synchronized CLI updates.

AGENTS.md reference: AGENTS.md:L22-L23

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cACK, especially since there is a tracked issue to add this to the GUI if requested.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated in f1aec05.

Moved worksheet decoding and construction into _from_book_worksheet() in profiles/ms32.py. It owns the fixed Book shape, ms profile, header/payload split and validated artifact construction. The CLI now handles prompts and output. The helper stays private, so this adds no public completion API; it is also available for the GUI work tracked in #153.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why no public completion API? Just curious.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1a14000 removed complete_checksum() to narrow the reviewable interface: under the pre-1.0 "remove unused public API" policy nothing in the repo used it, and a public function makes re-checksumming an existing backup one call away for any app. f1aec05 kept the helper private for the same reason.

Your cNACK changes that, so b3bfe59 restores complete_checksum() as public, generic API (any HRP, registered profile payload rules still apply, result reparsed). Its docstring and docs/security/model.md say it has none of the CLI's safeguards and that apps exposing it must add their own. ms32 checksum still accepts only ms Book worksheet data.


Generated by Claude Code

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Current head 1887cf6 has the domain helper _from_unchecksummed_string, so the CLI/domain split is fixed. But the earlier reply promised a public complete_checksum() API; this head exposes only a private helper. Please confirm the deliberate API decision and update the thread/description. AI-assisted current-head check.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed, private is deliberate. My 2026-10-20 reply above is superseded: on 2026-10-21 you said "it can be private API, but we definitely don't need to duplicate it between CLI and GUI", so the rebuild dropped the public complete_checksum().

The one generic helper is _from_unchecksummed_string() in bip93.py (any HRP, not exported). The CLI uses it now, and the GUI (#153) will import the same function. Keeping it private means no app gets re-checksumming of an existing backup in one call, and it can go public later without a break if a real user asks for it. The description now states this.


Generated by Claude Code

Comment thread src/codex32/cli.py Outdated
"Consult the Codex32 Book and check the non-pink bold squares."
) from error
clear = "\x1b[3J\x1b[2J\x1b[H" if sys.stderr.isatty() else ""
if _worksheet_text(clear + "Re-enter the worksheet non-pink bold squares").lower() != text.lower():

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject non-ASCII checksum re-entry

When the worksheet text contains k, a second entry using Unicode Kelvin sign K in its place passes this comparison because Python evaluates "K".lower() == "k", even though K is not a valid Bech32 character. The command then emits the completed secret despite the two normalized worksheet entries being different, weakening the independent re-entry check; validate that the second entry is ASCII/Bech32-compatible before performing the case-insensitive comparison.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know why the entries are being normalized at all, they should require both to be all upper case or all lower case like codex32 does and the output should keep the input case if --plain otherwise be pretty if that's the default behavior.

Also should we display and confirm the new string like share and create? or just the checksum? (since they already had to type the payload and prefix twice..)

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated in f1aec05.

Both entries now pass ASCII and single-case validation before comparison, so Unicode Kelvin signs and mixed-case input are rejected. --plain keeps the first input's case; default terminal output keeps the usual uppercase card layout.

Per your follow-up, the non-pink data is entered once. The full string is shown, you copy the checksum into the pink squares and press Enter, then the screen clears and you type back only the 13 pink squares. Successful confirmation releases the full string on stdout; mismatch, EOF or interruption does not. This confirms the checksum copy, not the non-pink transcription. The warning and docs say so.

Regression tests cover these cases, including all-uppercase input containing a Kelvin sign.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you remove the double entry with terminal blanking of the non-pink bold squares? That was intentional to detect errors and should be kept. cACK "The full string is shown, you copy the checksum into the pink squares and press Enter, then the screen clears and you type back only the 13 pink squares."

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, f1aec05 removed it by misreading your follow-up. Restored in b3bfe59. The flow is now:

  1. Enter the non-pink squares.
  2. Screen clears; re-enter them. A mismatch stops before anything is computed or shown.
  3. The full string is shown; copy the checksum into the pink squares and press Enter.
  4. Screen clears; type back only the 13 pink squares.
  5. Only then does the string go to stdout.

Both comparisons require single-case ASCII. The warning and docs now say the repeated entries catch typing errors, not errors already on the worksheet.


Generated by Claude Code

Comment thread src/codex32/cli.py Outdated
BenWestgate added a commit that referenced this pull request Oct 20, 2026
Move the fixed Book worksheet format, profile/header decoding and validated artifact construction into the ms profile. Keep the CLI responsible for prompts and presentation; expose no public completion API.

Validation: 25 checksum and size-budget tests pass; Ruff and strict mypy pass. Refs #144.
BenWestgate added a commit that referenced this pull request Oct 20, 2026
Enter the non-pink Book data once, preview the completed string, clear the terminal after copying, then require re-entry of only the pink checksum. Gate stdout on successful confirmation even with --plain or redirected output.

Validate ASCII and single case before comparison, preserve first-entry case in plain output, and make command names explicit in diagnostics. Document that checksum confirmation cannot verify non-pink transcription or entropy.

Validation: 938 normal tests pass; Ruff check/format, strict mypy and git diff --check pass. A real-TTY smoke test confirms stdout gating and Unicode rejection. Refs #144.

Copy link
Copy Markdown
Owner Author

Updated to f1aec05 in two focused commits: worksheet construction now belongs to the ms profile, and confirmation asks for only the 13 pink checksum squares after entering the non-pink data once. The full completed string is previewed before copying and emitted on stdout only after confirmation.

938 tests pass normally and 938 under python -O. Ruff lint/format, strict mypy and git diff --check pass. A real-terminal test checks successful checksum confirmation and Unicode rejection with stdout redirected to a pipe. The PR description and user/security docs match the new flow.

The current target-branch AI policy is the tool-neutral policy merged in #152; this follow-up uses that policy.

@codex security review

Please review current head f1aec05, particularly the fixed Book worksheet input boundary, ASCII/single-case checks before comparison, pink-square-only confirmation, and preview-versus-confirmed-output behavior.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. You're on a roll.

Reviewed commit: f1aec0535c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@BenWestgate

Copy link
Copy Markdown
Owner Author

cNACK: worksheet construction now belongs to the ms profile

The secretcodex32.com website generates worksheets for any HRP and a few lengths plus there are worksheets for NOT RECOMMENDED profiles/hrp. So worksheet construction is generic however our CLI and possibly GUI would only do it for "ms" since no other applications are recommended but we shouldn't make it impossible for users of our library to expose this for their applications.

BenWestgate added a commit that referenced this pull request Oct 20, 2026
Old topic branches can retain superseded contribution rules, as happened while addressing PR #144 after #152 merged. Require agents to consult the current target-branch contributor guide and AI policy before acting on a PR.

State that the tool-neutral policy permits AI-written descriptions and review replies while keeping publication within the user-authorized scope. The maintainer explicitly approved this AGENTS.md patch.

Validation: reviewed the exact approved patch, checked referenced local paths, and ran git diff --check. Documentation only; application tests are not applicable. Refs #144 and #152.

Copy link
Copy Markdown
Owner Author

Re the cNACK on worksheet construction in the ms profile: addressed in b3bfe59.

  • profiles/ms32.py is back to its base-branch state.
  • Public complete_checksum(unchecksummed_text) in bip93.py (the name 1a14000 removed) checksums worksheet data for any HRP. Registered profile payload rules still apply, e.g. CL stays unshared-only. Tests restore the checksums of BIP-93 vectors 1 to 6, including the long checksum.
  • The CLI only adds the ms-only, 35-character Book check and the refusal of complete string lengths, then calls complete_checksum().

Checks: ruff, ruff format, mypy, python -m pytest -q and python -O -m pytest -q (944 passed).

Per CONTRIBUTING.md this is a fixup commit for now. Squashing into atomic commits on the current reviewability-v1 needs a force-push, which I'll ask about in the project thread.


Generated by Claude Code

Copy link
Copy Markdown
Owner Author

@codex security review

Focus: the restored public complete_checksum() (bip93.py) and the ms32 checksum double entry and pink-square confirmation in cli.py at b3bfe59.


Generated by Claude Code

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b3bfe59c64

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/codex32/bip93.py
Comment thread src/codex32/bip93.py Outdated
Comment thread src/codex32/cli.py Outdated
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

1 similar comment
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@BenWestgate
BenWestgate force-pushed the claude/project-thread-ufnlez branch from 1105472 to 62f293e Compare October 21, 2026 07:26
@BenWestgate
BenWestgate changed the base branch from reviewability-v1 to claude/project-thread-2q3smy October 21, 2026 07:26

Copy link
Copy Markdown
Owner Author

@codex security review

Rebuilt as two atomic commits on #146 (62f293e). Focus: the private _complete_checksum() in bip93.py and the ms32 checksum entry, double entry and pink-square confirmation in cli.py.


Generated by Claude Code

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep them coming!

Reviewed commit: 62f293e596

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@BenWestgate BenWestgate left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security review of PR #144 at base ffebbbd5, head 8a04a420.

Result: No confirmed security vulnerability in the changed source. I reviewed the three changed runtime files, their parser/input/output dependencies, the updated security model, tests, and malformed-input corpus.

  • ms32 checksum rejects non-TTY stdin, all intact complete ms lengths, non-35-character input, and non-ms HRPs. The private helper validates container/header syntax and reparses the generated artifact.
  • The non-pink data must match a second entry, and the pink checksum must match before the completed string reaches stdout. The completed preview intentionally reaches stderr earlier; terminal clearing is best effort.
  • Residual operator risk: A damaged existing backup shortened or lengthened to the accepted 35-character shape cannot be distinguished from new worksheet data. The latest security-model edit now says this explicitly. The warning to use only new Book data remains essential.
  • Documentation correction (non-exploitable): docs/security/model.md says nothing is “computed or displayed” before the second entry. _complete_checksum() runs before that entry; only display/output is gated. Please align the wording when convenient.

Patch risk: hold_for_evidence for merge readiness: impact high, regression likelihood moderate, protection partial, recoverability hard, confidence moderate. The code-identical previous head passed cross-platform CI and CodeQL. At this head, two Ubuntu 3.13 jobs are still running; confirm all required checks pass before merging. Because this PR is stacked on #146, retarget it after #146 merges and recheck the final comparison. This review is a comment, not an approval.

@BenWestgate
BenWestgate force-pushed the claude/project-thread-ufnlez branch from 8a04a42 to 1887cf6 Compare October 22, 2026 02:26

@BenWestgate BenWestgate left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI-assisted current-head code/security review.

Concept ACK 1887cf6. ms32 checksum is generation-only, interactive, checks worksheet data twice and the resulting checksum once, and leaves existing check/correct paths unchanged. It cannot authenticate worksheet entropy or prevent incorrectly recorded non-pink data; those limitations are documented. A real-terminal workflow test and security gate remain required before merge.

@BenWestgate BenWestgate left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI-assisted current-head review.

Approach ACK 7fcffa7; not a final code/security ACK. ms32 checksum is isolated from repair, refuses nonterminal input, rechecks worksheet input and confirms the new checksum. The private shared helper matches the maintainer's API decision. Blocked: GitHub reports merge conflicts against its #146 base (dirty), and no current-head CI result is visible. Resolve the stack, rerun checks, and exercise a real-terminal worksheet ceremony before human review.

@BenWestgate BenWestgate left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI-assisted review at maintainer request.

Code ACK 96f6493 (static, scoped to #144). The generic checksum helper reparses its result; ms32 checksum limits input to the Book worksheet, requires double entry and pink-square confirmation, and emits to stdout only after both checks. Malformed-input cases and CI pass. No new finding in this diff.

Before merge: land/review parent #146 and exercise the worksheet flow in a real terminal on supported Tails. The command cannot detect errors already written on the worksheet.

@BenWestgate

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🚀

Reviewed commit: 96f6493e1a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Replay the existing #144 checksum helper and command above the focused #146 stack. The net patch is unchanged; merge-only history from the old dependency has been removed.
@BenWestgate
BenWestgate removed this pull request from stack #168 October 24, 2026 04:34
@BenWestgate
BenWestgate force-pushed the claude/project-thread-ufnlez branch from 96f6493 to dff3bb8 Compare October 24, 2026 04:36
@BenWestgate
BenWestgate force-pushed the claude/project-thread-2q3smy branch from bb52ac4 to 58f9487 Compare October 24, 2026 04:36
@BenWestgate
BenWestgate changed the base branch from claude/project-thread-2q3smy to codex/split146-context October 24, 2026 04:36

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant