@jeffusion/bungee-core 5.9.0 → 5.11.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/main.js +31348 -17337
- package/dist/plugins/ai-transformer/index.js.map +2 -2
- package/dist/plugins/anthropic-request-sanitizer/index.js.map +2 -2
- package/dist/plugins/anthropic-tool-name-transformer/index.js.map +2 -2
- package/dist/plugins/chatgpt-oauth/control.js +513 -1
- package/dist/plugins/chatgpt-oauth/control.js.map +12 -4
- package/dist/plugins/chatgpt-oauth/index.js +511 -4
- package/dist/plugins/chatgpt-oauth/index.js.map +13 -5
- package/dist/plugins/chatgpt-oauth/manifest.json +19 -0
- package/dist/plugins/deepseek-reasoning-fix/index.js.map +2 -2
- package/dist/plugins/key-access/control.js.map +1 -1
- package/dist/plugins/key-access/index.js.map +3 -3
- package/dist/plugins/key-access/ingress.js.map +1 -1
- package/dist/plugins/key-rate-limit/index.js.map +2 -2
- package/dist/plugins/local-accounts/control.js +68 -18
- package/dist/plugins/local-accounts/control.js.map +4 -4
- package/dist/plugins/local-accounts/index.js.map +2 -2
- package/dist/plugins/local-accounts/manifest.json +48 -2
- package/dist/plugins/local-accounts/ui/Settings.svelte +73 -1
- package/dist/plugins/model-mapping/control.js +72 -17741
- package/dist/plugins/model-mapping/control.js.map +6 -58
- package/dist/plugins/model-mapping/index.js +32 -17433
- package/dist/plugins/model-mapping/index.js.map +6 -58
- package/dist/plugins/model-mapping/manifest.json +30 -14
- package/dist/plugins/models-dev/control.js +1042 -0
- package/dist/plugins/models-dev/control.js.map +16 -0
- package/dist/plugins/models-dev/index.js +15418 -0
- package/dist/plugins/models-dev/index.js.map +134 -0
- package/dist/plugins/models-dev/manifest.json +199 -0
- package/dist/plugins/models-dev/ui/ModelsDevSettings.svelte +120 -0
- package/dist/plugins/openai-messages-to-chat/index.js.map +2 -2
- package/dist/plugins/signature-repair/index.js.map +2 -2
- package/dist/plugins/token-budget/control.js +524 -9
- package/dist/plugins/token-budget/control.js.map +12 -4
- package/dist/plugins/token-budget/index.js +519 -12
- package/dist/plugins/token-budget/index.js.map +13 -6
- package/dist/plugins/token-budget/manifest.json +16 -2
- package/dist/plugins/token-metering/index.js +93 -2
- package/dist/plugins/token-metering/index.js.map +12 -6
- package/dist/plugins/token-stats/control.js +174 -312
- package/dist/plugins/token-stats/control.js.map +7 -7
- package/dist/plugins/token-stats/index.js +283 -486
- package/dist/plugins/token-stats/index.js.map +16 -12
- package/dist/plugins/token-stats/manifest.json +99 -12
- package/dist/plugins/token-stats/ui/ClientModelPicker.svelte +76 -0
- package/dist/plugins/token-stats/ui/PriceModelPicker.svelte +87 -0
- package/dist/plugins/token-stats/ui/TokenStatsSettings.svelte +136 -80
- package/dist/plugins/token-stats/ui/client-model-search.test.ts +58 -0
- package/dist/plugins/token-stats/ui/client-model-search.ts +16 -0
- package/dist/plugins/token-stats/ui/model-search.ts +45 -0
- package/dist/plugins/token-stats/ui/pricing-catalog.test.ts +114 -0
- package/dist/plugins/token-stats/ui/pricing-catalog.ts +17 -0
- package/package.json +2 -2
|
@@ -3,19 +3,17 @@
|
|
|
3
3
|
import { createHash, createHmac, randomBytes, randomUUID, timingSafeEqual } from "crypto";
|
|
4
4
|
|
|
5
5
|
// packages/core/src/plugin-durable-state.ts
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
super("Durable state version conflict");
|
|
9
|
-
this.name = "DurableStateConflictError";
|
|
10
|
-
}
|
|
6
|
+
function isDurableStateConflictError(error) {
|
|
7
|
+
return error instanceof Error && "code" in error && error.code === "durable_state_conflict";
|
|
11
8
|
}
|
|
12
9
|
var MAX_BYTES = 1024 * 1024;
|
|
13
10
|
|
|
14
11
|
// plugins/local-accounts/server/control.ts
|
|
15
12
|
var PROVIDER = "local-accounts";
|
|
16
13
|
var COOKIE = "bungee_local_session";
|
|
17
|
-
var
|
|
18
|
-
var
|
|
14
|
+
var DEFAULT_SESSION_POLICY = Object.freeze({ idleTimeoutMinutes: 30, absoluteTimeoutMinutes: 480 });
|
|
15
|
+
var COOKIE_LEASE_SECONDS = 400 * 24 * 60 * 60;
|
|
16
|
+
var MAX_TIMEOUT_MINUTES = Math.floor(Number.MAX_SAFE_INTEGER / 60000);
|
|
19
17
|
var ALL = ["config.read", "config.write", "logs.read", "logs.body", "keys.read", "keys.write", "plugins.read", "plugins.toggle", "plugins.code", "auth.mode", "self.password", "self.logout"];
|
|
20
18
|
|
|
21
19
|
class AccountError extends Error {
|
|
@@ -113,8 +111,16 @@ function origin(request, expected) {
|
|
|
113
111
|
if (request.headers.get("origin") !== (expected ?? new URL(request.url).origin))
|
|
114
112
|
fail("invalid_origin", 403);
|
|
115
113
|
}
|
|
116
|
-
function cookie(request, token,
|
|
117
|
-
return `${COOKIE}=${token}; Path=/; HttpOnly; SameSite=Strict; Max-Age=${
|
|
114
|
+
function cookie(request, token, maxAge, managementOrigin) {
|
|
115
|
+
return `${COOKIE}=${token}; Path=/; HttpOnly; SameSite=Strict; Max-Age=${maxAge}${new URL(managementOrigin ?? request.url).protocol === "https:" ? "; Secure" : ""}`;
|
|
116
|
+
}
|
|
117
|
+
function validateSessionPolicy(value, code = "invalid_session_policy", status = 400) {
|
|
118
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
119
|
+
fail(code, status);
|
|
120
|
+
const p = value;
|
|
121
|
+
if (Object.keys(p).some((key) => !["idleTimeoutMinutes", "absoluteTimeoutMinutes"].includes(key)) || ![p.idleTimeoutMinutes, p.absoluteTimeoutMinutes].every((n) => Number.isSafeInteger(n) && n >= 0 && n <= MAX_TIMEOUT_MINUTES))
|
|
122
|
+
fail(code, status);
|
|
123
|
+
return { idleTimeoutMinutes: p.idleTimeoutMinutes, absoluteTimeoutMinutes: p.absoluteTimeoutMinutes };
|
|
118
124
|
}
|
|
119
125
|
function validateAdministrator(m) {
|
|
120
126
|
const a = m;
|
|
@@ -152,6 +158,9 @@ function validateAccountState(value, recoveryUsername) {
|
|
|
152
158
|
for (const x of s.sessions)
|
|
153
159
|
if (!x || !/^[a-f0-9]{64}$/.test(x.digest) || x.administratorId !== s.administrator?.id || !Number.isSafeInteger(x.generation) || x.generation < 1 || !Number.isFinite(x.created) || !Number.isFinite(x.touched) || !["cookie", "bearer"].includes(x.transport))
|
|
154
160
|
fail("corrupt_state", 503);
|
|
161
|
+
for (const x of s.sessions)
|
|
162
|
+
if (x.policy !== undefined)
|
|
163
|
+
validateSessionPolicy(x.policy, "corrupt_state", 503);
|
|
155
164
|
for (const x of s.failures)
|
|
156
165
|
if (!x || typeof x.key !== "string" || !Number.isSafeInteger(x.count) || x.count < 0 || !Number.isFinite(x.until))
|
|
157
166
|
fail("corrupt_state", 503);
|
|
@@ -192,7 +201,7 @@ class LocalAccountsControl {
|
|
|
192
201
|
const b = await body(c.request);
|
|
193
202
|
exact(b, ["currentPassword", "password", "passwordConfirmation"]);
|
|
194
203
|
await this.changePassword(c.subject.id, b, () => this.requireCapability(c, "self.password", true));
|
|
195
|
-
return json({ ok: true }, 200, { "set-cookie": cookie(c.request, "",
|
|
204
|
+
return json({ ok: true }, 200, { "set-cookie": cookie(c.request, "", 0, this.host.managementOrigin) });
|
|
196
205
|
}) },
|
|
197
206
|
{ path: "/logout", methods: ["POST"], handler: "logout", invoke: invoke((c) => {
|
|
198
207
|
this.requireCapability(c, "self.logout", true);
|
|
@@ -203,6 +212,25 @@ class LocalAccountsControl {
|
|
|
203
212
|
const m = this.read().value.administrator;
|
|
204
213
|
const creds = credentials(c.request);
|
|
205
214
|
return json({ administrator: dto(m), ...creds?.transport === "cookie" ? { csrfToken: csrf(creds.token) } : {} });
|
|
215
|
+
}) },
|
|
216
|
+
{ path: "/session-policy", methods: ["GET", "PUT"], handler: "sessionPolicy", invoke: invoke(async (c) => {
|
|
217
|
+
this.requireCapability(c, "config.write", c.request.method === "PUT");
|
|
218
|
+
if (c.request.method === "GET")
|
|
219
|
+
return json(this.readSessionPolicy());
|
|
220
|
+
const b = await body(c.request);
|
|
221
|
+
exact(b, ["version", "policy"]);
|
|
222
|
+
if (!Number.isSafeInteger(b.version) || b.version < 0)
|
|
223
|
+
fail("invalid_session_policy");
|
|
224
|
+
const policy = validateSessionPolicy(b.policy);
|
|
225
|
+
this.requireCapability(c, "config.write", true);
|
|
226
|
+
try {
|
|
227
|
+
this.state.execute({ commandId: randomUUID(), mutations: [{ key: "session-policy", expectedVersion: b.version, value: policy }] });
|
|
228
|
+
} catch (e) {
|
|
229
|
+
if (isDurableStateConflictError(e))
|
|
230
|
+
fail("version_conflict", 409);
|
|
231
|
+
throw e;
|
|
232
|
+
}
|
|
233
|
+
return json(this.readSessionPolicy());
|
|
206
234
|
}) }
|
|
207
235
|
];
|
|
208
236
|
}
|
|
@@ -226,15 +254,21 @@ class LocalAccountsControl {
|
|
|
226
254
|
this.state.execute({ commandId: randomUUID(), mutations: [{ key: "accounts", expectedVersion: version, value }] });
|
|
227
255
|
return result;
|
|
228
256
|
} catch (e) {
|
|
229
|
-
if (!(e
|
|
257
|
+
if (!isDurableStateConflictError(e))
|
|
230
258
|
throw e;
|
|
231
259
|
}
|
|
232
260
|
}
|
|
233
261
|
return fail("version_conflict", 409);
|
|
234
262
|
}
|
|
263
|
+
readSessionPolicy() {
|
|
264
|
+
this.alive();
|
|
265
|
+
const record = this.state.get("session-policy");
|
|
266
|
+
return { version: record?.version ?? 0, policy: record ? validateSessionPolicy(record.value, "corrupt_state", 503) : { ...DEFAULT_SESSION_POLICY } };
|
|
267
|
+
}
|
|
235
268
|
async start() {
|
|
236
269
|
const record = this.state.get("accounts");
|
|
237
270
|
this.read();
|
|
271
|
+
this.readSessionPolicy();
|
|
238
272
|
if (record && record.value.schema === 1)
|
|
239
273
|
this.mutate(() => {
|
|
240
274
|
return;
|
|
@@ -279,12 +313,25 @@ class LocalAccountsControl {
|
|
|
279
313
|
});
|
|
280
314
|
}
|
|
281
315
|
live(s, session) {
|
|
282
|
-
const now = this.now();
|
|
283
|
-
if (now < session.touched || now - session.touched >=
|
|
316
|
+
const now = this.now(), policy = session.policy ?? DEFAULT_SESSION_POLICY;
|
|
317
|
+
if (now < session.touched || now < session.created || policy.idleTimeoutMinutes > 0 && now - session.touched >= policy.idleTimeoutMinutes * 60000 || policy.absoluteTimeoutMinutes > 0 && now - session.created >= policy.absoluteTimeoutMinutes * 60000)
|
|
284
318
|
return;
|
|
285
319
|
const m = s.administrator;
|
|
286
320
|
return m && m.id === session.administratorId && !m.disabled && m.generation === session.generation ? m : undefined;
|
|
287
321
|
}
|
|
322
|
+
cookieAge(policy, elapsedMs = 0) {
|
|
323
|
+
return policy.absoluteTimeoutMinutes === 0 ? COOKIE_LEASE_SECONDS : Math.max(0, Math.min(COOKIE_LEASE_SECONDS, Math.floor((policy.absoluteTimeoutMinutes * 60000 - elapsedMs) / 1000)));
|
|
324
|
+
}
|
|
325
|
+
sessionCookie(request) {
|
|
326
|
+
this.alive();
|
|
327
|
+
const creds = credentials(request);
|
|
328
|
+
if (creds?.transport !== "cookie")
|
|
329
|
+
return;
|
|
330
|
+
const s = this.read().value, session = s.sessions.find((x) => x.digest === digest(creds.token) && x.transport === "cookie");
|
|
331
|
+
if (!session || !this.live(s, session))
|
|
332
|
+
return;
|
|
333
|
+
return cookie(request, creds.token, this.cookieAge(session.policy ?? DEFAULT_SESSION_POLICY, this.now() - session.created), this.host.managementOrigin);
|
|
334
|
+
}
|
|
288
335
|
async authenticate(request) {
|
|
289
336
|
this.alive();
|
|
290
337
|
const c = credentials(request);
|
|
@@ -372,6 +419,8 @@ class LocalAccountsControl {
|
|
|
372
419
|
if (!valid || !administrator || administrator.disabled)
|
|
373
420
|
fail("invalid_credentials", 401);
|
|
374
421
|
const token = randomBytes(32).toString("base64url");
|
|
422
|
+
const policy = this.readSessionPolicy().policy;
|
|
423
|
+
const created = this.now();
|
|
375
424
|
this.mutate((s) => {
|
|
376
425
|
const m = s.administrator;
|
|
377
426
|
if (!m || m.id !== administrator.id || m.disabled || m.generation !== administrator.generation)
|
|
@@ -379,13 +428,13 @@ class LocalAccountsControl {
|
|
|
379
428
|
s.sessions = s.sessions.filter((x) => !!this.live(s, x));
|
|
380
429
|
if (s.sessions.length >= 512)
|
|
381
430
|
fail("session_limit", 429);
|
|
382
|
-
s.sessions.push({ digest: digest(token), administratorId: m.id, generation: m.generation, created
|
|
431
|
+
s.sessions.push({ digest: digest(token), administratorId: m.id, generation: m.generation, created, touched: created, transport, policy });
|
|
383
432
|
s.failures = s.failures.filter((x) => x.key !== keys[0]);
|
|
384
433
|
const sourceFailure = s.failures.find((x) => x.key === keys[1]);
|
|
385
434
|
if (sourceFailure)
|
|
386
435
|
sourceFailure.count = Math.max(0, sourceFailure.count - 1);
|
|
387
436
|
});
|
|
388
|
-
return transport === "cookie" ? json({ administrator: dto(administrator), csrfToken: csrf(token) }, 200, { "set-cookie": cookie(request, token,
|
|
437
|
+
return transport === "cookie" ? json({ administrator: dto(administrator), csrfToken: csrf(token) }, 200, { "set-cookie": cookie(request, token, this.cookieAge(policy, this.now() - created), this.host.managementOrigin) }) : json({ administrator: dto(administrator), token, expiresIn: policy.absoluteTimeoutMinutes === 0 ? null : policy.absoluteTimeoutMinutes * 60 });
|
|
389
438
|
} catch (e) {
|
|
390
439
|
return safe(e);
|
|
391
440
|
}
|
|
@@ -399,7 +448,7 @@ class LocalAccountsControl {
|
|
|
399
448
|
this.mutate((s) => {
|
|
400
449
|
s.sessions = s.sessions.filter((x) => x.digest !== digest(c.token));
|
|
401
450
|
});
|
|
402
|
-
return json({ ok: true }, 200, { "set-cookie": cookie(request, "",
|
|
451
|
+
return json({ ok: true }, 200, { "set-cookie": cookie(request, "", 0, this.host.managementOrigin) });
|
|
403
452
|
} catch (e) {
|
|
404
453
|
return safe(e);
|
|
405
454
|
}
|
|
@@ -434,7 +483,8 @@ function createControl(host, dependencies = {}) {
|
|
|
434
483
|
var api = [
|
|
435
484
|
{ path: "/password", methods: ["POST"], handler: "changePassword" },
|
|
436
485
|
{ path: "/logout", methods: ["POST"], handler: "logout" },
|
|
437
|
-
{ path: "/self", methods: ["GET"], handler: "self" }
|
|
486
|
+
{ path: "/self", methods: ["GET"], handler: "self" },
|
|
487
|
+
{ path: "/session-policy", methods: ["GET", "PUT"], handler: "sessionPolicy" }
|
|
438
488
|
];
|
|
439
489
|
var rpc = [];
|
|
440
490
|
var controlApi = api;
|
|
@@ -489,4 +539,4 @@ export {
|
|
|
489
539
|
rpc
|
|
490
540
|
};
|
|
491
541
|
|
|
492
|
-
//# debugId=
|
|
542
|
+
//# debugId=9FABE2F2EC4EEDD964756E2164756E21
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../plugins/local-accounts/server/control.ts", "../../../src/plugin-durable-state.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import { createHash, createHmac, randomBytes, randomUUID, timingSafeEqual } from 'node:crypto';\nimport type { ControlHostContext, ControlApiHandlerContext, PluginControl, ControlPlugin } from '../../../packages/core/src/plugin-control/contracts';\nimport type { ManagementProvider, ManagementSubject } from '../../../packages/core/src/plugin-extensions';\nimport { DurableStateConflictError, type DurableJson, type PluginDurableState } from '../../../packages/core/src/plugin-durable-state';\n\ninterface Administrator { id: string; username: string; disabled: boolean; passwordHash: string; temporary: boolean; generation: number }\ninterface Session { digest: string; administratorId: string; generation: number; created: number; touched: number; transport: 'cookie' | 'bearer' }\ninterface Failure { key: string; count: number; until: number }\ninterface State { schema: 2; administrator: Administrator | null; sessions: Session[]; failures: Failure[] }\nexport interface Dependencies { now?: () => number; trustedSource?: (request: Request) => string }\nconst PROVIDER = 'local-accounts';\nconst COOKIE = 'bungee_local_session';\nconst IDLE = 30 * 60_000, ABSOLUTE = 8 * 60 * 60_000;\nconst ALL = ['config.read', 'config.write', 'logs.read', 'logs.body', 'keys.read', 'keys.write', 'plugins.read', 'plugins.toggle', 'plugins.code', 'auth.mode', 'self.password', 'self.logout'];\nclass AccountError extends Error { constructor(readonly code: string, readonly status = 400) { super(code); } }\nfunction fail(code: string, status = 400): never { throw new AccountError(code, status); }\nfunction object(v: unknown): Record<string, unknown> { if (!v || typeof v !== 'object' || Array.isArray(v)) fail('invalid_input'); return v as Record<string, unknown>; }\nfunction exact(v: Record<string, unknown>, fields: string[]) { if (Object.keys(v).some(k => !fields.includes(k))) fail('invalid_input'); }\nfunction username(v: unknown): string { if (typeof v !== 'string' || !/^[A-Za-z0-9][A-Za-z0-9_.@-]{0,63}$/.test(v)) fail('invalid_input'); return v.toLowerCase(); }\nfunction password(v: unknown): string { if (typeof v !== 'string' || [...v].length < 6 || [...v].length > 64) fail('invalid_password'); return v; }\nfunction digest(v: string): string { return createHash('sha256').update(v).digest('hex'); }\nfunction csrf(token: string): string { return createHmac('sha256', token).update('local-accounts/csrf/v1').digest('base64url'); }\nfunction constant(a: string, b: string): boolean { const aa = Buffer.from(a), bb = Buffer.from(b); return aa.length === bb.length && timingSafeEqual(aa, bb); }\nfunction dto(m: Administrator) { return { id: m.id, username: m.username, requiresPasswordChange: m.temporary }; }\nfunction json(v: unknown, status = 200, headers: Record<string, string> = {}): Response { return Response.json(v, { status, headers: { 'cache-control': 'no-store', ...headers } }); }\nfunction safe(error: unknown): Response { return error instanceof AccountError ? json({ error: error.code }, error.status) : json({ error: 'provider_unavailable' }, 503); }\nasync function body(request: Request): Promise<Record<string, unknown>> {\n const reader = request.body?.getReader(); if (!reader) fail('invalid_input');\n let size = 0; const chunks: Uint8Array[] = [];\n try { for (;;) { const r = await reader.read(); if (r.done) break; size += r.value.length; if (size > 8192) { await reader.cancel(); fail('body_limit', 413); } chunks.push(r.value); } }\n finally { reader.releaseLock(); }\n try { return object(JSON.parse(Buffer.concat(chunks).toString('utf8'))); } catch (e) { if (e instanceof AccountError) throw e; return fail('invalid_input'); }\n}\nfunction credentials(request: Request): { token: string; transport: Session['transport'] } | null {\n const auth = request.headers.get('authorization');\n if (auth !== null) { const m = /^Bearer ([A-Za-z0-9_-]{43})$/.exec(auth); return m ? { token: m[1]!, transport: 'bearer' } : null; }\n const tokens = (request.headers.get('cookie') ?? '').split(';').map(x => x.trim()).filter(x => x.startsWith(COOKIE + '='));\n if (tokens.length !== 1) return null; const token = tokens[0]!.slice(COOKIE.length + 1);\n return /^[A-Za-z0-9_-]{43}$/.test(token) ? { token, transport: 'cookie' } : null;\n}\nfunction origin(request: Request, expected?: string) { if (request.headers.get('origin') !== (expected ?? new URL(request.url).origin)) fail('invalid_origin', 403); }\nfunction cookie(request: Request, token: string, clear = false, managementOrigin?: string) { return `${COOKIE}=${token}; Path=/; HttpOnly; SameSite=Strict; Max-Age=${clear ? 0 : ABSOLUTE / 1000}${new URL(managementOrigin ?? request.url).protocol === 'https:' ? '; Secure' : ''}`; }\n\nfunction validateAdministrator(m: unknown): asserts m is Administrator {\n const a = m as Administrator;\n if (!a || typeof a.id !== 'string' || !a.id || typeof a.username !== 'string' || !/^[a-z0-9][a-z0-9_.@-]{0,63}$/.test(a.username) || typeof a.disabled !== 'boolean' || typeof a.temporary !== 'boolean' || typeof a.passwordHash !== 'string' || !a.passwordHash.startsWith('$argon2id$') || !Number.isSafeInteger(a.generation) || a.generation < 1) fail('corrupt_state', 503);\n}\n/** Migration never promotes a former admin/viewer. Ambiguous owners require offline selection. */\nfunction validateAccountState(value: unknown, recoveryUsername?: string): State {\n if (!value || typeof value !== 'object' || Array.isArray(value)) fail('corrupt_state', 503);\n const raw = value as Record<string, unknown>;\n if (raw.schema === 1) {\n if (!Array.isArray(raw.members) || !Array.isArray(raw.sessions) || !Array.isArray(raw.failures)) fail('corrupt_state', 503);\n const ids = new Set<string>(), names = new Set<string>();\n for (const member of raw.members) {\n validateAdministrator(member);\n const legacy = member as Administrator & {role: string};\n if (!['owner', 'admin', 'viewer'].includes(legacy.role) || ids.has(member.id) || names.has(member.username)) fail('corrupt_state', 503);\n ids.add(member.id); names.add(member.username);\n }\n const candidates = raw.members.filter(m => m.role === 'owner' && (recoveryUsername ? m.username === recoveryUsername : !m.disabled));\n if (raw.members.length && candidates.length !== 1) fail(recoveryUsername ? 'recovery_requires_existing_administrator' : 'administrator_migration_required', 503);\n const chosen = candidates[0];\n const administrator = chosen ? { id: chosen.id, username: chosen.username, disabled: chosen.disabled, temporary: chosen.temporary, passwordHash: chosen.passwordHash, generation: chosen.generation } : null;\n return {schema: 2, administrator, sessions: [], failures: []};\n }\n const s = raw as unknown as State;\n if (s.schema !== 2 || !Array.isArray(s.sessions) || !Array.isArray(s.failures)) fail('corrupt_state', 503);\n if (s.administrator !== null) validateAdministrator(s.administrator);\n for (const x of s.sessions) if (!x || !/^[a-f0-9]{64}$/.test(x.digest) || x.administratorId !== s.administrator?.id || !Number.isSafeInteger(x.generation) || x.generation < 1 || !Number.isFinite(x.created) || !Number.isFinite(x.touched) || !['cookie','bearer'].includes(x.transport)) fail('corrupt_state', 503);\n for (const x of s.failures) if (!x || typeof x.key !== 'string' || !Number.isSafeInteger(x.count) || x.count < 0 || !Number.isFinite(x.until)) fail('corrupt_state', 503);\n return s;\n}\n\nexport class LocalAccountsControl implements PluginControl, ManagementProvider {\n readonly management = this;\n readonly rpc = [];\n readonly api;\n private readonly state: PluginDurableState;\n private readonly now: () => number;\n private readonly subjects = new WeakMap<ManagementSubject, { generation: number; digest: string }>();\n private dummy = '';\n private disposed = false;\n constructor(private readonly host: ControlHostContext, private readonly dependencies: Dependencies = {}) {\n if (!host.durableState) fail('durable_state_required', 503);\n this.state = host.durableState;\n this.now = dependencies.now ?? Date.now;\n const invoke = (fn: (c: ControlApiHandlerContext) => Promise<Response> | Response) => async (c: ControlApiHandlerContext) => {\n try { this.alive(); if (c.requestSignal.aborted) fail('cancelled'); return await fn(c); } catch (e) { return safe(e); }\n };\n this.api = [\n { path: '/password', methods: ['POST'], handler: 'changePassword', invoke: invoke(async c => { this.requireCapability(c, 'self.password', true); const b = await body(c.request); exact(b, ['currentPassword', 'password', 'passwordConfirmation']); await this.changePassword(c.subject!.id, b, () => this.requireCapability(c, 'self.password', true)); return json({ ok: true }, 200, { 'set-cookie': cookie(c.request, '', true, this.host.managementOrigin) }); }) },\n { path: '/logout', methods: ['POST'], handler: 'logout', invoke: invoke(c => { this.requireCapability(c, 'self.logout', true); return this.logout(c.request); }) },\n { path: '/self', methods: ['GET'], handler: 'self', invoke: invoke(c => { this.requireCapability(c, 'self.password'); const m = this.read().value.administrator!; const creds = credentials(c.request); return json({ administrator: dto(m), ...(creds?.transport === 'cookie' ? { csrfToken: csrf(creds.token) } : {}) }); }) },\n ];\n }\n private alive() { if (this.disposed || this.host.signal.aborted) fail('provider_unavailable', 503); }\n private read(): { version: number; value: State } {\n this.alive(); const record = this.state.get('accounts');\n if (!record) return { version: 0, value: { schema: 2, administrator: null, sessions: [], failures: [] } };\n const s = validateAccountState(record.value);\n return { version: record.version, value: s };\n }\n private mutate<T>(fn: (s: State) => T): T {\n for (let i = 0; i < 8; i++) { const {version, value} = this.read(); const result = fn(value);\n try { this.state.execute({ commandId: randomUUID(), mutations: [{ key: 'accounts', expectedVersion: version, value: value as unknown as DurableJson }] }); return result; }\n catch (e) { if (!(e instanceof DurableStateConflictError)) throw e; }\n } return fail('version_conflict', 409);\n }\n async start() { const record = this.state.get('accounts'); this.read(); if (record && (record.value as any).schema === 1) this.mutate(() => undefined); this.dummy = await this.hash(randomBytes(32).toString('base64url')); }\n dispose() { this.disposed = true; }\n private hash(p: string) { return Bun.password.hash(p, { algorithm: 'argon2id', memoryCost: 65536, timeCost: 3 }); }\n hasIdentity() { const a = this.read().value.administrator; return !!a && !a.disabled; }\n revokeSessions() { this.mutate(s => { s.sessions = []; }); }\n async bootstrap(input: unknown) {\n const b = object(input); exact(b, ['username', 'password', 'passwordConfirmation']); const name = username(b.username), p = password(b.password);\n if (b.passwordConfirmation !== p) fail('password_confirmation');\n const prior = this.read().value.administrator;\n if (prior) {\n if (prior.username !== name || prior.disabled || !await Bun.password.verify(p, prior.passwordHash)) fail('invalid_credentials', 401);\n const latest = this.read().value.administrator;\n if (!latest || latest.generation !== prior.generation || latest.disabled) fail('invalid_credentials', 401);\n return;\n }\n const hashed = await this.hash(p);\n this.mutate(s => { if (s.administrator) fail('bootstrap_conflict', 409); s.administrator = { id: randomUUID(), username: name, disabled: false, temporary: false, passwordHash: hashed, generation: 1 }; });\n }\n private live(s: State, session: Session): Administrator | undefined { const now = this.now(); if (now < session.touched || now - session.touched >= IDLE || now - session.created >= ABSOLUTE) return; const m = s.administrator; return m && m.id === session.administratorId && !m.disabled && m.generation === session.generation ? m : undefined; }\n async authenticate(request: Request): Promise<ManagementSubject | null> {\n this.alive(); const c = credentials(request); if (!c) return null;\n return this.mutate(s => { const session = s.sessions.find(x => x.digest === digest(c.token) && x.transport === c.transport); const administrator = session && this.live(s, session); if (!session || !administrator) return null; session.touched = this.now(); const subject = Object.freeze({ id: administrator.id, provider: PROVIDER, capabilities: Object.freeze([...ALL]), requiresPasswordChange: administrator.temporary }); this.subjects.set(subject, { generation: administrator.generation, digest: session.digest }); return subject; });\n }\n authorize(subject: ManagementSubject, _capability: string): boolean {\n this.alive(); const issued = this.subjects.get(subject); if (!issued || subject.provider !== PROVIDER) return false;\n const s = this.read().value, session = s.sessions.find(x => x.digest === issued.digest), m = session && this.live(s, session);\n return !!m && m.id === subject.id && m.generation === issued.generation;\n }\n private requireCapability(c: ControlApiHandlerContext, capability: string, write = false) { if (!c.subject || !this.authorize(c.subject, capability)) fail('forbidden', 403); if (write) this.checkWrite(c.request); }\n validateWrite(request: Request) { this.checkWrite(request); }\n csrfToken(request: Request): string | undefined { const c = credentials(request); return c?.transport === 'cookie' ? csrf(c.token) : undefined; }\n private checkWrite(request: Request) { const c = credentials(request); if (!c) fail('unauthorized', 401); if (c.transport === 'cookie') { origin(request, this.host.managementOrigin); if (!constant(request.headers.get('x-csrf-token') ?? '', csrf(c.token))) fail('invalid_csrf', 403); } }\n async login(request: Request): Promise<Response> {\n try {\n this.alive(); if (request.method !== 'POST') fail('method_not_allowed', 405);\n const b = await body(request); exact(b, ['username','password','transport']);\n const name = username(b.username); const p = typeof b.password === 'string' ? b.password : '';\n const transport = b.transport ?? 'cookie'; if (transport !== 'cookie' && transport !== 'bearer') fail('invalid_input');\n if (transport === 'cookie') origin(request, this.host.managementOrigin); else if (request.headers.has('origin')) origin(request, this.host.managementOrigin);\n const source = (this.dependencies.trustedSource ?? this.host.trustedSource)?.(request) ?? 'unknown';\n const keys = ['account:' + digest(name), 'source:' + digest(source)]; const now = this.now();\n // Reserve before password work so simultaneous requests cannot bypass throttling.\n this.mutate(s => { s.failures = s.failures.filter(x => x.until > now); if (keys.some(k => s.failures.some(x => x.key === k && x.count >= 10))) fail('login_limited', 429); for (const key of keys) { let f = s.failures.find(x => x.key === key); if (!f) { f = { key, count: 0, until: now + 15 * 60_000 }; s.failures.push(f); } f.count++; } if (s.failures.length > 1024) fail('login_limited', 429); });\n const candidate = this.read().value.administrator; const administrator = candidate?.username === name ? candidate : null;\n const valid = await Bun.password.verify(p, administrator?.passwordHash ?? (this.dummy || await this.hash('dummy-invalid-password')));\n if (!valid || !administrator || administrator.disabled) fail('invalid_credentials', 401);\n const token = randomBytes(32).toString('base64url');\n this.mutate(s => { const m = s.administrator; if (!m || m.id !== administrator.id || m.disabled || m.generation !== administrator.generation) fail('invalid_credentials', 401); s.sessions = s.sessions.filter(x => !!this.live(s, x)); if (s.sessions.length >= 512) fail('session_limit', 429); s.sessions.push({ digest: digest(token), administratorId: m.id, generation: m.generation, created: this.now(), touched: this.now(), transport }); s.failures = s.failures.filter(x => x.key !== keys[0]); const sourceFailure = s.failures.find(x => x.key === keys[1]); if (sourceFailure) sourceFailure.count = Math.max(0, sourceFailure.count - 1); });\n return transport === 'cookie' ? json({ administrator: dto(administrator), csrfToken: csrf(token) }, 200, { 'set-cookie': cookie(request, token, false, this.host.managementOrigin) }) : json({ administrator: dto(administrator), token, expiresIn: ABSOLUTE / 1000 });\n } catch (e) { return safe(e); }\n }\n async logout(request: Request): Promise<Response> {\n try { if (request.method !== 'POST') fail('method_not_allowed', 405); this.checkWrite(request); const c = credentials(request)!; this.mutate(s => { s.sessions = s.sessions.filter(x => x.digest !== digest(c.token)); }); return json({ ok: true }, 200, { 'set-cookie': cookie(request, '', true, this.host.managementOrigin) }); } catch(e) { return safe(e); }\n }\n private async changePassword(id: string, b: Record<string, unknown>, guard: () => void) {\n const p = password(b.password); if (b.passwordConfirmation !== p) fail('password_confirmation'); const m = this.read().value.administrator; if (!m || m.id !== id || typeof b.currentPassword !== 'string' || !await Bun.password.verify(b.currentPassword, m.passwordHash)) fail('invalid_credentials', 401); if (constant(p, b.currentPassword)) fail('password_unchanged'); const hashed = await this.hash(p);\n this.mutate(s => { guard(); const current = s.administrator; if (!current || current.id !== id || current.disabled || current.generation !== m.generation) fail('version_conflict', 409); if (!Number.isSafeInteger(current.generation + 1)) fail('generation_overflow'); current.passwordHash = hashed; current.temporary = false; current.generation++; s.sessions = []; });\n }\n}\nexport function createControl(host: ControlHostContext, dependencies: Dependencies = {}): LocalAccountsControl { return new LocalAccountsControl(host, dependencies); }\nexport const api = [\n { path: '/password', methods: ['POST'], handler: 'changePassword' },\n { path: '/logout', methods: ['POST'], handler: 'logout' },\n { path: '/self', methods: ['GET'], handler: 'self' },\n] as const;\nexport const rpc = [];\nexport const controlApi = api, controlRpc = rpc;\nexport async function recoverIdentity(input: unknown, context: { durableState: PluginDurableState }) {\n const b = object(input); exact(b, ['username', 'newUsername', 'password', 'reason']);\n const name = b.username === undefined ? undefined : username(b.username), p = password(b.password);\n const newName = b.newUsername === undefined ? undefined : username(b.newUsername);\n if (typeof b.reason !== 'string' || b.reason.trim().length < 1 || b.reason.length > 512) fail('invalid_reason');\n const state = context.durableState, record = state.get('accounts');\n const s = record ? validateAccountState(record.value, name) : { schema: 2 as const, administrator: null, sessions: [], failures: [] };\n let administrator = s.administrator;\n if (administrator && name !== undefined && administrator.username !== name) fail('recovery_requires_existing_administrator');\n const passwordHash = await Bun.password.hash(p, { algorithm: 'argon2id', memoryCost: 65536, timeCost: 3 });\n if (!administrator) { administrator = { id: randomUUID(), username: newName ?? name ?? fail('invalid_input'), disabled: false, temporary: false, passwordHash, generation: 1 }; s.administrator = administrator; }\n else { if (!Number.isSafeInteger(administrator.generation + 1)) fail('generation_overflow'); administrator.username = newName ?? administrator.username; administrator.passwordHash = passwordHash; administrator.disabled = false; administrator.temporary = false; administrator.generation++; }\n s.sessions = [];\n s.failures = [];\n state.execute({commandId: randomUUID(), mutations: [\n {key: 'accounts', expectedVersion: record?.version ?? 0, value: s as unknown as DurableJson},\n {key: 'recovery:' + randomUUID(), expectedVersion: 0, value: {administratorId: administrator.id, reason: b.reason, at: Date.now()}},\n ]});\n return dto(administrator);\n}\nexport function readManagementSetup(state: Pick<PluginDurableState,'get'|'list'>) {\n const record = state.get('accounts');\n return {initialized:record ? !!validateAccountState(record.value).administrator : false};\n}\nexport default { createControl, readManagementSetup, offlineRecovery: {kind: 'identity', recover: recoverIdentity} } satisfies ControlPlugin;\n",
|
|
6
|
-
"import type { Database } from 'bun:sqlite';\nimport { createHash } from 'node:crypto';\n\n/** Configuration migration owns this DDL; constructors never modify schema. */\nexport const PLUGIN_DURABLE_STATE_SCHEMA_SQL = `\nCREATE TABLE plugin_durable_records (\n namespace TEXT NOT NULL, key TEXT NOT NULL, version INTEGER NOT NULL CHECK(version > 0),\n value_json TEXT NOT NULL, PRIMARY KEY(namespace, key)\n) STRICT;\nCREATE TABLE plugin_durable_commands (\n namespace TEXT NOT NULL, command_id TEXT NOT NULL, fingerprint TEXT NOT NULL,\n result_json TEXT NOT NULL, PRIMARY KEY(namespace, command_id)\n) STRICT;\n`;\nexport type DurableJson = null | boolean | number | string | DurableJson[] | { [key: string]: DurableJson };\nexport interface DurableRecord { readonly key: string; readonly version: number; readonly value: DurableJson }\nexport interface DurableMutation { key: string; expectedVersion: number; value: DurableJson }\nexport interface DurableCommand { commandId: string; mutations: readonly DurableMutation[] }\nexport interface PluginDurableState {\n get(key: string): DurableRecord | null;\n list(): readonly DurableRecord[];\n execute(command: DurableCommand): readonly DurableRecord[];\n}\nexport class DurableStateConflictError extends Error {\n constructor() { super('Durable state version conflict'); this.name = 'DurableStateConflictError'; }\n}\nconst MAX_BYTES = 1024 * 1024;\nfunction identifier(value: unknown): asserts value is string {\n if (typeof value !== 'string' || !/^[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$/.test(value)) throw new Error('Invalid durable state identifier');\n}\n/** Reject objects with behavior, lossy JSON values and cycles before JSON.stringify. */\nfunction encode(value: unknown): string {\n const ancestors = new Set<object>();\n function check(current: unknown, depth: number): void {\n if (depth > 64) throw new Error('Durable state nesting limit exceeded');\n if (current === null || typeof current === 'string' || typeof current === 'boolean') return;\n if (typeof current === 'number' && Number.isFinite(current)) return;\n if (typeof current !== 'object' || current === null || ancestors.has(current)) throw new Error('Durable state must be pure JSON');\n const array = Array.isArray(current);\n if (!array && Object.getPrototypeOf(current) !== Object.prototype && Object.getPrototypeOf(current) !== null) throw new Error('Durable state must be pure JSON');\n ancestors.add(current);\n const descriptors = Object.getOwnPropertyDescriptors(current);\n if (Reflect.ownKeys(current).some(key => typeof key === 'symbol')) throw new Error('Durable state must be pure JSON');\n if (array) {\n const length = (current as unknown[]).length;\n const indices = Object.keys(descriptors).filter(key => key !== 'length');\n if (indices.length !== length || indices.some((key, index) => key !== String(index))) throw new Error('Durable state must be pure JSON');\n }\n for (const [key, descriptor] of Object.entries(descriptors)) {\n if (array && key === 'length') continue;\n if (!descriptor.enumerable || !('value' in descriptor)) throw new Error('Durable state must be pure JSON');\n check(descriptor.value, depth + 1);\n }\n ancestors.delete(current);\n }\n check(value, 0);\n const json = JSON.stringify(value);\n if (Buffer.byteLength(json) > MAX_BYTES) throw new Error('Durable state size limit exceeded');\n return json;\n}\ntype Row = { key: string; version: number; value_json: string };\nfunction record(row: Row): DurableRecord {\n return Object.freeze({ key: row.key, version: row.version, value: JSON.parse(row.value_json) as DurableJson });\n}\n\n/** Host-only factory. Inject only the returned namespace capability into trusted plugins.\n * Consumers validate their own record schema. expectedVersion=0 requires absence.\n * Null values are retained records, so versions and historical command IDs never reset.\n */\nexport class PluginDurableStateStore {\n constructor(private readonly db: Database) {}\n forNamespace(namespace: string): PluginDurableState {\n identifier(namespace);\n const db = this.db;\n const get = (key: string): DurableRecord | null => {\n identifier(key);\n const row = db.query<Row, [string, string]>('SELECT key,version,value_json FROM plugin_durable_records WHERE namespace = ? AND key = ?').get(namespace, key);\n return row ? record(row) : null;\n };\n return Object.freeze({\n get,\n list: () => Object.freeze(db.query<Row, [string]>('SELECT key,version,value_json FROM plugin_durable_records WHERE namespace = ? ORDER BY key').all(namespace).map(record)),\n execute: (command: DurableCommand): readonly DurableRecord[] => {\n identifier(command.commandId);\n if (!Array.isArray(command.mutations) || command.mutations.length === 0 || command.mutations.length > 256) throw new Error('Invalid durable state command');\n const keys = new Set<string>();\n const mutations = command.mutations.map(mutation => {\n identifier(mutation.key);\n if (keys.has(mutation.key) || !Number.isSafeInteger(mutation.expectedVersion) || mutation.expectedVersion < 0 || mutation.expectedVersion >= Number.MAX_SAFE_INTEGER) throw new Error('Invalid durable state mutation');\n keys.add(mutation.key);\n return { key: mutation.key, expectedVersion: mutation.expectedVersion, json: encode(mutation.value) };\n });\n const commandJson = JSON.stringify(mutations);\n if (Buffer.byteLength(commandJson) > MAX_BYTES) throw new Error('Durable state command size limit exceeded');\n const fingerprint = createHash('sha256').update(commandJson).digest('hex');\n return db.transaction(() => {\n const prior = db.query<{ fingerprint: string; result_json: string }, [string, string]>('SELECT fingerprint,result_json FROM plugin_durable_commands WHERE namespace = ? AND command_id = ?').get(namespace, command.commandId);\n if (prior) {\n if (prior.fingerprint !== fingerprint) throw new Error('Durable state command ID already used');\n return Object.freeze((JSON.parse(prior.result_json) as DurableRecord[]).map(item => Object.freeze(item)));\n }\n const results: DurableRecord[] = [];\n for (const mutation of mutations) {\n const current = get(mutation.key);\n if ((current?.version ?? 0) !== mutation.expectedVersion) throw new DurableStateConflictError();\n const version = mutation.expectedVersion + 1;\n db.query(`INSERT INTO plugin_durable_records(namespace,key,version,value_json) VALUES (?,?,?,?)\n ON CONFLICT(namespace,key) DO UPDATE SET version=excluded.version,value_json=excluded.value_json`).run(namespace, mutation.key, version, mutation.json);\n results.push(record({ key: mutation.key, version, value_json: mutation.json }));\n }\n db.query('INSERT INTO plugin_durable_commands(namespace,command_id,fingerprint,result_json) VALUES (?,?,?,?)').run(namespace, command.commandId, fingerprint, JSON.stringify(results));\n return Object.freeze(results);\n }).immediate();\n },\n });\n }\n}\n"
|
|
5
|
+
"import { createHash, createHmac, randomBytes, randomUUID, timingSafeEqual } from 'node:crypto';\nimport type { ControlHostContext, ControlApiHandlerContext, PluginControl, ControlPlugin } from '../../../packages/core/src/plugin-control/contracts';\nimport type { ManagementProvider, ManagementSubject } from '../../../packages/core/src/plugin-extensions';\nimport { isDurableStateConflictError, type DurableJson, type PluginDurableState } from '../../../packages/core/src/plugin-durable-state';\n\ninterface Administrator { id: string; username: string; disabled: boolean; passwordHash: string; temporary: boolean; generation: number }\ninterface SessionPolicy { idleTimeoutMinutes: number; absoluteTimeoutMinutes: number }\ninterface Session { digest: string; administratorId: string; generation: number; created: number; touched: number; transport: 'cookie' | 'bearer'; policy?: SessionPolicy }\ninterface Failure { key: string; count: number; until: number }\ninterface State { schema: 2; administrator: Administrator | null; sessions: Session[]; failures: Failure[] }\nexport interface Dependencies { now?: () => number; trustedSource?: (request: Request) => string }\nconst PROVIDER = 'local-accounts';\nconst COOKIE = 'bungee_local_session';\nconst DEFAULT_SESSION_POLICY: Readonly<SessionPolicy> = Object.freeze({ idleTimeoutMinutes: 30, absoluteTimeoutMinutes: 480 });\n// Chromium caps persistent cookies at 400 days. Verification renews this browser lease,\n// never the server-side absolute deadline. Browser/user cleanup remains outside our control.\nconst COOKIE_LEASE_SECONDS = 400 * 24 * 60 * 60;\nconst MAX_TIMEOUT_MINUTES = Math.floor(Number.MAX_SAFE_INTEGER / 60_000);\nconst ALL = ['config.read', 'config.write', 'logs.read', 'logs.body', 'keys.read', 'keys.write', 'plugins.read', 'plugins.toggle', 'plugins.code', 'auth.mode', 'self.password', 'self.logout'];\nclass AccountError extends Error { constructor(readonly code: string, readonly status = 400) { super(code); } }\nfunction fail(code: string, status = 400): never { throw new AccountError(code, status); }\nfunction object(v: unknown): Record<string, unknown> { if (!v || typeof v !== 'object' || Array.isArray(v)) fail('invalid_input'); return v as Record<string, unknown>; }\nfunction exact(v: Record<string, unknown>, fields: string[]) { if (Object.keys(v).some(k => !fields.includes(k))) fail('invalid_input'); }\nfunction username(v: unknown): string { if (typeof v !== 'string' || !/^[A-Za-z0-9][A-Za-z0-9_.@-]{0,63}$/.test(v)) fail('invalid_input'); return v.toLowerCase(); }\nfunction password(v: unknown): string { if (typeof v !== 'string' || [...v].length < 6 || [...v].length > 64) fail('invalid_password'); return v; }\nfunction digest(v: string): string { return createHash('sha256').update(v).digest('hex'); }\nfunction csrf(token: string): string { return createHmac('sha256', token).update('local-accounts/csrf/v1').digest('base64url'); }\nfunction constant(a: string, b: string): boolean { const aa = Buffer.from(a), bb = Buffer.from(b); return aa.length === bb.length && timingSafeEqual(aa, bb); }\nfunction dto(m: Administrator) { return { id: m.id, username: m.username, requiresPasswordChange: m.temporary }; }\nfunction json(v: unknown, status = 200, headers: Record<string, string> = {}): Response { return Response.json(v, { status, headers: { 'cache-control': 'no-store', ...headers } }); }\nfunction safe(error: unknown): Response { return error instanceof AccountError ? json({ error: error.code }, error.status) : json({ error: 'provider_unavailable' }, 503); }\nasync function body(request: Request): Promise<Record<string, unknown>> {\n const reader = request.body?.getReader(); if (!reader) fail('invalid_input');\n let size = 0; const chunks: Uint8Array[] = [];\n try { for (;;) { const r = await reader.read(); if (r.done) break; size += r.value.length; if (size > 8192) { await reader.cancel(); fail('body_limit', 413); } chunks.push(r.value); } }\n finally { reader.releaseLock(); }\n try { return object(JSON.parse(Buffer.concat(chunks).toString('utf8'))); } catch (e) { if (e instanceof AccountError) throw e; return fail('invalid_input'); }\n}\nfunction credentials(request: Request): { token: string; transport: Session['transport'] } | null {\n const auth = request.headers.get('authorization');\n if (auth !== null) { const m = /^Bearer ([A-Za-z0-9_-]{43})$/.exec(auth); return m ? { token: m[1]!, transport: 'bearer' } : null; }\n const tokens = (request.headers.get('cookie') ?? '').split(';').map(x => x.trim()).filter(x => x.startsWith(COOKIE + '='));\n if (tokens.length !== 1) return null; const token = tokens[0]!.slice(COOKIE.length + 1);\n return /^[A-Za-z0-9_-]{43}$/.test(token) ? { token, transport: 'cookie' } : null;\n}\nfunction origin(request: Request, expected?: string) { if (request.headers.get('origin') !== (expected ?? new URL(request.url).origin)) fail('invalid_origin', 403); }\nfunction cookie(request: Request, token: string, maxAge: number, managementOrigin?: string) { return `${COOKIE}=${token}; Path=/; HttpOnly; SameSite=Strict; Max-Age=${maxAge}${new URL(managementOrigin ?? request.url).protocol === 'https:' ? '; Secure' : ''}`; }\n\nfunction validateSessionPolicy(value: unknown, code = 'invalid_session_policy', status = 400): SessionPolicy {\n if (!value || typeof value !== 'object' || Array.isArray(value)) fail(code, status);\n const p = value as SessionPolicy;\n if (Object.keys(p).some(key => !['idleTimeoutMinutes', 'absoluteTimeoutMinutes'].includes(key))\n || ![p.idleTimeoutMinutes, p.absoluteTimeoutMinutes].every(n => Number.isSafeInteger(n) && n >= 0 && n <= MAX_TIMEOUT_MINUTES)) fail(code, status);\n return { idleTimeoutMinutes: p.idleTimeoutMinutes, absoluteTimeoutMinutes: p.absoluteTimeoutMinutes };\n}\n\nfunction validateAdministrator(m: unknown): asserts m is Administrator {\n const a = m as Administrator;\n if (!a || typeof a.id !== 'string' || !a.id || typeof a.username !== 'string' || !/^[a-z0-9][a-z0-9_.@-]{0,63}$/.test(a.username) || typeof a.disabled !== 'boolean' || typeof a.temporary !== 'boolean' || typeof a.passwordHash !== 'string' || !a.passwordHash.startsWith('$argon2id$') || !Number.isSafeInteger(a.generation) || a.generation < 1) fail('corrupt_state', 503);\n}\n/** Migration never promotes a former admin/viewer. Ambiguous owners require offline selection. */\nfunction validateAccountState(value: unknown, recoveryUsername?: string): State {\n if (!value || typeof value !== 'object' || Array.isArray(value)) fail('corrupt_state', 503);\n const raw = value as Record<string, unknown>;\n if (raw.schema === 1) {\n if (!Array.isArray(raw.members) || !Array.isArray(raw.sessions) || !Array.isArray(raw.failures)) fail('corrupt_state', 503);\n const ids = new Set<string>(), names = new Set<string>();\n for (const member of raw.members) {\n validateAdministrator(member);\n const legacy = member as Administrator & {role: string};\n if (!['owner', 'admin', 'viewer'].includes(legacy.role) || ids.has(member.id) || names.has(member.username)) fail('corrupt_state', 503);\n ids.add(member.id); names.add(member.username);\n }\n const candidates = raw.members.filter(m => m.role === 'owner' && (recoveryUsername ? m.username === recoveryUsername : !m.disabled));\n if (raw.members.length && candidates.length !== 1) fail(recoveryUsername ? 'recovery_requires_existing_administrator' : 'administrator_migration_required', 503);\n const chosen = candidates[0];\n const administrator = chosen ? { id: chosen.id, username: chosen.username, disabled: chosen.disabled, temporary: chosen.temporary, passwordHash: chosen.passwordHash, generation: chosen.generation } : null;\n return {schema: 2, administrator, sessions: [], failures: []};\n }\n const s = raw as unknown as State;\n if (s.schema !== 2 || !Array.isArray(s.sessions) || !Array.isArray(s.failures)) fail('corrupt_state', 503);\n if (s.administrator !== null) validateAdministrator(s.administrator);\n for (const x of s.sessions) if (!x || !/^[a-f0-9]{64}$/.test(x.digest) || x.administratorId !== s.administrator?.id || !Number.isSafeInteger(x.generation) || x.generation < 1 || !Number.isFinite(x.created) || !Number.isFinite(x.touched) || !['cookie','bearer'].includes(x.transport)) fail('corrupt_state', 503);\n for (const x of s.sessions) if (x.policy !== undefined) validateSessionPolicy(x.policy, 'corrupt_state', 503);\n for (const x of s.failures) if (!x || typeof x.key !== 'string' || !Number.isSafeInteger(x.count) || x.count < 0 || !Number.isFinite(x.until)) fail('corrupt_state', 503);\n return s;\n}\n\nexport class LocalAccountsControl implements PluginControl, ManagementProvider {\n readonly management = this;\n readonly rpc = [];\n readonly api;\n private readonly state: PluginDurableState;\n private readonly now: () => number;\n private readonly subjects = new WeakMap<ManagementSubject, { generation: number; digest: string }>();\n private dummy = '';\n private disposed = false;\n constructor(private readonly host: ControlHostContext, private readonly dependencies: Dependencies = {}) {\n if (!host.durableState) fail('durable_state_required', 503);\n this.state = host.durableState;\n this.now = dependencies.now ?? Date.now;\n const invoke = (fn: (c: ControlApiHandlerContext) => Promise<Response> | Response) => async (c: ControlApiHandlerContext) => {\n try { this.alive(); if (c.requestSignal.aborted) fail('cancelled'); return await fn(c); } catch (e) { return safe(e); }\n };\n this.api = [\n { path: '/password', methods: ['POST'], handler: 'changePassword', invoke: invoke(async c => { this.requireCapability(c, 'self.password', true); const b = await body(c.request); exact(b, ['currentPassword', 'password', 'passwordConfirmation']); await this.changePassword(c.subject!.id, b, () => this.requireCapability(c, 'self.password', true)); return json({ ok: true }, 200, { 'set-cookie': cookie(c.request, '', 0, this.host.managementOrigin) }); }) },\n { path: '/logout', methods: ['POST'], handler: 'logout', invoke: invoke(c => { this.requireCapability(c, 'self.logout', true); return this.logout(c.request); }) },\n { path: '/self', methods: ['GET'], handler: 'self', invoke: invoke(c => { this.requireCapability(c, 'self.password'); const m = this.read().value.administrator!; const creds = credentials(c.request); return json({ administrator: dto(m), ...(creds?.transport === 'cookie' ? { csrfToken: csrf(creds.token) } : {}) }); }) },\n { path: '/session-policy', methods: ['GET', 'PUT'], handler: 'sessionPolicy', invoke: invoke(async c => {\n this.requireCapability(c, 'config.write', c.request.method === 'PUT');\n if (c.request.method === 'GET') return json(this.readSessionPolicy());\n const b = await body(c.request); exact(b, ['version', 'policy']);\n if (!Number.isSafeInteger(b.version) || (b.version as number) < 0) fail('invalid_session_policy');\n const policy = validateSessionPolicy(b.policy);\n this.requireCapability(c, 'config.write', true);\n try { this.state.execute({commandId: randomUUID(), mutations: [{key: 'session-policy', expectedVersion: b.version as number, value: policy as unknown as DurableJson}]}); }\n catch (e) { if (isDurableStateConflictError(e)) fail('version_conflict', 409); throw e; }\n return json(this.readSessionPolicy());\n }) },\n ];\n }\n private alive() { if (this.disposed || this.host.signal.aborted) fail('provider_unavailable', 503); }\n private read(): { version: number; value: State } {\n this.alive(); const record = this.state.get('accounts');\n if (!record) return { version: 0, value: { schema: 2, administrator: null, sessions: [], failures: [] } };\n const s = validateAccountState(record.value);\n return { version: record.version, value: s };\n }\n private mutate<T>(fn: (s: State) => T): T {\n for (let i = 0; i < 8; i++) { const {version, value} = this.read(); const result = fn(value);\n try { this.state.execute({ commandId: randomUUID(), mutations: [{ key: 'accounts', expectedVersion: version, value: value as unknown as DurableJson }] }); return result; }\n catch (e) { if (!isDurableStateConflictError(e)) throw e; }\n } return fail('version_conflict', 409);\n }\n private readSessionPolicy(): {version: number; policy: SessionPolicy} {\n this.alive(); const record = this.state.get('session-policy');\n return {version: record?.version ?? 0, policy: record ? validateSessionPolicy(record.value, 'corrupt_state', 503) : {...DEFAULT_SESSION_POLICY}};\n }\n async start() { const record = this.state.get('accounts'); this.read(); this.readSessionPolicy(); if (record && (record.value as any).schema === 1) this.mutate(() => undefined); this.dummy = await this.hash(randomBytes(32).toString('base64url')); }\n dispose() { this.disposed = true; }\n private hash(p: string) { return Bun.password.hash(p, { algorithm: 'argon2id', memoryCost: 65536, timeCost: 3 }); }\n hasIdentity() { const a = this.read().value.administrator; return !!a && !a.disabled; }\n revokeSessions() { this.mutate(s => { s.sessions = []; }); }\n async bootstrap(input: unknown) {\n const b = object(input); exact(b, ['username', 'password', 'passwordConfirmation']); const name = username(b.username), p = password(b.password);\n if (b.passwordConfirmation !== p) fail('password_confirmation');\n const prior = this.read().value.administrator;\n if (prior) {\n if (prior.username !== name || prior.disabled || !await Bun.password.verify(p, prior.passwordHash)) fail('invalid_credentials', 401);\n const latest = this.read().value.administrator;\n if (!latest || latest.generation !== prior.generation || latest.disabled) fail('invalid_credentials', 401);\n return;\n }\n const hashed = await this.hash(p);\n this.mutate(s => { if (s.administrator) fail('bootstrap_conflict', 409); s.administrator = { id: randomUUID(), username: name, disabled: false, temporary: false, passwordHash: hashed, generation: 1 }; });\n }\n private live(s: State, session: Session): Administrator | undefined {\n const now = this.now(), policy = session.policy ?? DEFAULT_SESSION_POLICY;\n if (now < session.touched || now < session.created\n || (policy.idleTimeoutMinutes > 0 && now - session.touched >= policy.idleTimeoutMinutes * 60_000)\n || (policy.absoluteTimeoutMinutes > 0 && now - session.created >= policy.absoluteTimeoutMinutes * 60_000)) return;\n const m = s.administrator; return m && m.id === session.administratorId && !m.disabled && m.generation === session.generation ? m : undefined;\n }\n private cookieAge(policy: SessionPolicy, elapsedMs = 0): number {\n return policy.absoluteTimeoutMinutes === 0 ? COOKIE_LEASE_SECONDS\n : Math.max(0, Math.min(COOKIE_LEASE_SECONDS, Math.floor((policy.absoluteTimeoutMinutes * 60_000 - elapsedMs) / 1000)));\n }\n sessionCookie(request: Request): string | undefined {\n this.alive(); const creds = credentials(request); if (creds?.transport !== 'cookie') return;\n const s = this.read().value, session = s.sessions.find(x => x.digest === digest(creds.token) && x.transport === 'cookie');\n if (!session || !this.live(s, session)) return;\n return cookie(request, creds.token, this.cookieAge(session.policy ?? DEFAULT_SESSION_POLICY, this.now() - session.created), this.host.managementOrigin);\n }\n async authenticate(request: Request): Promise<ManagementSubject | null> {\n this.alive(); const c = credentials(request); if (!c) return null;\n return this.mutate(s => { const session = s.sessions.find(x => x.digest === digest(c.token) && x.transport === c.transport); const administrator = session && this.live(s, session); if (!session || !administrator) return null; session.touched = this.now(); const subject = Object.freeze({ id: administrator.id, provider: PROVIDER, capabilities: Object.freeze([...ALL]), requiresPasswordChange: administrator.temporary }); this.subjects.set(subject, { generation: administrator.generation, digest: session.digest }); return subject; });\n }\n authorize(subject: ManagementSubject, _capability: string): boolean {\n this.alive(); const issued = this.subjects.get(subject); if (!issued || subject.provider !== PROVIDER) return false;\n const s = this.read().value, session = s.sessions.find(x => x.digest === issued.digest), m = session && this.live(s, session);\n return !!m && m.id === subject.id && m.generation === issued.generation;\n }\n private requireCapability(c: ControlApiHandlerContext, capability: string, write = false) { if (!c.subject || !this.authorize(c.subject, capability)) fail('forbidden', 403); if (write) this.checkWrite(c.request); }\n validateWrite(request: Request) { this.checkWrite(request); }\n csrfToken(request: Request): string | undefined { const c = credentials(request); return c?.transport === 'cookie' ? csrf(c.token) : undefined; }\n private checkWrite(request: Request) { const c = credentials(request); if (!c) fail('unauthorized', 401); if (c.transport === 'cookie') { origin(request, this.host.managementOrigin); if (!constant(request.headers.get('x-csrf-token') ?? '', csrf(c.token))) fail('invalid_csrf', 403); } }\n async login(request: Request): Promise<Response> {\n try {\n this.alive(); if (request.method !== 'POST') fail('method_not_allowed', 405);\n const b = await body(request); exact(b, ['username','password','transport']);\n const name = username(b.username); const p = typeof b.password === 'string' ? b.password : '';\n const transport = b.transport ?? 'cookie'; if (transport !== 'cookie' && transport !== 'bearer') fail('invalid_input');\n if (transport === 'cookie') origin(request, this.host.managementOrigin); else if (request.headers.has('origin')) origin(request, this.host.managementOrigin);\n const source = (this.dependencies.trustedSource ?? this.host.trustedSource)?.(request) ?? 'unknown';\n const keys = ['account:' + digest(name), 'source:' + digest(source)]; const now = this.now();\n // Reserve before password work so simultaneous requests cannot bypass throttling.\n this.mutate(s => { s.failures = s.failures.filter(x => x.until > now); if (keys.some(k => s.failures.some(x => x.key === k && x.count >= 10))) fail('login_limited', 429); for (const key of keys) { let f = s.failures.find(x => x.key === key); if (!f) { f = { key, count: 0, until: now + 15 * 60_000 }; s.failures.push(f); } f.count++; } if (s.failures.length > 1024) fail('login_limited', 429); });\n const candidate = this.read().value.administrator; const administrator = candidate?.username === name ? candidate : null;\n const valid = await Bun.password.verify(p, administrator?.passwordHash ?? (this.dummy || await this.hash('dummy-invalid-password')));\n if (!valid || !administrator || administrator.disabled) fail('invalid_credentials', 401);\n const token = randomBytes(32).toString('base64url');\n const policy = this.readSessionPolicy().policy;\n const created = this.now();\n this.mutate(s => { const m = s.administrator; if (!m || m.id !== administrator.id || m.disabled || m.generation !== administrator.generation) fail('invalid_credentials', 401); s.sessions = s.sessions.filter(x => !!this.live(s, x)); if (s.sessions.length >= 512) fail('session_limit', 429); s.sessions.push({ digest: digest(token), administratorId: m.id, generation: m.generation, created, touched: created, transport, policy }); s.failures = s.failures.filter(x => x.key !== keys[0]); const sourceFailure = s.failures.find(x => x.key === keys[1]); if (sourceFailure) sourceFailure.count = Math.max(0, sourceFailure.count - 1); });\n return transport === 'cookie' ? json({ administrator: dto(administrator), csrfToken: csrf(token) }, 200, { 'set-cookie': cookie(request, token, this.cookieAge(policy, this.now() - created), this.host.managementOrigin) }) : json({ administrator: dto(administrator), token, expiresIn: policy.absoluteTimeoutMinutes === 0 ? null : policy.absoluteTimeoutMinutes * 60 });\n } catch (e) { return safe(e); }\n }\n async logout(request: Request): Promise<Response> {\n try { if (request.method !== 'POST') fail('method_not_allowed', 405); this.checkWrite(request); const c = credentials(request)!; this.mutate(s => { s.sessions = s.sessions.filter(x => x.digest !== digest(c.token)); }); return json({ ok: true }, 200, { 'set-cookie': cookie(request, '', 0, this.host.managementOrigin) }); } catch(e) { return safe(e); }\n }\n private async changePassword(id: string, b: Record<string, unknown>, guard: () => void) {\n const p = password(b.password); if (b.passwordConfirmation !== p) fail('password_confirmation'); const m = this.read().value.administrator; if (!m || m.id !== id || typeof b.currentPassword !== 'string' || !await Bun.password.verify(b.currentPassword, m.passwordHash)) fail('invalid_credentials', 401); if (constant(p, b.currentPassword)) fail('password_unchanged'); const hashed = await this.hash(p);\n this.mutate(s => { guard(); const current = s.administrator; if (!current || current.id !== id || current.disabled || current.generation !== m.generation) fail('version_conflict', 409); if (!Number.isSafeInteger(current.generation + 1)) fail('generation_overflow'); current.passwordHash = hashed; current.temporary = false; current.generation++; s.sessions = []; });\n }\n}\nexport function createControl(host: ControlHostContext, dependencies: Dependencies = {}): LocalAccountsControl { return new LocalAccountsControl(host, dependencies); }\nexport const api = [\n { path: '/password', methods: ['POST'], handler: 'changePassword' },\n { path: '/logout', methods: ['POST'], handler: 'logout' },\n { path: '/self', methods: ['GET'], handler: 'self' },\n { path: '/session-policy', methods: ['GET', 'PUT'], handler: 'sessionPolicy' },\n] as const;\nexport const rpc = [];\nexport const controlApi = api, controlRpc = rpc;\nexport async function recoverIdentity(input: unknown, context: { durableState: PluginDurableState }) {\n const b = object(input); exact(b, ['username', 'newUsername', 'password', 'reason']);\n const name = b.username === undefined ? undefined : username(b.username), p = password(b.password);\n const newName = b.newUsername === undefined ? undefined : username(b.newUsername);\n if (typeof b.reason !== 'string' || b.reason.trim().length < 1 || b.reason.length > 512) fail('invalid_reason');\n const state = context.durableState, record = state.get('accounts');\n const s = record ? validateAccountState(record.value, name) : { schema: 2 as const, administrator: null, sessions: [], failures: [] };\n let administrator = s.administrator;\n if (administrator && name !== undefined && administrator.username !== name) fail('recovery_requires_existing_administrator');\n const passwordHash = await Bun.password.hash(p, { algorithm: 'argon2id', memoryCost: 65536, timeCost: 3 });\n if (!administrator) { administrator = { id: randomUUID(), username: newName ?? name ?? fail('invalid_input'), disabled: false, temporary: false, passwordHash, generation: 1 }; s.administrator = administrator; }\n else { if (!Number.isSafeInteger(administrator.generation + 1)) fail('generation_overflow'); administrator.username = newName ?? administrator.username; administrator.passwordHash = passwordHash; administrator.disabled = false; administrator.temporary = false; administrator.generation++; }\n s.sessions = [];\n s.failures = [];\n state.execute({commandId: randomUUID(), mutations: [\n {key: 'accounts', expectedVersion: record?.version ?? 0, value: s as unknown as DurableJson},\n {key: 'recovery:' + randomUUID(), expectedVersion: 0, value: {administratorId: administrator.id, reason: b.reason, at: Date.now()}},\n ]});\n return dto(administrator);\n}\nexport function readManagementSetup(state: Pick<PluginDurableState,'get'|'list'>) {\n const record = state.get('accounts');\n return {initialized:record ? !!validateAccountState(record.value).administrator : false};\n}\nexport default { createControl, readManagementSetup, offlineRecovery: {kind: 'identity', recover: recoverIdentity} } satisfies ControlPlugin;\n",
|
|
6
|
+
"import type { Database } from 'bun:sqlite';\nimport { createHash } from 'node:crypto';\n\n/** Configuration migration owns this DDL; constructors never modify schema. */\nexport const PLUGIN_DURABLE_STATE_SCHEMA_SQL = `\nCREATE TABLE plugin_durable_records (\n namespace TEXT NOT NULL, key TEXT NOT NULL, version INTEGER NOT NULL CHECK(version > 0),\n value_json TEXT NOT NULL, PRIMARY KEY(namespace, key)\n) STRICT;\nCREATE TABLE plugin_durable_commands (\n namespace TEXT NOT NULL, command_id TEXT NOT NULL, fingerprint TEXT NOT NULL,\n result_json TEXT NOT NULL, PRIMARY KEY(namespace, command_id)\n) STRICT;\n`;\nexport type DurableJson = null | boolean | number | string | DurableJson[] | { [key: string]: DurableJson };\nexport interface DurableRecord { readonly key: string; readonly version: number; readonly value: DurableJson }\nexport interface DurableMutation { key: string; expectedVersion: number; value: DurableJson }\nexport interface DurableCommand { commandId: string; mutations: readonly DurableMutation[] }\n/**\n * Host-only execution options. `extend` runs inside the SAME immediate\n * transaction, after the record mutations and the command row: it is the\n * outbox seam that commits a communication record atomically with the business\n * state. A throw from `extend` rolls back the whole command, and an idempotent\n * replay never runs it again (the first committed run already wrote its rows).\n */\nexport interface DurableCommandOptions { readonly extend?: () => void }\nexport interface PluginDurableState {\n get(key: string): DurableRecord | null;\n list(): readonly DurableRecord[];\n execute(command: DurableCommand, options?: DurableCommandOptions): readonly DurableRecord[];\n}\nexport class DurableStateConflictError extends Error {\n readonly code = 'durable_state_conflict';\n constructor() { super('Durable state version conflict'); this.name = 'DurableStateConflictError'; }\n}\n/** Plugins load as independent bundles, so the host's error has a different constructor. */\nexport function isDurableStateConflictError(error: unknown): error is DurableStateConflictError {\n return error instanceof Error && 'code' in error && error.code === 'durable_state_conflict';\n}\nconst MAX_BYTES = 1024 * 1024;\nfunction identifier(value: unknown): asserts value is string {\n if (typeof value !== 'string' || !/^[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$/.test(value)) throw new Error('Invalid durable state identifier');\n}\n/** Reject objects with behavior, lossy JSON values and cycles before JSON.stringify. */\nfunction encode(value: unknown): string {\n const ancestors = new Set<object>();\n function check(current: unknown, depth: number): void {\n if (depth > 64) throw new Error('Durable state nesting limit exceeded');\n if (current === null || typeof current === 'string' || typeof current === 'boolean') return;\n if (typeof current === 'number' && Number.isFinite(current)) return;\n if (typeof current !== 'object' || current === null || ancestors.has(current)) throw new Error('Durable state must be pure JSON');\n const array = Array.isArray(current);\n if (!array && Object.getPrototypeOf(current) !== Object.prototype && Object.getPrototypeOf(current) !== null) throw new Error('Durable state must be pure JSON');\n ancestors.add(current);\n const descriptors = Object.getOwnPropertyDescriptors(current);\n if (Reflect.ownKeys(current).some(key => typeof key === 'symbol')) throw new Error('Durable state must be pure JSON');\n if (array) {\n const length = (current as unknown[]).length;\n const indices = Object.keys(descriptors).filter(key => key !== 'length');\n if (indices.length !== length || indices.some((key, index) => key !== String(index))) throw new Error('Durable state must be pure JSON');\n }\n for (const [key, descriptor] of Object.entries(descriptors)) {\n if (array && key === 'length') continue;\n if (!descriptor.enumerable || !('value' in descriptor)) throw new Error('Durable state must be pure JSON');\n check(descriptor.value, depth + 1);\n }\n ancestors.delete(current);\n }\n check(value, 0);\n const json = JSON.stringify(value);\n if (Buffer.byteLength(json) > MAX_BYTES) throw new Error('Durable state size limit exceeded');\n return json;\n}\ntype Row = { key: string; version: number; value_json: string };\nfunction record(row: Row): DurableRecord {\n return Object.freeze({ key: row.key, version: row.version, value: JSON.parse(row.value_json) as DurableJson });\n}\n\n/** Host-only factory. Inject only the returned namespace capability into trusted plugins.\n * Consumers validate their own record schema. expectedVersion=0 requires absence.\n * Null values are retained records, so versions and historical command IDs never reset.\n */\nexport class PluginDurableStateStore {\n constructor(private readonly db: Database) {}\n /**\n * Host-only: the shared database this store's records live in, so a host-owned\n * durable journal can run its own atomic planner/reader against exactly the\n * same `plugin_durable_records` rows the plugin sees. Never exposed through\n * `PluginServices` and never handed to a plugin.\n */\n get database(): Database { return this.db; }\n forNamespace(namespace: string): PluginDurableState {\n identifier(namespace);\n const db = this.db;\n const get = (key: string): DurableRecord | null => {\n identifier(key);\n const row = db.query<Row, [string, string]>('SELECT key,version,value_json FROM plugin_durable_records WHERE namespace = ? AND key = ?').get(namespace, key);\n return row ? record(row) : null;\n };\n return Object.freeze({\n get,\n list: () => Object.freeze(db.query<Row, [string]>('SELECT key,version,value_json FROM plugin_durable_records WHERE namespace = ? ORDER BY key').all(namespace).map(record)),\n execute: (command: DurableCommand, options?: DurableCommandOptions): readonly DurableRecord[] => {\n identifier(command.commandId);\n if (!Array.isArray(command.mutations) || command.mutations.length === 0 || command.mutations.length > 256) throw new Error('Invalid durable state command');\n if (options !== undefined && options !== null && typeof options.extend !== 'undefined' && typeof options.extend !== 'function') throw new Error('Invalid durable state options');\n const keys = new Set<string>();\n const mutations = command.mutations.map(mutation => {\n identifier(mutation.key);\n if (keys.has(mutation.key) || !Number.isSafeInteger(mutation.expectedVersion) || mutation.expectedVersion < 0 || mutation.expectedVersion >= Number.MAX_SAFE_INTEGER) throw new Error('Invalid durable state mutation');\n keys.add(mutation.key);\n return { key: mutation.key, expectedVersion: mutation.expectedVersion, json: encode(mutation.value) };\n });\n const commandJson = JSON.stringify(mutations);\n if (Buffer.byteLength(commandJson) > MAX_BYTES) throw new Error('Durable state command size limit exceeded');\n const fingerprint = createHash('sha256').update(commandJson).digest('hex');\n return db.transaction(() => {\n const prior = db.query<{ fingerprint: string; result_json: string }, [string, string]>('SELECT fingerprint,result_json FROM plugin_durable_commands WHERE namespace = ? AND command_id = ?').get(namespace, command.commandId);\n if (prior) {\n if (prior.fingerprint !== fingerprint) throw new Error('Durable state command ID already used');\n return Object.freeze((JSON.parse(prior.result_json) as DurableRecord[]).map(item => Object.freeze(item)));\n }\n const results: DurableRecord[] = [];\n for (const mutation of mutations) {\n const current = get(mutation.key);\n if ((current?.version ?? 0) !== mutation.expectedVersion) throw new DurableStateConflictError();\n const version = mutation.expectedVersion + 1;\n db.query(`INSERT INTO plugin_durable_records(namespace,key,version,value_json) VALUES (?,?,?,?)\n ON CONFLICT(namespace,key) DO UPDATE SET version=excluded.version,value_json=excluded.value_json`).run(namespace, mutation.key, version, mutation.json);\n results.push(record({ key: mutation.key, version, value_json: mutation.json }));\n }\n db.query('INSERT INTO plugin_durable_commands(namespace,command_id,fingerprint,result_json) VALUES (?,?,?,?)').run(namespace, command.commandId, fingerprint, JSON.stringify(results));\n // Outbox seam: same transaction, same connection, first execution only.\n options?.extend?.();\n return Object.freeze(results);\n }).immediate();\n },\n });\n }\n}\n"
|
|
7
7
|
],
|
|
8
|
-
"mappings": "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",
|
|
9
|
-
"debugId": "
|
|
8
|
+
"mappings": "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",
|
|
9
|
+
"debugId": "9FABE2F2EC4EEDD964756E2164756E21",
|
|
10
10
|
"names": []
|
|
11
11
|
}
|