@rehearsal-db/core 0.1.0-beta.14 → 0.1.0-beta.16

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 (236) hide show
  1. package/CHANGELOG.md +51 -1
  2. package/README.md +1 -0
  3. package/dist/package.json +101 -0
  4. package/dist/scripts/install/create_root_config.d.mts +3 -0
  5. package/dist/scripts/install/create_root_config.mjs +13 -0
  6. package/dist/scripts/runtime/manage_database.d.mts +6 -0
  7. package/{scripts → dist/scripts}/runtime/manage_database.mjs +6 -8
  8. package/dist/src/application/session.d.mts +96 -0
  9. package/dist/src/application/session.mjs +380 -0
  10. package/dist/src/baseline/artifact.d.mts +119 -0
  11. package/dist/src/baseline/artifact.mjs +522 -0
  12. package/dist/src/baseline/builder.d.mts +19 -0
  13. package/dist/src/baseline/builder.mjs +142 -0
  14. package/dist/src/baseline/input_discovery.d.mts +13 -0
  15. package/dist/src/baseline/input_discovery.mjs +149 -0
  16. package/dist/src/baseline/policy_review.d.mts +56 -0
  17. package/dist/src/baseline/policy_review.mjs +73 -0
  18. package/dist/src/baseline/preparation.d.mts +63 -0
  19. package/dist/src/baseline/preparation.mjs +295 -0
  20. package/dist/src/baseline/privacy_contract.d.mts +147 -0
  21. package/dist/src/baseline/privacy_contract.mjs +2 -0
  22. package/dist/src/baseline/privacy_dependency_graph.d.mts +7 -0
  23. package/dist/src/baseline/privacy_dependency_graph.mjs +110 -0
  24. package/dist/src/baseline/privacy_engine.d.mts +5 -0
  25. package/dist/src/baseline/privacy_engine.mjs +4 -0
  26. package/dist/src/baseline/privacy_key.d.mts +7 -0
  27. package/dist/src/baseline/privacy_key.mjs +42 -0
  28. package/dist/src/baseline/privacy_pipeline.d.mts +7 -0
  29. package/dist/src/baseline/privacy_pipeline.mjs +127 -0
  30. package/dist/src/baseline/privacy_policy.d.mts +6 -0
  31. package/dist/src/baseline/privacy_policy.mjs +237 -0
  32. package/dist/src/baseline/privacy_recipe_validation.d.mts +5 -0
  33. package/dist/src/baseline/privacy_recipe_validation.mjs +289 -0
  34. package/dist/src/baseline/privacy_rule_registry.d.mts +18 -0
  35. package/dist/src/baseline/privacy_rule_registry.mjs +143 -0
  36. package/dist/src/baseline/privacy_structured_json.d.mts +66 -0
  37. package/dist/src/baseline/privacy_structured_json.mjs +464 -0
  38. package/dist/src/baseline/privacy_transforms.d.mts +18 -0
  39. package/dist/src/baseline/privacy_transforms.mjs +142 -0
  40. package/dist/src/baseline/privacy_validation_shared.d.mts +31 -0
  41. package/dist/src/baseline/privacy_validation_shared.mjs +127 -0
  42. package/dist/src/baseline/sanitization_policy.d.mts +69 -0
  43. package/dist/src/baseline/sanitization_policy.mjs +227 -0
  44. package/dist/src/baseline/schema_snapshot.d.mts +19 -0
  45. package/dist/src/baseline/schema_snapshot.mjs +79 -0
  46. package/dist/src/cli/application_command_handlers.d.mts +8 -0
  47. package/dist/src/cli/application_command_handlers.mjs +52 -0
  48. package/dist/src/cli/arguments.d.mts +38 -0
  49. package/dist/src/cli/arguments.mjs +128 -0
  50. package/dist/src/cli/basic_command_handlers.d.mts +4 -0
  51. package/dist/src/cli/basic_command_handlers.mjs +56 -0
  52. package/dist/src/cli/cli_commands.d.mts +14 -0
  53. package/dist/src/cli/cli_commands.mjs +32 -0
  54. package/dist/src/cli/command_contract.d.mts +57 -0
  55. package/dist/src/cli/command_contract.mjs +39 -0
  56. package/dist/src/cli/command_output.d.mts +12 -0
  57. package/dist/src/cli/command_output.mjs +20 -0
  58. package/dist/src/cli/command_registry.d.mts +7 -0
  59. package/dist/src/cli/command_registry.mjs +14 -0
  60. package/dist/src/cli/guided.d.mts +53 -0
  61. package/dist/src/cli/guided.mjs +719 -0
  62. package/dist/src/cli/identity_command_handlers.d.mts +8 -0
  63. package/dist/src/cli/identity_command_handlers.mjs +43 -0
  64. package/dist/src/cli/init_command.d.mts +21 -0
  65. package/dist/src/cli/init_command.mjs +90 -0
  66. package/dist/src/cli/inspection_command_handlers.d.mts +3 -0
  67. package/dist/src/cli/inspection_command_handlers.mjs +79 -0
  68. package/dist/src/cli/project_command_handlers.d.mts +11 -0
  69. package/dist/src/cli/project_command_handlers.mjs +92 -0
  70. package/dist/src/cli/project_commands.d.mts +159 -0
  71. package/dist/src/cli/project_commands.mjs +183 -0
  72. package/dist/src/cli/rehearsal.d.mts +7 -0
  73. package/dist/src/cli/rehearsal.mjs +190 -0
  74. package/dist/src/cli/renderers.d.mts +299 -0
  75. package/dist/src/cli/renderers.mjs +554 -0
  76. package/dist/src/cli/runtime_action_handlers.d.mts +12 -0
  77. package/dist/src/cli/runtime_action_handlers.mjs +201 -0
  78. package/dist/src/cli/runtime_commands.d.mts +269 -0
  79. package/dist/src/cli/runtime_commands.mjs +601 -0
  80. package/dist/src/cli/source_command_handlers.d.mts +8 -0
  81. package/dist/src/cli/source_command_handlers.mjs +62 -0
  82. package/dist/src/cli/source_commands.d.mts +436 -0
  83. package/dist/src/cli/source_commands.mjs +301 -0
  84. package/dist/src/cli/terminal.d.mts +59 -0
  85. package/dist/src/cli/terminal.mjs +230 -0
  86. package/dist/src/identity/claim.d.mts +5 -0
  87. package/dist/src/identity/claim.mjs +4 -0
  88. package/dist/src/identity/claim_contract.d.mts +135 -0
  89. package/dist/src/identity/claim_contract.mjs +6 -0
  90. package/dist/src/identity/claim_executor.d.mts +10 -0
  91. package/dist/src/identity/claim_executor.mjs +358 -0
  92. package/dist/src/identity/claim_identity_lookup.d.mts +17 -0
  93. package/dist/src/identity/claim_identity_lookup.mjs +125 -0
  94. package/dist/src/identity/claim_plan.d.mts +8 -0
  95. package/dist/src/identity/claim_plan.mjs +61 -0
  96. package/dist/src/identity/claim_policy.d.mts +3 -0
  97. package/dist/src/identity/claim_policy.mjs +377 -0
  98. package/dist/src/identity/claim_sql.d.mts +10 -0
  99. package/dist/src/identity/claim_sql.mjs +46 -0
  100. package/dist/src/identity/claim_verification.d.mts +13 -0
  101. package/dist/src/identity/claim_verification.mjs +35 -0
  102. package/dist/src/identity/provider_configuration.d.mts +37 -0
  103. package/dist/src/identity/provider_configuration.mjs +132 -0
  104. package/dist/src/identity/storage.d.mts +21 -0
  105. package/dist/src/identity/storage.mjs +122 -0
  106. package/dist/src/index.d.mts +4 -0
  107. package/dist/src/index.mjs +3 -0
  108. package/dist/src/project/configuration.d.mts +13 -0
  109. package/dist/src/project/configuration.mjs +9 -0
  110. package/dist/src/project/configuration_contract.d.mts +125 -0
  111. package/dist/src/project/configuration_contract.mjs +27 -0
  112. package/dist/src/project/configuration_discovery.d.mts +7 -0
  113. package/dist/src/project/configuration_discovery.mjs +37 -0
  114. package/dist/src/project/configuration_normalization.d.mts +107 -0
  115. package/dist/src/project/configuration_normalization.mjs +302 -0
  116. package/dist/src/project/configuration_rendering.d.mts +14 -0
  117. package/dist/src/project/configuration_rendering.mjs +224 -0
  118. package/dist/src/project/configuration_resolution.d.mts +125 -0
  119. package/dist/src/project/configuration_resolution.mjs +81 -0
  120. package/dist/src/project/configuration_schema.d.mts +22 -0
  121. package/dist/src/project/configuration_schema.mjs +160 -0
  122. package/dist/src/project/configuration_validation.d.mts +22 -0
  123. package/dist/src/project/configuration_validation.mjs +136 -0
  124. package/dist/src/project/install_scaffold.d.mts +42 -0
  125. package/dist/src/project/install_scaffold.mjs +263 -0
  126. package/dist/src/project/project_detection.d.mts +14 -0
  127. package/dist/src/project/project_detection.mjs +47 -0
  128. package/dist/src/project/setup.d.mts +87 -0
  129. package/dist/src/project/setup.mjs +414 -0
  130. package/dist/src/project/support_report.d.mts +88 -0
  131. package/dist/src/project/support_report.mjs +83 -0
  132. package/dist/src/runtime/cleanup.d.mts +85 -0
  133. package/dist/src/runtime/cleanup.mjs +311 -0
  134. package/dist/src/runtime/lifecycle_engine.d.mts +63 -0
  135. package/dist/src/runtime/lifecycle_engine.mjs +114 -0
  136. package/dist/src/runtime/migration_history.d.mts +51 -0
  137. package/dist/src/runtime/migration_history.mjs +170 -0
  138. package/dist/src/runtime/plan.d.mts +134 -0
  139. package/dist/src/runtime/plan.mjs +637 -0
  140. package/dist/src/runtime/policy.d.mts +66 -0
  141. package/dist/src/runtime/policy.mjs +369 -0
  142. package/dist/src/runtime/restore.d.mts +22 -0
  143. package/dist/src/runtime/restore.mjs +276 -0
  144. package/dist/src/runtime/service_environment.d.mts +11 -0
  145. package/dist/src/runtime/service_environment.mjs +58 -0
  146. package/dist/src/runtime/topology.d.mts +51 -0
  147. package/dist/src/runtime/topology.mjs +128 -0
  148. package/dist/src/shared/diagnostics.d.mts +97 -0
  149. package/dist/src/shared/diagnostics.mjs +170 -0
  150. package/dist/src/shared/human_output.d.mts +2 -0
  151. package/{src → dist/src}/shared/human_output.mjs +1 -3
  152. package/dist/src/shared/node_runtime.d.mts +14 -0
  153. package/dist/src/shared/node_runtime.mjs +25 -0
  154. package/dist/src/shared/operation_guard.d.mts +22 -0
  155. package/dist/src/shared/operation_guard.mjs +150 -0
  156. package/dist/src/shared/process_environment.d.mts +15 -0
  157. package/dist/src/shared/process_environment.mjs +50 -0
  158. package/dist/src/source/access.d.mts +165 -0
  159. package/dist/src/source/access.mjs +602 -0
  160. package/dist/src/source/asset_transfer.d.mts +27 -0
  161. package/dist/src/source/asset_transfer.mjs +202 -0
  162. package/dist/src/source/baseline.d.mts +66 -0
  163. package/dist/src/source/baseline.mjs +372 -0
  164. package/dist/src/source/external_reader.d.mts +42 -0
  165. package/dist/src/source/external_reader.mjs +278 -0
  166. package/dist/src/source/postgresql_access.d.mts +86 -0
  167. package/dist/src/source/postgresql_access.mjs +454 -0
  168. package/dist/src/source/privacy_paths.d.mts +10 -0
  169. package/dist/src/source/privacy_paths.mjs +27 -0
  170. package/dist/src/targets/driver.d.mts +2 -0
  171. package/dist/src/targets/driver.mjs +13 -0
  172. package/dist/src/targets/postgresql.d.mts +5 -0
  173. package/dist/src/targets/postgresql.mjs +620 -0
  174. package/dist/src/targets/supabase.d.mts +8 -0
  175. package/dist/src/targets/supabase.mjs +627 -0
  176. package/dist/src/targets/supabase_environment.d.mts +49 -0
  177. package/dist/src/targets/supabase_environment.mjs +162 -0
  178. package/dist/src/targets/target.d.mts +33 -0
  179. package/dist/src/targets/target.mjs +39 -0
  180. package/docs/README.md +1 -0
  181. package/docs/architecture.md +133 -10
  182. package/docs/configuration.md +9 -3
  183. package/docs/index.md +1 -0
  184. package/docs/releasing.md +8 -3
  185. package/docs/typescript.md +134 -0
  186. package/package.json +36 -29
  187. package/types/configuration.d.mts +5 -0
  188. package/scripts/install/create_root_config.mjs +0 -19
  189. package/src/README.md +0 -17
  190. package/src/application/session.mjs +0 -435
  191. package/src/baseline/artifact.mjs +0 -684
  192. package/src/baseline/builder.mjs +0 -164
  193. package/src/baseline/input_discovery.mjs +0 -155
  194. package/src/baseline/policy_review.mjs +0 -92
  195. package/src/baseline/preparation.mjs +0 -323
  196. package/src/baseline/privacy_engine.mjs +0 -1399
  197. package/src/baseline/privacy_structured_json.mjs +0 -554
  198. package/src/baseline/sanitization_policy.mjs +0 -299
  199. package/src/baseline/schema_snapshot.mjs +0 -113
  200. package/src/cli/arguments.mjs +0 -126
  201. package/src/cli/guided.mjs +0 -814
  202. package/src/cli/init_command.mjs +0 -94
  203. package/src/cli/rehearsal.mjs +0 -972
  204. package/src/cli/renderers.mjs +0 -638
  205. package/src/cli/runtime_commands.mjs +0 -707
  206. package/src/cli/source_commands.mjs +0 -355
  207. package/src/cli/terminal.mjs +0 -275
  208. package/src/identity/claim.mjs +0 -1165
  209. package/src/identity/provider_configuration.mjs +0 -177
  210. package/src/identity/storage.mjs +0 -165
  211. package/src/project/configuration.d.mts +0 -164
  212. package/src/project/configuration.mjs +0 -1337
  213. package/src/project/install_scaffold.mjs +0 -325
  214. package/src/project/setup.mjs +0 -474
  215. package/src/project/support_report.mjs +0 -105
  216. package/src/runtime/cleanup.mjs +0 -381
  217. package/src/runtime/migration_history.mjs +0 -220
  218. package/src/runtime/plan.mjs +0 -722
  219. package/src/runtime/policy.mjs +0 -438
  220. package/src/runtime/restore.mjs +0 -337
  221. package/src/runtime/service_environment.mjs +0 -82
  222. package/src/runtime/topology.mjs +0 -177
  223. package/src/shared/diagnostics.mjs +0 -207
  224. package/src/shared/node_runtime.mjs +0 -31
  225. package/src/shared/operation_guard.mjs +0 -162
  226. package/src/shared/process_environment.mjs +0 -68
  227. package/src/source/access.mjs +0 -798
  228. package/src/source/asset_transfer.mjs +0 -259
  229. package/src/source/baseline.mjs +0 -482
  230. package/src/source/external_reader.mjs +0 -368
  231. package/src/source/postgresql_access.mjs +0 -638
  232. package/src/source/privacy_paths.mjs +0 -38
  233. package/src/targets/postgresql.mjs +0 -808
  234. package/src/targets/supabase.mjs +0 -840
  235. package/src/targets/supabase_environment.mjs +0 -229
  236. package/src/targets/target.mjs +0 -66
@@ -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 CHANGED
@@ -24,6 +24,7 @@ want to accomplish and follow that path.
24
24
 
25
25
  - [CLI commands](commands.md)
26
26
  - [Configuration](configuration.md)
27
+ - [TypeScript](typescript.md)
27
28
  - [Runtime and identity policies](runtime-policies.md)
28
29
  - [Database adapters](adapters.md)
29
30
  - [Glossary](glossary.md)
@@ -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,130 @@ 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
+
146
+ Repository contracts keep the facade at 50 lines or fewer and every identity-claim
147
+ stage at 600 lines or fewer. Provider callbacks and consumer application behavior stay
148
+ outside this pipeline.
149
+
150
+ ## Privacy rule pipeline
151
+
152
+ The stable `baseline/privacy_engine.mts` facade preserves the documented privacy import
153
+ path while policy work is divided into fail-closed typed stages:
154
+
155
+ 1. `privacy_contract.mts` defines normalized policy and execution types.
156
+ 2. `privacy_recipe_validation.mts` normalizes only reviewed rule shapes;
157
+ `privacy_policy.mts` validates complete policy structure.
158
+ 3. `privacy_dependency_graph.mts` checks owner bindings, path mappings, sanitized digest
159
+ inputs, cycles, and shared date groups.
160
+ 4. `privacy_transforms.mts` implements deterministic pseudonyms and bounded paths.
161
+ 5. `privacy_rule_registry.mts` explicitly registers every action and derivation kind;
162
+ unknown kinds have no fallback execution path.
163
+ 6. `privacy_structured_json.mts` owns bounded object, array, union, and dictionary rules.
164
+ 7. `privacy_pipeline.mts` resolves reviewed bindings and executes rows, while
165
+ `privacy_key.mts` owns the local secret-file boundary.
166
+
167
+ Repository contracts keep the facade at 50 lines or fewer and every privacy stage at
168
+ 700 lines or fewer. Adding a rule requires its normalized type, validator, registered
169
+ handler, focused boundary tests, and documentation—without widening policy version 2.
50
170
 
51
171
  ## Adding something new
52
172
 
@@ -56,3 +176,6 @@ application layer:
56
176
  4. Add an integration or contract test only when behavior crosses domains or becomes a
57
177
  public promise.
58
178
  5. Update the documentation map when adding a new guide.
179
+
180
+ Run `npm run build` after changing TypeScript source. Tests import the generated package
181
+ code so the same JavaScript boundary consumers install is exercised locally.
@@ -25,6 +25,11 @@ Use this page when changing the generated file. The schema is strict: misspelled
25
25
  unknown fields, and unsupported versions are errors. The `.mjs` extension works in both
26
26
  CommonJS and ESM projects.
27
27
 
28
+ The generated file also receives editor and compiler checking through the package's
29
+ public TypeScript declarations. See [TypeScript](typescript.md) for the supported type
30
+ surface and checked examples. Keep the runnable configuration as `.mjs`; a project does
31
+ not need to rename it to `.ts`.
32
+
28
33
  ```ts
29
34
  // @ts-check
30
35
  import { defineRehearsalConfig } from "@rehearsal-db/core";
@@ -466,9 +471,10 @@ may use these explicit subpaths:
466
471
  - `@rehearsal-db/core/service-environment`
467
472
  - `@rehearsal-db/core/source-access`
468
473
 
469
- These advanced entry points are ESM JavaScript APIs in the first beta. The root
470
- configuration and sanitization API has TypeScript declarations; the advanced subpaths do
471
- not yet promise a typed surface.
474
+ These advanced entry points ship as ordinary ESM JavaScript with generated TypeScript
475
+ declarations. The root configuration and sanitization contract remains the explicitly
476
+ reviewed public type surface. The exact current boundary is documented in
477
+ [TypeScript](typescript.md).
472
478
 
473
479
  Undocumented files under `scripts/` are package internals and are not compatibility
474
480
  contracts.
package/docs/index.md CHANGED
@@ -11,6 +11,7 @@ you want, then follow the links when a term or safety check is new.
11
11
  | Try Rehearsal without touching my app | [Hands-on tutorial](tutorial.md) |
12
12
  | Understand what makes a copy safe | [Baselines](baselines.md) and [Sanitization](sanitization.md) |
13
13
  | Look up a command or setting | [CLI commands](commands.md) and [Configuration](configuration.md) |
14
+ | Add editor and compiler type checks | [TypeScript](typescript.md) |
14
15
  | Fix something that did not work | [Troubleshooting](troubleshooting.md) |
15
16
 
16
17
  ## The short version
package/docs/releasing.md CHANGED
@@ -31,9 +31,10 @@ publication must change and prove the workflow before narrowing that permission.
31
31
 
32
32
  1. Start from protected `main` on a dedicated ticketed release branch.
33
33
  2. Verify the exact version, changelog, compatibility notes, and packed file list.
34
- 3. Run unit and contract tests, formatting, package-content and secret audits,
35
- dependency audit, packed onboarding, clean tarball installation, and the installed
36
- Docker fixtures.
34
+ 3. Run `npm run release:verify`. It performs the package checks and every
35
+ installed-consumer scenario against one tarball, then records the exact package
36
+ version, SHA-256, environment, commands, timings, and results in
37
+ `test-results/release-gate/`. Run the dependency audit separately.
37
38
  4. When an unfamiliar developer is available, have them follow clean-project onboarding.
38
39
  Correct and retest the first confusing, missing, or wrong instruction. Record when
39
40
  this human observation was unavailable; automated checks must not impersonate it.
@@ -53,6 +54,10 @@ publication must change and prove the workflow before narrowing that permission.
53
54
  11. Replace consuming projects' temporary Git/archive references only on their own
54
55
  protected integration branches and rerun their complete verification.
55
56
 
57
+ The independent Rehearsal Test Lab is the primary pre-release consumer environment.
58
+ Real product integrations provide additional compatibility evidence; they do not
59
+ replace the package-owned release gate or Test Lab.
60
+
56
61
  The workflow publishes prereleases under the `beta` dist-tag and refuses a stable
57
62
  version. While Rehearsal has no stable release, the workflow also moves `latest` to the
58
63
  same reviewed beta. This keeps the npm package page and the ordinary
@@ -0,0 +1,134 @@
1
+ # TypeScript
2
+
3
+ Rehearsal includes types for its documented public APIs. TypeScript is optional: the CLI and the
4
+ generated `rehearsal.config.mjs` work in JavaScript, TypeScript, CommonJS, and ESM
5
+ applications.
6
+
7
+ ## Type-check the generated config
8
+
9
+ Keep the generated configuration as `.mjs`. The `// @ts-check` line and
10
+ `defineRehearsalConfig` provide editor feedback without adding a build step or asking
11
+ Node.js to execute a TypeScript config file.
12
+
13
+ <!-- checked-example: javascript-config -->
14
+
15
+ ```js
16
+ // @ts-check
17
+ import { defineRehearsalConfig } from "@rehearsal-db/core";
18
+
19
+ export default defineRehearsalConfig({
20
+ schemaVersion: 1,
21
+ project: { name: "example-postgresql-app" },
22
+ postgresql: { migrationDirectory: "migrations" },
23
+ baseline: {
24
+ sanitizationPolicy: "rehearsal/sanitization-policy.json",
25
+ },
26
+ application: {
27
+ startCommand: "npm run dev",
28
+ proofCommand: "npm test",
29
+ },
30
+ runtime: {
31
+ target: "postgresql",
32
+ databasePort: 55432,
33
+ },
34
+ });
35
+ ```
36
+
37
+ This catches misspelled keys, missing required values, invalid runtime targets, and wrong
38
+ value types before Rehearsal starts. Runtime validation remains authoritative and still
39
+ fails closed when a configuration is unsafe.
40
+
41
+ ## Import the public types
42
+
43
+ Application tooling may import types from the package root. Type-only imports disappear
44
+ from compiled JavaScript and do not start Rehearsal.
45
+
46
+ <!-- checked-example: type-usage -->
47
+
48
+ ```ts
49
+ import type {
50
+ NormalizedRehearsalConfig,
51
+ RehearsalConfig,
52
+ RehearsalConfigVersion,
53
+ } from "@rehearsal-db/core";
54
+
55
+ export const schemaVersion: RehearsalConfigVersion = 1;
56
+
57
+ export const application = {
58
+ startCommand: "npm run dev",
59
+ proofCommand: "npm test",
60
+ } satisfies RehearsalConfig["application"];
61
+
62
+ export const localDatabasePort = (config: NormalizedRehearsalConfig): number =>
63
+ config.runtime.ports.database;
64
+ ```
65
+
66
+ ## Exported configuration types
67
+
68
+ | Export | Meaning |
69
+ | --------------------------- | ------------------------------------------------------------------------- |
70
+ | `RehearsalConfigVersion` | The supported configuration format. It is currently the literal type `1`. |
71
+ | `RehearsalConfig` | The reviewed input shape of `rehearsal.config.mjs`. |
72
+ | `NormalizedRehearsalConfig` | The immutable, defaulted configuration returned by Rehearsal's loader. |
73
+ | `defineRehearsalConfig()` | Checks a config while preserving its more specific inferred value types. |
74
+
75
+ Nested sections are available through indexed access types such as
76
+ `RehearsalConfig["application"]`, `RehearsalConfig["runtime"]`, and
77
+ `RehearsalConfig["safety"]`. The [configuration reference](configuration.md) explains
78
+ what each setting does and remains the source of truth for runtime behavior.
79
+
80
+ ## Type reviewed privacy policies
81
+
82
+ The advanced privacy entry point exports the normalized policy, table, column, engine,
83
+ foreign-key, and source-record types emitted from the same implementation used for
84
+ runtime validation. Keep policy input as ordinary JSON-compatible data and use the
85
+ validator's typed return value; runtime validation remains the authority for untrusted
86
+ files.
87
+
88
+ <!-- checked-example: privacy-usage -->
89
+
90
+ ```ts
91
+ import {
92
+ validateExecutablePrivacyPolicy,
93
+ type ExecutablePrivacyPolicy,
94
+ type PrivacyColumn,
95
+ } from "@rehearsal-db/core/privacy";
96
+
97
+ export const policy: ExecutablePrivacyPolicy = validateExecutablePrivacyPolicy({
98
+ policyVersion: 2,
99
+ migrationCutoff: "20260101000000",
100
+ tables: [
101
+ {
102
+ name: "widgets",
103
+ sourceRows: "STREAM AND SANITIZE",
104
+ columns: [
105
+ {
106
+ name: "id",
107
+ action: "PSEUDONYMIZE",
108
+ recipe: { format: "uuid", namespace: "widget-id" },
109
+ generated: "NEVER",
110
+ identity: "NO",
111
+ foreignKey: null,
112
+ },
113
+ ],
114
+ },
115
+ ],
116
+ });
117
+
118
+ export const identifierColumn: PrivacyColumn = policy.tables[0]!.columns[0]!;
119
+ ```
120
+
121
+ ## Package implementation and declarations
122
+
123
+ All shipped Rehearsal implementation source is TypeScript. The package build emits
124
+ ordinary ESM JavaScript for Node.js together with declaration files. Consumers do not
125
+ need TypeScript, a transpiler, or a TypeScript runtime.
126
+
127
+ The package-root import, `@rehearsal-db/core`, uses declarations generated from the
128
+ same TypeScript implementation that runs at runtime; the small `types/` entry point
129
+ only forwards those generated declarations. Advanced subpath imports such as
130
+ `@rehearsal-db/core/baseline` and `@rehearsal-db/core/privacy` also receive generated declarations, but they remain
131
+ advanced APIs: only their documented exports and behavior are compatibility promises.
132
+
133
+ Rehearsal's own `npm run typecheck` compiles every example on this page. A documentation
134
+ contract also requires the displayed snippets to match those checked files exactly.