@intentius/sql-yodeler 0.3.0 → 0.5.0

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 (220) hide show
  1. package/README.md +2 -2
  2. package/dist/apply-steps/index.d.ts +65 -0
  3. package/dist/apply-steps/index.js +106 -0
  4. package/dist/apply-steps/index.js.map +1 -0
  5. package/dist/approval-mode/index.d.ts +78 -0
  6. package/dist/approval-mode/index.js +105 -0
  7. package/dist/approval-mode/index.js.map +1 -0
  8. package/dist/chant/access.d.ts +84 -0
  9. package/dist/chant/access.js +155 -0
  10. package/dist/chant/access.js.map +1 -0
  11. package/dist/chant/drift.d.ts +17 -1
  12. package/dist/chant/drift.js +55 -2
  13. package/dist/chant/drift.js.map +1 -1
  14. package/dist/chant/plan.d.ts +18 -2
  15. package/dist/chant/plan.js +21 -3
  16. package/dist/chant/plan.js.map +1 -1
  17. package/dist/ci/login.d.ts +78 -0
  18. package/dist/ci/login.js +199 -0
  19. package/dist/ci/login.js.map +1 -0
  20. package/dist/ci/render.d.ts +64 -10
  21. package/dist/ci/render.js +385 -88
  22. package/dist/ci/render.js.map +1 -1
  23. package/dist/cleanup/index.d.ts +92 -0
  24. package/dist/cleanup/index.js +213 -0
  25. package/dist/cleanup/index.js.map +1 -0
  26. package/dist/commands/apply.js +178 -20
  27. package/dist/commands/apply.js.map +1 -1
  28. package/dist/commands/approve.d.ts +13 -0
  29. package/dist/commands/approve.js +206 -24
  30. package/dist/commands/approve.js.map +1 -1
  31. package/dist/commands/ci.js +12 -0
  32. package/dist/commands/ci.js.map +1 -1
  33. package/dist/commands/cleanup.d.ts +13 -0
  34. package/dist/commands/cleanup.js +158 -0
  35. package/dist/commands/cleanup.js.map +1 -0
  36. package/dist/commands/config.d.ts +3 -0
  37. package/dist/commands/config.js +136 -0
  38. package/dist/commands/config.js.map +1 -0
  39. package/dist/commands/drift.js +33 -3
  40. package/dist/commands/drift.js.map +1 -1
  41. package/dist/commands/index.js +6 -0
  42. package/dist/commands/index.js.map +1 -1
  43. package/dist/commands/init.d.ts +11 -0
  44. package/dist/commands/init.js +98 -10
  45. package/dist/commands/init.js.map +1 -1
  46. package/dist/commands/lint.js +67 -10
  47. package/dist/commands/lint.js.map +1 -1
  48. package/dist/commands/new.js +135 -54
  49. package/dist/commands/new.js.map +1 -1
  50. package/dist/commands/plan.js +39 -5
  51. package/dist/commands/plan.js.map +1 -1
  52. package/dist/commands/test.d.ts +3 -0
  53. package/dist/commands/test.js +164 -0
  54. package/dist/commands/test.js.map +1 -0
  55. package/dist/config/define.d.ts +175 -2
  56. package/dist/config/define.js +2 -0
  57. package/dist/config/define.js.map +1 -1
  58. package/dist/config/load.js +78 -10
  59. package/dist/config/load.js.map +1 -1
  60. package/dist/config/settings.d.ts +20 -0
  61. package/dist/config/settings.js +28 -0
  62. package/dist/config/settings.js.map +1 -1
  63. package/dist/credentials.d.ts +119 -0
  64. package/dist/credentials.js +119 -0
  65. package/dist/credentials.js.map +1 -0
  66. package/dist/exit.js +1 -1
  67. package/dist/exit.js.map +1 -1
  68. package/dist/index.d.ts +5 -1
  69. package/dist/index.js +2 -0
  70. package/dist/index.js.map +1 -1
  71. package/dist/init/adopt.js +1 -1
  72. package/dist/init/adopt.js.map +1 -1
  73. package/dist/init/clickhouse-access.d.ts +64 -0
  74. package/dist/init/clickhouse-access.js +211 -0
  75. package/dist/init/clickhouse-access.js.map +1 -0
  76. package/dist/init/index.d.ts +2 -0
  77. package/dist/init/index.js +2 -0
  78. package/dist/init/index.js.map +1 -1
  79. package/dist/init/live.d.ts +4 -0
  80. package/dist/init/live.js +16 -0
  81. package/dist/init/live.js.map +1 -1
  82. package/dist/init/second.d.ts +70 -0
  83. package/dist/init/second.js +149 -0
  84. package/dist/init/second.js.map +1 -0
  85. package/dist/lint/access.d.ts +18 -0
  86. package/dist/lint/access.js +34 -0
  87. package/dist/lint/access.js.map +1 -0
  88. package/dist/lint/annotations.d.ts +49 -0
  89. package/dist/lint/annotations.js +82 -0
  90. package/dist/lint/annotations.js.map +1 -0
  91. package/dist/lint/check.js +25 -7
  92. package/dist/lint/check.js.map +1 -1
  93. package/dist/lint/config.d.ts +7 -1
  94. package/dist/lint/config.js +11 -5
  95. package/dist/lint/config.js.map +1 -1
  96. package/dist/lint/index.d.ts +4 -0
  97. package/dist/lint/index.js +4 -0
  98. package/dist/lint/index.js.map +1 -1
  99. package/dist/lint/naming.d.ts +62 -0
  100. package/dist/lint/naming.js +138 -0
  101. package/dist/lint/naming.js.map +1 -0
  102. package/dist/lint/rules.d.ts +37 -4
  103. package/dist/lint/rules.js +16 -4
  104. package/dist/lint/rules.js.map +1 -1
  105. package/dist/lint/schema-checks.d.ts +63 -0
  106. package/dist/lint/schema-checks.js +128 -0
  107. package/dist/lint/schema-checks.js.map +1 -0
  108. package/dist/lint/statements.d.ts +22 -1
  109. package/dist/lint/statements.js +40 -1
  110. package/dist/lint/statements.js.map +1 -1
  111. package/dist/mcp/tools.d.ts +1 -1
  112. package/dist/mcp/tools.js +1 -1
  113. package/dist/mcp/tools.js.map +1 -1
  114. package/dist/migrations/checkpoint.js +0 -2
  115. package/dist/migrations/checkpoint.js.map +1 -1
  116. package/dist/migrations/checks.d.ts +19 -1
  117. package/dist/migrations/checks.js +15 -0
  118. package/dist/migrations/checks.js.map +1 -1
  119. package/dist/migrations/create.d.ts +13 -4
  120. package/dist/migrations/create.js +24 -9
  121. package/dist/migrations/create.js.map +1 -1
  122. package/dist/migrations/routines.d.ts +5 -15
  123. package/dist/migrations/routines.js +5 -30
  124. package/dist/migrations/routines.js.map +1 -1
  125. package/dist/pr/model.d.ts +4 -1
  126. package/dist/pr/model.js +13 -5
  127. package/dist/pr/model.js.map +1 -1
  128. package/dist/pr/render.d.ts +4 -1
  129. package/dist/pr/render.js +22 -8
  130. package/dist/pr/render.js.map +1 -1
  131. package/dist/pr/tenants.d.ts +37 -0
  132. package/dist/pr/tenants.js +138 -0
  133. package/dist/pr/tenants.js.map +1 -0
  134. package/dist/probe.d.ts +27 -0
  135. package/dist/probe.js +106 -0
  136. package/dist/probe.js.map +1 -0
  137. package/dist/project.d.ts +16 -0
  138. package/dist/project.js +29 -1
  139. package/dist/project.js.map +1 -1
  140. package/dist/replay/clickhouse.d.ts +31 -0
  141. package/dist/replay/clickhouse.js +103 -6
  142. package/dist/replay/clickhouse.js.map +1 -1
  143. package/dist/replay/replay.d.ts +5 -2
  144. package/dist/replay/replay.js.map +1 -1
  145. package/dist/report/audit.d.ts +1 -1
  146. package/dist/report/audit.js +20 -3
  147. package/dist/report/audit.js.map +1 -1
  148. package/dist/schemas.d.ts +3 -1
  149. package/dist/schemas.js +2 -0
  150. package/dist/schemas.js.map +1 -1
  151. package/dist/sources/ddl.d.ts +15 -20
  152. package/dist/sources/ddl.js +34 -328
  153. package/dist/sources/ddl.js.map +1 -1
  154. package/dist/sources/index.js +2 -2
  155. package/dist/sources/index.js.map +1 -1
  156. package/dist/steps/backfill.d.ts +40 -5
  157. package/dist/steps/backfill.js +128 -8
  158. package/dist/steps/backfill.js.map +1 -1
  159. package/dist/steps/index.d.ts +19 -1
  160. package/dist/steps/index.js +34 -7
  161. package/dist/steps/index.js.map +1 -1
  162. package/dist/steps/kinds.d.ts +42 -4
  163. package/dist/steps/kinds.js +88 -14
  164. package/dist/steps/kinds.js.map +1 -1
  165. package/dist/steps/postgres-migration.d.ts +3 -0
  166. package/dist/steps/postgres-migration.js +7 -3
  167. package/dist/steps/postgres-migration.js.map +1 -1
  168. package/dist/steps/rebuild.d.ts +15 -6
  169. package/dist/steps/rebuild.js +12 -9
  170. package/dist/steps/rebuild.js.map +1 -1
  171. package/dist/tenants/index.d.ts +2 -1
  172. package/dist/tenants/index.js +3 -4
  173. package/dist/tenants/index.js.map +1 -1
  174. package/dist/tenants/wave.d.ts +128 -0
  175. package/dist/tenants/wave.js +254 -0
  176. package/dist/tenants/wave.js.map +1 -0
  177. package/dist/testing/define.d.ts +62 -0
  178. package/dist/testing/define.js +32 -0
  179. package/dist/testing/define.js.map +1 -0
  180. package/dist/testing/files.d.ts +5 -0
  181. package/dist/testing/files.js +18 -0
  182. package/dist/testing/files.js.map +1 -0
  183. package/dist/testing/report.d.ts +14 -0
  184. package/dist/testing/report.js +83 -0
  185. package/dist/testing/report.js.map +1 -0
  186. package/dist/testing/run.d.ts +104 -0
  187. package/dist/testing/run.js +328 -0
  188. package/dist/testing/run.js.map +1 -0
  189. package/dist/versioned/approval.d.ts +6 -0
  190. package/dist/versioned/approval.js +11 -5
  191. package/dist/versioned/approval.js.map +1 -1
  192. package/dist/versioned/checks.d.ts +8 -2
  193. package/dist/versioned/checks.js +34 -13
  194. package/dist/versioned/checks.js.map +1 -1
  195. package/dist/versioned/driver.d.ts +2 -2
  196. package/dist/versioned/engine.d.ts +10 -0
  197. package/dist/versioned/engine.js +8 -4
  198. package/dist/versioned/engine.js.map +1 -1
  199. package/dist/versioned/explain.d.ts +2 -0
  200. package/dist/versioned/explain.js +3 -1
  201. package/dist/versioned/explain.js.map +1 -1
  202. package/dist/versioned/op.d.ts +4 -0
  203. package/dist/versioned/op.js +5 -2
  204. package/dist/versioned/op.js.map +1 -1
  205. package/dist/versioned/state.js +1 -1
  206. package/dist/versioned/state.js.map +1 -1
  207. package/dist/waves/index.d.ts +58 -13
  208. package/dist/waves/index.js +109 -24
  209. package/dist/waves/index.js.map +1 -1
  210. package/dist/waves/record.d.ts +10 -0
  211. package/dist/waves/record.js.map +1 -1
  212. package/package.json +8 -7
  213. package/schemas/apply.schema.json +1 -1
  214. package/schemas/cleanup.schema.json +40 -0
  215. package/schemas/init.schema.json +51 -22
  216. package/schemas/lint-rules.schema.json +4 -0
  217. package/schemas/new.schema.json +41 -3
  218. package/schemas/plan.schema.json +39 -0
  219. package/schemas/report.schema.json +1 -1
  220. package/schemas/test.schema.json +41 -0
package/dist/probe.js ADDED
@@ -0,0 +1,106 @@
1
+ /**
2
+ * The write probe (#50): `yodel config check <env> --write-probe` tries a
3
+ * write with the credentials the job holds and reports whether the server
4
+ * let it. A pull request job runs it before its plan, so a reader that can
5
+ * write (the writer's secrets mapped into the job, a reader granted too
6
+ * much) fails the pull request.
7
+ *
8
+ * The write leaves nothing behind. On Postgres it is a `CREATE TABLE` in
9
+ * the environment's first schema (`CREATE SCHEMA` when that schema is not
10
+ * there yet) inside a transaction that is rolled back. On ClickHouse, which
11
+ * has no transactions, a `Memory` table with a random name in the first
12
+ * database (the database itself when it is not there yet), dropped at once
13
+ * when it was made.
14
+ *
15
+ * Only a refusal for want of privilege counts as "cannot write" (Postgres
16
+ * 42501 and 25006, ClickHouse 164 READONLY and 497 ACCESS_DENIED); any
17
+ * other failure is an error, so a probe that could not tell never passes.
18
+ */
19
+ import { randomBytes } from "node:crypto";
20
+ import { environmentSettings } from "./config/settings.js";
21
+ import { YodelError } from "./project.js";
22
+ /** Postgres SQLSTATEs that mean the role may not write. */
23
+ const PG_REFUSED = new Set(["42501", "25006"]);
24
+ /** ClickHouse error codes that mean the user may not write: READONLY, ACCESS_DENIED. */
25
+ const CH_REFUSED = new Set([164, 497]);
26
+ const CH_UNKNOWN_DATABASE = 81;
27
+ const pgIdent = (s) => `"${s.replace(/"/g, '""')}"`;
28
+ const chIdent = (s) => `\`${s.replace(/\\/g, "\\\\").replace(/`/g, "\\`")}\``;
29
+ /** The first line of a server message, without ClickHouse's trailing version. */
30
+ const firstLine = (s) => (s.trim().split("\n")[0] ?? "").replace(/ \(version .*\)\.?$/, "");
31
+ /** Tries a write in `env` with the credentials this process holds. */
32
+ export async function writeProbe(project, env, processEnv = process.env) {
33
+ return project.dialect === "postgres" ? postgresProbe(project, env, processEnv) : clickhouseProbe(project, env, processEnv);
34
+ }
35
+ async function postgresProbe(project, env, processEnv) {
36
+ const { resolvePostgresTarget, isUnresolvedTarget } = await import("@intentius/chant-lexicon-sql/postgres/live/bind");
37
+ const target = resolvePostgresTarget({ environment: env.name, config: project.config, env: processEnv });
38
+ if (isUnresolvedTarget(target))
39
+ throw new YodelError(`${env.name}: ${target.detail}`);
40
+ const { connectPostgres } = await import("@intentius/chant-lexicon-sql/postgres/live/client");
41
+ let client;
42
+ try {
43
+ client = await connectPostgres(target.endpoint, { applicationName: "yodel write probe" });
44
+ }
45
+ catch (e) {
46
+ throw new YodelError(`${env.name}: the write probe could not connect: ${e instanceof Error ? firstLine(e.message) : String(e)}`);
47
+ }
48
+ const schema = target.schemas?.[0] ?? target.defaultSchema;
49
+ try {
50
+ await client.query("BEGIN");
51
+ const there = (await client.query("SELECT 1 AS n FROM pg_catalog.pg_namespace WHERE nspname = $1", [schema])).length > 0;
52
+ const sql = there ? `CREATE TABLE ${pgIdent(schema)}.yodel_write_probe (x integer)` : `CREATE SCHEMA ${pgIdent(schema)}`;
53
+ try {
54
+ await client.query(sql);
55
+ return { wrote: true, detail: `${sql} succeeded (rolled back)` };
56
+ }
57
+ catch (e) {
58
+ const code = e.code;
59
+ const message = e instanceof Error ? firstLine(e.message) : String(e);
60
+ if (typeof code === "string" && PG_REFUSED.has(code))
61
+ return { wrote: false, detail: `${sql}: ${message}` };
62
+ throw new YodelError(`${env.name}: the write probe could not tell whether this job can write: ${sql}: ${message}`);
63
+ }
64
+ }
65
+ finally {
66
+ await client.query("ROLLBACK").catch(() => undefined);
67
+ await client.end();
68
+ }
69
+ }
70
+ async function clickhouseProbe(project, env, processEnv) {
71
+ const { resolveClickHouseTarget, isUnresolvedTarget } = await import("@intentius/chant-lexicon-sql/clickhouse/live/bind");
72
+ const target = resolveClickHouseTarget({ environment: env.name, config: project.config, env: processEnv });
73
+ if (isUnresolvedTarget(target))
74
+ throw new YodelError(`${env.name}: ${target.detail}`);
75
+ const { clickhouseQuery } = await import("@intentius/chant-lexicon-sql/clickhouse/http");
76
+ const database = target.databases?.[0] ?? environmentSettings(project, env.name, processEnv).historyDatabase;
77
+ const table = `${chIdent(database)}.${chIdent(`yodel_write_probe_${randomBytes(6).toString("hex")}`)}`;
78
+ const attempt = async (sql, undo) => {
79
+ try {
80
+ await clickhouseQuery(target.endpoint, sql);
81
+ }
82
+ catch (e) {
83
+ const text = e.serverMessage;
84
+ const message = typeof text === "string" ? text : e instanceof Error ? e.message : String(e);
85
+ const code = Number(/Code: (\d+)/.exec(message)?.[1] ?? NaN);
86
+ if (CH_REFUSED.has(code))
87
+ return { wrote: false, detail: `${sql}: ${firstLine(message)}` };
88
+ if (Number.isFinite(code) && !/AUTHENTICATION_FAILED/.test(message))
89
+ return code;
90
+ throw new YodelError(`${env.name}: the write probe could not tell whether this job can write: ${sql}: ${firstLine(message)}`);
91
+ }
92
+ await clickhouseQuery(target.endpoint, undo);
93
+ return { wrote: true, detail: `${sql} succeeded (dropped again)` };
94
+ };
95
+ const first = await attempt(`CREATE TABLE ${table} (x UInt8) ENGINE = Memory`, `DROP TABLE IF EXISTS ${table}`);
96
+ if (typeof first !== "number")
97
+ return first;
98
+ if (first === CH_UNKNOWN_DATABASE) {
99
+ const second = await attempt(`CREATE DATABASE ${chIdent(database)}`, `DROP DATABASE IF EXISTS ${chIdent(database)}`);
100
+ if (typeof second !== "number")
101
+ return second;
102
+ throw new YodelError(`${env.name}: the write probe could not tell whether this job can write: CREATE DATABASE ${database} failed with code ${String(second)}`);
103
+ }
104
+ throw new YodelError(`${env.name}: the write probe could not tell whether this job can write: CREATE TABLE ${table} failed with code ${String(first)}`);
105
+ }
106
+ //# sourceMappingURL=probe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"probe.js","sourceRoot":"","sources":["../src/probe.ts"],"names":[],"mappings":"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"}
package/dist/project.d.ts CHANGED
@@ -36,6 +36,12 @@ export interface Project {
36
36
  path: string;
37
37
  config: YodelConfig;
38
38
  } | undefined;
39
+ /**
40
+ * `sql.profiles.<env>.access` as chant.config.ts says it, before
41
+ * yodel.config.ts's `environments.<env>.access` is put in {@link config}'s
42
+ * profile. Only the environments whose profile sets it.
43
+ */
44
+ profileAccess?: Record<string, boolean>;
39
45
  }
40
46
  export interface Environment {
41
47
  name: string;
@@ -61,6 +67,16 @@ export declare function findProjectDir(start: string): string | undefined;
61
67
  export declare function projectDialect(config: ProjectConfig, configPath: string): SqlDialect;
62
68
  /** Builds a {@link Project} from a config already loaded. Pure, for tests and callers that load the config themselves. */
63
69
  export declare function projectFromConfig(dir: string, configPath: string, config: ProjectConfig, yodel?: Project["yodel"]): Project;
70
+ /**
71
+ * `config` with each profile's `access` set to yodel.config.ts's
72
+ * `environments.<env>.access` where it sets one, so the chant functions yodel
73
+ * calls in process (the plan, the import, the server reads) manage access as
74
+ * yodel.config.ts says. Pure.
75
+ */
76
+ export declare function accessInProfiles(config: ProjectConfig, yodel: YodelConfig | undefined): {
77
+ config: ProjectConfig;
78
+ profileAccess: Record<string, boolean>;
79
+ };
64
80
  /**
65
81
  * Finds the project at or above `start` (default: the working directory) and
66
82
  * loads its `chant.config.ts` through chant's own loader, so it is validated
package/dist/project.js CHANGED
@@ -50,7 +50,30 @@ export function projectFromConfig(dir, configPath, config, yodel) {
50
50
  throw new YodelError(`${configPath}: lexicons does not include "sql"; add lexicons: ["sql"] and import "@intentius/chant-lexicon-sql"`);
51
51
  }
52
52
  const sourceDir = config.sourceDir ?? (existsSync(join(dir, "src")) ? "src" : ".");
53
- return { dir, configPath, config, dialect: projectDialect(config, configPath), sourceDir, ...(yodel ? { yodel } : {}) };
53
+ const { config: withAccess, profileAccess } = accessInProfiles(config, yodel?.config);
54
+ return { dir, configPath, config: withAccess, dialect: projectDialect(config, configPath), sourceDir, ...(yodel ? { yodel } : {}), profileAccess };
55
+ }
56
+ /**
57
+ * `config` with each profile's `access` set to yodel.config.ts's
58
+ * `environments.<env>.access` where it sets one, so the chant functions yodel
59
+ * calls in process (the plan, the import, the server reads) manage access as
60
+ * yodel.config.ts says. Pure.
61
+ */
62
+ export function accessInProfiles(config, yodel) {
63
+ const profiles = config.sql?.profiles ?? {};
64
+ const profileAccess = {};
65
+ for (const [name, profile] of Object.entries(profiles)) {
66
+ const access = profile.access;
67
+ if (typeof access === "boolean")
68
+ profileAccess[name] = access;
69
+ }
70
+ const own = Object.entries(yodel?.environments ?? {}).filter(([name, e]) => e.access !== undefined && profiles[name] !== undefined);
71
+ if (own.length === 0)
72
+ return { config, profileAccess };
73
+ const next = { ...profiles };
74
+ for (const [name, e] of own)
75
+ next[name] = { ...profiles[name], access: e.access };
76
+ return { config: { ...config, sql: { ...config.sql, profiles: next } }, profileAccess };
54
77
  }
55
78
  /**
56
79
  * Finds the project at or above `start` (default: the working directory) and
@@ -71,6 +94,11 @@ export async function loadProject(start = process.cwd()) {
71
94
  throw new YodelError(e instanceof Error ? e.message : String(e));
72
95
  }
73
96
  const config = loaded.config;
97
+ // An environment whose reader and writer are one identity is refused before anything reads or writes (#50).
98
+ const { sharedCredentialsIn } = await import("./credentials.js");
99
+ const shared = sharedCredentialsIn(config.sql?.profiles ?? {});
100
+ if (shared)
101
+ throw new YodelError(`refused: ${shared}`, 4);
74
102
  const { loadYodelConfig } = await import("./config/load.js");
75
103
  const yodel = await loadYodelConfig(dir, Object.keys(config.sql?.profiles ?? {}));
76
104
  return projectFromConfig(dir, loaded.configPath ?? join(dir, "chant.config.ts"), config, yodel);
@@ -1 +1 @@
1
- {"version":3,"file":"project.js","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"project.js","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"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"}
@@ -13,6 +13,18 @@
13
13
  * so is a database a migration should have dropped. chant's working objects
14
14
  * (a rebuild's retained `__chant_old` table) are not read, as a plan does
15
15
  * not read them.
16
+ *
17
+ * Functions, users, roles and row policies (#46) belong to no database (a
18
+ * row policy outlives its table's), so emptying the databases leaves them:
19
+ * the ones the history declares are counted as occupying the server and
20
+ * dropped with the databases. A grantee's grants go with the grantee.
21
+ * A user declared without `IDENTIFIED` is the environment's to create, with
22
+ * its password, and no migration creates it: the replay stands in for the
23
+ * environment and creates it with a random password before the first
24
+ * statement, so the grants and `ALTER USER` statements that name it run,
25
+ * and gives it its declared clauses (`DEFAULT ROLE`, `SETTINGS`, ...)
26
+ * before each migration is compared, as the environment that made it as
27
+ * declared would ({@link alterToDeclared}).
16
28
  */
17
29
  import { type Environment, type Project } from "../project.js";
18
30
  import { type ClickHousePort } from "../history/index.js";
@@ -29,5 +41,24 @@ export interface ClickHouseReplayOptions {
29
41
  }
30
42
  /** The databases a ClickHouse build output names, with bare names in `defaultDatabase`. */
31
43
  export declare function clickhouseDatabases(schema: unknown, defaultDatabase: string): Promise<string[]>;
44
+ /** A function, user, role or row policy a history declares, which emptying its databases does not remove. */
45
+ export interface GlobalObject {
46
+ kind: "function" | "user" | "role" | "rowPolicy";
47
+ name: string;
48
+ /** A user declared without `IDENTIFIED`, which the environment creates. */
49
+ withheld?: true;
50
+ /** A row policy's table, `database.table`. */
51
+ on?: string;
52
+ }
53
+ /** The functions, users, roles and row policies a ClickHouse build output declares. */
54
+ export declare function clickhouseGlobals(schema: unknown, defaultDatabase: string): Promise<GlobalObject[]>;
55
+ /**
56
+ * A user declared without `IDENTIFIED`, given its declared clauses:
57
+ * `CREATE USER u DEFAULT ROLE r` as `ALTER USER u DEFAULT ROLE r`, or
58
+ * `undefined` when it declares none (or is not such a user).
59
+ */
60
+ export declare function alterToDeclared(ddl: string): string | undefined;
61
+ /** `DROP ... IF EXISTS` for one, row policies before the users and roles they apply to. */
62
+ export declare const dropGlobal: (g: GlobalObject) => string;
32
63
  /** The replay driver for `env`, a ClickHouse environment, over the history `ordered`. */
33
64
  export declare function clickhouseReplay(project: Project, env: Environment, ordered: readonly Migration[], options?: ClickHouseReplayOptions): Promise<ReplayDriver>;
@@ -13,7 +13,20 @@
13
13
  * so is a database a migration should have dropped. chant's working objects
14
14
  * (a rebuild's retained `__chant_old` table) are not read, as a plan does
15
15
  * not read them.
16
+ *
17
+ * Functions, users, roles and row policies (#46) belong to no database (a
18
+ * row policy outlives its table's), so emptying the databases leaves them:
19
+ * the ones the history declares are counted as occupying the server and
20
+ * dropped with the databases. A grantee's grants go with the grantee.
21
+ * A user declared without `IDENTIFIED` is the environment's to create, with
22
+ * its password, and no migration creates it: the replay stands in for the
23
+ * environment and creates it with a random password before the first
24
+ * statement, so the grants and `ALTER USER` statements that name it run,
25
+ * and gives it its declared clauses (`DEFAULT ROLE`, `SETTINGS`, ...)
26
+ * before each migration is compared, as the environment that made it as
27
+ * declared would ({@link alterToDeclared}).
16
28
  */
29
+ import { randomBytes } from "node:crypto";
17
30
  import { YodelError } from "../project.js";
18
31
  import { environmentSettings } from "../config/settings.js";
19
32
  import { httpPort } from "../history/index.js";
@@ -23,11 +36,44 @@ const SYSTEM = new Set(["system", "information_schema", "INFORMATION_SCHEMA"]);
23
36
  const DEFAULT = "default";
24
37
  const ident = (s) => `\`${s.replace(/`/g, "``")}\``;
25
38
  const quote = (s) => `'${s.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
39
+ /** The kinds that belong to no database: a function, a user, a role, a grantee's grants. */
40
+ const GLOBAL_KINDS = new Set(["function", "user", "role", "grants"]);
26
41
  /** The databases a ClickHouse build output names, with bare names in `defaultDatabase`. */
27
42
  export async function clickhouseDatabases(schema, defaultDatabase) {
28
43
  const { schemaFromBuildOutput } = await import("@intentius/chant-lexicon-sql/clickhouse/plan/schema");
29
- return [...new Set(schemaFromBuildOutput(JSON.stringify(schema), defaultDatabase).map((o) => o.canonical.database ?? o.canonical.name))];
44
+ return [...new Set(schemaFromBuildOutput(JSON.stringify(schema), defaultDatabase).filter((o) => !GLOBAL_KINDS.has(o.canonical.kind)).map((o) => o.canonical.database ?? o.canonical.name))];
45
+ }
46
+ /** The functions, users, roles and row policies a ClickHouse build output declares. */
47
+ export async function clickhouseGlobals(schema, defaultDatabase) {
48
+ const { schemaFromBuildOutput } = await import("@intentius/chant-lexicon-sql/clickhouse/plan/schema");
49
+ return schemaFromBuildOutput(JSON.stringify(schema), defaultDatabase).flatMap((o) => {
50
+ const c = o.canonical;
51
+ if (c.kind === "user" && c.access?.identified === undefined)
52
+ return [{ kind: "user", name: c.name, withheld: true }];
53
+ if (c.kind === "function" || c.kind === "user" || c.kind === "role")
54
+ return [{ kind: c.kind, name: c.name }];
55
+ if (c.kind === "rowPolicy")
56
+ return [{ kind: "rowPolicy", name: c.name, on: `${c.database ?? defaultDatabase}.${c.table ?? ""}` }];
57
+ return [];
58
+ });
59
+ }
60
+ const CREATE_USER = /^\s*CREATE\s+USER\s+(?:IF\s+NOT\s+EXISTS\s+|OR\s+REPLACE\s+)?(`(?:[^`]|``)*`|[^\s,]+)(?:\s+ON\s+CLUSTER\s+\S+)?/i;
61
+ /**
62
+ * A user declared without `IDENTIFIED`, given its declared clauses:
63
+ * `CREATE USER u DEFAULT ROLE r` as `ALTER USER u DEFAULT ROLE r`, or
64
+ * `undefined` when it declares none (or is not such a user).
65
+ */
66
+ export function alterToDeclared(ddl) {
67
+ const m = CREATE_USER.exec(ddl);
68
+ if (!m || /\bIDENTIFIED\b/i.test(ddl))
69
+ return undefined;
70
+ const rest = ddl.slice(m[0].length).trim().replace(/;\s*$/, "");
71
+ return rest === "" ? undefined : `ALTER USER ${m[1] ?? ""} ${rest}`;
30
72
  }
73
+ const KEYWORD = { function: "FUNCTION", user: "USER", role: "ROLE", rowPolicy: "ROW POLICY" };
74
+ const onTable = (on) => on.split(".").map(ident).join(".");
75
+ /** `DROP ... IF EXISTS` for one, row policies before the users and roles they apply to. */
76
+ export const dropGlobal = (g) => `DROP ${KEYWORD[g.kind]} IF EXISTS ${ident(g.name)}${g.on !== undefined ? ` ON ${onTable(g.on)}` : ""}`;
31
77
  /** The replay driver for `env`, a ClickHouse environment, over the history `ordered`. */
32
78
  export async function clickhouseReplay(project, env, ordered, options = {}) {
33
79
  const processEnv = options.processEnv ?? process.env;
@@ -40,9 +86,19 @@ export async function clickhouseReplay(project, env, ordered, options = {}) {
40
86
  const topology = settings.topology;
41
87
  const defaultDatabase = (m) => m.document.defaultDatabase ?? target.defaultDatabase;
42
88
  const named = new Set();
43
- for (const m of ordered)
89
+ const globals = new Map();
90
+ for (const m of ordered) {
44
91
  for (const d of await clickhouseDatabases(m.document.schema, defaultDatabase(m)))
45
92
  named.add(d);
93
+ for (const g of await clickhouseGlobals(m.document.schema, defaultDatabase(m))) {
94
+ // Withheld in one migration and created in another is created by the history: not the replay's to make.
95
+ const seen = globals.get(dropGlobal(g));
96
+ const made = { kind: g.kind, name: g.name, ...(g.on !== undefined ? { on: g.on } : {}) };
97
+ globals.set(dropGlobal(g), seen && !(seen.withheld && g.withheld) ? made : g);
98
+ }
99
+ }
100
+ const order = { rowPolicy: 0, user: 1, role: 2, function: 3 };
101
+ const declaredGlobals = [...globals.values()].sort((a, b) => order[a.kind] - order[b.kind] || a.name.localeCompare(b.name));
46
102
  const scope = [...named].sort();
47
103
  const system = scope.filter((d) => SYSTEM.has(d));
48
104
  if (system.length > 0)
@@ -53,6 +109,28 @@ export async function clickhouseReplay(project, env, ordered, options = {}) {
53
109
  const port = options.port ?? (await httpPort(endpoint));
54
110
  const log = options.log ?? (() => undefined);
55
111
  const runStep = options.runStep ?? defaultStepRunner;
112
+ /** The declared functions, users, roles and row policies the server holds, as `<kind> <name>`. */
113
+ const globalsThere = async () => {
114
+ const there = async (kind, sql) => new Set((await port.query(sql)).map((r) => r.name));
115
+ const names = (kind) => declaredGlobals.filter((g) => g.kind === kind).map((g) => quote(g.kind === "rowPolicy" ? `${g.name} ON ${g.on ?? ""}` : g.name));
116
+ const out = [];
117
+ const sets = [
118
+ ["function", `SELECT name FROM system.functions WHERE origin = 'SQLUserDefined' AND name IN (${names("function").join(", ")})`],
119
+ ["user", `SELECT name FROM system.users WHERE name IN (${names("user").join(", ")})`],
120
+ ["role", `SELECT name FROM system.roles WHERE name IN (${names("role").join(", ")})`],
121
+ ["rowPolicy", `SELECT concat(short_name, ' ON ', database, '.', table) AS name FROM system.row_policies WHERE name IN (${names("rowPolicy").join(", ")}) OR concat(short_name, ' ON ', database, '.', table) IN (${names("rowPolicy").join(", ")})`],
122
+ ];
123
+ for (const [kind, sql] of sets) {
124
+ if (names(kind).length === 0)
125
+ continue;
126
+ const held = await there(kind, sql);
127
+ out.push(...declaredGlobals.filter((g) => g.kind === kind && held.has(g.kind === "rowPolicy" ? `${g.name} ON ${g.on ?? ""}` : g.name)));
128
+ }
129
+ return out;
130
+ };
131
+ // The withheld users are made before the first statement after the server is emptied, and dropped with the rest.
132
+ let environmentUsers = false;
133
+ const describeGlobal = (g) => `${g.kind === "rowPolicy" ? "row policy" : g.kind} ${g.name}${g.on !== undefined ? ` ON ${g.on}` : ""}`;
56
134
  const tablesInDefault = async () => (await port.query(`SELECT name FROM system.tables WHERE database = ${quote(DEFAULT)} AND NOT is_temporary ORDER BY name`)).map((r) => r.name);
57
135
  return {
58
136
  dialect: "clickhouse",
@@ -63,7 +141,7 @@ export async function clickhouseReplay(project, env, ordered, options = {}) {
63
141
  const there = others.length === 0 ? [] : (await port.query(`SELECT name FROM system.databases WHERE name IN (${others.map(quote).join(", ")}) ORDER BY name`)).map((r) => r.name);
64
142
  if (scope.includes(DEFAULT) && (await tablesInDefault()).length > 0)
65
143
  there.unshift(`${DEFAULT} (not empty)`);
66
- return there;
144
+ return [...there, ...(await globalsThere()).map(describeGlobal)];
67
145
  },
68
146
  async clear() {
69
147
  for (const d of scope) {
@@ -73,28 +151,47 @@ export async function clickhouseReplay(project, env, ordered, options = {}) {
73
151
  for (const t of await tablesInDefault())
74
152
  await port.query(`DROP TABLE IF EXISTS ${ident(DEFAULT)}.${ident(t)} SYNC`);
75
153
  }
154
+ for (const g of declaredGlobals)
155
+ await port.query(dropGlobal(g));
156
+ environmentUsers = false;
76
157
  },
77
158
  async statement(_m, _index, step) {
159
+ if (!environmentUsers) {
160
+ for (const g of declaredGlobals.filter((x) => x.withheld)) {
161
+ await port.query(`CREATE USER IF NOT EXISTS ${ident(g.name)} IDENTIFIED BY ${quote(randomBytes(24).toString("base64url"))}`);
162
+ log(`created user ${g.name}, which the history declares without a password, with a random one, as the environment would`);
163
+ }
164
+ environmentUsers = true;
165
+ }
78
166
  await port.query(renderForEnvironment(step.sql, topology), step.waitsForMutation ? { settings: { mutations_sync: "2" } } : {});
79
167
  },
80
- async opStep(m, index) {
168
+ async opStep(m, index, opts = {}) {
81
169
  const step = m.document.steps[index];
82
170
  if (!step)
83
171
  return { refused: `${m.id} has no step ${String(index)}` };
84
172
  const plan = planStep(step);
85
173
  if (plan.run !== "rebuild")
86
174
  return { refused: plan.run === "refused" ? plan.reason : `step ${String(index)} is not one the replay runs` };
87
- const { summary } = await runStep({ environment: env.name, projectDir: project.dir, port, endpoint, migration: m, index, plan, log: (line) => { log(` ${line}`); } });
175
+ const { summary } = await runStep({ environment: env.name, projectDir: project.dir, port, endpoint, migration: m, index, plan, log: (line) => { log(` ${line}`); }, ...(opts.receipts ? { rebuildReceipts: opts.receipts } : {}) });
88
176
  const s = summary;
89
177
  return { ran: true, ...(s?.swapped !== undefined ? { note: s.swapped ? "swapped" : "not swapped" } : {}) };
90
178
  },
91
179
  async compare(m) {
180
+ for (const o of m.document.schema.objects.filter((x) => x.type === "ClickHouse::User")) {
181
+ const alter = alterToDeclared(o.ddl);
182
+ if (alter)
183
+ await port.query(renderForEnvironment(alter, topology));
184
+ }
92
185
  const { keyedByQualifiedName, schemaFromBuildOutput, schemaFromServer } = await import("@intentius/chant-lexicon-sql/clickhouse/plan/schema");
93
186
  const { diffSchemas } = await import("@intentius/chant-lexicon-sql/clickhouse/plan/diff");
94
187
  const { dropFormattingOnly } = await import("@intentius/chant-lexicon-sql/clickhouse/plan/server-format");
95
188
  const db = defaultDatabase(m);
189
+ const { scopeOf } = await import("@intentius/chant-lexicon-sql/clickhouse/plan/normalize");
190
+ const { declaredAccess } = await import("@intentius/chant-lexicon-sql/clickhouse/live/catalog");
96
191
  const declared = keyedByQualifiedName(schemaFromBuildOutput(JSON.stringify(m.document.schema), db, topology));
97
- const live = await schemaFromServer({ ...target, databases: scope, defaultDatabase: db }, new Set(scope));
192
+ // A function, user, role or grantee is its own scope (chant's scopeOf), read when the migration declares it.
193
+ const scopes = new Set([...scope, ...declared.filter((o) => GLOBAL_KINDS.has(o.canonical.kind)).map((o) => scopeOf(o.canonical))]);
194
+ const live = await schemaFromServer({ ...target, databases: scope, defaultDatabase: db }, scopes, undefined, declaredAccess(declared.map((o) => o.canonical)));
98
195
  const diff = diffSchemas(live, declared);
99
196
  const changes = await dropFormattingOnly(endpoint, diff.changes);
100
197
  const label = new Map(declared.map((o) => [o.key, `${o.exportName} (${o.key})`]));
@@ -1 +1 @@
1
- {"version":3,"file":"clickhouse.js","sourceRoot":"","sources":["../../src/replay/clickhouse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,OAAO,EAAE,UAAU,EAAkC,MAAM,eAAe,CAAC;AAC3E,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAuB,MAAM,qBAAqB,CAAC;AAEpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAmB,MAAM,mBAAmB,CAAC;AAGjF,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,oBAAoB,EAAE,oBAAoB,CAAC,CAAC,CAAC;AAC/E,MAAM,OAAO,GAAG,SAAS,CAAC;AAE1B,MAAM,KAAK,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC;AAC5D,MAAM,KAAK,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC;AAWlF,2FAA2F;AAC3F,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,MAAe,EAAE,eAAuB;IAChF,MAAM,EAAE,qBAAqB,EAAE,GAAG,MAAM,MAAM,CAAC,qDAAqD,CAAC,CAAC;IACtG,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,qBAAqB,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,eAAe,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,QAAQ,IAAI,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC3I,CAAC;AAED,yFAAyF;AACzF,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,OAAgB,EAAE,GAAgB,EAAE,OAA6B,EAAE,UAAmC,EAAE;IAC7I,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,GAAG,CAAC;IACrD,MAAM,QAAQ,GAAG,mBAAmB,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IACpE,MAAM,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,GAAG,MAAM,MAAM,CAAC,mDAAmD,CAAC,CAAC;IAC1H,MAAM,MAAM,GAAG,uBAAuB,CAAC,EAAE,WAAW,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC,CAAC;IAC3G,IAAI,kBAAkB,CAAC,MAAM,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACpE,MAAM,QAAQ,GAAuB,MAAM,CAAC,QAAQ,CAAC;IACrD,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC;IACnC,MAAM,eAAe,GAAG,CAAC,CAAY,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,eAAe,IAAI,MAAM,CAAC,eAAe,CAAC;IAE/F,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,KAAK,MAAM,CAAC,IAAI,OAAO;QAAE,KAAK,MAAM,CAAC,IAAI,MAAM,mBAAmB,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC;YAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACxH,MAAM,KAAK,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;IAChC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAClD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,mCAAmC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,8EAA8E,CAAC,CAAC;IAChL,IAAI,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;QAC7C,MAAM,IAAI,UAAU,CAAC,mCAAmC,QAAQ,CAAC,eAAe,2CAA2C,GAAG,CAAC,IAAI,uFAAuF,CAAC,CAAC;IAC9N,CAAC;IAED,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,CAAC,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;IACxD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAC7C,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,iBAAiB,CAAC;IAErD,MAAM,eAAe,GAAG,KAAK,IAAI,EAAE,CACjC,CAAC,MAAM,IAAI,CAAC,KAAK,CAAmB,mDAAmD,KAAK,CAAC,OAAO,CAAC,qCAAqC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAElK,OAAO;QACL,OAAO,EAAE,YAAY;QACrB,KAAK,EAAE,GAAG,QAAQ,CAAC,GAAG,KAAK,MAAM,CAAC,MAAM,GAAG;QAC3C,KAAK;QAEL,KAAK,CAAC,QAAQ;YACZ,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC;YAClD,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,KAAK,CAAmB,oDAAoD,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YACpM,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,eAAe,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC;gBAAE,KAAK,CAAC,OAAO,CAAC,GAAG,OAAO,cAAc,CAAC,CAAC;YAC7G,OAAO,KAAK,CAAC;QACf,CAAC;QAED,KAAK,CAAC,KAAK;YACT,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;gBACtB,IAAI,CAAC,KAAK,OAAO;oBAAE,MAAM,IAAI,CAAC,KAAK,CAAC,2BAA2B,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;;oBAC3E,KAAK,MAAM,CAAC,IAAI,MAAM,eAAe,EAAE;wBAAE,MAAM,IAAI,CAAC,KAAK,CAAC,wBAAwB,KAAK,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;YAC5H,CAAC;QACH,CAAC;QAED,KAAK,CAAC,SAAS,CAAC,EAAa,EAAE,MAAc,EAAE,IAAmB;YAChE,MAAM,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,cAAc,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACjI,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,CAAY,EAAE,KAAa;YACtC,MAAM,IAAI,GAAG,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACrC,IAAI,CAAC,IAAI;gBAAE,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC,EAAE,gBAAgB,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;YACtE,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC5B,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS;gBAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,MAAM,CAAC,KAAK,CAAC,6BAA6B,EAAE,CAAC;YAC1I,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,OAAO,CAAC,EAAE,WAAW,EAAE,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,GAAG,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACvK,MAAM,CAAC,GAAG,OAA4C,CAAC;YACvD,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,EAAE,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;QAC7G,CAAC;QAED,KAAK,CAAC,OAAO,CAAC,CAAY;YACxB,MAAM,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,qDAAqD,CAAC,CAAC;YAC9I,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,MAAM,CAAC,mDAAmD,CAAC,CAAC;YAC1F,MAAM,EAAE,kBAAkB,EAAE,GAAG,MAAM,MAAM,CAAC,4DAA4D,CAAC,CAAC;YAC1G,MAAM,EAAE,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;YAC9B,MAAM,QAAQ,GAAG,oBAAoB,CAAC,qBAAqB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC;YAC9G,MAAM,IAAI,GAAG,MAAM,gBAAgB,CAAC,EAAE,GAAG,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,eAAe,EAAE,EAAE,EAAE,EAAE,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;YAC1G,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YACzC,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YACjE,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,UAAU,KAAK,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;YAClF,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACjF,CAAC;QAED,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE;KAC/B,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"clickhouse.js","sourceRoot":"","sources":["../../src/replay/clickhouse.ts"],"names":[],"mappings":"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"}
@@ -38,6 +38,7 @@ import type { ClassifiedChange } from "@intentius/chant-lexicon-sql/core/classif
38
38
  import type { StatementStep } from "@intentius/chant-lexicon-sql/migration-statements";
39
39
  import { type SqlDialect } from "../project.js";
40
40
  import { type Migration } from "../migrations/index.js";
41
+ import type { RebuildReceiptStore } from "../steps/rebuild.js";
41
42
  /** Exit code: the target is not fresh and `reset` was not given; nothing was run. */
42
43
  export declare const NOT_FRESH = 4;
43
44
  /** Exit code: a step the replay cannot run (a manual step, an Op it does not run). */
@@ -64,8 +65,10 @@ export interface ReplayDriver {
64
65
  clear(): Promise<void>;
65
66
  /** Sends one statement step of `m`, as apply sends it. Throws the server's error. */
66
67
  statement(m: Migration, index: number, step: StatementStep): Promise<void>;
67
- /** Runs an Op step that is neither a backfill nor refused by {@link planStep}; or says why it cannot. */
68
- opStep(m: Migration, index: number): Promise<OpStepOutcome>;
68
+ /** Runs an Op step that is neither a backfill nor refused by {@link planStep}; or says why it cannot. `receipts` keeps a rebuild's partition receipts instead of the server. */
69
+ opStep(m: Migration, index: number, options?: {
70
+ receipts?: RebuildReceiptStore;
71
+ }): Promise<OpStepOutcome>;
69
72
  /** The replayed database against `m`'s recorded schema. Empty when they match. */
70
73
  compare(m: Migration): Promise<ReplayChange[]>;
71
74
  close(): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"replay.js","sourceRoot":"","sources":["../../src/replay/replay.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"replay.js","sourceRoot":"","sources":["../../src/replay/replay.ts"],"names":[],"mappings":"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"}
@@ -36,7 +36,7 @@
36
36
  * none.
37
37
  */
38
38
  import type { HistoryRow } from "../history/index.js";
39
- export declare const AUDIT_KINDS: readonly ["approval-requested", "approved", "override", "silenced", "applied", "refused", "failed", "repaired", "reverted"];
39
+ export declare const AUDIT_KINDS: readonly ["approval-requested", "approved", "override", "silenced", "applied", "refused", "failed", "repaired", "reverted", "step"];
40
40
  export type AuditKind = (typeof AUDIT_KINDS)[number];
41
41
  export type AuditSource = {
42
42
  ledger: string;
@@ -37,7 +37,8 @@
37
37
  */
38
38
  import { createHash } from "node:crypto";
39
39
  import { waveRecordOf } from "../waves/record.js";
40
- export const AUDIT_KINDS = ["approval-requested", "approved", "override", "silenced", "applied", "refused", "failed", "repaired", "reverted"];
40
+ import { describeStep, stepsOfNote } from "../apply-steps/index.js";
41
+ export const AUDIT_KINDS = ["approval-requested", "approved", "override", "silenced", "applied", "refused", "failed", "repaired", "reverted", "step"];
41
42
  /** `2026-10-10 09:12:44.123456` (the history's UTC) as ISO 8601. An ISO time is returned as it is. */
42
43
  export function isoTime(t) {
43
44
  if (!t)
@@ -70,12 +71,25 @@ function fromHistory(input) {
70
71
  const silenced = new Set();
71
72
  /** Each migration's wave, from its latest started row. */
72
73
  const waveOf = new Map();
74
+ /** The steps around apply (#64) a run recorded: the before steps are on every migration's started row of the run, listed once. */
75
+ const stepsSeen = new Set();
76
+ const steps = (r, at) => {
77
+ for (const o of stepsOfNote(r.note)) {
78
+ const key = `${r.run_id}\u0000${o.when}\u0000${o.name}`;
79
+ if (stepsSeen.has(key))
80
+ continue;
81
+ stepsSeen.add(key);
82
+ // A before step is the run's, not one migration's; an after step ran after the last.
83
+ out.push(entry({ at: at.at, environment: at.environment, ...(at.by ? { by: at.by } : {}), ...(o.when === "after" ? { migration: r.migration_id } : {}), source: at.source, kind: "step", detail: describeStep(o) }));
84
+ }
85
+ };
73
86
  for (const r of [...input.rows].sort((a, b) => a.seq - b.seq)) {
74
87
  if (r.kind !== "migration")
75
88
  continue;
76
89
  const source = { history, seq: r.seq, run: r.run_id };
77
90
  const base = { at: isoTime(r.recorded_at ?? ""), environment, by: r.applied_by, migration: r.migration_id, ...(r.plan_digest ? { digest: r.plan_digest } : {}), source };
78
91
  if (r.status === "started") {
92
+ steps(r, base);
79
93
  const w = waveRecordOf(r.note);
80
94
  if (w)
81
95
  waveOf.set(r.migration_id, { gate: w.gate, digest: w.digest, status: w.status });
@@ -102,13 +116,16 @@ function fromHistory(input) {
102
116
  out.push(entry({ ...base, kind: "reverted", ...(r.note ? { detail: r.note } : {}) }));
103
117
  }
104
118
  else if (r.status === "succeeded") {
119
+ // The after steps' outcomes are entries of their own, not the applied entry's detail.
120
+ const note = stepsOfNote(r.note).length > 0 ? "" : r.note;
105
121
  if (applied.has(r.migration_id))
106
- out.push(entry({ ...base, kind: "repaired", detail: r.note || `checksum ${r.checksum}` }));
122
+ out.push(entry({ ...base, kind: "repaired", detail: note || `checksum ${r.checksum}` }));
107
123
  else {
108
124
  applied.add(r.migration_id);
109
125
  const wave = waveOf.get(r.migration_id);
110
- out.push(entry({ ...base, kind: "applied", ...(r.note ? { detail: r.note } : {}), ...(wave ? { wave } : {}) }));
126
+ out.push(entry({ ...base, kind: "applied", ...(note ? { detail: note } : {}), ...(wave ? { wave } : {}) }));
111
127
  }
128
+ steps(r, base);
112
129
  }
113
130
  else {
114
131
  out.push(entry({ ...base, kind: CHECK_FAILED.test(r.error) ? "refused" : "failed", detail: r.error }));