Five layers of rules. One namespace policy stack.

Every memory write hits five rule layers in order: validation → scope → governance → namespace standard → parent-namespace inheritance. Each layer is independently configurable. Each layer can refuse the write with a specific reason. Together they let you take a flat memory store and turn it into a multi-tenant, audit-friendly, compliance-ready substrate.

5 rule layers per-namespace parent-inheritance refuses with reason — never silently drops
The five-layer stack

In order, top to bottom.

A write that survives all five layers gets persisted. A write that fails any one layer gets a 4xx with a specific reason — AI clients can quote the rejection verbatim. There is no "rule somewhere" — every gate is named, and every reason is human-readable.

memory_store incoming write L1 · Validation size · format · charset 23 validate_* fns L2 · Scope private/team/unit/org/collective visibility filter L3 · Governance Allow / Deny / Pending write · promote · delete L4 · Namespace Standard source-of-truth memory carries the policy L5 · Parent inheritance Reject (HTTP 400) "title cannot be empty" "namespace depth 9 exceeds max" Filter on read scope=private hides from peers scope=team prefix-matches by ns Pending(id) → 202 approver gates the write queue + replay on approve Standard's rules apply metadata.governance · metadata.scope tier overrides · TTL overrides Walk up to root Allow → persist all 5 layers passed all green → DB + KG + federation

Layer by layer.

L1Validationstructural · per-write · always-on
23 single-purpose validators in src/validate.rs. Reject malformed input before anything else runs. The same checks run on HTTP, MCP, CLI, and federation receive — there is no privileged path that bypasses them.
  • validate_title — non-empty, ≤512 chars, no control chars
  • validate_content — non-empty, ≤65 536 bytes, no control chars
  • validate_namespace — ≤512 chars, ≤8 segments, no path-traversal (.. rejected per red-team #240)
  • validate_metadata — JSON object only, ≤65 536 bytes serialized, ≤32 nesting depth
  • validate_priority — 1–10 range
  • validate_confidence — 0.0–1.0, finite (no NaN, no Inf)
  • validate_tags — ≤50 tags, ≤128 bytes each
  • validate_ttl_secs — positive, ≤1 year (caps "accidental immortality")
  • validate_source — closed set: user, claude, hook, api, cli, import, consolidation, system, chaos, notify

Full validators atlas →

L2Scope visibilityread-time filter · enforced via metadata.scope
Every memory carries a metadata.scope in { private, team, unit, org, collective }. The query layer filters reads against the calling agent's namespace position (as_agent param). Memories with no explicit scope are treated as private.
// closed set VALID_SCOPES = ["private", "team", "unit", "org", "collective"]; // matching rules // private → only the originating agent // team → same namespace prefix, one level // unit → up the hierarchy two levels // org → across the org namespace // collective → federation-wide // // if as_agent="alphaone/eng/platform/team-a/alice", these resolve as: // memory.scope=private + agent_id="alice" → alice only // memory.scope=team + ns="alphaone/eng/platform/team-a" → team-a // memory.scope=unit + ns="alphaone/eng/platform" → all teams // memory.scope=org + ns="alphaone" → all of alphaone // memory.scope=collective → every peer
L3Governance — Allow / Deny / Pendingwrite-time gate · per-action
Three actions are gated: store, promote, delete. Four levels: Any, Registered, Owner, Approve. Three approver types: Human, Agent(id), Consensus(N). The default policy opens writes/promotes wide and gates deletes to owners — operators tighten as needed.
// Default policy { "write": "any", "promote": "any", "delete": "owner", "approver": "human" } // Tight policy — every write needs 2 votes from registered agents { "write": "approve", "promote": "approve", "delete": "owner", "approver": {"consensus": 2} }

Full governance atlas →

L4Namespace Standardper-namespace · source of truth
A namespace can have a standard — the canonical memory at that namespace whose metadata carries the per-namespace policy. The standard's metadata holds the governance block (L3 source) and the default scope for new memories. Setting / clearing a standard is itself an MCP operation: memory_namespace_set_standard / get_standard / clear_standard.
// MCP — memory_namespace_set_standard { "namespace": "alphaone/engineering/platform", "title": "Platform team standard", "content": "Architectural decisions for the platform namespace…", "metadata": { "governance": { "write": "registered", "promote": "approve", "delete": "owner", "approver": {"consensus": 2} }, "scope": "team", "parent_namespace": "alphaone/engineering" } } // Result: every write to alphaone/engineering/platform/* now flows through this policy. // Federation: namespace_meta row propagates via sync_push.namespace_meta (S35).
L5Parent-namespace inheritancewalk up the tree until a standard is found
If a namespace has no standard, the resolver walks up the path until it finds one — alphaone/engineering/platform/team-a/squad-1 can inherit from alphaone/engineering/platform without setting its own. parent_namespace can be set explicitly on the standard, or auto-detected via auto_detect_parent. v0.6.2 (S35) propagates the namespace_meta row across federation peers so inheritance walks return identical answers everywhere.
// Inheritance chain — first standard wins write to: alphaone/engineering/platform/team-a/squad-1 ↓ no standard walk to: alphaone/engineering/platform/team-a ↓ no standard walk to: alphaone/engineering/platform ↓ FOUND — standard with governance.write=registered ↓ apply: policy.write=registered to the new memory's L3 check
What "memory rules" gives you

Practical patterns this stack unlocks.

▸ Multi-tenant isolation

Set scope=team as the namespace standard's default. New memories get team-only visibility automatically. Tenants can't read each other's notes even though they share the same daemon + DB.

▸ Compliance-grade retention

Set TTL caps in the namespace standard. Set delete: owner so other agents can't drop your evidence. Set promote: approve + consensus(3) so "this stays forever" is a 3-vote decision with a paper trail in pending_actions.

▸ AI-supervisor patterns

Junior agent's namespace gets write: approve, approver: {agent: "supervisor-1"}. Every memory the junior tries to store queues for supervisor approval. Supervisor reviews via memory_pending_list, decides via memory_pending_approve / _reject.

▸ Inherited org policy

Set the org-wide standard at the root namespace once. Every sub-namespace inherits unless it sets its own. Adding a new team becomes mkdir -p: write under the new namespace and the existing rules apply.

▸ Per-environment defaults

Different namespace standards for dev, staging, prod. Dev keeps writes wide-open. Prod tightens to registered writes + consensus(2) promotes. Same daemon, same code, namespace-scoped behavior.

Diagnostic

When a write is refused — what to look for.

Each layer fails with its own error message; AI clients can quote the reason verbatim. Here's a 1-line cheatsheet of which layer the rejection came from.

"validation failed: title cannot be empty"L1 — validate_title "validation failed: namespace depth 9 exceeds max of 8"L1 — validate_namespace "validation failed: content exceeds max size of 65536"L1 — validate_content "validation failed: invalid scope 'public'"L1 — validate_scope // L2 has no rejection — scope filters reads, doesn't refuse writes "governance error: agent not registered"L3 — Registered policy "governance error: caller is not the memory owner"L3 — Owner policy "governance error: consensus quorum must be >= 1"L3 — invalid policy itself 202 → {"status":"pending","pending_id":"..."}L3 — Approve policy queues "namespace_meta lookup failed: …"L4 — standard resolution "parent walk truncated at depth 8"L5 — inheritance reached MAX_NAMESPACE_DEPTH