Skip to main content

axonstore

Since v1.31.0 · Top-level declaration

Grammar

axonstore <Name> {
backend: <ident> # required — postgres | mysql | sqlite | in_memory
connection: "<conn-str>" # optional — backend connection string
isolation: <read_committed|repeatable_read|serializable> # optional
on_breach: <log|raise|rollback> # optional — policy on type-check breach
capability: "<slug.dotted>" # optional — required cap to access
confidence_floor: <0.0..1.0> # optional — minimum certainty
schema { <col>: <Type> [<constraint>...], ... } # optional — v1.31.0 inline schema
schema: "<manifest.ref>" # optional — manifest-bound schema
schema: env:VAR # optional — per-tenant schema env-var
}

axonstore declares a typed, audit-chained data store — the data-plane primitive that backs every v1.31.0+ persistence surface. It binds a name, a backend, an isolation level, an on-breach policy, and (optionally) a column schema, retention policy, encryption setting, and capability slug.

This is the structural commitment of the data plane: everything declared here is auditable, isolated by tenancy by construction, and gated by typed capability checks. The v2.0.0 column-proof rule cross-validates that compliance-tagged stores (compliance: [HIPAA]) carry the right tenant_id column; runtime mutations land in the v1.14.0 PIX provenance chain.

Surface

axonstore is a top-level declaration. It is not nested inside a dataspace, manifest, or flow.

axonstore PaymentVault {
backend: postgresql
connection: "postgres://payments.internal/vault"
isolation: serializable
on_breach: raise
capability: "payment.write"
schema {
txn_id: Text primary_key
amount: Numeric not_null
card_token: Text not_null
cardholder: Text
posted_at: Timestamp not_null
}
}

Column types are a closed v1.38.0 catalogue: Uuid | Text | Int | BigInt | Float | Double | Bool | Timestamp | Timestamptz | Date | Time | Json | Jsonb | Bytea | Numeric. The type names from the general type system (String, Number, Bool) do not appear here — axonstore column types map to SQL backend types directly.

Fields

backend: (required)

A single identifier naming the backend kind. Closed catalogue (axon-frontend::type_checker::VALID_STORE_BACKENDS):

ValueStatus
postgresqlProduction-ready. The standard.
mysqlType-check-valid; runtime-absent (future).
sqliteType-check-valid; runtime-absent (future).
in_memoryProduction-ready for tests + zero-infra demos.

connection: (optional)

A string literal containing the backend connection string. Format is backend-specific (Postgres URL, in-memory :memory:). Optional — for in_memory backends and for manifests that inject connection strings via env.

isolation: (optional)

A single identifier from the closed isolation catalogue (axon-frontend::type_checker::VALID_STORE_ISOLATION):

ValueSemantic
read_committedLowest — phantom reads allowed.
repeatable_readMiddle — snapshot per transaction.
serializableStrictest — serialisable. The production default for regulated stores.

on_breach: (optional)

A single identifier from the closed breach catalogue (axon-frontend::type_checker::VALID_STORE_ON_BREACH):

ValueBehaviour on a type-check breach (column-type mismatch, capability deny, etc.)
logEmit audit row + accept the mutation (development only).
raiseHalt with a typed error. Production default for compliance-tagged stores.
rollbackRoll back the current transaction; emit audit row.

capability: (optional, v1.30.0 D11)

A string literal containing a dotted-slug capability ("admin", "tenant.read", "hipaa.phi.read"). Mutations that don't carry this capability are rejected. Validated at parse time against the closed grammar ^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)*$.

confidence_floor: (optional)

A numeric literal in [0.0, 1.0]. Minimum certainty required to commit a write. Below the floor, mutations land in a quarantine table for review.

schema { ... } / schema: "<ref>" / schema: env:VAR (v1.31.0 D1)

Three closed forms for declaring the store's typed column schema:

(a) Inline — the most common:

schema {
id: BigInt primary_key identity
tenant_id: String not_null
amount: Number not_null
posted_at: Timestamp not_null default now()
}

Column constraints (position-independent): primary_key, auto_increment, identity (v1.31.0), not_null, unique, default <value>.

(b) Manifest referenceschema: "public.tenants". The schema is declared in a separate manifest file (typed + diff-reviewable).

(c) Env-var schemaschema: env:TENANT_SCHEMA or schema: "env:TENANT_SCHEMA". The schema namespace is read from an environment variable at runtime (per-tenant schemas on the same backend).

The runtime cross-validates the declared schema against the actual DDL at deploy time; mismatches surface as axon-E044 schema drift detected.

Runtime behaviour

axonstore lowers to an AxonStoreDefinition IR node. At deploy time, the runtime connects to the named backend, asserts isolation level, validates the schema (if declared), and arms the on-breach policy.

Every mutation flows through:

  1. Capability checkcapability: slug must be in the actor's capability set.
  2. Column proof — the v2.0.0 column proof verifies the mutation respects compliance tags (e.g. HIPAA-tagged store requires tenant_id in the WHERE clause).
  3. Type check — column types are enforced.
  4. PIX provenance row — every mutation lands in the declared pix chain (if one is bound).
  5. Audit rowaxonstore:<name>:<op> with full context.

Reading the store — retrieve (operations)

A declared store is read with a flow-body retrieve block. Beyond the where: filter and the as: result binding, two v2.21.0 clauses bound and order the result, and the v2.21.0 time-aware where: admits now() ± interval:

flow StaleSessions() -> Unit {
retrieve Sessions {
where: "last_activity_at < now() - interval '30 minutes'"
order_by: "last_activity_at desc"
limit: 100
as: stale
}
}
ClauseFormMeaningBad-input error
where:stringrow filter; time-aware forms are now() and now() ± interval '<n> <unit>' (v2.21.0)axon-T806 — malformed now() ± interval or a non-temporal column
order_by:string "col [asc|desc], …"sort terms; column existence proven when the store has an inline schemaaxon-T807 — empty term, bad identifier, bad direction, or unknown column
limit:<u32> or ${param}row capaxon-T808 — not a non-negative integer (or a non-integer parameter)
as:identifierbinds the result rows

These compile-time proofs (axon check) mirror the runtime filter::{parse_order_by, parse_limit} in lockstep (cross-crate parity test), so a bounded/ordered retrieve that type-checks is one the runtime executes identically. Iterate the rows with for s in <retrieve> { … } and project columns as ${s.<col>} (v2.21.0).

What this primitive is NOT

  • Not a generic ORM. AXON does not generate models from the schema — it validates the schema against the runtime DDL. ORM/migration tooling is upstream.
  • Not a memory. memory is cognitive working state (often vector + retrieval); axonstore is structured, audit-chained persistence.
  • Not a dataspace. A dataspace is a namespace for axonstores (multi-tenant isolation); the store is one named entry within a dataspace.
  • Not silent on compliance. A compliance: [HIPAA] axonstore without tenant_id in the schema is rejected by the v2.0.0 column proof at parse time.

See also

  • axon://primitives/dataspace — multi-tenant namespace.
  • axon://primitives/pix — provenance chain.
  • axon://primitives/corpus — RAG-oriented document store.
  • axon://primitives/resource — lower-level external-resource handle.
  • axon://compliance/hipaa — example of column-proof enforcement on a HIPAA-tagged axonstore.