@sanoma-ai/workflows 0.10.2 → 0.10.3
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/README.md +43 -11
- package/dist/apply.js +1 -1
- package/dist/apply.js.map +1 -1
- package/dist/call.d.ts +5 -2
- package/dist/call.js +65 -20
- package/dist/call.js.map +1 -1
- package/dist/change.d.ts +5 -6
- package/dist/change.js +6 -9
- package/dist/change.js.map +1 -1
- package/dist/client.d.ts +18 -0
- package/dist/client.js +35 -3
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +42 -4
- package/dist/config.js +71 -10
- package/dist/config.js.map +1 -1
- package/dist/db.d.ts +2 -0
- package/dist/db.js +7 -0
- package/dist/db.js.map +1 -1
- package/dist/deadlines.d.ts +26 -13
- package/dist/deadlines.js +50 -11
- package/dist/deadlines.js.map +1 -1
- package/dist/define.d.ts +22 -0
- package/dist/define.js +2 -0
- package/dist/define.js.map +1 -1
- package/dist/deployment-key.d.ts +20 -1
- package/dist/deployment-key.js +28 -3
- package/dist/deployment-key.js.map +1 -1
- package/dist/describe.js +28 -1
- package/dist/describe.js.map +1 -1
- package/dist/description.d.ts +3 -0
- package/dist/description.js +2 -0
- package/dist/description.js.map +1 -1
- package/dist/host.d.ts +13 -4
- package/dist/host.js +14 -5
- package/dist/host.js.map +1 -1
- package/dist/index.d.ts +10 -6
- package/dist/index.js +8 -5
- package/dist/index.js.map +1 -1
- package/dist/ledger.d.ts +30 -1
- package/dist/ledger.js +31 -0
- package/dist/ledger.js.map +1 -1
- package/dist/login-code.d.ts +17 -0
- package/dist/login-code.js +32 -0
- package/dist/login-code.js.map +1 -0
- package/dist/op.d.ts +78 -10
- package/dist/op.js +20 -0
- package/dist/op.js.map +1 -1
- package/dist/outline.js +3 -3
- package/dist/outline.js.map +1 -1
- package/dist/resource.d.ts +6 -4
- package/dist/resource.js +8 -5
- package/dist/resource.js.map +1 -1
- package/dist/resources.d.ts +4 -2
- package/dist/resources.js +15 -6
- package/dist/resources.js.map +1 -1
- package/dist/run.d.ts +3 -0
- package/dist/run.js.map +1 -1
- package/dist/runtime-ops.d.ts +123 -0
- package/dist/runtime-ops.js +222 -0
- package/dist/runtime-ops.js.map +1 -0
- package/dist/seal.d.ts +27 -0
- package/dist/seal.js +76 -0
- package/dist/seal.js.map +1 -0
- package/dist/secret-store.d.ts +6 -4
- package/dist/secret-store.js +11 -6
- package/dist/secret-store.js.map +1 -1
- package/dist/secret.d.ts +7 -0
- package/dist/secret.js +13 -1
- package/dist/secret.js.map +1 -1
- package/dist/shared.d.ts +15 -4
- package/dist/shared.js +27 -7
- package/dist/shared.js.map +1 -1
- package/dist/ssh-key.d.ts +11 -0
- package/dist/ssh-key.js +44 -0
- package/dist/ssh-key.js.map +1 -0
- package/dist/tokens.d.ts +35 -0
- package/dist/tokens.js +71 -0
- package/dist/tokens.js.map +1 -0
- package/dist/wakeup-service.js +2 -7
- package/dist/wakeup-service.js.map +1 -1
- package/dist/wakeup.d.ts +18 -0
- package/dist/wakeup.js +15 -0
- package/dist/wakeup.js.map +1 -1
- package/dist/worker.d.ts +2 -2
- package/dist/worker.js +17 -9
- package/dist/worker.js.map +1 -1
- package/oxlint.json +1 -1
- package/package.json +1 -1
- package/src/apply.ts +1 -1
- package/src/call.ts +88 -18
- package/src/change.ts +9 -20
- package/src/client.ts +48 -7
- package/src/config.ts +111 -17
- package/src/db.ts +8 -1
- package/src/deadlines.ts +66 -20
- package/src/define.ts +25 -0
- package/src/deployment-key.ts +34 -8
- package/src/describe.ts +39 -2
- package/src/description.ts +2 -0
- package/src/host.ts +22 -6
- package/src/index.ts +18 -1
- package/src/ledger.ts +52 -1
- package/src/login-code.ts +52 -0
- package/src/op.ts +84 -11
- package/src/outline.ts +3 -3
- package/src/resource.ts +8 -5
- package/src/resources.ts +13 -4
- package/src/run.ts +3 -0
- package/src/runtime-ops.ts +234 -0
- package/src/seal.ts +95 -0
- package/src/secret-store.ts +12 -9
- package/src/secret.ts +16 -1
- package/src/shared.ts +31 -7
- package/src/ssh-key.ts +48 -0
- package/src/tokens.ts +100 -0
- package/src/wakeup-service.ts +2 -8
- package/src/wakeup.ts +21 -0
- package/src/worker.ts +29 -11
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { keyBytes } from "./deployment-key.js";
|
|
4
|
+
import { defineConnector, defineDriver, DriverError, retryableStatus } from "./op.js";
|
|
5
|
+
import { generateSecret, SECRET_NAME } from "./secret.js";
|
|
6
|
+
import { sealInvite } from "./seal.js";
|
|
7
|
+
import { errorMessage } from "./shared.js";
|
|
8
|
+
import { sourceKeyPair, sshPublicKey } from "./ssh-key.js";
|
|
9
|
+
import { memoryTokens } from "./tokens.js";
|
|
10
|
+
// What a workflow cannot do itself and the runtime does for it, as operations of the vendor
|
|
11
|
+
// `sanoma` (`sanoma.secret.*`, `sanoma.invite.mint`, `sanoma.token.*`): named in `uses`, decided by
|
|
12
|
+
// the policy, recorded in the ledger, and never answering a secret's value. `resolveConfig`
|
|
13
|
+
// registers them in every config with their driver (`runtimeDriver`), so a policy may name them;
|
|
14
|
+
// a sandbox run calls `sandboxRuntimeDriver`, over its own secrets and tokens, posting nothing.
|
|
15
|
+
/** A secret's name, as the store takes it (upper case), other than the runtime's own (`SANOMA_…`: its keys and credentials). */
|
|
16
|
+
const SecretName = z
|
|
17
|
+
.string()
|
|
18
|
+
.regex(SECRET_NAME, "a secret's name: upper case, A-Z, 0-9 and _")
|
|
19
|
+
.refine((name) => !name.startsWith("SANOMA_"), "a SANOMA_ name is the runtime's own, not a workflow's to use");
|
|
20
|
+
/** How long an instance gets to answer `POST /auth/invite`. */
|
|
21
|
+
const INVITE_TIMEOUT_MS = 10_000;
|
|
22
|
+
/**
|
|
23
|
+
* The runtime's own operations a workflow calls: `import { sanoma } from "sanoma"`, then
|
|
24
|
+
* `uses: [sanoma.secret.generate]` and `ctx.sanoma.secret.generate({ name, kind })`.
|
|
25
|
+
*/
|
|
26
|
+
export const sanoma = defineConnector("sanoma", {
|
|
27
|
+
secret: {
|
|
28
|
+
generate: {
|
|
29
|
+
effect: "write",
|
|
30
|
+
// A value stored is kept: a retry answers what the first try stored.
|
|
31
|
+
idempotent: true,
|
|
32
|
+
description: "Make a secret and store it under a name: a random value, or an RSA key pair whose private half (PEM) is stored and whose public half (OpenSSH) is answered. A name stored already is kept",
|
|
33
|
+
input: z.object({
|
|
34
|
+
name: SecretName,
|
|
35
|
+
kind: z.enum(["random", "ssh-rsa"]).describe("random: 32 random bytes; ssh-rsa: an RSA deploy key"),
|
|
36
|
+
}),
|
|
37
|
+
output: z.object({
|
|
38
|
+
name: z.string(),
|
|
39
|
+
publicKey: z.string().optional().describe("For ssh-rsa: the public half, `ssh-rsa <base64>`"),
|
|
40
|
+
}),
|
|
41
|
+
target: ({ name }) => name,
|
|
42
|
+
createsSecrets: ({ name }) => [name],
|
|
43
|
+
},
|
|
44
|
+
delete: {
|
|
45
|
+
effect: "write",
|
|
46
|
+
idempotent: true,
|
|
47
|
+
description: "Delete a stored secret; one not stored is nothing to do",
|
|
48
|
+
input: z.object({ name: SecretName }),
|
|
49
|
+
output: z.object({}),
|
|
50
|
+
target: ({ name }) => name,
|
|
51
|
+
createsSecrets: ({ name }) => [name],
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
invite: {
|
|
55
|
+
mint: {
|
|
56
|
+
effect: "access",
|
|
57
|
+
// Each try seals a new request (good for `sealInvite`'s few minutes), and the instance's newest
|
|
58
|
+
// invite for an email replaces the last.
|
|
59
|
+
idempotent: true,
|
|
60
|
+
description: "Ask an instance for an invite link that signs a declared person in: a request sealed under the instance's signing key, named by a secret marker, posted to its /auth/invite",
|
|
61
|
+
input: z.object({
|
|
62
|
+
host: z.url({ protocol: /^https?$/ }).describe("The instance's address, such as https://acme.sanoma.work"),
|
|
63
|
+
email: z.email().describe("The email the instance's people file declares"),
|
|
64
|
+
key: z
|
|
65
|
+
.strictObject({ $secret: SecretName })
|
|
66
|
+
.describe('The instance\'s SANOMA_SIGNING_KEY, as stored here: secret("NAME")'),
|
|
67
|
+
}),
|
|
68
|
+
output: z.object({ url: z.string().describe("The one-use invite link the instance minted") }),
|
|
69
|
+
target: ({ host }) => host,
|
|
70
|
+
// A link that signs someone in: the ledger records that there was one, not what it was.
|
|
71
|
+
opaque: ["url"],
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
token: {
|
|
75
|
+
mint: {
|
|
76
|
+
effect: "access",
|
|
77
|
+
description: "Mint an api token acting for a subject in groups, store it under a name, and answer its id (never the token)",
|
|
78
|
+
input: z.object({
|
|
79
|
+
subject: z.string().regex(/^\S+$/, "a principal's id, such as visitor:better-auth:<id>"),
|
|
80
|
+
groups: z.array(z.string().min(1)),
|
|
81
|
+
store: SecretName.describe("The secret the token is stored under"),
|
|
82
|
+
}),
|
|
83
|
+
output: z.object({ id: z.string() }),
|
|
84
|
+
target: ({ subject }) => subject,
|
|
85
|
+
createsSecrets: ({ store }) => [store],
|
|
86
|
+
},
|
|
87
|
+
revoke: {
|
|
88
|
+
effect: "access",
|
|
89
|
+
idempotent: true,
|
|
90
|
+
description: "Revoke an api token: it resolves to nobody from now on",
|
|
91
|
+
input: z.object({ id: z.string().min(1) }),
|
|
92
|
+
output: z.object({}),
|
|
93
|
+
target: ({ id }) => `token:${id}`,
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
/** A `DriverError` that a retry would not change. */
|
|
98
|
+
const refuse = (message) => new DriverError(`sanoma: ${message}`, { retryable: false });
|
|
99
|
+
/** The token id a call mints, from its idempotency key: the same on every try of one call, so a retry finds its own. */
|
|
100
|
+
function tokenIdOf(call) {
|
|
101
|
+
const hex = createHash("sha256").update(call.idempotencyKey).digest("hex");
|
|
102
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;
|
|
103
|
+
}
|
|
104
|
+
/** The 32 bytes of a signing key stored as text (base64, or base64url as `generate` makes one), or a refusal. */
|
|
105
|
+
function signingKeyOf(secret, text) {
|
|
106
|
+
if (text === undefined)
|
|
107
|
+
throw refuse(`the secret ${secret} is not set: store the instance's signing key under it`);
|
|
108
|
+
const key = keyBytes(text);
|
|
109
|
+
if (!key)
|
|
110
|
+
throw refuse(`${secret} is not a signing key: 32 bytes in base64`);
|
|
111
|
+
return key;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Posts the sealed `request` to the instance's `/auth/invite`, and answers the link it minted
|
|
115
|
+
* (`sanoma.invite.mint`, and going live's sign-in); a `DriverError` otherwise, retryable by status.
|
|
116
|
+
*/
|
|
117
|
+
export async function postInvite(host, request) {
|
|
118
|
+
const at = new URL("/auth/invite", host);
|
|
119
|
+
let res;
|
|
120
|
+
try {
|
|
121
|
+
res = await fetch(at, {
|
|
122
|
+
method: "POST",
|
|
123
|
+
headers: { "content-type": "application/json" },
|
|
124
|
+
body: JSON.stringify({ request }),
|
|
125
|
+
// A redirect is answered as it is (a 3xx, not retried): the sealed request goes to `host` alone.
|
|
126
|
+
redirect: "manual",
|
|
127
|
+
signal: AbortSignal.timeout(INVITE_TIMEOUT_MS),
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
throw new DriverError(`sanoma: ${at.host} could not be reached: ${errorMessage(err)}`, {
|
|
132
|
+
retryable: true,
|
|
133
|
+
cause: err,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
const body = (await res.json().catch(() => undefined));
|
|
137
|
+
if (res.ok && typeof body?.url === "string")
|
|
138
|
+
return { url: body.url };
|
|
139
|
+
const why = typeof body?.error === "string" ? `: ${body.error}` : res.ok ? ": no url" : "";
|
|
140
|
+
throw new DriverError(`sanoma: ${at.host} answered ${res.status} to POST /auth/invite${why}`, {
|
|
141
|
+
retryable: !res.ok && retryableStatus(res.status),
|
|
142
|
+
status: res.status,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* The driver of the runtime's own operations, over the call's secrets and `tokens` (the config's
|
|
147
|
+
* database's, `tokenStore`); `invite` posts a sealed request to an instance (`postInvite` by default).
|
|
148
|
+
*/
|
|
149
|
+
export function runtimeDriver({ tokens, invite = postInvite, }) {
|
|
150
|
+
return defineDriver(sanoma, {
|
|
151
|
+
secret: {
|
|
152
|
+
async generate({ name, kind }, call) {
|
|
153
|
+
if (kind === "random") {
|
|
154
|
+
await call.secrets.ensure(name, generateSecret);
|
|
155
|
+
return { name };
|
|
156
|
+
}
|
|
157
|
+
// A pair made only when none is stored: the public half is always derived from what is.
|
|
158
|
+
let stored = await call.secrets.get(name);
|
|
159
|
+
if (stored === undefined) {
|
|
160
|
+
const pair = await sourceKeyPair();
|
|
161
|
+
stored = await call.secrets.ensure(name, () => pair.privateKey);
|
|
162
|
+
}
|
|
163
|
+
const publicKey = sshPublicKey(stored);
|
|
164
|
+
if (!publicKey)
|
|
165
|
+
throw refuse(`${name} holds a value that is not an RSA private key: delete it, or name another`);
|
|
166
|
+
return { name, publicKey };
|
|
167
|
+
},
|
|
168
|
+
async delete({ name }, call) {
|
|
169
|
+
await call.secrets.delete(name);
|
|
170
|
+
return {};
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
invite: {
|
|
174
|
+
async mint({ host, email, key }, call) {
|
|
175
|
+
const signingKey = signingKeyOf(key.$secret, await call.secrets.get(key.$secret));
|
|
176
|
+
const request = sealInvite({ email }, signingKey);
|
|
177
|
+
return invite(host, request, call);
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
token: {
|
|
181
|
+
async mint({ subject, groups, store }, call) {
|
|
182
|
+
const id = tokenIdOf(call);
|
|
183
|
+
const held = await call.secrets.get(store);
|
|
184
|
+
if (held !== undefined) {
|
|
185
|
+
// This call's own, stored by a try whose answer was lost.
|
|
186
|
+
if ((await tokens.resolve(held))?.principal.id === `token:${id}`)
|
|
187
|
+
return { id };
|
|
188
|
+
throw refuse(`${store} holds a value already: delete it, or store the token under another name`);
|
|
189
|
+
}
|
|
190
|
+
let token;
|
|
191
|
+
try {
|
|
192
|
+
({ token } = await tokens.mint({ id, subject, groups }));
|
|
193
|
+
}
|
|
194
|
+
catch (err) {
|
|
195
|
+
// A try that minted this id and stopped before storing it left a token nobody holds: revoked here.
|
|
196
|
+
if ((await tokens.subjectOf(id)) === undefined)
|
|
197
|
+
throw err;
|
|
198
|
+
await tokens.revoke({ id });
|
|
199
|
+
throw refuse(`an earlier try minted token ${id} and stopped before storing it: it is revoked, start again`);
|
|
200
|
+
}
|
|
201
|
+
if ((await call.secrets.ensure(store, () => token)) !== token) {
|
|
202
|
+
await tokens.revoke({ id });
|
|
203
|
+
throw refuse(`${store} was stored by someone else meanwhile: the token minted is revoked`);
|
|
204
|
+
}
|
|
205
|
+
return { id };
|
|
206
|
+
},
|
|
207
|
+
async revoke({ id }) {
|
|
208
|
+
await tokens.revoke({ id });
|
|
209
|
+
return {};
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* The runtime's own operations for one sandbox run: the run's secrets (in memory), tokens in
|
|
216
|
+
* memory, and an invite that posts nothing, answering a link on the host named.
|
|
217
|
+
*/
|
|
218
|
+
export const sandboxRuntimeDriver = () => runtimeDriver({
|
|
219
|
+
tokens: memoryTokens(),
|
|
220
|
+
invite: async (host, _request, call) => ({ url: new URL(`/auth/invite/sandbox-${tokenIdOf(call)}`, host).href }),
|
|
221
|
+
});
|
|
222
|
+
//# sourceMappingURL=runtime-ops.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-ops.js","sourceRoot":"","sources":["../src/runtime-ops.ts"],"names":[],"mappings":"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"}
|
package/dist/seal.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A sign-in code sealed with the email it is for, for a `login-code` run's input, so the run's
|
|
3
|
+
* input never shows it and a copy of it opens for no one else.
|
|
4
|
+
*/
|
|
5
|
+
export declare const sealLoginCode: (to: string, code: string) => string;
|
|
6
|
+
/** The code `sealLoginCode` sealed for `to`; throws for anything else, a code sealed for another email among it. */
|
|
7
|
+
export declare function openLoginCode(sealed: string, to: string): string;
|
|
8
|
+
/** A request for an invite (`POST /auth/invite { request }`): for whom, until when (ms since the epoch), and a nonce. */
|
|
9
|
+
export interface InviteRequest {
|
|
10
|
+
email: string;
|
|
11
|
+
exp: number;
|
|
12
|
+
nonce: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* A request for `email`'s invite, sealed under a key derived from `SANOMA_SIGNING_KEY` (purpose
|
|
16
|
+
* `invite request`), or from `signingKey`, another deployment's signing key (its 32 bytes): what
|
|
17
|
+
* a holder of the deployment's signing key sends the instance as `POST /auth/invite { request }`
|
|
18
|
+
* (going live, and Sanoma Cloud's birth invite, `sanoma.invite.mint`). `exp` defaults to five
|
|
19
|
+
* minutes from now, `nonce` to 16 random bytes.
|
|
20
|
+
*/
|
|
21
|
+
export declare function sealInvite({ email, exp, nonce }: {
|
|
22
|
+
email: string;
|
|
23
|
+
exp?: number;
|
|
24
|
+
nonce?: string;
|
|
25
|
+
}, signingKey?: Buffer): string;
|
|
26
|
+
/** The request `sealInvite` sealed, while `exp` is after `now`; undefined for anything else, or once it expired. */
|
|
27
|
+
export declare function openInvite(sealed: string, now?: number): InviteRequest | undefined;
|
package/dist/seal.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { createCipheriv, createDecipheriv, randomBytes } from "node:crypto";
|
|
2
|
+
import { deriveSigningKey, signingKeyFor } from "./deployment-key.js";
|
|
3
|
+
// Small values sealed under a key of their own, derived from the deployment's SANOMA_SIGNING_KEY
|
|
4
|
+
// for one purpose (HKDF-SHA256): a sign-in code in a `login-code` run's input, and a request for
|
|
5
|
+
// an invite that a holder of the key sends to the instance (`POST /auth/invite`). AES-256-GCM, the
|
|
6
|
+
// purpose as its additional data, so a value sealed for one purpose never opens for another.
|
|
7
|
+
const IV = 12;
|
|
8
|
+
const TAG = 16;
|
|
9
|
+
/** The key for `purpose`: derived from `signingKey`, a deployment's signing key, else from this process's own. */
|
|
10
|
+
const keyFor = (purpose, signingKey) => signingKey ? deriveSigningKey(signingKey, purpose) : signingKeyFor(purpose);
|
|
11
|
+
/**
|
|
12
|
+
* `value` as JSON, sealed for `purpose` under `signingKey` (this process's own by default): base64url
|
|
13
|
+
* of the IV, the tag and the ciphertext.
|
|
14
|
+
*/
|
|
15
|
+
function seal(purpose, value, signingKey) {
|
|
16
|
+
const iv = randomBytes(IV);
|
|
17
|
+
const cipher = createCipheriv("aes-256-gcm", keyFor(purpose, signingKey), iv).setAAD(Buffer.from(purpose));
|
|
18
|
+
const text = Buffer.concat([cipher.update(JSON.stringify(value), "utf8"), cipher.final()]);
|
|
19
|
+
return Buffer.concat([iv, cipher.getAuthTag(), text]).toString("base64url");
|
|
20
|
+
}
|
|
21
|
+
/** What `seal(purpose, …)` sealed, or undefined for anything else: another key, another purpose, a change. */
|
|
22
|
+
function unseal(purpose, sealed) {
|
|
23
|
+
const bytes = Buffer.from(sealed, "base64url");
|
|
24
|
+
if (bytes.length <= IV + TAG)
|
|
25
|
+
return undefined;
|
|
26
|
+
try {
|
|
27
|
+
const decipher = createDecipheriv("aes-256-gcm", keyFor(purpose), bytes.subarray(0, IV))
|
|
28
|
+
.setAAD(Buffer.from(purpose))
|
|
29
|
+
.setAuthTag(bytes.subarray(IV, IV + TAG));
|
|
30
|
+
const text = Buffer.concat([decipher.update(bytes.subarray(IV + TAG)), decipher.final()]);
|
|
31
|
+
return JSON.parse(text.toString("utf8"));
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const CODE = "login code";
|
|
38
|
+
const INVITE = "invite request";
|
|
39
|
+
/**
|
|
40
|
+
* A sign-in code sealed with the email it is for, for a `login-code` run's input, so the run's
|
|
41
|
+
* input never shows it and a copy of it opens for no one else.
|
|
42
|
+
*/
|
|
43
|
+
export const sealLoginCode = (to, code) => seal(CODE, { to, code });
|
|
44
|
+
/** The code `sealLoginCode` sealed for `to`; throws for anything else, a code sealed for another email among it. */
|
|
45
|
+
export function openLoginCode(sealed, to) {
|
|
46
|
+
const opened = unseal(CODE, sealed);
|
|
47
|
+
if (typeof opened?.code !== "string" || opened.to !== to) {
|
|
48
|
+
throw new Error(`The sign-in code is not one this deployment sealed for ${to}`);
|
|
49
|
+
}
|
|
50
|
+
return opened.code;
|
|
51
|
+
}
|
|
52
|
+
/** How long a sealed invite request is good for when `exp` is not given: five minutes. */
|
|
53
|
+
const INVITE_REQUEST_MS = 5 * 60_000;
|
|
54
|
+
/**
|
|
55
|
+
* A request for `email`'s invite, sealed under a key derived from `SANOMA_SIGNING_KEY` (purpose
|
|
56
|
+
* `invite request`), or from `signingKey`, another deployment's signing key (its 32 bytes): what
|
|
57
|
+
* a holder of the deployment's signing key sends the instance as `POST /auth/invite { request }`
|
|
58
|
+
* (going live, and Sanoma Cloud's birth invite, `sanoma.invite.mint`). `exp` defaults to five
|
|
59
|
+
* minutes from now, `nonce` to 16 random bytes.
|
|
60
|
+
*/
|
|
61
|
+
export function sealInvite({ email, exp, nonce }, signingKey) {
|
|
62
|
+
const request = {
|
|
63
|
+
email,
|
|
64
|
+
exp: exp ?? Date.now() + INVITE_REQUEST_MS,
|
|
65
|
+
nonce: nonce ?? randomBytes(16).toString("base64url"),
|
|
66
|
+
};
|
|
67
|
+
return seal(INVITE, request, signingKey);
|
|
68
|
+
}
|
|
69
|
+
/** The request `sealInvite` sealed, while `exp` is after `now`; undefined for anything else, or once it expired. */
|
|
70
|
+
export function openInvite(sealed, now = Date.now()) {
|
|
71
|
+
const request = unseal(INVITE, sealed);
|
|
72
|
+
if (typeof request?.email !== "string" || typeof request.exp !== "number" || typeof request.nonce !== "string")
|
|
73
|
+
return undefined;
|
|
74
|
+
return request.exp > now ? request : undefined;
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=seal.js.map
|
package/dist/seal.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seal.js","sourceRoot":"","sources":["../src/seal.ts"],"names":[],"mappings":"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"}
|
package/dist/secret-store.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type DeploymentKeyName } from "./deployment-key.ts";
|
|
1
2
|
/** Opaque values belong only in trusted runtime code, never workflow history or descriptions. */
|
|
2
3
|
export interface SecretValue {
|
|
3
4
|
value: string;
|
|
@@ -55,7 +56,7 @@ export type SecretBinding = {
|
|
|
55
56
|
path?: never;
|
|
56
57
|
bootstrap?: never;
|
|
57
58
|
} | {
|
|
58
|
-
bootstrap:
|
|
59
|
+
bootstrap: DeploymentKeyName;
|
|
59
60
|
management?: "external";
|
|
60
61
|
env?: never;
|
|
61
62
|
path?: never;
|
|
@@ -92,9 +93,10 @@ export declare class SecretAccess {
|
|
|
92
93
|
expectedVersion: string | null;
|
|
93
94
|
by: string;
|
|
94
95
|
}): Promise<SecretValue>;
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
/** Deletes the value at `expectedVersion`; without one, the value stored now, and none stored is nothing to do. */
|
|
97
|
+
delete(name: string, options?: {
|
|
98
|
+
expectedVersion?: string;
|
|
99
|
+
by?: string;
|
|
98
100
|
}): Promise<void>;
|
|
99
101
|
ensure(name: string, make: () => string): Promise<string>;
|
|
100
102
|
private writable;
|
package/dist/secret-store.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { deploymentKey } from "./deployment-key.js";
|
|
1
|
+
import { DEPLOYMENT_KEYS, deploymentKey } from "./deployment-key.js";
|
|
2
2
|
/** Intentionally carries no provider message, cause, path or value. */
|
|
3
3
|
export class SecretStoreError extends Error {
|
|
4
4
|
code;
|
|
@@ -68,10 +68,10 @@ export function checkSecretConfiguration(config) {
|
|
|
68
68
|
for (const [name, b] of Object.entries(config.bindings ?? {})) {
|
|
69
69
|
if (!namePattern.test(name) || !b || typeof b !== "object")
|
|
70
70
|
invalid();
|
|
71
|
-
if (
|
|
71
|
+
if (DEPLOYMENT_KEYS.includes(name) && !("env" in b) && !("bootstrap" in b))
|
|
72
72
|
invalid();
|
|
73
73
|
if ("bootstrap" in b) {
|
|
74
|
-
if (!
|
|
74
|
+
if (!DEPLOYMENT_KEYS.includes(b.bootstrap) ||
|
|
75
75
|
b.path !== undefined ||
|
|
76
76
|
b.env !== undefined ||
|
|
77
77
|
(b.management !== undefined && b.management !== "external"))
|
|
@@ -108,7 +108,7 @@ export class SecretAccess {
|
|
|
108
108
|
const binding = Object.hasOwn(this.bindings, name) ? this.bindings[name] : undefined;
|
|
109
109
|
if (binding?.bootstrap !== undefined)
|
|
110
110
|
return { store: "bootstrap", namespace: "", path: binding.bootstrap, management: "external" };
|
|
111
|
-
if (
|
|
111
|
+
if (DEPLOYMENT_KEYS.includes(name) && !binding)
|
|
112
112
|
throw new SecretStoreError("invalid_configuration");
|
|
113
113
|
if (binding?.env !== undefined)
|
|
114
114
|
return { store: "environment", namespace: "", path: binding.env, management: "external" };
|
|
@@ -144,11 +144,16 @@ export class SecretAccess {
|
|
|
144
144
|
throw new SecretStoreError("too_large");
|
|
145
145
|
return secretStoreCall(() => this.store.write(location, value, options));
|
|
146
146
|
}
|
|
147
|
-
|
|
147
|
+
/** Deletes the value at `expectedVersion`; without one, the value stored now, and none stored is nothing to do. */
|
|
148
|
+
async delete(name, options = {}) {
|
|
148
149
|
const location = this.writable(name);
|
|
149
150
|
if (this.store.capabilities.deletion === "unsupported")
|
|
150
151
|
throw new SecretStoreError("unsupported");
|
|
151
|
-
|
|
152
|
+
const expectedVersion = options.expectedVersion ?? (await this.read(name))?.version;
|
|
153
|
+
if (expectedVersion === undefined)
|
|
154
|
+
return;
|
|
155
|
+
const by = options.by ?? "sanoma";
|
|
156
|
+
await secretStoreCall(() => this.store.delete(location, { expectedVersion, by }));
|
|
152
157
|
}
|
|
153
158
|
async ensure(name, make) {
|
|
154
159
|
const stored = await this.read(name);
|
package/dist/secret-store.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secret-store.js","sourceRoot":"","sources":["../src/secret-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"secret-store.js","sourceRoot":"","sources":["../src/secret-store.ts"],"names":[],"mappings":"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"}
|
package/dist/secret.d.ts
CHANGED
|
@@ -26,11 +26,18 @@ export interface Secrets {
|
|
|
26
26
|
get(name: string): Promise<string | undefined>;
|
|
27
27
|
/** The stored value; when there is none, `make()`'s, stored first. */
|
|
28
28
|
ensure(name: string, make: () => string): Promise<string>;
|
|
29
|
+
/** Deletes the stored value; none stored is nothing to do. The runtime's own `sanoma.secret.delete` calls it. */
|
|
30
|
+
delete(name: string): Promise<void>;
|
|
29
31
|
}
|
|
30
32
|
/** A named call can resolve only the auxiliary secret markers present in its authorized input. */
|
|
31
33
|
export declare function secretsForInput(input: unknown, secrets: Secrets, creates?: readonly string[]): Secrets;
|
|
32
34
|
/** A value for a secret with `generate`: 32 random bytes, base64url. */
|
|
33
35
|
export declare const generateSecret: () => string;
|
|
36
|
+
/**
|
|
37
|
+
* A bearer token's sha256, hex: all a table keeps of one (the wakeup service's, the api tokens). A
|
|
38
|
+
* token is found by its hash (a unique index), so the secret itself is never compared.
|
|
39
|
+
*/
|
|
40
|
+
export declare const tokenHash: (token: string) => string;
|
|
34
41
|
/** `T` with each secret marker's place holding its value: what `resolveSecrets` returns. */
|
|
35
42
|
export type Resolved<T> = T extends Secret ? string : T extends readonly (infer I)[] ? Resolved<I>[] : T extends object ? {
|
|
36
43
|
[K in keyof T]: Resolved<T[K]>;
|
package/dist/secret.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { randomBytes } from "node:crypto";
|
|
1
|
+
import { createHash, randomBytes } from "node:crypto";
|
|
2
2
|
import { DriverError } from "./op.js";
|
|
3
3
|
/** A secret's name: an environment variable's, upper case. */
|
|
4
4
|
export const SECRET_NAME = /^[A-Z][A-Z0-9_]*$/;
|
|
@@ -49,10 +49,19 @@ export function secretsForInput(input, secrets, creates = []) {
|
|
|
49
49
|
check(name, true);
|
|
50
50
|
return secrets.ensure(name, make);
|
|
51
51
|
},
|
|
52
|
+
async delete(name) {
|
|
53
|
+
check(name, true);
|
|
54
|
+
return secrets.delete(name);
|
|
55
|
+
},
|
|
52
56
|
};
|
|
53
57
|
}
|
|
54
58
|
/** A value for a secret with `generate`: 32 random bytes, base64url. */
|
|
55
59
|
export const generateSecret = () => randomBytes(32).toString("base64url");
|
|
60
|
+
/**
|
|
61
|
+
* A bearer token's sha256, hex: all a table keeps of one (the wakeup service's, the api tokens). A
|
|
62
|
+
* token is found by its hash (a unique index), so the secret itself is never compared.
|
|
63
|
+
*/
|
|
64
|
+
export const tokenHash = (token) => createHash("sha256").update(token).digest("hex");
|
|
56
65
|
/**
|
|
57
66
|
* `value` with each secret marker in it replaced by the stored value: generated and stored first
|
|
58
67
|
* for one with `generate` and none stored. A marker naming nothing stored fails the call, for good.
|
|
@@ -85,6 +94,9 @@ export function memorySecrets(initial = {}) {
|
|
|
85
94
|
values.set(name, make());
|
|
86
95
|
return values.get(name);
|
|
87
96
|
},
|
|
97
|
+
async delete(name) {
|
|
98
|
+
values.delete(name);
|
|
99
|
+
},
|
|
88
100
|
};
|
|
89
101
|
}
|
|
90
102
|
//# sourceMappingURL=secret.js.map
|
package/dist/secret.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secret.js","sourceRoot":"","sources":["../src/secret.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"secret.js","sourceRoot":"","sources":["../src/secret.ts"],"names":[],"mappings":"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"}
|
package/dist/shared.d.ts
CHANGED
|
@@ -173,7 +173,13 @@ export declare const CHANGE_EVENT = "change";
|
|
|
173
173
|
export declare const CHANGE_TOPIC = "change:event";
|
|
174
174
|
/** Lists the apps on GitHub with Sanoma's claims: the one runtime operation a page may call (`isDirect`). */
|
|
175
175
|
export declare const APPS_LIST = "sanoma.apps.list";
|
|
176
|
-
/**
|
|
176
|
+
/**
|
|
177
|
+
* The built-in workflow that sends a staff or visitor sign-in code through the config's
|
|
178
|
+
* `login.sender`, started by the runtime's agent `login` (`LOGIN_AGENT`): its input's code is
|
|
179
|
+
* sealed, and the mail's body is recorded as `<text>` and `<html>`.
|
|
180
|
+
*/
|
|
181
|
+
export declare const LOGIN_CODE_WORKFLOW = "login-code";
|
|
182
|
+
/** The workflows the runtime adds itself, which a config's own may not be named: drift, apply, call, change and login-code. */
|
|
177
183
|
export declare const BUILT_IN_WORKFLOWS: ReadonlySet<string>;
|
|
178
184
|
/**
|
|
179
185
|
* Every run status, in the order a run may pass through them: waiting on the queue, running,
|
|
@@ -213,10 +219,13 @@ export declare const VISITORS = "visitors";
|
|
|
213
219
|
/** The principal a public page runs as when nobody is signed in: no groups. */
|
|
214
220
|
export declare const ANONYMOUS = "anonymous";
|
|
215
221
|
/**
|
|
216
|
-
* True for `anonymous
|
|
217
|
-
* logins never admit. Marked by the id alone, since a principal crosses to
|
|
222
|
+
* True for `anonymous`, a visitor's id and a token's (`token:<id>`): a principal no data file
|
|
223
|
+
* declares and the staff logins never admit. Marked by the id alone, since a principal crosses to
|
|
224
|
+
* the worker as JSON.
|
|
218
225
|
*/
|
|
219
226
|
export declare const isVisitor: (p: Pick<Principal, "id">) => boolean;
|
|
227
|
+
/** True for an api token's principal (`token:<id>`), whose groups are its row's. */
|
|
228
|
+
export declare const isToken: (p: Pick<Principal, "id">) => boolean;
|
|
220
229
|
/**
|
|
221
230
|
* The visitor a public site's login vouches for: `subject` from the provider behind the `login`
|
|
222
231
|
* connector, in `visitors`. Throws for a login or subject that would make an id `isVisitor` does not tell.
|
|
@@ -230,7 +239,9 @@ export declare const WAKEUP_AGENT = "wakeup";
|
|
|
230
239
|
export declare const SCHEDULE_AGENT = "schedule";
|
|
231
240
|
/** The runtime's agent that checks and deploys the hosts: drift's, and apply's after a push to `main` (`SanomaClient.remoteEvent`). */
|
|
232
241
|
export declare const HOST_CHECK_AGENT = "host-check";
|
|
233
|
-
/** The runtime's
|
|
242
|
+
/** The runtime's agent that sends a sign-in code (`LOGIN_CODE_WORKFLOW`): a company's policy exempts it from its holds on sending. */
|
|
243
|
+
export declare const LOGIN_AGENT = "login";
|
|
244
|
+
/** The runtime's own agents (scenarios, the host check, scheduled runs, the wakeup's registration, sign-in codes), declared whether a data file names them or not. */
|
|
234
245
|
export declare const RUNTIME_AGENTS: readonly string[];
|
|
235
246
|
type PersonFields = {
|
|
236
247
|
id: string;
|