@stigmer/server 3.24.0 → 3.25.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.
Files changed (208) hide show
  1. package/dist/authorization/authorizer.d.ts +10 -4
  2. package/dist/authorization/authorizer.d.ts.map +1 -1
  3. package/dist/authorization/authorizer.js +11 -4
  4. package/dist/authorization/authorizer.js.map +1 -1
  5. package/dist/authorization/model/index.d.ts +4 -4
  6. package/dist/authorization/model/index.d.ts.map +1 -1
  7. package/dist/authorization/model/index.js +2 -0
  8. package/dist/authorization/model/index.js.map +1 -1
  9. package/dist/authorization/model/oauth_app.d.ts.map +1 -1
  10. package/dist/authorization/model/oauth_app.js +3 -2
  11. package/dist/authorization/model/oauth_app.js.map +1 -1
  12. package/dist/authorization/model/platform_client.d.ts +2 -0
  13. package/dist/authorization/model/platform_client.d.ts.map +1 -0
  14. package/dist/authorization/model/platform_client.js +31 -0
  15. package/dist/authorization/model/platform_client.js.map +1 -0
  16. package/dist/boot/compose.d.ts.map +1 -1
  17. package/dist/boot/compose.js +88 -5
  18. package/dist/boot/compose.js.map +1 -1
  19. package/dist/boot/route-shadowing.d.ts +25 -0
  20. package/dist/boot/route-shadowing.d.ts.map +1 -0
  21. package/dist/boot/route-shadowing.js +17 -0
  22. package/dist/boot/route-shadowing.js.map +1 -0
  23. package/dist/domain/iampolicy/membership.d.ts +6 -1
  24. package/dist/domain/iampolicy/membership.d.ts.map +1 -1
  25. package/dist/domain/iampolicy/membership.js +8 -2
  26. package/dist/domain/iampolicy/membership.js.map +1 -1
  27. package/dist/domain/identityaccount/constants.d.ts +13 -0
  28. package/dist/domain/identityaccount/constants.d.ts.map +1 -1
  29. package/dist/domain/identityaccount/constants.js +17 -0
  30. package/dist/domain/identityaccount/constants.js.map +1 -1
  31. package/dist/domain/identityaccount/controller.d.ts +3 -1
  32. package/dist/domain/identityaccount/controller.d.ts.map +1 -1
  33. package/dist/domain/identityaccount/controller.js +15 -6
  34. package/dist/domain/identityaccount/controller.js.map +1 -1
  35. package/dist/domain/identityaccount/operator.d.ts.map +1 -1
  36. package/dist/domain/identityaccount/operator.js +1 -0
  37. package/dist/domain/identityaccount/operator.js.map +1 -1
  38. package/dist/domain/identityaccount/provisioning.d.ts +18 -0
  39. package/dist/domain/identityaccount/provisioning.d.ts.map +1 -1
  40. package/dist/domain/identityaccount/provisioning.js +1 -0
  41. package/dist/domain/identityaccount/provisioning.js.map +1 -1
  42. package/dist/domain/identityaccount/resource-store.js +9 -5
  43. package/dist/domain/identityaccount/resource-store.js.map +1 -1
  44. package/dist/domain/identityaccount/steps.d.ts +11 -2
  45. package/dist/domain/identityaccount/steps.d.ts.map +1 -1
  46. package/dist/domain/identityaccount/steps.js +42 -4
  47. package/dist/domain/identityaccount/steps.js.map +1 -1
  48. package/dist/domain/identityaccount/store-contract.d.ts.map +1 -1
  49. package/dist/domain/identityaccount/store-contract.js +33 -0
  50. package/dist/domain/identityaccount/store-contract.js.map +1 -1
  51. package/dist/domain/identityaccount/store.d.ts +7 -5
  52. package/dist/domain/identityaccount/store.d.ts.map +1 -1
  53. package/dist/domain/identityaccount/store.js.map +1 -1
  54. package/dist/domain/platform/controller.d.ts +10 -0
  55. package/dist/domain/platform/controller.d.ts.map +1 -1
  56. package/dist/domain/platform/controller.js +2 -1
  57. package/dist/domain/platform/controller.js.map +1 -1
  58. package/dist/domain/platformclient/constants.d.ts +60 -0
  59. package/dist/domain/platformclient/constants.d.ts.map +1 -0
  60. package/dist/domain/platformclient/constants.js +78 -0
  61. package/dist/domain/platformclient/constants.js.map +1 -0
  62. package/dist/domain/platformclient/controller.d.ts +59 -0
  63. package/dist/domain/platformclient/controller.d.ts.map +1 -0
  64. package/dist/domain/platformclient/controller.js +191 -0
  65. package/dist/domain/platformclient/controller.js.map +1 -0
  66. package/dist/domain/platformclient/credentials.d.ts +13 -0
  67. package/dist/domain/platformclient/credentials.d.ts.map +1 -0
  68. package/dist/domain/platformclient/credentials.js +56 -0
  69. package/dist/domain/platformclient/credentials.js.map +1 -0
  70. package/dist/domain/platformclient/mint.d.ts +23 -0
  71. package/dist/domain/platformclient/mint.d.ts.map +1 -0
  72. package/dist/domain/platformclient/mint.js +254 -0
  73. package/dist/domain/platformclient/mint.js.map +1 -0
  74. package/dist/domain/platformclient/origin-guard.d.ts +9 -0
  75. package/dist/domain/platformclient/origin-guard.d.ts.map +1 -0
  76. package/dist/domain/platformclient/origin-guard.js +81 -0
  77. package/dist/domain/platformclient/origin-guard.js.map +1 -0
  78. package/dist/domain/platformclient/resource-store.d.ts +4 -0
  79. package/dist/domain/platformclient/resource-store.d.ts.map +1 -0
  80. package/dist/domain/platformclient/resource-store.js +117 -0
  81. package/dist/domain/platformclient/resource-store.js.map +1 -0
  82. package/dist/domain/platformclient/steps.d.ts +51 -0
  83. package/dist/domain/platformclient/steps.d.ts.map +1 -0
  84. package/dist/domain/platformclient/steps.js +339 -0
  85. package/dist/domain/platformclient/steps.js.map +1 -0
  86. package/dist/domain/platformclient/store-contract.d.ts +8 -0
  87. package/dist/domain/platformclient/store-contract.d.ts.map +1 -0
  88. package/dist/domain/platformclient/store-contract.js +208 -0
  89. package/dist/domain/platformclient/store-contract.js.map +1 -0
  90. package/dist/domain/platformclient/store.d.ts +58 -0
  91. package/dist/domain/platformclient/store.d.ts.map +1 -0
  92. package/dist/domain/platformclient/store.js +13 -0
  93. package/dist/domain/platformclient/store.js.map +1 -0
  94. package/dist/domain/platformclient/system-managed.d.ts +18 -0
  95. package/dist/domain/platformclient/system-managed.d.ts.map +1 -0
  96. package/dist/domain/platformclient/system-managed.js +80 -0
  97. package/dist/domain/platformclient/system-managed.js.map +1 -0
  98. package/dist/domain/platformclient/token-controller.d.ts +11 -0
  99. package/dist/domain/platformclient/token-controller.d.ts.map +1 -0
  100. package/dist/domain/platformclient/token-controller.js +32 -0
  101. package/dist/domain/platformclient/token-controller.js.map +1 -0
  102. package/dist/domain/platformclient/verifier.d.ts +10 -0
  103. package/dist/domain/platformclient/verifier.d.ts.map +1 -0
  104. package/dist/domain/platformclient/verifier.js +76 -0
  105. package/dist/domain/platformclient/verifier.js.map +1 -0
  106. package/dist/encryption/key-manager.d.ts +20 -3
  107. package/dist/encryption/key-manager.d.ts.map +1 -1
  108. package/dist/encryption/key-manager.js +64 -42
  109. package/dist/encryption/key-manager.js.map +1 -1
  110. package/dist/extensions/caller-guards.d.ts +8 -3
  111. package/dist/extensions/caller-guards.d.ts.map +1 -1
  112. package/dist/extensions/drivers.d.ts +37 -0
  113. package/dist/extensions/drivers.d.ts.map +1 -1
  114. package/dist/extensions/guest-token-minting.d.ts +26 -0
  115. package/dist/extensions/guest-token-minting.d.ts.map +1 -0
  116. package/dist/extensions/guest-token-minting.js +2 -0
  117. package/dist/extensions/guest-token-minting.js.map +1 -0
  118. package/dist/extensions/identity.d.ts +6 -4
  119. package/dist/extensions/identity.d.ts.map +1 -1
  120. package/dist/extensions/identity.js.map +1 -1
  121. package/dist/extensions/registry.d.ts +30 -1
  122. package/dist/extensions/registry.d.ts.map +1 -1
  123. package/dist/extensions/registry.js +34 -1
  124. package/dist/extensions/registry.js.map +1 -1
  125. package/dist/index.d.ts +13 -1
  126. package/dist/index.d.ts.map +1 -1
  127. package/dist/index.js +6 -0
  128. package/dist/index.js.map +1 -1
  129. package/dist/pipeline/interceptors/auth.d.ts +14 -0
  130. package/dist/pipeline/interceptors/auth.d.ts.map +1 -1
  131. package/dist/pipeline/interceptors/auth.js +24 -0
  132. package/dist/pipeline/interceptors/auth.js.map +1 -1
  133. package/dist/pipeline/steps/build-update-state.d.ts +11 -1
  134. package/dist/pipeline/steps/build-update-state.d.ts.map +1 -1
  135. package/dist/pipeline/steps/build-update-state.js +5 -2
  136. package/dist/pipeline/steps/build-update-state.js.map +1 -1
  137. package/dist/platformtoken/envelope.d.ts +100 -0
  138. package/dist/platformtoken/envelope.d.ts.map +1 -0
  139. package/dist/platformtoken/envelope.js +184 -0
  140. package/dist/platformtoken/envelope.js.map +1 -0
  141. package/dist/platformtoken/key-ring.d.ts +85 -0
  142. package/dist/platformtoken/key-ring.d.ts.map +1 -0
  143. package/dist/platformtoken/key-ring.js +164 -0
  144. package/dist/platformtoken/key-ring.js.map +1 -0
  145. package/package.json +6 -6
  146. package/src/authorization/README.md +1 -1
  147. package/src/authorization/__tests__/authorizer.test.ts +6 -2
  148. package/src/authorization/__tests__/wire-permissions.test.ts +1 -0
  149. package/src/authorization/authorizer.ts +11 -4
  150. package/src/authorization/model/__tests__/registry.test.ts +8 -1
  151. package/src/authorization/model/index.ts +6 -4
  152. package/src/authorization/model/oauth_app.ts +3 -2
  153. package/src/authorization/model/platform_client.ts +43 -0
  154. package/src/boot/__tests__/auth-enabled-composition.test.ts +2 -1
  155. package/src/boot/__tests__/route-shadowing.test.ts +67 -0
  156. package/src/boot/compose.ts +90 -5
  157. package/src/boot/route-shadowing.ts +47 -0
  158. package/src/domain/iampolicy/__tests__/membership.test.ts +7 -0
  159. package/src/domain/iampolicy/membership.ts +8 -2
  160. package/src/domain/identityaccount/__tests__/platform-client-accounts.test.ts +124 -0
  161. package/src/domain/identityaccount/__tests__/resource-store.test.ts +1 -0
  162. package/src/domain/identityaccount/constants.ts +20 -0
  163. package/src/domain/identityaccount/controller.ts +16 -4
  164. package/src/domain/identityaccount/operator.ts +1 -0
  165. package/src/domain/identityaccount/provisioning.ts +17 -0
  166. package/src/domain/identityaccount/resource-store.ts +9 -5
  167. package/src/domain/identityaccount/steps.ts +58 -3
  168. package/src/domain/identityaccount/store-contract.ts +51 -0
  169. package/src/domain/identityaccount/store.ts +7 -5
  170. package/src/domain/platform/__tests__/platform.test.ts +7 -1
  171. package/src/domain/platform/controller.ts +12 -1
  172. package/src/domain/platformclient/__tests__/controller.test.ts +397 -0
  173. package/src/domain/platformclient/__tests__/credentials.test.ts +46 -0
  174. package/src/domain/platformclient/__tests__/mint.test.ts +415 -0
  175. package/src/domain/platformclient/__tests__/resource-store.test.ts +140 -0
  176. package/src/domain/platformclient/__tests__/system-managed.test.ts +101 -0
  177. package/src/domain/platformclient/__tests__/verifier-and-guard.test.ts +207 -0
  178. package/src/domain/platformclient/constants.ts +120 -0
  179. package/src/domain/platformclient/controller.ts +449 -0
  180. package/src/domain/platformclient/credentials.ts +68 -0
  181. package/src/domain/platformclient/mint.ts +412 -0
  182. package/src/domain/platformclient/origin-guard.ts +117 -0
  183. package/src/domain/platformclient/resource-store.ts +150 -0
  184. package/src/domain/platformclient/steps.ts +472 -0
  185. package/src/domain/platformclient/store-contract.ts +318 -0
  186. package/src/domain/platformclient/store.ts +63 -0
  187. package/src/domain/platformclient/system-managed.ts +115 -0
  188. package/src/domain/platformclient/token-controller.ts +49 -0
  189. package/src/domain/platformclient/verifier.ts +106 -0
  190. package/src/encryption/key-manager.ts +87 -44
  191. package/src/extensions/__tests__/extension-composition.test.ts +3 -2
  192. package/src/extensions/__tests__/platform-client-composed.test.ts +288 -0
  193. package/src/extensions/__tests__/registry.test.ts +4 -1
  194. package/src/extensions/__tests__/tier-truthfulness.test.ts +8 -0
  195. package/src/extensions/caller-guards.ts +8 -3
  196. package/src/extensions/drivers.ts +37 -0
  197. package/src/extensions/guest-token-minting.ts +32 -0
  198. package/src/extensions/identity.ts +6 -4
  199. package/src/extensions/registry.ts +77 -3
  200. package/src/index.ts +55 -0
  201. package/src/pipeline/interceptors/auth.ts +27 -0
  202. package/src/pipeline/steps/__tests__/references.test.ts +2 -0
  203. package/src/pipeline/steps/build-update-state.ts +5 -2
  204. package/src/platformtoken/__tests__/envelope.test.ts +277 -0
  205. package/src/platformtoken/__tests__/key-ring.test.ts +205 -0
  206. package/src/platformtoken/envelope.ts +276 -0
  207. package/src/platformtoken/key-ring.ts +266 -0
  208. package/src/runnerauth/__tests__/runner-subject-composed.test.ts +9 -3
@@ -0,0 +1,58 @@
1
+ /**
2
+ * The PlatformClientStore PORT: the storage contract the platform-client
3
+ * domain writes and reads through, so the cloud serves the same chains
4
+ * over its own `cloud.iam_platform_client` table by registering an
5
+ * implementation as `drivers.platformClientStore` (the identity-account
6
+ * and IamPolicy precedent: a port for an IAM kind whose rows an edition
7
+ * keeps in its own table). Open source's implementation is
8
+ * resource-store.ts over the generic Store.
9
+ *
10
+ * The methods are exactly the lookups the domain asks: by id (every
11
+ * chain, and the verifier's liveness read), by client_id (the mint), by
12
+ * org-scoped slug (getByReference, update addressed by slug, the
13
+ * duplicate check), by organization (listByOrg). A port carries nothing
14
+ * only one edition calls.
15
+ *
16
+ * Contract every implementation must satisfy — proven by the port-contract
17
+ * kit (store-contract.ts, exported), which the OSS adapter's test iterates
18
+ * on both drivers and a composition's driver test iterates too:
19
+ * - `save` is create-only in effect: a held id, a held (org, slug) or a
20
+ * held client_id raises DuplicatePlatformClientError, never a silent
21
+ * overwrite;
22
+ * - `update` replaces by id and never creates: an unknown id writes
23
+ * nothing;
24
+ * - `deleteById` of an unknown id resolves;
25
+ * - `findByOrg` answers every client of the organization and no other,
26
+ * in no promised order (the chain sorts);
27
+ * - a typed not-found reads as `undefined`; any other storage failure
28
+ * propagates as the infrastructure fault it is (the ratified
29
+ * store-fault mapping — an outage must never read as "no client", which
30
+ * on the verifier's path would revoke every live token).
31
+ */
32
+ import type { PlatformClient } from "@stigmer/protos/ai/stigmer/iam/platformclient/v1/api_pb";
33
+ /**
34
+ * Raised by `save` when the id, the (org, slug) pair or the client_id is
35
+ * already held, so the create chain answers ALREADY_EXISTS. `cause`
36
+ * carries a driver's own error (the cloud's SQLSTATE 23505) for the logs;
37
+ * the message is the port's.
38
+ */
39
+ export declare class DuplicatePlatformClientError extends Error {
40
+ constructor(message: string, options?: {
41
+ cause?: unknown;
42
+ });
43
+ }
44
+ export interface PlatformClientStore {
45
+ /** Insert; a held id, (org, slug) or client_id raises DuplicatePlatformClientError. */
46
+ save(client: PlatformClient): Promise<void>;
47
+ /** Full-row replace by id; an unknown id writes nothing. */
48
+ update(client: PlatformClient): Promise<void>;
49
+ /** Removes the row; no error when it does not exist. */
50
+ deleteById(id: string): Promise<void>;
51
+ findById(id: string): Promise<PlatformClient | undefined>;
52
+ /** The client holding this public identifier — the mint's lookup. */
53
+ findByClientId(clientId: string): Promise<PlatformClient | undefined>;
54
+ findByOrgAndSlug(org: string, slug: string): Promise<PlatformClient | undefined>;
55
+ /** Every client of the organization, in no promised order. */
56
+ findByOrg(org: string): Promise<ReadonlyArray<PlatformClient>>;
57
+ }
58
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/domain/platformclient/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yDAAyD,CAAC;AAE9F;;;;;GAKG;AACH,qBAAa,4BAA6B,SAAQ,KAAK;gBACzC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;CAI3D;AAED,MAAM,WAAW,mBAAmB;IAClC,uFAAuF;IACvF,IAAI,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,4DAA4D;IAC5D,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,wDAAwD;IACxD,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAAC;IAC1D,qEAAqE;IACrE,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAAC;IACtE,gBAAgB,CACd,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAAC;IACvC,8DAA8D;IAC9D,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC,CAAC;CAChE"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Raised by `save` when the id, the (org, slug) pair or the client_id is
3
+ * already held, so the create chain answers ALREADY_EXISTS. `cause`
4
+ * carries a driver's own error (the cloud's SQLSTATE 23505) for the logs;
5
+ * the message is the port's.
6
+ */
7
+ export class DuplicatePlatformClientError extends Error {
8
+ constructor(message, options) {
9
+ super(message, options);
10
+ this.name = "DuplicatePlatformClientError";
11
+ }
12
+ }
13
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/domain/platformclient/store.ts"],"names":[],"mappings":"AAiCA;;;;;GAKG;AACH,MAAM,OAAO,4BAA6B,SAAQ,KAAK;IACrD,YAAY,OAAe,EAAE,OAA6B;QACxD,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,8BAA8B,CAAC;IAC7C,CAAC;CACF"}
@@ -0,0 +1,18 @@
1
+ import type { PlatformClient } from "@stigmer/protos/ai/stigmer/iam/platformclient/v1/api_pb";
2
+ export interface SystemManagedPlatformClientInput {
3
+ /** The owning organization. */
4
+ readonly org: string;
5
+ /** A reserved slug (RESERVED_PLATFORM_CLIENT_SLUGS); anything else throws. */
6
+ readonly slug: string;
7
+ /** The display name a console would show. */
8
+ readonly name: string;
9
+ /** The creation instant stamped on both audit slots; defaults to the wall clock. */
10
+ readonly now?: Date;
11
+ }
12
+ /**
13
+ * A new system-managed client, ready for a store's `save`. Throws on an
14
+ * empty organization or a slug that is not reserved — an edition's
15
+ * programming error, never a request's.
16
+ */
17
+ export declare function newSystemManagedPlatformClient(input: SystemManagedPlatformClientInput): PlatformClient;
18
+ //# sourceMappingURL=system-managed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"system-managed.d.ts","sourceRoot":"","sources":["../../../src/domain/platformclient/system-managed.ts"],"names":[],"mappings":"AAmCA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yDAAyD,CAAC;AAsB9F,MAAM,WAAW,gCAAgC;IAC/C,+BAA+B;IAC/B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,8EAA8E;IAC9E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,6CAA6C;IAC7C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,oFAAoF;IACpF,QAAQ,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,gCAAgC,GACtC,cAAc,CAuChB"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * The one builder of a system-managed PlatformClient: the row an edition
3
+ * creates for itself, never through the create chain, so the tokens it
4
+ * signs on the platform's own behalf (a guest's, a schedule fire's) name a
5
+ * client that exists. Stigmer Cloud keeps one per organization under
6
+ * SYSTEM_SHARE_CLIENT_SLUG and persists it through its store driver.
7
+ *
8
+ * The domain already owns what such a client is — the create chain refuses
9
+ * its reserved slug (RefuseReservedSlug) and every mutation refuses its
10
+ * label (RefuseSystemManaged) — so the row is built here too, and the
11
+ * rules that make it safe hold by construction:
12
+ * - it lives only under a reserved slug, which no user can create, so a
13
+ * user client can never be mistaken for one;
14
+ * - it carries the reserved `stigmer.ai/system-managed` label, so update,
15
+ * delete and rotate refuse it;
16
+ * - its credentials are real (a `client_id` unique like any other, a
17
+ * hash, a fingerprint), but the secret is discarded here: nobody ever
18
+ * authenticates as the platform's own client;
19
+ * - its id is spelled like every other (`pcl_` + ULID, generateId);
20
+ * - its audit names no actor, because no caller made it: the platform did.
21
+ *
22
+ * Who decides when one exists, and where it is stored, is the edition's:
23
+ * this function writes nothing. It writes no authorization tuples either —
24
+ * nothing authorizes against a system-managed client, and with none it
25
+ * stays out of every list and reference read a person makes.
26
+ */
27
+ import { create } from "@bufbuild/protobuf";
28
+ import { timestampFromDate } from "@bufbuild/protobuf/wkt";
29
+ import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
30
+ import { ApiResourceAuditInfoSchema, ApiResourceAuditSchema, } from "@stigmer/protos/ai/stigmer/commons/apiresource/status_pb";
31
+ import { PlatformClientSchema } from "@stigmer/protos/ai/stigmer/iam/platformclient/v1/api_pb";
32
+ import { RESERVED_LABEL_TRUE, SYSTEM_MANAGED_LABEL, } from "../../pipeline/apiresource-labels.js";
33
+ import { defaultVisibilityFor, getIdPrefix, } from "../../pipeline/apiresource-meta.js";
34
+ import { generateId } from "../../pipeline/steps/defaults.js";
35
+ import { PLATFORM_CLIENT_KIND_NAME, RESERVED_PLATFORM_CLIENT_SLUGS, } from "./constants.js";
36
+ import { generateClientId, generateClientSecret, hashClientSecret, secretFingerprint, } from "./credentials.js";
37
+ /**
38
+ * A new system-managed client, ready for a store's `save`. Throws on an
39
+ * empty organization or a slug that is not reserved — an edition's
40
+ * programming error, never a request's.
41
+ */
42
+ export function newSystemManagedPlatformClient(input) {
43
+ if (input.org === "") {
44
+ throw new Error("a system-managed platform client needs an organization");
45
+ }
46
+ if (!RESERVED_PLATFORM_CLIENT_SLUGS.has(input.slug)) {
47
+ throw new Error(`'${input.slug}' is not a reserved platform-client slug; a system-managed client lives only under one (${[...RESERVED_PLATFORM_CLIENT_SLUGS].join(", ")})`);
48
+ }
49
+ const secret = generateClientSecret();
50
+ const created = timestampFromDate(input.now ?? new Date());
51
+ const audit = create(ApiResourceAuditInfoSchema, {
52
+ createdAt: created,
53
+ updatedAt: created,
54
+ event: "created",
55
+ });
56
+ return create(PlatformClientSchema, {
57
+ apiVersion: "iam.stigmer.ai/v1",
58
+ kind: PLATFORM_CLIENT_KIND_NAME,
59
+ metadata: {
60
+ id: generateId(getIdPrefix(ApiResourceKind.platform_client)),
61
+ org: input.org,
62
+ name: input.name,
63
+ slug: input.slug,
64
+ labels: { [SYSTEM_MANAGED_LABEL]: RESERVED_LABEL_TRUE },
65
+ visibility: defaultVisibilityFor(ApiResourceKind.platform_client),
66
+ },
67
+ spec: {
68
+ clientId: generateClientId(),
69
+ clientSecretHash: hashClientSecret(secret),
70
+ secretFingerprint: secretFingerprint(secret),
71
+ },
72
+ status: {
73
+ audit: create(ApiResourceAuditSchema, {
74
+ specAudit: audit,
75
+ statusAudit: audit,
76
+ }),
77
+ },
78
+ });
79
+ }
80
+ //# sourceMappingURL=system-managed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"system-managed.js","sourceRoot":"","sources":["../../../src/domain/platformclient/system-managed.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,OAAO,EAAE,eAAe,EAAE,MAAM,qFAAqF,CAAC;AACtH,OAAO,EACL,0BAA0B,EAC1B,sBAAsB,GACvB,MAAM,0DAA0D,CAAC;AAClE,OAAO,EAAE,oBAAoB,EAAE,MAAM,yDAAyD,CAAC;AAG/F,OAAO,EACL,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EACL,oBAAoB,EACpB,WAAW,GACZ,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AAC9D,OAAO,EACL,yBAAyB,EACzB,8BAA8B,GAC/B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,kBAAkB,CAAC;AAa1B;;;;GAIG;AACH,MAAM,UAAU,8BAA8B,CAC5C,KAAuC;IAEvC,IAAI,KAAK,CAAC,GAAG,KAAK,EAAE,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;IAC5E,CAAC;IACD,IAAI,CAAC,8BAA8B,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACpD,MAAM,IAAI,KAAK,CACb,IAAI,KAAK,CAAC,IAAI,2FAA2F,CAAC,GAAG,8BAA8B,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAC3J,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAG,oBAAoB,EAAE,CAAC;IACtC,MAAM,OAAO,GAAG,iBAAiB,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC;IAC3D,MAAM,KAAK,GAAG,MAAM,CAAC,0BAA0B,EAAE;QAC/C,SAAS,EAAE,OAAO;QAClB,SAAS,EAAE,OAAO;QAClB,KAAK,EAAE,SAAS;KACjB,CAAC,CAAC;IACH,OAAO,MAAM,CAAC,oBAAoB,EAAE;QAClC,UAAU,EAAE,mBAAmB;QAC/B,IAAI,EAAE,yBAAyB;QAC/B,QAAQ,EAAE;YACR,EAAE,EAAE,UAAU,CAAC,WAAW,CAAC,eAAe,CAAC,eAAe,CAAC,CAAC;YAC5D,GAAG,EAAE,KAAK,CAAC,GAAG;YACd,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,MAAM,EAAE,EAAE,CAAC,oBAAoB,CAAC,EAAE,mBAAmB,EAAE;YACvD,UAAU,EAAE,oBAAoB,CAAC,eAAe,CAAC,eAAe,CAAC;SAClE;QACD,IAAI,EAAE;YACJ,QAAQ,EAAE,gBAAgB,EAAE;YAC5B,gBAAgB,EAAE,gBAAgB,CAAC,MAAM,CAAC;YAC1C,iBAAiB,EAAE,iBAAiB,CAAC,MAAM,CAAC;SAC7C;QACD,MAAM,EAAE;YACN,KAAK,EAAE,MAAM,CAAC,sBAAsB,EAAE;gBACpC,SAAS,EAAE,KAAK;gBAChB,WAAW,EAAE,KAAK;aACnB,CAAC;SACH;KACF,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { ConnectRouter } from "@connectrpc/connect";
2
+ import type { GuestTokenMinting } from "../../extensions/guest-token-minting.js";
3
+ import type { PlatformClientMintDeps } from "./mint.js";
4
+ export interface PlatformClientTokenControllerDeps {
5
+ readonly mint: PlatformClientMintDeps;
6
+ /** The composed capability; undefined = mintGuestToken refuses UNIMPLEMENTED. */
7
+ readonly guestTokenMinting: GuestTokenMinting | undefined;
8
+ }
9
+ /** Registers the token service on the router (routes stage). */
10
+ export declare function registerPlatformClientTokenService(router: ConnectRouter, deps: PlatformClientTokenControllerDeps): void;
11
+ //# sourceMappingURL=token-controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-controller.d.ts","sourceRoot":"","sources":["../../../src/domain/platformclient/token-controller.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAIzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AAGjF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAExD,MAAM,WAAW,iCAAiC;IAChD,QAAQ,CAAC,IAAI,EAAE,sBAAsB,CAAC;IACtC,iFAAiF;IACjF,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,GAAG,SAAS,CAAC;CAC3D;AAED,gEAAgE;AAChE,wBAAgB,kCAAkC,CAChD,MAAM,EAAE,aAAa,EACrB,IAAI,EAAE,iCAAiC,GACtC,IAAI,CAaN"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * PlatformClientTokenController — the two public token RPCs, registered in
3
+ * every composition so the service has one owner (the routes stage refuses
4
+ * an extension that registers it again, boot/route-shadowing.ts):
5
+ *
6
+ * - mintUserToken: the PlatformClient mint (mint.ts). Public on the wire
7
+ * — the client authenticates with its credentials in the body, not a
8
+ * bearer token — so there is no annotation to evaluate; the mint never
9
+ * reads the chain's caller.
10
+ * - mintGuestToken: the credential-free mint for anonymous visitors of a
11
+ * shared agent's hosted page, dispatched to the composed guest-token
12
+ * capability (extensions/guest-token-minting.ts). Without one — open
13
+ * source hosts no shared-agent pages — it answers UNIMPLEMENTED with
14
+ * the edition sentence, the identityFederation absent shape.
15
+ */
16
+ import { Code, ConnectError } from "@connectrpc/connect";
17
+ import { PlatformClientTokenController } from "@stigmer/protos/ai/stigmer/iam/platformclient/v1/token_pb";
18
+ import { GUEST_MINT_UNIMPLEMENTED_MESSAGE } from "./constants.js";
19
+ import { mintUserToken } from "./mint.js";
20
+ /** Registers the token service on the router (routes stage). */
21
+ export function registerPlatformClientTokenService(router, deps) {
22
+ router.service(PlatformClientTokenController, {
23
+ mintUserToken: (request) => mintUserToken(deps.mint, request),
24
+ mintGuestToken: (request, ctx) => {
25
+ if (deps.guestTokenMinting === undefined) {
26
+ throw new ConnectError(GUEST_MINT_UNIMPLEMENTED_MESSAGE, Code.Unimplemented);
27
+ }
28
+ return deps.guestTokenMinting.mintGuestToken(request, ctx.requestHeader);
29
+ },
30
+ });
31
+ }
32
+ //# sourceMappingURL=token-controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-controller.js","sourceRoot":"","sources":["../../../src/domain/platformclient/token-controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGzD,OAAO,EAAE,6BAA6B,EAAE,MAAM,2DAA2D,CAAC;AAG1G,OAAO,EAAE,gCAAgC,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAS1C,gEAAgE;AAChE,MAAM,UAAU,kCAAkC,CAChD,MAAqB,EACrB,IAAuC;IAEvC,MAAM,CAAC,OAAO,CAAC,6BAA6B,EAAE;QAC5C,aAAa,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC;QAC7D,cAAc,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE;YAC/B,IAAI,IAAI,CAAC,iBAAiB,KAAK,SAAS,EAAE,CAAC;gBACzC,MAAM,IAAI,YAAY,CACpB,gCAAgC,EAChC,IAAI,CAAC,aAAa,CACnB,CAAC;YACJ,CAAC;YACD,OAAO,IAAI,CAAC,iBAAiB,CAAC,cAAc,CAAC,OAAO,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC;QAC3E,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { IdentityVerifier } from "../../extensions/identity.js";
2
+ import type { PlatformTokenKeyRing } from "../../platformtoken/key-ring.js";
3
+ import type { PlatformClientStore } from "./store.js";
4
+ export interface PlatformClientTokenVerifierDeps {
5
+ readonly keys: PlatformTokenKeyRing;
6
+ readonly clients: Pick<PlatformClientStore, "findById">;
7
+ readonly now?: () => Date;
8
+ }
9
+ export declare function newPlatformClientTokenVerifier(deps: PlatformClientTokenVerifierDeps): IdentityVerifier;
10
+ //# sourceMappingURL=verifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verifier.d.ts","sourceRoot":"","sources":["../../../src/domain/platformclient/verifier.ts"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAEV,gBAAgB,EACjB,MAAM,8BAA8B,CAAC;AAOtC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAM5E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,CAAC;IACxD,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B;AAED,wBAAgB,8BAA8B,CAC5C,IAAI,EAAE,+BAA+B,GACpC,gBAAgB,CA8ClB"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * The PlatformClient user-token verifier: open source's one platform-token
3
+ * lane. It claims a token with `iss: "stigmer"` and NO `token_type` — the
4
+ * user token the mint signs — and passes every other token on:
5
+ * - a token that is not a platform token is another verifier's (the
6
+ * OIDC verifier's, an API key's);
7
+ * - a typed platform token (guest, schedule, channel, the sandbox
8
+ * family) belongs to the edition that mints it; open source verifies
9
+ * only its own vocabulary, and on a server with no verifier for that
10
+ * lane the chain refuses it as unclaimed.
11
+ * A platform token whose signature, expiry, audience or subject fails is
12
+ * refused here with the envelope's pinned copy, whichever lane it names —
13
+ * the refusal the cloud's verifier has always answered for it.
14
+ *
15
+ * Liveness is the verifier's (not a guard's), so every lane that
16
+ * authenticates — the serving chain and the extension HTTP edges that run
17
+ * the verifier chain without guards — refuses a deleted client's tokens on
18
+ * the next request, with the cloud's copy. A store fault propagates as the
19
+ * infrastructure fault it is, never as a revocation.
20
+ *
21
+ * Composed between `apikey` and `oidc`, only under an authentication
22
+ * posture (compose.ts): the OIDC verifier claims every JWT-shaped token and
23
+ * throws on one it cannot verify, so a platform token must be claimed
24
+ * before it gets there (stigmer#1137's lesson).
25
+ *
26
+ * The identity is the account the token was minted for: `sub` IS the
27
+ * account id (the mint signs it), so no account read is needed; class
28
+ * `user`, issuer "stigmer", the token carried (the memory-capture gate and
29
+ * the origin guard read its `platform_client_id`), and the email and name
30
+ * the platform asserted, for display only.
31
+ */
32
+ import { Code, ConnectError } from "@connectrpc/connect";
33
+ import { PLATFORM_TOKEN_ISSUER, platformTokenRefusalError, stringClaim, verifyPlatformToken, } from "../../platformtoken/envelope.js";
34
+ import { DELETED_CLIENT_MESSAGE, TOKEN_NAMES_NO_CLIENT_MESSAGE, USER_TOKEN_CLAIMS, } from "./constants.js";
35
+ export function newPlatformClientTokenVerifier(deps) {
36
+ return {
37
+ name: "platform-client",
38
+ async verify(token) {
39
+ const result = verifyPlatformToken(deps.keys, token, deps.now?.());
40
+ switch (result.outcome) {
41
+ case "foreign":
42
+ return null;
43
+ case "refused":
44
+ throw platformTokenRefusalError(result.refusal);
45
+ case "verified":
46
+ break;
47
+ default: {
48
+ const exhaustive = result;
49
+ throw new Error(`unknown verification ${JSON.stringify(exhaustive)}`);
50
+ }
51
+ }
52
+ const verified = result.token;
53
+ if (verified.tokenType !== undefined) {
54
+ return null;
55
+ }
56
+ const platformClientId = stringClaim(verified.payload, USER_TOKEN_CLAIMS.platformClientId);
57
+ if (platformClientId === undefined) {
58
+ throw new ConnectError(TOKEN_NAMES_NO_CLIENT_MESSAGE, Code.Unauthenticated);
59
+ }
60
+ if ((await deps.clients.findById(platformClientId)) === undefined) {
61
+ throw new ConnectError(DELETED_CLIENT_MESSAGE, Code.Unauthenticated);
62
+ }
63
+ const email = stringClaim(verified.payload, USER_TOKEN_CLAIMS.email);
64
+ const displayName = stringClaim(verified.payload, USER_TOKEN_CLAIMS.name);
65
+ return {
66
+ identityId: verified.subject,
67
+ callerClass: "user",
68
+ issuer: PLATFORM_TOKEN_ISSUER,
69
+ rawToken: token,
70
+ ...(email !== undefined ? { email } : {}),
71
+ ...(displayName !== undefined ? { displayName } : {}),
72
+ };
73
+ },
74
+ };
75
+ }
76
+ //# sourceMappingURL=verifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verifier.js","sourceRoot":"","sources":["../../../src/domain/platformclient/verifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAMzD,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,WAAW,EACX,mBAAmB,GACpB,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EACL,sBAAsB,EACtB,6BAA6B,EAC7B,iBAAiB,GAClB,MAAM,gBAAgB,CAAC;AASxB,MAAM,UAAU,8BAA8B,CAC5C,IAAqC;IAErC,OAAO;QACL,IAAI,EAAE,iBAAiB;QACvB,KAAK,CAAC,MAAM,CAAC,KAAa;YACxB,MAAM,MAAM,GAAG,mBAAmB,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACnE,QAAQ,MAAM,CAAC,OAAO,EAAE,CAAC;gBACvB,KAAK,SAAS;oBACZ,OAAO,IAAI,CAAC;gBACd,KAAK,SAAS;oBACZ,MAAM,yBAAyB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;gBAClD,KAAK,UAAU;oBACb,MAAM;gBACR,OAAO,CAAC,CAAC,CAAC;oBACR,MAAM,UAAU,GAAU,MAAM,CAAC;oBACjC,MAAM,IAAI,KAAK,CAAC,wBAAwB,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;gBACxE,CAAC;YACH,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC;YAC9B,IAAI,QAAQ,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;gBACrC,OAAO,IAAI,CAAC;YACd,CAAC;YACD,MAAM,gBAAgB,GAAG,WAAW,CAClC,QAAQ,CAAC,OAAO,EAChB,iBAAiB,CAAC,gBAAgB,CACnC,CAAC;YACF,IAAI,gBAAgB,KAAK,SAAS,EAAE,CAAC;gBACnC,MAAM,IAAI,YAAY,CACpB,6BAA6B,EAC7B,IAAI,CAAC,eAAe,CACrB,CAAC;YACJ,CAAC;YACD,IAAI,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;gBAClE,MAAM,IAAI,YAAY,CAAC,sBAAsB,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;YACvE,CAAC;YACD,MAAM,KAAK,GAAG,WAAW,CAAC,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC,KAAK,CAAC,CAAC;YACrE,MAAM,WAAW,GAAG,WAAW,CAAC,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC,IAAI,CAAC,CAAC;YAC1E,OAAO;gBACL,UAAU,EAAE,QAAQ,CAAC,OAAO;gBAC5B,WAAW,EAAE,MAAM;gBACnB,MAAM,EAAE,qBAAqB;gBAC7B,QAAQ,EAAE,KAAK;gBACf,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACzC,GAAG,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACtD,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -13,11 +13,28 @@ export interface KeyLoaderOptions {
13
13
  readonly homeDir?: string;
14
14
  }
15
15
  /**
16
- * Go GetOrCreateNamedKey: env var → key file → auto-generate. Throws only
17
- * on unusable EXPLICIT configuration (bad env value) or when no key can be
18
- * produced at all.
16
+ * What one kind of key is, for the ladder. `fromEnv` receives the env
17
+ * value already strictly Base64-decoded and THROWS when the bytes are not
18
+ * a usable key (explicit configuration is never silently ignored);
19
+ * `fromFile` answers `undefined` for content it does not accept, so the
20
+ * ladder falls through exactly as it does for a wrong-sized raw key.
21
+ */
22
+ export interface KeyCodec<Key> {
23
+ fromEnv(envVar: string, decoded: Buffer): Key;
24
+ fromFile(content: Buffer): Key | undefined;
25
+ generate(): Key;
26
+ toFile(key: Key): Buffer;
27
+ }
28
+ /** The 32 raw bytes the encryption and runner-token keys are. */
29
+ export declare const RAW_32_BYTE_KEY: KeyCodec<Buffer>;
30
+ /**
31
+ * Go GetOrCreateNamedKey: env var → key file → auto-generate, for a 32-byte
32
+ * raw key. Throws only on unusable EXPLICIT configuration (bad env value)
33
+ * or when no key can be produced at all.
19
34
  */
20
35
  export declare function getOrCreateNamedKey(envVar: string, fileName: string, options?: KeyLoaderOptions): Buffer;
36
+ /** The ladder over any codec: env var → key file → auto-generate. */
37
+ export declare function getOrCreateKey<Key>(codec: KeyCodec<Key>, envVar: string, fileName: string, options?: KeyLoaderOptions): Key;
21
38
  /** Path to a named key file under <home>/.stigmer. */
22
39
  export declare function namedKeyFilePath(fileName: string, options?: KeyLoaderOptions): string;
23
40
  //# sourceMappingURL=key-manager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"key-manager.d.ts","sourceRoot":"","sources":["../../src/encryption/key-manager.ts"],"names":[],"mappings":"AAgCA,yEAAyE;AACzE,eAAO,MAAM,QAAQ,KAAK,CAAC;AAE3B,0DAA0D;AAC1D,eAAO,MAAM,YAAY,aAAa,CAAC;AAEvC,4EAA4E;AAC5E,eAAO,MAAM,oBAAoB,MAAQ,CAAC;AAE1C,wDAAwD;AACxD,eAAO,MAAM,mBAAmB,MAAQ,CAAC;AAEzC,MAAM,WAAW,gBAAgB;IAC/B,yDAAyD;IACzD,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACjC,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,gBAAqB,GAC7B,MAAM,CA2BR;AAoBD,sDAAsD;AACtD,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,gBAAqB,GAC7B,MAAM,CAGR"}
1
+ {"version":3,"file":"key-manager.d.ts","sourceRoot":"","sources":["../../src/encryption/key-manager.ts"],"names":[],"mappings":"AAsCA,yEAAyE;AACzE,eAAO,MAAM,QAAQ,KAAK,CAAC;AAE3B,0DAA0D;AAC1D,eAAO,MAAM,YAAY,aAAa,CAAC;AAEvC,4EAA4E;AAC5E,eAAO,MAAM,oBAAoB,MAAQ,CAAC;AAE1C,wDAAwD;AACxD,eAAO,MAAM,mBAAmB,MAAQ,CAAC;AAEzC,MAAM,WAAW,gBAAgB;IAC/B,yDAAyD;IACzD,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACjC,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,QAAQ,CAAC,GAAG;IAC3B,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,GAAG,CAAC;IAC9C,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,GAAG,GAAG,SAAS,CAAC;IAC3C,QAAQ,IAAI,GAAG,CAAC;IAChB,MAAM,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CAAC;CAC1B;AAED,iEAAiE;AACjE,eAAO,MAAM,eAAe,EAAE,QAAQ,CAAC,MAAM,CAkB5C,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,gBAAqB,GAC7B,MAAM,CAER;AAED,qEAAqE;AACrE,wBAAgB,cAAc,CAAC,GAAG,EAChC,KAAK,EAAE,QAAQ,CAAC,GAAG,CAAC,EACpB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,gBAAqB,GAC7B,GAAG,CA6BL;AAeD,sDAAsD;AACtD,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,gBAAqB,GAC7B,MAAM,CAGR"}
@@ -1,20 +1,26 @@
1
1
  /**
2
2
  * Named-key loader — ports pkg/encryption/keymanager.go.
3
3
  *
4
- * One convention for every 32-byte key the server holds (sub-project
5
- * DD-002): env var (Base64) → ~/.stigmer/<file> (raw bytes, 0600) →
6
- * auto-generate and persist. The loader is generalized over the env var
7
- * and file name so sibling key material (the runner-token signing key,
8
- * oss#535) rides the same ladder instead of growing a divergent loader.
4
+ * One convention for every key the server holds: env var (Base64) →
5
+ * ~/.stigmer/<file> (0600) → auto-generate and persist. The
6
+ * loader is generalized over the env var, the file name and a KeyCodec so
7
+ * sibling key material rides the same ladder instead of growing a
8
+ * divergent loader: the runner-token signing key (oss#535) and the
9
+ * encryption key are 32 raw bytes (RAW_32_BYTE_KEY); the platform-token
10
+ * signing key is an RSA private key (platformtoken/key-ring.ts). The codec
11
+ * says what a key IS — how an env value and a file decode, how one is
12
+ * generated and written — and nothing about the ladder, which stays one.
9
13
  *
10
- * Ladder semantics, exactly Go's:
14
+ * Ladder semantics, exactly Go's, for every codec:
11
15
  * - An EXPLICITLY configured env key that is unusable (bad Base64, wrong
12
- * length) is an ERROR, never a degrade — silently ignoring deliberate
13
- * configuration would be worse than refusing to boot.
16
+ * length, not the key type the codec holds) is an ERROR, never a
17
+ * degrade — silently ignoring deliberate configuration would be worse
18
+ * than refusing to boot.
14
19
  * - A key file that fails its load checks (permissions other than 0600,
15
- * wrong size) is never adopted; the ladder FALLS THROUGH to
16
- * auto-generate, which overwrites the file's content — Go's shipped
17
- * behavior (loadKeyFromFile error → generate → save), ported as-is.
20
+ * content the codec does not accept) is never adopted; the ladder
21
+ * FALLS THROUGH to auto-generate, which overwrites the file's content —
22
+ * Go's shipped behavior (loadKeyFromFile error → generate → save),
23
+ * ported as-is.
18
24
  * - Auto-generation persists for future boots; a persist FAILURE is a
19
25
  * stderr warning only — the key is still usable for this process.
20
26
  *
@@ -37,28 +43,52 @@ export const KEY_FILE_DIR = ".stigmer";
37
43
  export const KEY_FILE_PERMISSIONS = 0o600;
38
44
  /** Key directory permissions — Go KeyDirPermissions. */
39
45
  export const KEY_DIR_PERMISSIONS = 0o700;
46
+ /** The 32 raw bytes the encryption and runner-token keys are. */
47
+ export const RAW_32_BYTE_KEY = {
48
+ fromEnv(envVar, decoded) {
49
+ if (decoded.length !== KEY_SIZE) {
50
+ throw new Error(`${envVar} must be exactly 32 bytes (256 bits) when decoded, got ${decoded.length} bytes`);
51
+ }
52
+ return decoded;
53
+ },
54
+ fromFile(content) {
55
+ return content.length === KEY_SIZE ? content : undefined;
56
+ },
57
+ generate() {
58
+ return randomBytes(KEY_SIZE);
59
+ },
60
+ toFile(key) {
61
+ return key;
62
+ },
63
+ };
40
64
  /**
41
- * Go GetOrCreateNamedKey: env var → key file → auto-generate. Throws only
42
- * on unusable EXPLICIT configuration (bad env value) or when no key can be
43
- * produced at all.
65
+ * Go GetOrCreateNamedKey: env var → key file → auto-generate, for a 32-byte
66
+ * raw key. Throws only on unusable EXPLICIT configuration (bad env value)
67
+ * or when no key can be produced at all.
44
68
  */
45
69
  export function getOrCreateNamedKey(envVar, fileName, options = {}) {
70
+ return getOrCreateKey(RAW_32_BYTE_KEY, envVar, fileName, options);
71
+ }
72
+ /** The ladder over any codec: env var → key file → auto-generate. */
73
+ export function getOrCreateKey(codec, envVar, fileName, options = {}) {
46
74
  const env = options.env ?? process.env;
47
- // 1. Environment variable (highest priority) — Base64-encoded 32 bytes.
75
+ // 1. Environment variable (highest priority) — Base64-encoded.
48
76
  const envValue = env[envVar];
49
77
  if (envValue !== undefined && envValue !== "") {
50
- return decodeEnvKey(envVar, envValue);
78
+ return codec.fromEnv(envVar, decodeEnvBase64(envVar, envValue));
51
79
  }
52
- // 2. Local key file — raw 32 bytes, refused on insecure permissions.
80
+ // 2. Local key file — refused on insecure permissions or content the
81
+ // codec does not accept.
53
82
  const keyPath = namedKeyFilePath(fileName, options);
54
- const fromFile = loadKeyFromFile(keyPath);
83
+ const content = readKeyFile(keyPath);
84
+ const fromFile = content === undefined ? undefined : codec.fromFile(content);
55
85
  if (fromFile !== undefined) {
56
86
  return fromFile;
57
87
  }
58
88
  // 3. Auto-generate (local development); persist for future boots.
59
- const key = randomBytes(KEY_SIZE);
89
+ const key = codec.generate();
60
90
  try {
61
- saveKeyToFile(keyPath, key);
91
+ saveKeyToFile(keyPath, codec.toFile(key));
62
92
  }
63
93
  catch (error) {
64
94
  // Warn but don't fail — the key is still usable (Go's posture).
@@ -66,20 +96,17 @@ export function getOrCreateNamedKey(envVar, fileName, options = {}) {
66
96
  }
67
97
  return key;
68
98
  }
69
- /** Strict Base64 decode + length check for an env-configured key. */
70
- function decodeEnvKey(envVar, value) {
71
- const key = Buffer.from(value, "base64");
99
+ /** Strict Base64 decode for an env-configured key. */
100
+ function decodeEnvBase64(envVar, value) {
101
+ const decoded = Buffer.from(value, "base64");
72
102
  // Node's base64 decoder is lenient (skips invalid characters, accepts
73
103
  // missing padding) and never throws; Go's StdEncoding errors on any
74
104
  // non-canonical input. Round-tripping — Buffer always re-emits the
75
105
  // canonical padded form — restores Go's strictness.
76
- if (key.toString("base64") !== value) {
106
+ if (decoded.toString("base64") !== value) {
77
107
  throw new Error(`invalid Base64 encoding in ${envVar}`);
78
108
  }
79
- if (key.length !== KEY_SIZE) {
80
- throw new Error(`${envVar} must be exactly 32 bytes (256 bits) when decoded, got ${key.length} bytes`);
81
- }
82
- return key;
109
+ return decoded;
83
110
  }
84
111
  /** Path to a named key file under <home>/.stigmer. */
85
112
  export function namedKeyFilePath(fileName, options = {}) {
@@ -87,13 +114,13 @@ export function namedKeyFilePath(fileName, options = {}) {
87
114
  return path.join(home, KEY_FILE_DIR, fileName);
88
115
  }
89
116
  /**
90
- * Reads raw key bytes, mirroring Go loadKeyFromFile: missing file →
91
- * undefined (fall through the ladder); present-but-wrong (insecure
92
- * permissions, wrong size) also falls through — exactly Go's behavior,
93
- * where any load error falls to auto-generate. The 0600 check is skipped
94
- * on Windows, where POSIX modes are not meaningful.
117
+ * Reads a key file's bytes, mirroring Go loadKeyFromFile: missing file →
118
+ * undefined (fall through the ladder); present with insecure permissions
119
+ * also falls through — exactly Go's behavior, where any load error falls
120
+ * to auto-generate. The 0600 check is skipped on Windows, where POSIX
121
+ * modes are not meaningful.
95
122
  */
96
- function loadKeyFromFile(keyPath) {
123
+ function readKeyFile(keyPath) {
97
124
  let stat;
98
125
  try {
99
126
  stat = fs.statSync(keyPath);
@@ -107,24 +134,19 @@ function loadKeyFromFile(keyPath) {
107
134
  return undefined;
108
135
  }
109
136
  }
110
- let key;
111
137
  try {
112
- key = fs.readFileSync(keyPath);
138
+ return fs.readFileSync(keyPath);
113
139
  }
114
140
  catch {
115
141
  return undefined;
116
142
  }
117
- if (key.length !== KEY_SIZE) {
118
- return undefined;
119
- }
120
- return key;
121
143
  }
122
144
  /** Writes the key with secure permissions (dir 0700, file 0600). */
123
- function saveKeyToFile(keyPath, key) {
145
+ function saveKeyToFile(keyPath, content) {
124
146
  fs.mkdirSync(path.dirname(keyPath), {
125
147
  recursive: true,
126
148
  mode: KEY_DIR_PERMISSIONS,
127
149
  });
128
- fs.writeFileSync(keyPath, key, { mode: KEY_FILE_PERMISSIONS });
150
+ fs.writeFileSync(keyPath, content, { mode: KEY_FILE_PERMISSIONS });
129
151
  }
130
152
  //# sourceMappingURL=key-manager.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"key-manager.js","sourceRoot":"","sources":["../../src/encryption/key-manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"key-manager.js","sourceRoot":"","sources":["../../src/encryption/key-manager.ts"],"names":[],"mappings":"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"}
@@ -10,9 +10,14 @@
10
10
  * allowed_origins, oss#375). Java separates the two classes the same way.
11
11
  *
12
12
  * List point — guards concatenate in unit order and run in composed
13
- * order; the first throw wins. OSS composes zero guards, so with none
14
- * registered the serving chain behaves byte-identically to before the
15
- * point existed (the conformance rosters pin that).
13
+ * order; the first throw wins. Open source's own guards run first (the
14
+ * verifier list's "OSS entries first" rule): today the PlatformClient
15
+ * origin guard (domain/platformclient/origin-guard.ts), composed only
16
+ * under an authentication posture, where PlatformClient tokens exist.
17
+ * Liveness is not a guard in open source: the PlatformClient verifier
18
+ * refuses a deleted client's tokens itself, so verifier-only lanes (the
19
+ * extension HTTP edges) refuse them too. With no posture and no unit
20
+ * guards, the serving chain runs no guard at all.
16
21
  *
17
22
  * The in-process exemption is STRUCTURAL, not policed: guards are a
18
23
  * parameter of the serving chain's identity source only
@@ -1 +1 @@
1
- {"version":3,"file":"caller-guards.d.ts","sourceRoot":"","sources":["../../src/extensions/caller-guards.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,MAAM,WAAW,WAAW;IAC1B,0EAA0E;IAC1E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;;;;;OAQG;IACH,KAAK,CACH,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,IAAI,CAAC,CAAC;CAClB"}
1
+ {"version":3,"file":"caller-guards.d.ts","sourceRoot":"","sources":["../../src/extensions/caller-guards.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,MAAM,WAAW,WAAW;IAC1B,0EAA0E;IAC1E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;;;;;OAQG;IACH,KAAK,CACH,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,IAAI,CAAC,CAAC;CAClB"}