@rehearsal-db/core 0.1.0-beta.15 → 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 (102) hide show
  1. package/CHANGELOG.md +34 -1
  2. package/dist/package.json +10 -9
  3. package/dist/src/baseline/privacy_contract.d.mts +147 -0
  4. package/dist/src/baseline/privacy_contract.mjs +2 -0
  5. package/dist/src/baseline/privacy_dependency_graph.d.mts +7 -0
  6. package/dist/src/baseline/privacy_dependency_graph.mjs +110 -0
  7. package/dist/src/baseline/privacy_engine.d.mts +5 -162
  8. package/dist/src/baseline/privacy_engine.mjs +4 -1162
  9. package/dist/src/baseline/privacy_key.d.mts +7 -0
  10. package/dist/src/baseline/privacy_key.mjs +42 -0
  11. package/dist/src/baseline/privacy_pipeline.d.mts +7 -0
  12. package/dist/src/baseline/privacy_pipeline.mjs +127 -0
  13. package/dist/src/baseline/privacy_policy.d.mts +6 -0
  14. package/dist/src/baseline/privacy_policy.mjs +237 -0
  15. package/dist/src/baseline/privacy_recipe_validation.d.mts +5 -0
  16. package/dist/src/baseline/privacy_recipe_validation.mjs +289 -0
  17. package/dist/src/baseline/privacy_rule_registry.d.mts +18 -0
  18. package/dist/src/baseline/privacy_rule_registry.mjs +143 -0
  19. package/dist/src/baseline/privacy_transforms.d.mts +18 -0
  20. package/dist/src/baseline/privacy_transforms.mjs +142 -0
  21. package/dist/src/baseline/privacy_validation_shared.d.mts +31 -0
  22. package/dist/src/baseline/privacy_validation_shared.mjs +127 -0
  23. package/dist/src/cli/application_command_handlers.d.mts +8 -0
  24. package/dist/src/cli/application_command_handlers.mjs +52 -0
  25. package/dist/src/cli/arguments.d.mts +0 -5
  26. package/dist/src/cli/arguments.mjs +0 -7
  27. package/dist/src/cli/basic_command_handlers.d.mts +4 -0
  28. package/dist/src/cli/basic_command_handlers.mjs +56 -0
  29. package/dist/src/cli/cli_commands.d.mts +14 -0
  30. package/dist/src/cli/cli_commands.mjs +32 -0
  31. package/dist/src/cli/command_contract.d.mts +57 -0
  32. package/dist/src/cli/command_contract.mjs +39 -0
  33. package/dist/src/cli/command_output.d.mts +12 -0
  34. package/dist/src/cli/command_output.mjs +20 -0
  35. package/dist/src/cli/command_registry.d.mts +7 -0
  36. package/dist/src/cli/command_registry.mjs +14 -0
  37. package/dist/src/cli/guided.d.mts +3 -1
  38. package/dist/src/cli/guided.mjs +13 -7
  39. package/dist/src/cli/identity_command_handlers.d.mts +8 -0
  40. package/dist/src/cli/identity_command_handlers.mjs +43 -0
  41. package/dist/src/cli/init_command.d.mts +1 -1
  42. package/dist/src/cli/inspection_command_handlers.d.mts +3 -0
  43. package/dist/src/cli/inspection_command_handlers.mjs +79 -0
  44. package/dist/src/cli/project_command_handlers.d.mts +11 -0
  45. package/dist/src/cli/project_command_handlers.mjs +92 -0
  46. package/dist/src/cli/project_commands.d.mts +6 -4
  47. package/dist/src/cli/project_commands.mjs +6 -6
  48. package/dist/src/cli/rehearsal.d.mts +2 -2
  49. package/dist/src/cli/rehearsal.mjs +51 -567
  50. package/dist/src/cli/runtime_action_handlers.d.mts +12 -0
  51. package/dist/src/cli/runtime_action_handlers.mjs +201 -0
  52. package/dist/src/cli/runtime_commands.d.mts +7 -3
  53. package/dist/src/cli/runtime_commands.mjs +10 -8
  54. package/dist/src/cli/source_command_handlers.d.mts +8 -0
  55. package/dist/src/cli/source_command_handlers.mjs +62 -0
  56. package/dist/src/cli/source_commands.d.mts +5 -1
  57. package/dist/src/cli/source_commands.mjs +3 -1
  58. package/dist/src/identity/claim.d.mts +5 -144
  59. package/dist/src/identity/claim.mjs +4 -947
  60. package/dist/src/identity/claim_contract.d.mts +135 -0
  61. package/dist/src/identity/claim_contract.mjs +6 -0
  62. package/dist/src/identity/claim_executor.d.mts +10 -0
  63. package/dist/src/identity/claim_executor.mjs +358 -0
  64. package/dist/src/identity/claim_identity_lookup.d.mts +17 -0
  65. package/dist/src/identity/claim_identity_lookup.mjs +125 -0
  66. package/dist/src/identity/claim_plan.d.mts +8 -0
  67. package/dist/src/identity/claim_plan.mjs +61 -0
  68. package/dist/src/identity/claim_policy.d.mts +3 -0
  69. package/dist/src/identity/claim_policy.mjs +377 -0
  70. package/dist/src/identity/claim_sql.d.mts +10 -0
  71. package/dist/src/identity/claim_sql.mjs +46 -0
  72. package/dist/src/identity/claim_verification.d.mts +13 -0
  73. package/dist/src/identity/claim_verification.mjs +35 -0
  74. package/dist/src/index.d.mts +1 -1
  75. package/dist/src/project/configuration.d.mts +11 -179
  76. package/dist/src/project/configuration.mjs +7 -956
  77. package/dist/src/project/configuration_contract.d.mts +125 -0
  78. package/dist/src/project/configuration_contract.mjs +27 -0
  79. package/dist/src/project/configuration_discovery.d.mts +7 -0
  80. package/dist/src/project/configuration_discovery.mjs +37 -0
  81. package/dist/src/project/configuration_normalization.d.mts +107 -0
  82. package/dist/src/project/configuration_normalization.mjs +302 -0
  83. package/dist/src/project/configuration_rendering.d.mts +14 -0
  84. package/dist/src/project/configuration_rendering.mjs +224 -0
  85. package/dist/src/project/configuration_resolution.d.mts +125 -0
  86. package/dist/src/project/configuration_resolution.mjs +81 -0
  87. package/dist/src/project/configuration_schema.d.mts +22 -0
  88. package/dist/src/project/configuration_schema.mjs +160 -0
  89. package/dist/src/project/configuration_validation.d.mts +22 -0
  90. package/dist/src/project/configuration_validation.mjs +136 -0
  91. package/dist/src/project/project_detection.d.mts +14 -0
  92. package/dist/src/project/project_detection.mjs +47 -0
  93. package/dist/src/runtime/lifecycle_engine.d.mts +63 -0
  94. package/dist/src/runtime/lifecycle_engine.mjs +114 -0
  95. package/dist/src/runtime/plan.mjs +2 -1
  96. package/dist/src/targets/postgresql.mjs +142 -163
  97. package/dist/src/targets/supabase.mjs +142 -174
  98. package/docs/architecture.md +118 -3
  99. package/docs/releasing.md +8 -3
  100. package/docs/typescript.md +57 -10
  101. package/package.json +10 -9
  102. package/types/configuration.d.mts +5 -164
@@ -0,0 +1,201 @@
1
+ /** Database runtime action handlers shared by guided and scripted CLI flows. */
2
+ import * as prompts from "@clack/prompts";
3
+ import { buildApplicationEnvironment, runHttpProofs, startApplicationSession, } from "../application/session.mjs";
4
+ import { exactCommands, renderedCommand, silentCommand, } from "./command_contract.mjs";
5
+ import { topologyCommandEnvironment, topologyEnvironmentFiles, } from "./runtime_commands.mjs";
6
+ import { formatDuration, isHumanTerminal, terminalStyle, useStyledPrompts, } from "./terminal.mjs";
7
+ const RUNTIME_ACTIONS = [
8
+ "run",
9
+ "start",
10
+ "migrate",
11
+ "reset",
12
+ "status",
13
+ "stop",
14
+ "discard",
15
+ "verify",
16
+ ];
17
+ const isRuntimeAction = (command) => RUNTIME_ACTIONS.includes(command);
18
+ export const createRuntimeActionHandlers = ({ prepareCandidateConfirmation, prepareDependentTargets, proveRuntimeStack, runRuntimeStack, }) => [
19
+ {
20
+ ...exactCommands("runtime-action", RUNTIME_ACTIONS, async () => silentCommand()),
21
+ matches: ({ command, flags }) => isRuntimeAction(command) && !(command === "run" && flags.dryRun),
22
+ handle: async ({ command, flags, planOptions, guided, state }) => {
23
+ if (!isRuntimeAction(command)) {
24
+ throw new Error(`Unsupported runtime action: ${command}.`);
25
+ }
26
+ if (flags.dryRun && command !== "run") {
27
+ throw new Error("--dry-run is supported only by rehearsal run.");
28
+ }
29
+ if (!(await prepareCandidateConfirmation({
30
+ command,
31
+ flags,
32
+ planOptions,
33
+ session: state,
34
+ }))) {
35
+ return silentCommand();
36
+ }
37
+ const stack = await runRuntimeStack({
38
+ command,
39
+ flags,
40
+ planOptions,
41
+ session: state,
42
+ });
43
+ const { runtime, topology } = stack;
44
+ const stackEnvironment = topologyCommandEnvironment(topology);
45
+ const preparations = ["run", "reset", "migrate"].includes(command)
46
+ ? prepareDependentTargets({
47
+ topology,
48
+ environment: stackEnvironment,
49
+ })
50
+ : [];
51
+ let applicationProof;
52
+ let dependentProofs = [];
53
+ let httpProofResults = [];
54
+ let applicationReadiness;
55
+ if (command === "run") {
56
+ const applicationConfig = topology.primary.config.application;
57
+ const mappedApplicationEnvironment = Object.keys(applicationConfig.environmentVariables).length
58
+ ? await buildApplicationEnvironment({
59
+ files: topologyEnvironmentFiles(topology),
60
+ mappings: applicationConfig.environmentVariables,
61
+ })
62
+ : {};
63
+ const proofEnvironment = {
64
+ ...stackEnvironment,
65
+ ...mappedApplicationEnvironment,
66
+ };
67
+ const proofLabel = topology.targets.length > 1
68
+ ? "project-owned dependent and application proofs"
69
+ : "project-owned application proof";
70
+ const proofSpinner = useStyledPrompts(flags) ? prompts.spinner() : null;
71
+ if (proofSpinner) {
72
+ proofSpinner.start(`Running the ${proofLabel}.`);
73
+ }
74
+ else if (isHumanTerminal(flags)) {
75
+ console.log(`${terminalStyle(flags, "36", "→")} Running the ${proofLabel}.`);
76
+ }
77
+ let applicationSession;
78
+ try {
79
+ if (applicationConfig.readiness) {
80
+ applicationSession = await startApplicationSession({
81
+ command: applicationConfig.startCommand,
82
+ cwd: topology.projectRoot,
83
+ files: topologyEnvironmentFiles(topology),
84
+ mappings: applicationConfig.environmentVariables,
85
+ readiness: applicationConfig.readiness,
86
+ });
87
+ applicationReadiness = applicationSession.ready;
88
+ }
89
+ ({ applicationProof, dependentProofs } = await proveRuntimeStack({
90
+ topology,
91
+ planOptions,
92
+ environment: proofEnvironment,
93
+ }));
94
+ if (applicationConfig.httpProofs.length) {
95
+ httpProofResults = await runHttpProofs({
96
+ checks: applicationConfig.httpProofs,
97
+ });
98
+ }
99
+ }
100
+ catch (error) {
101
+ if (proofSpinner)
102
+ proofSpinner.stop("A project proof failed.");
103
+ throw error;
104
+ }
105
+ finally {
106
+ await applicationSession?.stop();
107
+ }
108
+ if (proofSpinner) {
109
+ proofSpinner.stop("Project proofs passed.");
110
+ }
111
+ else if (isHumanTerminal(flags)) {
112
+ console.log(`${terminalStyle(flags, "32", "✓")} Project proofs passed.`);
113
+ }
114
+ }
115
+ const data = command === "run"
116
+ ? {
117
+ runtime,
118
+ preparations,
119
+ dependentProofs,
120
+ applicationProof,
121
+ applicationReadiness,
122
+ httpProofResults,
123
+ }
124
+ : preparations.length
125
+ ? { ...runtime, preparations }
126
+ : runtime;
127
+ if (guided) {
128
+ state.lastGuidedDetails = [
129
+ runtime.output,
130
+ ...preparations.map((preparation) => preparation.output),
131
+ ...dependentProofs.map((proof) => proof.output),
132
+ applicationProof?.output,
133
+ ]
134
+ .filter(Boolean)
135
+ .join("\n");
136
+ }
137
+ return renderedCommand({
138
+ data,
139
+ render: (value) => {
140
+ const runtimeResult = "runtime" in value ? value.runtime : value;
141
+ const renderedPreparations = "preparations" in value ? value.preparations : [];
142
+ const renderedDependentProofs = "dependentProofs" in value ? value.dependentProofs : [];
143
+ const renderedApplicationProof = "applicationProof" in value ? value.applicationProof : undefined;
144
+ const renderedApplicationReadiness = "applicationReadiness" in value
145
+ ? value.applicationReadiness
146
+ : undefined;
147
+ const renderedHttpProofResults = "httpProofResults" in value ? value.httpProofResults : [];
148
+ const nextAction = {
149
+ run: "Next: run rehearsal open for hands-on testing, then rehearsal verify.",
150
+ start: "Next: run rehearsal open for hands-on testing or rehearsal status.",
151
+ migrate: "Next: run rehearsal verify to prove the current runtime.",
152
+ reset: "Next: run rehearsal open or rehearsal verify.",
153
+ status: "Next: run rehearsal verify, reset, stop, or discard.",
154
+ stop: "Next: run rehearsal start when you want to resume.",
155
+ discard: "The disposable runtime was removed; the immutable baseline remains.",
156
+ verify: "Next: continue testing, reset to the baseline, or stop the runtime.",
157
+ }[runtimeResult.action];
158
+ if (guided) {
159
+ const title = runtimeResult.action === "run"
160
+ ? "REHEARSAL PASSED"
161
+ : "ACTION COMPLETE";
162
+ return [
163
+ title,
164
+ `✓ ${runtimeResult.action} completed in ${formatDuration(runtimeResult.durationMs)}`,
165
+ ...renderedPreparations.map((preparation) => `✓ ${preparation.target} preparation passed: ${preparation.command}`),
166
+ ...renderedDependentProofs.map((proof) => `✓ ${proof.target} proof passed: ${proof.command}`),
167
+ renderedApplicationProof
168
+ ? `✓ Application proof passed: ${renderedApplicationProof.command}`
169
+ : null,
170
+ renderedApplicationReadiness
171
+ ? `✓ Application became ready at ${renderedApplicationReadiness.url}`
172
+ : null,
173
+ ...renderedHttpProofResults.map((proof) => `✓ ${proof.kind} HTTP proof passed: ${proof.name}`),
174
+ "",
175
+ "Technical output is available from Show details in the guide.",
176
+ ]
177
+ .filter(Boolean)
178
+ .join("\n");
179
+ }
180
+ return [
181
+ runtimeResult.output ||
182
+ `Rehearsal ${runtimeResult.action} completed.`,
183
+ ...renderedPreparations.map((preparation) => `${preparation.target} preparation passed: ${preparation.command}`),
184
+ ...renderedDependentProofs.map((proof) => `${proof.target} proof passed: ${proof.command}`),
185
+ renderedApplicationProof
186
+ ? `Application proof passed: ${renderedApplicationProof.command}`
187
+ : null,
188
+ renderedApplicationReadiness
189
+ ? `Application readiness passed: ${renderedApplicationReadiness.url}`
190
+ : null,
191
+ ...renderedHttpProofResults.map((proof) => `${proof.kind} HTTP proof passed: ${proof.name}`),
192
+ nextAction ? "" : null,
193
+ nextAction,
194
+ ]
195
+ .filter((entry) => entry !== null)
196
+ .join("\n");
197
+ },
198
+ });
199
+ },
200
+ },
201
+ ];
@@ -10,6 +10,7 @@ import type { RuntimeTopologyTarget } from "../runtime/topology.mjs";
10
10
  import type { InstalledPackageFingerprint } from "../shared/operation_guard.mjs";
11
11
  import type { RehearsalCliFlags } from "./arguments.mjs";
12
12
  import type { RehearsalErrorCategory } from "../shared/diagnostics.mjs";
13
+ import type { CliSessionState } from "./command_contract.mjs";
13
14
  type RuntimeTopology = Awaited<ReturnType<typeof loadRuntimeTopology>>;
14
15
  type RuntimeAction = "run" | "start" | "migrate" | "reset" | "status" | "stop" | "discard" | "verify";
15
16
  interface ManagerReceipt {
@@ -188,9 +189,10 @@ export declare const createRuntimeCommands: ({ packageRoot, projectRoot, manager
188
189
  managerPath: string;
189
190
  getActivePackageFingerprint: () => InstalledPackageFingerprint | undefined;
190
191
  }) => {
191
- openRuntimeApplication: ({ flags, planOptions, onReady, }: {
192
+ openRuntimeApplication: ({ flags, planOptions, session: commandSession, onReady, }: {
192
193
  flags: RehearsalCliFlags;
193
194
  planOptions: RehearsalConfigPathOptions;
195
+ session: CliSessionState;
194
196
  onReady?: Parameters<typeof holdApplicationSession>[0]["onReady"];
195
197
  }) => Promise<{
196
198
  action: string;
@@ -221,10 +223,11 @@ export declare const createRuntimeCommands: ({ packageRoot, projectRoot, manager
221
223
  diagnostics: import("../application/session.mjs").ApplicationDiagnostics;
222
224
  };
223
225
  }>;
224
- prepareCandidateConfirmation: ({ command, flags, planOptions, }: {
226
+ prepareCandidateConfirmation: ({ command, flags, planOptions, session, }: {
225
227
  command: RuntimeAction;
226
228
  flags: RehearsalCliFlags;
227
229
  planOptions: RehearsalConfigPathOptions;
230
+ session: CliSessionState;
228
231
  }) => Promise<boolean>;
229
232
  prepareDependentTargets: ({ topology, environment, }: {
230
233
  topology: RuntimeTopology;
@@ -256,10 +259,11 @@ export declare const createRuntimeCommands: ({ packageRoot, projectRoot, manager
256
259
  confirmation?: string;
257
260
  targetName?: string;
258
261
  }) => ManagerReceipt;
259
- runRuntimeStack: ({ command, flags, planOptions, }: {
262
+ runRuntimeStack: ({ command, flags, planOptions, session, }: {
260
263
  command: RuntimeAction;
261
264
  flags: RehearsalCliFlags;
262
265
  planOptions: RehearsalConfigPathOptions;
266
+ session: CliSessionState;
263
267
  }) => Promise<RuntimeStackResult>;
264
268
  };
265
269
  export {};
@@ -403,15 +403,15 @@ export const createRuntimeCommands = ({ packageRoot, projectRoot, managerPath, g
403
403
  output: String(redactDiagnosticValue(String(result.stdout ?? "").trim())),
404
404
  };
405
405
  };
406
- const runRuntimeStack = async ({ command, flags, planOptions, }) => {
407
- const topology = flags.runtimeTopology ??
406
+ const runRuntimeStack = async ({ command, flags, planOptions, session, }) => {
407
+ const topology = session.runtimeTopology ??
408
408
  (await loadRuntimeTopology(planOptions));
409
409
  const reverse = ["stop", "discard"].includes(command);
410
410
  const targets = reverse
411
411
  ? [...topology.targets].reverse()
412
412
  : topology.targets;
413
413
  const results = targets.map((target) => {
414
- const confirmation = flags.targetConfirmations?.get(target.configPath);
414
+ const confirmation = session.targetConfirmations?.get(target.configPath);
415
415
  return runManager({
416
416
  action: command,
417
417
  flags,
@@ -479,7 +479,7 @@ export const createRuntimeCommands = ({ packageRoot, projectRoot, managerPath, g
479
479
  });
480
480
  return { applicationProof, dependentProofs };
481
481
  };
482
- const openRuntimeApplication = async ({ flags, planOptions, onReady = () => undefined, }) => {
482
+ const openRuntimeApplication = async ({ flags, planOptions, session: commandSession, onReady = () => undefined, }) => {
483
483
  const topology = await loadRuntimeTopology(planOptions);
484
484
  const application = topology.primary.config.application;
485
485
  if (!application.readiness) {
@@ -498,16 +498,18 @@ export const createRuntimeCommands = ({ packageRoot, projectRoot, managerPath, g
498
498
  if (runtimeReceipts.some((present) => !present)) {
499
499
  throw new Error("rehearsal open requires an existing verified runtime. Run rehearsal run first.");
500
500
  }
501
- flags.runtimeTopology = topology;
501
+ commandSession.runtimeTopology = topology;
502
502
  const started = await runRuntimeStack({
503
503
  command: "start",
504
504
  flags,
505
505
  planOptions,
506
+ session: commandSession,
506
507
  });
507
508
  const verified = await runRuntimeStack({
508
509
  command: "verify",
509
510
  flags,
510
511
  planOptions,
512
+ session: commandSession,
511
513
  });
512
514
  const preparations = prepareDependentTargets({
513
515
  topology,
@@ -534,12 +536,12 @@ export const createRuntimeCommands = ({ packageRoot, projectRoot, managerPath, g
534
536
  },
535
537
  };
536
538
  };
537
- const prepareCandidateConfirmation = async ({ command, flags, planOptions, }) => {
539
+ const prepareCandidateConfirmation = async ({ command, flags, planOptions, session, }) => {
538
540
  if (!["run", "migrate"].includes(command) || flags.dryRun)
539
541
  return true;
540
542
  const summary = await topologyCandidateSummary(planOptions);
541
- flags.runtimeTopology = summary.topology;
542
- flags.targetConfirmations = new Map(summary.targets.map((target) => [
543
+ session.runtimeTopology = summary.topology;
544
+ session.targetConfirmations = new Map(summary.targets.map((target) => [
543
545
  target.configPath,
544
546
  target.candidateSha256,
545
547
  ]));
@@ -0,0 +1,8 @@
1
+ /** Temporary source-access and privacy-safe baseline refresh command handlers. */
2
+ import { createRefreshWorkflow } from "./source_commands.mjs";
3
+ import type { CommandDefinition } from "./command_contract.mjs";
4
+ type RefreshWorkflow = ReturnType<typeof createRefreshWorkflow>;
5
+ export declare const createSourceCommandHandlers: ({ runRefreshWorkflow, }: {
6
+ runRefreshWorkflow: RefreshWorkflow;
7
+ }) => readonly CommandDefinition[];
8
+ export {};
@@ -0,0 +1,62 @@
1
+ /** Temporary source-access and privacy-safe baseline refresh command handlers. */
2
+ import { createSourceAccessPlan } from "../source/access.mjs";
3
+ import { formatCount } from "../shared/human_output.mjs";
4
+ import { createRefreshWorkflow, loadPreparationContext, runSourceAccess, runSourceBaselineRefresh, runSourceRetirement, } from "./source_commands.mjs";
5
+ import { formatBytes, renderRefreshWorkflow, renderSourceAccessPlan, renderSourceRetirement, } from "./renderers.mjs";
6
+ import { exactCommands, renderedCommand } from "./command_contract.mjs";
7
+ export const createSourceCommandHandlers = ({ runRefreshWorkflow, }) => [
8
+ exactCommands("source-plan", ["source plan"], async ({ flags, planOptions }) => {
9
+ const { sourcePolicy } = await loadPreparationContext(planOptions);
10
+ const data = createSourceAccessPlan({ policy: sourcePolicy });
11
+ return renderedCommand({
12
+ data,
13
+ render: renderSourceAccessPlan,
14
+ });
15
+ }),
16
+ exactCommands("source-apply", ["source apply"], async ({ flags, planOptions }) => {
17
+ const data = await runSourceAccess({ flags, planOptions });
18
+ return renderedCommand({
19
+ data,
20
+ render: (result) => result.mode === "preview"
21
+ ? renderSourceAccessPlan(result.plan)
22
+ : [
23
+ "SOURCE ACCESS — READY",
24
+ `${result.receipt.accessMode === "external" ? "External" : "Temporary"} reader expires: ${result.receipt.expiresAt}`,
25
+ result.receipt.accessMode === "external"
26
+ ? "Rehearsal made no source-side changes."
27
+ : "Rehearsal created only the reviewed temporary source access.",
28
+ `Local credential: ${result.credentialFile}`,
29
+ "",
30
+ "Next: run rehearsal baseline refresh, then retire source access.",
31
+ ].join("\n"),
32
+ });
33
+ }),
34
+ exactCommands("source-retire", ["source retire"], async ({ flags, planOptions }) => {
35
+ const data = await runSourceRetirement({ flags, planOptions });
36
+ return renderedCommand({ data, render: renderSourceRetirement });
37
+ }),
38
+ exactCommands("baseline-refresh", ["baseline refresh"], async ({ flags, planOptions }) => {
39
+ const data = await runSourceBaselineRefresh({ planOptions });
40
+ return renderedCommand({
41
+ data,
42
+ render: (result) => [
43
+ `Activated refreshed baseline ${result.generationId}.`,
44
+ `${formatCount(result.manifest.rowCount, "sanitized row")} across ${formatCount(Object.keys(result.manifest.tableCounts).length, "table")}.`,
45
+ `Source estimate: ${formatCount(result.estimate.rows, "row")}, ${formatBytes(result.estimate.bytes)}.`,
46
+ "",
47
+ "Next: run rehearsal source retire, then rehearsal doctor.",
48
+ ].join("\n"),
49
+ });
50
+ }),
51
+ exactCommands("refresh", ["refresh"], async ({ flags, planOptions, state }) => {
52
+ const data = await runRefreshWorkflow({
53
+ flags,
54
+ planOptions,
55
+ session: state,
56
+ });
57
+ return renderedCommand({
58
+ data,
59
+ render: (result) => renderRefreshWorkflow(result),
60
+ });
61
+ }),
62
+ ];
@@ -4,6 +4,7 @@
4
4
  */
5
5
  import type { RehearsalConfigPathOptions } from "../project/configuration.mjs";
6
6
  import type { RehearsalCliFlags } from "./arguments.mjs";
7
+ import type { CliSessionState } from "./command_contract.mjs";
7
8
  import { loadRuntimeTopology } from "../runtime/topology.mjs";
8
9
  import type { RuntimeTopologyTarget } from "../runtime/topology.mjs";
9
10
  type RuntimeTopology = Awaited<ReturnType<typeof loadRuntimeTopology>>;
@@ -327,6 +328,7 @@ export declare const createRefreshWorkflow: ({ runRuntimeStack, prepareDependent
327
328
  command: "reset";
328
329
  flags: RehearsalCliFlags;
329
330
  planOptions: RehearsalConfigPathOptions;
331
+ session: CliSessionState;
330
332
  }) => Promise<{
331
333
  runtime: unknown;
332
334
  topology: RuntimeTopology;
@@ -338,7 +340,9 @@ export declare const createRefreshWorkflow: ({ runRuntimeStack, prepareDependent
338
340
  topologyCommandEnvironment: (topology: RuntimeTopology) => NodeJS.ProcessEnv;
339
341
  buildPlan?: (options: RehearsalConfigPathOptions) => Promise<RefreshPlanContext>;
340
342
  refreshBaseline?: typeof runSourceBaselineRefresh;
341
- }) => ({ flags, planOptions }: SourceCommandInput) => Promise<{
343
+ }) => ({ flags, planOptions, session, }: SourceCommandInput & {
344
+ session: CliSessionState;
345
+ }) => Promise<{
342
346
  mode: "preview";
343
347
  plan: {
344
348
  review: {
@@ -224,7 +224,7 @@ export const buildRefreshWorkflowPlan = async (planOptions) => {
224
224
  },
225
225
  };
226
226
  };
227
- export const createRefreshWorkflow = ({ runRuntimeStack, prepareDependentTargets, topologyCommandEnvironment, buildPlan = buildRefreshWorkflowPlan, refreshBaseline = runSourceBaselineRefresh, }) => async ({ flags, planOptions }) => {
227
+ export const createRefreshWorkflow = ({ runRuntimeStack, prepareDependentTargets, topologyCommandEnvironment, buildPlan = buildRefreshWorkflowPlan, refreshBaseline = runSourceBaselineRefresh, }) => async ({ flags, planOptions, session, }) => {
228
228
  const context = await buildPlan(planOptions);
229
229
  if (!flags.refreshConfirmation) {
230
230
  return { mode: "preview", plan: context.plan };
@@ -241,6 +241,7 @@ export const createRefreshWorkflow = ({ runRuntimeStack, prepareDependentTargets
241
241
  command: "reset",
242
242
  flags,
243
243
  planOptions,
244
+ session,
244
245
  });
245
246
  runtime = stack.runtime;
246
247
  preparations = prepareDependentTargets({
@@ -259,6 +260,7 @@ export const createRefreshWorkflow = ({ runRuntimeStack, prepareDependentTargets
259
260
  command: "reset",
260
261
  flags,
261
262
  planOptions,
263
+ session,
262
264
  });
263
265
  prepareDependentTargets({
264
266
  topology: rollback.topology,
@@ -1,144 +1,5 @@
1
- /** Associate a reviewed copied owner graph with one verified local Auth identity. */
2
- import type { SupabaseStorageTransfer } from "./storage.mjs";
3
- declare const SUPPORTED_IDENTITY_PROVIDERS: readonly ["email", "github", "google"];
4
- type JsonObject = Record<string, unknown>;
5
- type IdentityProvider = (typeof SUPPORTED_IDENTITY_PROVIDERS)[number];
6
- type SubjectIdentityProvider = Exclude<IdentityProvider, "email">;
7
- type IdentityStrategy = "transfer" | "preserve-audit";
8
- type PathValueType = "text" | "jsonb";
9
- interface Relation {
10
- readonly schema: string;
11
- readonly table: string;
12
- }
13
- interface PatternDefaultMatcher {
14
- readonly kind: "pattern";
15
- readonly pattern: string;
16
- }
17
- interface ExactDefaultMatcher {
18
- readonly kind: "exact";
19
- readonly value: unknown;
20
- }
21
- type SignupDefaultMatcher = PatternDefaultMatcher | ExactDefaultMatcher;
22
- interface VerifiedEmailMatcher {
23
- readonly type: "verified-email";
24
- readonly providers: readonly IdentityProvider[];
25
- readonly emailEnvironmentVariable: string;
26
- readonly approvedEmailSha256: string;
27
- }
28
- interface ProviderSubjectMatcher {
29
- readonly type: "provider-subject";
30
- readonly provider: SubjectIdentityProvider;
31
- readonly subjectEnvironmentVariable: string;
32
- readonly approvedSubjectSha256: string;
33
- }
34
- type IdentityMatcher = VerifiedEmailMatcher | ProviderSubjectMatcher;
35
- interface IdentityReference extends Relation {
36
- readonly column: string;
37
- readonly required: boolean;
38
- readonly strategy: IdentityStrategy;
39
- }
40
- interface JsonIdentityReference extends Relation {
41
- readonly column: string;
42
- readonly path: readonly string[];
43
- }
44
- interface SignupDefaultDeclaration {
45
- readonly table: Relation;
46
- readonly identityColumn: string;
47
- readonly ignoredColumns: readonly string[];
48
- readonly values: Readonly<Record<string, SignupDefaultMatcher>>;
49
- }
50
- interface PathIdentityReference extends Relation {
51
- readonly column: string;
52
- readonly valueType: PathValueType;
53
- }
54
- interface IdentityAsset {
55
- readonly bucket: string;
56
- readonly prefix: string;
57
- readonly rewritePath: boolean;
58
- }
59
- interface IdentityTokenHook {
60
- readonly function: Readonly<{
61
- schema: string;
62
- name: string;
63
- }>;
64
- readonly expectedClaims: JsonObject;
65
- }
66
- export interface IdentityDeclaration {
67
- readonly name: string;
68
- readonly matcher: IdentityMatcher;
69
- readonly placeholderUserId: string;
70
- readonly references: readonly IdentityReference[];
71
- readonly jsonReferences: readonly JsonIdentityReference[];
72
- readonly signupDefaults: readonly SignupDefaultDeclaration[];
73
- readonly pathReferences: readonly PathIdentityReference[];
74
- readonly assets: readonly IdentityAsset[];
75
- readonly claims: JsonObject;
76
- readonly tokenHook: IdentityTokenHook | null;
77
- }
78
- export interface IdentityPolicy {
79
- readonly identityVersion: 1;
80
- readonly identities: readonly IdentityDeclaration[];
81
- }
82
- interface IdentityClaimReview {
83
- readonly planVersion: 3;
84
- readonly operation: "claim-local-identity";
85
- readonly name: string;
86
- readonly matcher: IdentityMatcher;
87
- readonly placeholderUserId: string;
88
- readonly references: readonly IdentityReference[];
89
- readonly jsonReferences: readonly JsonIdentityReference[];
90
- readonly signupDefaults: readonly Readonly<{
91
- table: Relation;
92
- identityColumn: string;
93
- ignoredColumns: readonly string[];
94
- valuesSha256: string;
95
- }>[];
96
- readonly pathReferences: readonly PathIdentityReference[];
97
- readonly assets: readonly IdentityAsset[];
98
- readonly claimKeys: readonly string[];
99
- readonly claimsSha256: string;
100
- readonly tokenHook: Readonly<{
101
- function: Readonly<{
102
- schema: string;
103
- name: string;
104
- }>;
105
- expectedClaimsSha256: string;
106
- }> | null;
107
- }
108
- export interface IdentityClaimPlan {
109
- readonly identity: IdentityDeclaration;
110
- readonly review: Readonly<IdentityClaimReview>;
111
- readonly digest: string;
112
- }
113
- interface QueryResult<Row extends JsonObject = JsonObject> {
114
- readonly rows: Row[];
115
- }
116
- interface IdentityDatabaseClient {
117
- connect?(): Promise<void>;
118
- end?(): Promise<void>;
119
- query<Row extends JsonObject = JsonObject>(sql: string, parameters?: readonly unknown[]): Promise<QueryResult<Row>>;
120
- }
121
- type IdentityClientFactory = (connectionString: string) => IdentityDatabaseClient | Promise<IdentityDatabaseClient>;
122
- export declare const validateIdentityPolicy: (policy: unknown) => IdentityPolicy;
123
- export declare const createIdentityClaimPlan: ({ policy, name, environment, }: {
124
- policy: unknown;
125
- name: string;
126
- environment?: Readonly<Record<string, string | undefined>>;
127
- }) => IdentityClaimPlan;
128
- export declare const applyIdentityClaim: ({ plan, confirmation, connectionString, clientFactory, storageTransfer, }: {
129
- plan: IdentityClaimPlan;
130
- confirmation: string;
131
- connectionString: string;
132
- clientFactory?: IdentityClientFactory;
133
- storageTransfer?: SupabaseStorageTransfer;
134
- }) => Promise<{
135
- name: string;
136
- provider: IdentityProvider;
137
- claimed: true;
138
- removedSignupDefaults: number;
139
- tokenHookVerified: boolean;
140
- placeholderRetainedForAudit: boolean;
141
- storageObjectsTransferred: number;
142
- idempotent: boolean;
143
- }>;
144
- export {};
1
+ /** Stable public facade for local identity claim planning and execution. */
2
+ export type { IdentityClaimPlan, IdentityDeclaration, IdentityPolicy, } from "./claim_contract.mjs";
3
+ export { applyIdentityClaim } from "./claim_executor.mjs";
4
+ export { createIdentityClaimPlan } from "./claim_plan.mjs";
5
+ export { validateIdentityPolicy } from "./claim_policy.mjs";