P3.4.1 — Signed Time Anchors (STA) — Execution Packet
1. Goal
Implement src/domains/consensus/time-anchors.ts and
src/__tests__/domains/consensus/time-anchors.test.ts per
contract. All build,
lint, and test gates pass.
2. Pre-flight (already done in Steps 1-2)
- Audit committed:
c1329200 - Contract committed:
90277baa - Worktree on
feature/p3-4-1-time-anchorsfromorigin/main @ e63a8bcf - λ Phase 2 dependency confirmed shipped (#226 P2.1.1 → #232 P2.5.1)
- P3.1.1 wave-1 sig path inventoried at
src/domains/consensus/messages.ts
3. Implementation order
Step 4a — time-anchors.ts (single commit)
File layout (top-to-bottom):
§1. Module docstring (similar shape to messages.ts §1; cites s06, s08,
concept, λ P2.1.1, P3.1.1)
§2. Imports (node:crypto named; canonicalize from rules; re-export
ConsensusSerializationError from messages.js)
§3. Re-export error class
§4. Type exports (STA, DriftStatus, MonotonicityFault)
§5. Canonical body — STA-local rewriteBuffersToHex + canonicalSerializeAnchor
§6. signAnchor / verifyAnchor
§7. eligiblePublishers / isEligiblePublisher
§8. computeMedian (replay filter + per-publisher selection + sort + median)
§9. detectDrift
§10. validateMonotonicity
§11. rejectReplay
Estimated 380-420 lines including documentation. Each section gets a JSDoc preamble that cites the spec authority.
Step 4b — time-anchors.test.ts (single commit)
File layout (top-to-bottom):
§1. Module docstring (T1–T30 coverage map)
§2. Imports
§3. Key-pair fixture builder (Ed25519 PURE; uses generateKeyPairSync)
§4. Reputation snapshot fixture builder
§5. Group 1 — STA roundtrip (T1–T4)
§6. Group 2 — eligiblePublishers (T5–T9)
§7. Group 3 — computeMedian (T10–T14)
§8. Group 4 — detectDrift (T15–T18)
§9. Group 5 — validateMonotonicity (T19–T22)
§10. Group 6 — rejectReplay (T23–T26)
§11. Group 7 — Determinism + error re-export (T27, T29, T30)
§12. Group 8 — Forbidden-token scanner (T28)
Estimated 430-460 lines. Each test() has a one-line description that
mirrors the contract test ID for reviewer cross-reference.
4. Risk register (from audit §6)
| Risk | Concrete handling |
|---|---|
| Even-count median floor | bigint division IS floor; test T11 confirms (1000n + 1030n) / 2n === 1015n |
| Single-arbiter eligibility | eligiblePublishers returns full set when n >= map.size; T7 confirms |
| Monotonicity false positives | Strict-> on epoch, non-decreasing on timestamp; T21 confirms same-epoch is non-violation |
| Replay arithmetic | Use current_epoch - 10n literal; T23/T24 cover boundary |
| Drift advisory only | Return type narrow union 'ok' \| 'deprioritized'; T15-T18 cover both directions |
| Buffer leakage in canonical body | canonicalSerializeAnchor strips signature before encoding; mirrors messages.ts stripSignatureForSig |
| Forbidden-token scanner | Test §Group 8; scans source body with comment stripping |
5. Determinism plan
- All quantities
bigint; no float arithmetic. - No
Math.*, noMath.random. - Tests fix seed by passing all
timestamp_ms,epoch, andcurrent_epochas literal bigints. No wall-clock reads. - Ed25519 PURE is deterministic — same key + same message = same signature. Test T4 asserts byte-equal signatures on repeat sign.
6. Build gates
cd E:/AMS/.worktrees/claude/p3-4-1-time-anchors
npm run build # tsc clean
npm run lint # eslint clean — same posture as messages.ts (no
# unused-vars, no any leaks)
npm test # full Jest run — expected delta +30 over 2687
A focused test run for fast iteration:
npm test -- src/__tests__/domains/consensus/time-anchors.test.ts
7. Commit plan
| # | Commit | Description |
|---|---|---|
| 1 | audit | Already done (c1329200) |
| 2 | contract | Already done (90277baa) |
| 3 | packet | This file |
| 4 | feat | time-anchors.ts source + time-anchors.test.ts |
| 5 | verify | docs/verification/p3-4-1-time-anchors-verification.md |
The implementation and test files ship together in commit 4 because the forbidden-token scanner in the test depends on the source file path. The build / lint / test gate runs at the end of commit 4 before the verify commit can declare them green.
8. Out-of-scope (deferred to Wave 3+)
- STA periodic broadcast scheduler (P3.3.x gossip; gossip emits STAs)
- STA-aware proposal priority queue (a future P3.4.2 or downstream of P3.4.1 + P3.3.x)
- STA persistence (an STA store; library-only Phase 3)
- π governance hooks for the four defaults (Phase 4+)
eligiblePublishersdirect-from-DB convenience (usesidx_reputations_leaderboard; deferred)
9. Done definition
time-anchors.tslands with all 8 exports per contract §2time-anchors.test.tslands with all 30 tests per contract §7npm run buildpassesnpm run lintpassesnpm testpasses (≈ 2717 / 2717)- Step 5 verification doc cross-walks every invariant to a test
- PR opens with writeback block per dispatch packet
Ready to implement.