@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.
- package/BENCHMARKS.md +61 -0
- package/CHANGELOG.md +59 -0
- package/COMPATIBILITY.md +22 -0
- package/LICENSE +21 -0
- package/README.md +375 -0
- package/SECURITY.md +19 -0
- package/SUPPORT.md +15 -0
- package/docs/adapters.md +23 -0
- package/docs/baselines.md +33 -0
- package/docs/commands.md +35 -0
- package/docs/configuration.md +98 -0
- package/docs/getting-started.md +247 -0
- package/docs/glossary.md +33 -0
- package/docs/production-source.md +33 -0
- package/docs/releasing.md +79 -0
- package/docs/sanitization.md +69 -0
- package/docs/security-model.md +40 -0
- package/docs/troubleshooting.md +50 -0
- package/docs/tutorial.md +96 -0
- package/package.json +77 -0
- package/scripts/lib/environment/local_supabase.mjs +197 -0
- package/scripts/lib/rehearsal/baseline_artifact.mjs +536 -0
- package/scripts/lib/rehearsal/baseline_builder.mjs +155 -0
- package/scripts/lib/rehearsal/configuration.d.mts +85 -0
- package/scripts/lib/rehearsal/configuration.mjs +559 -0
- package/scripts/lib/rehearsal/diagnostics.mjs +193 -0
- package/scripts/lib/rehearsal/migration_history.mjs +220 -0
- package/scripts/lib/rehearsal/plan.mjs +587 -0
- package/scripts/lib/rehearsal/process_environment.mjs +64 -0
- package/scripts/lib/rehearsal/runtime_restore.mjs +310 -0
- package/scripts/lib/rehearsal/sanitization_policy.mjs +169 -0
- package/scripts/lib/rehearsal/schema_snapshot.mjs +113 -0
- package/scripts/lib/rehearsal/service_environment.mjs +82 -0
- package/scripts/operations/database/manage_rehearsal_database.mjs +784 -0
- 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
|
package/COMPATIBILITY.md
ADDED
|
@@ -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.
|
package/docs/adapters.md
ADDED
|
@@ -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.
|