@alma-harness/runtime 0.11.0 → 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,179 @@
1
+ import {
2
+ namespace,
3
+ policies
4
+ } from "./chunk-II7NDZRL.js";
5
+
6
+ // src/postgres.ts
7
+ import pg from "pg";
8
+ import {
9
+ PostgresAuditLog,
10
+ PostgresSessionStore,
11
+ PostgresExecutionStore,
12
+ PostgresExecutionResultStore,
13
+ PostgresUsageInbox,
14
+ PostgresCostSettlementStore,
15
+ PostgresSpendStore,
16
+ migrateSessionStore,
17
+ migrateExecutionStore,
18
+ migrateExecutionResultStore,
19
+ migrateUsageInbox
20
+ } from "@alma-harness/postgres";
21
+ import { PostgresOperationSessionStore, PostgresOperationTreeStore, PostgresOperationAccountingStore, PostgresSessionLabelStore, migrateOperationAccountingStore, migrateOperationSessionStore, migrateSessionLabelStore } from "@alma-harness/postgres-execution";
22
+
23
+ // src/maintenance-schema.ts
24
+ import { roleBootstrapSql } from "@alma-harness/postgres";
25
+ var MAINTENANCE_ROLE = "alma_maintenance";
26
+ var DISCOVERY = {
27
+ alma_operation_admissions: ["org", "uid", "status", "deadline_at"],
28
+ alma_operation_roots: ["org", "uid", "id", "key", "status", "deadline_at"],
29
+ alma_operation_calls: ["org", "uid", "root_id", "operation_key", "call_id"],
30
+ alma_operation_financial_calls: ["org", "uid", "root_id", "call_id"],
31
+ alma_executions: ["org", "uid", "operation_key", "state", "deadline_at", "created_at", "pricing"],
32
+ alma_usage_inbox_pending: ["org", "uid", "id", "received_at"]
33
+ };
34
+ var policy = (table, name, clause) => `
35
+ drop policy if exists ${name} on ${table};
36
+ create policy ${name} on ${table} ${clause} to ${MAINTENANCE_ROLE} using (true)${clause.includes("select") ? "" : " with check (true)"};`;
37
+ function maintenanceMigrationSql(schema) {
38
+ return `${roleBootstrapSql(MAINTENANCE_ROLE)}
39
+ grant usage on schema ${schema} to ${MAINTENANCE_ROLE};
40
+ ${Object.entries(DISCOVERY).map(([table, columns]) => `revoke all on ${table} from ${MAINTENANCE_ROLE};
41
+ grant select (${columns.join(", ")}) on ${table} to ${MAINTENANCE_ROLE};${policy(table, "alma_maintenance_discovery", "for select")}`).join("\n")}
42
+ create table if not exists alma_maintenance_cursor (
43
+ id int primary key check (id = 1), org text collate "C", uid text collate "C", updated_at timestamptz not null default clock_timestamp(),
44
+ check ((org is null) = (uid is null))
45
+ );
46
+ create table if not exists alma_maintenance_scopes (
47
+ org text collate "C" not null, uid text collate "C" not null,
48
+ executions_after jsonb, usage_after jsonb, updated_at timestamptz not null default clock_timestamp(),
49
+ primary key (org, uid)
50
+ );
51
+ -- Bounded laps (spec: receipt-projections): additive and nullable, so a cursor written before them keeps its position.
52
+ alter table alma_maintenance_scopes add column if not exists executions_bound jsonb;
53
+ alter table alma_maintenance_scopes add column if not exists executions_budget int;
54
+ alter table alma_maintenance_scopes add column if not exists usage_bound jsonb;
55
+ alter table alma_maintenance_scopes add column if not exists usage_budget int;
56
+ -- FORCE RLS binds the owner too, so the seed is written with it lifted inside this migration.
57
+ alter table alma_maintenance_cursor no force row level security;
58
+ insert into alma_maintenance_cursor (id) values (1) on conflict do nothing;
59
+ ${["alma_maintenance_cursor", "alma_maintenance_scopes"].map((t) => `alter table ${t} enable row level security;
60
+ alter table ${t} force row level security;
61
+ revoke all on ${t} from public, alma_app, alma_retention;${policy(t, "alma_maintenance_only", "for all")}`).join("\n")}
62
+ grant select, update on alma_maintenance_cursor to ${MAINTENANCE_ROLE};
63
+ grant select, insert, update on alma_maintenance_scopes to ${MAINTENANCE_ROLE};
64
+ `;
65
+ }
66
+
67
+ // src/projections-schema.ts
68
+ import { roleBootstrapSql as roleBootstrapSql2 } from "@alma-harness/postgres";
69
+ var PROJECTION_ROLE = "alma_projection";
70
+ var DISCOVERY2 = {
71
+ alma_cost_projection_pending: ["org", "uid", "consumer", "cost_id"],
72
+ alma_audit_cost: ["org", "uid", "id", "at", "settlement_id", "settlement_governed"]
73
+ };
74
+ function projectionMigrationSql(schema) {
75
+ return `${roleBootstrapSql2(PROJECTION_ROLE)}
76
+ grant usage on schema ${schema} to ${PROJECTION_ROLE};
77
+ ${Object.entries(DISCOVERY2).map(([table, columns]) => `revoke all on ${table} from ${PROJECTION_ROLE};
78
+ grant select (${columns.join(", ")}) on ${table} to ${PROJECTION_ROLE};
79
+ drop policy if exists alma_projection_discovery on ${table};
80
+ create policy alma_projection_discovery on ${table} for select to ${PROJECTION_ROLE} using (true);`).join("\n")}
81
+ create table if not exists alma_projection_cursors (
82
+ consumer text collate "C" primary key, org text collate "C", uid text collate "C", updated_at timestamptz not null default clock_timestamp(),
83
+ check ((org is null) = (uid is null))
84
+ );
85
+ create table if not exists alma_projection_scopes (
86
+ consumer text collate "C" not null, org text collate "C" not null, uid text collate "C" not null,
87
+ after jsonb, bound jsonb, budget int, updated_at timestamptz not null default clock_timestamp(),
88
+ primary key (consumer, org, uid)
89
+ );
90
+ ${["alma_projection_cursors", "alma_projection_scopes"].map((t) => `alter table ${t} enable row level security;
91
+ alter table ${t} force row level security;
92
+ revoke all on ${t} from public, alma_app, alma_retention, alma_maintenance;
93
+ drop policy if exists alma_projection_only on ${t};
94
+ create policy alma_projection_only on ${t} for all to ${PROJECTION_ROLE} using (true) with check (true);
95
+ grant select, insert, update on ${t} to ${PROJECTION_ROLE};`).join("\n")}
96
+ `;
97
+ }
98
+
99
+ // src/postgres.ts
100
+ function limits(value) {
101
+ if (value === void 0) return { execution: 5, roots: 5 };
102
+ if (!value || typeof value !== "object" || Array.isArray(value)) throw new TypeError("Invalid runtime pool limits");
103
+ const fields = Object.getOwnPropertyDescriptors(value), keys = Reflect.ownKeys(fields);
104
+ if (keys.length !== 2 || !keys.includes("execution") || !keys.includes("roots")) throw new TypeError("Invalid runtime pool limits");
105
+ const execution = fields.execution?.value, roots = fields.roots?.value;
106
+ if (!Number.isSafeInteger(execution) || execution < 1 || !Number.isSafeInteger(roots) || roots < 1 || !Number.isSafeInteger(execution + roots)) throw new TypeError("Invalid runtime pool limits");
107
+ return { execution, roots };
108
+ }
109
+ function pools(n, max) {
110
+ const open = (schema, size) => {
111
+ const pool = new pg.Pool({
112
+ connectionString: n.connectionString,
113
+ options: `-c search_path=${schema} -c extra_float_digits=3`,
114
+ max: size,
115
+ connectionTimeoutMillis: 5e3,
116
+ idleTimeoutMillis: 1e4
117
+ });
118
+ pool.on("error", (error) => n.onPoolError(error, schema));
119
+ return pool;
120
+ };
121
+ const execution = open(n.schema, max.execution), roots = open(n.rootSchema, max.roots);
122
+ let closing;
123
+ return { execution, roots, close() {
124
+ return closing ??= Promise.allSettled([Promise.resolve().then(() => execution.end()), Promise.resolve().then(() => roots.end())]).then((results) => {
125
+ const errors = results.flatMap((r) => r.status === "rejected" ? [r.reason] : []);
126
+ if (errors.length) throw new AggregateError(errors, "Runtime pool cleanup failed");
127
+ });
128
+ } };
129
+ }
130
+ function createPostgresRuntime(value) {
131
+ const n = namespace(value), p = policies(value), max = limits(value.poolMax), owned = pools(n, max);
132
+ return { stores: {
133
+ sessions: new PostgresSessionStore(owned.execution),
134
+ admissions: new PostgresOperationSessionStore(owned.execution),
135
+ rootResults: new PostgresExecutionResultStore(owned.roots, p.rootResultPolicy),
136
+ step: {
137
+ executions: new PostgresExecutionStore(owned.execution),
138
+ results: new PostgresExecutionResultStore(owned.execution, p.stepResultPolicy),
139
+ inbox: new PostgresUsageInbox(owned.execution),
140
+ settlements: new PostgresCostSettlementStore(owned.execution),
141
+ spend: new PostgresSpendStore(owned.execution),
142
+ trees: new PostgresOperationTreeStore(owned.execution),
143
+ accounting: new PostgresOperationAccountingStore(owned.execution)
144
+ },
145
+ // The settlement migration already installs the audit tables in this namespace.
146
+ labels: new PostgresSessionLabelStore(owned.execution),
147
+ audit: new PostgresAuditLog(owned.execution)
148
+ }, close: owned.close };
149
+ }
150
+ async function migratePostgresRuntime(value) {
151
+ const n = namespace(value), owned = pools(n, { execution: 1, roots: 1 });
152
+ try {
153
+ await owned.execution.query(`create schema if not exists ${n.schema}`);
154
+ await owned.roots.query(`create schema if not exists ${n.rootSchema}`);
155
+ await migrateSessionStore(owned.execution);
156
+ await migrateExecutionStore(owned.execution);
157
+ await migrateExecutionResultStore(owned.execution);
158
+ await migrateUsageInbox(owned.execution);
159
+ await migrateOperationAccountingStore(owned.execution);
160
+ await migrateOperationSessionStore(owned.execution);
161
+ await migrateSessionLabelStore(owned.execution);
162
+ await migrateExecutionResultStore(owned.roots);
163
+ await owned.execution.query(maintenanceMigrationSql(n.schema));
164
+ await owned.execution.query(projectionMigrationSql(n.schema));
165
+ for (const [pool, schema] of [[owned.execution, n.schema], [owned.roots, n.rootSchema]]) {
166
+ await pool.query(`grant usage on schema ${schema} to alma_app, alma_retention; revoke create on schema ${schema} from public, alma_app, alma_retention`);
167
+ }
168
+ } finally {
169
+ await owned.close();
170
+ }
171
+ }
172
+
173
+ export {
174
+ MAINTENANCE_ROLE,
175
+ PROJECTION_ROLE,
176
+ createPostgresRuntime,
177
+ migratePostgresRuntime
178
+ };
179
+ //# sourceMappingURL=chunk-EGQL2P7U.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/postgres.ts","../src/maintenance-schema.ts","../src/projections-schema.ts"],"sourcesContent":["import pg from \"pg\";\nimport { PostgresAuditLog, PostgresSessionStore, PostgresExecutionStore, PostgresExecutionResultStore, PostgresUsageInbox, PostgresCostSettlementStore, PostgresSpendStore,\n migrateSessionStore, migrateExecutionStore, migrateExecutionResultStore, migrateUsageInbox } from \"@alma-harness/postgres\";\nimport { PostgresOperationSessionStore, PostgresOperationTreeStore, PostgresOperationAccountingStore, PostgresSessionLabelStore, migrateOperationAccountingStore, migrateOperationSessionStore, migrateSessionLabelStore } from \"@alma-harness/postgres-execution\";\nimport type { Runtime, RuntimePolicies } from \"./index\";\nimport { namespace, policies } from \"./policies\";\nimport { maintenanceMigrationSql } from \"./maintenance-schema\";\nimport { projectionMigrationSql } from \"./projections-schema\";\nexport interface PostgresRuntimeNamespace { connectionString: string; schema: string; rootSchema: string; onPoolError: (error: Error, schema: string) => void }\nexport type PostgresRuntimeOptions = PostgresRuntimeNamespace & RuntimePolicies & {\n /** Per owned pool, not per turn. Omission keeps five connections in each pool. */\n poolMax?: { execution: number; roots: number };\n};\nfunction limits(value: unknown): { execution: number; roots: number } {\n if(value===undefined)return {execution:5,roots:5};\n if(!value || typeof value!==\"object\" || Array.isArray(value))throw new TypeError(\"Invalid runtime pool limits\");\n const fields=Object.getOwnPropertyDescriptors(value),keys=Reflect.ownKeys(fields);\n if(keys.length!==2 || !keys.includes(\"execution\") || !keys.includes(\"roots\"))throw new TypeError(\"Invalid runtime pool limits\");\n const execution=fields.execution?.value,roots=fields.roots?.value;\n if(!Number.isSafeInteger(execution) || execution<1 || !Number.isSafeInteger(roots) || roots<1 || !Number.isSafeInteger(execution+roots))throw new TypeError(\"Invalid runtime pool limits\");\n return {execution,roots};\n}\nfunction pools(n: PostgresRuntimeNamespace, max: { execution: number; roots: number }) {\n const open = (schema: string, size: number) => {\n const pool = new pg.Pool({ connectionString: n.connectionString,\n options: `-c search_path=${schema} -c extra_float_digits=3`, max: size, connectionTimeoutMillis: 5000, idleTimeoutMillis: 10000 });\n pool.on(\"error\", error => n.onPoolError(error, schema));\n return pool;\n };\n const execution = open(n.schema,max.execution), roots = open(n.rootSchema,max.roots);\n let closing: Promise<void> | undefined;\n return { execution, roots, close() {\n return closing ??= Promise.allSettled([Promise.resolve().then(() => execution.end()), Promise.resolve().then(() => roots.end())]).then(results => {\n const errors = results.flatMap(r => r.status === \"rejected\" ? [r.reason] : []);\n if (errors.length) throw new AggregateError(errors, \"Runtime pool cleanup failed\");\n });\n } };\n}\n/** No connections, migrations or grants occur at construction. Owned pools pin both namespaces. */\nexport function createPostgresRuntime(value: PostgresRuntimeOptions): Runtime {\n const n = namespace(value), p = policies(value), max = limits(value.poolMax), owned = pools(n,max);\n return { stores: {\n sessions: new PostgresSessionStore(owned.execution), admissions: new PostgresOperationSessionStore(owned.execution),\n rootResults: new PostgresExecutionResultStore(owned.roots, p.rootResultPolicy),\n step: { executions: new PostgresExecutionStore(owned.execution), results: new PostgresExecutionResultStore(owned.execution, p.stepResultPolicy),\n inbox: new PostgresUsageInbox(owned.execution), settlements: new PostgresCostSettlementStore(owned.execution), spend: new PostgresSpendStore(owned.execution),\n trees: new PostgresOperationTreeStore(owned.execution), accounting: new PostgresOperationAccountingStore(owned.execution) },\n // The settlement migration already installs the audit tables in this namespace.\n labels: new PostgresSessionLabelStore(owned.execution), audit: new PostgresAuditLog(owned.execution),\n }, close: owned.close };\n}\n/** Explicit administrator operation. Partial installation may be rerun; no login memberships are granted. */\nexport async function migratePostgresRuntime(value: PostgresRuntimeNamespace): Promise<void> {\n const n = namespace(value), owned = pools(n,{execution:1,roots:1});\n try {\n await owned.execution.query(`create schema if not exists ${n.schema}`);\n await owned.roots.query(`create schema if not exists ${n.rootSchema}`);\n await migrateSessionStore(owned.execution);\n await migrateExecutionStore(owned.execution);\n await migrateExecutionResultStore(owned.execution);\n await migrateUsageInbox(owned.execution);\n await migrateOperationAccountingStore(owned.execution);\n await migrateOperationSessionStore(owned.execution);\n await migrateSessionLabelStore(owned.execution);\n await migrateExecutionResultStore(owned.roots);\n await owned.execution.query(maintenanceMigrationSql(n.schema));\n await owned.execution.query(projectionMigrationSql(n.schema));\n for (const [pool, schema] of [[owned.execution, n.schema], [owned.roots, n.rootSchema]] as const) {\n await pool.query(`grant usage on schema ${schema} to alma_app, alma_retention; revoke create on schema ${schema} from public, alma_app, alma_retention`);\n }\n } finally { await owned.close(); }\n}\n","import { roleBootstrapSql } from \"@alma-harness/postgres\";\nexport const MAINTENANCE_ROLE = \"alma_maintenance\";\n// DECISION: identifiers, states and times only; no input, evidence, settlement or result column (spec: runtime-maintenance).\nconst DISCOVERY: Record<string, string[]> = {\n alma_operation_admissions: [\"org\", \"uid\", \"status\", \"deadline_at\"],\n alma_operation_roots: [\"org\", \"uid\", \"id\", \"key\", \"status\", \"deadline_at\"],\n alma_operation_calls: [\"org\", \"uid\", \"root_id\", \"operation_key\", \"call_id\"],\n alma_operation_financial_calls: [\"org\", \"uid\", \"root_id\", \"call_id\"],\n alma_executions: [\"org\", \"uid\", \"operation_key\", \"state\", \"deadline_at\", \"created_at\", \"pricing\"],\n alma_usage_inbox_pending: [\"org\", \"uid\", \"id\", \"received_at\"],\n};\nconst policy = (table: string, name: string, clause: string) => `\ndrop policy if exists ${name} on ${table};\ncreate policy ${name} on ${table} ${clause} to ${MAINTENANCE_ROLE} using (true)${clause.includes(\"select\") ? \"\" : \" with check (true)\"};`;\n/** Runs in the execution namespace after the runtime's own migrations; the tables it grants on must exist. */\nexport function maintenanceMigrationSql(schema: string): string {\n return `${roleBootstrapSql(MAINTENANCE_ROLE)}\ngrant usage on schema ${schema} to ${MAINTENANCE_ROLE};\n${Object.entries(DISCOVERY).map(([table, columns]) => `revoke all on ${table} from ${MAINTENANCE_ROLE};\ngrant select (${columns.join(\", \")}) on ${table} to ${MAINTENANCE_ROLE};${policy(table, \"alma_maintenance_discovery\", \"for select\")}`).join(\"\\n\")}\ncreate table if not exists alma_maintenance_cursor (\n id int primary key check (id = 1), org text collate \"C\", uid text collate \"C\", updated_at timestamptz not null default clock_timestamp(),\n check ((org is null) = (uid is null))\n);\ncreate table if not exists alma_maintenance_scopes (\n org text collate \"C\" not null, uid text collate \"C\" not null,\n executions_after jsonb, usage_after jsonb, updated_at timestamptz not null default clock_timestamp(),\n primary key (org, uid)\n);\n-- Bounded laps (spec: receipt-projections): additive and nullable, so a cursor written before them keeps its position.\nalter table alma_maintenance_scopes add column if not exists executions_bound jsonb;\nalter table alma_maintenance_scopes add column if not exists executions_budget int;\nalter table alma_maintenance_scopes add column if not exists usage_bound jsonb;\nalter table alma_maintenance_scopes add column if not exists usage_budget int;\n-- FORCE RLS binds the owner too, so the seed is written with it lifted inside this migration.\nalter table alma_maintenance_cursor no force row level security;\ninsert into alma_maintenance_cursor (id) values (1) on conflict do nothing;\n${[\"alma_maintenance_cursor\", \"alma_maintenance_scopes\"].map(t => `alter table ${t} enable row level security;\nalter table ${t} force row level security;\nrevoke all on ${t} from public, alma_app, alma_retention;${policy(t, \"alma_maintenance_only\", \"for all\")}`).join(\"\\n\")}\ngrant select, update on alma_maintenance_cursor to ${MAINTENANCE_ROLE};\ngrant select, insert, update on alma_maintenance_scopes to ${MAINTENANCE_ROLE};\n`;\n}\n","import { roleBootstrapSql } from \"@alma-harness/postgres\";\nexport const PROJECTION_ROLE = \"alma_projection\";\n// DECISION: identifiers, times and the governed flag only; no usage, cost, model or payload column (spec: receipt-projections).\nconst DISCOVERY: Record<string, string[]> = {\n alma_cost_projection_pending: [\"org\", \"uid\", \"consumer\", \"cost_id\"],\n alma_audit_cost: [\"org\", \"uid\", \"id\", \"at\", \"settlement_id\", \"settlement_governed\"],\n};\n/** Runs in the execution namespace after the runtime's own migrations. */\nexport function projectionMigrationSql(schema: string): string {\n return `${roleBootstrapSql(PROJECTION_ROLE)}\ngrant usage on schema ${schema} to ${PROJECTION_ROLE};\n${Object.entries(DISCOVERY).map(([table, columns]) => `revoke all on ${table} from ${PROJECTION_ROLE};\ngrant select (${columns.join(\", \")}) on ${table} to ${PROJECTION_ROLE};\ndrop policy if exists alma_projection_discovery on ${table};\ncreate policy alma_projection_discovery on ${table} for select to ${PROJECTION_ROLE} using (true);`).join(\"\\n\")}\ncreate table if not exists alma_projection_cursors (\n consumer text collate \"C\" primary key, org text collate \"C\", uid text collate \"C\", updated_at timestamptz not null default clock_timestamp(),\n check ((org is null) = (uid is null))\n);\ncreate table if not exists alma_projection_scopes (\n consumer text collate \"C\" not null, org text collate \"C\" not null, uid text collate \"C\" not null,\n after jsonb, bound jsonb, budget int, updated_at timestamptz not null default clock_timestamp(),\n primary key (consumer, org, uid)\n);\n${[\"alma_projection_cursors\", \"alma_projection_scopes\"].map(t => `alter table ${t} enable row level security;\nalter table ${t} force row level security;\nrevoke all on ${t} from public, alma_app, alma_retention, alma_maintenance;\ndrop policy if exists alma_projection_only on ${t};\ncreate policy alma_projection_only on ${t} for all to ${PROJECTION_ROLE} using (true) with check (true);\ngrant select, insert, update on ${t} to ${PROJECTION_ROLE};`).join(\"\\n\")}\n`;\n}\n"],"mappings":"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","names":["roleBootstrapSql","DISCOVERY"]}
@@ -0,0 +1,31 @@
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
+ function isAuditLog(value) {
7
+ return !!value && typeof value === "object" && ["access", "routing", "cost", "recall", "context"].every((k) => typeof value[k] === "function");
8
+ }
9
+ function namespace(value) {
10
+ const { connectionString, schema, rootSchema, onPoolError } = value;
11
+ if (typeof onPoolError !== "function") throw new TypeError("Runtime requires onPoolError reporting");
12
+ for (const s of [schema, rootSchema]) {
13
+ if (typeof s !== "string" || !/^[a-z_][a-z0-9_]{0,62}$/.test(s) || s === "public" || s === "information_schema" || s.startsWith("pg_")) throw new TypeError("Invalid dedicated runtime schema");
14
+ }
15
+ if (schema === rootSchema) throw new TypeError("Runtime result namespaces must be distinct");
16
+ let url;
17
+ try {
18
+ url = new URL(connectionString);
19
+ } catch {
20
+ throw new TypeError("Invalid PostgreSQL connection URL");
21
+ }
22
+ if (!["postgres:", "postgresql:"].includes(url.protocol) || !url.hostname || url.searchParams.has("options")) throw new TypeError("Runtime requires a PostgreSQL URL without startup options");
23
+ return { connectionString, schema, rootSchema, onPoolError };
24
+ }
25
+
26
+ export {
27
+ policies,
28
+ isAuditLog,
29
+ namespace
30
+ };
31
+ //# sourceMappingURL=chunk-II7NDZRL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/policies.ts"],"sourcesContent":["import { normalizeExecutionResultPolicy } from \"@alma-harness/memory\";\nimport type { AuditLog } from \"@alma-harness/core\";\nimport type { RuntimePolicies } from \"./index\";\nimport type { PostgresRuntimeNamespace } from \"./postgres\";\nexport function policies(value: RuntimePolicies): RuntimePolicies {\n return { stepResultPolicy: normalizeExecutionResultPolicy(value.stepResultPolicy), rootResultPolicy: normalizeExecutionResultPolicy(value.rootResultPolicy) };\n}\n/** An object carrying all five audit families; anything else fails construction rather than going unaudited. */\nexport function isAuditLog(value: unknown): value is AuditLog {\n return !!value && typeof value === \"object\" && [\"access\", \"routing\", \"cost\", \"recall\", \"context\"].every(k => typeof (value as Record<string, unknown>)[k] === \"function\");\n}\n\n/** One validation for every login a runtime composition opens: dedicated schemas and a URL without startup options. */\nexport function namespace(value: PostgresRuntimeNamespace): PostgresRuntimeNamespace {\n const { connectionString, schema, rootSchema, onPoolError } = value;\n if (typeof onPoolError !== \"function\") throw new TypeError(\"Runtime requires onPoolError reporting\");\n for (const s of [schema, rootSchema]) {\n if (typeof s !== \"string\" || !/^[a-z_][a-z0-9_]{0,62}$/.test(s) || s === \"public\" || s === \"information_schema\" || s.startsWith(\"pg_\")) throw new TypeError(\"Invalid dedicated runtime schema\");\n }\n if (schema === rootSchema) throw new TypeError(\"Runtime result namespaces must be distinct\");\n let url: URL;\n try { url = new URL(connectionString); } catch { throw new TypeError(\"Invalid PostgreSQL connection URL\"); }\n if (![\"postgres:\", \"postgresql:\"].includes(url.protocol) || !url.hostname || url.searchParams.has(\"options\")) throw new TypeError(\"Runtime requires a PostgreSQL URL without startup options\");\n return { connectionString, schema, rootSchema, onPoolError };\n}\n"],"mappings":";AAAA,SAAS,sCAAsC;AAIxC,SAAS,SAAS,OAAyC;AAChE,SAAO,EAAE,kBAAkB,+BAA+B,MAAM,gBAAgB,GAAG,kBAAkB,+BAA+B,MAAM,gBAAgB,EAAE;AAC9J;AAEO,SAAS,WAAW,OAAmC;AAC5D,SAAO,CAAC,CAAC,SAAS,OAAO,UAAU,YAAY,CAAC,UAAU,WAAW,QAAQ,UAAU,SAAS,EAAE,MAAM,OAAK,OAAQ,MAAkC,CAAC,MAAM,UAAU;AAC1K;AAGO,SAAS,UAAU,OAA2D;AACnF,QAAM,EAAE,kBAAkB,QAAQ,YAAY,YAAY,IAAI;AAC9D,MAAI,OAAO,gBAAgB,WAAY,OAAM,IAAI,UAAU,wCAAwC;AACnG,aAAW,KAAK,CAAC,QAAQ,UAAU,GAAG;AACpC,QAAI,OAAO,MAAM,YAAY,CAAC,0BAA0B,KAAK,CAAC,KAAK,MAAM,YAAY,MAAM,wBAAwB,EAAE,WAAW,KAAK,EAAG,OAAM,IAAI,UAAU,kCAAkC;AAAA,EAChM;AACA,MAAI,WAAW,WAAY,OAAM,IAAI,UAAU,4CAA4C;AAC3F,MAAI;AACJ,MAAI;AAAE,UAAM,IAAI,IAAI,gBAAgB;AAAA,EAAG,QAAQ;AAAE,UAAM,IAAI,UAAU,mCAAmC;AAAA,EAAG;AAC3G,MAAI,CAAC,CAAC,aAAa,aAAa,EAAE,SAAS,IAAI,QAAQ,KAAK,CAAC,IAAI,YAAY,IAAI,aAAa,IAAI,SAAS,EAAG,OAAM,IAAI,UAAU,2DAA2D;AAC7L,SAAO,EAAE,kBAAkB,QAAQ,YAAY,YAAY;AAC7D;","names":[]}
@@ -0,0 +1,88 @@
1
+ import * as _alma_harness_conversation from '@alma-harness/conversation';
2
+ import { ConversationConfig } from '@alma-harness/conversation';
3
+ import * as _alma_harness_execution from '@alma-harness/execution';
4
+ import * as _alma_harness_core from '@alma-harness/core';
5
+ import { BudgetCaps, ProviderId, SingleDispatchModelClient, ModelPrice } from '@alma-harness/core';
6
+ import * as _alma_harness_single_call from '@alma-harness/single-call';
7
+ import { SingleCallConfig, StructuredCallConfig } from '@alma-harness/single-call';
8
+ import { Runtime } from './index.js';
9
+
10
+ interface DeploymentLimits {
11
+ deadlineMs?: number;
12
+ runTimeoutMs?: number;
13
+ stepTimeoutMs?: number;
14
+ maxCalls?: number;
15
+ maxInputChars?: number;
16
+ maxRequestChars?: number;
17
+ maxOutputChars?: number;
18
+ }
19
+ type Observer = SingleCallConfig["onBackgroundError"];
20
+ interface RuntimeDeploymentOptions {
21
+ runtime: Runtime;
22
+ clients: Partial<Record<ProviderId, SingleDispatchModelClient>>;
23
+ prices: ModelPrice[];
24
+ priceVersion: string;
25
+ consumers: string[];
26
+ caps: BudgetCaps;
27
+ retentionMs: number;
28
+ limits?: DeploymentLimits;
29
+ onBackgroundError: Observer;
30
+ }
31
+ /** `caps` replaces the deployment's caps whole; `limits` merge field by field. */
32
+ interface OperationOverrides {
33
+ caps?: BudgetCaps;
34
+ limits?: DeploymentLimits;
35
+ onBackgroundError?: Observer;
36
+ }
37
+ type TextSupplied = "executions" | "results" | "inbox" | "settlements" | "spend" | "audit" | "clients" | "prices" | "priceVersion" | "consumers" | "resultRetentionMs" | "caps" | "maxInputChars" | "maxOutputChars" | "deadlineMs" | "onBackgroundError";
38
+ type SingleCallOperation = Omit<SingleCallConfig, TextSupplied> & OperationOverrides;
39
+ type StructuredCallOperation = Omit<StructuredCallConfig, TextSupplied | "trees" | "accounting"> & OperationOverrides;
40
+ type ConversationOperation = Omit<ConversationConfig, "sessions" | "admissions" | "rootResults" | "step" | "prices" | "priceVersion" | "consumers" | "resultRetentionMs" | "caps" | "runTimeoutMs" | "maxCalls" | "maxInputChars"> & OperationOverrides;
41
+ /** Deployment choices given once. Runners come from the existing factories, which keep every validation and binding. */
42
+ declare function createRuntimeDeployment(value: RuntimeDeploymentOptions): {
43
+ singleCall(value: SingleCallOperation): {
44
+ run: (value: _alma_harness_single_call.SingleCallInput) => Promise<_alma_harness_single_call.SingleCallView>;
45
+ read: (scope: _alma_harness_core.Scope, operationKey: string) => Promise<_alma_harness_single_call.SingleCallView | null>;
46
+ recover: (scope: _alma_harness_core.Scope, operationKey: string, opts: {
47
+ leaseMs: number;
48
+ }) => Promise<_alma_harness_single_call.SingleCallView | null>;
49
+ reconcileUsage: (scope: _alma_harness_core.Scope, query?: _alma_harness_core.UsageInboxQuery, options?: {
50
+ skip?(operationKey: string): boolean | Promise<boolean>;
51
+ }) => Promise<{
52
+ after?: {
53
+ receivedAt: string;
54
+ id: string;
55
+ };
56
+ scanned: number;
57
+ acknowledged: number;
58
+ }>;
59
+ reconcileExpired: (scope: _alma_harness_core.Scope, opts?: {
60
+ limit?: number;
61
+ }) => Promise<_alma_harness_core.ExecutionRecord[]>;
62
+ };
63
+ structuredCall(value: StructuredCallOperation): {
64
+ run: (value: _alma_harness_single_call.SingleCallInput) => Promise<_alma_harness_single_call.StructuredCallView>;
65
+ read: (scope: _alma_harness_core.Scope, operationKey: string) => Promise<_alma_harness_single_call.StructuredCallView | null>;
66
+ recover(scope: _alma_harness_core.Scope, operationKey: string, opts: {
67
+ leaseMs: number;
68
+ }): Promise<_alma_harness_single_call.GovernedStepView | null>;
69
+ reconcileUsage(scope: _alma_harness_core.Scope, operationKey: string, query?: _alma_harness_core.UsageInboxQuery): Promise<{
70
+ after?: {
71
+ receivedAt: string;
72
+ id: string;
73
+ };
74
+ scanned: number;
75
+ acknowledged: number;
76
+ }>;
77
+ reconcileExpired(scope: _alma_harness_core.Scope, opts?: {
78
+ limit?: number;
79
+ }): Promise<{
80
+ roots: _alma_harness_execution.OperationRootRecord[];
81
+ executions: _alma_harness_core.ExecutionRecord[];
82
+ }>;
83
+ };
84
+ conversation(value: ConversationOperation): _alma_harness_conversation.ConversationRunner;
85
+ };
86
+ type RuntimeDeployment = ReturnType<typeof createRuntimeDeployment>;
87
+
88
+ export { type ConversationOperation, type DeploymentLimits, type OperationOverrides, type RuntimeDeployment, type RuntimeDeploymentOptions, type SingleCallOperation, type StructuredCallOperation, createRuntimeDeployment };
@@ -0,0 +1,130 @@
1
+ import {
2
+ isAuditLog
3
+ } from "./chunk-II7NDZRL.js";
4
+
5
+ // src/deployment.ts
6
+ import { createConversationRunner } from "@alma-harness/conversation";
7
+ import { createSingleCallRunner, createStructuredCallRunner } from "@alma-harness/single-call";
8
+ var LIMITS = ["deadlineMs", "runTimeoutMs", "stepTimeoutMs", "maxCalls", "maxInputChars", "maxRequestChars", "maxOutputChars"];
9
+ var OWNED = /* @__PURE__ */ new Set([
10
+ "sessions",
11
+ "admissions",
12
+ "rootResults",
13
+ "executions",
14
+ "results",
15
+ "inbox",
16
+ "settlements",
17
+ "spend",
18
+ "trees",
19
+ "accounting",
20
+ "labels",
21
+ "audit",
22
+ "clients",
23
+ "prices",
24
+ "priceVersion",
25
+ "consumers",
26
+ "resultRetentionMs",
27
+ "step",
28
+ ...LIMITS
29
+ ]);
30
+ var invalid = (what) => {
31
+ throw new TypeError(`Invalid runtime deployment ${what}`);
32
+ };
33
+ var record = (value, what) => value && typeof value === "object" && !Array.isArray(value) ? value : invalid(what);
34
+ function data(value, what) {
35
+ const d = Object.getOwnPropertyDescriptors(record(value, what));
36
+ return Object.fromEntries(Reflect.ownKeys(d).map((k) => {
37
+ const p = d[k];
38
+ if (typeof k !== "string" || !("value" in p) || p.value === void 0) invalid(what);
39
+ return [k, p.value];
40
+ }));
41
+ }
42
+ function limits(value) {
43
+ const l = data(value, "limits");
44
+ for (const [k, n] of Object.entries(l)) if (!LIMITS.includes(k) || !Number.isSafeInteger(n) || n < 1) invalid("limits");
45
+ return l;
46
+ }
47
+ function createRuntimeDeployment(value) {
48
+ const o = data(value, "options");
49
+ for (const k of Object.keys(o)) if (!["runtime", "clients", "prices", "priceVersion", "consumers", "caps", "retentionMs", "limits", "onBackgroundError"].includes(k)) invalid("options");
50
+ const runtimeStores = record(record(o.runtime, "runtime").stores, "runtime");
51
+ const stores = { ...runtimeStores, step: { ...record(runtimeStores.step, "runtime") } };
52
+ if (!isAuditLog(stores.audit)) invalid("audit");
53
+ const clients = { ...record(o.clients, "clients") };
54
+ if (!Array.isArray(o.prices) || !Array.isArray(o.consumers) || typeof o.priceVersion !== "string" || typeof o.onBackgroundError !== "function") invalid("options");
55
+ if (!Number.isSafeInteger(o.retentionMs) || o.retentionMs < 1) invalid("retention");
56
+ const prices = structuredClone(o.prices), consumers = [...o.consumers], caps = structuredClone(record(o.caps, "caps"));
57
+ const base = limits(o.limits ?? {}), observer = o.onBackgroundError, priceVersion = o.priceVersion, retention = o.retentionMs;
58
+ function split(value2, required) {
59
+ const { caps: c, limits: l, onBackgroundError: ob, ...operation } = data(value2, "operation");
60
+ for (const k of Object.keys(operation)) if (OWNED.has(k)) invalid(`operation field ${k}`);
61
+ if (ob !== void 0 && typeof ob !== "function") invalid("operation observer");
62
+ const merged = { ...base, ...l === void 0 ? {} : limits(l) };
63
+ for (const k of required) if (merged[k] === void 0) invalid(`limit ${k}`);
64
+ return {
65
+ operation,
66
+ caps: structuredClone(c === void 0 ? caps : record(c, "caps")),
67
+ limits: merged,
68
+ onBackgroundError: ob ?? observer
69
+ };
70
+ }
71
+ const text = (s) => ({
72
+ executions: stores.step.executions,
73
+ results: stores.step.results,
74
+ inbox: stores.step.inbox,
75
+ settlements: stores.step.settlements,
76
+ spend: stores.step.spend,
77
+ audit: stores.audit,
78
+ clients: { ...clients },
79
+ prices: structuredClone(prices),
80
+ priceVersion,
81
+ consumers: [...consumers],
82
+ caps: s.caps,
83
+ resultRetentionMs: retention,
84
+ deadlineMs: s.limits.deadlineMs,
85
+ maxInputChars: s.limits.maxInputChars,
86
+ maxOutputChars: s.limits.maxOutputChars,
87
+ onBackgroundError: s.onBackgroundError
88
+ });
89
+ const TEXT = ["deadlineMs", "maxInputChars", "maxOutputChars"];
90
+ return {
91
+ singleCall(value2) {
92
+ const s = split(value2, TEXT);
93
+ return createSingleCallRunner({ ...s.operation, ...text(s) });
94
+ },
95
+ structuredCall(value2) {
96
+ const s = split(value2, TEXT);
97
+ return createStructuredCallRunner({ ...s.operation, ...text(s), trees: stores.step.trees, accounting: stores.step.accounting });
98
+ },
99
+ conversation(value2) {
100
+ const s = split(value2, ["runTimeoutMs", "stepTimeoutMs", "maxCalls", "maxInputChars", "maxRequestChars", "maxOutputChars"]);
101
+ return createConversationRunner({
102
+ ...s.operation,
103
+ sessions: stores.sessions,
104
+ admissions: stores.admissions,
105
+ rootResults: stores.rootResults,
106
+ prices: structuredClone(prices),
107
+ priceVersion,
108
+ consumers: [...consumers],
109
+ caps: s.caps,
110
+ resultRetentionMs: retention,
111
+ runTimeoutMs: s.limits.runTimeoutMs,
112
+ maxCalls: s.limits.maxCalls,
113
+ maxInputChars: s.limits.maxInputChars,
114
+ step: {
115
+ ...stores.step,
116
+ audit: stores.audit,
117
+ clients: { ...clients },
118
+ runTimeoutMs: s.limits.stepTimeoutMs,
119
+ maxRequestChars: s.limits.maxRequestChars,
120
+ maxOutputChars: s.limits.maxOutputChars,
121
+ onBackgroundError: s.onBackgroundError
122
+ }
123
+ });
124
+ }
125
+ };
126
+ }
127
+ export {
128
+ createRuntimeDeployment
129
+ };
130
+ //# sourceMappingURL=deployment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/deployment.ts"],"sourcesContent":["import type { BudgetCaps, ModelPrice, ProviderId, SingleDispatchModelClient } from \"@alma-harness/core\";\nimport { createConversationRunner, type ConversationConfig } from \"@alma-harness/conversation\";\nimport { createSingleCallRunner, createStructuredCallRunner, type SingleCallConfig, type StructuredCallConfig } from \"@alma-harness/single-call\";\nimport type { Runtime } from \"./index\";\nimport { isAuditLog } from \"./policies\";\n\nexport interface DeploymentLimits {\n deadlineMs?: number; runTimeoutMs?: number; stepTimeoutMs?: number; maxCalls?: number;\n maxInputChars?: number; maxRequestChars?: number; maxOutputChars?: number;\n}\ntype Observer = SingleCallConfig[\"onBackgroundError\"];\nexport interface RuntimeDeploymentOptions {\n runtime: Runtime;\n clients: Partial<Record<ProviderId, SingleDispatchModelClient>>;\n prices: ModelPrice[]; priceVersion: string; consumers: string[];\n caps: BudgetCaps; retentionMs: number; limits?: DeploymentLimits;\n onBackgroundError: Observer;\n}\n/** `caps` replaces the deployment's caps whole; `limits` merge field by field. */\nexport interface OperationOverrides { caps?: BudgetCaps; limits?: DeploymentLimits; onBackgroundError?: Observer }\ntype TextSupplied = \"executions\" | \"results\" | \"inbox\" | \"settlements\" | \"spend\" | \"audit\" | \"clients\" | \"prices\" | \"priceVersion\" | \"consumers\"\n | \"resultRetentionMs\" | \"caps\" | \"maxInputChars\" | \"maxOutputChars\" | \"deadlineMs\" | \"onBackgroundError\";\nexport type SingleCallOperation = Omit<SingleCallConfig, TextSupplied> & OperationOverrides;\nexport type StructuredCallOperation = Omit<StructuredCallConfig, TextSupplied | \"trees\" | \"accounting\"> & OperationOverrides;\nexport type ConversationOperation = Omit<ConversationConfig, \"sessions\" | \"admissions\" | \"rootResults\" | \"step\" | \"prices\" | \"priceVersion\" | \"consumers\"\n | \"resultRetentionMs\" | \"caps\" | \"runTimeoutMs\" | \"maxCalls\" | \"maxInputChars\"> & OperationOverrides;\n\nconst LIMITS = [\"deadlineMs\", \"runTimeoutMs\", \"stepTimeoutMs\", \"maxCalls\", \"maxInputChars\", \"maxRequestChars\", \"maxOutputChars\"] as const;\ntype Limit = typeof LIMITS[number];\n// DECISION: one owned set for every runner kind. None of these is a legitimate operation field of any kind.\nconst OWNED = new Set<string>([\"sessions\", \"admissions\", \"rootResults\", \"executions\", \"results\", \"inbox\", \"settlements\", \"spend\", \"trees\", \"accounting\",\n \"labels\", \"audit\", \"clients\", \"prices\", \"priceVersion\", \"consumers\", \"resultRetentionMs\", \"step\", ...LIMITS]);\nconst invalid = (what: string): never => { throw new TypeError(`Invalid runtime deployment ${what}`); };\nconst record = (value: unknown, what: string): Record<string, unknown> =>\n value && typeof value === \"object\" && !Array.isArray(value) ? value as Record<string, unknown> : invalid(what);\n\n/** Own data properties only: an accessor or an explicit undefined never reads as omitted. */\nfunction data(value: unknown, what: string): Record<string, unknown> {\n const d = Object.getOwnPropertyDescriptors(record(value, what));\n return Object.fromEntries(Reflect.ownKeys(d).map(k => {\n const p = d[k as string]!;\n if (typeof k !== \"string\" || !(\"value\" in p) || p.value === undefined) invalid(what);\n return [k, p.value];\n }));\n}\nfunction limits(value: unknown): DeploymentLimits {\n const l = data(value, \"limits\");\n for (const [k, n] of Object.entries(l)) if (!(LIMITS as readonly string[]).includes(k) || !Number.isSafeInteger(n) || (n as number) < 1) invalid(\"limits\");\n return l as DeploymentLimits;\n}\n\n/** Deployment choices given once. Runners come from the existing factories, which keep every validation and binding. */\nexport function createRuntimeDeployment(value: RuntimeDeploymentOptions) {\n const o = data(value, \"options\") as unknown as RuntimeDeploymentOptions;\n for (const k of Object.keys(o)) if (![\"runtime\", \"clients\", \"prices\", \"priceVersion\", \"consumers\", \"caps\", \"retentionMs\", \"limits\", \"onBackgroundError\"].includes(k)) invalid(\"options\");\n // Snapshot: collections copied at both store levels; the capabilities inside stay the originals.\n const runtimeStores = record(record(o.runtime, \"runtime\").stores, \"runtime\") as unknown as Runtime[\"stores\"];\n const stores = { ...runtimeStores, step: { ...record(runtimeStores.step, \"runtime\") } } as Runtime[\"stores\"];\n if (!isAuditLog(stores.audit)) invalid(\"audit\");\n const clients = { ...record(o.clients, \"clients\") } as RuntimeDeploymentOptions[\"clients\"];\n if (!Array.isArray(o.prices) || !Array.isArray(o.consumers) || typeof o.priceVersion !== \"string\" || typeof o.onBackgroundError !== \"function\") invalid(\"options\");\n if (!Number.isSafeInteger(o.retentionMs) || o.retentionMs < 1) invalid(\"retention\");\n const prices = structuredClone(o.prices), consumers = [...o.consumers], caps = structuredClone(record(o.caps, \"caps\")) as BudgetCaps;\n const base = limits(o.limits ?? {}), observer = o.onBackgroundError, priceVersion = o.priceVersion, retention = o.retentionMs;\n\n function split(value: unknown, required: readonly Limit[]) {\n const { caps: c, limits: l, onBackgroundError: ob, ...operation } = data(value, \"operation\");\n for (const k of Object.keys(operation)) if (OWNED.has(k)) invalid(`operation field ${k}`);\n if (ob !== undefined && typeof ob !== \"function\") invalid(\"operation observer\");\n const merged: DeploymentLimits = { ...base, ...(l === undefined ? {} : limits(l)) };\n for (const k of required) if (merged[k] === undefined) invalid(`limit ${k}`);\n return { operation, caps: structuredClone(c === undefined ? caps : record(c, \"caps\")) as BudgetCaps,\n limits: merged as Required<DeploymentLimits>, onBackgroundError: (ob ?? observer) as Observer };\n }\n const text = (s: ReturnType<typeof split>) => ({ executions: stores.step.executions, results: stores.step.results, inbox: stores.step.inbox,\n settlements: stores.step.settlements, spend: stores.step.spend, audit: stores.audit, clients: { ...clients }, prices: structuredClone(prices),\n priceVersion, consumers: [...consumers], caps: s.caps, resultRetentionMs: retention, deadlineMs: s.limits.deadlineMs,\n maxInputChars: s.limits.maxInputChars, maxOutputChars: s.limits.maxOutputChars, onBackgroundError: s.onBackgroundError });\n const TEXT = [\"deadlineMs\", \"maxInputChars\", \"maxOutputChars\"] as const;\n return {\n singleCall(value: SingleCallOperation) {\n const s = split(value, TEXT);\n return createSingleCallRunner({ ...s.operation, ...text(s) } as SingleCallConfig);\n },\n structuredCall(value: StructuredCallOperation) {\n const s = split(value, TEXT);\n return createStructuredCallRunner({ ...s.operation, ...text(s), trees: stores.step.trees, accounting: stores.step.accounting } as StructuredCallConfig);\n },\n conversation(value: ConversationOperation) {\n const s = split(value, [\"runTimeoutMs\", \"stepTimeoutMs\", \"maxCalls\", \"maxInputChars\", \"maxRequestChars\", \"maxOutputChars\"]);\n return createConversationRunner({ ...s.operation, sessions: stores.sessions, admissions: stores.admissions, rootResults: stores.rootResults,\n prices: structuredClone(prices), priceVersion, consumers: [...consumers], caps: s.caps, resultRetentionMs: retention,\n runTimeoutMs: s.limits.runTimeoutMs, maxCalls: s.limits.maxCalls, maxInputChars: s.limits.maxInputChars,\n step: { ...stores.step, audit: stores.audit, clients: { ...clients }, runTimeoutMs: s.limits.stepTimeoutMs,\n maxRequestChars: s.limits.maxRequestChars, maxOutputChars: s.limits.maxOutputChars, onBackgroundError: s.onBackgroundError },\n } as ConversationConfig);\n },\n };\n}\nexport type RuntimeDeployment = ReturnType<typeof createRuntimeDeployment>;\n"],"mappings":"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","names":["value"]}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ExecutionResultPolicy } from '@alma-harness/core';
1
+ import { SessionLabelStore, AuditLog, ExecutionResultPolicy } from '@alma-harness/core';
2
2
  import { ConversationConfig } from '@alma-harness/conversation';
3
3
 
4
4
  interface RuntimePolicies {
@@ -7,6 +7,10 @@ interface RuntimePolicies {
7
7
  }
8
8
  type RuntimeStores = Pick<ConversationConfig, "sessions" | "admissions" | "rootResults"> & {
9
9
  step: Pick<ConversationConfig["step"], "executions" | "results" | "inbox" | "settlements" | "spend" | "trees" | "accounting">;
10
+ /** Host attribution per session; register it with erasure (spec: session-labels). */
11
+ labels: SessionLabelStore;
12
+ /** The runtime's own audit trail, on the execution namespace (spec: runtime-deployment). */
13
+ audit: AuditLog;
10
14
  };
11
15
  interface Runtime {
12
16
  stores: RuntimeStores;
@@ -0,0 +1,73 @@
1
+ import { UsageInboxQuery, Scope } from '@alma-harness/core';
2
+ import { RuntimeStores } from './index.js';
3
+
4
+ type ExecutionCursor = {
5
+ createdAt: string;
6
+ operationKey: string;
7
+ };
8
+ type UsageCursor = NonNullable<UsageInboxQuery["after"]>;
9
+ interface RecoverableExecution {
10
+ operationKey: string;
11
+ createdAt: string;
12
+ rootKey: string | null;
13
+ }
14
+ interface ScopeClaim {
15
+ alive(): boolean;
16
+ release(): Promise<void>;
17
+ onLost?(fn: () => void): void;
18
+ }
19
+ /** A finite lap: items after `after` up to `bound`, at most `budget` more attempts (spec: receipt-projections). A null bound is a cursor written before laps existed. */
20
+ interface Lap<C> {
21
+ after: C | null;
22
+ bound: C | null;
23
+ budget: number | null;
24
+ }
25
+ interface MaintenanceCursors {
26
+ executions: Lap<ExecutionCursor> | null;
27
+ usage: Lap<UsageCursor> | null;
28
+ }
29
+ /** Cross-scope metadata only: identifiers, states, times and the maintenance cursors (spec: runtime-maintenance). */
30
+ interface MaintenanceDiscovery {
31
+ /** Throws unless the logins keep discovery and scoped work apart. */
32
+ verify(): Promise<void>;
33
+ nextScopes(limit: number): Promise<Scope[]>;
34
+ claim(scope: Scope): Promise<ScopeClaim | null>;
35
+ recoverable(scope: Scope, after: ExecutionCursor | null, bound: ExecutionCursor, limit: number): Promise<RecoverableExecution[]>;
36
+ /** The greatest eligible execution and how many are eligible up to it; null when none is. */
37
+ executionLap(scope: Scope): Promise<{
38
+ bound: ExecutionCursor;
39
+ budget: number;
40
+ } | null>;
41
+ usageLap(scope: Scope): Promise<{
42
+ bound: UsageCursor;
43
+ budget: number;
44
+ } | null>;
45
+ /** Root keys of the given operation keys that are members of a root. */
46
+ members(scope: Scope, operationKeys: string[]): Promise<Map<string, string>>;
47
+ cursors(scope: Scope): Promise<MaintenanceCursors>;
48
+ saveCursors(scope: Scope, cursors: MaintenanceCursors): Promise<void>;
49
+ }
50
+ interface MaintenanceReport {
51
+ scopes: number;
52
+ skipped: number;
53
+ expired: {
54
+ admissions: number;
55
+ roots: number;
56
+ executions: number;
57
+ };
58
+ recovered: number;
59
+ acknowledged: number;
60
+ failed: number;
61
+ }
62
+ /** Store work per scope; no client, no release, no content in the report. */
63
+ declare function createMaintenance(options: {
64
+ stores: RuntimeStores;
65
+ discovery: MaintenanceDiscovery;
66
+ }): {
67
+ maintain(value: {
68
+ limit: number;
69
+ signal?: AbortSignal;
70
+ }): Promise<MaintenanceReport>;
71
+ };
72
+
73
+ export { type ExecutionCursor as E, type Lap as L, type MaintenanceReport as M, type RecoverableExecution as R, type ScopeClaim as S, type UsageCursor as U, type MaintenanceDiscovery as a, type MaintenanceCursors as b, createMaintenance as c };
@@ -0,0 +1,32 @@
1
+ import { M as MaintenanceReport, a as MaintenanceDiscovery } from './maintenance-core-DDX5ryx7.js';
2
+ export { E as ExecutionCursor, L as Lap, b as MaintenanceCursors, R as RecoverableExecution, S as ScopeClaim, U as UsageCursor, c as createMaintenance } from './maintenance-core-DDX5ryx7.js';
3
+ import pg from 'pg';
4
+ import { RuntimePolicies } from './index.js';
5
+ import '@alma-harness/core';
6
+ import '@alma-harness/conversation';
7
+
8
+ interface PostgresMaintenanceOptions extends RuntimePolicies {
9
+ /** A login that is a member of alma_maintenance only. */
10
+ discovery: {
11
+ connectionString: string;
12
+ };
13
+ /** A login that is a member of alma_app only, never the request path's. */
14
+ worker: {
15
+ connectionString: string;
16
+ };
17
+ schema: string;
18
+ rootSchema: string;
19
+ onPoolError: (error: Error, schema: string) => void;
20
+ }
21
+ /** The PostgreSQL discovery on a pool of the discovery login; `workerURL` is only used to verify the worker login. */
22
+ declare function createPostgresMaintenanceDiscovery(pool: pg.Pool, workerURL: string): MaintenanceDiscovery;
23
+ /** Its own logins and pools, never the request path's. Construction opens no connection (spec: runtime-maintenance). */
24
+ declare function createPostgresMaintenance(value: PostgresMaintenanceOptions): {
25
+ maintain: (value: {
26
+ limit: number;
27
+ signal?: AbortSignal;
28
+ }) => Promise<MaintenanceReport>;
29
+ close(): Promise<void>;
30
+ };
31
+
32
+ export { MaintenanceDiscovery, MaintenanceReport, type PostgresMaintenanceOptions, createPostgresMaintenance, createPostgresMaintenanceDiscovery };