@rehearsal-db/core 0.1.0-beta.11 → 0.1.0-beta.13
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/CHANGELOG.md +77 -1
- package/COMPATIBILITY.md +6 -0
- package/README.md +11 -2
- package/docs/commands.md +18 -13
- package/docs/configuration.md +78 -12
- package/docs/getting-started.md +14 -4
- package/docs/production-source.md +138 -16
- package/docs/runtime-policies.md +4 -2
- package/docs/sanitization.md +73 -7
- package/docs/security-model.md +8 -0
- package/docs/standalone-workflow.md +24 -9
- package/docs/troubleshooting.md +26 -8
- package/docs/tutorial.md +2 -1
- package/package.json +4 -3
- package/src/baseline/artifact.mjs +27 -4
- package/src/baseline/privacy_engine.mjs +220 -9
- package/src/cli/arguments.mjs +3 -0
- package/src/cli/guided.mjs +8 -6
- package/src/cli/init_command.mjs +17 -0
- package/src/cli/rehearsal.mjs +20 -2
- package/src/cli/renderers.mjs +41 -4
- package/src/cli/runtime_commands.mjs +92 -9
- package/src/cli/source_commands.mjs +26 -5
- package/src/identity/provider_configuration.mjs +177 -0
- package/src/project/configuration.d.mts +11 -0
- package/src/project/configuration.mjs +155 -19
- package/src/project/setup.mjs +5 -23
- package/src/runtime/plan.mjs +40 -3
- package/src/runtime/restore.mjs +13 -5
- package/src/shared/diagnostics.mjs +7 -0
- package/src/shared/node_runtime.mjs +31 -0
- package/src/source/access.mjs +224 -49
- package/src/source/asset_transfer.mjs +35 -5
- package/src/source/baseline.mjs +42 -6
- package/src/source/external_reader.mjs +255 -0
- package/src/source/postgresql_access.mjs +143 -42
- package/src/source/privacy_paths.mjs +38 -0
- package/src/targets/supabase.mjs +11 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,81 @@ a Changelog, and versions will follow Semantic Versioning after the package exis
|
|
|
5
5
|
|
|
6
6
|
## Unreleased
|
|
7
7
|
|
|
8
|
+
### Added
|
|
9
|
+
|
|
10
|
+
- Runtime and CI compatibility now cover maintained Node.js 22, 24, and 26 releases;
|
|
11
|
+
Node.js 24 LTS remains the recommended default and release-build runtime.
|
|
12
|
+
- Source access policies can use an externally provisioned, database-expiring
|
|
13
|
+
PostgreSQL reader without administrator credentials. Rehearsal binds canonical export
|
|
14
|
+
view definitions, verifies the complete approved read surface and deny controls, and
|
|
15
|
+
never changes or retires provider-owned source objects.
|
|
16
|
+
- `rehearsal --version`, its conventional `-V` alias, and `rehearsal version` now
|
|
17
|
+
report the installed package version without requiring project configuration.
|
|
18
|
+
- Privacy policy version 2 can use one reviewed identity-aware path mapping for both
|
|
19
|
+
database references and physical Storage destinations. Owner prefixes stay in the
|
|
20
|
+
environment, review plans retain only their hashes, and unsafe or mismatched paths
|
|
21
|
+
fail closed.
|
|
22
|
+
- Related timestamps can share a named deterministic date-shift group, preserving their
|
|
23
|
+
ordering and duration without consumer callbacks.
|
|
24
|
+
- The baseline verification corpus now exercises two unrelated target schemas, a
|
|
25
|
+
10,003-row packed-package stream, concurrent row/schema/ledger changes, malformed and
|
|
26
|
+
truncated results, connection loss, low disk, interruption, and deterministic
|
|
27
|
+
fixed-key output.
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- Baseline preparation now rejects missing, negative, overflowing, malformed, or
|
|
32
|
+
oversized PostgreSQL estimate and cursor results before activation. Every preparation
|
|
33
|
+
failure preserves the active baseline, removes private staging, and leaves an edited
|
|
34
|
+
runtime untouched.
|
|
35
|
+
- Approved-owner UUID columns are no longer confused with PostgreSQL sequence-backed
|
|
36
|
+
identities. Restore checks the actual local schema before resetting a sequence, while
|
|
37
|
+
genuine numeric identity columns retain correct next-value behavior.
|
|
38
|
+
- A failed Storage transfer now recursively restores write permission only within its
|
|
39
|
+
owned staging tree, removes that incomplete generation, and preserves the original
|
|
40
|
+
safe preparation error instead of replacing it with a cleanup error.
|
|
41
|
+
- Storage preparation now records a canonical media type from reviewed object metadata,
|
|
42
|
+
removing response-only parameters such as a text charset that local bucket MIME
|
|
43
|
+
allowlists reject during restore.
|
|
44
|
+
- Container startup and health failures are now classified as runtime dependency
|
|
45
|
+
failures and include safe Docker/Colima capacity context instead of being mislabeled
|
|
46
|
+
as migration verification failures.
|
|
47
|
+
|
|
48
|
+
## [0.1.0-beta.12] - 2026-10-04
|
|
49
|
+
|
|
50
|
+
### Added
|
|
51
|
+
|
|
52
|
+
- Supabase projects can declaratively configure local Google or GitHub OAuth in
|
|
53
|
+
`rehearsal.config.mjs`. Rehearsal derives the credential allowlist, injects only the
|
|
54
|
+
ignored owner-only environment values, and generates the exact loopback callback in
|
|
55
|
+
the disposable runtime without tracking secrets. Local signup requires an explicit
|
|
56
|
+
acknowledgment and is enabled only in that generated runtime copy.
|
|
57
|
+
- Branded, responsive documentation is now hosted on GitHub Pages with searchable
|
|
58
|
+
navigation, light and dark themes, and automatic deployment from `main`.
|
|
59
|
+
- The documentation home page and packaged README show the live monthly npm download
|
|
60
|
+
count and link directly to the npm package.
|
|
61
|
+
- Packed-package onboarding acceptance now proves both fresh root-config creation and a
|
|
62
|
+
real beta.11 upgrade that preserves the user's existing configuration byte for byte.
|
|
63
|
+
|
|
64
|
+
### Changed
|
|
65
|
+
|
|
66
|
+
- The packaged README now links prominently to the hosted documentation, npm package,
|
|
67
|
+
and issue tracker. Package homepage metadata also points to the hosted documentation.
|
|
68
|
+
- GitHub Pages publishing uses the current Node.js 24 action generations without legacy
|
|
69
|
+
runtime warnings.
|
|
70
|
+
- `rehearsal init` now calls out important optional settings that are available but not
|
|
71
|
+
enabled before showing the current installed-release template.
|
|
72
|
+
|
|
73
|
+
### Fixed
|
|
74
|
+
|
|
75
|
+
- Existing Google or GitHub provider sections can transition to declarative ownership
|
|
76
|
+
without editing the tracked Supabase template. Rehearsal replaces only a compatible
|
|
77
|
+
section in the disposable runtime copy, while `doctor` refuses ambiguous or
|
|
78
|
+
safety-weakening provider settings before reset.
|
|
79
|
+
- Multi-target plain-text plans now print each declarative OAuth callback, and `init`
|
|
80
|
+
advertises the declarative replacement even when a project still uses legacy provider
|
|
81
|
+
fields.
|
|
82
|
+
|
|
8
83
|
## [0.1.0-beta.11] - 2026-10-03
|
|
9
84
|
|
|
10
85
|
### Added
|
|
@@ -314,7 +389,8 @@ a Changelog, and versions will follow Semantic Versioning after the package exis
|
|
|
314
389
|
publication uses short-lived trusted OIDC, and every release tag must already exist on
|
|
315
390
|
protected `main`.
|
|
316
391
|
|
|
317
|
-
[Unreleased]: https://github.com/Ddupasquier/rehearsal-db/compare/v0.1.0-beta.
|
|
392
|
+
[Unreleased]: https://github.com/Ddupasquier/rehearsal-db/compare/v0.1.0-beta.12...HEAD
|
|
393
|
+
[0.1.0-beta.12]: https://github.com/Ddupasquier/rehearsal-db/compare/v0.1.0-beta.11...v0.1.0-beta.12
|
|
318
394
|
[0.1.0-beta.11]: https://github.com/Ddupasquier/rehearsal-db/compare/v0.1.0-beta.10...v0.1.0-beta.11
|
|
319
395
|
[0.1.0-beta.10]: https://github.com/Ddupasquier/rehearsal-db/compare/v0.1.0-beta.9...v0.1.0-beta.10
|
|
320
396
|
[0.1.0-beta.9]: https://github.com/Ddupasquier/rehearsal-db/compare/v0.1.0-beta.8...v0.1.0-beta.9
|
package/COMPATIBILITY.md
CHANGED
|
@@ -21,6 +21,12 @@ The first stable `1.0.0` requires external beta evidence, a support policy, and
|
|
|
21
21
|
public API. Supporting additional database families, package managers, or operating
|
|
22
22
|
systems is not implied by the 0.x contract.
|
|
23
23
|
|
|
24
|
+
Rehearsal supports maintained even-numbered Node.js release lines that pass its CI
|
|
25
|
+
matrix. Beta.13 supports Node.js 22, 24, and 26; Node.js 24 LTS is the recommended
|
|
26
|
+
default and the release-build runtime. End-of-life and odd-numbered Node.js releases are
|
|
27
|
+
not supported. A future release may remove a Node.js line after its upstream end-of-life
|
|
28
|
+
date, with that change called out in the changelog.
|
|
29
|
+
|
|
24
30
|
The npm install hook may create project scaffolding only when it proves one application
|
|
25
31
|
root. Ordinary npm application installs are covered. A workspace is automatic only when
|
|
26
32
|
one declaring consumer is already visible in its manifest or lockfile; npm can save a
|
package/README.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Rehearsal
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/@rehearsal-db/core)
|
|
4
|
+
|
|
5
|
+
[Read the documentation](https://ddupasquier.github.io/rehearsal-db/) · [View on npm](https://www.npmjs.com/package/@rehearsal-db/core) · [Report a problem](https://github.com/Ddupasquier/rehearsal-db/issues)
|
|
6
|
+
|
|
3
7
|
Rehearsal tests PostgreSQL and Supabase migrations on your computer before you run them
|
|
4
8
|
anywhere important. It restores safe test data into a disposable local database, applies
|
|
5
9
|
only the migrations you approve, and runs your project's own test command.
|
|
@@ -18,7 +22,7 @@ production deployment tool.
|
|
|
18
22
|
|
|
19
23
|
## What you need
|
|
20
24
|
|
|
21
|
-
- Node.js 24 and npm
|
|
25
|
+
- Node.js 22, 24, or 26 and npm (Node.js 24 LTS recommended)
|
|
22
26
|
- Docker Desktop, Colima, or another Docker-compatible engine
|
|
23
27
|
- timestamped `.sql` migration files
|
|
24
28
|
- a project test command that can prove the migrated application works
|
|
@@ -55,6 +59,11 @@ docker pull postgres:17-alpine
|
|
|
55
59
|
|
|
56
60
|
Rehearsal itself never downloads a database image during a rehearsal.
|
|
57
61
|
|
|
62
|
+
For local Google or GitHub sign-in, the generated config includes a commented
|
|
63
|
+
`supabase.authentication` example. It names an ignored owner-only credential file;
|
|
64
|
+
Rehearsal generates the provider block and local callback inside the disposable runtime.
|
|
65
|
+
See [Supabase authentication](docs/configuration.md#supabase-authentication).
|
|
66
|
+
|
|
58
67
|
## Three terms you will see
|
|
59
68
|
|
|
60
69
|
- **Baseline:** a locked, safe starting copy of your schema and test data.
|
|
@@ -160,7 +169,7 @@ problems belong in the private process described in [SECURITY.md](SECURITY.md).
|
|
|
160
169
|
|
|
161
170
|
## For contributors
|
|
162
171
|
|
|
163
|
-
Use Node.js 24, run `npm ci`, then run:
|
|
172
|
+
Use a supported Node.js release (22, 24, or 26), run `npm ci`, then run:
|
|
164
173
|
|
|
165
174
|
```bash
|
|
166
175
|
npm run check
|
package/docs/commands.md
CHANGED
|
@@ -34,25 +34,26 @@ Storage files. `baseline create` and `baseline prepare` are local-only.
|
|
|
34
34
|
|
|
35
35
|
`setup --write` is idempotent: supported existing config files and completed runtime
|
|
36
36
|
files remain unchanged, while missing safe ignore entries may be appended. On upgrades,
|
|
37
|
-
`init`
|
|
38
|
-
|
|
37
|
+
`init` first lists important optional settings that are available but not enabled, then
|
|
38
|
+
prints the installed release's template for comparison. `init --write` never replaces an
|
|
39
|
+
existing config.
|
|
39
40
|
|
|
40
41
|
## Optional source preparation
|
|
41
42
|
|
|
42
43
|
These commands are separate from ordinary rehearsals. Configure `preparation` only after
|
|
43
44
|
reviewing [the standalone security contract](standalone-workflow.md).
|
|
44
45
|
|
|
45
|
-
| Command | What it does
|
|
46
|
-
| ------------------------------------------------------------- |
|
|
47
|
-
| `npx rehearsal privacy key` | Preview the owner-only pseudonym-key path.
|
|
48
|
-
| `npx rehearsal privacy key --write` | Create the key once; refuses to replace an existing key.
|
|
49
|
-
| `npx rehearsal source plan` | Preview the exact temporary reader, views, columns, and asset scope.
|
|
50
|
-
| `npx rehearsal source apply --confirm-source-access=<sha256>` | Create
|
|
51
|
-
| `npx rehearsal baseline refresh` | Replace only the baseline from a reviewed source.
|
|
52
|
-
| `npx rehearsal refresh` | Preview a complete safe refresh of the baseline and local runtime.
|
|
53
|
-
| Add `--confirm-refresh=<sha256>` | Create the replacement, reset locally, and prune listed old copies.
|
|
54
|
-
| `npx rehearsal source retire` | Preview
|
|
55
|
-
| Add `--confirm-source-retirement=<sha256>` | Apply that retirement plan and verify the exact object inventory.
|
|
46
|
+
| Command | What it does |
|
|
47
|
+
| ------------------------------------------------------------- | ----------------------------------------------------------------------- |
|
|
48
|
+
| `npx rehearsal privacy key` | Preview the owner-only pseudonym-key path. |
|
|
49
|
+
| `npx rehearsal privacy key --write` | Create the key once; refuses to replace an existing key. |
|
|
50
|
+
| `npx rehearsal source plan` | Preview the exact temporary reader, views, columns, and asset scope. |
|
|
51
|
+
| `npx rehearsal source apply --confirm-source-access=<sha256>` | Create managed access, or verify external access without source writes. |
|
|
52
|
+
| `npx rehearsal baseline refresh` | Replace only the baseline from a reviewed source. |
|
|
53
|
+
| `npx rehearsal refresh` | Preview a complete safe refresh of the baseline and local runtime. |
|
|
54
|
+
| Add `--confirm-refresh=<sha256>` | Create the replacement, reset locally, and prune listed old copies. |
|
|
55
|
+
| `npx rehearsal source retire` | Preview managed retirement or external local-secret cleanup. |
|
|
56
|
+
| Add `--confirm-source-retirement=<sha256>` | Apply that retirement plan and verify the exact object inventory. |
|
|
56
57
|
|
|
57
58
|
Source credentials are read from environment variables named in the reviewed source
|
|
58
59
|
policy. Never paste a connection string into an argument. `baseline refresh` leaves the
|
|
@@ -175,6 +176,8 @@ belonging to other projects are never included. This follows
|
|
|
175
176
|
|
|
176
177
|
| Option | Meaning |
|
|
177
178
|
| -------------------------------------- | ---------------------------------------------------------------- |
|
|
179
|
+
| `--help`, `-h` | Show the installed command reference. |
|
|
180
|
+
| `--version`, `-V` | Print the installed package version and exit. |
|
|
178
181
|
| `--json` | Return the versioned machine-readable result. |
|
|
179
182
|
| `--verbose` | Show more safe detail. |
|
|
180
183
|
| `--debug` | Show the most diagnostic detail; still review it before sharing. |
|
|
@@ -192,6 +195,8 @@ belonging to other projects are never included. This follows
|
|
|
192
195
|
| `--write` | Apply a setup, policy, or cleanup preview. |
|
|
193
196
|
|
|
194
197
|
Run `npx rehearsal --help` to print the command list available in your installed version.
|
|
198
|
+
Run `npx rehearsal --version` to print only its version number. Add `--json` when a
|
|
199
|
+
script also needs the package name.
|
|
195
200
|
|
|
196
201
|
When a project has more than one config, pass `--config=<path>` on every command for the
|
|
197
202
|
non-default one. Rehearsal keeps that exact config selected through status, run, reset,
|
package/docs/configuration.md
CHANGED
|
@@ -42,9 +42,21 @@ export default defineRehearsalConfig({
|
|
|
42
42
|
rehearsalConfig: "infrastructure/rehearsal/supabase/config.toml",
|
|
43
43
|
runtimeWorkdir: ".rehearsal/runtime",
|
|
44
44
|
|
|
45
|
-
// Optional
|
|
46
|
-
//
|
|
47
|
-
//
|
|
45
|
+
// Optional local OAuth connection. Secrets stay in the ignored owner-only file.
|
|
46
|
+
// Register http://127.0.0.1:58321/auth/v1/callback with the provider.
|
|
47
|
+
// authentication: {
|
|
48
|
+
// enableLocalSignup: true,
|
|
49
|
+
// environmentFile: ".env.rehearsal-service.local",
|
|
50
|
+
// providers: [
|
|
51
|
+
// {
|
|
52
|
+
// name: "google",
|
|
53
|
+
// clientIdEnvironmentVariable: "REHEARSAL_GOOGLE_CLIENT_ID",
|
|
54
|
+
// clientSecretEnvironmentVariable: "REHEARSAL_GOOGLE_CLIENT_SECRET",
|
|
55
|
+
// skipNonceCheck: false,
|
|
56
|
+
// emailOptional: false,
|
|
57
|
+
// },
|
|
58
|
+
// ],
|
|
59
|
+
// },
|
|
48
60
|
},
|
|
49
61
|
baseline: {
|
|
50
62
|
artifactDirectory: ".rehearsal",
|
|
@@ -124,7 +136,8 @@ safe, run setup again, and compare the two files before deleting either one.
|
|
|
124
136
|
After upgrading, run `npx rehearsal init` to print the current release's generated
|
|
125
137
|
template beside the path of your existing config. This comparison is read-only; adding a
|
|
126
138
|
new optional key remains your decision. `npx rehearsal init --write` still refuses to
|
|
127
|
-
replace an existing config.
|
|
139
|
+
replace an existing config. Rehearsal lists important optional settings that are
|
|
140
|
+
available but not enabled before printing the template, so they are easier to find.
|
|
128
141
|
|
|
129
142
|
### Workspaces and custom paths
|
|
130
143
|
|
|
@@ -247,19 +260,72 @@ negative controls, such as unauthorized, malformed, withheld, or missing records
|
|
|
247
260
|
response that merely avoids a server error does not prove that eligible data was
|
|
248
261
|
published or can be found.
|
|
249
262
|
|
|
250
|
-
## Supabase
|
|
263
|
+
## Supabase authentication
|
|
251
264
|
|
|
252
|
-
|
|
253
|
-
|
|
265
|
+
Rehearsal can configure a Google or GitHub OAuth connection in its disposable local
|
|
266
|
+
Supabase runtime. Declare the provider and the names of its credential variables:
|
|
254
267
|
|
|
255
268
|
```ts
|
|
256
|
-
|
|
257
|
-
|
|
269
|
+
authentication: {
|
|
270
|
+
enableLocalSignup: true,
|
|
271
|
+
environmentFile: ".env.rehearsal-service.local",
|
|
272
|
+
providers: [
|
|
273
|
+
{
|
|
274
|
+
name: "google",
|
|
275
|
+
clientIdEnvironmentVariable: "REHEARSAL_GOOGLE_CLIENT_ID",
|
|
276
|
+
clientSecretEnvironmentVariable: "REHEARSAL_GOOGLE_CLIENT_SECRET",
|
|
277
|
+
skipNonceCheck: false,
|
|
278
|
+
emailOptional: false,
|
|
279
|
+
},
|
|
280
|
+
],
|
|
281
|
+
},
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
Create the ignored file, add the values, then restrict it to your account:
|
|
285
|
+
|
|
286
|
+
```dotenv
|
|
287
|
+
REHEARSAL_GOOGLE_CLIENT_ID=your-local-oauth-client-id
|
|
288
|
+
REHEARSAL_GOOGLE_CLIENT_SECRET=your-local-oauth-client-secret
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
```bash
|
|
292
|
+
chmod 600 .env.rehearsal-service.local
|
|
258
293
|
```
|
|
259
294
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
295
|
+
Register `http://127.0.0.1:<apiPort>/auth/v1/callback` with the provider, using the
|
|
296
|
+
`runtime.apiPort` value from this config. `rehearsal explain` also prints the exact URL.
|
|
297
|
+
Rehearsal writes that callback and `env(...)` references into the disposable runtime; it
|
|
298
|
+
never copies credential values into tracked configuration. Use `name: "github"` and
|
|
299
|
+
distinct GitHub variable names for GitHub. Duplicate providers, reused variable names,
|
|
300
|
+
unsupported providers, extra keys, and a template that already owns the same provider
|
|
301
|
+
are refused. This follows Supabase's documented
|
|
302
|
+
[`env()` configuration pattern](https://supabase.com/docs/guides/local-development/managing-config).
|
|
303
|
+
|
|
304
|
+
`enableLocalSignup: true` explicitly acknowledges that disposable local Auth may create
|
|
305
|
+
the temporary user returned by OAuth. Rehearsal changes the generated runtime copy only;
|
|
306
|
+
the tracked Supabase template and every hosted project remain unchanged.
|
|
307
|
+
|
|
308
|
+
The older `serviceEnvironmentFile`, `serviceEnvironmentVariables`, and
|
|
309
|
+
`safety.authenticationProviders` fields remain compatible for projects that manually
|
|
310
|
+
own their Supabase provider TOML. Do not combine those fields with the declarative
|
|
311
|
+
`authentication` block.
|
|
312
|
+
|
|
313
|
+
To migrate a manual Google or GitHub setup, replace those three legacy config fields
|
|
314
|
+
with the `authentication` block together. The tracked Supabase template may keep its
|
|
315
|
+
existing provider section: Rehearsal replaces a compatible legacy section only in the
|
|
316
|
+
generated disposable runtime copy. The section may contain `enabled`, `client_id`,
|
|
317
|
+
`secret`, `redirect_uri`, `skip_nonce_check`, and `email_optional`. The latter two must
|
|
318
|
+
match the explicit `skipNonceCheck` and `emailOptional` declarations, which default to
|
|
319
|
+
`false`. Keep them false unless the provider integration has a reviewed need; Supabase
|
|
320
|
+
warns in its [CLI configuration reference](https://supabase.com/docs/guides/local-development/cli/config#auth.external.provider.skip_nonce_check)
|
|
321
|
+
that skipping nonce validation reduces replay protection. Unknown settings,
|
|
322
|
+
duplicate sections, nested provider tables, or mismatched options fail
|
|
323
|
+
`rehearsal doctor` before reset. Rehearsal never edits the tracked template during this
|
|
324
|
+
transition.
|
|
325
|
+
|
|
326
|
+
Provider connection and copied-account association are separate. This block lets the
|
|
327
|
+
ordinary application sign-in reach local Auth. An optional `identityPolicy` decides
|
|
328
|
+
whether that verified local identity may claim a reviewed copied account.
|
|
263
329
|
|
|
264
330
|
## Safety fields
|
|
265
331
|
|
package/docs/getting-started.md
CHANGED
|
@@ -7,7 +7,8 @@ Want to experiment first? Use the [safe hands-on tutorial](tutorial.md).
|
|
|
7
7
|
|
|
8
8
|
## 1. Check the required tools
|
|
9
9
|
|
|
10
|
-
You need Node.js 24, npm, and a running Docker-compatible engine
|
|
10
|
+
You need Node.js 22, 24, or 26, npm, and a running Docker-compatible engine. Node.js 24
|
|
11
|
+
LTS is the recommended default:
|
|
11
12
|
|
|
12
13
|
```bash
|
|
13
14
|
node --version
|
|
@@ -15,8 +16,8 @@ npm --version
|
|
|
15
16
|
docker info
|
|
16
17
|
```
|
|
17
18
|
|
|
18
|
-
`node --version` must begin with `v24`. If `docker info` fails, start
|
|
19
|
-
Colima, or your usual Docker engine.
|
|
19
|
+
`node --version` must begin with `v22`, `v24`, or `v26`. If `docker info` fails, start
|
|
20
|
+
Docker Desktop, Colima, or your usual Docker engine.
|
|
20
21
|
|
|
21
22
|
Choose the extra requirement for your project:
|
|
22
23
|
|
|
@@ -55,6 +56,13 @@ Supabase or PostgreSQL, and approve the same safe setup preview.
|
|
|
55
56
|
The proof command should check behavior changed by the migration. A test that only checks
|
|
56
57
|
whether the home page loads is usually too weak.
|
|
57
58
|
|
|
59
|
+
If the sandbox needs Google or GitHub sign-in, uncomment
|
|
60
|
+
`supabase.authentication` in `rehearsal.config.mjs`. Add the named credentials to
|
|
61
|
+
`.env.rehearsal-service.local`, run `chmod 600 .env.rehearsal-service.local`, and
|
|
62
|
+
register the local callback printed in the config. See
|
|
63
|
+
[Supabase authentication](configuration.md#supabase-authentication). Rehearsal keeps the
|
|
64
|
+
values out of tracked files and generates the disposable provider configuration for you.
|
|
65
|
+
|
|
58
66
|
## 3. Prepare safe baseline inputs
|
|
59
67
|
|
|
60
68
|
A **baseline** is the locked starting point restored before each rehearsal. Start with a
|
|
@@ -168,7 +176,9 @@ complete reference and [Troubleshooting](troubleshooting.md) when a check fails.
|
|
|
168
176
|
|
|
169
177
|
Running setup again is safe: existing configuration and runtime files are reported as
|
|
170
178
|
unchanged. Rehearsal only adds missing ignore entries. It never refreshes an existing
|
|
171
|
-
config during an upgrade.
|
|
179
|
+
config during an upgrade. After upgrading, run `npx rehearsal init` to see important
|
|
180
|
+
optional settings you have not enabled and compare your file with the installed
|
|
181
|
+
release's current template.
|
|
172
182
|
|
|
173
183
|
## Files Rehearsal creates
|
|
174
184
|
|
|
@@ -33,6 +33,7 @@ URLs, or raw owner identifiers.
|
|
|
33
33
|
"targetFingerprint": "<sha256 of the approved PostgreSQL host, port, and database>",
|
|
34
34
|
"administratorEnvironmentVariable": "REHEARSAL_SOURCE_ADMIN_URL",
|
|
35
35
|
"reader": {
|
|
36
|
+
"mode": "managed",
|
|
36
37
|
"role": "rehearsal_example_reader",
|
|
37
38
|
"ownerRole": "rehearsal_example_owner",
|
|
38
39
|
"credentialFile": ".rehearsal/secrets/source-reader.env",
|
|
@@ -61,7 +62,7 @@ URLs, or raw owner identifiers.
|
|
|
61
62
|
"view": "approved_owner_profile",
|
|
62
63
|
"targetSchema": "app_api",
|
|
63
64
|
"targetTable": "profiles",
|
|
64
|
-
"columns": ["id", "email"],
|
|
65
|
+
"columns": ["id", "email", "avatar_path"],
|
|
65
66
|
"orderBy": ["id"],
|
|
66
67
|
"rowScope": {
|
|
67
68
|
"kind": "approved-owner",
|
|
@@ -70,10 +71,28 @@ URLs, or raw owner identifiers.
|
|
|
70
71
|
}
|
|
71
72
|
}
|
|
72
73
|
],
|
|
73
|
-
"
|
|
74
|
+
"assetReader": {
|
|
75
|
+
"endpointFingerprint": "<sha256 of the approved Storage endpoint>",
|
|
76
|
+
"baseUrlEnvironmentVariable": "REHEARSAL_SOURCE_STORAGE_URL",
|
|
77
|
+
"tokenEnvironmentVariable": "REHEARSAL_SOURCE_STORAGE_TOKEN",
|
|
78
|
+
"maximumObjects": 1000,
|
|
79
|
+
"maximumObjectBytes": 52428800,
|
|
80
|
+
"maximumTotalBytes": 2147483648
|
|
81
|
+
},
|
|
82
|
+
"assets": [
|
|
83
|
+
{
|
|
84
|
+
"bucket": "avatars",
|
|
85
|
+
"prefixEnvironmentVariable": "REHEARSAL_APPROVED_OWNER_ID",
|
|
86
|
+
"rights": "approved-owner",
|
|
87
|
+
"pathMapping": "owner-storage"
|
|
88
|
+
}
|
|
89
|
+
]
|
|
74
90
|
}
|
|
75
91
|
```
|
|
76
92
|
|
|
93
|
+
`managed` is the default for existing policies, but writing it explicitly makes the
|
|
94
|
+
credential boundary easier to review.
|
|
95
|
+
|
|
77
96
|
Calculate fingerprints with the exported helpers from `@rehearsal-db/core/source-access`
|
|
78
97
|
or a reviewed local script. A fingerprint binds the destination without recording its
|
|
79
98
|
address. Changing the host, port, or database invalidates the plan.
|
|
@@ -82,13 +101,72 @@ address. Changing the host, port, or database invalidates the plan.
|
|
|
82
101
|
use. `approved-owner` requires one explicit owner value from the named environment
|
|
83
102
|
variable. Rehearsal never chooses an owner by finding an administrator.
|
|
84
103
|
|
|
104
|
+
### Use a provider-managed reader
|
|
105
|
+
|
|
106
|
+
If a database owner already supplies the restricted export views and reader, use
|
|
107
|
+
`mode: "external"`. Omit `administratorEnvironmentVariable`; Rehearsal will not request
|
|
108
|
+
an administrator credential or change the source:
|
|
109
|
+
|
|
110
|
+
```json
|
|
111
|
+
{
|
|
112
|
+
"reader": {
|
|
113
|
+
"mode": "external",
|
|
114
|
+
"role": "provided_rehearsal_reader",
|
|
115
|
+
"connectionEnvironmentVariable": "REHEARSAL_SOURCE_READER_URL",
|
|
116
|
+
"credentialFile": ".rehearsal/secrets/source-reader.env",
|
|
117
|
+
"maximumValidForMinutes": 30
|
|
118
|
+
},
|
|
119
|
+
"exportSchema": "provided_rehearsal_export",
|
|
120
|
+
"relations": [
|
|
121
|
+
{
|
|
122
|
+
"source": { "schema": "private", "table": "profiles" },
|
|
123
|
+
"view": "approved_owner_profile",
|
|
124
|
+
"targetSchema": "app_api",
|
|
125
|
+
"targetTable": "profiles",
|
|
126
|
+
"columns": ["id", "email", "avatar_path"],
|
|
127
|
+
"orderBy": ["id"],
|
|
128
|
+
"rowScope": {
|
|
129
|
+
"kind": "approved-owner",
|
|
130
|
+
"column": "id",
|
|
131
|
+
"valueEnvironmentVariable": "REHEARSAL_APPROVED_OWNER_ID"
|
|
132
|
+
},
|
|
133
|
+
"viewDefinitionSha256": "<sha256 from externalViewDefinitionFingerprint>"
|
|
134
|
+
}
|
|
135
|
+
]
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
The database owner must create a `security_barrier` view owned by a role other than the
|
|
140
|
+
reader. Record PostgreSQL's exact canonical definition, not handwritten SQL:
|
|
141
|
+
|
|
142
|
+
```js
|
|
143
|
+
import { externalViewDefinitionFingerprint } from "@rehearsal-db/core/source-access";
|
|
144
|
+
|
|
145
|
+
console.log(externalViewDefinitionFingerprint(canonicalViewDefinition));
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Obtain `canonicalViewDefinition` with
|
|
149
|
+
`select pg_get_viewdef('provided_rehearsal_export.approved_owner_profile'::regclass, false)`.
|
|
150
|
+
Rehearsal verifies that fingerprint before saving any local access receipt.
|
|
151
|
+
The resulting receipt also binds the normalized source-policy fingerprint. Editing the
|
|
152
|
+
view hash, columns, scopes, or reader declaration requires a new verification.
|
|
153
|
+
|
|
154
|
+
External mode also requires all non-system readable columns to match only the declared
|
|
155
|
+
views and migration-ledger columns. It refuses database, schema, relation, or column
|
|
156
|
+
writes; inherited roles; privileged role attributes; executable non-system
|
|
157
|
+
security-definer functions; a reader-owned view; or a database-enforced expiration
|
|
158
|
+
beyond `maximumValidForMinutes`.
|
|
159
|
+
|
|
85
160
|
`targetSchema` is optional and defaults to `public`. Set it when the restored relation
|
|
86
161
|
belongs elsewhere, and use the same schema in privacy policy version 2. This is relation
|
|
87
162
|
identity, not a request to search every schema.
|
|
88
163
|
|
|
89
|
-
For Storage,
|
|
90
|
-
|
|
91
|
-
|
|
164
|
+
For Storage, the reader URL and token come from named environment variables. A public,
|
|
165
|
+
non-identity prefix may use `prefix`. A private owner prefix uses
|
|
166
|
+
`prefixEnvironmentVariable`, `rights: "approved-owner"`, and a `pathMapping` declared in
|
|
167
|
+
the privacy policy below. Its raw value stays out of tracked files and the review plan
|
|
168
|
+
records only its SHA-256. Objects outside the exact bucket/prefix are not listed or
|
|
169
|
+
downloaded. Size, object-count, path, ETag, and exact-byte checks apply.
|
|
92
170
|
|
|
93
171
|
## 3. Use executable privacy policy version 2
|
|
94
172
|
|
|
@@ -98,6 +176,21 @@ Every selected column has one action and, where required, a bounded recipe:
|
|
|
98
176
|
{
|
|
99
177
|
"policyVersion": 2,
|
|
100
178
|
"migrationCutoff": "20260101000000",
|
|
179
|
+
"bindings": {
|
|
180
|
+
"approved-owner": {
|
|
181
|
+
"environmentVariable": "REHEARSAL_APPROVED_OWNER_ID",
|
|
182
|
+
"approvedValueSha256": "<sha256 of the exact approved owner ID>"
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
"pathMappings": {
|
|
186
|
+
"owner-storage": {
|
|
187
|
+
"binding": "approved-owner",
|
|
188
|
+
"format": "uuid",
|
|
189
|
+
"namespace": "account-id",
|
|
190
|
+
"maximumBytes": 512,
|
|
191
|
+
"maximumSegments": 8
|
|
192
|
+
}
|
|
193
|
+
},
|
|
101
194
|
"tables": [
|
|
102
195
|
{
|
|
103
196
|
"schema": "app_api",
|
|
@@ -119,6 +212,14 @@ Every selected column has one action and, where required, a bounded recipe:
|
|
|
119
212
|
"generated": "NEVER",
|
|
120
213
|
"identity": "NO",
|
|
121
214
|
"foreignKey": null
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
"name": "avatar_path",
|
|
218
|
+
"action": "DERIVE",
|
|
219
|
+
"recipe": { "kind": "path-map", "mapping": "owner-storage" },
|
|
220
|
+
"generated": "NEVER",
|
|
221
|
+
"identity": "NO",
|
|
222
|
+
"foreignKey": null
|
|
122
223
|
}
|
|
123
224
|
]
|
|
124
225
|
}
|
|
@@ -127,9 +228,10 @@ Every selected column has one action and, where required, a bounded recipe:
|
|
|
127
228
|
```
|
|
128
229
|
|
|
129
230
|
Supported recipes are intentionally small: keyed UUID/email/text/integer pseudonyms,
|
|
130
|
-
explicit constants, bounded date shifts,
|
|
131
|
-
tables, columns, JSON keys, formats, and recipes
|
|
132
|
-
or SQL escape hatch.
|
|
231
|
+
explicit constants, bounded or grouped date shifts, identity-aware path mappings, and
|
|
232
|
+
fully classified JSON objects. Unknown tables, columns, JSON keys, formats, and recipes
|
|
233
|
+
stop the refresh. There is no JavaScript or SQL escape hatch. See
|
|
234
|
+
[Sanitization policy](sanitization.md) for complete path and date examples.
|
|
133
235
|
|
|
134
236
|
## 4. Preview, apply, refresh, and retire
|
|
135
237
|
|
|
@@ -146,10 +248,12 @@ npx rehearsal source retire
|
|
|
146
248
|
npx rehearsal source retire --confirm-source-retirement=<full-sha256>
|
|
147
249
|
```
|
|
148
250
|
|
|
149
|
-
`source apply` creates new time-limited roles and export views only when
|
|
150
|
-
is unused. It verifies the reader cannot read raw tables, write,
|
|
151
|
-
an exposed security-definer network function.
|
|
152
|
-
|
|
251
|
+
In managed mode, `source apply` creates new time-limited roles and export views only when
|
|
252
|
+
every exact name is unused. It verifies the reader cannot read raw tables, write,
|
|
253
|
+
escalate roles, or call an exposed security-definer network function. In external mode,
|
|
254
|
+
the same command performs only the read-only checks above and stores the already supplied
|
|
255
|
+
credential in the ignored owner-only local file. It never creates, grants, alters, or
|
|
256
|
+
drops a source object.
|
|
153
257
|
|
|
154
258
|
`refresh` previews the complete replacement first. After exact confirmation, its baseline
|
|
155
259
|
step uses one read-only repeatable-read transaction for the schema shape,
|
|
@@ -160,13 +264,31 @@ runtime is rolled back to the previous baseline and runtime. The lower-level `ba
|
|
|
160
264
|
refresh` command remains available when automation should activate a baseline without
|
|
161
265
|
resetting the runtime or pruning old generations.
|
|
162
266
|
|
|
267
|
+
Rows committed after the repeatable-read transaction begins belong to the next refresh;
|
|
268
|
+
they cannot leak into the current snapshot midway through streaming. A schema or ledger
|
|
269
|
+
change during preparation stops activation. Malformed batches, network loss, interruption,
|
|
270
|
+
limit overruns, and low disk also leave the previous baseline active. Because `baseline
|
|
271
|
+
refresh` never resets the runtime, local runtime edits remain in place whether that
|
|
272
|
+
baseline-only preparation succeeds or fails.
|
|
273
|
+
|
|
274
|
+
Privacy `identity` metadata describes PostgreSQL `GENERATED ... AS IDENTITY`, not a
|
|
275
|
+
person or account identifier. UUID account keys normally use `identity: "NO"` while
|
|
276
|
+
remaining explicitly pseudonymized. During restore, Rehearsal consults the actual local
|
|
277
|
+
table for a backing sequence before resetting it; UUID columns never receive numeric
|
|
278
|
+
`max` or `setval` operations.
|
|
279
|
+
|
|
163
280
|
Storage cannot share PostgreSQL's transaction snapshot. Rehearsal instead verifies each
|
|
164
281
|
object's inventory version and byte count during transfer, then records its SHA-256 in
|
|
165
|
-
the immutable baseline.
|
|
282
|
+
the immutable baseline. For an identity-aware path, the database reference and physical
|
|
283
|
+
destination use the same package-owned pseudonym; the source suffix is preserved.
|
|
166
284
|
|
|
167
|
-
`source retire` inventories the exact recorded views before removal,
|
|
168
|
-
those views, the two recorded roles, and local credential/receipt
|
|
169
|
-
|
|
285
|
+
In managed mode, `source retire` inventories the exact recorded views before removal,
|
|
286
|
+
then removes only those views, the two recorded roles, and local credential/receipt
|
|
287
|
+
files. In external mode, it removes only Rehearsal's local credential and receipt; the
|
|
288
|
+
provider-owned role and views remain untouched. The database-enforced expiration still
|
|
289
|
+
limits access, and the provider may revoke it sooner. Rehearsal does not claim that local
|
|
290
|
+
cleanup revoked a provider-owned credential. Unrelated roles, grants, objects, baselines,
|
|
291
|
+
runtimes, and Docker resources are preserved.
|
|
170
292
|
|
|
171
293
|
## Limits
|
|
172
294
|
|
package/docs/runtime-policies.md
CHANGED
|
@@ -157,8 +157,10 @@ graph without an application callback patch:
|
|
|
157
157
|
|
|
158
158
|
Authentication has three separate parts:
|
|
159
159
|
|
|
160
|
-
1.
|
|
161
|
-
|
|
160
|
+
1. `config.supabase.authentication` can enable a Google or GitHub connection in local
|
|
161
|
+
Supabase and reads its credentials from the ignored owner-only environment file.
|
|
162
|
+
Existing projects may still own that local provider TOML manually. Email sign-in does
|
|
163
|
+
not use an OAuth credential declaration.
|
|
162
164
|
2. The application completes the ordinary sign-in and receives a normal Supabase
|
|
163
165
|
session. Rehearsal does not intercept the callback.
|
|
164
166
|
3. The identity policy matches that verified local identity and transfers only the
|