Commit Graph
43 Commits
Author SHA1 Message Date
samiandClaude Opus 5.5 203bd9044d README: plain-language guide for users, hosting and building
ci / test (push) Canceled after 0s
ci / wasm (push) Canceled after 0s
ci / deny (push) Canceled after 0s
ci / fuzz (push) Canceled after 0s
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 10:21:58 +07:00
samiandClaude Opus 5.5 20d465185d Sign in with Google, Apple…: item field, bridge save and identities
ci / test (push) Canceled after 0s
ci / wasm (push) Canceled after 0s
ci / deny (push) Canceled after 0s
ci / fuzz (push) Canceled after 0s
Items record sign_in_with {provider, account}; the browser bridge reports it
with the site's identities and saves it after the usual app prompt. Items
now keep fields they don't know, so editing in an older app never drops what
a newer one added.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
v1.1.0
2026-10-24 15:19:14 +07:00
samiandClaude Opus 5.5 8622123b00 Browser passkeys: ask to unlock instead of falling back when locked
ci / test (push) Canceled after 0s
ci / wasm (push) Canceled after 0s
ci / deny (push) Canceled after 0s
ci / fuzz (push) Canceled after 0s
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-24 14:58:04 +07:00
samiandClaude Opus 5.5 8f0743d964 Passkeys for the browser extension, tags in item lists
The browser bridge answers passkey_query/get/create/result/cancel: the page's
RP ID is checked against the tab origin (no public suffixes), every request
waits for the user to approve it in the app, and the extension polls for the
result. Tags are normalised on save and included in item summaries.
confirm_master_password verifies the user where there are no biometrics.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-24 09:28:51 +07:00
samiandClaude Opus 5.5 d9756d34c1 kv-ffi: report multi-user and open sign-up in server info
ci / test (push) Canceled after 0s
ci / wasm (push) Canceled after 0s
ci / deny (push) Canceled after 0s
ci / fuzz (push) Canceled after 0s
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-24 07:46:11 +07:00
samiandClaude Opus 5.5 92457d4a07 live test: wait out the per-IP auth limit before the second user's new device
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-24 07:40:22 +07:00
samiandClaude Opus 5.5 c84015f67b Multi-user: email sign-in, invite/open registration, admin calls
- kv-proto: email on setup, AccountInfo.email/is_admin, ServerInfo.registration, admin DTOs.
- kv-sync: prelogin by email or account id (setup QR / Emergency Kit), register with email,
  set_email, /v1/admin/* client calls.
- kv-ffi: register_account(code, email), login(.., email), account_details, set_account_email,
  admin_create_invite. kv-wasm: the same plus the full admin API for the web vault.
- Live test: two users on one server stay isolated; a new device signs in by email.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-24 07:35:23 +07:00
samiandClaude Opus 5.5 ead95bb605 server_url / server_pins: the configured sync server, for the apps' Settings
ci / test (push) Canceled after 0s
ci / wasm (push) Canceled after 0s
ci / deny (push) Canceled after 0s
ci / fuzz (push) Canceled after 0s
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-23 23:17:22 +07:00
samiandClaude Opus 5.5 2e16892287 sign_out_device: remove the vault from this device, keep the account on the server
ci / test (push) Canceled after 0s
ci / wasm (push) Canceled after 0s
ci / deny (push) Canceled after 0s
ci / fuzz (push) Canceled after 0s
Syncs first (fails if that sync fails, unless discard_unsynced), ends the session best effort and
wipes the local store, keeping the device identity. Refused for a vault with no server, which would
be lost. Test: unsynced item survives sign-out and returns after signing in again.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-23 23:08:10 +07:00
samiandClaude Opus 5.5 a564633ffb delete_account: re-check the master password, delete on the server, wipe the device
ci / test (push) Canceled after 0s
ci / wasm (push) Canceled after 0s
ci / deny (push) Canceled after 0s
ci / fuzz (push) Canceled after 0s
VaultCore::delete_account verifies the password against the keyset (Secret Key from its sealed copy),
calls DELETE /v1/account when a server is configured (needs a session; a failure deletes nothing),
then wipes the local store and keeps only the device identity. Unit test plus a live test against a
real server.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-22 16:12:46 +09:00
samiandClaude Opus 5.5 86e90569f2 build-apple.sh: kestrove-nmh with a dSYM (App Store Connect wants one per executable)
ci / test (push) Canceled after 0s
ci / wasm (push) Canceled after 0s
ci / deny (push) Canceled after 0s
ci / fuzz (push) Canceled after 0s
Built with debug info, symbols extracted with dsymutil (same UUIDs), then the shipped binary stripped.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-21 20:20:52 +09:00
samiandClaude Opus 5.5 b5a13b16d6 Version 1.0.0
ci / test (push) Canceled after 0s
ci / wasm (push) Canceled after 0s
ci / deny (push) Canceled after 0s
ci / fuzz (push) Canceled after 0s
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-21 16:28:52 +09:00
samiandClaude Opus 5.5 9044b00a2b Browser bridge in the core (shared by the Mac and desktop apps); webpki security update
ci / test (push) Canceled after 0s
ci / wasm (push) Canceled after 0s
ci / deny (push) Canceled after 0s
ci / fuzz (push) Canceled after 0s
- crates/kv-ipc: native-messaging framing and the local IPC socket/pipe (moved from kestrove-desktop),
  plus Listener::bind_in/connect_in and, on macOS, the App Group socket for the kestrove-nmh bundled
  in Kestrove.app (Contents/Resources/kestrove-app-group).
- crates/kv-nmh: the native-messaging host, with an embedded Info.plist on macOS so it can run
  sandboxed (KV_NMH_BUNDLE_ID).
- kv-ffi feature browser-bridge: broker, pairing channel and word list (moved from kestrove-desktop)
  and BrowserBridge for Swift. build-apple.sh enables it and builds a universal kestrove-nmh.
- RUSTSEC-2026-0381/0382: rustls-webpki 0.103.16, webpki-roots 1.0.10 (distrusted emSign roots).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-21 10:02:45 +09:00
samiandClaude Opus 5.5 d45033f424 Bump uniffi 0.28 -> 0.32.2; drop the bincode and paste deny ignores
ci / test (push) Canceled after 0s
ci / wasm (push) Canceled after 0s
ci / deny (push) Canceled after 0s
ci / fuzz (push) Canceled after 0s
uniffi 0.32 no longer depends on bincode (RUSTSEC-2025-0141) or paste
(RUSTSEC-2024-0436), so their ignores go. basic-toml (RUSTSEC-2026-0374)
stays: askama_derive 0.16 in uniffi_bindgen 0.32 still pulls it in.
kv-ffi compiles unchanged; regenerated Swift/Kotlin bindings need no
caller changes in kestrove-apple or kestrove-android.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-20 23:25:22 +09:00
samiandClaude Opus 5.5 2d32b20e81 deny: ignore RUSTSEC-2026-0374 (basic-toml unmaintained, build-time via uniffi_bindgen)
ci / test (push) Canceled after 0s
ci / wasm (push) Canceled after 0s
ci / deny (push) Canceled after 0s
ci / fuzz (push) Canceled after 0s
No known vulnerability and no safe upgrade; only askama_derive 0.12 in uniffi_bindgen 0.28's code generator uses it. Goes away with a uniffi upgrade.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-20 22:42:24 +09:00
samiandClaude Opus 5.5 059398ff58 kv-ffi live test: a removed device re-enrols against the real server
Ignored like the other live test: a phone denied while pending keeps its
identity over a reinstall and a fresh Add-a-device QR signs it straight in as
a new device. Passed against kestrove-server reenroll 62fe35d.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-20 22:40:13 +09:00
samiandClaude Opus 5.5 83d56d43e2 Removed devices: DeviceRevoked, identity reset and one retry with the ticket
kv-sync: SyncError::DeviceRevoked for 403 device_revoked (drops the session);
the test server answers it after OPAQUE (before the ticket) and for valid
signatures by a revoked device's key.

kv-ffi: CoreError::DeviceRevoked; the foreign DeviceSigner gains reset() (new key
and id). On device_revoked the core resets the identity, forgets the session
and the kept OPAQUE input (no silent re-enrolment) and keeps the vault data; a
login carrying a ticket retries once as the new device. reset_device_identity()
runs the reset on demand. Signed calls (sync, devices, tickets, join) reset too.

kv-wasm: DeviceRevoked; the browser binding replaces the WebCrypto key and id in
IndexedDB (same name and platform), loginWithSetup retries once with a ticket;
resetDeviceIdentity().

Tests: end to end revoked -> reset -> re-enrol with the same ticket (kv-ffi and
web core), no-ticket path, in-browser IndexedDB reset.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-20 22:25:03 +09:00
samiandClaude Opus 5.5 460580bcc8 Android: link every target with 16 KB-aligned ELF segments
ci / test (push) Canceled after 0s
ci / wasm (push) Canceled after 0s
ci / deny (push) Canceled after 0s
ci / fuzz (push) Canceled after 0s
Google Play requires 16 KB page-size support for apps targeting Android 15+.
The 64-bit builds happened to be 16 KB-aligned by toolchain default, but
armeabi-v7a was 4 KB. Pin -z max-page-size=16384 for all Android targets.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-19 23:15:30 +09:00
samiandClaude Opus 5.5 1e073e1f09 kv-wasm: forget the Secret Key on logout and on any failed unlock or login
ci / test (push) Canceled after 0s
ci / wasm (push) Canceled after 0s
ci / deny (push) Canceled after 0s
ci / fuzz (push) Canceled after 0s
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-18 07:00:50 +09:00
samiandClaude Opus 5.5 2e2c8cd26f kv-wasm: onboarding (setup codes, enrollment tickets, scan-to-join) for the web vault
Mirrors kv-ffi's docs/10 §5 API in WebCore and binds it under the names the web app codes
against: setupPayloadForKit, addDevicePayload, revokeEnrollmentTicket, loginWithSetup,
joinStart/joinPoll/joinCancel, joinApprove, joinSend, and the free function parseSetupPayload
(also callable through the worker client).

Unlike kv-ffi, the Secret Key is not persisted: every unlock on the web takes it, so it is
kept zeroized in the unlocked state and dropped on lock. loginWithSetup refuses a code for a
different server than the configured origin (the browser only talks to its own origin).

Tests: ticket enrollment and scan-to-join in both roles against kv-ffi via the kv-sync test
server, a swapped-approver rejection, a Chrome test (IndexedDB never holds the Secret Key,
JS shapes, error codes) and a Node smoke check of the built package.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-18 06:58:13 +09:00
sami d70beef92c Merge branch 'wasm' into wasm-onboarding 2026-10-18 06:45:47 +09:00
sami bd25e6fcf7 Merge branch 'onboarding' into wasm-onboarding 2026-10-18 06:45:47 +09:00
samiandClaude Opus 5.5 f9f2d14aa2 kv-wasm: ItemSummary carries tags and modifiedAt for the web vault's filters and sort
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-17 23:59:58 +09:00
samiandClaude Opus 5.5 b5ced32be3 Add kv-wasm: the core compiled to WebAssembly for the web vault
New crate crates/kv-wasm runs the same crypto, item model and sync engine in the browser:
- WebStore: in-memory replica of kv-store's Store, each changed entry written to IndexedDB
  (ciphertext only) before the JS call resolves.
- Device key: non-extractable WebCrypto ECDSA P-256 key in IndexedDB (raw r||s signatures).
- WebCore mirrors kv-ffi's VaultCore; wasm-bindgen surface in camelCase with TypeScript types,
  plus a Web Worker wrapper (connectVault) so Argon2id never blocks the page.
- Tests: Chrome (IndexedDB, WebCrypto, RFC 9421 verify), shared envelope fixtures both ways
  with kv-ffi, native sync with kv-ffi via the test server, Node smoke of the built package.

Small changes to shared crates so they build for wasm32:
- kv-store: SqliteStore moved to a native-only module.
- kv-sync: rustls/pinning/tokio native only (fetch on wasm); DeviceSigner::sign_async (default
  wraps sign) used by ApiClient; unix_now() instead of SystemTime/now_utc.
- kv-model: Public Suffix List behind a default `psl` feature (kv-ffi keeps it; the web build
  drops ~0.9 MB of code and matches same-host only).
- wasm-release profile (opt-level z, Argon2 at 3) and a wasm CI job.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-17 23:58:07 +09:00
samiandClaude Opus 5.5 266fb90e45 Onboarding core: setup payloads, enrollment tickets, scan-to-join (docs/10)
* kv-proto: ticket and join wire types, LoginFinish.ticket, b64_opt.
* kv-crypto: pairing.rs (HPKE AuthPSK seal/open with the QR secret as PSK, SAS code).
* kv-sync: onboarding.rs (kestrove://setup/v1 and kestrove://join/v1 codec with
  strict validation), ApiClient ticket/join calls and login_with_ticket, test
  server support for tickets and rendezvous.
* kv-ffi: parse/encode_setup_payload, setup_payload_for_kit, add_device_payload,
  revoke_enrollment_ticket, login_with_setup, join_start/poll/cancel,
  join_approve/send. The Secret Key is kept locally, HPKE-sealed to enc_pk.
* Tests: codec round trips and rejections, AuthPSK tamper cases, end-to-end
  Add-device QR and scan-to-join between two clients, forged bundles, bound
  tickets; live test extended with scan-to-join.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-17 23:49:48 +09:00
samiandClaude Opus 5.5 f20380d293 Merge hardening: fuzz targets, cargo-deny policy, CI, two parser fixes
ci / test (push) Canceled after 0s
ci / deny (push) Canceled after 0s
ci / fuzz (push) Canceled after 0s
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-17 01:03:36 +09:00
samiandClaude Opus 5.5 37332b4abe Merge import: 1Password .1pux / CSV import and encrypted export
Conflicts in kv-ffi (module list, dev-dependencies) with passkeys: kept both.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-17 01:03:36 +09:00
samiandClaude Opus 5.5 60c5cd9c0b CI: pinned actions, cargo deny, fuzz smoke; build-android.sh works on Linux
- deny.toml: allow-wildcard-paths for the workspace's own path crates; ignore two
  unmaintained notices for uniffi 0.28's build-time deps (bincode, paste).
- build-android.sh ran uniffi-bindgen on libkv_ffi.dylib, which doesn't exist on the
  Linux CI runner; pick .so there.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-17 01:01:44 +09:00
samiandClaude Opus 5.5 83ab00c03c Add cargo-fuzz targets for the untrusted-input parsers and the hardening report
envelope_json, manifest_decode, item_replay, secret_key_parse, totp_parse, url_match,
with seeds. fuzz/README.md records the runs (and the server/desktop targets), the two
bugs fixed in the previous commits, dependency-policy results, CI changes and the
deploy check.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-17 01:01:44 +09:00
samiandClaude Opus 5.5 a15d301b53 kv-sync: saturate seq increments instead of overflowing at u64::MAX
next_version() and the two merge paths in the engine computed max(seq) + 1 on seq
values read from decrypted plaintext. A version carrying seq = u64::MAX panicked in
debug builds and wrapped to 0 in release, so the next save looked like a replay to
every other device. Found while checking fuzz/item_replay; needs an authentic
plaintext, so low severity.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-17 00:52:50 +09:00
samiandClaude Opus 5.5 26664e141b kv-import: 1Password .1pux and CSV import, encrypted export (M5)
New crate kv-import (pure parsing, no store) and kv-ffi/src/import.rs:
- .1pux: accounts -> vaults -> items; Login/Password/Card/Note/Identity mapped, other categories
  as secure notes; unmapped fields appended to notes; attachments and password history reported.
- CSV: 1Password 8 export and generic headers (aliases, BOM, quotes, embedded newlines,
  extra columns into notes).
- Duplicates on (title, username, URL host): skip or add " (imported)".
- Encrypted export KVEX v1: Argon2id (>= account KDF minimum) + XChaCha20-Poly1305,
  authenticated header, padded JSON; restorable through import.
- Caps: 100 MB input, 64 MB decompressed export.data, 10k zip entries, 100k items.
- FFI: VaultCore.import_preview / import_commit / export_encrypted (unlocked only); items are
  sealed, seq-stamped and queued for sync like save_item.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-17 00:36:21 +09:00
samiandClaude Opus 5.5 cee40af622 kv-crypto: SecretKey::parse rejects non-ASCII input instead of panicking
parse() checked the cleaned key's byte length and then split it at byte 26, which
panics when a multibyte character straddles that index (found by
fuzz/secret_key_parse). Under panic = "abort" this would crash the app on a
mistyped or pasted Secret Key.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-17 00:31:16 +09:00
samiandClaude Opus 5.5 8c40b6cccc kv-ffi: passkey API (create_passkey, passkeys_for_rp, get_assertion, list_passkeys, delete_passkey, kestrove_aaguid)
New module crates/kv-ffi/src/passkeys.rs; lib.rs only gains the mod/pub use lines.
Tests verify registrations and assertions like an RP (ciborium + p256), check RP isolation,
reopening the vault and use on a second device after a sync.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-17 00:28:55 +09:00
samiandClaude Opus 5.5 5eb2b622dd Raise workspace rust-version to 1.88 (needed by zip 9, the only non-yanked zip release, for .1pux import)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-17 00:26:06 +09:00
samiandClaude Opus 5.5 13eb5a34ee kv-model: passkey module (ES256, none attestation, AAGUID, KAT + independent verifier tests)
WIP: FFI surface and spec docs not yet added.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-16 22:59:02 +09:00
samiandClaude Opus 5.5 cfab3ab543 kv-sync: authenticated tombstones (sealed {id, seq, deleted: true})
Tombstones carried no ciphertext, so the server could forge a delete (hiding
an item), and a device that pulled one accepted the next live version without
a seq comparison (delete-then-replay rollback).

* A delete is sealed like an item (same AAD and padding) with plaintext
  {id, seq, deleted: true}; seq = working/base seq + 1. DELETE carries it as
  the ItemPut body; the test server stores and serves it.
* replay: Base is None | LegacyTombstone | Sealed(plaintext). check_pulled
  refuses a record without ciphertext, a deleted flag that disagrees with the
  plaintext, or a tombstone naming another item, then requires seq to grow
  for tombstones too. The `restores` exception is gone: edit beats delete
  re-seals with max(edit, tombstone) + 1. next_version returns just seq.
* Legacy: a pulled tombstone without ciphertext is an integrity alarm (cannot
  be told apart from a forgery). A pending legacy delete is sealed on push; a
  legacy tombstone already held as base is accepted as unknown seq.
* engine: open_sealed, seal_tombstone; next_local_version -> u64. Merkle leaf
  hashes a sealed tombstone's envelope like a live record's.
* kv-model Item: `restores` removed. kv-ffi delete_item seals the tombstone;
  FFI surface unchanged.
* Tests: forged (unsealed and relabelled) tombstones raise an integrity alarm
  (kv-sync and kv-ffi), replay after a tombstone, replays of the tombstone and
  of the restore, legacy pending delete, shared item_replay.json table; the
  live test now deletes an item through the real server.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-16 11:34:08 +09:00
samiandClaude Opus 5.5 abcb758b67 kv-sync: refuse per-item replays (seq/restores in the item plaintext)
A malicious server could re-serve an old but valid envelope of an item under
a new, higher revision: the AAD does not bind the revision and the Merkle
root was only checked when head_revision == cursor. The client took it as
the latest version, rolled the item back and signed over it in its next
manifest.

* kv-model Item: `seq: u64` (serde default 0) and `restores: Option<u64>`.
* kv-sync replay module: pure decision rules (check_successor,
  next_version, stamp, same_content). Every pulled live record must
  authenticate and have seq > the base's seq, unless it carries
  restores = t with base_revision < t < revision (edit beat a delete this
  device never saw) or is identical to the base. Otherwise: Integrity alarm.
  Tombstones and items without a base pass.
* engine: check on every pulled record; edit-beats-delete re-seals with
  restores = tombstone revision; merges write seq = max + 1 and adopt the
  remote version when only seq/restores differ. Public
  engine::next_local_version gives the seq/restores for a local save
  (used by kv-ffi save_item and the tests).
* verify_manifest checks the Merkle root whenever no held item is newer
  than head_revision (previously only at head == cursor).
* Tests: replay alarm (clean and pending receivers, plus kv-ffi), harmless
  replay of the current version, tampered envelope, concurrent equal-seq
  edits across three devices, edit-beats-delete with a device that skipped
  the tombstone and a later replay of the restore, legacy items without seq,
  hidden item with cursor past the manifest head, and the shared
  item_replay.json decision table.
* gen-vectors: envelope vector item payload now includes seq.

FFI surface unchanged.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-16 11:08:42 +09:00
samiandClaude Opus 5.5 9da4472ad8 Untrack .DS_Store; compile rustls without TLS 1.2
The transport already restricts to TLS 1.3 (docs/02); dropping the tls12
feature keeps TLS 1.2 code out of the binary entirely.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-16 10:55:29 +09:00
samiandClaude Opus 5.5 2be9a3baad M1: persistent vault, local unlock key, sync client, test vectors
kv-store: SQLite (bundled) and in-memory Store holding only ciphertext
envelopes, with base copies for three-way merges and a 10-version history.

kv-ffi: VaultCore::open(path); persisted account record; local unlock key
(enable/unlock_with_local_key/disable); async sync API (configure_server,
set_device_signer, register_account, login, sync_now, logout, devices);
DeviceSigner foreign trait; IntegrityAlarm/PinMismatch/... error variants.

kv-sync: reqwest + rustls (TLS 1.3 only, ring) with SPKI pinning; OPAQUE
client on kv-proto's OpaqueSuite; RFC 9421 signing per kv_proto::httpsig;
pull/push with If-Match, field-level three-way merge, edit-beats-delete;
signed manifest (canonical CBOR, Merkle root, prev chain, Ed25519) with
rollback/fork/Merkle checks as hard integrity alarms. Tested against a
wiremock fake server, plus an #[ignore] test against kestrove-server.

kv-crypto: gen-vectors example and tests reproducing kestrove-spec/vectors.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 21:52:14 +09:00
samiandClaude Opus 5.5 cbef689903 kv-proto: add PreloginResponse for GET /v1/auth/prelogin
A new device needs account_id and the KDF params to derive AUTH_INPUT
before it can build KE1, so they cannot come only from login/start.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 21:31:46 +09:00
samiandClaude Opus 5.5 48c7e32d33 kv-proto: OPAQUE suite, RFC 9421 signing profile and M1 auth wire types
Adds the OpaqueSuite (Ristretto255 OPRF, TripleDH, SHA-512, identity KSF)
shared by client and server, the httpsig signature-base builders, and the
setup/credentials/account/device/SSE types for milestone M1.
Cargo.lock changes only for kv-proto's new dependencies.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 21:22:03 +09:00
samiandClaude Opus 5.5 4a152bde11 Fix Secret Key decode rejecting valid keys; verify build
The first base32 symbol carries 3 data bits (26 symbols = 130 bits, 2 spare),
but decode only accepted values 0-3, so ~half of generated keys failed to parse.
Adds an edge-case test, rustfmt config, Cargo.lock, and on-demand cross targets
instead of installing all seven in rust-toolchain.toml.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 21:14:15 +09:00
samiandClaude Opus 5.5 462fbbc523 Initial scaffold for kestrove-core
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-15 18:30:14 +09:00