Backup and restore
Canonical Octonode repository documentation.
Backup and restore
Community publication metadata belongs to marketplace D1, immutable bodies belong to
COMMUNITY_CONTENT, and FTS/retrieval indexes are derived. Recovery restores D1 and R2 to a
consistent point and rebuilds indexes; see Community publications.
Local v1 targets an RPO of the last successful backup and an RTO of 30 minutes for a typical single-project workspace. Create a portable, checksummed snapshot with:
octonode backup octonode-backup.json --root /path/to/project
octonode restore octonode-backup.json --root /empty/restore/directoryThe versioned v3 archive includes the workspace registry, project stores, managed source, file modes,
repository recovery descriptors, and a manifest checksum. Registered repository working trees are
excluded: clean remotely reachable commits carry a reclone descriptor; dirty, local-only, or
unreachable repositories are marked relink_required. Restore validates every path and checksum
before writing to an empty destination and leaves repository-backed records missing until their exact
source is recloned or revision-checked through relink. Restore still accepts v2 project archives.
Cloud workspaces use the same recovery unit through the Sandbox backup stored in R2. The gateway records the backup descriptor only after a successful snapshot and restores it before starting the server. Operators should perform a scheduled restore drill into an isolated workspace and compare workflow revisions before promoting it.
Collaboration data
Workspace collaboration is a separate recovery unit from project files. D1 owns the workspace registry, profiles, scoped-agent metadata, and Architecture-scoped GitHub connections; one SQLite Durable Object generation owns chat, review threads, suggestions, notifications, provider message/thread mappings, and the durable GitHub and Slack outboxes; private R2 owns avatars and logical backups. The complete table and binding map is in the R6 design.
SocialBackupWorkflow fences mutations with a new write epoch while reads remain available,
exports every durable table in bounded JSON pages, copies avatars and control metadata, and writes
the manifest last. Every object carries a SHA-256 checksum. The manifest records workspace and
schema identity, row counts, chunk paths, the Durable Object bookmark, and the matching D1
bookmark. A failed workflow always reopens the prior epoch. Nightly exports retain daily manifests
for 90 days and one manifest per month for one year; pruning removes the whole manifest prefix.
Recovery endpoints are authenticated Hono routes and are also available through MCP/plugin tools:
| Operation | Request | Result used for rollback |
|---|---|---|
| Logical R2 restore | POST /api/social/restores with mode=logical and manifestKey | previousGeneration, rollbackUntil |
| Native DO PITR | Same route with mode=pitr and manifestKey | rollbackBookmark |
| Undo native PITR | Same route with mode=pitr_rollback and bookmark | A new rollback bookmark |
| Undo logical cutover | Same route with mode=generation_rollback and sourceOperationId | The replaced generation is retained for seven days |
| Status | GET /api/social/operations/:id | queued, running, succeeded, or failed |
Before either manifest-based restore, recover the manifest's D1 control rows from an isolated D1
Time Travel database and verify them against control.json. Never rewind the shared production D1
database in place for one workspace. The workflow fails closed until the scoped D1 snapshot hash
matches. It then restores the DO either through its native bookmark or into a new isolated
generation, validates foreign keys and exact row counts, and reopens routing only after the smoke
read succeeds. Logical cutovers keep the previous generation fenced for seven days; the daily
cleanup queue erases it after the deadline.
Slack OAuth credentials and the live channel-binding registry remain D1 control data, not portable social-backup content. Restoring a collaboration generation can recover its local Slack messages and mapping history, but delivery resumes only when the same explicit active binding and connection still exist in D1. A restore never installs an app or copies credentials into another workspace.
Social schema v3 adds design artifacts, immutable artifact revisions, exact comment targets, and append-only anchor projections to the same logical export/delete unit. Restores still accept v1 (pre-Slack) and v2 (Slack without design) manifests; their missing v3 tables start empty. Project source and build output are not copied into the social backup—the recorded project revision continues to identify source owned by the project/repository. Backup pruning never rewrites a live or restored historical anchor.
Social schema v4 adds design-document metadata and immutable R2 object references to the logical
export/delete unit. The referenced content remains in the dedicated private DESIGN_DOCS bucket;
restoring metadata reattaches those immutable keys, and workspace deletion removes the entire
workspace document prefix after fencing writes. Restores continue to accept v1-v3 manifests and
start their missing document tables empty.
Social schema v8 adds Task Spaces, work items, hierarchy, statuses, types, typed fields, tags, sprints, releases, saved views, comments/activity, and workflow/pull-request links to that same workspace logical export, generation rollback, and deletion unit. Restores continue to accept v1-v6 manifests; task tables start empty when an older manifest is restored.
Workspace deletion requires the exact kind:id confirmation. It fences the active generation,
drains installation coordinators, erases active and rollback DO generations, deletes workspace
backups and personal avatar objects, removes local Slack inbox/binding/credential/audit records,
revokes scoped agents and Architecture GitHub links, and finally marks the registry deleted. It does not claim to
delete Slack's remote history. Only the final deletion operation record remains as the documented
audit minimum.
Restore drill evidence
Record each quarterly cloud drill here before expanding SOCIAL_ROLLOUT:
| Date | Environment | Backup age / RPO | Restore RTO | Checks | Result |
|---|---|---|---|---|---|
| 2026-07-26 | Local validation | Fixture | Under 1 second | Wrong workspace, duplicate/truncated chunks, control hash, restore-mode validation | Passed (tests/social-recovery.test.ts) |
The first real D1/DO/R2 drill and its measured RPO/RTO remain a production rollout gate; local fixture timing is not a production SLO measurement.