@rehearsal-db/core 0.1.0-beta.7 → 0.1.0-beta.9
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 +15 -3
- package/README.md +31 -13
- package/docs/README.md +29 -0
- package/docs/adapters.md +15 -6
- package/docs/architecture.md +58 -0
- package/docs/baselines.md +22 -1
- package/docs/commands.md +81 -14
- package/docs/configuration.md +144 -11
- package/docs/getting-started.md +12 -2
- package/docs/glossary.md +4 -0
- package/docs/production-source.md +176 -33
- package/docs/roadmap.md +30 -28
- package/docs/runtime-policies.md +191 -0
- package/docs/sanitization.md +24 -8
- package/docs/security-model.md +29 -8
- package/docs/standalone-workflow.md +107 -0
- package/docs/troubleshooting.md +8 -0
- package/package.json +25 -22
- package/scripts/runtime/manage_database.mjs +18 -0
- package/src/README.md +17 -0
- package/src/application/session.mjs +313 -0
- package/{scripts/lib/rehearsal/baseline_artifact.mjs → src/baseline/artifact.mjs} +110 -14
- package/{scripts/lib/rehearsal/baseline_builder.mjs → src/baseline/builder.mjs} +8 -4
- package/{scripts/lib/rehearsal/baseline_preparation.mjs → src/baseline/preparation.mjs} +11 -4
- package/src/baseline/privacy_engine.mjs +413 -0
- package/{scripts/lib/rehearsal → src/baseline}/sanitization_policy.mjs +27 -7
- package/{scripts/lib/rehearsal → src/baseline}/schema_snapshot.mjs +1 -1
- package/src/cli/arguments.mjs +120 -0
- package/src/cli/guided.mjs +807 -0
- package/src/cli/rehearsal.mjs +933 -0
- package/src/cli/renderers.mjs +584 -0
- package/src/cli/runtime_commands.mjs +553 -0
- package/src/cli/source_commands.mjs +326 -0
- package/src/cli/terminal.mjs +275 -0
- package/src/identity/claim.mjs +975 -0
- package/src/identity/storage.mjs +165 -0
- package/{scripts/lib/rehearsal → src/project}/configuration.d.mts +34 -0
- package/{scripts/lib/rehearsal → src/project}/configuration.mjs +353 -3
- package/{scripts/lib/rehearsal → src/project}/setup.mjs +1 -1
- package/{scripts/lib/rehearsal → src/project}/support_report.mjs +5 -2
- package/{scripts/lib/rehearsal → src/runtime}/cleanup.mjs +3 -3
- package/{scripts/lib/rehearsal → src/runtime}/plan.mjs +5 -5
- package/src/runtime/policy.mjs +438 -0
- package/{scripts/lib/rehearsal/runtime_restore.mjs → src/runtime/restore.mjs} +40 -25
- package/src/runtime/topology.mjs +177 -0
- package/{scripts/lib/rehearsal → src/shared}/diagnostics.mjs +1 -1
- package/src/shared/operation_guard.mjs +162 -0
- package/{scripts/lib/rehearsal → src/shared}/process_environment.mjs +5 -1
- package/src/source/access.mjs +578 -0
- package/src/source/asset_transfer.mjs +177 -0
- package/src/source/baseline.mjs +446 -0
- package/src/source/postgresql_access.mjs +480 -0
- package/{scripts/lib/runtime/postgresql_runtime.mjs → src/targets/postgresql.mjs} +49 -13
- package/{scripts/lib/runtime/supabase_runtime.mjs → src/targets/supabase.mjs} +54 -16
- package/{scripts/lib/environment/local_supabase.mjs → src/targets/supabase_environment.mjs} +52 -20
- package/{scripts/lib/runtime/runtime_target.mjs → src/targets/target.mjs} +27 -2
- package/scripts/operations/database/manage_rehearsal_database.mjs +0 -11
- package/scripts/operations/rehearsal/rehearsal_cli.mjs +0 -2166
- /package/{scripts/lib/rehearsal → src/baseline}/input_discovery.mjs +0 -0
- /package/{scripts/lib/rehearsal → src/baseline}/policy_review.mjs +0 -0
- /package/{scripts/lib/rehearsal → src/runtime}/migration_history.mjs +0 -0
- /package/{scripts/lib/rehearsal → src/runtime}/service_environment.mjs +0 -0
- /package/{scripts/lib/rehearsal → src/shared}/human_output.mjs +0 -0
package/docs/configuration.md
CHANGED
|
@@ -44,17 +44,45 @@ export default defineRehearsalConfig({
|
|
|
44
44
|
artifactDirectory: ".rehearsal",
|
|
45
45
|
sanitizationPolicy: "infrastructure/rehearsal/sanitization-policy.json",
|
|
46
46
|
},
|
|
47
|
+
// Optional, separately approved production-shaped preparation.
|
|
48
|
+
// preparation: {
|
|
49
|
+
// sourcePolicy: "infrastructure/rehearsal/source-access-policy.json",
|
|
50
|
+
// privacyKey: ".rehearsal/secrets/privacy.key",
|
|
51
|
+
// batchRows: 500,
|
|
52
|
+
// maximumRows: 1000000,
|
|
53
|
+
// maximumBytes: 2147483648,
|
|
54
|
+
// diskHeadroomBytes: 67108864,
|
|
55
|
+
// },
|
|
56
|
+
// runtimePolicy: "infrastructure/rehearsal/runtime-policy.json",
|
|
57
|
+
// Optional signup defaults, role/reference transfer, Storage paths, and token checks.
|
|
58
|
+
// identityPolicy: "infrastructure/rehearsal/identity-policy.json",
|
|
47
59
|
containerRuntime: {
|
|
48
60
|
autoStartColima: true,
|
|
49
61
|
},
|
|
50
62
|
cleanup: {
|
|
51
63
|
retainBaselineGenerations: 2,
|
|
52
64
|
},
|
|
65
|
+
// Optional. Each dependent database uses another complete Rehearsal config.
|
|
66
|
+
// dependentTargets: [
|
|
67
|
+
// {
|
|
68
|
+
// name: "publication-api",
|
|
69
|
+
// configPath: "rehearsal.publication.config.mjs",
|
|
70
|
+
// prepareCommand: "npm run rehearsal:prepare-publication",
|
|
71
|
+
// },
|
|
72
|
+
// ],
|
|
53
73
|
application: {
|
|
54
74
|
// CHECK: replace these when the detected package scripts are not correct.
|
|
55
75
|
startCommand: "npm run dev:rehearsal",
|
|
56
76
|
proofCommand: "npm run test:rehearsal",
|
|
57
77
|
environmentFile: ".rehearsal/runtime.env",
|
|
78
|
+
// environmentVariables: { DATABASE_URL: "primary:DATABASE_URL" },
|
|
79
|
+
readiness: {
|
|
80
|
+
url: "http://localhost:5175/health",
|
|
81
|
+
expectedStatus: 200,
|
|
82
|
+
timeoutSeconds: 30,
|
|
83
|
+
},
|
|
84
|
+
// Add at least one real positive and one negative before enabling.
|
|
85
|
+
// httpProofs: [],
|
|
58
86
|
},
|
|
59
87
|
runtime: {
|
|
60
88
|
target: "supabase",
|
|
@@ -86,6 +114,31 @@ All paths resolve inside the consuming project. The artifact directory must be n
|
|
|
86
114
|
Rehearsal never overwrites this config. To start over, move the existing file somewhere
|
|
87
115
|
safe, run setup again, and compare the two files before deleting either one.
|
|
88
116
|
|
|
117
|
+
`preparation.privacyKey` must stay inside `.rehearsal`; it is ignored and owner-readable
|
|
118
|
+
only. Source, runtime, and identity policy files are declarations that may be reviewed in
|
|
119
|
+
source control. They must never contain passwords, tokens, production URLs, raw owner
|
|
120
|
+
identifiers, SQL, or executable code.
|
|
121
|
+
|
|
122
|
+
## Optional source preparation
|
|
123
|
+
|
|
124
|
+
`preparation` enables the separate `source` and `baseline refresh` commands. It does not
|
|
125
|
+
change ordinary `run`, `reset`, `migrate`, or `verify` behavior.
|
|
126
|
+
|
|
127
|
+
- `sourcePolicy` declares the hashed target identity, temporary roles, exact export
|
|
128
|
+
columns, public/approved-owner row scope, migration ledger, and optional Storage scope.
|
|
129
|
+
- `privacyKey` stores the local keyed-pseudonym secret.
|
|
130
|
+
- `batchRows`, `maximumRows`, and `maximumBytes` bound extraction.
|
|
131
|
+
- `diskHeadroomBytes` prevents activation when the copy cannot be built safely.
|
|
132
|
+
|
|
133
|
+
See [Production source](production-source.md) for complete examples and the exact
|
|
134
|
+
approval sequence.
|
|
135
|
+
|
|
136
|
+
`runtimePolicy` replaces common restore adapters with reviewed schemas, allowlisted
|
|
137
|
+
extensions, managed triggers, local-only singleton rows, and structural expectations.
|
|
138
|
+
`identityPolicy` declares a hashed verified email, copied placeholder, safe signup
|
|
139
|
+
defaults, required role/reference transfers, Storage path rewrites, and token checks. See
|
|
140
|
+
[Runtime and identity policies](runtime-policies.md).
|
|
141
|
+
|
|
89
142
|
## Container runtime and cleanup
|
|
90
143
|
|
|
91
144
|
```ts
|
|
@@ -102,9 +155,67 @@ is running and `autoStartColima` is `true`, Rehearsal may run `colima start`. It
|
|
|
102
155
|
the user's Colima CPU, memory, and disk settings and never changes them. Set the field to
|
|
103
156
|
`false` when you prefer to start Docker or Colima yourself.
|
|
104
157
|
|
|
105
|
-
`retainBaselineGenerations` controls how many immutable baseline generations survive
|
|
106
|
-
`rehearsal cleanup`; it must be at least 1.
|
|
107
|
-
|
|
158
|
+
`retainBaselineGenerations` controls how many immutable baseline generations survive an
|
|
159
|
+
approved `rehearsal refresh` or `rehearsal cleanup`; it must be at least 1. Refresh shows
|
|
160
|
+
the exact old generations before confirmation and never removes the active baseline
|
|
161
|
+
before its replacement is verified. Runtime deletion outside refresh and shared-image
|
|
162
|
+
inspection remain explicit command choices. See [CLI commands](commands.md).
|
|
163
|
+
|
|
164
|
+
## Dependent databases
|
|
165
|
+
|
|
166
|
+
Use `dependentTargets` when one local application needs another database, such as a
|
|
167
|
+
publication or read-model database:
|
|
168
|
+
|
|
169
|
+
```ts
|
|
170
|
+
dependentTargets: [
|
|
171
|
+
{
|
|
172
|
+
name: "publication-api",
|
|
173
|
+
configPath: "rehearsal.publication.config.mjs",
|
|
174
|
+
prepareCommand: "npm run rehearsal:prepare-publication",
|
|
175
|
+
},
|
|
176
|
+
],
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
The referenced file is an ordinary complete Rehearsal config. Give it its own runtime
|
|
180
|
+
project ID, ports, application environment file, and artifact folder ending in
|
|
181
|
+
`.rehearsal`, for example `infrastructure/rehearsal/publication/.rehearsal`. Create and
|
|
182
|
+
review its baseline separately:
|
|
183
|
+
|
|
184
|
+
The easiest starting point is to copy the generated primary config, then change the
|
|
185
|
+
project name, migration folder, artifact folder, environment file, runtime project ID,
|
|
186
|
+
ports, and proof command. Keep the same fail-closed safety settings. Omit
|
|
187
|
+
`prepareCommand` when the dependent baseline is already ready to test. Rehearsal never
|
|
188
|
+
copies rows between databases automatically. A dependent Supabase target also needs its
|
|
189
|
+
own local `rehearsalConfig` file with matching dedicated ports. Preparation must be safe
|
|
190
|
+
to rerun because `run`, `reset`, and `migrate` each invoke it after the databases are
|
|
191
|
+
ready.
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
npx rehearsal baseline create \
|
|
195
|
+
--config=rehearsal.publication.config.mjs \
|
|
196
|
+
--records=path/to/publication-data.ndjson \
|
|
197
|
+
--ledger=path/to/publication-ledger.json
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
The primary `doctor`, `explain`, `candidates`, lifecycle, and cleanup commands then cover
|
|
201
|
+
the whole stack. Rehearsal restores and migrates the primary target first, followed by
|
|
202
|
+
dependents in the listed order. For `run`, `reset`, and `migrate`, it next runs each
|
|
203
|
+
`prepareCommand`. On `run`, it executes each dependent config's
|
|
204
|
+
`application.proofCommand` before the primary proof. `stop` and `discard` run in reverse
|
|
205
|
+
order. Cleanup verifies every target's exact preview before removing any selected
|
|
206
|
+
resource.
|
|
207
|
+
|
|
208
|
+
Legacy preparation commands receive paths—not credentials—in environment variables:
|
|
209
|
+
`REHEARSAL_PRIMARY_ENV_FILE` and
|
|
210
|
+
`REHEARSAL_DEPENDENT_<UPPERCASE_NAME>_ENV_FILE`. New integrations should prefer an
|
|
211
|
+
already prepared dependent baseline or the package's declarative source/privacy
|
|
212
|
+
workflow. `prepareCommand` remains compatible for existing projects but is ordinary
|
|
213
|
+
project code and must be reviewed. Nested dependencies are rejected.
|
|
214
|
+
|
|
215
|
+
The dependent proof must include at least one known successful lookup and appropriate
|
|
216
|
+
negative controls, such as unauthorized, malformed, withheld, or missing records. A
|
|
217
|
+
response that merely avoids a server error does not prove that eligible data was
|
|
218
|
+
published or can be found.
|
|
108
219
|
|
|
109
220
|
## Supabase service environment
|
|
110
221
|
|
|
@@ -166,20 +277,40 @@ the exactly named container and volume carrying the matching project label.
|
|
|
166
277
|
Plain PostgreSQL does not restore Supabase Storage assets or synthesize Supabase Auth
|
|
167
278
|
users.
|
|
168
279
|
|
|
169
|
-
|
|
170
|
-
checks
|
|
280
|
+
Declarative runtime policies are preferred for supported schema prerequisites and
|
|
281
|
+
checks. Existing project-owned adapters remain compatible but do not replace the
|
|
282
|
+
database driver.
|
|
171
283
|
|
|
172
284
|
## Application proof
|
|
173
285
|
|
|
174
|
-
`
|
|
175
|
-
|
|
176
|
-
|
|
286
|
+
`startCommand` is the ordinary application command. When `readiness` is present,
|
|
287
|
+
`rehearsal run` launches it with a minimal environment, waits for the exact local status,
|
|
288
|
+
runs proofs, and stops only that child process group. `environmentVariables` explicitly
|
|
289
|
+
maps generated runtime values such as `primary:DATABASE_URL`; undeclared inherited
|
|
290
|
+
hosted secrets are not passed through.
|
|
291
|
+
|
|
292
|
+
Your application framework may still load `.env` files from the project directory on
|
|
293
|
+
its own. Rehearsal cannot intercept that file loading. If a local proof could otherwise
|
|
294
|
+
pick up a hosted URL, token, CAPTCHA key, or similar value, set an explicit safe local
|
|
295
|
+
value in the configured `startCommand` or the framework's test-mode configuration.
|
|
296
|
+
Environment filtering is a process boundary, not an operating-system or file-access
|
|
297
|
+
firewall.
|
|
298
|
+
|
|
299
|
+
Supabase targets write validated loopback-only `DATABASE_URL`, `PGHOST`, `PGPORT`,
|
|
300
|
+
`PGDATABASE`, `PGUSER`, and `PGPASSWORD` values into the ignored runtime environment.
|
|
301
|
+
Package-owned identity commands use that same local connection; an adapter is not
|
|
302
|
+
required to provide it.
|
|
303
|
+
|
|
304
|
+
`proofCommand` remains an ordinary project test command. Optional `httpProofs` add
|
|
305
|
+
package-owned checks and must include real positive and negative expectations. A 200,
|
|
306
|
+
404, 401, empty result, or non-5xx response is not a positive unless it matches the
|
|
307
|
+
declared status and body assertion.
|
|
177
308
|
|
|
178
309
|
## Runtime adapters
|
|
179
310
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
311
|
+
Existing adapters remain compatible, but new projects should first use `runtimePolicy`,
|
|
312
|
+
`identityPolicy`, environment mappings, and HTTP proofs. Use an adapter only for a shape
|
|
313
|
+
the documented declarations explicitly reject. See [adapters](adapters.md).
|
|
183
314
|
|
|
184
315
|
## Advanced library entry points
|
|
185
316
|
|
|
@@ -191,7 +322,9 @@ may use these explicit subpaths:
|
|
|
191
322
|
- `@rehearsal-db/core/schema`
|
|
192
323
|
- `@rehearsal-db/core/diagnostics`
|
|
193
324
|
- `@rehearsal-db/core/process-environment`
|
|
325
|
+
- `@rehearsal-db/core/privacy`
|
|
194
326
|
- `@rehearsal-db/core/service-environment`
|
|
327
|
+
- `@rehearsal-db/core/source-access`
|
|
195
328
|
|
|
196
329
|
These advanced entry points are ESM JavaScript APIs in the first beta. The root
|
|
197
330
|
configuration and sanitization API has TypeScript declarations; the advanced subpaths do
|
package/docs/getting-started.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Getting started
|
|
2
2
|
|
|
3
3
|
This guide sets up Rehearsal in an existing project. It creates a disposable database on
|
|
4
|
-
your computer and never
|
|
4
|
+
your computer. Normal setup and rehearsal commands never connect to a hosted database.
|
|
5
5
|
|
|
6
6
|
Want to experiment first? Use the [safe hands-on tutorial](tutorial.md).
|
|
7
7
|
|
|
@@ -111,10 +111,20 @@ A successful run:
|
|
|
111
111
|
1. restores the baseline;
|
|
112
112
|
2. applies only the migrations you approved;
|
|
113
113
|
3. verifies the local database;
|
|
114
|
-
4.
|
|
114
|
+
4. launches the ordinary application when readiness is configured;
|
|
115
|
+
5. runs the ordinary test command and declared positive/negative HTTP proofs;
|
|
116
|
+
6. stops only the application process it launched.
|
|
115
117
|
|
|
116
118
|
Your original baseline remains unchanged.
|
|
117
119
|
|
|
120
|
+
If a source owner later approves a production-shaped copy, use the separate workflow in
|
|
121
|
+
[Optional production-shaped preparation](production-source.md). Do not add source
|
|
122
|
+
credentials to the normal config or runtime environment.
|
|
123
|
+
|
|
124
|
+
Once temporary source access is ready, `npx rehearsal refresh` previews the safe
|
|
125
|
+
replacement workflow. It means “get a newly verified copy.” By contrast, `reset` means
|
|
126
|
+
“discard local edits and restore the copy I already have.”
|
|
127
|
+
|
|
118
128
|
## 6. Test and clean up
|
|
119
129
|
|
|
120
130
|
Use the guide for normal runtime tasks:
|
package/docs/glossary.md
CHANGED
|
@@ -6,6 +6,10 @@
|
|
|
6
6
|
|
|
7
7
|
**Candidate digest** — checksum binding the exact candidate filenames and bytes.
|
|
8
8
|
|
|
9
|
+
**Dependent target** — another isolated local database managed with the primary runtime.
|
|
10
|
+
|
|
11
|
+
**Combined digest** — one checksum binding candidate or cleanup sets across every target.
|
|
12
|
+
|
|
9
13
|
**Project-owned** — application-specific policy or code that remains outside the package.
|
|
10
14
|
|
|
11
15
|
**Represented migration** — historical migration whose exact bytes are bound into the
|
|
@@ -1,33 +1,176 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
1.
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
1
|
+
# Optional production-shaped preparation
|
|
2
|
+
|
|
3
|
+
Start with synthetic data. Use this workflow only when the source owner has approved the
|
|
4
|
+
exact tables, columns, owner scope, assets, and privacy policy.
|
|
5
|
+
|
|
6
|
+
Ordinary Rehearsal commands remain local-only. Source preparation is separate and cannot
|
|
7
|
+
be triggered by `run`, `reset`, `migrate`, `verify`, or application launch.
|
|
8
|
+
|
|
9
|
+
## 1. Add the config paths
|
|
10
|
+
|
|
11
|
+
```js
|
|
12
|
+
preparation: {
|
|
13
|
+
sourcePolicy: "infrastructure/rehearsal/source-access-policy.json",
|
|
14
|
+
privacyKey: ".rehearsal/secrets/privacy.key",
|
|
15
|
+
batchRows: 500,
|
|
16
|
+
maximumRows: 1000000,
|
|
17
|
+
maximumBytes: 2147483648,
|
|
18
|
+
diskHeadroomBytes: 67108864,
|
|
19
|
+
},
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
The privacy key stays ignored under `.rehearsal`. The policy is safe to review in source
|
|
23
|
+
control because it contains hashes and environment-variable names, not credentials,
|
|
24
|
+
URLs, or raw owner identifiers.
|
|
25
|
+
|
|
26
|
+
## 2. Declare the source boundary
|
|
27
|
+
|
|
28
|
+
`source-access-policy.json` uses this shape:
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"accessVersion": 1,
|
|
33
|
+
"targetFingerprint": "<sha256 of the approved PostgreSQL host, port, and database>",
|
|
34
|
+
"administratorEnvironmentVariable": "REHEARSAL_SOURCE_ADMIN_URL",
|
|
35
|
+
"reader": {
|
|
36
|
+
"role": "rehearsal_example_reader",
|
|
37
|
+
"ownerRole": "rehearsal_example_owner",
|
|
38
|
+
"credentialFile": ".rehearsal/secrets/source-reader.env",
|
|
39
|
+
"validForMinutes": 30
|
|
40
|
+
},
|
|
41
|
+
"exportSchema": "rehearsal_export_example",
|
|
42
|
+
"migrationLedger": {
|
|
43
|
+
"schema": "supabase_migrations",
|
|
44
|
+
"table": "schema_migrations",
|
|
45
|
+
"versionColumn": "version",
|
|
46
|
+
"nameColumn": "name",
|
|
47
|
+
"statementsColumn": "statements"
|
|
48
|
+
},
|
|
49
|
+
"relations": [
|
|
50
|
+
{
|
|
51
|
+
"source": { "schema": "public", "table": "widgets" },
|
|
52
|
+
"view": "widgets",
|
|
53
|
+
"targetSchema": "public",
|
|
54
|
+
"targetTable": "widgets",
|
|
55
|
+
"columns": ["id", "owner_id", "name"],
|
|
56
|
+
"orderBy": ["id"],
|
|
57
|
+
"rowScope": { "kind": "approved-public" }
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"source": { "schema": "public", "table": "profiles" },
|
|
61
|
+
"view": "approved_owner_profile",
|
|
62
|
+
"targetSchema": "app_api",
|
|
63
|
+
"targetTable": "profiles",
|
|
64
|
+
"columns": ["id", "email"],
|
|
65
|
+
"orderBy": ["id"],
|
|
66
|
+
"rowScope": {
|
|
67
|
+
"kind": "approved-owner",
|
|
68
|
+
"column": "id",
|
|
69
|
+
"valueEnvironmentVariable": "REHEARSAL_APPROVED_OWNER_ID"
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
],
|
|
73
|
+
"assets": []
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Calculate fingerprints with the exported helpers from `@rehearsal-db/core/source-access`
|
|
78
|
+
or a reviewed local script. A fingerprint binds the destination without recording its
|
|
79
|
+
address. Changing the host, port, or database invalidates the plan.
|
|
80
|
+
|
|
81
|
+
`approved-public` means every selected row is licensed or otherwise approved for this
|
|
82
|
+
use. `approved-owner` requires one explicit owner value from the named environment
|
|
83
|
+
variable. Rehearsal never chooses an owner by finding an administrator.
|
|
84
|
+
|
|
85
|
+
`targetSchema` is optional and defaults to `public`. Set it when the restored relation
|
|
86
|
+
belongs elsewhere, and use the same schema in privacy policy version 2. This is relation
|
|
87
|
+
identity, not a request to search every schema.
|
|
88
|
+
|
|
89
|
+
For Storage, add an `assetReader` block and approved `assets` entries. The reader URL and
|
|
90
|
+
token come from named environment variables. Objects outside the exact bucket/prefix are
|
|
91
|
+
not listed or downloaded. Size, object-count, path, ETag, and exact-byte checks apply.
|
|
92
|
+
|
|
93
|
+
## 3. Use executable privacy policy version 2
|
|
94
|
+
|
|
95
|
+
Every selected column has one action and, where required, a bounded recipe:
|
|
96
|
+
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"policyVersion": 2,
|
|
100
|
+
"migrationCutoff": "20260101000000",
|
|
101
|
+
"tables": [
|
|
102
|
+
{
|
|
103
|
+
"schema": "app_api",
|
|
104
|
+
"name": "profiles",
|
|
105
|
+
"sourceRows": "STREAM AND SANITIZE",
|
|
106
|
+
"columns": [
|
|
107
|
+
{
|
|
108
|
+
"name": "id",
|
|
109
|
+
"action": "PSEUDONYMIZE",
|
|
110
|
+
"recipe": { "format": "uuid", "namespace": "account-id" },
|
|
111
|
+
"generated": "NEVER",
|
|
112
|
+
"identity": "NO",
|
|
113
|
+
"foreignKey": null
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"name": "email",
|
|
117
|
+
"action": "PSEUDONYMIZE",
|
|
118
|
+
"recipe": { "format": "email", "namespace": "account-email" },
|
|
119
|
+
"generated": "NEVER",
|
|
120
|
+
"identity": "NO",
|
|
121
|
+
"foreignKey": null
|
|
122
|
+
}
|
|
123
|
+
]
|
|
124
|
+
}
|
|
125
|
+
]
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Supported recipes are intentionally small: keyed UUID/email/text/integer pseudonyms,
|
|
130
|
+
explicit constants, bounded date shifts, and fully classified JSON objects. Unknown
|
|
131
|
+
tables, columns, JSON keys, formats, and recipes stop the refresh. There is no JavaScript
|
|
132
|
+
or SQL escape hatch.
|
|
133
|
+
|
|
134
|
+
## 4. Preview, apply, refresh, and retire
|
|
135
|
+
|
|
136
|
+
Keep credentials out of shell history by loading them from an owner-only environment
|
|
137
|
+
manager or file, then run:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
npx rehearsal privacy key --write
|
|
141
|
+
npx rehearsal source plan
|
|
142
|
+
npx rehearsal source apply --confirm-source-access=<full-sha256>
|
|
143
|
+
npx rehearsal refresh
|
|
144
|
+
npx rehearsal refresh --confirm-refresh=<full-sha256>
|
|
145
|
+
npx rehearsal source retire
|
|
146
|
+
npx rehearsal source retire --confirm-source-retirement=<full-sha256>
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
`source apply` creates new time-limited roles and export views only when every exact name
|
|
150
|
+
is unused. It verifies the reader cannot read raw tables, write, escalate roles, or call
|
|
151
|
+
an exposed security-definer network function. Externally provisioned readers are not yet
|
|
152
|
+
supported; use the managed reader so Rehearsal can prove its scope and retirement.
|
|
153
|
+
|
|
154
|
+
`refresh` previews the complete replacement first. After exact confirmation, its baseline
|
|
155
|
+
step uses one read-only repeatable-read transaction for the schema shape,
|
|
156
|
+
migration ledger, and rows. It streams in bounded batches, records only counts and
|
|
157
|
+
hashes, stages privately, rechecks schema/ledger drift, and activates atomically. It then
|
|
158
|
+
resets the local runtime stack and applies configured baseline retention. A failed new
|
|
159
|
+
runtime is rolled back to the previous baseline and runtime. The lower-level `baseline
|
|
160
|
+
refresh` command remains available when automation should activate a baseline without
|
|
161
|
+
resetting the runtime or pruning old generations.
|
|
162
|
+
|
|
163
|
+
Storage cannot share PostgreSQL's transaction snapshot. Rehearsal instead verifies each
|
|
164
|
+
object's inventory version and byte count during transfer, then records its SHA-256 in
|
|
165
|
+
the immutable baseline.
|
|
166
|
+
|
|
167
|
+
`source retire` inventories the exact recorded views before removal, then removes only
|
|
168
|
+
those views, the two recorded roles, and local credential/receipt files. Unrelated roles,
|
|
169
|
+
grants, objects, baselines, runtimes, and Docker resources are preserved.
|
|
170
|
+
|
|
171
|
+
## Limits
|
|
172
|
+
|
|
173
|
+
Rehearsal does not decide consent, licensing, retention rights, privileged-role meaning,
|
|
174
|
+
or which owner is yours. It does not provide an OS firewall, backup, disaster recovery,
|
|
175
|
+
or universal database support. Real Google account selection and provider callbacks
|
|
176
|
+
still require direct human observation; a synthetic redirect cannot prove them.
|
package/docs/roadmap.md
CHANGED
|
@@ -1,39 +1,41 @@
|
|
|
1
1
|
# Next steps
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
Rehearsal supports guided Supabase and ordinary PostgreSQL migration rehearsals. The
|
|
4
|
+
current development track removes the need for consumer-owned Rehearsal engines while
|
|
5
|
+
keeping application meaning and privacy decisions project-owned.
|
|
5
6
|
|
|
6
|
-
##
|
|
7
|
+
## Standalone workflow
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
branch, then prove:
|
|
9
|
+
The implementation sequence is dependency-driven:
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
1. exact temporary source access and retirement;
|
|
12
|
+
2. bounded coherent extraction and executable privacy rules;
|
|
13
|
+
3. approved Storage assets and declarative restore prerequisites;
|
|
14
|
+
4. verified local identity association;
|
|
15
|
+
5. ordinary application launch and meaningful positive/negative proofs;
|
|
16
|
+
6. onboarding, upgrade safety, and exact packaged-artifact acceptance.
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
These capabilities stay behind separate review boundaries. Normal runtime commands never
|
|
19
|
+
receive source credentials. Source-side writes, package publication, consumer cleanup,
|
|
20
|
+
and real provider observation each require their own authorization.
|
|
18
21
|
|
|
19
|
-
|
|
22
|
+
Track the full breakdown in
|
|
23
|
+
[standalone roadmap issue #38](https://github.com/Ddupasquier/rehearsal-db/issues/38).
|
|
20
24
|
|
|
21
|
-
|
|
22
|
-
developer. Reduce manual file preparation without weakening review, checksum, or
|
|
23
|
-
local-only safety rules.
|
|
25
|
+
## Acceptance still required
|
|
24
26
|
|
|
25
|
-
|
|
27
|
+
- Install the exact packed candidate in clean Supabase and PostgreSQL consumers.
|
|
28
|
+
- Exercise two unrelated synthetic schemas, bounded large data, interruption, drift,
|
|
29
|
+
invalid migrations, identities, images, persistence, reset, and cleanup.
|
|
30
|
+
- Run the released package in the real reporting consumer and record positives and
|
|
31
|
+
negatives.
|
|
32
|
+
- Directly observe any claimed Google account-picker/callback and unfamiliar-developer
|
|
33
|
+
onboarding behavior; automation cannot invent that evidence.
|
|
34
|
+
- Remove consumer integration code only after its replacement passes and that deletion
|
|
35
|
+
is separately approved.
|
|
26
36
|
|
|
27
|
-
|
|
28
|
-
Fix general PostgreSQL problems before adding provider-specific behavior.
|
|
37
|
+
## Later database targets
|
|
29
38
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
for individual PostgreSQL services. Keep rehearsals disposable and local; hosted database
|
|
34
|
-
execution remains outside the current safety model.
|
|
35
|
-
|
|
36
|
-
## Later
|
|
37
|
-
|
|
38
|
-
MySQL, MongoDB, and unrelated database families require different migration and restore
|
|
39
|
-
behavior. They remain out of scope until the PostgreSQL experience is proven and stable.
|
|
39
|
+
After the PostgreSQL family is stable in real projects, evaluate individual PostgreSQL
|
|
40
|
+
services. MySQL, MongoDB, and unrelated database families require different migration,
|
|
41
|
+
restore, and safety behavior and remain out of scope.
|