Skip to content

ADR-009: Content-addressed artifacts and rebuildable Neo4j

Status: accepted · Date: 2026-09-10

Context

Artifacts are large and intermediate; canonical notes need human edits; Neo4j is useful for traversal but must never become the source of truth.

Decision

The artifact service stores SHA-256-addressed immutable bundles and manifests in a Docker volume. Canonical notes publish to iCloud with expected hashes. Neo4j receives approved-note projections with stable IDs, typed relationships, parameterized Cypher, and relationship reconciliation.

Mechanics and tests

Reject unsafe paths, oversized chunks, digest mismatch, missing auth, and shell-like operations. Graph rebuild starts from canonical notes, detects dangling references and prerequisite cycles, and reproduces IDs/properties. A failed projection never edits canonical notes.

Consequences

Rebuilds are slower than treating the graph as authoritative but make corruption recoverable and handoff safe. A future vector index may be added only as another projection.

Alternatives considered

Writing extracted text directly into canonical notes was rejected because proposals need review and source artifacts need immutability. Making Neo4j authoritative was rejected because a graph cannot represent handwritten editorial intent safely. Mounting arbitrary host paths into the API was rejected because it would turn a content store into a filesystem service.

Implementation detail and example

PUT /v1/artifacts/{sha256} accepts an authenticated, content-addressed stream up to the configured request limit, verifies the digest, and returns the existing object for an identical replay. A different body under the same digest is rejected. Authenticated GET supports only an exact digest lookup. It rejects unsafe archive paths, shell-like fields, arbitrary reads, and path traversal. Canonical publication writes an expected hash and creates a conflict record if the note changed. Graph sync uses stable IDs, parameterized Cypher, explicit relationship types, and a reconciliation pass that removes relationships absent from the approved projection.

Configuration and failure behavior

Artifacts, operational state, logs, and Neo4j data use separate named volumes. A failed upload, checksum mismatch, API health check, or graph transaction leaves canonical notes untouched and marks the stage failed. Rebuild starts from approved notes, reports dangling references and prerequisite cycles, and never invents missing nodes. Redirects preserve every merged proposal ID.

The publication command is deadwire publish-note; it accepts only a validated proposal and reviewer identity, writes to the configured Hacking/Deadwire/notes subtree, and uses a same-directory temporary file plus fsync and atomic replace. Existing notes require an expected SHA-256 hash, so a concurrent handwritten or iCloud edit becomes a conflict rather than an overwrite. deadwire graph-rebuild canonical-notes.json validates the note array, rejects dangling prerequisites or cycles through the pure projection, and writes the resulting projection using DEADWIRE_NEO4J_PASSWORD; it never creates notes or infers content.

The pure graph projection in src/deadwire/graph.py is the source for the Neo4j adapter: it emits stable node properties, points PREREQUISITE_OF from prerequisite to dependent, rejects unresolved references and cycles, and computes relationship additions/removals. src/deadwire/neo4j_sync.py now rebuilds that projection through injected-driver transactions, uses parameters for IDs/properties, restricts relationship labels to an explicit allowlist, and deletes stale nodes/edges. It may not derive new canonical knowledge from Neo4j.

Verification and revisit trigger

API tests cover missing/invalid auth, size bounds, digest mismatch, idempotency, unsafe paths, and absence of shell/filesystem operations. Projection tests compare stable IDs, properties, relationships, and deletion reconciliation before and after a clean rebuild. Revisit persistence only when measured scale or collaboration needs justify a new projection with equivalent rebuild and conflict guarantees.