@opensoftware/contracts 2.6.0 → 2.7.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
@@ -54,6 +54,8 @@ Each format has one schema, generated from `typespec/`, and fixtures that CONTRA
54
54
  | factory lock | `factory-lock/factory-lock.schema.json` | `FactoryLock` | `factory.lock` next to `factory.yaml`: the registry MCP servers, the adapters and the skills of other Git repositories that `factory plan` pinned, a skill with its commit and the hash of its files (ADR 0020, ADR 0125, ADR 0146). factory-spec writes it, the foreman reads the adapter pins and the skill pins. |
55
55
  | access | `access/access.schema.json` | `Access` | `access.yaml` next to `factory.yaml`: the people who may sign in to the factory UI, each by email with one role, `member`, `factory-engineer` or `admin` (ADR 0134). The console reads it at each request. |
56
56
  | skill catalog | `skill-catalog/skill-catalog.schema.json` | `SkillCatalog` | What `factory skills` prints: every skill the factory's agents use, with its needs, its agents and what each lacks, its files, the Markdown of its `SKILL.md` and its problems, and for a skill of another Git repository its URL and commit (ADR 0141, ADR 0143, ADR 0146). factory-spec writes it, the console reads it for `/skills`. |
57
+ | person proof | `person-proof/person-proof.schema.json` | `PersonProof` | The claims of the JSON Web Token in the header `OSF-Person` that the console signs for one call of a module API in a person's name: the issuer, the person and their role, the module as the audience, 30 seconds from its issue, and the request's method, path and the SHA-256 of its body (ADR 0151). foreman, intake and gatekeeper check it. Open: a reader ignores a claim it does not know. |
58
+ | person keys | `person-keys/person-keys.schema.json` | `PersonKeys` | The JSON Web Key Set of an issuer of person proofs, as the console publishes it at `/.well-known/jwks.json`: Ed25519 public keys, each with its thumbprint as `kid` (ADR 0151). Closed: a key with a private part is invalid. |
57
59
  | events | `events/<event>/<event>.schema.json`, `events/asyncapi.yaml` | `WorkReceived`, `WorkRetryRequested`, `RunStarted`, `RunCompleted`, `RunBlocked`, `DoctorPing` … `IssueLabeled` | CloudEvents 1.0, structured JSON. |
58
60
 
59
61
  ## HTTP APIs
@@ -176,3 +178,9 @@ None. The CLI reads no environment variables.
176
178
  | SCN-CTR-022 | implemented | A pinned skill with a short commit is rejected with its path |
177
179
  | SCN-CTR-023 | implemented | The pins of skills in factory.lock are no breaking change |
178
180
  | SCN-CTR-024 | implemented | A skill catalog with a skill of another repository at its commit validates |
181
+ | SCN-CTR-025 | implemented | A person proof for one call of the foreman validates |
182
+ | SCN-CTR-026 | implemented | A person proof without claims is rejected with the path of each required claim |
183
+ | SCN-CTR-027 | implemented | A person proof with an unknown role, a method in lower case and a short body digest is rejected with their paths |
184
+ | SCN-CTR-028 | implemented | A key set with one Ed25519 public key validates |
185
+ | SCN-CTR-029 | implemented | A key set whose key holds its private part is rejected with its path |
186
+ | SCN-CTR-030 | implemented | The person proof and its key set are no breaking change |
package/dist/formats.js CHANGED
@@ -11,6 +11,8 @@ export const FORMATS = [
11
11
  format("factory-lock", "FactoryLock"),
12
12
  format("access", "Access"),
13
13
  format("skill-catalog", "SkillCatalog"),
14
+ format("person-proof", "PersonProof"),
15
+ format("person-keys", "PersonKeys"),
14
16
  format("events/work-received", "WorkReceived"),
15
17
  format("events/work-retry-requested", "WorkRetryRequested"),
16
18
  format("events/run-started", "RunStarted"),
@@ -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,cAAc,EAAE,aAAa,CAAC;IACrC,MAAM,CAAC,cAAc,EAAE,aAAa,CAAC;IACrC,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC1B,MAAM,CAAC,eAAe,EAAE,cAAc,CAAC;IACvC,MAAM,CAAC,sBAAsB,EAAE,cAAc,CAAC;IAC9C,MAAM,CAAC,6BAA6B,EAAE,oBAAoB,CAAC;IAC3D,MAAM,CAAC,oBAAoB,EAAE,YAAY,CAAC;IAC1C,MAAM,CAAC,sBAAsB,EAAE,cAAc,CAAC;IAC9C,MAAM,CAAC,oBAAoB,EAAE,YAAY,CAAC;IAC1C,MAAM,CAAC,oBAAoB,EAAE,YAAY,CAAC;IAC1C,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;IACtC,MAAM,CAAC,sBAAsB,EAAE,cAAc,CAAC;CAC/C,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,cAAc,EAAE,aAAa,CAAC;IACrC,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC1B,MAAM,CAAC,eAAe,EAAE,cAAc,CAAC;IACvC,MAAM,CAAC,cAAc,EAAE,aAAa,CAAC;IACrC,MAAM,CAAC,aAAa,EAAE,YAAY,CAAC;IACnC,MAAM,CAAC,sBAAsB,EAAE,cAAc,CAAC;IAC9C,MAAM,CAAC,6BAA6B,EAAE,oBAAoB,CAAC;IAC3D,MAAM,CAAC,oBAAoB,EAAE,YAAY,CAAC;IAC1C,MAAM,CAAC,sBAAsB,EAAE,cAAc,CAAC;IAC9C,MAAM,CAAC,oBAAoB,EAAE,YAAY,CAAC;IAC1C,MAAM,CAAC,oBAAoB,EAAE,YAAY,CAAC;IAC1C,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;IACtC,MAAM,CAAC,sBAAsB,EAAE,cAAc,CAAC;CAC/C,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"}
@@ -334,6 +334,8 @@ export type components = {
334
334
  /** @description Job to run. Required with `cron`; without it an event starts the workflow. */
335
335
  run?: components["schemas"]["Name"];
336
336
  } & (unknown | unknown);
337
+ /** @description 43 characters of base64url without padding: 32 bytes, like a SHA-256 or an Ed25519 public key. */
338
+ Base64url32: string;
337
339
  Benchmark: {
338
340
  /** @description Path to the Harbor task suite. */
339
341
  suite: string;
@@ -827,6 +829,55 @@ export type components = {
827
829
  /** @description ID in the source system. */
828
830
  externalId?: string;
829
831
  };
832
+ /** @description One Ed25519 public key. Closed: a key with its private part `d` or any other member is invalid. */
833
+ PersonKey: {
834
+ /** @constant */
835
+ kty: "OKP";
836
+ /** @constant */
837
+ crv: "Ed25519";
838
+ /** @constant */
839
+ alg: "Ed25519";
840
+ /** @constant */
841
+ use: "sig";
842
+ /** @description The key's JWK thumbprint (RFC 7638) with SHA-256; a proof names it in its `kid`. */
843
+ kid: components["schemas"]["Base64url32"];
844
+ /** @description The public key. */
845
+ x: components["schemas"]["Base64url32"];
846
+ };
847
+ /**
848
+ * @description The public keys of an issuer of person proofs (ADR 0151): a JSON Web Key Set (RFC 7517), as the console publishes it
849
+ * at `/.well-known/jwks.json`. The first key of the issuer's setting signs; every key here verifies.
850
+ */
851
+ PersonKeys: {
852
+ keys: components["schemas"]["PersonKey"][];
853
+ };
854
+ /**
855
+ * @description The claims of a person proof (ADR 0151): the JSON Web Token that the console signs for one call of a module API in
856
+ * the name of a person, sent in the header `OSF-Person`, signed with `alg` "Ed25519" and `typ` "osf-person+jwt". It is
857
+ * bound to one module, one request and 30 seconds. Open: a module ignores a claim it does not know.
858
+ */
859
+ PersonProof: {
860
+ /** @description The issuer: "console" for the console, or the name a team gives its own tool in the modules' setting. */
861
+ iss: components["schemas"]["Name"];
862
+ /** @description The person, as the module records the actor's `id`: an email in lower case, or the sign-in proxy's value. */
863
+ sub: string;
864
+ /** @description The name to show, recorded as the actor's `displayName`. */
865
+ name?: string;
866
+ /** @description The person's role from the access file at the time of the call. */
867
+ role: components["schemas"]["AccessRole"];
868
+ /** @description The module the call goes to: "foreman", "intake" or "gatekeeper". */
869
+ aud: components["schemas"]["Name"];
870
+ /** @description When it was signed, in seconds since 1970-01-01T00:00:00Z. */
871
+ iat: number;
872
+ /** @description When it ends, in seconds since 1970-01-01T00:00:00Z; at most 60 seconds after `iat`. */
873
+ exp: number;
874
+ /** @description The request's method in upper case. */
875
+ method: string;
876
+ /** @description The request's path as sent in the request line, without the query. */
877
+ path: string;
878
+ /** @description The SHA-256 of the request's body bytes as sent, in base64url without padding. */
879
+ bodyDigest: components["schemas"]["Base64url32"];
880
+ };
830
881
  /** @description forge adapters: a pull request was merged or closed without a merge. */
831
882
  PrClosed: {
832
883
  /** @constant */
package/dist/index.d.ts CHANGED
@@ -50,6 +50,9 @@ export type SkillCatalog = Schemas["SkillCatalog"];
50
50
  export type CatalogSkill = Schemas["CatalogSkill"];
51
51
  export type CatalogSkillAgent = Schemas["CatalogSkillAgent"];
52
52
  export type SkillNeeds = Schemas["SkillNeeds"];
53
+ export type PersonProof = Schemas["PersonProof"];
54
+ export type PersonKeys = Schemas["PersonKeys"];
55
+ export type PersonKey = Schemas["PersonKey"];
53
56
  export type Health = Schemas["Health"];
54
57
  export type HealthCheck = Schemas["HealthCheck"];
55
58
  /** One reason a document does not match its format. `path` is a JSON Pointer into the document. */
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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"}
@@ -2,7 +2,7 @@
2
2
  "openapi": "3.1.0",
3
3
  "info": {
4
4
  "title": "Open Software Factory contracts",
5
- "version": "2.6.0",
5
+ "version": "2.7.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",
@@ -1173,6 +1173,11 @@
1173
1173
  ],
1174
1174
  "additionalProperties": false
1175
1175
  },
1176
+ "Base64url32": {
1177
+ "type": "string",
1178
+ "pattern": "^[A-Za-z0-9_-]{43}$",
1179
+ "description": "43 characters of base64url without padding: 32 bytes, like a SHA-256 or an Ed25519 public key."
1180
+ },
1176
1181
  "Benchmark": {
1177
1182
  "type": "object",
1178
1183
  "properties": {
@@ -2445,6 +2450,125 @@
2445
2450
  "source"
2446
2451
  ]
2447
2452
  },
2453
+ "PersonKey": {
2454
+ "type": "object",
2455
+ "properties": {
2456
+ "kty": {
2457
+ "type": "string",
2458
+ "const": "OKP"
2459
+ },
2460
+ "crv": {
2461
+ "type": "string",
2462
+ "const": "Ed25519"
2463
+ },
2464
+ "alg": {
2465
+ "type": "string",
2466
+ "const": "Ed25519"
2467
+ },
2468
+ "use": {
2469
+ "type": "string",
2470
+ "const": "sig"
2471
+ },
2472
+ "kid": {
2473
+ "$ref": "#/components/schemas/Base64url32",
2474
+ "description": "The key's JWK thumbprint (RFC 7638) with SHA-256; a proof names it in its `kid`."
2475
+ },
2476
+ "x": {
2477
+ "$ref": "#/components/schemas/Base64url32",
2478
+ "description": "The public key."
2479
+ }
2480
+ },
2481
+ "required": [
2482
+ "kty",
2483
+ "crv",
2484
+ "alg",
2485
+ "use",
2486
+ "kid",
2487
+ "x"
2488
+ ],
2489
+ "description": "One Ed25519 public key. Closed: a key with its private part `d` or any other member is invalid.",
2490
+ "additionalProperties": false
2491
+ },
2492
+ "PersonKeys": {
2493
+ "type": "object",
2494
+ "properties": {
2495
+ "keys": {
2496
+ "type": "array",
2497
+ "items": {
2498
+ "$ref": "#/components/schemas/PersonKey"
2499
+ },
2500
+ "minItems": 1
2501
+ }
2502
+ },
2503
+ "required": [
2504
+ "keys"
2505
+ ],
2506
+ "description": "The public keys of an issuer of person proofs (ADR 0151): a JSON Web Key Set (RFC 7517), as the console publishes it\nat `/.well-known/jwks.json`. The first key of the issuer's setting signs; every key here verifies.",
2507
+ "additionalProperties": false
2508
+ },
2509
+ "PersonProof": {
2510
+ "type": "object",
2511
+ "properties": {
2512
+ "iss": {
2513
+ "$ref": "#/components/schemas/Name",
2514
+ "description": "The issuer: \"console\" for the console, or the name a team gives its own tool in the modules' setting."
2515
+ },
2516
+ "sub": {
2517
+ "type": "string",
2518
+ "minLength": 1,
2519
+ "description": "The person, as the module records the actor's `id`: an email in lower case, or the sign-in proxy's value."
2520
+ },
2521
+ "name": {
2522
+ "type": "string",
2523
+ "minLength": 1,
2524
+ "description": "The name to show, recorded as the actor's `displayName`."
2525
+ },
2526
+ "role": {
2527
+ "$ref": "#/components/schemas/AccessRole",
2528
+ "description": "The person's role from the access file at the time of the call."
2529
+ },
2530
+ "aud": {
2531
+ "$ref": "#/components/schemas/Name",
2532
+ "description": "The module the call goes to: \"foreman\", \"intake\" or \"gatekeeper\"."
2533
+ },
2534
+ "iat": {
2535
+ "type": "integer",
2536
+ "minimum": 0,
2537
+ "description": "When it was signed, in seconds since 1970-01-01T00:00:00Z."
2538
+ },
2539
+ "exp": {
2540
+ "type": "integer",
2541
+ "minimum": 0,
2542
+ "description": "When it ends, in seconds since 1970-01-01T00:00:00Z; at most 60 seconds after `iat`."
2543
+ },
2544
+ "method": {
2545
+ "type": "string",
2546
+ "pattern": "^[A-Z]+$",
2547
+ "description": "The request's method in upper case."
2548
+ },
2549
+ "path": {
2550
+ "type": "string",
2551
+ "pattern": "^/[^?#]*$",
2552
+ "description": "The request's path as sent in the request line, without the query."
2553
+ },
2554
+ "bodyDigest": {
2555
+ "$ref": "#/components/schemas/Base64url32",
2556
+ "description": "The SHA-256 of the request's body bytes as sent, in base64url without padding."
2557
+ }
2558
+ },
2559
+ "required": [
2560
+ "iss",
2561
+ "sub",
2562
+ "role",
2563
+ "aud",
2564
+ "iat",
2565
+ "exp",
2566
+ "method",
2567
+ "path",
2568
+ "bodyDigest"
2569
+ ],
2570
+ "description": "The claims of a person proof (ADR 0151): the JSON Web Token that the console signs for one call of a module API in\nthe name of a person, sent in the header `OSF-Person`, signed with `alg` \"Ed25519\" and `typ` \"osf-person+jwt\". It is\nbound to one module, one request and 30 seconds. Open: a module ignores a claim it does not know."
2571
+ },
2448
2572
  "PrClosed": {
2449
2573
  "type": "object",
2450
2574
  "properties": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opensoftware/contracts",
3
- "version": "2.6.0",
3
+ "version": "2.7.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": {
@@ -0,0 +1,59 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://raw.githubusercontent.com/sesigl/open-software-factory/main/contracts/person-keys/person-keys.schema.json",
4
+ "title": "PersonKeys",
5
+ "$comment": "Generated by `pnpm build` in contracts/ from typespec/. Do not edit.",
6
+ "type": "object",
7
+ "properties": {
8
+ "keys": {
9
+ "type": "array",
10
+ "items": {
11
+ "type": "object",
12
+ "properties": {
13
+ "kty": {
14
+ "type": "string",
15
+ "const": "OKP"
16
+ },
17
+ "crv": {
18
+ "type": "string",
19
+ "const": "Ed25519"
20
+ },
21
+ "alg": {
22
+ "type": "string",
23
+ "const": "Ed25519"
24
+ },
25
+ "use": {
26
+ "type": "string",
27
+ "const": "sig"
28
+ },
29
+ "kid": {
30
+ "type": "string",
31
+ "pattern": "^[A-Za-z0-9_-]{43}$",
32
+ "description": "The key's JWK thumbprint (RFC 7638) with SHA-256; a proof names it in its `kid`."
33
+ },
34
+ "x": {
35
+ "type": "string",
36
+ "pattern": "^[A-Za-z0-9_-]{43}$",
37
+ "description": "The public key."
38
+ }
39
+ },
40
+ "required": [
41
+ "kty",
42
+ "crv",
43
+ "alg",
44
+ "use",
45
+ "kid",
46
+ "x"
47
+ ],
48
+ "description": "One Ed25519 public key. Closed: a key with its private part `d` or any other member is invalid.",
49
+ "additionalProperties": false
50
+ },
51
+ "minItems": 1
52
+ }
53
+ },
54
+ "required": [
55
+ "keys"
56
+ ],
57
+ "description": "The public keys of an issuer of person proofs (ADR 0151): a JSON Web Key Set (RFC 7517), as the console publishes it\nat `/.well-known/jwks.json`. The first key of the issuer's setting signs; every key here verifies.",
58
+ "additionalProperties": false
59
+ }
@@ -0,0 +1,75 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://raw.githubusercontent.com/sesigl/open-software-factory/main/contracts/person-proof/person-proof.schema.json",
4
+ "title": "PersonProof",
5
+ "$comment": "Generated by `pnpm build` in contracts/ from typespec/. Do not edit.",
6
+ "type": "object",
7
+ "properties": {
8
+ "iss": {
9
+ "type": "string",
10
+ "pattern": "^[a-z][a-z0-9-]{0,62}$",
11
+ "description": "The issuer: \"console\" for the console, or the name a team gives its own tool in the modules' setting."
12
+ },
13
+ "sub": {
14
+ "type": "string",
15
+ "minLength": 1,
16
+ "description": "The person, as the module records the actor's `id`: an email in lower case, or the sign-in proxy's value."
17
+ },
18
+ "name": {
19
+ "type": "string",
20
+ "minLength": 1,
21
+ "description": "The name to show, recorded as the actor's `displayName`."
22
+ },
23
+ "role": {
24
+ "type": "string",
25
+ "enum": [
26
+ "member",
27
+ "factory-engineer",
28
+ "admin"
29
+ ],
30
+ "description": "The person's role from the access file at the time of the call."
31
+ },
32
+ "aud": {
33
+ "type": "string",
34
+ "pattern": "^[a-z][a-z0-9-]{0,62}$",
35
+ "description": "The module the call goes to: \"foreman\", \"intake\" or \"gatekeeper\"."
36
+ },
37
+ "iat": {
38
+ "type": "integer",
39
+ "minimum": 0,
40
+ "description": "When it was signed, in seconds since 1970-01-01T00:00:00Z."
41
+ },
42
+ "exp": {
43
+ "type": "integer",
44
+ "minimum": 0,
45
+ "description": "When it ends, in seconds since 1970-01-01T00:00:00Z; at most 60 seconds after `iat`."
46
+ },
47
+ "method": {
48
+ "type": "string",
49
+ "pattern": "^[A-Z]+$",
50
+ "description": "The request's method in upper case."
51
+ },
52
+ "path": {
53
+ "type": "string",
54
+ "pattern": "^/[^?#]*$",
55
+ "description": "The request's path as sent in the request line, without the query."
56
+ },
57
+ "bodyDigest": {
58
+ "type": "string",
59
+ "pattern": "^[A-Za-z0-9_-]{43}$",
60
+ "description": "The SHA-256 of the request's body bytes as sent, in base64url without padding."
61
+ }
62
+ },
63
+ "required": [
64
+ "iss",
65
+ "sub",
66
+ "role",
67
+ "aud",
68
+ "iat",
69
+ "exp",
70
+ "method",
71
+ "path",
72
+ "bodyDigest"
73
+ ],
74
+ "description": "The claims of a person proof (ADR 0151): the JSON Web Token that the console signs for one call of a module API in\nthe name of a person, sent in the header `OSF-Person`, signed with `alg` \"Ed25519\" and `typ` \"osf-person+jwt\". It is\nbound to one module, one request and 30 seconds. Open: a module ignores a claim it does not know."
75
+ }
package/typespec/main.tsp CHANGED
@@ -18,4 +18,5 @@ import "./sandbox.tsp";
18
18
  import "./factory-lock.tsp";
19
19
  import "./access.tsp";
20
20
  import "./skill-catalog.tsp";
21
+ import "./person-proof.tsp";
21
22
  import "./health.tsp";
@@ -0,0 +1,79 @@
1
+ import "@typespec/json-schema";
2
+ import "./common.tsp";
3
+ import "./access.tsp";
4
+
5
+ using TypeSpec.JsonSchema;
6
+
7
+ namespace Osf.Contracts;
8
+
9
+ /** 43 characters of base64url without padding: 32 bytes, like a SHA-256 or an Ed25519 public key. */
10
+ @pattern("^[A-Za-z0-9_-]{43}$")
11
+ scalar Base64url32 extends string;
12
+
13
+ /**
14
+ * The claims of a person proof (ADR 0151): the JSON Web Token that the console signs for one call of a module API in
15
+ * the name of a person, sent in the header `OSF-Person`, signed with `alg` "Ed25519" and `typ` "osf-person+jwt". It is
16
+ * bound to one module, one request and 30 seconds. Open: a module ignores a claim it does not know.
17
+ */
18
+ model PersonProof {
19
+ /** The issuer: "console" for the console, or the name a team gives its own tool in the modules' setting. */
20
+ iss: Name;
21
+
22
+ /** The person, as the module records the actor's `id`: an email in lower case, or the sign-in proxy's value. */
23
+ @minLength(1)
24
+ sub: string;
25
+
26
+ /** The name to show, recorded as the actor's `displayName`. */
27
+ @minLength(1)
28
+ name?: string;
29
+
30
+ /** The person's role from the access file at the time of the call. */
31
+ role: AccessRole;
32
+
33
+ /** The module the call goes to: "foreman", "intake" or "gatekeeper". */
34
+ aud: Name;
35
+
36
+ /** When it was signed, in seconds since 1970-01-01T00:00:00Z. */
37
+ @minValue(0)
38
+ iat: safeint;
39
+
40
+ /** When it ends, in seconds since 1970-01-01T00:00:00Z; at most 60 seconds after `iat`. */
41
+ @minValue(0)
42
+ exp: safeint;
43
+
44
+ /** The request's method in upper case. */
45
+ @pattern("^[A-Z]+$")
46
+ method: string;
47
+
48
+ /** The request's path as sent in the request line, without the query. */
49
+ @pattern("^/[^?#]*$")
50
+ path: string;
51
+
52
+ /** The SHA-256 of the request's body bytes as sent, in base64url without padding. */
53
+ bodyDigest: Base64url32;
54
+ }
55
+
56
+ /**
57
+ * The public keys of an issuer of person proofs (ADR 0151): a JSON Web Key Set (RFC 7517), as the console publishes it
58
+ * at `/.well-known/jwks.json`. The first key of the issuer's setting signs; every key here verifies.
59
+ */
60
+ @extension("additionalProperties", Json<false>)
61
+ model PersonKeys {
62
+ @minItems(1)
63
+ keys: PersonKey[];
64
+ }
65
+
66
+ /** One Ed25519 public key. Closed: a key with its private part `d` or any other member is invalid. */
67
+ @extension("additionalProperties", Json<false>)
68
+ model PersonKey {
69
+ kty: "OKP";
70
+ crv: "Ed25519";
71
+ alg: "Ed25519";
72
+ use: "sig";
73
+
74
+ /** The key's JWK thumbprint (RFC 7638) with SHA-256; a proof names it in its `kid`. */
75
+ kid: Base64url32;
76
+
77
+ /** The public key. */
78
+ x: Base64url32;
79
+ }