README now presents the widget as the complete login surface (four methods, method-aware events, window.bitlogin session API) and retires the stale 'NIP-46/NIP-07 interop deferred' line. CHANGELOG gains a 2026-08-04 entry -- leading with the 'wasm-unsafe-eval' CSP requirement and the service-worker cache:'reload' pattern, since a vendored site without them has broken password flows. TODO records the shipped expansion and the owner follow-ups: live-fire Amber QR and real-device passkey tests, the new passkey derivation compatibility contract, and the unchanged NIP-46 persistence gate. Removes a dangling on-ramp fragment my earlier llms.txt edit left fused to the passkey bullet. Co-Authored-By: Claude Fable 5 <[email protected]>
6.3 KiB
BitLogin — open items
Updated: 2026-08-04
Login-surface expansion (2026-08-04) — shipped, with owner follow-ups
One login surface, four methods (login-methods.md, passkey-login.md):
password (primary), NIP-07 extension, NIP-46 remote signer (memory-only),
and passkey via WebAuthn PRF. OAuth on-ramps were built, then removed the
same day for requiring per-site provider registration
(centralized-onramps.md, superseded, kept on the record). Also shipped:
the deployment-CSP 'wasm-unsafe-eval' fix (live password flows were
broken since 2026-07-31), the service-worker cache: "reload" precache
fix, window.bitlogin.activeMethod()/activeSession(), and welcome/sign-in
UI polish.
Owner action items:
- Live-fire the NIP-46 QR with Amber on bitlogin.network (flow was verified against a fake bunker in tests, not yet against a real phone signer end-to-end).
- Live-fire passkey sign-in on a real device (Chrome + Google Password Manager, and once on iOS Safari). PRF cannot be exercised in CI; the ceremony paths are untested against real authenticators.
- Passkey derivation is a new compatibility contract —
packages/widget/src/passkey.test.tsknown-answer vectors carry the same never-update-the-expected-value rule asknownAnswer.test.ts. - NIP-46 credential persistence (vault record) stays gated on the external security review, as before.
Entropy audit (2026-07-31)
entropy-audit-2026-07-31.md — RNG and
randomness-integration audit. No predictable-fallback defect: random.ts
is the single chokepoint, throws rather than degrading, and rejection-samples to
avoid modulo bias. Three hardening items, in order:
- M2 — done. Nine tests in
packages/core/src/crypto/crypto.test.tspin fail-closed behaviour andrandomUniformInt's uniformity. Mutation-verified: a zero-filling stub in place of the throw turns five of them red, and swapping rejection sampling for bare modulo gives chi-square 5614 against a threshold of 147. - M1 — done.
nip44Encrypt/nip04Encryptno longer take a nonce or IV; the capability lives in the non-exportedcrypto/testing.ts, andcrypto/index.tsre-exports explicitly instead ofexport *. Only one test ever used an override andivOverridehad no callers, so nothing was lost. Verified from a real consumer against the built package: all three deep-import routes fail withERR_PACKAGE_PATH_NOT_EXPORTED.knownAnswer.test.tsgreen throughout — the derivation chain is untouched. - L1 — done. Both
Math.randomcalls (backup-quiz picker, relay subscription id) now use the CSPRNG, so the ban has no standing exception..semgrep.ymlenforces it in CI alongside two more rules: no fallback aroundgetRandomValues, and no timestamp-seeded secrets. Verified the rules fire — reintroducing the old call gives 1 blocking finding and exit 1.
The entropy audit is closed for this repo. The only gate left is an independent review of the RNG path by someone other than the author, which is not something a coding agent can sign off.
Owner action items
-
Close the Dependabot PR on
dependabot/npm_and_yarn/npm-security-and-maintenance-83024bc549. It bundles seven major bumps into one change (@noble/hashes1.8→2.2,@noble/curves1.9→2.2,@scure/base1.2→2.2,@scure/bip391.6→2.2, TypeScript 5→7, Vite 6→8, Vitest 3→4) and fails the build: noble v2 dropped the extensionless subpath exports this code imports. It should be closed, not merged or fixed —.github/dependabot.ymlnow groups only minor/patch and ignores majors of the derivation chain, so this PR will not recur.The four
dependabot/github_actions/*PRs are unaffected and fine to merge. -
Decide whether the manual-password removal is final. User-chosen passwords were removed entirely (not merely discouraged) in the 2026-07-31 hardening, and
packages/widget/src/securityPolicy.test.tspins that. The security argument is sound — a user-chosen password against a downloadable capsule is offline-guessable forever — but it is a product decision that changes what users can do, and it is now enforced by a test rather than by preference.
Standing rule: the derivation chain is a compatibility contract
Account capsules live on public relays. The login name plus password derive the locator, signing scalar and capsule key deterministically, so those outputs are a contract with every account that already exists — change them and users are locked out permanently, with no server-side record to migrate from.
packages/core/src/crypto/knownAnswer.test.ts pins HKDF-Extract, HKDF-Expand,
ScalarExpand (scalar, counter, and resulting public key), BIP-39 phrase and
seed, base64url framing, and JCS ordering.
A failure there is never "update the expected value". It means the change being attempted is account-breaking and needs a migration plan or rejection. The rest of the crypto suite only checks self-consistency — same input, same output within one run — which stays green through exactly the kind of upgrade that would lock everyone out.
Deferred hardening
Carried from the 2026-07-30 audit; none are live defects.
- Tier 2 —
packages/widget/src/element.tsis ~1,600 lines with no direct test coverage.securityPolicy.test.tsnow asserts a few properties of its source text, which is a start, not coverage. - Tier 3 — compare-and-swap on capsule writes (relays offer no atomic primitive, so this needs a protocol-level answer), and an encrypted high-water-mark store.
- Tier 4 — moving high-value authorization into a cross-origin or extension
boundary. An embedded widget is same-origin with its host page, so a
compromised host can reach the worker directly. Documented honestly in
llms.txtand the README rather than papered over.
Gates still in force
- External security review before the vault holds anything beyond a budget-capped NWC connection. The S3 and password profiles stay designs until then.
- Personal-tier UI was gated on the sudo key leaving the credential capsule. That gate is now met — the sudo key lives only in the phrase-gated recovery capsule — but the UI still needs a separately reviewed key ceremony before it ships.