Clone this repository
For self-hosted knots, clone URLs may differ based on your setup.
Download tar.gz
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
Critical:
- Add 7 unit tests for serde serialization contract (AC2.2, AC2.5, AC3.1-AC3.5)
- create_mobile_account_request_serializes_camel_case: verifies camelCase field names
- create_account_result_serializes_camel_case: verifies nextStep serialization
- error_*_serializes_correctly: 5 tests for all CreateAccountError variants
Important:
- Change CreateAccountResult and CreateAccountError from interface to type
(pure data shapes, not class contracts; CreateAccountParams correctly stays interface)
- Use LazyLock<RelayClient> static for RELAY_CLIENT to avoid allocating new
connection pool and TLS session per IPC invocation
Minor:
- Remove greet dead code: greet command, tests, and generate_handler! entry
- Document OnboardingStep deviation: per-screen error rewinding is better UX
than a dedicated error screen (no 'error' step needed)
Verification:
- cargo test --lib: 7/7 tests pass
- cargo build --workspace: success
- cargo clippy --workspace -- -D warnings: success
- cargo fmt --all --check: success
- pnpm build: success
- svelte-check: 0 errors, 0 warnings