@opensoftware/contracts 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -5
- package/dist/generated/types.d.ts +122 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js.map +1 -1
- package/openapi/openapi.json +150 -1
- package/package.json +2 -2
- package/typespec/foreman.tsp +3 -0
- package/typespec/health.tsp +42 -0
- package/typespec/intake-api.tsp +8 -0
- package/typespec/intake.tsp +5 -0
- package/typespec/main.tsp +1 -0
package/README.md
CHANGED
|
@@ -51,9 +51,11 @@ Each format has one schema, generated from `typespec/`, and fixtures that CONTRA
|
|
|
51
51
|
`openapi/openapi.json` also holds the paths of the module APIs, from the operations in `typespec/` (ADR 0048). The
|
|
52
52
|
first is gatekeeper's: `POST /v1/gates` and `GET /v1/gates/{gateId}` with the models `GateRequest`, `GateView` and
|
|
53
53
|
`ApiProblem` (RFC 9457). The second is intake's (ADR 0063): `POST /v1/work-items` and
|
|
54
|
-
`GET /v1/work-items/{workItemId}` with the models `WorkSubmission`, `WorkItemView` and `WorkRequest
|
|
54
|
+
`GET /v1/work-items/{workItemId}` with the models `WorkSubmission`, `WorkItemView` and `WorkRequest`, and
|
|
55
|
+
`GET /v1/inbox` with `WorkItemList`. The third is the
|
|
55
56
|
foreman's (ADR 0067): `POST /v1/runs`, `GET /v1/runs/{runId}` and `POST /v1/runs/{runId}/signals` with the models
|
|
56
|
-
`RunView`, `StageView`, `CheckView` (ADR 0069) and `RunSignal`.
|
|
57
|
+
`RunView`, `StageView`, `CheckView` (ADR 0069) and `RunSignal`. All three answer `GET /v1/health` with the models
|
|
58
|
+
`Health` and `HealthCheck` (`HealthApi`, ADR 0086). `pnpm build` compiles the operations with the TypeSpec OpenAPI 3 emitter and copies their
|
|
57
59
|
paths next to the named models; an operation that uses a type that is no model fails the build. The package exports
|
|
58
60
|
the type `paths`, which types a client such as openapi-fetch.
|
|
59
61
|
|
|
@@ -100,9 +102,10 @@ One-time setup (no credential is ever stored in the repository):
|
|
|
100
102
|
repository is published.
|
|
101
103
|
2. GitHub: the publish job runs in the environment `npm` (Settings → Environments; GitHub creates it on the first
|
|
102
104
|
run).
|
|
103
|
-
3.
|
|
104
|
-
first version
|
|
105
|
-
`
|
|
105
|
+
3. New package only: npm adds a trusted publisher only to a package that exists. Before the release pull request
|
|
106
|
+
with its first version merges, a maintainer creates it: build and pack it as version `0.0.0`, then run
|
|
107
|
+
`npm publish <file>.tgz --tag placeholder --access public` without `--otp`. npm stages that version, so the
|
|
108
|
+
package exists and nothing is public (`skills/release-packages`).
|
|
106
109
|
4. Then add the trusted publisher, on npmjs.com (package settings → Trusted publishing) or with
|
|
107
110
|
`npm trust github <package> --file publish-<name>.yml --repository sesigl/open-software-factory --environment npm
|
|
108
111
|
--allow-publish --allow-stage-publish`. Every later version publishes through OIDC only, with a provenance
|
|
@@ -33,6 +33,40 @@ export type paths = {
|
|
|
33
33
|
patch?: never;
|
|
34
34
|
trace?: never;
|
|
35
35
|
};
|
|
36
|
+
"/v1/health": {
|
|
37
|
+
parameters: {
|
|
38
|
+
query?: never;
|
|
39
|
+
header?: never;
|
|
40
|
+
path?: never;
|
|
41
|
+
cookie?: never;
|
|
42
|
+
};
|
|
43
|
+
/** @description The server's health. Needs no token, and names no secret. 503 when a check fails. */
|
|
44
|
+
get: operations["HealthApi_getHealth"];
|
|
45
|
+
put?: never;
|
|
46
|
+
post?: never;
|
|
47
|
+
delete?: never;
|
|
48
|
+
options?: never;
|
|
49
|
+
head?: never;
|
|
50
|
+
patch?: never;
|
|
51
|
+
trace?: never;
|
|
52
|
+
};
|
|
53
|
+
"/v1/inbox": {
|
|
54
|
+
parameters: {
|
|
55
|
+
query?: never;
|
|
56
|
+
header?: never;
|
|
57
|
+
path?: never;
|
|
58
|
+
cookie?: never;
|
|
59
|
+
};
|
|
60
|
+
/** @description The 50 latest work items, the one received last first; with `status`, only the work items in that status. */
|
|
61
|
+
get: operations["IntakeApi_listWorkItems"];
|
|
62
|
+
put?: never;
|
|
63
|
+
post?: never;
|
|
64
|
+
delete?: never;
|
|
65
|
+
options?: never;
|
|
66
|
+
head?: never;
|
|
67
|
+
patch?: never;
|
|
68
|
+
trace?: never;
|
|
69
|
+
};
|
|
36
70
|
"/v1/runs": {
|
|
37
71
|
parameters: {
|
|
38
72
|
query?: never;
|
|
@@ -439,6 +473,19 @@ export type components = {
|
|
|
439
473
|
/** @description The record, once the gate is decided. */
|
|
440
474
|
record?: components["schemas"]["GateRecord"];
|
|
441
475
|
};
|
|
476
|
+
/** @description The state of a server: `ok` when every check is ok. */
|
|
477
|
+
Health: {
|
|
478
|
+
status: "ok" | "failing";
|
|
479
|
+
checks: components["schemas"]["HealthCheck"][];
|
|
480
|
+
};
|
|
481
|
+
/** @description One system a server needs, such as its database or NATS, and whether the server reaches it now. */
|
|
482
|
+
HealthCheck: {
|
|
483
|
+
/** @description The system, like "database", "nats" or "temporal". */
|
|
484
|
+
name: components["schemas"]["Name"];
|
|
485
|
+
ok: boolean;
|
|
486
|
+
/** @description What failed and how to fix it, when `ok` is false. Never a secret. */
|
|
487
|
+
detail?: string;
|
|
488
|
+
};
|
|
442
489
|
/** @description A hostname without scheme or port, for example "api.linear.app". */
|
|
443
490
|
Hostname: string;
|
|
444
491
|
/** @description An identifier chosen by the producer. ULIDs are recommended; consumers treat it as opaque. */
|
|
@@ -840,6 +887,8 @@ export type components = {
|
|
|
840
887
|
startedAt: string;
|
|
841
888
|
/** Format: date-time */
|
|
842
889
|
endedAt?: string;
|
|
890
|
+
/** @description The OpenTelemetry trace of the run: the first 32 hex digits of the SHA-256 of `runId` (ADR 0087). */
|
|
891
|
+
traceId?: components["schemas"]["TraceId"];
|
|
843
892
|
/** @description The stages of the workflow, in order. */
|
|
844
893
|
stages: components["schemas"]["StageView"][];
|
|
845
894
|
};
|
|
@@ -1039,6 +1088,10 @@ export type components = {
|
|
|
1039
1088
|
/** @description Related material: an error report, a change, a document. */
|
|
1040
1089
|
links?: components["schemas"]["Link"][];
|
|
1041
1090
|
};
|
|
1091
|
+
/** @description intake: the latest work items, as `GET /v1/inbox` answers them, the one received last first. */
|
|
1092
|
+
WorkItemList: {
|
|
1093
|
+
workItems: components["schemas"]["WorkItemView"][];
|
|
1094
|
+
};
|
|
1042
1095
|
/**
|
|
1043
1096
|
* @description Where a work item stands: received, then as its run in the foreman goes (ADR 0071).
|
|
1044
1097
|
* @enum {string}
|
|
@@ -1200,6 +1253,75 @@ export interface operations {
|
|
|
1200
1253
|
};
|
|
1201
1254
|
};
|
|
1202
1255
|
};
|
|
1256
|
+
HealthApi_getHealth: {
|
|
1257
|
+
parameters: {
|
|
1258
|
+
query?: never;
|
|
1259
|
+
header?: never;
|
|
1260
|
+
path?: never;
|
|
1261
|
+
cookie?: never;
|
|
1262
|
+
};
|
|
1263
|
+
requestBody?: never;
|
|
1264
|
+
responses: {
|
|
1265
|
+
/** @description The request has succeeded. */
|
|
1266
|
+
200: {
|
|
1267
|
+
headers: {
|
|
1268
|
+
[name: string]: unknown;
|
|
1269
|
+
};
|
|
1270
|
+
content: {
|
|
1271
|
+
"application/json": components["schemas"]["Health"];
|
|
1272
|
+
};
|
|
1273
|
+
};
|
|
1274
|
+
/** @description Service unavailable. */
|
|
1275
|
+
503: {
|
|
1276
|
+
headers: {
|
|
1277
|
+
[name: string]: unknown;
|
|
1278
|
+
};
|
|
1279
|
+
content: {
|
|
1280
|
+
"application/json": components["schemas"]["Health"];
|
|
1281
|
+
};
|
|
1282
|
+
};
|
|
1283
|
+
};
|
|
1284
|
+
};
|
|
1285
|
+
IntakeApi_listWorkItems: {
|
|
1286
|
+
parameters: {
|
|
1287
|
+
query?: {
|
|
1288
|
+
status?: components["schemas"]["WorkItemStatus"];
|
|
1289
|
+
};
|
|
1290
|
+
header?: never;
|
|
1291
|
+
path?: never;
|
|
1292
|
+
cookie?: never;
|
|
1293
|
+
};
|
|
1294
|
+
requestBody?: never;
|
|
1295
|
+
responses: {
|
|
1296
|
+
/** @description The request has succeeded. */
|
|
1297
|
+
200: {
|
|
1298
|
+
headers: {
|
|
1299
|
+
[name: string]: unknown;
|
|
1300
|
+
};
|
|
1301
|
+
content: {
|
|
1302
|
+
"application/json": components["schemas"]["WorkItemList"];
|
|
1303
|
+
};
|
|
1304
|
+
};
|
|
1305
|
+
/** @description The server could not understand the request due to invalid syntax. */
|
|
1306
|
+
400: {
|
|
1307
|
+
headers: {
|
|
1308
|
+
[name: string]: unknown;
|
|
1309
|
+
};
|
|
1310
|
+
content: {
|
|
1311
|
+
"application/problem+json": components["schemas"]["ApiProblem"];
|
|
1312
|
+
};
|
|
1313
|
+
};
|
|
1314
|
+
/** @description Access is unauthorized. */
|
|
1315
|
+
401: {
|
|
1316
|
+
headers: {
|
|
1317
|
+
[name: string]: unknown;
|
|
1318
|
+
};
|
|
1319
|
+
content: {
|
|
1320
|
+
"application/problem+json": components["schemas"]["ApiProblem"];
|
|
1321
|
+
};
|
|
1322
|
+
};
|
|
1323
|
+
};
|
|
1324
|
+
};
|
|
1203
1325
|
ForemanApi_listRuns: {
|
|
1204
1326
|
parameters: {
|
|
1205
1327
|
query?: {
|
package/dist/index.d.ts
CHANGED
|
@@ -26,12 +26,15 @@ export type GateView = Schemas["GateView"];
|
|
|
26
26
|
export type ApiProblem = Schemas["ApiProblem"];
|
|
27
27
|
export type WorkSubmission = Schemas["WorkSubmission"];
|
|
28
28
|
export type WorkItemView = Schemas["WorkItemView"];
|
|
29
|
+
export type WorkItemList = Schemas["WorkItemList"];
|
|
29
30
|
export type WorkRequest = Schemas["WorkRequest"];
|
|
30
31
|
export type RunView = Schemas["RunView"];
|
|
31
32
|
export type StageView = Schemas["StageView"];
|
|
32
33
|
export type CheckView = Schemas["CheckView"];
|
|
33
34
|
export type RunSignal = Schemas["RunSignal"];
|
|
34
35
|
export type SandboxSpec = Schemas["SandboxSpec"];
|
|
36
|
+
export type Health = Schemas["Health"];
|
|
37
|
+
export type HealthCheck = Schemas["HealthCheck"];
|
|
35
38
|
/** One reason a document does not match its format. `path` is a JSON Pointer into the document. */
|
|
36
39
|
export interface Problem {
|
|
37
40
|
path: string;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,oHAAoH;AACpH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,OAAO,EAAE,EAA2C,MAAM,kBAAkB,CAAC;AACpF,OAAO,UAAU,MAAM,aAAa,CAAC;AACrC,OAAO,EAAe,WAAW,EAAE,MAAM,cAAc,CAAC;AAGxD,OAAO,EAAE,IAAI,IAAI,eAAe,EAAe,MAAM,eAAe,CAAC;AACrE,OAAO,EAAE,OAAO,EAAe,WAAW,EAAE,MAAM,cAAc,CAAC;AAEjE,OAAO,EAAqC,QAAQ,EAAuB,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/openapi/openapi.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"openapi": "3.1.0",
|
|
3
3
|
"info": {
|
|
4
4
|
"title": "Open Software Factory contracts",
|
|
5
|
-
"version": "2.
|
|
5
|
+
"version": "2.2.0",
|
|
6
6
|
"description": "The shared formats as named models, and the HTTP APIs of the modules. Generated by `pnpm build` in contracts/ from typespec/. Do not edit.",
|
|
7
7
|
"license": {
|
|
8
8
|
"name": "Apache-2.0",
|
|
@@ -117,6 +117,87 @@
|
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
119
|
},
|
|
120
|
+
"/v1/health": {
|
|
121
|
+
"get": {
|
|
122
|
+
"operationId": "HealthApi_getHealth",
|
|
123
|
+
"description": "The server's health. Needs no token, and names no secret. 503 when a check fails.",
|
|
124
|
+
"parameters": [],
|
|
125
|
+
"responses": {
|
|
126
|
+
"200": {
|
|
127
|
+
"description": "The request has succeeded.",
|
|
128
|
+
"content": {
|
|
129
|
+
"application/json": {
|
|
130
|
+
"schema": {
|
|
131
|
+
"$ref": "#/components/schemas/Health"
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
"503": {
|
|
137
|
+
"description": "Service unavailable.",
|
|
138
|
+
"content": {
|
|
139
|
+
"application/json": {
|
|
140
|
+
"schema": {
|
|
141
|
+
"$ref": "#/components/schemas/Health"
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
"security": [
|
|
148
|
+
{}
|
|
149
|
+
]
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
"/v1/inbox": {
|
|
153
|
+
"get": {
|
|
154
|
+
"operationId": "IntakeApi_listWorkItems",
|
|
155
|
+
"description": "The 50 latest work items, the one received last first; with `status`, only the work items in that status.",
|
|
156
|
+
"parameters": [
|
|
157
|
+
{
|
|
158
|
+
"name": "status",
|
|
159
|
+
"in": "query",
|
|
160
|
+
"required": false,
|
|
161
|
+
"schema": {
|
|
162
|
+
"$ref": "#/components/schemas/WorkItemStatus"
|
|
163
|
+
},
|
|
164
|
+
"explode": false
|
|
165
|
+
}
|
|
166
|
+
],
|
|
167
|
+
"responses": {
|
|
168
|
+
"200": {
|
|
169
|
+
"description": "The request has succeeded.",
|
|
170
|
+
"content": {
|
|
171
|
+
"application/json": {
|
|
172
|
+
"schema": {
|
|
173
|
+
"$ref": "#/components/schemas/WorkItemList"
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
"400": {
|
|
179
|
+
"description": "The server could not understand the request due to invalid syntax.",
|
|
180
|
+
"content": {
|
|
181
|
+
"application/problem+json": {
|
|
182
|
+
"schema": {
|
|
183
|
+
"$ref": "#/components/schemas/ApiProblem"
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
"401": {
|
|
189
|
+
"description": "Access is unauthorized.",
|
|
190
|
+
"content": {
|
|
191
|
+
"application/problem+json": {
|
|
192
|
+
"schema": {
|
|
193
|
+
"$ref": "#/components/schemas/ApiProblem"
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
},
|
|
120
201
|
"/v1/runs": {
|
|
121
202
|
"post": {
|
|
122
203
|
"operationId": "ForemanApi_startRun",
|
|
@@ -1388,6 +1469,55 @@
|
|
|
1388
1469
|
],
|
|
1389
1470
|
"description": "gatekeeper: a gate as the HTTP API shows it (ADR 0048)."
|
|
1390
1471
|
},
|
|
1472
|
+
"Health": {
|
|
1473
|
+
"type": "object",
|
|
1474
|
+
"properties": {
|
|
1475
|
+
"status": {
|
|
1476
|
+
"anyOf": [
|
|
1477
|
+
{
|
|
1478
|
+
"type": "string",
|
|
1479
|
+
"const": "ok"
|
|
1480
|
+
},
|
|
1481
|
+
{
|
|
1482
|
+
"type": "string",
|
|
1483
|
+
"const": "failing"
|
|
1484
|
+
}
|
|
1485
|
+
]
|
|
1486
|
+
},
|
|
1487
|
+
"checks": {
|
|
1488
|
+
"type": "array",
|
|
1489
|
+
"items": {
|
|
1490
|
+
"$ref": "#/components/schemas/HealthCheck"
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
},
|
|
1494
|
+
"required": [
|
|
1495
|
+
"status",
|
|
1496
|
+
"checks"
|
|
1497
|
+
],
|
|
1498
|
+
"description": "The state of a server: `ok` when every check is ok."
|
|
1499
|
+
},
|
|
1500
|
+
"HealthCheck": {
|
|
1501
|
+
"type": "object",
|
|
1502
|
+
"properties": {
|
|
1503
|
+
"name": {
|
|
1504
|
+
"$ref": "#/components/schemas/Name",
|
|
1505
|
+
"description": "The system, like \"database\", \"nats\" or \"temporal\"."
|
|
1506
|
+
},
|
|
1507
|
+
"ok": {
|
|
1508
|
+
"type": "boolean"
|
|
1509
|
+
},
|
|
1510
|
+
"detail": {
|
|
1511
|
+
"type": "string",
|
|
1512
|
+
"description": "What failed and how to fix it, when `ok` is false. Never a secret."
|
|
1513
|
+
}
|
|
1514
|
+
},
|
|
1515
|
+
"required": [
|
|
1516
|
+
"name",
|
|
1517
|
+
"ok"
|
|
1518
|
+
],
|
|
1519
|
+
"description": "One system a server needs, such as its database or NATS, and whether the server reaches it now."
|
|
1520
|
+
},
|
|
1391
1521
|
"Hostname": {
|
|
1392
1522
|
"type": "string",
|
|
1393
1523
|
"pattern": "^[A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?(\\.[A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?)*$",
|
|
@@ -2423,6 +2553,10 @@
|
|
|
2423
2553
|
"type": "string",
|
|
2424
2554
|
"format": "date-time"
|
|
2425
2555
|
},
|
|
2556
|
+
"traceId": {
|
|
2557
|
+
"$ref": "#/components/schemas/TraceId",
|
|
2558
|
+
"description": "The OpenTelemetry trace of the run: the first 32 hex digits of the SHA-256 of `runId` (ADR 0087)."
|
|
2559
|
+
},
|
|
2426
2560
|
"stages": {
|
|
2427
2561
|
"type": "array",
|
|
2428
2562
|
"items": {
|
|
@@ -2959,6 +3093,21 @@
|
|
|
2959
3093
|
],
|
|
2960
3094
|
"description": "One unit of requested work: the `data` of a `work.received@v1` CloudEvent."
|
|
2961
3095
|
},
|
|
3096
|
+
"WorkItemList": {
|
|
3097
|
+
"type": "object",
|
|
3098
|
+
"properties": {
|
|
3099
|
+
"workItems": {
|
|
3100
|
+
"type": "array",
|
|
3101
|
+
"items": {
|
|
3102
|
+
"$ref": "#/components/schemas/WorkItemView"
|
|
3103
|
+
}
|
|
3104
|
+
}
|
|
3105
|
+
},
|
|
3106
|
+
"required": [
|
|
3107
|
+
"workItems"
|
|
3108
|
+
],
|
|
3109
|
+
"description": "intake: the latest work items, as `GET /v1/inbox` answers them, the one received last first."
|
|
3110
|
+
},
|
|
2962
3111
|
"WorkItemStatus": {
|
|
2963
3112
|
"type": "string",
|
|
2964
3113
|
"enum": [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opensoftware/contracts",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "The shared formats of the open software factory: JSON Schemas, TypeScript types and the osf-contracts CLI.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"@typespec/openapi": "1.17.0",
|
|
45
45
|
"@typespec/openapi3": "1.17.0",
|
|
46
46
|
"openapi-typescript": "7.13.0",
|
|
47
|
-
"@opensoftware/testkit": "0.
|
|
47
|
+
"@opensoftware/testkit": "0.31.0"
|
|
48
48
|
},
|
|
49
49
|
"scripts": {
|
|
50
50
|
"build": "node scripts/build.ts",
|
package/typespec/foreman.tsp
CHANGED
|
@@ -97,6 +97,9 @@ model RunView {
|
|
|
97
97
|
startedAt: utcDateTime;
|
|
98
98
|
endedAt?: utcDateTime;
|
|
99
99
|
|
|
100
|
+
/** The OpenTelemetry trace of the run: the first 32 hex digits of the SHA-256 of `runId` (ADR 0087). */
|
|
101
|
+
traceId?: TraceId;
|
|
102
|
+
|
|
100
103
|
/** The stages of the workflow, in order. */
|
|
101
104
|
stages: StageView[];
|
|
102
105
|
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// The health route that intake, gatekeeper and the foreman each serve (ADR 0086): the state of the server and of each
|
|
2
|
+
// system it needs. `console doctor` and the Compose profile's health checks read it.
|
|
3
|
+
import "@typespec/http";
|
|
4
|
+
import "./common.tsp";
|
|
5
|
+
import "./gatekeeper-api.tsp";
|
|
6
|
+
|
|
7
|
+
using TypeSpec.Http;
|
|
8
|
+
|
|
9
|
+
namespace Osf.Contracts;
|
|
10
|
+
|
|
11
|
+
/** One system a server needs, such as its database or NATS, and whether the server reaches it now. */
|
|
12
|
+
model HealthCheck {
|
|
13
|
+
/** The system, like "database", "nats" or "temporal". */
|
|
14
|
+
name: Name;
|
|
15
|
+
|
|
16
|
+
ok: boolean;
|
|
17
|
+
|
|
18
|
+
/** What failed and how to fix it, when `ok` is false. Never a secret. */
|
|
19
|
+
detail?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** The state of a server: `ok` when every check is ok. */
|
|
23
|
+
model Health {
|
|
24
|
+
status: "ok" | "failing";
|
|
25
|
+
checks: HealthCheck[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
namespace HealthApi {
|
|
29
|
+
/** The server's health. Needs no token, and names no secret. 503 when a check fails. */
|
|
30
|
+
@route("/v1/health")
|
|
31
|
+
@get
|
|
32
|
+
@useAuth(NoAuth)
|
|
33
|
+
op getHealth():
|
|
34
|
+
| {
|
|
35
|
+
@statusCode statusCode: 200;
|
|
36
|
+
@body health: Health;
|
|
37
|
+
}
|
|
38
|
+
| {
|
|
39
|
+
@statusCode statusCode: 503;
|
|
40
|
+
@body health: Health;
|
|
41
|
+
};
|
|
42
|
+
}
|
package/typespec/intake-api.tsp
CHANGED
|
@@ -33,6 +33,14 @@ namespace IntakeApi {
|
|
|
33
33
|
| GatekeeperApi.Failure<401>
|
|
34
34
|
| GatekeeperApi.Failure<404>;
|
|
35
35
|
|
|
36
|
+
/** The 50 latest work items, the one received last first; with `status`, only the work items in that status. */
|
|
37
|
+
@route("/v1/inbox")
|
|
38
|
+
@get
|
|
39
|
+
op listWorkItems(@query status?: WorkItemStatus):
|
|
40
|
+
| WorkItemList
|
|
41
|
+
| GatekeeperApi.Failure<400>
|
|
42
|
+
| GatekeeperApi.Failure<401>;
|
|
43
|
+
|
|
36
44
|
/** A work item, its status and every request that asked for it. */
|
|
37
45
|
@route("/v1/work-items/{workItemId}")
|
|
38
46
|
@get
|
package/typespec/intake.tsp
CHANGED
|
@@ -43,6 +43,11 @@ model WorkRequest {
|
|
|
43
43
|
receivedAt: utcDateTime;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
/** intake: the latest work items, as `GET /v1/inbox` answers them, the one received last first. */
|
|
47
|
+
model WorkItemList {
|
|
48
|
+
workItems: WorkItemView[];
|
|
49
|
+
}
|
|
50
|
+
|
|
46
51
|
/** intake: a work item as the HTTP API shows it (ADR 0063). */
|
|
47
52
|
model WorkItemView {
|
|
48
53
|
/** Its ID is "wi_" and 20 hex digits of the SHA-256 of its dedupe key. */
|
package/typespec/main.tsp
CHANGED