@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.
- package/dist/authorization/authorizer.d.ts +10 -4
- package/dist/authorization/authorizer.d.ts.map +1 -1
- package/dist/authorization/authorizer.js +11 -4
- package/dist/authorization/authorizer.js.map +1 -1
- package/dist/authorization/model/index.d.ts +4 -4
- package/dist/authorization/model/index.d.ts.map +1 -1
- package/dist/authorization/model/index.js +2 -0
- package/dist/authorization/model/index.js.map +1 -1
- package/dist/authorization/model/oauth_app.d.ts.map +1 -1
- package/dist/authorization/model/oauth_app.js +3 -2
- package/dist/authorization/model/oauth_app.js.map +1 -1
- package/dist/authorization/model/platform_client.d.ts +2 -0
- package/dist/authorization/model/platform_client.d.ts.map +1 -0
- package/dist/authorization/model/platform_client.js +31 -0
- package/dist/authorization/model/platform_client.js.map +1 -0
- package/dist/boot/compose.d.ts.map +1 -1
- package/dist/boot/compose.js +88 -5
- package/dist/boot/compose.js.map +1 -1
- package/dist/boot/route-shadowing.d.ts +25 -0
- package/dist/boot/route-shadowing.d.ts.map +1 -0
- package/dist/boot/route-shadowing.js +17 -0
- package/dist/boot/route-shadowing.js.map +1 -0
- package/dist/domain/iampolicy/membership.d.ts +6 -1
- package/dist/domain/iampolicy/membership.d.ts.map +1 -1
- package/dist/domain/iampolicy/membership.js +8 -2
- package/dist/domain/iampolicy/membership.js.map +1 -1
- package/dist/domain/identityaccount/constants.d.ts +13 -0
- package/dist/domain/identityaccount/constants.d.ts.map +1 -1
- package/dist/domain/identityaccount/constants.js +17 -0
- package/dist/domain/identityaccount/constants.js.map +1 -1
- package/dist/domain/identityaccount/controller.d.ts +3 -1
- package/dist/domain/identityaccount/controller.d.ts.map +1 -1
- package/dist/domain/identityaccount/controller.js +15 -6
- package/dist/domain/identityaccount/controller.js.map +1 -1
- package/dist/domain/identityaccount/operator.d.ts.map +1 -1
- package/dist/domain/identityaccount/operator.js +1 -0
- package/dist/domain/identityaccount/operator.js.map +1 -1
- package/dist/domain/identityaccount/provisioning.d.ts +18 -0
- package/dist/domain/identityaccount/provisioning.d.ts.map +1 -1
- package/dist/domain/identityaccount/provisioning.js +1 -0
- package/dist/domain/identityaccount/provisioning.js.map +1 -1
- package/dist/domain/identityaccount/resource-store.js +9 -5
- package/dist/domain/identityaccount/resource-store.js.map +1 -1
- package/dist/domain/identityaccount/steps.d.ts +11 -2
- package/dist/domain/identityaccount/steps.d.ts.map +1 -1
- package/dist/domain/identityaccount/steps.js +42 -4
- package/dist/domain/identityaccount/steps.js.map +1 -1
- package/dist/domain/identityaccount/store-contract.d.ts.map +1 -1
- package/dist/domain/identityaccount/store-contract.js +33 -0
- package/dist/domain/identityaccount/store-contract.js.map +1 -1
- package/dist/domain/identityaccount/store.d.ts +7 -5
- package/dist/domain/identityaccount/store.d.ts.map +1 -1
- package/dist/domain/identityaccount/store.js.map +1 -1
- package/dist/domain/platform/controller.d.ts +10 -0
- package/dist/domain/platform/controller.d.ts.map +1 -1
- package/dist/domain/platform/controller.js +2 -1
- package/dist/domain/platform/controller.js.map +1 -1
- package/dist/domain/platformclient/constants.d.ts +60 -0
- package/dist/domain/platformclient/constants.d.ts.map +1 -0
- package/dist/domain/platformclient/constants.js +78 -0
- package/dist/domain/platformclient/constants.js.map +1 -0
- package/dist/domain/platformclient/controller.d.ts +59 -0
- package/dist/domain/platformclient/controller.d.ts.map +1 -0
- package/dist/domain/platformclient/controller.js +191 -0
- package/dist/domain/platformclient/controller.js.map +1 -0
- package/dist/domain/platformclient/credentials.d.ts +13 -0
- package/dist/domain/platformclient/credentials.d.ts.map +1 -0
- package/dist/domain/platformclient/credentials.js +56 -0
- package/dist/domain/platformclient/credentials.js.map +1 -0
- package/dist/domain/platformclient/mint.d.ts +23 -0
- package/dist/domain/platformclient/mint.d.ts.map +1 -0
- package/dist/domain/platformclient/mint.js +254 -0
- package/dist/domain/platformclient/mint.js.map +1 -0
- package/dist/domain/platformclient/origin-guard.d.ts +9 -0
- package/dist/domain/platformclient/origin-guard.d.ts.map +1 -0
- package/dist/domain/platformclient/origin-guard.js +81 -0
- package/dist/domain/platformclient/origin-guard.js.map +1 -0
- package/dist/domain/platformclient/resource-store.d.ts +4 -0
- package/dist/domain/platformclient/resource-store.d.ts.map +1 -0
- package/dist/domain/platformclient/resource-store.js +117 -0
- package/dist/domain/platformclient/resource-store.js.map +1 -0
- package/dist/domain/platformclient/steps.d.ts +51 -0
- package/dist/domain/platformclient/steps.d.ts.map +1 -0
- package/dist/domain/platformclient/steps.js +339 -0
- package/dist/domain/platformclient/steps.js.map +1 -0
- package/dist/domain/platformclient/store-contract.d.ts +8 -0
- package/dist/domain/platformclient/store-contract.d.ts.map +1 -0
- package/dist/domain/platformclient/store-contract.js +208 -0
- package/dist/domain/platformclient/store-contract.js.map +1 -0
- package/dist/domain/platformclient/store.d.ts +58 -0
- package/dist/domain/platformclient/store.d.ts.map +1 -0
- package/dist/domain/platformclient/store.js +13 -0
- package/dist/domain/platformclient/store.js.map +1 -0
- package/dist/domain/platformclient/system-managed.d.ts +18 -0
- package/dist/domain/platformclient/system-managed.d.ts.map +1 -0
- package/dist/domain/platformclient/system-managed.js +80 -0
- package/dist/domain/platformclient/system-managed.js.map +1 -0
- package/dist/domain/platformclient/token-controller.d.ts +11 -0
- package/dist/domain/platformclient/token-controller.d.ts.map +1 -0
- package/dist/domain/platformclient/token-controller.js +32 -0
- package/dist/domain/platformclient/token-controller.js.map +1 -0
- package/dist/domain/platformclient/verifier.d.ts +10 -0
- package/dist/domain/platformclient/verifier.d.ts.map +1 -0
- package/dist/domain/platformclient/verifier.js +76 -0
- package/dist/domain/platformclient/verifier.js.map +1 -0
- package/dist/encryption/key-manager.d.ts +20 -3
- package/dist/encryption/key-manager.d.ts.map +1 -1
- package/dist/encryption/key-manager.js +64 -42
- package/dist/encryption/key-manager.js.map +1 -1
- package/dist/extensions/caller-guards.d.ts +8 -3
- package/dist/extensions/caller-guards.d.ts.map +1 -1
- package/dist/extensions/drivers.d.ts +37 -0
- package/dist/extensions/drivers.d.ts.map +1 -1
- package/dist/extensions/guest-token-minting.d.ts +26 -0
- package/dist/extensions/guest-token-minting.d.ts.map +1 -0
- package/dist/extensions/guest-token-minting.js +2 -0
- package/dist/extensions/guest-token-minting.js.map +1 -0
- package/dist/extensions/identity.d.ts +6 -4
- package/dist/extensions/identity.d.ts.map +1 -1
- package/dist/extensions/identity.js.map +1 -1
- package/dist/extensions/registry.d.ts +30 -1
- package/dist/extensions/registry.d.ts.map +1 -1
- package/dist/extensions/registry.js +34 -1
- package/dist/extensions/registry.js.map +1 -1
- package/dist/index.d.ts +13 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/pipeline/interceptors/auth.d.ts +14 -0
- package/dist/pipeline/interceptors/auth.d.ts.map +1 -1
- package/dist/pipeline/interceptors/auth.js +24 -0
- package/dist/pipeline/interceptors/auth.js.map +1 -1
- package/dist/pipeline/steps/build-update-state.d.ts +11 -1
- package/dist/pipeline/steps/build-update-state.d.ts.map +1 -1
- package/dist/pipeline/steps/build-update-state.js +5 -2
- package/dist/pipeline/steps/build-update-state.js.map +1 -1
- package/dist/platformtoken/envelope.d.ts +100 -0
- package/dist/platformtoken/envelope.d.ts.map +1 -0
- package/dist/platformtoken/envelope.js +184 -0
- package/dist/platformtoken/envelope.js.map +1 -0
- package/dist/platformtoken/key-ring.d.ts +85 -0
- package/dist/platformtoken/key-ring.d.ts.map +1 -0
- package/dist/platformtoken/key-ring.js +164 -0
- package/dist/platformtoken/key-ring.js.map +1 -0
- package/package.json +6 -6
- package/src/authorization/README.md +1 -1
- package/src/authorization/__tests__/authorizer.test.ts +6 -2
- package/src/authorization/__tests__/wire-permissions.test.ts +1 -0
- package/src/authorization/authorizer.ts +11 -4
- package/src/authorization/model/__tests__/registry.test.ts +8 -1
- package/src/authorization/model/index.ts +6 -4
- package/src/authorization/model/oauth_app.ts +3 -2
- package/src/authorization/model/platform_client.ts +43 -0
- package/src/boot/__tests__/auth-enabled-composition.test.ts +2 -1
- package/src/boot/__tests__/route-shadowing.test.ts +67 -0
- package/src/boot/compose.ts +90 -5
- package/src/boot/route-shadowing.ts +47 -0
- package/src/domain/iampolicy/__tests__/membership.test.ts +7 -0
- package/src/domain/iampolicy/membership.ts +8 -2
- package/src/domain/identityaccount/__tests__/platform-client-accounts.test.ts +124 -0
- package/src/domain/identityaccount/__tests__/resource-store.test.ts +1 -0
- package/src/domain/identityaccount/constants.ts +20 -0
- package/src/domain/identityaccount/controller.ts +16 -4
- package/src/domain/identityaccount/operator.ts +1 -0
- package/src/domain/identityaccount/provisioning.ts +17 -0
- package/src/domain/identityaccount/resource-store.ts +9 -5
- package/src/domain/identityaccount/steps.ts +58 -3
- package/src/domain/identityaccount/store-contract.ts +51 -0
- package/src/domain/identityaccount/store.ts +7 -5
- package/src/domain/platform/__tests__/platform.test.ts +7 -1
- package/src/domain/platform/controller.ts +12 -1
- package/src/domain/platformclient/__tests__/controller.test.ts +397 -0
- package/src/domain/platformclient/__tests__/credentials.test.ts +46 -0
- package/src/domain/platformclient/__tests__/mint.test.ts +415 -0
- package/src/domain/platformclient/__tests__/resource-store.test.ts +140 -0
- package/src/domain/platformclient/__tests__/system-managed.test.ts +101 -0
- package/src/domain/platformclient/__tests__/verifier-and-guard.test.ts +207 -0
- package/src/domain/platformclient/constants.ts +120 -0
- package/src/domain/platformclient/controller.ts +449 -0
- package/src/domain/platformclient/credentials.ts +68 -0
- package/src/domain/platformclient/mint.ts +412 -0
- package/src/domain/platformclient/origin-guard.ts +117 -0
- package/src/domain/platformclient/resource-store.ts +150 -0
- package/src/domain/platformclient/steps.ts +472 -0
- package/src/domain/platformclient/store-contract.ts +318 -0
- package/src/domain/platformclient/store.ts +63 -0
- package/src/domain/platformclient/system-managed.ts +115 -0
- package/src/domain/platformclient/token-controller.ts +49 -0
- package/src/domain/platformclient/verifier.ts +106 -0
- package/src/encryption/key-manager.ts +87 -44
- package/src/extensions/__tests__/extension-composition.test.ts +3 -2
- package/src/extensions/__tests__/platform-client-composed.test.ts +288 -0
- package/src/extensions/__tests__/registry.test.ts +4 -1
- package/src/extensions/__tests__/tier-truthfulness.test.ts +8 -0
- package/src/extensions/caller-guards.ts +8 -3
- package/src/extensions/drivers.ts +37 -0
- package/src/extensions/guest-token-minting.ts +32 -0
- package/src/extensions/identity.ts +6 -4
- package/src/extensions/registry.ts +77 -3
- package/src/index.ts +55 -0
- package/src/pipeline/interceptors/auth.ts +27 -0
- package/src/pipeline/steps/__tests__/references.test.ts +2 -0
- package/src/pipeline/steps/build-update-state.ts +5 -2
- package/src/platformtoken/__tests__/envelope.test.ts +277 -0
- package/src/platformtoken/__tests__/key-ring.test.ts +205 -0
- package/src/platformtoken/envelope.ts +276 -0
- package/src/platformtoken/key-ring.ts +266 -0
- 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
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
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":"
|
|
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
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
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
|
|
13
|
-
* configuration would be worse
|
|
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
|
-
*
|
|
16
|
-
* auto-generate, which overwrites the file's content —
|
|
17
|
-
* behavior (loadKeyFromFile error → generate → save),
|
|
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
|
|
42
|
-
* on unusable EXPLICIT configuration (bad env value)
|
|
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
|
|
75
|
+
// 1. Environment variable (highest priority) — Base64-encoded.
|
|
48
76
|
const envValue = env[envVar];
|
|
49
77
|
if (envValue !== undefined && envValue !== "") {
|
|
50
|
-
return
|
|
78
|
+
return codec.fromEnv(envVar, decodeEnvBase64(envVar, envValue));
|
|
51
79
|
}
|
|
52
|
-
// 2. Local key file —
|
|
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
|
|
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 =
|
|
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
|
|
70
|
-
function
|
|
71
|
-
const
|
|
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 (
|
|
106
|
+
if (decoded.toString("base64") !== value) {
|
|
77
107
|
throw new Error(`invalid Base64 encoding in ${envVar}`);
|
|
78
108
|
}
|
|
79
|
-
|
|
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
|
|
91
|
-
* undefined (fall through the ladder); present
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
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
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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":"AAAA
|
|
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.
|
|
14
|
-
*
|
|
15
|
-
*
|
|
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
|
|
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"}
|