Skip to content

6. Persistence

Context

The Phylactery is LychD's jurisdiction for committed truth. It gives one body a transactional home for relational records, JSON documents, vectors, execution history, and recoverable graph state; it does not decide what a Domain record means.

Decision

PostgreSQL is the single-node persistence backend. LychD reaches it through async SQLAlchemy and asyncpg. The Phylactery alone owns engine construction, codecs, sessions and transaction boundaries, migration order, and schema admission. Domains own record meaning and lifecycle; neither they nor extension packages gain ambient migration authority.

In durable operation, Phylactery means PostgreSQL: the one database cluster assigned to an application partition. It is not a generic storage facade, a repository of interchangeable save/retrieve backends, or an abstraction that makes committed application truth backend-agnostic. Domain repositories isolate SQL mechanics and permit bounded test substitutes; they do not turn a process-local or in-memory store into a deployed Phylactery. LychD does not use loose application-managed files as a shadow database around PostgreSQL transactions, constraints, and migrations.

Core owns the schema-admission seam across native and extension models. Every admitted model derives from Core's UUIDBase; an extension explicitly calls register_model(MyModel) during initialization; Core aggregates those references before Alembic derives migration order. Runtime package scanning is not admission, and migration generation or application remains an explicit release or operator act. Colliding models, table names, or migrations refuse before a schema is changed.

The target chambers are deliberately logical rather than a claim of present deployment:

Chamber Responsibility
public relational state, configuration, and extension registries
vectors attributed vector material, including its trust status
traces execution and observability traces
queue durable work distribution
verbatim JSONB exact values that must be consulted before semantic retrieval

vectors status can distinguish, for example, speculative material from governed precedent; consecration records authority, not universal factual truth.

Default topology and scale seam

The default topology is one LychD host with one Phylactery—one PostgreSQL cluster—for its application partition. Capacity scales up before it scales out: an operator may enlarge or relocate the physical storage beneath the admitted postgres/data mount without changing application authority. Member disks, filesystems, and volume topology remain host substrate rather than domain or table-routing facts. The move must preserve Layout identity and use a PostgreSQL-consistent capture or restore; this decision promises no automatic or online storage expansion.

Scale-up does not imply indefinite retention. Before automated retirement, every persisted record class must declare its owning lifecycle, holds and terminal eligibility, compaction or archival, deletion or tombstone and derivative handling, and operational maintenance. Age or disk pressure alone grants no deletion authority. The Reaper remains Shadow-owned branch hygiene; it has no ambient authority to trim Phylactery records.

One cluster does not require every PostgreSQL object to occupy the same physical storage tier. A measured later schema may use native partitioning and tablespaces to place identified relations, indexes, or partitions across local SSD, NVMe, or HDD mounts while callers continue to query one logical relation. This is physical placement inside one Phylactery, not an application storage adapter, independent backup target, or shard. Before admission, Layout and Containers must bind every durable mount, while Snapshots must capture and restore PGDATA and every tablespace at one PostgreSQL-consistent boundary. The current topology admits only the postgres/data mount; this decision promises neither a partition policy nor tablespace delivery.

A future Domain may admit a separate, named store only by amending the smallest existing Covenant that owns the responsibility and introducing its typed port. Such a store is not a Phylactery backend, inherits no authority over Phylactery relational records or PostgreSQL transactions by proximity, and must define its authorization, commit or handoff, retention and deletion, backup, restore, and reconciliation contract. A filesystem path alone is storage geography, never application authority.

This decision neither delivers nor promises sharding. A later amendment may assign different whole application partitions to separate PostgreSQL Phylacteries, with routing completed before a unit of work opens and typed handoffs between partitions. It admits no shared PGDATA, routing implementation, table-level, row-level, or intra-partition sharding, and no cross-Phylactery transaction. A Portal remains a remote capability road, while Intercom and Legion carry bounded work or references; none forms a shared database fabric.

Wire and work contracts

The async boundary uses the repository JSON serializer and deserializer. PostgreSQL binary json is the JSON payload; binary jsonb prefixes it with the \x01 format-version byte. The connection hook registers separate codecs for those wire shapes. Focused hook tests pin their exact framing, and a disposable PostgreSQL receipt round-trips both a plain json expression and JSONB through the production engine factory. Avoiding an intermediate text conversion is not zero-copy storage.

The loop-confined Run-ledger adapter deep-detaches mutable Run records, nested manifests, and event metadata on write and every public read. That matches the database adapter's value boundary: a caller cannot mutate canonical truth through an object it was handed. This parity rule does not turn the memory profile into durable evidence.

The same value boundary applies to loop-confined consent and Bridge-session stores. Censored arguments, turns, fragments, and model-history values are detached both when retained and when projected; mutating a submitted object or a read view cannot rewrite the store's canonical value.

Workers select pending work under row locks with SKIP LOCKED. Selection, ownership transition, and all facts that establish the claim commit atomically: no two workers may own one labor unit. The replaceable JSONB run_checkpoint is one unique, cascading row per run; it is recovery state, not the ordered run/step ledger.

Deployment authority and edge journals

One application partition has exactly one active Phylactery—one PostgreSQL cluster—and authority epoch. PostgreSQL is never exposed, shared, synchronously replicated, dual-written, or failed over across a WAN. Backups and inactive migration restores are recovery artifacts, not live authorities. Moving authority requires a quiesced, typed export/import that preserves schema, labels, dedupe and external-effect identities; it never copies an unrelated home partition by implication.

A platform adapter on another host may own a bounded durable journal for immutable envelope bytes, digests, external identities, attempt generations, and observed receipts. That journal proves only transport or effect custody. It cannot admit or settle application truth, own a Run, Context, Ward decision, Sigil, corpus judgment, or become a Phylactery replica. The authoritative body adopts events and settlements through typed authenticated operations. Loss or ambiguity remains explicit and never triggers silent application replay.

Each Run hop also owns one run_delivery row. Run admission or wait re-admission and its exact delivery identity commit together; broker publication happens afterward under an idempotent key. HELD, PENDING, PUBLISHED, CLAIMED, and SETTLED distinguish admission custody from broker acknowledgement and execution ownership. One partial unique index permits only one unsettled delivery per Run, while (run_id, enqueue_seq) permanently fences old workers. A process-owned relay repairs publication without treating the broker as canonical Run truth.

Migration 0004 refuses both introduction and removal of that delivery authority while any Run is nonterminal. PostgreSQL transactional DDL leaves the schema revision and outbox intact on refusal; an operator must settle or explicitly fail the work before crossing the boundary. This is a narrow delivery-schema compatibility fence, not a general application rollback mechanism.

Operator Nexus transitions reserve their caller-owned request id in nexus_swap_request before launch. The unique request id and immutable first target are a durable duplicate-effect fence, not a transition state machine: loss of the process-local ticket causes exact retries to refuse without relaunch rather than inventing an outcome. Migration 0007 refuses downgrade while any request identity remains; erase or archive is an explicit operator act, not an incidental rollback. The downgrade holds an ACCESS EXCLUSIVE lock through the refusal check and table removal so a concurrent old writer cannot create a request identity between inspection and DDL.

Consent waits persist their exact owner on Run.consent_id; newest-row ordering is not ownership. Settled Consent rows require a decision principal and decision time, while terminal delegated jobs require result evidence whose job and status match the durable row. Migration 0008 refuses an upgrade that would have to infer an existing consent-wait owner or accept settled rows without that evidence. Its downgrade refuses while any Run remains AWAITING_CONSENT, so exact ownership cannot be erased underneath live work.

Privacy and delivery boundary

Persistence is designed to retain the labels and lineage defined by Context: defaults may originate in table or column metadata, policy may refine them by row, subject, or namespace, and derivatives retain their material sources and transformations. Checkpoints, history, memory, artifacts, and delegated records retain the applicable label or omit sensitive content. Missing ORM annotation never makes raw data public.

This is storage and information-flow support, not declassification. Context owns the Privacy Cut; the trusted Security Egress Gate enforces the resulting decision immediately before transmission. Dispatcher may provisionally refuse or bind a capability, but it cannot declassify bytes. Exact label schema, row policy, and full production persistence remain subject to the delivery boundary in State of Work.

A reversible Privacy Cut persists no pseudonym map in Run, Graph checkpoint, receipt, event, or general Phylactery row. Those records may hold one opaque PseudonymMapLease@1 reference. Mapping bytes require the Context-owned lease registry and rehydration port backed by a deployment-local Privacy Vault with exact Cut/Run/attempt ownership, idempotent claim CAS, key epoch, TTL, access audit, and one per-lease data-encryption key that never enters ordinary backup. Expiry, revocation, consumption, or abandoned-work cleanup destroys that key; a restore drill proves any retained ciphertext undecryptable and never claims physical erasure from opaque provider media. Loss or expiry means rehydration is unavailable and never permits raw-history reconstruction.

The accepted Vault profile also contains transient plaintext: its map pages are unswappable or the host swap is disabled, core/crash dumps and debugger attachment are disabled, buffers are bounded and zeroized after use, and map material is excluded from traces and allocator diagnostics. A deployment unable to verify those properties cannot enable reversible Cuts.

Consequences

One logical state transition can share a PostgreSQL transaction, while write-heavy queue and trace tables need workload-specific retention and autovacuum policy. The delivery outbox is transactional with Run truth but not with the external SAQ transaction; its relay and exact keys close that gap. This is not a transactional Step/event outbox, complete behavioral parity between memory profiles and PostgreSQL repositories, or a production deployment receipt. A disposable two-boot application-factory lifecycle proves the repository composition with an offline model and HTTP test client; real host/model/browser operation remains outside that evidence.