From 7c465b64f44e457817b2c60b49e44bc6eb5782ba Mon Sep 17 00:00:00 2001 From: John Dvorak Date: Sat, 1 Aug 2026 22:58:32 -0700 Subject: [PATCH] js-rigor: challenge proofs treat zero timestamps as valid; flake root-caused MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The transient full-suite flake (fail 1 in ~5-10% of runs, only visible on some invocations) was finally captured: challenge-proof's most-recent-proof property failed once in 800 cases. Root cause: _addChallengeProof built issuedAt with proof.issuedAt || proof.issued_at || proof.timestamp || Date.now() — a generated issuedAt of 0 (epoch) was replaced with the wall clock, so an epoch-issued proof became the most recent one and the lookup returned a timestamp (1.7e12) that could never match the expectation. The same ||-chain corrupted expiresAt: 0 into null, making epoch-expired proofs never expire. All three chains (issuedAt, expiresAt, proofId) now use nullish coalescing so zero is a valid timestamp. Fixed pin added; the challenge-proof file went from ~10% flake to 20/20 clean, and the full suite is stable at 801 tests / 739 pass / 0 fail. --- src/core/PartialGraphContext.js | 9 ++++++--- tests/rigor/challenge-proof.test.js | 20 +++++++++++++++++++- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/core/PartialGraphContext.js b/src/core/PartialGraphContext.js index cc123b3..5e45a1a 100644 --- a/src/core/PartialGraphContext.js +++ b/src/core/PartialGraphContext.js @@ -120,15 +120,18 @@ export class PartialGraphContext { _addChallengeProof(proof) { const subjectId = this._resolveNodeId(proof.subject); const now = Date.now(); - const issuedAt = proof.issuedAt || proof.issued_at || proof.timestamp || now; - const expiresAt = proof.expiresAt || proof.expires_at || null; + // 0 is a valid timestamp (epoch-issued / already-expired); `||` would + // replace it with the wall clock or null, making an epoch-issued proof + // the most recent one and an epoch-expired proof never expire. + const issuedAt = proof.issuedAt ?? proof.issued_at ?? proof.timestamp ?? now; + const expiresAt = proof.expiresAt ?? proof.expires_at ?? null; const record = { name: proof.name, subject: subjectId, issuedAt, expiresAt, source: proof.source || 'partial', - proofId: proof.proofId || proof.proof_id || null, + proofId: proof.proofId ?? proof.proof_id ?? null, metadata: proof.metadata || null }; const key = this._challengeKey(record.name, subjectId); diff --git a/tests/rigor/challenge-proof.test.js b/tests/rigor/challenge-proof.test.js index 38754a4..45e5aed 100644 --- a/tests/rigor/challenge-proof.test.js +++ b/tests/rigor/challenge-proof.test.js @@ -163,6 +163,23 @@ describe('PartialGraphContext.getChallengeProof (rigor)', () => { `getChallengeProof returned an expired proof in ${inv.failureCount} cases`); }); + it('FIXED: zero timestamps are valid, not sentinels', () => { + const ctx = buildContext({ subjectIds: ['user:abc'], proofs: [ + { name: 'mfa', subject: 'user:abc', issuedAt: 42802, expiresAt: null }, + { name: 'mfa', subject: 'user:abc', issuedAt: 0, expiresAt: null } + ] }); + const subjectId = ctx._resolveNodeId('user:abc'); + // issuedAt: 0 must not be replaced with the wall clock + const best = ctx.getChallengeProof('mfa', subjectId, null, 167844); + assert.equal(best.issuedAt, 42802, 'epoch-issued proof must not win via wall-clock stamping'); + // expiresAt: 0 is an already-expired proof, not "no expiry" + const ctx2 = buildContext({ subjectIds: ['user:abc'], proofs: [ + { name: 'mfa', subject: 'user:abc', issuedAt: 100, expiresAt: 0 } + ] }); + const best2 = ctx2.getChallengeProof('mfa', subjectId, null, 167844); + assert.equal(best2, null, 'epoch-expired proof must stay expired'); + }); + it('returns the most-recently-issued proof when withinMs=null', async () => { async function recentCheck(proofs, name, subject, now) { const ctx = buildContext({ subjectIds: [subject], proofs }); @@ -218,7 +235,8 @@ describe('PartialGraphContext.getChallengeProof (rigor)', () => { const inv = report.crucibleVerdict?.invariants?.find(i => i.name === 'most-recent'); assert.ok(inv); assert.equal(inv.passed, true, - `getChallengeProof did not return the most-recent proof in ${inv.failureCount} cases`); + `getChallengeProof did not return the most-recent proof in ${inv.failureCount} cases: ` + + JSON.stringify((report.failures || []).slice(0, 2).map(f => ({ name: f.name, msg: f.message, seq: (f.sequence || []).map(s => s.args) })))); }); it('enforces withinMs freshness window', async () => {