v0.9.0 · security-hardening · shipped

The release that closes the
attestation gap.

v0.7.0 made ai-memory a substrate that proves who wrote a memory. v0.8.0 made that substrate multi-agent and governed. v0.9.0 makes the guarantees actually bind. Agent attestation is now required by default on every direct write — an unsigned store is rejected, not silently flagged. The mandatory-hook enforce gate that shipped non-functional at v0.8.0 is now wired live on both the MCP and HTTP write paths. And 49 fixes from a five-lane adversarial code + security review land, alongside three-key governance signing separation, macaroon capability tokens, and a signed identity-lineage key-succession chain.

schema v70 → v78 101 MCP tools / 7 core 49 review fixes SQLite + Postgres/AGE
What's new at a glance

v0.9.0 ships the security-hardening & code-review release

The whole release is a hardening pass: two secure-by-default flips that turn v0.8.0's promises into enforcement, a five-lane adversarial code + security review (#1885#1935) landing 49 fixes, a governance signing-layer separation, and a small set of additive read surfaces. Everything is additive over v0.8.1 except the two flips — review those before you upgrade.

Area What landed Default posture Status
Attestation required An unsigned direct store (MCP memory_store / HTTP POST /api/v1/memories / CLI store) is rejected with 403 ATTESTATION_FAILED instead of landing attest_level="claimed" (#1751) Secure by default — fail-closed. Opt-out: AI_MEMORY_REQUIRE_AGENT_ATTESTATION=0. Setup guide → ✅ shipped
Hook enforcement wired The enforce gate shipped at v0.8.0 but was non-functional (empty HookChain returned Allow — a silent bypass). v0.9.0 wires it live on the MCP (#1885) and HTTP (#1924) write paths Opt-in (AI_MEMORY_HOOKS_ENFORCE_MODE); now actually fails closed when configured ✅ shipped
Adversarial review — 49 fixes Five-lane code + security review: per-row bulk_create attestation gating (#1919), federated PENDING approvals through the registered-approver gate (#1920), tightened team/unit/org visibility scope (#1921), a skill_register symlink jail (#1923), a non-argv postgres-credential channel (#1927) Hardened; several paths fail closed ✅ shipped
Governance signing Three-key Recorder/Judge/Stopper signing-layer separation (#1826), macaroon capability tokens end-to-end (#1827), a signed identity-lineage key-succession chain for rotation survival (#1828, schema v76) Opt-in role keys; verify-side fails closed once enrolled ✅ shipped
Additive features First-class skill memories with parameters_schema + invocation_record (#1865), a recall_observations shadow-feedback loop (#1706), a memory-derivation lineage-DAG (#1859), and an opt-in vector-search slice with capacity/dimension guards (#1005) Additive; default behaviour byte-unchanged ✅ shipped
Schema v70 → v78memory_revisions (v72), signed_events.cause_hash (v73), memories.cid BLAKE3 (v74), memory_links.source_cid/target_cid (v75), agent_lineage (v76), recall_observations.folded (v77), model_attestations (v78) Auto-migrates on first open; additive ladder ✅ shipped
Executive brief

What v0.9.0 means — for three audiences

The same release in three framings — what it means, why it matters, the value, and what it is now.

👤 1 · Non-technical end users

Your AI's memory now proves who wrote each entry.

What it means Install once and your assistant keeps a durable, private, self-hosted memory that survives restarts — and now, by default, every entry it saves is tied to a signed identity, not a name anyone could type.

Why it matters A saved fact or decision can be trusted because it is provably authored — a spoofed or unsigned entry is rejected outright.

The value Peace of mind with zero new habits: nothing to relearn, and your data never leaves a machine you control.

What it is now A durable, private, cryptographically-attributed memory for your AI that runs entirely on your own device.

🏢 2 · C-level decision makers

Attribution you can enforce, not just claim.

What it means The substrate no longer merely can prove who wrote a memory — it requires it. Unsigned writes are rejected by default.

Why it matters The difference between an audit trail an auditor trusts and one full of unverifiable name-strings — and governance verdicts can be signed by physically-separated Recorder/Judge/Stopper keys, so no single compromised process forges a favorable record.

The value Defensible provenance, reduced insider / compromise risk, no lock-in (self-hosted, single binary or container, SQLite or your existing PostgreSQL, provider-agnostic), and a hardened posture: 49 findings from a five-lane adversarial security review, each fixed and tested.

What it is now An enforceable, attested memory & coordination substrate for AI-agent fleets — the release that makes the audit trail hold up.

🛠️ 3 · SME software engineers & architects

The guarantees now bind — enforced at every write path.

What it means Attestation-required-by-default on MCP / HTTP / CLI writes (verified against each agent's bound Ed25519 key); mandatory-hook enforcement actually wired (#1885 / #1924); three-key governance signing (#1826), macaroon capability tokens (#1827), signed identity-lineage succession (#1828).

Why it matters It closes real bypass gaps: the v0.8.0 enforce gate was a silent no-op and unsigned writes landed claimed. v0.9.0 fails closed — 403 ATTESTATION_FAILED on unsigned / forged writes.

The value A substrate you can architect real trust boundaries on: separable signing roles, per-write content attestation, fail-closed hooks, plus an opt-in vector-search slice and a memory-derivation lineage-DAG (#1005 / #1859).

What it is now Schema v78 · 101 MCP tools (7 core) · 92 HTTP routes (78 paths) · 89 CLI (87 default) · 28-field Memory · SQLite + PostgreSQL/AGE, one API. Set up attestation →

Read this before you upgrade

Two secure-default flips & a lossless migration

v0.9.0 is additive over v0.8.1 on every surface except the two flips below. They are secure-by-default breaking changes — read them first.

⚠ Secure-default flip — agent attestation REQUIRED on direct writes

Every store surface (MCP memory_store, HTTP POST /api/v1/memories, CLI store) that receives a write without a caller-presented Ed25519 signature is now rejected with 403 ATTESTATION_FAILED instead of landing attest_level="claimed" (#1751). This is the flip promised by the v0.8.0 one-cycle deprecation WARN from the #1464 vote. A presented signature is verified against the agent's bound public key regardless (valid → agent_attested; forged → 403); this flip only governs the unsigned-write disposition.

Migration: either sign your writes — ai-memory store --sign with a keypair bound via ai-memory agents bind-key — or restore the pre-v0.9 permissive posture with AI_MEMORY_REQUIRE_AGENT_ATTESTATION=0. Scope is the direct-write path only; the federation receive path and curator/autonomy self-writes are unaffected. Running Claude Code or another non-signing MCP client? Its memory_store writes are unsigned and ai-memory does not self-sign memory writes, so a v0.9.0 MCP server returns 403 on them — a solo / local setup should set the opt-out on the MCP server (attested writes stay available on the signed CLI). Full walk-through: Attestation setup guide →.

⚠ Enforcement change — the mandatory-hook gate now actually blocks

At v0.8.0 the AI_MEMORY_HOOKS_ENFORCE_MODE=enforce gate shipped but was non-functional: every write resolved an empty HookChain whose fire returned Allow — a silent bypass. v0.9.0 wires the gate onto both the MCP write path (#1885, dispatch_pre_event_enforced) and the HTTP write path (#1924, http_pre_event_gate). If you enabled enforce with a populated [hooks].required_events expecting it to block, it now does — a required event with no enabled hook returns Deny{code:503}. Review your required_events list before upgrading.

ℹ Compatibility note — drop-in upgrade, lossless migration

brew upgrade ai-memory / cargo install ai-memory --force; the live DB auto-migrates v70 → v78 on first open (archive → restore is lossless). The SDKs (@alphaone/ai-memory npm, ai-memory-mcp PyPI) publish at 0.9.0. Every surface except the two flips above is additive — no existing tool, route, or wire shape changes.

The hardening primitives

Headline changes in v0.9.0

Every card below is anchored to a GitHub issue and, where relevant, a schema migration or config knob. Every tool is verified against the registry (src/mcp/registry.rs); every schema number is cited in the architecture SSOT.

Attestation · #1751

Unsigned writes are rejected, not flagged

The store path flips fail-closed: an unsigned MCP memory_store / HTTP POST /api/v1/memories / CLI store returns 403 ATTESTATION_FAILED instead of landing attest_level="claimed". A presented signature is still verified against the agent's bound key (valid → agent_attested, forged → 403). Opt-out via AI_MEMORY_REQUIRE_AGENT_ATTESTATION=0. This is the flip the v0.8.0 #1464 deprecation WARN promised.

Governance →

Enforcement · #1885 / #1924

The hook gate that finally blocks

At v0.8.0 the enforce gate shipped as pure helpers that nothing composed into a dispatch path — every write resolved an empty HookChain returning Allow (silent bypass). v0.9.0 wires it live: dispatch_pre_event_enforced on the MCP write path (#1885) and http_pre_event_gate on the HTTP handler (#1924). A required pre-write event with no enabled hook now returns Deny{code:503}.

Hook enforcement →

Review lane · #1919 / #1920 / #1921

Attestation, approvals & visibility, tightened

Three of the 49 review fixes: bulk_create now gates attestation per row (#1919) so a batch can't smuggle an unsigned write; federated PENDING approvals route through the registered-approver gate (#1920) so an unregistered peer can't approve; and team/unit/org visibility scope is tightened (#1921) so a scoped read can't over-return.

Feature matrix →

Review lane · #1923 / #1927

Symlink jail & off-cmdline credentials

skill_register now confines a folder_path to a symlink jail (#1923) so a crafted skill can't escape the resource root. And a non-argv credential channel — AI_MEMORY_STORE_URL / AI_MEMORY_STORE_URL_FILE (#1927) — keeps the postgres password off /proc/<pid>/cmdline where any local process could read it from the argv of --store-url.

Deployment security →

Governance · #1826

Three-key Recorder / Judge / Stopper separation

Governance signing splits into three physically-separable custody roles: a Recorder signs each signed_events row, a Judge signs a verdict checkpoint on every governed decision (allow and block), and a Stopper signs an enforcement anchor on deny. Each role has its own key dir + enrolled pubkey; verify-audit-trail demotes any daemon-signed governance row to Forged once a Recorder key is enrolled (#1826).

Signed governance →

Governance · #1827

Macaroon capability tokens, end-to-end

A stateless macaroon capability layer (#1827): a valid token whose caveat chain + issuer ceiling cover an in-flight (action, namespace) flips an otherwise-Deny/pending coarse-gate decision to Allow (attenuation-only). Lifecycle via ai-memory capability keygen|mint|attenuate|inspect|verify; the closed issuer allowlist is the sole issuer source. Off by default (GA-inert — zero new audit bytes) until AI_MEMORY_CAPABILITIES=on.

Capability tokens →

Identity · #1828 · schema v76

Signed identity-lineage key succession

A dedicated agent_lineage table (schema v76) records one signed succession record per (agent_id, epoch), with the composite primary key as the DB-enforced anti-equivocation constraint. Each append lands the record, the flat metadata.agent_pubkey sync, and an append-only signed_events witness in one transaction; verify_lineage walks genesis→head. Scope is single-node key-rotation survival — a rotated key doesn't orphan the identity's prior signed record (#1828).

Identity lineage →

Additive · #1859 / #1865 / #1706 / #1005

Lineage-DAG, skills, feedback & vectors

Four additive surfaces, default byte-unchanged: a memory-derivation lineage-DAG (memory_lineage MCP tool + GET /api/v1/memories/{id}/lineage + ai-memory lineage, #1859); first-class skill memories with parameters_schema + invocation_record (#1865); a recall_observations shadow-feedback loop (#1706); and an opt-in vector-search slice with capacity/dimension guards (#1005).

Everything on one page →

Same binary, five tiers

v0.9.0 hardens every tier from laptop to global hive

ai-memory's architecture scales from one developer's laptop to a multi-region hive of agents without switching products. The security-hardening work in v0.9.0 — required attestation, enforced hooks, signed governance roles — applies uniformly across the tiers; you turn the enforcement flags on as the trust boundary widens.

What v0.9.0 changes beyond v0.8.1

Capability v0.8.1 (hardened-patch) v0.9.0 (security-hardening)
Agent attestation on direct writes⚠️ accept-and-flag (attest_level="claimed")required by default — unsigned is 403 (#1751)
Mandatory-hook enforcement⚠️ gate shipped but non-functional (silent bypass)✅ wired live on MCP (#1885) + HTTP (#1924)
Governance role separation❌ single daemon signer✅ three-key Recorder/Judge/Stopper (#1826)
Capability tokens✅ macaroon tokens end-to-end (#1827)
Identity-lineage key succession✅ signed agent_lineage chain (#1828, v76)
Memory-derivation lineage✅ lineage-DAG surface (#1859)
Skill memories⚠️ partial✅ first-class parameters_schema + invocation_record (#1865)
Recall feedbackrecall_observations shadow-feedback loop (#1706)
Vector search✅ opt-in slice with capacity/dim guards (#1005)
Adversarial review fixes49 across five lanes (#1885–#1935)
Schemav71v78 (additive v72–v78)
Surface area

New read surfaces & the numbers in v0.9.0

The MCP surface grows to 101 advertised entries at --profile full (100 callable + the always-on memory_capabilities bootstrap) / 7 at --profile core. HTTP registers 92 production routes (78 unique URL paths); the CLI ships 89 subcommands (87 in the default build). The additive v0.9.0 surfaces below each ship across all three interfaces; each is verified against src/mcp/registry.rs and the route/subcommand count invariants.

Surface MCP / HTTP / CLI Purpose
Derivation lineage-DAGmemory_lineage · GET /api/v1/memories/{id}/lineage · ai-memory lineageWalk the provenance subset (derived_from/reflects_on/derives_from) via the schema-v74 content-id mirror (#1859)
Capability tokensai-memory capability keygen|mint|attenuate|inspect|verifyMacaroon capability-token lifecycle; a covering token flips a coarse-gate Deny/pending to Allow (#1827)
Skill memoriesmemory_skill_* familyFirst-class skills with parameters_schema + invocation_record, folder-path symlink jail on register (#1865 / #1923)
Recall feedbackmemory_recall_observations · ai-memory recall-observationsShadow-feedback loop over the append-only recall ledger (#1706)
Vector searchrecall pipeline (opt-in)Minimal vector-search slice with AI_MEMORY_VECTOR_INDEX_CAPACITY / _HARD_FAIL / REQUIRE_DIM_MATCH guards (#1005)

Two production backends — embedded SQLite and PostgreSQL + Apache AGE — behind one identical API. 9 typed link relations; a 28-field Memory (the v74 cid content-id is the newest field).

Built with AI · reviewed adversarially

Why every claim on this page is anchored

v0.9.0 follows the same evidence discipline as prior releases — every claim above resolves to a public, verifiable artifact:

Governance guide

docs/governance.md

The canonical write-up of the L1–L6 substrate governance model: required attestation, the mandatory-hook enforce gate, the three-key Recorder/Judge/Stopper signing separation, macaroon capability tokens, and the signed identity-lineage succession chain. Every gate's env-var knob and fail-closed default is documented.

Read the governance guide →

Release notes

v0.9.0 release notes

Full track-by-track ship status, the schema v70 → v78 migration ladder (v72–v78), the two secure-default flips, the 49 review fixes (#1885#1935), and the upgrade / compatibility notes. The operator's source of truth for what changed since v0.8.1.

Open the release notes →

Security posture

Hardened, secure by default

The federation + deployment security surface — peer enrollment, per-transition and per-write attestation, the non-argv postgres-credential channel, the secret-screen pre-write gate — with the exact env-var knobs, fail-closed defaults, and rollout escape-hatches. Read this before upgrading a fleet.

Open federation.md →

Quality gate

Reviewed & validated end-to-end

Full CI matrix green on the release commit — Linux/macOS/Windows, the SQLite and PostgreSQL+AGE feature gates, clippy -D pedantic + fmt, per-module coverage, iOS/Android cross-compile, MSRV, Docker build, cargo audit clean. Hardened by a five-lane adversarial code + security review whose 49 findings were each fixed and pinned by a regression test.

Discovery Gate →

Install shortcuts

Install the current release (v0.9.0)

v0.9.0 (security-hardening) is the current release. The core channels publish 0.9.0; the SDK packages ship the 0.9.0 line under fresh versions (the 0.9.0 SDK slots were reserved by a withdrawn build) — PyPI 0.9.0.post1, npm 0.9.1.

macOS / Linux

Homebrew

brew install alphaonedev/tap/ai-memory
ai-memory install claude-code --apply
Cargo (any host)

From crates.io

cargo install ai-memory --version 0.9.0
Docker

ghcr.io

docker pull ghcr.io/alphaonedev/ai-memory:0.9.0
Fedora / RHEL / Rocky

COPR

sudo dnf copr enable alpha-one-ai/ai-memory
sudo dnf install ai-memory
TypeScript SDK

npm

npm install @alphaone/ai-memory@0.9.1
Python SDK

PyPI

pip install ai-memory-mcp==0.9.0.post1
# import name remains ai_memory
⚠️ Required next step — set up attestation. v0.9.0 requires agent attestation by default, so an unsigned first write returns 403 ATTESTATION_FAILED. Before your first write, either bind a key and sign, or set the AI_MEMORY_REQUIRE_AGENT_ATTESTATION=0 opt-out. The guide walks it through step-by-step for CLI / HTTP / MCP on Linux / macOS / Windows / iOS / Android: Attestation setup guide →