Repository navigation
Epic 4: stop claiming things that aren't true - #369
Merged
Merged
Conversation
Two fixes to claims the code does not make. - "A `did:keri` derived from your **Ed25519** key" — the default is P-256, and has been since the Secure Enclave work: iOS's enclave holds P-256 and not Ed25519, so hardware-backed mobile pairing requires it. `auths demo` emits `did:key:zDna…` (P-256 multicodec); `z6Mk…` would be Ed25519. - Replaces the implied offline-verification differentiator with the claim that survives scrutiny. Cosign has shipped `--offline` since 2023-02-23 and v3 made offline-capable bundles the default; v4 deprecates `--rekor-url` outright. GitHub documents offline attestation verification first-party. "We verify offline" invites a correction in the first technical conversation. What is actually true and narrower: their offline path checks against a trust-root *snapshot*, so a rotation or revocation you have not downloaded is one you cannot see — GitHub's own docs say "You will not know if key material has been revoked since you last generated the trusted root file", and sigstore-python#1175 proposes erroring after ~a week offline. A KEL carries its own rotation history. That is a trust-freshness claim about long-lived device keys, which is precisely Auths's model and precisely not Sigstore's. Also documents the trust/KEL distribution that Epic 1 made real. Not changed: the README lists 10 commands where `--help-all` shows 45. That is a curated quick-reference that already points at `--help-all` on the next line — deliberate, not drift.
Three related fixes to `auths init` and every registry-touching verb. They are one commit because they are interleaved in the same struct and the same test fixtures — splitting them yields commits that do not compile, which is worse than an honest combined one. 1. No default registry (4.1). `DEFAULT_REGISTRY_URL` was `https://registry.auths.dev`, which returns HTTP 404 (Vercel: DEPLOYMENT_NOT_FOUND) — the worst failure shape there is: it looks configured and dies at the network. It was the default for `init --registry`, `publish`, `account`, `org join`, `id claim|register`, `artifact publish` and `namespace`, and `auths doctor` probed it on every run, so every user saw a failing "Registry connectivity" check for a service they neither had nor needed. Nothing needs it: identity, signing and verification are local and git-native, and since Epic 1 a signer's KEL reaches a verifier over the same git remote as the code. "No central server" is the README's own headline; a default that contradicts it is worse than no default. Registry use is now explicit (`--registry` / `AUTHS_REGISTRY_URL`), refused through one shared `require_registry` so the message is stated once, in terms of what the user can do: "Auths needs no registry … pass --registry only if you are running one." New `RegistrationError::NoRegistryConfigured` (AUTHS-E5400). Doctor now reports "not configured (optional)" and passes. 2. GitHub linking is no longer gated on `--register` (4.2). Linking uploads the SSH signing key, and that is the only thing that makes a user's commits render Verified to everyone else. It sat behind `interactive && cmd.register` — a flag whose documented job is publishing to the (dead) registry. So the default first run left commits Unverified while the code to fix it was one boolean away. Research puts a number on the cost: 73.73% of commit-signature verification failures in the wild are `unknown_key` — developers sign and never register the key; "a usability problem, not a cryptographic one" (arXiv:2604.14014). Auths mints the key, signs with it, and emits a standard SSHSIG that GitHub *can* verify — the thing that is structurally impossible for gitsign, whose CA is not in GitHub's trust root. New `--github` / `--no-github`, defaulting on when the repo has a GitHub remote and there is a TTY. Remote detection matches on the parsed host, never a substring: `github.com.evil.example` is a different host. 3. A scripted init no longer rewrites your global git config (4.4). `prompt_for_git_scope` returned `Global` unconditionally when non-interactive, with no flag to override — so `auths init --non-interactive`, the CI and agent path, silently rewrote `~/.gitconfig` and repointed `core.hooksPath` machine-wide, disabling every repo's own `.git/hooks` (husky, pre-commit, prek) as a side effect. New `--git-scope local|global|skip`, defaulting to `local` when non-interactive. Verified: `--non-interactive` leaves ~/.gitconfig byte-identical (md5), while `--git-scope global` still writes it and `skip` touches nothing.
Follow-on from scoping `auths init` to the repo by default: the doctor read `git config --global`, so a correctly configured repo reported as broken. Two reads were wrong in the same way — `system_diagnostic::get_git_config` (the "Git signing config" check) and `check_commit_hook_installed`'s `core.hooksPath`. Both now read the effective value. That is not merely "what makes the tests pass" — it is the value git itself resolves, which is the only thing a diagnostic about git's behaviour should assert on. A global-only read was already wrong for anyone who had scoped signing to one repo by hand. The integration tests caught this, and two of them encoded the old behaviour rather than the intent: - `test_init_happy_path` asserted the *global* gitconfig gains ssh signing. It now asserts the opposite — a scripted init must leave ~/.gitconfig alone — and that the repo-local config gains it instead. - `test_doctor_detects_missing_gpg_format` unset `gpg.format` from --global, a scope init no longer writes. It would have silently no-op'd and passed for the wrong reason; it now unsets --local. 400 tests green across auths-cli (67 integration + 157 lib) and auths-sdk (176).
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Auths Commit Verification
Result: ❌ 0/3 commits verified How to fixCommit 1. Install auths macOS: 2. One-time setup (creates your identity and configures Git) auths init3. Sign this branch and push auths sign origin/main..HEAD
git push --force-with-leaseFor CI to verify the signer, commit an identity bundle: auths id export-bundle --alias main --output .auths/ci-bundle.json --max-age-secs 31536000 |
The golden-path smoke test caught a real design flaw in the previous commit, not a test artifact: defaulting `--non-interactive` to `local` unconditionally breaks `auths init` run outside a git repository, because `git config --local` there is an error. `docs/smoketests/end_to_end.py:241` runs init from the home directory and creates the repo afterwards — which is not a contrived case but an ordinary first run. It failed rc=1 and took nine downstream assertions with it. The default is now local **when standing in a repository**, global otherwise. That is what makes the conservative default safe rather than merely strict: the surprise being fixed is "I ran a scripted init inside my repo and it silently reconfigured my whole machine". A user who is not in a repository has nothing to scope to, and is not being surprised by machine-wide config — it is the only scope that means anything there. `--git-scope` still decides outright. Also regenerates the error docs for AUTHS-E5400 (the `gen-error-docs --check` gate was correctly red) and reflows its message to a single line: the generator extracts the raw source string, so `\` line-continuations rendered literally in docs/errors/AUTHS-E5400.md. The unit test for the default was dropped in favour of asserting explicit `--git-scope` in all three directions — the default is now CWD-dependent, so testing it in a unit test would assert on wherever cargo happened to run. The integration suite controls the working directory and covers it properly. Verified: golden-path smoke 60/60 (was 50/60); inside a repo the global gitconfig is byte-identical while the repo-local config gains signing; outside a repo init succeeds and configures global.
Auths Commit Verification
Result: ❌ 0/4 commits verified How to fixCommit 1. Install auths macOS: 2. One-time setup (creates your identity and configures Git) auths init3. Sign this branch and push auths sign origin/main..HEAD
git push --force-with-leaseFor CI to verify the signer, commit an identity bundle: auths id export-bundle --alias main --output .auths/ci-bundle.json --max-age-secs 31536000 |
bordumb
added a commit
that referenced
this pull request
Jul 17, 2026
) * fix(cli): keep global the default scope; guard the hooksPath instead I over-corrected in 3c21e0c, and two suites said so before I listened. Reverting the default and fixing the thing that was actually harmful. `auths init`'s own description is "Create your signing identity and configure Git", and its *interactive* default is already "All repositories". Making --non-interactive default to something else made the scripted path disagree with the prompted one, and broke two real flows: the golden-path smoke test inits from a home directory (where `git config --local` is an error), and the E2E suite inits in one repo and commits in another (so repo-scoped signing left commits unsigned — "No signature found", 3 tests, which I merged in #369 before noticing). Setting up signing for one repo and silently not the next is its own surprise. The default is global again. What was genuinely wrong in W4 was never the default — it was that the scope was **unchooseable**: `--non-interactive` hard-returned Global with no override, so a scripted, CI or agent init had no way to keep its hands off ~/.gitconfig. `--git-scope local|global|skip` closes that, and stays. And the actual harm — clobbering `core.hooksPath` — is now guarded. It replaces .git/hooks entirely, so pointing it at ours when husky/pre-commit/prek already own it silently disables every hook they installed; the user experiences that as "my pre-commit checks stopped running" with nothing tying it to `auths init`. `enable_commit_trailers` refuses, naming the occupying path and the two ways out. Needed a `get` on GitConfigProvider — a port that could only write was how this went unnoticed. Tests: the two I "fixed" in bbc5b88 to match the over-correction are restored, plus new coverage for the capability that is actually new (`--git-scope local` leaves ~/.gitconfig byte-identical; `skip` touches nothing but still pins the root), and two SDK tests for the clobber guard including its message being actionable rather than merely a refusal. Verified: golden-path smoke 60/60 · e2e git-signing + key-rotation 9/9 · cli integration 69 · cli lib 157 · sdk lib 180 · clippy 0 errors. * fix(cli): drop the helper the reverted default left dead `in_git_repository` and its import became unused when the git-scope default went back to global. CI builds with `-D warnings`, so dead code is an error there and merely a warning locally — which is why this passed my `cargo build` and failed Clippy, MSRV, smoke and KERI conformance all at once.
This branch was successfully deployed
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.
Four fixes where the product asserted something the code didn't do. Ordered by how much they cost a new user.
4.1 — The default registry was a 404
DEFAULT_REGISTRY_URL = "https://registry.auths.dev"returns HTTP 404 (Vercel:DEPLOYMENT_NOT_FOUND). Verified again today. It was the default forinit --registry,publish,account,org join,id claim|register,artifact publishandnamespace— andauths doctorprobed it on every run, so every user saw a failing "Registry connectivity" check for a service they neither had nor needed.That's the worst failure shape available: it looks configured and dies at the network.
Nothing needs it. Identity, signing and verification are local and git-native, and since Epic 1 a signer's KEL reaches a verifier over the same git remote as the code. "No central server" is the README's own headline; a default contradicting it is worse than no default.
Registry use is now explicit, refused through one shared
require_registryso the message is stated once, in terms of what the user can do:New
RegistrationError::NoRegistryConfigured(AUTHS-E5400). Doctor reports "not configured (optional)" and passes.Per your decision on the roadmap's Open Question 3. Checked first that no sibling repo depends on the constant —
auths-github-appcarries its own copy of the string, so it's unaffected.4.2 — The green badge was gated behind an unrelated dead flag
Linking GitHub uploads the SSH signing key, and that is the only thing that makes a user's commits render Verified to everyone else. It sat behind
interactive && cmd.register— a flag whose documented job is publishing to the (404) registry. So the default first run left commits Unverified while the code to fix it was one boolean away.The research puts a number on the cost: 73.73% of commit-signature verification failures in the wild are
unknown_key— developers sign and never register the key. The authors' verdict: "a usability problem, not a cryptographic one" (arXiv:2604.14014). Auths mints the key, signs with it, and emits a standard SSHSIG GitHub can verify — the thing that is structurally impossible for gitsign, whose CA isn't in GitHub's trust root (gitsign#40, open since 2022).New
--github/--no-github, defaulting on when the repo has a GitHub remote and there's a TTY. Remote detection matches on the parsed host, never a substring —github.com.evil.exampleis a different host, and there's a test that says so.4.3 — README: wrong curve, and a claim that wouldn't survive contact
did:keriderived from your Ed25519 key" — the default is P-256 (the iOS Secure Enclave holds P-256, not Ed25519, so hardware-backed mobile pairing requires it).auths demoemitsdid:key:zDna….--offlinesince 2023-02-23, v3 made offline bundles the default, v4 deprecates--rekor-url. What's actually true is narrower — their offline path checks a trust-root snapshot, so a revocation you haven't downloaded is one you can't see (GitHub's own docs say exactly that). A KEL carries its own rotation history. That's a trust-freshness claim about long-lived device keys — Auths's model, and precisely not Sigstore's.Not changed: the README lists 10 commands where
--help-allshows 45. My roadmap called that drift; it isn't — it's a curated quick-reference that points at--help-allon the next line. My report was unfair there.4.4 — A scripted init rewrote your global git config
prompt_for_git_scopereturnedGlobalunconditionally when non-interactive, with no flag to override. Soauths init --non-interactive— the CI and agent path — silently rewrote~/.gitconfigand repointedcore.hooksPathmachine-wide, disabling every repo's own.git/hooks(husky, pre-commit, prek) as a side effect.This repo is living with that right now: its prek pre-commit and pre-commit pre-push hooks are being bypassed by exactly this.
New
--git-scope local|global|skip, defaulting tolocalwhen non-interactive. Verified:--non-interactive(default)--git-scope local--git-scope global--git-scope skipThe follow-on the tests caught (
bbc5b889)Scoping init to the repo exposed that the doctor read
git config --globalin two places, so a correctly configured repo reported as broken. Both now read the effective value — which is what git itself resolves, and was already wrong for anyone who'd scoped signing by hand.Two integration tests encoded the old behaviour and were corrected, not silenced:
test_init_happy_pathnow asserts a scripted init leaves~/.gitconfigalone;test_doctor_detects_missing_gpg_formatunset--global, a scope init no longer writes, so it would have no-op'd and passed for the wrong reason.Verification
cargo test -p auths-cli --test integration→ 67 passedcargo test -p auths-cli --lib→ 157 passedcargo test -p auths-sdk --lib→ 176 passedcargo clippy -p auths-sdk -p auths-cli --all-targets→ clean ·cargo fmt --all→ appliedOn commit granularity
You asked for one commit per task. 4.1, 4.2 and 4.4 are interleaved in the same struct and the same five test fixtures in
init/mod.rs— splitting them produces commits that don't compile. I combined those three and kept 4.3 and the diagnostics follow-on separate, rather than fake atomicity.