@volter/twin-fal 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.
@@ -45,7 +45,7 @@
45
45
  // Kernel SUBJECT ids are type-prefixed (`request:<uuid>`) — the PUBLIC request_id emitted to
46
46
  // clients is the bare uuid. `kid()` builds the subject id; `rows()` strips the prefix back off.
47
47
  import { createHash } from 'node:crypto';
48
- import { applyTwinWrite, projectResources } from '@volter/world-core';
48
+ import { applyTwinWrite, projectResources, worldNow } from '@volter/world-core';
49
49
  import { falJwks } from "./fal-webhooks.js";
50
50
  const SERVICE = 'fal';
51
51
  // Resource types the twin actually PROJECTS in the kernel — the honest v1 subset. `signing_key`
@@ -114,7 +114,7 @@ function parseBody(body) {
114
114
  }
115
115
  }
116
116
  function nowIso(occurredAt) {
117
- return occurredAt ?? new Date().toISOString();
117
+ return occurredAt ?? worldNow();
118
118
  }
119
119
  function kid(type, id) {
120
120
  return `${type}:${id}`;
@@ -40,7 +40,7 @@
40
40
  //
41
41
  // `node:crypto` is required LAZILY (server-only), same convention as replicate-webhooks.ts, so
42
42
  // this module stays browser-bundle safe.
43
- import { applyTwinWriteAtomic, projectResources, nodeBuiltin } from '@volter/world-core';
43
+ import { applyTwinWriteAtomic, projectResources, nodeBuiltin, worldNow } from '@volter/world-core';
44
44
  function nodeCrypto() {
45
45
  // eslint-disable-next-line @typescript-eslint/no-require-imports
46
46
  return nodeBuiltin('node:crypto');
@@ -152,7 +152,7 @@ function verifyRaw(rawBody, headers, publicKey, opts) {
152
152
  throw new FalWebhookVerificationError('Missing required webhook headers (X-Fal-Webhook-Request-Id / X-Fal-Webhook-User-Id / X-Fal-Webhook-Timestamp / X-Fal-Webhook-Signature).');
153
153
  }
154
154
  const tolerance = opts.tolerance ?? 300;
155
- const now = opts.now ?? Math.floor(Date.now() / 1000);
155
+ const now = opts.now ?? Math.floor(Date.parse(worldNow()) / 1000);
156
156
  if (Math.abs(now - ts) > tolerance) {
157
157
  throw new FalWebhookVerificationError(`Webhook timestamp outside the ${tolerance}s tolerance.`);
158
158
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter/twin-fal",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Local fal.ai twin for the model-inference queue lifecycle (submit/status/response/cancel on queue.fal.run, the sync fal.run variant, host-split routing, ed25519-signed webhooks) 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.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.0",
43
+ "@volter/world-core": "2.0.1",
44
44
  "@volter/world-tooling": "0.1.0",
45
45
  "@fal-ai/client": "^1.10.1",
46
46
  "typescript": "^5.9.0"
package/src/fal-twin.ts CHANGED
@@ -45,7 +45,7 @@
45
45
  // Kernel SUBJECT ids are type-prefixed (`request:<uuid>`) — the PUBLIC request_id emitted to
46
46
  // clients is the bare uuid. `kid()` builds the subject id; `rows()` strips the prefix back off.
47
47
  import { createHash } from 'node:crypto';
48
- import { applyTwinWrite, projectResources } from '@volter/world-core';
48
+ import { applyTwinWrite, projectResources, worldNow } from '@volter/world-core';
49
49
  import { falJwks } from './fal-webhooks.ts';
50
50
  import type { FalScenarioEngine, FalScenarioRespond } from './fal-scenario.ts';
51
51
 
@@ -149,7 +149,7 @@ function parseBody(body?: string): { ok: true; value: Record<string, unknown> }
149
149
  }
150
150
  }
151
151
  function nowIso(occurredAt?: string): string {
152
- return occurredAt ?? new Date().toISOString();
152
+ return occurredAt ?? worldNow();
153
153
  }
154
154
  function kid(type: string, id: string): string {
155
155
  return `${type}:${id}`;
@@ -40,7 +40,7 @@
40
40
  //
41
41
  // `node:crypto` is required LAZILY (server-only), same convention as replicate-webhooks.ts, so
42
42
  // this module stays browser-bundle safe.
43
- import { applyTwinWriteAtomic, projectResources, nodeBuiltin } from '@volter/world-core';
43
+ import { applyTwinWriteAtomic, projectResources, nodeBuiltin, worldNow } from '@volter/world-core';
44
44
 
45
45
  type NodeCrypto = typeof import('node:crypto');
46
46
  function nodeCrypto(): NodeCrypto {
@@ -173,7 +173,7 @@ function verifyRaw(rawBody: string, headers: Record<string, string>, publicKey:
173
173
  throw new FalWebhookVerificationError('Missing required webhook headers (X-Fal-Webhook-Request-Id / X-Fal-Webhook-User-Id / X-Fal-Webhook-Timestamp / X-Fal-Webhook-Signature).');
174
174
  }
175
175
  const tolerance = opts.tolerance ?? 300;
176
- const now = opts.now ?? Math.floor(Date.now() / 1000);
176
+ const now = opts.now ?? Math.floor(Date.parse(worldNow()) / 1000);
177
177
  if (Math.abs(now - ts) > tolerance) {
178
178
  throw new FalWebhookVerificationError(`Webhook timestamp outside the ${tolerance}s tolerance.`);
179
179
  }