@threadbase-sh/streamer 1.56.0 → 1.58.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/cli.cjs +73 -6
- package/dist/cli.cjs.map +1 -1
- package/dist/index.cjs +73 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +26 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.js +73 -6
- package/dist/index.js.map +1 -1
- package/dist/runtime-migrations/004_add_device_e2ee.sql +47 -0
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -97011,7 +97011,12 @@ function toDeviceView(row) {
|
|
|
97011
97011
|
capabilities: parseCapabilities(row.capabilities),
|
|
97012
97012
|
createdAt: row.created_at,
|
|
97013
97013
|
lastSeenAt: row.last_seen_at,
|
|
97014
|
-
revokedAt: row.revoked_at
|
|
97014
|
+
revokedAt: row.revoked_at,
|
|
97015
|
+
// Reported from `e2ee_required` rather than from the key's presence. The
|
|
97016
|
+
// two agree today, but they answer different questions — the key is what a
|
|
97017
|
+
// handshake is checked against, `e2ee_required` is whether plaintext is
|
|
97018
|
+
// refused — and it is the second one a user is asking about.
|
|
97019
|
+
e2ee: row.e2ee_required === 1
|
|
97015
97020
|
};
|
|
97016
97021
|
}
|
|
97017
97022
|
var import_crypto3, DevicesRepository;
|
|
@@ -97029,13 +97034,29 @@ var init_devices_repository = __esm({
|
|
|
97029
97034
|
touchStmt;
|
|
97030
97035
|
deleteStmt;
|
|
97031
97036
|
deleteRevokedStmt;
|
|
97037
|
+
byE2eeStaticPubStmt;
|
|
97038
|
+
repairStmt;
|
|
97032
97039
|
constructor(db) {
|
|
97033
97040
|
this.insertStmt = db.prepare(`
|
|
97034
97041
|
INSERT INTO devices (
|
|
97035
|
-
device_id, public_key, token_hash, name, capabilities, created_at
|
|
97042
|
+
device_id, public_key, token_hash, name, capabilities, created_at,
|
|
97043
|
+
e2ee_static_pub, e2ee_required, e2ee_version
|
|
97036
97044
|
) VALUES (
|
|
97037
|
-
@device_id, @public_key, @token_hash, @name, @capabilities, @created_at
|
|
97045
|
+
@device_id, @public_key, @token_hash, @name, @capabilities, @created_at,
|
|
97046
|
+
@e2ee_static_pub, @e2ee_required, @e2ee_version
|
|
97038
97047
|
)
|
|
97048
|
+
`);
|
|
97049
|
+
this.byE2eeStaticPubStmt = db.prepare("SELECT * FROM devices WHERE e2ee_static_pub = ?");
|
|
97050
|
+
this.repairStmt = db.prepare(`
|
|
97051
|
+
UPDATE devices SET
|
|
97052
|
+
public_key = @public_key,
|
|
97053
|
+
token_hash = @token_hash,
|
|
97054
|
+
name = @name,
|
|
97055
|
+
capabilities = @capabilities,
|
|
97056
|
+
e2ee_required = 1,
|
|
97057
|
+
e2ee_version = @e2ee_version,
|
|
97058
|
+
revoked_at = NULL
|
|
97059
|
+
WHERE device_id = @device_id
|
|
97039
97060
|
`);
|
|
97040
97061
|
this.byTokenHashStmt = db.prepare("SELECT * FROM devices WHERE token_hash = ?");
|
|
97041
97062
|
this.byIdStmt = db.prepare("SELECT * FROM devices WHERE device_id = ?");
|
|
@@ -97052,19 +97073,42 @@ var init_devices_repository = __esm({
|
|
|
97052
97073
|
* moment it exists outside the client.
|
|
97053
97074
|
*/
|
|
97054
97075
|
register(args) {
|
|
97055
|
-
const deviceId = (0, import_crypto3.randomUUID)();
|
|
97056
97076
|
const deviceToken = generateDeviceToken();
|
|
97057
97077
|
const capabilities = capabilitiesForPreset(args.preset ?? "full");
|
|
97078
|
+
const now = args.now ?? Date.now();
|
|
97079
|
+
const existing = args.e2eeStaticPub ? this.byE2eeStaticPubStmt.get(args.e2eeStaticPub) : void 0;
|
|
97080
|
+
if (existing) {
|
|
97081
|
+
this.repairStmt.run({
|
|
97082
|
+
device_id: existing.device_id,
|
|
97083
|
+
public_key: args.publicKey,
|
|
97084
|
+
token_hash: hashDeviceToken(deviceToken),
|
|
97085
|
+
name: args.name ?? null,
|
|
97086
|
+
capabilities: JSON.stringify(capabilities),
|
|
97087
|
+
e2ee_version: args.e2eeVersion ?? null
|
|
97088
|
+
});
|
|
97089
|
+
return { deviceId: existing.device_id, deviceToken, capabilities };
|
|
97090
|
+
}
|
|
97091
|
+
const deviceId = (0, import_crypto3.randomUUID)();
|
|
97058
97092
|
this.insertStmt.run({
|
|
97059
97093
|
device_id: deviceId,
|
|
97060
97094
|
public_key: args.publicKey,
|
|
97061
97095
|
token_hash: hashDeviceToken(deviceToken),
|
|
97062
97096
|
name: args.name ?? null,
|
|
97063
97097
|
capabilities: JSON.stringify(capabilities),
|
|
97064
|
-
created_at:
|
|
97098
|
+
created_at: now,
|
|
97099
|
+
e2ee_static_pub: args.e2eeStaticPub ?? null,
|
|
97100
|
+
// The downgrade lock, set in the same write that records the key. Once
|
|
97101
|
+
// set, nothing a client can send clears it (design.md §6.3) — which is
|
|
97102
|
+
// what makes it a lock rather than a preference.
|
|
97103
|
+
e2ee_required: args.e2eeStaticPub ? 1 : 0,
|
|
97104
|
+
e2ee_version: args.e2eeVersion ?? null
|
|
97065
97105
|
});
|
|
97066
97106
|
return { deviceId, deviceToken, capabilities };
|
|
97067
97107
|
}
|
|
97108
|
+
/** The device that owns a Noise static key, or null. */
|
|
97109
|
+
getByE2eeStaticPub(staticPub) {
|
|
97110
|
+
return this.byE2eeStaticPubStmt.get(staticPub) ?? null;
|
|
97111
|
+
}
|
|
97068
97112
|
/**
|
|
97069
97113
|
* Resolve a presented token to a device, or null.
|
|
97070
97114
|
*
|
|
@@ -145659,6 +145703,7 @@ function readBody2(req) {
|
|
|
145659
145703
|
// src/api/handlers/conversations.handlers.ts
|
|
145660
145704
|
var SEARCH_OVERFETCH = 4;
|
|
145661
145705
|
var SEARCH_MAX_SCAN = 1e3;
|
|
145706
|
+
var MAX_BYTES_CEILING = 32 * 1024 * 1024;
|
|
145662
145707
|
var ConversationHandlers = class {
|
|
145663
145708
|
constructor(deps) {
|
|
145664
145709
|
this.deps = deps;
|
|
@@ -146064,7 +146109,7 @@ var ConversationHandlers = class {
|
|
|
146064
146109
|
const total = filtered.length;
|
|
146065
146110
|
const hasAnchor = url2.searchParams.has("anchor_index");
|
|
146066
146111
|
const hasAfter = url2.searchParams.has("after_index");
|
|
146067
|
-
const usePaging = url2.searchParams.has("msg_limit") || url2.searchParams.has("before_index") || hasAnchor || hasAfter;
|
|
146112
|
+
const usePaging = url2.searchParams.has("msg_limit") || url2.searchParams.has("before_index") || url2.searchParams.has("max_bytes") || hasAnchor || hasAfter;
|
|
146068
146113
|
let slice = filtered;
|
|
146069
146114
|
let fromIdx = 0;
|
|
146070
146115
|
let messagePagination;
|
|
@@ -146186,6 +146231,28 @@ var ConversationHandlers = class {
|
|
|
146186
146231
|
content
|
|
146187
146232
|
};
|
|
146188
146233
|
});
|
|
146234
|
+
const requestedMaxBytes = intParam(url2, "max_bytes", 0);
|
|
146235
|
+
if (requestedMaxBytes > 0 && messagesPayload.length > 0) {
|
|
146236
|
+
const budget = Math.min(requestedMaxBytes, MAX_BYTES_CEILING);
|
|
146237
|
+
let used = 0;
|
|
146238
|
+
let firstKept = messagesPayload.length - 1;
|
|
146239
|
+
for (let i = messagesPayload.length - 1; i >= 0; i--) {
|
|
146240
|
+
const size = Buffer.byteLength(JSON.stringify(messagesPayload[i]));
|
|
146241
|
+
if (i < messagesPayload.length - 1 && used + size > budget) break;
|
|
146242
|
+
used += size;
|
|
146243
|
+
firstKept = i;
|
|
146244
|
+
}
|
|
146245
|
+
if (firstKept > 0) {
|
|
146246
|
+
messagesPayload.splice(0, firstKept);
|
|
146247
|
+
if (messagePagination) {
|
|
146248
|
+
const newFrom = fromIdx + firstKept;
|
|
146249
|
+
messagePagination.from_index = newFrom;
|
|
146250
|
+
messagePagination.has_more_older = newFrom > 0;
|
|
146251
|
+
messagePagination.next_before_index = newFrom > 0 ? newFrom : null;
|
|
146252
|
+
}
|
|
146253
|
+
}
|
|
146254
|
+
if (messagePagination) messagePagination.served_bytes = used;
|
|
146255
|
+
}
|
|
146189
146256
|
const conv = conversation;
|
|
146190
146257
|
const cachedConvMeta = this.cache?.getMetaById(id);
|
|
146191
146258
|
const convProvider = coerceProviderForRunner(conv.provider ?? cachedConvMeta?.provider);
|