@belvador/api 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -0
- package/dist/cli.js +119 -0
- package/dist/client.d.ts +1 -1
- package/dist/client.js +1 -1
- package/dist/operations.gen.d.ts +214 -4
- package/dist/operations.gen.js +99 -1
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -56,4 +56,17 @@ try {
|
|
|
56
56
|
`edge.belvador.dev` directly, so the data never passes the API gateway; it falls back to the gateway
|
|
57
57
|
when the token may not hold a ticket.
|
|
58
58
|
|
|
59
|
+
## Command line
|
|
60
|
+
|
|
61
|
+
`belvador-api privacy pull` writes a project's privacy policy as the JSON the Belvador SDKs accept
|
|
62
|
+
(`privacyPolicy()`, SDK 0.6.0+), so a build can ship the same rules your node applies:
|
|
63
|
+
|
|
64
|
+
```sh
|
|
65
|
+
BELVADOR_TOKEN=blv_svc_… npx -p @belvador/api belvador-api privacy pull --project 42 --out belvador-privacy.json
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`--project` is the project's number (the end of its DSN). The token needs `projects:read`; it is read
|
|
69
|
+
only from `BELVADOR_TOKEN` and never printed. Exit codes: 0 written, 1 refused by the API (the code is
|
|
70
|
+
printed), 2 wrong usage.
|
|
71
|
+
|
|
59
72
|
Node ≥ 20.10, Bun, Deno and modern browsers (any runtime with `fetch` and `AbortSignal.any`). MIT licensed.
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// packages/api/bin/belvador-api.ts
|
|
4
|
+
import { writeFileSync } from "node:fs";
|
|
5
|
+
|
|
6
|
+
// packages/api/bin/run.ts
|
|
7
|
+
import { BelvadorApiError, createClient, TOKEN_PATTERN } from "@belvador/api";
|
|
8
|
+
var USAGE = `Usage: belvador-api privacy pull --project <numeric project id> [--out <file>] [--base-url <url>]
|
|
9
|
+
|
|
10
|
+
privacy pull Write the project's privacy policy as JSON (for init({ privacyPolicy })).
|
|
11
|
+
Reads BELVADOR_TOKEN: a token that can read the project (scope projects:read).
|
|
12
|
+
--out <file> Write to a file instead of stdout.
|
|
13
|
+
`;
|
|
14
|
+
function isPolicy(v) {
|
|
15
|
+
if (!v || typeof v !== "object")
|
|
16
|
+
return false;
|
|
17
|
+
const p = v;
|
|
18
|
+
return typeof p.schema === "number" && typeof p.version === "number" && typeof p.mode === "string" && Array.isArray(p.rules) && Array.isArray(p.allowlist);
|
|
19
|
+
}
|
|
20
|
+
function flags(args) {
|
|
21
|
+
const out = new Map;
|
|
22
|
+
for (let i = 0;i < args.length; i++) {
|
|
23
|
+
const a = args[i];
|
|
24
|
+
if (!a.startsWith("--"))
|
|
25
|
+
return `unexpected argument ${a}`;
|
|
26
|
+
const eq = a.indexOf("=");
|
|
27
|
+
const name = eq > 0 ? a.slice(2, eq) : a.slice(2);
|
|
28
|
+
const value = eq > 0 ? a.slice(eq + 1) : args[++i];
|
|
29
|
+
if (!["project", "out", "base-url"].includes(name))
|
|
30
|
+
return `unknown option --${name}`;
|
|
31
|
+
if (value === undefined || value === "" || value.startsWith("--"))
|
|
32
|
+
return `--${name} needs a value`;
|
|
33
|
+
out.set(name, value);
|
|
34
|
+
}
|
|
35
|
+
return out;
|
|
36
|
+
}
|
|
37
|
+
async function run(argv, deps) {
|
|
38
|
+
const [group, command, ...rest] = argv;
|
|
39
|
+
if (group === "--help" || group === "-h" || group === "help") {
|
|
40
|
+
deps.stdout(USAGE);
|
|
41
|
+
return 0;
|
|
42
|
+
}
|
|
43
|
+
if (group !== "privacy" || command !== "pull") {
|
|
44
|
+
deps.stderr(USAGE);
|
|
45
|
+
return 2;
|
|
46
|
+
}
|
|
47
|
+
const opts = flags(rest);
|
|
48
|
+
if (typeof opts === "string") {
|
|
49
|
+
deps.stderr(`belvador-api: ${opts}
|
|
50
|
+
|
|
51
|
+
${USAGE}`);
|
|
52
|
+
return 2;
|
|
53
|
+
}
|
|
54
|
+
const raw = opts.get("project");
|
|
55
|
+
if (!raw) {
|
|
56
|
+
deps.stderr(`belvador-api: --project is required
|
|
57
|
+
|
|
58
|
+
${USAGE}`);
|
|
59
|
+
return 2;
|
|
60
|
+
}
|
|
61
|
+
if (!/^[1-9][0-9]{0,15}$/.test(raw)) {
|
|
62
|
+
deps.stderr(`belvador-api: --project is the project's numeric id (the number at the end of the project DSN, or GET /v1/projects)
|
|
63
|
+
`);
|
|
64
|
+
return 2;
|
|
65
|
+
}
|
|
66
|
+
const project = Number(raw);
|
|
67
|
+
const token = deps.env["BELVADOR_TOKEN"]?.trim();
|
|
68
|
+
if (!token) {
|
|
69
|
+
deps.stderr(`belvador-api: BELVADOR_TOKEN is not set
|
|
70
|
+
`);
|
|
71
|
+
return 2;
|
|
72
|
+
}
|
|
73
|
+
if (!TOKEN_PATTERN.test(token)) {
|
|
74
|
+
deps.stderr(`belvador-api: BELVADOR_TOKEN is not a Belvador token (blv_pat_, blv_svc_ or blv_oat_)
|
|
75
|
+
`);
|
|
76
|
+
return 2;
|
|
77
|
+
}
|
|
78
|
+
let policy;
|
|
79
|
+
try {
|
|
80
|
+
const baseUrl = opts.get("base-url");
|
|
81
|
+
const client = (deps.client ?? createClient)({ token, ...baseUrl ? { baseUrl } : {}, userAgent: "belvador-api-cli" });
|
|
82
|
+
const res = await client.call("privacy.get", { project_id: project });
|
|
83
|
+
policy = res.data?.policy;
|
|
84
|
+
} catch (e) {
|
|
85
|
+
if (e instanceof BelvadorApiError) {
|
|
86
|
+
const hint = e.code === "API_SCOPE_INSUFFICIENT" && e.scope ? ` (needs ${e.scope})` : "";
|
|
87
|
+
deps.stderr(`belvador-api: ${e.code}${hint}${e.requestId ? ` · request ${e.requestId}` : ""}
|
|
88
|
+
`);
|
|
89
|
+
return 1;
|
|
90
|
+
}
|
|
91
|
+
deps.stderr(`belvador-api: ${e instanceof TypeError ? e.message : "request failed"}
|
|
92
|
+
`);
|
|
93
|
+
return 1;
|
|
94
|
+
}
|
|
95
|
+
if (!isPolicy(policy)) {
|
|
96
|
+
deps.stderr(`belvador-api: the API answered without a privacy policy
|
|
97
|
+
`);
|
|
98
|
+
return 1;
|
|
99
|
+
}
|
|
100
|
+
const text = `${JSON.stringify({ schema: policy.schema, version: policy.version, mode: policy.mode, rules: policy.rules, allowlist: policy.allowlist }, null, 2)}
|
|
101
|
+
`;
|
|
102
|
+
const out = opts.get("out");
|
|
103
|
+
if (out) {
|
|
104
|
+
deps.writeFile(out, text);
|
|
105
|
+
deps.stderr(`belvador-api: wrote privacy policy v${policy.version} (${policy.rules.length} rules) to ${out}
|
|
106
|
+
`);
|
|
107
|
+
} else {
|
|
108
|
+
deps.stdout(text);
|
|
109
|
+
}
|
|
110
|
+
return 0;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// packages/api/bin/belvador-api.ts
|
|
114
|
+
process.exitCode = await run(process.argv.slice(2), {
|
|
115
|
+
env: process.env,
|
|
116
|
+
stdout: (t) => process.stdout.write(t),
|
|
117
|
+
stderr: (t) => process.stderr.write(t),
|
|
118
|
+
writeFile: (path, text) => writeFileSync(path, text, { mode: 420 })
|
|
119
|
+
});
|
package/dist/client.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { OPERATIONS, type OperationId, type OperationMeta, type OperationParams } from "./operations.gen.js";
|
|
2
|
-
export declare const CLIENT_VERSION = "0.
|
|
2
|
+
export declare const CLIENT_VERSION = "0.5.0";
|
|
3
3
|
export declare const DEFAULT_BASE_URL = "https://api.belvador.dev";
|
|
4
4
|
/** Personal (`blv_pat_`), service (`blv_svc_`) or OAuth access (`blv_oat_`) token. */
|
|
5
5
|
export declare const TOKEN_PATTERN: RegExp;
|
package/dist/client.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BelvadorApiError, errorFrom } from "./errors.js";
|
|
2
2
|
import { nodeErrorWord, nodeReadRequest, nodeRefusal, nodeWindowMissing, NODE_REFUSAL_STATUS, reshapeNodeAnswer, } from "./node-wire.gen.js";
|
|
3
3
|
import { OPERATIONS } from "./operations.gen.js";
|
|
4
|
-
export const CLIENT_VERSION = "0.
|
|
4
|
+
export const CLIENT_VERSION = "0.5.0";
|
|
5
5
|
export const DEFAULT_BASE_URL = "https://api.belvador.dev";
|
|
6
6
|
/** Personal (`blv_pat_`), service (`blv_svc_`) or OAuth access (`blv_oat_`) token. */
|
|
7
7
|
export const TOKEN_PATTERN = /^blv_(pat|svc|oat)_[A-Za-z0-9_-]{20,200}$/;
|
package/dist/operations.gen.d.ts
CHANGED
|
@@ -138,6 +138,34 @@ export declare const OPERATIONS: {
|
|
|
138
138
|
readonly node: null;
|
|
139
139
|
readonly defaults: {};
|
|
140
140
|
};
|
|
141
|
+
readonly "coverage.get": {
|
|
142
|
+
readonly method: "GET";
|
|
143
|
+
readonly path: "/v1/coverage";
|
|
144
|
+
readonly pathParams: readonly [];
|
|
145
|
+
readonly scope: "coverage:read";
|
|
146
|
+
readonly kind: "read";
|
|
147
|
+
readonly sensitivity: "normal";
|
|
148
|
+
readonly idempotency: "none";
|
|
149
|
+
readonly ifMatch: false;
|
|
150
|
+
readonly paged: false;
|
|
151
|
+
readonly status: 200;
|
|
152
|
+
readonly node: null;
|
|
153
|
+
readonly defaults: {};
|
|
154
|
+
};
|
|
155
|
+
readonly "coverage.set": {
|
|
156
|
+
readonly method: "PUT";
|
|
157
|
+
readonly path: "/v1/projects/{project_id}/coverage-expectations";
|
|
158
|
+
readonly pathParams: readonly ["project_id"];
|
|
159
|
+
readonly scope: "coverage:write";
|
|
160
|
+
readonly kind: "write";
|
|
161
|
+
readonly sensitivity: "normal";
|
|
162
|
+
readonly idempotency: "optional";
|
|
163
|
+
readonly ifMatch: false;
|
|
164
|
+
readonly paged: false;
|
|
165
|
+
readonly status: 200;
|
|
166
|
+
readonly node: null;
|
|
167
|
+
readonly defaults: {};
|
|
168
|
+
};
|
|
141
169
|
readonly "destinations.create": {
|
|
142
170
|
readonly method: "POST";
|
|
143
171
|
readonly path: "/v1/destinations";
|
|
@@ -744,6 +772,56 @@ export declare const OPERATIONS: {
|
|
|
744
772
|
readonly node: null;
|
|
745
773
|
readonly defaults: {};
|
|
746
774
|
};
|
|
775
|
+
readonly "metrics.names": {
|
|
776
|
+
readonly method: "GET";
|
|
777
|
+
readonly path: "/v1/metrics/names";
|
|
778
|
+
readonly pathParams: readonly [];
|
|
779
|
+
readonly scope: "metrics:read";
|
|
780
|
+
readonly kind: "node";
|
|
781
|
+
readonly sensitivity: "normal";
|
|
782
|
+
readonly idempotency: "none";
|
|
783
|
+
readonly ifMatch: false;
|
|
784
|
+
readonly paged: false;
|
|
785
|
+
readonly status: 200;
|
|
786
|
+
readonly node: {
|
|
787
|
+
readonly path: "q/metrics/names";
|
|
788
|
+
};
|
|
789
|
+
readonly defaults: {};
|
|
790
|
+
};
|
|
791
|
+
readonly "metrics.query": {
|
|
792
|
+
readonly method: "GET";
|
|
793
|
+
readonly path: "/v1/metrics/query";
|
|
794
|
+
readonly pathParams: readonly [];
|
|
795
|
+
readonly scope: "metrics:read";
|
|
796
|
+
readonly kind: "node";
|
|
797
|
+
readonly sensitivity: "normal";
|
|
798
|
+
readonly idempotency: "none";
|
|
799
|
+
readonly ifMatch: false;
|
|
800
|
+
readonly paged: false;
|
|
801
|
+
readonly status: 200;
|
|
802
|
+
readonly node: {
|
|
803
|
+
readonly path: "q/metrics/query";
|
|
804
|
+
readonly window: true;
|
|
805
|
+
};
|
|
806
|
+
readonly defaults: {};
|
|
807
|
+
};
|
|
808
|
+
readonly "metrics.series": {
|
|
809
|
+
readonly method: "GET";
|
|
810
|
+
readonly path: "/v1/metrics/series";
|
|
811
|
+
readonly pathParams: readonly [];
|
|
812
|
+
readonly scope: "metrics:read";
|
|
813
|
+
readonly kind: "node";
|
|
814
|
+
readonly sensitivity: "normal";
|
|
815
|
+
readonly idempotency: "none";
|
|
816
|
+
readonly ifMatch: false;
|
|
817
|
+
readonly paged: true;
|
|
818
|
+
readonly status: 200;
|
|
819
|
+
readonly node: {
|
|
820
|
+
readonly path: "q/metrics/series";
|
|
821
|
+
readonly list: "series";
|
|
822
|
+
};
|
|
823
|
+
readonly defaults: {};
|
|
824
|
+
};
|
|
747
825
|
readonly "monitors.backtest": {
|
|
748
826
|
readonly method: "POST";
|
|
749
827
|
readonly path: "/v1/monitors/backtest";
|
|
@@ -1175,6 +1253,34 @@ export declare const OPERATIONS: {
|
|
|
1175
1253
|
readonly node: null;
|
|
1176
1254
|
readonly defaults: {};
|
|
1177
1255
|
};
|
|
1256
|
+
readonly "privacy.get": {
|
|
1257
|
+
readonly method: "GET";
|
|
1258
|
+
readonly path: "/v1/projects/{project_id}/privacy";
|
|
1259
|
+
readonly pathParams: readonly ["project_id"];
|
|
1260
|
+
readonly scope: "projects:read";
|
|
1261
|
+
readonly kind: "read";
|
|
1262
|
+
readonly sensitivity: "normal";
|
|
1263
|
+
readonly idempotency: "none";
|
|
1264
|
+
readonly ifMatch: false;
|
|
1265
|
+
readonly paged: false;
|
|
1266
|
+
readonly status: 200;
|
|
1267
|
+
readonly node: null;
|
|
1268
|
+
readonly defaults: {};
|
|
1269
|
+
};
|
|
1270
|
+
readonly "privacy.set": {
|
|
1271
|
+
readonly method: "PUT";
|
|
1272
|
+
readonly path: "/v1/projects/{project_id}/privacy";
|
|
1273
|
+
readonly pathParams: readonly ["project_id"];
|
|
1274
|
+
readonly scope: "privacy:write";
|
|
1275
|
+
readonly kind: "write";
|
|
1276
|
+
readonly sensitivity: "approval";
|
|
1277
|
+
readonly idempotency: "optional";
|
|
1278
|
+
readonly ifMatch: false;
|
|
1279
|
+
readonly paged: false;
|
|
1280
|
+
readonly status: 200;
|
|
1281
|
+
readonly node: null;
|
|
1282
|
+
readonly defaults: {};
|
|
1283
|
+
};
|
|
1178
1284
|
readonly "project_keys.create": {
|
|
1179
1285
|
readonly method: "POST";
|
|
1180
1286
|
readonly path: "/v1/projects/{project_id}/keys";
|
|
@@ -1335,7 +1441,7 @@ export declare const OPERATIONS: {
|
|
|
1335
1441
|
readonly pathParams: readonly ["project_id", "group"];
|
|
1336
1442
|
readonly scope: "privacy:write";
|
|
1337
1443
|
readonly kind: "write";
|
|
1338
|
-
readonly sensitivity: "
|
|
1444
|
+
readonly sensitivity: "approval";
|
|
1339
1445
|
readonly idempotency: "none";
|
|
1340
1446
|
readonly ifMatch: false;
|
|
1341
1447
|
readonly paged: false;
|
|
@@ -1864,7 +1970,7 @@ export interface OperationParams {
|
|
|
1864
1970
|
is_enabled: boolean;
|
|
1865
1971
|
notify_all: boolean;
|
|
1866
1972
|
destination_ids: Array<string>;
|
|
1867
|
-
monitor_kinds?: Array<"missed" | "failed" | "timeout" | "unknown" | "count" | "assertion" | "deadline" | "stalled">;
|
|
1973
|
+
monitor_kinds?: Array<"missed" | "failed" | "timeout" | "unknown" | "count" | "assertion" | "deadline" | "stalled" | "metric">;
|
|
1868
1974
|
slo_severities?: Array<"page" | "ticket">;
|
|
1869
1975
|
policy_id?: string | null;
|
|
1870
1976
|
};
|
|
@@ -1889,6 +1995,23 @@ export interface OperationParams {
|
|
|
1889
1995
|
limit?: number;
|
|
1890
1996
|
cursor?: string;
|
|
1891
1997
|
};
|
|
1998
|
+
/** What each app is expected to send (surface × signal × environment) against what Belvador saw: `verified`, `stale`, `problem` or `unknown`, the verified rate, and signals seen but not declared. Same numbers as the Coverage page. */
|
|
1999
|
+
"coverage.get": {
|
|
2000
|
+
project_id?: number;
|
|
2001
|
+
environment?: string;
|
|
2002
|
+
};
|
|
2003
|
+
/** Replace a project's coverage expectations (one per environment × surface). `config_source: code` locks them in the app; send `ui` once to hand them back. Members and up. */
|
|
2004
|
+
"coverage.set": {
|
|
2005
|
+
project_id: number;
|
|
2006
|
+
config_source?: "ui" | "code";
|
|
2007
|
+
expectations: Array<{
|
|
2008
|
+
environment: string;
|
|
2009
|
+
surface: "browser" | "server" | "worker" | "job" | "edge_function" | "database" | "uptime";
|
|
2010
|
+
signals: Array<"errors" | "traces" | "logs" | "metrics" | "check_ins" | "web_vitals" | "probes">;
|
|
2011
|
+
stale_after_hours?: number;
|
|
2012
|
+
note?: string;
|
|
2013
|
+
}>;
|
|
2014
|
+
};
|
|
1892
2015
|
/** Start adding a Telegram, Slack, email, webhook, PagerDuty or incident.io destination; a person enters its secrets. */
|
|
1893
2016
|
"destinations.create": {
|
|
1894
2017
|
provider: "telegram" | "slack" | "email" | "webhook" | "pagerduty" | "incident_io";
|
|
@@ -1994,7 +2117,7 @@ export interface OperationParams {
|
|
|
1994
2117
|
"ingest_keys.create": {
|
|
1995
2118
|
project_id: number;
|
|
1996
2119
|
name: string;
|
|
1997
|
-
scopes: Array<"traces" | "logs" | "errors" | "monitors">;
|
|
2120
|
+
scopes: Array<"traces" | "logs" | "metrics" | "errors" | "monitors">;
|
|
1998
2121
|
environments: Array<string>;
|
|
1999
2122
|
expires_at: string | null;
|
|
2000
2123
|
};
|
|
@@ -2205,6 +2328,32 @@ export interface OperationParams {
|
|
|
2205
2328
|
"members.remove": {
|
|
2206
2329
|
user_id: string;
|
|
2207
2330
|
};
|
|
2331
|
+
/** The metric catalog of one project (name, type, kind, unit, series count, last seen) and the node's series and name caps with the metrics it is dropping points for. */
|
|
2332
|
+
"metrics.names": {
|
|
2333
|
+
project: number;
|
|
2334
|
+
environment?: string;
|
|
2335
|
+
q?: string;
|
|
2336
|
+
};
|
|
2337
|
+
/** One metric aggregated per step (avg, sum, min, max, count, rate, p50–p99) in a window of at most 7 days, optionally grouped by up to two attributes (≤ 50 groups, ≤ 10,000 points), with exemplar trace ids. */
|
|
2338
|
+
"metrics.query": {
|
|
2339
|
+
project: number;
|
|
2340
|
+
name: string;
|
|
2341
|
+
aggregation: "avg" | "sum" | "min" | "max" | "count" | "rate" | "p50" | "p90" | "p95" | "p99";
|
|
2342
|
+
start?: string;
|
|
2343
|
+
end?: string;
|
|
2344
|
+
step?: number;
|
|
2345
|
+
attrs?: string;
|
|
2346
|
+
group_by?: string;
|
|
2347
|
+
environment?: string;
|
|
2348
|
+
};
|
|
2349
|
+
/** The time series of one metric (attributes, service, environment, first and last seen), 100 per page. */
|
|
2350
|
+
"metrics.series": {
|
|
2351
|
+
project?: number;
|
|
2352
|
+
name?: string;
|
|
2353
|
+
environment?: string;
|
|
2354
|
+
attrs?: string;
|
|
2355
|
+
cursor?: string;
|
|
2356
|
+
};
|
|
2208
2357
|
/** How often count/assertion settings would have alerted over the last 30 days of stored data (same rule as the live evaluator). */
|
|
2209
2358
|
"monitors.backtest": {
|
|
2210
2359
|
project: number;
|
|
@@ -2325,6 +2474,26 @@ export interface OperationParams {
|
|
|
2325
2474
|
environments: Array<string>;
|
|
2326
2475
|
severity: "critical" | "high" | "medium" | "low";
|
|
2327
2476
|
recovery_threshold: number;
|
|
2477
|
+
} | {
|
|
2478
|
+
type: "metric";
|
|
2479
|
+
metric_query: {
|
|
2480
|
+
name: string;
|
|
2481
|
+
aggregation: "avg" | "sum" | "min" | "max" | "count" | "rate" | "p50" | "p90" | "p95" | "p99";
|
|
2482
|
+
filter: Array<{
|
|
2483
|
+
k: string;
|
|
2484
|
+
op: "=" | "!=" | "exists";
|
|
2485
|
+
v?: string;
|
|
2486
|
+
}>;
|
|
2487
|
+
group_by: Array<string>;
|
|
2488
|
+
};
|
|
2489
|
+
window_minutes: number;
|
|
2490
|
+
comparator: "lt" | "gt" | "outside";
|
|
2491
|
+
threshold: number;
|
|
2492
|
+
threshold_high: number | null;
|
|
2493
|
+
missing_data: "alert" | "keep" | "resolve" | "treat_as_zero";
|
|
2494
|
+
environments: Array<string>;
|
|
2495
|
+
severity: "critical" | "high" | "medium" | "low";
|
|
2496
|
+
recovery_threshold: number;
|
|
2328
2497
|
};
|
|
2329
2498
|
}));
|
|
2330
2499
|
/** Delete a monitor; `confirm_slug` must repeat its slug. */
|
|
@@ -2345,7 +2514,7 @@ export interface OperationParams {
|
|
|
2345
2514
|
limit?: number;
|
|
2346
2515
|
cursor?: string;
|
|
2347
2516
|
project_id?: number;
|
|
2348
|
-
type?: "job" | "count" | "assertion" | "deadline" | "progress";
|
|
2517
|
+
type?: "job" | "count" | "assertion" | "deadline" | "progress" | "metric";
|
|
2349
2518
|
};
|
|
2350
2519
|
/** Occurrences of a deadline monitor (pending, on time, late, missed, failed, cancelled), newest due first. */
|
|
2351
2520
|
"monitors.occurrences": {
|
|
@@ -2444,6 +2613,26 @@ export interface OperationParams {
|
|
|
2444
2613
|
environments: Array<string>;
|
|
2445
2614
|
severity: "critical" | "high" | "medium" | "low";
|
|
2446
2615
|
recovery_threshold: number;
|
|
2616
|
+
} | {
|
|
2617
|
+
type: "metric";
|
|
2618
|
+
metric_query: {
|
|
2619
|
+
name: string;
|
|
2620
|
+
aggregation: "avg" | "sum" | "min" | "max" | "count" | "rate" | "p50" | "p90" | "p95" | "p99";
|
|
2621
|
+
filter: Array<{
|
|
2622
|
+
k: string;
|
|
2623
|
+
op: "=" | "!=" | "exists";
|
|
2624
|
+
v?: string;
|
|
2625
|
+
}>;
|
|
2626
|
+
group_by: Array<string>;
|
|
2627
|
+
};
|
|
2628
|
+
window_minutes: number;
|
|
2629
|
+
comparator: "lt" | "gt" | "outside";
|
|
2630
|
+
threshold: number;
|
|
2631
|
+
threshold_high: number | null;
|
|
2632
|
+
missing_data: "alert" | "keep" | "resolve" | "treat_as_zero";
|
|
2633
|
+
environments: Array<string>;
|
|
2634
|
+
severity: "critical" | "high" | "medium" | "low";
|
|
2635
|
+
recovery_threshold: number;
|
|
2447
2636
|
};
|
|
2448
2637
|
}));
|
|
2449
2638
|
/** Start a backup now (at most once per 10 minutes). */
|
|
@@ -2544,6 +2733,27 @@ export interface OperationParams {
|
|
|
2544
2733
|
monitor_id: string;
|
|
2545
2734
|
grace_hours: number;
|
|
2546
2735
|
};
|
|
2736
|
+
/** A project's privacy policy (mode, rules, strict allowlist, version), the built-in detectors that are off, whether user ids are pseudonymised, the last 20 versions and what the node applies and counted in the last 24 h. */
|
|
2737
|
+
"privacy.get": {
|
|
2738
|
+
project_id: number;
|
|
2739
|
+
};
|
|
2740
|
+
/** Replace a project's privacy policy (rules are applied in order on the node before anything is stored). Always needs an admin's approval; loosening (a rule removed or changed, strict off, allowlist grown) also needs their fresh authenticator code and emails owners. */
|
|
2741
|
+
"privacy.set": {
|
|
2742
|
+
project_id: number;
|
|
2743
|
+
expected_version: number;
|
|
2744
|
+
mode: "standard" | "strict";
|
|
2745
|
+
rules: Array<{
|
|
2746
|
+
id: string;
|
|
2747
|
+
selector: string;
|
|
2748
|
+
type: "pattern" | "anything" | "creditcard" | "ip" | "email" | "phone_e164";
|
|
2749
|
+
method: "remove" | "replace" | "mask" | "hash";
|
|
2750
|
+
pattern?: string;
|
|
2751
|
+
ignore_case?: boolean;
|
|
2752
|
+
replace_with?: string;
|
|
2753
|
+
enabled?: boolean;
|
|
2754
|
+
}>;
|
|
2755
|
+
allowlist: Array<string>;
|
|
2756
|
+
};
|
|
2547
2757
|
/** Add a DSN key. */
|
|
2548
2758
|
"project_keys.create": {
|
|
2549
2759
|
project_id: number;
|
package/dist/operations.gen.js
CHANGED
|
@@ -114,6 +114,34 @@ export const OPERATIONS = {
|
|
|
114
114
|
node: null,
|
|
115
115
|
defaults: {},
|
|
116
116
|
},
|
|
117
|
+
"coverage.get": {
|
|
118
|
+
method: "GET",
|
|
119
|
+
path: "/v1/coverage",
|
|
120
|
+
pathParams: [],
|
|
121
|
+
scope: "coverage:read",
|
|
122
|
+
kind: "read",
|
|
123
|
+
sensitivity: "normal",
|
|
124
|
+
idempotency: "none",
|
|
125
|
+
ifMatch: false,
|
|
126
|
+
paged: false,
|
|
127
|
+
status: 200,
|
|
128
|
+
node: null,
|
|
129
|
+
defaults: {},
|
|
130
|
+
},
|
|
131
|
+
"coverage.set": {
|
|
132
|
+
method: "PUT",
|
|
133
|
+
path: "/v1/projects/{project_id}/coverage-expectations",
|
|
134
|
+
pathParams: ["project_id"],
|
|
135
|
+
scope: "coverage:write",
|
|
136
|
+
kind: "write",
|
|
137
|
+
sensitivity: "normal",
|
|
138
|
+
idempotency: "optional",
|
|
139
|
+
ifMatch: false,
|
|
140
|
+
paged: false,
|
|
141
|
+
status: 200,
|
|
142
|
+
node: null,
|
|
143
|
+
defaults: {},
|
|
144
|
+
},
|
|
117
145
|
"destinations.create": {
|
|
118
146
|
method: "POST",
|
|
119
147
|
path: "/v1/destinations",
|
|
@@ -688,6 +716,48 @@ export const OPERATIONS = {
|
|
|
688
716
|
node: null,
|
|
689
717
|
defaults: {},
|
|
690
718
|
},
|
|
719
|
+
"metrics.names": {
|
|
720
|
+
method: "GET",
|
|
721
|
+
path: "/v1/metrics/names",
|
|
722
|
+
pathParams: [],
|
|
723
|
+
scope: "metrics:read",
|
|
724
|
+
kind: "node",
|
|
725
|
+
sensitivity: "normal",
|
|
726
|
+
idempotency: "none",
|
|
727
|
+
ifMatch: false,
|
|
728
|
+
paged: false,
|
|
729
|
+
status: 200,
|
|
730
|
+
node: { path: "q/metrics/names" },
|
|
731
|
+
defaults: {},
|
|
732
|
+
},
|
|
733
|
+
"metrics.query": {
|
|
734
|
+
method: "GET",
|
|
735
|
+
path: "/v1/metrics/query",
|
|
736
|
+
pathParams: [],
|
|
737
|
+
scope: "metrics:read",
|
|
738
|
+
kind: "node",
|
|
739
|
+
sensitivity: "normal",
|
|
740
|
+
idempotency: "none",
|
|
741
|
+
ifMatch: false,
|
|
742
|
+
paged: false,
|
|
743
|
+
status: 200,
|
|
744
|
+
node: { path: "q/metrics/query", window: true },
|
|
745
|
+
defaults: {},
|
|
746
|
+
},
|
|
747
|
+
"metrics.series": {
|
|
748
|
+
method: "GET",
|
|
749
|
+
path: "/v1/metrics/series",
|
|
750
|
+
pathParams: [],
|
|
751
|
+
scope: "metrics:read",
|
|
752
|
+
kind: "node",
|
|
753
|
+
sensitivity: "normal",
|
|
754
|
+
idempotency: "none",
|
|
755
|
+
ifMatch: false,
|
|
756
|
+
paged: true,
|
|
757
|
+
status: 200,
|
|
758
|
+
node: { path: "q/metrics/series", list: "series" },
|
|
759
|
+
defaults: {},
|
|
760
|
+
},
|
|
691
761
|
"monitors.backtest": {
|
|
692
762
|
method: "POST",
|
|
693
763
|
path: "/v1/monitors/backtest",
|
|
@@ -1108,6 +1178,34 @@ export const OPERATIONS = {
|
|
|
1108
1178
|
node: null,
|
|
1109
1179
|
defaults: {},
|
|
1110
1180
|
},
|
|
1181
|
+
"privacy.get": {
|
|
1182
|
+
method: "GET",
|
|
1183
|
+
path: "/v1/projects/{project_id}/privacy",
|
|
1184
|
+
pathParams: ["project_id"],
|
|
1185
|
+
scope: "projects:read",
|
|
1186
|
+
kind: "read",
|
|
1187
|
+
sensitivity: "normal",
|
|
1188
|
+
idempotency: "none",
|
|
1189
|
+
ifMatch: false,
|
|
1190
|
+
paged: false,
|
|
1191
|
+
status: 200,
|
|
1192
|
+
node: null,
|
|
1193
|
+
defaults: {},
|
|
1194
|
+
},
|
|
1195
|
+
"privacy.set": {
|
|
1196
|
+
method: "PUT",
|
|
1197
|
+
path: "/v1/projects/{project_id}/privacy",
|
|
1198
|
+
pathParams: ["project_id"],
|
|
1199
|
+
scope: "privacy:write",
|
|
1200
|
+
kind: "write",
|
|
1201
|
+
sensitivity: "approval",
|
|
1202
|
+
idempotency: "optional",
|
|
1203
|
+
ifMatch: false,
|
|
1204
|
+
paged: false,
|
|
1205
|
+
status: 200,
|
|
1206
|
+
node: null,
|
|
1207
|
+
defaults: {},
|
|
1208
|
+
},
|
|
1111
1209
|
"project_keys.create": {
|
|
1112
1210
|
method: "POST",
|
|
1113
1211
|
path: "/v1/projects/{project_id}/keys",
|
|
@@ -1268,7 +1366,7 @@ export const OPERATIONS = {
|
|
|
1268
1366
|
pathParams: ["project_id", "group"],
|
|
1269
1367
|
scope: "privacy:write",
|
|
1270
1368
|
kind: "write",
|
|
1271
|
-
sensitivity: "
|
|
1369
|
+
sensitivity: "approval",
|
|
1272
1370
|
idempotency: "none",
|
|
1273
1371
|
ifMatch: false,
|
|
1274
1372
|
paged: false,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@belvador/api",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Typed client for the Belvador API (api.belvador.dev, OpenAPI 3.1): every operation by operationId, problem+json errors, retries, and node reads straight from the edge with short-lived tickets.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Belvador (https://belvador.dev)",
|
|
@@ -15,6 +15,9 @@
|
|
|
15
15
|
],
|
|
16
16
|
"type": "module",
|
|
17
17
|
"sideEffects": false,
|
|
18
|
+
"bin": {
|
|
19
|
+
"belvador-api": "dist/cli.js"
|
|
20
|
+
},
|
|
18
21
|
"main": "./dist/index.js",
|
|
19
22
|
"types": "./dist/index.d.ts",
|
|
20
23
|
"exports": {
|