Skip to content

Rust Core foundation + DeepSeek route + transport/pairing/offline + UniFFI + workflow core (Units 2–5a, 9-core)#455

Merged
thesongzhu merged 13 commits into
mainfrom
rust-core-foundation-20260601
Jun 2, 2026
Merged

Rust Core foundation + DeepSeek route + transport/pairing/offline + UniFFI + workflow core (Units 2–5a, 9-core)#455
thesongzhu merged 13 commits into
mainfrom
rust-core-foundation-20260601

Conversation

@thesongzhu
Copy link
Copy Markdown
Owner

Summary

First landing of the all-Rust Friday Core (the v1 source-of-truth) per the Rust/mobile rewrite goal folder. Purely additive: a new rust-core/ Cargo workspace + one paths-filtered CI workflow; no TypeScript changed. Overall Friday v1 status remains NO-GO (greenfield) — this is foundational, not v1.

Included (committed, tested, reviewed)

  • Unit 2 — Rust Core foundation: SQLite (bundled) schema + forward migrations + destructive-backup guard + refuse-when-newer; hash-chained append-only audit ledger; token ledger; encrypted blob store (XChaCha20-Poly1305); atomic multi-table write; Hub-vs-Phone schema split (phone omits secret/audit tables); domain state machines. Keys ZeroizeOnDrop, no Debug.
  • Unit 3 — DeepSeek Friday-provider route (friday-deepseek, Hub-only): runtime /models discovery, chat, usage→ledger fallback=false, no fallback to any provider/mock; credential read only from the locked env, never logged. Live route smoke proven (gated #[ignore]), direct API probe, no-hidden-call + adverse-credential tests.
  • Unit 4 — transport/protocol/pairing/offline (library + transport-properties): friday-protocol (versioned envelope, version negotiation, idempotency execute-once, resumable replay); offline-queue engine (ack≠completion, exactly-once, approval-fails-closed, atomic receipt); X25519/HKDF E2E session keys with relay-cannot-decrypt proven over real loopback sockets; authenticated pairing (HMAC binds device pubkey to QR secret; MITM-substituted-pubkey rejected) + revoke + rotation; live framed transport over loopback (direct E2E, relay-blind forwarding, reconnect + resumable catch-up).
  • Unit 5a — UniFFI bindings (host): friday-ffi UniFFI interface; Swift+Kotlin bindings generated; a host swiftc client exercised the Rust core over FFI.
  • Unit 9 (core): workflow run/step state machine + evidence-gated completion (a model self-claim never marks a side-effect verified; missing evidence → proof_pending) + Needs-Me urgency-first aggregation.
  • CI: .github/workflows/rust-core.yml (cargo fmt/clippy -D warnings/test on rust-core/**) + pinned toolchain.

Tests / checks

  • cargo test --workspace97 passed / 0 failed (+1 #[ignore]d live DeepSeek route test, run separately with the locked key).
  • cargo clippy --workspace --all-targets -- -D warnings clean; cargo fmt --all -- --check clean; git diff --check clean.
  • Dependency boundary asserted: friday-ffi (phone) excludes friday-deepseek (provider-secret-bearing) — "no provider secret on phone" is a compile-time property.
  • Secret scan clean; DeepSeek key value never committed/logged.
  • Reviewers: per-unit reviewer A (coverage) + adversarial reviewer B + independent re-reviews.

Commits

0ca9d121,21417322 (Unit 2); 07999266 (Unit 3); 3c99759a,34fbc2d8,aeb81c6d,3e4485bf,ef61f7ca,e6b870b7,733a1aaa (Unit 4); aae27f44 (Unit 5a); c4641547 (Unit 9 core); 0d0c3244 (CI).

Honestly NOT done (deferred / gated — NOT claimed PASS)

  • Unit 4 full PASS remaining: WebSocket upgrade/handshake framing wrapper; real-network LAN/Tailscale/SSH multi-host transport; Direct|Relay|Stale conn-state machine over live sockets. (Gate §4 is "first slice only"; loopback proves the security/reconnect/resume properties.)
  • Unit 5b/5c native iOS/Android shells + simulator/emulator screenshots + physical-device proof: operator-gated (no full Xcode/Android SDK/rustup mobile targets/kotlinc in this env).
  • Units 6/7 Codex/Claude adapters + auth: operator-gated provider login.
  • Units 8/10/11 session-detail UI, memory/Context Passport/token-trust, full parity/release/device.
  • The 10 §4 token-safety full-lifecycle no-hidden-call sweep (Unit 3 proved the library-level property only).

Why merging this partial is safe + useful

Purely additive (rust-core/ + one paths-filtered CI workflow); no TS touched; existing CI unaffected; the new workspace is locally proven and now CI-gated. It establishes the v1 Rust source-of-truth foundation later units build on. Overall Friday v1 remains NO-GO.

🤖 Generated with Claude Code

thesongzhu and others added 13 commits June 1, 2026 19:34
Unit 2 of the Friday Rust/mobile rewrite (goal folder 2026-06-01, gate 21).
- friday-core: pure domain types + state machines (incl. offline-queue
  ack!=completion invariant).
- friday-crypto: XChaCha20-Poly1305 field/blob encryption + KEK wrap/rotation
  + SecureStore (in-memory; native Keychain/Keystore deferred to Unit 5).
- friday-storage: SQLite (bundled) schema + forward migrations + destructive
  backup guard + refuse-when-newer; hash-chained append-only audit ledger;
  token ledger (fallback=false); encrypted blob store; atomic multi-table
  write; Hub-vs-Phone schema split (phone omits secret/audit tables).
- friday-deepseek / friday-ffi: dependency-boundary stubs; friday-arch-tests
  asserts friday-ffi excludes friday-deepseek (no provider secret on phone,
  compile-time). DeepSeek route -> Unit 3; UniFFI bindings -> Unit 5.

51 tests pass; clippy -D warnings clean; fmt clean. Overall Friday v1: NO-GO
(greenfield). Not pushed / no PR.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
friday-deepseek: runtime /models discovery + chat/completions through a
Transport seam (ureq blocking client), usage->LedgerEntry mapping with
fallback=false hard-wired. No fallback to any other provider/local/mock — a
failed route returns DeepSeekError (Auth/ProviderUnavailable/...). Credential
read only from FRIDAY_DEEPSEEK_API_KEY on the Hub; never printed/logged.

Tests: 11 offline (mock transport: discovery, usage mapping, fallback=false,
call-counting no-hidden-call, provider-error-does-not-fallback, auth/credential
adverse, JSON shape errors) + 1 gated live route smoke (run with the locked key
sourced) proving real fallback=false from real usage, persisted to token_ledger
(fallback=0). Direct-API probe (GET /models 200, POST /chat 200) captured
secret-safe. Dep boundary unchanged: friday-ffi still excludes friday-deepseek
and ureq.

Closes the Friday-provider-route DeepSeek gate (was NO-GO at intake). Overall
Friday v1 remains NO-GO; the 10 sec4 token-safety gate (full lifecycle sweep)
is deferred to Units 4/5, not claimed closed. Not pushed / no PR.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Versioned E2E envelope (schema_version per message), first-slice Message kinds
(Pair/PairAck/HubStatus/AskFriday{Request,Stream,Result}/LedgerEntry/ActivityItem/
OfflineQueueAck/Error), serde-JSON encode/decode, highest-common-version
negotiation (errors, never silent downgrade), explicit ErrorCode set,
IdempotencyTracker (msg_id dedup => execute exactly once), and ResumableStream
(replay only missed seq frames). 7 tests incl. forward-compat unknown-field
tolerance + explicit unknown-kind rejection.

Pure types + logic; no networking/encryption (transport seals the serialized
payload). Phone-safe (no provider secret); friday-ffi dep-boundary unchanged.

Unit 4 remains IN PROGRESS: offline-queue execution engine, E2E payload
encryption + relay-cannot-decrypt (X25519), pairing/revoke, and the live
networked WebSocket transport are the remaining sub-slices. Overall v1: NO-GO.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
friday-storage::offline — enqueue (idempotent on msg_id; resend returns the
existing row), ack (Queued->Acked), execute_once: requires Acked (an ack is NOT
completion), idempotent (second execute on an Executed action is a no-op),
fails closed when the original approval is no longer valid (no side effect), and
on success flips Acked->Executed while writing an offline_result activity
receipt atomically. Enforces 02 sec15 / gate 21 sec4.4.

4 integration tests: ack-is-not-completion + execute-requires-ack, exactly-once
on re-delivery (side effect runs once, one receipt), approval-invalid
fails-closed (no run, state Failed, no receipt), msg_id dedup.

Workspace: 73 tests pass; clippy -D warnings + fmt clean. Unit 4 still IN
PROGRESS (E2E payload/relay-cannot-decrypt, pairing/revoke, live transport
remain). Overall v1: NO-GO.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
friday-crypto::session — X25519 ECDH device keypairs + HKDF-SHA256 session-key
derivation; envelope payloads sealed under the session key with the existing
AEAD. Proves the relay-cannot-decrypt property (09 sec7/sec8): two paired devices
derive the same key and exchange sealed payloads, while a relay holding only the
public keys cannot derive the key and cannot decrypt forwarded ciphertext; the
legitimate peer can. Private key has no Debug and StaticSecret zeroizes on drop.

4 new tests (13 total in friday-crypto): shared-key agreement, distinct keys for
distinct pairs, relay-cannot-decrypt-but-peer-can, secret-bytes determinism.
Workspace: 77 tests pass; clippy -D warnings + fmt clean. x25519 reaches the
phone (E2E is a phone capability); friday-deepseek still excluded from ffi.

Unit 4 still IN PROGRESS: pairing/revoke (slice d) + live networked transport
(slice e) remain. Overall v1: NO-GO.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- relay-decrypt asserts tightened to == Err(CryptoError::Open) (lock out the
  BadNonce path so a regression cannot pass silently);
- zeroize the intermediate HKDF okm buffer in derive_session_key;
- name x25519-dalek 'zeroize' feature explicitly (guard StaticSecret wipe-on-drop
  against a future default-features change);
- doc note: relay-cannot-decrypt = passive relay; active MITM is prevented by
  authenticated QR pairing (slice d).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
friday-crypto::pairing — HMAC-SHA256(qr_secret, device_pubkey) pairing proof +
constant-time verify. friday-storage::pairing — pair_device (verifies the proof
binds the device pubkey to the out-of-band QR secret; rejects otherwise),
is_trusted, revoke_device, rotate_device_key; each writes an audit_ledger entry
atomically with the trusted_device change.

This discharges the active-MITM property the E2E session module (slice c)
deferred to pairing: a relay substituting its own pubkey without the QR secret
cannot forge a valid proof and is rejected (tested). 9 new tests (crypto 17
total; storage pairing 5) incl. MITM-substituted-pubkey rejection, wrong-secret
rejection, revoke-blocks + double-revoke error, rotation + audit, rotate-revoked
error. Workspace: 86 tests pass (+1 ignored live DeepSeek); clippy -D warnings
+ fmt clean.

Unit 4: library slices a-d done; only live networked transport (slice e) remains
(next session: confirm whether a localhost socket harness is buildable here
before labeling it gated). Overall v1: NO-GO.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
friday-transport: length-prefixed frames carrying friday-protocol envelopes
sealed under friday-crypto X25519/HKDF session keys; recv/send helpers + a relay
model. Proven over REAL loopback TCP (loopback bind/connect confirmed available
in this env):
- direct E2E round-trip (phone<->hub derive the same session key, exchange);
- relay-forwards-ciphertext-but-cannot-decrypt: a real relay hop forwards frames
  while holding no session key; the plaintext never appears in forwarded bytes
  and the relay (own keypair vs the public keys) cannot decrypt a captured frame;
- reconnect + resumable catch-up: after a dropped connection the phone reconnects,
  reports its last-acked seq, and the hub replays exactly the missed frames.
6 tests (3 unit + 3 socket integration). Workspace: 92 tests pass; clippy
-D warnings + fmt clean; friday-ffi still excludes friday-deepseek.

Scope: proves the transport's security/reconnect/resume PROPERTIES over a real
socket; the WebSocket upgrade/handshake framing is a mechanical wrapper around
the same frame+seal contract (the only remaining transport detail). Overall
v1: NO-GO.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…view nits)

- README: update to Units 2-4 (crate table, 92-test count, security properties,
  accurate deferred list) — was stale at the Unit-2 '52 tests' snapshot.
- friday-transport doc: WS framing is *a* remaining transport detail, not the
  *only* one (real-network LAN/Tailscale/SSH transports + Direct|Relay|Stale
  connection-state machine are also first-slice-deferred per gate 21 §4).

Doc-only; no behavior change. Overall v1: NO-GO.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
friday-ffi: UniFFI 0.31 proc-macro/library mode (cdylib + lib) exposing a
first-slice, FFI-safe interface (ConnStateFfi enum; initial_connection_state,
connection_is_online, connection_is_stale_or_offline, protocol_schema_version,
negotiate_schema_version) over friday-core + friday-protocol. Added a
uniffi-bindgen bin for host binding generation.

Generated Swift + Kotlin bindings from the built cdylib; a host swiftc-compiled
sample client called into the Rust core through the generated Swift bindings and
returned correct results (schema=1, conn-state + version-negotiation) -- 'Swift
bindings exist and are exercised by a sample client' (gate 03 §8). Kotlin
generation succeeded; Kotlin run-smoke is gated (no kotlinc). Native app shells +
simulator/emulator screenshots + device proof remain operator-gated (no full
Xcode/Android SDK/rustup mobile targets).

Trust boundary preserved: friday-ffi still excludes friday-deepseek (asserted).
Workspace: 93 tests pass; clippy -D warnings + fmt clean. Overall v1: NO-GO.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
friday-core::workflow — WorkflowRunState machine (Pending/Running/
AwaitingCheckpoint/Done/Failed, checkpoints pause the run); StepStatus +
resolve_step_completion encoding the load-bearing invariant (08 §6 / 10 §6 /
00 §2): a side-effect step is Verified ONLY with deterministic evidence, else
ProofPending -- a model self-claim never marks a side-effect verified; only
no-side-effect steps may complete on a model result. NeedsMeItem +
aggregate_needs_me (urgency-first, stable; preserves provider detail).

4 new friday-core tests. Workspace: 97 passed / 0 failed (+1 ignored live
DeepSeek); clippy -D warnings + fmt clean.

Scope: Unit-9 CORE logic (evidence-gating + needs-me invariants). Workflow/activity
PERSISTENCE + Activity inbox UI are remaining Unit-9 work. Overall v1: NO-GO.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…int)

.github/workflows/rust-core.yml: runs cargo fmt --check, clippy -D warnings, and
cargo test --workspace for rust-core/** on PRs and main pushes (paths-filtered;
the live DeepSeek test is #[ignore]d so no network/secrets needed).
rust-core/rust-toolchain.toml pins 1.95.0 + clippy/rustfmt so CI matches local.

Gives the merged all-Rust workspace a real CI gate. Overall v1: NO-GO.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@thesongzhu thesongzhu merged commit 538ee2d into main Jun 2, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant