@opensoftware/contracts 1.5.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 +1 -0
- package/dist/formats.js +1 -0
- package/dist/formats.js.map +1 -1
- package/dist/generated/types.d.ts +38 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js.map +1 -1
- package/openapi/openapi.json +90 -1
- package/package.json +2 -2
- package/sandbox-spec/sandbox-spec.schema.json +90 -0
- package/typespec/main.tsp +1 -0
- package/typespec/sandbox.tsp +63 -0
package/README.md
CHANGED
|
@@ -43,6 +43,7 @@ Each format has one schema, generated from `typespec/`, and fixtures that CONTRA
|
|
|
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
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. |
|
|
46
47
|
| events | `events/<event>/<event>.schema.json`, `events/asyncapi.yaml` | `WorkReceived` … `PrClosed` | CloudEvents 1.0, structured JSON. |
|
|
47
48
|
|
|
48
49
|
## HTTP APIs
|
package/dist/formats.js
CHANGED
|
@@ -7,6 +7,7 @@ export const FORMATS = [
|
|
|
7
7
|
format("evidence-bundle", "EvidenceManifest"),
|
|
8
8
|
format("score", "Score"),
|
|
9
9
|
format("gate-record", "GateRecord"),
|
|
10
|
+
format("sandbox-spec", "SandboxSpec"),
|
|
10
11
|
format("events/work-received", "WorkReceived"),
|
|
11
12
|
format("events/run-completed", "RunCompleted"),
|
|
12
13
|
format("events/gate-requested", "GateRequested"),
|
package/dist/formats.js.map
CHANGED
|
@@ -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,aAAa,EAAE,YAAY,CAAC;IACnC,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"}
|
|
@@ -328,6 +328,8 @@ export type components = {
|
|
|
328
328
|
/** @description The record, once the gate is decided. */
|
|
329
329
|
record?: components["schemas"]["GateRecord"];
|
|
330
330
|
};
|
|
331
|
+
/** @description A hostname without scheme or port, for example "api.linear.app". */
|
|
332
|
+
Hostname: string;
|
|
331
333
|
/** @description An identifier chosen by the producer. ULIDs are recommended; consumers treat it as opaque. */
|
|
332
334
|
Identifier: string;
|
|
333
335
|
Link: {
|
|
@@ -611,6 +613,42 @@ export type components = {
|
|
|
611
613
|
/** @description Hostnames the sandbox may reach. Everything else is blocked. */
|
|
612
614
|
egress?: string[];
|
|
613
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
|
+
};
|
|
614
652
|
ScenarioEvidence: {
|
|
615
653
|
id: components["schemas"]["ScenarioId"];
|
|
616
654
|
result: components["schemas"]["ScenarioResult"];
|
package/dist/index.d.ts
CHANGED
|
@@ -22,6 +22,7 @@ export type GateRecord = Schemas["GateRecord"];
|
|
|
22
22
|
export type GateRequest = Schemas["GateRequest"];
|
|
23
23
|
export type GateView = Schemas["GateView"];
|
|
24
24
|
export type ApiProblem = Schemas["ApiProblem"];
|
|
25
|
+
export type SandboxSpec = Schemas["SandboxSpec"];
|
|
25
26
|
/** One reason a document does not match its format. `path` is a JSON Pointer into the document. */
|
|
26
27
|
export interface Problem {
|
|
27
28
|
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": "1.
|
|
5
|
+
"version": "1.6.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",
|
|
@@ -941,6 +941,11 @@
|
|
|
941
941
|
],
|
|
942
942
|
"description": "gatekeeper: a gate as the HTTP API shows it (ADR 0048)."
|
|
943
943
|
},
|
|
944
|
+
"Hostname": {
|
|
945
|
+
"type": "string",
|
|
946
|
+
"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])?)*$",
|
|
947
|
+
"description": "A hostname without scheme or port, for example \"api.linear.app\"."
|
|
948
|
+
},
|
|
944
949
|
"Identifier": {
|
|
945
950
|
"type": "string",
|
|
946
951
|
"minLength": 1,
|
|
@@ -1688,6 +1693,90 @@
|
|
|
1688
1693
|
],
|
|
1689
1694
|
"additionalProperties": false
|
|
1690
1695
|
},
|
|
1696
|
+
"SandboxMcpServer": {
|
|
1697
|
+
"type": "object",
|
|
1698
|
+
"properties": {
|
|
1699
|
+
"name": {
|
|
1700
|
+
"$ref": "#/components/schemas/Name",
|
|
1701
|
+
"description": "The name in the egress log, for example \"wiki\"."
|
|
1702
|
+
},
|
|
1703
|
+
"url": {
|
|
1704
|
+
"type": "string",
|
|
1705
|
+
"pattern": "^https?://[^/]+",
|
|
1706
|
+
"description": "The server's endpoint, for example \"https://wiki.example.com/mcp\"."
|
|
1707
|
+
},
|
|
1708
|
+
"tools": {
|
|
1709
|
+
"type": "array",
|
|
1710
|
+
"items": {
|
|
1711
|
+
"type": "string"
|
|
1712
|
+
},
|
|
1713
|
+
"minItems": 1,
|
|
1714
|
+
"description": "The tools the sandbox may call. A call to any other tool is refused."
|
|
1715
|
+
}
|
|
1716
|
+
},
|
|
1717
|
+
"required": [
|
|
1718
|
+
"name",
|
|
1719
|
+
"url",
|
|
1720
|
+
"tools"
|
|
1721
|
+
],
|
|
1722
|
+
"description": "An MCP server that a sandbox may call over Streamable HTTP.",
|
|
1723
|
+
"additionalProperties": false
|
|
1724
|
+
},
|
|
1725
|
+
"SandboxSpec": {
|
|
1726
|
+
"type": "object",
|
|
1727
|
+
"properties": {
|
|
1728
|
+
"template": {
|
|
1729
|
+
"type": "string",
|
|
1730
|
+
"minLength": 1,
|
|
1731
|
+
"description": "What the sandbox starts from: an image for the docker adapter, a SandboxTemplate for kubernetes, or a snapshot."
|
|
1732
|
+
},
|
|
1733
|
+
"cpu": {
|
|
1734
|
+
"type": "number",
|
|
1735
|
+
"minimum": 0.001,
|
|
1736
|
+
"description": "CPU cores. The smallest unit is 0.001 (one millicore)."
|
|
1737
|
+
},
|
|
1738
|
+
"memory": {
|
|
1739
|
+
"type": "string",
|
|
1740
|
+
"pattern": "^[0-9]+(Ki|Mi|Gi|Ti)?$",
|
|
1741
|
+
"description": "Kubernetes quantity, for example \"8Gi\"."
|
|
1742
|
+
},
|
|
1743
|
+
"egress": {
|
|
1744
|
+
"type": "array",
|
|
1745
|
+
"items": {
|
|
1746
|
+
"$ref": "#/components/schemas/Hostname"
|
|
1747
|
+
},
|
|
1748
|
+
"description": "Hostnames the sandbox may reach through its egress proxy. Everything else is refused."
|
|
1749
|
+
},
|
|
1750
|
+
"env": {
|
|
1751
|
+
"type": "object",
|
|
1752
|
+
"properties": {},
|
|
1753
|
+
"unevaluatedProperties": {
|
|
1754
|
+
"type": "string"
|
|
1755
|
+
},
|
|
1756
|
+
"description": "Variables of the sandbox's environment that hold no secret."
|
|
1757
|
+
},
|
|
1758
|
+
"secrets": {
|
|
1759
|
+
"type": "object",
|
|
1760
|
+
"properties": {},
|
|
1761
|
+
"unevaluatedProperties": {
|
|
1762
|
+
"$ref": "#/components/schemas/SecretReference"
|
|
1763
|
+
},
|
|
1764
|
+
"description": "Secrets by the name of the variable that holds the placeholder in the sandbox. The egress proxy puts the real\nvalue in on the way out, for the hosts of `egress`."
|
|
1765
|
+
},
|
|
1766
|
+
"mcp": {
|
|
1767
|
+
"type": "array",
|
|
1768
|
+
"items": {
|
|
1769
|
+
"$ref": "#/components/schemas/SandboxMcpServer"
|
|
1770
|
+
},
|
|
1771
|
+
"description": "The MCP servers the sandbox may call. A call to any other MCP server is refused."
|
|
1772
|
+
}
|
|
1773
|
+
},
|
|
1774
|
+
"required": [
|
|
1775
|
+
"template"
|
|
1776
|
+
],
|
|
1777
|
+
"description": "The input of a sandbox adapter's `create` (ADR 0054): what one sandbox runs, how much it may use, and what it may\nreach. Realizes SCN-FACTORY-RUNTIME-004, -006 and -007.",
|
|
1778
|
+
"additionalProperties": false
|
|
1779
|
+
},
|
|
1691
1780
|
"ScenarioEvidence": {
|
|
1692
1781
|
"type": "object",
|
|
1693
1782
|
"properties": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opensoftware/contracts",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.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.16.0"
|
|
48
48
|
},
|
|
49
49
|
"scripts": {
|
|
50
50
|
"build": "node scripts/build.ts",
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://raw.githubusercontent.com/sesigl/open-software-factory/main/contracts/sandbox-spec/sandbox-spec.schema.json",
|
|
4
|
+
"title": "SandboxSpec",
|
|
5
|
+
"$comment": "Generated by `pnpm build` in contracts/ from typespec/. Do not edit.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"properties": {
|
|
8
|
+
"template": {
|
|
9
|
+
"type": "string",
|
|
10
|
+
"minLength": 1,
|
|
11
|
+
"description": "What the sandbox starts from: an image for the docker adapter, a SandboxTemplate for kubernetes, or a snapshot."
|
|
12
|
+
},
|
|
13
|
+
"cpu": {
|
|
14
|
+
"type": "number",
|
|
15
|
+
"minimum": 0.001,
|
|
16
|
+
"description": "CPU cores. The smallest unit is 0.001 (one millicore)."
|
|
17
|
+
},
|
|
18
|
+
"memory": {
|
|
19
|
+
"type": "string",
|
|
20
|
+
"pattern": "^[0-9]+(Ki|Mi|Gi|Ti)?$",
|
|
21
|
+
"description": "Kubernetes quantity, for example \"8Gi\"."
|
|
22
|
+
},
|
|
23
|
+
"egress": {
|
|
24
|
+
"type": "array",
|
|
25
|
+
"items": {
|
|
26
|
+
"type": "string",
|
|
27
|
+
"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])?)*$",
|
|
28
|
+
"description": "A hostname without scheme or port, for example \"api.linear.app\"."
|
|
29
|
+
},
|
|
30
|
+
"description": "Hostnames the sandbox may reach through its egress proxy. Everything else is refused."
|
|
31
|
+
},
|
|
32
|
+
"env": {
|
|
33
|
+
"type": "object",
|
|
34
|
+
"properties": {},
|
|
35
|
+
"unevaluatedProperties": {
|
|
36
|
+
"type": "string"
|
|
37
|
+
},
|
|
38
|
+
"description": "Variables of the sandbox's environment that hold no secret."
|
|
39
|
+
},
|
|
40
|
+
"secrets": {
|
|
41
|
+
"type": "object",
|
|
42
|
+
"properties": {},
|
|
43
|
+
"unevaluatedProperties": {
|
|
44
|
+
"type": "string",
|
|
45
|
+
"pattern": "^ref:[a-z][a-z0-9-]*/[A-Za-z0-9_./-]+$",
|
|
46
|
+
"description": "A reference to a secret, resolved at the egress proxy, never in the sandbox: \"ref:<provider>/<name>\"."
|
|
47
|
+
},
|
|
48
|
+
"description": "Secrets by the name of the variable that holds the placeholder in the sandbox. The egress proxy puts the real\nvalue in on the way out, for the hosts of `egress`."
|
|
49
|
+
},
|
|
50
|
+
"mcp": {
|
|
51
|
+
"type": "array",
|
|
52
|
+
"items": {
|
|
53
|
+
"type": "object",
|
|
54
|
+
"properties": {
|
|
55
|
+
"name": {
|
|
56
|
+
"type": "string",
|
|
57
|
+
"pattern": "^[a-z][a-z0-9-]{0,62}$",
|
|
58
|
+
"description": "The name in the egress log, for example \"wiki\"."
|
|
59
|
+
},
|
|
60
|
+
"url": {
|
|
61
|
+
"type": "string",
|
|
62
|
+
"pattern": "^https?://[^/]+",
|
|
63
|
+
"description": "The server's endpoint, for example \"https://wiki.example.com/mcp\"."
|
|
64
|
+
},
|
|
65
|
+
"tools": {
|
|
66
|
+
"type": "array",
|
|
67
|
+
"items": {
|
|
68
|
+
"type": "string"
|
|
69
|
+
},
|
|
70
|
+
"minItems": 1,
|
|
71
|
+
"description": "The tools the sandbox may call. A call to any other tool is refused."
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
"required": [
|
|
75
|
+
"name",
|
|
76
|
+
"url",
|
|
77
|
+
"tools"
|
|
78
|
+
],
|
|
79
|
+
"description": "An MCP server that a sandbox may call over Streamable HTTP.",
|
|
80
|
+
"additionalProperties": false
|
|
81
|
+
},
|
|
82
|
+
"description": "The MCP servers the sandbox may call. A call to any other MCP server is refused."
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
"required": [
|
|
86
|
+
"template"
|
|
87
|
+
],
|
|
88
|
+
"description": "The input of a sandbox adapter's `create` (ADR 0054): what one sandbox runs, how much it may use, and what it may\nreach. Realizes SCN-FACTORY-RUNTIME-004, -006 and -007.",
|
|
89
|
+
"additionalProperties": false
|
|
90
|
+
}
|
package/typespec/main.tsp
CHANGED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import "@typespec/json-schema";
|
|
2
|
+
import "./common.tsp";
|
|
3
|
+
import "./factory-definition.tsp";
|
|
4
|
+
|
|
5
|
+
using TypeSpec.JsonSchema;
|
|
6
|
+
|
|
7
|
+
namespace Osf.Contracts;
|
|
8
|
+
|
|
9
|
+
// The sandbox spec is written by a program (foreman) for a sandbox adapter, and a sandbox must never get more than
|
|
10
|
+
// it asked for: every object is closed, so an unknown field is an error and not a silent grant.
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The input of a sandbox adapter's `create` (ADR 0054): what one sandbox runs, how much it may use, and what it may
|
|
14
|
+
* reach. Realizes SCN-FACTORY-RUNTIME-004, -006 and -007.
|
|
15
|
+
*/
|
|
16
|
+
@extension("additionalProperties", Json<false>)
|
|
17
|
+
model SandboxSpec {
|
|
18
|
+
/** What the sandbox starts from: an image for the docker adapter, a SandboxTemplate for kubernetes, or a snapshot. */
|
|
19
|
+
@minLength(1)
|
|
20
|
+
template: string;
|
|
21
|
+
|
|
22
|
+
/** CPU cores. The smallest unit is 0.001 (one millicore). */
|
|
23
|
+
@minValue(0.001)
|
|
24
|
+
cpu?: float64;
|
|
25
|
+
|
|
26
|
+
/** Kubernetes quantity, for example "8Gi". */
|
|
27
|
+
@pattern("^[0-9]+(Ki|Mi|Gi|Ti)?$")
|
|
28
|
+
memory?: string;
|
|
29
|
+
|
|
30
|
+
/** Hostnames the sandbox may reach through its egress proxy. Everything else is refused. */
|
|
31
|
+
egress?: Hostname[];
|
|
32
|
+
|
|
33
|
+
/** Variables of the sandbox's environment that hold no secret. */
|
|
34
|
+
env?: Record<string>;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Secrets by the name of the variable that holds the placeholder in the sandbox. The egress proxy puts the real
|
|
38
|
+
* value in on the way out, for the hosts of `egress`.
|
|
39
|
+
*/
|
|
40
|
+
secrets?: Record<SecretReference>;
|
|
41
|
+
|
|
42
|
+
/** The MCP servers the sandbox may call. A call to any other MCP server is refused. */
|
|
43
|
+
mcp?: SandboxMcpServer[];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** A hostname without scheme or port, for example "api.linear.app". */
|
|
47
|
+
@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])?)*$")
|
|
48
|
+
scalar Hostname extends string;
|
|
49
|
+
|
|
50
|
+
/** An MCP server that a sandbox may call over Streamable HTTP. */
|
|
51
|
+
@extension("additionalProperties", Json<false>)
|
|
52
|
+
model SandboxMcpServer {
|
|
53
|
+
/** The name in the egress log, for example "wiki". */
|
|
54
|
+
name: Name;
|
|
55
|
+
|
|
56
|
+
/** The server's endpoint, for example "https://wiki.example.com/mcp". */
|
|
57
|
+
@pattern("^https?://[^/]+")
|
|
58
|
+
url: string;
|
|
59
|
+
|
|
60
|
+
/** The tools the sandbox may call. A call to any other tool is refused. */
|
|
61
|
+
@minItems(1)
|
|
62
|
+
tools: string[];
|
|
63
|
+
}
|