@rei-standard/amsg-server 3.1.0-next.0 → 3.1.0-next.1
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/adapters/d1.d.ts +5 -0
- package/dist/{chunk-3NIYNYZY.cjs → chunk-D4SKSCIY.cjs} +260 -77
- package/dist/{chunk-6TCZEACV.mjs → chunk-EIM3PKFY.mjs} +240 -57
- package/dist/cloudflare.cjs +2 -2
- package/dist/cloudflare.mjs +1 -1
- package/dist/index.cjs +25 -25
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
package/dist/adapters/d1.d.ts
CHANGED
|
@@ -57,6 +57,7 @@ export class D1Adapter {
|
|
|
57
57
|
};
|
|
58
58
|
_cloudBatch(statements: any, userId: any, guards?: any[], metadata?: Map<any, any>): Promise<any[]>;
|
|
59
59
|
getCloudResourceMetadata(userId: any, resourceKey: any): Promise<any>;
|
|
60
|
+
getOutboxPayload(userId: any, messageId: any): Promise<any>;
|
|
60
61
|
listCloudResourceRows(userId: any): Promise<{
|
|
61
62
|
gaps: any[];
|
|
62
63
|
}>;
|
|
@@ -148,6 +149,10 @@ export class D1Adapter {
|
|
|
148
149
|
updatedAt: any;
|
|
149
150
|
}>;
|
|
150
151
|
isCloudOwnerGuardValid(userId: any, guard: any): Promise<boolean>;
|
|
152
|
+
_rowSnapshotMatch(spec: any, row: any): {
|
|
153
|
+
predicate: string;
|
|
154
|
+
values: any[];
|
|
155
|
+
};
|
|
151
156
|
/** Delete only the exact physical snapshot; no untrusted SQL identifiers. */
|
|
152
157
|
deleteCloudResourceRows(userId: any, locators: any, { operationId, leaseToken }?: {}): Promise<{
|
|
153
158
|
deleted: number;
|
|
@@ -147,14 +147,33 @@ var _amsgshared = require('@rei-standard/amsg-shared');
|
|
|
147
147
|
// src/server/lib/encryption.js
|
|
148
148
|
var base64ToBytes = _amsgshared.base64UrlToBytes;
|
|
149
149
|
var TAG_LENGTH_BYTES = 16;
|
|
150
|
+
var AES_KEY_CACHE_MAX = 128;
|
|
151
|
+
var aesKeyCache = /* @__PURE__ */ new Map();
|
|
150
152
|
function importAesKey(hexKey, usage) {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
153
|
+
const cacheKey = `${usage}:${hexKey}`;
|
|
154
|
+
const cached = aesKeyCache.get(cacheKey);
|
|
155
|
+
if (cached) return cached;
|
|
156
|
+
let promise;
|
|
157
|
+
try {
|
|
158
|
+
promise = globalThis.crypto.subtle.importKey(
|
|
159
|
+
"raw",
|
|
160
|
+
_amsgshared.hexToBytes.call(void 0, hexKey),
|
|
161
|
+
{ name: "AES-GCM" },
|
|
162
|
+
false,
|
|
163
|
+
[usage]
|
|
164
|
+
).catch((err6) => {
|
|
165
|
+
aesKeyCache.delete(cacheKey);
|
|
166
|
+
throw err6;
|
|
167
|
+
});
|
|
168
|
+
} catch (err6) {
|
|
169
|
+
return Promise.reject(err6);
|
|
170
|
+
}
|
|
171
|
+
if (aesKeyCache.size >= AES_KEY_CACHE_MAX) {
|
|
172
|
+
const oldest = aesKeyCache.keys().next().value;
|
|
173
|
+
if (oldest !== void 0) aesKeyCache.delete(oldest);
|
|
174
|
+
}
|
|
175
|
+
aesKeyCache.set(cacheKey, promise);
|
|
176
|
+
return promise;
|
|
158
177
|
}
|
|
159
178
|
async function aesGcmSeal(hexKey, iv, plaintextBytes) {
|
|
160
179
|
const key = await importAesKey(hexKey, "encrypt");
|
|
@@ -5451,12 +5470,37 @@ var D1Adapter = class {
|
|
|
5451
5470
|
const row = await this._db.prepare("SELECT encrypted_value FROM cloud_resource_metadata WHERE user_id=? AND resource_key=?").bind(userId, resourceKey).first();
|
|
5452
5471
|
return _nullishCoalesce(_optionalChain([row, 'optionalAccess', _52 => _52.encrypted_value]), () => ( null));
|
|
5453
5472
|
}
|
|
5473
|
+
async getOutboxPayload(userId, messageId) {
|
|
5474
|
+
const row = await this._db.prepare(
|
|
5475
|
+
"SELECT payload FROM message_outbox WHERE user_id = ? AND message_id = ? LIMIT 1"
|
|
5476
|
+
).bind(userId, messageId).first();
|
|
5477
|
+
return _nullishCoalesce(_optionalChain([row, 'optionalAccess', _53 => _53.payload]), () => ( null));
|
|
5478
|
+
}
|
|
5454
5479
|
async listCloudResourceRows(userId) {
|
|
5455
|
-
const
|
|
5480
|
+
const queries = {
|
|
5481
|
+
task: "SELECT * FROM scheduled_messages WHERE user_id = ?",
|
|
5482
|
+
state: `SELECT user_id, namespace, key,
|
|
5483
|
+
CASE WHEN LENGTH(value) <= 1024 THEN value ELSE NULL END AS value,
|
|
5484
|
+
LENGTH(CAST(value AS BLOB)) AS byte_size,
|
|
5485
|
+
substr(value, 1, 128) AS value_prefix,
|
|
5486
|
+
CASE WHEN LENGTH(value) > 128 THEN substr(value, -64) ELSE '' END AS value_suffix,
|
|
5487
|
+
updated_at
|
|
5488
|
+
FROM client_state WHERE user_id = ?`,
|
|
5489
|
+
credential: "SELECT * FROM llm_credentials WHERE user_id = ?",
|
|
5490
|
+
outbox: `SELECT id, user_id, message_id, task_uuid, session_id, message_index, total_messages,
|
|
5491
|
+
CASE WHEN LENGTH(payload) <= 1024 THEN payload ELSE NULL END AS payload,
|
|
5492
|
+
LENGTH(CAST(payload AS BLOB)) AS byte_size,
|
|
5493
|
+
substr(payload, 1, 128) AS payload_prefix,
|
|
5494
|
+
CASE WHEN LENGTH(payload) > 128 THEN substr(payload, -64) ELSE '' END AS payload_suffix,
|
|
5495
|
+
created_at, delivered_at, acked_at
|
|
5496
|
+
FROM message_outbox WHERE user_id = ?`,
|
|
5497
|
+
subscription: "SELECT * FROM push_subscriptions WHERE user_id = ?",
|
|
5498
|
+
metadata: "SELECT * FROM cloud_resource_metadata WHERE user_id = ?"
|
|
5499
|
+
};
|
|
5456
5500
|
const result = { gaps: [] };
|
|
5457
|
-
await Promise.all(Object.entries(
|
|
5501
|
+
await Promise.all(Object.entries(queries).map(async ([type, sql]) => {
|
|
5458
5502
|
try {
|
|
5459
|
-
const response = await this._db.prepare(
|
|
5503
|
+
const response = await this._db.prepare(sql).bind(userId).all();
|
|
5460
5504
|
result[type] = response.results || [];
|
|
5461
5505
|
} catch (e4) {
|
|
5462
5506
|
result[type] = [];
|
|
@@ -5521,7 +5565,10 @@ var D1Adapter = class {
|
|
|
5521
5565
|
if (idempotencyKey) {
|
|
5522
5566
|
return this._cloudRecord(await this._db.prepare(`SELECT * FROM cloud_data_records WHERE user_id=? AND kind=? AND idempotency_key=?`).bind(userId, kind, idempotencyKey).first());
|
|
5523
5567
|
}
|
|
5524
|
-
|
|
5568
|
+
if (createOnly) {
|
|
5569
|
+
return this.getCloudDataRecord(userId, kind, id);
|
|
5570
|
+
}
|
|
5571
|
+
return { id, userId, kind, data, updatedAt: now };
|
|
5525
5572
|
}
|
|
5526
5573
|
async getCloudDataRecord(userId, kind, id) {
|
|
5527
5574
|
return this._cloudRecord(await this._db.prepare("SELECT * FROM cloud_data_records WHERE user_id=? AND kind=? AND id=?").bind(userId, kind, id).first());
|
|
@@ -5654,7 +5701,7 @@ var D1Adapter = class {
|
|
|
5654
5701
|
const name = "metadata-sidecars-v1";
|
|
5655
5702
|
const batch = await this.getCloudMaintenanceBatch(name, "cloud_resource_metadata", limit);
|
|
5656
5703
|
if (batch.completed) return;
|
|
5657
|
-
const cursor = _nullishCoalesce(_optionalChain([batch, 'access',
|
|
5704
|
+
const cursor = _nullishCoalesce(_optionalChain([batch, 'access', _54 => _54.rows, 'access', _55 => _55.at, 'call', _56 => _56(-1), 'optionalAccess', _57 => _57.maintenance_rowid]), () => ( batch.upperBound));
|
|
5658
5705
|
if (batch.rows.length) await this.cleanupCloudResourceMetadata(null, { after: batch.cursor, through: cursor });
|
|
5659
5706
|
await this.finishCloudMaintenanceBatch(name, cursor, batch.rows.length < limit || cursor >= batch.upperBound);
|
|
5660
5707
|
}
|
|
@@ -5728,7 +5775,30 @@ var D1Adapter = class {
|
|
|
5728
5775
|
if (!guard) return true;
|
|
5729
5776
|
const condition = this._cloudGuardPredicate(userId, guard);
|
|
5730
5777
|
const row = await this._db.prepare(`SELECT ${condition.sql} AS valid`).bind(...condition.args).first();
|
|
5731
|
-
return !!_optionalChain([row, 'optionalAccess',
|
|
5778
|
+
return !!_optionalChain([row, 'optionalAccess', _58 => _58.valid]);
|
|
5779
|
+
}
|
|
5780
|
+
_rowSnapshotMatch(spec, row) {
|
|
5781
|
+
const clauses = [];
|
|
5782
|
+
const args = [];
|
|
5783
|
+
for (const column of spec.columns) {
|
|
5784
|
+
if (!Object.hasOwn(row, column)) continue;
|
|
5785
|
+
if ((column === "value" || column === "payload") && row[column] === null && typeof row.byte_size === "number") {
|
|
5786
|
+
clauses.push(
|
|
5787
|
+
`LENGTH(CAST(${column} AS BLOB)) IS ?`,
|
|
5788
|
+
`substr(${column}, 1, 128) IS ?`,
|
|
5789
|
+
`(CASE WHEN LENGTH(${column}) > 128 THEN substr(${column}, -64) ELSE '' END) IS ?`
|
|
5790
|
+
);
|
|
5791
|
+
args.push(
|
|
5792
|
+
row.byte_size,
|
|
5793
|
+
_nullishCoalesce(row[`${column}_prefix`], () => ( null)),
|
|
5794
|
+
_nullishCoalesce(row[`${column}_suffix`], () => ( ""))
|
|
5795
|
+
);
|
|
5796
|
+
} else {
|
|
5797
|
+
clauses.push(`${column} IS ?`);
|
|
5798
|
+
args.push(row[column]);
|
|
5799
|
+
}
|
|
5800
|
+
}
|
|
5801
|
+
return { predicate: clauses.join(" AND "), values: args };
|
|
5732
5802
|
}
|
|
5733
5803
|
/** Delete only the exact physical snapshot; no untrusted SQL identifiers. */
|
|
5734
5804
|
async deleteCloudResourceRows(userId, locators, { operationId, leaseToken } = {}) {
|
|
@@ -5777,9 +5847,7 @@ var D1Adapter = class {
|
|
|
5777
5847
|
).bind(userId, namespace, key, "amsg-chunks" + namespace, key + "", key + " ", identities));
|
|
5778
5848
|
}
|
|
5779
5849
|
for (const row of locator.rows) {
|
|
5780
|
-
const
|
|
5781
|
-
const predicate = columns.map((column) => `${column} IS ?`).join(" AND ");
|
|
5782
|
-
const values = columns.map((column) => row[column]);
|
|
5850
|
+
const { predicate, values } = this._rowSnapshotMatch(spec, row);
|
|
5783
5851
|
const identity = spec.keys.map((column) => `${column} IS ?`).join(" AND ");
|
|
5784
5852
|
statements.push(this._db.prepare(
|
|
5785
5853
|
`INSERT INTO cloud_guard_assertions (allowed)
|
|
@@ -5788,8 +5856,8 @@ var D1Adapter = class {
|
|
|
5788
5856
|
).bind(...spec.keys.map((column) => row[column]), ...values));
|
|
5789
5857
|
}
|
|
5790
5858
|
for (const row of locator.rows) {
|
|
5791
|
-
const
|
|
5792
|
-
statements.push(this._db.prepare(`DELETE FROM ${spec.table} WHERE ${
|
|
5859
|
+
const { predicate, values } = this._rowSnapshotMatch(spec, row);
|
|
5860
|
+
statements.push(this._db.prepare(`DELETE FROM ${spec.table} WHERE ${predicate}`).bind(...values));
|
|
5793
5861
|
}
|
|
5794
5862
|
if (locator.metadataKey) statements.push(this._db.prepare("DELETE FROM cloud_resource_metadata WHERE user_id=? AND resource_key=?").bind(userId, locator.metadataKey));
|
|
5795
5863
|
try {
|
|
@@ -5981,7 +6049,7 @@ var D1Adapter = class {
|
|
|
5981
6049
|
).bind(...values);
|
|
5982
6050
|
const ownerUser = cloudGuard ? await this._db.prepare("SELECT user_id FROM scheduled_messages WHERE id=?").bind(taskId).first() : null;
|
|
5983
6051
|
if (cloudGuard && !ownerUser) return null;
|
|
5984
|
-
await this._cloudBatch([statement], _optionalChain([ownerUser, 'optionalAccess',
|
|
6052
|
+
await this._cloudBatch([statement], _optionalChain([ownerUser, 'optionalAccess', _59 => _59.user_id]), [cloudGuard]);
|
|
5985
6053
|
return this._db.prepare("SELECT * FROM scheduled_messages WHERE id = ?").bind(taskId).first();
|
|
5986
6054
|
}
|
|
5987
6055
|
/**
|
|
@@ -6106,7 +6174,7 @@ var D1Adapter = class {
|
|
|
6106
6174
|
).bind(...values);
|
|
6107
6175
|
const ownerUser = cloudGuard ? await this._db.prepare("SELECT user_id FROM scheduled_messages WHERE id=?").bind(taskId).first() : null;
|
|
6108
6176
|
if (cloudGuard && !ownerUser) return false;
|
|
6109
|
-
const [res] = await this._cloudBatch([statement], _optionalChain([ownerUser, 'optionalAccess',
|
|
6177
|
+
const [res] = await this._cloudBatch([statement], _optionalChain([ownerUser, 'optionalAccess', _60 => _60.user_id]), [cloudGuard]);
|
|
6110
6178
|
return (res.meta.changes || 0) > 0;
|
|
6111
6179
|
}
|
|
6112
6180
|
/**
|
|
@@ -6125,7 +6193,7 @@ var D1Adapter = class {
|
|
|
6125
6193
|
).bind(this._iso(leaseUntil), taskId);
|
|
6126
6194
|
const ownerUser = cloudGuard ? await this._db.prepare("SELECT user_id FROM scheduled_messages WHERE id=?").bind(taskId).first() : null;
|
|
6127
6195
|
if (cloudGuard && !ownerUser) return false;
|
|
6128
|
-
const [res] = await this._cloudBatch([statement], _optionalChain([ownerUser, 'optionalAccess',
|
|
6196
|
+
const [res] = await this._cloudBatch([statement], _optionalChain([ownerUser, 'optionalAccess', _61 => _61.user_id]), [cloudGuard]);
|
|
6129
6197
|
return (res.meta.changes || 0) > 0;
|
|
6130
6198
|
}
|
|
6131
6199
|
async listTasks(userId, opts = {}) {
|
|
@@ -6286,7 +6354,7 @@ var D1Adapter = class {
|
|
|
6286
6354
|
result.cleanupOutcomes = probeIndexes.map((probeAt) => {
|
|
6287
6355
|
if (probeAt === null) return null;
|
|
6288
6356
|
const row = results[probeAt] && Array.isArray(results[probeAt].results) ? results[probeAt].results[0] : null;
|
|
6289
|
-
return Number(_nullishCoalesce(_optionalChain([row, 'optionalAccess',
|
|
6357
|
+
return Number(_nullishCoalesce(_optionalChain([row, 'optionalAccess', _62 => _62.n]), () => ( 0))) === 0;
|
|
6290
6358
|
});
|
|
6291
6359
|
}
|
|
6292
6360
|
return result;
|
|
@@ -7160,7 +7228,7 @@ function createClientStateNamespacesHandler(ctx) {
|
|
|
7160
7228
|
}
|
|
7161
7229
|
|
|
7162
7230
|
// src/server/lib/version.js
|
|
7163
|
-
var SERVER_VERSION = true ? "3.1.0-next.
|
|
7231
|
+
var SERVER_VERSION = true ? "3.1.0-next.1" : "0.0.0-dev";
|
|
7164
7232
|
|
|
7165
7233
|
// src/server/handlers/capabilities.js
|
|
7166
7234
|
var SERVER_FEATURES = Object.freeze([
|
|
@@ -7328,6 +7396,39 @@ function objectOrText(value) {
|
|
|
7328
7396
|
return value;
|
|
7329
7397
|
}
|
|
7330
7398
|
}
|
|
7399
|
+
function utf8ByteLength(text) {
|
|
7400
|
+
if (typeof text !== "string" || text.length === 0) return 0;
|
|
7401
|
+
return /[^\x00-\x7f]/.test(text) ? encoder.encode(text).length : text.length;
|
|
7402
|
+
}
|
|
7403
|
+
function rowByteSize(row) {
|
|
7404
|
+
if (typeof row.byte_size === "number") return row.byte_size;
|
|
7405
|
+
return utf8ByteLength(
|
|
7406
|
+
String(
|
|
7407
|
+
_nullishCoalesce(_nullishCoalesce(_nullishCoalesce(_nullishCoalesce(_nullishCoalesce(row.value, () => ( row.encrypted_payload)), () => ( row.encrypted_value)), () => ( row.payload)), () => ( row.subscription)), () => ( ""))
|
|
7408
|
+
)
|
|
7409
|
+
);
|
|
7410
|
+
}
|
|
7411
|
+
var STORAGE_PREFIX_RE = /^[0-9a-f]{32}:[0-9a-f]{24,32}:[0-9a-f]*$/i;
|
|
7412
|
+
var HEX_RE = /^[0-9a-f]*$/i;
|
|
7413
|
+
function isValidStorageCiphertext(fullText, prefix, suffix, byteSize) {
|
|
7414
|
+
if (typeof fullText === "string") {
|
|
7415
|
+
if (!STORAGE_PREFIX_RE.test(fullText)) return false;
|
|
7416
|
+
const secondColon = fullText.indexOf(":", 33);
|
|
7417
|
+
return secondColon > 32 && (fullText.length - secondColon - 1) % 2 === 0;
|
|
7418
|
+
}
|
|
7419
|
+
if (typeof prefix === "string" && typeof byteSize === "number") {
|
|
7420
|
+
if (!STORAGE_PREFIX_RE.test(prefix)) return false;
|
|
7421
|
+
if (typeof suffix === "string" && !HEX_RE.test(suffix)) return false;
|
|
7422
|
+
const secondColon = prefix.indexOf(":", 33);
|
|
7423
|
+
return secondColon > 32 && (byteSize - secondColon - 1) % 2 === 0;
|
|
7424
|
+
}
|
|
7425
|
+
return false;
|
|
7426
|
+
}
|
|
7427
|
+
function hasCompleteStoredMetadata(stored) {
|
|
7428
|
+
return Boolean(
|
|
7429
|
+
stored && safeOwner(stored.owner) !== null && typeof stored.kind === "string" && stored.kind.length > 0
|
|
7430
|
+
);
|
|
7431
|
+
}
|
|
7331
7432
|
async function buildCloudDataInventory({
|
|
7332
7433
|
db,
|
|
7333
7434
|
userId,
|
|
@@ -7340,6 +7441,20 @@ async function buildCloudDataInventory({
|
|
|
7340
7441
|
const metadata = new Map(
|
|
7341
7442
|
(raw.metadata || []).map((row) => [row.resource_key, row.encrypted_value])
|
|
7342
7443
|
);
|
|
7444
|
+
const readStoredMetadata = async (metadataKey) => {
|
|
7445
|
+
const encryptedMetadata = metadata.get(metadataKey) || null;
|
|
7446
|
+
if (!encryptedMetadata) {
|
|
7447
|
+
return { encryptedMetadata: null, stored: null, unreadable: false };
|
|
7448
|
+
}
|
|
7449
|
+
try {
|
|
7450
|
+
const stored = JSON.parse(
|
|
7451
|
+
await decryptFromStorage(encryptedMetadata, userKey)
|
|
7452
|
+
);
|
|
7453
|
+
return { encryptedMetadata, stored, unreadable: false };
|
|
7454
|
+
} catch (e6) {
|
|
7455
|
+
return { encryptedMetadata, stored: null, unreadable: true };
|
|
7456
|
+
}
|
|
7457
|
+
};
|
|
7343
7458
|
const taskPayloads = /* @__PURE__ */ new Map();
|
|
7344
7459
|
const taskByUuid = /* @__PURE__ */ new Map();
|
|
7345
7460
|
for (const row of raw.task || []) {
|
|
@@ -7349,7 +7464,7 @@ async function buildCloudDataInventory({
|
|
|
7349
7464
|
);
|
|
7350
7465
|
taskPayloads.set(row.id, payload);
|
|
7351
7466
|
if (row.uuid) taskByUuid.set(row.uuid, payload);
|
|
7352
|
-
} catch (
|
|
7467
|
+
} catch (e7) {
|
|
7353
7468
|
}
|
|
7354
7469
|
}
|
|
7355
7470
|
const tasks = (raw.task || []).filter((row) => taskPayloads.has(row.id)).map((row) => ({ ...taskPayloads.get(row.id), uuid: row.uuid }));
|
|
@@ -7364,23 +7479,19 @@ async function buildCloudDataInventory({
|
|
|
7364
7479
|
status = null,
|
|
7365
7480
|
namespace,
|
|
7366
7481
|
key,
|
|
7367
|
-
credId
|
|
7482
|
+
credId,
|
|
7483
|
+
metadataInfo
|
|
7368
7484
|
}) => {
|
|
7369
7485
|
const metadataKey = JSON.stringify([type, ...identity]);
|
|
7370
7486
|
const id = await cloudDataHash(JSON.stringify([userId, metadataKey]));
|
|
7371
|
-
|
|
7372
|
-
|
|
7373
|
-
|
|
7374
|
-
|
|
7375
|
-
|
|
7376
|
-
|
|
7377
|
-
);
|
|
7378
|
-
} catch (e7) {
|
|
7379
|
-
unreadable = true;
|
|
7380
|
-
}
|
|
7381
|
-
}
|
|
7487
|
+
const {
|
|
7488
|
+
encryptedMetadata,
|
|
7489
|
+
stored,
|
|
7490
|
+
unreadable: metadataUnreadable
|
|
7491
|
+
} = await _asyncNullishCoalesce(metadataInfo, async () => ( await readStoredMetadata(metadataKey)));
|
|
7492
|
+
if (metadataUnreadable) unreadable = true;
|
|
7382
7493
|
let resolved = null;
|
|
7383
|
-
if (resolveOwner) {
|
|
7494
|
+
if (resolveOwner && !hasCompleteStoredMetadata(stored)) {
|
|
7384
7495
|
try {
|
|
7385
7496
|
resolved = await resolveOwner({
|
|
7386
7497
|
type,
|
|
@@ -7400,17 +7511,10 @@ async function buildCloudDataInventory({
|
|
|
7400
7511
|
});
|
|
7401
7512
|
}
|
|
7402
7513
|
}
|
|
7403
|
-
const owner = safeOwner(_optionalChain([stored, 'optionalAccess',
|
|
7404
|
-
const kind = _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(_nullishCoalesce(_optionalChain([stored, 'optionalAccess',
|
|
7514
|
+
const owner = safeOwner(_optionalChain([stored, 'optionalAccess', _63 => _63.owner])) || safeOwner(_optionalChain([payload, 'optionalAccess', _64 => _64.__cloudOwnerGuard, 'optionalAccess', _65 => _65.owner])) || safeOwner(_optionalChain([payload, 'optionalAccess', _66 => _66.metadata, 'optionalAccess', _67 => _67.cloudOwner])) || safeOwner(_optionalChain([payload, 'optionalAccess', _68 => _68.metadata, 'optionalAccess', _69 => _69.owner])) || safeOwner(_optionalChain([payload, 'optionalAccess', _70 => _70.owner])) || safeOwner(_optionalChain([task, 'optionalAccess', _71 => _71.__cloudOwnerGuard, 'optionalAccess', _72 => _72.owner])) || safeOwner(_optionalChain([task, 'optionalAccess', _73 => _73.metadata, 'optionalAccess', _74 => _74.cloudOwner])) || safeOwner(_optionalChain([task, 'optionalAccess', _75 => _75.metadata, 'optionalAccess', _76 => _76.owner])) || safeOwner(_optionalChain([task, 'optionalAccess', _77 => _77.owner])) || safeOwner(_optionalChain([resolved, 'optionalAccess', _78 => _78.owner]));
|
|
7515
|
+
const kind = _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(_nullishCoalesce(_optionalChain([stored, 'optionalAccess', _79 => _79.kind]), () => ( _optionalChain([payload, 'optionalAccess', _80 => _80.metadata, 'optionalAccess', _81 => _81.kind]))), () => ( _optionalChain([payload, 'optionalAccess', _82 => _82.kind]))), () => ( _optionalChain([resolved, 'optionalAccess', _83 => _83.kind]))), () => ( null));
|
|
7405
7516
|
const times = rows.map((row) => timestamp(_nullishCoalesce(row.updated_at, () => ( row.created_at)))).filter((time) => time !== null);
|
|
7406
|
-
const byteSize = rows.reduce(
|
|
7407
|
-
(sum, row) => sum + encoder.encode(
|
|
7408
|
-
String(
|
|
7409
|
-
_nullishCoalesce(_nullishCoalesce(_nullishCoalesce(_nullishCoalesce(_nullishCoalesce(row.value, () => ( row.encrypted_payload)), () => ( row.encrypted_value)), () => ( row.payload)), () => ( row.subscription)), () => ( ""))
|
|
7410
|
-
)
|
|
7411
|
-
).length,
|
|
7412
|
-
0
|
|
7413
|
-
);
|
|
7517
|
+
const byteSize = rows.reduce((sum, row) => sum + rowByteSize(row), 0);
|
|
7414
7518
|
const label = type === "state" ? `${namespace}/${key}` : type === "credential" ? credId : type === "task" ? rows[0].uuid || `task row ${rows[0].id}` : type === "outbox" ? rows[0].message_id : "Web Push subscription";
|
|
7415
7519
|
entries.push({
|
|
7416
7520
|
resource: {
|
|
@@ -7465,22 +7569,75 @@ async function buildCloudDataInventory({
|
|
|
7465
7569
|
const slices = chunks.get(group) || [];
|
|
7466
7570
|
chunks.delete(group);
|
|
7467
7571
|
const rows = [row, ...slices.sort((a, b) => a.key.localeCompare(b.key))];
|
|
7468
|
-
|
|
7572
|
+
const metadataKey = JSON.stringify(["state", row.namespace, row.key]);
|
|
7573
|
+
const metadataInfo = await readStoredMetadata(metadataKey);
|
|
7574
|
+
const skipFullDecrypt = !metadataInfo.unreadable && hasCompleteStoredMetadata(metadataInfo.stored);
|
|
7575
|
+
let value, unreadable = metadataInfo.unreadable;
|
|
7469
7576
|
try {
|
|
7470
|
-
const
|
|
7471
|
-
|
|
7472
|
-
|
|
7577
|
+
const rootMarker = _nullishCoalesce(_nullishCoalesce(row.value, () => ( row.value_prefix)), () => ( ""));
|
|
7578
|
+
const count = parseChunkedRootCount(rootMarker);
|
|
7579
|
+
if (count === null) {
|
|
7580
|
+
if (typeof row.value === "string" && (!skipFullDecrypt || row.value.length <= 1024)) {
|
|
7581
|
+
value = await decryptFromStorage(row.value, userKey);
|
|
7582
|
+
} else if (skipFullDecrypt) {
|
|
7583
|
+
if (!isValidStorageCiphertext(
|
|
7584
|
+
row.value,
|
|
7585
|
+
row.value_prefix,
|
|
7586
|
+
row.value_suffix,
|
|
7587
|
+
row.byte_size
|
|
7588
|
+
)) {
|
|
7589
|
+
throw new Error("Invalid state ciphertext");
|
|
7590
|
+
}
|
|
7591
|
+
} else {
|
|
7592
|
+
const fetched = typeof db.getClientState === "function" ? await db.getClientState(userId, row.namespace, { key: row.key }) : [];
|
|
7593
|
+
const rawValue = _optionalChain([fetched, 'optionalAccess', _84 => _84[0], 'optionalAccess', _85 => _85.value]);
|
|
7594
|
+
if (typeof rawValue !== "string") {
|
|
7595
|
+
throw new Error("Missing state value");
|
|
7596
|
+
}
|
|
7597
|
+
value = await decryptFromStorage(rawValue, userKey);
|
|
7598
|
+
}
|
|
7599
|
+
} else {
|
|
7473
7600
|
if (count > slices.length) throw new Error("Missing state chunks");
|
|
7474
|
-
const
|
|
7601
|
+
const sliceByKey = new Map(
|
|
7602
|
+
slices.map((candidate) => [candidate.key, candidate])
|
|
7603
|
+
);
|
|
7604
|
+
const orderedSlices = [];
|
|
7475
7605
|
for (let i = 0; i < count; i++) {
|
|
7476
|
-
const slice =
|
|
7477
|
-
(candidate) => candidate.key === chunkKeyFor(row.key, i)
|
|
7478
|
-
);
|
|
7606
|
+
const slice = sliceByKey.get(chunkKeyFor(row.key, i));
|
|
7479
7607
|
if (!slice || slice.updated_at !== row.updated_at)
|
|
7480
7608
|
throw new Error("Mismatched state chunks");
|
|
7481
|
-
|
|
7609
|
+
if (!isValidStorageCiphertext(
|
|
7610
|
+
slice.value,
|
|
7611
|
+
slice.value_prefix,
|
|
7612
|
+
slice.value_suffix,
|
|
7613
|
+
slice.byte_size
|
|
7614
|
+
)) {
|
|
7615
|
+
throw new Error("Corrupt state chunk");
|
|
7616
|
+
}
|
|
7617
|
+
orderedSlices.push(slice);
|
|
7618
|
+
}
|
|
7619
|
+
if (!skipFullDecrypt) {
|
|
7620
|
+
let fetchedByKey = null;
|
|
7621
|
+
if (orderedSlices.some((slice) => typeof slice.value !== "string")) {
|
|
7622
|
+
const fetchedSlices = typeof db.getClientState === "function" ? await db.getClientState(
|
|
7623
|
+
userId,
|
|
7624
|
+
CHUNK_NAMESPACE_PREFIX + row.namespace,
|
|
7625
|
+
{ keyPrefix: `${row.key}` }
|
|
7626
|
+
) : [];
|
|
7627
|
+
fetchedByKey = new Map(
|
|
7628
|
+
fetchedSlices.map((candidate) => [candidate.key, candidate.value])
|
|
7629
|
+
);
|
|
7630
|
+
}
|
|
7631
|
+
const parts = [];
|
|
7632
|
+
for (const slice of orderedSlices) {
|
|
7633
|
+
const rawSliceValue = typeof slice.value === "string" ? slice.value : _optionalChain([fetchedByKey, 'optionalAccess', _86 => _86.get, 'call', _87 => _87(slice.key)]);
|
|
7634
|
+
if (typeof rawSliceValue !== "string") {
|
|
7635
|
+
throw new Error("Missing state chunk value");
|
|
7636
|
+
}
|
|
7637
|
+
parts.push(await decryptFromStorage(rawSliceValue, userKey));
|
|
7638
|
+
}
|
|
7639
|
+
value = parts.join("");
|
|
7482
7640
|
}
|
|
7483
|
-
value = parts.join("");
|
|
7484
7641
|
}
|
|
7485
7642
|
} catch (e9) {
|
|
7486
7643
|
unreadable = true;
|
|
@@ -7493,7 +7650,8 @@ async function buildCloudDataInventory({
|
|
|
7493
7650
|
rows,
|
|
7494
7651
|
value,
|
|
7495
7652
|
unreadable,
|
|
7496
|
-
status: null
|
|
7653
|
+
status: null,
|
|
7654
|
+
metadataInfo
|
|
7497
7655
|
});
|
|
7498
7656
|
}
|
|
7499
7657
|
for (const [group, rows] of chunks) {
|
|
@@ -7517,9 +7675,29 @@ async function buildCloudDataInventory({
|
|
|
7517
7675
|
});
|
|
7518
7676
|
}
|
|
7519
7677
|
for (const row of raw.outbox || []) {
|
|
7520
|
-
|
|
7678
|
+
const metadataKey = JSON.stringify(["outbox", row.message_id]);
|
|
7679
|
+
const metadataInfo = await readStoredMetadata(metadataKey);
|
|
7680
|
+
const skipFullDecrypt = !metadataInfo.unreadable && hasCompleteStoredMetadata(metadataInfo.stored);
|
|
7681
|
+
let payload, unreadable = metadataInfo.unreadable;
|
|
7521
7682
|
try {
|
|
7522
|
-
payload
|
|
7683
|
+
if (typeof row.payload === "string" && (!skipFullDecrypt || row.payload.length <= 1024)) {
|
|
7684
|
+
payload = objectOrText(await decryptFromStorage(row.payload, userKey));
|
|
7685
|
+
} else if (skipFullDecrypt) {
|
|
7686
|
+
if (!isValidStorageCiphertext(
|
|
7687
|
+
row.payload,
|
|
7688
|
+
row.payload_prefix,
|
|
7689
|
+
row.payload_suffix,
|
|
7690
|
+
row.byte_size
|
|
7691
|
+
)) {
|
|
7692
|
+
throw new Error("Invalid outbox ciphertext");
|
|
7693
|
+
}
|
|
7694
|
+
} else {
|
|
7695
|
+
const rawPayload = typeof db.getOutboxPayload === "function" ? await db.getOutboxPayload(userId, row.message_id) : null;
|
|
7696
|
+
if (typeof rawPayload !== "string") {
|
|
7697
|
+
throw new Error("Missing outbox payload");
|
|
7698
|
+
}
|
|
7699
|
+
payload = objectOrText(await decryptFromStorage(rawPayload, userKey));
|
|
7700
|
+
}
|
|
7523
7701
|
} catch (e10) {
|
|
7524
7702
|
unreadable = true;
|
|
7525
7703
|
}
|
|
@@ -7530,7 +7708,8 @@ async function buildCloudDataInventory({
|
|
|
7530
7708
|
payload,
|
|
7531
7709
|
task: taskByUuid.get(row.task_uuid),
|
|
7532
7710
|
unreadable,
|
|
7533
|
-
status: row.acked_at != null ? "acked" : row.delivered_at != null ? "delivered" : "pending"
|
|
7711
|
+
status: row.acked_at != null ? "acked" : row.delivered_at != null ? "delivered" : "pending",
|
|
7712
|
+
metadataInfo
|
|
7534
7713
|
});
|
|
7535
7714
|
}
|
|
7536
7715
|
for (const row of raw.subscription || []) {
|
|
@@ -7544,7 +7723,7 @@ async function buildCloudDataInventory({
|
|
|
7544
7723
|
const ownerLabels = /* @__PURE__ */ new Map();
|
|
7545
7724
|
for (const { resource } of entries) {
|
|
7546
7725
|
const owner = resource.owner;
|
|
7547
|
-
if (!_optionalChain([owner, 'optionalAccess',
|
|
7726
|
+
if (!_optionalChain([owner, 'optionalAccess', _88 => _88.label, 'optionalAccess', _89 => _89.trim, 'call', _90 => _90()])) continue;
|
|
7548
7727
|
const identity = JSON.stringify([owner.type, owner.id]);
|
|
7549
7728
|
const current = ownerLabels.get(identity);
|
|
7550
7729
|
if (!current || (_nullishCoalesce(resource.updatedAt, () => ( 0))) > current.updatedAt) {
|
|
@@ -7556,7 +7735,7 @@ async function buildCloudDataInventory({
|
|
|
7556
7735
|
}
|
|
7557
7736
|
for (const { resource } of entries) {
|
|
7558
7737
|
const owner = resource.owner;
|
|
7559
|
-
if (!owner || _optionalChain([owner, 'access',
|
|
7738
|
+
if (!owner || _optionalChain([owner, 'access', _91 => _91.label, 'optionalAccess', _92 => _92.trim, 'call', _93 => _93()])) continue;
|
|
7560
7739
|
const known = ownerLabels.get(JSON.stringify([owner.type, owner.id]));
|
|
7561
7740
|
if (known) resource.owner = { ...owner, label: known.label };
|
|
7562
7741
|
}
|
|
@@ -7584,7 +7763,7 @@ async function cloudInventory(ctx, db, userId, userKey) {
|
|
|
7584
7763
|
db,
|
|
7585
7764
|
userId,
|
|
7586
7765
|
userKey,
|
|
7587
|
-
resolveOwner: _optionalChain([ctx, 'access',
|
|
7766
|
+
resolveOwner: _optionalChain([ctx, 'access', _94 => _94.cloudData, 'optionalAccess', _95 => _95.resolveOwner])
|
|
7588
7767
|
});
|
|
7589
7768
|
}
|
|
7590
7769
|
function operationWork(operation) {
|
|
@@ -7641,7 +7820,7 @@ async function makeCleanupPlan(ctx, db, userId, key, input) {
|
|
|
7641
7820
|
throw cloudError("INVALID_CLEANUP_SELECTION", "\u8BF7\u9009\u62E9\u81F3\u5C11\u4E00\u9879\u8D44\u6E90");
|
|
7642
7821
|
if (types !== void 0 && (!Array.isArray(types) || !types.length || types.some((type) => !CLOUD_RESOURCE_TYPES.includes(type))))
|
|
7643
7822
|
throw cloudError("INVALID_CLEANUP_SELECTION", "\u8D44\u6E90\u7C7B\u522B\u65E0\u6548");
|
|
7644
|
-
if (mode === "purge" && !owner && !_optionalChain([resourceIds, 'optionalAccess',
|
|
7823
|
+
if (mode === "purge" && !owner && !_optionalChain([resourceIds, 'optionalAccess', _96 => _96.length]))
|
|
7645
7824
|
throw cloudError("INVALID_CLEANUP_SELECTION", "\u6E05\u7406\u9700\u8981\u660E\u786E\u8D44\u6E90\u6216\u5F52\u5C5E");
|
|
7646
7825
|
if (mode === "retire-owner" && (resourceIds || types))
|
|
7647
7826
|
throw cloudError("INVALID_CLEANUP_SELECTION", "\u5F7B\u5E95\u79FB\u9664\u4E0D\u80FD\u9650\u5236\u8D44\u6E90\u7C7B\u522B");
|
|
@@ -7653,10 +7832,12 @@ async function makeCleanupPlan(ctx, db, userId, key, input) {
|
|
|
7653
7832
|
"\u4E91\u7AEF\u6E05\u5355\u4E0D\u5B8C\u6574\uFF0C\u6682\u4E0D\u80FD\u751F\u6210\u6E05\u7406\u8BA1\u5212",
|
|
7654
7833
|
409
|
|
7655
7834
|
);
|
|
7835
|
+
const resourceIdSet = resourceIds ? new Set(resourceIds) : null;
|
|
7836
|
+
const typeSet = types ? new Set(types) : null;
|
|
7656
7837
|
const entries = inventory.entries.filter(
|
|
7657
|
-
(e) => (!owner || ownerEquals(e.resource.owner, owner)) && (!
|
|
7838
|
+
(e) => (!owner || ownerEquals(e.resource.owner, owner)) && (!resourceIdSet || resourceIdSet.has(e.resource.id)) && (!typeSet || typeSet.has(e.resource.type))
|
|
7658
7839
|
);
|
|
7659
|
-
if (
|
|
7840
|
+
if (resourceIdSet && resourceIdSet.size !== entries.length)
|
|
7660
7841
|
throw cloudError(
|
|
7661
7842
|
"CLOUD_RESOURCE_NOT_FOUND",
|
|
7662
7843
|
"\u90E8\u5206\u9009\u4E2D\u8D44\u6E90\u4E0D\u5B58\u5728\u6216\u4E0D\u5C5E\u4E8E\u5F53\u524D\u8303\u56F4",
|
|
@@ -7814,6 +7995,7 @@ async function advanceCleanup(ctx, db, userId, key, operation) {
|
|
|
7814
7995
|
if (operation.status === "completed" || operation.status === "failed")
|
|
7815
7996
|
return operation;
|
|
7816
7997
|
operation.status = "running";
|
|
7998
|
+
let retirementInventory = null;
|
|
7817
7999
|
if (operation.mode === "retire-owner") {
|
|
7818
8000
|
if (operation.fencedGeneration == null) {
|
|
7819
8001
|
const state = await db.setCloudOwnerActive(
|
|
@@ -7841,6 +8023,7 @@ async function advanceCleanup(ctx, db, userId, key, operation) {
|
|
|
7841
8023
|
"\u65E0\u6CD5\u786E\u8BA4\u5F85\u6E05\u7406\u8D44\u6E90",
|
|
7842
8024
|
503
|
|
7843
8025
|
);
|
|
8026
|
+
retirementInventory = inventory;
|
|
7844
8027
|
const known = new Set(operation.knownResourceIds || []);
|
|
7845
8028
|
operation.knownResourceVersions ||= {};
|
|
7846
8029
|
operation.entries = inventory.entries.filter((entry) => {
|
|
@@ -7867,7 +8050,7 @@ async function advanceCleanup(ctx, db, userId, key, operation) {
|
|
|
7867
8050
|
).length;
|
|
7868
8051
|
await save(db, userId, key, "operation", operation, { leaseToken });
|
|
7869
8052
|
}
|
|
7870
|
-
const beforeBatch = await cloudInventory(ctx, db, userId, key);
|
|
8053
|
+
const beforeBatch = await _asyncNullishCoalesce(retirementInventory, async () => ( await cloudInventory(ctx, db, userId, key)));
|
|
7871
8054
|
if (!beforeBatch.complete)
|
|
7872
8055
|
throw cloudError("CLOUD_INVENTORY_INCOMPLETE", "\u65E0\u6CD5\u786E\u8BA4\u5F85\u6E05\u7406\u8D44\u6E90", 503);
|
|
7873
8056
|
const currentById = new Map(
|
|
@@ -7905,7 +8088,6 @@ async function advanceCleanup(ctx, db, userId, key, operation) {
|
|
|
7905
8088
|
delete entry.locator;
|
|
7906
8089
|
operation.cursor++;
|
|
7907
8090
|
operation.updatedAt = Date.now();
|
|
7908
|
-
await save(db, userId, key, "operation", operation, { leaseToken });
|
|
7909
8091
|
}
|
|
7910
8092
|
await renewLease();
|
|
7911
8093
|
const current = await cloudInventory(ctx, db, userId, key);
|
|
@@ -7916,8 +8098,9 @@ async function advanceCleanup(ctx, db, userId, key, operation) {
|
|
|
7916
8098
|
503
|
|
7917
8099
|
);
|
|
7918
8100
|
const selected = new Set(operation.entries.map((e) => e.resource.id));
|
|
8101
|
+
const knownIds = new Set(operation.knownResourceIds || []);
|
|
7919
8102
|
const remaining = current.entries.filter(
|
|
7920
|
-
(e) => operation.mode === "retire-owner" ? ownerEquals(e.resource.owner, operation.owner) ||
|
|
8103
|
+
(e) => operation.mode === "retire-owner" ? ownerEquals(e.resource.owner, operation.owner) || knownIds.has(e.resource.id) : selected.has(e.resource.id)
|
|
7921
8104
|
);
|
|
7922
8105
|
for (const count of operation.counts)
|
|
7923
8106
|
count.remaining = remaining.filter(
|
|
@@ -8006,12 +8189,12 @@ async function repairLegacyWorkIndex(ctx) {
|
|
|
8006
8189
|
entries.push({ userId: row.user_id, kind: row.kind, id: row.id, work, writeToken: row.write_token });
|
|
8007
8190
|
}
|
|
8008
8191
|
await db.indexCloudDataRecordWorkBatch(entries);
|
|
8009
|
-
const cursor = _nullishCoalesce(_optionalChain([batch, 'access',
|
|
8192
|
+
const cursor = _nullishCoalesce(_optionalChain([batch, 'access', _97 => _97.rows, 'access', _98 => _98.at, 'call', _99 => _99(-1), 'optionalAccess', _100 => _100.maintenance_rowid]), () => ( batch.upperBound));
|
|
8010
8193
|
await db.finishCloudMaintenanceBatch(name, cursor, batch.rows.length < 100 || cursor >= batch.upperBound);
|
|
8011
8194
|
}
|
|
8012
8195
|
async function resumeCloudDataCleanups(ctx) {
|
|
8013
8196
|
const db = ctx.db;
|
|
8014
|
-
if (!_optionalChain([db, 'optionalAccess',
|
|
8197
|
+
if (!_optionalChain([db, 'optionalAccess', _101 => _101.cloudDataManagement])) return;
|
|
8015
8198
|
const indexed = WORK_INDEX_METHODS.every((method) => typeof db[method] === "function");
|
|
8016
8199
|
let rows;
|
|
8017
8200
|
if (indexed) {
|
|
@@ -8043,7 +8226,7 @@ async function resumeCloudDataCleanups(ctx) {
|
|
|
8043
8226
|
}
|
|
8044
8227
|
} catch (error) {
|
|
8045
8228
|
console.warn("[amsg] A cloud cleanup operation could not be resumed");
|
|
8046
|
-
if (!indexed || _optionalChain([error, 'optionalAccess',
|
|
8229
|
+
if (!indexed || _optionalChain([error, 'optionalAccess', _102 => _102.code]) === "CLOUD_LEASE_LOST") continue;
|
|
8047
8230
|
await db.rescheduleCloudDataRecordWork(
|
|
8048
8231
|
row.userId,
|
|
8049
8232
|
"operation",
|
|
@@ -8151,7 +8334,7 @@ function createCloudDataHandler(ctx) {
|
|
|
8151
8334
|
summary: inventorySummary(inventory),
|
|
8152
8335
|
expiresAt: Date.now() + 15 * 60 * 1e3,
|
|
8153
8336
|
resources: inventory.entries.map((e) => e.resource).filter(
|
|
8154
|
-
(r) => (!type || r.type === type) && (!ownerId || _optionalChain([r, 'access',
|
|
8337
|
+
(r) => (!type || r.type === type) && (!ownerId || _optionalChain([r, 'access', _103 => _103.owner, 'optionalAccess', _104 => _104.type]) === ownerType && r.owner.id === ownerId)
|
|
8155
8338
|
),
|
|
8156
8339
|
complete: inventory.complete,
|
|
8157
8340
|
gaps: inventory.gaps
|
|
@@ -8234,7 +8417,7 @@ function createCloudDataHandler(ctx) {
|
|
|
8234
8417
|
const rows = await db.listCloudDataRecords(userId, "operation");
|
|
8235
8418
|
for (const row of rows) {
|
|
8236
8419
|
const op = JSON.parse(await decryptFromStorage(row.data, key));
|
|
8237
|
-
if (op.mode === "retire-owner" && _optionalChain([op, 'access',
|
|
8420
|
+
if (op.mode === "retire-owner" && _optionalChain([op, 'access', _105 => _105.owner, 'optionalAccess', _106 => _106.type]) === owner.type && _optionalChain([op, 'access', _107 => _107.owner, 'optionalAccess', _108 => _108.id]) === owner.id && ["pending", "running"].includes(op.status))
|
|
8238
8421
|
throw cloudError(
|
|
8239
8422
|
"CLOUD_CLEANUP_IN_PROGRESS",
|
|
8240
8423
|
"\u6E05\u7406\u5B8C\u6210\u540E\u624D\u80FD\u91CD\u65B0\u542F\u7528",
|
|
@@ -8452,7 +8635,7 @@ function createSingleUserServer(config) {
|
|
|
8452
8635
|
if (!config.masterKey) throw new Error("[amsg-server single-user] config.masterKey is required");
|
|
8453
8636
|
const vapid = config.vapid || {};
|
|
8454
8637
|
const tenantManager = createSingleUserContextManager({
|
|
8455
|
-
db: createCloudGuardedAdapter(config.db, { masterKey: config.masterKey, resolveOwner: _optionalChain([config, 'access',
|
|
8638
|
+
db: createCloudGuardedAdapter(config.db, { masterKey: config.masterKey, resolveOwner: _optionalChain([config, 'access', _109 => _109.cloudData, 'optionalAccess', _110 => _110.resolveOwner]) }),
|
|
8456
8639
|
masterKey: config.masterKey,
|
|
8457
8640
|
serverToken: config.serverToken
|
|
8458
8641
|
});
|
|
@@ -8538,7 +8721,7 @@ async function getSchemaVersion(db) {
|
|
|
8538
8721
|
for (const index of SQLITE_REQUIRED_SCHEMA.indexes) {
|
|
8539
8722
|
if (!liveIndexes.has(index)) missing.push(`index:${index}`);
|
|
8540
8723
|
}
|
|
8541
|
-
if (Array.isArray(_optionalChain([live, 'optionalAccess',
|
|
8724
|
+
if (Array.isArray(_optionalChain([live, 'optionalAccess', _111 => _111.triggers]))) {
|
|
8542
8725
|
const liveTriggers = new Set(live.triggers);
|
|
8543
8726
|
for (const name of SQLITE_REQUIRED_SCHEMA.triggers) {
|
|
8544
8727
|
if (!liveTriggers.has(name)) missing.push(`trigger:${name}`);
|
|
@@ -147,14 +147,33 @@ import {
|
|
|
147
147
|
// src/server/lib/encryption.js
|
|
148
148
|
var base64ToBytes = base64UrlToBytes;
|
|
149
149
|
var TAG_LENGTH_BYTES = 16;
|
|
150
|
+
var AES_KEY_CACHE_MAX = 128;
|
|
151
|
+
var aesKeyCache = /* @__PURE__ */ new Map();
|
|
150
152
|
function importAesKey(hexKey, usage) {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
153
|
+
const cacheKey = `${usage}:${hexKey}`;
|
|
154
|
+
const cached = aesKeyCache.get(cacheKey);
|
|
155
|
+
if (cached) return cached;
|
|
156
|
+
let promise;
|
|
157
|
+
try {
|
|
158
|
+
promise = globalThis.crypto.subtle.importKey(
|
|
159
|
+
"raw",
|
|
160
|
+
hexToBytes(hexKey),
|
|
161
|
+
{ name: "AES-GCM" },
|
|
162
|
+
false,
|
|
163
|
+
[usage]
|
|
164
|
+
).catch((err6) => {
|
|
165
|
+
aesKeyCache.delete(cacheKey);
|
|
166
|
+
throw err6;
|
|
167
|
+
});
|
|
168
|
+
} catch (err6) {
|
|
169
|
+
return Promise.reject(err6);
|
|
170
|
+
}
|
|
171
|
+
if (aesKeyCache.size >= AES_KEY_CACHE_MAX) {
|
|
172
|
+
const oldest = aesKeyCache.keys().next().value;
|
|
173
|
+
if (oldest !== void 0) aesKeyCache.delete(oldest);
|
|
174
|
+
}
|
|
175
|
+
aesKeyCache.set(cacheKey, promise);
|
|
176
|
+
return promise;
|
|
158
177
|
}
|
|
159
178
|
async function aesGcmSeal(hexKey, iv, plaintextBytes) {
|
|
160
179
|
const key = await importAesKey(hexKey, "encrypt");
|
|
@@ -5451,12 +5470,37 @@ var D1Adapter = class {
|
|
|
5451
5470
|
const row = await this._db.prepare("SELECT encrypted_value FROM cloud_resource_metadata WHERE user_id=? AND resource_key=?").bind(userId, resourceKey).first();
|
|
5452
5471
|
return row?.encrypted_value ?? null;
|
|
5453
5472
|
}
|
|
5473
|
+
async getOutboxPayload(userId, messageId) {
|
|
5474
|
+
const row = await this._db.prepare(
|
|
5475
|
+
"SELECT payload FROM message_outbox WHERE user_id = ? AND message_id = ? LIMIT 1"
|
|
5476
|
+
).bind(userId, messageId).first();
|
|
5477
|
+
return row?.payload ?? null;
|
|
5478
|
+
}
|
|
5454
5479
|
async listCloudResourceRows(userId) {
|
|
5455
|
-
const
|
|
5480
|
+
const queries = {
|
|
5481
|
+
task: "SELECT * FROM scheduled_messages WHERE user_id = ?",
|
|
5482
|
+
state: `SELECT user_id, namespace, key,
|
|
5483
|
+
CASE WHEN LENGTH(value) <= 1024 THEN value ELSE NULL END AS value,
|
|
5484
|
+
LENGTH(CAST(value AS BLOB)) AS byte_size,
|
|
5485
|
+
substr(value, 1, 128) AS value_prefix,
|
|
5486
|
+
CASE WHEN LENGTH(value) > 128 THEN substr(value, -64) ELSE '' END AS value_suffix,
|
|
5487
|
+
updated_at
|
|
5488
|
+
FROM client_state WHERE user_id = ?`,
|
|
5489
|
+
credential: "SELECT * FROM llm_credentials WHERE user_id = ?",
|
|
5490
|
+
outbox: `SELECT id, user_id, message_id, task_uuid, session_id, message_index, total_messages,
|
|
5491
|
+
CASE WHEN LENGTH(payload) <= 1024 THEN payload ELSE NULL END AS payload,
|
|
5492
|
+
LENGTH(CAST(payload AS BLOB)) AS byte_size,
|
|
5493
|
+
substr(payload, 1, 128) AS payload_prefix,
|
|
5494
|
+
CASE WHEN LENGTH(payload) > 128 THEN substr(payload, -64) ELSE '' END AS payload_suffix,
|
|
5495
|
+
created_at, delivered_at, acked_at
|
|
5496
|
+
FROM message_outbox WHERE user_id = ?`,
|
|
5497
|
+
subscription: "SELECT * FROM push_subscriptions WHERE user_id = ?",
|
|
5498
|
+
metadata: "SELECT * FROM cloud_resource_metadata WHERE user_id = ?"
|
|
5499
|
+
};
|
|
5456
5500
|
const result = { gaps: [] };
|
|
5457
|
-
await Promise.all(Object.entries(
|
|
5501
|
+
await Promise.all(Object.entries(queries).map(async ([type, sql]) => {
|
|
5458
5502
|
try {
|
|
5459
|
-
const response = await this._db.prepare(
|
|
5503
|
+
const response = await this._db.prepare(sql).bind(userId).all();
|
|
5460
5504
|
result[type] = response.results || [];
|
|
5461
5505
|
} catch {
|
|
5462
5506
|
result[type] = [];
|
|
@@ -5521,7 +5565,10 @@ var D1Adapter = class {
|
|
|
5521
5565
|
if (idempotencyKey) {
|
|
5522
5566
|
return this._cloudRecord(await this._db.prepare(`SELECT * FROM cloud_data_records WHERE user_id=? AND kind=? AND idempotency_key=?`).bind(userId, kind, idempotencyKey).first());
|
|
5523
5567
|
}
|
|
5524
|
-
|
|
5568
|
+
if (createOnly) {
|
|
5569
|
+
return this.getCloudDataRecord(userId, kind, id);
|
|
5570
|
+
}
|
|
5571
|
+
return { id, userId, kind, data, updatedAt: now };
|
|
5525
5572
|
}
|
|
5526
5573
|
async getCloudDataRecord(userId, kind, id) {
|
|
5527
5574
|
return this._cloudRecord(await this._db.prepare("SELECT * FROM cloud_data_records WHERE user_id=? AND kind=? AND id=?").bind(userId, kind, id).first());
|
|
@@ -5730,6 +5777,29 @@ var D1Adapter = class {
|
|
|
5730
5777
|
const row = await this._db.prepare(`SELECT ${condition.sql} AS valid`).bind(...condition.args).first();
|
|
5731
5778
|
return !!row?.valid;
|
|
5732
5779
|
}
|
|
5780
|
+
_rowSnapshotMatch(spec, row) {
|
|
5781
|
+
const clauses = [];
|
|
5782
|
+
const args = [];
|
|
5783
|
+
for (const column of spec.columns) {
|
|
5784
|
+
if (!Object.hasOwn(row, column)) continue;
|
|
5785
|
+
if ((column === "value" || column === "payload") && row[column] === null && typeof row.byte_size === "number") {
|
|
5786
|
+
clauses.push(
|
|
5787
|
+
`LENGTH(CAST(${column} AS BLOB)) IS ?`,
|
|
5788
|
+
`substr(${column}, 1, 128) IS ?`,
|
|
5789
|
+
`(CASE WHEN LENGTH(${column}) > 128 THEN substr(${column}, -64) ELSE '' END) IS ?`
|
|
5790
|
+
);
|
|
5791
|
+
args.push(
|
|
5792
|
+
row.byte_size,
|
|
5793
|
+
row[`${column}_prefix`] ?? null,
|
|
5794
|
+
row[`${column}_suffix`] ?? ""
|
|
5795
|
+
);
|
|
5796
|
+
} else {
|
|
5797
|
+
clauses.push(`${column} IS ?`);
|
|
5798
|
+
args.push(row[column]);
|
|
5799
|
+
}
|
|
5800
|
+
}
|
|
5801
|
+
return { predicate: clauses.join(" AND "), values: args };
|
|
5802
|
+
}
|
|
5733
5803
|
/** Delete only the exact physical snapshot; no untrusted SQL identifiers. */
|
|
5734
5804
|
async deleteCloudResourceRows(userId, locators, { operationId, leaseToken } = {}) {
|
|
5735
5805
|
const specs = {
|
|
@@ -5777,9 +5847,7 @@ var D1Adapter = class {
|
|
|
5777
5847
|
).bind(userId, namespace, key, "amsg-chunks" + namespace, key + "", key + " ", identities));
|
|
5778
5848
|
}
|
|
5779
5849
|
for (const row of locator.rows) {
|
|
5780
|
-
const
|
|
5781
|
-
const predicate = columns.map((column) => `${column} IS ?`).join(" AND ");
|
|
5782
|
-
const values = columns.map((column) => row[column]);
|
|
5850
|
+
const { predicate, values } = this._rowSnapshotMatch(spec, row);
|
|
5783
5851
|
const identity = spec.keys.map((column) => `${column} IS ?`).join(" AND ");
|
|
5784
5852
|
statements.push(this._db.prepare(
|
|
5785
5853
|
`INSERT INTO cloud_guard_assertions (allowed)
|
|
@@ -5788,8 +5856,8 @@ var D1Adapter = class {
|
|
|
5788
5856
|
).bind(...spec.keys.map((column) => row[column]), ...values));
|
|
5789
5857
|
}
|
|
5790
5858
|
for (const row of locator.rows) {
|
|
5791
|
-
const
|
|
5792
|
-
statements.push(this._db.prepare(`DELETE FROM ${spec.table} WHERE ${
|
|
5859
|
+
const { predicate, values } = this._rowSnapshotMatch(spec, row);
|
|
5860
|
+
statements.push(this._db.prepare(`DELETE FROM ${spec.table} WHERE ${predicate}`).bind(...values));
|
|
5793
5861
|
}
|
|
5794
5862
|
if (locator.metadataKey) statements.push(this._db.prepare("DELETE FROM cloud_resource_metadata WHERE user_id=? AND resource_key=?").bind(userId, locator.metadataKey));
|
|
5795
5863
|
try {
|
|
@@ -7160,7 +7228,7 @@ function createClientStateNamespacesHandler(ctx) {
|
|
|
7160
7228
|
}
|
|
7161
7229
|
|
|
7162
7230
|
// src/server/lib/version.js
|
|
7163
|
-
var SERVER_VERSION = true ? "3.1.0-next.
|
|
7231
|
+
var SERVER_VERSION = true ? "3.1.0-next.1" : "0.0.0-dev";
|
|
7164
7232
|
|
|
7165
7233
|
// src/server/handlers/capabilities.js
|
|
7166
7234
|
var SERVER_FEATURES = Object.freeze([
|
|
@@ -7328,6 +7396,39 @@ function objectOrText(value) {
|
|
|
7328
7396
|
return value;
|
|
7329
7397
|
}
|
|
7330
7398
|
}
|
|
7399
|
+
function utf8ByteLength(text) {
|
|
7400
|
+
if (typeof text !== "string" || text.length === 0) return 0;
|
|
7401
|
+
return /[^\x00-\x7f]/.test(text) ? encoder.encode(text).length : text.length;
|
|
7402
|
+
}
|
|
7403
|
+
function rowByteSize(row) {
|
|
7404
|
+
if (typeof row.byte_size === "number") return row.byte_size;
|
|
7405
|
+
return utf8ByteLength(
|
|
7406
|
+
String(
|
|
7407
|
+
row.value ?? row.encrypted_payload ?? row.encrypted_value ?? row.payload ?? row.subscription ?? ""
|
|
7408
|
+
)
|
|
7409
|
+
);
|
|
7410
|
+
}
|
|
7411
|
+
var STORAGE_PREFIX_RE = /^[0-9a-f]{32}:[0-9a-f]{24,32}:[0-9a-f]*$/i;
|
|
7412
|
+
var HEX_RE = /^[0-9a-f]*$/i;
|
|
7413
|
+
function isValidStorageCiphertext(fullText, prefix, suffix, byteSize) {
|
|
7414
|
+
if (typeof fullText === "string") {
|
|
7415
|
+
if (!STORAGE_PREFIX_RE.test(fullText)) return false;
|
|
7416
|
+
const secondColon = fullText.indexOf(":", 33);
|
|
7417
|
+
return secondColon > 32 && (fullText.length - secondColon - 1) % 2 === 0;
|
|
7418
|
+
}
|
|
7419
|
+
if (typeof prefix === "string" && typeof byteSize === "number") {
|
|
7420
|
+
if (!STORAGE_PREFIX_RE.test(prefix)) return false;
|
|
7421
|
+
if (typeof suffix === "string" && !HEX_RE.test(suffix)) return false;
|
|
7422
|
+
const secondColon = prefix.indexOf(":", 33);
|
|
7423
|
+
return secondColon > 32 && (byteSize - secondColon - 1) % 2 === 0;
|
|
7424
|
+
}
|
|
7425
|
+
return false;
|
|
7426
|
+
}
|
|
7427
|
+
function hasCompleteStoredMetadata(stored) {
|
|
7428
|
+
return Boolean(
|
|
7429
|
+
stored && safeOwner(stored.owner) !== null && typeof stored.kind === "string" && stored.kind.length > 0
|
|
7430
|
+
);
|
|
7431
|
+
}
|
|
7331
7432
|
async function buildCloudDataInventory({
|
|
7332
7433
|
db,
|
|
7333
7434
|
userId,
|
|
@@ -7340,6 +7441,20 @@ async function buildCloudDataInventory({
|
|
|
7340
7441
|
const metadata = new Map(
|
|
7341
7442
|
(raw.metadata || []).map((row) => [row.resource_key, row.encrypted_value])
|
|
7342
7443
|
);
|
|
7444
|
+
const readStoredMetadata = async (metadataKey) => {
|
|
7445
|
+
const encryptedMetadata = metadata.get(metadataKey) || null;
|
|
7446
|
+
if (!encryptedMetadata) {
|
|
7447
|
+
return { encryptedMetadata: null, stored: null, unreadable: false };
|
|
7448
|
+
}
|
|
7449
|
+
try {
|
|
7450
|
+
const stored = JSON.parse(
|
|
7451
|
+
await decryptFromStorage(encryptedMetadata, userKey)
|
|
7452
|
+
);
|
|
7453
|
+
return { encryptedMetadata, stored, unreadable: false };
|
|
7454
|
+
} catch {
|
|
7455
|
+
return { encryptedMetadata, stored: null, unreadable: true };
|
|
7456
|
+
}
|
|
7457
|
+
};
|
|
7343
7458
|
const taskPayloads = /* @__PURE__ */ new Map();
|
|
7344
7459
|
const taskByUuid = /* @__PURE__ */ new Map();
|
|
7345
7460
|
for (const row of raw.task || []) {
|
|
@@ -7364,23 +7479,19 @@ async function buildCloudDataInventory({
|
|
|
7364
7479
|
status = null,
|
|
7365
7480
|
namespace,
|
|
7366
7481
|
key,
|
|
7367
|
-
credId
|
|
7482
|
+
credId,
|
|
7483
|
+
metadataInfo
|
|
7368
7484
|
}) => {
|
|
7369
7485
|
const metadataKey = JSON.stringify([type, ...identity]);
|
|
7370
7486
|
const id = await cloudDataHash(JSON.stringify([userId, metadataKey]));
|
|
7371
|
-
|
|
7372
|
-
|
|
7373
|
-
|
|
7374
|
-
|
|
7375
|
-
|
|
7376
|
-
|
|
7377
|
-
);
|
|
7378
|
-
} catch {
|
|
7379
|
-
unreadable = true;
|
|
7380
|
-
}
|
|
7381
|
-
}
|
|
7487
|
+
const {
|
|
7488
|
+
encryptedMetadata,
|
|
7489
|
+
stored,
|
|
7490
|
+
unreadable: metadataUnreadable
|
|
7491
|
+
} = metadataInfo ?? await readStoredMetadata(metadataKey);
|
|
7492
|
+
if (metadataUnreadable) unreadable = true;
|
|
7382
7493
|
let resolved = null;
|
|
7383
|
-
if (resolveOwner) {
|
|
7494
|
+
if (resolveOwner && !hasCompleteStoredMetadata(stored)) {
|
|
7384
7495
|
try {
|
|
7385
7496
|
resolved = await resolveOwner({
|
|
7386
7497
|
type,
|
|
@@ -7403,14 +7514,7 @@ async function buildCloudDataInventory({
|
|
|
7403
7514
|
const owner = safeOwner(stored?.owner) || safeOwner(payload?.__cloudOwnerGuard?.owner) || safeOwner(payload?.metadata?.cloudOwner) || safeOwner(payload?.metadata?.owner) || safeOwner(payload?.owner) || safeOwner(task?.__cloudOwnerGuard?.owner) || safeOwner(task?.metadata?.cloudOwner) || safeOwner(task?.metadata?.owner) || safeOwner(task?.owner) || safeOwner(resolved?.owner);
|
|
7404
7515
|
const kind = stored?.kind ?? payload?.metadata?.kind ?? payload?.kind ?? resolved?.kind ?? null;
|
|
7405
7516
|
const times = rows.map((row) => timestamp(row.updated_at ?? row.created_at)).filter((time) => time !== null);
|
|
7406
|
-
const byteSize = rows.reduce(
|
|
7407
|
-
(sum, row) => sum + encoder.encode(
|
|
7408
|
-
String(
|
|
7409
|
-
row.value ?? row.encrypted_payload ?? row.encrypted_value ?? row.payload ?? row.subscription ?? ""
|
|
7410
|
-
)
|
|
7411
|
-
).length,
|
|
7412
|
-
0
|
|
7413
|
-
);
|
|
7517
|
+
const byteSize = rows.reduce((sum, row) => sum + rowByteSize(row), 0);
|
|
7414
7518
|
const label = type === "state" ? `${namespace}/${key}` : type === "credential" ? credId : type === "task" ? rows[0].uuid || `task row ${rows[0].id}` : type === "outbox" ? rows[0].message_id : "Web Push subscription";
|
|
7415
7519
|
entries.push({
|
|
7416
7520
|
resource: {
|
|
@@ -7465,22 +7569,75 @@ async function buildCloudDataInventory({
|
|
|
7465
7569
|
const slices = chunks.get(group) || [];
|
|
7466
7570
|
chunks.delete(group);
|
|
7467
7571
|
const rows = [row, ...slices.sort((a, b) => a.key.localeCompare(b.key))];
|
|
7468
|
-
|
|
7572
|
+
const metadataKey = JSON.stringify(["state", row.namespace, row.key]);
|
|
7573
|
+
const metadataInfo = await readStoredMetadata(metadataKey);
|
|
7574
|
+
const skipFullDecrypt = !metadataInfo.unreadable && hasCompleteStoredMetadata(metadataInfo.stored);
|
|
7575
|
+
let value, unreadable = metadataInfo.unreadable;
|
|
7469
7576
|
try {
|
|
7470
|
-
const
|
|
7471
|
-
|
|
7472
|
-
|
|
7577
|
+
const rootMarker = row.value ?? row.value_prefix ?? "";
|
|
7578
|
+
const count = parseChunkedRootCount(rootMarker);
|
|
7579
|
+
if (count === null) {
|
|
7580
|
+
if (typeof row.value === "string" && (!skipFullDecrypt || row.value.length <= 1024)) {
|
|
7581
|
+
value = await decryptFromStorage(row.value, userKey);
|
|
7582
|
+
} else if (skipFullDecrypt) {
|
|
7583
|
+
if (!isValidStorageCiphertext(
|
|
7584
|
+
row.value,
|
|
7585
|
+
row.value_prefix,
|
|
7586
|
+
row.value_suffix,
|
|
7587
|
+
row.byte_size
|
|
7588
|
+
)) {
|
|
7589
|
+
throw new Error("Invalid state ciphertext");
|
|
7590
|
+
}
|
|
7591
|
+
} else {
|
|
7592
|
+
const fetched = typeof db.getClientState === "function" ? await db.getClientState(userId, row.namespace, { key: row.key }) : [];
|
|
7593
|
+
const rawValue = fetched?.[0]?.value;
|
|
7594
|
+
if (typeof rawValue !== "string") {
|
|
7595
|
+
throw new Error("Missing state value");
|
|
7596
|
+
}
|
|
7597
|
+
value = await decryptFromStorage(rawValue, userKey);
|
|
7598
|
+
}
|
|
7599
|
+
} else {
|
|
7473
7600
|
if (count > slices.length) throw new Error("Missing state chunks");
|
|
7474
|
-
const
|
|
7601
|
+
const sliceByKey = new Map(
|
|
7602
|
+
slices.map((candidate) => [candidate.key, candidate])
|
|
7603
|
+
);
|
|
7604
|
+
const orderedSlices = [];
|
|
7475
7605
|
for (let i = 0; i < count; i++) {
|
|
7476
|
-
const slice =
|
|
7477
|
-
(candidate) => candidate.key === chunkKeyFor(row.key, i)
|
|
7478
|
-
);
|
|
7606
|
+
const slice = sliceByKey.get(chunkKeyFor(row.key, i));
|
|
7479
7607
|
if (!slice || slice.updated_at !== row.updated_at)
|
|
7480
7608
|
throw new Error("Mismatched state chunks");
|
|
7481
|
-
|
|
7609
|
+
if (!isValidStorageCiphertext(
|
|
7610
|
+
slice.value,
|
|
7611
|
+
slice.value_prefix,
|
|
7612
|
+
slice.value_suffix,
|
|
7613
|
+
slice.byte_size
|
|
7614
|
+
)) {
|
|
7615
|
+
throw new Error("Corrupt state chunk");
|
|
7616
|
+
}
|
|
7617
|
+
orderedSlices.push(slice);
|
|
7618
|
+
}
|
|
7619
|
+
if (!skipFullDecrypt) {
|
|
7620
|
+
let fetchedByKey = null;
|
|
7621
|
+
if (orderedSlices.some((slice) => typeof slice.value !== "string")) {
|
|
7622
|
+
const fetchedSlices = typeof db.getClientState === "function" ? await db.getClientState(
|
|
7623
|
+
userId,
|
|
7624
|
+
CHUNK_NAMESPACE_PREFIX + row.namespace,
|
|
7625
|
+
{ keyPrefix: `${row.key}` }
|
|
7626
|
+
) : [];
|
|
7627
|
+
fetchedByKey = new Map(
|
|
7628
|
+
fetchedSlices.map((candidate) => [candidate.key, candidate.value])
|
|
7629
|
+
);
|
|
7630
|
+
}
|
|
7631
|
+
const parts = [];
|
|
7632
|
+
for (const slice of orderedSlices) {
|
|
7633
|
+
const rawSliceValue = typeof slice.value === "string" ? slice.value : fetchedByKey?.get(slice.key);
|
|
7634
|
+
if (typeof rawSliceValue !== "string") {
|
|
7635
|
+
throw new Error("Missing state chunk value");
|
|
7636
|
+
}
|
|
7637
|
+
parts.push(await decryptFromStorage(rawSliceValue, userKey));
|
|
7638
|
+
}
|
|
7639
|
+
value = parts.join("");
|
|
7482
7640
|
}
|
|
7483
|
-
value = parts.join("");
|
|
7484
7641
|
}
|
|
7485
7642
|
} catch {
|
|
7486
7643
|
unreadable = true;
|
|
@@ -7493,7 +7650,8 @@ async function buildCloudDataInventory({
|
|
|
7493
7650
|
rows,
|
|
7494
7651
|
value,
|
|
7495
7652
|
unreadable,
|
|
7496
|
-
status: null
|
|
7653
|
+
status: null,
|
|
7654
|
+
metadataInfo
|
|
7497
7655
|
});
|
|
7498
7656
|
}
|
|
7499
7657
|
for (const [group, rows] of chunks) {
|
|
@@ -7517,9 +7675,29 @@ async function buildCloudDataInventory({
|
|
|
7517
7675
|
});
|
|
7518
7676
|
}
|
|
7519
7677
|
for (const row of raw.outbox || []) {
|
|
7520
|
-
|
|
7678
|
+
const metadataKey = JSON.stringify(["outbox", row.message_id]);
|
|
7679
|
+
const metadataInfo = await readStoredMetadata(metadataKey);
|
|
7680
|
+
const skipFullDecrypt = !metadataInfo.unreadable && hasCompleteStoredMetadata(metadataInfo.stored);
|
|
7681
|
+
let payload, unreadable = metadataInfo.unreadable;
|
|
7521
7682
|
try {
|
|
7522
|
-
payload
|
|
7683
|
+
if (typeof row.payload === "string" && (!skipFullDecrypt || row.payload.length <= 1024)) {
|
|
7684
|
+
payload = objectOrText(await decryptFromStorage(row.payload, userKey));
|
|
7685
|
+
} else if (skipFullDecrypt) {
|
|
7686
|
+
if (!isValidStorageCiphertext(
|
|
7687
|
+
row.payload,
|
|
7688
|
+
row.payload_prefix,
|
|
7689
|
+
row.payload_suffix,
|
|
7690
|
+
row.byte_size
|
|
7691
|
+
)) {
|
|
7692
|
+
throw new Error("Invalid outbox ciphertext");
|
|
7693
|
+
}
|
|
7694
|
+
} else {
|
|
7695
|
+
const rawPayload = typeof db.getOutboxPayload === "function" ? await db.getOutboxPayload(userId, row.message_id) : null;
|
|
7696
|
+
if (typeof rawPayload !== "string") {
|
|
7697
|
+
throw new Error("Missing outbox payload");
|
|
7698
|
+
}
|
|
7699
|
+
payload = objectOrText(await decryptFromStorage(rawPayload, userKey));
|
|
7700
|
+
}
|
|
7523
7701
|
} catch {
|
|
7524
7702
|
unreadable = true;
|
|
7525
7703
|
}
|
|
@@ -7530,7 +7708,8 @@ async function buildCloudDataInventory({
|
|
|
7530
7708
|
payload,
|
|
7531
7709
|
task: taskByUuid.get(row.task_uuid),
|
|
7532
7710
|
unreadable,
|
|
7533
|
-
status: row.acked_at != null ? "acked" : row.delivered_at != null ? "delivered" : "pending"
|
|
7711
|
+
status: row.acked_at != null ? "acked" : row.delivered_at != null ? "delivered" : "pending",
|
|
7712
|
+
metadataInfo
|
|
7534
7713
|
});
|
|
7535
7714
|
}
|
|
7536
7715
|
for (const row of raw.subscription || []) {
|
|
@@ -7653,10 +7832,12 @@ async function makeCleanupPlan(ctx, db, userId, key, input) {
|
|
|
7653
7832
|
"\u4E91\u7AEF\u6E05\u5355\u4E0D\u5B8C\u6574\uFF0C\u6682\u4E0D\u80FD\u751F\u6210\u6E05\u7406\u8BA1\u5212",
|
|
7654
7833
|
409
|
|
7655
7834
|
);
|
|
7835
|
+
const resourceIdSet = resourceIds ? new Set(resourceIds) : null;
|
|
7836
|
+
const typeSet = types ? new Set(types) : null;
|
|
7656
7837
|
const entries = inventory.entries.filter(
|
|
7657
|
-
(e) => (!owner || ownerEquals(e.resource.owner, owner)) && (!
|
|
7838
|
+
(e) => (!owner || ownerEquals(e.resource.owner, owner)) && (!resourceIdSet || resourceIdSet.has(e.resource.id)) && (!typeSet || typeSet.has(e.resource.type))
|
|
7658
7839
|
);
|
|
7659
|
-
if (
|
|
7840
|
+
if (resourceIdSet && resourceIdSet.size !== entries.length)
|
|
7660
7841
|
throw cloudError(
|
|
7661
7842
|
"CLOUD_RESOURCE_NOT_FOUND",
|
|
7662
7843
|
"\u90E8\u5206\u9009\u4E2D\u8D44\u6E90\u4E0D\u5B58\u5728\u6216\u4E0D\u5C5E\u4E8E\u5F53\u524D\u8303\u56F4",
|
|
@@ -7814,6 +7995,7 @@ async function advanceCleanup(ctx, db, userId, key, operation) {
|
|
|
7814
7995
|
if (operation.status === "completed" || operation.status === "failed")
|
|
7815
7996
|
return operation;
|
|
7816
7997
|
operation.status = "running";
|
|
7998
|
+
let retirementInventory = null;
|
|
7817
7999
|
if (operation.mode === "retire-owner") {
|
|
7818
8000
|
if (operation.fencedGeneration == null) {
|
|
7819
8001
|
const state = await db.setCloudOwnerActive(
|
|
@@ -7841,6 +8023,7 @@ async function advanceCleanup(ctx, db, userId, key, operation) {
|
|
|
7841
8023
|
"\u65E0\u6CD5\u786E\u8BA4\u5F85\u6E05\u7406\u8D44\u6E90",
|
|
7842
8024
|
503
|
|
7843
8025
|
);
|
|
8026
|
+
retirementInventory = inventory;
|
|
7844
8027
|
const known = new Set(operation.knownResourceIds || []);
|
|
7845
8028
|
operation.knownResourceVersions ||= {};
|
|
7846
8029
|
operation.entries = inventory.entries.filter((entry) => {
|
|
@@ -7867,7 +8050,7 @@ async function advanceCleanup(ctx, db, userId, key, operation) {
|
|
|
7867
8050
|
).length;
|
|
7868
8051
|
await save(db, userId, key, "operation", operation, { leaseToken });
|
|
7869
8052
|
}
|
|
7870
|
-
const beforeBatch = await cloudInventory(ctx, db, userId, key);
|
|
8053
|
+
const beforeBatch = retirementInventory ?? await cloudInventory(ctx, db, userId, key);
|
|
7871
8054
|
if (!beforeBatch.complete)
|
|
7872
8055
|
throw cloudError("CLOUD_INVENTORY_INCOMPLETE", "\u65E0\u6CD5\u786E\u8BA4\u5F85\u6E05\u7406\u8D44\u6E90", 503);
|
|
7873
8056
|
const currentById = new Map(
|
|
@@ -7905,7 +8088,6 @@ async function advanceCleanup(ctx, db, userId, key, operation) {
|
|
|
7905
8088
|
delete entry.locator;
|
|
7906
8089
|
operation.cursor++;
|
|
7907
8090
|
operation.updatedAt = Date.now();
|
|
7908
|
-
await save(db, userId, key, "operation", operation, { leaseToken });
|
|
7909
8091
|
}
|
|
7910
8092
|
await renewLease();
|
|
7911
8093
|
const current = await cloudInventory(ctx, db, userId, key);
|
|
@@ -7916,8 +8098,9 @@ async function advanceCleanup(ctx, db, userId, key, operation) {
|
|
|
7916
8098
|
503
|
|
7917
8099
|
);
|
|
7918
8100
|
const selected = new Set(operation.entries.map((e) => e.resource.id));
|
|
8101
|
+
const knownIds = new Set(operation.knownResourceIds || []);
|
|
7919
8102
|
const remaining = current.entries.filter(
|
|
7920
|
-
(e) => operation.mode === "retire-owner" ? ownerEquals(e.resource.owner, operation.owner) ||
|
|
8103
|
+
(e) => operation.mode === "retire-owner" ? ownerEquals(e.resource.owner, operation.owner) || knownIds.has(e.resource.id) : selected.has(e.resource.id)
|
|
7921
8104
|
);
|
|
7922
8105
|
for (const count of operation.counts)
|
|
7923
8106
|
count.remaining = remaining.filter(
|
package/dist/cloudflare.cjs
CHANGED
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
var
|
|
32
|
+
var _chunkD4SKSCIYcjs = require('./chunk-D4SKSCIY.cjs');
|
|
33
33
|
require('./chunk-7NMQFTDJ.cjs');
|
|
34
34
|
|
|
35
35
|
|
|
@@ -62,4 +62,4 @@ require('./chunk-7NMQFTDJ.cjs');
|
|
|
62
62
|
|
|
63
63
|
|
|
64
64
|
|
|
65
|
-
exports.DEFAULT_MAX_DELIVERY_RETRIES =
|
|
65
|
+
exports.DEFAULT_MAX_DELIVERY_RETRIES = _chunkD4SKSCIYcjs.DEFAULT_MAX_DELIVERY_RETRIES; exports.DEFAULT_MAX_REQUEST_BODY_BYTES = _chunkD4SKSCIYcjs.DEFAULT_MAX_REQUEST_BODY_BYTES; exports.MAX_DEFER_AFTER_MS = _chunkD4SKSCIYcjs.MAX_DEFER_AFTER_MS; exports.MAX_PUSH_PAYLOAD_BYTES = _chunkD4SKSCIYcjs.MAX_PUSH_PAYLOAD_BYTES; exports.NonRetryableError = _chunkD4SKSCIYcjs.NonRetryableError; exports.PUSH_ENVELOPE_RESERVED_BYTES = _chunkD4SKSCIYcjs.PUSH_ENVELOPE_RESERVED_BYTES; exports.SCHEMA_VERSION = _chunkD4SKSCIYcjs.SCHEMA_VERSION; exports.WEB_PUSH_ENCRYPTION_OVERHEAD_BYTES = _chunkD4SKSCIYcjs.WEB_PUSH_ENCRYPTION_OVERHEAD_BYTES; exports.WEB_PUSH_MAX_BODY_BYTES = _chunkD4SKSCIYcjs.WEB_PUSH_MAX_BODY_BYTES; exports.advanceOccurrence = _chunkD4SKSCIYcjs.advanceOccurrence; exports.createD1Adapter = _chunkD4SKSCIYcjs.createD1Adapter; exports.createSingleUserCloudflareWorker = _chunkD4SKSCIYcjs.createSingleUserCloudflareWorker; exports.createSingleUserServer = _chunkD4SKSCIYcjs.createSingleUserServer; exports.createWebCryptoWebPush = _chunkD4SKSCIYcjs.createWebCryptoWebPush; exports.decryptFromStorage = _chunkD4SKSCIYcjs.decryptFromStorage; exports.decryptPayload = _chunkD4SKSCIYcjs.decryptPayload; exports.deriveUserEncryptionKey = _chunkD4SKSCIYcjs.deriveUserEncryptionKey; exports.encryptForStorage = _chunkD4SKSCIYcjs.encryptForStorage; exports.encryptPayload = _chunkD4SKSCIYcjs.encryptPayload; exports.ensureSchema = _chunkD4SKSCIYcjs.ensureSchema; exports.getSchemaVersion = _chunkD4SKSCIYcjs.getSchemaVersion; exports.isNonRetryableError = _chunkD4SKSCIYcjs.isNonRetryableError; exports.isValidTimeZoneId = _chunkD4SKSCIYcjs.isValidTimeZoneId; exports.measurePushPayload = _chunkD4SKSCIYcjs.measurePushPayload; exports.nextFutureOccurrence = _chunkD4SKSCIYcjs.nextFutureOccurrence; exports.planNextOccurrence = _chunkD4SKSCIYcjs.planNextOccurrence; exports.readRequestBody = _chunkD4SKSCIYcjs.readRequestBody; exports.runScheduledTick = _chunkD4SKSCIYcjs.runScheduledTick; exports.runTask = _chunkD4SKSCIYcjs.runTask; exports.summarizeErrorCause = _chunkD4SKSCIYcjs.summarizeErrorCause;
|
package/dist/cloudflare.mjs
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
|
|
75
75
|
|
|
76
76
|
|
|
77
|
-
var
|
|
77
|
+
var _chunkD4SKSCIYcjs = require('./chunk-D4SKSCIY.cjs');
|
|
78
78
|
require('./chunk-7NMQFTDJ.cjs');
|
|
79
79
|
|
|
80
80
|
// src/server/adapters/factory.js
|
|
@@ -108,7 +108,7 @@ async function createAdapter(config) {
|
|
|
108
108
|
// src/server/handlers/init-tenant.js
|
|
109
109
|
function createInitTenantHandler(ctx) {
|
|
110
110
|
async function POST(headers, body) {
|
|
111
|
-
const initSecret =
|
|
111
|
+
const initSecret = _chunkD4SKSCIYcjs.getHeader.call(void 0, headers, "x-init-secret");
|
|
112
112
|
if (ctx.tenant.initSecret && initSecret !== ctx.tenant.initSecret) {
|
|
113
113
|
return {
|
|
114
114
|
status: 401,
|
|
@@ -121,7 +121,7 @@ function createInitTenantHandler(ctx) {
|
|
|
121
121
|
}
|
|
122
122
|
};
|
|
123
123
|
}
|
|
124
|
-
const parsed =
|
|
124
|
+
const parsed = _chunkD4SKSCIYcjs.parseJsonBody.call(void 0, body);
|
|
125
125
|
if (!parsed.ok) {
|
|
126
126
|
return {
|
|
127
127
|
status: 400,
|
|
@@ -135,7 +135,7 @@ function createInitTenantHandler(ctx) {
|
|
|
135
135
|
const tenantId = payload.tenantId || void 0;
|
|
136
136
|
const driver = payload.driver;
|
|
137
137
|
const databaseUrl = payload.databaseUrl || payload.connectionString;
|
|
138
|
-
if (tenantId && !
|
|
138
|
+
if (tenantId && !_chunkD4SKSCIYcjs.isValidUUIDv4.call(void 0, tenantId)) {
|
|
139
139
|
return {
|
|
140
140
|
status: 400,
|
|
141
141
|
body: {
|
|
@@ -255,7 +255,7 @@ function createSendNotificationsHandler(ctx) {
|
|
|
255
255
|
}
|
|
256
256
|
};
|
|
257
257
|
}
|
|
258
|
-
const data = await
|
|
258
|
+
const data = await _chunkD4SKSCIYcjs.runScheduledTick.call(void 0, { ...ctx, db, masterKey });
|
|
259
259
|
return { status: 200, body: { success: true, data } };
|
|
260
260
|
}
|
|
261
261
|
return { POST };
|
|
@@ -277,16 +277,16 @@ function encryptConfig(config, kekBuffer) {
|
|
|
277
277
|
const plaintext = Buffer.from(JSON.stringify(config), "utf8");
|
|
278
278
|
const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
|
|
279
279
|
const authTag = cipher.getAuthTag();
|
|
280
|
-
return `v1.${
|
|
280
|
+
return `v1.${_chunkD4SKSCIYcjs.bytesToBase64Url.call(void 0, iv)}.${_chunkD4SKSCIYcjs.bytesToBase64Url.call(void 0, authTag)}.${_chunkD4SKSCIYcjs.bytesToBase64Url.call(void 0, ciphertext)}`;
|
|
281
281
|
}
|
|
282
282
|
function decryptConfig(encrypted, kekBuffer) {
|
|
283
283
|
const parts = String(encrypted || "").split(".");
|
|
284
284
|
if (parts.length !== 4 || parts[0] !== "v1") {
|
|
285
285
|
throw new Error("INVALID_TENANT_CONFIG");
|
|
286
286
|
}
|
|
287
|
-
const iv =
|
|
288
|
-
const authTag =
|
|
289
|
-
const ciphertext =
|
|
287
|
+
const iv = _chunkD4SKSCIYcjs.base64UrlToBytes.call(void 0, parts[1]);
|
|
288
|
+
const authTag = _chunkD4SKSCIYcjs.base64UrlToBytes.call(void 0, parts[2]);
|
|
289
|
+
const ciphertext = _chunkD4SKSCIYcjs.base64UrlToBytes.call(void 0, parts[3]);
|
|
290
290
|
const decipher = _crypto.createDecipheriv.call(void 0, "aes-256-gcm", kekBuffer, iv);
|
|
291
291
|
decipher.setAuthTag(authTag);
|
|
292
292
|
const plaintext = Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString("utf8");
|
|
@@ -354,7 +354,7 @@ function createTenantBlobStore(options) {
|
|
|
354
354
|
// src/server/tenant/token.js
|
|
355
355
|
|
|
356
356
|
function sign(input, secret) {
|
|
357
|
-
return
|
|
357
|
+
return _chunkD4SKSCIYcjs.bytesToBase64Url.call(void 0, _crypto.createHmac.call(void 0, "sha256", secret).update(input).digest());
|
|
358
358
|
}
|
|
359
359
|
function nowEpochSeconds() {
|
|
360
360
|
return Math.floor(Date.now() / 1e3);
|
|
@@ -370,8 +370,8 @@ function createTenantToken(params, secret) {
|
|
|
370
370
|
v: 1
|
|
371
371
|
};
|
|
372
372
|
const header = { alg: "HS256", typ: "JWT" };
|
|
373
|
-
const encodedHeader =
|
|
374
|
-
const encodedPayload =
|
|
373
|
+
const encodedHeader = _chunkD4SKSCIYcjs.bytesToBase64Url.call(void 0, _chunkD4SKSCIYcjs.utf8.call(void 0, JSON.stringify(header)));
|
|
374
|
+
const encodedPayload = _chunkD4SKSCIYcjs.bytesToBase64Url.call(void 0, _chunkD4SKSCIYcjs.utf8.call(void 0, JSON.stringify(payload)));
|
|
375
375
|
const signingInput = `${encodedHeader}.${encodedPayload}`;
|
|
376
376
|
const signature = sign(signingInput, secret);
|
|
377
377
|
return `${signingInput}.${signature}`;
|
|
@@ -390,17 +390,17 @@ function verifyTenantToken(token, secret, options = {}) {
|
|
|
390
390
|
let receivedBytes;
|
|
391
391
|
let expectedBytes;
|
|
392
392
|
try {
|
|
393
|
-
receivedBytes =
|
|
394
|
-
expectedBytes =
|
|
393
|
+
receivedBytes = _chunkD4SKSCIYcjs.base64UrlToBytes.call(void 0, receivedSignature);
|
|
394
|
+
expectedBytes = _chunkD4SKSCIYcjs.base64UrlToBytes.call(void 0, expectedSignature);
|
|
395
395
|
} catch (e) {
|
|
396
396
|
throw new Error("INVALID_TENANT_AUTH");
|
|
397
397
|
}
|
|
398
|
-
if (!
|
|
398
|
+
if (!_chunkD4SKSCIYcjs.timingSafeEqualBytes.call(void 0, receivedBytes, expectedBytes)) {
|
|
399
399
|
throw new Error("INVALID_TENANT_AUTH");
|
|
400
400
|
}
|
|
401
401
|
let payload;
|
|
402
402
|
try {
|
|
403
|
-
payload = JSON.parse(
|
|
403
|
+
payload = JSON.parse(_chunkD4SKSCIYcjs.utf8Decode.call(void 0, _chunkD4SKSCIYcjs.base64UrlToBytes.call(void 0, encodedPayload)));
|
|
404
404
|
} catch (e2) {
|
|
405
405
|
throw new Error("INVALID_TENANT_AUTH");
|
|
406
406
|
}
|
|
@@ -628,15 +628,15 @@ async function createReiServer(config) {
|
|
|
628
628
|
return {
|
|
629
629
|
handlers: {
|
|
630
630
|
initTenant: createInitTenantHandler(ctx),
|
|
631
|
-
getUserKey:
|
|
632
|
-
scheduleMessage:
|
|
631
|
+
getUserKey: _chunkD4SKSCIYcjs.createGetUserKeyHandler.call(void 0, ctx),
|
|
632
|
+
scheduleMessage: _chunkD4SKSCIYcjs.createScheduleMessageHandler.call(void 0, ctx),
|
|
633
633
|
sendNotifications: createSendNotificationsHandler(ctx),
|
|
634
|
-
updateMessage:
|
|
635
|
-
cancelMessage:
|
|
636
|
-
messages:
|
|
637
|
-
getMessage:
|
|
638
|
-
pushSubscription:
|
|
639
|
-
llmCredentials:
|
|
634
|
+
updateMessage: _chunkD4SKSCIYcjs.createUpdateMessageHandler.call(void 0, ctx),
|
|
635
|
+
cancelMessage: _chunkD4SKSCIYcjs.createCancelMessageHandler.call(void 0, ctx),
|
|
636
|
+
messages: _chunkD4SKSCIYcjs.createMessagesHandler.call(void 0, ctx),
|
|
637
|
+
getMessage: _chunkD4SKSCIYcjs.createGetMessageHandler.call(void 0, ctx),
|
|
638
|
+
pushSubscription: _chunkD4SKSCIYcjs.createPushSubscriptionHandler.call(void 0, ctx),
|
|
639
|
+
llmCredentials: _chunkD4SKSCIYcjs.createLlmCredentialsHandler.call(void 0, ctx)
|
|
640
640
|
}
|
|
641
641
|
};
|
|
642
642
|
}
|
|
@@ -705,4 +705,4 @@ async function createReiServer(config) {
|
|
|
705
705
|
|
|
706
706
|
|
|
707
707
|
|
|
708
|
-
exports.CORS_ALLOW_HEADERS =
|
|
708
|
+
exports.CORS_ALLOW_HEADERS = _chunkD4SKSCIYcjs.CORS_ALLOW_HEADERS; exports.CORS_ALLOW_METHODS = _chunkD4SKSCIYcjs.CORS_ALLOW_METHODS; exports.CRED_ID_MAX_LENGTH = _chunkD4SKSCIYcjs.CRED_ID_MAX_LENGTH; exports.CRED_PUT_BATCH_MAX = _chunkD4SKSCIYcjs.CRED_PUT_BATCH_MAX; exports.CRED_REFS_MAX_ENTRIES = _chunkD4SKSCIYcjs.CRED_REFS_MAX_ENTRIES; exports.CRED_ROWS_PER_USER_MAX = _chunkD4SKSCIYcjs.CRED_ROWS_PER_USER_MAX; exports.DEFAULT_CLAIM_LEASE_MS = _chunkD4SKSCIYcjs.DEFAULT_CLAIM_LEASE_MS; exports.DEFAULT_HEARTBEAT_LEASE_TTL_MS = _chunkD4SKSCIYcjs.DEFAULT_HEARTBEAT_LEASE_TTL_MS; exports.DEFAULT_LEASE_HEARTBEAT_MS = _chunkD4SKSCIYcjs.DEFAULT_LEASE_HEARTBEAT_MS; exports.DEFAULT_MAX_DELIVERY_RETRIES = _chunkD4SKSCIYcjs.DEFAULT_MAX_DELIVERY_RETRIES; exports.DEFAULT_MAX_REQUEST_BODY_BYTES = _chunkD4SKSCIYcjs.DEFAULT_MAX_REQUEST_BODY_BYTES; exports.DEFAULT_MAX_SCHEDULED_TASKS_PER_FIRE = _chunkD4SKSCIYcjs.DEFAULT_MAX_SCHEDULED_TASKS_PER_FIRE; exports.DEFAULT_MAX_TOOL_ITERATIONS = _chunkD4SKSCIYcjs.DEFAULT_MAX_TOOL_ITERATIONS; exports.DEFAULT_TOTAL_TIMEOUT_MS = _chunkD4SKSCIYcjs.DEFAULT_TOTAL_TIMEOUT_MS; exports.DeploymentConfigError = _chunkD4SKSCIYcjs.DeploymentConfigError; exports.MAX_DEFER_AFTER_MS = _chunkD4SKSCIYcjs.MAX_DEFER_AFTER_MS; exports.MAX_PUSH_PAYLOAD_BYTES = _chunkD4SKSCIYcjs.MAX_PUSH_PAYLOAD_BYTES; exports.MAX_TASK_PAYLOAD_BYTES = _chunkD4SKSCIYcjs.MAX_TASK_PAYLOAD_BYTES; exports.MIN_SCHEDULE_LEAD_MS = _chunkD4SKSCIYcjs.MIN_SCHEDULE_LEAD_MS; exports.NonRetryableError = _chunkD4SKSCIYcjs.NonRetryableError; exports.PUSH_ENVELOPE_RESERVED_BYTES = _chunkD4SKSCIYcjs.PUSH_ENVELOPE_RESERVED_BYTES; exports.SCHEMA_VERSION = _chunkD4SKSCIYcjs.SCHEMA_VERSION; exports.WEB_PUSH_ENCRYPTION_OVERHEAD_BYTES = _chunkD4SKSCIYcjs.WEB_PUSH_ENCRYPTION_OVERHEAD_BYTES; exports.WEB_PUSH_MAX_BODY_BYTES = _chunkD4SKSCIYcjs.WEB_PUSH_MAX_BODY_BYTES; exports.advanceOccurrence = _chunkD4SKSCIYcjs.advanceOccurrence; exports.createAdapter = createAdapter; exports.createD1Adapter = _chunkD4SKSCIYcjs.createD1Adapter; exports.createReiServer = createReiServer; exports.createSingleUserCloudflareWorker = _chunkD4SKSCIYcjs.createSingleUserCloudflareWorker; exports.createSingleUserServer = _chunkD4SKSCIYcjs.createSingleUserServer; exports.createTenantToken = createTenantToken; exports.createWebCryptoWebPush = _chunkD4SKSCIYcjs.createWebCryptoWebPush; exports.decryptFromStorage = _chunkD4SKSCIYcjs.decryptFromStorage; exports.decryptPayload = _chunkD4SKSCIYcjs.decryptPayload; exports.deriveUserEncryptionKey = _chunkD4SKSCIYcjs.deriveUserEncryptionKey; exports.encryptForStorage = _chunkD4SKSCIYcjs.encryptForStorage; exports.encryptPayload = _chunkD4SKSCIYcjs.encryptPayload; exports.ensureSchema = _chunkD4SKSCIYcjs.ensureSchema; exports.getSchemaVersion = _chunkD4SKSCIYcjs.getSchemaVersion; exports.hasChatCredRef = _chunkD4SKSCIYcjs.hasChatCredRef; exports.isNonRetryableError = _chunkD4SKSCIYcjs.isNonRetryableError; exports.isValidCredId = _chunkD4SKSCIYcjs.isValidCredId; exports.isValidISO8601 = _chunkD4SKSCIYcjs.isValidISO8601; exports.isValidTimeZoneId = _chunkD4SKSCIYcjs.isValidTimeZoneId; exports.isValidUUID = _chunkD4SKSCIYcjs.isValidUUID; exports.isValidUUIDv4 = _chunkD4SKSCIYcjs.isValidUUIDv4; exports.isValidUrl = _chunkD4SKSCIYcjs.isValidUrl; exports.measurePushPayload = _chunkD4SKSCIYcjs.measurePushPayload; exports.nextFutureOccurrence = _chunkD4SKSCIYcjs.nextFutureOccurrence; exports.planNextOccurrence = _chunkD4SKSCIYcjs.planNextOccurrence; exports.readRequestBody = _chunkD4SKSCIYcjs.readRequestBody; exports.resolveLlmCredential = _chunkD4SKSCIYcjs.resolveLlmCredential; exports.runScheduledTick = _chunkD4SKSCIYcjs.runScheduledTick; exports.runTask = _chunkD4SKSCIYcjs.runTask; exports.sanitizeErrorSummary = _chunkD4SKSCIYcjs.sanitizeErrorSummary; exports.summarizeErrorCause = _chunkD4SKSCIYcjs.summarizeErrorCause; exports.supportsLlmCredentialsStore = _chunkD4SKSCIYcjs.supportsLlmCredentialsStore; exports.validateAvatarUrl = _chunkD4SKSCIYcjs.validateAvatarUrl; exports.validateCredRefs = _chunkD4SKSCIYcjs.validateCredRefs; exports.validateCredValue = _chunkD4SKSCIYcjs.validateCredValue; exports.validateLlmMessagesArray = _chunkD4SKSCIYcjs.validateLlmMessagesArray; exports.validateScheduleMessagePayload = _chunkD4SKSCIYcjs.validateScheduleMessagePayload; exports.validateSplitPattern = _chunkD4SKSCIYcjs.validateSplitPattern; exports.verifyTenantToken = verifyTenantToken;
|
package/dist/index.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rei-standard/amsg-server",
|
|
3
|
-
"version": "3.1.0-next.
|
|
3
|
+
"version": "3.1.0-next.1",
|
|
4
4
|
"description": "ReiStandard Active Messaging server SDK with pluggable database adapters. Three-axis push schema (messageKind / messageType / messageSubtype) from @rei-standard/amsg-shared. Auto-emits ReasoningPush when the LLM response carries reasoning_content.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|