@rehearsal-db/core 0.1.0-beta.9 → 0.1.0-rc.2

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 (247) hide show
  1. package/CHANGELOG.md +319 -1
  2. package/COMPATIBILITY.md +15 -0
  3. package/README.md +73 -16
  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/{scripts → dist/scripts}/runtime/manage_database.mjs +6 -8
  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 +228 -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 +640 -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/{src → 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 +629 -0
  183. package/dist/src/targets/supabase_environment.d.mts +54 -0
  184. package/dist/src/targets/supabase_environment.mjs +184 -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 +35 -16
  188. package/docs/architecture.md +135 -10
  189. package/docs/commands.md +53 -15
  190. package/docs/configuration.md +186 -31
  191. package/docs/getting-started.md +66 -9
  192. package/docs/index.md +67 -0
  193. package/docs/production-source.md +175 -17
  194. package/docs/releasing.md +24 -12
  195. package/docs/roadmap.md +3 -2
  196. package/docs/runtime-lifecycle.md +99 -0
  197. package/docs/runtime-policies.md +80 -7
  198. package/docs/sanitization.md +572 -4
  199. package/docs/security-model.md +8 -0
  200. package/docs/stability.md +70 -0
  201. package/docs/standalone-workflow.md +36 -13
  202. package/docs/troubleshooting.md +82 -10
  203. package/docs/tutorial.md +7 -1
  204. package/docs/typescript.md +134 -0
  205. package/package.json +44 -29
  206. package/types/configuration.d.mts +5 -0
  207. package/src/README.md +0 -17
  208. package/src/application/session.mjs +0 -313
  209. package/src/baseline/artifact.mjs +0 -661
  210. package/src/baseline/builder.mjs +0 -164
  211. package/src/baseline/input_discovery.mjs +0 -155
  212. package/src/baseline/policy_review.mjs +0 -92
  213. package/src/baseline/preparation.mjs +0 -323
  214. package/src/baseline/privacy_engine.mjs +0 -413
  215. package/src/baseline/sanitization_policy.mjs +0 -299
  216. package/src/baseline/schema_snapshot.mjs +0 -113
  217. package/src/cli/arguments.mjs +0 -120
  218. package/src/cli/guided.mjs +0 -807
  219. package/src/cli/rehearsal.mjs +0 -933
  220. package/src/cli/renderers.mjs +0 -584
  221. package/src/cli/runtime_commands.mjs +0 -553
  222. package/src/cli/source_commands.mjs +0 -326
  223. package/src/cli/terminal.mjs +0 -275
  224. package/src/identity/claim.mjs +0 -975
  225. package/src/identity/storage.mjs +0 -165
  226. package/src/project/configuration.d.mts +0 -153
  227. package/src/project/configuration.mjs +0 -1197
  228. package/src/project/setup.mjs +0 -379
  229. package/src/project/support_report.mjs +0 -105
  230. package/src/runtime/cleanup.mjs +0 -381
  231. package/src/runtime/migration_history.mjs +0 -220
  232. package/src/runtime/plan.mjs +0 -685
  233. package/src/runtime/policy.mjs +0 -438
  234. package/src/runtime/restore.mjs +0 -329
  235. package/src/runtime/service_environment.mjs +0 -82
  236. package/src/runtime/topology.mjs +0 -177
  237. package/src/shared/diagnostics.mjs +0 -199
  238. package/src/shared/operation_guard.mjs +0 -162
  239. package/src/shared/process_environment.mjs +0 -68
  240. package/src/source/access.mjs +0 -578
  241. package/src/source/asset_transfer.mjs +0 -177
  242. package/src/source/baseline.mjs +0 -446
  243. package/src/source/postgresql_access.mjs +0 -480
  244. package/src/targets/postgresql.mjs +0 -808
  245. package/src/targets/supabase.mjs +0 -830
  246. package/src/targets/supabase_environment.mjs +0 -229
  247. package/src/targets/target.mjs +0 -66
@@ -0,0 +1,184 @@
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 = false, } = {}) => {
94
+ if (localCommandSucceeds("docker", ["info"], { cwd }))
95
+ return;
96
+ if (autoStartColima && localCommandSucceeds("colima", ["version"], { cwd })) {
97
+ runLocalCommand("colima", ["start"], { cwd });
98
+ console.log("Started Colima because containerRuntime.autoStartColima is enabled. Rehearsal will not stop this shared Docker runtime automatically.");
99
+ }
100
+ if (!localCommandSucceeds("docker", ["info"], { cwd })) {
101
+ throw new Error(autoStartColima
102
+ ? "A local Docker-compatible runtime is required. Install Docker or Colima, then rerun the command."
103
+ : "A local Docker-compatible runtime is stopped or unavailable. Start Docker or Colima explicitly, or opt in with containerRuntime.autoStartColima: true.");
104
+ }
105
+ };
106
+ export const preventOwnedSupabaseAutoRestart = ({ cwd = process.cwd(), projectId, }) => {
107
+ if (!/^[a-z0-9][a-z0-9-]{1,62}$/u.test(projectId)) {
108
+ throw new Error("Refusing to change container restart policies without an exact safe Supabase project id.");
109
+ }
110
+ const label = `com.supabase.cli.project=${projectId}`;
111
+ const containers = runLocalCommand("docker", ["ps", "--all", "--filter", `label=${label}`, "--format", "{{.ID}}"], { capture: true, cwd })
112
+ .split("\n")
113
+ .map((value) => value.trim())
114
+ .filter(Boolean);
115
+ if (containers.length) {
116
+ runLocalCommand("docker", ["update", "--restart=no", ...containers], {
117
+ capture: true,
118
+ cwd,
119
+ });
120
+ }
121
+ return Object.freeze(containers);
122
+ };
123
+ const withWorkdir = (args, workdir) => (workdir ? [...args, "--workdir", workdir] : [...args]);
124
+ export const readLocalSupabaseEnvironment = ({ cwd, workdir, environment = {}, } = {}) => {
125
+ const output = runLocalCommand("supabase", withWorkdir(["status", "-o", "env"], workdir), { capture: true, cwd, environment });
126
+ return parseLocalSupabaseEnvironment(output);
127
+ };
128
+ export const startLocalSupabase = ({ cwd, workdir, exclude = [], environment = {}, applyMigrations = true, autoStartColima = false, projectId, } = {}) => {
129
+ ensureLocalContainerRuntime({ cwd, autoStartColima });
130
+ const startArguments = withWorkdir(["start", ...(exclude.length ? ["--exclude", exclude.join(",")] : [])], workdir);
131
+ runLocalCommand("supabase", startArguments, {
132
+ capture: true,
133
+ cwd,
134
+ environment,
135
+ });
136
+ if (projectId)
137
+ preventOwnedSupabaseAutoRestart({ cwd, projectId });
138
+ if (applyMigrations) {
139
+ runLocalCommand("supabase", withWorkdir(["migration", "up", "--local"], workdir), { capture: true, cwd, environment });
140
+ }
141
+ return readLocalSupabaseEnvironment({ cwd, workdir, environment });
142
+ };
143
+ export const stopLocalSupabase = ({ cwd, workdir, environment = {}, } = {}) => {
144
+ if (!localCommandSucceeds("docker", ["info"], { cwd }))
145
+ return;
146
+ runLocalCommand("supabase", withWorkdir(["stop"], workdir), {
147
+ cwd,
148
+ environment,
149
+ });
150
+ };
151
+ export const removeLocalSupabaseProjectResources = ({ cwd = process.cwd(), projectId, } = {}) => {
152
+ if (!/^[a-z0-9][a-z0-9-]{1,62}$/u.test(projectId ?? "")) {
153
+ throw new Error("Refusing to remove local Supabase resources without an exact safe project id.");
154
+ }
155
+ const label = `com.supabase.cli.project=${projectId}`;
156
+ const list = (resource, format) => runLocalCommand("docker", [resource, "ls", "--filter", `label=${label}`, "--format", format], { capture: true, cwd })
157
+ .split("\n")
158
+ .map((value) => value.trim())
159
+ .filter(Boolean);
160
+ const containers = runLocalCommand("docker", ["ps", "--all", "--filter", `label=${label}`, "--format", "{{.ID}}"], { capture: true, cwd })
161
+ .split("\n")
162
+ .map((value) => value.trim())
163
+ .filter(Boolean);
164
+ if (containers.length) {
165
+ runLocalCommand("docker", ["rm", "--force", ...containers], {
166
+ capture: true,
167
+ cwd,
168
+ });
169
+ }
170
+ const volumes = list("volume", "{{.Name}}");
171
+ if (volumes.length) {
172
+ runLocalCommand("docker", ["volume", "rm", "--force", ...volumes], {
173
+ capture: true,
174
+ cwd,
175
+ });
176
+ }
177
+ const networks = list("network", "{{.ID}}");
178
+ if (networks.length) {
179
+ runLocalCommand("docker", ["network", "rm", ...networks], {
180
+ capture: true,
181
+ cwd,
182
+ });
183
+ }
184
+ };
@@ -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 CHANGED
@@ -1,29 +1,48 @@
1
- # Documentation map
1
+ # Rehearsal documentation
2
+
3
+ Most migration tests start with an empty database. Production does not. Existing rows,
4
+ relationships, authentication identities, stored files, and migration history are where
5
+ risky changes break.
6
+
7
+ Rehearsal restores a reviewed, sanitized baseline into a disposable local environment,
8
+ applies only the exact migrations you approve, and runs your application's own proof.
9
+
10
+ You do not need to read this documentation from top to bottom. Choose what you want to
11
+ accomplish and follow that path.
2
12
 
3
13
  ## Start here
4
14
 
5
- - [Getting started](getting-started.md)
6
- - [Hands-on tutorial](tutorial.md)
7
- - [Troubleshooting](troubleshooting.md)
15
+ | Your goal | Best next page |
16
+ | ----------------------------------- | ------------------------------------- |
17
+ | Add Rehearsal to a project | [Getting started](getting-started.md) |
18
+ | Try it in a disposable project | [Hands-on tutorial](tutorial.md) |
19
+ | Fix a setup or runtime problem | [Troubleshooting](troubleshooting.md) |
20
+ | Browse the friendlier web-docs home | [Documentation home](index.md) |
8
21
 
9
- ## Understand the safety model
22
+ ## Work safely
10
23
 
11
- - [Baselines](baselines.md)
12
- - [Sanitization](sanitization.md)
13
- - [Production source boundary](production-source.md)
14
- - [Security model](security-model.md)
24
+ - [Baselines](baselines.md) — the verified starting copy
25
+ - [Sanitization](sanitization.md) — what may enter that copy
26
+ - [Production-shaped preparation](production-source.md) — the optional source boundary
27
+ - [Security model](security-model.md) — the independent safety barriers
28
+ - [Standalone workflow](standalone-workflow.md) — the complete declarative contract
15
29
 
16
- ## Configure Rehearsal
30
+ ## Look something up
17
31
 
32
+ - [CLI commands](commands.md)
18
33
  - [Configuration](configuration.md)
19
- - [Commands](commands.md)
20
- - [Runtime policies](runtime-policies.md)
34
+ - [Container runtime lifecycle](runtime-lifecycle.md)
35
+ - [TypeScript](typescript.md)
36
+ - [Runtime and identity policies](runtime-policies.md)
21
37
  - [Database adapters](adapters.md)
22
- - [Standalone PostgreSQL workflow](standalone-workflow.md)
38
+ - [Glossary](glossary.md)
23
39
 
24
- ## Maintain the project
40
+ ## Follow the project
25
41
 
42
+ - [Roadmap](roadmap.md)
43
+ - [Stability and the first stable release](stability.md)
26
44
  - [Repository architecture](architecture.md)
27
45
  - [Release process](releasing.md)
28
- - [Roadmap](roadmap.md)
29
- - [Glossary](glossary.md)
46
+
47
+ To preview the styled documentation locally, run `npm run docs:preview`, then open the
48
+ address it prints.
@@ -5,7 +5,7 @@ documentation so each file has one obvious home.
5
5
 
6
6
  ```text
7
7
  rehearsal-db/
8
- ├── src/ shipped package code
8
+ ├── src/ TypeScript product source
9
9
  │ ├── application/ application lifecycle and HTTP proofs
10
10
  │ ├── baseline/ sanitized baseline creation and validation
11
11
  │ ├── cli/ the `rehearsal` executable
@@ -16,8 +16,12 @@ rehearsal-db/
16
16
  │ ├── source/ approved source access and refresh
17
17
  │ └── targets/ PostgreSQL and Supabase adapters
18
18
  ├── scripts/
19
- │ ├── runtime/ shipped internal runtime launcher
19
+ │ ├── build/ clean TypeScript compilation helpers
20
+ │ ├── install/ TypeScript install-hook source
21
+ │ ├── runtime/ TypeScript runtime-launcher source
20
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
21
25
  ├── tests/
22
26
  │ ├── unit/ mirrors the `src/` domains
23
27
  │ ├── integration/ multi-module and terminal behavior
@@ -29,6 +33,7 @@ rehearsal-db/
29
33
  ## Boundaries
30
34
 
31
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.
32
37
  - Database-specific lifecycle behavior belongs in `src/targets/`.
33
38
  - `scripts/verification/` is never included in the npm package.
34
39
  - Public consumers use only the paths declared in `package.json#exports`.
@@ -38,15 +43,132 @@ rehearsal-db/
38
43
  ## CLI modules
39
44
 
40
45
  The executable is split by responsibility so no command file becomes a second
41
- application layer:
46
+ application layer. Scripted commands and the interactive guide resolve through the same
47
+ typed registry and produce the same result contract:
42
48
 
43
- - `rehearsal.mjs` starts the process and dispatches commands.
44
- - `arguments.mjs` owns the command-line contract and mutation classification.
45
- - `guided.mjs` owns the interactive home screen and first-run questions.
46
- - `runtime_commands.mjs` coordinates local runtimes and project proofs.
47
- - `source_commands.mjs` coordinates approved source access and refresh.
48
- - `renderers.mjs` formats human-readable results without changing state.
49
- - `terminal.mjs` owns prompts, colors, and terminal exit behavior.
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.
50
172
 
51
173
  ## Adding something new
52
174
 
@@ -56,3 +178,6 @@ application layer:
56
178
  4. Add an integration or contract test only when behavior crosses domains or becomes a
57
179
  public promise.
58
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/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,22 +32,28 @@ 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` first lists important optional settings that are available but not enabled, then
38
+ prints the installed release's template for comparison. `init --write` never replaces an
39
+ existing config.
40
+
35
41
  ## Optional source preparation
36
42
 
37
43
  These commands are separate from ordinary rehearsals. Configure `preparation` only after
38
44
  reviewing [the standalone security contract](standalone-workflow.md).
39
45
 
40
- | Command | What it does |
41
- | ------------------------------------------------------------- | -------------------------------------------------------------------- |
42
- | `npx rehearsal privacy key` | Preview the owner-only pseudonym-key path. |
43
- | `npx rehearsal privacy key --write` | Create the key once; refuses to replace an existing key. |
44
- | `npx rehearsal source plan` | Preview the exact temporary reader, views, columns, and asset scope. |
45
- | `npx rehearsal source apply --confirm-source-access=<sha256>` | Create only the reviewed, time-limited source access. |
46
- | `npx rehearsal baseline refresh` | Replace only the baseline from a reviewed source. |
47
- | `npx rehearsal refresh` | Preview a complete safe refresh of the baseline and local runtime. |
48
- | Add `--confirm-refresh=<sha256>` | Create the replacement, reset locally, and prune listed old copies. |
49
- | `npx rehearsal source retire` | Preview exact reader/view/credential retirement. |
50
- | Add `--confirm-source-retirement=<sha256>` | Apply that retirement plan and verify the exact object inventory. |
46
+ | Command | What it does |
47
+ | ------------------------------------------------------------- | ----------------------------------------------------------------------- |
48
+ | `npx rehearsal privacy key` | Preview the owner-only pseudonym-key path. |
49
+ | `npx rehearsal privacy key --write` | Create the key once; refuses to replace an existing key. |
50
+ | `npx rehearsal source plan` | Preview the exact temporary reader, views, columns, and asset scope. |
51
+ | `npx rehearsal source apply --confirm-source-access=<sha256>` | Create managed access, or verify external access without source writes. |
52
+ | `npx rehearsal baseline refresh` | Replace only the baseline from a reviewed source. |
53
+ | `npx rehearsal refresh` | Preview a complete safe refresh of the baseline and local runtime. |
54
+ | Add `--confirm-refresh=<sha256>` | Create the replacement, reset locally, and prune listed old copies. |
55
+ | `npx rehearsal source retire` | Preview managed retirement or external local-secret cleanup. |
56
+ | Add `--confirm-source-retirement=<sha256>` | Apply that retirement plan and verify the exact object inventory. |
51
57
 
52
58
  Source credentials are read from environment variables named in the reviewed source
53
59
  policy. Never paste a connection string into an argument. `baseline refresh` leaves the
@@ -67,7 +73,26 @@ In short: `refresh` gets a new source copy; `reset` restores the copy you alread
67
73
 
68
74
  ## Local identity association
69
75
 
70
- After an ordinary local Google or email sign-in creates a verified local Auth identity:
76
+ For a reviewed Google, GitHub, or email identity, use the guided connection:
77
+
78
+ ```bash
79
+ npx rehearsal identity connect
80
+ ```
81
+
82
+ Rehearsal starts and checks the local runtime, keeps the configured application open,
83
+ and waits for an ordinary provider sign-in. It reads only the local Auth database—not
84
+ browser cookies, passwords, passkeys, MFA secrets, or session tokens. When exactly one
85
+ approved verified identity matches, it stops the owned app, shows a redacted preview,
86
+ and offers **Connect my copied account**. One confirmation binds the exact current plan.
87
+ After the verified transfer, Rehearsal reopens the app and asks for one sign-out/sign-in
88
+ so the application receives fresh role claims.
89
+
90
+ If the policy declares more than one copied identity, choose one with
91
+ `--identity=<reviewed-name>`. The interactive guide presents the reviewed names. A
92
+ completed connection is recognized from its local runtime receipt and is not repeated.
93
+ Resetting the runtime removes that receipt and requires a fresh review and connection.
94
+
95
+ For automation or detailed inspection, keep using the explicit commands:
71
96
 
72
97
  ```bash
73
98
  npx rehearsal identity plan --identity=approved-owner
@@ -78,7 +103,8 @@ npx rehearsal identity claim --identity=approved-owner \
78
103
  The first command shows only hashes and declared reference counts. The second updates
79
104
  only the reviewed local relational, JSON, Storage-owner, and claim locations in one
80
105
  transaction. It rejects hosted database URLs, wrong or unverified people, ambiguity, and
81
- stale confirmation digests.
106
+ stale confirmation digests. Reopen the application and sign in again afterward to obtain
107
+ fresh claims. Neither flow bypasses application roles, account blocks, RLS, or MFA.
82
108
 
83
109
  If a runtime-policy seed moves with that identity, declare its `identityAssociation` in
84
110
  the runtime policy. Later `verify` calls then require the transferred row instead of the
@@ -100,11 +126,12 @@ obsolete placeholder key.
100
126
  State-reporting commands accept `--json` for scripts. Scripts should use the JSON fields
101
127
  and process exit code, not parse human-facing text.
102
128
 
103
- ## Run and manage the local database
129
+ ## Run and manage the local sandbox
104
130
 
105
131
  | Command | What it does |
106
132
  | ----------------------------------------------------- | ------------------------------------------------------------------- |
107
133
  | `npx rehearsal run --confirm-candidates=<sha256>` | Reset, apply exact candidates, launch the app, and run its proofs. |
134
+ | `npx rehearsal open` | Start, verify, and keep the configured application open. |
108
135
  | `npx rehearsal migrate --confirm-candidates=<sha256>` | Apply the exact candidates without resetting existing runtime data. |
109
136
  | `npx rehearsal start` | Start an existing verified runtime. |
110
137
  | `npx rehearsal verify` | Verify the current runtime and receipt. |
@@ -117,6 +144,13 @@ In a terminal, the guide displays candidate filenames and asks for confirmation.
117
144
  script, copy the digest from `candidates` into `--confirm-candidates`. Adding, removing,
118
145
  reordering, or editing a migration changes that digest.
119
146
 
147
+ `open` does not reset the runtime or apply migrations. It starts and verifies every
148
+ configured database target, runs dependent preparation commands, and launches
149
+ `application.startCommand` with the declared local environment mappings. It waits for
150
+ `application.readiness`, then stays attached until `Ctrl+C` or `Ctrl+Z`. On exit it stops
151
+ only the application process group it launched. Use `stop` separately when you also want
152
+ to stop the databases; a later `open` preserves their database and Storage changes.
153
+
120
154
  ## Clean up disk space
121
155
 
122
156
  Start with a preview:
@@ -145,6 +179,8 @@ belonging to other projects are never included. This follows
145
179
 
146
180
  | Option | Meaning |
147
181
  | -------------------------------------- | ---------------------------------------------------------------- |
182
+ | `--help`, `-h` | Show the installed command reference. |
183
+ | `--version`, `-V` | Print the installed package version and exit. |
148
184
  | `--json` | Return the versioned machine-readable result. |
149
185
  | `--verbose` | Show more safe detail. |
150
186
  | `--debug` | Show the most diagnostic detail; still review it before sharing. |
@@ -162,6 +198,8 @@ belonging to other projects are never included. This follows
162
198
  | `--write` | Apply a setup, policy, or cleanup preview. |
163
199
 
164
200
  Run `npx rehearsal --help` to print the command list available in your installed version.
201
+ Run `npx rehearsal --version` to print only its version number. Add `--json` when a
202
+ script also needs the package name.
165
203
 
166
204
  When a project has more than one config, pass `--config=<path>` on every command for the
167
205
  non-default one. Rehearsal keeps that exact config selected through status, run, reset,