@opensoftware/contracts 1.4.0 → 1.6.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 CHANGED
@@ -42,8 +42,18 @@ Each format has one schema, generated from `typespec/`, and fixtures that CONTRA
42
42
  | run record | `run-record/run-record.schema.json` | `RunRecord` | OTel resource and root-span attributes; pins in `typespec/run-record.tsp`. |
43
43
  | evidence bundle | `evidence-bundle/evidence-bundle.schema.json` | `EvidenceManifest` | `evidence.json` at the bundle root. |
44
44
  | score | `score/score.schema.json` | `Score` | Subset of Langfuse's create-score request; factory fields in `metadata`. |
45
+ | gate record | `gate-record/gate-record.schema.json` | `GateRecord` | gatekeeper's signed approval record (ADR 0047). |
46
+ | sandbox spec | `sandbox-spec/sandbox-spec.schema.json` | `SandboxSpec` | The input of a sandbox adapter's `create` (ADR 0054). Closed objects: an unknown field is an error. |
45
47
  | events | `events/<event>/<event>.schema.json`, `events/asyncapi.yaml` | `WorkReceived` … `PrClosed` | CloudEvents 1.0, structured JSON. |
46
48
 
49
+ ## HTTP APIs
50
+
51
+ `openapi/openapi.json` also holds the paths of the module APIs, from the operations in `typespec/` (ADR 0048). The
52
+ first is gatekeeper's: `POST /v1/gates` and `GET /v1/gates/{gateId}` with the models `GateRequest`, `GateView` and
53
+ `ApiProblem` (RFC 9457). `pnpm build` compiles the operations with the TypeSpec OpenAPI 3 emitter and copies their
54
+ paths next to the named models; an operation that uses a type that is no model fails the build. The package exports
55
+ the type `paths`, which types a client such as openapi-fetch.
56
+
47
57
  Wire formats (everything but the factory definition) are open: readers ignore fields they do not know, so a minor
48
58
  version may add optional fields. Read `factory.yaml` with a YAML 1.2 parser: YAML 1.1 parsers turn the key `on`
49
59
  into `true`.
@@ -71,8 +81,9 @@ release-please opens a release pull request from the Conventional Commits under
71
81
  the tag `contracts-v<version>`. The release pull request also sets the version in `openapi/openapi.json`, which
72
82
  `pnpm build` copies from `package.json`, so the generated file stays current. The workflow `.github/workflows/publish-contracts.yml` then builds the package and
73
83
  publishes it to npm as `@opensoftware/contracts`. npm accepts a provenance statement only from a public
74
- repository, so the workflow adds one only when this repository is public. To publish a tag again, run the
75
- workflow by hand with the tag. The CONTRACT check and `osf-contracts breaking` compare with the newest `contracts-v*` tag.
84
+ repository, so the workflow adds one only when this repository is public. When the newest tag is missing on npm,
85
+ for example after a failed upload, the next run of the workflow on `main` publishes it. To publish a tag again, run
86
+ the workflow by hand with the tag. The CONTRACT check and `osf-contracts breaking` compare with the newest `contracts-v*` tag.
76
87
 
77
88
  Only the TypeScript package exists (ADR 0012). A client for another language can be generated from
78
89
  `openapi/openapi.json` with any OpenAPI generator when someone needs one.
package/dist/formats.js CHANGED
@@ -6,6 +6,8 @@ export const FORMATS = [
6
6
  format("run-record", "RunRecord"),
7
7
  format("evidence-bundle", "EvidenceManifest"),
8
8
  format("score", "Score"),
9
+ format("gate-record", "GateRecord"),
10
+ format("sandbox-spec", "SandboxSpec"),
9
11
  format("events/work-received", "WorkReceived"),
10
12
  format("events/run-completed", "RunCompleted"),
11
13
  format("events/gate-requested", "GateRequested"),
@@ -1 +1 @@
1
- {"version":3,"file":"formats.js","sourceRoot":"","sources":["../src/formats.ts"],"names":[],"mappings":"AAAA,2GAA2G;AAW3G,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,KAAa,EAAU,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAY,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAEjH,MAAM,CAAC,MAAM,OAAO,GAAsB;IACxC,MAAM,CAAC,oBAAoB,EAAE,mBAAmB,CAAC;IACjD,MAAM,CAAC,WAAW,EAAE,UAAU,CAAC;IAC/B,MAAM,CAAC,YAAY,EAAE,WAAW,CAAC;IACjC,MAAM,CAAC,iBAAiB,EAAE,kBAAkB,CAAC;IAC7C,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC;IACxB,MAAM,CAAC,sBAAsB,EAAE,cAAc,CAAC;IAC9C,MAAM,CAAC,sBAAsB,EAAE,cAAc,CAAC;IAC9C,MAAM,CAAC,uBAAuB,EAAE,eAAe,CAAC;IAChD,MAAM,CAAC,qBAAqB,EAAE,aAAa,CAAC;IAC5C,MAAM,CAAC,uBAAuB,EAAE,eAAe,CAAC;IAChD,MAAM,CAAC,kBAAkB,EAAE,UAAU,CAAC;IACtC,MAAM,CAAC,oBAAoB,EAAE,YAAY,CAAC;IAC1C,MAAM,CAAC,kBAAkB,EAAE,UAAU,CAAC;CACvC,CAAC;AAEF,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AAC9D,CAAC"}
1
+ {"version":3,"file":"formats.js","sourceRoot":"","sources":["../src/formats.ts"],"names":[],"mappings":"AAAA,2GAA2G;AAW3G,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,KAAa,EAAU,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAY,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAEjH,MAAM,CAAC,MAAM,OAAO,GAAsB;IACxC,MAAM,CAAC,oBAAoB,EAAE,mBAAmB,CAAC;IACjD,MAAM,CAAC,WAAW,EAAE,UAAU,CAAC;IAC/B,MAAM,CAAC,YAAY,EAAE,WAAW,CAAC;IACjC,MAAM,CAAC,iBAAiB,EAAE,kBAAkB,CAAC;IAC7C,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC;IACxB,MAAM,CAAC,aAAa,EAAE,YAAY,CAAC;IACnC,MAAM,CAAC,cAAc,EAAE,aAAa,CAAC;IACrC,MAAM,CAAC,sBAAsB,EAAE,cAAc,CAAC;IAC9C,MAAM,CAAC,sBAAsB,EAAE,cAAc,CAAC;IAC9C,MAAM,CAAC,uBAAuB,EAAE,eAAe,CAAC;IAChD,MAAM,CAAC,qBAAqB,EAAE,aAAa,CAAC;IAC5C,MAAM,CAAC,uBAAuB,EAAE,eAAe,CAAC;IAChD,MAAM,CAAC,kBAAkB,EAAE,UAAU,CAAC;IACtC,MAAM,CAAC,oBAAoB,EAAE,YAAY,CAAC;IAC1C,MAAM,CAAC,kBAAkB,EAAE,UAAU,CAAC;CACvC,CAAC;AAEF,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AAC9D,CAAC"}
@@ -1,4 +1,39 @@
1
- export type paths = Record<string, never>;
1
+ export type paths = {
2
+ "/v1/gates": {
3
+ parameters: {
4
+ query?: never;
5
+ header?: never;
6
+ path?: never;
7
+ cookie?: never;
8
+ };
9
+ get?: never;
10
+ put?: never;
11
+ /** @description Ask the policy's approver groups for a decision. The same request again answers the gate it made before. */
12
+ post: operations["GatekeeperApi_requestGate"];
13
+ delete?: never;
14
+ options?: never;
15
+ head?: never;
16
+ patch?: never;
17
+ trace?: never;
18
+ };
19
+ "/v1/gates/{gateId}": {
20
+ parameters: {
21
+ query?: never;
22
+ header?: never;
23
+ path?: never;
24
+ cookie?: never;
25
+ };
26
+ /** @description A gate: its state, and its record once it is decided. */
27
+ get: operations["GatekeeperApi_getGate"];
28
+ put?: never;
29
+ post?: never;
30
+ delete?: never;
31
+ options?: never;
32
+ head?: never;
33
+ patch?: never;
34
+ trace?: never;
35
+ };
36
+ };
2
37
  export type webhooks = Record<string, never>;
3
38
  export type components = {
4
39
  schemas: {
@@ -33,6 +68,15 @@ export type components = {
33
68
  /** @description Runtime of the agent. */
34
69
  sandbox?: components["schemas"]["Sandbox"];
35
70
  };
71
+ /** @description An error of an HTTP API (RFC 9457). */
72
+ ApiProblem: {
73
+ /** @description A short summary, the same for every occurrence of the problem. */
74
+ title: string;
75
+ /** @description The HTTP status code. */
76
+ status: number;
77
+ /** @description What went wrong this time, for example the field that is missing. */
78
+ detail?: string;
79
+ };
36
80
  Artifact: {
37
81
  path: components["schemas"]["BundlePath"];
38
82
  kind: components["schemas"]["ArtifactKind"];
@@ -172,6 +216,47 @@ export type components = {
172
216
  };
173
217
  /** @enum {string} */
174
218
  GateDecision: "approved" | "rejected" | "expired";
219
+ /** @description gatekeeper: who decided what and when, signed with Ed25519 (ADR 0047). */
220
+ GateRecord: {
221
+ gate: string;
222
+ workItem: string;
223
+ stage: components["schemas"]["Name"];
224
+ summary: string;
225
+ /** @description SHA-256 of the canonical request: what was approved. */
226
+ request: string;
227
+ /** @description The policy file. */
228
+ policy: string;
229
+ /** @description SHA-256 of the policy's text: the rules that picked the approvers. */
230
+ policyDigest: string;
231
+ risk?: string;
232
+ approvers: components["schemas"]["Name"][];
233
+ channel: string;
234
+ /** Format: date-time */
235
+ requestedAt: string;
236
+ decision: components["schemas"]["GateDecision"];
237
+ /** @description Who decided. Absent only when the gate expired. A policy that names no group decides as a trigger. */
238
+ decidedBy?: components["schemas"]["Actor"];
239
+ /** Format: date-time */
240
+ decidedAt: string;
241
+ /** @description The reason of a rejection. */
242
+ reason?: string;
243
+ /** @description Ed25519 over the canonical JSON of the rest of the record. Absent when the record is unsigned. */
244
+ signature?: components["schemas"]["RecordSignature"];
245
+ };
246
+ /** @description gatekeeper: what a person is asked to approve, and the facts the policy decides on (ADR 0047). */
247
+ GateRequest: {
248
+ /** @description What waits: a work item ID or a URL. */
249
+ workItem: string;
250
+ /** @description The stage that waits, for example "merge". */
251
+ stage: components["schemas"]["Name"];
252
+ /** @description What the approvers decide, shown in the channel. */
253
+ summary: string;
254
+ links?: components["schemas"]["Link"][];
255
+ /** @description Any facts the policy needs, such as changed paths, labels or the author. */
256
+ change?: {
257
+ [key: string]: unknown;
258
+ };
259
+ };
175
260
  /** @description gatekeeper: a decision is needed before a stage starts. */
176
261
  GateRequested: {
177
262
  /** @constant */
@@ -210,6 +295,41 @@ export type components = {
210
295
  /** Format: date-time */
211
296
  expiresAt?: string;
212
297
  };
298
+ /**
299
+ * @description A gate's state: waiting, or how it was decided.
300
+ * @enum {string}
301
+ */
302
+ GateState: "pending" | "approved" | "rejected" | "expired";
303
+ /** @description gatekeeper: a gate as the HTTP API shows it (ADR 0048). */
304
+ GateView: {
305
+ /** @description "g" and 16 hex digits of the SHA-256 of the work item, the stage and the change. */
306
+ id: string;
307
+ workItem: string;
308
+ stage: components["schemas"]["Name"];
309
+ summary: string;
310
+ /** @description The risk the policy named, for example "high". */
311
+ risk?: string;
312
+ /** @description The groups whose members may decide. Empty when the policy approved without a person. */
313
+ approvers: components["schemas"]["Name"][];
314
+ /** @description The groups asked after the escalation time. */
315
+ escalateTo?: components["schemas"]["Name"][];
316
+ /** @description Where people decide, for example "slack:C0GATES". */
317
+ channel: string;
318
+ state: components["schemas"]["GateState"];
319
+ /** @description The groups that may decide now. Only while the gate is pending. */
320
+ waitingFor?: components["schemas"]["Name"][];
321
+ /** Format: date-time */
322
+ requestedAt: string;
323
+ /**
324
+ * Format: date-time
325
+ * @description When the gate expires without a decision.
326
+ */
327
+ expiresAt?: string;
328
+ /** @description The record, once the gate is decided. */
329
+ record?: components["schemas"]["GateRecord"];
330
+ };
331
+ /** @description A hostname without scheme or port, for example "api.linear.app". */
332
+ Hostname: string;
213
333
  /** @description An identifier chosen by the producer. ULIDs are recommended; consumers treat it as opaque. */
214
334
  Identifier: string;
215
335
  Link: {
@@ -367,6 +487,14 @@ export type components = {
367
487
  [key: string]: components["schemas"]["VersionRange"];
368
488
  };
369
489
  };
490
+ RecordSignature: {
491
+ /** @constant */
492
+ algorithm: "Ed25519";
493
+ /** @description SHA-256 of the public key in DER, like "sha256:…". */
494
+ key: string;
495
+ /** @description The signature in base64. */
496
+ value: string;
497
+ };
370
498
  /** @enum {string} */
371
499
  ReviewState: "approved" | "changes_requested" | "commented";
372
500
  /** @description foreman: a run ended. */
@@ -485,6 +613,42 @@ export type components = {
485
613
  /** @description Hostnames the sandbox may reach. Everything else is blocked. */
486
614
  egress?: string[];
487
615
  };
616
+ /** @description An MCP server that a sandbox may call over Streamable HTTP. */
617
+ SandboxMcpServer: {
618
+ /** @description The name in the egress log, for example "wiki". */
619
+ name: components["schemas"]["Name"];
620
+ /** @description The server's endpoint, for example "https://wiki.example.com/mcp". */
621
+ url: string;
622
+ /** @description The tools the sandbox may call. A call to any other tool is refused. */
623
+ tools: string[];
624
+ };
625
+ /**
626
+ * @description The input of a sandbox adapter's `create` (ADR 0054): what one sandbox runs, how much it may use, and what it may
627
+ * reach. Realizes SCN-FACTORY-RUNTIME-004, -006 and -007.
628
+ */
629
+ SandboxSpec: {
630
+ /** @description What the sandbox starts from: an image for the docker adapter, a SandboxTemplate for kubernetes, or a snapshot. */
631
+ template: string;
632
+ /** @description CPU cores. The smallest unit is 0.001 (one millicore). */
633
+ cpu?: number;
634
+ /** @description Kubernetes quantity, for example "8Gi". */
635
+ memory?: string;
636
+ /** @description Hostnames the sandbox may reach through its egress proxy. Everything else is refused. */
637
+ egress?: components["schemas"]["Hostname"][];
638
+ /** @description Variables of the sandbox's environment that hold no secret. */
639
+ env?: {
640
+ [key: string]: string;
641
+ };
642
+ /**
643
+ * @description Secrets by the name of the variable that holds the placeholder in the sandbox. The egress proxy puts the real
644
+ * value in on the way out, for the hosts of `egress`.
645
+ */
646
+ secrets?: {
647
+ [key: string]: components["schemas"]["SecretReference"];
648
+ };
649
+ /** @description The MCP servers the sandbox may call. A call to any other MCP server is refused. */
650
+ mcp?: components["schemas"]["SandboxMcpServer"][];
651
+ };
488
652
  ScenarioEvidence: {
489
653
  id: components["schemas"]["ScenarioId"];
490
654
  result: components["schemas"]["ScenarioResult"];
@@ -633,4 +797,96 @@ export type components = {
633
797
  pathItems: never;
634
798
  };
635
799
  export type $defs = Record<string, never>;
636
- export type operations = Record<string, never>;
800
+ export interface operations {
801
+ GatekeeperApi_requestGate: {
802
+ parameters: {
803
+ query?: never;
804
+ header?: never;
805
+ path?: never;
806
+ cookie?: never;
807
+ };
808
+ requestBody: {
809
+ content: {
810
+ "application/json": components["schemas"]["GateRequest"];
811
+ };
812
+ };
813
+ responses: {
814
+ /** @description The request has succeeded. */
815
+ 200: {
816
+ headers: {
817
+ [name: string]: unknown;
818
+ };
819
+ content: {
820
+ "application/json": components["schemas"]["GateView"];
821
+ };
822
+ };
823
+ /** @description The request has succeeded and a new resource has been created as a result. */
824
+ 201: {
825
+ headers: {
826
+ [name: string]: unknown;
827
+ };
828
+ content: {
829
+ "application/json": components["schemas"]["GateView"];
830
+ };
831
+ };
832
+ /** @description The server could not understand the request due to invalid syntax. */
833
+ 400: {
834
+ headers: {
835
+ [name: string]: unknown;
836
+ };
837
+ content: {
838
+ "application/problem+json": components["schemas"]["ApiProblem"];
839
+ };
840
+ };
841
+ /** @description Access is unauthorized. */
842
+ 401: {
843
+ headers: {
844
+ [name: string]: unknown;
845
+ };
846
+ content: {
847
+ "application/problem+json": components["schemas"]["ApiProblem"];
848
+ };
849
+ };
850
+ };
851
+ };
852
+ GatekeeperApi_getGate: {
853
+ parameters: {
854
+ query?: never;
855
+ header?: never;
856
+ path: {
857
+ gateId: string;
858
+ };
859
+ cookie?: never;
860
+ };
861
+ requestBody?: never;
862
+ responses: {
863
+ /** @description The request has succeeded. */
864
+ 200: {
865
+ headers: {
866
+ [name: string]: unknown;
867
+ };
868
+ content: {
869
+ "application/json": components["schemas"]["GateView"];
870
+ };
871
+ };
872
+ /** @description Access is unauthorized. */
873
+ 401: {
874
+ headers: {
875
+ [name: string]: unknown;
876
+ };
877
+ content: {
878
+ "application/problem+json": components["schemas"]["ApiProblem"];
879
+ };
880
+ };
881
+ /** @description The server cannot find the requested resource. */
882
+ 404: {
883
+ headers: {
884
+ [name: string]: unknown;
885
+ };
886
+ content: {
887
+ "application/problem+json": components["schemas"]["ApiProblem"];
888
+ };
889
+ };
890
+ };
891
+ };
892
+ }
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import { type Format } from "./formats.ts";
2
2
  import type { components } from "./generated/types.ts";
3
3
  export { diff as breakingChanges, type Schema } from "./breaking.ts";
4
4
  export { FORMATS, type Format, formatNamed } from "./formats.ts";
5
- export type { components } from "./generated/types.ts";
5
+ export type { components, paths } from "./generated/types.ts";
6
6
  export { type AttributeValue, type RunSpan, runSpans, type SpanAttributes } from "./run-record.ts";
7
7
  type Schemas = components["schemas"];
8
8
  export type FactoryDefinition = Schemas["FactoryDefinition"];
@@ -18,6 +18,11 @@ export type ScoreRecorded = Schemas["ScoreRecorded"];
18
18
  export type PrOpened = Schemas["PrOpened"];
19
19
  export type PrReviewed = Schemas["PrReviewed"];
20
20
  export type PrClosed = Schemas["PrClosed"];
21
+ export type GateRecord = Schemas["GateRecord"];
22
+ export type GateRequest = Schemas["GateRequest"];
23
+ export type GateView = Schemas["GateView"];
24
+ export type ApiProblem = Schemas["ApiProblem"];
25
+ export type SandboxSpec = Schemas["SandboxSpec"];
21
26
  /** One reason a document does not match its format. `path` is a JSON Pointer into the document. */
22
27
  export interface Problem {
23
28
  path: string;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,140 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://raw.githubusercontent.com/sesigl/open-software-factory/main/contracts/gate-record/gate-record.schema.json",
4
+ "title": "GateRecord",
5
+ "$comment": "Generated by `pnpm build` in contracts/ from typespec/. Do not edit.",
6
+ "type": "object",
7
+ "properties": {
8
+ "gate": {
9
+ "type": "string",
10
+ "pattern": "^g[0-9a-f]{16}$"
11
+ },
12
+ "workItem": {
13
+ "type": "string"
14
+ },
15
+ "stage": {
16
+ "type": "string",
17
+ "pattern": "^[a-z][a-z0-9-]{0,62}$",
18
+ "description": "A lowercase name: letters, digits and hyphens, starting with a letter. Agents, stages, adapters, sources."
19
+ },
20
+ "summary": {
21
+ "type": "string"
22
+ },
23
+ "request": {
24
+ "type": "string",
25
+ "pattern": "^sha256:[0-9a-f]{64}$",
26
+ "description": "SHA-256 of the canonical request: what was approved."
27
+ },
28
+ "policy": {
29
+ "type": "string",
30
+ "minLength": 1,
31
+ "description": "The policy file."
32
+ },
33
+ "policyDigest": {
34
+ "type": "string",
35
+ "pattern": "^sha256:[0-9a-f]{64}$",
36
+ "description": "SHA-256 of the policy's text: the rules that picked the approvers."
37
+ },
38
+ "risk": {
39
+ "type": "string"
40
+ },
41
+ "approvers": {
42
+ "type": "array",
43
+ "items": {
44
+ "type": "string",
45
+ "pattern": "^[a-z][a-z0-9-]{0,62}$",
46
+ "description": "A lowercase name: letters, digits and hyphens, starting with a letter. Agents, stages, adapters, sources."
47
+ }
48
+ },
49
+ "channel": {
50
+ "type": "string"
51
+ },
52
+ "requestedAt": {
53
+ "type": "string",
54
+ "format": "date-time"
55
+ },
56
+ "decision": {
57
+ "type": "string",
58
+ "enum": [
59
+ "approved",
60
+ "rejected",
61
+ "expired"
62
+ ]
63
+ },
64
+ "decidedBy": {
65
+ "type": "object",
66
+ "properties": {
67
+ "kind": {
68
+ "type": "string",
69
+ "enum": [
70
+ "person",
71
+ "trigger"
72
+ ],
73
+ "description": "Who caused something: a person, or an automated trigger such as a cron rule or an alert."
74
+ },
75
+ "id": {
76
+ "type": "string",
77
+ "minLength": 1,
78
+ "description": "Stable ID in the source system, prefixed with the source, for example \"slack:U024BE7LH\"."
79
+ },
80
+ "displayName": {
81
+ "type": "string",
82
+ "description": "Shown to people, for example \"Varun\"."
83
+ }
84
+ },
85
+ "required": [
86
+ "kind",
87
+ "id"
88
+ ],
89
+ "description": "Who decided. Absent only when the gate expired. A policy that names no group decides as a trigger."
90
+ },
91
+ "decidedAt": {
92
+ "type": "string",
93
+ "format": "date-time"
94
+ },
95
+ "reason": {
96
+ "type": "string",
97
+ "description": "The reason of a rejection."
98
+ },
99
+ "signature": {
100
+ "type": "object",
101
+ "properties": {
102
+ "algorithm": {
103
+ "type": "string",
104
+ "const": "Ed25519"
105
+ },
106
+ "key": {
107
+ "type": "string",
108
+ "pattern": "^sha256:",
109
+ "description": "SHA-256 of the public key in DER, like \"sha256:…\"."
110
+ },
111
+ "value": {
112
+ "type": "string",
113
+ "minLength": 1,
114
+ "description": "The signature in base64."
115
+ }
116
+ },
117
+ "required": [
118
+ "algorithm",
119
+ "key",
120
+ "value"
121
+ ],
122
+ "description": "Ed25519 over the canonical JSON of the rest of the record. Absent when the record is unsigned."
123
+ }
124
+ },
125
+ "required": [
126
+ "gate",
127
+ "workItem",
128
+ "stage",
129
+ "summary",
130
+ "request",
131
+ "policy",
132
+ "policyDigest",
133
+ "approvers",
134
+ "channel",
135
+ "requestedAt",
136
+ "decision",
137
+ "decidedAt"
138
+ ],
139
+ "description": "gatekeeper: who decided what and when, signed with Ed25519 (ADR 0047)."
140
+ }