@alma-harness/postgres-execution
v0.12.0
Published
PostgreSQL operation lineage for Alma.
Readme
@alma-harness/postgres-execution
PostgreSQL operation lineage (spec: durable-operation-lineage). This additive
package depends on the matching core, execution and postgres release; it
reuses the shared scoped transaction, role and statement-timeout helpers.
migrateOperationTreeStore(pool) installs the current execution shape helper and
alma_operation_roots/alma_operation_calls. PostgresOperationTreeStore(pool,
ScopedStoreOptions?) implements the neutral OperationTreeStore from execution.
Default transactions SET LOCAL ROLE alma_app and bind org/uid with a 30s timeout.
An explicit null role retains the existing host opt-out from role switching.
Migration needs the same privileged migration connection as postgres; runtime
connections use limited login membership via grantRole.
Claim a root once; only its first claimant receives an opaque fence. Reserve stable main/direct/delegate/summary slots before dispatch. Root/child scope, session, policy, caps, sensitivity and deadline must agree. Parent links stay within a root. SQL locks serialize ordinals; a trigger validates root admission and updates membership count atomically. Lost acknowledgements are resolved by scoped reads or equal reservation replay, never a new root execution authority.
A root claim INSERT uniqueness failure permits one read after rollback and connection
release. Only an exactly equal normalized binding returns existing, without a
fence; a closed or expired winner gains no renewed authority. Readback failures,
other SQL errors and COMMIT uncertainty remain errors. Mapped errors retain the
original PostgreSQL cause non-enumerably for trusted diagnostics; do not serialize
that cause into client output or routine logs (spec: operation-tree-claim-readback).
Expired roots cannot reserve even before reconcileExpired(scope) marks them for
reconciliation. The bounded sweep skips locked roots. close stops admission;
it does not mean accounting or delivery completed. listCalls pages by ordinal,
default50/max100, with at most512 members per root. Reads never return the fence
token. Metadata is content-free and retained; no deletion or takeover API exists.
Governed conversation and step runners bind these reservations before egress. Lineage itself creates no billable cost rows.
Root financial accounting
migrateOperationAccountingStore composes lineage and governed-cost migrations.
PostgresOperationAccountingStore reads actual governed receipts by registered
call identity and writes only alma_operation_financial_calls and
alma_operation_warnings. A root lock serializes accounting ordinals and totals;
SQL verifies financial associations and exact decision metadata, and inserts
warning evidence atomically. Source cost rows/counters are never incremented.
The source settlement and aggregate are separate transactions. Lost aggregate acknowledgements replay the stored receipt; missing aggregates can be repaired without root dispatch authority, including after closure/expiry. Scoped FKs retain the source governed rows; ordinary cost retention already preserves those rows. Summary counts do not certify completion or external delivery. Out-of-order root accounting uses original session/day amounts; root warnings are immutable evidence, not a notification outbox (spec: root-financial-receipts).
migrateOperationSessionStore(pool) installs scoped session lock rows and immutable
admissions. PostgresOperationSessionStore serializes claims across connections;
a partial unique index permits only one unfinished admission per scoped session.
Deadlines mark uncertainty without granting takeover. Finish requires the original
fence before expiry; its replay remains stable. Operator resolution has a separate
receipt and cannot be replayed as an owner finish.
Normal operations assume alma_app; explicit resolve assumes the separately
configured operatorRole (default alma_retention) with membership required and
FORCE RLS still active. Grant that membership only to the trusted reconciliation
host. Migration accepts matching role/operatorRole. Do not invoke resolution
from a runner, sweeper or timeout handler. Admit before root creation; a crash
between those transactions intentionally leaves the session occupied. Deploy
matching readers and roles before adoption; admission itself includes no automatic retention. See the governed-session-admission spec.
Operation-tree migration also upgrades the legacy parent-kind CHECK to permit parentless prelude summaries. Scoped parent FKs and lower-ordinal checks remain. Reapplying old migration SQL preserves the upgrade; old TypeScript readers may still reject this new representation and must be replaced before adoption.
Conversation request descriptors roundtrip through both admission input and the
nullable root request column. New SQL checks validate closed bounded metadata;
a root UPDATE trigger protects original binding fields while allowing existing
status/count changes. Migration retains legacy descriptor absence and survives
frozen old SQL replay. Install migrations before current adapters (which select the
new column), then replace old readers before enabling descriptors. No fabricated
revisions, content rows or charges are created (spec: conversation-root-binding).
Batch submission ownership
migrateBatchSubmissionStore adds alma_batch_submissions and alma_batch_items;
PostgresBatchSubmissionStore implements the execution package's neutral contract.
The parent insert creates the complete membership through a SQL trigger in the
same transaction. Scoped operation/call/settlement uniqueness and immutable JSON
bindings prevent reassociation. FORCE RLS covers both org and uid; use the ordinary
limited login with alma_app membership and statement-timeout settings. Runtime
gets no delete grants or ownership reset API.
SQL guards reject expired new dispatch, reverse transitions and acceptance without a prior dispatch marker. The clock is sampled after row locks. A late handle stays available under reconciliation; acceptance is not batch completion, accounting or permission to submit again. Scoped reads never expose the original fence token. SQL access remains a trusted host capability, as with existing fenced stores.
A claim INSERT uniqueness failure is read back once after transaction cleanup,
in a fresh scoped transaction. Only an identical complete normalized manifest
returns existing; no fence is recovered and the INSERT is never retried.
Missing or changed bindings still conflict; unrelated errors and lost COMMIT
acknowledgements cannot enable this path (spec: batch-claim-readback).
Mapped batch conflict/state errors retain the original SQL error in non-enumerable
cause, including any constraint/detail supplied by PostgreSQL. These diagnostics
are for trusted inspection only: they may contain scoped identifiers. Do not
serialize causes into client responses or automatically log the entire error.
Install the additive migration before constructing the adapter; populated replay is supported and old execution migrations leave the new tables intact. Input normalization caps manifests at 2 MiB; SQL additionally bounds JSONB text to 4 MiB because its numeric/whitespace encoding differs. All recursive metadata shapes are closed; content must use a separate result store. No automatic retention, provider access, collection, settlement or routine integration is included.
migrateBatchUsageStore composes batch and governed settlement migrations and
adds alma_batch_usage. PostgresBatchUsageStore uses the normal scoped limited
login and timeout options. SQL binds observations to the accepted handle/member,
checks closed evidence, and permits only a one-way association to an existing
matching governed cost. FORCE RLS and scoped FKs protect observations and source
receipt retention; app receives no delete grant. Readers validate complete saved
pricing and receipt consistency, failing on corrupt metadata.
Receipt adoption locks the observation first, then reads its joined receipt in a fresh SQL statement: a statement snapshot taken before a competing adoption must not mix the new association with old joined data. Lost append, settlement and adoption acknowledgements replay the same identities. The adapter never increments spend or invokes a provider. Install the additive migration before new readers; populated repeated upgrades preserve records. See execution's batch usage journal contract; content, valid EOF, collection completion and delivery remain separate. The SQL association guard also computes the frozen batch price, including highest applicable prompt band, cache fallback/one-hour rates and provider search charges. Parity tests compare its amount with core pricing; a matching identity/usage receipt with a different monetary amount cannot make an observation unreadable or resolved.
migrateBatchAccountingStore adds alma_batch_financial_items and
alma_batch_warnings on top of the batch usage migrations.
PostgresBatchAccountingStore uses the same limited scoped connection options.
A batch row lock serializes accounting ordinals and inclusive totals; item and
warning inserts commit atomically. Unique scoped item keys prevent two observations
from contributing twice. SQL checks the adopted observation, source amount,
manifest position and exact decisions/warning set. App grants are SELECT/INSERT
only; scoped FKs protect source observations. Populated upgrade replay is supported.
The adapter never writes monetary counters or cost rows and grants no execution
or channel-delivery authority.
SQL validators and triggers that depend on Alma objects pin their invoker path to
pg_catalog, installation_schema, pg_temp. Install in a trusted schema and rerun
current migrations before backup; old startup SQL may replace function settings.
This preserves CHECK evaluation during pg_restore and prevents caller-path shadows.
Tool selection in nested execution.controls.toolChoice remains part of each immutable call or batch item. Run both migrateOperationTreeStore and migrateBatchSubmissionStore before writing choices. Populated schemas upgrade their closed guards without changing existing records; versioned helpers preserve validation when older migration SQL is replayed. Reapplying the migrations preserves constraint identities. A changed choice conflicts with the original call slot or batch manifest and does not authorize another dispatch. Deploy readers that understand the optional field before enabling writers; prior binaries cannot normalize selected-tool records.
Session labels
migrateSessionLabelStore(pool) adds alma_session_labels; PostgresSessionLabelStore
implements core's SessionLabelStore under FORCE RLS with the standard scoped
options (spec: session-labels). A CHECK validates the label shape and the
available/erased state; a trigger freezes row identity and creation, allows only
available → erased and makes tombstones terminal. The row with an empty
session ID is the scope seal. alma_app gets SELECT/INSERT/UPDATE, never DELETE.
Every write takes a per-scope advisory lock, so put and erase serialize. The insert trigger takes the same lock, refuses labels in a sealed scope, and refuses to run outside read committed, since an older snapshot would miss a seal committed while it waited.
