@noodleseed/one 0.17.0 → 0.18.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 (144) hide show
  1. package/dist/cli.d.ts.map +1 -1
  2. package/dist/cli.js +3 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/alerts-ops.d.ts +2 -0
  5. package/dist/commands/alerts-ops.d.ts.map +1 -0
  6. package/dist/commands/alerts-ops.js +249 -0
  7. package/dist/commands/alerts-ops.js.map +1 -0
  8. package/dist/commands/analytics-ops.d.ts +13 -0
  9. package/dist/commands/analytics-ops.d.ts.map +1 -1
  10. package/dist/commands/analytics-ops.js +5 -2
  11. package/dist/commands/analytics-ops.js.map +1 -1
  12. package/dist/commands/catalog-data-resources.d.ts.map +1 -1
  13. package/dist/commands/catalog-data-resources.js +45 -0
  14. package/dist/commands/catalog-data-resources.js.map +1 -1
  15. package/dist/commands/github-ops.d.ts.map +1 -1
  16. package/dist/commands/github-ops.js +24 -4
  17. package/dist/commands/github-ops.js.map +1 -1
  18. package/dist/commands/github-runs-ops.d.ts +32 -0
  19. package/dist/commands/github-runs-ops.d.ts.map +1 -0
  20. package/dist/commands/github-runs-ops.js +132 -0
  21. package/dist/commands/github-runs-ops.js.map +1 -0
  22. package/node_modules/@noodle-borg/agent-kit/dist/curated/command-groups.d.ts.map +1 -1
  23. package/node_modules/@noodle-borg/agent-kit/dist/curated/command-groups.js +5 -0
  24. package/node_modules/@noodle-borg/agent-kit/dist/curated/command-groups.js.map +1 -1
  25. package/node_modules/@noodle-borg/agent-kit/dist/generated/surface.d.ts.map +1 -1
  26. package/node_modules/@noodle-borg/agent-kit/dist/generated/surface.js +1 -0
  27. package/node_modules/@noodle-borg/agent-kit/dist/generated/surface.js.map +1 -1
  28. package/node_modules/@noodle-borg/agent-kit/package.json +1 -1
  29. package/node_modules/@noodle-borg/authoring/dist/recording.js +18 -23
  30. package/node_modules/@noodle-borg/authoring/dist/recording.js.map +1 -1
  31. package/node_modules/@noodle-borg/service/dist/alert-evaluator.d.ts +57 -0
  32. package/node_modules/@noodle-borg/service/dist/alert-evaluator.d.ts.map +1 -0
  33. package/node_modules/@noodle-borg/service/dist/alert-evaluator.js +158 -0
  34. package/node_modules/@noodle-borg/service/dist/alert-evaluator.js.map +1 -0
  35. package/node_modules/@noodle-borg/service/dist/alert-webhook.d.ts +72 -0
  36. package/node_modules/@noodle-borg/service/dist/alert-webhook.d.ts.map +1 -0
  37. package/node_modules/@noodle-borg/service/dist/alert-webhook.js +138 -0
  38. package/node_modules/@noodle-borg/service/dist/alert-webhook.js.map +1 -0
  39. package/node_modules/@noodle-borg/service/dist/github/pending-installations.d.ts +15 -8
  40. package/node_modules/@noodle-borg/service/dist/github/pending-installations.d.ts.map +1 -1
  41. package/node_modules/@noodle-borg/service/dist/github/pending-installations.js +16 -9
  42. package/node_modules/@noodle-borg/service/dist/github/pending-installations.js.map +1 -1
  43. package/node_modules/@noodle-borg/service/dist/index.d.ts +10 -2
  44. package/node_modules/@noodle-borg/service/dist/index.d.ts.map +1 -1
  45. package/node_modules/@noodle-borg/service/dist/index.js +9 -1
  46. package/node_modules/@noodle-borg/service/dist/index.js.map +1 -1
  47. package/node_modules/@noodle-borg/service/dist/options.d.ts +20 -1
  48. package/node_modules/@noodle-borg/service/dist/options.d.ts.map +1 -1
  49. package/node_modules/@noodle-borg/service/dist/routes/alerts-dispatch.d.ts +28 -0
  50. package/node_modules/@noodle-borg/service/dist/routes/alerts-dispatch.d.ts.map +1 -0
  51. package/node_modules/@noodle-borg/service/dist/routes/alerts-dispatch.js +50 -0
  52. package/node_modules/@noodle-borg/service/dist/routes/alerts-dispatch.js.map +1 -0
  53. package/node_modules/@noodle-borg/service/dist/routes/alerts.d.ts +39 -0
  54. package/node_modules/@noodle-borg/service/dist/routes/alerts.d.ts.map +1 -0
  55. package/node_modules/@noodle-borg/service/dist/routes/alerts.js +204 -0
  56. package/node_modules/@noodle-borg/service/dist/routes/alerts.js.map +1 -0
  57. package/node_modules/@noodle-borg/service/dist/routes/contracts.d.ts +149 -0
  58. package/node_modules/@noodle-borg/service/dist/routes/contracts.d.ts.map +1 -1
  59. package/node_modules/@noodle-borg/service/dist/routes/contracts.js +81 -0
  60. package/node_modules/@noodle-borg/service/dist/routes/contracts.js.map +1 -1
  61. package/node_modules/@noodle-borg/service/dist/routes/github-connection.js +1 -1
  62. package/node_modules/@noodle-borg/service/dist/routes/github-connection.js.map +1 -1
  63. package/node_modules/@noodle-borg/service/dist/routes/github-dispatch.d.ts +2 -1
  64. package/node_modules/@noodle-borg/service/dist/routes/github-dispatch.d.ts.map +1 -1
  65. package/node_modules/@noodle-borg/service/dist/routes/github-dispatch.js +37 -2
  66. package/node_modules/@noodle-borg/service/dist/routes/github-dispatch.js.map +1 -1
  67. package/node_modules/@noodle-borg/service/dist/routes/github-runs.d.ts +8 -0
  68. package/node_modules/@noodle-borg/service/dist/routes/github-runs.d.ts.map +1 -0
  69. package/node_modules/@noodle-borg/service/dist/routes/github-runs.js +33 -0
  70. package/node_modules/@noodle-borg/service/dist/routes/github-runs.js.map +1 -0
  71. package/node_modules/@noodle-borg/service/dist/routes/github-setup.d.ts +1 -1
  72. package/node_modules/@noodle-borg/service/dist/routes/github-setup.d.ts.map +1 -1
  73. package/node_modules/@noodle-borg/service/dist/routes/github-setup.js +3 -3
  74. package/node_modules/@noodle-borg/service/dist/routes/github-setup.js.map +1 -1
  75. package/node_modules/@noodle-borg/service/dist/routes/github-webhook.d.ts +29 -0
  76. package/node_modules/@noodle-borg/service/dist/routes/github-webhook.d.ts.map +1 -0
  77. package/node_modules/@noodle-borg/service/dist/routes/github-webhook.js +355 -0
  78. package/node_modules/@noodle-borg/service/dist/routes/github-webhook.js.map +1 -0
  79. package/node_modules/@noodle-borg/service/dist/routes/org-admin-dispatch.d.ts +27 -0
  80. package/node_modules/@noodle-borg/service/dist/routes/org-admin-dispatch.d.ts.map +1 -0
  81. package/node_modules/@noodle-borg/service/dist/routes/org-admin-dispatch.js +61 -0
  82. package/node_modules/@noodle-borg/service/dist/routes/org-admin-dispatch.js.map +1 -0
  83. package/node_modules/@noodle-borg/service/dist/routes/paths.d.ts +20 -1
  84. package/node_modules/@noodle-borg/service/dist/routes/paths.d.ts.map +1 -1
  85. package/node_modules/@noodle-borg/service/dist/routes/paths.js +54 -0
  86. package/node_modules/@noodle-borg/service/dist/routes/paths.js.map +1 -1
  87. package/node_modules/@noodle-borg/service/dist/serve.d.ts.map +1 -1
  88. package/node_modules/@noodle-borg/service/dist/serve.js +42 -1
  89. package/node_modules/@noodle-borg/service/dist/serve.js.map +1 -1
  90. package/node_modules/@noodle-borg/service/dist/service.d.ts.map +1 -1
  91. package/node_modules/@noodle-borg/service/dist/service.js +37 -53
  92. package/node_modules/@noodle-borg/service/dist/service.js.map +1 -1
  93. package/node_modules/@noodle-borg/service/dist/store/alert-rules-json-file.d.ts +21 -0
  94. package/node_modules/@noodle-borg/service/dist/store/alert-rules-json-file.d.ts.map +1 -0
  95. package/node_modules/@noodle-borg/service/dist/store/alert-rules-json-file.js +115 -0
  96. package/node_modules/@noodle-borg/service/dist/store/alert-rules-json-file.js.map +1 -0
  97. package/node_modules/@noodle-borg/service/dist/store/alert-rules.d.ts +108 -0
  98. package/node_modules/@noodle-borg/service/dist/store/alert-rules.d.ts.map +1 -0
  99. package/node_modules/@noodle-borg/service/dist/store/alert-rules.js +181 -0
  100. package/node_modules/@noodle-borg/service/dist/store/alert-rules.js.map +1 -0
  101. package/node_modules/@noodle-borg/service/dist/store/github-connections-json-file.d.ts +1 -0
  102. package/node_modules/@noodle-borg/service/dist/store/github-connections-json-file.d.ts.map +1 -1
  103. package/node_modules/@noodle-borg/service/dist/store/github-connections-json-file.js +4 -0
  104. package/node_modules/@noodle-borg/service/dist/store/github-connections-json-file.js.map +1 -1
  105. package/node_modules/@noodle-borg/service/dist/store/github-connections.d.ts +1 -0
  106. package/node_modules/@noodle-borg/service/dist/store/github-connections.d.ts.map +1 -1
  107. package/node_modules/@noodle-borg/service/dist/store/github-connections.js +4 -0
  108. package/node_modules/@noodle-borg/service/dist/store/github-connections.js.map +1 -1
  109. package/node_modules/@noodle-borg/service/dist/store/github-runs-json-file.d.ts +22 -0
  110. package/node_modules/@noodle-borg/service/dist/store/github-runs-json-file.d.ts.map +1 -0
  111. package/node_modules/@noodle-borg/service/dist/store/github-runs-json-file.js +116 -0
  112. package/node_modules/@noodle-borg/service/dist/store/github-runs-json-file.js.map +1 -0
  113. package/node_modules/@noodle-borg/service/dist/store/github-runs.d.ts +51 -0
  114. package/node_modules/@noodle-borg/service/dist/store/github-runs.d.ts.map +1 -0
  115. package/node_modules/@noodle-borg/service/dist/store/github-runs.js +158 -0
  116. package/node_modules/@noodle-borg/service/dist/store/github-runs.js.map +1 -0
  117. package/node_modules/@noodle-borg/service/dist/store/pending-installations-postgres.d.ts +19 -0
  118. package/node_modules/@noodle-borg/service/dist/store/pending-installations-postgres.d.ts.map +1 -0
  119. package/node_modules/@noodle-borg/service/dist/store/pending-installations-postgres.js +46 -0
  120. package/node_modules/@noodle-borg/service/dist/store/pending-installations-postgres.js.map +1 -0
  121. package/node_modules/@noodle-borg/service/dist/store/postgres-alerts.d.ts +26 -0
  122. package/node_modules/@noodle-borg/service/dist/store/postgres-alerts.d.ts.map +1 -0
  123. package/node_modules/@noodle-borg/service/dist/store/postgres-alerts.js +142 -0
  124. package/node_modules/@noodle-borg/service/dist/store/postgres-alerts.js.map +1 -0
  125. package/node_modules/@noodle-borg/service/dist/store/postgres-github-runs.d.ts +9 -0
  126. package/node_modules/@noodle-borg/service/dist/store/postgres-github-runs.d.ts.map +1 -0
  127. package/node_modules/@noodle-borg/service/dist/store/postgres-github-runs.js +113 -0
  128. package/node_modules/@noodle-borg/service/dist/store/postgres-github-runs.js.map +1 -0
  129. package/node_modules/@noodle-borg/service/dist/store/postgres-github.d.ts +1 -0
  130. package/node_modules/@noodle-borg/service/dist/store/postgres-github.d.ts.map +1 -1
  131. package/node_modules/@noodle-borg/service/dist/store/postgres-github.js +7 -2
  132. package/node_modules/@noodle-borg/service/dist/store/postgres-github.js.map +1 -1
  133. package/node_modules/@noodle-borg/service/dist/store/postgres-schema.d.ts.map +1 -1
  134. package/node_modules/@noodle-borg/service/dist/store/postgres-schema.js +49 -0
  135. package/node_modules/@noodle-borg/service/dist/store/postgres-schema.js.map +1 -1
  136. package/node_modules/@noodle-borg/service/dist/store/postgres.d.ts +9 -2
  137. package/node_modules/@noodle-borg/service/dist/store/postgres.d.ts.map +1 -1
  138. package/node_modules/@noodle-borg/service/dist/store/postgres.js +17 -1
  139. package/node_modules/@noodle-borg/service/dist/store/postgres.js.map +1 -1
  140. package/node_modules/@noodle-borg/service/dist/store.d.ts +104 -0
  141. package/node_modules/@noodle-borg/service/dist/store.d.ts.map +1 -1
  142. package/node_modules/@noodle-borg/service/dist/store.js +2 -0
  143. package/node_modules/@noodle-borg/service/dist/store.js.map +1 -1
  144. package/package.json +2 -2
@@ -0,0 +1,355 @@
1
+ import { createHmac, randomBytes, timingSafeEqual } from 'node:crypto';
2
+ import { sendJson } from '../http-util.js';
3
+ const SIGNATURE_HEADER = 'x-hub-signature-256';
4
+ /** Timing-safe check of GitHub's `X-Hub-Signature-256: sha256=<hex>` over the raw body bytes. */
5
+ export function verifyWebhookSignature(rawBody, signatureHeader, secret) {
6
+ if (signatureHeader === undefined || !signatureHeader.startsWith('sha256='))
7
+ return false;
8
+ const received = signatureHeader.slice('sha256='.length);
9
+ // Exactly 64 hex chars: Buffer.from(..., 'hex') silently drops a trailing odd nibble, so a lax
10
+ // length check would accept multiple encodings of the same digest.
11
+ if (!/^[0-9a-f]{64}$/i.test(received))
12
+ return false;
13
+ const expected = createHmac('sha256', secret).update(rawBody).digest();
14
+ const receivedBuf = Buffer.from(received, 'hex');
15
+ return receivedBuf.length === expected.length && timingSafeEqual(receivedBuf, expected);
16
+ }
17
+ async function readRawBody(req, max) {
18
+ const chunks = [];
19
+ let size = 0;
20
+ for await (const chunk of req) {
21
+ const buf = chunk;
22
+ size += buf.length;
23
+ if (size > max)
24
+ return { ok: false };
25
+ chunks.push(buf);
26
+ }
27
+ return { ok: true, raw: Buffer.concat(chunks) };
28
+ }
29
+ function defaultRunId() {
30
+ return `run-${randomBytes(6).toString('hex')}`;
31
+ }
32
+ function positiveInt(value) {
33
+ return typeof value === 'number' && Number.isInteger(value) && value > 0 ? value : undefined;
34
+ }
35
+ function asRecord(value) {
36
+ return typeof value === 'object' && value !== null
37
+ ? value
38
+ : undefined;
39
+ }
40
+ /** GitHub's `sender.login`, or `'unknown'` when the payload omits it. */
41
+ function senderLogin(payload) {
42
+ const login = asRecord(payload.sender)?.login;
43
+ return typeof login === 'string' ? login : 'unknown';
44
+ }
45
+ function outcome(res, data) {
46
+ sendJson(res, 200, { ok: true, data });
47
+ }
48
+ function ignored(res, reason) {
49
+ outcome(res, { outcome: 'ignored', reason });
50
+ }
51
+ /** Repository id + installation-binding guard shared by every repo-scoped event. */
52
+ async function boundConnection(ctx, payload) {
53
+ const repository = asRecord(payload.repository);
54
+ const repositoryId = positiveInt(repository?.id);
55
+ if (repositoryId === undefined) {
56
+ sendJson(ctx.res, 400, { error: 'malformed payload' });
57
+ return 'responded';
58
+ }
59
+ const connection = await ctx.deps.connectionStore.getRepoConnectionByRepository(repositoryId);
60
+ if (connection === undefined) {
61
+ ignored(ctx.res, 'no_connection');
62
+ return 'responded';
63
+ }
64
+ const installationId = positiveInt(asRecord(payload.installation)?.id);
65
+ if (installationId !== connection.installationId) {
66
+ // Signed traffic naming a bound repo under the WRONG installation is suspicious — audit it.
67
+ await ctx.deps.audit.emit({
68
+ eventType: 'github.webhook.installation_mismatch',
69
+ org: connection.orgSlug,
70
+ app: connection.appSlug,
71
+ decision: 'deny',
72
+ status: 200,
73
+ details: {
74
+ deliveryId: ctx.deliveryId,
75
+ expectedInstallationId: connection.installationId,
76
+ receivedInstallationId: installationId ?? 0,
77
+ },
78
+ });
79
+ ignored(ctx.res, 'installation_mismatch');
80
+ return 'responded';
81
+ }
82
+ return connection;
83
+ }
84
+ async function recordRun(ctx, connection, input) {
85
+ const result = await ctx.deps.runStore.createDeployRun({
86
+ ...input,
87
+ runId: (ctx.deps.newRunId ?? defaultRunId)(),
88
+ orgSlug: connection.orgSlug,
89
+ appSlug: connection.appSlug,
90
+ deliveryId: ctx.deliveryId,
91
+ });
92
+ if (!result.ok) {
93
+ outcome(ctx.res, { outcome: 'duplicate', reason: result.reason });
94
+ return;
95
+ }
96
+ await ctx.deps.audit.emit({
97
+ eventType: 'github.webhook.run_queued',
98
+ org: connection.orgSlug,
99
+ app: connection.appSlug,
100
+ decision: 'allow',
101
+ status: 200,
102
+ details: {
103
+ deliveryId: ctx.deliveryId,
104
+ runId: result.record.runId,
105
+ envName: result.record.envName,
106
+ commitSha: result.record.commitSha,
107
+ sourceEvent: result.record.sourceEvent,
108
+ supersededCount: result.superseded.length,
109
+ ...(result.record.blockedReason !== undefined
110
+ ? { blockedReason: result.record.blockedReason }
111
+ : {}),
112
+ },
113
+ });
114
+ outcome(ctx.res, {
115
+ outcome: 'run_queued',
116
+ runId: result.record.runId,
117
+ envName: result.record.envName,
118
+ superseded: result.superseded,
119
+ });
120
+ }
121
+ async function cancelRuns(ctx, connection, filter) {
122
+ const canceled = await ctx.deps.runStore.cancelQueuedDeployRuns({
123
+ orgSlug: connection.orgSlug,
124
+ appSlug: connection.appSlug,
125
+ ...filter,
126
+ });
127
+ if (canceled.length > 0) {
128
+ await ctx.deps.audit.emit({
129
+ eventType: 'github.webhook.runs_canceled',
130
+ org: connection.orgSlug,
131
+ app: connection.appSlug,
132
+ decision: 'allow',
133
+ status: 200,
134
+ details: {
135
+ deliveryId: ctx.deliveryId,
136
+ count: canceled.length,
137
+ ...(filter.envName !== undefined ? { envName: filter.envName } : {}),
138
+ ...(filter.ref !== undefined ? { ref: filter.ref } : {}),
139
+ },
140
+ });
141
+ }
142
+ outcome(ctx.res, { outcome: 'runs_canceled', canceled });
143
+ }
144
+ async function handlePush(ctx, payload) {
145
+ const connection = await boundConnection(ctx, payload);
146
+ if (connection === 'responded')
147
+ return;
148
+ const ref = typeof payload.ref === 'string' ? payload.ref : undefined;
149
+ if (ref === undefined)
150
+ return sendJson(ctx.res, 400, { error: 'malformed payload' });
151
+ if (payload.deleted === true)
152
+ return cancelRuns(ctx, connection, { ref });
153
+ const after = typeof payload.after === 'string' && payload.after.length > 0 ? payload.after : undefined;
154
+ if (after === undefined)
155
+ return sendJson(ctx.res, 400, { error: 'malformed payload' });
156
+ const actorLogin = senderLogin(payload);
157
+ if (ref !== `refs/heads/${connection.defaultBranch}`) {
158
+ // The pinned mapping: non-default-branch pushes with no PR produce NO run — an audit-level
159
+ // record only, so the runs feed stays signal.
160
+ await ctx.deps.audit.emit({
161
+ eventType: 'github.webhook.push_ignored',
162
+ org: connection.orgSlug,
163
+ app: connection.appSlug,
164
+ decision: 'allow',
165
+ status: 200,
166
+ details: { deliveryId: ctx.deliveryId, ref, commitSha: after },
167
+ });
168
+ return ignored(ctx.res, 'non_default_branch');
169
+ }
170
+ return recordRun(ctx, connection, {
171
+ envName: 'prod',
172
+ sourceEvent: 'push',
173
+ githubRepositoryId: connection.githubRepositoryId,
174
+ commitSha: after,
175
+ ref,
176
+ actorLogin,
177
+ });
178
+ }
179
+ async function handlePullRequest(ctx, payload) {
180
+ const connection = await boundConnection(ctx, payload);
181
+ if (connection === 'responded')
182
+ return;
183
+ const pr = asRecord(payload.pull_request);
184
+ const number = positiveInt(pr?.number);
185
+ const head = asRecord(pr?.head);
186
+ const headSha = typeof head?.sha === 'string' ? head.sha : undefined;
187
+ const headRef = typeof head?.ref === 'string' ? head.ref : undefined;
188
+ const action = typeof payload.action === 'string' ? payload.action : undefined;
189
+ if (number === undefined ||
190
+ headSha === undefined ||
191
+ headRef === undefined ||
192
+ action === undefined) {
193
+ return sendJson(ctx.res, 400, { error: 'malformed payload' });
194
+ }
195
+ const envName = `pr-${number}`;
196
+ if (action === 'closed')
197
+ return cancelRuns(ctx, connection, { envName });
198
+ if (action !== 'opened' && action !== 'synchronize' && action !== 'reopened') {
199
+ return ignored(ctx.res, 'unhandled_action');
200
+ }
201
+ const headRepoId = positiveInt(asRecord(head?.repo)?.id);
202
+ // ADR 0111 §8: fork PRs are recorded but inert — no secrets, no build until owner approval.
203
+ const isFork = headRepoId !== connection.githubRepositoryId;
204
+ const actorLogin = senderLogin(payload);
205
+ return recordRun(ctx, connection, {
206
+ envName,
207
+ sourceEvent: 'pull_request',
208
+ githubRepositoryId: connection.githubRepositoryId,
209
+ commitSha: headSha,
210
+ ref: `refs/heads/${headRef}`,
211
+ prNumber: number,
212
+ actorLogin,
213
+ ...(isFork ? { blockedReason: 'fork_pending_approval' } : {}),
214
+ });
215
+ }
216
+ async function disableConnections(ctx, connections, reason) {
217
+ let count = 0;
218
+ for (const connection of connections) {
219
+ const disabled = await ctx.deps.connectionStore.disableRepoConnection(connection.orgSlug, connection.appSlug);
220
+ if (!disabled)
221
+ continue;
222
+ count += 1;
223
+ await ctx.deps.audit.emit({
224
+ eventType: 'github.webhook.connection_disabled',
225
+ org: connection.orgSlug,
226
+ app: connection.appSlug,
227
+ decision: 'allow',
228
+ status: 200,
229
+ details: {
230
+ deliveryId: ctx.deliveryId,
231
+ githubRepositoryId: connection.githubRepositoryId,
232
+ reason,
233
+ },
234
+ });
235
+ }
236
+ if (count === 0)
237
+ return ignored(ctx.res, 'no_connection');
238
+ outcome(ctx.res, { outcome: 'connection_disabled', count });
239
+ }
240
+ async function handleRepository(ctx, payload) {
241
+ const connection = await boundConnection(ctx, payload);
242
+ if (connection === 'responded')
243
+ return;
244
+ const action = typeof payload.action === 'string' ? payload.action : undefined;
245
+ const repository = asRecord(payload.repository);
246
+ if (action === 'archived')
247
+ return disableConnections(ctx, [connection], 'repository_archived');
248
+ if (action === 'renamed' || action === 'transferred' || action === 'edited') {
249
+ const fullName = typeof repository?.full_name === 'string' ? repository.full_name : undefined;
250
+ const defaultBranch = typeof repository?.default_branch === 'string' ? repository.default_branch : undefined;
251
+ const refreshed = await ctx.deps.connectionStore.refreshRepoMetadata(connection.githubRepositoryId, {
252
+ ...(fullName !== undefined
253
+ ? { repoName: fullName, ownerLogin: fullName.split('/')[0] ?? connection.ownerLogin }
254
+ : {}),
255
+ ...(defaultBranch !== undefined ? { defaultBranch } : {}),
256
+ });
257
+ if (refreshed === undefined)
258
+ return ignored(ctx.res, 'no_connection');
259
+ await ctx.deps.audit.emit({
260
+ eventType: 'github.webhook.metadata_refreshed',
261
+ org: connection.orgSlug,
262
+ app: connection.appSlug,
263
+ decision: 'allow',
264
+ status: 200,
265
+ details: { deliveryId: ctx.deliveryId, githubRepositoryId: connection.githubRepositoryId },
266
+ });
267
+ return outcome(ctx.res, { outcome: 'metadata_refreshed' });
268
+ }
269
+ return ignored(ctx.res, 'unhandled_action');
270
+ }
271
+ async function handleInstallation(ctx, payload) {
272
+ const action = typeof payload.action === 'string' ? payload.action : undefined;
273
+ const installationId = positiveInt(asRecord(payload.installation)?.id);
274
+ if (installationId === undefined)
275
+ return sendJson(ctx.res, 400, { error: 'malformed payload' });
276
+ if (action !== 'deleted')
277
+ return ignored(ctx.res, 'unhandled_action');
278
+ const connections = await ctx.deps.connectionStore.listRepoConnectionsByInstallation(installationId);
279
+ return disableConnections(ctx, connections, 'installation_removed');
280
+ }
281
+ async function handleInstallationRepositories(ctx, payload) {
282
+ const action = typeof payload.action === 'string' ? payload.action : undefined;
283
+ if (action !== 'removed')
284
+ return ignored(ctx.res, 'unhandled_action');
285
+ const installationId = positiveInt(asRecord(payload.installation)?.id);
286
+ if (installationId === undefined)
287
+ return sendJson(ctx.res, 400, { error: 'malformed payload' });
288
+ const removed = Array.isArray(payload.repositories_removed) ? payload.repositories_removed : [];
289
+ const connections = [];
290
+ for (const item of removed) {
291
+ const id = positiveInt(asRecord(item)?.id);
292
+ if (id === undefined)
293
+ continue;
294
+ const connection = await ctx.deps.connectionStore.getRepoConnectionByRepository(id);
295
+ // Same repository+installation binding rule as every other event: a delivery for installation X
296
+ // must never disable a repo bound under installation Y.
297
+ if (connection !== undefined && connection.installationId === installationId) {
298
+ connections.push(connection);
299
+ }
300
+ }
301
+ return disableConnections(ctx, connections, 'repository_removed_from_installation');
302
+ }
303
+ export async function handleGithubWebhook(req, res, deps) {
304
+ // Fail closed when the feature is unconfigured: with no secret there is nothing to verify against.
305
+ if (deps.webhookSecret === undefined || deps.webhookSecret.length === 0) {
306
+ return sendJson(res, 403, { error: 'webhook not configured' });
307
+ }
308
+ const body = await readRawBody(req, deps.maxBody);
309
+ if (!body.ok)
310
+ return sendJson(res, 413, { error: 'request body too large' });
311
+ // Layer 1: the signature, over raw bytes, before ANY header/JSON interpretation.
312
+ const signature = req.headers[SIGNATURE_HEADER];
313
+ const signatureValue = Array.isArray(signature) ? signature[0] : signature;
314
+ if (!verifyWebhookSignature(body.raw, signatureValue, deps.webhookSecret)) {
315
+ return sendJson(res, 401, { error: 'invalid signature' });
316
+ }
317
+ // Layer 2: required delivery headers.
318
+ const eventHeader = req.headers['x-github-event'];
319
+ const deliveryHeader = req.headers['x-github-delivery'];
320
+ const eventName = Array.isArray(eventHeader) ? eventHeader[0] : eventHeader;
321
+ const deliveryId = Array.isArray(deliveryHeader) ? deliveryHeader[0] : deliveryHeader;
322
+ if (eventName === undefined || deliveryId === undefined || deliveryId.length === 0) {
323
+ return sendJson(res, 400, { error: 'missing event headers' });
324
+ }
325
+ // Layer 3: payload shape.
326
+ let payload;
327
+ try {
328
+ const parsed = JSON.parse(body.raw.toString('utf8'));
329
+ const record = asRecord(parsed);
330
+ if (record === undefined)
331
+ return sendJson(res, 400, { error: 'malformed payload' });
332
+ payload = record;
333
+ }
334
+ catch {
335
+ return sendJson(res, 400, { error: 'malformed payload' });
336
+ }
337
+ const ctx = { deliveryId, deps, res };
338
+ switch (eventName) {
339
+ case 'push':
340
+ return handlePush(ctx, payload);
341
+ case 'pull_request':
342
+ return handlePullRequest(ctx, payload);
343
+ case 'repository':
344
+ return handleRepository(ctx, payload);
345
+ case 'installation':
346
+ return handleInstallation(ctx, payload);
347
+ case 'installation_repositories':
348
+ return handleInstallationRepositories(ctx, payload);
349
+ default:
350
+ // The subscribed-event set can drift ahead of the handled set — unknown events are safely
351
+ // acknowledged so GitHub never retries them.
352
+ return ignored(res, 'unsupported_event');
353
+ }
354
+ }
355
+ //# sourceMappingURL=github-webhook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-webhook.js","sourceRoot":"","sources":["../../src/routes/github-webhook.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Dispatch for the org-admin control-plane routes: the orgs collection, the single-org item
3
+ * (PATCH rename / GET inspect), members, and invitations. Extracted verbatim from `service.ts`
4
+ * (which stays a thin composition root under the size gate), the same way as
5
+ * `analytics-dispatch.ts`/`github-dispatch.ts`. The path families here (`/v1/orgs`,
6
+ * `/v1/orgs/{org}`, `.../members`, `.../invitations`) are disjoint from the ADR 0128 resource
7
+ * reads (`apps`/`envs`/`deployments`), so this dispatcher's position next to them in the
8
+ * composition root is not behavior-bearing.
9
+ */
10
+ import type { IncomingMessage, ServerResponse } from 'node:http';
11
+ import type { TlsPosture } from '@noodle-borg/transport-http';
12
+ import type { DeployAuthGate } from '../auth/deploy-gate.js';
13
+ import type { AuditSink } from '../store/audit.js';
14
+ import type { ControlPlaneStore } from '../store.js';
15
+ export interface OrgAdminDispatchDeps {
16
+ readonly gate: DeployAuthGate;
17
+ readonly controlPlane: ControlPlaneStore;
18
+ readonly audit: AuditSink;
19
+ readonly maxBody: number;
20
+ readonly applySecurityHeaders: (res: ServerResponse, tls: TlsPosture) => void;
21
+ readonly enforceHttps: (req: IncomingMessage, res: ServerResponse, tls: TlsPosture) => boolean;
22
+ readonly sendJson: (res: ServerResponse, status: number, body: unknown) => void;
23
+ readonly tls: TlsPosture;
24
+ }
25
+ /** Try the org-admin routes; returns true when the request was handled (or a guard ended it). */
26
+ export declare function dispatchOrgAdminRoutes(req: IncomingMessage, res: ServerResponse, url: URL, deps: OrgAdminDispatchDeps): boolean;
27
+ //# sourceMappingURL=org-admin-dispatch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"org-admin-dispatch.d.ts","sourceRoot":"","sources":["../../src/routes/org-admin-dispatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAUrD,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,iBAAiB,CAAC;IACzC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,oBAAoB,EAAE,CAAC,GAAG,EAAE,cAAc,EAAE,GAAG,EAAE,UAAU,KAAK,IAAI,CAAC;IAC9E,QAAQ,CAAC,YAAY,EAAE,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,EAAE,GAAG,EAAE,UAAU,KAAK,OAAO,CAAC;IAC/F,QAAQ,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAChF,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC;CAC1B;AAED,iGAAiG;AACjG,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,oBAAoB,GACzB,OAAO,CAkDT"}
@@ -0,0 +1,61 @@
1
+ import { handleInvitations, handleMembers, handleOrgInspect, handleOrgs, handleOrgUpdate, } from './org-admin.js';
2
+ import { parseInvitationsPath, parseMembersPath, parseOrgPath } from './paths.js';
3
+ /** Try the org-admin routes; returns true when the request was handled (or a guard ended it). */
4
+ export function dispatchOrgAdminRoutes(req, res, url, deps) {
5
+ const { gate, controlPlane, audit, maxBody, applySecurityHeaders, enforceHttps, sendJson, tls } = deps;
6
+ if (url.pathname === '/v1/orgs' && (req.method === 'GET' || req.method === 'POST')) {
7
+ applySecurityHeaders(res, tls);
8
+ if (enforceHttps(req, res, tls))
9
+ return true;
10
+ handleOrgs(req, res, gate, controlPlane, maxBody).catch(() => {
11
+ if (!res.headersSent)
12
+ sendJson(res, 500, { error: 'internal error' });
13
+ });
14
+ return true;
15
+ }
16
+ const orgRef = parseOrgPath(url.pathname);
17
+ if (orgRef !== undefined && req.method === 'PATCH') {
18
+ applySecurityHeaders(res, tls);
19
+ if (enforceHttps(req, res, tls))
20
+ return true;
21
+ handleOrgUpdate(req, res, gate, controlPlane, maxBody, orgRef, audit).catch(() => {
22
+ if (!res.headersSent)
23
+ sendJson(res, 500, { error: 'internal error' });
24
+ });
25
+ return true;
26
+ }
27
+ if (orgRef !== undefined && req.method === 'GET') {
28
+ applySecurityHeaders(res, tls);
29
+ if (enforceHttps(req, res, tls))
30
+ return true;
31
+ handleOrgInspect(req, res, gate, controlPlane, orgRef).catch(() => {
32
+ if (!res.headersSent)
33
+ sendJson(res, 500, { error: 'internal error' });
34
+ });
35
+ return true;
36
+ }
37
+ const membersRef = parseMembersPath(url.pathname);
38
+ if (membersRef !== undefined) {
39
+ applySecurityHeaders(res, tls);
40
+ if (enforceHttps(req, res, tls))
41
+ return true;
42
+ handleMembers(req, res, gate, controlPlane, maxBody, membersRef, audit).catch(() => {
43
+ if (!res.headersSent)
44
+ sendJson(res, 500, { error: 'internal error' });
45
+ });
46
+ return true;
47
+ }
48
+ const invitationsRef = parseInvitationsPath(url.pathname);
49
+ if (invitationsRef !== undefined) {
50
+ applySecurityHeaders(res, tls);
51
+ if (enforceHttps(req, res, tls))
52
+ return true;
53
+ handleInvitations(req, res, gate, controlPlane, maxBody, invitationsRef, audit, url).catch(() => {
54
+ if (!res.headersSent)
55
+ sendJson(res, 500, { error: 'internal error' });
56
+ });
57
+ return true;
58
+ }
59
+ return false;
60
+ }
61
+ //# sourceMappingURL=org-admin-dispatch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"org-admin-dispatch.js","sourceRoot":"","sources":["../../src/routes/org-admin-dispatch.ts"],"names":[],"mappings":"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"}
@@ -98,6 +98,18 @@ export declare function parseTenantAccessPath(pathname: string): TenantRef | und
98
98
  export declare function parseTenantLogsPath(pathname: string): TenantRef | undefined;
99
99
  export declare function parseTenantMetricsPath(pathname: string): TenantRef | undefined;
100
100
  export declare function parseTenantEventsPath(pathname: string): TenantRef | undefined;
101
+ /** `GET|POST /v1/orgs/{org}/apps/{app}/envs/{env}/alerts` — the alert-rule collection (E2, ADR 0130). */
102
+ export declare function parseTenantAlertsPath(pathname: string): TenantRef | undefined;
103
+ /** `DELETE .../alerts/{id}` — one alert rule. Non-UUID ids never match (they cannot exist). */
104
+ export declare function parseTenantAlertItemPath(pathname: string): {
105
+ readonly ref: TenantRef;
106
+ readonly id: string;
107
+ } | undefined;
108
+ /** `POST .../alerts/{id}/test` — synthetic test-fire through the rule's webhook (E2, ADR 0130). */
109
+ export declare function parseTenantAlertTestPath(pathname: string): {
110
+ readonly ref: TenantRef;
111
+ readonly id: string;
112
+ } | undefined;
101
113
  /** `GET /v1/orgs/{org}/apps/{app}/envs/{env}/sessions/{id}` — the analytics session view (ADR 0121). */
102
114
  export declare function parseTenantSessionPath(pathname: string): {
103
115
  readonly ref: TenantRef;
@@ -108,13 +120,20 @@ export declare function parseGithubConnectionPath(pathname: string): {
108
120
  org: string;
109
121
  app: string;
110
122
  } | undefined;
123
+ /** Parse `/v1/orgs/{org}/apps/{app}/github/runs` (GHD-2, the deploy-runs read surface). */
124
+ export declare function parseGithubRunsPath(pathname: string): {
125
+ org: string;
126
+ app: string;
127
+ } | undefined;
111
128
  /** Match the fixed path `/v1/github/install-url` (GHD-1). */
112
129
  export declare function isGithubInstallUrlPath(pathname: string): boolean;
113
130
  /** Match the fixed path `/v1/github/installations/claim` (GHD-1). */
114
131
  export declare function isGithubInstallationClaimPath(pathname: string): boolean;
132
+ /** Match the fixed path `/v1/github/webhook` (GHD-2, the GitHub App's webhook receiver). */
133
+ export declare function isGithubWebhookPath(pathname: string): boolean;
115
134
  /** Match the fixed path `/v1/github/setup` (GHD-1.4, the GitHub App's configured Setup URL). */
116
135
  export declare function isGithubSetupPath(pathname: string): boolean;
117
136
  /** Match the fixed path `/v1/github/installations/pending` (GHD-1.4, the CLI's install poll target). */
118
137
  export declare function isGithubInstallationPendingPath(pathname: string): boolean;
119
- export declare function parseTenantActionPath(pathname: string, action: 'status' | 'access' | 'rollback' | 'inspect' | 'smoke' | 'logs' | 'metrics' | 'events'): TenantRef | undefined;
138
+ export declare function parseTenantActionPath(pathname: string, action: 'status' | 'access' | 'rollback' | 'inspect' | 'smoke' | 'logs' | 'metrics' | 'events' | 'alerts'): TenantRef | undefined;
120
139
  //# sourceMappingURL=paths.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/routes/paths.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/routes/paths.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { isAlertRuleId } from '../store/alert-rules.js';
1
2
  import { DEPLOYMENT_ID_PATTERN, validateConfigName, validateConfigScope, validateSlug, validateTenantRef, } from '../store.js';
2
3
  export function parseTenantDeployPath(pathname) {
3
4
  const match = /^\/v1\/orgs\/([^/]+)\/apps\/([^/]+)\/envs\/([^/]+)\/deploy$/.exec(pathname);
@@ -333,6 +334,40 @@ export function parseTenantMetricsPath(pathname) {
333
334
  export function parseTenantEventsPath(pathname) {
334
335
  return parseTenantActionPath(pathname, 'events');
335
336
  }
337
+ /** `GET|POST /v1/orgs/{org}/apps/{app}/envs/{env}/alerts` — the alert-rule collection (E2, ADR 0130). */
338
+ export function parseTenantAlertsPath(pathname) {
339
+ return parseTenantActionPath(pathname, 'alerts');
340
+ }
341
+ /** `DELETE .../alerts/{id}` — one alert rule. Non-UUID ids never match (they cannot exist). */
342
+ export function parseTenantAlertItemPath(pathname) {
343
+ const match = /^\/v1\/orgs\/([^/]+)\/apps\/([^/]+)\/envs\/([^/]+)\/alerts\/([^/]+)$/.exec(pathname);
344
+ return match ? tenantAlertRef(match) : undefined;
345
+ }
346
+ /** `POST .../alerts/{id}/test` — synthetic test-fire through the rule's webhook (E2, ADR 0130). */
347
+ export function parseTenantAlertTestPath(pathname) {
348
+ const match = /^\/v1\/orgs\/([^/]+)\/apps\/([^/]+)\/envs\/([^/]+)\/alerts\/([^/]+)\/test$/.exec(pathname);
349
+ return match ? tenantAlertRef(match) : undefined;
350
+ }
351
+ function tenantAlertRef(match) {
352
+ // Everything decodes inside the try: a malformed escape (`%zz`) throws URIError and must read
353
+ // as "no match", never an uncaught synchronous throw out of the dispatcher.
354
+ try {
355
+ const id = decodeURIComponent(match[4]);
356
+ if (!isAlertRuleId(id))
357
+ return undefined;
358
+ return {
359
+ ref: validateTenantRef({
360
+ org: decodeURIComponent(match[1]),
361
+ app: decodeURIComponent(match[2]),
362
+ env: decodeURIComponent(match[3]),
363
+ }),
364
+ id,
365
+ };
366
+ }
367
+ catch {
368
+ return undefined;
369
+ }
370
+ }
336
371
  /** `GET /v1/orgs/{org}/apps/{app}/envs/{env}/sessions/{id}` — the analytics session view (ADR 0121). */
337
372
  export function parseTenantSessionPath(pathname) {
338
373
  const match = /^\/v1\/orgs\/([^/]+)\/apps\/([^/]+)\/envs\/([^/]+)\/sessions\/([^/]+)$/.exec(pathname);
@@ -367,6 +402,21 @@ export function parseGithubConnectionPath(pathname) {
367
402
  return undefined;
368
403
  }
369
404
  }
405
+ /** Parse `/v1/orgs/{org}/apps/{app}/github/runs` (GHD-2, the deploy-runs read surface). */
406
+ export function parseGithubRunsPath(pathname) {
407
+ const match = /^\/v1\/orgs\/([^/]+)\/apps\/([^/]+)\/github\/runs$/.exec(pathname);
408
+ if (!match)
409
+ return undefined;
410
+ try {
411
+ return {
412
+ org: validateSlug('org', decodeURIComponent(match[1])),
413
+ app: validateSlug('app', decodeURIComponent(match[2])),
414
+ };
415
+ }
416
+ catch {
417
+ return undefined;
418
+ }
419
+ }
370
420
  /** Match the fixed path `/v1/github/install-url` (GHD-1). */
371
421
  export function isGithubInstallUrlPath(pathname) {
372
422
  return pathname === '/v1/github/install-url';
@@ -375,6 +425,10 @@ export function isGithubInstallUrlPath(pathname) {
375
425
  export function isGithubInstallationClaimPath(pathname) {
376
426
  return pathname === '/v1/github/installations/claim';
377
427
  }
428
+ /** Match the fixed path `/v1/github/webhook` (GHD-2, the GitHub App's webhook receiver). */
429
+ export function isGithubWebhookPath(pathname) {
430
+ return pathname === '/v1/github/webhook';
431
+ }
378
432
  /** Match the fixed path `/v1/github/setup` (GHD-1.4, the GitHub App's configured Setup URL). */
379
433
  export function isGithubSetupPath(pathname) {
380
434
  return pathname === '/v1/github/setup';