@intentius/sql-yodeler 0.1.0 → 0.2.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 (177) hide show
  1. package/README.md +26 -24
  2. package/dist/bin.js +15 -0
  3. package/dist/bin.js.map +1 -1
  4. package/dist/chant/apply.d.ts +9 -1
  5. package/dist/chant/apply.js +13 -1
  6. package/dist/chant/apply.js.map +1 -1
  7. package/dist/chant/drift.d.ts +69 -1
  8. package/dist/chant/drift.js +152 -5
  9. package/dist/chant/drift.js.map +1 -1
  10. package/dist/chant/runnable.d.ts +19 -0
  11. package/dist/chant/runnable.js +47 -0
  12. package/dist/chant/runnable.js.map +1 -0
  13. package/dist/cli.d.ts +4 -0
  14. package/dist/cli.js +40 -0
  15. package/dist/cli.js.map +1 -1
  16. package/dist/command.d.ts +6 -0
  17. package/dist/command.js.map +1 -1
  18. package/dist/commands/apply.js +161 -41
  19. package/dist/commands/apply.js.map +1 -1
  20. package/dist/commands/approve.d.ts +5 -0
  21. package/dist/commands/approve.js +111 -0
  22. package/dist/commands/approve.js.map +1 -0
  23. package/dist/commands/drift.d.ts +11 -0
  24. package/dist/commands/drift.js +247 -18
  25. package/dist/commands/drift.js.map +1 -1
  26. package/dist/commands/index.js +6 -0
  27. package/dist/commands/index.js.map +1 -1
  28. package/dist/commands/init.d.ts +3 -0
  29. package/dist/commands/init.js +15 -11
  30. package/dist/commands/init.js.map +1 -1
  31. package/dist/commands/lint.js +14 -5
  32. package/dist/commands/lint.js.map +1 -1
  33. package/dist/commands/mcp.d.ts +3 -0
  34. package/dist/commands/mcp.js +50 -0
  35. package/dist/commands/mcp.js.map +1 -0
  36. package/dist/commands/new.d.ts +2 -0
  37. package/dist/commands/new.js +134 -10
  38. package/dist/commands/new.js.map +1 -1
  39. package/dist/commands/override.d.ts +3 -0
  40. package/dist/commands/override.js +118 -0
  41. package/dist/commands/override.js.map +1 -0
  42. package/dist/commands/plan.js +38 -26
  43. package/dist/commands/plan.js.map +1 -1
  44. package/dist/commands/repair.d.ts +11 -0
  45. package/dist/commands/repair.js +15 -7
  46. package/dist/commands/repair.js.map +1 -1
  47. package/dist/commands/status.js +12 -12
  48. package/dist/commands/status.js.map +1 -1
  49. package/dist/config/define.d.ts +101 -3
  50. package/dist/config/define.js +1 -1
  51. package/dist/config/define.js.map +1 -1
  52. package/dist/config/load.js +64 -4
  53. package/dist/config/load.js.map +1 -1
  54. package/dist/config/settings.d.ts +14 -1
  55. package/dist/config/settings.js +32 -4
  56. package/dist/config/settings.js.map +1 -1
  57. package/dist/env-args.d.ts +6 -0
  58. package/dist/env-args.js +31 -1
  59. package/dist/env-args.js.map +1 -1
  60. package/dist/exit.d.ts +20 -0
  61. package/dist/exit.js +28 -0
  62. package/dist/exit.js.map +1 -0
  63. package/dist/history/client.d.ts +8 -0
  64. package/dist/history/client.js +24 -1
  65. package/dist/history/client.js.map +1 -1
  66. package/dist/history/lock.d.ts +5 -1
  67. package/dist/history/lock.js +8 -2
  68. package/dist/history/lock.js.map +1 -1
  69. package/dist/index.d.ts +1 -1
  70. package/dist/init/adopt.js +8 -3
  71. package/dist/init/adopt.js.map +1 -1
  72. package/dist/init/live.d.ts +11 -0
  73. package/dist/init/live.js +25 -2
  74. package/dist/init/live.js.map +1 -1
  75. package/dist/lint/check.d.ts +8 -1
  76. package/dist/lint/check.js +23 -4
  77. package/dist/lint/check.js.map +1 -1
  78. package/dist/mcp/server.d.ts +40 -0
  79. package/dist/mcp/server.js +106 -0
  80. package/dist/mcp/server.js.map +1 -0
  81. package/dist/mcp/tools.d.ts +72 -0
  82. package/dist/mcp/tools.js +178 -0
  83. package/dist/mcp/tools.js.map +1 -0
  84. package/dist/migrations/checks.d.ts +28 -0
  85. package/dist/migrations/checks.js +97 -0
  86. package/dist/migrations/checks.js.map +1 -0
  87. package/dist/migrations/create.d.ts +3 -1
  88. package/dist/migrations/create.js +1 -0
  89. package/dist/migrations/create.js.map +1 -1
  90. package/dist/migrations/directory.js +4 -0
  91. package/dist/migrations/directory.js.map +1 -1
  92. package/dist/migrations/document.d.ts +23 -0
  93. package/dist/migrations/document.js +1 -0
  94. package/dist/migrations/document.js.map +1 -1
  95. package/dist/migrations/index.d.ts +1 -0
  96. package/dist/migrations/index.js +1 -0
  97. package/dist/migrations/index.js.map +1 -1
  98. package/dist/pr/forge.d.ts +4 -0
  99. package/dist/pr/forge.js +21 -7
  100. package/dist/pr/forge.js.map +1 -1
  101. package/dist/pr/issue.d.ts +68 -0
  102. package/dist/pr/issue.js +107 -0
  103. package/dist/pr/issue.js.map +1 -0
  104. package/dist/pr/model.d.ts +9 -1
  105. package/dist/pr/model.js +30 -6
  106. package/dist/pr/model.js.map +1 -1
  107. package/dist/pr/render.d.ts +3 -1
  108. package/dist/pr/render.js +36 -3
  109. package/dist/pr/render.js.map +1 -1
  110. package/dist/replay/index.d.ts +3 -0
  111. package/dist/replay/index.js +3 -0
  112. package/dist/replay/index.js.map +1 -1
  113. package/dist/replay/replay.js +1 -1
  114. package/dist/replay/replay.js.map +1 -1
  115. package/dist/replay/shared.d.ts +28 -0
  116. package/dist/replay/shared.js +77 -0
  117. package/dist/replay/shared.js.map +1 -0
  118. package/dist/schemas.d.ts +34 -0
  119. package/dist/schemas.js +38 -0
  120. package/dist/schemas.js.map +1 -0
  121. package/dist/server.d.ts +40 -0
  122. package/dist/server.js +87 -0
  123. package/dist/server.js.map +1 -0
  124. package/dist/steps/backfill.d.ts +21 -17
  125. package/dist/steps/backfill.js +20 -20
  126. package/dist/steps/backfill.js.map +1 -1
  127. package/dist/steps/index.d.ts +2 -2
  128. package/dist/steps/index.js +3 -3
  129. package/dist/steps/index.js.map +1 -1
  130. package/dist/steps/rebuild.d.ts +15 -15
  131. package/dist/steps/rebuild.js +17 -24
  132. package/dist/steps/rebuild.js.map +1 -1
  133. package/dist/versioned/checks.d.ts +29 -0
  134. package/dist/versioned/checks.js +54 -0
  135. package/dist/versioned/checks.js.map +1 -0
  136. package/dist/versioned/clickhouse.js +8 -0
  137. package/dist/versioned/clickhouse.js.map +1 -1
  138. package/dist/versioned/driver.d.ts +10 -0
  139. package/dist/versioned/engine.d.ts +55 -1
  140. package/dist/versioned/engine.js +99 -6
  141. package/dist/versioned/engine.js.map +1 -1
  142. package/dist/versioned/explain.js +7 -2
  143. package/dist/versioned/explain.js.map +1 -1
  144. package/dist/versioned/index.d.ts +9 -0
  145. package/dist/versioned/index.js +24 -1
  146. package/dist/versioned/index.js.map +1 -1
  147. package/dist/versioned/op.d.ts +10 -0
  148. package/dist/versioned/op.js +36 -4
  149. package/dist/versioned/op.js.map +1 -1
  150. package/dist/versioned/policy.d.ts +67 -0
  151. package/dist/versioned/policy.js +161 -0
  152. package/dist/versioned/policy.js.map +1 -0
  153. package/dist/versioned/postgres/driver.d.ts +3 -1
  154. package/dist/versioned/postgres/driver.js +30 -3
  155. package/dist/versioned/postgres/driver.js.map +1 -1
  156. package/dist/versioned/postgres/waits.d.ts +46 -0
  157. package/dist/versioned/postgres/waits.js +78 -0
  158. package/dist/versioned/postgres/waits.js.map +1 -0
  159. package/dist/versioned/report.d.ts +3 -0
  160. package/dist/versioned/report.js +4 -1
  161. package/dist/versioned/report.js.map +1 -1
  162. package/dist/versioned/stand-down.d.ts +30 -0
  163. package/dist/versioned/stand-down.js +56 -0
  164. package/dist/versioned/stand-down.js.map +1 -0
  165. package/package.json +18 -8
  166. package/schemas/apply.schema.json +269 -0
  167. package/schemas/common.schema.json +213 -0
  168. package/schemas/drift.schema.json +36 -0
  169. package/schemas/init.schema.json +31 -0
  170. package/schemas/lint-rules.schema.json +54 -0
  171. package/schemas/lint.schema.json +290 -0
  172. package/schemas/mcp.schema.json +70 -0
  173. package/schemas/new.schema.json +71 -0
  174. package/schemas/plan.schema.json +371 -0
  175. package/schemas/rebase.schema.json +54 -0
  176. package/schemas/repair.schema.json +20 -0
  177. package/schemas/status.schema.json +310 -0
@@ -22,13 +22,13 @@
22
22
  * `PATH="$PWD/node_modules/.bin:$PATH"`. When `yodel apply` runs it, yodel
23
23
  * puts a `yodel` that runs itself first on the child's PATH.
24
24
  */
25
- import { chmodSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
25
+ import { chmodSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
26
26
  import { tmpdir } from "node:os";
27
27
  import { delimiter, extname, join } from "node:path";
28
28
  import { fileURLToPath } from "node:url";
29
29
  import { YodelError } from "../project.js";
30
30
  import { chantInstall, runChant } from "../chant/process.js";
31
- import { GATED, readApplyRun } from "../chant/apply.js";
31
+ import { discoveryError, GATED, readApplyRun } from "../chant/apply.js";
32
32
  /** The env var the Apply step reads the approved digest from. */
33
33
  export const APPROVED_PLAN_ENV = "YODEL_APPROVED_PLAN";
34
34
  /** Passes `--allow-out-of-order` through `chant run` to the Op's steps. */
@@ -106,7 +106,7 @@ export async function findMigrateOp(project, env, name) {
106
106
  found = await discoverOps({ cwd: project.dir });
107
107
  }
108
108
  catch (e) {
109
- throw new YodelError(`could not discover Ops in ${project.dir}: ${e instanceof Error ? e.message : String(e)}`);
109
+ throw discoveryError(project.dir, e);
110
110
  }
111
111
  if (found.errors.length > 0 && found.ops.size === 0)
112
112
  throw new YodelError(`could not discover Ops in ${project.dir}:\n${found.errors.join("\n")}`);
@@ -127,6 +127,34 @@ export function yodelShim() {
127
127
  chmodSync(path, 0o755);
128
128
  return { dir, dispose: () => { rmSync(dir, { recursive: true, force: true }); } };
129
129
  }
130
+ /**
131
+ * Where `yodel apply --execute` (the Op's Apply step) writes its exit code,
132
+ * so the outer `yodel apply` exits with it (5 for the lock, 4 for a refusal)
133
+ * rather than with `chant run`'s 1.
134
+ */
135
+ export const STEP_EXIT_ENV = "YODEL_STEP_EXIT_FILE";
136
+ /** Records an Op step's exit code where the outer `yodel apply` reads it. Never fails the step. */
137
+ export function recordStepExit(code, env = process.env) {
138
+ const file = env[STEP_EXIT_ENV];
139
+ if (!file)
140
+ return;
141
+ try {
142
+ writeFileSync(file, `${String(code)}\n`);
143
+ }
144
+ catch {
145
+ // The outer run then reports chant run's own exit.
146
+ }
147
+ }
148
+ /** The exit code the Op's Apply step recorded, when it ran. */
149
+ export function readStepExit(file) {
150
+ try {
151
+ const n = Number(readFileSync(file, "utf8").trim());
152
+ return Number.isInteger(n) ? n : undefined;
153
+ }
154
+ catch {
155
+ return undefined;
156
+ }
157
+ }
130
158
  /** Runs the migrations Op with `chant run`, with this yodel on PATH and `--allow-out-of-order` passed through. */
131
159
  export async function runMigrateOp(project, op, options) {
132
160
  const shim = yodelShim();
@@ -134,8 +162,10 @@ export async function runMigrateOp(project, op, options) {
134
162
  const base = options.env ?? process.env;
135
163
  // The approved digest only ever comes from the gate, never from the caller's environment.
136
164
  const rest = Object.fromEntries(Object.entries(base).filter(([k]) => k !== APPROVED_PLAN_ENV && k !== ALLOW_OUT_OF_ORDER_ENV));
165
+ const exitFile = join(shim.dir, "step-exit");
137
166
  const env = {
138
167
  ...rest,
168
+ [STEP_EXIT_ENV]: exitFile,
139
169
  PATH: [shim.dir, base.PATH ?? ""].filter(Boolean).join(delimiter),
140
170
  ...(options.allowOutOfOrder ? { [ALLOW_OUT_OF_ORDER_ENV]: "1" } : {}),
141
171
  };
@@ -144,7 +174,9 @@ export async function runMigrateOp(project, op, options) {
144
174
  env,
145
175
  ...(options.onOutput ? { onStdout: options.onOutput, onStderr: options.onOutput } : {}),
146
176
  });
147
- return readApplyRun(result.code, `${result.stdout}\n${result.stderr}`);
177
+ const run = readApplyRun(result.code, `${result.stdout}\n${result.stderr}`);
178
+ const stepExit = readStepExit(exitFile);
179
+ return stepExit === undefined ? run : { ...run, stepExit };
148
180
  }
149
181
  finally {
150
182
  shim.dispose();
@@ -1 +1 @@
1
- {"version":3,"file":"op.js","sourceRoot":"","sources":["../../src/versioned/op.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"op.js","sourceRoot":"","sources":["../../src/versioned/op.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Policy over the plan (#53): the rules `yodel.config.ts` `policy` declares
3
+ * (`../config/define.ts`), evaluated over the plan `yodel apply` would run,
4
+ * and the overrides recorded against them.
5
+ *
6
+ * `yodel plan` reports each rule's outcome; `yodel apply` refuses (exit 4)
7
+ * before the gate, and its Apply step again under the lock, a plan a rule
8
+ * denies. An override is a person's decision to run that plan anyway:
9
+ * `yodel override <env> --rule <id> --reason <text>` records it on chant's
10
+ * gate ledger (the `chant/lifecycle` branch) as an approval of the gate
11
+ * `override-<id>` of the migrations Op, for exactly the current plan digest,
12
+ * with the reason as its note. It counts only when the plan digest is the
13
+ * same, so it is refused once the plan moves, and only when
14
+ * `policy.overriders` lists who recorded it. The Apply step writes the
15
+ * overrides it relied on into the history (the `note` of each migration's
16
+ * `started` row).
17
+ */
18
+ import type { GateLedgerPort } from "@intentius/chant/op/gate";
19
+ import type { PolicyConfig, PolicyPlan } from "../config/define.js";
20
+ import type { SqlDialect } from "../project.js";
21
+ import { YodelError } from "../project.js";
22
+ import type { MigrateOpRef } from "./op.js";
23
+ import type { PendingMigration } from "./state.js";
24
+ /** The gate an override of `rule` is recorded as an approval of. */
25
+ export declare const overrideGate: (rule: string) => string;
26
+ /** An override that counts: who recorded it, when, why, and the digest it is for. */
27
+ export interface PolicyOverride {
28
+ rule: string;
29
+ by: string;
30
+ at: string;
31
+ reason: string;
32
+ digest: string;
33
+ }
34
+ export interface RuleResult {
35
+ id: string;
36
+ description?: string | undefined;
37
+ /** `denied` stands; `overridden` was denied, and an override counts. */
38
+ outcome: "allowed" | "denied" | "overridden";
39
+ /** Why it denies the plan, one line each. */
40
+ reasons: string[];
41
+ override?: PolicyOverride | undefined;
42
+ }
43
+ /** The plan a rule sees. */
44
+ export declare function policyPlan(environment: string, dialect: SqlDialect, toApply: readonly PendingMigration[], now?: Date): PolicyPlan;
45
+ /** Each rule that applies to the plan's environment, allowed or denied. No overrides yet. */
46
+ export declare function evaluatePolicy(policy: PolicyConfig | undefined, plan: PolicyPlan): RuleResult[];
47
+ /** The overrides on the ledger that count for `digest`: of a rule's override gate, for that digest, with a reason, by someone `overriders` lists. The newest per rule. */
48
+ export declare function readOverrides(port: GateLedgerPort, op: MigrateOpRef, digest: string, overriders: readonly string[] | undefined): Promise<PolicyOverride[]>;
49
+ /** The results with each denied rule an override counts for marked overridden. */
50
+ export declare function withOverrides(results: readonly RuleResult[], overrides: readonly PolicyOverride[]): RuleResult[];
51
+ /** The refusal for the rules that deny the plan with no override, or `undefined`. */
52
+ export declare function policyRefusal(results: readonly RuleResult[], environment: string, digest: string | undefined, when: string): YodelError | undefined;
53
+ /** The whole evaluation: the rules over the plan, with the overrides on the ledger for `digest`. Empty when the config declares no policy. */
54
+ export declare function judgePlan(input: {
55
+ policy: PolicyConfig | undefined;
56
+ environment: string;
57
+ dialect: SqlDialect;
58
+ toApply: readonly PendingMigration[];
59
+ digest: string | undefined;
60
+ ledger: () => Promise<{
61
+ port: GateLedgerPort;
62
+ op: MigrateOpRef;
63
+ } | undefined>;
64
+ now?: Date;
65
+ }): Promise<RuleResult[]>;
66
+ /** One line per rule, for text output. */
67
+ export declare function describeResults(results: readonly RuleResult[]): string[];
@@ -0,0 +1,161 @@
1
+ /**
2
+ * Policy over the plan (#53): the rules `yodel.config.ts` `policy` declares
3
+ * (`../config/define.ts`), evaluated over the plan `yodel apply` would run,
4
+ * and the overrides recorded against them.
5
+ *
6
+ * `yodel plan` reports each rule's outcome; `yodel apply` refuses (exit 4)
7
+ * before the gate, and its Apply step again under the lock, a plan a rule
8
+ * denies. An override is a person's decision to run that plan anyway:
9
+ * `yodel override <env> --rule <id> --reason <text>` records it on chant's
10
+ * gate ledger (the `chant/lifecycle` branch) as an approval of the gate
11
+ * `override-<id>` of the migrations Op, for exactly the current plan digest,
12
+ * with the reason as its note. It counts only when the plan digest is the
13
+ * same, so it is refused once the plan moves, and only when
14
+ * `policy.overriders` lists who recorded it. The Apply step writes the
15
+ * overrides it relied on into the history (the `note` of each migration's
16
+ * `started` row).
17
+ */
18
+ import { YodelError } from "../project.js";
19
+ import { EXIT_REFUSED } from "../exit.js";
20
+ import { silencesOf } from "../lint/index.js";
21
+ import { sameDigest } from "./digest.js";
22
+ /** The gate an override of `rule` is recorded as an approval of. */
23
+ export const overrideGate = (rule) => `override-${rule}`;
24
+ /** The plan a rule sees. */
25
+ export function policyPlan(environment, dialect, toApply, now = new Date()) {
26
+ return {
27
+ environment,
28
+ dialect,
29
+ now: now.toISOString(),
30
+ pending: toApply.map((p) => ({
31
+ id: p.id,
32
+ checksum: p.checksum,
33
+ outOfOrder: p.outOfOrder,
34
+ steps: p.migration.document.steps.map((s, index) => {
35
+ if (s.kind === "statement") {
36
+ return { index, kind: "statement", object: s.object, name: s.name, classes: [s.class], destructive: s.destructive === true, rules: [s.rule], sql: s.sql };
37
+ }
38
+ return {
39
+ index,
40
+ kind: s.kind,
41
+ object: s.object,
42
+ name: s.name,
43
+ classes: [...new Set(s.changes.map((c) => c.class))],
44
+ destructive: s.changes.some((c) => c.destructive === true),
45
+ rules: [...new Set(s.changes.map((c) => c.rule))],
46
+ ...(s.kind === "op" ? { op: s.op } : {}),
47
+ };
48
+ }),
49
+ silences: silencesOf(p.migration).map(({ step, rule, reason }) => ({ step, rule, reason })),
50
+ })),
51
+ };
52
+ }
53
+ const applies = (rule, environment) => rule.environments === undefined || rule.environments.includes(environment);
54
+ function denials(rule, plan) {
55
+ const out = [];
56
+ if (rule.refuse) {
57
+ const { classes = [], destructive = false } = rule.refuse;
58
+ for (const m of plan.pending) {
59
+ for (const s of m.steps) {
60
+ const cls = s.classes.filter((c) => classes.includes(c));
61
+ if (cls.length > 0)
62
+ out.push(`${m.id} step ${String(s.index)} (${s.name}) is ${cls.join(", ")}`);
63
+ else if (destructive && s.destructive)
64
+ out.push(`${m.id} step ${String(s.index)} (${s.name}) is destructive`);
65
+ }
66
+ }
67
+ }
68
+ if (rule.silences) {
69
+ const { rules, reason } = rule.silences;
70
+ for (const m of plan.pending) {
71
+ for (const s of m.silences) {
72
+ if (rules && !rules.includes(s.rule))
73
+ continue;
74
+ reason.lastIndex = 0;
75
+ if (!reason.test(s.reason))
76
+ out.push(`${m.id} step ${String(s.step)} silences ${s.rule} with a reason that does not match ${String(reason)}: ${JSON.stringify(s.reason)}`);
77
+ }
78
+ }
79
+ }
80
+ if (rule.check) {
81
+ let said;
82
+ try {
83
+ said = rule.check(plan);
84
+ }
85
+ catch (e) {
86
+ said = `its check threw: ${e instanceof Error ? e.message : String(e)}`;
87
+ }
88
+ if (said === false)
89
+ out.push(rule.description ?? "its check denies the plan");
90
+ else if (typeof said === "string")
91
+ out.push(said);
92
+ else if (Array.isArray(said))
93
+ out.push(...said);
94
+ }
95
+ return out;
96
+ }
97
+ /** Each rule that applies to the plan's environment, allowed or denied. No overrides yet. */
98
+ export function evaluatePolicy(policy, plan) {
99
+ return (policy?.rules ?? [])
100
+ .filter((r) => applies(r, plan.environment))
101
+ .map((r) => {
102
+ const reasons = denials(r, plan);
103
+ return { id: r.id, ...(r.description ? { description: r.description } : {}), outcome: reasons.length > 0 ? "denied" : "allowed", reasons };
104
+ });
105
+ }
106
+ /** The overrides on the ledger that count for `digest`: of a rule's override gate, for that digest, with a reason, by someone `overriders` lists. The newest per rule. */
107
+ export async function readOverrides(port, op, digest, overriders) {
108
+ const { resolutions } = await port.read(op.name);
109
+ const byRule = new Map();
110
+ for (const r of resolutions) {
111
+ if (!r.gate.startsWith("override-") || !r.note || !(overriders ?? []).includes(r.resolvedBy))
112
+ continue;
113
+ if (!(await sameDigest(r.planDigest, digest)))
114
+ continue;
115
+ const rule = r.gate.slice("override-".length);
116
+ const prior = byRule.get(rule);
117
+ if (!prior || prior.at < r.timestamp)
118
+ byRule.set(rule, { rule, by: r.resolvedBy, at: r.timestamp, reason: r.note, digest });
119
+ }
120
+ return [...byRule.values()];
121
+ }
122
+ /** The results with each denied rule an override counts for marked overridden. */
123
+ export function withOverrides(results, overrides) {
124
+ return results.map((r) => {
125
+ const o = r.outcome === "denied" ? overrides.find((x) => x.rule === r.id) : undefined;
126
+ return o ? { ...r, outcome: "overridden", override: o } : r;
127
+ });
128
+ }
129
+ /** The refusal for the rules that deny the plan with no override, or `undefined`. */
130
+ export function policyRefusal(results, environment, digest, when) {
131
+ const denied = results.filter((r) => r.outcome === "denied");
132
+ if (denied.length === 0)
133
+ return undefined;
134
+ const lines = denied.flatMap((r) => [` ${r.id}${r.description ? ` (${r.description})` : ""}:`, ...r.reasons.map((x) => ` ${x}`)]);
135
+ const ids = denied.map((r) => r.id).join(", ");
136
+ return new YodelError(`refused by policy ${when}: ${denied.length === 1 ? "rule" : "rules"} ${ids} ${denied.length === 1 ? "denies" : "deny"} this plan${digest ? ` (${digest})` : ""}. Nothing was applied:\n${lines.join("\n")}\n` +
137
+ `To run it anyway, someone policy.overriders lists records why, for exactly this plan: ${denied.map((r) => `yodel override ${environment} --rule ${r.id} --reason "<why>"`).join("; ")}`, EXIT_REFUSED);
138
+ }
139
+ /** The whole evaluation: the rules over the plan, with the overrides on the ledger for `digest`. Empty when the config declares no policy. */
140
+ export async function judgePlan(input) {
141
+ if (!input.policy || input.toApply.length === 0)
142
+ return [];
143
+ const results = evaluatePolicy(input.policy, policyPlan(input.environment, input.dialect, input.toApply, input.now));
144
+ if (!input.digest || !results.some((r) => r.outcome === "denied"))
145
+ return results;
146
+ const at = await input.ledger();
147
+ if (!at)
148
+ return results;
149
+ return withOverrides(results, await readOverrides(at.port, at.op, input.digest, input.policy.overriders));
150
+ }
151
+ /** One line per rule, for text output. */
152
+ export function describeResults(results) {
153
+ return results.map((r) => {
154
+ if (r.outcome === "allowed")
155
+ return `policy ${r.id}: allowed`;
156
+ if (r.outcome === "overridden" && r.override)
157
+ return `policy ${r.id}: denied, overridden by ${r.override.by} at ${r.override.at}: ${r.override.reason}`;
158
+ return `policy ${r.id}: denied: ${r.reasons.join("; ")}`;
159
+ });
160
+ }
161
+ //# sourceMappingURL=policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.js","sourceRoot":"","sources":["../../src/versioned/policy.ts"],"names":[],"mappings":"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"}
@@ -11,7 +11,7 @@
11
11
  *
12
12
  * and from `sql.profiles.<env>`, as chant's applier reads them:
13
13
  *
14
- * lockTimeoutMs lock_timeout for every statement (default 5000)
14
+ * lockTimeoutMs lock_timeout for every statement, and for the live-schema read (default 5000)
15
15
  * statementTimeoutMs statement_timeout for a catalog change (default 60000)
16
16
  * scanTimeoutMs statement_timeout for a statement that reads or rewrites rows (default none)
17
17
  * schemas the schemas the plan digest's fingerprint covers (default every schema but the server's own)
@@ -65,5 +65,7 @@ export interface PostgresDriverInput {
65
65
  store: PostgresHistoryStore;
66
66
  sleep?: (ms: number) => Promise<void>;
67
67
  retryBaseMs?: number;
68
+ /** Where a read held up by another session's lock says so; default stderr. */
69
+ log?: (line: string) => void;
68
70
  }
69
71
  export declare function postgresDriver(input: PostgresDriverInput): VersionedDriver;
@@ -11,7 +11,7 @@
11
11
  *
12
12
  * and from `sql.profiles.<env>`, as chant's applier reads them:
13
13
  *
14
- * lockTimeoutMs lock_timeout for every statement (default 5000)
14
+ * lockTimeoutMs lock_timeout for every statement, and for the live-schema read (default 5000)
15
15
  * statementTimeoutMs statement_timeout for a catalog change (default 60000)
16
16
  * scanTimeoutMs statement_timeout for a statement that reads or rewrites rows (default none)
17
17
  * schemas the schemas the plan digest's fingerprint covers (default every schema but the server's own)
@@ -22,8 +22,9 @@
22
22
  */
23
23
  import { YodelError } from "../../project.js";
24
24
  import { DEFAULT_HISTORY_DATABASE } from "../../history/index.js";
25
- import { acquireAdvisoryLock, PostgresHistoryStore } from "../../history/postgres/index.js";
25
+ import { acquireAdvisoryLock, pgIdent, PostgresHistoryStore } from "../../history/postgres/index.js";
26
26
  import { pgCatalogFingerprint, readPgCatalog } from "./catalog.js";
27
+ import { readUnderLockTimeout } from "./waits.js";
27
28
  import { DEFAULT_LOCK_RETRIES, DEFAULT_PG_TIMEOUTS, PgStatementError, runPgStatement } from "./executor.js";
28
29
  export function pgSettings(target, env = process.env, historySchema = env.YODEL_HISTORY_DATABASE || DEFAULT_HISTORY_DATABASE) {
29
30
  const retries = env.YODEL_LOCK_RETRIES ? Number(env.YODEL_LOCK_RETRIES) : DEFAULT_LOCK_RETRIES;
@@ -83,7 +84,33 @@ export function postgresDriver(input) {
83
84
  return acquireAdvisoryLock(await input.connect(), { schema: settings.historySchema, holder });
84
85
  },
85
86
  async liveFingerprint() {
86
- return pgCatalogFingerprint(await readPgCatalog(client, { schemas: input.schemas, historySchema: settings.historySchema }));
87
+ const read = () => readPgCatalog(client, { schemas: input.schemas, historySchema: settings.historySchema });
88
+ const entries = await readUnderLockTimeout(client, read, {
89
+ lockTimeoutMs: settings.timeouts.lockTimeoutMs,
90
+ retries: settings.lockRetries,
91
+ schemas: input.schemas,
92
+ what: "the live schema",
93
+ log: input.log ?? ((line) => process.stderr.write(`yodel: ${line}\n`)),
94
+ ...(input.sleep ? { sleep: input.sleep } : {}),
95
+ ...(input.retryBaseMs !== undefined ? { retryBaseMs: input.retryBaseMs } : {}),
96
+ });
97
+ return pgCatalogFingerprint(entries);
98
+ },
99
+ async readCheck(sql, where) {
100
+ await client.query("BEGIN READ ONLY");
101
+ try {
102
+ if (where.defaultSchema)
103
+ await client.query(`SELECT pg_catalog.set_config('search_path', $1, true)`, [pgIdent(where.defaultSchema)]);
104
+ // A check reads rows: the scan timeout (default none), and the lock timeout every statement gets.
105
+ await client.query(`SELECT pg_catalog.set_config('statement_timeout', $1, true), pg_catalog.set_config('lock_timeout', $2, true)`, [
106
+ String(settings.timeouts.scanTimeoutMs),
107
+ String(settings.timeouts.lockTimeoutMs),
108
+ ]);
109
+ return await client.query(sql);
110
+ }
111
+ finally {
112
+ await client.query("ROLLBACK").catch(() => undefined);
113
+ }
87
114
  },
88
115
  async runStatement(step, run) {
89
116
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"driver.js","sourceRoot":"","sources":["../../../src/versioned/postgres/driver.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"driver.js","sourceRoot":"","sources":["../../../src/versioned/postgres/driver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Reads of the live schema that another session's lock can block (#18): the
3
+ * fingerprint the plan digest covers, read before every apply and plan.
4
+ * chant's catalog reader calls `pg_get_viewdef()` and friends, which wait
5
+ * for a table's ACCESS SHARE lock, so a session holding ACCESS EXCLUSIVE on
6
+ * a declared table (a long `ALTER TABLE`, a `LOCK TABLE`) would hold the read
7
+ * up for as long as it holds the lock, with nothing printed.
8
+ *
9
+ * So the read runs under the profile's `lockTimeoutMs`, and when that passes
10
+ * (SQLSTATE 55P03) yodel says which lock it waited on and who holds it, and
11
+ * tries again with the same pauses and count as a statement (250 ms, then
12
+ * doubling, YODEL_LOCK_RETRIES more times). When the lock is still held after
13
+ * the last try, the read fails with the same description.
14
+ */
15
+ import type { PgClient } from "../../history/postgres/index.js";
16
+ /** A session's ACCESS EXCLUSIVE lock on a relation, held or queued for. */
17
+ export interface LockHolder {
18
+ schema: string;
19
+ name: string;
20
+ pid: number;
21
+ granted: boolean;
22
+ application: string;
23
+ }
24
+ /** The ACCESS EXCLUSIVE locks other sessions hold (or wait for) on relations in `schemas` (every schema but the server's own when undefined). */
25
+ export declare function lockHolders(client: PgClient, schemas: readonly string[] | undefined): Promise<LockHolder[]>;
26
+ /** `a lock on shop.orders (held by pid 123, psql)`, or `a lock held by another session` when none could be named. */
27
+ export declare function describeHolders(holders: readonly LockHolder[]): string;
28
+ export interface LockedReadOptions {
29
+ lockTimeoutMs: number;
30
+ retries: number;
31
+ /** The schemas to look for the lock in. */
32
+ schemas: readonly string[] | undefined;
33
+ /** What is being read, for the messages: `the live schema`. */
34
+ what: string;
35
+ log: (line: string) => void;
36
+ retryBaseMs?: number;
37
+ sleep?: (ms: number) => Promise<void>;
38
+ }
39
+ declare const seconds: (ms: number) => string;
40
+ /** Runs `read` on `client` with `lock_timeout` set, retrying (and saying why) when another session's lock holds it up. */
41
+ export declare function readUnderLockTimeout<T>(client: PgClient, read: () => Promise<T>, o: LockedReadOptions): Promise<T>;
42
+ /** The `PGOPTIONS` a chant child reads Postgres under, so a read blocked by a lock gives up after `lockTimeoutMs` (node-postgres passes it to the server). */
43
+ export declare function lockTimeoutOptions(lockTimeoutMs: number, existing: string | undefined): string;
44
+ /** Whether a read failed because the lock timeout passed. */
45
+ export declare const isLockTimeout: (text: string | undefined) => boolean;
46
+ export { seconds as describeMs };
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Reads of the live schema that another session's lock can block (#18): the
3
+ * fingerprint the plan digest covers, read before every apply and plan.
4
+ * chant's catalog reader calls `pg_get_viewdef()` and friends, which wait
5
+ * for a table's ACCESS SHARE lock, so a session holding ACCESS EXCLUSIVE on
6
+ * a declared table (a long `ALTER TABLE`, a `LOCK TABLE`) would hold the read
7
+ * up for as long as it holds the lock, with nothing printed.
8
+ *
9
+ * So the read runs under the profile's `lockTimeoutMs`, and when that passes
10
+ * (SQLSTATE 55P03) yodel says which lock it waited on and who holds it, and
11
+ * tries again with the same pauses and count as a statement (250 ms, then
12
+ * doubling, YODEL_LOCK_RETRIES more times). When the lock is still held after
13
+ * the last try, the read fails with the same description.
14
+ */
15
+ import { YodelError } from "../../project.js";
16
+ import { DEFAULT_RETRY_BASE_MS, LOCK_NOT_AVAILABLE } from "./executor.js";
17
+ const sqlstate = (e) => e && typeof e === "object" && "code" in e && typeof e.code === "string" ? e.code : undefined;
18
+ /** The ACCESS EXCLUSIVE locks other sessions hold (or wait for) on relations in `schemas` (every schema but the server's own when undefined). */
19
+ export async function lockHolders(client, schemas) {
20
+ const rows = await client.query(`SELECT n.nspname AS schema, c.relname AS name, l.pid, l.granted, a.application_name AS application
21
+ FROM pg_catalog.pg_locks l
22
+ JOIN pg_catalog.pg_class c ON c.oid = l.relation
23
+ JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
24
+ LEFT JOIN pg_catalog.pg_stat_activity a ON a.pid = l.pid
25
+ WHERE l.locktype = 'relation' AND l.mode = 'AccessExclusiveLock' AND l.pid <> pg_catalog.pg_backend_pid()
26
+ AND n.nspname NOT IN ('pg_catalog', 'information_schema') AND n.nspname NOT LIKE 'pg\\_toast%'
27
+ AND ($1::text[] IS NULL OR n.nspname = ANY ($1::text[]))
28
+ ORDER BY l.granted DESC, n.nspname, c.relname, l.pid
29
+ LIMIT 5`, [schemas ? [...schemas] : null]);
30
+ return rows.map((r) => ({ schema: r.schema, name: r.name, pid: Number(r.pid), granted: r.granted, application: r.application ?? "" }));
31
+ }
32
+ /** `a lock on shop.orders (held by pid 123, psql)`, or `a lock held by another session` when none could be named. */
33
+ export function describeHolders(holders) {
34
+ if (holders.length === 0)
35
+ return "a lock another session holds on an object in scope";
36
+ const one = (h) => `${h.schema}.${h.name} (${h.granted ? "held" : "queued for"} by pid ${String(h.pid)}${h.application ? `, ${h.application}` : ""})`;
37
+ return `a lock on ${holders.map(one).join(", ")}`;
38
+ }
39
+ const sleeper = (ms) => new Promise((r) => setTimeout(r, ms));
40
+ const seconds = (ms) => (ms < 1000 ? `${String(ms)}ms` : `${String(Math.round(ms / 100) / 10)}s`);
41
+ /** Runs `read` on `client` with `lock_timeout` set, retrying (and saying why) when another session's lock holds it up. */
42
+ export async function readUnderLockTimeout(client, read, o) {
43
+ const sleep = o.sleep ?? sleeper;
44
+ const base = o.retryBaseMs ?? DEFAULT_RETRY_BASE_MS;
45
+ const [prev] = await client.query("SELECT pg_catalog.current_setting('lock_timeout') AS lock_timeout");
46
+ await client.query("SELECT pg_catalog.set_config('lock_timeout', $1, false)", [`${String(Math.max(0, Math.floor(o.lockTimeoutMs)))}ms`]);
47
+ try {
48
+ for (let attempt = 0;; attempt++) {
49
+ try {
50
+ return await read();
51
+ }
52
+ catch (e) {
53
+ if (sqlstate(e) !== LOCK_NOT_AVAILABLE)
54
+ throw e;
55
+ const holders = await lockHolders(client, o.schemas).catch(() => []);
56
+ const waited = `reading ${o.what} waited ${seconds(o.lockTimeoutMs)} for ${describeHolders(holders)}`;
57
+ if (attempt >= o.retries) {
58
+ const pid = holders.find((h) => h.granted)?.pid;
59
+ throw new YodelError(`${waited}, ${String(attempt + 1)} time(s); nothing was changed. Try again once it is released${pid !== undefined ? `, or end that session with: SELECT pg_terminate_backend(${String(pid)})` : ""}`);
60
+ }
61
+ const pause = base * 2 ** attempt;
62
+ o.log(`${waited}; trying again in ${seconds(pause)} (${String(attempt + 1)} of ${String(o.retries)})`);
63
+ await sleep(pause);
64
+ }
65
+ }
66
+ }
67
+ finally {
68
+ await client.query("SELECT pg_catalog.set_config('lock_timeout', $1, false)", [prev?.lock_timeout ?? "0"]).catch(() => undefined);
69
+ }
70
+ }
71
+ /** The `PGOPTIONS` a chant child reads Postgres under, so a read blocked by a lock gives up after `lockTimeoutMs` (node-postgres passes it to the server). */
72
+ export function lockTimeoutOptions(lockTimeoutMs, existing) {
73
+ return [existing?.trim(), `-c lock_timeout=${String(Math.max(0, Math.floor(lockTimeoutMs)))}`].filter(Boolean).join(" ");
74
+ }
75
+ /** Whether a read failed because the lock timeout passed. */
76
+ export const isLockTimeout = (text) => text !== undefined && /lock timeout/i.test(text);
77
+ export { seconds as describeMs };
78
+ //# sourceMappingURL=waits.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"waits.js","sourceRoot":"","sources":["../../../src/versioned/postgres/waits.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,12 @@
1
1
  /** The versioned status as text and as JSON, for `yodel status` and `yodel apply --plan`. */
2
2
  import type { SqlDialect } from "../project.js";
3
3
  import { type HistoryLocation } from "../history/index.js";
4
+ import { type ServerInfo } from "../server.js";
4
5
  import { type VersionedStatus } from "./state.js";
5
6
  export interface StatusReport {
6
7
  environment: string;
8
+ /** The server the history was read from (#11). */
9
+ server?: ServerInfo | undefined;
7
10
  /** Postgres has no topology: its report leaves it out. Default ClickHouse. */
8
11
  dialect?: SqlDialect | undefined;
9
12
  location: HistoryLocation;