@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
package/docs/releasing.md CHANGED
@@ -5,48 +5,27 @@ environment. The workflow builds and hashes the candidate before the environment
5
5
  approval gate, then publishes those exact bytes with npm provenance. A local working
6
6
  tree is never the release source.
7
7
 
8
- The initial publishable `0.1.0-beta.1` release branch is the first change allowed to set
9
- `"private": false`. Publication still requires the exact protected-main tag, prerelease
10
- flag, artifact checks, and protected `npm` environment gate described below.
11
-
12
8
  `0.1.0-beta.0` was prepared under the unavailable `@rehearsal` npm scope and was never
13
9
  published. `0.1.0-beta.1` supersedes that candidate under `@rehearsal-db/core` without
14
10
  rewriting the earlier Git tag or GitHub prerelease.
15
11
 
16
- ## One-time first-package bootstrap
12
+ ## Trusted publication boundary
17
13
 
18
- npm trusted publishing and staged publishing are package-level settings, so they cannot
19
- be configured until `@rehearsal-db/core` exists in the registry. The first public version has
20
- a deliberately narrower bootstrap path:
14
+ `@rehearsal-db/core` trusts only the GitHub Actions publisher for repository
15
+ `Ddupasquier/rehearsal-db`, workflow `publish.yml`, and environment `npm`. The publish job
16
+ requests a short-lived GitHub OIDC identity after the protected environment approval;
17
+ it does not read an npm token or retain a registry credential. Package publishing access
18
+ requires 2FA and disallows bypass tokens.
21
19
 
22
- 1. The npm owner enables 2FA and creates or confirms the public `@rehearsal-db` organization
23
- scope. Do not send a password, OTP, recovery code, or access token to another person.
24
- 2. After the reviewed release change reaches protected `main`, the owner creates the
25
- exact `v0.1.0-beta.1` GitHub release and marks it as a prerelease. The prepare job runs without npm credentials,
26
- packs the tag, and uploads its versioned tarball plus SHA-1 and SHA-256 metadata. The
27
- publish job waits at the protected environment and cannot run yet.
28
- 3. The owner downloads or inspects that prepared artifact, confirms its version and
29
- checksum, and explicitly authorizes those exact bytes.
30
- 4. Only then, the owner creates a short-lived granular npm token with read/write access
31
- limited to the `@rehearsal-db` scope and **Bypass 2FA** enabled. npm requires that bypass
32
- for a non-interactive first publish; the environment approval remains the human
33
- release gate. Store the token only as the `NPM_TOKEN` secret in the protected GitHub
34
- `npm` environment.
35
- 5. The owner approves the waiting `npm` deployment. GitHub Actions publishes the exact
36
- uploaded tarball with provenance. The workflow
37
- refuses to use the bootstrap secret for any version other than `0.1.0-beta.1`.
38
- 6. Immediately after the registry verification passes, the owner deletes the GitHub
39
- environment secret and revokes the temporary npm token.
40
- 7. From the new package's npm settings, configure the trusted GitHub Actions publisher
41
- for repository `Ddupasquier/rehearsal-db`, workflow `publish.yml`, and environment
42
- `npm`. Allow direct `npm publish` for this workflow because the protected GitHub
43
- environment supplies the human gate. A later switch to npm staged publication must
44
- change and prove the workflow before narrowing the trusted publisher permission.
45
- 8. Set package publishing access to require 2FA and disallow traditional tokens.
20
+ The initial `0.1.0-beta.1` package creation required a one-time bootstrap credential
21
+ because npm cannot configure a trusted publisher before a package exists. That
22
+ credential is not part of the maintained release architecture: it was deleted from the
23
+ GitHub environment after publication, must remain revoked at npm, and cannot be consumed
24
+ by this workflow.
46
25
 
47
- This bootstrap token is a one-release compromise imposed by npm's package-creation
48
- boundary. It is never committed, printed, copied into a ticket, or retained for later
49
- versions.
26
+ Direct `npm publish` is allowed only for this trusted publisher because the protected
27
+ GitHub `npm` environment supplies the human gate. A later switch to npm staged
28
+ publication must change and prove the workflow before narrowing that permission.
50
29
 
51
30
  ## Every release candidate
52
31
 
@@ -58,7 +37,7 @@ versions.
58
37
  onboarding. Correct and retest the first confusing, missing, or wrong instruction.
59
38
  5. Change `private` to `false` only in the reviewed release change.
60
39
  6. Record the exact tarball filename, SHA-1, SHA-256, allowlisted files, unpacked size,
61
- executable, and zero-runtime-dependency result.
40
+ executable, declared runtime dependency inventory, and dependency audit result.
62
41
  7. Obtain explicit publication authorization for that exact version and artifact.
63
42
  8. Merge the approved release commit through protected `main` and create the exact
64
43
  `v<package-version>` tag and GitHub release.
@@ -66,12 +45,23 @@ versions.
66
45
  the approved version and checksum.
67
46
  10. Verify public visibility, ownership, provenance, registry SHA-1, README rendering,
68
47
  exact-version clean installation, CLI execution, signatures, and the unrelated
69
- installed Docker fixture.
48
+ installed Docker fixture. Allow up to six minutes for a first package to propagate
49
+ through the public registry before classifying a missing packument as a release
50
+ failure.
70
51
  11. Replace consuming projects' temporary Git/archive references only on their own
71
52
  protected integration branches and rerun their complete verification.
72
53
 
73
54
  The workflow publishes prereleases under the `beta` dist-tag and refuses a stable
74
- version. A stable tag requires a later contract, compatibility, and release decision.
55
+ version. While Rehearsal has no stable release, the workflow also moves `latest` to the
56
+ same reviewed beta. This keeps the npm package page and the ordinary
57
+ `npm install @rehearsal-db/core` command current. When Rehearsal gains a stable release,
58
+ `latest` must switch to the stable line while `beta` continues to identify prereleases.
59
+
60
+ The trusted publisher allows `npm dist-tag` only so this workflow can maintain those two
61
+ tags without a stored npm token. A manual workflow run from `main` can repair the tags
62
+ for the exact prerelease version currently recorded in `package.json`; it cannot publish
63
+ a package or select a different version. The protected `npm` environment still supplies
64
+ the human approval gate.
75
65
 
76
66
  Creating the repository, passing CI, extracting the engine, merging a release branch,
77
67
  or creating a tag does not authorize npm publication. Publication requires explicit
@@ -0,0 +1,41 @@
1
+ # Next steps
2
+
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.
6
+
7
+ ## Standalone workflow
8
+
9
+ The implementation sequence is dependency-driven:
10
+
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.
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.
21
+
22
+ Track the full breakdown in
23
+ [standalone roadmap issue #38](https://github.com/Ddupasquier/rehearsal-db/issues/38).
24
+
25
+ ## Acceptance still required
26
+
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.
36
+
37
+ ## Later database targets
38
+
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.
@@ -0,0 +1,193 @@
1
+ # Runtime and identity policies
2
+
3
+ These optional JSON files replace common project-owned Rehearsal adapters. They contain
4
+ declarations only: unknown fields, SQL, JavaScript, and unsupported extensions fail.
5
+
6
+ ## Runtime policy
7
+
8
+ Point `runtimePolicy` in `rehearsal.config.mjs` to a reviewed file:
9
+
10
+ ```json
11
+ {
12
+ "policyVersion": 1,
13
+ "prerequisites": {
14
+ "schemas": ["extensions"],
15
+ "extensions": [{ "name": "pgcrypto", "schema": "extensions" }]
16
+ },
17
+ "triggers": [
18
+ {
19
+ "name": "profile_after_auth_insert",
20
+ "table": { "schema": "auth", "name": "users" },
21
+ "timing": "after",
22
+ "events": ["insert"],
23
+ "function": { "schema": "public", "name": "handle_new_user" }
24
+ }
25
+ ],
26
+ "localRows": [
27
+ {
28
+ "table": { "schema": "public", "name": "runtime_settings" },
29
+ "keyColumns": ["name"],
30
+ "values": { "name": "scheduler_enabled", "value": false }
31
+ },
32
+ {
33
+ "table": { "schema": "public", "name": "app_role_assignments" },
34
+ "keyColumns": ["user_id"],
35
+ "values": {
36
+ "user_id": "11111111-1111-4111-8111-111111111111",
37
+ "role": "owner"
38
+ },
39
+ "identityAssociation": {
40
+ "identity": "approved-owner",
41
+ "column": "user_id"
42
+ }
43
+ }
44
+ ],
45
+ "expectations": [
46
+ {
47
+ "table": { "schema": "public", "name": "profiles" },
48
+ "rowLevelSecurity": true,
49
+ "columns": [{ "name": "id", "generated": false, "identity": false }],
50
+ "foreignKeys": [],
51
+ "policies": []
52
+ }
53
+ ]
54
+ }
55
+ ```
56
+
57
+ Restore order is fixed: Rehearsal creates named schemas and allowlisted extensions
58
+ before dependent schema objects, adds declared triggers after their tables and functions
59
+ exist, then inserts local-only rows after baseline data. Application schema remains in
60
+ immutable migrations or the verified schema snapshot. Verification checks extensions,
61
+ triggers, local-only rows, columns, generated/identity behavior, foreign keys, named RLS
62
+ policies, RLS state, and unvalidated constraints.
63
+
64
+ Use `identityAssociation` when a local seed is intentionally transferred by a named
65
+ identity policy. Verification accepts the configured placeholder before association and
66
+ the exact recorded local identity afterward. Rehearsal stores that mapping only in its
67
+ local internal schema; it does not duplicate the old role or weaken the row check.
68
+
69
+ ## Identity policy
70
+
71
+ The identity policy links one verified local Supabase identity to a copied pseudonymous
72
+ graph without an application callback patch:
73
+
74
+ ```json
75
+ {
76
+ "identityVersion": 1,
77
+ "identities": [
78
+ {
79
+ "name": "approved-owner",
80
+ "provider": "google",
81
+ "emailEnvironmentVariable": "REHEARSAL_APPROVED_OWNER_EMAIL",
82
+ "approvedEmailSha256": "<sha256 of the lowercase approved email>",
83
+ "placeholderUserId": "11111111-1111-4111-8111-111111111111",
84
+ "references": [
85
+ {
86
+ "schema": "public",
87
+ "table": "profiles",
88
+ "column": "user_id",
89
+ "required": true
90
+ },
91
+ {
92
+ "schema": "public",
93
+ "table": "app_role_assignments",
94
+ "column": "user_id",
95
+ "required": true
96
+ },
97
+ {
98
+ "schema": "public",
99
+ "table": "food_compatibility_feedback",
100
+ "column": "reviewed_by",
101
+ "required": true,
102
+ "strategy": "preserve-audit"
103
+ }
104
+ ],
105
+ "jsonReferences": [
106
+ {
107
+ "schema": "public",
108
+ "table": "events",
109
+ "column": "payload",
110
+ "path": ["actor_id"]
111
+ }
112
+ ],
113
+ "signupDefaults": [
114
+ {
115
+ "table": { "schema": "public", "table": "profiles" },
116
+ "identityColumn": "user_id",
117
+ "ignoredColumns": ["created_at", "updated_at"],
118
+ "values": {
119
+ "display_name": {
120
+ "kind": "pattern",
121
+ "pattern": "^User[0-9]{14}$"
122
+ },
123
+ "avatar_path": null
124
+ }
125
+ }
126
+ ],
127
+ "pathReferences": [
128
+ {
129
+ "schema": "public",
130
+ "table": "profiles",
131
+ "column": "avatar_path",
132
+ "valueType": "text"
133
+ }
134
+ ],
135
+ "assets": [
136
+ {
137
+ "bucket": "avatars",
138
+ "prefix": "11111111-1111-4111-8111-111111111111/",
139
+ "rewritePath": true
140
+ }
141
+ ],
142
+ "claims": { "rehearsal_owner": true },
143
+ "tokenHook": {
144
+ "function": {
145
+ "schema": "public",
146
+ "name": "custom_access_token_hook"
147
+ },
148
+ "expectedClaims": { "app_role": "developer" }
149
+ }
150
+ }
151
+ ]
152
+ }
153
+ ```
154
+
155
+ 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:
158
+
159
+ ```bash
160
+ npx rehearsal identity plan --identity=approved-owner
161
+ npx rehearsal identity claim --identity=approved-owner \
162
+ --confirm-identity=<full-sha256>
163
+ ```
164
+
165
+ Rehearsal requires exactly one verified matching local provider identity. Every
166
+ `required` reference must exist after transfer. Declare application role tables as
167
+ references; `claims` alone is not a replacement for a database-backed token hook.
168
+
169
+ References use `"strategy": "transfer"` by default. Use `"preserve-audit"` only for
170
+ immutable historical authorship, such as a completed review. Rehearsal leaves that row
171
+ and its synthetic Auth actor unchanged, but still transfers the active profile, roles,
172
+ and other declared data. Undeclared references still stop the claim.
173
+
174
+ `signupDefaults` resolves a copied-profile collision only when the local row's complete
175
+ non-ignored shape matches. List every remaining column. Use ignored columns only for
176
+ server-managed values such as timestamps. An edited value, extra column, ambiguous row,
177
+ or unrelated local application data rolls back the entire claim.
178
+
179
+ `rewritePath` copies approved Storage objects through the local Supabase Storage API,
180
+ verifies the destination bytes, updates the declared database paths, and then removes
181
+ the old objects. A database failure removes the new copies and leaves the originals
182
+ usable. Restored objects may begin with either the placeholder owner or no owner;
183
+ another owner is refused. `pathReferences` updates matching text or JSONB pointers. A
184
+ configured `tokenHook` must return the declared claim subset before commit. The browser must then
185
+ refresh its session or sign in again because Rehearsal cannot rewrite an issued JWT.
186
+ Run `rehearsal open` again for that fresh-session check; runtime data is preserved.
187
+
188
+ The transaction does not import production passwords, sessions, refresh tokens,
189
+ cookies, MFA secrets, or provider credentials. Local MFA and authorization rules remain
190
+ real.
191
+
192
+ A synthetic test can prove the plumbing and refusal controls. Claim that Google account
193
+ selection or callback behavior works only after directly observing that real flow.
@@ -1,7 +1,7 @@
1
1
  # Sanitization policy
2
2
 
3
- Rehearsal deliberately does not decide what your application may copy. The consuming
4
- project owns an exhaustive, reviewable policy for its export surface.
3
+ Rehearsal never decides what your application may copy. The project owner reviews an
4
+ exhaustive policy; the package validates and executes the supported recipes.
5
5
 
6
6
  Every exported field should receive one action:
7
7
 
@@ -13,8 +13,39 @@ Every exported field should receive one action:
13
13
 
14
14
  Fail if a new column is unclassified. Do not default unknown fields to `KEEP`.
15
15
 
16
- The package exports `validateSanitizationCoverage` and
17
- `applySanitizationAction` as generic primitives:
16
+ For runtime restore, each included column must also classify whether it is generated,
17
+ whether it is an identity column, and its foreign-key target or explicit absence. Run
18
+ `rehearsal baseline prepare` to create a shape-only draft from synthetic NDJSON. The
19
+ draft uses `REVIEW REQUIRED` placeholders and cannot be activated until they are
20
+ replaced and the `draft` marker is removed.
21
+
22
+ Tables default to the `public` schema. Add `"schema": "app_api"` beside `name`
23
+ for another schema. Schema plus table is the identity, so two schemas may safely contain
24
+ tables with the same name.
25
+
26
+ In an interactive terminal, the guided **Review the script** action works table by table.
27
+ For larger tables, a human can explicitly apply safe defaults (`REPLACE`, `NEVER`
28
+ generated, `NO` identity, and no foreign key), then review only exceptions. Likely
29
+ structural columns such as `id`, `*_id`, and timestamps start selected as exceptions.
30
+ Users can instead review every column individually. Retaining a value is explicitly
31
+ labeled as sensitive, every saved field remains classified, and no preset is silently
32
+ applied. The reviewer validates the completed policy and refuses to overwrite a draft
33
+ changed during the session.
34
+
35
+ Two policy versions exist:
36
+
37
+ - Version 1 describes data that a project has already made safe. It remains supported
38
+ for synthetic/local inputs and existing baselines.
39
+ - Version 2 is required by `baseline refresh`. It adds bounded declarative recipes so
40
+ Rehearsal can sanitize without project callbacks.
41
+
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.
46
+
47
+ The package still exports `validateSanitizationCoverage` and
48
+ `applySanitizationAction` for existing version 1 preparation tools:
18
49
 
19
50
  ```ts
20
51
  import {
@@ -35,15 +66,15 @@ const safeValue = applySanitizationAction({
35
66
  ```
36
67
 
37
68
  Coverage validation requires a one-to-one table and column match: missing and unknown
38
- entries both fail. The package supplies the operation contract; the project supplies
39
- the schema inventory, keys, replacements, and derivation logic.
69
+ entries both fail. New standalone preparation should use the version 2 engine described
70
+ in [Production source](production-source.md).
40
71
 
41
72
  ## Stable identity
42
73
 
43
74
  Use keyed, deterministic pseudonyms when relationships must survive across tables.
44
- Keep the key outside source control and outside the final baseline. The same source ID
75
+ Keep the key under `.rehearsal`, outside source control and the final baseline. The same source ID
45
76
  should map consistently within a generation, while the original value cannot be
46
- recovered from the artifact.
77
+ recovered from the artifact. The manifest records only the key fingerprint.
47
78
 
48
79
  ## High-risk fields
49
80
 
@@ -67,3 +98,7 @@ Before activation, verify:
67
98
 
68
99
  Completeness is not correctness. Human review of the policy and export boundary remains
69
100
  mandatory before any real source is introduced.
101
+
102
+ The exact reviewed policy bytes are checksum-bound to the active baseline. Planning,
103
+ candidate inspection, and runtime restore refuse to continue if that file later changes;
104
+ build a new reviewed baseline instead of editing the active policy in place.
@@ -5,24 +5,39 @@ misconfiguration fail closed before a state-changing operation.
5
5
 
6
6
  ## Trust boundaries
7
7
 
8
- The engine trusts the reviewed package code, strict project configuration, a verified
9
- active baseline, exact migration bytes, and explicitly project-owned proof code. It does
10
- not trust ambient environment variables, hosted project state, unknown config fields,
11
- changed migration history, incomplete artifacts, or an unverified runtime.
8
+ The engine trusts reviewed package code, strict declarations, a verified active baseline,
9
+ and exact migration bytes. It does not trust ambient environment variables, hosted
10
+ project state, unknown fields, changed history, incomplete artifacts, or an unverified
11
+ runtime.
12
12
 
13
13
  ## Independent barriers
14
14
 
15
15
  - loopback-only application and service URLs;
16
- - a dedicated unlinked Supabase workdir and project ID;
16
+ - a dedicated unlinked Supabase workdir, or an exactly named and labeled PostgreSQL
17
+ container and volume;
17
18
  - exact non-overlapping local ports;
18
19
  - a clean child-process environment that omits hosted credentials;
19
20
  - immutable baseline files and checksums;
20
21
  - exact migration-prefix and candidate digests;
21
22
  - local runtime labels used for bounded stop/removal;
23
+ - PostgreSQL images must already exist locally and are never pulled implicitly;
24
+ - plain PostgreSQL receives a fresh random password per disposable runtime, retained
25
+ only in owner-readable ignored runtime files;
22
26
  - successful receipts written only after verification.
27
+ - separate exact-digest approval for source setup, source retirement, and identity claim;
28
+ - short-lived source readers limited to reviewed views/columns and deny checks;
29
+ - bounded read-only extraction with no raw dump or row-value logging;
30
+ - exhaustive privacy policy version 2 with an owner-only local pseudonym key;
31
+ - application children receive only explicit local mappings and stay in an owned process
32
+ group.
33
+ - only one state-changing Rehearsal command may own a project at a time; stale locks are
34
+ recovered after their process exits;
35
+ - a state-changing command fingerprints its installed Rehearsal package and refuses to
36
+ continue if that installation changes while the command is running.
23
37
 
24
- No single environment variable or config edit should redirect the tool to production.
25
- Version 1 provides no hosted execution mode.
38
+ No single environment variable or config edit can redirect runtime commands to
39
+ production. Optional source preparation is a separate boundary and never provides a
40
+ hosted execution mode.
26
41
 
27
42
  ## Identity providers
28
43
 
@@ -31,10 +46,20 @@ credential names are read from an ignored owner-only file, and the callback must
31
46
  local Auth. The local account may represent a sanitized production identity, but its
32
47
  session and writes remain local.
33
48
 
49
+ Account association is one local transaction. Rehearsal removes a signup-created row
50
+ only when its complete declared default shape still matches, refuses unrelated local
51
+ application data, verifies required role references and an optional token hook, and can
52
+ copy, byte-check, and retire only declared placeholder-owned Storage paths. Immutable
53
+ audit references may explicitly retain their synthetic historical actor. Rehearsal also
54
+ refuses to rewrite application paths when copied records refer to files that are absent
55
+ from local Storage. Existing browser JWTs still require an ordinary refresh or new
56
+ sign-in.
57
+
34
58
  ## Remaining responsibilities
35
59
 
36
60
  Rehearsal cannot prove that retained data is lawful, a sanitization rule is ethically
37
- appropriate, a migration has the intended business meaning, or a project adapter is
38
- safe. Repository owners must review those decisions and protect artifacts.
61
+ appropriate, a migration has the intended business meaning, or a real provider flow was
62
+ observed. Repository owners must review those decisions and protect artifacts. The
63
+ configuration barriers are not an operating-system firewall.
39
64
 
40
65
  Report vulnerabilities using the private process in the root security policy.
@@ -0,0 +1,107 @@
1
+ # Standalone workflow contract
2
+
3
+ Rehearsal's normal commands remain local-only. `run`, `start`, `reset`,
4
+ `migrate`, `verify`, and `cleanup` never receive source credentials and never
5
+ connect to a hosted database.
6
+
7
+ The optional preparation workflow is a separate security boundary. It has
8
+ three deliberately separate phases:
9
+
10
+ 1. `source plan` reads declarations and produces a redacted, exact plan.
11
+ 2. `source apply` requires the plan digest and source-owner credentials from a
12
+ named environment variable. It creates only the declared, time-limited
13
+ reader and export surface.
14
+ 3. `refresh` uses that reader in a read-only repeatable-read transaction, builds
15
+ privately, activates only after verification, resets the local runtime, and applies
16
+ reviewed retention. `baseline refresh` is the lower-level baseline-only form.
17
+
18
+ `source retire` has its own preview and digest. It removes only the exact
19
+ reader and export objects Rehearsal recorded. It never searches for similarly
20
+ named roles or removes unrelated grants.
21
+
22
+ ## What belongs in declarations
23
+
24
+ Projects declare application meaning; Rehearsal executes it. Declarations may
25
+ name:
26
+
27
+ - approved source relations and columns;
28
+ - whether rows are approved public data or belong to one explicitly approved
29
+ owner;
30
+ - privacy actions and bounded transformation recipes;
31
+ - licensed or consented Storage buckets and prefixes;
32
+ - schema and extension prerequisites;
33
+ - local identities and reference locations;
34
+ - ordinary application commands and observable proof expectations.
35
+
36
+ Declarations cannot contain JavaScript callbacks, SQL fragments, passwords,
37
+ tokens, production URLs, or automatic consent decisions. Unknown fields,
38
+ tables, columns, recipes, JSON keys, and target identities fail closed.
39
+
40
+ ## Credential separation
41
+
42
+ Provisioning, extraction, asset, provider, and local-runtime credentials are
43
+ separate. A declaration contains only the name of an environment variable or
44
+ owner-only secret file. Rehearsal never puts credential values in command-line
45
+ arguments, reports, baselines, receipts, or a launched application.
46
+
47
+ The current workflow creates and verifies its own temporary PostgreSQL reader. An
48
+ externally provisioned reader is not yet accepted because Rehearsal cannot currently
49
+ prove that reader's complete scope and retirement behavior.
50
+
51
+ ## Snapshot and privacy guarantees
52
+
53
+ Database schema, migration evidence, and selected rows are read in one
54
+ read-only repeatable-read PostgreSQL transaction. Rehearsal rechecks the source
55
+ identity and migration evidence before commit. Rows stream in bounded batches;
56
+ record bodies never appear in progress or error output.
57
+
58
+ Storage objects do not share the database transaction guarantee. Their inventory records
59
+ size and version metadata; transfer requires that version, verifies the exact byte count,
60
+ and records a SHA-256 in the immutable baseline. Transfer refuses an object that changes,
61
+ exceeds its declared limit, or falls outside an approved bucket and prefix.
62
+
63
+ Privacy policy version 2 is executable without project sanitizer code. It
64
+ supports exact keep, exclusion, keyed pseudonyms, constants, and a small set of
65
+ documented derivations. Policies classify every selected field and supported
66
+ nested JSON key. A new or unknown field blocks refresh until the policy is
67
+ reviewed again.
68
+
69
+ The pseudonym key is an owner-only local secret. It is not stored in the
70
+ baseline or source control. Receipts bind the policy bytes, schema shape,
71
+ source scope, migration evidence, and key fingerprint without storing the key
72
+ or source identifiers.
73
+
74
+ ## Restore, identities, and applications
75
+
76
+ Restore performs only supported declarative prerequisites. Application schema
77
+ changes remain immutable migration files; configuration is never an arbitrary
78
+ privileged-SQL escape hatch.
79
+
80
+ Local identities never reuse production sessions, refresh tokens, password
81
+ hashes, provider secrets, or MFA material. An approved provider association is
82
+ performed inside the local runtime and must match the reviewed receipt.
83
+
84
+ Rehearsal launches ordinary project commands with a minimal environment and
85
+ generated local connection files. It verifies every configured dependency
86
+ before launch, owns only the child process group it starts, and does not claim
87
+ to provide an operating-system firewall.
88
+
89
+ Proofs require explicit positives and negatives. A process starting, a non-5xx
90
+ response, an empty 200, a 401, or a 404 cannot satisfy a declared positive.
91
+ Reports distinguish engine readiness, dependency readiness, proof completion,
92
+ and provider behavior that was directly observed by a person.
93
+
94
+ ## Failure and upgrade behavior
95
+
96
+ - Failed, interrupted, changed-policy, low-disk, or drifted refreshes leave the
97
+ prior active baseline and any edited runtime untouched.
98
+ - Setup and upgrades preview exact file changes and never overwrite a reviewed
99
+ policy, config, baseline, or local edit silently.
100
+ - Reset, discard, and cleanup operate only on purpose-created Rehearsal
101
+ resources and retain their existing exact-preview protections.
102
+ - Rehearsal does not make legal, consent, licensing, backup, disaster-recovery,
103
+ universal-database, or OS-firewall guarantees.
104
+
105
+ The final acceptance gate uses the exact packed or published artifact in clean
106
+ Supabase and PostgreSQL consumers. Consumer integration code is removed only
107
+ after that replacement is proved and the removal is separately approved.