@threadbase-sh/streamer 1.57.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/index.cjs CHANGED
@@ -4188,7 +4188,12 @@ function toDeviceView(row) {
4188
4188
  capabilities: parseCapabilities(row.capabilities),
4189
4189
  createdAt: row.created_at,
4190
4190
  lastSeenAt: row.last_seen_at,
4191
- revokedAt: row.revoked_at
4191
+ revokedAt: row.revoked_at,
4192
+ // Reported from `e2ee_required` rather than from the key's presence. The
4193
+ // two agree today, but they answer different questions — the key is what a
4194
+ // handshake is checked against, `e2ee_required` is whether plaintext is
4195
+ // refused — and it is the second one a user is asking about.
4196
+ e2ee: row.e2ee_required === 1
4192
4197
  };
4193
4198
  }
4194
4199
  var DevicesRepository = class {
@@ -4200,14 +4205,30 @@ var DevicesRepository = class {
4200
4205
  touchStmt;
4201
4206
  deleteStmt;
4202
4207
  deleteRevokedStmt;
4208
+ byE2eeStaticPubStmt;
4209
+ repairStmt;
4203
4210
  constructor(db) {
4204
4211
  this.insertStmt = db.prepare(`
4205
4212
  INSERT INTO devices (
4206
- device_id, public_key, token_hash, name, capabilities, created_at
4213
+ device_id, public_key, token_hash, name, capabilities, created_at,
4214
+ e2ee_static_pub, e2ee_required, e2ee_version
4207
4215
  ) VALUES (
4208
- @device_id, @public_key, @token_hash, @name, @capabilities, @created_at
4216
+ @device_id, @public_key, @token_hash, @name, @capabilities, @created_at,
4217
+ @e2ee_static_pub, @e2ee_required, @e2ee_version
4209
4218
  )
4210
4219
  `);
4220
+ this.byE2eeStaticPubStmt = db.prepare("SELECT * FROM devices WHERE e2ee_static_pub = ?");
4221
+ this.repairStmt = db.prepare(`
4222
+ UPDATE devices SET
4223
+ public_key = @public_key,
4224
+ token_hash = @token_hash,
4225
+ name = @name,
4226
+ capabilities = @capabilities,
4227
+ e2ee_required = 1,
4228
+ e2ee_version = @e2ee_version,
4229
+ revoked_at = NULL
4230
+ WHERE device_id = @device_id
4231
+ `);
4211
4232
  this.byTokenHashStmt = db.prepare("SELECT * FROM devices WHERE token_hash = ?");
4212
4233
  this.byIdStmt = db.prepare("SELECT * FROM devices WHERE device_id = ?");
4213
4234
  this.listStmt = db.prepare("SELECT * FROM devices ORDER BY created_at DESC");
@@ -4223,19 +4244,42 @@ var DevicesRepository = class {
4223
4244
  * moment it exists outside the client.
4224
4245
  */
4225
4246
  register(args) {
4226
- const deviceId = (0, import_crypto4.randomUUID)();
4227
4247
  const deviceToken = generateDeviceToken();
4228
4248
  const capabilities = capabilitiesForPreset(args.preset ?? "full");
4249
+ const now = args.now ?? Date.now();
4250
+ const existing = args.e2eeStaticPub ? this.byE2eeStaticPubStmt.get(args.e2eeStaticPub) : void 0;
4251
+ if (existing) {
4252
+ this.repairStmt.run({
4253
+ device_id: existing.device_id,
4254
+ public_key: args.publicKey,
4255
+ token_hash: hashDeviceToken(deviceToken),
4256
+ name: args.name ?? null,
4257
+ capabilities: JSON.stringify(capabilities),
4258
+ e2ee_version: args.e2eeVersion ?? null
4259
+ });
4260
+ return { deviceId: existing.device_id, deviceToken, capabilities };
4261
+ }
4262
+ const deviceId = (0, import_crypto4.randomUUID)();
4229
4263
  this.insertStmt.run({
4230
4264
  device_id: deviceId,
4231
4265
  public_key: args.publicKey,
4232
4266
  token_hash: hashDeviceToken(deviceToken),
4233
4267
  name: args.name ?? null,
4234
4268
  capabilities: JSON.stringify(capabilities),
4235
- created_at: args.now ?? Date.now()
4269
+ created_at: now,
4270
+ e2ee_static_pub: args.e2eeStaticPub ?? null,
4271
+ // The downgrade lock, set in the same write that records the key. Once
4272
+ // set, nothing a client can send clears it (design.md §6.3) — which is
4273
+ // what makes it a lock rather than a preference.
4274
+ e2ee_required: args.e2eeStaticPub ? 1 : 0,
4275
+ e2ee_version: args.e2eeVersion ?? null
4236
4276
  });
4237
4277
  return { deviceId, deviceToken, capabilities };
4238
4278
  }
4279
+ /** The device that owns a Noise static key, or null. */
4280
+ getByE2eeStaticPub(staticPub) {
4281
+ return this.byE2eeStaticPubStmt.get(staticPub) ?? null;
4282
+ }
4239
4283
  /**
4240
4284
  * Resolve a presented token to a device, or null.
4241
4285
  *