@rehearsal-db/core 0.1.0-beta.1 → 0.1.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/CHANGELOG.md +244 -1
  2. package/COMPATIBILITY.md +17 -0
  3. package/README.md +139 -346
  4. package/SECURITY.md +2 -1
  5. package/SUPPORT.md +5 -0
  6. package/docs/README.md +29 -0
  7. package/docs/adapters.md +20 -6
  8. package/docs/architecture.md +58 -0
  9. package/docs/baselines.md +102 -22
  10. package/docs/commands.md +196 -33
  11. package/docs/configuration.md +258 -13
  12. package/docs/getting-started.md +106 -182
  13. package/docs/glossary.md +11 -8
  14. package/docs/production-source.md +176 -33
  15. package/docs/releasing.md +28 -38
  16. package/docs/roadmap.md +41 -0
  17. package/docs/runtime-policies.md +193 -0
  18. package/docs/sanitization.md +43 -8
  19. package/docs/security-model.md +34 -9
  20. package/docs/standalone-workflow.md +107 -0
  21. package/docs/troubleshooting.md +102 -2
  22. package/docs/tutorial.md +70 -59
  23. package/package.json +30 -22
  24. package/scripts/runtime/manage_database.mjs +18 -0
  25. package/src/README.md +17 -0
  26. package/src/application/session.mjs +435 -0
  27. package/{scripts/lib/rehearsal/baseline_artifact.mjs → src/baseline/artifact.mjs} +142 -17
  28. package/{scripts/lib/rehearsal/baseline_builder.mjs → src/baseline/builder.mjs} +19 -10
  29. package/src/baseline/input_discovery.mjs +155 -0
  30. package/src/baseline/policy_review.mjs +92 -0
  31. package/src/baseline/preparation.mjs +323 -0
  32. package/src/baseline/privacy_engine.mjs +413 -0
  33. package/{scripts/lib/rehearsal → src/baseline}/sanitization_policy.mjs +133 -3
  34. package/{scripts/lib/rehearsal → src/baseline}/schema_snapshot.mjs +1 -1
  35. package/src/cli/arguments.mjs +123 -0
  36. package/src/cli/guided.mjs +812 -0
  37. package/src/cli/rehearsal.mjs +997 -0
  38. package/src/cli/renderers.mjs +584 -0
  39. package/src/cli/runtime_commands.mjs +624 -0
  40. package/src/cli/source_commands.mjs +326 -0
  41. package/src/cli/terminal.mjs +275 -0
  42. package/src/identity/claim.mjs +975 -0
  43. package/src/identity/storage.mjs +165 -0
  44. package/{scripts/lib/rehearsal → src/project}/configuration.d.mts +72 -4
  45. package/src/project/configuration.mjs +1199 -0
  46. package/src/project/setup.mjs +379 -0
  47. package/src/project/support_report.mjs +105 -0
  48. package/src/runtime/cleanup.mjs +381 -0
  49. package/{scripts/lib/rehearsal → src/runtime}/plan.mjs +118 -20
  50. package/src/runtime/policy.mjs +438 -0
  51. package/{scripts/lib/rehearsal/runtime_restore.mjs → src/runtime/restore.mjs} +46 -27
  52. package/src/runtime/topology.mjs +177 -0
  53. package/{scripts/lib/rehearsal → src/shared}/diagnostics.mjs +10 -3
  54. package/src/shared/human_output.mjs +4 -0
  55. package/src/shared/operation_guard.mjs +162 -0
  56. package/{scripts/lib/rehearsal → src/shared}/process_environment.mjs +5 -1
  57. package/src/source/access.mjs +578 -0
  58. package/src/source/asset_transfer.mjs +177 -0
  59. package/src/source/baseline.mjs +446 -0
  60. package/src/source/postgresql_access.mjs +480 -0
  61. package/src/targets/postgresql.mjs +808 -0
  62. package/{scripts/operations/database/manage_rehearsal_database.mjs → src/targets/supabase.mjs} +66 -20
  63. package/{scripts/lib/environment/local_supabase.mjs → src/targets/supabase_environment.mjs} +60 -28
  64. package/src/targets/target.mjs +66 -0
  65. package/scripts/lib/rehearsal/configuration.mjs +0 -559
  66. package/scripts/operations/rehearsal/rehearsal_cli.mjs +0 -565
  67. /package/{scripts/lib/rehearsal → src/runtime}/migration_history.mjs +0 -0
  68. /package/{scripts/lib/rehearsal → src/runtime}/service_environment.mjs +0 -0
@@ -1,36 +1,107 @@
1
1
  # Configuration reference
2
2
 
3
- `rehearsal.config.ts` is executable configuration with a strict versioned schema.
4
- Unknown fields and unknown schema versions are errors, not warnings.
3
+ Most users should let the guide create this file:
4
+
5
+ ```bash
6
+ npx rehearsal
7
+ ```
8
+
9
+ The first run uses your chosen database type and detects the project name, migration
10
+ folder, package-manager commands, and free local ports. After you approve the setup
11
+ preview, it creates a commented `rehearsal.config.mjs` with those values filled in.
12
+ Installation itself does not use a `postinstall` script or silently modify the project.
13
+
14
+ Review lines marked `CHECK`, especially the application proof command. Optional settings
15
+ are present as commented examples, and secrets never belong in this file. Rehearsal will
16
+ not overwrite an existing config.
17
+
18
+ Use this page when changing the generated file. The schema is strict: misspelled fields,
19
+ unknown fields, and unsupported versions are errors. The `.mjs` extension works in both
20
+ CommonJS and ESM projects.
5
21
 
6
22
  ```ts
23
+ // @ts-check
7
24
  import { defineRehearsalConfig } from "@rehearsal-db/core";
8
25
 
9
26
  export default defineRehearsalConfig({
27
+ // Configuration format. Rehearsal will explain if an upgrade is ever needed.
10
28
  schemaVersion: 1,
29
+ // Stable local name used in Rehearsal labels and reports.
11
30
  project: { name: "example-app" },
31
+
32
+ // Project files Rehearsal reads. Every path stays inside this repository.
12
33
  supabase: {
13
34
  workdir: ".",
14
35
  migrationDirectory: "supabase/migrations",
15
36
  rehearsalConfig: "infrastructure/rehearsal/supabase/config.toml",
16
37
  runtimeWorkdir: ".rehearsal/runtime",
38
+
39
+ // Optional; configure both keys together.
40
+ // serviceEnvironmentFile: ".env.rehearsal-service.local",
41
+ // serviceEnvironmentVariables: ["LOCAL_IDP_CLIENT_ID", "LOCAL_IDP_SECRET"],
17
42
  },
18
43
  baseline: {
19
44
  artifactDirectory: ".rehearsal",
20
45
  sanitizationPolicy: "infrastructure/rehearsal/sanitization-policy.json",
21
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",
59
+ containerRuntime: {
60
+ autoStartColima: true,
61
+ },
62
+ cleanup: {
63
+ retainBaselineGenerations: 2,
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
+ // ],
22
73
  application: {
74
+ // CHECK: replace these when the detected package scripts are not correct.
23
75
  startCommand: "npm run dev:rehearsal",
24
76
  proofCommand: "npm run test:rehearsal",
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: [],
25
86
  },
26
87
  runtime: {
88
+ target: "supabase",
27
89
  applicationUrl: "http://localhost:5175",
28
90
  projectId: "example-app-rehearsal",
29
91
  apiPort: 58321,
30
92
  databasePort: 58322,
31
93
  studioPort: 58323,
32
94
  },
33
- safety: { hostedAccess: "disabled", outboundNetwork: "deny" },
95
+ safety: {
96
+ allowedHosts: ["127.0.0.1", "::1", "localhost"],
97
+ blockedEnvironmentVariables: [
98
+ "SUPABASE_ACCESS_TOKEN",
99
+ "SUPABASE_DB_PASSWORD",
100
+ "SUPABASE_PROJECT_ID",
101
+ ],
102
+ hostedAccess: "disabled",
103
+ outboundNetwork: "deny",
104
+ },
34
105
  });
35
106
  ```
36
107
 
@@ -40,6 +111,112 @@ All paths resolve inside the consuming project. The artifact directory must be n
40
111
  `.rehearsal`; this is an intentional deletion guard. `runtimeWorkdir` must be its
41
112
  `runtime` child, and the generated application environment file must remain inside it.
42
113
 
114
+ Rehearsal never overwrites this config. To start over, move the existing file somewhere
115
+ safe, run setup again, and compare the two files before deleting either one.
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
+
142
+ ## Container runtime and cleanup
143
+
144
+ ```ts
145
+ containerRuntime: {
146
+ autoStartColima: true,
147
+ },
148
+ cleanup: {
149
+ retainBaselineGenerations: 2,
150
+ },
151
+ ```
152
+
153
+ Rehearsal uses whichever Docker-compatible engine already answers `docker info`. If none
154
+ is running and `autoStartColima` is `true`, Rehearsal may run `colima start`. It respects
155
+ the user's Colima CPU, memory, and disk settings and never changes them. Set the field to
156
+ `false` when you prefer to start Docker or Colima yourself.
157
+
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.
219
+
43
220
  ## Supabase service environment
44
221
 
45
222
  Some local identity providers need a client ID and secret. Configure both fields or
@@ -56,9 +233,12 @@ terminate at local Auth. They do not grant hosted database access.
56
233
 
57
234
  ## Safety fields
58
235
 
59
- Version 1 accepts loopback hosts only. `hostedAccess` can only be `disabled`, and
60
- `outboundNetwork` can only be `deny`. Ambient hosted Supabase variables are quarantined
61
- from child processes. There is no force flag to weaken these rules.
236
+ Version 1 accepts loopback runtime URLs only. `hostedAccess` can only be `disabled`, and
237
+ `outboundNetwork` can only be `deny`. Common hosted Supabase and PostgreSQL credentials
238
+ are quarantined from child processes. These fields are fail-closed configuration rules,
239
+ not a host firewall: trusted project proof commands and runtime adapters remain ordinary
240
+ local code and must be reviewed. There is no force flag to weaken the configuration
241
+ rules.
62
242
 
63
243
  ## Ports and project identity
64
244
 
@@ -66,17 +246,80 @@ Use unique, non-privileged ports that do not overlap. `projectId` accepts lowerc
66
246
  letters, numbers, and hyphens. It labels the local Docker resources so cleanup targets
67
247
  only this project.
68
248
 
69
- ## Application proof
249
+ ## Database runtime
250
+
251
+ `runtime.target` selects the isolated database driver. It is optional in existing
252
+ configurations and currently defaults to `"supabase"`, so upgrading does not change an
253
+ existing project's behavior. Unknown targets are rejected before any runtime action.
254
+
255
+ For ordinary PostgreSQL, use `postgresql` instead of `supabase`:
256
+
257
+ ```ts
258
+ postgresql: {
259
+ migrationDirectory: "database/migrations",
260
+ runtimeWorkdir: ".rehearsal/runtime",
261
+ image: "postgres:17-alpine",
262
+ database: "postgres",
263
+ user: "postgres",
264
+ },
265
+ runtime: {
266
+ target: "postgresql",
267
+ applicationUrl: "http://localhost:5175",
268
+ projectId: "example-app-rehearsal",
269
+ databasePort: 58322,
270
+ },
271
+ ```
272
+
273
+ The image must be an official versioned Alpine PostgreSQL image and must already exist
274
+ locally. Rehearsal runs it with `--pull=never`, publishes it only on `127.0.0.1`, and
275
+ creates a fresh random runtime password in owner-readable ignored files. It manages only
276
+ the exactly named container and volume carrying the matching project label.
277
+ Plain PostgreSQL does not restore Supabase Storage assets or synthesize Supabase Auth
278
+ users.
279
+
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.
283
+
284
+ ## Application proof and hands-on sessions
285
+
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.
308
+
309
+ After a successful rehearsal, `rehearsal open` uses the same `startCommand`, readiness
310
+ check, and environment mappings for a hands-on session. It starts and verifies every
311
+ configured database target but does not reset them. The app remains available until
312
+ `Ctrl+C` or `Ctrl+Z`; Rehearsal then stops only its application process group. Database
313
+ and Storage changes remain for the next `open`, `verify`, or `start` command.
70
314
 
71
- `proofCommand` is mandatory and project-owned. It should test restored relationships,
72
- authentication shape, critical reads, and candidate-migration behavior. A command that
73
- only checks whether the home page returns 200 is usually too weak.
315
+ `application.readiness` is required for `open`. Point it at a route that returns the
316
+ configured status only when the local app is ready. Keep the URL on a loopback host.
74
317
 
75
318
  ## Runtime adapters
76
319
 
77
- Most projects do not need an adapter. Use one only for schema-specific restore setup,
78
- synthetic local identities, explicit generated environment variables, or post-restore
79
- invariants. See [adapters](adapters.md).
320
+ Existing adapters remain compatible, but new projects should first use `runtimePolicy`,
321
+ `identityPolicy`, environment mappings, and HTTP proofs. Use an adapter only for a shape
322
+ the documented declarations explicitly reject. See [adapters](adapters.md).
80
323
 
81
324
  ## Advanced library entry points
82
325
 
@@ -88,7 +331,9 @@ may use these explicit subpaths:
88
331
  - `@rehearsal-db/core/schema`
89
332
  - `@rehearsal-db/core/diagnostics`
90
333
  - `@rehearsal-db/core/process-environment`
334
+ - `@rehearsal-db/core/privacy`
91
335
  - `@rehearsal-db/core/service-environment`
336
+ - `@rehearsal-db/core/source-access`
92
337
 
93
338
  These advanced entry points are ESM JavaScript APIs in the first beta. The root
94
339
  configuration and sanitization API has TypeScript declarations; the advanced subpaths do