Clone this repository
For self-hosted knots, clone URLs may differ based on your setup.
Download tar.gz
Eliminate duplicated patterns identified in a full codebase scan:
- P1: New `routes::token` module — `generate_token()`, `sha256_hex()`,
`hash_bearer_token()` replace 10+ copy-pasted token generation/hashing
blocks across route handlers and auth functions.
- P2: Centralize `is_unique_violation()` and `unique_violation_column()`
in `db::mod` — replaces 4 divergent implementations of SQLite constraint
classification in claim_codes, create_account, create_did, and
create_mobile_account.
- P3: New `routes::uniqueness` module — `email_taken()` / `handle_taken()`
extract the identical OR EXISTS pre-flight queries from create_account
and create_mobile_account.
- P4: Replace string-based `is_valid_platform()` with a `Platform` enum
that deserializes via serde, moving validation to the type system.
- P5: Extract `base32_lowercase()` helper in crypto::plc to deduplicate
the base32 encoding setup used in both build and verify paths.
- P6: Break up the 270-line `create_did_handler` into a 45-line
orchestrator calling six focused helpers: load_pending_account,
verify_and_validate_genesis_op, pre_store_did, check_already_promoted,
post_to_plc_directory, promote_account.
- P7: Remove AC-prefixed test section comments in crypto::shamir per
project convention (no ticket references in source code).
Net: -505 lines added / +669 lines = ~114 fewer lines of production code
(new lines are the extracted modules + design plan doc). All 328 tests pass.
Strip MM-NNN and AC-numbered comments from .rs files and CLAUDE.md files.
Source comments now describe system behavior, not ticket traceability.
Adds a CLAUDE.md convention to prevent recurrence.
Replaces `next_step: String` in CreateMobileAccountResponse and
CreateAccountResult with a typed `NextStep` enum. Serde rejects any
relay response with an unrecognized next_step value at deserialization
time, surfacing it as CreateAccountError::Unknown rather than silently
forwarding an unknown string to the frontend.
TypeScript now sees `nextStep: 'did_creation'` (a literal type), so
the redundant if/else check in +page.svelte is removed — the type
system and Rust enum together guarantee the value at this point.
Adds three NextStep serde tests: correct deserialization, correct
serialization, and rejection of unknown values.
- Complete compensation path: session-token failure now also deletes
device-token to avoid orphaned credentials
- Extract map_409_subcode() helper; test calls the real function instead
of duplicating its logic
- HandleScreen: tighten handle regex to RFC 1035 DNS label (no dots or
underscores — these create multi-label handles or violate DNS spec)
- CLAUDE.md: document delete_item in both keychain listings
CRITICAL fix:
- Prevent orphaned private key on token-storage failure: add keychain::delete_item()
and best-effort cleanup when device-token or session-token write fails after relay
201 success. This prevents a situation where the account is created on relay but
the device has no tokens due to local Keychain failure.
IMPORTANT fixes:
- Map keychain failures to new CreateAccountError::KeychainError (not Unknown),
giving users accurate error message: 'Couldn't save credentials to your device.
Try again.' instead of misleading 'Couldn't reach the server.'
- Distinguish UNKNOWN from NETWORK_ERROR: NETWORK_ERROR is genuine connectivity
failure, UNKNOWN is for relay-reachable errors (e.g., unrecognized 409 subcodes).
Frontend routes each to different screens with appropriate messages.
- Fix 404 comment to clarify relay returns 404 for both invalid and expired codes.
- Add unit test for 409 subcode dispatch table to prevent typos in
CLAIM_CODE_REDEEMED/ACCOUNT_EXISTS/HANDLE_TAKEN mapping.
- Fix HandleScreen handle validation: change from non-empty string to ATProto
regex /^[a-zA-Z0-9]([a-zA-Z0-9._-]*[a-zA-Z0-9])?$/ to prevent relying on
relay validation for invalid formats.
- Update CreateMobileAccountResponse comment to note that relay returns 5 fields
but only 3 are captured (additional fields ignored by serde).
- Add console.error for unexpected nextStep values in submit flow.
- Update ipc.ts with KEYCHAIN_ERROR variant and clean up JSDoc.
- Add Cargo.toml comment explaining rustls-tls requirement (no OpenSSL on iOS).
- Update CLAUDE.md to clarify keypair generation behavior: fresh keypair per
attempt (with best-effort Keychain cleanup on failure), not retry reuse.
TESTS:
- Add CreateAccountError::KeychainError serialization test
- Add CreateAccountError::Unknown serialization test
- Add 409 subcode dispatch table test (verifies correct mapping of
CLAIM_CODE_REDEEMED, ACCOUNT_EXISTS, HANDLE_TAKEN, unknown subcodes)
All tests pass: cargo test --workspace (231 tests)
Clippy: no warnings
Formatting: passes
Frontend: pnpm build succeeds, svelte-check passes