@tokenoftrust/storefront-runner 4.9.2 → 4.9.3

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.
Files changed (27) hide show
  1. package/apps/storefront/migrations-apps/0021_contact_vault.sql +162 -0
  2. package/apps/storefront/src/lib/access/auth/contactReaderAuthority.ts +64 -0
  3. package/apps/storefront/src/lib/access/shared/viewerGrant.ts +30 -0
  4. package/apps/storefront/src/lib/customers/contactVault/contactAudit.ts +80 -0
  5. package/apps/storefront/src/lib/customers/contactVault/envelope.ts +166 -0
  6. package/apps/storefront/src/lib/customers/contactVault/retention.ts +44 -0
  7. package/apps/storefront/src/lib/engagement/contact/contactMessages.ts +242 -65
  8. package/apps/storefront/src/lib/engagement/contact/contract.ts +2 -0
  9. package/apps/storefront/src/lib/fulfillment/commerceProjection.ts +0 -1
  10. package/apps/storefront/src/lib/fulfillment/fulfillmentService.ts +3 -78
  11. package/apps/storefront/src/lib/integrations/webhooks/deliveryEngine.ts +4 -0
  12. package/apps/storefront/src/lib/orders/admin/orderActions.ts +229 -19
  13. package/apps/storefront/src/lib/orders/data/commerceCallerConfig.ts +37 -0
  14. package/apps/storefront/src/lib/orders/data/orderForwardReceiver.ts +10 -3
  15. package/apps/storefront/src/lib/orders/data/orderMapper.ts +9 -0
  16. package/apps/storefront/src/lib/orders/data/sourceAuthorityContract.ts +2 -1
  17. package/apps/storefront/src/lib/orders/vault/contactIntake.ts +61 -0
  18. package/apps/storefront/src/lib/orders/vault/contactRoutes.ts +99 -0
  19. package/apps/storefront/src/lib/orders/vault/keyringEnv.ts +7 -0
  20. package/apps/storefront/src/lib/orders/vault/orderContact.ts +96 -0
  21. package/apps/storefront/src/lib/orders/vault/orderContactVault.ts +369 -0
  22. package/apps/storefront/src/lib/publication/d1/schema-apps.ts +22 -11
  23. package/apps/storefront/src/lib/publication/shared/routedApiParam.ts +3 -0
  24. package/apps/storefront/src/pages/api/admin/fulfillment/orders/[id]/address.ts +26 -23
  25. package/apps/storefront/src/pages/api/contact.ts +16 -4
  26. package/apps/storefront/src/scheduled/contactVaultSweep.ts +80 -0
  27. package/package.json +1 -1
@@ -0,0 +1,80 @@
1
+ /**
2
+ * The hourly contact vault sweep — the Worker's `scheduled` handler body. One `now` per firing,
3
+ * taken from its scheduled time: purge expired order contacts and contact messages, shorten terminal
4
+ * orders' retention, and seal any contact message still held as legacy plaintext. Expiry predicates
5
+ * only; it never touches an order, audit or other row.
6
+ *
7
+ * It logs ONE structured line of counts on success and ONE fixed error code on failure — never an
8
+ * error message, id or row, since either could carry data. It composes orders and engagement, which
9
+ * no module under src/lib may do, so it lives beside the Worker entry.
10
+ */
11
+ import { fromD1, type Queryable } from "@/lib/catalog/d1/catalog.js";
12
+ import type { VaultKeyring } from "@/lib/customers/contactVault/envelope.js";
13
+ import { purgeExpiredContactMessages, sealLegacyContactMessages } from "@/lib/engagement/contact/contactMessages.js";
14
+ import { loadVaultKeyring } from "@/lib/orders/vault/keyringEnv.js";
15
+ import { purgeOrderContacts, type PurgeCounts } from "@/lib/orders/vault/orderContactVault.js";
16
+ import { readD1 } from "@/lib/publication/shared/env";
17
+
18
+ export const SWEEP_LEGACY_SEAL_LIMIT = 500;
19
+ export const CONTACT_VAULT_SWEEP_EVENT = "contact-vault-sweep";
20
+ export const SWEEP_DB_UNAVAILABLE = "contact-vault-sweep-db-unavailable";
21
+ export const SWEEP_FAILED = "contact-vault-sweep-failed";
22
+
23
+ export interface SweepCounts {
24
+ orders: PurgeCounts;
25
+ messagesPurged: number;
26
+ legacySealed: number;
27
+ legacyRemaining: number;
28
+ }
29
+
30
+ export async function runContactVaultSweep(db: Queryable, keyring: VaultKeyring | null, now: Date): Promise<SweepCounts> {
31
+ if (Number.isNaN(now.getTime())) throw new Error("contact vault sweep: unreadable clock");
32
+ const orders = await purgeOrderContacts(db, now);
33
+ const messagesPurged = await purgeExpiredContactMessages(db, now);
34
+ const legacy = keyring
35
+ ? await sealLegacyContactMessages(db, keyring, now, SWEEP_LEGACY_SEAL_LIMIT)
36
+ : { sealed: 0, remaining: -1 };
37
+ return { orders, messagesPurged, legacySealed: legacy.sealed, legacyRemaining: legacy.remaining };
38
+ }
39
+
40
+ export interface ScheduledSweepDeps {
41
+ openDb(): Promise<Queryable | null>;
42
+ loadKeyring(): Promise<VaultKeyring | null>;
43
+ sweep(db: Queryable, keyring: VaultKeyring | null, now: Date): Promise<SweepCounts>;
44
+ log(line: string): void;
45
+ logError(line: string): void;
46
+ }
47
+
48
+ const workerDeps: ScheduledSweepDeps = {
49
+ openDb: async () => {
50
+ const d1 = await readD1("STOREFRONT_APPS_DB");
51
+ return d1 ? fromD1(d1) : null;
52
+ },
53
+ loadKeyring: loadVaultKeyring,
54
+ sweep: runContactVaultSweep,
55
+ log: (line) => console.log(line),
56
+ logError: (line) => console.error(line),
57
+ };
58
+
59
+ /** Never throws: every failure is reported as a fixed code. */
60
+ export async function runScheduledContactVaultSweep(scheduledTime: number, deps: ScheduledSweepDeps = workerDeps): Promise<void> {
61
+ const fail = (error: string) => deps.logError(JSON.stringify({ event: CONTACT_VAULT_SWEEP_EVENT, error }));
62
+ try {
63
+ const db = await deps.openDb();
64
+ if (!db) return fail(SWEEP_DB_UNAVAILABLE);
65
+ const keyring = await deps.loadKeyring();
66
+ const counts = await deps.sweep(db, keyring, new Date(scheduledTime));
67
+ deps.log(JSON.stringify({
68
+ event: CONTACT_VAULT_SWEEP_EVENT,
69
+ keyringAvailable: keyring !== null,
70
+ ordersPurged: counts.orders.purged,
71
+ tombstonesRemoved: counts.orders.tombstonesRemoved,
72
+ ordersShortened: counts.orders.shortened,
73
+ messagesPurged: counts.messagesPurged,
74
+ legacySealed: counts.legacySealed,
75
+ legacyRemaining: counts.legacyRemaining,
76
+ }));
77
+ } catch {
78
+ fail(SWEEP_FAILED);
79
+ }
80
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tokenoftrust/storefront-runner",
3
- "version": "4.9.2",
3
+ "version": "4.9.3",
4
4
  "license": "SEE LICENSE IN LICENSE",
5
5
  "description": "World-shareable storefront runner: multi-tenant renderer on Astro/Cloudflare. No control plane.",
6
6
  "packageManager": "pnpm@11.9.0",