@rehearsal-db/core 0.1.0-beta.8 → 0.1.0-rc.1

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 (232) hide show
  1. package/CHANGELOG.md +364 -1
  2. package/COMPATIBILITY.md +30 -3
  3. package/README.md +69 -22
  4. package/dist/package.json +100 -0
  5. package/dist/scripts/install/create_root_config.d.mts +3 -0
  6. package/dist/scripts/install/create_root_config.mjs +13 -0
  7. package/dist/scripts/runtime/manage_database.d.mts +6 -0
  8. package/dist/scripts/runtime/manage_database.mjs +16 -0
  9. package/dist/src/application/interactive_task.d.mts +30 -0
  10. package/dist/src/application/interactive_task.mjs +83 -0
  11. package/dist/src/application/session.d.mts +97 -0
  12. package/dist/src/application/session.mjs +380 -0
  13. package/dist/src/baseline/artifact.d.mts +119 -0
  14. package/dist/src/baseline/artifact.mjs +522 -0
  15. package/dist/src/baseline/builder.d.mts +19 -0
  16. package/dist/src/baseline/builder.mjs +142 -0
  17. package/dist/src/baseline/input_discovery.d.mts +13 -0
  18. package/dist/src/baseline/input_discovery.mjs +149 -0
  19. package/dist/src/baseline/policy_review.d.mts +56 -0
  20. package/dist/src/baseline/policy_review.mjs +73 -0
  21. package/dist/src/baseline/preparation.d.mts +63 -0
  22. package/dist/src/baseline/preparation.mjs +295 -0
  23. package/dist/src/baseline/privacy_contract.d.mts +147 -0
  24. package/dist/src/baseline/privacy_contract.mjs +2 -0
  25. package/dist/src/baseline/privacy_dependency_graph.d.mts +7 -0
  26. package/dist/src/baseline/privacy_dependency_graph.mjs +110 -0
  27. package/dist/src/baseline/privacy_engine.d.mts +5 -0
  28. package/dist/src/baseline/privacy_engine.mjs +4 -0
  29. package/dist/src/baseline/privacy_key.d.mts +7 -0
  30. package/dist/src/baseline/privacy_key.mjs +42 -0
  31. package/dist/src/baseline/privacy_pipeline.d.mts +7 -0
  32. package/dist/src/baseline/privacy_pipeline.mjs +127 -0
  33. package/dist/src/baseline/privacy_policy.d.mts +6 -0
  34. package/dist/src/baseline/privacy_policy.mjs +237 -0
  35. package/dist/src/baseline/privacy_recipe_validation.d.mts +5 -0
  36. package/dist/src/baseline/privacy_recipe_validation.mjs +289 -0
  37. package/dist/src/baseline/privacy_rule_registry.d.mts +18 -0
  38. package/dist/src/baseline/privacy_rule_registry.mjs +143 -0
  39. package/dist/src/baseline/privacy_structured_json.d.mts +66 -0
  40. package/dist/src/baseline/privacy_structured_json.mjs +464 -0
  41. package/dist/src/baseline/privacy_transforms.d.mts +18 -0
  42. package/dist/src/baseline/privacy_transforms.mjs +142 -0
  43. package/dist/src/baseline/privacy_validation_shared.d.mts +31 -0
  44. package/dist/src/baseline/privacy_validation_shared.mjs +127 -0
  45. package/dist/src/baseline/sanitization_policy.d.mts +69 -0
  46. package/dist/src/baseline/sanitization_policy.mjs +227 -0
  47. package/dist/src/baseline/schema_snapshot.d.mts +19 -0
  48. package/dist/src/baseline/schema_snapshot.mjs +79 -0
  49. package/dist/src/cli/application_command_handlers.d.mts +8 -0
  50. package/dist/src/cli/application_command_handlers.mjs +52 -0
  51. package/dist/src/cli/arguments.d.mts +38 -0
  52. package/dist/src/cli/arguments.mjs +130 -0
  53. package/dist/src/cli/basic_command_handlers.d.mts +4 -0
  54. package/dist/src/cli/basic_command_handlers.mjs +57 -0
  55. package/dist/src/cli/cli_commands.d.mts +14 -0
  56. package/dist/src/cli/cli_commands.mjs +34 -0
  57. package/dist/src/cli/command_contract.d.mts +57 -0
  58. package/dist/src/cli/command_contract.mjs +39 -0
  59. package/dist/src/cli/command_output.d.mts +12 -0
  60. package/dist/src/cli/command_output.mjs +20 -0
  61. package/dist/src/cli/command_registry.d.mts +7 -0
  62. package/dist/src/cli/command_registry.mjs +14 -0
  63. package/dist/src/cli/guided.d.mts +53 -0
  64. package/dist/src/cli/guided.mjs +727 -0
  65. package/dist/src/cli/identity_command_handlers.d.mts +12 -0
  66. package/dist/src/cli/identity_command_handlers.mjs +239 -0
  67. package/dist/src/cli/identity_renderer.d.mts +8 -0
  68. package/dist/src/cli/identity_renderer.mjs +33 -0
  69. package/dist/src/cli/init_command.d.mts +21 -0
  70. package/dist/src/cli/init_command.mjs +90 -0
  71. package/dist/src/cli/inspection_command_handlers.d.mts +3 -0
  72. package/dist/src/cli/inspection_command_handlers.mjs +79 -0
  73. package/dist/src/cli/project_command_handlers.d.mts +11 -0
  74. package/dist/src/cli/project_command_handlers.mjs +92 -0
  75. package/dist/src/cli/project_commands.d.mts +283 -0
  76. package/dist/src/cli/project_commands.mjs +192 -0
  77. package/dist/src/cli/rehearsal.d.mts +7 -0
  78. package/dist/src/cli/rehearsal.mjs +190 -0
  79. package/dist/src/cli/renderers.d.mts +299 -0
  80. package/dist/src/cli/renderers.mjs +554 -0
  81. package/dist/src/cli/runtime_action_handlers.d.mts +12 -0
  82. package/dist/src/cli/runtime_action_handlers.mjs +201 -0
  83. package/dist/src/cli/runtime_commands.d.mts +294 -0
  84. package/dist/src/cli/runtime_commands.mjs +619 -0
  85. package/dist/src/cli/source_command_handlers.d.mts +8 -0
  86. package/dist/src/cli/source_command_handlers.mjs +62 -0
  87. package/dist/src/cli/source_commands.d.mts +436 -0
  88. package/dist/src/cli/source_commands.mjs +301 -0
  89. package/dist/src/cli/terminal.d.mts +59 -0
  90. package/dist/src/cli/terminal.mjs +230 -0
  91. package/dist/src/identity/claim.d.mts +5 -0
  92. package/dist/src/identity/claim.mjs +4 -0
  93. package/dist/src/identity/claim_contract.d.mts +135 -0
  94. package/dist/src/identity/claim_contract.mjs +6 -0
  95. package/dist/src/identity/claim_executor.d.mts +10 -0
  96. package/dist/src/identity/claim_executor.mjs +358 -0
  97. package/dist/src/identity/claim_identity_lookup.d.mts +23 -0
  98. package/dist/src/identity/claim_identity_lookup.mjs +134 -0
  99. package/dist/src/identity/claim_plan.d.mts +8 -0
  100. package/dist/src/identity/claim_plan.mjs +61 -0
  101. package/dist/src/identity/claim_policy.d.mts +3 -0
  102. package/dist/src/identity/claim_policy.mjs +377 -0
  103. package/dist/src/identity/claim_sql.d.mts +10 -0
  104. package/dist/src/identity/claim_sql.mjs +46 -0
  105. package/dist/src/identity/claim_verification.d.mts +13 -0
  106. package/dist/src/identity/claim_verification.mjs +35 -0
  107. package/dist/src/identity/connect.d.mts +30 -0
  108. package/dist/src/identity/connect.mjs +111 -0
  109. package/dist/src/identity/provider_configuration.d.mts +37 -0
  110. package/dist/src/identity/provider_configuration.mjs +132 -0
  111. package/dist/src/identity/storage.d.mts +21 -0
  112. package/dist/src/identity/storage.mjs +122 -0
  113. package/dist/src/index.d.mts +4 -0
  114. package/dist/src/index.mjs +3 -0
  115. package/dist/src/project/configuration.d.mts +13 -0
  116. package/dist/src/project/configuration.mjs +9 -0
  117. package/dist/src/project/configuration_contract.d.mts +125 -0
  118. package/dist/src/project/configuration_contract.mjs +27 -0
  119. package/dist/src/project/configuration_discovery.d.mts +7 -0
  120. package/dist/src/project/configuration_discovery.mjs +37 -0
  121. package/dist/src/project/configuration_normalization.d.mts +107 -0
  122. package/dist/src/project/configuration_normalization.mjs +302 -0
  123. package/dist/src/project/configuration_rendering.d.mts +14 -0
  124. package/dist/src/project/configuration_rendering.mjs +226 -0
  125. package/dist/src/project/configuration_resolution.d.mts +125 -0
  126. package/dist/src/project/configuration_resolution.mjs +81 -0
  127. package/dist/src/project/configuration_schema.d.mts +22 -0
  128. package/dist/src/project/configuration_schema.mjs +160 -0
  129. package/dist/src/project/configuration_validation.d.mts +22 -0
  130. package/dist/src/project/configuration_validation.mjs +136 -0
  131. package/dist/src/project/install_scaffold.d.mts +42 -0
  132. package/dist/src/project/install_scaffold.mjs +263 -0
  133. package/dist/src/project/project_detection.d.mts +14 -0
  134. package/dist/src/project/project_detection.mjs +47 -0
  135. package/dist/src/project/setup.d.mts +87 -0
  136. package/dist/src/project/setup.mjs +414 -0
  137. package/dist/src/project/support_report.d.mts +88 -0
  138. package/dist/src/project/support_report.mjs +83 -0
  139. package/dist/src/runtime/cleanup.d.mts +85 -0
  140. package/dist/src/runtime/cleanup.mjs +311 -0
  141. package/dist/src/runtime/lifecycle_engine.d.mts +63 -0
  142. package/dist/src/runtime/lifecycle_engine.mjs +114 -0
  143. package/dist/src/runtime/migration_history.d.mts +51 -0
  144. package/dist/src/runtime/migration_history.mjs +170 -0
  145. package/dist/src/runtime/plan.d.mts +134 -0
  146. package/dist/src/runtime/plan.mjs +637 -0
  147. package/dist/src/runtime/policy.d.mts +66 -0
  148. package/dist/src/runtime/policy.mjs +369 -0
  149. package/dist/src/runtime/restore.d.mts +22 -0
  150. package/dist/src/runtime/restore.mjs +276 -0
  151. package/dist/src/runtime/service_environment.d.mts +11 -0
  152. package/dist/src/runtime/service_environment.mjs +58 -0
  153. package/dist/src/runtime/topology.d.mts +51 -0
  154. package/dist/src/runtime/topology.mjs +128 -0
  155. package/dist/src/shared/diagnostics.d.mts +97 -0
  156. package/dist/src/shared/diagnostics.mjs +170 -0
  157. package/dist/src/shared/human_output.d.mts +2 -0
  158. package/{scripts/lib/rehearsal → dist/src/shared}/human_output.mjs +1 -3
  159. package/dist/src/shared/node_runtime.d.mts +14 -0
  160. package/dist/src/shared/node_runtime.mjs +25 -0
  161. package/dist/src/shared/operation_guard.d.mts +22 -0
  162. package/dist/src/shared/operation_guard.mjs +150 -0
  163. package/dist/src/shared/process_environment.d.mts +15 -0
  164. package/dist/src/shared/process_environment.mjs +50 -0
  165. package/dist/src/source/access.d.mts +165 -0
  166. package/dist/src/source/access.mjs +602 -0
  167. package/dist/src/source/asset_transfer.d.mts +27 -0
  168. package/dist/src/source/asset_transfer.mjs +202 -0
  169. package/dist/src/source/baseline.d.mts +66 -0
  170. package/dist/src/source/baseline.mjs +372 -0
  171. package/dist/src/source/external_reader.d.mts +42 -0
  172. package/dist/src/source/external_reader.mjs +278 -0
  173. package/dist/src/source/postgresql_access.d.mts +86 -0
  174. package/dist/src/source/postgresql_access.mjs +454 -0
  175. package/dist/src/source/privacy_paths.d.mts +10 -0
  176. package/dist/src/source/privacy_paths.mjs +27 -0
  177. package/dist/src/targets/driver.d.mts +2 -0
  178. package/dist/src/targets/driver.mjs +13 -0
  179. package/dist/src/targets/postgresql.d.mts +5 -0
  180. package/dist/src/targets/postgresql.mjs +620 -0
  181. package/dist/src/targets/supabase.d.mts +8 -0
  182. package/dist/src/targets/supabase.mjs +627 -0
  183. package/dist/src/targets/supabase_environment.d.mts +49 -0
  184. package/dist/src/targets/supabase_environment.mjs +162 -0
  185. package/dist/src/targets/target.d.mts +33 -0
  186. package/dist/src/targets/target.mjs +39 -0
  187. package/docs/README.md +40 -0
  188. package/docs/adapters.md +15 -6
  189. package/docs/architecture.md +183 -0
  190. package/docs/baselines.md +22 -1
  191. package/docs/commands.md +116 -16
  192. package/docs/configuration.md +314 -34
  193. package/docs/getting-started.md +77 -10
  194. package/docs/glossary.md +4 -0
  195. package/docs/index.md +48 -0
  196. package/docs/production-source.md +334 -33
  197. package/docs/releasing.md +24 -12
  198. package/docs/roadmap.md +40 -37
  199. package/docs/runtime-policies.md +264 -0
  200. package/docs/sanitization.md +592 -8
  201. package/docs/security-model.md +37 -8
  202. package/docs/stability.md +69 -0
  203. package/docs/standalone-workflow.md +130 -0
  204. package/docs/troubleshooting.md +88 -8
  205. package/docs/tutorial.md +7 -1
  206. package/docs/typescript.md +134 -0
  207. package/package.json +45 -27
  208. package/types/configuration.d.mts +5 -0
  209. package/scripts/lib/environment/local_supabase.mjs +0 -197
  210. package/scripts/lib/rehearsal/baseline_artifact.mjs +0 -565
  211. package/scripts/lib/rehearsal/baseline_builder.mjs +0 -160
  212. package/scripts/lib/rehearsal/baseline_preparation.mjs +0 -316
  213. package/scripts/lib/rehearsal/cleanup.mjs +0 -381
  214. package/scripts/lib/rehearsal/configuration.d.mts +0 -119
  215. package/scripts/lib/rehearsal/configuration.mjs +0 -847
  216. package/scripts/lib/rehearsal/diagnostics.mjs +0 -199
  217. package/scripts/lib/rehearsal/input_discovery.mjs +0 -155
  218. package/scripts/lib/rehearsal/migration_history.mjs +0 -220
  219. package/scripts/lib/rehearsal/plan.mjs +0 -685
  220. package/scripts/lib/rehearsal/policy_review.mjs +0 -92
  221. package/scripts/lib/rehearsal/process_environment.mjs +0 -64
  222. package/scripts/lib/rehearsal/runtime_restore.mjs +0 -314
  223. package/scripts/lib/rehearsal/sanitization_policy.mjs +0 -279
  224. package/scripts/lib/rehearsal/schema_snapshot.mjs +0 -113
  225. package/scripts/lib/rehearsal/service_environment.mjs +0 -82
  226. package/scripts/lib/rehearsal/setup.mjs +0 -379
  227. package/scripts/lib/rehearsal/support_report.mjs +0 -102
  228. package/scripts/lib/runtime/postgresql_runtime.mjs +0 -773
  229. package/scripts/lib/runtime/runtime_target.mjs +0 -66
  230. package/scripts/lib/runtime/supabase_runtime.mjs +0 -793
  231. package/scripts/operations/database/manage_rehearsal_database.mjs +0 -18
  232. package/scripts/operations/rehearsal/rehearsal_cli.mjs +0 -2169
@@ -0,0 +1,162 @@
1
+ /**
2
+ * Purpose: Start and inspect local-only Supabase workdirs without inheriting hosted
3
+ * credentials. Do not run directly; this module is reusable script infrastructure.
4
+ */
5
+ import { spawnSync } from "node:child_process";
6
+ import { createCleanProcessEnvironment, } from "../shared/process_environment.mjs";
7
+ export const parseSupabaseStatusEnvironment = (output) => {
8
+ const values = {};
9
+ for (const line of output.split("\n")) {
10
+ const match = line.match(/^([A-Z][A-Z0-9_]*)=(.*)$/u);
11
+ if (!match)
12
+ continue;
13
+ const key = match[1];
14
+ const rawValue = match[2];
15
+ if (key === undefined || rawValue === undefined)
16
+ continue;
17
+ let value = rawValue.trim();
18
+ if (value.startsWith('"') && value.endsWith('"')) {
19
+ const parsed = JSON.parse(value);
20
+ if (typeof parsed !== "string")
21
+ continue;
22
+ value = parsed;
23
+ }
24
+ values[key] = value;
25
+ }
26
+ return values;
27
+ };
28
+ export const parseLocalSupabaseEnvironment = (output) => {
29
+ const values = parseSupabaseStatusEnvironment(output);
30
+ const required = (label, value) => {
31
+ if (!value)
32
+ throw new Error(`Local Supabase status omitted its ${label}.`);
33
+ return value;
34
+ };
35
+ const apiUrl = required("API URL", values.API_URL);
36
+ const databaseUrl = required("database URL", values.DB_URL);
37
+ const publishableKey = required("publishable key", values.PUBLISHABLE_KEY ?? values.ANON_KEY);
38
+ const serviceRoleKey = required("service-role key", values.SERVICE_ROLE_KEY ?? values.SECRET_KEY);
39
+ const api = new URL(apiUrl);
40
+ const database = new URL(databaseUrl);
41
+ const loopbackHosts = ["127.0.0.1", "::1", "localhost"];
42
+ if (!loopbackHosts.includes(api.hostname) ||
43
+ !loopbackHosts.includes(database.hostname) ||
44
+ !["postgres:", "postgresql:"].includes(database.protocol)) {
45
+ throw new Error("Refusing to use a non-local Supabase status target.");
46
+ }
47
+ const databaseName = decodeURIComponent(database.pathname.replace(/^\//u, ""));
48
+ if (!database.port ||
49
+ !databaseName ||
50
+ !database.username ||
51
+ !database.password) {
52
+ throw new Error("Local Supabase status returned an incomplete database URL.");
53
+ }
54
+ return {
55
+ apiUrl,
56
+ databaseUrl,
57
+ publishableKey,
58
+ serviceRoleKey,
59
+ studioUrl: values.STUDIO_URL,
60
+ databaseHost: database.hostname,
61
+ databasePort: database.port,
62
+ databaseName,
63
+ databaseUser: decodeURIComponent(database.username),
64
+ databasePassword: decodeURIComponent(database.password),
65
+ };
66
+ };
67
+ export const runLocalCommand = (command, args, { capture = false, cwd = process.cwd(), input, environment = {}, maxBuffer = 16 * 1024 * 1024, } = {}) => {
68
+ const shouldPipe = capture || input !== undefined;
69
+ const result = spawnSync(command, args, {
70
+ cwd,
71
+ encoding: "utf8",
72
+ env: createCleanProcessEnvironment({ overrides: environment }),
73
+ input,
74
+ maxBuffer,
75
+ stdio: shouldPipe ? ["pipe", "pipe", "pipe"] : "inherit",
76
+ });
77
+ if (result.error)
78
+ throw result.error;
79
+ if (result.status !== 0) {
80
+ const detail = [result.stdout, result.stderr]
81
+ .filter(Boolean)
82
+ .join("\n")
83
+ .trim();
84
+ throw new Error(`${command} ${args.join(" ")} failed${detail ? `:\n${detail}` : "."}`);
85
+ }
86
+ return result.stdout ?? "";
87
+ };
88
+ export const localCommandSucceeds = (command, args, { cwd = process.cwd(), environment = {}, } = {}) => spawnSync(command, args, {
89
+ cwd,
90
+ env: createCleanProcessEnvironment({ overrides: environment }),
91
+ stdio: "ignore",
92
+ }).status === 0;
93
+ export const ensureLocalContainerRuntime = ({ cwd = process.cwd(), autoStartColima = true, } = {}) => {
94
+ if (localCommandSucceeds("docker", ["info"], { cwd }))
95
+ return;
96
+ if (autoStartColima && localCommandSucceeds("colima", ["version"], { cwd })) {
97
+ runLocalCommand("colima", ["start"], { cwd });
98
+ }
99
+ if (!localCommandSucceeds("docker", ["info"], { cwd })) {
100
+ throw new Error("A local Docker-compatible runtime is required. Install Docker or Colima, then rerun the command.");
101
+ }
102
+ };
103
+ const withWorkdir = (args, workdir) => (workdir ? [...args, "--workdir", workdir] : [...args]);
104
+ export const readLocalSupabaseEnvironment = ({ cwd, workdir, environment = {}, } = {}) => {
105
+ const output = runLocalCommand("supabase", withWorkdir(["status", "-o", "env"], workdir), { capture: true, cwd, environment });
106
+ return parseLocalSupabaseEnvironment(output);
107
+ };
108
+ export const startLocalSupabase = ({ cwd, workdir, exclude = [], environment = {}, applyMigrations = true, autoStartColima = true, } = {}) => {
109
+ ensureLocalContainerRuntime({ cwd, autoStartColima });
110
+ const startArguments = withWorkdir(["start", ...(exclude.length ? ["--exclude", exclude.join(",")] : [])], workdir);
111
+ runLocalCommand("supabase", startArguments, {
112
+ capture: true,
113
+ cwd,
114
+ environment,
115
+ });
116
+ if (applyMigrations) {
117
+ runLocalCommand("supabase", withWorkdir(["migration", "up", "--local"], workdir), { capture: true, cwd, environment });
118
+ }
119
+ return readLocalSupabaseEnvironment({ cwd, workdir, environment });
120
+ };
121
+ export const stopLocalSupabase = ({ cwd, workdir, environment = {}, } = {}) => {
122
+ if (!localCommandSucceeds("docker", ["info"], { cwd }))
123
+ return;
124
+ runLocalCommand("supabase", withWorkdir(["stop"], workdir), {
125
+ cwd,
126
+ environment,
127
+ });
128
+ };
129
+ export const removeLocalSupabaseProjectResources = ({ cwd = process.cwd(), projectId, } = {}) => {
130
+ if (!/^[a-z0-9][a-z0-9-]{1,62}$/u.test(projectId ?? "")) {
131
+ throw new Error("Refusing to remove local Supabase resources without an exact safe project id.");
132
+ }
133
+ const label = `com.supabase.cli.project=${projectId}`;
134
+ const list = (resource, format) => runLocalCommand("docker", [resource, "ls", "--filter", `label=${label}`, "--format", format], { capture: true, cwd })
135
+ .split("\n")
136
+ .map((value) => value.trim())
137
+ .filter(Boolean);
138
+ const containers = runLocalCommand("docker", ["ps", "--all", "--filter", `label=${label}`, "--format", "{{.ID}}"], { capture: true, cwd })
139
+ .split("\n")
140
+ .map((value) => value.trim())
141
+ .filter(Boolean);
142
+ if (containers.length) {
143
+ runLocalCommand("docker", ["rm", "--force", ...containers], {
144
+ capture: true,
145
+ cwd,
146
+ });
147
+ }
148
+ const volumes = list("volume", "{{.Name}}");
149
+ if (volumes.length) {
150
+ runLocalCommand("docker", ["volume", "rm", "--force", ...volumes], {
151
+ capture: true,
152
+ cwd,
153
+ });
154
+ }
155
+ const networks = list("network", "{{.ID}}");
156
+ if (networks.length) {
157
+ runLocalCommand("docker", ["network", "rm", ...networks], {
158
+ capture: true,
159
+ cwd,
160
+ });
161
+ }
162
+ };
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Purpose: Define the small, closed set of database runtimes Rehearsal can select.
3
+ * Runtime implementations stay behind this boundary so the shared CLI does not
4
+ * need target-specific branches.
5
+ */
6
+ declare const TARGETS: Readonly<{
7
+ supabase: Readonly<{
8
+ id: "supabase";
9
+ label: "Supabase";
10
+ }>;
11
+ postgresql: Readonly<{
12
+ id: "postgresql";
13
+ label: "PostgreSQL";
14
+ }>;
15
+ }>;
16
+ export type RehearsalRuntimeTargetId = keyof typeof TARGETS;
17
+ export type RehearsalRuntimeTarget = (typeof TARGETS)[RehearsalRuntimeTargetId];
18
+ export interface RuntimeInvocation {
19
+ readonly action: string;
20
+ readonly configPath: string | undefined;
21
+ readonly confirmation: string | undefined;
22
+ }
23
+ export interface RuntimeManagerArguments {
24
+ managerPath: string;
25
+ action: string;
26
+ configPath?: string;
27
+ confirmation?: string;
28
+ }
29
+ export declare const REHEARSAL_RUNTIME_TARGETS: readonly ("postgresql" | "supabase")[];
30
+ export declare const parseRuntimeInvocation: (arguments_?: readonly string[]) => RuntimeInvocation;
31
+ export declare const buildRuntimeManagerArguments: ({ managerPath, action, configPath, confirmation, }: RuntimeManagerArguments) => string[];
32
+ export declare const resolveRuntimeTarget: (value?: unknown) => RehearsalRuntimeTarget;
33
+ export {};
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Purpose: Define the small, closed set of database runtimes Rehearsal can select.
3
+ * Runtime implementations stay behind this boundary so the shared CLI does not
4
+ * need target-specific branches.
5
+ */
6
+ const TARGETS = Object.freeze({
7
+ supabase: Object.freeze({
8
+ id: "supabase",
9
+ label: "Supabase",
10
+ }),
11
+ postgresql: Object.freeze({
12
+ id: "postgresql",
13
+ label: "PostgreSQL",
14
+ }),
15
+ });
16
+ export const REHEARSAL_RUNTIME_TARGETS = Object.freeze(Object.keys(TARGETS));
17
+ export const parseRuntimeInvocation = (arguments_ = process.argv.slice(2)) => {
18
+ const action = arguments_.find((argument) => !argument.startsWith("--"));
19
+ const valueAfter = (prefix) => arguments_
20
+ .find((argument) => argument.startsWith(prefix))
21
+ ?.slice(prefix.length);
22
+ return Object.freeze({
23
+ action: action ?? "status",
24
+ configPath: valueAfter("--config="),
25
+ confirmation: valueAfter("--confirm-candidates="),
26
+ });
27
+ };
28
+ export const buildRuntimeManagerArguments = ({ managerPath, action, configPath, confirmation, }) => [
29
+ managerPath,
30
+ action,
31
+ ...(configPath ? [`--config=${configPath}`] : []),
32
+ ...(confirmation ? [`--confirm-candidates=${confirmation}`] : []),
33
+ ];
34
+ export const resolveRuntimeTarget = (value = "supabase") => {
35
+ if (typeof value !== "string" || !Object.hasOwn(TARGETS, value)) {
36
+ throw new Error(`Unsupported Rehearsal runtime target: ${String(value)}. Supported targets: ${REHEARSAL_RUNTIME_TARGETS.join(", ")}.`);
37
+ }
38
+ return TARGETS[value];
39
+ };
package/docs/README.md ADDED
@@ -0,0 +1,40 @@
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.
5
+
6
+ ## Start here
7
+
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) |
14
+
15
+ ## Work safely
16
+
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
22
+
23
+ ## Look something up
24
+
25
+ - [CLI commands](commands.md)
26
+ - [Configuration](configuration.md)
27
+ - [TypeScript](typescript.md)
28
+ - [Runtime and identity policies](runtime-policies.md)
29
+ - [Database adapters](adapters.md)
30
+ - [Glossary](glossary.md)
31
+
32
+ ## Follow the project
33
+
34
+ - [Roadmap](roadmap.md)
35
+ - [Stability and the first stable release](stability.md)
36
+ - [Repository architecture](architecture.md)
37
+ - [Release process](releasing.md)
38
+
39
+ To preview the styled documentation locally, run `npm run docs:preview`, then open the
40
+ address it prints.
package/docs/adapters.md CHANGED
@@ -5,8 +5,17 @@ database driver starts and manages a kind of local database, such as Supabase or
5
5
  PostgreSQL. A project
6
6
  runtime adapter adds narrowly scoped application behavior after that database is ready.
7
7
 
8
- Adapters are an advanced escape hatch for project-specific restore behavior. They live
9
- in the consuming repository and are loaded only from the path declared in config.
8
+ Adapters are a backward-compatible advanced escape hatch for project-specific restore
9
+ behavior. New projects should first use `runtimePolicy`, `identityPolicy`, application
10
+ environment mappings, HTTP proofs, and dependent targets. Those package-owned paths are
11
+ portable and reject executable declarations.
12
+
13
+ If the application needs another database, use
14
+ [`dependentTargets`](configuration.md#dependent-databases) instead of opening a second
15
+ connection or managing another container from a runtime adapter. Rehearsal owns that
16
+ database's identity, ports, lifecycle, verification order, and cleanup preview; the
17
+ project declares its baseline and proof. `prepareCommand` remains available for legacy
18
+ schema-specific transformations.
10
19
 
11
20
  An adapter may export:
12
21
 
@@ -18,10 +27,10 @@ An adapter may export:
18
27
  Each hook must return the documented status shape expected by the engine. It receives a
19
28
  local SQL executor; it should not open another connection or perform network access.
20
29
 
21
- Good adapter responsibilities include mapping sanitized application identities to local
22
- Auth users and verifying a domain-specific relationship after restore. Bad responsibilities
23
- include extracting production data, embedding credentials, contacting hosted services,
24
- or weakening the engine's local-only checks.
30
+ Use an adapter only when the documented declarative formats clearly reject a required
31
+ local behavior. Extracting production data, embedding credentials, contacting hosted
32
+ services, weakening local-only checks, or reimplementing container lifecycle is never an
33
+ adapter responsibility.
25
34
 
26
35
  Keep adapters small, deterministic, tested, and visibly project-owned. If a behavior is
27
36
  generic across unrelated projects, propose it for the engine instead of copying it into
@@ -0,0 +1,183 @@
1
+ # Repository architecture
2
+
3
+ Rehearsal separates shipped product code, repository automation, tests, fixtures, and
4
+ documentation so each file has one obvious home.
5
+
6
+ ```text
7
+ rehearsal-db/
8
+ ├── src/ TypeScript product source
9
+ │ ├── application/ application lifecycle and HTTP proofs
10
+ │ ├── baseline/ sanitized baseline creation and validation
11
+ │ ├── cli/ the `rehearsal` executable
12
+ │ ├── identity/ local account and Storage association
13
+ │ ├── project/ configuration, setup, and support
14
+ │ ├── runtime/ plans and disposable-runtime lifecycle
15
+ │ ├── shared/ small target-neutral utilities
16
+ │ ├── source/ approved source access and refresh
17
+ │ └── targets/ PostgreSQL and Supabase adapters
18
+ ├── scripts/
19
+ │ ├── build/ clean TypeScript compilation helpers
20
+ │ ├── install/ TypeScript install-hook source
21
+ │ ├── runtime/ TypeScript runtime-launcher source
22
+ │ └── verification/ repository-only package and fixture proofs
23
+ ├── dist/ generated ESM and declaration output; never edit directly
24
+ ├── types/ compatibility entry point for generated declarations
25
+ ├── tests/
26
+ │ ├── unit/ mirrors the `src/` domains
27
+ │ ├── integration/ multi-module and terminal behavior
28
+ │ ├── contracts/ public documentation and package promises
29
+ │ └── fixtures/ disposable example projects
30
+ └── docs/ user and maintainer documentation
31
+ ```
32
+
33
+ ## Boundaries
34
+
35
+ - `src/` must never import from tests or repository-only verification scripts.
36
+ - `dist/` is rebuilt from TypeScript before tests and packaging; never hand-edit it.
37
+ - Database-specific lifecycle behavior belongs in `src/targets/`.
38
+ - `scripts/verification/` is never included in the npm package.
39
+ - Public consumers use only the paths declared in `package.json#exports`.
40
+ - Unit tests mirror their source domain. Cross-domain workflows belong in
41
+ `tests/integration/`; durable public promises belong in `tests/contracts/`.
42
+
43
+ ## CLI modules
44
+
45
+ The executable is split by responsibility so no command file becomes a second
46
+ application layer. Scripted commands and the interactive guide resolve through the same
47
+ typed registry and produce the same result contract:
48
+
49
+ - `rehearsal.mts` owns process lifecycle, project locking, guided-loop coordination, and
50
+ top-level error handling. It does not implement commands.
51
+ - `arguments.mts` owns the command-line contract and mutation classification.
52
+ - `command_contract.mts`, `command_registry.mts`, and `command_output.mts` define command
53
+ context, handler selection, stable JSON envelopes, human rendering, and exit codes.
54
+ - `*_command_handlers.mts` and `runtime_action_handlers.mts` group handlers by project,
55
+ source, identity, inspection, application, or runtime responsibility.
56
+ - `cli_commands.mts` composes those focused families in precedence order without
57
+ implementing their behavior.
58
+ - `guided.mts` owns the interactive home screen and first-run questions.
59
+ - `runtime_commands.mts` coordinates local runtimes and project proofs.
60
+ - `source_commands.mts` coordinates approved source access and refresh.
61
+ - `renderers.mts` formats human-readable results without changing state.
62
+ - `terminal.mts` owns prompts, colors, and terminal exit behavior.
63
+
64
+ Command handlers receive an explicit context containing parsed flags, selected config,
65
+ guided state, and session-local caches. They return a rendered, text, or silent result;
66
+ only the shared output boundary creates JSON envelopes or writes final human output.
67
+ Session caches never appear in the public parsed-flags type.
68
+
69
+ Repository contracts keep the process entry point at 300 lines or fewer and every
70
+ handler-family module at 350 lines or fewer. A new command belongs in the narrowest
71
+ existing family, or in a new focused family when it represents a genuinely separate
72
+ responsibility.
73
+
74
+ ## Configuration pipeline
75
+
76
+ The stable `project/configuration.mts` facade keeps existing imports compatible while
77
+ configuration work moves through explicit phases:
78
+
79
+ 1. `configuration_discovery.mts` selects one supported project-owned config path.
80
+ 2. `configuration_schema.mts` validates the raw object shape and rejects unknown keys.
81
+ 3. `configuration_normalization.mts` applies defaults and semantic safety constraints.
82
+ 4. `configuration_resolution.mts` resolves owned paths from the project root and checks
83
+ destructive-operation boundaries.
84
+
85
+ The public contract/defaults, primitive validators, project detection, and starter
86
+ rendering have their own focused modules. `NormalizedRehearsalConfig` is inferred from
87
+ the normalizer, while the package's public declarations are emitted from the same
88
+ TypeScript implementation. Repository contracts keep the facade at 50 lines or fewer
89
+ and each configuration phase at 700 lines or fewer.
90
+
91
+ ## Installed-consumer verification
92
+
93
+ Repository verification installs the package tarball into disposable projects; it must
94
+ not import unpublished product source by accident. One scenario catalog drives both the
95
+ individual fixture commands and `npm run release:verify`.
96
+
97
+ - `scenarios/artifact.mjs` selects or packs one tarball, reads its package identity, and
98
+ records its SHA-256 before installation.
99
+ - `scenarios/workspace.mjs` creates and removes only scenario-owned scratch roots.
100
+ - `scenarios/process.mjs` starts commands with inherited credentials removed unless a
101
+ scenario explicitly supplies a safe value.
102
+ - `scenarios/application_session.mjs` owns persistent application and terminal-session
103
+ checks.
104
+ - `scenarios/catalog.mjs` is the sole ordered list of installed-consumer scenarios.
105
+ - Fixture files contain only the target setup and assertions unique to that scenario.
106
+
107
+ Each scenario remains independently runnable through its `test:fixture:*` script. The
108
+ complete release gate runs every catalog entry against the same immutable tarball and
109
+ writes its version, SHA-256, tool environment, commands, timings, and results under
110
+ `test-results/release-gate/`.
111
+
112
+ ## Runtime lifecycle
113
+
114
+ `runtime/lifecycle_engine.mts` owns the target-neutral lifecycle contract. Both
115
+ PostgreSQL and Supabase use it to dispatch commands, verify active baseline inputs,
116
+ calculate and confirm the exact migration set, write target-bound receipts, validate
117
+ runtime markers, and roll back a failed reset or migration without hiding the original
118
+ failure.
119
+
120
+ The files in `src/targets/` remain drivers. They prove ownership before deleting local
121
+ resources and implement only the behavior that genuinely differs: Docker PostgreSQL
122
+ containers and SQL setup on one side; Supabase CLI, Auth, Storage, and generated config
123
+ on the other. An ordinary `stop` never enters rollback or discard, so later `start`
124
+ preserves the sandbox database and Storage contents.
125
+
126
+ Repository contracts keep each target driver at 900 lines or fewer and the shared
127
+ lifecycle engine at 300 lines or fewer. A new database target must use this lifecycle
128
+ boundary rather than copying an existing driver's orchestration.
129
+
130
+ ## Identity claim pipeline
131
+
132
+ The stable `identity/claim.mts` facade exposes policy validation, deterministic planning,
133
+ and confirmed execution while keeping those responsibilities separate:
134
+
135
+ 1. `claim_contract.mts` defines the normalized policy, plan, database, and receipt types.
136
+ 2. `claim_policy.mts` validates and normalizes the reviewed declaration.
137
+ 3. `claim_plan.mts` binds the local matcher value to an immutable redacted review and
138
+ digest without opening a database or Storage connection.
139
+ 4. `claim_sql.mts` generates identifier-safe relational, JSON, signup-default, and path
140
+ SQL without executing it.
141
+ 5. `claim_identity_lookup.mts` performs read-only local Auth and reference discovery.
142
+ 6. `claim_verification.mts` checks signup defaults and token-hook claim shapes.
143
+ 7. `claim_executor.mts` alone owns the database transaction, Storage staging, rollback,
144
+ commit, old-object cleanup, and final receipt.
145
+ 8. `connect.mts` performs read-only, provider-neutral sign-in discovery and produces the
146
+ redacted preview used by the interactive copied-account connection.
147
+
148
+ Repository contracts keep the facade at 50 lines or fewer and every identity-claim
149
+ stage at 600 lines or fewer. Provider callbacks and consumer application behavior stay
150
+ outside this pipeline.
151
+
152
+ ## Privacy rule pipeline
153
+
154
+ The stable `baseline/privacy_engine.mts` facade preserves the documented privacy import
155
+ path while policy work is divided into fail-closed typed stages:
156
+
157
+ 1. `privacy_contract.mts` defines normalized policy and execution types.
158
+ 2. `privacy_recipe_validation.mts` normalizes only reviewed rule shapes;
159
+ `privacy_policy.mts` validates complete policy structure.
160
+ 3. `privacy_dependency_graph.mts` checks owner bindings, path mappings, sanitized digest
161
+ inputs, cycles, and shared date groups.
162
+ 4. `privacy_transforms.mts` implements deterministic pseudonyms and bounded paths.
163
+ 5. `privacy_rule_registry.mts` explicitly registers every action and derivation kind;
164
+ unknown kinds have no fallback execution path.
165
+ 6. `privacy_structured_json.mts` owns bounded object, array, union, and dictionary rules.
166
+ 7. `privacy_pipeline.mts` resolves reviewed bindings and executes rows, while
167
+ `privacy_key.mts` owns the local secret-file boundary.
168
+
169
+ Repository contracts keep the facade at 50 lines or fewer and every privacy stage at
170
+ 700 lines or fewer. Adding a rule requires its normalized type, validator, registered
171
+ handler, focused boundary tests, and documentation—without widening policy version 2.
172
+
173
+ ## Adding something new
174
+
175
+ 1. Put policy and reusable behavior in the domain that owns it.
176
+ 2. Put target-specific implementation behind the target boundary.
177
+ 3. Add its focused test under the matching `tests/unit/` domain.
178
+ 4. Add an integration or contract test only when behavior crosses domains or becomes a
179
+ public promise.
180
+ 5. Update the documentation map when adding a new guide.
181
+
182
+ Run `npm run build` after changing TypeScript source. Tests import the generated package
183
+ code so the same JavaScript boundary consumers install is exercised locally.
package/docs/baselines.md CHANGED
@@ -15,6 +15,20 @@ safe row.
15
15
  { "table": "widgets", "row": { "id": 1, "name": "Synthetic Widget" } }
16
16
  ```
17
17
 
18
+ `public` is the default schema. Name another schema explicitly when needed:
19
+
20
+ ```json
21
+ {
22
+ "schema": "app_api",
23
+ "table": "publication_products",
24
+ "row": { "id": 1 }
25
+ }
26
+ ```
27
+
28
+ Use the same optional `schema` on that table in the sanitization policy. Rehearsal keeps
29
+ same-named tables in different schemas separate. An undeclared schema or table is
30
+ rejected.
31
+
18
32
  Use synthetic or reviewed sanitized values. A `.json` array is not NDJSON and will be
19
33
  rejected.
20
34
 
@@ -67,7 +81,14 @@ npx rehearsal baseline create \
67
81
  ```
68
82
 
69
83
  Add `--assets=rehearsal/assets.json` only when using approved Supabase Storage files.
70
- Rehearsal validates everything and shows counts before activation. It never extracts data.
84
+ Rehearsal validates everything and shows counts before activation. These commands read
85
+ project-local files only.
86
+
87
+ The separately enabled `baseline refresh` command can stream a reviewed source through
88
+ privacy policy version 2. It stages a private generation, verifies capacity, counts,
89
+ checksums, source schema, migration evidence, privacy coverage, and drift, then switches
90
+ the active symlink atomically. Failure or interruption removes the staged generation and
91
+ preserves the prior active baseline and edited runtime.
71
92
 
72
93
  ## Why historical migrations are locked
73
94