@alma-harness/runtime 0.10.2 → 0.12.0

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/projections.ts","../src/projections-core.ts"],"sourcesContent":["import pg from \"pg\";\nimport type { Scope } from \"@alma-harness/core\";\nimport type { RuntimePolicies } from \"./index\";\nimport type { Lap } from \"./maintenance-core\";\nimport { namespace } from \"./policies\";\nimport { createPostgresRuntime } from \"./postgres\";\nimport { createProjections, type ProjectionDiscovery, type ProjectionItem } from \"./projections-core\";\nimport { PROJECTION_ROLE } from \"./projections-schema\";\nimport { scopeRotation } from \"./scope-rotation\";\nexport { createProjections, IncompleteErasureError } from \"./projections-core\";\nexport type { Attribution, ProjectionDelivery, ProjectionDiscovery, ProjectionItem, ProjectionReport } from \"./projections-core\";\n\nexport interface PostgresProjectionsOptions extends RuntimePolicies {\n /** A login that is a member of alma_projection only. */\n discovery: { connectionString: string };\n /** A login that is a member of alma_app only, never the request path's. */\n worker: { connectionString: string };\n schema: string; rootSchema: string;\n onPoolError: (error: Error, schema: string) => void;\n}\n// Pending governed receipts for one consumer ($1). Column grants restrict this role to the columns named here.\nconst PENDING = `from alma_cost_projection_pending p join alma_audit_cost c on c.org=p.org and c.uid=p.uid and c.id=p.cost_id\n where p.consumer=$1 and c.settlement_governed`;\nconst KEY = `(c.at, c.settlement_id collate \"C\")`;\nconst json = (v: unknown) => v === null || v === undefined ? null : JSON.stringify(v);\n\n/** The PostgreSQL projection discovery on a pool of the discovery login; `workerURL` is only used to verify the worker login. */\nexport function createPostgresProjectionDiscovery(pool: pg.Pool, workerURL: string): ProjectionDiscovery {\n const rotation = scopeRotation(pool, { role: PROJECTION_ROLE, lockPrefix: \"alma-projection\", workerURL }), tx = rotation.tx;\n const due = `select distinct p.org collate \"C\" as org, p.uid collate \"C\" as uid ${PENDING}`;\n return {\n verify: rotation.verify, claim: rotation.claim,\n quiesce: (scope, fn, timeoutMs) => rotation.quiesce(scope, fn, timeoutMs),\n nextScopes(consumer, limit) {\n return tx(async c => {\n await c.query(\"insert into alma_projection_cursors (consumer) values ($1) on conflict do nothing\", [consumer]);\n const cur = (await c.query<{ org: string | null; uid: string | null }>(\"select org, uid from alma_projection_cursors where consumer=$1 for update\", [consumer])).rows[0]!;\n const page = (where: string, params: unknown[]) => c.query<Scope>(`select org, uid from (${due}) d where ${where} order by org collate \"C\", uid collate \"C\" limit $${params.length + 1}`, [consumer, ...params]);\n let rows = (await page(`$2::text is null or (org, uid) > ($2::text collate \"C\", $3::text collate \"C\")`, [cur.org, cur.uid, limit])).rows;\n if (rows.length < limit && cur.org !== null)\n rows = rows.concat((await page(`(org, uid) <= ($2::text collate \"C\", $3::text collate \"C\")`, [cur.org, cur.uid, limit - rows.length])).rows);\n const last = rows.at(-1);\n if (last) await c.query(\"update alma_projection_cursors set org=$2, uid=$3, updated_at=clock_timestamp() where consumer=$1\", [consumer, last.org, last.uid]);\n return rows.map(r => ({ org: r.org, uid: r.uid }));\n });\n },\n lap(consumer, scope) {\n return tx(async c => {\n const r = (await c.query<{ at: string; settlement_id: string; n: number }>(`select c.at::text as at, c.settlement_id, count(*) over ()::int as n ${PENDING}\n and p.org=$2 and p.uid=$3 order by c.at desc, c.settlement_id collate \"C\" desc limit 1`, [consumer, scope.org, scope.uid])).rows[0];\n return r ? { bound: { at: r.at, settlementId: r.settlement_id }, budget: r.n } : null;\n });\n },\n items(consumer, scope, after, bound, limit) {\n return tx(async c => (await c.query<{ at: string; settlement_id: string }>(`select c.at::text as at, c.settlement_id ${PENDING} and p.org=$2 and p.uid=$3\n and ($4::timestamptz is null or ${KEY} > ($4::timestamptz, $5::text collate \"C\")) and ${KEY} <= ($6::timestamptz, $7::text collate \"C\")\n order by c.at, c.settlement_id collate \"C\" limit $8`, [consumer, scope.org, scope.uid, after?.at ?? null, after?.settlementId ?? null, bound.at, bound.settlementId, limit])).rows\n .map(r => ({ at: r.at, settlementId: r.settlement_id })));\n },\n cursor(consumer, scope) {\n return tx(async c => {\n const row = (await c.query<{ after: ProjectionItem | null; bound: ProjectionItem | null; budget: number | null }>(\n \"select after, bound, budget from alma_projection_scopes where consumer=$1 and org=$2 and uid=$3\", [consumer, scope.org, scope.uid])).rows[0];\n return row && (row.after || row.bound) ? { after: row.after, bound: row.bound, budget: row.budget } as Lap<ProjectionItem> : null;\n });\n },\n async saveCursor(consumer, scope, l) {\n await tx(c => c.query(`insert into alma_projection_scopes (consumer, org, uid, after, bound, budget) values ($1, $2, $3, $4::jsonb, $5::jsonb, $6)\n on conflict (consumer, org, uid) do update set after=excluded.after, bound=excluded.bound, budget=excluded.budget, updated_at=clock_timestamp()`,\n [consumer, scope.org, scope.uid, json(l?.after), json(l?.bound), l?.budget ?? null]));\n },\n };\n}\n\n/** Its own logins and pools, never the request path's. Construction opens no connection (spec: receipt-projections). */\nexport function createPostgresProjections(value: PostgresProjectionsOptions) {\n if (!value || typeof value !== \"object\" || !value.discovery || !value.worker) throw new TypeError(\"Projections require discovery and worker logins\");\n const base = { schema: value.schema, rootSchema: value.rootSchema, onPoolError: value.onPoolError };\n const d = namespace({ ...base, connectionString: value.discovery.connectionString }), workerURL = namespace({ ...base, connectionString: value.worker.connectionString }).connectionString;\n const runtime = createPostgresRuntime({ ...base, connectionString: workerURL, stepResultPolicy: value.stepResultPolicy, rootResultPolicy: value.rootResultPolicy, poolMax: { execution: 2, roots: 1 } });\n const pool = new pg.Pool({ connectionString: d.connectionString, options: `-c search_path=${d.schema}`, max: 2, connectionTimeoutMillis: 5000, idleTimeoutMillis: 10000 });\n pool.on(\"error\", error => d.onPoolError(error, d.schema));\n const projections = createProjections({ stores: runtime.stores, discovery: createPostgresProjectionDiscovery(pool, workerURL) });\n let closing: Promise<void> | undefined;\n return {\n drain: projections.drain, quiesce: projections.quiesce,\n close() {\n return closing ??= Promise.allSettled([runtime.close(), pool.end()]).then(results => {\n const errors = results.flatMap(r => r.status === \"rejected\" ? [r.reason] : []);\n if (errors.length) throw new AggregateError(errors, \"Projection pool cleanup failed\");\n });\n },\n };\n}\n","import { settlementIdentifier, settlementScope, type Scope, type SessionLabels } from \"@alma-harness/core\";\nimport type { GovernedCostReceipt } from \"@alma-harness/execution\";\nimport type { RuntimeStores } from \"./index\";\nimport { resumeLap, type Lap, type ScopeClaim } from \"./maintenance-core\";\n\nexport type Attribution = { state: \"available\"; labels: SessionLabels } | { state: \"erased\" } | { state: \"none\" };\nexport interface ProjectionDelivery {\n scope: Scope; consumer: string; settlementId: string;\n /** `receipt.receipt.settlement.sessionId` names the session. */\n receipt: GovernedCostReceipt;\n /** Erased is never none: never fall back to attribution kept earlier (spec: session-labels). */\n attribution: Attribution;\n /** Aborted when this drain loses its claim or its caller aborts. */\n signal: AbortSignal;\n}\nexport interface ProjectionItem { at: string; settlementId: string }\n/** Cross-scope metadata only: pending receipt identities and times, and the projection cursors (spec: receipt-projections). */\nexport interface ProjectionDiscovery {\n verify(): Promise<void>;\n nextScopes(consumer: string, limit: number): Promise<Scope[]>;\n claim(scope: Scope): Promise<ScopeClaim | null>;\n lap(consumer: string, scope: Scope): Promise<{ bound: ProjectionItem; budget: number } | null>;\n items(consumer: string, scope: Scope, after: ProjectionItem | null, bound: ProjectionItem, limit: number): Promise<ProjectionItem[]>;\n cursor(consumer: string, scope: Scope): Promise<Lap<ProjectionItem> | null>;\n saveCursor(consumer: string, scope: Scope, lap: Lap<ProjectionItem> | null): Promise<void>;\n quiesce<T>(scope: Scope, fn: () => Promise<T>, timeoutMs: number): Promise<T>;\n}\nexport interface ProjectionReport { scopes: number; skipped: number; delivered: number; acknowledged: number; failed: number }\n/** An erasure that reported `complete: false` inside `quiesce`: nothing is released as done; retry the erasure. */\nexport class IncompleteErasureError extends Error {\n constructor() { super(\"Erasure reported incomplete inside quiesce\"); this.name = \"IncompleteErasureError\"; }\n}\nconst BUDGET = 50;\n\n/** At-least-once delivery: acknowledged only after the handler resolved. Counts only in the report. */\nexport function createProjections(options: { stores: Pick<RuntimeStores, \"labels\"> & { step: Pick<RuntimeStores[\"step\"], \"settlements\"> }; discovery: ProjectionDiscovery }) {\n const { stores, discovery } = options, settlements = stores.step.settlements;\n async function attribution(scope: Scope, sessionId: string): Promise<Attribution> {\n const record = await stores.labels.get(scope, sessionId);\n return !record ? { state: \"none\" } : record.state === \"erased\" ? { state: \"erased\" } : { state: \"available\", labels: structuredClone(record.labels) };\n }\n async function work(consumer: string, scope: Scope, handler: (d: ProjectionDelivery) => Promise<void>, signal: AbortSignal, r: ProjectionReport) {\n const stored = await discovery.cursor(consumer, scope);\n const l = await resumeLap(stored, () => discovery.lap(consumer, scope));\n if (!l) { await discovery.saveCursor(consumer, scope, null); return; }\n const want = Math.min(BUDGET, l.budget), items = await discovery.items(consumer, scope, l.after, l.bound, want);\n let attempted = 0;\n for (const item of items) {\n // A lost claim or an aborted caller starts no further receipt.\n if (signal.aborted) break;\n try {\n const receipt = await settlements.getGoverned(scope, item.settlementId);\n if (!receipt) throw new Error(\"Pending receipt missing\");\n const delivery: ProjectionDelivery = Object.freeze({ scope: { ...scope }, consumer, settlementId: item.settlementId, receipt,\n attribution: Object.freeze(await attribution(scope, receipt.receipt.settlement.sessionId)), signal });\n // A loss observed during the reads: no handler starts once ownership has ended.\n if (signal.aborted) break;\n await handler(delivery); r.delivered++;\n // After an observed claim loss no acknowledgement starts: the receipt stays pending and is redelivered, and the\n // handler deduplicates. Only an acknowledgement already started when the loss arrives may still commit.\n if (signal.aborted) break;\n if (await settlements.acknowledge(scope, consumer, item.settlementId)) r.acknowledged++;\n } catch { r.failed++; }\n l.after = item; l.budget--; attempted++;\n }\n await discovery.saveCursor(consumer, scope, attempted < items.length ? l : items.length < want || l.budget < 1 ? null : l);\n }\n // One call at a time per instance: each holds a claim connection plus one query connection.\n let queue: Promise<unknown> = Promise.resolve();\n const serial = <T>(fn: () => Promise<T>): Promise<T> => { const run = queue.then(fn, fn); queue = run.catch(() => undefined); return run; };\n return {\n drain(consumerName: string, handler: (d: ProjectionDelivery) => Promise<void>, value: { limit: number; signal?: AbortSignal }): Promise<ProjectionReport> {\n return serial(async () => {\n const consumer = settlementIdentifier(consumerName);\n if (typeof handler !== \"function\" || !value || !Number.isSafeInteger(value.limit) || value.limit < 1 || value.limit > 1000) throw new TypeError(\"Invalid projection drain\");\n await discovery.verify();\n const r: ProjectionReport = { scopes: 0, skipped: 0, delivered: 0, acknowledged: 0, failed: 0 };\n // A lost claim ends the whole drain: its discovery connection is not to be trusted for another scope.\n let lost = false;\n for (const scope of await discovery.nextScopes(consumer, value.limit)) {\n if (value.signal?.aborted || lost) break;\n const claim = await discovery.claim(scope);\n if (!claim) { r.skipped++; continue; }\n r.scopes++;\n const controller = new AbortController(), abort = () => controller.abort();\n value.signal?.addEventListener(\"abort\", abort, { once: true }); claim.onLost?.(() => { lost = true; abort(); });\n // An abort during the claim's acquisition is not replayed to a listener added afterwards.\n if (value.signal?.aborted || !claim.alive()) abort();\n try { await work(consumer, scope, handler, controller.signal, r); } catch { r.failed++; }\n finally { value.signal?.removeEventListener(\"abort\", abort); await claim.release(); }\n }\n return r;\n });\n },\n /** Waits for any drain of the scope, holds new ones off, and runs `fn`. An erasure reporting `complete: false` rejects. */\n quiesce<T>(scopeValue: Scope, fn: () => Promise<T>, value: { timeoutMs: number }): Promise<T> {\n return serial(async () => {\n const scope = settlementScope(scopeValue);\n if (typeof fn !== \"function\" || !value || !Number.isSafeInteger(value.timeoutMs) || value.timeoutMs < 1 || value.timeoutMs > 600_000) throw new TypeError(\"Invalid quiesce\");\n await discovery.verify();\n const result = await discovery.quiesce(scope, fn, value.timeoutMs);\n if (result && typeof result === \"object\" && (result as { complete?: unknown }).complete === false) throw new IncompleteErasureError();\n return result;\n });\n },\n };\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alma-harness/runtime",
3
- "version": "0.10.2",
3
+ "version": "0.12.0",
4
4
  "description": "Official store composition for governed Alma conversations.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -31,6 +31,18 @@
31
31
  "./agent": {
32
32
  "types": "./dist/agent.d.ts",
33
33
  "default": "./dist/agent.js"
34
+ },
35
+ "./deployment": {
36
+ "types": "./dist/deployment.d.ts",
37
+ "default": "./dist/deployment.js"
38
+ },
39
+ "./maintenance": {
40
+ "types": "./dist/maintenance.d.ts",
41
+ "default": "./dist/maintenance.js"
42
+ },
43
+ "./projections": {
44
+ "types": "./dist/projections.d.ts",
45
+ "default": "./dist/projections.js"
34
46
  }
35
47
  },
36
48
  "repository": {
@@ -40,13 +52,13 @@
40
52
  },
41
53
  "peerDependencies": {
42
54
  "pg": "^8.16.3",
43
- "@alma-harness/core": "^0.10.2",
44
- "@alma-harness/memory": "^0.10.2",
45
- "@alma-harness/execution": "^0.10.2",
46
- "@alma-harness/conversation": "^0.10.2",
47
- "@alma-harness/postgres": "^0.10.2",
48
- "@alma-harness/single-call": "^0.10.2",
49
- "@alma-harness/postgres-execution": "^0.10.2"
55
+ "@alma-harness/conversation": "^0.12.0",
56
+ "@alma-harness/core": "^0.12.0",
57
+ "@alma-harness/memory": "^0.12.0",
58
+ "@alma-harness/postgres": "^0.12.0",
59
+ "@alma-harness/execution": "^0.12.0",
60
+ "@alma-harness/postgres-execution": "^0.12.0",
61
+ "@alma-harness/single-call": "^0.12.0"
50
62
  },
51
63
  "peerDependenciesMeta": {
52
64
  "pg": {
@@ -65,13 +77,13 @@
65
77
  "typescript": "^5.9.2",
66
78
  "vitest": "^3.2.4",
67
79
  "pg": "^8.16.3",
68
- "@alma-harness/memory": "^0.10.2",
69
- "@alma-harness/postgres-execution": "^0.10.2",
70
- "@alma-harness/single-call": "^0.10.2",
71
- "@alma-harness/conversation": "^0.10.2",
72
- "@alma-harness/execution": "^0.10.2",
73
- "@alma-harness/postgres": "^0.10.2",
74
- "@alma-harness/core": "^0.10.2"
80
+ "@alma-harness/core": "^0.12.0",
81
+ "@alma-harness/memory": "^0.12.0",
82
+ "@alma-harness/postgres": "^0.12.0",
83
+ "@alma-harness/conversation": "^0.12.0",
84
+ "@alma-harness/postgres-execution": "^0.12.0",
85
+ "@alma-harness/execution": "^0.12.0",
86
+ "@alma-harness/single-call": "^0.12.0"
75
87
  },
76
88
  "files": [
77
89
  "dist"
@@ -1,10 +0,0 @@
1
- // src/policies.ts
2
- import { normalizeExecutionResultPolicy } from "@alma-harness/memory";
3
- function policies(value) {
4
- return { stepResultPolicy: normalizeExecutionResultPolicy(value.stepResultPolicy), rootResultPolicy: normalizeExecutionResultPolicy(value.rootResultPolicy) };
5
- }
6
-
7
- export {
8
- policies
9
- };
10
- //# sourceMappingURL=chunk-3OEFEOI4.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/policies.ts"],"sourcesContent":["import { normalizeExecutionResultPolicy } from \"@alma-harness/memory\";\nimport type { RuntimePolicies } from \"./index\";\nexport function policies(value: RuntimePolicies): RuntimePolicies {\n return { stepResultPolicy: normalizeExecutionResultPolicy(value.stepResultPolicy), rootResultPolicy: normalizeExecutionResultPolicy(value.rootResultPolicy) };\n}\n"],"mappings":";AAAA,SAAS,sCAAsC;AAExC,SAAS,SAAS,OAAyC;AAChE,SAAO,EAAE,kBAAkB,+BAA+B,MAAM,gBAAgB,GAAG,kBAAkB,+BAA+B,MAAM,gBAAgB,EAAE;AAC9J;","names":[]}