From a697ebda859bd2b5cabc69a070db63cb7c786070 Mon Sep 17 00:00:00 2001 From: Haining Yin Date: Fri, 3 Jul 2026 09:35:48 +0200 Subject: [PATCH 1/2] fix(aep): Date.now() default timestamps + addAction capability_decision sync Two fixes in AEPEmitter: 1. Replace performance.now() with Date.now() for all default timestamps. performance.now() returns ms-since-process-start (~730ms), not Unix epoch, causing downstream tools to show 1970-01-01 for all records. (#14) 2. addAction() with capability_decision now auto-registers to the record-level capability_decisions[] array (deduped by capability+subject+resource). Previously the split API caused silent empty manifests. (#15) Fixes #14 Fixes #15 Co-Authored-By: Claude Opus 4.6 --- .changeset/fix-emitter-timestamps.md | 11 +++++++++++ packages/aep/src/emitter.ts | 13 ++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 .changeset/fix-emitter-timestamps.md diff --git a/.changeset/fix-emitter-timestamps.md b/.changeset/fix-emitter-timestamps.md new file mode 100644 index 0000000..30b50d5 --- /dev/null +++ b/.changeset/fix-emitter-timestamps.md @@ -0,0 +1,11 @@ +--- +"@wasmagent/aep": patch +--- + +fix(aep): use Date.now() instead of performance.now() for default timestamps + +- `emit()` / `build()` now defaults `created_at_ms` to `Date.now()` (Unix epoch ms) instead of `performance.now()` (ms since process start). Fixes records showing `1970-01-01` in downstream audit tools. +- `addAction()` without explicit `timestamp_ms` also defaults to `Date.now()`. +- `addAction()` with `capability_decision` now auto-registers to `capability_decisions[]` (deduped), fixing silent empty manifest in downstream `toEvents()`. + +Fixes: #14, #15 diff --git a/packages/aep/src/emitter.ts b/packages/aep/src/emitter.ts index 14ed148..e00974e 100644 --- a/packages/aep/src/emitter.ts +++ b/packages/aep/src/emitter.ts @@ -47,9 +47,16 @@ export class AEPEmitter { ): void { this.#actions.push({ action_id: action.action_id ?? `action-${this.#actions.length}`, - timestamp_ms: action.timestamp_ms ?? performance.now(), + timestamp_ms: action.timestamp_ms ?? Date.now(), ...action, } as ActionEvidence); + if (action.capability_decision) { + const cd = action.capability_decision; + const exists = this.#capabilityDecisions.some( + (d) => d.capability === cd.capability && d.subject === cd.subject && d.resource === cd.resource + ); + if (!exists) this.#capabilityDecisions.push(cd); + } } addCapabilityDecision(decision: CapabilityDecision): void { @@ -78,7 +85,7 @@ export class AEPEmitter { * * For a fully signed record use `emit()` instead. * - * @param createdAtMs - Override creation timestamp (defaults to performance.now()). + * @param createdAtMs - Override creation timestamp (defaults to Date.now()). * @param signerOverride - Optional: provide a signer to sign inline (async variant). * Prefer `emit()` for async signing. */ @@ -150,7 +157,7 @@ export class AEPEmitter { actions: this.#actions, verifier_results: this.#verifierResults, budget_ledger: this.#budgetLedger, - created_at_ms: createdAtMs ?? performance.now(), + created_at_ms: createdAtMs ?? Date.now(), }; } From 5550aab2cd7b9deff77e2137eb31c7b5cf100647 Mon Sep 17 00:00:00 2001 From: Haining Yin Date: Fri, 3 Jul 2026 09:40:44 +0200 Subject: [PATCH 2/2] style: biome format emitter.ts Co-Authored-By: Claude Opus 4.6 --- packages/aep/src/emitter.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/aep/src/emitter.ts b/packages/aep/src/emitter.ts index e00974e..0a52026 100644 --- a/packages/aep/src/emitter.ts +++ b/packages/aep/src/emitter.ts @@ -53,7 +53,8 @@ export class AEPEmitter { if (action.capability_decision) { const cd = action.capability_decision; const exists = this.#capabilityDecisions.some( - (d) => d.capability === cd.capability && d.subject === cd.subject && d.resource === cd.resource + (d) => + d.capability === cd.capability && d.subject === cd.subject && d.resource === cd.resource ); if (!exists) this.#capabilityDecisions.push(cd); }