Files
buzz/docs/nips/NIP-PMA.md
Wes 4da22a7635 Document PMA fence and migration lock cost
Define the last-binding behavior for shared definition coordinates and call out migration 0028's ACCESS EXCLUSIVE full-table rewrite before capability rollout.

Co-authored-by: Carl <c7ebe626f000404285d3686e1dc74cc07cc60a9754a150041ba132e14bd3e2ec@buzz.block.builderlab.xyz>
Signed-off-by: Wes <wesbillman@users.noreply.github.com>
2026-08-05 13:21:53 -06:00

7.9 KiB

NIP-PMA: Private Managed-Agent Aggregate

draft — protocol/codec reservation only. Relays MUST reject this kind until privacy, transactional CAS, backup/restore, revocation, and capability gates are deployed.

Purpose and kind

Kind 30179 is an owner-authored, addressable, owner-readable aggregate for one runnable managed agent. Its coordinate is (owner pubkey, 30179, agent pubkey). It is the only durable authority after a per-agent migration is independently verified. Kinds 30175 and 30177 remain public/compatibility projections.

This reservation does not change current agent authority, storage, startup, mutation, deletion, catalog, or sharing behavior.

Signed outer envelope

Exactly these two-element tags are permitted:

  • d = <64 lowercase hex agent pubkey> exactly once;
  • g = <canonical positive decimal generation> exactly once;
  • prev = <64 lowercase hex predecessor event id> exactly once after generation 1 and absent at generation 1;
  • state = active|deleted exactly once.

Content is bounded NIP-44 v2 ciphertext encrypted owner-to-owner. Event ID and signature, exact kind/author/tag grammar, canonical curve-valid agent keys, and size are validated before decrypt. The decrypted payload repeats owner, agent, generation, predecessor, and state; any mismatch is corruption.

Decrypted v1 payload

Top-level and nested core schemas reject unknown and duplicate JSON member names. Forward-compatible data is confined to namespaced extensions entries; core semantics never depend on an extension. Projection recovery v1 contains the complete signed public event; validation verifies its signature and ID, owner, kind and d coordinate, and hashes its exact content bytes against the binding. This makes reconstruction deterministic rather than an agreement over an untyped JSON blob.

An active payload binds exact signed 30175 and 30177 event IDs, SHA-256 of their exact content bytes, and complete versioned recovery material. It also contains the preserved agent nsec and an optional NIP-OA attestation, plus explicitly allowlisted private runnable configuration. When present, the attestation MUST be a cryptographically valid unconditional (conditions = "") owner-to-agent authorization: its owner equals the aggregate author and its agent equals the nsec-derived d coordinate. Conditional, malformed, wrong-owner, or wrong-agent attestations are rejected. The nsec MUST derive the d coordinate.

All active aggregates require a stable 30175 definition binding. Before a legacy definition-less agent can be encoded, the migrator MUST deterministically materialize its definition fields as a non-shared 30175 under the owner, with a stable collision-safe slug derived from the agent pubkey. Materialization and read-back verification are prerequisites: failure leaves the agent LegacyOnly and preserves its local record/key unchanged. No client may synthesize a default or mint a replacement identity to satisfy this schema.

A deleted payload is minimal: it contains no active body, advances generation from its predecessor, and includes deleted_at. Relay anti-resurrection and undelete rules are specified by the later transactional CAS contract; generic NIP-33 LWW is explicitly insufficient.

Field authority

  • 30175 definition projection: display name, prompt, runtime/model/provider, name pool, definition behavior defaults, sharing/provenance, public avatar.
  • 30177 instance projection: agent pubkey/name/definition linkage, parallelism, respond_to, and allowlist.
  • private portable canonical: nsec, auth tag, env, durable timeout/team fields, and secret-bearing backend configuration.
  • private but device-validated: relay URL, explicit command/args, backend remote identity, and any explicitly portable path/provider reference.
  • local device policy/derived: start-on-launch, auto-restart, effective binary paths, installed team directory, and catalog-derived commands.
  • legacy conversion only: create-time command/model/provider mirrors, deprecated MCP/turn timeout, source-version drift markers, and relay-mesh fallback markers where a definition is authoritative.
  • transient local only: PID and all last start/stop/exit/error receipts/logs.

Adding a ManagedAgentRecord field must update an exhaustive Desktop classification/conversion fixture before migration-writing code can merge. The fixture is part of the relay-authority follow-up and fails when a durable field has no explicit private, projection, local/derived, or transient classification.

Aggregate submission boundary

Three ordinary Nostr EVENT writes cannot atomically commit an aggregate. The relay contract accepts independently signed projection candidates plus the signed encrypted private head through one authenticated aggregate submission and one PostgreSQL transaction. The relay validates the outer envelope, owner and agent coordinates, signed public candidates, relay-owned definition revision, and CAS predecessor/generation before exposing any candidate. Fan-out begins only after commit.

The relay cannot decrypt kind 30179 and MUST NOT receive the plaintext payload or agent nsec. It therefore cannot prove that ciphertext-internal bindings match the co-submitted public projections. It records the exact submitted projections as the active bindings; Desktop performs the integrity gate by decrypting a writer-consistent read-back and verifying those bindings before promoting the agent to relay-authoritative state.

A definition edit shared by multiple authoritative agents advances each agent's aggregate independently. Agents may transiently pin different revisions of the same definition coordinate; each immutable aggregate revision retains its exact bound recovery bytes while catalog browsing reads the latest active public projection. Browsing never requires decrypting kind 30179.

The relay's ordinary-write fence for a 30175 definition coordinate follows active aggregate bindings, not retained definition revision history. When the last active agent bound to a definition is tombstoned, that coordinate is no longer PMA-authoritative and an ordinary owner-authored NIP-33 write may become the public head. managed_agent_definition_heads still retains the revision floor; a later aggregate rebind advances from that retained revision rather than adopting generic LWW history as an untracked revision. Deleted 30177 instance coordinates remain fenced by their deleted aggregate head, so neither ordinary writes nor legacy kind 5 deletion can bypass generation CAS.

Deployment note: migration 0028

0028_private_managed_agent_foundation.sql changes events.search_tsv by dropping and re-adding the generated stored column, then rebuilding its GIN index. PostgreSQL performs a full events table rewrite while holding an ACCESS EXCLUSIVE lock. Operators MUST treat this as planned write downtime, size the migration window from production table/index size, and complete the migration before deploying binaries that advertise nip-pma-aggregate-v1. Rolling application deployment does not make this DDL online.

Required deployment order

  1. Inert reservation: codec and kind reservation while generic ingest still rejects 30179 (shipped in #4593).
  2. Relay-authority release: author-only pre-pagination privacy and FTS gates, transactional CAS/authority storage, capability-advertised aggregate submission, tombstone revocation across every transport, and the Desktop reader with verified migration. Desktop keeps every agent LegacyOnly when the relay does not advertise the aggregate capability. Promotion requires a crash-safe writer-consistent decrypt-and-binding verification; PostgreSQL backup covers the authority tables and bound recovery bytes as one consistency domain.
  3. Independent later capabilities: export/import and restore drills, owner rotation, and physical legacy cleanup.

No phase may publish secrets before the privacy gates are active or retire local recovery evidence before the complete migration exit gate passes.