@picked/app-protocol 0.0.0-stage → 0.0.115-next.2

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.
@@ -0,0 +1,391 @@
1
+ //#region src/manifest.ts
2
+ var e = [
3
+ "app-home",
4
+ "workspace-prepublish-actions",
5
+ "workspace-postpublish-actions"
6
+ ], t = ["workspace.published"], n = [
7
+ "string",
8
+ "number",
9
+ "boolean",
10
+ "json"
11
+ ], r = /^[a-z0-9][a-z0-9-]{1,62}$/, i = /^[a-z][a-z0-9_]{0,62}$/, a = /^[a-zA-Z]\w{0,62}$/;
12
+ function o(e) {
13
+ return typeof e == "object" && !!e && !Array.isArray(e);
14
+ }
15
+ function s(e) {
16
+ if (typeof e != "string") return !1;
17
+ try {
18
+ let t = new URL(e);
19
+ return t.protocol === "https:" || t.protocol === "http:" && [
20
+ "localhost",
21
+ "127.0.0.1",
22
+ "[::1]"
23
+ ].includes(t.hostname);
24
+ } catch {
25
+ return !1;
26
+ }
27
+ }
28
+ function c(e, t) {
29
+ return typeof t == "string" && e.includes(t);
30
+ }
31
+ function l(t, n, r) {
32
+ if (!o(t)) return r.push(`${n} must be an object`), null;
33
+ let { location: i, url: a, title: l, height: u } = t;
34
+ return c(e, i) ? s(a) ? {
35
+ location: i,
36
+ url: a,
37
+ ...typeof l == "string" ? { title: l } : {},
38
+ ...typeof u == "number" ? { height: u } : {}
39
+ } : (r.push(`${n}.url must be an https URL, or http on localhost`), null) : (r.push(`${n}.location must be one of ${e.join(", ")}`), null);
40
+ }
41
+ function u(e, t, r) {
42
+ if (!o(e)) return r.push(`${t} must be an object`), null;
43
+ if (typeof e.label != "string" || e.label === "") return r.push(`${t}.label is required`), null;
44
+ if (!c(n, e.type)) return r.push(`${t}.type must be one of ${n.join(", ")}`), null;
45
+ let i = Array.isArray(e.options) ? e.options.filter((e) => typeof e == "string") : [];
46
+ return {
47
+ label: e.label,
48
+ type: e.type,
49
+ ...typeof e.description == "string" ? { description: e.description } : {},
50
+ ...typeof e.required == "boolean" ? { required: e.required } : {},
51
+ ...typeof e.optional == "boolean" ? { optional: e.optional } : {},
52
+ ...i.length > 0 ? { options: i } : {}
53
+ };
54
+ }
55
+ function d(e, t, n) {
56
+ let r = {};
57
+ if (!o(e)) return n.push(`${t} must be an object keyed by field name`), r;
58
+ for (let [i, o] of Object.entries(e)) {
59
+ let e = `${t}.${i}`;
60
+ a.test(i) || n.push(`${e} is not a valid field name`);
61
+ let s = u(o, e, n);
62
+ s !== null && (r[i] = s);
63
+ }
64
+ return r;
65
+ }
66
+ function f(e, t, n) {
67
+ if (!o(e)) return n.push(`${t} must be an object`), null;
68
+ let { name: r, label: a, description: s, effect: c } = e;
69
+ return typeof r != "string" || !i.test(r) ? (n.push(`${t}.name must be lower-case letters, digits and underscores`), null) : typeof a != "string" || a === "" ? (n.push(`${t}.label is required`), null) : c !== "read" && c !== "write" ? (n.push(`${t}.effect must be read or write`), null) : {
70
+ name: r,
71
+ label: a,
72
+ description: typeof s == "string" ? s : "",
73
+ effect: c,
74
+ arguments: d(e.arguments ?? {}, `${t}.arguments`, n),
75
+ output: d(e.output ?? {}, `${t}.output`, n)
76
+ };
77
+ }
78
+ function p(e, t, n, r) {
79
+ if (e !== void 0) {
80
+ if (!Array.isArray(e)) n.push(`${t} must be an array`);
81
+ else return e.map((e, i) => r(e, `${t}[${i}]`, n)).filter((e) => e !== null);
82
+ }
83
+ }
84
+ function m(e, t) {
85
+ let n = e.length;
86
+ for (; n > 0 && e[n - 1] === t;) --n;
87
+ return e.slice(0, n);
88
+ }
89
+ function h(e, t) {
90
+ if (e !== void 0) {
91
+ if (!o(e) || !s(e.url)) t.push("mcp.url must be an https URL, or http on localhost");
92
+ else return { url: e.url };
93
+ }
94
+ }
95
+ function g(e, t) {
96
+ if (e !== void 0) {
97
+ if (!Array.isArray(e) || !e.every((e) => typeof e == "string")) t.push("scopes must be an array of scope names");
98
+ else return e.filter((e) => typeof e == "string");
99
+ }
100
+ }
101
+ function _(e, n, r) {
102
+ if (e !== void 0) {
103
+ if (!Array.isArray(e) || !e.every((e) => c(t, e))) r.push(`events must be an array of ${t.join(", ")}`);
104
+ else if (n === void 0) r.push("events need an endpoint to send them to");
105
+ else return [...new Set(e.filter((e) => c(t, e)))];
106
+ }
107
+ }
108
+ function v(e, t, n) {
109
+ let r = p(e, "workflowTools", n, f);
110
+ (r?.length ?? 0) > 0 && t === void 0 && n.push("workflowTools need an endpoint to call");
111
+ let i = /* @__PURE__ */ new Set();
112
+ for (let e of r ?? []) i.has(e.name) && n.push(`workflowTools has two tools named ${e.name}`), i.add(e.name);
113
+ return r;
114
+ }
115
+ function y(e, t) {
116
+ return e !== void 0 && typeof e != "boolean" && t.push("offlineAccess must be true or false"), e === !0;
117
+ }
118
+ function b(e) {
119
+ let t = [];
120
+ if (!o(e)) return {
121
+ ok: !1,
122
+ issues: ["The manifest must be an object"]
123
+ };
124
+ let { handle: n, name: i, description: a, endpoint: c } = e;
125
+ (typeof n != "string" || !r.test(n)) && t.push("handle must be 2-63 lower-case letters, digits and hyphens"), (typeof i != "string" || i.trim() === "") && t.push("name is required"), c !== void 0 && !s(c) && t.push("endpoint must be an https URL, or http on localhost");
126
+ let u = g(e.scopes, t), d = p(e.slots, "slots", t, l), f = v(e.workflowTools, c, t), b = h(e.mcp, t), x = _(e.events, c, t), S = y(e.offlineAccess, t);
127
+ return t.length > 0 || typeof n != "string" || typeof i != "string" ? {
128
+ ok: !1,
129
+ issues: t
130
+ } : {
131
+ ok: !0,
132
+ manifest: {
133
+ handle: n,
134
+ name: i.trim(),
135
+ ...typeof a == "string" ? { description: a } : {},
136
+ ...typeof c == "string" ? { endpoint: m(c, "/") } : {},
137
+ ...u === void 0 ? {} : { scopes: u },
138
+ ...d === void 0 ? {} : { slots: d },
139
+ ...f === void 0 ? {} : { workflowTools: f },
140
+ ...b === void 0 ? {} : { mcp: b },
141
+ ...x === void 0 ? {} : { events: x },
142
+ ...S ? { offlineAccess: S } : {}
143
+ }
144
+ };
145
+ }
146
+ //#endregion
147
+ //#region src/keys.ts
148
+ var x = new TextEncoder(), S = { name: "Ed25519" };
149
+ function C(e) {
150
+ let t = [...e].map((e) => String.fromCodePoint(e)).join("");
151
+ return m(btoa(t).replaceAll("+", "-").replaceAll("/", "_"), "=");
152
+ }
153
+ function w(e) {
154
+ let t = atob(e.replaceAll("-", "+").replaceAll("_", "/")), n = new Uint8Array(t.length);
155
+ for (let e = 0; e < t.length; e += 1) n[e] = t.codePointAt(e) ?? 0;
156
+ return n;
157
+ }
158
+ async function T(e) {
159
+ let t = await globalThis.crypto.subtle.digest("SHA-256", w(e));
160
+ return C(new Uint8Array(t)).slice(0, 16);
161
+ }
162
+ function E(e) {
163
+ return w(e.replaceAll(String.raw`\n`, "\n").replace(/-----(?:BEGIN|END) PRIVATE KEY-----/g, "").replace(/\s+/g, ""));
164
+ }
165
+ async function D() {
166
+ let e = await globalThis.crypto.subtle.generateKey(S, !0, ["sign", "verify"]);
167
+ if (!("privateKey" in e)) throw Error("Ed25519 generated no key pair");
168
+ let t = new Uint8Array(await globalThis.crypto.subtle.exportKey("pkcs8", e.privateKey)), n = C(new Uint8Array(await globalThis.crypto.subtle.exportKey("raw", e.publicKey)));
169
+ return {
170
+ privateKey: btoa([...t].map((e) => String.fromCodePoint(e)).join("")),
171
+ publicKey: n,
172
+ kid: await T(n)
173
+ };
174
+ }
175
+ async function O(e) {
176
+ let t, n;
177
+ try {
178
+ t = await globalThis.crypto.subtle.importKey("pkcs8", E(e), S, !0, ["sign"]), n = await globalThis.crypto.subtle.exportKey("jwk", t);
179
+ } catch {
180
+ throw Error("The value is not an Ed25519 private key in PKCS#8");
181
+ }
182
+ let r = n.x ?? "";
183
+ return {
184
+ kid: await T(r),
185
+ publicKey: r,
186
+ async sign(e) {
187
+ let n = await globalThis.crypto.subtle.sign(S, t, x.encode(e));
188
+ return C(new Uint8Array(n));
189
+ }
190
+ };
191
+ }
192
+ async function k(e, t) {
193
+ let n = await globalThis.crypto.subtle.importKey("raw", E(e), "HKDF", !1, ["deriveKey"]);
194
+ return globalThis.crypto.subtle.deriveKey({
195
+ name: "HKDF",
196
+ hash: "SHA-256",
197
+ salt: /* @__PURE__ */ new Uint8Array(32),
198
+ info: x.encode(`picked-app-kit ${t}`)
199
+ }, n, {
200
+ name: "AES-GCM",
201
+ length: 256
202
+ }, !1, ["encrypt", "decrypt"]);
203
+ }
204
+ var A = /* @__PURE__ */ new Map();
205
+ function j(e) {
206
+ let t = A.get(e);
207
+ return t === void 0 && (t = O(e), A.set(e, t)), t;
208
+ }
209
+ async function M(e) {
210
+ try {
211
+ return await globalThis.crypto.subtle.importKey("raw", w(e), S, !1, ["verify"]);
212
+ } catch {
213
+ return null;
214
+ }
215
+ }
216
+ async function N(e, t, n, r) {
217
+ let i = await e.get(t);
218
+ if (i === null) return !1;
219
+ try {
220
+ return await globalThis.crypto.subtle.verify(S, i, w(r), x.encode(n));
221
+ } catch {
222
+ return !1;
223
+ }
224
+ }
225
+ function P(e) {
226
+ let t = new Map(e.map((e) => [e.kid, M(e.publicKey)]));
227
+ return { get: (e) => t.get(e) ?? Promise.resolve(null) };
228
+ }
229
+ function F(e) {
230
+ return { keys: e.map(({ kid: e, publicKey: t }) => ({
231
+ kty: "OKP",
232
+ crv: "Ed25519",
233
+ alg: "EdDSA",
234
+ use: "sig",
235
+ kid: e,
236
+ x: t
237
+ })) };
238
+ }
239
+ function I(e) {
240
+ let t = typeof e == "object" && e ? Reflect.get(e, "keys") : [];
241
+ return Array.isArray(t) ? t.flatMap((e) => {
242
+ if (typeof e != "object" || !e) return [];
243
+ let [t, n, r] = [
244
+ Reflect.get(e, "kid"),
245
+ Reflect.get(e, "x"),
246
+ Reflect.get(e, "crv")
247
+ ];
248
+ return typeof t == "string" && typeof n == "string" && r === "Ed25519" ? [{
249
+ kid: t,
250
+ publicKey: n
251
+ }] : [];
252
+ }) : [];
253
+ }
254
+ var ee = 1e4;
255
+ function L(e) {
256
+ let t = e.fetch ?? fetch, n = e.refreshAfterMs ?? 6e4, r = P([]), i, a, o = async () => {
257
+ i = Date.now();
258
+ let n = await t(e.url, { signal: AbortSignal.timeout(ee) });
259
+ n.ok && (r = P(I(await n.json())));
260
+ };
261
+ return { async get(e) {
262
+ let t = await r.get(e);
263
+ return t === null ? i !== void 0 && Date.now() - i < n ? null : (a ??= o().finally(() => {
264
+ a = void 0;
265
+ }), await a.catch(() => void 0), r.get(e)) : t;
266
+ } };
267
+ }
268
+ function R(e) {
269
+ return C(x.encode(JSON.stringify(e)));
270
+ }
271
+ async function z(e, t) {
272
+ let n = `${R({
273
+ alg: "EdDSA",
274
+ typ: "JWT",
275
+ kid: e.kid
276
+ })}.${R(t)}`;
277
+ return `${n}.${await e.sign(n)}`;
278
+ }
279
+ function B(e) {
280
+ try {
281
+ return JSON.parse(new TextDecoder().decode(w(e)));
282
+ } catch {
283
+ return;
284
+ }
285
+ }
286
+ async function V(e, t) {
287
+ let [n = "", r = "", i = "", ...a] = t.split(".");
288
+ if (a.length > 0) return null;
289
+ let o = B(n), s = B(r);
290
+ if (typeof o != "object" || !o || typeof s != "object" || !s) return null;
291
+ let c = Reflect.get(o, "kid");
292
+ if (Reflect.get(o, "alg") !== "EdDSA" || typeof c != "string" || !await N(e, c, `${n}.${r}`, i)) return null;
293
+ let l = Reflect.get(s, "exp");
294
+ return typeof l == "number" && l < Date.now() / 1e3 ? null : Object.fromEntries(Object.entries(s));
295
+ }
296
+ //#endregion
297
+ //#region src/protocol.ts
298
+ var H = "picked-signature", U = "picked-installation-id", W = "picked-app-assertion", G = "picked-context", K = 300, q = "/.well-known/picked-app-keys.json", J = 300, Y = new TextEncoder();
299
+ async function X(e, t, n = Math.floor(Date.now() / 1e3)) {
300
+ let r = await e.sign(`${String(n)}.${t}`);
301
+ return `t=${String(n)},kid=${e.kid},v1=${r}`;
302
+ }
303
+ async function Z(e, t, n) {
304
+ if (n === null) return !1;
305
+ let r = new Map(n.split(",").map((e) => {
306
+ let [t = "", n = ""] = e.split("=");
307
+ return [t.trim(), n.trim()];
308
+ })), i = Number(r.get("t")), a = r.get("kid"), o = r.get("v1");
309
+ return !Number.isFinite(i) || a === void 0 || o === void 0 || Math.abs(Date.now() / 1e3 - i) > K ? !1 : N(e, a, `${String(i)}.${t}`, o);
310
+ }
311
+ async function Q(e, t, n) {
312
+ let r = C(Y.encode(JSON.stringify(t)));
313
+ return {
314
+ [G]: r,
315
+ [U]: t.installationId,
316
+ [H]: await X(e, `${r}\n${n}`)
317
+ };
318
+ }
319
+ function $(e) {
320
+ if (typeof e != "object" || !e) return null;
321
+ let t = (t) => Reflect.get(e, t), [n, r, i, a] = [
322
+ t("installationId"),
323
+ t("organizationId"),
324
+ t("projectId"),
325
+ t("apiUrl")
326
+ ];
327
+ if (typeof n != "string" || typeof r != "string" || typeof i != "string" || typeof a != "string") return null;
328
+ let [o, s] = [t("token"), t("tokenExpiresAt")];
329
+ return {
330
+ installationId: n,
331
+ organizationId: r,
332
+ projectId: i,
333
+ apiUrl: a,
334
+ ...typeof o == "string" && typeof s == "string" ? {
335
+ token: o,
336
+ tokenExpiresAt: s
337
+ } : {}
338
+ };
339
+ }
340
+ async function te(e, t, n) {
341
+ let r = t.get(G);
342
+ if (r === null || !await Z(e, `${r}\n${n}`, t.get("picked-signature"))) return null;
343
+ try {
344
+ return $(JSON.parse(new TextDecoder().decode(w(r))));
345
+ } catch {
346
+ return null;
347
+ }
348
+ }
349
+ async function ne(e, t) {
350
+ return z(e, { ...t });
351
+ }
352
+ async function re(e, t) {
353
+ let n = await V(e, t), r = $(n);
354
+ if (n === null || r === null) return null;
355
+ let { userId: i, exp: a } = n;
356
+ return typeof i != "string" || typeof a != "number" ? null : {
357
+ ...r,
358
+ userId: i,
359
+ exp: a
360
+ };
361
+ }
362
+ async function ie(e, t) {
363
+ let n = Math.floor(Date.now() / 1e3);
364
+ return z(e, {
365
+ sub: t.installationId,
366
+ aud: t.audience,
367
+ iat: n,
368
+ exp: n + 60,
369
+ jti: globalThis.crypto.randomUUID()
370
+ });
371
+ }
372
+ async function ae(e, t, n) {
373
+ let r = await V(e, t);
374
+ if (r === null) return null;
375
+ let { sub: i, aud: a, iat: o, exp: s, jti: c } = r;
376
+ return typeof i != "string" || a !== n.audience || typeof o != "number" || typeof s != "number" || typeof c != "string" || s - o > J ? null : {
377
+ installationId: i,
378
+ jti: c,
379
+ exp: s
380
+ };
381
+ }
382
+ function oe(e) {
383
+ try {
384
+ let t = JSON.parse(new TextDecoder().decode(w(e.split(".")[1] ?? ""))), n = typeof t == "object" && t ? Reflect.get(t, "sub") : null;
385
+ return typeof n == "string" ? n : null;
386
+ } catch {
387
+ return null;
388
+ }
389
+ }
390
+ //#endregion
391
+ export { W as APP_ASSERTION_HEADER, t as APP_EVENTS, e as APP_SLOT_LOCATIONS, n as APP_VALUE_TYPES, G as CONTEXT_HEADER, U as INSTALLATION_HEADER, q as PICKED_KEYS_PATH, H as SIGNATURE_HEADER, ie as createAppAssertion, ne as createSessionToken, O as createSigner, k as deriveSecretKey, w as fromBase64url, D as generateKeyPair, M as importPublicKey, s as isAppUrl, T as keyIdOf, b as parseManifest, L as remoteKeySet, X as signBody, z as signJwt, Q as signMcpRequest, j as signerFor, P as staticKeySet, C as toBase64url, F as toJwks, m as trimTrailing, oe as unverifiedAssertionSubject, ae as verifyAppAssertion, Z as verifyBody, V as verifyJwt, te as verifyMcpRequest, re as verifySessionToken, N as verifySignature };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @file `@picked/app-protocol`: the app manifest, the Ed25519 keys both sides sign with, and the
3
+ * signed requests, session tokens and app assertions Picked and an app exchange.
4
+ */
5
+ export * from './manifest';
6
+ export * from './protocol';
7
+ export * from './keys';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA;AAC1B,cAAc,QAAQ,CAAA"}
@@ -0,0 +1,166 @@
1
+ /**
2
+ * @file Ed25519 keys and the EdDSA JWTs signed with them.
3
+ *
4
+ * Picked signs what it sends an app with Picked's key, and an app signs what it sends Picked
5
+ * with its own; each side holds only the other's public key. A private key is the one-line
6
+ * base64 of its PKCS#8 DER (a PKCS#8 PEM of it reads the same), a public key the base64url of
7
+ * its 32 raw bytes, and a key id the first 16 base64url characters of the public key's SHA-256.
8
+ */
9
+ /** A public key and the id signatures name it by. */
10
+ export interface PublicKey {
11
+ kid: string;
12
+ /** The base64url of the key's 32 raw bytes. */
13
+ publicKey: string;
14
+ }
15
+ /** A private key ready to sign, with its public half. */
16
+ export interface Signer extends PublicKey {
17
+ /** Signs a message, returning the base64url signature. */
18
+ sign: (message: string) => Promise<string>;
19
+ }
20
+ /** The public keys a verifier trusts, found by key id. */
21
+ export interface PublicKeySet {
22
+ /** The key with this id, or null when the set holds none. */
23
+ get: (kid: string) => Promise<CryptoKey | null>;
24
+ }
25
+ /** A JSON Web Key Set of Ed25519 public keys. */
26
+ export interface Jwks {
27
+ keys: {
28
+ kty: 'OKP';
29
+ crv: 'Ed25519';
30
+ alg: 'EdDSA';
31
+ use: 'sig';
32
+ kid: string;
33
+ x: string;
34
+ }[];
35
+ }
36
+ /**
37
+ * Encodes bytes as unpadded base64url.
38
+ *
39
+ * @param {Uint8Array} bytes - The bytes.
40
+ * @returns {string} The encoding.
41
+ * @example toBase64url(new Uint8Array([251])) // '-w'
42
+ */
43
+ export declare function toBase64url(bytes: Uint8Array): string;
44
+ /**
45
+ * Decodes unpadded base64url or base64 to bytes.
46
+ *
47
+ * @param {string} encoded - The encoding.
48
+ * @returns {Uint8Array<ArrayBuffer>} The bytes.
49
+ * @example fromBase64url('-w') // Uint8Array [251]
50
+ */
51
+ export declare function fromBase64url(encoded: string): Uint8Array<ArrayBuffer>;
52
+ /**
53
+ * Computes a public key's id.
54
+ *
55
+ * @param {string} publicKey - The base64url public key.
56
+ * @returns {Promise<string>} The key id.
57
+ * @example await keyIdOf(publicKey)
58
+ */
59
+ export declare function keyIdOf(publicKey: string): Promise<string>;
60
+ /**
61
+ * Generates an Ed25519 key pair.
62
+ *
63
+ * @returns {Promise<PublicKey & { privateKey: string }>} The private key as the one-line base64 of its PKCS#8 DER, the public key and its id.
64
+ * @example const { privateKey, publicKey, kid } = await generateKeyPair()
65
+ */
66
+ export declare function generateKeyPair(): Promise<PublicKey & {
67
+ privateKey: string;
68
+ }>;
69
+ /**
70
+ * Imports a private key as a signer.
71
+ *
72
+ * @param {string} privateKey - The base64 of the PKCS#8 DER, or a PKCS#8 PEM of it.
73
+ * @returns {Promise<Signer>} The signer.
74
+ * @throws {Error} When the value is not an Ed25519 private key.
75
+ * @example const signer = await createSigner(process.env.PICKED_APP_PRIVATE_KEY ?? '')
76
+ */
77
+ export declare function createSigner(privateKey: string): Promise<Signer>;
78
+ /**
79
+ * Derives an AES-GCM key from a private key for one purpose, so an app can encrypt what only it
80
+ * reads back without holding a second secret.
81
+ *
82
+ * @param {string} privateKey - The base64 of the PKCS#8 DER, or a PKCS#8 PEM of it.
83
+ * @param {string} purpose - What the key is for; another purpose derives another key.
84
+ * @returns {Promise<CryptoKey>} The key.
85
+ * @example await deriveSecretKey(environment.privateKey, 'oauth-state')
86
+ */
87
+ export declare function deriveSecretKey(privateKey: string, purpose: string): Promise<CryptoKey>;
88
+ /**
89
+ * Imports a private key as a signer once per process.
90
+ *
91
+ * @param {string} privateKey - The base64 of the PKCS#8 DER, or a PKCS#8 PEM of it.
92
+ * @returns {Promise<Signer>} The signer.
93
+ * @example await signerFor(environment.privateKey)
94
+ */
95
+ export declare function signerFor(privateKey: string): Promise<Signer>;
96
+ /**
97
+ * Imports a base64url public key for verifying.
98
+ *
99
+ * @param {string} publicKey - The public key.
100
+ * @returns {Promise<CryptoKey | null>} The key, or null when it is not an Ed25519 public key.
101
+ * @example await importPublicKey(publicKey)
102
+ */
103
+ export declare function importPublicKey(publicKey: string): Promise<CryptoKey | null>;
104
+ /**
105
+ * Checks a signature against a key in a set.
106
+ *
107
+ * @param {PublicKeySet} keys - The trusted keys.
108
+ * @param {string} kid - The id of the key that signed.
109
+ * @param {string} message - What was signed.
110
+ * @param {string} signature - The base64url signature.
111
+ * @returns {Promise<boolean>} Whether a trusted key signed the message.
112
+ * @example await verifySignature(keys, kid, message, signature)
113
+ */
114
+ export declare function verifySignature(keys: PublicKeySet, kid: string, message: string, signature: string): Promise<boolean>;
115
+ /**
116
+ * A key set holding the given public keys.
117
+ *
118
+ * @param {readonly PublicKey[]} keys - The trusted keys.
119
+ * @returns {PublicKeySet} The set.
120
+ * @example staticKeySet([{ kid, publicKey }])
121
+ */
122
+ export declare function staticKeySet(keys: readonly PublicKey[]): PublicKeySet;
123
+ /**
124
+ * Renders public keys as a JSON Web Key Set.
125
+ *
126
+ * @param {readonly PublicKey[]} keys - The keys.
127
+ * @returns {Jwks} The set.
128
+ * @example toJwks([signer])
129
+ */
130
+ export declare function toJwks(keys: readonly PublicKey[]): Jwks;
131
+ /**
132
+ * A key set read from a JSON Web Key Set URL. It fetches the set on first use, and again for a
133
+ * key id it does not hold once `refreshAfterMs` has passed since the last fetch. A fetch that
134
+ * takes longer than ten seconds is aborted.
135
+ *
136
+ * @param {object} options - Where the set lives.
137
+ * @param {string} options.url - The set's URL.
138
+ * @param {typeof fetch} [options.fetch] - The fetch to read it with.
139
+ * @param {number} [options.refreshAfterMs] - The least time between fetches; one minute by default.
140
+ * @returns {PublicKeySet} The set.
141
+ * @example remoteKeySet({ url: 'https://api.picked.app/.well-known/picked-app-keys.json' })
142
+ */
143
+ export declare function remoteKeySet(options: {
144
+ url: string;
145
+ fetch?: typeof fetch;
146
+ refreshAfterMs?: number;
147
+ }): PublicKeySet;
148
+ /**
149
+ * Signs claims as an EdDSA JWT.
150
+ *
151
+ * @param {Signer} signer - The key to sign with.
152
+ * @param {Record<string, unknown>} claims - The claims.
153
+ * @returns {Promise<string>} The JWT.
154
+ * @example await signJwt(signer, { sub: 'appi_1', exp })
155
+ */
156
+ export declare function signJwt(signer: Signer, claims: Record<string, unknown>): Promise<string>;
157
+ /**
158
+ * Checks an EdDSA JWT and reads its claims. A token past its `exp` fails.
159
+ *
160
+ * @param {PublicKeySet} keys - The trusted keys.
161
+ * @param {string} token - The JWT.
162
+ * @returns {Promise<Record<string, unknown> | null>} The claims, or null when the token fails.
163
+ * @example await verifyJwt(keys, token)
164
+ */
165
+ export declare function verifyJwt(keys: PublicKeySet, token: string): Promise<Record<string, unknown> | null>;
166
+ //# sourceMappingURL=keys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keys.d.ts","sourceRoot":"","sources":["../../src/keys.ts"],"names":[],"mappings":"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"}