js-rigor: the partial graph carries the temporal context

The partial graph is the caller's self-contained view of the world — so
the time belongs in it. partialGraph.now becomes the evaluation clock for
that check (TTL gates, proof expiry, decay all honor it), with an
explicit options.now taking precedence. The explain rerun replays the
SAME partial graph object and reproduces the original decision; the
serializer records request.temporal.now for the record.

Pins: partialGraph.now driving a challenge decision both sides of the
window, the explicit-override precedence, and the explain rerun with the
same object.
This commit is contained in:
John Dvorak
2026-08-02 10:58:49 -07:00
parent f1167d19fc
commit 0cb0d7c8cb
3 changed files with 35 additions and 0 deletions
+22
View File
@@ -289,3 +289,25 @@ describe('Temporal replay (re-entrant diagnostics) (rigor)', () => {
assert.deepEqual(e.request.temporal, { now: issued + 301000 }, 'challenge temporal recorded');
});
});
describe('Partial graph carries the temporal context (rigor)', () => {
it('FIXED: partialGraph.now drives the decision, and the rerun replays the same object', () => {
const a = new Arbiter();
a.addNode('u:0', 'user');
a.addNode('d:0', 'doc');
a.setRelationConfig('can_download', { type: 'challenge', challenge: 'mfa', subject: 'user', withinMinutes: 5 });
const issued = 500000;
// One self-contained request object: evidence + the caller's time.
const pg = { challenges: [{ name: 'mfa', subject: 'u:0', issuedAt: issued, expiresAt: null }], now: issued + 299000 };
assert.equal(a.check('u:0', 'can_download', 'd:0', { partialGraph: pg }).possibility, 1, 'within window via partialGraph.now');
pg.now = issued + 301000;
assert.equal(a.check('u:0', 'can_download', 'd:0', { partialGraph: pg }).possibility, 0, 'past window via partialGraph.now');
// an explicit options.now overrides the partial graph's time
assert.equal(a.check('u:0', 'can_download', 'd:0', { partialGraph: pg, now: issued + 299000 }).possibility, 1, 'explicit now overrides');
// the rerun replays the same object and reproduces the decision
pg.now = issued + 299000;
const e = a.explain('u:0', 'can_download', 'd:0', { partialGraph: pg });
assert.equal(e.decision.possibility, 1, 'explain rerun with the same partial graph reproduces');
assert.deepEqual(e.request.temporal, { now: issued + 299000 }, 'temporal recorded from the partial graph');
});
});