@atlasauth/backend 0.1.7 → 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/captcha.d.ts +43 -0
- package/dist/client/captcha.js +27 -0
- package/dist/client/captcha.js.map +1 -0
- package/dist/client/index.d.ts +44 -2
- package/dist/client/index.js +9 -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,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>;
|