{"_id":"@agenttool/repo-archive","name":"@agenttool/repo-archive","dist-tags":{"next":"0.1.0-dev.0","latest":"0.1.0-dev.0"},"versions":{"0.1.0-dev.0":{"name":"@agenttool/repo-archive","version":"0.1.0-dev.0","description":"Local-first encrypted multi-zone Git repository archive protocol and simulator","license":"Apache-2.0","type":"module","main":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./schema.json":{"default":"./schema/agent-repo-archive-v0.1.schema.json"},"./vectors.json":{"default":"./vectors/agent-repo-archive-v0.1-vectors.json"}},"bin":{"agent-repo-archive":"dist/cli.js"},"publishConfig":{"access":"public"},"engines":{"node":">=20.19.0","bun":">=1.3.5"},"scripts":{"clean":"node --eval \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"","build":"bun run clean && tsc","typecheck":"tsc --noEmit","test":"bun test","smoke:node":"node scripts/smoke-node.mjs","ci":"bun run typecheck && bun test && bun run build && bun run smoke:node","prepack":"bun run ci"},"peerDependencies":{"@agenttool/adds":"^0.2.1"},"dependencies":{"@noble/ed25519":"^2.2.3","@noble/hashes":"^2.0.1"},"devDependencies":{"@agenttool/adds":"0.2.1","@types/bun":"^1.2.0","ajv":"^8.20.0","ajv-formats":"^3.0.1","typescript":"^5.7.0"},"keywords":["agents","backup","content-addressed","decentralised","encrypted","git","multi-zone","storage"],"repository":{"type":"git","url":"git+https://github.com/cambridgetcg/agenttool.git","directory":"packages/repo-archive"},"homepage":"https://docs.agenttool.dev/AGENT-REPO-ARCHIVE.md","_id":"@agenttool/repo-archive@0.1.0-dev.0","bugs":{"url":"https://github.com/cambridgetcg/agenttool/issues"},"_integrity":"sha512-h2+dZlUf/i11mNGaiVm8EbIhsSytYZu/rmfFe9xZChqYRhNOys1ODK9NVyzkXXLt4E1AVVzr1V1TjJDfjIBRgw==","_resolved":"/home/runner/work/_temp/agenttool-npm-release/agenttool-repo-archive-0.1.0-dev.0.tgz","_from":"file:/home/runner/work/_temp/agenttool-npm-release/agenttool-repo-archive-0.1.0-dev.0.tgz","_nodeVersion":"24.18.0","_npmVersion":"11.17.0","dist":{"integrity":"sha512-h2+dZlUf/i11mNGaiVm8EbIhsSytYZu/rmfFe9xZChqYRhNOys1ODK9NVyzkXXLt4E1AVVzr1V1TjJDfjIBRgw==","shasum":"e85aa017432c13e062151f2c673ec681cf18b73a","tarball":"https://registry.npmjs.org/@agenttool/repo-archive/-/repo-archive-0.1.0-dev.0.tgz","fileCount":51,"unpackedSize":302693,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@agenttool%2frepo-archive@0.1.0-dev.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDt3C13SkpgCZa73IY/qedzFY5MzG0l2TppfaeRebGzegIhAM8hY4LmSrv+46O4EdcpfzhhlClU0kGTH04OTpY5Kgdg"}]},"_npmUser":{"name":"agenttool","email":"contact@cambridgetcg.com"},"directories":{},"maintainers":[{"name":"agenttool","email":"contact@cambridgetcg.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/repo-archive_0.1.0-dev.0_1784834374999_0.15183327436237626"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-23T19:19:34.874Z","0.1.0-dev.0":"2026-07-23T19:19:35.124Z","modified":"2026-07-23T19:19:35.453Z"},"maintainers":[{"name":"agenttool","email":"contact@cambridgetcg.com"}],"description":"Local-first encrypted multi-zone Git repository archive protocol and simulator","homepage":"https://docs.agenttool.dev/AGENT-REPO-ARCHIVE.md","keywords":["agents","backup","content-addressed","decentralised","encrypted","git","multi-zone","storage"],"repository":{"type":"git","url":"git+https://github.com/cambridgetcg/agenttool.git","directory":"packages/repo-archive"},"bugs":{"url":"https://github.com/cambridgetcg/agenttool/issues"},"license":"Apache-2.0","readme":"# `@agenttool/repo-archive`\n\nLocal reference implementation of **Agent Repo Archive 0.1**: encrypted,\nsigned, independently verified Git repository snapshots across multiple\nstorage zones.\n\nThe package does:\n\n- capture every named Git ref plus the exact attached or detached `HEAD` in a\n  self-contained Git bundle, with direct tree/blob refs requiring explicit\n  incomplete-capture opt-in;\n- report excluded workspace, submodule, LFS, filter, shallow/partial clone,\n  alternate-object, linked-worktree, and non-commit-ref state without calling\n  it complete;\n- sign closed Snapshot, Placement, Verification, and Recovery Catalog records;\n- encrypt snapshot and catalog bytes through `@agenttool/adds`;\n- encrypt each ADDS object key under one caller-custodied vault recovery key;\n- import the same validated ADDS portable object into each zone independently;\n- issue a verified receipt only after a per-zone decrypt, payload digest,\n  `git bundle verify`, fresh no-checkout restore, and `git fsck --full --strict`;\n- restore exact refs from one zone and an offline recovery capsule without the\n  publisher's process or ADDS MemoryKeyStore.\n\nIt does not:\n\n- pool providers into one filesystem;\n- prove future retention, geographic independence, provider honesty, or secure\n  deletion;\n- capture dirty/untracked bytes, ignored files, hooks, local Git config,\n  reflogs, submodule repositories, LFS objects, or external filter output;\n- run checkout, hooks, filters, LFS, submodules, or repository code during\n  restore;\n- provide R2, B2, S3, WebDAV, IPFS, rclone, discovery, pruning, scheduling,\n  repair, or production key-vault adapters in v0.1;\n- turn a same-device three-directory simulation into three physical failure\n  domains.\n\n## Local three-zone proof\n\n```bash\nbun install\nbun run build\nnode dist/cli.js simulate --repo /absolute/path/to/clean/repository\n```\n\nThe default simulation uses a temporary directory and removes it when the\nproof finishes. Supplying `--root /new/absolute/path` preserves the simulated\nzones and no-checkout restores for inspection. The process-held recovery key\nis deliberately erased before exit, so preserved simulator ciphertext is not\na usable long-term backup.\n\nAn incomplete committed-history proof must be explicit:\n\n```bash\nnode dist/cli.js simulate \\\n  --repo /absolute/path/to/repository \\\n  --allow-incomplete\n```\n\nThe output says `capture_status: \"incomplete\"` and the signed catalog remains\n`incomplete`; successful recovery of committed Git history never upgrades\nexcluded workspace bytes or unassessable direct tree/blob refs into a complete\nclaim.\n\n## Library shape\n\n```ts\nimport { FileSystemBlockStore } from \"@agenttool/adds/fs\";\nimport { generateIdentity } from \"@agenttool/adds\";\nimport {\n  archiveRepository,\n  restoreRepository,\n  type ArchiveZone,\n} from \"@agenttool/repo-archive\";\n\nconst zones: ArchiveZone[] = [\n  // Each descriptor names a real failure-domain classification and each store\n  // is an independent ADDS BlockStore adapter.\n];\n\nconst archived = await archiveRepository({\n  repositoryPath: \"/repos/example\",\n  repositoryId: \"repo:kingdom:example\",\n  zones,\n  publisherIdentity: generateIdentity(\"urn:example:archive-publisher\"),\n  requiredVerifiedZones: 3,\n});\n\nif (!archived.outcome.policy_satisfied) {\n  // The capsule and any healthy zones remain recoverable. The outcome lists\n  // failed snapshot/catalog zones so policy can schedule an explicit repair.\n}\n\nawait restoreRepository({\n  zone: zones[1]!,\n  recoveryCapsule: archived.recoveryCapsule,\n  targetPath: \"/fresh/restore-target\",\n  expectedSnapshotId: archived.snapshot.record_id,\n});\n```\n\n`recoveryCapsule` contains a 32-byte secret. The library-returned object keeps\nthe key non-enumerable and throws on JSON serialization; callers can still read\nthe bytes, so this is an accident guard rather than custody. A real operator\nmust put the recovery key plus current catalog pointer/envelope into an\nindependently protected offline or OS-managed secret store. Losing it makes\nintact zone bytes unrecoverable; exposing it compromises every object envelope\nfor that vault.\n\n`outcome` is unsigned process telemetry. A degraded archive is returned when at\nleast one catalog copy survives: verified recovery-zone IDs and failed\nsnapshot/catalog zone IDs remain visible so healthy copies are not orphaned\nmerely because the requested threshold was missed. Only\n`outcome.policy_satisfied === true` means the creation-time catalog and snapshot\nround-trips met the requested distinct-domain threshold.\n\n## Why complete replicas first\n\nADDS `MultiBlockStore` applies its threshold per Block. Rotating provider\nfailures can satisfy every Block's write quorum while leaving no provider with\none complete object. Repo Archive therefore encrypts once in a private staging\nstore, exports one strict portable ADDS bundle, and imports/read-backs that\nexact bundle against every named zone separately.\n\nThe included simulator's three zones are full replicas. Repo histories in the\ncurrent ecosystem are small enough that this is easier to audit and recover\nthan cross-provider erasure shards. Erasure coding remains outside v0.1.\n\n## Plaintext and metadata boundary\n\nGit requires a bundle file for verification. The reference implementation\nuses private temporary directories and mode `0600`, then removes the files.\nRemoval is not secure erasure, especially on copy-on-write or SSD media.\n\nStorage zones receive ADDS ciphertext and signed Manifests. They still learn\nobject sizes, timing, ciphertext CIDs, the publisher claim, schema/media\nlabels, and access patterns. Encryption does not hide that metadata.\n\n## Development\n\n```bash\nbun install\nbun run ci\nnpm pack --dry-run --ignore-scripts\n```\n\nNormative schema and vectors are exported as\n`@agenttool/repo-archive/schema.json` and\n`@agenttool/repo-archive/vectors.json`.\n\nSee\n[`../../docs/specs/AGENT-REPO-ARCHIVE-0.1.md`](../../docs/specs/AGENT-REPO-ARCHIVE-0.1.md)\nfor the wire and state rules.\n","readmeFilename":"README.md","_rev":"1-a75660e8e0ccbd88f001764c25b674f4"}