@rehearsal-db/core 0.1.0-beta.10 → 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.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,32 @@ a Changelog, and versions will follow Semantic Versioning after the package exis
5
5
 
6
6
  ## Unreleased
7
7
 
8
+ ## [0.1.0-beta.11] - 2026-10-03
9
+
10
+ ### Added
11
+
12
+ - Privacy policy version 2 now supports hashed approved-owner bindings, conditional
13
+ approved/other-owner transformations, bounded JSON arrays, nested recipes, and
14
+ explicitly optional object fields without consumer sanitizer callbacks.
15
+ - Local npm installs now create a validated, commented project-root
16
+ `rehearsal.config.mjs`, dedicated local runtime configuration, and additive safe ignore
17
+ entries when exactly one consumer application can be proven. Guided setup remains the
18
+ tested recovery path when lifecycle scripts are disabled or a workspace is ambiguous.
19
+ - Copied-account association accepts explicit verified-email provider allowlists and
20
+ hashed provider-subject matchers for supported Supabase identities. Google, GitHub,
21
+ and email sign-in now share one review-and-confirm claim workflow.
22
+
23
+ ### Changed
24
+
25
+ - Setup is idempotent, supported custom config paths are preserved, `.gitignore` updates
26
+ use an exclusive lock and atomic replacement, and `rehearsal init` shows the current
27
+ release template without replacing an existing config.
28
+
29
+ ### Fixed
30
+
31
+ - Identity plan JSON no longer serializes the raw approved email or provider subject;
32
+ only the environment-variable name and reviewed SHA-256 receipt leave the process.
33
+
8
34
  ## [0.1.0-beta.10] - 2026-10-03
9
35
 
10
36
  ### Added
@@ -288,7 +314,8 @@ a Changelog, and versions will follow Semantic Versioning after the package exis
288
314
  publication uses short-lived trusted OIDC, and every release tag must already exist on
289
315
  protected `main`.
290
316
 
291
- [Unreleased]: https://github.com/Ddupasquier/rehearsal-db/compare/v0.1.0-beta.10...HEAD
317
+ [Unreleased]: https://github.com/Ddupasquier/rehearsal-db/compare/v0.1.0-beta.11...HEAD
318
+ [0.1.0-beta.11]: https://github.com/Ddupasquier/rehearsal-db/compare/v0.1.0-beta.10...v0.1.0-beta.11
292
319
  [0.1.0-beta.10]: https://github.com/Ddupasquier/rehearsal-db/compare/v0.1.0-beta.9...v0.1.0-beta.10
293
320
  [0.1.0-beta.9]: https://github.com/Ddupasquier/rehearsal-db/compare/v0.1.0-beta.8...v0.1.0-beta.9
294
321
  [0.1.0-beta.8]: https://github.com/Ddupasquier/rehearsal-db/compare/v0.1.0-beta.7...v0.1.0-beta.8
package/COMPATIBILITY.md CHANGED
@@ -21,6 +21,15 @@ 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
+ The npm install hook may create project scaffolding only when it proves one application
25
+ root. Ordinary npm application installs are covered. A workspace is automatic only when
26
+ one declaring consumer is already visible in its manifest or lockfile; npm can save a
27
+ new `--workspace` declaration after dependency hooks run, so a first workspace install
28
+ may use the guided fallback. pnpm and Yarn install layouts are not yet an
29
+ automatic-generation contract. Run `npx rehearsal` from the application directory for
30
+ all skipped cases. Global, cache, temporary `npx`, and ambiguous multi-application
31
+ workspace installs do not receive files.
32
+
24
33
  The PostgreSQL target covers timestamped SQL migrations running in a dedicated local
25
34
  `postgres` Docker image. Runtime commands reject hosted connection strings and existing
26
35
  unmanaged servers. The separately opted-in PostgreSQL preparation boundary may use a
package/README.md CHANGED
@@ -37,11 +37,15 @@ npm install --save-dev @rehearsal-db/core@beta
37
37
  npx rehearsal
38
38
  ```
39
39
 
40
- The first run detects your project and offers to create a commented
41
- `rehearsal.config.mjs` with the project name, migration paths, commands, ports, and safe
42
- defaults already filled in. Choose **Set the stage**, select Supabase or PostgreSQL,
43
- review the preview, and confirm the files it will create. Existing files are never
44
- overwritten.
40
+ For an ordinary npm application install, Rehearsal safely creates a commented
41
+ `rehearsal.config.mjs` in the project root, adds only its local-artifact entries to
42
+ `.gitignore`, and prepares the isolated local runtime configuration. It detects the
43
+ project name, database target, migration paths, commands, and free ports. Review lines
44
+ marked `CHECK`, then open the guide. Existing files are never overwritten.
45
+
46
+ If install scripts are disabled or the workspace root is ambiguous, installation makes
47
+ no guess. Run `npx rehearsal` inside the application and choose **Set the stage** for the
48
+ same previewed setup.
45
49
 
46
50
  For PostgreSQL, download the reviewed local image once before running the guide:
47
51
 
@@ -64,7 +68,8 @@ source-owner approval; see [Standalone workflow](docs/standalone-workflow.md).
64
68
  ## The normal workflow
65
69
 
66
70
  1. Run `npx rehearsal`.
67
- 2. Let the guide create the local-only configuration.
71
+ 2. Review the generated local-only configuration, or let the guide create it when the
72
+ install hook safely skipped it.
68
73
  3. Review the sanitization policy and create the baseline.
69
74
  4. Review the exact candidate migration list.
70
75
  5. Run the rehearsal and your application proof.
@@ -119,7 +124,7 @@ See [COMPATIBILITY.md](COMPATIBILITY.md) for the exact support contract.
119
124
 
120
125
  Start here:
121
126
 
122
- - [Documentation map](docs/README.md) — find the right guide quickly
127
+ - [Documentation home](docs/index.md) — choose the shortest path for your goal
123
128
  - [Getting started](docs/getting-started.md) — set up your own project
124
129
  - [Safe hands-on tutorial](docs/tutorial.md) — try the full flow in a disposable project
125
130
  - [Troubleshooting](docs/troubleshooting.md) — fix common setup problems
@@ -166,3 +171,9 @@ npm run test:fixture
166
171
 
167
172
  The fixture commands install the packed package into clean synthetic projects. They do
168
173
  not connect to hosted services. See [CONTRIBUTING.md](CONTRIBUTING.md) for the full rules.
174
+
175
+ Preview the styled documentation site locally with:
176
+
177
+ ```bash
178
+ npm run docs:preview
179
+ ```
package/docs/README.md CHANGED
@@ -1,29 +1,38 @@
1
- # Documentation map
1
+ # Rehearsal documentation
2
+
3
+ Welcome. You do not need to read this documentation from top to bottom. Choose what you
4
+ want to accomplish and follow that path.
2
5
 
3
6
  ## Start here
4
7
 
5
- - [Getting started](getting-started.md)
6
- - [Hands-on tutorial](tutorial.md)
7
- - [Troubleshooting](troubleshooting.md)
8
+ | Your goal | Best next page |
9
+ | ----------------------------------- | ------------------------------------- |
10
+ | Add Rehearsal to a project | [Getting started](getting-started.md) |
11
+ | Try it in a disposable project | [Hands-on tutorial](tutorial.md) |
12
+ | Fix a setup or runtime problem | [Troubleshooting](troubleshooting.md) |
13
+ | Browse the friendlier web-docs home | [Documentation home](index.md) |
8
14
 
9
- ## Understand the safety model
15
+ ## Work safely
10
16
 
11
- - [Baselines](baselines.md)
12
- - [Sanitization](sanitization.md)
13
- - [Production source boundary](production-source.md)
14
- - [Security model](security-model.md)
17
+ - [Baselines](baselines.md) — the verified starting copy
18
+ - [Sanitization](sanitization.md) — what may enter that copy
19
+ - [Production-shaped preparation](production-source.md) — the optional source boundary
20
+ - [Security model](security-model.md) — the independent safety barriers
21
+ - [Standalone workflow](standalone-workflow.md) — the complete declarative contract
15
22
 
16
- ## Configure Rehearsal
23
+ ## Look something up
17
24
 
25
+ - [CLI commands](commands.md)
18
26
  - [Configuration](configuration.md)
19
- - [Commands](commands.md)
20
- - [Runtime policies](runtime-policies.md)
27
+ - [Runtime and identity policies](runtime-policies.md)
21
28
  - [Database adapters](adapters.md)
22
- - [Standalone PostgreSQL workflow](standalone-workflow.md)
29
+ - [Glossary](glossary.md)
23
30
 
24
- ## Maintain the project
31
+ ## Follow the project
25
32
 
33
+ - [Roadmap](roadmap.md)
26
34
  - [Repository architecture](architecture.md)
27
35
  - [Release process](releasing.md)
28
- - [Roadmap](roadmap.md)
29
- - [Glossary](glossary.md)
36
+
37
+ To preview the styled documentation locally, run `npm run docs:preview`, then open the
38
+ address it prints.
package/docs/commands.md CHANGED
@@ -23,7 +23,7 @@ bare `npx rehearsal` prints help instead of waiting for input.
23
23
  | `npx rehearsal setup --target=supabase` | Preview Supabase setup files. |
24
24
  | `npx rehearsal setup --target=postgresql` | Preview PostgreSQL setup files. |
25
25
  | Add `--write` to either setup command | Create the previewed files without overwriting. |
26
- | `npx rehearsal init` | Preview only `rehearsal.config.mjs`. |
26
+ | `npx rehearsal init` | Preview the current config template without writing. |
27
27
  | `npx rehearsal init --write` | Create only `rehearsal.config.mjs`. |
28
28
  | `npx rehearsal baseline prepare --records=<path> --ledger=<path>` | Preview a sanitization-policy draft. |
29
29
  | Add `--write` to `baseline prepare` | Write the draft for human review. |
@@ -32,6 +32,11 @@ bare `npx rehearsal` prints help instead of waiting for input.
32
32
  Add `--assets=<manifest.json>` to `baseline create` only for approved local Supabase
33
33
  Storage files. `baseline create` and `baseline prepare` are local-only.
34
34
 
35
+ `setup --write` is idempotent: supported existing config files and completed runtime
36
+ files remain unchanged, while missing safe ignore entries may be appended. On upgrades,
37
+ `init` prints the installed release's template for comparison; `init --write` never
38
+ replaces an existing config.
39
+
35
40
  ## Optional source preparation
36
41
 
37
42
  These commands are separate from ordinary rehearsals. Configure `preparation` only after
@@ -67,7 +72,7 @@ In short: `refresh` gets a new source copy; `reset` restores the copy you alread
67
72
 
68
73
  ## Local identity association
69
74
 
70
- For a reviewed Google identity, use this sequence:
75
+ For a reviewed Google, GitHub, or email identity, use this sequence:
71
76
 
72
77
  1. Run a successful rehearsal, then start the persistent app:
73
78
 
@@ -75,9 +80,10 @@ For a reviewed Google identity, use this sequence:
75
80
  npx rehearsal open
76
81
  ```
77
82
 
78
- 2. Open the printed local URL and complete the normal Google sign-in. Press `Ctrl+C`
83
+ 2. Open the printed local URL and complete the normal provider sign-in. Press `Ctrl+C`
79
84
  after the callback returns. This closes only the app; the databases and Storage stay
80
- running with their current data.
85
+ running with their current data. Provider setup and credentials belong to the local
86
+ Supabase runtime, not the identity policy.
81
87
 
82
88
  3. Preview and confirm the reviewed association:
83
89
 
@@ -1,15 +1,21 @@
1
1
  # Configuration reference
2
2
 
3
- Most users should let the guide create this file:
3
+ An ordinary npm application install creates this file in the application root when the
4
+ root can be identified safely:
4
5
 
5
6
  ```bash
6
- npx rehearsal
7
+ npm install --save-dev @rehearsal-db/core@beta
7
8
  ```
8
9
 
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.
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.
13
19
 
14
20
  Review lines marked `CHECK`, especially the application proof command. Optional settings
15
21
  are present as commented examples, and secrets never belong in this file. Rehearsal will
@@ -54,7 +60,8 @@ export default defineRehearsalConfig({
54
60
  // diskHeadroomBytes: 67108864,
55
61
  // },
56
62
  // runtimePolicy: "infrastructure/rehearsal/runtime-policy.json",
57
- // Optional signup defaults, role/reference transfer, Storage paths, and token checks.
63
+ // Optional copied-account association. The JSON stores reviewed matcher hashes only;
64
+ // raw emails/subjects and provider credentials stay in ignored environment files.
58
65
  // identityPolicy: "infrastructure/rehearsal/identity-policy.json",
59
66
  containerRuntime: {
60
67
  autoStartColima: true,
@@ -114,6 +121,26 @@ All paths resolve inside the consuming project. The artifact directory must be n
114
121
  Rehearsal never overwrites this config. To start over, move the existing file somewhere
115
122
  safe, run setup again, and compare the two files before deleting either one.
116
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
+
117
144
  `preparation.privacyKey` must stay inside `.rehearsal`; it is ignored and owner-readable
118
145
  only. Source, runtime, and identity policy files are declarations that may be reviewed in
119
146
  source control. They must never contain passwords, tokens, production URLs, raw owner
@@ -135,8 +162,11 @@ approval sequence.
135
162
 
136
163
  `runtimePolicy` replaces common restore adapters with reviewed schemas, allowlisted
137
164
  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
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
140
170
  [Runtime and identity policies](runtime-policies.md).
141
171
 
142
172
  ## Container runtime and cleanup
@@ -38,15 +38,20 @@ npm install --save-dev @rehearsal-db/core@beta
38
38
  npx rehearsal
39
39
  ```
40
40
 
41
- Choose **Set the stage**, then choose Supabase or PostgreSQL. Rehearsal previews every file
42
- before asking to create it. It will not replace an existing file.
43
-
44
- Review the generated `rehearsal.config.mjs`, especially:
41
+ With npm, a normal application install creates `rehearsal.config.mjs`, the dedicated
42
+ local runtime config, and the required `.gitignore` entries when Rehearsal can prove the
43
+ application root. It never replaces an existing file. Review the generated config,
44
+ especially:
45
45
 
46
46
  - the migration directory;
47
47
  - the application start and proof commands;
48
48
  - the local ports.
49
49
 
50
+ If lifecycle scripts were disabled, a global/cache install was used, or a workspace has
51
+ more than one possible application, no project files are created automatically. Run
52
+ `npx rehearsal` inside the intended application, choose **Set the stage**, select
53
+ Supabase or PostgreSQL, and approve the same safe setup preview.
54
+
50
55
  The proof command should check behavior changed by the migration. A test that only checks
51
56
  whether the home page loads is usually too weak.
52
57
 
@@ -161,6 +166,10 @@ npx rehearsal run --confirm-candidates=PASTE_DIGEST_HERE
161
166
  Replace `postgresql` with `supabase` when needed. See [CLI commands](commands.md) for the
162
167
  complete reference and [Troubleshooting](troubleshooting.md) when a check fails.
163
168
 
169
+ Running setup again is safe: existing configuration and runtime files are reported as
170
+ unchanged. Rehearsal only adds missing ignore entries. It never refreshes an existing
171
+ config during an upgrade.
172
+
164
173
  ## Files Rehearsal creates
165
174
 
166
175
  - `rehearsal.config.mjs` — reviewed project configuration
package/docs/index.md ADDED
@@ -0,0 +1,47 @@
1
+ # Rehearsal documentation
2
+
3
+ ## Pick the path that fits today
4
+
5
+ You do not need to read everything before your first rehearsal. Start with the outcome
6
+ you want, then follow the links when a term or safety check is new.
7
+
8
+ | I want to… | Go here |
9
+ | ------------------------------------- | ----------------------------------------------------------------- |
10
+ | Set up my own project | [Getting started](getting-started.md) |
11
+ | Try Rehearsal without touching my app | [Hands-on tutorial](tutorial.md) |
12
+ | Understand what makes a copy safe | [Baselines](baselines.md) and [Sanitization](sanitization.md) |
13
+ | Look up a command or setting | [CLI commands](commands.md) and [Configuration](configuration.md) |
14
+ | Fix something that did not work | [Troubleshooting](troubleshooting.md) |
15
+
16
+ ## The short version
17
+
18
+ Rehearsal restores an approved local baseline, applies only the migration files you
19
+ reviewed, and runs the application checks your project owns. The normal workflow stays
20
+ on your computer and does not deploy anything.
21
+
22
+ 1. **Prepare** a safe baseline.
23
+ 2. **Review** the exact candidate migrations.
24
+ 3. **Run** them in a disposable local database.
25
+ 4. **Prove** the application behavior that matters.
26
+ 5. **Open** the sandbox for hands-on testing.
27
+
28
+ ## Safety is part of the workflow
29
+
30
+ Rehearsal does not ask you to trust one giant switch. Baseline checksums, local-only
31
+ networking, exact confirmation digests, project-owned proofs, and narrowly owned cleanup
32
+ each protect a different boundary.
33
+
34
+ Start with synthetic data when you can. If a project needs a production-shaped copy,
35
+ read [Production-shaped preparation](production-source.md) before providing any source
36
+ access.
37
+
38
+ ## Still unsure where to begin?
39
+
40
+ Run the interactive guide from the project you want to test:
41
+
42
+ ```bash
43
+ npx rehearsal
44
+ ```
45
+
46
+ It reads the project state, explains the next safe step, and keeps the full command
47
+ reference available when you need it.
@@ -77,9 +77,12 @@ graph without an application callback patch:
77
77
  "identities": [
78
78
  {
79
79
  "name": "approved-owner",
80
- "provider": "google",
81
- "emailEnvironmentVariable": "REHEARSAL_APPROVED_OWNER_EMAIL",
82
- "approvedEmailSha256": "<sha256 of the lowercase approved email>",
80
+ "matcher": {
81
+ "type": "verified-email",
82
+ "providers": ["google"],
83
+ "emailEnvironmentVariable": "REHEARSAL_APPROVED_OWNER_EMAIL",
84
+ "approvedEmailSha256": "<sha256 of the lowercase approved email>"
85
+ },
83
86
  "placeholderUserId": "11111111-1111-4111-8111-111111111111",
84
87
  "references": [
85
88
  {
@@ -152,9 +155,18 @@ graph without an application callback patch:
152
155
  }
153
156
  ```
154
157
 
158
+ Authentication has three separate parts:
159
+
160
+ 1. The local Supabase configuration enables Google, GitHub, or email sign-in and reads
161
+ any provider credentials from the environment.
162
+ 2. The application completes the ordinary sign-in and receives a normal Supabase
163
+ session. Rehearsal does not intercept the callback.
164
+ 3. The identity policy matches that verified local identity and transfers only the
165
+ reviewed copied-account graph.
166
+
155
167
  The email stays in an environment variable; only its reviewed hash is committed. Run
156
- `rehearsal open`, complete the ordinary local Google sign-in, and stop the app with
157
- `Ctrl+C`. Then preview and confirm the association:
168
+ `rehearsal open`, complete the ordinary local sign-in, and stop the app with `Ctrl+C`.
169
+ Then preview and confirm the association:
158
170
 
159
171
  ```bash
160
172
  npx rehearsal identity plan --identity=approved-owner
@@ -166,6 +178,50 @@ Rehearsal requires exactly one verified matching local provider identity. Every
166
178
  `required` reference must exist after transfer. Declare application role tables as
167
179
  references; `claims` alone is not a replacement for a database-backed token hook.
168
180
 
181
+ ### Supported identity matchers
182
+
183
+ Rehearsal currently supports the Supabase provider values `email`, `google`, and
184
+ `github`. Other provider names fail closed until their Auth representation has package
185
+ coverage. Two matcher types are supported:
186
+
187
+ - `verified-email` accepts one or more supported providers. It lowercases the email from
188
+ the named environment variable and compares its SHA-256 receipt before querying Auth.
189
+ - `provider-subject` accepts one OAuth provider (`google` or `github`). It compares the
190
+ reviewed SHA-256 to Supabase's stable provider ID/subject without placing the raw
191
+ subject in the policy, baseline, command output, SQL parameters, or receipt.
192
+
193
+ Google by verified email:
194
+
195
+ ```json
196
+ "matcher": {
197
+ "type": "verified-email",
198
+ "providers": ["google"],
199
+ "emailEnvironmentVariable": "REHEARSAL_APPROVED_OWNER_EMAIL",
200
+ "approvedEmailSha256": "<sha256 of the lowercase email>"
201
+ }
202
+ ```
203
+
204
+ Supabase email/password or magic-link sign-in uses the same matcher with
205
+ `"providers": ["email"]`. An account intentionally allowed to use either ordinary
206
+ email or Google can declare `"providers": ["email", "google"]`; the claim still refuses
207
+ zero or multiple matching identities.
208
+
209
+ GitHub by stable provider subject:
210
+
211
+ ```json
212
+ "matcher": {
213
+ "type": "provider-subject",
214
+ "provider": "github",
215
+ "subjectEnvironmentVariable": "REHEARSAL_APPROVED_OWNER_SUBJECT",
216
+ "approvedSubjectSha256": "<sha256 of the exact GitHub subject>"
217
+ }
218
+ ```
219
+
220
+ Set the raw value only in the local shell or an ignored environment file. Existing
221
+ policies using the older top-level `provider`, `emailEnvironmentVariable`, and
222
+ `approvedEmailSha256` fields remain accepted as a single-provider verified-email
223
+ matcher. New policies should use the explicit `matcher` object.
224
+
169
225
  References use `"strategy": "transfer"` by default. Use `"preserve-audit"` only for
170
226
  immutable historical authorship, such as a completed review. Rehearsal leaves that row
171
227
  and its synthetic Auth actor unchanged, but still transfers the active profile, roles,
@@ -185,6 +241,10 @@ configured `tokenHook` must return the declared claim subset before commit. The
185
241
  refresh its session or sign in again because Rehearsal cannot rewrite an issued JWT.
186
242
  Run `rehearsal open` again for that fresh-session check; runtime data is preserved.
187
243
 
244
+ After a claim, sign out and sign in again (or otherwise force a full token refresh) before
245
+ judging application roles. This preserves normal RLS, account blocks, role checks, and
246
+ MFA; identity association is not an authentication bypass.
247
+
188
248
  The transaction does not import production passwords, sessions, refresh tokens,
189
249
  cookies, MFA secrets, or provider credentials. Local MFA and authorization rules remain
190
250
  real.
@@ -40,9 +40,110 @@ Two policy versions exist:
40
40
  Rehearsal can sanitize without project callbacks.
41
41
 
42
42
  Version 2 supports keyed UUID, email, text, and integer pseudonyms; explicit constant
43
- replacement; bounded date shifting; and exhaustively classified JSON objects. Unknown
44
- tables, columns, nested keys, formats, recipes, or missing fields fail closed. It never
45
- evaluates JavaScript or SQL from the policy.
43
+ replacement; bounded date shifting; approved-owner conditionals; exhaustively classified
44
+ JSON objects; and bounded JSON arrays. Unknown tables, columns, nested keys, formats,
45
+ recipes, or missing required fields fail closed. It never evaluates JavaScript or SQL
46
+ from the policy.
47
+
48
+ ## Approved-owner values
49
+
50
+ Keep the raw approved owner outside the policy and baseline. The policy stores only its
51
+ environment-variable name and SHA-256 receipt:
52
+
53
+ ```json
54
+ {
55
+ "bindings": {
56
+ "approved-owner": {
57
+ "environmentVariable": "REHEARSAL_APPROVED_OWNER_ID",
58
+ "approvedValueSha256": "<lowercase sha256 of the exact owner value>"
59
+ }
60
+ },
61
+ "tables": [
62
+ {
63
+ "name": "profiles",
64
+ "sourceRows": "STREAM AND SANITIZE",
65
+ "ownerBinding": { "binding": "approved-owner", "column": "user_id" },
66
+ "columns": [
67
+ {
68
+ "name": "user_id",
69
+ "action": "PSEUDONYMIZE",
70
+ "recipe": { "format": "uuid", "namespace": "account-id" },
71
+ "generated": "NEVER",
72
+ "identity": "YES",
73
+ "foreignKey": null
74
+ },
75
+ {
76
+ "name": "display_name",
77
+ "action": "DERIVE",
78
+ "recipe": {
79
+ "kind": "approved-owner",
80
+ "approved": { "action": "KEEP" },
81
+ "otherwise": {
82
+ "action": "REPLACE",
83
+ "recipe": { "kind": "constant", "value": "Synthetic account" }
84
+ }
85
+ },
86
+ "generated": "NEVER",
87
+ "identity": "NO",
88
+ "foreignKey": null
89
+ }
90
+ ]
91
+ }
92
+ ]
93
+ }
94
+ ```
95
+
96
+ Generate the receipt without putting the owner value in shell history:
97
+
98
+ ```sh
99
+ node -e 'const {createHash}=require("node:crypto"); process.stdout.write(createHash("sha256").update(process.env.REHEARSAL_APPROVED_OWNER_ID).digest("hex")+"\n")'
100
+ ```
101
+
102
+ Every conditional table names its owner column. Missing bindings, hash mismatches,
103
+ missing owner columns, null/unsupported owner values, and conditionals without an owner
104
+ binding are refused. The owner column must be marked `identity: "YES"` and use
105
+ `PSEUDONYMIZE`, preventing a conditional policy from retaining raw account IDs. Other
106
+ owners take the declared `otherwise` path; every other identity-bearing field still
107
+ needs its own pseudonymization declaration. Supply the binding only to the local
108
+ server-side Rehearsal process; do not put it in the policy, baseline, or tracked files.
109
+
110
+ ## Structured JSON
111
+
112
+ `json-object` fields are required by default. Set `"required": false` on an explicitly
113
+ optional field. Unknown keys remain errors. `json-array` declares one item recipe and a
114
+ required `maximumItems`. Both recipes accept `maximumDepth`, `maximumBytes`, and
115
+ `allowNull`; defaults are 8 levels, 65,536 bytes, and no null container. Bounds are
116
+ checked before producing the transformed structure. Nested objects and arrays repeat
117
+ the same declarations, and every nested identity uses an explicit pseudonym recipe.
118
+
119
+ ```json
120
+ {
121
+ "action": "DERIVE",
122
+ "recipe": {
123
+ "kind": "json-array",
124
+ "maximumItems": 25,
125
+ "maximumDepth": 4,
126
+ "maximumBytes": 8192,
127
+ "items": {
128
+ "action": "DERIVE",
129
+ "recipe": {
130
+ "kind": "json-object",
131
+ "fields": {
132
+ "actor_id": {
133
+ "action": "PSEUDONYMIZE",
134
+ "recipe": { "format": "uuid", "namespace": "account-id" }
135
+ },
136
+ "note": {
137
+ "action": "REPLACE",
138
+ "required": false,
139
+ "recipe": { "kind": "constant", "value": "Synthetic note" }
140
+ }
141
+ }
142
+ }
143
+ }
144
+ }
145
+ }
146
+ ```
46
147
 
47
148
  The package still exports `validateSanitizationCoverage` and
48
149
  `applySanitizationAction` for existing version 1 preparation tools:
@@ -28,6 +28,8 @@ name:
28
28
  - whether rows are approved public data or belong to one explicitly approved
29
29
  owner;
30
30
  - privacy actions and bounded transformation recipes;
31
+ - hashed server-side owner bindings and explicit approved/other-owner branches;
32
+ - bounded nested JSON objects and arrays with required/optional fields;
31
33
  - licensed or consented Storage buckets and prefixes;
32
34
  - schema and extension prerequisites;
33
35
  - local identities and reference locations;
@@ -20,6 +20,20 @@ npx rehearsal --help
20
20
 
21
21
  Do not use `sudo` or require a global install.
22
22
 
23
+ ## Installation did not create `rehearsal.config.mjs`
24
+
25
+ Rehearsal intentionally skips automatic creation when install scripts are disabled, the
26
+ install is global or temporary, or more than one workspace application could own the
27
+ config. From the intended application directory, run:
28
+
29
+ ```bash
30
+ npx rehearsal
31
+ ```
32
+
33
+ Choose **Set the stage** and approve the preview. For pnpm and Yarn, use this guided path;
34
+ automatic root generation is currently tested with npm. An existing supported config is
35
+ kept in place, including `infrastructure/rehearsal/rehearsal.config.mjs`.
36
+
23
37
  ## Setup says Node.js 24 is required
24
38
 
25
39
  Rehearsal intentionally supports one maintained Node.js major in its first beta. Switch
@@ -136,6 +150,17 @@ Confirm the provider is enabled in the dedicated local Supabase config, the allo
136
150
  service environment file exists with owner-only permissions, and the provider callback
137
151
  is the local Auth callback. Do not paste provider secrets into config or terminal output.
138
152
 
153
+ If `identity plan` refuses the matcher, read the message literally:
154
+
155
+ - **Provider or matcher type is unsupported:** use only the combinations documented in
156
+ [Runtime and identity policies](runtime-policies.md).
157
+ - **No verified identity matches:** complete an ordinary local sign-in, confirm the
158
+ correct environment value is present, then run the plan again.
159
+ - **More than one identity matches:** narrow the provider allowlist or use a hashed
160
+ provider-subject matcher. Rehearsal will not guess between accounts.
161
+ - **Provider subject conflicts:** the local Auth identity disagrees with itself; remove
162
+ and recreate that disposable local sign-in instead of forcing a claim.
163
+
139
164
  ## Runtime changes disappeared
140
165
 
141
166
  `reset` deliberately restores the immutable baseline. `stop` should preserve Docker