@intentius/chant 0.122.0 → 0.123.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 (156) hide show
  1. package/dist/cli/commands/lint.d.ts.map +1 -1
  2. package/dist/cli/handlers/gate-resume.d.ts +1 -1
  3. package/dist/cli/handlers/gate-resume.d.ts.map +1 -1
  4. package/dist/cli/handlers/operator.d.ts +1 -1
  5. package/dist/cli/handlers/operator.d.ts.map +1 -1
  6. package/dist/cli/handlers/override-approve.d.ts +17 -0
  7. package/dist/cli/handlers/override-approve.d.ts.map +1 -0
  8. package/dist/cli/handlers/run-wave.d.ts.map +1 -1
  9. package/dist/cli/main.d.ts.map +1 -1
  10. package/dist/cli/registry.d.ts +4 -0
  11. package/dist/cli/registry.d.ts.map +1 -1
  12. package/dist/gate-decision.d.ts +157 -0
  13. package/dist/gate-decision.d.ts.map +1 -0
  14. package/dist/lifecycle/gate-applied.d.ts +75 -0
  15. package/dist/lifecycle/gate-applied.d.ts.map +1 -0
  16. package/dist/lifecycle/gate-audit.d.ts +145 -0
  17. package/dist/lifecycle/gate-audit.d.ts.map +1 -0
  18. package/dist/lifecycle/gate-ledger-select.d.ts +54 -0
  19. package/dist/lifecycle/gate-ledger-select.d.ts.map +1 -0
  20. package/dist/lifecycle/gate-ledger.d.ts +1 -45
  21. package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
  22. package/dist/lifecycle/override-ledger.d.ts +34 -0
  23. package/dist/lifecycle/override-ledger.d.ts.map +1 -0
  24. package/dist/lifecycle/rollback.d.ts.map +1 -1
  25. package/dist/lifecycle/work-item-id.d.ts +22 -0
  26. package/dist/lifecycle/work-item-id.d.ts.map +1 -0
  27. package/dist/lifecycle/work-lease.d.ts +2 -2
  28. package/dist/lifecycle/work-lease.d.ts.map +1 -1
  29. package/dist/lint/post-synth.d.ts +20 -1
  30. package/dist/lint/post-synth.d.ts.map +1 -1
  31. package/dist/notify-verify.d.ts +62 -0
  32. package/dist/notify-verify.d.ts.map +1 -0
  33. package/dist/notify.d.ts +202 -0
  34. package/dist/notify.d.ts.map +1 -0
  35. package/dist/op/activities/activity-contracts.d.ts +4 -4
  36. package/dist/op/activities/gh-host.d.ts +37 -0
  37. package/dist/op/activities/gh-host.d.ts.map +1 -0
  38. package/dist/op/activities/lexicon-upgrade.d.ts +11 -0
  39. package/dist/op/activities/lexicon-upgrade.d.ts.map +1 -1
  40. package/dist/op/activities/propose-upgrade.d.ts.map +1 -1
  41. package/dist/op/activities/reconcile.d.ts +74 -76
  42. package/dist/op/activities/reconcile.d.ts.map +1 -1
  43. package/dist/op/gate-approval.d.ts +17 -1
  44. package/dist/op/gate-approval.d.ts.map +1 -1
  45. package/dist/op/gate-name.d.ts +8 -1
  46. package/dist/op/gate-name.d.ts.map +1 -1
  47. package/dist/op/gate-resume.d.ts +4 -2
  48. package/dist/op/gate-resume.d.ts.map +1 -1
  49. package/dist/op/gate-review.d.ts +2 -1
  50. package/dist/op/gate-review.d.ts.map +1 -1
  51. package/dist/op/gate.d.ts +43 -6
  52. package/dist/op/gate.d.ts.map +1 -1
  53. package/dist/op/index.d.ts +8 -6
  54. package/dist/op/index.d.ts.map +1 -1
  55. package/dist/op/op-waves-notify.d.ts +31 -0
  56. package/dist/op/op-waves-notify.d.ts.map +1 -0
  57. package/dist/op/op-waves-run.d.ts +91 -16
  58. package/dist/op/op-waves-run.d.ts.map +1 -1
  59. package/dist/op/op-waves.d.ts +99 -2
  60. package/dist/op/op-waves.d.ts.map +1 -1
  61. package/dist/op/operator.d.ts +15 -0
  62. package/dist/op/operator.d.ts.map +1 -1
  63. package/dist/op/work-lease-decl.d.ts.map +1 -1
  64. package/dist/op/work-lease-run.d.ts.map +1 -1
  65. package/dist/override-gate.d.ts +224 -0
  66. package/dist/override-gate.d.ts.map +1 -0
  67. package/dist/pr-forge.d.ts +198 -19
  68. package/dist/pr-forge.d.ts.map +1 -1
  69. package/dist/workspace/status-gates.d.ts +1 -0
  70. package/dist/workspace/status-gates.d.ts.map +1 -1
  71. package/dist/workspace/trust/gate-seal.d.ts +96 -0
  72. package/dist/workspace/trust/gate-seal.d.ts.map +1 -0
  73. package/dist/workspace/trust/policy.d.ts +2 -41
  74. package/dist/workspace/trust/policy.d.ts.map +1 -1
  75. package/dist/workspace/trust/seal.d.ts +2 -27
  76. package/dist/workspace/trust/seal.d.ts.map +1 -1
  77. package/dist/workspace/trust/trust-files.d.ts +57 -0
  78. package/dist/workspace/trust/trust-files.d.ts.map +1 -0
  79. package/dist/workspace/work-cli.d.ts.map +1 -1
  80. package/package.json +2 -1
  81. package/src/cli/commands/build.ts +1 -1
  82. package/src/cli/commands/lint.ts +5 -2
  83. package/src/cli/handlers/__snapshots__/build-member.test.ts.snap +2 -2
  84. package/src/cli/handlers/gate-resume.ts +3 -2
  85. package/src/cli/handlers/operator.test.ts +12 -1
  86. package/src/cli/handlers/operator.ts +25 -13
  87. package/src/cli/handlers/override-approve.test.ts +87 -0
  88. package/src/cli/handlers/override-approve.ts +103 -0
  89. package/src/cli/handlers/run-wave.ts +10 -2
  90. package/src/cli/main.test.ts +8 -0
  91. package/src/cli/main.ts +15 -0
  92. package/src/cli/registry.ts +4 -0
  93. package/src/gate-decision-bundle.test.ts +56 -0
  94. package/src/gate-decision.test.ts +237 -0
  95. package/src/gate-decision.ts +321 -0
  96. package/src/lifecycle/gate-applied.ts +115 -0
  97. package/src/lifecycle/gate-audit-bundle.test.ts +47 -0
  98. package/src/lifecycle/gate-audit.test.ts +134 -0
  99. package/src/lifecycle/gate-audit.ts +438 -0
  100. package/src/lifecycle/gate-ledger-select.ts +113 -0
  101. package/src/lifecycle/gate-ledger.test.ts +22 -0
  102. package/src/lifecycle/gate-ledger.ts +9 -104
  103. package/src/lifecycle/override-ledger.test.ts +63 -0
  104. package/src/lifecycle/override-ledger.ts +69 -0
  105. package/src/lifecycle/rollback.ts +5 -1
  106. package/src/lifecycle/work-item-id.test.ts +71 -0
  107. package/src/lifecycle/work-item-id.ts +35 -0
  108. package/src/lifecycle/work-lease.ts +4 -5
  109. package/src/lint/post-synth.test.ts +29 -0
  110. package/src/lint/post-synth.ts +21 -2
  111. package/src/notify-bundle.test.ts +50 -0
  112. package/src/notify-verify.test.ts +59 -0
  113. package/src/notify-verify.ts +93 -0
  114. package/src/notify.schema.json +72 -0
  115. package/src/notify.test.ts +279 -0
  116. package/src/notify.ts +398 -0
  117. package/src/op/activities/gh-host.test.ts +130 -0
  118. package/src/op/activities/gh-host.ts +79 -0
  119. package/src/op/activities/lexicon-upgrade.ts +22 -1
  120. package/src/op/activities/propose-upgrade.ts +5 -1
  121. package/src/op/activities/reconcile.test.ts +284 -280
  122. package/src/op/activities/reconcile.ts +128 -131
  123. package/src/op/gate-approval.test.ts +175 -7
  124. package/src/op/gate-approval.ts +27 -1
  125. package/src/op/gate-name.ts +10 -2
  126. package/src/op/gate-resume.ts +6 -3
  127. package/src/op/gate-review.ts +4 -7
  128. package/src/op/gate.ts +117 -16
  129. package/src/op/index.ts +20 -5
  130. package/src/op/op-waves-notify.test.ts +127 -0
  131. package/src/op/op-waves-notify.ts +101 -0
  132. package/src/op/op-waves-run.ts +527 -104
  133. package/src/op/op-waves.test.ts +383 -3
  134. package/src/op/op-waves.ts +187 -6
  135. package/src/op/operator.test.ts +29 -0
  136. package/src/op/operator.ts +27 -2
  137. package/src/op/run-context.test.ts +2 -2
  138. package/src/op/work-lease-decl.ts +4 -4
  139. package/src/op/work-lease-run.test.ts +5 -0
  140. package/src/op/work-lease-run.ts +4 -3
  141. package/src/override-gate-bundle.test.ts +47 -0
  142. package/src/override-gate.test.ts +239 -0
  143. package/src/override-gate.ts +395 -0
  144. package/src/pr-forge-bundle.test.ts +40 -0
  145. package/src/pr-forge.test.ts +303 -0
  146. package/src/pr-forge.ts +502 -47
  147. package/src/workspace/records-write-contract.test.ts +3 -2
  148. package/src/workspace/status-gates.ts +7 -4
  149. package/src/workspace/trust/gate-seal.test.ts +156 -0
  150. package/src/workspace/trust/gate-seal.ts +254 -0
  151. package/src/workspace/trust/policy.ts +10 -165
  152. package/src/workspace/trust/seal.ts +19 -34
  153. package/src/workspace/trust/trust-files.test.ts +50 -0
  154. package/src/workspace/trust/trust-files.ts +245 -0
  155. package/src/workspace/work-cli.ts +5 -3
  156. package/src/workspace/work-history.test.ts +7 -0
@@ -0,0 +1,224 @@
1
+ /**
2
+ * The override gate (#3760, decision #3756): a person's recorded, reasoned
3
+ * decision to apply one plan a policy denied, spent once a run applies it.
4
+ *
5
+ * The policy engines stay in the products (OPA and conftest in terragucci,
6
+ * config rules in SQL Yodeler). They say a plan is denied and by which rules.
7
+ * This module records and decides the overrides of those denials, so a
8
+ * product keeps a thin layer over it:
9
+ *
10
+ * - A denial is a pending fact on `_gates/policy-override.jsonl` on
11
+ * `chant/lifecycle`, gate the subject (a root, an environment, whatever the
12
+ * product applies one plan to), with the rules that denied it
13
+ * ({@link overridePending}). Its `planDigest` is the override digest
14
+ * ({@link overrideDigest}), which binds the subject, the plan digest and
15
+ * the rule ids, so `chant approve` copies it by default.
16
+ * - An override is an approval of that gate and digest, written with
17
+ * `chant approve policy-override <subject> --rule <id> --reason <text>`
18
+ * (`--sign` under `sealed`). The reason is its `note`.
19
+ * - It counts ({@link decideOverride}) when it is newer than the subject's
20
+ * newest pending fact, names this digest, was written by a person the
21
+ * overriders at base list ({@link overridersAt}), gives a reason, and under
22
+ * `sealed` carries a seal that verifies for its approver against the
23
+ * signers file at base. A line a job wrote (one that carries `via` or a
24
+ * forge `review`) or an agent wrote never counts.
25
+ * - Before a run applies under an override it appends an applied record
26
+ * ({@link appliedOverride}) to `_gates/policy-override/applied.jsonl`. An
27
+ * override with an applied record is spent: it counts for nothing again, so
28
+ * a plan that is denied again waits for its own override, and a spent
29
+ * override of an older plan is not reported as a moved plan.
30
+ *
31
+ * Like `./gate-decision.ts` it reads the lines it is handed and writes
32
+ * nothing; `override-gate-bundle.test.ts` holds its import graph to the
33
+ * same bundle. chant's own writers are in `./lifecycle/override-ledger.ts`.
34
+ */
35
+ import { type GateSigners } from "./workspace/trust/gate-seal.js";
36
+ import type { GateResolutionRecord, PendingGateRecord } from "./lifecycle/gate-ledger.js";
37
+ import type { GateApprovalSource } from "./op/op-waves.js";
38
+ import type { GateAuditApply } from "./lifecycle/gate-audit.js";
39
+ export type { GateResolutionRecord, PendingGateRecord } from "./lifecycle/gate-ledger.js";
40
+ export type { GateSigners } from "./workspace/trust/gate-seal.js";
41
+ /** The op every override and denial is recorded under. `./lifecycle/gate-audit.ts` reads this op as overrides by default. */
42
+ export declare const OVERRIDE_OP = "policy-override";
43
+ /** The ledger file on `chant/lifecycle` that holds denials and overrides. */
44
+ export declare const OVERRIDE_LEDGER = "_gates/policy-override.jsonl";
45
+ /** The file beside it that holds the overrides a run applied under. chant reads only the `.jsonl` files directly under `_gates/` as gate ledgers, so it never reads these lines as gate records. */
46
+ export declare const OVERRIDE_APPLIED = "_gates/policy-override/applied.jsonl";
47
+ /** Where the overriders are read at base when the caller names no other file: one principal per line, `#` starts a comment. */
48
+ export declare const OVERRIDERS_PATH = ".chant/overriders";
49
+ /** The rules as an override names them: trimmed, each once, sorted. */
50
+ export declare function sortedRules(rules: readonly string[]): string[];
51
+ /**
52
+ * The digest an override binds: the subject, its plan digest and the rules
53
+ * that denied it, as `sha256:<hex>` over their LF-joined lines after the op
54
+ * name. A plan that moved, or a different set of rules, gives another digest,
55
+ * so an override of one denial never lets another through.
56
+ */
57
+ export declare function overrideDigest(subject: string, planDigest: string, rules: readonly string[]): string;
58
+ /** The command that overrides a denial. */
59
+ export declare function overrideCommand(subject: string, rules: readonly string[], sealed?: boolean): string;
60
+ /** A denial's pending fact: the gate's record, with the plan it denied and the rules that denied it. `planDigest` is the override digest. */
61
+ export interface OverridePendingRecord extends PendingGateRecord {
62
+ /** The plan digest the policy denied. */
63
+ plan: string;
64
+ /** The ids of the rules that denied it, sorted. */
65
+ rules: string[];
66
+ }
67
+ export interface OverridePendingInput {
68
+ subject: string;
69
+ planDigest: string;
70
+ rules: readonly string[];
71
+ /** ISO-8601. */
72
+ timestamp: string;
73
+ /** ISO-8601; past it a run that is still denied records a fresh fact. */
74
+ expiresAt: string;
75
+ description?: string;
76
+ runId?: string;
77
+ url?: string;
78
+ }
79
+ /** The pending fact a run records when the policy denies a plan and no override counts for it ({@link decideOverride} returns no `standing` fact). Appending it is the caller's. */
80
+ export declare function overridePending(input: OverridePendingInput): OverridePendingRecord;
81
+ /** The denials on the ledger: each subject's newest pending fact of the override op that names a plan. Sorted by subject. */
82
+ export declare function recordedDenials(pending: readonly PendingGateRecord[]): OverridePendingRecord[];
83
+ /** The overriders file at base. */
84
+ export interface Overriders {
85
+ /** The commit it was read at. */
86
+ base: string | null;
87
+ path: string;
88
+ /** Whether the file exists at base. Without it nobody may override. */
89
+ active: boolean;
90
+ principals: string[];
91
+ }
92
+ /** The principals in an overriders file: one per line, blank lines and `#` comments skipped. */
93
+ export declare function parseOverriders(text: string): string[];
94
+ /**
95
+ * The overriders at `base` (a commit the repository holds, such as
96
+ * `baseCommit(repo)` from `@intentius/chant/gate-decision`), from `path`
97
+ * (default {@link OVERRIDERS_PATH}). Read at base, so the change being
98
+ * applied cannot add the person who overrides its own denial. A product that
99
+ * keeps its list in its own config at base reads it there and passes the
100
+ * principals to {@link decideOverride} instead.
101
+ */
102
+ export declare function overridersAt(repo: string, base: string, path?: string): Overriders;
103
+ /** A line of `_gates/policy-override/applied.jsonl`: a run applied under the override of `planDigest` made at `approvedAt`. */
104
+ export interface AppliedOverrideRecord {
105
+ version: 1;
106
+ kind: "applied";
107
+ op: string;
108
+ /** The subject. */
109
+ gate: string;
110
+ /** The override digest. */
111
+ planDigest: string;
112
+ /** The override's own timestamp: every override of this digest at or before it is spent. */
113
+ approvedAt: string;
114
+ approvedBy: string;
115
+ /** When the run recorded it. */
116
+ timestamp: string;
117
+ runId?: string;
118
+ commit?: string;
119
+ }
120
+ /** The applied records in the text of an applied file. Malformed lines, and lines of another kind, are skipped. */
121
+ export declare function parseAppliedOverrides(text: string): AppliedOverrideRecord[];
122
+ /** What judges an override line: who may write one, the approval mode, and under `sealed` the signers at base. */
123
+ export interface OverrideRule {
124
+ /** The principals who may override (an overriders file's, or a product's own list at base). */
125
+ overriders: readonly string[];
126
+ /** Where they were read, for the refusals. Default {@link OVERRIDERS_PATH}. */
127
+ overridersPath?: string;
128
+ /** `sealed` counts only a seal that verifies; `ledger` and `pr-review` count an unsealed override (an override is a person's line on the ledger, never a review). Default `ledger`. */
129
+ mode?: GateApprovalSource;
130
+ /** The signers at base (`gateSignersAt`). Under `sealed`, absent means nothing counts. */
131
+ signers?: GateSigners;
132
+ }
133
+ /** Why this ledger line does not count as an override, or null when it does. */
134
+ export declare function overrideRefusal(rule: OverrideRule, r: GateResolutionRecord): string | null;
135
+ export interface OverrideInput extends OverrideRule {
136
+ /** The lines of `_gates/policy-override.jsonl`. Lines of other ops are ignored. */
137
+ ledger: {
138
+ resolutions: readonly GateResolutionRecord[];
139
+ pending: readonly PendingGateRecord[];
140
+ };
141
+ /** The lines of `_gates/policy-override/applied.jsonl`. Absent reads as none. */
142
+ applied?: readonly AppliedOverrideRecord[];
143
+ subject: string;
144
+ /** The plan digest the policy denied. */
145
+ planDigest: string;
146
+ /** The ids of the rules that denied it. */
147
+ rules: readonly string[];
148
+ /** ISO-8601 now, for whether the standing pending fact has expired. */
149
+ now?: string;
150
+ }
151
+ /** An override that counts. */
152
+ export interface StandingOverride {
153
+ subject: string;
154
+ by: string;
155
+ at: string;
156
+ reason: string;
157
+ rules: string[];
158
+ /** The plan digest it lets through. */
159
+ planDigest: string;
160
+ /** The override digest. */
161
+ digest: string;
162
+ sealed: boolean;
163
+ resolution: GateResolutionRecord;
164
+ }
165
+ export type OverrideDecision =
166
+ /** An override of this digest counts: the run may apply this plan, after recording {@link appliedOverride}. */
167
+ {
168
+ status: "overridden";
169
+ digest: string;
170
+ override: StandingOverride;
171
+ }
172
+ /**
173
+ * No override counts. `refusals` says why each override of this digest
174
+ * does not. `standing` is the unexpired pending fact for this digest, so a
175
+ * run that finds one records no other. `spent` is the newest override of
176
+ * another digest a run already applied under.
177
+ */
178
+ | {
179
+ status: "none";
180
+ digest: string;
181
+ refusals: string[];
182
+ standing?: OverridePendingRecord;
183
+ spent?: {
184
+ digest: string;
185
+ by: string;
186
+ at: string;
187
+ };
188
+ }
189
+ /** An override counts for another digest and was never applied: the plan or its rules changed after it was written. */
190
+ | {
191
+ status: "moved";
192
+ digest: string;
193
+ by: string;
194
+ was: string | undefined;
195
+ refusals: string[];
196
+ standing?: OverridePendingRecord;
197
+ };
198
+ /**
199
+ * Decide one denied plan against the override ledger, as `decideGateApproval`
200
+ * decides a gate: a line counts only when it is an override of this subject
201
+ * newer than the subject's newest pending fact, names this digest, passes
202
+ * {@link overrideRefusal}, and is not spent (an applied record of its digest
203
+ * made at or after it). The newest counting line wins.
204
+ *
205
+ * Decide before recording a denial: an override written after an expired
206
+ * pending fact still counts, and a run that records a fresh fact first would
207
+ * make it older than the anchor.
208
+ */
209
+ export declare function decideOverride(input: OverrideInput): OverrideDecision;
210
+ /** The applied record a run appends before it applies under `override`, which spends it. Appending it is the caller's. */
211
+ export declare function appliedOverride(override: StandingOverride, at: {
212
+ timestamp: string;
213
+ runId?: string;
214
+ commit?: string;
215
+ }): AppliedOverrideRecord;
216
+ /**
217
+ * The applied records as applies for the audit reader
218
+ * (`@intentius/chant/lifecycle/gate-audit`), each citing the override it
219
+ * spent, so the trail shows an `override-spent` entry for it and a gap when
220
+ * the ledger holds no such override. A product that records its applies
221
+ * elsewhere cites the override on its own apply instead.
222
+ */
223
+ export declare function overrideAuditApplies(applied: readonly AppliedOverrideRecord[], path?: string): GateAuditApply[];
224
+ //# sourceMappingURL=override-gate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"override-gate.d.ts","sourceRoot":"","sources":["../src/override-gate.ts"],"names":[],"mappings":"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"}
@@ -1,20 +1,29 @@
1
1
  /**
2
- * What the pull-request loop (#3183) asks of a forge: keep one note on the
3
- * pull request up to date, set a commit status per stage, list who approved
4
- * the pull request, and find the pull request that merged a commit.
2
+ * What chant and the products built on it ask of a forge: keep one comment
3
+ * (a merge request note on GitLab) on a pull request up to date, set a commit
4
+ * status, keep one tracking issue in the repository, list who approved a pull
5
+ * request, and find the pull request that merged a commit.
5
6
  *
6
- * GitHub and Forgejo speak the same REST shapes for the first three, at
7
+ * The pull-request loop (#3183) uses the note, the status and the review
8
+ * calls. `reconcilePr`'s `comment` and `issue` finding modes post through the
9
+ * same clients (#3757), so a finding needs no `gh` on the runner. terragucci
10
+ * and SQL Yodeler post their own notes, statuses and drift issues through
11
+ * them too (#3759): bodies stay with each product, the finding by marker and
12
+ * the forge's REST shapes live here.
13
+ *
14
+ * GitHub and Forgejo speak the same REST shapes for most of this, at
7
15
  * different base URLs (`$GITHUB_API_URL` is right on both, #2305); they part
8
- * on the commit-to-pull-request lookup and on review states. GitLab has its
9
- * own API for all four. Each client takes a `fetch`, so the tests drive them
10
- * with a recording fake and no network.
16
+ * on the commit-to-pull-request lookup, on review states and on page size.
17
+ * GitLab has its own API for all of it. Each client takes a `fetch`, so the
18
+ * tests drive them with a recording fake and no network.
11
19
  *
12
20
  * A reviewer is named the way #3163 names a person: `github:<login>`,
13
21
  * `gitlab:<login>`, or `<forge>@<host>:<login>` off the forge's default host.
14
22
  * The apply compares that string with the approval's `resolvedBy`.
15
23
  *
16
24
  * Like `./pr-loop.ts`, this bundles without the TypeScript toolchain (#3421):
17
- * it imports nothing.
25
+ * it imports nothing but `node:fs`, to read a CI job's event payload.
26
+ * `./pr-forge-bundle.test.ts` holds it to that.
18
27
  */
19
28
  export type ForgeKind = "github" | "gitlab" | "forgejo";
20
29
  export declare const FORGE_KINDS: readonly ForgeKind[];
@@ -29,12 +38,67 @@ export type ForgeFetch = (url: string, init: {
29
38
  text(): Promise<string>;
30
39
  }>;
31
40
  export interface ForgeStatus {
32
- /** `chant/plan` or `chant/apply`. */
41
+ /** The status's name, such as `chant/plan` or `terragucci/plan`. */
33
42
  context: string;
34
43
  state: "pending" | "success" | "failure";
44
+ /** Cut to what the forge keeps: 140 characters on GitHub and Forgejo, 255 on GitLab. */
35
45
  description: string;
36
46
  /** The pipeline run, linked from the status. */
37
47
  url?: string;
48
+ /** GitLab only: the pipeline the status belongs to. */
49
+ pipelineId?: number;
50
+ }
51
+ /**
52
+ * How a comment or an issue is told to be the caller's own. By default the
53
+ * body starts with the marker, chant's recipe since #2291, and anyone may
54
+ * have written it.
55
+ */
56
+ export interface MarkerMatch {
57
+ /** `prefix` (the default): the body starts with the marker. `anywhere`: the body carries it. */
58
+ match?: "prefix" | "anywhere";
59
+ /**
60
+ * Only a comment or issue written by this login counts: `user.login` on
61
+ * GitHub and Forgejo, `author.username` on GitLab, compared without case.
62
+ * A merge request's author can write a note carrying any marker, so a
63
+ * product that reads its own notes back names its bot here.
64
+ */
65
+ author?: string;
66
+ }
67
+ /** What {@link PrForge.upsertComment} did. */
68
+ export interface CommentResult {
69
+ action: "created" | "updated" | "unchanged";
70
+ /** The comment's or note's id. */
71
+ id: number;
72
+ /** Its web URL, when the forge's answer carries one (GitHub and Forgejo do; a GitLab note does not). */
73
+ url?: string;
74
+ }
75
+ /** A finding to keep in a tracking issue. `body` carries the marker. */
76
+ export interface IssueFinding {
77
+ title: string;
78
+ body: string;
79
+ }
80
+ export interface TrackIssueOptions extends MarkerMatch {
81
+ /**
82
+ * When the finding has cleared (`null`), close the open issue, after
83
+ * {@link clearComment} when one is given. Off by default: `reconcilePr`'s
84
+ * `issue` mode never closes an issue, and a closed one is never reopened,
85
+ * so the next finding opens a fresh issue.
86
+ */
87
+ closeOnClear?: boolean;
88
+ /** Posted on the issue before it is closed. */
89
+ clearComment?: string;
90
+ }
91
+ /** What {@link PrForge.trackIssue} did. */
92
+ export interface IssueResult {
93
+ /**
94
+ * `opened`, `updated`, or `unchanged` (title and body already current) for
95
+ * a finding; `closed`, `left` (open, `closeOnClear` off) or `none` (no open
96
+ * issue) for a cleared one.
97
+ */
98
+ action: "opened" | "updated" | "unchanged" | "closed" | "left" | "none";
99
+ /** The issue's number (GitHub, Forgejo) or iid (GitLab). */
100
+ number?: number;
101
+ url?: string;
38
102
  }
39
103
  export interface PrForge {
40
104
  kind: ForgeKind;
@@ -44,14 +108,43 @@ export interface PrForge {
44
108
  runUrl?: string;
45
109
  /** How #3163 names `login` on this forge. */
46
110
  principalOf(login: string): string;
47
- /** Update the note on `pr` whose body starts with `marker`, or add one. */
48
- upsertNote(pr: number, marker: string, body: string): Promise<void>;
111
+ /**
112
+ * Keep one comment on pull request `pr` (one note on merge request `pr`):
113
+ * the one {@link MarkerMatch} finds is updated, unless its body is already
114
+ * `body`, or one is added. `body` must carry the marker the same way, or
115
+ * the next run could not find it; that is refused before any call. Every
116
+ * page of comments is read, and GitLab's system notes are skipped. When
117
+ * several match, the oldest is kept.
118
+ */
119
+ upsertComment(pr: number, marker: string, body: string, opts?: MarkerMatch): Promise<CommentResult>;
120
+ /**
121
+ * {@link upsertComment} by prefix, without the body check, resolving to the
122
+ * comment's web URL. The pull-request loop's form.
123
+ */
124
+ upsertNote(pr: number, marker: string, body: string): Promise<string | undefined>;
49
125
  setStatus(sha: string, status: ForgeStatus): Promise<void>;
126
+ /**
127
+ * Keep one OPEN tracking issue for `marker` in line with `finding`: open
128
+ * it, update its title and body, or, when `finding` is `null` and
129
+ * `closeOnClear` is set, close it with a comment. Only open issues are
130
+ * read, so an issue closed by hand stays closed. Pull requests are never
131
+ * taken for issues. When several match, the oldest is kept.
132
+ */
133
+ trackIssue(marker: string, finding: IssueFinding | null, opts?: TrackIssueOptions): Promise<IssueResult>;
134
+ /**
135
+ * {@link trackIssue} by prefix for a finding, without the body check,
136
+ * resolving to the issue's web URL. `reconcilePr`'s `issue` mode's form.
137
+ */
138
+ upsertIssue(marker: string, title: string, body: string): Promise<string | undefined>;
50
139
  /** Logins whose standing review approves `pr`. */
51
140
  approvers(pr: number): Promise<string[]>;
52
141
  /** The merged pull request that produced `sha`, or null. */
53
142
  pullRequestFor(sha: string): Promise<number | null>;
54
143
  }
144
+ /** A GitHub or Forgejo client. */
145
+ export type GithubShapedForge = PrForge & {
146
+ kind: "github" | "forgejo";
147
+ };
55
148
  /** Thrown when a forge answers a call with an error status. */
56
149
  export declare class ForgeApiError extends Error {
57
150
  readonly method: string;
@@ -73,33 +166,119 @@ export interface GithubForgeOptions {
73
166
  fetch?: ForgeFetch;
74
167
  }
75
168
  /** A GitHub client (github.com or GitHub Enterprise Server). */
76
- export declare function githubForge(opts: GithubForgeOptions): PrForge;
169
+ export declare function githubForge(opts: GithubForgeOptions): GithubShapedForge;
77
170
  /** A Forgejo (or Gitea) client. `host` is required: Forgejo has no default host. */
78
171
  export declare function forgejoForge(opts: GithubForgeOptions & {
79
172
  host: string;
80
- }): PrForge;
173
+ }): GithubShapedForge;
81
174
  export interface GitlabForgeOptions {
82
175
  /** `$CI_API_V4_URL`. */
83
176
  apiBase: string;
84
177
  /** `$CI_PROJECT_ID`, or the URL-encoded path. */
85
178
  project: string;
86
179
  token: string;
180
+ /**
181
+ * The header the token goes in: `PRIVATE-TOKEN` (the default) for an
182
+ * access token, `JOB-TOKEN` for `CI_JOB_TOKEN`. One in the other's header
183
+ * is a 401.
184
+ */
185
+ tokenHeader?: "PRIVATE-TOKEN" | "JOB-TOKEN";
87
186
  /** Default gitlab.com. */
88
187
  host?: string;
89
188
  runUrl?: string;
90
189
  fetch?: ForgeFetch;
91
190
  }
92
- /** A GitLab client. The token needs the `api` scope: a job token cannot write merge-request notes. */
191
+ /**
192
+ * A GitLab client. Writing notes needs an access token with the `api` scope
193
+ * on most instances: the job token reaches only the endpoints the instance's
194
+ * job-token allowlist names.
195
+ */
93
196
  export declare function gitlabForge(opts: GitlabForgeOptions): PrForge;
94
197
  /** Thrown when the environment lacks what a forge client needs. */
95
198
  export declare class ForgeEnvironmentError extends Error {
96
- constructor(kind: ForgeKind, missing: string[]);
199
+ readonly kind: ForgeKind | undefined;
200
+ readonly missing: string[];
201
+ /**
202
+ * @param kind The forge, or undefined when the environment does not say which.
203
+ * @param missing What is missing, each naming the variable to set.
204
+ */
205
+ constructor(kind: ForgeKind | undefined, missing: string[]);
97
206
  }
98
207
  /**
99
- * A client for `kind` from the CI job's environment. The token is
100
- * `CHANT_FORGE_TOKEN` when set, else the forge's own: `GITHUB_TOKEN` (also
101
- * set on Forgejo Actions) or `GITLAB_TOKEN`. GitLab's `CI_JOB_TOKEN` cannot
102
- * write notes, so a GitLab pipeline names a project access token.
208
+ * A client for `kind` from the CI job's environment, as the pull-request
209
+ * loop reads it. The token is `CHANT_FORGE_TOKEN` when set, else the forge's
210
+ * own: `GITHUB_TOKEN` (also set on Forgejo Actions) or `GITLAB_TOKEN`.
211
+ * GitLab's `CI_JOB_TOKEN` cannot write notes, so a GitLab pipeline names a
212
+ * project access token. {@link forgeTargetFromEnv} is the general reading,
213
+ * with the finding modes' token order.
103
214
  */
104
215
  export declare function forgeFromEnv(kind: ForgeKind, env?: Record<string, string | undefined>, fetchImpl?: ForgeFetch): PrForge;
216
+ type Env = Record<string, string | undefined>;
217
+ /**
218
+ * The forge a CI job runs on, from its environment, or undefined outside a
219
+ * GitHub Actions, GitLab CI or Forgejo Actions job. Forgejo is told apart by
220
+ * `FORGEJO_ACTIONS` or `GITEA_ACTIONS`, or by a GitHub-style job whose
221
+ * `GITHUB_API_URL` ends in `/api/v1`, which GitHub never serves.
222
+ */
223
+ export declare function detectForge(env?: Env): ForgeKind | undefined;
224
+ /** Where a CI job posts: the forge, the repository, the token, and the pull request and commit when there are ones. */
225
+ export interface ForgeTarget {
226
+ kind: ForgeKind;
227
+ /** The REST base: `https://api.github.com`, `<host>/api/v3`, `<host>/api/v1`, or `<host>/api/v4`. */
228
+ apiBase: string;
229
+ /** `owner/name` on GitHub and Forgejo; the project id or path on GitLab. */
230
+ repo: string;
231
+ /** Lower-cased. */
232
+ host: string;
233
+ token: string;
234
+ /** The variable the token came from, for messages. Never the token itself. */
235
+ tokenSource: string;
236
+ /** GitLab: `JOB-TOKEN` when the token is `CI_JOB_TOKEN`, else `PRIVATE-TOKEN`. */
237
+ tokenHeader?: "PRIVATE-TOKEN" | "JOB-TOKEN";
238
+ /** The pull request's number, or the merge request's iid. */
239
+ pr?: number;
240
+ /** The commit a status belongs on: the pull request's head when the event names it. */
241
+ sha?: string;
242
+ /** The run, to link from a status. */
243
+ runUrl?: string;
244
+ }
245
+ export interface ForgeTargetOptions {
246
+ /** The forge, in place of {@link detectForge}. */
247
+ kind?: ForgeKind;
248
+ /** Read the token from this variable only, in place of the default order. */
249
+ tokenEnv?: string;
250
+ /** Refuse an environment with no pull or merge request. Default false. */
251
+ requirePr?: boolean;
252
+ /** Reads the event payload `GITHUB_EVENT_PATH` names. Default `node:fs`. */
253
+ readFile?: (path: string) => string;
254
+ }
255
+ /**
256
+ * The token order guide/ops documents for the finding modes (#2291, #2256):
257
+ * a chant-specific variable first, for posting to an instance other than the
258
+ * one the job runs on, then what the job already carries.
259
+ */
260
+ export declare const FORGE_TOKEN_ORDER: Record<ForgeKind, readonly string[]>;
261
+ /**
262
+ * Where a CI job posts, read from its environment: the forge
263
+ * ({@link detectForge} unless `kind` is given), the repository, the REST
264
+ * base, the host, the token, and the pull request and its head commit when
265
+ * the run has them. Throws {@link ForgeEnvironmentError} naming every
266
+ * missing piece.
267
+ *
268
+ * - GitHub Actions: `GITHUB_REPOSITORY`, `GITHUB_API_URL` (default
269
+ * `https://api.github.com`), `GITHUB_SERVER_URL`; the pull request from
270
+ * the event payload at `GITHUB_EVENT_PATH` or `refs/pull/<n>/` in
271
+ * `GITHUB_REF`, its head from the payload, else `GITHUB_SHA`.
272
+ * - Forgejo Actions: the same, with `FORGEJO_*` read before `GITHUB_*`,
273
+ * and the REST base `<server>/api/v1` when no API URL is set.
274
+ * - GitLab CI: `CI_API_V4_URL` (or `CI_SERVER_URL/api/v4`), the merge
275
+ * request's project before the pipeline's (a fork's merge request runs in
276
+ * the fork), `CI_MERGE_REQUEST_IID`, `CI_COMMIT_SHA`, `CI_PIPELINE_URL`.
277
+ *
278
+ * The token is read in {@link FORGE_TOKEN_ORDER}, or from `tokenEnv` alone.
279
+ */
280
+ export declare function forgeTargetFromEnv(env?: Env, opts?: ForgeTargetOptions): ForgeTarget;
281
+ /** The client for a {@link ForgeTarget}, from {@link forgeTargetFromEnv} or built by hand. */
282
+ export declare function forgeClient(target: ForgeTarget, fetchImpl?: ForgeFetch): PrForge;
283
+ export {};
105
284
  //# sourceMappingURL=pr-forge.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pr-forge.d.ts","sourceRoot":"","sources":["../src/pr-forge.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pr-forge.d.ts","sourceRoot":"","sources":["../src/pr-forge.ts"],"names":[],"mappings":"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"}
@@ -16,6 +16,7 @@
16
16
  * gate in its environment is the anchor, only approvals recorded since it and
17
17
  * for its plan count, and a gate with an `approval` block counts them with
18
18
  * `tallyGateApprovals`, as `describeApprovalProgress` does after an approve.
19
+ * Its human quorum reaches back to `humanQuorumSince` (#3206), as a run's does.
19
20
  */
20
21
  import { type GateApprovalRule } from "../op/gate.js";
21
22
  /** Why a member's gates can't be listed. Closed: a new code is a contract change. */
@@ -1 +1 @@
1
- {"version":3,"file":"status-gates.d.ts","sourceRoot":"","sources":["../../src/workspace/status-gates.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"status-gates.d.ts","sourceRoot":"","sources":["../../src/workspace/status-gates.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * A gate approval's seal (#3163, ws-080), checked with node:crypto (#3763).
3
+ *
4
+ * `chant approve --sign` seals an approval with `ssh-keygen -Y sign` in the
5
+ * `chant-gate` namespace, over {@link gateSealPayload}. Signing shells to
6
+ * ssh-keygen; checking does not. This module checks a seal with node:crypto
7
+ * and no zod, and `checkGateSeal` (`./seal.ts`) and `sealedApprovalRule` use
8
+ * it, so an apply job needs no ssh-keygen. A tool that decides a gate from one bundled file
9
+ * (terragucci's apply job) runs the same rule: `@intentius/chant/gate-decision`
10
+ * exports it.
11
+ *
12
+ * An SSHSIG (OpenSSH's PROTOCOL.sshsig) holds the public key, the namespace,
13
+ * the hash algorithm and the signature over `"SSHSIG"`, the namespace, the
14
+ * reserved field, the algorithm and the message's hash. Ed25519, ECDSA (P-256,
15
+ * P-384, P-521), RSA with SHA-2, and the security-key forms of Ed25519 and
16
+ * P-256 verify, with the touch flag required, as ssh-keygen requires it for a
17
+ * signers line with no `no-touch-required` option (which the signers parser
18
+ * does not accept). An RSA signature over SHA-1 does not verify.
19
+ */
20
+ import type { Signer } from "./trust-files.js";
21
+ /**
22
+ * The ssh signature namespace of a gate approval's seal (#3163, ws-080), so a
23
+ * verdict, record or commit signature can't stand in for one.
24
+ */
25
+ export declare const GATE_SEAL_NAMESPACE = "chant-gate";
26
+ /** The gate approval a seal covers (#3163): the fields of a gate resolution line that say what was approved, by whom and when. */
27
+ export interface SealedGateApproval {
28
+ op: string;
29
+ gate: string;
30
+ environment?: string;
31
+ planDigest?: string;
32
+ resolvedBy: string;
33
+ /** Who relayed the approval for `resolvedBy` (#3402), when someone did. */
34
+ relayedBy?: string;
35
+ timestamp: string;
36
+ seal?: unknown;
37
+ }
38
+ /**
39
+ * The bytes a gate approval's seal signs (#3163): the op (or component), the
40
+ * gate, the environment, the plan digest, the approver and the time, joined
41
+ * by LF with no final newline. An approval that binds no environment or plan
42
+ * signs an empty line for it. A relayed approval (#3402) signs a seventh line,
43
+ * `relayed-by <principal>`, so the relay can't be added, changed or removed
44
+ * after sealing; an approval nobody relayed signs the six lines it always did,
45
+ * so seals made before #3402 still verify.
46
+ */
47
+ export declare function gateSealPayload(a: SealedGateApproval): Buffer;
48
+ /** `SHA256:<base64>`, the fingerprint ssh-keygen prints for a public key blob. */
49
+ export declare function sshKeyFingerprint(blob: Buffer): string;
50
+ /** What {@link verifySshSignatureWith} found. */
51
+ export type SshSignatureCheck = {
52
+ ok: true;
53
+ key: string;
54
+ } | {
55
+ ok: false;
56
+ reason: string;
57
+ };
58
+ /**
59
+ * Whether `armored`, an SSHSIG as `ssh-keygen -Y sign` writes it, signs
60
+ * `message` in `namespace` with one of `keys` (public key blobs, ssh wire
61
+ * format). Never throws. On success, `key` is the signing key's fingerprint.
62
+ */
63
+ export declare function verifySshSignatureWith(armored: string, message: Buffer, namespace: string, keys: readonly Buffer[]): SshSignatureCheck;
64
+ /**
65
+ * The key blob an armored SSHSIG carries, or null when it is not one. For
66
+ * `ssh-keygen -Y check-novalidate`'s question, whether the signature is
67
+ * intact whoever's key it is: verify against this key.
68
+ */
69
+ export declare function sshSignatureKey(armored: string): Buffer | null;
70
+ /**
71
+ * The signers a sealed gate is judged by, read at base. chant's own
72
+ * `TrustPolicy` (`./policy.ts`) is one; `gateSignersAt` in
73
+ * `@intentius/chant/gate-decision` reads one without zod.
74
+ */
75
+ export interface GateSigners {
76
+ /** The commit the signers were read at, or null when there is no base. */
77
+ base: string | null;
78
+ /** The signers path used. */
79
+ signersPath: string;
80
+ /** Whether a signers file exists at base. False: no seal verifies, so a sealed gate passes nothing. */
81
+ active: boolean;
82
+ signers: Signer[];
83
+ /** Why the trust config could not be read, when it could not. `active` is false then. */
84
+ problems: string[];
85
+ }
86
+ /** Whether ssh-keygen's `namespaces="..."` pattern list admits `namespace`: a `*`/`?` pattern matches, and a `!` pattern that matches refuses. */
87
+ export declare function namespaceAllowed(list: string | undefined, namespace: string): boolean;
88
+ /**
89
+ * Why this approval does not count toward a sealed gate, or null when it
90
+ * does: its seal verifies, for the approver it names, against a key `signers`
91
+ * lists for that approver in the `chant-gate` namespace. With no signers file
92
+ * at base, nothing counts. The same rule as `sealedApprovalRule` in
93
+ * `../../op/gate-review.ts`, which checks with ssh-keygen.
94
+ */
95
+ export declare function gateSealRefusal(signers: GateSigners, a: SealedGateApproval): string | null;
96
+ //# sourceMappingURL=gate-seal.d.ts.map