REPOSITORY SOURCE

persistent-backup-acceptance.json

docs/evidence/persistent-backup-acceptance.json

1{
2  "recordedAt": "2026-10-25T14:09:42.635558+00:00",
3  "baseCommit": "e6fc8948a084dd7227510bb138abb38268a72b3d",
4  "fullPlanApproximatePercent": 65,
5  "numberedMilestonesClosed": [],
6  "capability": "Manifest-backed persistent database and engine backups, immutable filesystem/S3 storage, empty-target restore and recovery after uncertain acknowledgement.",
7  "sourceSha256": {
8    ".dockerignore": "2c985dc1a0ece1886bb0c1a7bd41c23fb66ce595f88e693ccdb365c8d7f078ab",
9    ".github/workflows/check.yml": "351fda6dbce20c756f870fc20ea799dc870a04e03f136c09415615bb78773874",
10    ".gitignore": "c10f1e207ed88a9961c8d11cfe84d688830257e8269079a4d7fc3a0d83cf0b9d",
11    "Dockerfile.backup": "3799ec5d59b68fb9a588e96835bd828c03ee02dc86beccbeb1ffc2df798280f3",
12    "compose.persistent.yaml": "d118c8c8f1b603dd3fa9f04865a85d3a7dd67fea37a845338c7bfe69596d7b3b",
13    "package-lock.json": "62827296bb5555b93f9cb6fa7aaefe786ac6996e6e2168c39d74082f8dd267b4",
14    "package.json": "174de037cd9dc1686599d4a0f264e0e642d4364085e3411eb5a8e9ebe27d2665",
15    "playwright.persistent-backup.config.ts": "017eb36b56df75ed514b754355bef663e1d4c9d35862521b40783c716a9641b3",
16    "services/backup/index.ts": "04bb73c909befba6bda76eadd003425817b5af39ce06b8b004c704e5c1b9e951",
17    "services/backup/manifest.ts": "0b730444ab1586a0a8ac30a14faaecab6e1727393784ee9f1604bc0528c0f865",
18    "services/backup/snapshot.ts": "6794cbd63fb154a973e0a34c69851b024f06f5905fcf50e6e6b0630baefe7f6b",
19    "services/persistent/bootstrap.ts": "6eff0740e232139bbbc2171b8ffa87be2505805642ae774a690fe017bb0eb973",
20    "services/storage/objects.ts": "035306276581132fc251a0b6d7c1623ffd507e9fd6ebbb2fdcb39776d0e63bdf",
21    "tests/backup.test.ts": "8c4e072b7ea60aee4e5d6a41dff358056eaf1c4b1c06c8c67d6bc51a1b981e8e",
22    "tests/browser/persistent-backup.spec.ts": "9f74ed8e9d7dc7ab25d495e833dc533afc04628df3a9e1295999d1ef587cd4fd",
23    "tests/fixtures/persistent-upgrade-host.ts": "8d917c27f4542adc779347ff5eceab9e04f09d906596d16d2aba2d716ed6c0e4",
24    "tests/object-store.test.ts": "aec86b7b8154d36b7c5cb115eb83a2b2550a60f4b90acbbd8546b9571a376c8d",
25    "tools/cli/backup.ts": "4c79f8dd5cd1204672f9c9c36a0bcf77b44ee3f8f46dbecd3afdea8b773af4b7",
26    "tools/cli/build-backup.mjs": "639a9027a682994f3cecf24aea14df5462d867512590137092407f2e3a1cd9fe",
27    "tools/cli/test-control.mjs": "ce3db3a34b24c9e00b5b8f5df4c7fd892865bdce7f835a6c656d1da040aabfc1",
28    "tools/cli/test-persistent.mjs": "8b71b7db20ac7c9a40f291e8ab986cfcde21632c5d12399b9d5e16e9488e0e4d"
29  },
30  "verification": {
31    "typeAndBoundaries": "passed; 124 package source files",
32    "standaloneBackupBuild": "passed",
33    "headless": {
34      "tests": 630,
35      "pass": 610,
36      "fail": 0,
37      "skipped": 20
38    },
39    "postgres": {
40      "tests": 21,
41      "pass": 21,
42      "fail": 0,
43      "skipped": 0,
44      "scope": "20 PostgreSQL cases plus the incomplete-restore bootstrap guard in the dedicated recovery suite."
45    },
46    "objectStores": {
47      "tests": 2,
48      "pass": 2,
49      "fail": 0,
50      "skipped": 0
51    },
52    "compose": "maintenance profile config --quiet passed; no Docker runtime claim",
53    "browser": {
54      "stats": {
55        "startTime": "2026-10-25T14:09:00.977Z",
56        "duration": 26707.22,
57        "expected": 1,
58        "skipped": 0,
59        "unexpected": 0,
60        "flaky": 0
61      },
62      "journey": {
63        "backup": {
64          "backup": "9633e4d23eb03d9c6c00da563a6458fb27c001e9e99101eb16d5c254bf51fce6:5797",
65          "capturedAt": "2026-10-25T14:09:11.705Z",
66          "rooms": [
67            {
68              "id": "persistent-browser",
69              "release": "e135f669ed1d2ac8a41a43a74f742d402929c83d3a4b7bc896454ae0460c8ce1",
70              "sequence": "5"
71            }
72          ],
73          "engines": 1,
74          "databaseBytes": 132619,
75          "durationMs": 483.86079399999994
76        },
77        "restored": {
78          "backup": "9633e4d23eb03d9c6c00da563a6458fb27c001e9e99101eb16d5c254bf51fce6:5797",
79          "capturedAt": "2026-10-25T14:09:11.705Z",
80          "rooms": [
81            {
82              "id": "persistent-browser",
83              "release": "e135f669ed1d2ac8a41a43a74f742d402929c83d3a4b7bc896454ae0460c8ce1",
84              "sequence": "5"
85            }
86          ],
87          "directory": "/tmp/darkwind-persistent-browser-w1dQ7Y/restored-room",
88          "durationMs": 401.802535
89        },
90        "actors": [
91          "f9b1d67e-302a-4f71-9676-991750e79d93",
92          "4cd22ea4-d368-4b31-af6c-51e068838d14"
93        ],
94        "sourceRelease": "e135f669ed1d2ac8a41a43a74f742d402929c83d3a4b7bc896454ae0460c8ce1",
95        "restoredRelease": "e135f669ed1d2ac8a41a43a74f742d402929c83d3a4b7bc896454ae0460c8ce1",
96        "inventory": [
97          "keeper-lantern"
98        ],
99        "errors": []
100      },
101      "version": "Playwright-matched Chromium 141.0.7390.37"
102    }
103  },
104  "snapshotRehearsal": {
105    "backup": "288d3293d84cccee651b956557e0bb9a72e6c2567e6ef2c9d780f14ed2ef97ff:2241",
106    "capturedAt": "2026-10-25T14:08:29.505Z",
107    "sourceSequenceAfterSnapshot": "2",
108    "restoredSequence": "1",
109    "databaseBytes": 131329,
110    "backupMs": 99.91632200000004,
111    "restoreMs": 84.5431450000001,
112    "exactRows": true,
113    "exactEngines": true
114  },
115  "checks": [
116    "MVCC snapshot keeps dump, logical table hashes and room sequences consistent while a later source checkpoint commits.",
117    "All twelve control tables are digested, including sessions, ownership, receipts, upgrade plans and both outboxes.",
118    "Restore validates engine bytes and SQL snapshot in a separate empty database/new directory; existing world state is refused without modification.",
119    "Corrupt object, source engine manifest changed during capture, failed SQL restore and pre-publication interruption reject completion.",
120    "Conditional immutable writes refuse overwrites and verify retrieved bytes after successful or duplicate upload.",
121    "S3 wire fixture checks SigV4 requests, SHA-256 headers, If-None-Match, duplicate response, corrupt response and denied authorization.",
122    "Restore marker prevents premature production bootstrap. Interrupted final acknowledgement can be finished by verifying exact state without replaying SQL.",
123    "Compiled backup CLI captures, verifies, restores and finishes; production bootstrap opens the restored exact engine after the original engine location is made unavailable.",
124    "Both original traveler credentials return; the shared chest retains the lantern, and withdrawal converges across both browsers.",
125    "PostgreSQL row-text digests detect a one-step epoch change above the JavaScript safe integer range without numeric rounding."
126  ],
127  "measurements": {
128    "productionFixtureBackupMs": 483.86079399999994,
129    "productionFixtureRestoreMs": 401.802535,
130    "meaning": "Same-host local archive timings cover capture/upload and verified database/engine restore respectively; exclude production promotion, WAN storage and browser re-admission. Backup restores through its recorded sequence, not later acknowledged transactions."
131  },
132  "art": {
133    "restored-persistent-chest.png": "cef1b1787cfa68ea5b73f08fc6ca6fc8b9b88e4966ad42b883d3dc171b94a63c"
134  },
135  "observations": [
136    "Initial type check exposed the S3 SDK web/native response union; the server adapter now uses the Node readable-stream contract.",
137    "Review added a check for engine.json changing between initial verification and archival; a fault fixture verifies rejection.",
138    "Final CLI also normalizes bracketed IPv6 hostnames for libpq environment variables; remote IPv6/TLS/provider configurations are not qualified here.",
139    "The complete headless suite preceded the engine-manifest race and bigint fingerprint refinements; the final PostgreSQL/recovery suite and standalone production restore journey exercise both final changes. Final type checks passed; the browser runner rebuilt the standalone CLI."
140  ],
141  "remaining": [
142    "Remote S3 account/provider execution and Docker/Coolify helper runtime await separate qualification; signed S3 requests are tested against a local HTTP fixture.",
143    "Only current schema 4 and the exact Node version and matching PostgreSQL major are supported; no automatic historical-schema migration.",
144    "Continuous WAL/remote replication, production RPO/RTO objectives, long-running capacity, backup catalog, retention and garbage collection remain open.",
145    "Source host must be stopped before promoting a restored copy; one database lease cannot fence two independent copies.",
146    "Full milestones 0\u201318 plan remains active, with final character redesign still deferred."
147  ]
148}
149