@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,8 @@
1
+ /** Provider-neutral copied-account planning and application handlers. */
2
+ import type { CommandDefinition } from "./command_contract.mjs";
3
+ import type { createProjectCommands } from "./project_commands.mjs";
4
+ type ProjectCommands = ReturnType<typeof createProjectCommands>;
5
+ export declare const createIdentityCommandHandlers: ({ loadIdentityClaimPlan, }: {
6
+ loadIdentityClaimPlan: ProjectCommands["loadIdentityClaimPlan"];
7
+ }) => readonly CommandDefinition[];
8
+ export {};
@@ -0,0 +1,43 @@
1
+ /** Provider-neutral copied-account planning and application handlers. */
2
+ import { readFile } from "node:fs/promises";
3
+ import { parseEnv } from "node:util";
4
+ import { applyIdentityClaim } from "../identity/claim.mjs";
5
+ import { createSupabaseStorageTransfer } from "../identity/storage.mjs";
6
+ import { exactCommands, renderedCommand } from "./command_contract.mjs";
7
+ import { renderIdentityPlan } from "./renderers.mjs";
8
+ export const createIdentityCommandHandlers = ({ loadIdentityClaimPlan, }) => [
9
+ exactCommands("identity", ["identity plan", "identity claim"], async ({ command, flags, planOptions }) => {
10
+ const { loaded, plan } = await loadIdentityClaimPlan({
11
+ flags,
12
+ planOptions,
13
+ });
14
+ if (command === "identity plan" || !flags.identityConfirmation) {
15
+ const data = { mode: "preview", plan };
16
+ return renderedCommand({ data, render: renderIdentityPlan });
17
+ }
18
+ const runtimeEnvironment = parseEnv(await readFile(loaded.paths.applicationEnvironment, "utf8"));
19
+ if (!runtimeEnvironment.DATABASE_URL) {
20
+ throw new Error("The local runtime environment has no DATABASE_URL.");
21
+ }
22
+ const needsStorageTransfer = plan.identity.assets.some((asset) => asset.rewritePath);
23
+ if (needsStorageTransfer &&
24
+ (!runtimeEnvironment.SUPABASE_URL ||
25
+ !runtimeEnvironment.SUPABASE_SERVICE_ROLE_KEY)) {
26
+ throw new Error("Identity asset transfer requires local Supabase URL and service-role credentials.");
27
+ }
28
+ const storageTransfer = needsStorageTransfer
29
+ ? createSupabaseStorageTransfer({
30
+ url: runtimeEnvironment.SUPABASE_URL,
31
+ serviceRoleKey: runtimeEnvironment.SUPABASE_SERVICE_ROLE_KEY,
32
+ })
33
+ : undefined;
34
+ const result = await applyIdentityClaim({
35
+ plan,
36
+ confirmation: flags.identityConfirmation,
37
+ connectionString: runtimeEnvironment.DATABASE_URL,
38
+ ...(storageTransfer === undefined ? {} : { storageTransfer }),
39
+ });
40
+ const data = { mode: "written", plan, result };
41
+ return renderedCommand({ data, render: renderIdentityPlan });
42
+ }),
43
+ ];
@@ -0,0 +1,21 @@
1
+ /** Preview or create the project-root Rehearsal configuration. */
2
+ interface InitFlags {
3
+ readonly configPath: string | undefined;
4
+ readonly write: boolean;
5
+ }
6
+ interface InitOptions {
7
+ readonly projectRoot: string;
8
+ readonly flags: InitFlags;
9
+ }
10
+ export declare const runRehearsalInit: ({ projectRoot, flags }: InitOptions) => Promise<{
11
+ mode: string;
12
+ destination: string;
13
+ detected: import("../project/project_detection.mjs").DetectedProject;
14
+ source: string;
15
+ availableOptions: {
16
+ path: string;
17
+ summary: string;
18
+ }[];
19
+ nextAction: string;
20
+ }>;
21
+ export {};
@@ -0,0 +1,90 @@
1
+ /** Preview or create the project-root Rehearsal configuration. */
2
+ import { writeFile } from "node:fs/promises";
3
+ import { join, relative } from "node:path";
4
+ import { findRehearsalConfigPath, inspectDetectedProject, loadRehearsalConfig, renderDetectedConfig, renderDetectedPostgresqlConfig, } from "../project/configuration.mjs";
5
+ const findExistingConfig = async ({ projectRoot, configPath, }) => {
6
+ try {
7
+ return await findRehearsalConfigPath({
8
+ projectRoot,
9
+ ...(configPath === undefined ? {} : { configPath }),
10
+ });
11
+ }
12
+ catch (error) {
13
+ if (String(error instanceof Error ? error.message : error).startsWith("No Rehearsal configuration")) {
14
+ return null;
15
+ }
16
+ throw error;
17
+ }
18
+ };
19
+ export const runRehearsalInit = async ({ projectRoot, flags }) => {
20
+ const detected = await inspectDetectedProject({ projectRoot });
21
+ const destination = join(projectRoot, "rehearsal.config.mjs");
22
+ const existingPath = await findExistingConfig({
23
+ projectRoot,
24
+ configPath: flags.configPath,
25
+ });
26
+ if (existingPath) {
27
+ if (flags.write) {
28
+ throw new Error(`A Rehearsal configuration already exists at ${relative(projectRoot, existingPath)}; Rehearsal will not overwrite it.`);
29
+ }
30
+ const loaded = await loadRehearsalConfig({
31
+ projectRoot,
32
+ ...(flags.configPath === undefined
33
+ ? {}
34
+ : { configPath: flags.configPath }),
35
+ });
36
+ let source;
37
+ if (loaded.config.supabase) {
38
+ const { api, database, studio } = loaded.config.runtime.ports;
39
+ if (api === undefined || studio === undefined) {
40
+ throw new Error("The normalized Supabase configuration is missing its API or Studio port.");
41
+ }
42
+ source = renderDetectedConfig(detected, {
43
+ applicationUrl: loaded.config.runtime.applicationUrl,
44
+ ports: { api, database, studio },
45
+ });
46
+ }
47
+ else {
48
+ source = renderDetectedPostgresqlConfig(detected, {
49
+ applicationUrl: loaded.config.runtime.applicationUrl,
50
+ databasePort: loaded.config.runtime.ports.database,
51
+ });
52
+ }
53
+ const usesLegacyAuthentication = Boolean(loaded.config.supabase?.serviceEnvironmentFile ||
54
+ loaded.config.safety.authenticationProviders.length);
55
+ const availableOptions = loaded.config.supabase && !loaded.config.supabase.authentication
56
+ ? [
57
+ {
58
+ path: "supabase.authentication",
59
+ summary: usesLegacyAuthentication
60
+ ? "A declarative Google/GitHub replacement is available; replace the legacy provider fields together after review."
61
+ : "Configure local Google or GitHub sign-in with credentials kept outside tracked files.",
62
+ },
63
+ ]
64
+ : [];
65
+ return {
66
+ mode: "current-template",
67
+ destination: relative(projectRoot, existingPath),
68
+ detected,
69
+ source,
70
+ availableOptions,
71
+ nextAction: "Your existing configuration was not changed. Compare it with this installed-release template to discover new optional keys.",
72
+ };
73
+ }
74
+ const source = detected.hasSupabaseConfig
75
+ ? renderDetectedConfig(detected)
76
+ : renderDetectedPostgresqlConfig(detected);
77
+ if (flags.write) {
78
+ await writeFile(destination, source, { flag: "wx", mode: 0o600 });
79
+ }
80
+ return {
81
+ mode: flags.write ? "written" : "preview",
82
+ destination: relative(projectRoot, destination),
83
+ detected,
84
+ source,
85
+ availableOptions: [],
86
+ nextAction: flags.write
87
+ ? "Review the generated safety settings and run rehearsal doctor."
88
+ : "Review this preview, then rerun rehearsal init --write to create it.",
89
+ };
90
+ };
@@ -0,0 +1,3 @@
1
+ /** Read-only readiness, support, planning, and inspection command handlers. */
2
+ import type { CommandDefinition } from "./command_contract.mjs";
3
+ export declare const createInspectionCommandHandlers: () => readonly CommandDefinition[];
@@ -0,0 +1,79 @@
1
+ /** Read-only readiness, support, planning, and inspection command handlers. */
2
+ import { collectRehearsalSupportReport } from "../project/support_report.mjs";
3
+ import { inspectRehearsalBaseline, inspectRehearsalMigrations, } from "../runtime/plan.mjs";
4
+ import { buildRuntimeStackPlan, runRuntimeStackDoctor, topologyCandidateSummary, } from "./runtime_commands.mjs";
5
+ import { renderBaseline, renderCandidates, renderDoctor, renderMigrations, renderPlan, renderSupportReport, } from "./renderers.mjs";
6
+ import { exactCommands, renderedCommand } from "./command_contract.mjs";
7
+ export const createInspectionCommandHandlers = () => [
8
+ exactCommands("doctor", ["doctor"], async ({ guided, flags, planOptions }) => {
9
+ const data = await runRuntimeStackDoctor(planOptions);
10
+ return renderedCommand({
11
+ data,
12
+ render: (result, verbosity) => renderDoctor(result, verbosity),
13
+ status: data.state === "READY" ? "success" : "not_ready",
14
+ ...(data.state !== "READY" && !guided ? { exitCode: 1 } : {}),
15
+ });
16
+ }),
17
+ exactCommands("support", ["support"], async ({ planOptions }) => {
18
+ const data = await collectRehearsalSupportReport(planOptions, {
19
+ runDoctor: async (options) => {
20
+ const report = await runRuntimeStackDoctor(options);
21
+ const targetAliases = new Map();
22
+ const aliasFor = (name) => {
23
+ if (!targetAliases.has(name)) {
24
+ targetAliases.set(name, `runtime-${targetAliases.size + 1}`);
25
+ }
26
+ return targetAliases.get(name);
27
+ };
28
+ return {
29
+ ...report,
30
+ checks: report.checks.map((check) => {
31
+ const separator = check.id.indexOf(":");
32
+ if (separator === -1)
33
+ return check;
34
+ const target = check.id.slice(0, separator);
35
+ const alias = aliasFor(target);
36
+ return {
37
+ ...check,
38
+ id: `${alias}:${check.id.slice(separator + 1)}`,
39
+ label: check.label.replace(`${target}:`, `${alias}:`),
40
+ };
41
+ }),
42
+ };
43
+ },
44
+ });
45
+ return renderedCommand({
46
+ data,
47
+ render: (result) => renderSupportReport(result),
48
+ });
49
+ }),
50
+ {
51
+ id: "explain",
52
+ matches: ({ command, flags }) => command === "explain" || (command === "run" && flags.dryRun),
53
+ handle: async ({ planOptions }) => {
54
+ const data = await buildRuntimeStackPlan(planOptions);
55
+ return renderedCommand({
56
+ data,
57
+ render: (result, verbosity) => renderPlan(result, verbosity),
58
+ });
59
+ },
60
+ },
61
+ exactCommands("inspect-baseline", ["inspect baseline"], async ({ planOptions }) => {
62
+ const data = await inspectRehearsalBaseline(planOptions);
63
+ return renderedCommand({ data, render: renderBaseline });
64
+ }),
65
+ exactCommands("inspect-migrations", ["inspect migrations"], async ({ planOptions }) => {
66
+ const data = await inspectRehearsalMigrations(planOptions);
67
+ return renderedCommand({
68
+ data,
69
+ render: (result, verbosity) => renderMigrations(result, verbosity),
70
+ });
71
+ }),
72
+ exactCommands("candidates", ["candidates"], async ({ planOptions }) => {
73
+ const { topology: _topology, ...data } = await topologyCandidateSummary(planOptions);
74
+ return renderedCommand({
75
+ data,
76
+ render: (result, verbosity) => renderCandidates(result, verbosity),
77
+ });
78
+ }),
79
+ ];
@@ -0,0 +1,11 @@
1
+ /** Project setup, baseline creation, privacy-key, and cleanup command handlers. */
2
+ import type { CommandDefinition } from "./command_contract.mjs";
3
+ import type { createProjectCommands } from "./project_commands.mjs";
4
+ type ProjectCommands = ReturnType<typeof createProjectCommands>;
5
+ export declare const createProjectCommandHandlers: ({ projectRoot, runSetup, runBaselinePreparation, runCleanup, }: {
6
+ projectRoot: string;
7
+ runSetup: ProjectCommands["runSetup"];
8
+ runBaselinePreparation: ProjectCommands["runBaselinePreparation"];
9
+ runCleanup: ProjectCommands["runCleanup"];
10
+ }) => readonly CommandDefinition[];
11
+ export {};
@@ -0,0 +1,92 @@
1
+ /** Project setup, baseline creation, privacy-key, and cleanup command handlers. */
2
+ import { relative } from "node:path";
3
+ import { createSyntheticBaselineFromFiles } from "../baseline/builder.mjs";
4
+ import { inspectBaselineInputFiles } from "../baseline/preparation.mjs";
5
+ import { createPrivacyKey } from "../baseline/privacy_engine.mjs";
6
+ import { formatCount } from "../shared/human_output.mjs";
7
+ import { runRehearsalInit } from "./init_command.mjs";
8
+ import { loadPreparationContext } from "./source_commands.mjs";
9
+ import { renderBaselinePreparation, renderCleanup, renderInit, renderSetup, } from "./renderers.mjs";
10
+ import { exactCommands, renderedCommand } from "./command_contract.mjs";
11
+ export const createProjectCommandHandlers = ({ projectRoot, runSetup, runBaselinePreparation, runCleanup, }) => [
12
+ exactCommands("setup", ["setup"], async ({ flags, planOptions, state }) => {
13
+ const data = await runSetup({ flags, planOptions, session: state });
14
+ return renderedCommand({
15
+ data,
16
+ render: () => renderSetup(data),
17
+ });
18
+ }),
19
+ exactCommands("init", ["init"], async ({ flags }) => {
20
+ const data = await runRehearsalInit({ projectRoot, flags });
21
+ return renderedCommand({
22
+ data,
23
+ render: (result) => renderInit(result),
24
+ });
25
+ }),
26
+ exactCommands("baseline-prepare", ["baseline prepare"], async ({ flags, planOptions, state }) => {
27
+ const data = await runBaselinePreparation({
28
+ flags,
29
+ planOptions,
30
+ session: state,
31
+ });
32
+ return renderedCommand({
33
+ data,
34
+ render: (result) => renderBaselinePreparation(result, flags),
35
+ });
36
+ }),
37
+ exactCommands("baseline-create", ["baseline create"], async ({ flags, planOptions }) => {
38
+ if (!flags.recordsPath || !flags.ledgerPath) {
39
+ throw new Error("baseline create requires --records and --ledger input paths.");
40
+ }
41
+ const baselineInput = {
42
+ ...planOptions,
43
+ recordsPath: flags.recordsPath,
44
+ ledgerPath: flags.ledgerPath,
45
+ ...(flags.assetsPath === undefined
46
+ ? {}
47
+ : { assetsPath: flags.assetsPath }),
48
+ };
49
+ await inspectBaselineInputFiles(baselineInput);
50
+ const data = await createSyntheticBaselineFromFiles(baselineInput);
51
+ return renderedCommand({
52
+ data,
53
+ render: (baseline) => [
54
+ `Activated synthetic baseline ${baseline.generationId}: ${formatCount(baseline.rowCount, "row")} across ${formatCount(baseline.tableCount, "table")}; ${formatCount(baseline.migrationCount, "migration")} through ${baseline.migrationCutoff}.`,
55
+ "",
56
+ flags.guided
57
+ ? "Next: choose Run a rehearsal when you are ready."
58
+ : "Next: run rehearsal doctor to check readiness.",
59
+ ].join("\n"),
60
+ });
61
+ }),
62
+ exactCommands("privacy-key", ["privacy key"], async ({ flags, planOptions }) => {
63
+ const { loaded } = await loadPreparationContext(planOptions);
64
+ if (!loaded.paths.privacyKey) {
65
+ throw new Error("No config.preparation.privacyKey is configured.");
66
+ }
67
+ const privacyKeyPath = loaded.paths.privacyKey;
68
+ const data = flags.write
69
+ ? {
70
+ mode: "written",
71
+ path: relative(loaded.projectRoot, privacyKeyPath),
72
+ ...(await createPrivacyKey(privacyKeyPath)),
73
+ }
74
+ : {
75
+ mode: "preview",
76
+ path: relative(loaded.projectRoot, privacyKeyPath),
77
+ };
78
+ return renderedCommand({
79
+ data,
80
+ render: (result) => result.mode === "preview"
81
+ ? `PRIVACY KEY — PREVIEW\n\nWould create ${result.path} with owner-only permissions.\nNothing was written. Rerun with --write after reviewing the path.`
82
+ : `Created owner-only privacy key at ${result.path}.\nFingerprint: ${result.fingerprint}\nThe key is excluded from source control and must not be shared.`,
83
+ });
84
+ }),
85
+ exactCommands("cleanup", ["cleanup"], async ({ flags, planOptions, state }) => {
86
+ const data = await runCleanup({ flags, planOptions, session: state });
87
+ return renderedCommand({
88
+ data,
89
+ render: () => renderCleanup(data),
90
+ });
91
+ }),
92
+ ];
@@ -0,0 +1,159 @@
1
+ /** Project-scoped CLI orchestration that is shared by direct and guided commands. */
2
+ import { summarizeBaselinePreparation } from "../baseline/preparation.mjs";
3
+ import type { RehearsalConfigPathOptions } from "../project/configuration.mjs";
4
+ import type { RehearsalCleanupPlan } from "../runtime/cleanup.mjs";
5
+ import type { RehearsalCliFlags } from "./arguments.mjs";
6
+ import type { CliSessionState } from "./command_contract.mjs";
7
+ type CleanupStackPlan = Readonly<{
8
+ digest: string;
9
+ targets: readonly Readonly<{
10
+ name: string;
11
+ configPath: string;
12
+ plan: RehearsalCleanupPlan;
13
+ }>[];
14
+ }>;
15
+ type RunManager = (input: {
16
+ action: "discard";
17
+ flags: RehearsalCliFlags;
18
+ configPath?: string;
19
+ targetName?: string;
20
+ }) => unknown;
21
+ interface ProjectCommandInput {
22
+ readonly flags: RehearsalCliFlags;
23
+ readonly planOptions: RehearsalConfigPathOptions;
24
+ readonly session?: CliSessionState;
25
+ }
26
+ export declare const createProjectCommands: ({ projectRoot, runManager, }: {
27
+ projectRoot: string;
28
+ runManager: RunManager;
29
+ }) => Readonly<{
30
+ loadIdentityClaimPlan: ({ flags, planOptions, }: ProjectCommandInput) => Promise<{
31
+ loaded: Readonly<{
32
+ config: Readonly<{
33
+ schemaVersion: 1;
34
+ project: Readonly<{
35
+ name: string;
36
+ }>;
37
+ supabase: Readonly<{
38
+ workdir: string;
39
+ migrationDirectory: string;
40
+ rehearsalConfig: string;
41
+ runtimeWorkdir: string;
42
+ authentication: Readonly<{
43
+ enableLocalSignup: true;
44
+ environmentFile: string;
45
+ providers: readonly Readonly<{
46
+ name: "github" | "google";
47
+ clientIdEnvironmentVariable: string;
48
+ clientSecretEnvironmentVariable: string;
49
+ skipNonceCheck: boolean;
50
+ emailOptional: boolean;
51
+ }>[];
52
+ }> | null;
53
+ serviceEnvironmentFile: string | null;
54
+ serviceEnvironmentVariables: readonly string[];
55
+ }> | null;
56
+ postgresql: Readonly<{
57
+ migrationDirectory: string;
58
+ runtimeWorkdir: string;
59
+ image: string;
60
+ database: string;
61
+ user: string;
62
+ }> | null;
63
+ baseline: Readonly<{
64
+ artifactDirectory: string;
65
+ sanitizationPolicy: string;
66
+ }>;
67
+ containerRuntime: Readonly<{
68
+ autoStartColima: boolean;
69
+ }>;
70
+ cleanup: Readonly<{
71
+ retainBaselineGenerations: number;
72
+ }>;
73
+ preparation: Readonly<{
74
+ sourcePolicy: string;
75
+ privacyKey: string;
76
+ batchRows: number;
77
+ maximumRows: number;
78
+ maximumBytes: number;
79
+ diskHeadroomBytes: number;
80
+ }> | null;
81
+ runtimePolicy: string | null;
82
+ identityPolicy: string | null;
83
+ dependentTargets: readonly Readonly<{
84
+ name: string;
85
+ configPath: string;
86
+ prepareCommand: string | null;
87
+ }>[];
88
+ application: Readonly<{
89
+ startCommand: string;
90
+ proofCommand: string;
91
+ environmentFile: string;
92
+ environmentVariables: Readonly<Record<string, string>>;
93
+ readiness: Readonly<{
94
+ url: string;
95
+ expectedStatus: number;
96
+ timeoutSeconds: number;
97
+ }> | null;
98
+ httpProofs: readonly Readonly<{
99
+ name: string;
100
+ kind: "positive" | "negative";
101
+ url: string;
102
+ method: string;
103
+ expectedStatus: number;
104
+ json: Readonly<{
105
+ path: readonly string[];
106
+ equals?: unknown;
107
+ notEquals?: unknown;
108
+ minimumItems?: number;
109
+ }> | null;
110
+ }>[];
111
+ runtimeAdapter: string | null;
112
+ }>;
113
+ runtime: Readonly<{
114
+ target: "postgresql" | "supabase";
115
+ applicationUrl: string;
116
+ projectId: string;
117
+ ports: Readonly<{
118
+ api?: number;
119
+ database: number;
120
+ studio?: number;
121
+ }>;
122
+ }>;
123
+ safety: Readonly<{
124
+ allowedHosts: readonly string[];
125
+ blockedEnvironmentVariables: readonly string[];
126
+ authenticationProviders: readonly string[];
127
+ hostedAccess: "disabled";
128
+ outboundNetwork: "deny";
129
+ }>;
130
+ verification: Readonly<{
131
+ commands: readonly string[];
132
+ }>;
133
+ }>;
134
+ configPath: string;
135
+ projectRoot: string;
136
+ paths: Readonly<{
137
+ artifactDirectory: string;
138
+ applicationEnvironment: string;
139
+ migrationDirectory: string;
140
+ rehearsalConfig: string | null;
141
+ runtimeWorkdir: string;
142
+ serviceEnvironment: string | null;
143
+ sanitizationPolicy: string;
144
+ sourcePolicy: string | null;
145
+ privacyKey: string | null;
146
+ runtimePolicy: string | null;
147
+ identityPolicy: string | null;
148
+ supabaseWorkdir: string | null;
149
+ runtimeAdapter: string | null;
150
+ }>;
151
+ }>;
152
+ plan: import("../identity/claim_contract.mjs").IdentityClaimPlan;
153
+ }>;
154
+ planRuntimeStackCleanup: ({ flags, planOptions, }: ProjectCommandInput) => Promise<RehearsalCleanupPlan | CleanupStackPlan>;
155
+ runBaselinePreparation: ({ flags, planOptions, session, }: ProjectCommandInput) => Promise<ReturnType<typeof summarizeBaselinePreparation>>;
156
+ runCleanup: ({ flags, planOptions, session, }: ProjectCommandInput) => Promise<unknown>;
157
+ runSetup: ({ flags, planOptions, session, }: ProjectCommandInput) => Promise<unknown>;
158
+ }>;
159
+ export {};