@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
@@ -1,177 +0,0 @@
1
- /** Render reviewed local OAuth declarations into the disposable Supabase runtime. */
2
-
3
- const escapePattern = (value) =>
4
- value.replaceAll(/[.*+?^${}()|[\]\\]/gu, "\\$&");
5
-
6
- const LEGACY_PROVIDER_KEYS = new Set([
7
- "client_id",
8
- "email_optional",
9
- "enabled",
10
- "redirect_uri",
11
- "secret",
12
- "skip_nonce_check",
13
- ]);
14
- const SAFE_BOOLEAN_PROVIDER_KEYS = new Set([
15
- "email_optional",
16
- "skip_nonce_check",
17
- ]);
18
-
19
- const readTomlSections = (source) => {
20
- const lines = source.split("\n");
21
- const sections = [];
22
- for (let index = 0; index < lines.length; index += 1) {
23
- const match = /^\s*\[([^\]]+)\]\s*(?:#.*)?$/u.exec(lines[index]);
24
- if (!match) continue;
25
- if (sections.length) sections.at(-1).end = index;
26
- sections.push({ name: match[1], start: index, end: lines.length });
27
- }
28
- return { lines, sections };
29
- };
30
-
31
- const validateLegacyProviderSection = ({ lines, section, provider }) => {
32
- const seen = new Set();
33
- for (const line of lines.slice(section.start + 1, section.end)) {
34
- if (!line.trim() || /^\s*#/u.test(line)) continue;
35
- const assignment = /^\s*([A-Za-z0-9_]+)\s*=/u.exec(line);
36
- if (!assignment || !LEGACY_PROVIDER_KEYS.has(assignment[1])) {
37
- throw new Error(
38
- `The local Supabase template auth.external.${provider.name} section contains an unsupported setting. Rehearsal left the tracked template unchanged.`,
39
- );
40
- }
41
- const key = assignment[1];
42
- if (seen.has(key)) {
43
- throw new Error(
44
- `The local Supabase template auth.external.${provider.name} section contains duplicate ${key} settings.`,
45
- );
46
- }
47
- seen.add(key);
48
- if (
49
- SAFE_BOOLEAN_PROVIDER_KEYS.has(key) &&
50
- !new RegExp(
51
- `^\\s*${escapePattern(key)}\\s*=\\s*${
52
- key === "skip_nonce_check"
53
- ? (provider.skipNonceCheck ?? false)
54
- : (provider.emailOptional ?? false)
55
- }\\s*(?:#.*)?$`,
56
- "u",
57
- ).test(line)
58
- ) {
59
- throw new Error(
60
- `The local Supabase template auth.external.${provider.name}.${key} setting must match its explicit declarative authentication option before Rehearsal can replace the legacy provider in its disposable runtime copy.`,
61
- );
62
- }
63
- }
64
- };
65
-
66
- export const inspectSupabaseAuthenticationProviderTransition = ({
67
- source,
68
- authentication,
69
- }) => {
70
- if (!authentication) return Object.freeze({ replacedProviders: [] });
71
- const { lines, sections } = readTomlSections(source);
72
- const replacementSections = [];
73
- for (const provider of authentication.providers) {
74
- const sectionName = `auth.external.${provider.name}`;
75
- const nested = sections.filter((section) =>
76
- section.name.startsWith(`${sectionName}.`),
77
- );
78
- if (nested.length) {
79
- throw new Error(
80
- `The local Supabase template contains unsupported nested ${sectionName} configuration. Rehearsal left the tracked template unchanged.`,
81
- );
82
- }
83
- const matching = sections.filter((section) => section.name === sectionName);
84
- if (matching.length > 1) {
85
- throw new Error(
86
- `The local Supabase template declares ${sectionName} more than once.`,
87
- );
88
- }
89
- if (matching.length === 1) {
90
- validateLegacyProviderSection({
91
- lines,
92
- section: matching[0],
93
- provider,
94
- });
95
- replacementSections.push({ ...matching[0], provider: provider.name });
96
- }
97
- }
98
- return Object.freeze({
99
- replacedProviders: Object.freeze(
100
- replacementSections.map(({ provider }) => provider),
101
- ),
102
- replacementSections: Object.freeze(replacementSections),
103
- });
104
- };
105
-
106
- export const renderSupabaseAuthenticationProviders = ({
107
- authentication,
108
- apiPort,
109
- }) => {
110
- if (!authentication) return "";
111
- return authentication.providers
112
- .map(
113
- (
114
- provider,
115
- ) => `# Generated by Rehearsal from config.supabase.authentication.
116
- [auth.external.${provider.name}]
117
- enabled = true
118
- client_id = "env(${provider.clientIdEnvironmentVariable})"
119
- secret = "env(${provider.clientSecretEnvironmentVariable})"
120
- redirect_uri = "http://127.0.0.1:${apiPort}/auth/v1/callback"
121
- ${provider.skipNonceCheck ? "skip_nonce_check = true\n" : ""}${provider.emailOptional ? "email_optional = true\n" : ""}
122
- `,
123
- )
124
- .join("\n");
125
- };
126
-
127
- const enableLocalSignup = (source) => {
128
- const lines = source.split("\n");
129
- let inAuth = false;
130
- let authSections = 0;
131
- let signupSettings = 0;
132
- const updated = lines.map((line) => {
133
- const section = /^\s*\[([^\]]+)\]\s*(?:#.*)?$/u.exec(line);
134
- if (section) {
135
- inAuth = section[1] === "auth";
136
- if (inAuth) authSections += 1;
137
- return line;
138
- }
139
- if (!inAuth || !/^\s*enable_signup\s*=/u.test(line)) return line;
140
- signupSettings += 1;
141
- const comment = line.match(/\s+#.*$/u)?.[0] ?? "";
142
- return `enable_signup = true${comment}`;
143
- });
144
- if (authSections !== 1 || signupSettings !== 1) {
145
- throw new Error(
146
- "The local Supabase template must declare exactly one [auth] section with one enable_signup setting before Rehearsal can configure OAuth.",
147
- );
148
- }
149
- return updated.join("\n");
150
- };
151
-
152
- export const applySupabaseAuthenticationProviders = ({
153
- source,
154
- authentication,
155
- apiPort,
156
- }) => {
157
- if (!authentication) return source;
158
- const transition = inspectSupabaseAuthenticationProviderTransition({
159
- source,
160
- authentication,
161
- });
162
- const { lines } = readTomlSections(source);
163
- const replacedIndexes = new Set(
164
- transition.replacementSections.flatMap((section) =>
165
- Array.from(
166
- { length: section.end - section.start },
167
- (_, offset) => section.start + offset,
168
- ),
169
- ),
170
- );
171
- const transitionedSource = lines
172
- .filter((_, index) => !replacedIndexes.has(index))
173
- .join("\n");
174
- const runtimeSource = enableLocalSignup(transitionedSource);
175
- const separator = runtimeSource.endsWith("\n") ? "\n" : "\n\n";
176
- return `${runtimeSource}${separator}${renderSupabaseAuthenticationProviders({ authentication, apiPort })}`;
177
- };
@@ -1,165 +0,0 @@
1
- /** Copy and verify local Supabase Storage objects during an identity claim. */
2
-
3
- import { createHash } from "node:crypto";
4
- import { assertLoopbackUrl } from "../shared/process_environment.mjs";
5
-
6
- const BUCKET = /^[a-z0-9][a-z0-9.-]{0,99}$/u;
7
- const MAXIMUM_VERIFICATION_BYTES = 100 * 1024 * 1024;
8
- const REQUEST_TIMEOUT_MS = 30_000;
9
-
10
- const objectPath = (value) => {
11
- if (
12
- typeof value !== "string" ||
13
- !value ||
14
- value.startsWith("/") ||
15
- value.split("/").some((part) => !part || part === "." || part === "..")
16
- ) {
17
- throw new Error("A Storage identity-claim path is unsafe.");
18
- }
19
- return value.split("/").map(encodeURIComponent).join("/");
20
- };
21
-
22
- const readVerifiedObject = async ({
23
- fetchImpl,
24
- baseUrl,
25
- headers,
26
- bucket,
27
- path,
28
- }) => {
29
- const response = await fetchImpl(
30
- `${baseUrl}/storage/v1/object/${encodeURIComponent(bucket)}/${objectPath(path)}?rehearsal=${Date.now()}`,
31
- {
32
- headers,
33
- cache: "no-store",
34
- signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
35
- },
36
- );
37
- if (!response.ok) {
38
- throw new Error(
39
- `Supabase Storage could not read an identity-claim object (HTTP ${response.status}).`,
40
- );
41
- }
42
- const declaredBytes = Number(response.headers.get("content-length"));
43
- if (
44
- Number.isFinite(declaredBytes) &&
45
- declaredBytes > MAXIMUM_VERIFICATION_BYTES
46
- ) {
47
- throw new Error(
48
- "A Storage identity-claim object exceeds the 100 MiB verification limit.",
49
- );
50
- }
51
- const bytes = Buffer.from(await response.arrayBuffer());
52
- if (bytes.length > MAXIMUM_VERIFICATION_BYTES) {
53
- throw new Error(
54
- "A Storage identity-claim object exceeds the 100 MiB verification limit.",
55
- );
56
- }
57
- return Object.freeze({
58
- bytes: bytes.length,
59
- sha256: createHash("sha256").update(bytes).digest("hex"),
60
- });
61
- };
62
-
63
- export const createSupabaseStorageTransfer = ({
64
- url,
65
- serviceRoleKey,
66
- fetchImpl = globalThis.fetch,
67
- }) => {
68
- assertLoopbackUrl("Rehearsal Supabase Storage", url);
69
- if (typeof serviceRoleKey !== "string" || !serviceRoleKey) {
70
- throw new Error(
71
- "The local runtime environment has no Storage service key.",
72
- );
73
- }
74
- if (typeof fetchImpl !== "function") {
75
- throw new Error("A Fetch implementation is required for Storage transfer.");
76
- }
77
- const baseUrl = url.replace(/\/$/u, "");
78
- const headers = Object.freeze({
79
- apikey: serviceRoleKey,
80
- authorization: `Bearer ${serviceRoleKey}`,
81
- });
82
- const removePaths = async ({ bucket, paths }) => {
83
- if (!BUCKET.test(bucket ?? "") || !Array.isArray(paths) || !paths.length) {
84
- throw new Error("A Storage identity-claim removal is invalid.");
85
- }
86
- paths.forEach(objectPath);
87
- const response = await fetchImpl(
88
- `${baseUrl}/storage/v1/object/${encodeURIComponent(bucket)}`,
89
- {
90
- method: "DELETE",
91
- headers: { ...headers, "content-type": "application/json" },
92
- body: JSON.stringify({ prefixes: paths }),
93
- signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
94
- },
95
- );
96
- if (!response.ok) {
97
- throw new Error(
98
- `Supabase Storage could not remove identity-claim objects (HTTP ${response.status}).`,
99
- );
100
- }
101
- };
102
- return Object.freeze({
103
- async copyAndVerify({ bucket, source, destination }) {
104
- if (!BUCKET.test(bucket ?? "")) {
105
- throw new Error("A Storage identity-claim bucket is invalid.");
106
- }
107
- objectPath(source);
108
- objectPath(destination);
109
- if (source === destination) {
110
- throw new Error("A Storage identity-claim copy must change the path.");
111
- }
112
- const sourceReceipt = await readVerifiedObject({
113
- fetchImpl,
114
- baseUrl,
115
- headers,
116
- bucket,
117
- path: source,
118
- });
119
- try {
120
- const response = await fetchImpl(`${baseUrl}/storage/v1/object/copy`, {
121
- method: "POST",
122
- headers: { ...headers, "content-type": "application/json" },
123
- body: JSON.stringify({
124
- bucketId: bucket,
125
- sourceKey: source,
126
- destinationKey: destination,
127
- }),
128
- signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
129
- });
130
- if (!response.ok) {
131
- throw new Error(
132
- `Supabase Storage could not copy an identity-claim object (HTTP ${response.status}).`,
133
- );
134
- }
135
- const destinationReceipt = await readVerifiedObject({
136
- fetchImpl,
137
- baseUrl,
138
- headers,
139
- bucket,
140
- path: destination,
141
- });
142
- if (
143
- sourceReceipt.bytes !== destinationReceipt.bytes ||
144
- sourceReceipt.sha256 !== destinationReceipt.sha256
145
- ) {
146
- throw new Error(
147
- "Supabase Storage copied an identity object with a different byte digest.",
148
- );
149
- }
150
- return destinationReceipt;
151
- } catch (error) {
152
- try {
153
- await removePaths({ bucket, paths: [destination] });
154
- } catch (cleanupError) {
155
- throw new AggregateError(
156
- [error, cleanupError],
157
- "Storage identity-copy verification failed and destination cleanup needs attention.",
158
- );
159
- }
160
- throw error;
161
- }
162
- },
163
- remove: removePaths,
164
- });
165
- };
@@ -1,164 +0,0 @@
1
- export type RehearsalConfigVersion = 1;
2
-
3
- export interface RehearsalConfig {
4
- schemaVersion: RehearsalConfigVersion;
5
- project: { name: string };
6
- supabase?: {
7
- workdir: string;
8
- migrationDirectory: string;
9
- rehearsalConfig: string;
10
- runtimeWorkdir: string;
11
- authentication?: {
12
- enableLocalSignup: true;
13
- environmentFile: string;
14
- providers: Array<{
15
- name: "google" | "github";
16
- clientIdEnvironmentVariable: string;
17
- clientSecretEnvironmentVariable: string;
18
- skipNonceCheck?: boolean;
19
- emailOptional?: boolean;
20
- }>;
21
- };
22
- serviceEnvironmentFile?: string;
23
- serviceEnvironmentVariables?: string[];
24
- };
25
- postgresql?: {
26
- migrationDirectory: string;
27
- runtimeWorkdir?: string;
28
- image?: string;
29
- database?: string;
30
- user?: string;
31
- };
32
- baseline: {
33
- artifactDirectory?: string;
34
- sanitizationPolicy: string;
35
- };
36
- containerRuntime?: {
37
- autoStartColima?: boolean;
38
- };
39
- cleanup?: {
40
- retainBaselineGenerations?: number;
41
- };
42
- preparation?: {
43
- sourcePolicy: string;
44
- privacyKey: string;
45
- batchRows?: number;
46
- maximumRows?: number;
47
- maximumBytes?: number;
48
- diskHeadroomBytes?: number;
49
- };
50
- runtimePolicy?: string;
51
- identityPolicy?: string;
52
- dependentTargets?: Array<{
53
- name: string;
54
- configPath: string;
55
- prepareCommand?: string;
56
- }>;
57
- application: {
58
- startCommand: string;
59
- proofCommand: string;
60
- environmentFile?: string;
61
- environmentVariables?: Record<string, string>;
62
- readiness?: {
63
- url: string;
64
- expectedStatus: number;
65
- timeoutSeconds?: number;
66
- };
67
- httpProofs?: Array<{
68
- name: string;
69
- kind: "positive" | "negative";
70
- url: string;
71
- method?: string;
72
- expectedStatus: number;
73
- json?: {
74
- path: string[];
75
- equals?: unknown;
76
- notEquals?: unknown;
77
- minimumItems?: number;
78
- };
79
- }>;
80
- runtimeAdapter?: string;
81
- };
82
- runtime: {
83
- target?: "supabase" | "postgresql";
84
- applicationUrl?: string;
85
- projectId?: string;
86
- apiPort?: number;
87
- databasePort: number;
88
- studioPort?: number;
89
- };
90
- safety?: {
91
- allowedHosts?: string[];
92
- blockedEnvironmentVariables?: string[];
93
- authenticationProviders?: string[];
94
- hostedAccess?: "disabled";
95
- outboundNetwork?: "deny";
96
- };
97
- verification?: { commands?: string[] };
98
- }
99
-
100
- export declare const REHEARSAL_CONFIG_VERSION: 1;
101
- export declare const defineRehearsalConfig: <
102
- const Config extends RehearsalConfig,
103
- >(
104
- config: Config,
105
- ) => Config;
106
- export declare const loadRehearsalConfig: (options?: {
107
- projectRoot?: string;
108
- configPath?: string;
109
- }) => Promise<unknown>;
110
- export declare const inspectDetectedProject: (options?: {
111
- projectRoot?: string;
112
- }) => Promise<unknown>;
113
- export declare const renderDetectedConfig: (
114
- detected: unknown,
115
- options?: {
116
- applicationUrl?: string;
117
- ports?: { api: number; database: number; studio: number };
118
- },
119
- ) => string;
120
- export declare const renderDetectedPostgresqlConfig: (
121
- detected: unknown,
122
- options?: {
123
- applicationUrl?: string;
124
- databasePort?: number;
125
- },
126
- ) => string;
127
- export declare const SANITIZATION_ACTIONS: Readonly<{
128
- KEEP: "KEEP";
129
- PSEUDONYMIZE: "PSEUDONYMIZE";
130
- REPLACE: "REPLACE";
131
- EXCLUDE: "EXCLUDE";
132
- DERIVE: "DERIVE";
133
- }>;
134
- export declare const EXCLUDED_VALUE: unique symbol;
135
- export declare const normalizeSanitizationAction: (
136
- action: string,
137
- ) => "KEEP" | "PSEUDONYMIZE" | "REPLACE" | "EXCLUDE" | "DERIVE";
138
- export declare const validateSanitizationCoverage: (options: {
139
- policy: { policyVersion?: unknown; tables: Array<Record<string, unknown>> };
140
- schemaTables: Array<{
141
- name: string;
142
- columns: Array<string | { name: string }>;
143
- }>;
144
- }) => Readonly<{
145
- policyVersion: unknown;
146
- tableCount: number;
147
- columnCount: number;
148
- tables: ReadonlyArray<Record<string, unknown>>;
149
- }>;
150
- export declare const validateRuntimeSanitizationPolicy: (
151
- policy: unknown,
152
- ) => unknown;
153
- export declare const readBoundRuntimeSanitizationPolicy: (options: {
154
- bytes: Uint8Array | string;
155
- expectedSha256: string;
156
- }) => unknown;
157
- export declare const applySanitizationAction: (options: {
158
- action: string;
159
- value: unknown;
160
- replace?: (value: unknown, context: Record<string, unknown>) => unknown;
161
- pseudonymize?: (value: unknown, context: Record<string, unknown>) => unknown;
162
- derive?: (value: unknown, context: Record<string, unknown>) => unknown;
163
- context?: Record<string, unknown>;
164
- }) => unknown | typeof EXCLUDED_VALUE;