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

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 (72) hide show
  1. package/CHANGELOG.md +271 -1
  2. package/COMPATIBILITY.md +26 -0
  3. package/README.md +150 -346
  4. package/SECURITY.md +2 -1
  5. package/SUPPORT.md +5 -0
  6. package/docs/README.md +38 -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 +202 -33
  11. package/docs/configuration.md +288 -13
  12. package/docs/getting-started.md +114 -181
  13. package/docs/glossary.md +11 -8
  14. package/docs/index.md +47 -0
  15. package/docs/production-source.md +176 -33
  16. package/docs/releasing.md +28 -38
  17. package/docs/roadmap.md +41 -0
  18. package/docs/runtime-policies.md +253 -0
  19. package/docs/sanitization.md +144 -8
  20. package/docs/security-model.md +34 -9
  21. package/docs/standalone-workflow.md +109 -0
  22. package/docs/troubleshooting.md +127 -2
  23. package/docs/tutorial.md +70 -59
  24. package/package.json +39 -23
  25. package/scripts/install/create_root_config.mjs +36 -0
  26. package/scripts/runtime/manage_database.mjs +18 -0
  27. package/src/README.md +17 -0
  28. package/src/application/session.mjs +435 -0
  29. package/{scripts/lib/rehearsal/baseline_artifact.mjs → src/baseline/artifact.mjs} +142 -17
  30. package/{scripts/lib/rehearsal/baseline_builder.mjs → src/baseline/builder.mjs} +19 -10
  31. package/src/baseline/input_discovery.mjs +155 -0
  32. package/src/baseline/policy_review.mjs +92 -0
  33. package/src/baseline/preparation.mjs +323 -0
  34. package/src/baseline/privacy_engine.mjs +741 -0
  35. package/{scripts/lib/rehearsal → src/baseline}/sanitization_policy.mjs +133 -3
  36. package/{scripts/lib/rehearsal → src/baseline}/schema_snapshot.mjs +1 -1
  37. package/src/cli/arguments.mjs +123 -0
  38. package/src/cli/guided.mjs +812 -0
  39. package/src/cli/init_command.mjs +77 -0
  40. package/src/cli/rehearsal.mjs +952 -0
  41. package/src/cli/renderers.mjs +589 -0
  42. package/src/cli/runtime_commands.mjs +624 -0
  43. package/src/cli/source_commands.mjs +326 -0
  44. package/src/cli/terminal.mjs +275 -0
  45. package/src/identity/claim.mjs +1163 -0
  46. package/src/identity/storage.mjs +165 -0
  47. package/{scripts/lib/rehearsal → src/project}/configuration.d.mts +72 -4
  48. package/src/project/configuration.mjs +1201 -0
  49. package/src/project/install_scaffold.mjs +291 -0
  50. package/src/project/setup.mjs +484 -0
  51. package/src/project/support_report.mjs +105 -0
  52. package/src/runtime/cleanup.mjs +381 -0
  53. package/{scripts/lib/rehearsal → src/runtime}/plan.mjs +118 -20
  54. package/src/runtime/policy.mjs +438 -0
  55. package/{scripts/lib/rehearsal/runtime_restore.mjs → src/runtime/restore.mjs} +46 -27
  56. package/src/runtime/topology.mjs +177 -0
  57. package/{scripts/lib/rehearsal → src/shared}/diagnostics.mjs +10 -3
  58. package/src/shared/human_output.mjs +4 -0
  59. package/src/shared/operation_guard.mjs +162 -0
  60. package/{scripts/lib/rehearsal → src/shared}/process_environment.mjs +5 -1
  61. package/src/source/access.mjs +578 -0
  62. package/src/source/asset_transfer.mjs +177 -0
  63. package/src/source/baseline.mjs +446 -0
  64. package/src/source/postgresql_access.mjs +480 -0
  65. package/src/targets/postgresql.mjs +808 -0
  66. package/{scripts/operations/database/manage_rehearsal_database.mjs → src/targets/supabase.mjs} +66 -20
  67. package/{scripts/lib/environment/local_supabase.mjs → src/targets/supabase_environment.mjs} +60 -28
  68. package/src/targets/target.mjs +66 -0
  69. package/scripts/lib/rehearsal/configuration.mjs +0 -559
  70. package/scripts/operations/rehearsal/rehearsal_cli.mjs +0 -565
  71. /package/{scripts/lib/rehearsal → src/runtime}/migration_history.mjs +0 -0
  72. /package/{scripts/lib/rehearsal → src/runtime}/service_environment.mjs +0 -0
@@ -1,36 +1,114 @@
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
+ An ordinary npm application install creates this file in the application root when the
4
+ root can be identified safely:
5
+
6
+ ```bash
7
+ npm install --save-dev @rehearsal-db/core@beta
8
+ ```
9
+
10
+ The install hook detects the database type, project name, migration folder,
11
+ package-manager commands, and free local ports. It also creates the dedicated local
12
+ runtime config and appends the two Rehearsal local-artifact entries to `.gitignore`.
13
+ Existing configs and existing ignore content are never rewritten.
14
+
15
+ When lifecycle scripts are disabled or the application root is not provable, run
16
+ `npx rehearsal` inside the application. The guide provides the same setup with a preview
17
+ and confirmation. Automatic root generation is tested with npm. pnpm and Yarn users
18
+ should use this guided fallback because their lifecycle and workspace layouts vary.
19
+
20
+ Review lines marked `CHECK`, especially the application proof command. Optional settings
21
+ are present as commented examples, and secrets never belong in this file. Rehearsal will
22
+ not overwrite an existing config.
23
+
24
+ Use this page when changing the generated file. The schema is strict: misspelled fields,
25
+ unknown fields, and unsupported versions are errors. The `.mjs` extension works in both
26
+ CommonJS and ESM projects.
5
27
 
6
28
  ```ts
29
+ // @ts-check
7
30
  import { defineRehearsalConfig } from "@rehearsal-db/core";
8
31
 
9
32
  export default defineRehearsalConfig({
33
+ // Configuration format. Rehearsal will explain if an upgrade is ever needed.
10
34
  schemaVersion: 1,
35
+ // Stable local name used in Rehearsal labels and reports.
11
36
  project: { name: "example-app" },
37
+
38
+ // Project files Rehearsal reads. Every path stays inside this repository.
12
39
  supabase: {
13
40
  workdir: ".",
14
41
  migrationDirectory: "supabase/migrations",
15
42
  rehearsalConfig: "infrastructure/rehearsal/supabase/config.toml",
16
43
  runtimeWorkdir: ".rehearsal/runtime",
44
+
45
+ // Optional; configure both keys together.
46
+ // serviceEnvironmentFile: ".env.rehearsal-service.local",
47
+ // serviceEnvironmentVariables: ["LOCAL_IDP_CLIENT_ID", "LOCAL_IDP_SECRET"],
17
48
  },
18
49
  baseline: {
19
50
  artifactDirectory: ".rehearsal",
20
51
  sanitizationPolicy: "infrastructure/rehearsal/sanitization-policy.json",
21
52
  },
53
+ // Optional, separately approved production-shaped preparation.
54
+ // preparation: {
55
+ // sourcePolicy: "infrastructure/rehearsal/source-access-policy.json",
56
+ // privacyKey: ".rehearsal/secrets/privacy.key",
57
+ // batchRows: 500,
58
+ // maximumRows: 1000000,
59
+ // maximumBytes: 2147483648,
60
+ // diskHeadroomBytes: 67108864,
61
+ // },
62
+ // runtimePolicy: "infrastructure/rehearsal/runtime-policy.json",
63
+ // Optional copied-account association. The JSON stores reviewed matcher hashes only;
64
+ // raw emails/subjects and provider credentials stay in ignored environment files.
65
+ // identityPolicy: "infrastructure/rehearsal/identity-policy.json",
66
+ containerRuntime: {
67
+ autoStartColima: true,
68
+ },
69
+ cleanup: {
70
+ retainBaselineGenerations: 2,
71
+ },
72
+ // Optional. Each dependent database uses another complete Rehearsal config.
73
+ // dependentTargets: [
74
+ // {
75
+ // name: "publication-api",
76
+ // configPath: "rehearsal.publication.config.mjs",
77
+ // prepareCommand: "npm run rehearsal:prepare-publication",
78
+ // },
79
+ // ],
22
80
  application: {
81
+ // CHECK: replace these when the detected package scripts are not correct.
23
82
  startCommand: "npm run dev:rehearsal",
24
83
  proofCommand: "npm run test:rehearsal",
84
+ environmentFile: ".rehearsal/runtime.env",
85
+ // environmentVariables: { DATABASE_URL: "primary:DATABASE_URL" },
86
+ readiness: {
87
+ url: "http://localhost:5175/health",
88
+ expectedStatus: 200,
89
+ timeoutSeconds: 30,
90
+ },
91
+ // Add at least one real positive and one negative before enabling.
92
+ // httpProofs: [],
25
93
  },
26
94
  runtime: {
95
+ target: "supabase",
27
96
  applicationUrl: "http://localhost:5175",
28
97
  projectId: "example-app-rehearsal",
29
98
  apiPort: 58321,
30
99
  databasePort: 58322,
31
100
  studioPort: 58323,
32
101
  },
33
- safety: { hostedAccess: "disabled", outboundNetwork: "deny" },
102
+ safety: {
103
+ allowedHosts: ["127.0.0.1", "::1", "localhost"],
104
+ blockedEnvironmentVariables: [
105
+ "SUPABASE_ACCESS_TOKEN",
106
+ "SUPABASE_DB_PASSWORD",
107
+ "SUPABASE_PROJECT_ID",
108
+ ],
109
+ hostedAccess: "disabled",
110
+ outboundNetwork: "deny",
111
+ },
34
112
  });
35
113
  ```
36
114
 
@@ -40,6 +118,135 @@ All paths resolve inside the consuming project. The artifact directory must be n
40
118
  `.rehearsal`; this is an intentional deletion guard. `runtimeWorkdir` must be its
41
119
  `runtime` child, and the generated application environment file must remain inside it.
42
120
 
121
+ Rehearsal never overwrites this config. To start over, move the existing file somewhere
122
+ safe, run setup again, and compare the two files before deleting either one.
123
+
124
+ After upgrading, run `npx rehearsal init` to print the current release's generated
125
+ template beside the path of your existing config. This comparison is read-only; adding a
126
+ new optional key remains your decision. `npx rehearsal init --write` still refuses to
127
+ replace an existing config.
128
+
129
+ ### Workspaces and custom paths
130
+
131
+ For an npm workspace, automatic creation proceeds only when exactly one application
132
+ package already declares `@rehearsal-db/core` in the manifest or lockfile visible to the
133
+ install hook. npm can save a new `--workspace` dependency after that hook runs, so a
134
+ first workspace install may safely skip creation. If several applications declare it,
135
+ Rehearsal also refuses to choose. Run `npx rehearsal` inside each intended application.
136
+ Global installs, package caches, temporary `npx` installs, and Rehearsal's own source
137
+ checkout never receive project files.
138
+
139
+ Supported existing config paths—including
140
+ `infrastructure/rehearsal/rehearsal.config.mjs`—are preserved, and a second root config
141
+ is not created. Use `--config=<project-relative-path>` for other explicit paths when
142
+ running commands.
143
+
144
+ `preparation.privacyKey` must stay inside `.rehearsal`; it is ignored and owner-readable
145
+ only. Source, runtime, and identity policy files are declarations that may be reviewed in
146
+ source control. They must never contain passwords, tokens, production URLs, raw owner
147
+ identifiers, SQL, or executable code.
148
+
149
+ ## Optional source preparation
150
+
151
+ `preparation` enables the separate `source` and `baseline refresh` commands. It does not
152
+ change ordinary `run`, `reset`, `migrate`, or `verify` behavior.
153
+
154
+ - `sourcePolicy` declares the hashed target identity, temporary roles, exact export
155
+ columns, public/approved-owner row scope, migration ledger, and optional Storage scope.
156
+ - `privacyKey` stores the local keyed-pseudonym secret.
157
+ - `batchRows`, `maximumRows`, and `maximumBytes` bound extraction.
158
+ - `diskHeadroomBytes` prevents activation when the copy cannot be built safely.
159
+
160
+ See [Production source](production-source.md) for complete examples and the exact
161
+ approval sequence.
162
+
163
+ `runtimePolicy` replaces common restore adapters with reviewed schemas, allowlisted
164
+ extensions, managed triggers, local-only singleton rows, and structural expectations.
165
+ `identityPolicy` declares a hashed verified-email or provider-subject matcher, copied
166
+ placeholder, safe signup defaults, required role/reference transfers, Storage path
167
+ rewrites, and token checks. Provider credentials stay in the local Supabase runtime
168
+ environment; association values stay in named environment variables and only their
169
+ SHA-256 receipts are tracked. See
170
+ [Runtime and identity policies](runtime-policies.md).
171
+
172
+ ## Container runtime and cleanup
173
+
174
+ ```ts
175
+ containerRuntime: {
176
+ autoStartColima: true,
177
+ },
178
+ cleanup: {
179
+ retainBaselineGenerations: 2,
180
+ },
181
+ ```
182
+
183
+ Rehearsal uses whichever Docker-compatible engine already answers `docker info`. If none
184
+ is running and `autoStartColima` is `true`, Rehearsal may run `colima start`. It respects
185
+ the user's Colima CPU, memory, and disk settings and never changes them. Set the field to
186
+ `false` when you prefer to start Docker or Colima yourself.
187
+
188
+ `retainBaselineGenerations` controls how many immutable baseline generations survive an
189
+ approved `rehearsal refresh` or `rehearsal cleanup`; it must be at least 1. Refresh shows
190
+ the exact old generations before confirmation and never removes the active baseline
191
+ before its replacement is verified. Runtime deletion outside refresh and shared-image
192
+ inspection remain explicit command choices. See [CLI commands](commands.md).
193
+
194
+ ## Dependent databases
195
+
196
+ Use `dependentTargets` when one local application needs another database, such as a
197
+ publication or read-model database:
198
+
199
+ ```ts
200
+ dependentTargets: [
201
+ {
202
+ name: "publication-api",
203
+ configPath: "rehearsal.publication.config.mjs",
204
+ prepareCommand: "npm run rehearsal:prepare-publication",
205
+ },
206
+ ],
207
+ ```
208
+
209
+ The referenced file is an ordinary complete Rehearsal config. Give it its own runtime
210
+ project ID, ports, application environment file, and artifact folder ending in
211
+ `.rehearsal`, for example `infrastructure/rehearsal/publication/.rehearsal`. Create and
212
+ review its baseline separately:
213
+
214
+ The easiest starting point is to copy the generated primary config, then change the
215
+ project name, migration folder, artifact folder, environment file, runtime project ID,
216
+ ports, and proof command. Keep the same fail-closed safety settings. Omit
217
+ `prepareCommand` when the dependent baseline is already ready to test. Rehearsal never
218
+ copies rows between databases automatically. A dependent Supabase target also needs its
219
+ own local `rehearsalConfig` file with matching dedicated ports. Preparation must be safe
220
+ to rerun because `run`, `reset`, and `migrate` each invoke it after the databases are
221
+ ready.
222
+
223
+ ```bash
224
+ npx rehearsal baseline create \
225
+ --config=rehearsal.publication.config.mjs \
226
+ --records=path/to/publication-data.ndjson \
227
+ --ledger=path/to/publication-ledger.json
228
+ ```
229
+
230
+ The primary `doctor`, `explain`, `candidates`, lifecycle, and cleanup commands then cover
231
+ the whole stack. Rehearsal restores and migrates the primary target first, followed by
232
+ dependents in the listed order. For `run`, `reset`, and `migrate`, it next runs each
233
+ `prepareCommand`. On `run`, it executes each dependent config's
234
+ `application.proofCommand` before the primary proof. `stop` and `discard` run in reverse
235
+ order. Cleanup verifies every target's exact preview before removing any selected
236
+ resource.
237
+
238
+ Legacy preparation commands receive paths—not credentials—in environment variables:
239
+ `REHEARSAL_PRIMARY_ENV_FILE` and
240
+ `REHEARSAL_DEPENDENT_<UPPERCASE_NAME>_ENV_FILE`. New integrations should prefer an
241
+ already prepared dependent baseline or the package's declarative source/privacy
242
+ workflow. `prepareCommand` remains compatible for existing projects but is ordinary
243
+ project code and must be reviewed. Nested dependencies are rejected.
244
+
245
+ The dependent proof must include at least one known successful lookup and appropriate
246
+ negative controls, such as unauthorized, malformed, withheld, or missing records. A
247
+ response that merely avoids a server error does not prove that eligible data was
248
+ published or can be found.
249
+
43
250
  ## Supabase service environment
44
251
 
45
252
  Some local identity providers need a client ID and secret. Configure both fields or
@@ -56,9 +263,12 @@ terminate at local Auth. They do not grant hosted database access.
56
263
 
57
264
  ## Safety fields
58
265
 
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.
266
+ Version 1 accepts loopback runtime URLs only. `hostedAccess` can only be `disabled`, and
267
+ `outboundNetwork` can only be `deny`. Common hosted Supabase and PostgreSQL credentials
268
+ are quarantined from child processes. These fields are fail-closed configuration rules,
269
+ not a host firewall: trusted project proof commands and runtime adapters remain ordinary
270
+ local code and must be reviewed. There is no force flag to weaken the configuration
271
+ rules.
62
272
 
63
273
  ## Ports and project identity
64
274
 
@@ -66,17 +276,80 @@ Use unique, non-privileged ports that do not overlap. `projectId` accepts lowerc
66
276
  letters, numbers, and hyphens. It labels the local Docker resources so cleanup targets
67
277
  only this project.
68
278
 
69
- ## Application proof
279
+ ## Database runtime
280
+
281
+ `runtime.target` selects the isolated database driver. It is optional in existing
282
+ configurations and currently defaults to `"supabase"`, so upgrading does not change an
283
+ existing project's behavior. Unknown targets are rejected before any runtime action.
284
+
285
+ For ordinary PostgreSQL, use `postgresql` instead of `supabase`:
286
+
287
+ ```ts
288
+ postgresql: {
289
+ migrationDirectory: "database/migrations",
290
+ runtimeWorkdir: ".rehearsal/runtime",
291
+ image: "postgres:17-alpine",
292
+ database: "postgres",
293
+ user: "postgres",
294
+ },
295
+ runtime: {
296
+ target: "postgresql",
297
+ applicationUrl: "http://localhost:5175",
298
+ projectId: "example-app-rehearsal",
299
+ databasePort: 58322,
300
+ },
301
+ ```
302
+
303
+ The image must be an official versioned Alpine PostgreSQL image and must already exist
304
+ locally. Rehearsal runs it with `--pull=never`, publishes it only on `127.0.0.1`, and
305
+ creates a fresh random runtime password in owner-readable ignored files. It manages only
306
+ the exactly named container and volume carrying the matching project label.
307
+ Plain PostgreSQL does not restore Supabase Storage assets or synthesize Supabase Auth
308
+ users.
309
+
310
+ Declarative runtime policies are preferred for supported schema prerequisites and
311
+ checks. Existing project-owned adapters remain compatible but do not replace the
312
+ database driver.
313
+
314
+ ## Application proof and hands-on sessions
315
+
316
+ `startCommand` is the ordinary application command. When `readiness` is present,
317
+ `rehearsal run` launches it with a minimal environment, waits for the exact local status,
318
+ runs proofs, and stops only that child process group. `environmentVariables` explicitly
319
+ maps generated runtime values such as `primary:DATABASE_URL`; undeclared inherited
320
+ hosted secrets are not passed through.
321
+
322
+ Your application framework may still load `.env` files from the project directory on
323
+ its own. Rehearsal cannot intercept that file loading. If a local proof could otherwise
324
+ pick up a hosted URL, token, CAPTCHA key, or similar value, set an explicit safe local
325
+ value in the configured `startCommand` or the framework's test-mode configuration.
326
+ Environment filtering is a process boundary, not an operating-system or file-access
327
+ firewall.
328
+
329
+ Supabase targets write validated loopback-only `DATABASE_URL`, `PGHOST`, `PGPORT`,
330
+ `PGDATABASE`, `PGUSER`, and `PGPASSWORD` values into the ignored runtime environment.
331
+ Package-owned identity commands use that same local connection; an adapter is not
332
+ required to provide it.
333
+
334
+ `proofCommand` remains an ordinary project test command. Optional `httpProofs` add
335
+ package-owned checks and must include real positive and negative expectations. A 200,
336
+ 404, 401, empty result, or non-5xx response is not a positive unless it matches the
337
+ declared status and body assertion.
338
+
339
+ After a successful rehearsal, `rehearsal open` uses the same `startCommand`, readiness
340
+ check, and environment mappings for a hands-on session. It starts and verifies every
341
+ configured database target but does not reset them. The app remains available until
342
+ `Ctrl+C` or `Ctrl+Z`; Rehearsal then stops only its application process group. Database
343
+ and Storage changes remain for the next `open`, `verify`, or `start` command.
70
344
 
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.
345
+ `application.readiness` is required for `open`. Point it at a route that returns the
346
+ configured status only when the local app is ready. Keep the URL on a loopback host.
74
347
 
75
348
  ## Runtime adapters
76
349
 
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).
350
+ Existing adapters remain compatible, but new projects should first use `runtimePolicy`,
351
+ `identityPolicy`, environment mappings, and HTTP proofs. Use an adapter only for a shape
352
+ the documented declarations explicitly reject. See [adapters](adapters.md).
80
353
 
81
354
  ## Advanced library entry points
82
355
 
@@ -88,7 +361,9 @@ may use these explicit subpaths:
88
361
  - `@rehearsal-db/core/schema`
89
362
  - `@rehearsal-db/core/diagnostics`
90
363
  - `@rehearsal-db/core/process-environment`
364
+ - `@rehearsal-db/core/privacy`
91
365
  - `@rehearsal-db/core/service-environment`
366
+ - `@rehearsal-db/core/source-access`
92
367
 
93
368
  These advanced entry points are ESM JavaScript APIs in the first beta. The root
94
369
  configuration and sanitization API has TypeScript declarations; the advanced subpaths do