@volter/twin-inngest 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
// Poll-fold pattern ported from fal-twin.ts's `progressOnce` (fal-twin.ts:245-255): each call to
|
|
27
27
|
// `advanceRun` performs AT MOST ONE meaningful state transition (no wall clock, no timers), so a
|
|
28
28
|
// test suite re-running this file is bit-for-bit reproducible regardless of real elapsed time.
|
|
29
|
-
import { applyTwinWrite, projectResources } from '@volter/world-core';
|
|
29
|
+
import { applyTwinWrite, projectResources, worldNow } from '@volter/world-core';
|
|
30
30
|
import { createHash } from 'node:crypto';
|
|
31
31
|
const SERVICE = 'inngest';
|
|
32
32
|
const DEFAULT_MAX_ATTEMPTS = 4; // modeled default (§13 ⚠4 — doc-UNVERIFIED exact vendor default; config.retries overrides it, see inngest-twin.ts)
|
|
@@ -34,7 +34,7 @@ function kid(type, id) {
|
|
|
34
34
|
return `${type}:${id}`;
|
|
35
35
|
}
|
|
36
36
|
export function nowIso(occurredAt) {
|
|
37
|
-
return occurredAt ??
|
|
37
|
+
return occurredAt ?? worldNow();
|
|
38
38
|
}
|
|
39
39
|
// ── canonical JSON + deterministic stub hashing (ported convention: fal-twin.ts:186-195) ──────
|
|
40
40
|
export function canonicalJson(v) {
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
//
|
|
63
63
|
// `node:crypto` is required LAZILY (server-only), same convention as fal-webhooks.ts, so this
|
|
64
64
|
// module stays browser-bundle safe.
|
|
65
|
-
import { applyTwinWriteAtomic, projectResources, nodeBuiltin } from '@volter/world-core';
|
|
65
|
+
import { applyTwinWriteAtomic, projectResources, nodeBuiltin, worldNow } from '@volter/world-core';
|
|
66
66
|
function nodeCrypto() {
|
|
67
67
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
68
68
|
return nodeBuiltin('node:crypto');
|
|
@@ -160,7 +160,7 @@ function parseHeader(header) {
|
|
|
160
160
|
* `now`), or a signature mismatch (constant-time compare). Pure — never touches the handler. */
|
|
161
161
|
export function verifyInngestSignature(body, header, signingKey, opts = {}) {
|
|
162
162
|
const { t, s } = parseHeader(header);
|
|
163
|
-
const now = opts.now ?? Math.floor(Date.
|
|
163
|
+
const now = opts.now ?? Math.floor(Date.parse(worldNow()) / 1000);
|
|
164
164
|
const tolerance = opts.toleranceSec ?? 300;
|
|
165
165
|
if (Math.abs(now - t) > tolerance)
|
|
166
166
|
throw new InngestSignatureError(`Signature timestamp outside the ${tolerance}s tolerance.`);
|
package/dist/src/inngest-twin.js
CHANGED
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
// Honesty (D2): an unmodeled route returns Inngest's real v2 error envelope
|
|
40
40
|
// (`{errors:[{code,message}]}`, GROUNDED from the fetched v2 OpenAPI `v2ErrorResponse` schema),
|
|
41
41
|
// never a fabricated success. `readOnly` rejects writes with 405.
|
|
42
|
+
import { worldNow } from '@volter/world-core';
|
|
42
43
|
import { advanceRun, cancelRunsForFunction, createRun, functionsCancelledByEvent, functionsMatchingEvent, getRow, listFunctions, recordEvent, registerFunction, runsForEvent, } from "./inngest-runtime.js";
|
|
43
44
|
const SERVICE = 'inngest';
|
|
44
45
|
// The subject types this twin stores and serves — the mirror of the pack descriptor's
|
|
@@ -87,7 +88,7 @@ function parseJson(body) {
|
|
|
87
88
|
}
|
|
88
89
|
}
|
|
89
90
|
function nowIso(occurredAt) {
|
|
90
|
-
return occurredAt ??
|
|
91
|
+
return occurredAt ?? worldNow();
|
|
91
92
|
}
|
|
92
93
|
// ── views ──────────────────────────────────────────────────────────────────────────────────
|
|
93
94
|
const RUN_STATUS_MAP = { QUEUED: 'QUEUED', RUNNING: 'RUNNING', COMPLETED: 'COMPLETED', FAILED: 'FAILED', CANCELLED: 'CANCELLED' };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/twin-inngest",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Local Inngest twin for the durable-execution workflow-orchestration surface: event send/batch (Event API), function register/introspect (SDK exec protocol), and a REAL kernel-persisted step-machine (step.run memoize/replay, sleep/sleepUntil instant-advance, waitForEvent gating, exact retry-attempt counters), run status/get/list/cancel-via-event, HMAC-SHA256 executor<->SDK request signing, built on @volter/world-core.",
|
|
5
5
|
"author": "Volter (https://github.com/volter-ai)",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -35,12 +35,12 @@
|
|
|
35
35
|
"postpack": "node ../../../scripts/publish/prepare-publish.mjs postpack"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
|
-
"@volter/world-core": "2.0.
|
|
38
|
+
"@volter/world-core": "2.0.1"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/bun": "^1.2.20",
|
|
42
42
|
"@types/node": "^24.0.0",
|
|
43
|
-
"@volter/world-core": "2.0.
|
|
43
|
+
"@volter/world-core": "2.0.1",
|
|
44
44
|
"@volter/world-tooling": "0.1.0",
|
|
45
45
|
"inngest": "4.12.0",
|
|
46
46
|
"typescript": "^5.9.0"
|
package/src/inngest-runtime.ts
CHANGED
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
// Poll-fold pattern ported from fal-twin.ts's `progressOnce` (fal-twin.ts:245-255): each call to
|
|
27
27
|
// `advanceRun` performs AT MOST ONE meaningful state transition (no wall clock, no timers), so a
|
|
28
28
|
// test suite re-running this file is bit-for-bit reproducible regardless of real elapsed time.
|
|
29
|
-
import { applyTwinWrite, projectResources } from '@volter/world-core';
|
|
29
|
+
import { applyTwinWrite, projectResources, worldNow } from '@volter/world-core';
|
|
30
30
|
import { createHash } from 'node:crypto';
|
|
31
31
|
|
|
32
32
|
const SERVICE = 'inngest';
|
|
@@ -71,7 +71,7 @@ function kid(type: string, id: string): string {
|
|
|
71
71
|
return `${type}:${id}`;
|
|
72
72
|
}
|
|
73
73
|
export function nowIso(occurredAt?: string): string {
|
|
74
|
-
return occurredAt ??
|
|
74
|
+
return occurredAt ?? worldNow();
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
// ── canonical JSON + deterministic stub hashing (ported convention: fal-twin.ts:186-195) ──────
|
package/src/inngest-signing.ts
CHANGED
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
//
|
|
63
63
|
// `node:crypto` is required LAZILY (server-only), same convention as fal-webhooks.ts, so this
|
|
64
64
|
// module stays browser-bundle safe.
|
|
65
|
-
import { applyTwinWriteAtomic, projectResources, nodeBuiltin } from '@volter/world-core';
|
|
65
|
+
import { applyTwinWriteAtomic, projectResources, nodeBuiltin, worldNow } from '@volter/world-core';
|
|
66
66
|
|
|
67
67
|
type NodeCrypto = typeof import('node:crypto');
|
|
68
68
|
function nodeCrypto(): NodeCrypto {
|
|
@@ -169,7 +169,7 @@ function parseHeader(header: string): { t: number; s: string } {
|
|
|
169
169
|
* `now`), or a signature mismatch (constant-time compare). Pure — never touches the handler. */
|
|
170
170
|
export function verifyInngestSignature(body: unknown, header: string, signingKey: string, opts: { now?: number; toleranceSec?: number } = {}): void {
|
|
171
171
|
const { t, s } = parseHeader(header);
|
|
172
|
-
const now = opts.now ?? Math.floor(Date.
|
|
172
|
+
const now = opts.now ?? Math.floor(Date.parse(worldNow()) / 1000);
|
|
173
173
|
const tolerance = opts.toleranceSec ?? 300;
|
|
174
174
|
if (Math.abs(now - t) > tolerance) throw new InngestSignatureError(`Signature timestamp outside the ${tolerance}s tolerance.`);
|
|
175
175
|
const expected = signInngestRequest(body, t, signingKey);
|
package/src/inngest-twin.ts
CHANGED
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
// Honesty (D2): an unmodeled route returns Inngest's real v2 error envelope
|
|
40
40
|
// (`{errors:[{code,message}]}`, GROUNDED from the fetched v2 OpenAPI `v2ErrorResponse` schema),
|
|
41
41
|
// never a fabricated success. `readOnly` rejects writes with 405.
|
|
42
|
+
import { worldNow } from '@volter/world-core';
|
|
42
43
|
import {
|
|
43
44
|
advanceRun,
|
|
44
45
|
cancelRunsForFunction,
|
|
@@ -120,7 +121,7 @@ function parseJson(body?: string): unknown {
|
|
|
120
121
|
}
|
|
121
122
|
}
|
|
122
123
|
function nowIso(occurredAt?: string): string {
|
|
123
|
-
return occurredAt ??
|
|
124
|
+
return occurredAt ?? worldNow();
|
|
124
125
|
}
|
|
125
126
|
|
|
126
127
|
// ── views ──────────────────────────────────────────────────────────────────────────────────
|