Files
wz-phone/vault/Reports/T3.2-report.md
Siavash Sameni ed8a7ae5aa docs: protocol audit 2026-05-25, update architecture + Obsidian vault
Audit:
- docs/AUDIT-2026-05-25.md: full protocol audit covering 8 findings
  (4 critical, 2 high, 5 medium, 4 low) with code references and fix
  effort estimates
- vault/Audit/Tasks.md: Obsidian Tasks plugin file tracking all audit
  items with priorities, due dates, and per-step checklists

Architecture docs updated for Wire format v2 and Wave 5/6 features:
- ARCHITECTURE.md: adds wzp-video to dependency graph and project
  structure; wire format updated to v2 (16B header, 5B MiniHeader);
  relay concurrency section corrected (DashMap+RwLock is current, not
  a future optimization); test count 571→702; Android note
- PROGRESS.md: Wave 5 and Wave 6 sections appended; test count 372→702;
  current status and open blockers as of 2026-05-25
- ROAD-TO-VIDEO.md: implementation status table inserted (/🟡/🔴/🔲
  per phase); 6-step critical path to first video call
- WZP-SPEC.md: MediaHeader updated to v2 (16B byte-aligned); MiniHeader
  updated to 5B with seq_delta; codec IDs 9-12 added (H.264/H.265/AV1);
  version negotiation section added

Obsidian vault (vault/):
- 114 files across Architecture/, PRDs/, Reports/, Android/,
  Reference/, Audit/ with YAML frontmatter
- 00 - Home.md index note with wiki links
- .obsidian/app.json config

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 06:00:17 +04:00

3.1 KiB

tags, type, status
tags type status
report
wzp
report Pending Review

T3.2 — Document timestamp_ms rebase across rekey (W3)

Status: Pending Review Agent: Kimi Code CLI Started: 2026-05-11T21:15Z Completed: 2026-05-11T21:25Z Commit: (see git log) PRD: ../PRD-protocol-hardening.md

What I changed

  • crates/wzp-proto/src/packet.rs — Updated doc comment on MediaHeader::timestamp:

    /// Milliseconds since session start. Monotonic for the full session lifetime;
    /// NOT reset by rekey (rekey changes only key material, not framing state).
    pub timestamp: u32,
    
  • crates/wzp-crypto/src/rekey.rs — Added inline comment on perform_rekey():

    /// NOTE: Rekeying changes **only** the symmetric key material.  Sequence
    /// numbers and timestamps in the media framing layer (e.g. `MediaHeader`)
    /// are untouched — they continue monotonically across the rekey boundary.
    
  • docs/WZP-SPEC.md — Updated timestamp_ms field description:

    | timestamp_ms | 32 | ms since session start. Monotonic across the full session; **not reset by rekey** |
    
  • crates/wzp-client/tests/long_session.rs — Added rekey_timestamp_monotonic test:

    • Simulates a 3000-frame session with two conceptual rekey boundaries at frames 1000 and 2000.
    • Collects all MediaHeader::timestamp values across the three phases.
    • Asserts strict monotonicity (non-decreasing) with windows(2).
    • Sanity-checks that at least 3000 timestamps were collected.

Why these choices

The test uses CallEncoder (which owns timestamp_ms) rather than ChaChaSession (which owns RekeyManager) because the property we care about is at the framing layer: regardless of what happens in crypto, the media header timestamps must not jump backwards or reset. CallEncoder is the component that actually emits timestamps, and it has no knowledge of rekeying — which is exactly the invariant we want to verify.

Deviations from the task spec

None.

Verification output

$ cargo test -p wzp-client --test long_session
running 4 tests
test rekey_timestamp_monotonic ... ok
test long_session_no_drift ... ok
test long_session_with_simulated_loss ... ok
test long_session_stats_consistency ... ok

test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 14.62s

Test summary

  • Tests added: 1
    • rekey_timestamp_monotonic — 3000-frame session, two rekey boundaries, verifies timestamp monotonicity
  • Tests modified: 0
  • wzp-client integration test count: 4 (was 3 before T3.2)
  • cargo fmt --all -- --check: pass

Risks / follow-ups

  • The test simulates rekeys conceptually (phase boundaries) rather than invoking RekeyManager::perform_rekey() directly. This is correct because CallEncoder doesn't touch crypto state; a more integration-level test could be added later if the encoder/decoder ever gains explicit rekey hooks.

Reviewer checklist (filled in by reviewer)

  • Code matches PRD intent
  • Verification output is real
  • No backward-incompat surprises
  • Tests cover the new behavior
  • Approved