@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.
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +3 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/alerts-ops.d.ts +2 -0
- package/dist/commands/alerts-ops.d.ts.map +1 -0
- package/dist/commands/alerts-ops.js +249 -0
- package/dist/commands/alerts-ops.js.map +1 -0
- package/dist/commands/analytics-ops.d.ts +13 -0
- package/dist/commands/analytics-ops.d.ts.map +1 -1
- package/dist/commands/analytics-ops.js +5 -2
- package/dist/commands/analytics-ops.js.map +1 -1
- package/dist/commands/catalog-data-resources.d.ts.map +1 -1
- package/dist/commands/catalog-data-resources.js +45 -0
- package/dist/commands/catalog-data-resources.js.map +1 -1
- package/dist/commands/github-ops.d.ts.map +1 -1
- package/dist/commands/github-ops.js +24 -4
- package/dist/commands/github-ops.js.map +1 -1
- package/dist/commands/github-runs-ops.d.ts +32 -0
- package/dist/commands/github-runs-ops.d.ts.map +1 -0
- package/dist/commands/github-runs-ops.js +132 -0
- package/dist/commands/github-runs-ops.js.map +1 -0
- package/node_modules/@noodle-borg/agent-kit/dist/curated/command-groups.d.ts.map +1 -1
- package/node_modules/@noodle-borg/agent-kit/dist/curated/command-groups.js +5 -0
- package/node_modules/@noodle-borg/agent-kit/dist/curated/command-groups.js.map +1 -1
- package/node_modules/@noodle-borg/agent-kit/dist/generated/surface.d.ts.map +1 -1
- package/node_modules/@noodle-borg/agent-kit/dist/generated/surface.js +1 -0
- package/node_modules/@noodle-borg/agent-kit/dist/generated/surface.js.map +1 -1
- package/node_modules/@noodle-borg/agent-kit/package.json +1 -1
- package/node_modules/@noodle-borg/authoring/dist/recording.js +18 -23
- package/node_modules/@noodle-borg/authoring/dist/recording.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/alert-evaluator.d.ts +57 -0
- package/node_modules/@noodle-borg/service/dist/alert-evaluator.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/alert-evaluator.js +158 -0
- package/node_modules/@noodle-borg/service/dist/alert-evaluator.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/alert-webhook.d.ts +72 -0
- package/node_modules/@noodle-borg/service/dist/alert-webhook.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/alert-webhook.js +138 -0
- package/node_modules/@noodle-borg/service/dist/alert-webhook.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/github/pending-installations.d.ts +15 -8
- package/node_modules/@noodle-borg/service/dist/github/pending-installations.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/github/pending-installations.js +16 -9
- package/node_modules/@noodle-borg/service/dist/github/pending-installations.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/index.d.ts +10 -2
- package/node_modules/@noodle-borg/service/dist/index.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/index.js +9 -1
- package/node_modules/@noodle-borg/service/dist/index.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/options.d.ts +20 -1
- package/node_modules/@noodle-borg/service/dist/options.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/alerts-dispatch.d.ts +28 -0
- package/node_modules/@noodle-borg/service/dist/routes/alerts-dispatch.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/routes/alerts-dispatch.js +50 -0
- package/node_modules/@noodle-borg/service/dist/routes/alerts-dispatch.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/routes/alerts.d.ts +39 -0
- package/node_modules/@noodle-borg/service/dist/routes/alerts.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/routes/alerts.js +204 -0
- package/node_modules/@noodle-borg/service/dist/routes/alerts.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/routes/contracts.d.ts +149 -0
- package/node_modules/@noodle-borg/service/dist/routes/contracts.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/contracts.js +81 -0
- package/node_modules/@noodle-borg/service/dist/routes/contracts.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/github-connection.js +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/github-connection.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/github-dispatch.d.ts +2 -1
- package/node_modules/@noodle-borg/service/dist/routes/github-dispatch.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/github-dispatch.js +37 -2
- package/node_modules/@noodle-borg/service/dist/routes/github-dispatch.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/github-runs.d.ts +8 -0
- package/node_modules/@noodle-borg/service/dist/routes/github-runs.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/routes/github-runs.js +33 -0
- package/node_modules/@noodle-borg/service/dist/routes/github-runs.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/routes/github-setup.d.ts +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/github-setup.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/github-setup.js +3 -3
- package/node_modules/@noodle-borg/service/dist/routes/github-setup.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/github-webhook.d.ts +29 -0
- package/node_modules/@noodle-borg/service/dist/routes/github-webhook.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/routes/github-webhook.js +355 -0
- package/node_modules/@noodle-borg/service/dist/routes/github-webhook.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/routes/org-admin-dispatch.d.ts +27 -0
- package/node_modules/@noodle-borg/service/dist/routes/org-admin-dispatch.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/routes/org-admin-dispatch.js +61 -0
- package/node_modules/@noodle-borg/service/dist/routes/org-admin-dispatch.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/routes/paths.d.ts +20 -1
- package/node_modules/@noodle-borg/service/dist/routes/paths.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/paths.js +54 -0
- package/node_modules/@noodle-borg/service/dist/routes/paths.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/serve.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/serve.js +42 -1
- package/node_modules/@noodle-borg/service/dist/serve.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/service.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/service.js +37 -53
- package/node_modules/@noodle-borg/service/dist/service.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/store/alert-rules-json-file.d.ts +21 -0
- package/node_modules/@noodle-borg/service/dist/store/alert-rules-json-file.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/store/alert-rules-json-file.js +115 -0
- package/node_modules/@noodle-borg/service/dist/store/alert-rules-json-file.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/store/alert-rules.d.ts +108 -0
- package/node_modules/@noodle-borg/service/dist/store/alert-rules.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/store/alert-rules.js +181 -0
- package/node_modules/@noodle-borg/service/dist/store/alert-rules.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/store/github-connections-json-file.d.ts +1 -0
- package/node_modules/@noodle-borg/service/dist/store/github-connections-json-file.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/store/github-connections-json-file.js +4 -0
- package/node_modules/@noodle-borg/service/dist/store/github-connections-json-file.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/store/github-connections.d.ts +1 -0
- package/node_modules/@noodle-borg/service/dist/store/github-connections.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/store/github-connections.js +4 -0
- package/node_modules/@noodle-borg/service/dist/store/github-connections.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/store/github-runs-json-file.d.ts +22 -0
- package/node_modules/@noodle-borg/service/dist/store/github-runs-json-file.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/store/github-runs-json-file.js +116 -0
- package/node_modules/@noodle-borg/service/dist/store/github-runs-json-file.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/store/github-runs.d.ts +51 -0
- package/node_modules/@noodle-borg/service/dist/store/github-runs.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/store/github-runs.js +158 -0
- package/node_modules/@noodle-borg/service/dist/store/github-runs.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/store/pending-installations-postgres.d.ts +19 -0
- package/node_modules/@noodle-borg/service/dist/store/pending-installations-postgres.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/store/pending-installations-postgres.js +46 -0
- package/node_modules/@noodle-borg/service/dist/store/pending-installations-postgres.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/store/postgres-alerts.d.ts +26 -0
- package/node_modules/@noodle-borg/service/dist/store/postgres-alerts.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/store/postgres-alerts.js +142 -0
- package/node_modules/@noodle-borg/service/dist/store/postgres-alerts.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/store/postgres-github-runs.d.ts +9 -0
- package/node_modules/@noodle-borg/service/dist/store/postgres-github-runs.d.ts.map +1 -0
- package/node_modules/@noodle-borg/service/dist/store/postgres-github-runs.js +113 -0
- package/node_modules/@noodle-borg/service/dist/store/postgres-github-runs.js.map +1 -0
- package/node_modules/@noodle-borg/service/dist/store/postgres-github.d.ts +1 -0
- package/node_modules/@noodle-borg/service/dist/store/postgres-github.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/store/postgres-github.js +7 -2
- package/node_modules/@noodle-borg/service/dist/store/postgres-github.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/store/postgres-schema.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/store/postgres-schema.js +49 -0
- package/node_modules/@noodle-borg/service/dist/store/postgres-schema.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/store/postgres.d.ts +9 -2
- package/node_modules/@noodle-borg/service/dist/store/postgres.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/store/postgres.js +17 -1
- package/node_modules/@noodle-borg/service/dist/store/postgres.js.map +1 -1
- package/node_modules/@noodle-borg/service/dist/store.d.ts +104 -0
- package/node_modules/@noodle-borg/service/dist/store.d.ts.map +1 -1
- package/node_modules/@noodle-borg/service/dist/store.js +2 -0
- package/node_modules/@noodle-borg/service/dist/store.js.map +1 -1
- package/package.json +2 -2
|
@@ -10,9 +10,10 @@ import type { GitHubAppClient, GithubAppConfig } from './github/app-client.js';
|
|
|
10
10
|
import type { PendingGithubInstallationStore } from './github/pending-installations.js';
|
|
11
11
|
import type { LoadedServiceModule } from './modules/host.js';
|
|
12
12
|
import type { PolicyAssignmentStore, PolicyCounterStore } from './policy.js';
|
|
13
|
+
import type { AlertRuleStore } from './store/alert-rules.js';
|
|
13
14
|
import type { AuditSink } from './store/audit.js';
|
|
14
15
|
import type { UserAppLogStore } from './store/user-app-logs.js';
|
|
15
|
-
import type { ConfigStore, ControlPlaneStore, GithubConnectionStore } from './store.js';
|
|
16
|
+
import type { ConfigStore, ControlPlaneStore, GithubConnectionStore, GithubDeployRunStore } from './store.js';
|
|
16
17
|
export interface ServiceOptions {
|
|
17
18
|
/** Public base URL used to build returned endpoint URLs. Defaults to the request's Host header. */
|
|
18
19
|
readonly publicBaseUrl?: string;
|
|
@@ -109,6 +110,19 @@ export interface ServiceOptions {
|
|
|
109
110
|
* tiered by-plan retention is a later stage). Default 30.
|
|
110
111
|
*/
|
|
111
112
|
readonly requestEventRetentionDays?: number;
|
|
113
|
+
/**
|
|
114
|
+
* Analytics alert-rule store (E2, ADR 0130). Backs the tenant `alerts` CRUD/test routes and the
|
|
115
|
+
* periodic evaluator. Default: in-memory in the handler; `serveService` selects Postgres when
|
|
116
|
+
* persistence is configured, else a `dataDir` JSON-file store, else in-memory (mirrors the
|
|
117
|
+
* request-event store selection).
|
|
118
|
+
*/
|
|
119
|
+
readonly alertRuleStore?: AlertRuleStore;
|
|
120
|
+
/**
|
|
121
|
+
* Dev/test-only carve-out allowing `http://localhost` / `http://127.0.0.1` / `[::1]` alert
|
|
122
|
+
* webhook targets (mirrors `customerVerifierAllowInsecureLocalhost`). Production leaves this
|
|
123
|
+
* unset: webhooks are https-only and delivery is SSRF-guarded (DNS-pinned public unicast).
|
|
124
|
+
*/
|
|
125
|
+
readonly alertWebhookAllowLoopback?: boolean;
|
|
112
126
|
/**
|
|
113
127
|
* The self-hosted authorization server issuer (OA-2) advertised in protected-resource metadata so an
|
|
114
128
|
* MCP client can discover where to authenticate. When unset, the metadata omits `authorization_servers`.
|
|
@@ -143,6 +157,11 @@ export interface ServiceOptions {
|
|
|
143
157
|
* store, else in-memory (mirrors `controlPlaneStore`/`configStore`).
|
|
144
158
|
*/
|
|
145
159
|
readonly githubConnectionStore?: GithubConnectionStore;
|
|
160
|
+
/**
|
|
161
|
+
* GHD-2 deploy-run store (ADR 0111 §6): webhook-accepted runs, replay-safe. Same backend-selection
|
|
162
|
+
* rule as `githubConnectionStore`.
|
|
163
|
+
*/
|
|
164
|
+
readonly githubDeployRunStore?: GithubDeployRunStore;
|
|
146
165
|
/**
|
|
147
166
|
* Non-secret Noodle Seed GitHub App identity (ADR 0111). Everything is optional — the whole GHD-1
|
|
148
167
|
* connection feature is off (install-url 409s) when absent. Long-lived credentials
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAChF,OAAO,KAAK,EACV,aAAa,EACb,MAAM,EACN,kBAAkB,EAClB,UAAU,EACX,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACpF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,mCAAmC,CAAC;AACxF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,KAAK,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAC7E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAChF,OAAO,KAAK,EACV,aAAa,EACb,MAAM,EACN,kBAAkB,EAClB,UAAU,EACX,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACpF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,mCAAmC,CAAC;AACxF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,KAAK,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAC7E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,KAAK,EACV,WAAW,EACX,iBAAiB,EACjB,qBAAqB,EACrB,oBAAoB,EACrB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,cAAc;IAC7B,mGAAmG;IACnG,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,gEAAgE;IAChE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,0GAA0G;IAC1G,QAAQ,CAAC,UAAU,CAAC,EAAE,cAAc,CAAC;IACrC,oGAAoG;IACpG,QAAQ,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IAC/C,kGAAkG;IAClG,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC;IACnC;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC;IAC3B,sEAAsE;IACtE,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;IACjC,kGAAkG;IAClG,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC,yGAAyG;IACzG,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IACvC,wFAAwF;IACxF,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;IAC/B;;;OAGG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC;IAC1B;;;;OAIG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IACjD;;;OAGG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,kBAAkB,CAAC;IAC/C;;;OAGG;IACH,QAAQ,CAAC,sCAAsC,CAAC,EAAE,OAAO,CAAC;IAC1D;;;OAGG;IACH,QAAQ,CAAC,4BAA4B,CAAC,EAAE,aAAa,CAAC;IACtD,yFAAyF;IACzF,QAAQ,CAAC,+BAA+B,CAAC,EAAE,MAAM,CAAC;IAClD,qFAAqF;IACrF,QAAQ,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC;IACvC,4FAA4F;IAC5F,QAAQ,CAAC,WAAW,CAAC,EAAE,qBAAqB,CAAC;IAC7C,uFAAuF;IACvF,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,uEAAuE;IACvE,QAAQ,CAAC,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACjD,iGAAiG;IACjG,QAAQ,CAAC,qBAAqB,CAAC,EAAE,qBAAqB,CAAC;IACvD;;;;OAIG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,eAAe,CAAC;IAC3C;;;;OAIG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IAC/C;;;OAGG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAClE;;;OAGG;IACH,QAAQ,CAAC,yBAAyB,CAAC,EAAE,MAAM,CAAC;IAC5C;;;;;OAKG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,cAAc,CAAC;IACzC;;;;OAIG;IACH,QAAQ,CAAC,yBAAyB,CAAC,EAAE,OAAO,CAAC;IAC7C;;;OAGG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,KAAK,IAAI,CAAC;IAC7E;;;OAGG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,KAAK,IAAI,CAAC;IAC9E,0FAA0F;IAC1F,QAAQ,CAAC,0BAA0B,CAAC,EAAE,MAAM,CAAC;IAC7C,4GAA4G;IAC5G,QAAQ,CAAC,8BAA8B,CAAC,EAAE,MAAM,CAAC;IACjD,sGAAsG;IACtG,QAAQ,CAAC,sBAAsB,CAAC,EAAE,sBAAsB,CAAC;IACzD,6FAA6F;IAC7F,QAAQ,CAAC,mBAAmB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjD,4GAA4G;IAC5G,QAAQ,CAAC,oBAAoB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClD,0GAA0G;IAC1G,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACxD;;;;OAIG;IACH,QAAQ,CAAC,qBAAqB,CAAC,EAAE,qBAAqB,CAAC;IACvD;;;OAGG;IACH,QAAQ,CAAC,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IACrD;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,eAAe,CAAC;IACrC;;;;OAIG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,eAAe,CAAC;IAC3C;;;;OAIG;IACH,QAAQ,CAAC,8BAA8B,CAAC,EAAE,8BAA8B,CAAC;CAC1E"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dispatch for the analytics alerting routes (E2, ADR 0130), extracted the same way as
|
|
3
|
+
* `analytics-dispatch.ts`/`github-dispatch.ts` so `service.ts` stays a thin composition root
|
|
4
|
+
* under the size gate. The three path shapes are mutually exclusive by regex (the item pattern's
|
|
5
|
+
* final `[^/]+$` can never match the `/test` suffix), so dispatch order carries no behavior.
|
|
6
|
+
*/
|
|
7
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
8
|
+
import type { TlsPosture } from '@noodle-borg/transport-http';
|
|
9
|
+
import type { DeployAuthGate } from '../auth/deploy-gate.js';
|
|
10
|
+
import type { AlertRuleStore } from '../store/alert-rules.js';
|
|
11
|
+
import type { AuditSink } from '../store/audit.js';
|
|
12
|
+
import type { ControlPlaneStore } from '../store.js';
|
|
13
|
+
export interface AlertsDispatchDeps {
|
|
14
|
+
readonly gate: DeployAuthGate;
|
|
15
|
+
readonly controlPlane: ControlPlaneStore;
|
|
16
|
+
readonly alertRuleStore: AlertRuleStore;
|
|
17
|
+
readonly audit: AuditSink;
|
|
18
|
+
readonly maxBody: number;
|
|
19
|
+
readonly allowLoopbackWebhooks: boolean;
|
|
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
|
+
readonly clock?: () => Date;
|
|
25
|
+
}
|
|
26
|
+
/** Try the alerting routes; returns true when the request was handled (or a guard ended it). */
|
|
27
|
+
export declare function dispatchAlertRoutes(req: IncomingMessage, res: ServerResponse, url: URL, deps: AlertsDispatchDeps): boolean;
|
|
28
|
+
//# sourceMappingURL=alerts-dispatch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alerts-dispatch.d.ts","sourceRoot":"","sources":["../../src/routes/alerts-dispatch.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;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,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAQrD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,iBAAiB,CAAC;IACzC,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,qBAAqB,EAAE,OAAO,CAAC;IACxC,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;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;CAC7B;AAED,gGAAgG;AAChG,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,kBAAkB,GACvB,OAAO,CA2CT"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { handleAlertRuleDelete, handleAlertRules, handleAlertRuleTest } from './alerts.js';
|
|
2
|
+
import { parseTenantAlertItemPath, parseTenantAlertsPath, parseTenantAlertTestPath, } from './paths.js';
|
|
3
|
+
/** Try the alerting routes; returns true when the request was handled (or a guard ended it). */
|
|
4
|
+
export function dispatchAlertRoutes(req, res, url, deps) {
|
|
5
|
+
const { applySecurityHeaders, enforceHttps, sendJson, tls } = deps;
|
|
6
|
+
const routeDeps = {
|
|
7
|
+
gate: deps.gate,
|
|
8
|
+
controlPlane: deps.controlPlane,
|
|
9
|
+
store: deps.alertRuleStore,
|
|
10
|
+
audit: deps.audit,
|
|
11
|
+
maxBody: deps.maxBody,
|
|
12
|
+
allowLoopbackWebhooks: deps.allowLoopbackWebhooks,
|
|
13
|
+
...(deps.clock !== undefined ? { clock: deps.clock } : {}),
|
|
14
|
+
};
|
|
15
|
+
const collectionRef = parseTenantAlertsPath(url.pathname);
|
|
16
|
+
if (collectionRef !== undefined && (req.method === 'GET' || req.method === 'POST')) {
|
|
17
|
+
applySecurityHeaders(res, tls);
|
|
18
|
+
if (enforceHttps(req, res, tls))
|
|
19
|
+
return true;
|
|
20
|
+
handleAlertRules(req, res, collectionRef, routeDeps).catch(() => {
|
|
21
|
+
if (!res.headersSent)
|
|
22
|
+
sendJson(res, 500, { error: 'internal error' });
|
|
23
|
+
});
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
const testRef = parseTenantAlertTestPath(url.pathname);
|
|
27
|
+
if (testRef !== undefined && req.method === 'POST') {
|
|
28
|
+
applySecurityHeaders(res, tls);
|
|
29
|
+
if (enforceHttps(req, res, tls))
|
|
30
|
+
return true;
|
|
31
|
+
handleAlertRuleTest(req, res, testRef.ref, testRef.id, routeDeps).catch(() => {
|
|
32
|
+
if (!res.headersSent)
|
|
33
|
+
sendJson(res, 500, { error: 'internal error' });
|
|
34
|
+
});
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
const itemRef = parseTenantAlertItemPath(url.pathname);
|
|
38
|
+
if (itemRef !== undefined && req.method === 'DELETE') {
|
|
39
|
+
applySecurityHeaders(res, tls);
|
|
40
|
+
if (enforceHttps(req, res, tls))
|
|
41
|
+
return true;
|
|
42
|
+
handleAlertRuleDelete(req, res, itemRef.ref, itemRef.id, routeDeps).catch(() => {
|
|
43
|
+
if (!res.headersSent)
|
|
44
|
+
sendJson(res, 500, { error: 'internal error' });
|
|
45
|
+
});
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=alerts-dispatch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alerts-dispatch.js","sourceRoot":"","sources":["../../src/routes/alerts-dispatch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
import type { DeployAuthGate } from '../auth/deploy-gate.js';
|
|
3
|
+
import { type AlertRuleStore } from '../store/alert-rules.js';
|
|
4
|
+
import type { AuditSink } from '../store/audit.js';
|
|
5
|
+
import type { ControlPlaneStore, TenantRef } from '../store.js';
|
|
6
|
+
/**
|
|
7
|
+
* Analytics alerting routes (E2, ADR 0130): `GET`/`POST .../alerts`, `DELETE .../alerts/{id}`,
|
|
8
|
+
* and `POST .../alerts/{id}/test`. Reads are org-MEMBER gated (`authorizeTenantControl`, like the
|
|
9
|
+
* neighbouring analytics reads); mutations and test-fires are org-OWNER gated (`canManageMembers`,
|
|
10
|
+
* like the GHD-1 connection writes) and emit audit events with scalar details only.
|
|
11
|
+
*
|
|
12
|
+
* The webhook URL enters once through `POST` (validated by `validateAlertWebhookUrl`) and never
|
|
13
|
+
* leaves again: responses serialize rules through {@link publicAlertRule} and the strict Zod
|
|
14
|
+
* contract has no field that could carry it.
|
|
15
|
+
*/
|
|
16
|
+
export interface AlertRouteDeps {
|
|
17
|
+
readonly gate: DeployAuthGate;
|
|
18
|
+
readonly controlPlane: ControlPlaneStore;
|
|
19
|
+
readonly store: AlertRuleStore;
|
|
20
|
+
readonly audit: AuditSink;
|
|
21
|
+
readonly maxBody: number;
|
|
22
|
+
/** Dev/test-only loopback webhook carve-out (`alertWebhookAllowLoopback`). */
|
|
23
|
+
readonly allowLoopbackWebhooks: boolean;
|
|
24
|
+
/** Injectable clock for deterministic test-fire timestamps. */
|
|
25
|
+
readonly clock?: () => Date;
|
|
26
|
+
}
|
|
27
|
+
/** Redact a webhook URL to its origin — path/query (where tokens live) never leave the service. */
|
|
28
|
+
export declare function redactWebhookUrl(url: string): string;
|
|
29
|
+
/** `GET` (member) / `POST` (owner) on the alert-rule collection. */
|
|
30
|
+
export declare function handleAlertRules(req: IncomingMessage, res: ServerResponse, ref: TenantRef, deps: AlertRouteDeps): Promise<void>;
|
|
31
|
+
/** `DELETE .../alerts/{id}` — org OWNER only; 404 when the rule is not in this tenant scope. */
|
|
32
|
+
export declare function handleAlertRuleDelete(req: IncomingMessage, res: ServerResponse, ref: TenantRef, id: string, deps: AlertRouteDeps): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* `POST .../alerts/{id}/test` — org OWNER only: sends a synthetic `event: "test"` payload through
|
|
35
|
+
* the exact guarded delivery path a real breach uses. The response carries only the closed-code
|
|
36
|
+
* delivery outcome; a failed delivery is still a 200 (the route worked, the endpoint did not).
|
|
37
|
+
*/
|
|
38
|
+
export declare function handleAlertRuleTest(req: IncomingMessage, res: ServerResponse, ref: TenantRef, id: string, deps: AlertRouteDeps): Promise<void>;
|
|
39
|
+
//# sourceMappingURL=alerts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alerts.d.ts","sourceRoot":"","sources":["../../src/routes/alerts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAMjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE7D,OAAO,EAKL,KAAK,cAAc,EAGpB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAMhE;;;;;;;;;GASG;AAEH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,iBAAiB,CAAC;IACzC,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,8EAA8E;IAC9E,QAAQ,CAAC,qBAAqB,EAAE,OAAO,CAAC;IACxC,+DAA+D;IAC/D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;CAC7B;AAED,mGAAmG;AACnG,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAMpD;AAsBD,oEAAoE;AACpE,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,SAAS,EACd,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,IAAI,CAAC,CAWf;AAmHD,gGAAgG;AAChG,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,SAAS,EACd,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,IAAI,CAAC,CAiBf;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,SAAS,EACd,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,IAAI,CAAC,CA2Bf"}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { buildAlertWebhookPayload, deliverAlertWebhook, validateAlertWebhookUrl, } from '../alert-webhook.js';
|
|
2
|
+
import { readJsonBody, sendForbidden, sendJson } from '../http-util.js';
|
|
3
|
+
import { ALERT_METRICS, ALERT_WINDOWS_MINUTES, MAX_ALERT_RULES_PER_ENV, } from '../store/alert-rules.js';
|
|
4
|
+
import { sendContract } from './apps.js';
|
|
5
|
+
import { AlertRuleResponseSchema, AlertRulesListResponseSchema } from './contracts.js';
|
|
6
|
+
import { authorizeControlPlane, authorizeTenantControl } from './control-plane.js';
|
|
7
|
+
import { canManageMembers } from './org-admin.js';
|
|
8
|
+
/** Redact a webhook URL to its origin — path/query (where tokens live) never leave the service. */
|
|
9
|
+
export function redactWebhookUrl(url) {
|
|
10
|
+
try {
|
|
11
|
+
return `${new URL(url).origin}/…`;
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return '<redacted>';
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/** The redacted public view of a rule; the only shape routes may serialize. */
|
|
18
|
+
function publicAlertRule(record) {
|
|
19
|
+
return {
|
|
20
|
+
id: record.id,
|
|
21
|
+
...(record.name !== undefined ? { name: record.name } : {}),
|
|
22
|
+
metric: record.metric,
|
|
23
|
+
threshold: record.threshold,
|
|
24
|
+
windowMinutes: record.windowMinutes,
|
|
25
|
+
comparison: record.comparison,
|
|
26
|
+
webhook: redactWebhookUrl(record.webhookUrl),
|
|
27
|
+
enabled: record.enabled,
|
|
28
|
+
cooldownMinutes: record.cooldownMinutes,
|
|
29
|
+
breaching: record.breaching,
|
|
30
|
+
...(record.lastObserved !== undefined ? { lastObserved: record.lastObserved } : {}),
|
|
31
|
+
...(record.lastFiredAt !== undefined ? { lastFiredAt: record.lastFiredAt } : {}),
|
|
32
|
+
createdAt: record.createdAt,
|
|
33
|
+
updatedAt: record.updatedAt,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/** `GET` (member) / `POST` (owner) on the alert-rule collection. */
|
|
37
|
+
export async function handleAlertRules(req, res, ref, deps) {
|
|
38
|
+
if (req.method === 'GET') {
|
|
39
|
+
const identity = await authorizeTenantControl(req, res, deps.gate, deps.controlPlane, ref.org);
|
|
40
|
+
if (identity === false)
|
|
41
|
+
return;
|
|
42
|
+
const rules = await deps.store.listAlertRules(ref);
|
|
43
|
+
return sendContract(res, () => AlertRulesListResponseSchema.parse({ ok: true, data: { rules: rules.map(publicAlertRule) } }));
|
|
44
|
+
}
|
|
45
|
+
if (req.method === 'POST')
|
|
46
|
+
return handleCreate(req, res, ref, deps);
|
|
47
|
+
return sendJson(res, 404, { error: 'not found' });
|
|
48
|
+
}
|
|
49
|
+
async function handleCreate(req, res, ref, deps) {
|
|
50
|
+
const identity = await authorizeOwner(req, res, ref, deps);
|
|
51
|
+
if (identity === undefined)
|
|
52
|
+
return;
|
|
53
|
+
const body = await readJsonBody(req, deps.maxBody);
|
|
54
|
+
if (!body.ok)
|
|
55
|
+
return sendJson(res, body.status, { error: body.error });
|
|
56
|
+
const parsed = body.value;
|
|
57
|
+
if (typeof parsed.metric !== 'string' ||
|
|
58
|
+
!ALERT_METRICS.includes(parsed.metric)) {
|
|
59
|
+
return sendJson(res, 400, {
|
|
60
|
+
error: `"metric" must be one of ${ALERT_METRICS.join(', ')}`,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
if (typeof parsed.threshold !== 'number' ||
|
|
64
|
+
!Number.isFinite(parsed.threshold) ||
|
|
65
|
+
parsed.threshold < 0) {
|
|
66
|
+
return sendJson(res, 400, { error: '"threshold" must be a finite number >= 0' });
|
|
67
|
+
}
|
|
68
|
+
if (typeof parsed.windowMinutes !== 'number' ||
|
|
69
|
+
!ALERT_WINDOWS_MINUTES.includes(parsed.windowMinutes)) {
|
|
70
|
+
return sendJson(res, 400, {
|
|
71
|
+
error: `"windowMinutes" must be one of ${ALERT_WINDOWS_MINUTES.join(', ')}`,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
if (parsed.name !== undefined &&
|
|
75
|
+
(typeof parsed.name !== 'string' || parsed.name.length === 0 || parsed.name.length > 100)) {
|
|
76
|
+
return sendJson(res, 400, { error: '"name" must be a string of 1-100 characters' });
|
|
77
|
+
}
|
|
78
|
+
if (parsed.cooldownMinutes !== undefined &&
|
|
79
|
+
(typeof parsed.cooldownMinutes !== 'number' ||
|
|
80
|
+
!Number.isInteger(parsed.cooldownMinutes) ||
|
|
81
|
+
parsed.cooldownMinutes < 1 ||
|
|
82
|
+
parsed.cooldownMinutes > 24 * 60)) {
|
|
83
|
+
return sendJson(res, 400, { error: '"cooldownMinutes" must be an integer from 1 to 1440' });
|
|
84
|
+
}
|
|
85
|
+
if (parsed.enabled !== undefined && typeof parsed.enabled !== 'boolean') {
|
|
86
|
+
return sendJson(res, 400, { error: '"enabled" must be a boolean' });
|
|
87
|
+
}
|
|
88
|
+
if (typeof parsed.webhookUrl !== 'string') {
|
|
89
|
+
return sendJson(res, 400, { error: '"webhookUrl" must be a string' });
|
|
90
|
+
}
|
|
91
|
+
const webhook = validateAlertWebhookUrl(parsed.webhookUrl, {
|
|
92
|
+
allowLoopback: deps.allowLoopbackWebhooks,
|
|
93
|
+
});
|
|
94
|
+
if (!webhook.ok)
|
|
95
|
+
return sendJson(res, 400, { error: webhook.error });
|
|
96
|
+
// Soft abuse cap, checked read-then-write: two concurrent owner creates can overshoot by a
|
|
97
|
+
// request or two, which is acceptable for a bound whose only job is preventing webhook floods —
|
|
98
|
+
// a hard transactional cap is not worth a table lock here (unlike the GHD-1 uniqueness rules).
|
|
99
|
+
const existing = await deps.store.listAlertRules(ref);
|
|
100
|
+
if (existing.length >= MAX_ALERT_RULES_PER_ENV) {
|
|
101
|
+
return sendJson(res, 409, {
|
|
102
|
+
error: `alert rule limit reached (${MAX_ALERT_RULES_PER_ENV} per environment); remove one first`,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
const record = await deps.store.createAlertRule({
|
|
106
|
+
orgSlug: ref.org,
|
|
107
|
+
appSlug: ref.app,
|
|
108
|
+
environment: ref.env,
|
|
109
|
+
...(parsed.name !== undefined ? { name: parsed.name } : {}),
|
|
110
|
+
metric: parsed.metric,
|
|
111
|
+
threshold: parsed.threshold,
|
|
112
|
+
windowMinutes: parsed.windowMinutes,
|
|
113
|
+
webhookUrl: parsed.webhookUrl,
|
|
114
|
+
...(parsed.enabled !== undefined ? { enabled: parsed.enabled } : {}),
|
|
115
|
+
...(parsed.cooldownMinutes !== undefined ? { cooldownMinutes: parsed.cooldownMinutes } : {}),
|
|
116
|
+
createdBySubject: identity.subject,
|
|
117
|
+
});
|
|
118
|
+
// Audit details are scalar-only and NEVER include the webhook URL or its host.
|
|
119
|
+
await deps.audit.emit({
|
|
120
|
+
eventType: 'alert.rule.created',
|
|
121
|
+
org: ref.org,
|
|
122
|
+
app: ref.app,
|
|
123
|
+
env: ref.env,
|
|
124
|
+
decision: 'allow',
|
|
125
|
+
status: 200,
|
|
126
|
+
actorSubject: identity.subject,
|
|
127
|
+
...(identity.email !== undefined ? { actorEmail: identity.email } : {}),
|
|
128
|
+
details: {
|
|
129
|
+
ruleId: record.id,
|
|
130
|
+
metric: record.metric,
|
|
131
|
+
threshold: record.threshold,
|
|
132
|
+
windowMinutes: record.windowMinutes,
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
return sendContract(res, () => AlertRuleResponseSchema.parse({ ok: true, data: publicAlertRule(record) }));
|
|
136
|
+
}
|
|
137
|
+
/** `DELETE .../alerts/{id}` — org OWNER only; 404 when the rule is not in this tenant scope. */
|
|
138
|
+
export async function handleAlertRuleDelete(req, res, ref, id, deps) {
|
|
139
|
+
const identity = await authorizeOwner(req, res, ref, deps);
|
|
140
|
+
if (identity === undefined)
|
|
141
|
+
return;
|
|
142
|
+
const deleted = await deps.store.deleteAlertRule(ref, id);
|
|
143
|
+
if (!deleted)
|
|
144
|
+
return sendJson(res, 404, { error: 'not found' });
|
|
145
|
+
await deps.audit.emit({
|
|
146
|
+
eventType: 'alert.rule.deleted',
|
|
147
|
+
org: ref.org,
|
|
148
|
+
app: ref.app,
|
|
149
|
+
env: ref.env,
|
|
150
|
+
decision: 'allow',
|
|
151
|
+
status: 200,
|
|
152
|
+
actorSubject: identity.subject,
|
|
153
|
+
...(identity.email !== undefined ? { actorEmail: identity.email } : {}),
|
|
154
|
+
details: { ruleId: id },
|
|
155
|
+
});
|
|
156
|
+
return sendJson(res, 200, { ok: true, data: { deleted: true } });
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* `POST .../alerts/{id}/test` — org OWNER only: sends a synthetic `event: "test"` payload through
|
|
160
|
+
* the exact guarded delivery path a real breach uses. The response carries only the closed-code
|
|
161
|
+
* delivery outcome; a failed delivery is still a 200 (the route worked, the endpoint did not).
|
|
162
|
+
*/
|
|
163
|
+
export async function handleAlertRuleTest(req, res, ref, id, deps) {
|
|
164
|
+
const identity = await authorizeOwner(req, res, ref, deps);
|
|
165
|
+
if (identity === undefined)
|
|
166
|
+
return;
|
|
167
|
+
const rule = await deps.store.getAlertRule(ref, id);
|
|
168
|
+
if (rule === undefined)
|
|
169
|
+
return sendJson(res, 404, { error: 'not found' });
|
|
170
|
+
const firedAt = (deps.clock?.() ?? new Date()).toISOString();
|
|
171
|
+
const payload = buildAlertWebhookPayload(rule, 'test', rule.lastObserved ?? 0, firedAt);
|
|
172
|
+
const delivery = await deliverAlertWebhook(rule.webhookUrl, payload, {
|
|
173
|
+
allowLoopback: deps.allowLoopbackWebhooks,
|
|
174
|
+
});
|
|
175
|
+
await deps.audit.emit({
|
|
176
|
+
eventType: 'alert.rule.test_fired',
|
|
177
|
+
org: ref.org,
|
|
178
|
+
app: ref.app,
|
|
179
|
+
env: ref.env,
|
|
180
|
+
decision: 'allow',
|
|
181
|
+
status: 200,
|
|
182
|
+
actorSubject: identity.subject,
|
|
183
|
+
...(identity.email !== undefined ? { actorEmail: identity.email } : {}),
|
|
184
|
+
details: {
|
|
185
|
+
ruleId: rule.id,
|
|
186
|
+
delivered: delivery.delivered,
|
|
187
|
+
...(delivery.status !== undefined ? { httpStatus: delivery.status } : {}),
|
|
188
|
+
...(delivery.reason !== undefined ? { reason: delivery.reason } : {}),
|
|
189
|
+
},
|
|
190
|
+
});
|
|
191
|
+
return sendJson(res, 200, { ok: true, data: { delivery } });
|
|
192
|
+
}
|
|
193
|
+
/** Owner gate shared by every alert mutation (mirrors the GHD-1 write posture). */
|
|
194
|
+
async function authorizeOwner(req, res, ref, deps) {
|
|
195
|
+
const identity = await authorizeControlPlane(req, res, deps.gate, { requireIdentity: true });
|
|
196
|
+
if (identity === false)
|
|
197
|
+
return undefined;
|
|
198
|
+
if (!(await canManageMembers(deps.controlPlane, ref.org, identity))) {
|
|
199
|
+
sendForbidden(res, 'forbidden');
|
|
200
|
+
return undefined;
|
|
201
|
+
}
|
|
202
|
+
return identity;
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=alerts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alerts.js","sourceRoot":"","sources":["../../src/routes/alerts.ts"],"names":[],"mappings":"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"}
|
|
@@ -305,6 +305,76 @@ export declare const GithubConnectionResponseSchema: z.ZodObject<{
|
|
|
305
305
|
updatedAt: z.ZodString;
|
|
306
306
|
}, z.core.$strict>;
|
|
307
307
|
}, z.core.$strict>;
|
|
308
|
+
/** One webhook-accepted deploy run (GHD-2) — mirrors `DeployRunRecord` in `../store.ts`. */
|
|
309
|
+
export declare const DeployRunSchema: z.ZodObject<{
|
|
310
|
+
runId: z.ZodString;
|
|
311
|
+
orgSlug: z.ZodString;
|
|
312
|
+
appSlug: z.ZodString;
|
|
313
|
+
envName: z.ZodString;
|
|
314
|
+
sourceEvent: z.ZodEnum<{
|
|
315
|
+
push: "push";
|
|
316
|
+
pull_request: "pull_request";
|
|
317
|
+
}>;
|
|
318
|
+
deliveryId: z.ZodString;
|
|
319
|
+
githubRepositoryId: z.ZodNumber;
|
|
320
|
+
commitSha: z.ZodString;
|
|
321
|
+
ref: z.ZodString;
|
|
322
|
+
prNumber: z.ZodOptional<z.ZodNumber>;
|
|
323
|
+
status: z.ZodEnum<{
|
|
324
|
+
queued: "queued";
|
|
325
|
+
building: "building";
|
|
326
|
+
deploying: "deploying";
|
|
327
|
+
deployed: "deployed";
|
|
328
|
+
failed: "failed";
|
|
329
|
+
canceled: "canceled";
|
|
330
|
+
superseded: "superseded";
|
|
331
|
+
}>;
|
|
332
|
+
blockedReason: z.ZodOptional<z.ZodString>;
|
|
333
|
+
deploymentId: z.ZodOptional<z.ZodString>;
|
|
334
|
+
actorLogin: z.ZodString;
|
|
335
|
+
errorSummary: z.ZodOptional<z.ZodString>;
|
|
336
|
+
createdAt: z.ZodString;
|
|
337
|
+
startedAt: z.ZodOptional<z.ZodString>;
|
|
338
|
+
finishedAt: z.ZodOptional<z.ZodString>;
|
|
339
|
+
}, z.core.$strict>;
|
|
340
|
+
/** The full `GET /v1/orgs/{org}/apps/{app}/github/runs` response body. */
|
|
341
|
+
export declare const GithubRunsListResponseSchema: z.ZodObject<{
|
|
342
|
+
ok: z.ZodLiteral<true>;
|
|
343
|
+
data: z.ZodObject<{
|
|
344
|
+
runs: z.ZodArray<z.ZodObject<{
|
|
345
|
+
runId: z.ZodString;
|
|
346
|
+
orgSlug: z.ZodString;
|
|
347
|
+
appSlug: z.ZodString;
|
|
348
|
+
envName: z.ZodString;
|
|
349
|
+
sourceEvent: z.ZodEnum<{
|
|
350
|
+
push: "push";
|
|
351
|
+
pull_request: "pull_request";
|
|
352
|
+
}>;
|
|
353
|
+
deliveryId: z.ZodString;
|
|
354
|
+
githubRepositoryId: z.ZodNumber;
|
|
355
|
+
commitSha: z.ZodString;
|
|
356
|
+
ref: z.ZodString;
|
|
357
|
+
prNumber: z.ZodOptional<z.ZodNumber>;
|
|
358
|
+
status: z.ZodEnum<{
|
|
359
|
+
queued: "queued";
|
|
360
|
+
building: "building";
|
|
361
|
+
deploying: "deploying";
|
|
362
|
+
deployed: "deployed";
|
|
363
|
+
failed: "failed";
|
|
364
|
+
canceled: "canceled";
|
|
365
|
+
superseded: "superseded";
|
|
366
|
+
}>;
|
|
367
|
+
blockedReason: z.ZodOptional<z.ZodString>;
|
|
368
|
+
deploymentId: z.ZodOptional<z.ZodString>;
|
|
369
|
+
actorLogin: z.ZodString;
|
|
370
|
+
errorSummary: z.ZodOptional<z.ZodString>;
|
|
371
|
+
createdAt: z.ZodString;
|
|
372
|
+
startedAt: z.ZodOptional<z.ZodString>;
|
|
373
|
+
finishedAt: z.ZodOptional<z.ZodString>;
|
|
374
|
+
}, z.core.$strict>>;
|
|
375
|
+
truncated: z.ZodBoolean;
|
|
376
|
+
}, z.core.$strict>;
|
|
377
|
+
}, z.core.$strict>;
|
|
308
378
|
/** The full `GET /v1/github/install-url` response body. */
|
|
309
379
|
export declare const GithubInstallUrlResponseSchema: z.ZodObject<{
|
|
310
380
|
ok: z.ZodLiteral<true>;
|
|
@@ -313,4 +383,83 @@ export declare const GithubInstallUrlResponseSchema: z.ZodObject<{
|
|
|
313
383
|
state: z.ZodString;
|
|
314
384
|
}, z.core.$strict>;
|
|
315
385
|
}, z.core.$strict>;
|
|
386
|
+
/**
|
|
387
|
+
* The redacted public view of an alert rule (analytics alerting E2, ADR 0130). Deliberately has
|
|
388
|
+
* NO `webhookUrl` field and is `.strict()`: the sensitive URL structurally cannot pass this
|
|
389
|
+
* contract, so a would-be leak fails the parse (a 500) instead of reaching the wire. `webhook`
|
|
390
|
+
* carries only the redacted origin form (e.g. `https://hooks.example.com/…`).
|
|
391
|
+
*/
|
|
392
|
+
export declare const AlertRuleSchema: z.ZodObject<{
|
|
393
|
+
id: z.ZodString;
|
|
394
|
+
name: z.ZodOptional<z.ZodString>;
|
|
395
|
+
metric: z.ZodEnum<{
|
|
396
|
+
error_share: "error_share";
|
|
397
|
+
error_count: "error_count";
|
|
398
|
+
calls: "calls";
|
|
399
|
+
p95_ms: "p95_ms";
|
|
400
|
+
}>;
|
|
401
|
+
threshold: z.ZodNumber;
|
|
402
|
+
windowMinutes: z.ZodNumber;
|
|
403
|
+
comparison: z.ZodLiteral<">=">;
|
|
404
|
+
webhook: z.ZodString;
|
|
405
|
+
enabled: z.ZodBoolean;
|
|
406
|
+
cooldownMinutes: z.ZodNumber;
|
|
407
|
+
breaching: z.ZodBoolean;
|
|
408
|
+
lastObserved: z.ZodOptional<z.ZodNumber>;
|
|
409
|
+
lastFiredAt: z.ZodOptional<z.ZodString>;
|
|
410
|
+
createdAt: z.ZodString;
|
|
411
|
+
updatedAt: z.ZodString;
|
|
412
|
+
}, z.core.$strict>;
|
|
413
|
+
/** The full `POST /v1/orgs/{org}/apps/{app}/envs/{env}/alerts` response body. */
|
|
414
|
+
export declare const AlertRuleResponseSchema: z.ZodObject<{
|
|
415
|
+
ok: z.ZodLiteral<true>;
|
|
416
|
+
data: z.ZodObject<{
|
|
417
|
+
id: z.ZodString;
|
|
418
|
+
name: z.ZodOptional<z.ZodString>;
|
|
419
|
+
metric: z.ZodEnum<{
|
|
420
|
+
error_share: "error_share";
|
|
421
|
+
error_count: "error_count";
|
|
422
|
+
calls: "calls";
|
|
423
|
+
p95_ms: "p95_ms";
|
|
424
|
+
}>;
|
|
425
|
+
threshold: z.ZodNumber;
|
|
426
|
+
windowMinutes: z.ZodNumber;
|
|
427
|
+
comparison: z.ZodLiteral<">=">;
|
|
428
|
+
webhook: z.ZodString;
|
|
429
|
+
enabled: z.ZodBoolean;
|
|
430
|
+
cooldownMinutes: z.ZodNumber;
|
|
431
|
+
breaching: z.ZodBoolean;
|
|
432
|
+
lastObserved: z.ZodOptional<z.ZodNumber>;
|
|
433
|
+
lastFiredAt: z.ZodOptional<z.ZodString>;
|
|
434
|
+
createdAt: z.ZodString;
|
|
435
|
+
updatedAt: z.ZodString;
|
|
436
|
+
}, z.core.$strict>;
|
|
437
|
+
}, z.core.$strict>;
|
|
438
|
+
/** The full `GET /v1/orgs/{org}/apps/{app}/envs/{env}/alerts` response body. */
|
|
439
|
+
export declare const AlertRulesListResponseSchema: z.ZodObject<{
|
|
440
|
+
ok: z.ZodLiteral<true>;
|
|
441
|
+
data: z.ZodObject<{
|
|
442
|
+
rules: z.ZodArray<z.ZodObject<{
|
|
443
|
+
id: z.ZodString;
|
|
444
|
+
name: z.ZodOptional<z.ZodString>;
|
|
445
|
+
metric: z.ZodEnum<{
|
|
446
|
+
error_share: "error_share";
|
|
447
|
+
error_count: "error_count";
|
|
448
|
+
calls: "calls";
|
|
449
|
+
p95_ms: "p95_ms";
|
|
450
|
+
}>;
|
|
451
|
+
threshold: z.ZodNumber;
|
|
452
|
+
windowMinutes: z.ZodNumber;
|
|
453
|
+
comparison: z.ZodLiteral<">=">;
|
|
454
|
+
webhook: z.ZodString;
|
|
455
|
+
enabled: z.ZodBoolean;
|
|
456
|
+
cooldownMinutes: z.ZodNumber;
|
|
457
|
+
breaching: z.ZodBoolean;
|
|
458
|
+
lastObserved: z.ZodOptional<z.ZodNumber>;
|
|
459
|
+
lastFiredAt: z.ZodOptional<z.ZodString>;
|
|
460
|
+
createdAt: z.ZodString;
|
|
461
|
+
updatedAt: z.ZodString;
|
|
462
|
+
}, z.core.$strict>>;
|
|
463
|
+
}, z.core.$strict>;
|
|
464
|
+
}, z.core.$strict>;
|
|
316
465
|
//# sourceMappingURL=contracts.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../../src/routes/contracts.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAWxB,yDAAyD;AACzD,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;kBAezB,CAAC;AAEZ,4FAA4F;AAC5F,eAAO,MAAM,gBAAgB;;;;kBAMlB,CAAC;AAEZ,kDAAkD;AAClD,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAYlB,CAAC;AAEZ,wDAAwD;AACxD,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAUxB,CAAC;AAEZ,4EAA4E;AAC5E,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAKnB,CAAC;AAEZ,kDAAkD;AAClD,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAalB,CAAC;AAEZ,iHAAiH;AACjH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBASxB,CAAC;AAEZ,uFAAuF;AACvF,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAKnB,CAAC;AAEZ,mGAAmG;AACnG,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;kBAK1B,CAAC;AAEZ,qGAAqG;AACrG,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;kBAetB,CAAC;AAEZ,uFAAuF;AACvF,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;;kBAKhC,CAAC;AAEZ,2DAA2D;AAC3D,eAAO,MAAM,8BAA8B;;;;;;kBAUhC,CAAC"}
|
|
1
|
+
{"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../../src/routes/contracts.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAWxB,yDAAyD;AACzD,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;kBAezB,CAAC;AAEZ,4FAA4F;AAC5F,eAAO,MAAM,gBAAgB;;;;kBAMlB,CAAC;AAEZ,kDAAkD;AAClD,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAYlB,CAAC;AAEZ,wDAAwD;AACxD,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAUxB,CAAC;AAEZ,4EAA4E;AAC5E,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAKnB,CAAC;AAEZ,kDAAkD;AAClD,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAalB,CAAC;AAEZ,iHAAiH;AACjH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBASxB,CAAC;AAEZ,uFAAuF;AACvF,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAKnB,CAAC;AAEZ,mGAAmG;AACnG,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;kBAK1B,CAAC;AAEZ,qGAAqG;AACrG,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;kBAetB,CAAC;AAEZ,uFAAuF;AACvF,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;;kBAKhC,CAAC;AAEZ,4FAA4F;AAC5F,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA6BjB,CAAC;AAEZ,0EAA0E;AAC1E,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAU9B,CAAC;AAEZ,2DAA2D;AAC3D,eAAO,MAAM,8BAA8B;;;;;;kBAUhC,CAAC;AAEZ;;;;;GAKG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;kBAiBjB,CAAC;AAEZ,iFAAiF;AACjF,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;kBAKzB,CAAC;AAEZ,gFAAgF;AAChF,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;kBAK9B,CAAC"}
|