@rehearsal-db/core 0.1.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/BENCHMARKS.md +61 -0
  2. package/CHANGELOG.md +59 -0
  3. package/COMPATIBILITY.md +22 -0
  4. package/LICENSE +21 -0
  5. package/README.md +375 -0
  6. package/SECURITY.md +19 -0
  7. package/SUPPORT.md +15 -0
  8. package/docs/adapters.md +23 -0
  9. package/docs/baselines.md +33 -0
  10. package/docs/commands.md +35 -0
  11. package/docs/configuration.md +98 -0
  12. package/docs/getting-started.md +247 -0
  13. package/docs/glossary.md +33 -0
  14. package/docs/production-source.md +33 -0
  15. package/docs/releasing.md +79 -0
  16. package/docs/sanitization.md +69 -0
  17. package/docs/security-model.md +40 -0
  18. package/docs/troubleshooting.md +50 -0
  19. package/docs/tutorial.md +96 -0
  20. package/package.json +77 -0
  21. package/scripts/lib/environment/local_supabase.mjs +197 -0
  22. package/scripts/lib/rehearsal/baseline_artifact.mjs +536 -0
  23. package/scripts/lib/rehearsal/baseline_builder.mjs +155 -0
  24. package/scripts/lib/rehearsal/configuration.d.mts +85 -0
  25. package/scripts/lib/rehearsal/configuration.mjs +559 -0
  26. package/scripts/lib/rehearsal/diagnostics.mjs +193 -0
  27. package/scripts/lib/rehearsal/migration_history.mjs +220 -0
  28. package/scripts/lib/rehearsal/plan.mjs +587 -0
  29. package/scripts/lib/rehearsal/process_environment.mjs +64 -0
  30. package/scripts/lib/rehearsal/runtime_restore.mjs +310 -0
  31. package/scripts/lib/rehearsal/sanitization_policy.mjs +169 -0
  32. package/scripts/lib/rehearsal/schema_snapshot.mjs +113 -0
  33. package/scripts/lib/rehearsal/service_environment.mjs +82 -0
  34. package/scripts/operations/database/manage_rehearsal_database.mjs +784 -0
  35. package/scripts/operations/rehearsal/rehearsal_cli.mjs +565 -0
package/BENCHMARKS.md ADDED
@@ -0,0 +1,61 @@
1
+ # Rehearsal benchmark baseline
2
+
3
+ These measurements are regression signals, not performance guarantees. Compare future
4
+ runs on equivalent hardware and investigate material regressions before release.
5
+
6
+ Measured 2026-09-12 on macOS arm64, Apple M1, Node.js 24.18.0, Supabase CLI 2.117.0,
7
+ Docker 29.5.2, and local warm container images.
8
+
9
+ ## Large production-shaped baseline
10
+
11
+ The final pre-extraction corpus contained 1,139,884 sanitized rows across 126 tables and 251
12
+ represented migrations with zero candidates. These historical measurements establish a
13
+ starting regression signal; they are not bundled test data or a supported performance
14
+ guarantee.
15
+
16
+ | Phase | Time |
17
+ | ------------------------------------------ | -------- |
18
+ | Baseline checksum verification | 682 ms |
19
+ | Migration inventory and candidate planning | 1,012 ms |
20
+ | Database reset, restore, and verification | 83.70 s |
21
+ | Public CLI run plus project app proof | 105.56 s |
22
+
23
+ The complete run includes local Supabase stop/start overhead, replaying the historical
24
+ schema, streaming the baseline, the project-specific synthetic developer overlay, exact
25
+ row/FK verification, candidate reconciliation, and final migration-ledger verification.
26
+
27
+ ## Independent fixture
28
+
29
+ Measured again on 2026-09-14 with the same local macOS arm64 toolchain after the final
30
+ documentation and package-contract sweep.
31
+
32
+ Corpus: one synthetic row, one table, one represented migration, one valid candidate,
33
+ and one deliberately invalid candidate.
34
+
35
+ | Phase | Time |
36
+ | --------------------------------------------- | ------- |
37
+ | Baseline creation and plan | 81 ms |
38
+ | Installed-package valid CLI run and app proof | 42.70 s |
39
+ | Reset, stop, restart, and discard lifecycle | 63.95 s |
40
+ | Installed-package invalid refusal and cleanup | 35.09 s |
41
+
42
+ Most fixture time is local Supabase container lifecycle overhead. The fixture installs
43
+ the exact packed release candidate before both executions. The failure timing includes
44
+ rebuilding the baseline runtime, applying the valid prefix candidate, refusing the
45
+ invalid SQL candidate, and removing the untrusted runtime.
46
+
47
+ ## Linux portability proof
48
+
49
+ Measured 2026-09-12 using Node.js 24.21.0 in Ubuntu Bookworm arm64 against the local
50
+ Colima Docker host, Supabase CLI 2.117.0, and the exact installed prospective tarball.
51
+ The valid migration and application proof passed in 40.49 seconds. The invalid migration
52
+ was refused and its exact project-labelled runtime was removed in 39.39 seconds. This
53
+ run exposed and fixed the fresh-runtime cleanup path and proves Linux arm64 behavior;
54
+ the same proof remains required in GitHub Actions before public release.
55
+
56
+ ## Regression policy
57
+
58
+ Record a new equivalent sample before a beta release or after changing baseline format,
59
+ streaming, restore, migration application, verification, or local-runtime lifecycle.
60
+ Investigate a repeatable increase greater than 25% in a phase. Do not weaken checks to
61
+ recover time; optimize only after identifying the measured bottleneck.
package/CHANGELOG.md ADDED
@@ -0,0 +1,59 @@
1
+ # Changelog
2
+
3
+ All notable Rehearsal package changes will be documented here. The format follows Keep
4
+ a Changelog, and versions will follow Semantic Versioning after the package exists.
5
+
6
+ ## Unreleased
7
+
8
+ ## [0.1.0-beta.1] - 2026-09-14
9
+
10
+ ### Changed
11
+
12
+ - Moved the unpublished beta package from the unavailable `@rehearsal` organization to
13
+ the project-owned `@rehearsal-db/core` package name.
14
+ - Limited the one-time first-package credential to `0.1.0-beta.1`; `0.1.0-beta.0`
15
+ remains an unpublished, superseded GitHub release record.
16
+
17
+ ## [0.1.0-beta.0] - 2026-09-14
18
+
19
+ ### Added
20
+
21
+ - Versioned strict configuration and safe initializer contract.
22
+ - Doctor, immutable explain/dry-run plan, baseline inspection, and migration inspection.
23
+ - Verified run, start, migrate, reset, status, stop, discard, and runtime verification
24
+ commands with exact candidate confirmation.
25
+ - Versioned human/machine result model, stable exit categories, and recursive redaction.
26
+ - Independent synthetic Supabase fixture with valid and deliberately invalid migrations.
27
+ - Deny-by-default sanitization coverage validation and generic KEEP, PSEUDONYMIZE,
28
+ REPLACE, EXCLUDE, and DERIVE operation primitives.
29
+ - Public baseline, migration, schema, diagnostic, process-environment, and local-service
30
+ library entry points for project-owned tooling.
31
+ - Approachable quick start, tutorial, configuration, security, sanitization, source,
32
+ baseline, adapter, command, troubleshooting, release, support, and contribution guides.
33
+ - Protected verification CI, dependency updates, issue templates, package auditing, and
34
+ dormant tokenless trusted-publishing configuration.
35
+ - Two-stage release preparation that hashes and uploads the exact npm tarball before a
36
+ protected human approval gate, then verifies the same registry bytes and executable.
37
+ - A copyable synthetic onboarding path with matched migration, policy, data, and ledger
38
+ examples plus explicit expected output and recovery guidance.
39
+ - A direct comparison with backups, staging, seed data, database branches, and
40
+ migration-only tools, plus explicit beta support, typing, cost, and storage boundaries.
41
+ - Standalone repository language that removes source-project history, activates the
42
+ security and compatibility policies, and matches the repository's available support
43
+ channels.
44
+ - GitHub Actions upgraded to their Node.js 24 runtime generations before publication.
45
+
46
+ ### Security
47
+
48
+ - Version 1 permits loopback targets only and cannot enable hosted access or outbound
49
+ networking.
50
+ - Child processes use allowlisted environments rather than ambient hosted credentials.
51
+ - Package contents are scanned for runtime artifacts, source data, private application
52
+ identifiers, credential formats, and hosted connection strings.
53
+ - The one-time first-package credential is limited to the first publishable beta; future
54
+ publication uses short-lived trusted OIDC, and every release tag must already exist on
55
+ protected `main`.
56
+
57
+ [Unreleased]: https://github.com/Ddupasquier/rehearsal-db/compare/v0.1.0-beta.1...HEAD
58
+ [0.1.0-beta.1]: https://github.com/Ddupasquier/rehearsal-db/releases/tag/v0.1.0-beta.1
59
+ [0.1.0-beta.0]: https://github.com/Ddupasquier/rehearsal-db/releases/tag/v0.1.0-beta.0
@@ -0,0 +1,22 @@
1
+ # Rehearsal compatibility policy
2
+
3
+ Rehearsal begins at `0.x`. Minor releases may contain breaking changes, but every
4
+ intentional break must be called out in the changelog with a migration path. Patch
5
+ releases must remain backward compatible within their minor line.
6
+
7
+ The following are compatibility contracts for published 0.x releases:
8
+
9
+ - configuration property names, types, defaults, validation, and schema version;
10
+ - baseline format and checksum meaning;
11
+ - ordered migration digest semantics and classifications;
12
+ - CLI command names, flags, state-changing behavior, and exit codes;
13
+ - versioned JSON result and error envelopes;
14
+ - the meaning and ordering of verification gates.
15
+
16
+ A change to any of those requires either a compatible extension or a deliberate version
17
+ transition. Rehearsal must never silently reinterpret an old config, baseline, digest,
18
+ or successful verification receipt.
19
+
20
+ The first stable `1.0.0` requires external beta evidence, a support policy, and a settled
21
+ public API. Supporting additional database families, package managers, or operating
22
+ systems is not implied by the 0.x contract.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Rehearsal contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,375 @@
1
+ # Rehearsal
2
+
3
+ Rehearsal tests pending Supabase migrations against a verified, sanitized,
4
+ production-shaped baseline in a disposable local environment. It is designed for the
5
+ historical edge cases that synthetic seed data rarely represents.
6
+
7
+ Version 0.1 targets Supabase CLI projects running PostgreSQL locally. It does not yet
8
+ claim support for arbitrary unmanaged PostgreSQL installations.
9
+
10
+ Public beta releases are distributed through npm as `@rehearsal-db/core`. Publication is
11
+ restricted to reviewed artifacts from protected `main`; source availability alone does
12
+ not enable production access.
13
+
14
+ ## Documentation
15
+
16
+ - [Getting started](docs/getting-started.md)
17
+ - [End-to-end tutorial](docs/tutorial.md)
18
+ - [Configuration reference](docs/configuration.md)
19
+ - [CLI commands](docs/commands.md)
20
+ - [Sanitization policy](docs/sanitization.md)
21
+ - [Production source boundary](docs/production-source.md)
22
+ - [Baselines](docs/baselines.md)
23
+ - [Project adapters](docs/adapters.md)
24
+ - [Security model](docs/security-model.md)
25
+ - [Troubleshooting](docs/troubleshooting.md)
26
+ - [Release process](docs/releasing.md)
27
+ - [Glossary and architecture](docs/glossary.md)
28
+
29
+ ## Why use it?
30
+
31
+ A migration passing against an empty database proves only that the migration can build
32
+ a new schema. Rehearsal also proves that:
33
+
34
+ - the baseline is the exact immutable artifact you reviewed;
35
+ - historical migration files still match the baseline's digest-addressed prefix;
36
+ - only the exact suffix is treated as candidate work;
37
+ - production-shaped relationships survive restore and migration;
38
+ - optional bounded Storage objects retain exact checksums through local restore;
39
+ - the resulting local application can pass a project-owned proof;
40
+ - unsafe or ambiguous state stops execution.
41
+
42
+ ## What Rehearsal is—and is not
43
+
44
+ Rehearsal complements existing database workflows instead of replacing them:
45
+
46
+ | Tool or environment | Primary job | What Rehearsal adds |
47
+ | ----------------------------------------------- | ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
48
+ | Backups and point-in-time recovery | Recover lost production data | A disposable, writable migration test; Rehearsal is not disaster recovery. |
49
+ | Staging | Exercise an integrated deployed application | A local resettable database shaped by reviewed production history, without giving the runtime a hosted target. |
50
+ | Synthetic seed data | Create small, known test scenarios | Sanitized production-shaped relationships and historical edge cases, when the project explicitly authorizes them. |
51
+ | Database branches or preview databases | Isolate hosted database changes | A loopback-only runtime with immutable baseline checks, exact candidate confirmation, and project-owned acceptance proofs. |
52
+ | Migration linters and migration-only test tools | Inspect SQL or prove a migration applies | Restore, migrate, run the real application proof, preserve sandbox edits, and reset to the verified baseline. |
53
+
54
+ The package does not extract production data. A project may use Rehearsal entirely with
55
+ synthetic data, or build its own least-privilege extraction and sanitization boundary.
56
+ The current beta runs local Supabase services and therefore does not support an arbitrary
57
+ unmanaged PostgreSQL server.
58
+
59
+ ## Local cost and storage
60
+
61
+ Rehearsal itself has no hosted-service fee and never creates a cloud database. Normal
62
+ local costs are Docker CPU, memory, and disk space for Supabase images, the immutable
63
+ baseline, optional retained Storage assets, and the disposable runtime. Production-shaped
64
+ artifacts can be large: review their manifest size before activation, keep bounded
65
+ retention, and use `rehearsal discard` when the runtime is no longer needed. Deleting the
66
+ runtime does not delete the immutable baseline; baseline retention remains a project-owned
67
+ privacy and disk-management decision.
68
+
69
+ The restored runtime is intentionally writable. Exact baseline row counts and foreign
70
+ keys are proved during reset before the runtime is accepted; later verification allows
71
+ row-level divergence from sandbox interaction or candidate data migrations while still
72
+ checking the immutable artifact, migration lineage, runtime boundary, and project-owned
73
+ invariants. Reset restores and reproves the exact starting data.
74
+
75
+ ## Quick start
76
+
77
+ Install the current beta from npm:
78
+
79
+ ```bash
80
+ npm install --save-dev @rehearsal-db/core
81
+ ```
82
+
83
+ Contributors testing an unreleased change can use `npm link` or install the tarball
84
+ produced by `npm pack` from a local checkout. In a consuming project, the commands are:
85
+
86
+ ```bash
87
+ npx rehearsal init
88
+ npx rehearsal init --write
89
+ npx rehearsal baseline create --records=<safe.ndjson> --ledger=<ledger.json>
90
+ npx rehearsal doctor
91
+ npx rehearsal explain
92
+ npx rehearsal run --dry-run
93
+ npx rehearsal candidates
94
+ npx rehearsal inspect baseline
95
+ npx rehearsal inspect migrations
96
+ npx rehearsal start
97
+ npx rehearsal migrate --confirm-candidates=<sha256>
98
+ npx rehearsal status
99
+ npx rehearsal verify
100
+ npx rehearsal reset
101
+ npx rehearsal stop
102
+ npx rehearsal discard
103
+ ```
104
+
105
+ `init` previews a typed `rehearsal.config.ts`; it writes only with `--write` and never
106
+ overwrites an existing file. Review all detected values. Rehearsal intentionally does
107
+ not detect, copy, or enable a hosted project.
108
+
109
+ `doctor` must end with `READY` before execution. `explain` and `run --dry-run` use the
110
+ same immutable planner and perform no state-changing operations. If migrations are
111
+ pending, execution requires the exact candidate digest printed by the plan:
112
+
113
+ ```bash
114
+ npx rehearsal run --confirm-candidates=<sha256>
115
+ ```
116
+
117
+ The `rehearsal` executable is the public command contract. Repository availability does
118
+ not itself authorize an npm publication.
119
+
120
+ To try the entire workflow without configuring a project or touching hosted data, clone
121
+ this repository and run `npm ci --ignore-scripts && npm run test:fixture`. It installs
122
+ the exact packed artifact into a clean synthetic Supabase project and proves both
123
+ success and failure.
124
+
125
+ ## Configuration
126
+
127
+ Configuration has an explicit schema version. Version 1 rejects unknown versions,
128
+ unknown properties, paths outside the project root, non-loopback targets, duplicate or
129
+ privileged ports, enabled hosted access, and permissive outbound networking.
130
+
131
+ ```ts
132
+ import { defineRehearsalConfig } from "@rehearsal-db/core";
133
+
134
+ export default defineRehearsalConfig({
135
+ schemaVersion: 1,
136
+ project: { name: "my-supabase-app" },
137
+ supabase: {
138
+ workdir: ".",
139
+ migrationDirectory: "supabase/migrations",
140
+ rehearsalConfig: "infrastructure/rehearsal/supabase/config.toml",
141
+ runtimeWorkdir: ".rehearsal/runtime",
142
+ serviceEnvironmentFile: ".env.rehearsal-service.local",
143
+ serviceEnvironmentVariables: [
144
+ "LOCAL_IDENTITY_CLIENT_ID",
145
+ "LOCAL_IDENTITY_SECRET",
146
+ ],
147
+ },
148
+ baseline: {
149
+ artifactDirectory: ".rehearsal",
150
+ sanitizationPolicy: "infrastructure/rehearsal/sanitization-policy.json",
151
+ },
152
+ application: {
153
+ startCommand: "npm run dev:rehearsal",
154
+ proofCommand: "npm run test:rehearsal",
155
+ environmentFile: ".rehearsal/runtime.env",
156
+ },
157
+ runtime: {
158
+ applicationUrl: "http://localhost:5175",
159
+ projectId: "my-app-rehearsal",
160
+ apiPort: 58321,
161
+ databasePort: 58322,
162
+ studioPort: 58323,
163
+ },
164
+ safety: {
165
+ allowedHosts: ["127.0.0.1", "::1", "localhost"],
166
+ blockedEnvironmentVariables: [
167
+ "SUPABASE_ACCESS_TOKEN",
168
+ "SUPABASE_DB_PASSWORD",
169
+ "SUPABASE_PROJECT_ID",
170
+ ],
171
+ authenticationProviders: ["example-identity-provider"],
172
+ hostedAccess: "disabled",
173
+ outboundNetwork: "deny",
174
+ },
175
+ verification: { commands: ["npm run test:rehearsal"] },
176
+ });
177
+ ```
178
+
179
+ | Property | Type | Required | Default | Meaning and safety effect |
180
+ | -------------------------------------- | ---------- | -------- | ------------------------- | ------------------------------------------------------------- |
181
+ | `schemaVersion` | `1` | Yes | None | Pins configuration meaning; unknown versions fail. |
182
+ | `project.name` | `string` | Yes | None | Stable lowercase local identifier. |
183
+ | `supabase.workdir` | `string` | Yes | None | Project-owned Supabase workdir; cannot escape the project. |
184
+ | `supabase.migrationDirectory` | `string` | Yes | None | Ordered application migration source. |
185
+ | `supabase.rehearsalConfig` | `string` | Yes | None | Dedicated unlinked local Supabase configuration. |
186
+ | `supabase.runtimeWorkdir` | `string` | Yes | None | Must be `<artifactDirectory>/runtime`; always disposable. |
187
+ | `supabase.serviceEnvironmentFile` | `string` | No | None | Owner-only ignored credentials for the local service stack. |
188
+ | `supabase.serviceEnvironmentVariables` | `string[]` | No | `[]` | Exact variables accepted from the service environment file. |
189
+ | `baseline.artifactDirectory` | `string` | No | `.rehearsal` | Must be named `.rehearsal`; deletion-safe artifact boundary. |
190
+ | `baseline.sanitizationPolicy` | `string` | Yes | None | Exhaustive project-owned classification policy. |
191
+ | `application.startCommand` | `string` | Yes | None | Starts the app against the verified local runtime. |
192
+ | `application.proofCommand` | `string` | Yes | None | Project-owned proof after migration. |
193
+ | `application.environmentFile` | `string` | No | `.rehearsal/runtime.env` | Owner-only generated local runtime variables. |
194
+ | `application.runtimeAdapter` | `string` | No | None | Advanced project-owned post-restore adapter path. |
195
+ | `runtime.applicationUrl` | URL | No | `http://localhost:5175` | Must use an explicitly allowed loopback host. |
196
+ | `runtime.projectId` | `string` | No | `rehearsal-local` | Dedicated local Supabase/Docker identity. |
197
+ | `runtime.apiPort` | TCP port | Yes | None | Dedicated non-privileged API port. |
198
+ | `runtime.databasePort` | TCP port | Yes | None | Dedicated non-privileged PostgreSQL port. |
199
+ | `runtime.studioPort` | TCP port | Yes | None | Dedicated non-privileged Studio port. |
200
+ | `safety.allowedHosts` | `string[]` | No | loopback hosts | Version 1 rejects any non-loopback entry. |
201
+ | `safety.blockedEnvironmentVariables` | `string[]` | No | Supabase hosted variables | Ambient values excluded from child processes. |
202
+ | `safety.authenticationProviders` | `string[]` | No | `[]` | Declared identity-only external exchanges. |
203
+ | `safety.hostedAccess` | `disabled` | No | `disabled` | Cannot be enabled in version 1. |
204
+ | `safety.outboundNetwork` | `deny` | No | `deny` | Cannot be weakened in version 1. |
205
+ | `verification.commands` | `string[]` | No | `[]` | Additional declared project checks; commands remain explicit. |
206
+
207
+ Most projects should not use `runtimeAdapter`. It exists for a project that must create
208
+ synthetic local identities or add application-specific variables after a successful
209
+ restore. The adapter is project-owned, receives only the verified local environment and
210
+ baseline plus a local PostgreSQL executor, and is never bundled into the reusable
211
+ package. Its `configureRuntime` export returns a status message and explicit environment
212
+ variables. It must not read hosted credentials or perform network work.
213
+
214
+ ## What each command proves
215
+
216
+ ### `rehearsal doctor`
217
+
218
+ Doctor checks Node 24, the Supabase CLI, a running Docker-compatible engine, required
219
+ paths, config/runtime port agreement, baseline checksums and permissions, migration
220
+ prefix integrity, application proof command ownership, and the fail-closed safety
221
+ policy. Ambient hosted credential variables are reported only by name and remain
222
+ quarantined from children.
223
+
224
+ ### `rehearsal explain` and `rehearsal run --dry-run`
225
+
226
+ Both return the same plan data. They may read and hash configuration, migrations,
227
+ policy, and baseline metadata. They never start or stop services, restore rows, apply a
228
+ migration, launch the application, write a receipt, change an artifact, or contact a
229
+ hosted resource.
230
+
231
+ ### `rehearsal inspect baseline`
232
+
233
+ Inspection prints format and generation identifiers, the migration cutoff, table and
234
+ row counts, and hashes for baseline data and sanitization policy. It never prints source
235
+ rows or baseline values.
236
+
237
+ ### `rehearsal inspect migrations`
238
+
239
+ Every local migration receives one interpretation:
240
+
241
+ - `represented_by_baseline`: exact filename and SHA-256 in the baseline prefix;
242
+ - `candidate`: exact suffix after that prefix, not yet proven in the current runtime;
243
+ - `applied_to_current_runtime`: the exact suffix digest has a verified local receipt;
244
+ - `modified`: a prefix filename or digest changed, so planning fails closed;
245
+ - `invalid`: filename, ordering, uniqueness, or source structure is invalid.
246
+
247
+ `rehearsal candidates` is the concise machine-friendly alias for this same migration
248
+ inspection and exact candidate digest. It does not apply a migration.
249
+
250
+ ## Machine output and exit codes
251
+
252
+ Commands that report state accept `--json`. The version-1 envelope contains
253
+ `schemaVersion`, `command`, `status`, `startedAt`, `durationMs`, `warnings`, and `data`.
254
+ Failures contain a versioned error with category, stable code, message, expected and
255
+ actual state, context, refused action, suggestions, and a safe diagnostic identifier.
256
+
257
+ | Exit | Category |
258
+ | ---- | ------------------------------ |
259
+ | 0 | Success |
260
+ | 1 | Doctor completed but not ready |
261
+ | 2 | Configuration invalid |
262
+ | 3 | Unsafe environment |
263
+ | 4 | Baseline invalid |
264
+ | 5 | Baseline checksum mismatch |
265
+ | 6 | Migration candidate failure |
266
+ | 7 | Migration verification failure |
267
+ | 8 | Application proof failure |
268
+ | 9 | Runtime or dependency failure |
269
+ | 10 | Unexpected internal failure |
270
+
271
+ Human and JSON output are projections of the same model. `normal`, `--verbose`, and
272
+ `--debug` increase explanation only; none may print secrets or baseline row values.
273
+
274
+ ## Guarantees
275
+
276
+ Rehearsal version 1 intends to guarantee:
277
+
278
+ - configuration and runtime targets are local-only;
279
+ - hosted application/database credentials are neither required nor inherited by child processes;
280
+ - application, provider-data, email, and hosted-database side effects fail closed;
281
+ - any declared external identity exchange terminates in the local Auth service and its
282
+ credentials are read from an exact owner-only allowlist;
283
+ - an active baseline verifies before restore;
284
+ - migration identity uses ordered content digests, not timestamps alone;
285
+ - a changed prefix is never silently reinterpreted as a candidate;
286
+ - restore and migration failures cannot leave a runtime marked trusted;
287
+ - reports omit source rows and redact credentials, connection strings, keys, tokens,
288
+ JWTs, passwords, and sensitive environment values.
289
+
290
+ Independent barriers include strict loopback config, a dedicated unlinked Supabase
291
+ workdir/project ID, an allowlisted child environment, and application egress denial.
292
+ A project may explicitly declare an external identity provider, but that does not grant
293
+ hosted application/database access. A single ambient connection string is therefore
294
+ insufficient to redirect an operation.
295
+
296
+ ## Non-guarantees and user responsibilities
297
+
298
+ Rehearsal does not prove that a migration is semantically correct for every application
299
+ workflow, replace backups or disaster recovery, authorize production access, or make a
300
+ sanitization policy correct merely because it is exhaustive. Project owners must review
301
+ the policy, protect baseline artifacts, write meaningful application proofs, review the
302
+ candidate digest, and keep production credentials outside the Rehearsal configuration.
303
+
304
+ ## Baseline lifecycle
305
+
306
+ The source boundary exposes only reviewed versioned views through a least-privilege
307
+ read-only role. Every included column has an explicit KEEP, PSEUDONYMIZE, REPLACE,
308
+ EXCLUDE, or DERIVE action. Sanitized rows stream into an owner-only build directory.
309
+ Only after exact hashes, counts, migration receipts, and policy metadata exist does an
310
+ atomic pointer activate the generation. Failed builds cannot replace the current
311
+ baseline.
312
+
313
+ Restore replays the immutable historical migration bundle, streams sanitized rows into
314
+ the disposable local database, restores optional checksummed Storage assets through the
315
+ loopback service, restores normal enforcement, and verifies counts and foreign keys
316
+ before candidate work begins. The package accepts project-owned asset bytes; it does not
317
+ know how to authorize or extract them from a hosted source.
318
+
319
+ Project policies may attach field-aware JSON rules and project-owned identity adapters.
320
+ A consuming project can use those boundaries to preserve reviewed application data
321
+ while sanitizing unrelated private values, without teaching the package its table
322
+ names, identity relationships, or privacy decisions.
323
+
324
+ ## CI example
325
+
326
+ The tracked [verification workflow](.github/workflows/verify.yml) is intentionally based
327
+ on the synthetic independent fixture. A real repository should provide its own protected
328
+ sanitized baseline through an approved artifact mechanism; never commit production data
329
+ or credentials just to make CI convenient.
330
+
331
+ ## Run the independent proof
332
+
333
+ From this repository on Node.js 24 with Docker running:
334
+
335
+ ```bash
336
+ npm run test:fixture
337
+ ```
338
+
339
+ The proof copies the tracked synthetic fixture to a disposable directory, builds its
340
+ one-row and one-asset baseline, runs the public CLI through one valid migration and
341
+ application proof, verifies the exact Storage byte, then introduces invalid PostgreSQL.
342
+ Success means the valid migration preserved its row and asset, the invalid migration
343
+ received the intended stable failure category, and the untrusted runtime was removed.
344
+ It neither needs nor inherits application-specific or hosted credentials.
345
+
346
+ ## Support matrix for the first beta
347
+
348
+ | Runtime or tool | Status | Initial contract |
349
+ | ---------------- | ------------ | ----------------------------------------------------- |
350
+ | Node.js 24 | Supported | Exact maintained major |
351
+ | npm | Supported | Lockfile-backed install and CLI |
352
+ | macOS | Supported | Directly exercised with Docker/Colima |
353
+ | Linux | Supported | Ubuntu x64 CI and Bookworm arm64 Colima proofs |
354
+ | WSL | Experimental | Must be exercised and documented before support claim |
355
+ | Native Windows | Unsupported | Path, Docker, signal, and shell behavior unproven |
356
+ | pnpm | Unsupported | Detection is informational until direct proof exists |
357
+ | Yarn | Unsupported | Detection is informational until direct proof exists |
358
+ | MySQL/Mongo/etc. | Unsupported | Version 1 is PostgreSQL/Supabase only |
359
+
360
+ ## Troubleshooting
361
+
362
+ - `NOT READY` after Docker: start Docker Desktop or Colima, then rerun doctor.
363
+ - Baseline checksum mismatch: do not repair the hash manually. Rebuild through the
364
+ reviewed extraction/sanitization workflow.
365
+ - Migration prefix divergence: restore the exact reviewed historical file or create a
366
+ new baseline; never rename the edited file into the candidate suffix.
367
+ - Candidate confirmation mismatch: rerun explain, review the exact ordered candidates,
368
+ and use the new digest only if those files are intended.
369
+ - Hosted target refusal: remove the hosted value. Version 1 has no override.
370
+ - Application proof failure: inspect the project-owned proof output; the database must
371
+ not be treated as verified.
372
+
373
+ Security reporting, compatibility promises, and regression measurements are defined in
374
+ [SECURITY.md](SECURITY.md), [COMPATIBILITY.md](COMPATIBILITY.md), and
375
+ [BENCHMARKS.md](BENCHMARKS.md).
package/SECURITY.md ADDED
@@ -0,0 +1,19 @@
1
+ # Rehearsal security policy
2
+
3
+ Rehearsal handles sensitive database topology and may process sanitized derivatives of
4
+ production data. Do not include credentials, connection strings, raw data, or a real
5
+ baseline in a public report.
6
+
7
+ Report suspected vulnerabilities through GitHub's private vulnerability reporting for
8
+ this repository. Do not open a public issue containing an exploit, secret, hosted
9
+ target, or source record.
10
+
11
+ Supported security updates cover the latest released 0.x minor during beta. A security
12
+ fix may deliberately tighten configuration or refuse a workflow that an earlier beta
13
+ accepted. During beta, reports apply to the latest published release and current `main`.
14
+
15
+ The threat boundary and explicit non-guarantees live in [README.md](README.md). Every
16
+ release candidate must pass secret-pattern checks, dependency and package-content
17
+ audits, the installed Linux fixture, and private-reporting verification. The current
18
+ platform evidence covers protected Ubuntu x64 CI and a direct Bookworm arm64 Colima run;
19
+ the exact publishable artifact must repeat its required release checks.
package/SUPPORT.md ADDED
@@ -0,0 +1,15 @@
1
+ # Support
2
+
3
+ Use GitHub Issues for reproducible defects and setup problems that include a synthetic
4
+ reproduction. Include operating system, architecture, Node version, Supabase CLI version,
5
+ Docker engine, the failing command, safe diagnostics, and the smallest reproduction.
6
+ The first beta does not yet maintain a separate public discussion or feature-request
7
+ channel.
8
+
9
+ Do not include credentials, connection strings, source rows, baseline artifacts, private
10
+ URLs, or proprietary migrations. Report security problems through private vulnerability
11
+ reporting as described in [SECURITY.md](SECURITY.md).
12
+
13
+ The package is pre-release. The supported matrix is defined in
14
+ [COMPATIBILITY.md](COMPATIBILITY.md); unsupported environments are welcome as clearly
15
+ labelled experiments but cannot be treated as verified behavior.
@@ -0,0 +1,23 @@
1
+ # Project runtime adapters
2
+
3
+ Adapters are an advanced escape hatch for project-specific restore behavior. They live
4
+ in the consuming repository and are loaded only from the path declared in config.
5
+
6
+ An adapter may export:
7
+
8
+ - `prepareSchema({ baseline, runSql })` for local schema preparation before data restore;
9
+ - `configureRuntime({ baseline, environment, runSql })` to create synthetic identities
10
+ or return explicit application environment values;
11
+ - `verifyRuntime({ baseline, environment, runSql })` for project-owned invariants.
12
+
13
+ Each hook must return the documented status shape expected by the engine. It receives a
14
+ local SQL executor; it should not open another connection or perform network access.
15
+
16
+ Good adapter responsibilities include mapping sanitized application identities to local
17
+ Auth users and verifying a domain-specific relationship after restore. Bad responsibilities
18
+ include extracting production data, embedding credentials, contacting hosted services,
19
+ or weakening the engine's local-only checks.
20
+
21
+ Keep adapters small, deterministic, tested, and visibly project-owned. If a behavior is
22
+ generic across unrelated projects, propose it for the engine instead of copying it into
23
+ every adapter.
@@ -0,0 +1,33 @@
1
+ # Baselines
2
+
3
+ A baseline is an immutable, digest-addressed starting point for a disposable runtime.
4
+ It binds sanitized rows, represented migration bytes, optional Storage assets, schema
5
+ evidence, policy identity, and verification metadata.
6
+
7
+ ## Generation lifecycle
8
+
9
+ New content is written to a private building directory. Individual files are checksummed
10
+ and made read-only. A complete manifest is verified before an atomic `current` symlink
11
+ selects the generation. An interrupted build cannot replace the active baseline.
12
+
13
+ ## Migration lineage
14
+
15
+ The manifest records the exact ordered historical prefix. A migration with the same
16
+ timestamp but different bytes is modified history, not a candidate. New migrations must
17
+ form an ordered suffix. Candidate confirmation binds the exact filenames and checksums.
18
+
19
+ ## Restore lifecycle
20
+
21
+ `reset` destroys only the explicitly labelled local runtime, replays the represented
22
+ schema, streams sanitized rows, restores checksummed local Storage assets, reapplies
23
+ normal enforcement, and verifies counts and foreign keys. A failure removes trust and
24
+ cannot leave a successful receipt.
25
+
26
+ ## Persistence model
27
+
28
+ The baseline never changes during normal use. The restored runtime is writable and its
29
+ changes persist across application restarts while the local containers remain. Run
30
+ `reset` to discard sandbox changes and return to the exact baseline.
31
+
32
+ Treat baseline files as sensitive even after sanitization: owner-only permissions,
33
+ ignored paths, encrypted disks, bounded retention, and explicit deletion are prudent.