@atlasauth/backend 0.2.0 → 0.4.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/client/api-keys.d.ts +50 -1
- package/dist/client/api-keys.js +14 -0
- package/dist/client/api-keys.js.map +1 -1
- package/dist/client/index.d.ts +40 -2
- package/dist/client/index.js +4 -0
- package/dist/client/index.js.map +1 -1
- package/dist/client/machines.d.ts +183 -0
- package/dist/client/machines.js +73 -0
- package/dist/client/machines.js.map +1 -0
- package/dist/client/messaging.d.ts +287 -21
- package/dist/client/messaging.js +18 -6
- package/dist/client/messaging.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/dist/pca/require-pca.d.ts +47 -0
- package/dist/pca/require-pca.js +121 -0
- package/dist/pca/require-pca.js.map +1 -0
- package/dist/pca/verify.d.ts +36 -0
- package/dist/pca/verify.js +136 -0
- package/dist/pca/verify.js.map +1 -0
- package/package.json +3 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type RequestFn } from './request';
|
|
2
|
-
import type { ListPage } from './types';
|
|
2
|
+
import type { CursorPage, ListPage } from './types';
|
|
3
3
|
export type ApiKeySubjectType = 'user' | 'organization';
|
|
4
4
|
/**
|
|
5
5
|
* An end-user API key — Clerk `api_keys` parity. A tenant mints these for ITS OWN
|
|
@@ -56,6 +56,45 @@ export type ApiKeyVerification = {
|
|
|
56
56
|
claims: Record<string, unknown>;
|
|
57
57
|
last_used_at: number | null;
|
|
58
58
|
};
|
|
59
|
+
/**
|
|
60
|
+
* §P1-8 a short-lived, offline-verifiable access JWT minted from a long-lived
|
|
61
|
+
* `ak_` key (`POST /v1/api_keys/token`). Signed with the instance's RS256 key, so
|
|
62
|
+
* any resource server verifies it against the public JWKS without a round trip.
|
|
63
|
+
*/
|
|
64
|
+
export interface ApiKeyToken {
|
|
65
|
+
object: 'api_key_token';
|
|
66
|
+
token: string;
|
|
67
|
+
token_type: 'Bearer';
|
|
68
|
+
jti: string;
|
|
69
|
+
key_id: string;
|
|
70
|
+
subject_type: ApiKeySubjectType;
|
|
71
|
+
subject_id: string;
|
|
72
|
+
scopes: string[];
|
|
73
|
+
constraints: Record<string, unknown>;
|
|
74
|
+
expires_in: number;
|
|
75
|
+
expires_at: number;
|
|
76
|
+
/** Which JWKS/issuer a verifier should check, so it needn't parse the JWT first. */
|
|
77
|
+
issuer: string;
|
|
78
|
+
}
|
|
79
|
+
export interface MintApiKeyTokenBody {
|
|
80
|
+
/** The long-lived `ak_` secret to mint from. */
|
|
81
|
+
secret: string;
|
|
82
|
+
/** Requested lifetime; clamped to the key's ceiling, its expiry, and the global cap. */
|
|
83
|
+
ttl_seconds?: number;
|
|
84
|
+
audience?: string | string[];
|
|
85
|
+
}
|
|
86
|
+
/** One entry in the revocation feed: an id and when it was revoked. */
|
|
87
|
+
export interface RevokedApiKeyRef {
|
|
88
|
+
object: 'api_key';
|
|
89
|
+
id: string;
|
|
90
|
+
revoked_at: number | null;
|
|
91
|
+
}
|
|
92
|
+
export interface ListRevokedApiKeysQuery {
|
|
93
|
+
/** An ISO-8601 instant, epoch-millis, or a `next_cursor` from a previous page. */
|
|
94
|
+
since?: string;
|
|
95
|
+
/** Page size (server clamps to its own maximum). */
|
|
96
|
+
limit?: number;
|
|
97
|
+
}
|
|
59
98
|
export declare function apiKeysResource(request: RequestFn): {
|
|
60
99
|
/** Optionally narrowed to one subject. */
|
|
61
100
|
list(query?: {
|
|
@@ -74,4 +113,14 @@ export declare function apiKeysResource(request: RequestFn): {
|
|
|
74
113
|
id: string;
|
|
75
114
|
revoked: true;
|
|
76
115
|
}>;
|
|
116
|
+
/**
|
|
117
|
+
* §P1-8 mint a short-lived delegated token from an `ak_` key. Rate-limited —
|
|
118
|
+
* presenting the secret is the same online credential surface as verify.
|
|
119
|
+
*/
|
|
120
|
+
mintToken(body: MintApiKeyTokenBody): Promise<ApiKeyToken>;
|
|
121
|
+
/**
|
|
122
|
+
* §P1-8 the revocation feed a resource server polls to deny-list revoked keys
|
|
123
|
+
* while their delegated tokens are still live. Keyset-paginated via `since`.
|
|
124
|
+
*/
|
|
125
|
+
listRevoked(query?: ListRevokedApiKeysQuery): Promise<CursorPage<RevokedApiKeyRef>>;
|
|
77
126
|
};
|
package/dist/client/api-keys.js
CHANGED
|
@@ -26,6 +26,20 @@ function apiKeysResource(request) {
|
|
|
26
26
|
delete(id) {
|
|
27
27
|
return request({ method: 'DELETE', path: `/v1/api_keys/${(0, request_1.enc)(id)}` });
|
|
28
28
|
},
|
|
29
|
+
/**
|
|
30
|
+
* §P1-8 mint a short-lived delegated token from an `ak_` key. Rate-limited —
|
|
31
|
+
* presenting the secret is the same online credential surface as verify.
|
|
32
|
+
*/
|
|
33
|
+
mintToken(body) {
|
|
34
|
+
return request({ method: 'POST', path: '/v1/api_keys/token', body });
|
|
35
|
+
},
|
|
36
|
+
/**
|
|
37
|
+
* §P1-8 the revocation feed a resource server polls to deny-list revoked keys
|
|
38
|
+
* while their delegated tokens are still live. Keyset-paginated via `since`.
|
|
39
|
+
*/
|
|
40
|
+
listRevoked(query = {}) {
|
|
41
|
+
return request({ method: 'GET', path: '/v1/api_keys/revoked', query: { ...query } });
|
|
42
|
+
},
|
|
29
43
|
};
|
|
30
44
|
}
|
|
31
45
|
//# sourceMappingURL=api-keys.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-keys.js","sourceRoot":"","sources":["../../src/client/api-keys.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"api-keys.js","sourceRoot":"","sources":["../../src/client/api-keys.ts"],"names":[],"mappings":";;AA2GA,0CA0CC;AArJD,uCAAgD;AA2GhD,SAAgB,eAAe,CAAC,OAAkB;IAChD,OAAO;QACL,0CAA0C;QAC1C,IAAI,CAAC,KAGJ;YACC,OAAO,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAC;QACjE,CAAC;QACD,qDAAqD;QACrD,MAAM,CAAC,IAAsB,EAAE,cAAuB;YACpD,OAAO,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAC;QACjF,CAAC;QACD,iFAAiF;QACjF,MAAM,CAAC,MAAc;YACnB,OAAO,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,qBAAqB,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;QACpF,CAAC;QACD,GAAG,CAAC,EAAU;YACZ,OAAO,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,gBAAgB,IAAA,aAAG,EAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QACrE,CAAC;QACD,MAAM,CAAC,EAAU,EAAE,IAAsB;YACvC,OAAO,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,gBAAgB,IAAA,aAAG,EAAC,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7E,CAAC;QACD,sEAAsE;QACtE,MAAM,CAAC,EAAU;YACf,OAAO,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,gBAAgB,IAAA,aAAG,EAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QACxE,CAAC;QACD;;;WAGG;QACH,SAAS,CAAC,IAAyB;YACjC,OAAO,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,oBAAoB,EAAE,IAAI,EAAE,CAAC,CAAC;QACvE,CAAC;QACD;;;WAGG;QACH,WAAW,CAAC,QAAiC,EAAE;YAC7C,OAAO,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,sBAAsB,EAAE,KAAK,EAAE,EAAE,GAAG,KAAK,EAAE,EAAE,CAAC,CAAC;QACvF,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/dist/client/index.d.ts
CHANGED
|
@@ -390,6 +390,33 @@ export declare function createAtlasClient(config: AtlasClientConfig): {
|
|
|
390
390
|
id: string;
|
|
391
391
|
revoked: true;
|
|
392
392
|
}>;
|
|
393
|
+
mintToken(body: import("./api-keys").MintApiKeyTokenBody): Promise<import("./api-keys").ApiKeyToken>;
|
|
394
|
+
listRevoked(query?: import("./api-keys").ListRevokedApiKeysQuery): Promise<import("./types").CursorPage<import("./api-keys").RevokedApiKeyRef>>;
|
|
395
|
+
};
|
|
396
|
+
machines: {
|
|
397
|
+
list(query?: import("./machines").ListMachinesQuery): Promise<import("./machines").MachineListPage>;
|
|
398
|
+
create(body: import("./machines").CreateMachineBody, idempotencyKey?: string): Promise<import("./machines").MachineWithSecret>;
|
|
399
|
+
get(id: string): Promise<import("./machines").Machine>;
|
|
400
|
+
rename(id: string, name: string): Promise<import("./machines").Machine>;
|
|
401
|
+
patchMetadata(id: string, metadata: import("./machines").MachineMetadata): Promise<import("./machines").Machine>;
|
|
402
|
+
approve(id: string): Promise<import("./machines").Machine>;
|
|
403
|
+
revoke(id: string): Promise<import("./machines").Machine>;
|
|
404
|
+
rotateSecret(id: string): Promise<import("./machines").MachineWithSecret>;
|
|
405
|
+
rotateKey(id: string, publicKeyPem: string): Promise<import("./machines").Machine>;
|
|
406
|
+
delete(id: string): Promise<{
|
|
407
|
+
object: "machine";
|
|
408
|
+
id: string;
|
|
409
|
+
deleted: true;
|
|
410
|
+
}>;
|
|
411
|
+
organizationMemberships(id: string): Promise<import("./machines").MachineOrganizationMembershipPage>;
|
|
412
|
+
createEnrolmentToken(body?: import("./machines").CreateEnrolmentTokenBody, idempotencyKey?: string): Promise<import("./machines").MachineEnrolmentTokenWithSecret>;
|
|
413
|
+
listEnrolmentTokens(): Promise<import("./types").ListPage<import("./machines").MachineEnrolmentToken>>;
|
|
414
|
+
deleteEnrolmentToken(id: string): Promise<{
|
|
415
|
+
object: "machine_enrolment_token";
|
|
416
|
+
id: string;
|
|
417
|
+
deleted: true;
|
|
418
|
+
}>;
|
|
419
|
+
verifyM2mToken(token: string): Promise<import("./machines").M2mTokenVerification>;
|
|
393
420
|
};
|
|
394
421
|
oauthProviders: {
|
|
395
422
|
list(): Promise<import("./types").ListPage<import("./oauth-providers").OAuthProvider>>;
|
|
@@ -654,8 +681,18 @@ export declare function createAtlasClient(config: AtlasClientConfig): {
|
|
|
654
681
|
};
|
|
655
682
|
messaging: {
|
|
656
683
|
get(): Promise<import("./messaging").MessagingProviders>;
|
|
657
|
-
setEmail
|
|
658
|
-
|
|
684
|
+
setEmail: {
|
|
685
|
+
(body: import("./messaging").EmailProviderInput): Promise<import("./messaging").EmailProvider>;
|
|
686
|
+
<T extends string>(body: Omit<import("./messaging").MessagingProviderInput, "transport"> & {
|
|
687
|
+
transport: T;
|
|
688
|
+
} & (string extends T ? unknown : never)): Promise<import("./messaging").MessagingProvider>;
|
|
689
|
+
};
|
|
690
|
+
setSms: {
|
|
691
|
+
(body: import("./messaging").SmsProviderInput): Promise<import("./messaging").SmsProvider>;
|
|
692
|
+
<T extends string>(body: Omit<import("./messaging").MessagingProviderInput, "transport"> & {
|
|
693
|
+
transport: T;
|
|
694
|
+
} & (string extends T ? unknown : never)): Promise<import("./messaging").MessagingProvider>;
|
|
695
|
+
};
|
|
659
696
|
deleteChannel(channel: "email" | "sms"): Promise<import("./messaging").DeletedMessagingProvider>;
|
|
660
697
|
test(channel: "email" | "sms", body: {
|
|
661
698
|
to: string;
|
|
@@ -773,6 +810,7 @@ export * from './sign-in-tokens';
|
|
|
773
810
|
export * from './audit-logs';
|
|
774
811
|
export * from './jwt-templates';
|
|
775
812
|
export * from './api-keys';
|
|
813
|
+
export * from './machines';
|
|
776
814
|
export * from './oauth-providers';
|
|
777
815
|
export * from './sso-onboarding';
|
|
778
816
|
export * from './scim-provisioning';
|
package/dist/client/index.js
CHANGED
|
@@ -36,6 +36,7 @@ const sign_in_tokens_1 = require("./sign-in-tokens");
|
|
|
36
36
|
const audit_logs_1 = require("./audit-logs");
|
|
37
37
|
const jwt_templates_1 = require("./jwt-templates");
|
|
38
38
|
const api_keys_1 = require("./api-keys");
|
|
39
|
+
const machines_1 = require("./machines");
|
|
39
40
|
const oauth_providers_1 = require("./oauth-providers");
|
|
40
41
|
const sso_onboarding_1 = require("./sso-onboarding");
|
|
41
42
|
const scim_provisioning_1 = require("./scim-provisioning");
|
|
@@ -94,6 +95,8 @@ function createAtlasClient(config) {
|
|
|
94
95
|
auditLogs: (0, audit_logs_1.auditLogsResource)(request),
|
|
95
96
|
jwtTemplates: (0, jwt_templates_1.jwtTemplatesResource)(request),
|
|
96
97
|
apiKeys: (0, api_keys_1.apiKeysResource)(request),
|
|
98
|
+
// §9.3 / §P1-7 named machine identities + device registry + enrolment tokens.
|
|
99
|
+
machines: (0, machines_1.machinesResource)(request),
|
|
97
100
|
oauthProviders: (0, oauth_providers_1.oauthProvidersResource)(request),
|
|
98
101
|
ssoOnboarding: (0, sso_onboarding_1.ssoOnboardingResource)(request),
|
|
99
102
|
scimProvisioning: (0, scim_provisioning_1.scimProvisioningResource)(request),
|
|
@@ -151,6 +154,7 @@ __exportStar(require("./sign-in-tokens"), exports);
|
|
|
151
154
|
__exportStar(require("./audit-logs"), exports);
|
|
152
155
|
__exportStar(require("./jwt-templates"), exports);
|
|
153
156
|
__exportStar(require("./api-keys"), exports);
|
|
157
|
+
__exportStar(require("./machines"), exports);
|
|
154
158
|
__exportStar(require("./oauth-providers"), exports);
|
|
155
159
|
__exportStar(require("./sso-onboarding"), exports);
|
|
156
160
|
__exportStar(require("./scim-provisioning"), exports);
|
package/dist/client/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { type RequestFn } from './request';
|
|
2
|
+
import type { CursorParams, ListPage, Metadata } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* §9.3 / §P1-7 MACHINE identities + the device registry.
|
|
5
|
+
*
|
|
6
|
+
* A machine is a first-class non-human principal with its own secret (`mk_…`),
|
|
7
|
+
* distinct from an instance API key. §P1-7 layers a DEVICE half on top: a machine
|
|
8
|
+
* can carry a registered public KEY, a lifecycle `status`, device `metadata`, and
|
|
9
|
+
* optional org/owner ownership. This namespace is the `sk_`-authenticated
|
|
10
|
+
* MANAGEMENT surface (list/filter, create, rename, metadata, approve, revoke, key
|
|
11
|
+
* rotation, delete) plus enrolment-token management and M2M-token verification.
|
|
12
|
+
*
|
|
13
|
+
* The device self-serve half (`/v1/machines/enroll`, `/challenge`, `/token`) is a
|
|
14
|
+
* PUBLIC, credential-presented surface a bootstrapping device calls with no `sk_`,
|
|
15
|
+
* so it is deliberately NOT part of this secret-key client.
|
|
16
|
+
*/
|
|
17
|
+
/** A machine's lifecycle state. `pending` awaits approval; `revoked` is terminal. */
|
|
18
|
+
export type MachineStatus = 'pending' | 'active' | 'revoked';
|
|
19
|
+
/** Device metadata bag (hostname/os/app_version/last_seen_at/…). */
|
|
20
|
+
export type MachineMetadata = Record<string, unknown>;
|
|
21
|
+
/**
|
|
22
|
+
* A named machine identity. `secret_hash` is never present on any machine surface
|
|
23
|
+
* — only a hash is stored, so the `mk_` secret is shown exactly once at
|
|
24
|
+
* create/rotate (see {@link MachineWithSecret}).
|
|
25
|
+
*/
|
|
26
|
+
export interface Machine {
|
|
27
|
+
object: 'machine';
|
|
28
|
+
id: string;
|
|
29
|
+
name: string;
|
|
30
|
+
organization_id: string | null;
|
|
31
|
+
status: MachineStatus;
|
|
32
|
+
/** JWK thumbprint of the registered device key, or null for a secret-only machine. */
|
|
33
|
+
public_key_jkt: string | null;
|
|
34
|
+
metadata: MachineMetadata;
|
|
35
|
+
enrolled_at: number | null;
|
|
36
|
+
created_at: number;
|
|
37
|
+
updated_at: number;
|
|
38
|
+
}
|
|
39
|
+
/** The create / rotate_secret response: the machine plus its `mk_` secret, shown once. */
|
|
40
|
+
export interface MachineWithSecret extends Machine {
|
|
41
|
+
secret: string;
|
|
42
|
+
}
|
|
43
|
+
export interface CreateMachineBody {
|
|
44
|
+
name: string;
|
|
45
|
+
/** Round-7: the user who owns this machine identity. */
|
|
46
|
+
owner_user_id?: string;
|
|
47
|
+
/** Round-7: bind the machine to an organization at creation. */
|
|
48
|
+
organization_id?: string;
|
|
49
|
+
/** Round-7: free-form data bag stored on the machine. */
|
|
50
|
+
data?: Metadata;
|
|
51
|
+
/** Device metadata (hostname/os/app_version/…). */
|
|
52
|
+
metadata?: MachineMetadata;
|
|
53
|
+
}
|
|
54
|
+
export interface ListMachinesQuery extends CursorParams {
|
|
55
|
+
status?: MachineStatus;
|
|
56
|
+
/** Filter by the device's reported hostname. */
|
|
57
|
+
hostname?: string;
|
|
58
|
+
/** Round-7: only machines owned by this user. */
|
|
59
|
+
owner_user_id?: string;
|
|
60
|
+
/** Round-7: only machines belonging to this organization. */
|
|
61
|
+
organization_id?: string;
|
|
62
|
+
/** Round-7: a JSON-encoded metadata match filter. */
|
|
63
|
+
metadata?: string;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* The machine list page. The envelope is `{ object: 'list', data }`; §P1-7's
|
|
67
|
+
* cursor fields (`has_more`/`next_cursor`) are present on the round-7 surface and
|
|
68
|
+
* optional here so the type is honest against both.
|
|
69
|
+
*/
|
|
70
|
+
export interface MachineListPage {
|
|
71
|
+
object: 'list';
|
|
72
|
+
data: Machine[];
|
|
73
|
+
has_more?: boolean;
|
|
74
|
+
next_cursor?: string | null;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* A machine's org membership, membership-shaped like
|
|
78
|
+
* `GET /v1/users/:id/organization_memberships`. A machine belongs to at most one
|
|
79
|
+
* org today, so the list holds 0 or 1 entries; `role` is always null (a machine
|
|
80
|
+
* holds no org role).
|
|
81
|
+
*/
|
|
82
|
+
export interface MachineOrganizationMembership {
|
|
83
|
+
object: 'organization_membership';
|
|
84
|
+
organization_id: string;
|
|
85
|
+
organization_slug: string;
|
|
86
|
+
role: null;
|
|
87
|
+
plan: string | null;
|
|
88
|
+
joined_at: number;
|
|
89
|
+
}
|
|
90
|
+
export interface MachineOrganizationMembershipPage {
|
|
91
|
+
object: 'list';
|
|
92
|
+
data: MachineOrganizationMembership[];
|
|
93
|
+
has_more: boolean;
|
|
94
|
+
next_cursor: string | null;
|
|
95
|
+
}
|
|
96
|
+
/** An enrolment token — a short-lived credential a device presents to `/enroll`. */
|
|
97
|
+
export interface MachineEnrolmentToken {
|
|
98
|
+
object: 'machine_enrolment_token';
|
|
99
|
+
id: string;
|
|
100
|
+
organization_id: string | null;
|
|
101
|
+
max_uses: number;
|
|
102
|
+
uses: number;
|
|
103
|
+
expires_at: number;
|
|
104
|
+
requires_approval: boolean;
|
|
105
|
+
created_at: number;
|
|
106
|
+
}
|
|
107
|
+
/** The create response: the enrolment token plus its `met_` secret, shown once. */
|
|
108
|
+
export interface MachineEnrolmentTokenWithSecret extends MachineEnrolmentToken {
|
|
109
|
+
token: string;
|
|
110
|
+
}
|
|
111
|
+
export interface CreateEnrolmentTokenBody {
|
|
112
|
+
/** Bind machines enrolled with this token to an organization. */
|
|
113
|
+
organization_id?: string;
|
|
114
|
+
/** Round-7: the user who will own machines enrolled with this token. */
|
|
115
|
+
owner_user_id?: string;
|
|
116
|
+
/** Round-7: free-form data copied onto each enrolled machine. */
|
|
117
|
+
data?: Metadata;
|
|
118
|
+
/** Round-7: restrict the token to a single enrolment session. */
|
|
119
|
+
single_session?: boolean;
|
|
120
|
+
/** Round-7: the maximum number of machines that may enrol with this token. */
|
|
121
|
+
max_machines?: number;
|
|
122
|
+
/** How many times the token may be redeemed (defaults to 1 server-side). */
|
|
123
|
+
max_uses?: number;
|
|
124
|
+
/** Token lifetime; defaults to 3600s, capped at one year. */
|
|
125
|
+
expires_in_seconds?: number;
|
|
126
|
+
/** When true, enrolled machines start `pending` and must be approved. */
|
|
127
|
+
requires_approval?: boolean;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* The verify verdict for an M2M credential (Clerk `verifyM2MToken`): resolve a
|
|
131
|
+
* presented machine secret to its machine. An unknown, rotated, or revoked secret
|
|
132
|
+
* all resolve to the SAME `{ valid: false }`, so a caller cannot probe which
|
|
133
|
+
* machines exist.
|
|
134
|
+
*/
|
|
135
|
+
export type M2mTokenVerification = {
|
|
136
|
+
object: 'm2m_verification';
|
|
137
|
+
valid: false;
|
|
138
|
+
} | {
|
|
139
|
+
object: 'm2m_verification';
|
|
140
|
+
valid: true;
|
|
141
|
+
machine_id: string;
|
|
142
|
+
name: string;
|
|
143
|
+
};
|
|
144
|
+
export declare function machinesResource(request: RequestFn): {
|
|
145
|
+
/** List + filter machines (§P1-7 device-registry query). */
|
|
146
|
+
list(query?: ListMachinesQuery): Promise<MachineListPage>;
|
|
147
|
+
/** Create a machine. The `mk_` secret is returned once, here. */
|
|
148
|
+
create(body: CreateMachineBody, idempotencyKey?: string): Promise<MachineWithSecret>;
|
|
149
|
+
get(id: string): Promise<Machine>;
|
|
150
|
+
/** Rename a machine (`PATCH /v1/machines/:id`). */
|
|
151
|
+
rename(id: string, name: string): Promise<Machine>;
|
|
152
|
+
/** Merge device metadata (`PATCH /v1/machines/:id/metadata`). */
|
|
153
|
+
patchMetadata(id: string, metadata: MachineMetadata): Promise<Machine>;
|
|
154
|
+
/** Approve a `pending` device (→ `active`). */
|
|
155
|
+
approve(id: string): Promise<Machine>;
|
|
156
|
+
/** Revoke a machine (→ `revoked`). The record is kept; its key stops minting at once. */
|
|
157
|
+
revoke(id: string): Promise<Machine>;
|
|
158
|
+
/** Rotate the `mk_` secret. The new secret is shown once; the old stops working. */
|
|
159
|
+
rotateSecret(id: string): Promise<MachineWithSecret>;
|
|
160
|
+
/** Rotate the registered device keypair by supplying the new public key PEM. */
|
|
161
|
+
rotateKey(id: string, publicKeyPem: string): Promise<Machine>;
|
|
162
|
+
/** Delete a machine outright (distinct from {@link revoke}, which keeps the record). */
|
|
163
|
+
delete(id: string): Promise<{
|
|
164
|
+
object: "machine";
|
|
165
|
+
id: string;
|
|
166
|
+
deleted: true;
|
|
167
|
+
}>;
|
|
168
|
+
/** The machine's org memberships (0 or 1 entry). */
|
|
169
|
+
organizationMemberships(id: string): Promise<MachineOrganizationMembershipPage>;
|
|
170
|
+
/** Mint an enrolment token. The `met_` secret is returned once, here. */
|
|
171
|
+
createEnrolmentToken(body?: CreateEnrolmentTokenBody, idempotencyKey?: string): Promise<MachineEnrolmentTokenWithSecret>;
|
|
172
|
+
listEnrolmentTokens(): Promise<ListPage<MachineEnrolmentToken>>;
|
|
173
|
+
deleteEnrolmentToken(id: string): Promise<{
|
|
174
|
+
object: "machine_enrolment_token";
|
|
175
|
+
id: string;
|
|
176
|
+
deleted: true;
|
|
177
|
+
}>;
|
|
178
|
+
/**
|
|
179
|
+
* Verify a presented M2M credential (`POST /v1/m2m_tokens/verify`). Resolve a
|
|
180
|
+
* machine secret to its machine; every negative resolves to `{ valid: false }`.
|
|
181
|
+
*/
|
|
182
|
+
verifyM2mToken(token: string): Promise<M2mTokenVerification>;
|
|
183
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.machinesResource = machinesResource;
|
|
4
|
+
const request_1 = require("./request");
|
|
5
|
+
function machinesResource(request) {
|
|
6
|
+
return {
|
|
7
|
+
/** List + filter machines (§P1-7 device-registry query). */
|
|
8
|
+
list(query = {}) {
|
|
9
|
+
return request({ method: 'GET', path: '/v1/machines', query: { ...query } });
|
|
10
|
+
},
|
|
11
|
+
/** Create a machine. The `mk_` secret is returned once, here. */
|
|
12
|
+
create(body, idempotencyKey) {
|
|
13
|
+
return request({ method: 'POST', path: '/v1/machines', body, idempotencyKey });
|
|
14
|
+
},
|
|
15
|
+
get(id) {
|
|
16
|
+
return request({ method: 'GET', path: `/v1/machines/${(0, request_1.enc)(id)}` });
|
|
17
|
+
},
|
|
18
|
+
/** Rename a machine (`PATCH /v1/machines/:id`). */
|
|
19
|
+
rename(id, name) {
|
|
20
|
+
return request({ method: 'PATCH', path: `/v1/machines/${(0, request_1.enc)(id)}`, body: { name } });
|
|
21
|
+
},
|
|
22
|
+
/** Merge device metadata (`PATCH /v1/machines/:id/metadata`). */
|
|
23
|
+
patchMetadata(id, metadata) {
|
|
24
|
+
return request({ method: 'PATCH', path: `/v1/machines/${(0, request_1.enc)(id)}/metadata`, body: { metadata } });
|
|
25
|
+
},
|
|
26
|
+
/** Approve a `pending` device (→ `active`). */
|
|
27
|
+
approve(id) {
|
|
28
|
+
return request({ method: 'POST', path: `/v1/machines/${(0, request_1.enc)(id)}/approve` });
|
|
29
|
+
},
|
|
30
|
+
/** Revoke a machine (→ `revoked`). The record is kept; its key stops minting at once. */
|
|
31
|
+
revoke(id) {
|
|
32
|
+
return request({ method: 'POST', path: `/v1/machines/${(0, request_1.enc)(id)}/revoke` });
|
|
33
|
+
},
|
|
34
|
+
/** Rotate the `mk_` secret. The new secret is shown once; the old stops working. */
|
|
35
|
+
rotateSecret(id) {
|
|
36
|
+
return request({ method: 'POST', path: `/v1/machines/${(0, request_1.enc)(id)}/rotate_secret` });
|
|
37
|
+
},
|
|
38
|
+
/** Rotate the registered device keypair by supplying the new public key PEM. */
|
|
39
|
+
rotateKey(id, publicKeyPem) {
|
|
40
|
+
return request({
|
|
41
|
+
method: 'POST',
|
|
42
|
+
path: `/v1/machines/${(0, request_1.enc)(id)}/rotate_key`,
|
|
43
|
+
body: { public_key_pem: publicKeyPem },
|
|
44
|
+
});
|
|
45
|
+
},
|
|
46
|
+
/** Delete a machine outright (distinct from {@link revoke}, which keeps the record). */
|
|
47
|
+
delete(id) {
|
|
48
|
+
return request({ method: 'DELETE', path: `/v1/machines/${(0, request_1.enc)(id)}` });
|
|
49
|
+
},
|
|
50
|
+
/** The machine's org memberships (0 or 1 entry). */
|
|
51
|
+
organizationMemberships(id) {
|
|
52
|
+
return request({ method: 'GET', path: `/v1/machines/${(0, request_1.enc)(id)}/organization_memberships` });
|
|
53
|
+
},
|
|
54
|
+
/** Mint an enrolment token. The `met_` secret is returned once, here. */
|
|
55
|
+
createEnrolmentToken(body = {}, idempotencyKey) {
|
|
56
|
+
return request({ method: 'POST', path: '/v1/machine_enrolment_tokens', body, idempotencyKey });
|
|
57
|
+
},
|
|
58
|
+
listEnrolmentTokens() {
|
|
59
|
+
return request({ method: 'GET', path: '/v1/machine_enrolment_tokens' });
|
|
60
|
+
},
|
|
61
|
+
deleteEnrolmentToken(id) {
|
|
62
|
+
return request({ method: 'DELETE', path: `/v1/machine_enrolment_tokens/${(0, request_1.enc)(id)}` });
|
|
63
|
+
},
|
|
64
|
+
/**
|
|
65
|
+
* Verify a presented M2M credential (`POST /v1/m2m_tokens/verify`). Resolve a
|
|
66
|
+
* machine secret to its machine; every negative resolves to `{ valid: false }`.
|
|
67
|
+
*/
|
|
68
|
+
verifyM2mToken(token) {
|
|
69
|
+
return request({ method: 'POST', path: '/v1/m2m_tokens/verify', body: { token } });
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=machines.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"machines.js","sourceRoot":"","sources":["../../src/client/machines.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,30 +1,235 @@
|
|
|
1
1
|
import { type RequestFn } from './request';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
3
|
+
* Messaging providers — wire your own email or SMS provider (Resend, SES, SMTP,
|
|
4
|
+
* Brevo, Mailgun; Twilio, Vonage, MessageBird, Plivo, Telnyx, Sinch, Infobip,
|
|
5
|
+
* ClickSend, Bandwidth, AWS SNS) over the secret-key Backend API.
|
|
6
|
+
*
|
|
7
|
+
* Each transport accepts an exact set of `config` keys; the API refuses an
|
|
8
|
+
* unknown key with a 422 naming `config.<key>`. These types mirror that schema,
|
|
9
|
+
* so a typo or another provider's key name fails to compile.
|
|
5
10
|
*
|
|
6
11
|
* A provider SECRET is WRITE-ONLY: it goes in through `config` and is never
|
|
7
12
|
* read back — a response reports only WHICH secret keys are set (`secrets_set`).
|
|
8
|
-
*
|
|
9
|
-
*
|
|
13
|
+
*
|
|
14
|
+
* Required keys: every key marked "Required on first setup" must be sent the
|
|
15
|
+
* first time you configure a transport (or when you switch the channel to a
|
|
16
|
+
* different transport). When you update the SAME transport, the stored config is
|
|
17
|
+
* kept: omit a key — or send it as `''` — and its stored value (including a
|
|
18
|
+
* stored secret) stays. So a from-address change need not re-enter the API key.
|
|
10
19
|
*/
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
secrets_set: Record<string, boolean>;
|
|
21
|
-
updated_at: number;
|
|
20
|
+
/** Email transports accepted by `PUT /v1/messaging_providers/email`. */
|
|
21
|
+
export type EmailTransport = 'resend' | 'ses' | 'smtp' | 'brevo' | 'mailgun';
|
|
22
|
+
/** SMS transports accepted by `PUT /v1/messaging_providers/sms`. */
|
|
23
|
+
export type SmsTransport = 'twilio' | 'vonage' | 'messagebird' | 'plivo' | 'telnyx' | 'sinch' | 'infobip' | 'clicksend' | 'bandwidth' | 'aws_sns';
|
|
24
|
+
export type MessagingTransport = EmailTransport | SmsTransport;
|
|
25
|
+
/** Sender number or ID for an SMS provider. `from_address` on the request takes precedence. */
|
|
26
|
+
interface SmsFrom {
|
|
27
|
+
/** Sender number or ID for this provider. Optional; `from_address` on the request takes precedence. */
|
|
28
|
+
from?: string;
|
|
22
29
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
30
|
+
/** Resend. */
|
|
31
|
+
export interface ResendConfig {
|
|
32
|
+
/** Resend API key (`re_…`). Required on first setup. Write-only: never returned. */
|
|
33
|
+
api_key: string;
|
|
34
|
+
}
|
|
35
|
+
/** Brevo. */
|
|
36
|
+
export interface BrevoConfig {
|
|
37
|
+
/** Brevo API key (`xkeysib-…`). Required on first setup. Write-only: never returned. */
|
|
38
|
+
api_key: string;
|
|
39
|
+
}
|
|
40
|
+
/** Mailgun. */
|
|
41
|
+
export interface MailgunConfig {
|
|
42
|
+
/** Mailgun private API key. Required on first setup. Write-only: never returned. */
|
|
43
|
+
api_key: string;
|
|
44
|
+
/** Your Mailgun sending domain, e.g. `mg.example.com`. Required on first setup. */
|
|
45
|
+
domain: string;
|
|
46
|
+
/** Mailgun region. Default `us`. */
|
|
47
|
+
region?: 'us' | 'eu';
|
|
48
|
+
}
|
|
49
|
+
/** Amazon SES. */
|
|
50
|
+
export interface SesConfig {
|
|
51
|
+
/** AWS region, e.g. `us-east-1`. Required on first setup. */
|
|
52
|
+
region: string;
|
|
53
|
+
/** IAM access key ID. Required on first setup. Write-only: never returned. */
|
|
54
|
+
access_key_id: string;
|
|
55
|
+
/** IAM secret access key. Required on first setup. Write-only: never returned. */
|
|
56
|
+
secret_access_key: string;
|
|
57
|
+
/** STS session token, only for temporary credentials. Write-only: never returned. */
|
|
58
|
+
session_token?: string;
|
|
59
|
+
}
|
|
60
|
+
/** Any SMTP server. */
|
|
61
|
+
export interface SmtpConfig {
|
|
62
|
+
/** SMTP server hostname, e.g. `smtp.example.com`. Required on first setup. */
|
|
63
|
+
host: string;
|
|
64
|
+
/** SMTP port (1-65535). Default 587. */
|
|
65
|
+
port?: number;
|
|
66
|
+
/** Use implicit TLS. Default: `true` on port 465, otherwise STARTTLS. */
|
|
67
|
+
secure?: boolean;
|
|
68
|
+
/** SMTP username, if the server requires authentication. */
|
|
69
|
+
username?: string;
|
|
70
|
+
/** SMTP password or app password. Write-only: never returned. */
|
|
71
|
+
password?: string;
|
|
72
|
+
}
|
|
73
|
+
/** Twilio. */
|
|
74
|
+
export interface TwilioConfig extends SmsFrom {
|
|
75
|
+
/** Twilio Account SID (`AC…`). Required on first setup. */
|
|
76
|
+
account_sid: string;
|
|
77
|
+
/** Twilio auth token. Required on first setup. Write-only: never returned. */
|
|
78
|
+
auth_token: string;
|
|
79
|
+
/** WhatsApp-enabled sender number, for the WhatsApp channel. */
|
|
80
|
+
whatsapp_from?: string;
|
|
81
|
+
/** Voice-capable number, for the voice channel. */
|
|
82
|
+
voice_from?: string;
|
|
83
|
+
}
|
|
84
|
+
/** Vonage. */
|
|
85
|
+
export interface VonageConfig extends SmsFrom {
|
|
86
|
+
/** Vonage API key. Required on first setup. */
|
|
87
|
+
api_key: string;
|
|
88
|
+
/** Vonage API secret. Required on first setup. Write-only: never returned. */
|
|
89
|
+
api_secret: string;
|
|
90
|
+
}
|
|
91
|
+
/** MessageBird (Bird). */
|
|
92
|
+
export interface MessagebirdConfig extends SmsFrom {
|
|
93
|
+
/** MessageBird (Bird) access key. Required on first setup. Write-only: never returned. */
|
|
94
|
+
access_key: string;
|
|
95
|
+
}
|
|
96
|
+
/** Plivo. */
|
|
97
|
+
export interface PlivoConfig extends SmsFrom {
|
|
98
|
+
/** Plivo Auth ID. Required on first setup. */
|
|
99
|
+
auth_id: string;
|
|
100
|
+
/** Plivo auth token. Required on first setup. Write-only: never returned. */
|
|
101
|
+
auth_token: string;
|
|
102
|
+
}
|
|
103
|
+
/** Telnyx. */
|
|
104
|
+
export interface TelnyxConfig extends SmsFrom {
|
|
105
|
+
/** Telnyx API key. Required on first setup. Write-only: never returned. */
|
|
106
|
+
api_key: string;
|
|
107
|
+
}
|
|
108
|
+
/** Sinch. */
|
|
109
|
+
export interface SinchConfig extends SmsFrom {
|
|
110
|
+
/** Sinch service plan ID. Required on first setup. */
|
|
111
|
+
service_plan_id: string;
|
|
112
|
+
/** Sinch API token. Required on first setup. Write-only: never returned. */
|
|
113
|
+
api_token: string;
|
|
114
|
+
/** Sinch API region, a short lowercase code such as `us` or `eu`. Default `us`. */
|
|
115
|
+
region?: string;
|
|
116
|
+
}
|
|
117
|
+
/** Infobip. */
|
|
118
|
+
export interface InfobipConfig extends SmsFrom {
|
|
119
|
+
/** Your Infobip base URL, e.g. `https://xxxxx.api.infobip.com`. Must be https. Required on first setup. */
|
|
120
|
+
base_url: string;
|
|
121
|
+
/** Infobip API key. Required on first setup. Write-only: never returned. */
|
|
122
|
+
api_key: string;
|
|
123
|
+
}
|
|
124
|
+
/** ClickSend. */
|
|
125
|
+
export interface ClicksendConfig extends SmsFrom {
|
|
126
|
+
/** ClickSend username (your login email). Required on first setup. */
|
|
127
|
+
username: string;
|
|
128
|
+
/** ClickSend API key. Required on first setup. Write-only: never returned. */
|
|
129
|
+
api_key: string;
|
|
130
|
+
}
|
|
131
|
+
/** Bandwidth. */
|
|
132
|
+
export interface BandwidthConfig extends SmsFrom {
|
|
133
|
+
/** Bandwidth account ID. Required on first setup. */
|
|
134
|
+
account_id: string;
|
|
135
|
+
/** Bandwidth messaging application ID. Required on first setup. */
|
|
136
|
+
application_id: string;
|
|
137
|
+
/** Bandwidth API username. Required on first setup. */
|
|
138
|
+
username: string;
|
|
139
|
+
/** Bandwidth API password. Required on first setup. Write-only: never returned. */
|
|
140
|
+
password: string;
|
|
141
|
+
}
|
|
142
|
+
/** Amazon SNS. */
|
|
143
|
+
export interface AwsSnsConfig extends SmsFrom {
|
|
144
|
+
/** AWS region, e.g. `us-east-1`. Required on first setup. */
|
|
145
|
+
region: string;
|
|
146
|
+
/** IAM access key ID. Required on first setup. */
|
|
147
|
+
access_key_id: string;
|
|
148
|
+
/** IAM secret access key. Required on first setup. Write-only: never returned. */
|
|
149
|
+
secret_access_key: string;
|
|
150
|
+
/** STS session token, only for temporary credentials. Write-only: never returned. */
|
|
151
|
+
session_token?: string;
|
|
152
|
+
}
|
|
153
|
+
/** The `config` shape for each transport, keyed by transport. */
|
|
154
|
+
export interface MessagingTransportConfigs {
|
|
155
|
+
resend: ResendConfig;
|
|
156
|
+
ses: SesConfig;
|
|
157
|
+
smtp: SmtpConfig;
|
|
158
|
+
brevo: BrevoConfig;
|
|
159
|
+
mailgun: MailgunConfig;
|
|
160
|
+
twilio: TwilioConfig;
|
|
161
|
+
vonage: VonageConfig;
|
|
162
|
+
messagebird: MessagebirdConfig;
|
|
163
|
+
plivo: PlivoConfig;
|
|
164
|
+
telnyx: TelnyxConfig;
|
|
165
|
+
sinch: SinchConfig;
|
|
166
|
+
infobip: InfobipConfig;
|
|
167
|
+
clicksend: ClicksendConfig;
|
|
168
|
+
bandwidth: BandwidthConfig;
|
|
169
|
+
aws_sns: AwsSnsConfig;
|
|
27
170
|
}
|
|
171
|
+
/** The write-only (secret) keys of each transport — never present in a response. */
|
|
172
|
+
export interface MessagingSecretKeys {
|
|
173
|
+
resend: 'api_key';
|
|
174
|
+
ses: 'access_key_id' | 'secret_access_key' | 'session_token';
|
|
175
|
+
smtp: 'password';
|
|
176
|
+
brevo: 'api_key';
|
|
177
|
+
mailgun: 'api_key';
|
|
178
|
+
twilio: 'auth_token';
|
|
179
|
+
vonage: 'api_secret';
|
|
180
|
+
messagebird: 'access_key';
|
|
181
|
+
plivo: 'auth_token';
|
|
182
|
+
telnyx: 'api_key';
|
|
183
|
+
sinch: 'api_token';
|
|
184
|
+
infobip: 'api_key';
|
|
185
|
+
clicksend: 'api_key';
|
|
186
|
+
bandwidth: 'password';
|
|
187
|
+
aws_sns: 'secret_access_key' | 'session_token';
|
|
188
|
+
}
|
|
189
|
+
interface ProviderBodyBase<T extends MessagingTransport> {
|
|
190
|
+
transport: T;
|
|
191
|
+
/**
|
|
192
|
+
* Email: the From address, e.g. `"Acme <no-reply@acme.com>"` — a sender your
|
|
193
|
+
* provider accepts. SMS: the sender number in E.164 format, e.g. `+15551234567`.
|
|
194
|
+
*/
|
|
195
|
+
from_address?: string;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* First setup of transport `T` (or a switch to it): `config` carries every
|
|
199
|
+
* required key.
|
|
200
|
+
*/
|
|
201
|
+
export interface MessagingProviderSetup<T extends MessagingTransport> extends ProviderBodyBase<T> {
|
|
202
|
+
config: MessagingTransportConfigs[T];
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* An update of the transport already configured on the channel: every `config`
|
|
206
|
+
* key is optional. An omitted (or `''`) key keeps its stored value — including a
|
|
207
|
+
* stored secret.
|
|
208
|
+
*/
|
|
209
|
+
export interface MessagingProviderUpdate<T extends MessagingTransport> extends ProviderBodyBase<T> {
|
|
210
|
+
config?: Partial<MessagingTransportConfigs[T]>;
|
|
211
|
+
}
|
|
212
|
+
/** Body for `messaging.setEmail` — discriminated by `transport`. */
|
|
213
|
+
export type EmailProviderInput = {
|
|
214
|
+
[T in EmailTransport]: MessagingProviderSetup<T> | MessagingProviderUpdate<T>;
|
|
215
|
+
}[EmailTransport];
|
|
216
|
+
/** Body for `messaging.setSms` — discriminated by `transport`. */
|
|
217
|
+
export type SmsProviderInput = {
|
|
218
|
+
[T in SmsTransport]: MessagingProviderSetup<T> | MessagingProviderUpdate<T>;
|
|
219
|
+
}[SmsTransport];
|
|
220
|
+
/** First-setup body for the email channel. Use with `satisfies` to require every required key. */
|
|
221
|
+
export type EmailProviderSetup = {
|
|
222
|
+
[T in EmailTransport]: MessagingProviderSetup<T>;
|
|
223
|
+
}[EmailTransport];
|
|
224
|
+
/** First-setup body for the SMS channel. Use with `satisfies` to require every required key. */
|
|
225
|
+
export type SmsProviderSetup = {
|
|
226
|
+
[T in SmsTransport]: MessagingProviderSetup<T>;
|
|
227
|
+
}[SmsTransport];
|
|
228
|
+
/**
|
|
229
|
+
* @deprecated The untyped body accepted before per-transport typing. Use
|
|
230
|
+
* {@link EmailProviderInput} / {@link SmsProviderInput} instead; the API refuses
|
|
231
|
+
* any `config` key the transport does not use.
|
|
232
|
+
*/
|
|
28
233
|
export interface MessagingProviderInput {
|
|
29
234
|
/** The transport, e.g. `resend`, `ses`, `smtp` (email) or `twilio` (sms). */
|
|
30
235
|
transport: string;
|
|
@@ -32,6 +237,42 @@ export interface MessagingProviderInput {
|
|
|
32
237
|
/** Transport config; carries the write-only secret keys on write. */
|
|
33
238
|
config?: Record<string, unknown>;
|
|
34
239
|
}
|
|
240
|
+
/** The non-secret config keys of transport `T`. */
|
|
241
|
+
type PublicConfigKey<T extends MessagingTransport> = Exclude<keyof MessagingTransportConfigs[T], MessagingSecretKeys[T]>;
|
|
242
|
+
/**
|
|
243
|
+
* A configured provider as returned by the API. `config` holds the non-secret
|
|
244
|
+
* settings only (values come back as strings, e.g. `port: "587"`); secrets are
|
|
245
|
+
* never returned — `secrets_set` says which ones are stored.
|
|
246
|
+
*/
|
|
247
|
+
export interface MessagingProviderOf<C extends 'email' | 'sms', T extends MessagingTransport> {
|
|
248
|
+
object: 'messaging_provider';
|
|
249
|
+
channel: C;
|
|
250
|
+
transport: T;
|
|
251
|
+
from_address: string | null;
|
|
252
|
+
status: string;
|
|
253
|
+
/** Non-secret config only — secret values are never returned. */
|
|
254
|
+
config: {
|
|
255
|
+
[K in PublicConfigKey<T>]?: string;
|
|
256
|
+
};
|
|
257
|
+
/** For each secret key of this transport: whether a value is stored. Never the value. */
|
|
258
|
+
secrets_set: {
|
|
259
|
+
[K in MessagingSecretKeys[T]]: boolean;
|
|
260
|
+
};
|
|
261
|
+
updated_at: number;
|
|
262
|
+
}
|
|
263
|
+
export type EmailProvider = {
|
|
264
|
+
[T in EmailTransport]: MessagingProviderOf<'email', T>;
|
|
265
|
+
}[EmailTransport];
|
|
266
|
+
export type SmsProvider = {
|
|
267
|
+
[T in SmsTransport]: MessagingProviderOf<'sms', T>;
|
|
268
|
+
}[SmsTransport];
|
|
269
|
+
/** Either channel's provider. Narrow on `transport` (or `channel`) to read its config. */
|
|
270
|
+
export type MessagingProvider = EmailProvider | SmsProvider;
|
|
271
|
+
export interface MessagingProviders {
|
|
272
|
+
object: 'messaging_providers';
|
|
273
|
+
email: EmailProvider | null;
|
|
274
|
+
sms: SmsProvider | null;
|
|
275
|
+
}
|
|
35
276
|
export interface MessagingTestResult {
|
|
36
277
|
object: 'messaging_test';
|
|
37
278
|
channel: string;
|
|
@@ -43,14 +284,39 @@ export interface DeletedMessagingProvider {
|
|
|
43
284
|
channel: string;
|
|
44
285
|
deleted: true;
|
|
45
286
|
}
|
|
287
|
+
/**
|
|
288
|
+
* The deprecated untyped body, accepted only when `transport` is a plain
|
|
289
|
+
* `string` (not a known literal) — so a typed literal with a wrong key still
|
|
290
|
+
* fails to compile instead of falling through to the legacy overload.
|
|
291
|
+
*/
|
|
292
|
+
type LegacyInput<T extends string> = Omit<MessagingProviderInput, 'transport'> & {
|
|
293
|
+
transport: T;
|
|
294
|
+
} & (string extends T ? unknown : never);
|
|
46
295
|
export declare function messagingResource(request: RequestFn): {
|
|
47
296
|
/** The instance's configured email and SMS providers, secrets omitted. */
|
|
48
297
|
get(): Promise<MessagingProviders>;
|
|
49
|
-
|
|
50
|
-
|
|
298
|
+
/**
|
|
299
|
+
* Configure (or update) the email provider. `config` keys are checked per
|
|
300
|
+
* `transport`; on an update of the same transport, omitted keys — including
|
|
301
|
+
* secrets — keep their stored values.
|
|
302
|
+
*/
|
|
303
|
+
setEmail: {
|
|
304
|
+
(body: EmailProviderInput): Promise<EmailProvider>;
|
|
305
|
+
<T extends string>(body: LegacyInput<T>): Promise<MessagingProvider>;
|
|
306
|
+
};
|
|
307
|
+
/**
|
|
308
|
+
* Configure (or update) the SMS provider. `config` keys are checked per
|
|
309
|
+
* `transport`; on an update of the same transport, omitted keys — including
|
|
310
|
+
* secrets — keep their stored values.
|
|
311
|
+
*/
|
|
312
|
+
setSms: {
|
|
313
|
+
(body: SmsProviderInput): Promise<SmsProvider>;
|
|
314
|
+
<T extends string>(body: LegacyInput<T>): Promise<MessagingProvider>;
|
|
315
|
+
};
|
|
51
316
|
deleteChannel(channel: "email" | "sms"): Promise<DeletedMessagingProvider>;
|
|
52
317
|
/** Send a fixed, clearly-marked test message through the channel's provider. */
|
|
53
318
|
test(channel: "email" | "sms", body: {
|
|
54
319
|
to: string;
|
|
55
320
|
}): Promise<MessagingTestResult>;
|
|
56
321
|
};
|
|
322
|
+
export {};
|
package/dist/client/messaging.js
CHANGED
|
@@ -3,17 +3,29 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.messagingResource = messagingResource;
|
|
4
4
|
const request_1 = require("./request");
|
|
5
5
|
function messagingResource(request) {
|
|
6
|
+
function setEmail(body) {
|
|
7
|
+
return request({ method: 'PUT', path: '/v1/messaging_providers/email', body });
|
|
8
|
+
}
|
|
9
|
+
function setSms(body) {
|
|
10
|
+
return request({ method: 'PUT', path: '/v1/messaging_providers/sms', body });
|
|
11
|
+
}
|
|
6
12
|
return {
|
|
7
13
|
/** The instance's configured email and SMS providers, secrets omitted. */
|
|
8
14
|
get() {
|
|
9
15
|
return request({ method: 'GET', path: '/v1/messaging_providers' });
|
|
10
16
|
},
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Configure (or update) the email provider. `config` keys are checked per
|
|
19
|
+
* `transport`; on an update of the same transport, omitted keys — including
|
|
20
|
+
* secrets — keep their stored values.
|
|
21
|
+
*/
|
|
22
|
+
setEmail,
|
|
23
|
+
/**
|
|
24
|
+
* Configure (or update) the SMS provider. `config` keys are checked per
|
|
25
|
+
* `transport`; on an update of the same transport, omitted keys — including
|
|
26
|
+
* secrets — keep their stored values.
|
|
27
|
+
*/
|
|
28
|
+
setSms,
|
|
17
29
|
deleteChannel(channel) {
|
|
18
30
|
return request({ method: 'DELETE', path: `/v1/messaging_providers/${(0, request_1.enc)(channel)}` });
|
|
19
31
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messaging.js","sourceRoot":"","sources":["../../src/client/messaging.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"messaging.js","sourceRoot":"","sources":["../../src/client/messaging.ts"],"names":[],"mappings":";;AAsVA,8CA4CC;AAlYD,uCAAgD;AAsVhD,SAAgB,iBAAiB,CAAC,OAAkB;IAIlD,SAAS,QAAQ,CAAC,IAAa;QAC7B,OAAO,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,+BAA+B,EAAE,IAAI,EAAE,CAAC,CAAC;IACjF,CAAC;IAKD,SAAS,MAAM,CAAC,IAAa;QAC3B,OAAO,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,6BAA6B,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/E,CAAC;IAED,OAAO;QACL,0EAA0E;QAC1E,GAAG;YACD,OAAO,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,yBAAyB,EAAE,CAAC,CAAC;QACrE,CAAC;QACD;;;;WAIG;QACH,QAAQ;QACR;;;;WAIG;QACH,MAAM;QACN,aAAa,CAAC,OAAwB;YACpC,OAAO,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,2BAA2B,IAAA,aAAG,EAAC,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;QACxF,CAAC;QACD,gFAAgF;QAChF,IAAI,CAAC,OAAwB,EAAE,IAAoB;YACjD,OAAO,OAAO,CAAC;gBACb,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,2BAA2B,IAAA,aAAG,EAAC,OAAO,CAAC,OAAO;gBACpD,IAAI;aACL,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -7,3 +7,7 @@ export type { AtlasClient } from './client';
|
|
|
7
7
|
export * from './client';
|
|
8
8
|
export { createTestIssuer } from './testing';
|
|
9
9
|
export type { TestIssuer, CreateTestIssuerOptions } from './testing';
|
|
10
|
+
export { verifyPCActn } from './pca/verify';
|
|
11
|
+
export type { PcaVerdict, PcaContext, VerifyPCActnOptions } from './pca/verify';
|
|
12
|
+
export { requirePCA, defaultExtract, memoryPcaStore } from './pca/require-pca';
|
|
13
|
+
export type { RequirePcaOptions, PcaGuardResult, PcaRequestLike, PcaStateStore } from './pca/require-pca';
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.createTestIssuer = exports.createAtlasClient = void 0;
|
|
17
|
+
exports.memoryPcaStore = exports.defaultExtract = exports.requirePCA = exports.verifyPCActn = exports.createTestIssuer = exports.createAtlasClient = void 0;
|
|
18
18
|
// §7.3 token verification — the original surface, unchanged.
|
|
19
19
|
__exportStar(require("./jwks-cache"), exports);
|
|
20
20
|
__exportStar(require("./verify"), exports);
|
|
@@ -30,4 +30,12 @@ __exportStar(require("./client"), exports);
|
|
|
30
30
|
// Its own module, so it never sits on the hot verification path.
|
|
31
31
|
var testing_1 = require("./testing");
|
|
32
32
|
Object.defineProperty(exports, "createTestIssuer", { enumerable: true, get: function () { return testing_1.createTestIssuer; } });
|
|
33
|
+
// Proof-Carrying Authority (agentic auth): offline verifier + framework-agnostic guard,
|
|
34
|
+
// beside the session-token verifier above.
|
|
35
|
+
var verify_1 = require("./pca/verify");
|
|
36
|
+
Object.defineProperty(exports, "verifyPCActn", { enumerable: true, get: function () { return verify_1.verifyPCActn; } });
|
|
37
|
+
var require_pca_1 = require("./pca/require-pca");
|
|
38
|
+
Object.defineProperty(exports, "requirePCA", { enumerable: true, get: function () { return require_pca_1.requirePCA; } });
|
|
39
|
+
Object.defineProperty(exports, "defaultExtract", { enumerable: true, get: function () { return require_pca_1.defaultExtract; } });
|
|
40
|
+
Object.defineProperty(exports, "memoryPcaStore", { enumerable: true, get: function () { return require_pca_1.memoryPcaStore; } });
|
|
33
41
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,6DAA6D;AAC7D,+CAA6B;AAC7B,2CAAyB;AACzB,8CAA4B;AAE5B,oDAAoD;AACpD,6CAA2B;AAE3B,8DAA8D;AAC9D,mCAA6C;AAApC,2GAAA,iBAAiB,OAAA;AAE1B,2CAAyB;AAEzB,yEAAyE;AACzE,2EAA2E;AAC3E,iEAAiE;AACjE,qCAA6C;AAApC,2GAAA,gBAAgB,OAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,6DAA6D;AAC7D,+CAA6B;AAC7B,2CAAyB;AACzB,8CAA4B;AAE5B,oDAAoD;AACpD,6CAA2B;AAE3B,8DAA8D;AAC9D,mCAA6C;AAApC,2GAAA,iBAAiB,OAAA;AAE1B,2CAAyB;AAEzB,yEAAyE;AACzE,2EAA2E;AAC3E,iEAAiE;AACjE,qCAA6C;AAApC,2GAAA,gBAAgB,OAAA;AAGzB,wFAAwF;AACxF,2CAA2C;AAC3C,uCAA4C;AAAnC,sGAAA,YAAY,OAAA;AAErB,iDAA+E;AAAtE,yGAAA,UAAU,OAAA;AAAE,6GAAA,cAAc,OAAA;AAAE,6GAAA,cAAc,OAAA"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { type Capability, type PCActn, type TrustBudget, type VerifyHooks } from '@atlasauth/pca';
|
|
2
|
+
import { type PcaContext, type PcaVerdict } from './verify';
|
|
3
|
+
/** Framework-agnostic request shape: anything with headers and (optionally) a parsed/raw body. */
|
|
4
|
+
export interface PcaRequestLike {
|
|
5
|
+
headers: Record<string, string | string[] | undefined> | {
|
|
6
|
+
get(name: string): string | null;
|
|
7
|
+
};
|
|
8
|
+
body?: unknown;
|
|
9
|
+
}
|
|
10
|
+
/** Per-holder replay + budget state. Implement over Redis/DB; the in-memory one is for tests/single node. */
|
|
11
|
+
export interface PcaStateStore {
|
|
12
|
+
get(key: string): Promise<{
|
|
13
|
+
budget?: TrustBudget;
|
|
14
|
+
lastCounter?: number;
|
|
15
|
+
} | undefined>;
|
|
16
|
+
put(key: string, state: {
|
|
17
|
+
budget?: TrustBudget;
|
|
18
|
+
lastCounter?: number;
|
|
19
|
+
}): Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
export declare function memoryPcaStore(): PcaStateStore;
|
|
22
|
+
export interface RequirePcaOptions {
|
|
23
|
+
/** Resolve the Root Intent Grant from the PCActn's `grant_ref`. null = unknown grant. */
|
|
24
|
+
resolveGrant: (grantRef: string, pcactn: PCActn) => Promise<Capability | null>;
|
|
25
|
+
hooks?: VerifyHooks;
|
|
26
|
+
extract?: (req: PcaRequestLike) => PCActn | string | null;
|
|
27
|
+
/** Anti-replay counter + budget persistence. Without it counters are not checked (surfaced in checks). */
|
|
28
|
+
budgetStore?: PcaStateStore;
|
|
29
|
+
/** Build verification context (params, plan, risk) per request. */
|
|
30
|
+
context?: (req: PcaRequestLike, pcactn: PCActn) => PcaContext | Promise<PcaContext>;
|
|
31
|
+
now?: () => number;
|
|
32
|
+
/** WWW-Authenticate realm (default "pca"). */
|
|
33
|
+
realm?: string;
|
|
34
|
+
}
|
|
35
|
+
export type PcaGuardResult = {
|
|
36
|
+
ok: true;
|
|
37
|
+
verdict: PcaVerdict;
|
|
38
|
+
pcactn: PCActn;
|
|
39
|
+
} | {
|
|
40
|
+
ok: false;
|
|
41
|
+
status: 401 | 403;
|
|
42
|
+
verdict: PcaVerdict;
|
|
43
|
+
wwwAuthenticate?: string;
|
|
44
|
+
};
|
|
45
|
+
/** Default extraction: `PCA-Action: <base64url PCActn JSON>` header, else JSON body `{ pcactn }`. */
|
|
46
|
+
export declare function defaultExtract(req: PcaRequestLike): PCActn | string | null;
|
|
47
|
+
export declare function requirePCA(opts: RequirePcaOptions): (req: PcaRequestLike) => Promise<PcaGuardResult>;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.memoryPcaStore = memoryPcaStore;
|
|
4
|
+
exports.defaultExtract = defaultExtract;
|
|
5
|
+
exports.requirePCA = requirePCA;
|
|
6
|
+
const pca_1 = require("@atlasauth/pca");
|
|
7
|
+
const verify_1 = require("./verify");
|
|
8
|
+
function memoryPcaStore() {
|
|
9
|
+
const m = new Map();
|
|
10
|
+
return { get: async (k) => m.get(k), put: async (k, v) => void m.set(k, v) };
|
|
11
|
+
}
|
|
12
|
+
function header(req, name) {
|
|
13
|
+
const h = req.headers;
|
|
14
|
+
if (typeof h.get === 'function')
|
|
15
|
+
return h.get(name) ?? undefined;
|
|
16
|
+
const v = h[name] ?? h[name.toLowerCase()];
|
|
17
|
+
return Array.isArray(v) ? v[0] : v;
|
|
18
|
+
}
|
|
19
|
+
function fromB64u(s) {
|
|
20
|
+
const b = s.replace(/-/g, '+').replace(/_/g, '/');
|
|
21
|
+
return Buffer.from(b, 'base64').toString('utf8');
|
|
22
|
+
}
|
|
23
|
+
/** Default extraction: `PCA-Action: <base64url PCActn JSON>` header, else JSON body `{ pcactn }`. */
|
|
24
|
+
function defaultExtract(req) {
|
|
25
|
+
const h = header(req, 'pca-action');
|
|
26
|
+
if (h)
|
|
27
|
+
return fromB64u(h.trim());
|
|
28
|
+
let b = req.body;
|
|
29
|
+
if (typeof b === 'string') {
|
|
30
|
+
try {
|
|
31
|
+
b = JSON.parse(b);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const x = b?.pcactn;
|
|
38
|
+
if (typeof x === 'string' || (x !== null && typeof x === 'object'))
|
|
39
|
+
return x;
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
const denyVerdict = (reason) => ({
|
|
43
|
+
allow: false,
|
|
44
|
+
r: 1,
|
|
45
|
+
requiredThreshold: { t: 3, proof: 'strong', optimisticAllowed: false },
|
|
46
|
+
checks: { pcactn: 'fail' },
|
|
47
|
+
reasons: [reason],
|
|
48
|
+
});
|
|
49
|
+
function requirePCA(opts) {
|
|
50
|
+
const realm = opts.realm ?? 'pca';
|
|
51
|
+
const challenge = (error) => `PCA realm="${realm}"${error ? `, error="${error}"` : ''}, hint="send PCA-Action: <base64url PCActn> or JSON body {pcactn}"`;
|
|
52
|
+
const unauth = (reason, error = 'invalid_request') => ({
|
|
53
|
+
ok: false,
|
|
54
|
+
status: 401,
|
|
55
|
+
verdict: denyVerdict(reason),
|
|
56
|
+
wwwAuthenticate: challenge(error),
|
|
57
|
+
});
|
|
58
|
+
return async (req) => {
|
|
59
|
+
try {
|
|
60
|
+
let raw;
|
|
61
|
+
try {
|
|
62
|
+
raw = (opts.extract ?? defaultExtract)(req);
|
|
63
|
+
}
|
|
64
|
+
catch (e) {
|
|
65
|
+
return unauth(`unreadable PCActn: ${e.message}`);
|
|
66
|
+
}
|
|
67
|
+
if (raw === null || raw === undefined)
|
|
68
|
+
return unauth('no PCActn presented', 'missing_pcactn');
|
|
69
|
+
let p;
|
|
70
|
+
try {
|
|
71
|
+
p = typeof raw === 'string' ? (0, pca_1.decodePCActn)(raw) : raw;
|
|
72
|
+
}
|
|
73
|
+
catch (e) {
|
|
74
|
+
return unauth(`undecodable PCActn: ${e.message}`, 'invalid_pcactn');
|
|
75
|
+
}
|
|
76
|
+
if (p === null || typeof p !== 'object' || typeof p.grant_ref !== 'string') {
|
|
77
|
+
return unauth('malformed PCActn', 'invalid_pcactn');
|
|
78
|
+
}
|
|
79
|
+
const grant = await opts.resolveGrant(p.grant_ref, p);
|
|
80
|
+
if (!grant)
|
|
81
|
+
return unauth('unknown grant_ref', 'unknown_grant');
|
|
82
|
+
const now = opts.now?.() ?? Date.now();
|
|
83
|
+
const leafHolder = p.cap_chain?.[p.cap_chain.length - 1]?.holder;
|
|
84
|
+
const key = `${grant.id}:${leafHolder ?? ''}`;
|
|
85
|
+
const state = opts.budgetStore && leafHolder ? await opts.budgetStore.get(key) : undefined;
|
|
86
|
+
const ctx = { ...(await opts.context?.(req, p)) };
|
|
87
|
+
if (state?.budget && ctx.budget === undefined)
|
|
88
|
+
ctx.budget = state.budget;
|
|
89
|
+
const verdict = await (0, verify_1.verifyPCActn)(p, { grant, hooks: opts.hooks, now, context: ctx });
|
|
90
|
+
// Anti-replay (Appendix A step 5): strictly increasing per holder.
|
|
91
|
+
if (opts.budgetStore) {
|
|
92
|
+
if (state?.lastCounter !== undefined && !(p.counter > state.lastCounter)) {
|
|
93
|
+
verdict.allow = false;
|
|
94
|
+
verdict.checks.counter = 'fail';
|
|
95
|
+
verdict.reasons.push(`counter: ${String(p.counter)} is not greater than last seen ${state.lastCounter} (replay)`);
|
|
96
|
+
}
|
|
97
|
+
else if (verdict.checks.counter === 'pass') {
|
|
98
|
+
verdict.checks.counter = 'pass';
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
else if (verdict.checks.counter === 'pass') {
|
|
102
|
+
verdict.checks.counter = 'not-enforced';
|
|
103
|
+
}
|
|
104
|
+
if (!verdict.allow) {
|
|
105
|
+
// A bad signature / chain is an authentication failure; policy denial is authorization.
|
|
106
|
+
const authnFailed = ['version', 'cap_chain', 'leaf_signature', 'malformed', 'grant_ref'].some((c) => verdict.checks[c] === 'fail');
|
|
107
|
+
return authnFailed
|
|
108
|
+
? { ok: false, status: 401, verdict, wwwAuthenticate: challenge('invalid_pcactn') }
|
|
109
|
+
: { ok: false, status: 403, verdict };
|
|
110
|
+
}
|
|
111
|
+
if (opts.budgetStore && leafHolder) {
|
|
112
|
+
await opts.budgetStore.put(key, { budget: verdict.budget ?? state?.budget, lastCounter: p.counter });
|
|
113
|
+
}
|
|
114
|
+
return { ok: true, verdict, pcactn: p };
|
|
115
|
+
}
|
|
116
|
+
catch (e) {
|
|
117
|
+
return { ok: false, status: 403, verdict: denyVerdict(`guard error (fail closed): ${e instanceof Error ? e.message : 'unknown'}`) };
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=require-pca.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"require-pca.js","sourceRoot":"","sources":["../../src/pca/require-pca.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type Capability, type CheckStatus, type PCActn, type PlanNode, type RequiredThreshold, type RiskInputs, type TrustBudget, type VerifyHooks } from '@atlasauth/pca';
|
|
2
|
+
/**
|
|
3
|
+
* Resource-server side Proof-Carrying Authority verifier (spec §4, §7, Appendix A).
|
|
4
|
+
* Deterministic and offline; never throws (any internal error becomes a fail-closed verdict).
|
|
5
|
+
*/
|
|
6
|
+
export interface PcaContext {
|
|
7
|
+
/** Plaintext action params. If given they MUST hash to `action.params_digest`; needed by predicates. */
|
|
8
|
+
params?: Record<string, unknown>;
|
|
9
|
+
subject?: Record<string, unknown>;
|
|
10
|
+
env?: Record<string, unknown>;
|
|
11
|
+
/** The committed plan, if the RS knows it. Its Merkle root must equal `plan.root`. */
|
|
12
|
+
plan?: PlanNode[];
|
|
13
|
+
/** Risk inputs the RS can vouch for. Missing ones fail closed (worst case) except `taint`, see below. */
|
|
14
|
+
risk?: Partial<RiskInputs>;
|
|
15
|
+
/** Current trust budget for the leaf holder. Absent = a full budget (`budget` check reports not-enforced). */
|
|
16
|
+
budget?: TrustBudget;
|
|
17
|
+
recentActionTimes?: number[];
|
|
18
|
+
}
|
|
19
|
+
export interface VerifyPCActnOptions {
|
|
20
|
+
grant: Capability;
|
|
21
|
+
hooks?: VerifyHooks;
|
|
22
|
+
/** epoch ms (default Date.now()) */
|
|
23
|
+
now?: number;
|
|
24
|
+
context?: PcaContext;
|
|
25
|
+
}
|
|
26
|
+
export interface PcaVerdict {
|
|
27
|
+
allow: boolean;
|
|
28
|
+
/** Recomputed risk score in [0,1]. */
|
|
29
|
+
r: number;
|
|
30
|
+
requiredThreshold: RequiredThreshold;
|
|
31
|
+
checks: Record<string, CheckStatus>;
|
|
32
|
+
reasons: string[];
|
|
33
|
+
/** Budget after the decision (leaked, and debited when auto-admitted). Persist it on allow. */
|
|
34
|
+
budget?: TrustBudget;
|
|
35
|
+
}
|
|
36
|
+
export declare function verifyPCActn(pcactn: PCActn | string, opts: VerifyPCActnOptions): Promise<PcaVerdict>;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.verifyPCActn = verifyPCActn;
|
|
4
|
+
const pca_1 = require("@atlasauth/pca");
|
|
5
|
+
const WORST_THRESHOLD = { t: 3, proof: 'strong', optimisticAllowed: false };
|
|
6
|
+
function failClosed(reason, checks = {}) {
|
|
7
|
+
return {
|
|
8
|
+
allow: false,
|
|
9
|
+
r: 1,
|
|
10
|
+
requiredThreshold: WORST_THRESHOLD,
|
|
11
|
+
checks: { ...checks, malformed: 'fail' },
|
|
12
|
+
reasons: [reason],
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
async function verifyPCActn(pcactn, opts) {
|
|
16
|
+
try {
|
|
17
|
+
let p;
|
|
18
|
+
try {
|
|
19
|
+
p = typeof pcactn === 'string' ? (0, pca_1.decodePCActn)(pcactn) : pcactn;
|
|
20
|
+
}
|
|
21
|
+
catch (e) {
|
|
22
|
+
return failClosed(`undecodable PCActn: ${e.message}`);
|
|
23
|
+
}
|
|
24
|
+
if (p === null || typeof p !== 'object')
|
|
25
|
+
return failClosed('PCActn is not an object');
|
|
26
|
+
const now = opts.now ?? Date.now();
|
|
27
|
+
const ctx = opts.context ?? {};
|
|
28
|
+
const core = await (0, pca_1.verifyPCActnCore)(p, { grant: opts.grant, nowEpoch: now, hooks: opts.hooks });
|
|
29
|
+
const checks = { ...core.checks };
|
|
30
|
+
const reasons = [];
|
|
31
|
+
if (!core.allow && core.reason)
|
|
32
|
+
reasons.push(core.reason);
|
|
33
|
+
const fail = (name, why) => {
|
|
34
|
+
checks[name] = 'fail';
|
|
35
|
+
reasons.push(`${name}: ${why}`);
|
|
36
|
+
};
|
|
37
|
+
// grant_ref binds the object to this grant
|
|
38
|
+
if (p.grant_ref === opts.grant.id)
|
|
39
|
+
checks.grant_ref = 'pass';
|
|
40
|
+
else
|
|
41
|
+
fail('grant_ref', 'does not reference the supplied grant');
|
|
42
|
+
// params plaintext must open the committed digest
|
|
43
|
+
if (ctx.params !== undefined) {
|
|
44
|
+
if ((0, pca_1.hashCanonical)(ctx.params) === p.action?.params_digest)
|
|
45
|
+
checks.params_digest = 'pass';
|
|
46
|
+
else
|
|
47
|
+
fail('params_digest', 'supplied params do not hash to action.params_digest');
|
|
48
|
+
}
|
|
49
|
+
else
|
|
50
|
+
checks.params_digest = 'not-enforced';
|
|
51
|
+
// the RS's own copy of the plan must be the committed one
|
|
52
|
+
if (ctx.plan) {
|
|
53
|
+
if ((0, pca_1.merkleRoot)(ctx.plan.map(pca_1.planNodeLeaf)) === p.plan?.root)
|
|
54
|
+
checks.plan_root_authorized = 'pass';
|
|
55
|
+
else
|
|
56
|
+
fail('plan_root_authorized', 'known plan does not match plan.root');
|
|
57
|
+
}
|
|
58
|
+
const chain = Array.isArray(p.cap_chain) ? p.cap_chain : [];
|
|
59
|
+
const leaf = chain[chain.length - 1];
|
|
60
|
+
const depth = Math.max(0, chain.length - 1);
|
|
61
|
+
const now0 = now;
|
|
62
|
+
const budgetIn = ctx.budget ?? { B: Number.POSITIVE_INFINITY, tau: now0, asOf: now0 };
|
|
63
|
+
checks.budget = ctx.budget ? 'pass' : 'not-enforced';
|
|
64
|
+
// Taint: the agent's claim, used only as a default input (RS-supplied risk.taint wins).
|
|
65
|
+
const claimedTaint = p.provenance?.taint_level;
|
|
66
|
+
const risk = { ...ctx.risk };
|
|
67
|
+
if (risk.taint === undefined && typeof claimedTaint === 'number')
|
|
68
|
+
risk.taint = claimedTaint;
|
|
69
|
+
const reversibility = p.action?.reversibility_class;
|
|
70
|
+
const bMaxProbe = decideBudget(opts.grant, budgetIn, ctx.budget === undefined);
|
|
71
|
+
const d = (0, pca_1.decide)({
|
|
72
|
+
grant: opts.grant,
|
|
73
|
+
action: {
|
|
74
|
+
action: { verb: p.action?.verb, resource: p.action?.resource, params: ctx.params, reversibility_class: reversibility },
|
|
75
|
+
subject: ctx.subject,
|
|
76
|
+
env: ctx.env,
|
|
77
|
+
},
|
|
78
|
+
plan: ctx.plan,
|
|
79
|
+
nodeId: p.plan?.node_id,
|
|
80
|
+
risk,
|
|
81
|
+
budget: bMaxProbe,
|
|
82
|
+
now,
|
|
83
|
+
caveatContext: { delegationDepth: depth, recentActionTimes: ctx.recentActionTimes },
|
|
84
|
+
});
|
|
85
|
+
// Caveats added by delegation hops (beyond the root's) are conjunctive too.
|
|
86
|
+
if (leaf) {
|
|
87
|
+
const extra = leaf.caveats.slice(opts.grant.caveats.length);
|
|
88
|
+
const cv = (0, pca_1.evaluateCaveats)(extra, {
|
|
89
|
+
now,
|
|
90
|
+
blastRadius: risk.blastRadius,
|
|
91
|
+
reversibilityClass: reversibility,
|
|
92
|
+
delegationDepth: depth,
|
|
93
|
+
recentActionTimes: ctx.recentActionTimes,
|
|
94
|
+
});
|
|
95
|
+
if (cv.ok)
|
|
96
|
+
checks.delegated_caveats = 'pass';
|
|
97
|
+
else
|
|
98
|
+
fail('delegated_caveats', `delegation caveat(s) not satisfied: ${cv.failed.join(', ')}`);
|
|
99
|
+
}
|
|
100
|
+
if (d.releaseGuardianShare)
|
|
101
|
+
checks.policy = 'pass';
|
|
102
|
+
else {
|
|
103
|
+
checks.policy = 'fail';
|
|
104
|
+
reasons.push(...d.reasons.map((x) => `policy: ${x}`));
|
|
105
|
+
}
|
|
106
|
+
if (d.releaseGuardianShare) {
|
|
107
|
+
// informational reasons (step-up, assumed worst case) are kept even when released
|
|
108
|
+
reasons.push(...d.reasons.map((x) => `policy: ${x}`));
|
|
109
|
+
}
|
|
110
|
+
// Threshold: t > 1 needs a proof we can only get from an enforced threshold hook.
|
|
111
|
+
const th = checks.threshold;
|
|
112
|
+
if (d.requiredThreshold.t > 1 && d.releaseGuardianShare && th !== 'pass') {
|
|
113
|
+
fail('threshold', th === 'fail'
|
|
114
|
+
? `t=${d.requiredThreshold.t} required and the threshold proof was rejected`
|
|
115
|
+
: `t=${d.requiredThreshold.t} (${d.requiredThreshold.proof}) required but no threshold verifier is enforced`);
|
|
116
|
+
}
|
|
117
|
+
const allow = !Object.values(checks).includes('fail') && d.releaseGuardianShare && core.allow;
|
|
118
|
+
if (allow) {
|
|
119
|
+
return { allow, r: d.r, requiredThreshold: d.requiredThreshold, checks, reasons, budget: ctx.budget ? d.budget : undefined };
|
|
120
|
+
}
|
|
121
|
+
if (reasons.length === 0)
|
|
122
|
+
reasons.push('denied');
|
|
123
|
+
return { allow: false, r: d.r, requiredThreshold: d.requiredThreshold, checks, reasons };
|
|
124
|
+
}
|
|
125
|
+
catch (e) {
|
|
126
|
+
return failClosed(`verifier error (fail closed): ${e instanceof Error ? e.message : 'unknown'}`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/** Without a caller-supplied budget, use a full budget (grant's bMax) so absence does not itself deny. */
|
|
130
|
+
function decideBudget(grant, b, absent) {
|
|
131
|
+
if (!absent)
|
|
132
|
+
return b;
|
|
133
|
+
const bMax = (0, pca_1.readEnvelope)(grant)?.risk_policy.bMax;
|
|
134
|
+
return { ...b, B: typeof bMax === 'number' && Number.isFinite(bMax) ? bMax : 0 };
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=verify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/pca/verify.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlasauth/backend",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"jose": "^5.9.6",
|
|
8
|
-
"@atlasauth/authz": "0.1.1"
|
|
8
|
+
"@atlasauth/authz": "0.1.1",
|
|
9
|
+
"@atlasauth/pca": "0.1.0"
|
|
9
10
|
},
|
|
10
11
|
"devDependencies": {
|
|
11
12
|
"typescript": "^5.6.3",
|