@atproto/pds 0.4.135 → 0.4.136

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @atproto/pds
2
2
 
3
+ ## 0.4.136
4
+
5
+ ### Patch Changes
6
+
7
+ - [#3840](https://github.com/bluesky-social/atproto/pull/3840) [`088d06204`](https://github.com/bluesky-social/atproto/commit/088d06204f779412b94ae3363ff548a6c8d1299a) Thanks [@devinivy](https://github.com/devinivy)! - fix account management migration 005.
8
+
3
9
  ## 0.4.135
4
10
 
5
11
  ### Patch Changes
package/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  Dual MIT/Apache-2.0 License
2
2
 
3
- Copyright (c) 2022-2025 Bluesky PBC, and Contributors
3
+ Copyright (c) 2022-2025 Bluesky Social PBC, and Contributors
4
4
 
5
5
  Except as otherwise noted in individual files, this software is licensed under the MIT license (<http://opensource.org/licenses/MIT>), or the Apache License, Version 2.0 (<http://www.apache.org/licenses/LICENSE-2.0>).
6
6
 
@@ -2,6 +2,9 @@ import { Kysely } from 'kysely';
2
2
  import { ClientId, DeviceId } from '@atproto/oauth-provider';
3
3
  import { DateISO, JsonEncoded } from '../../../db';
4
4
  export declare function up(db: Kysely<{
5
+ account: {
6
+ did: string;
7
+ };
5
8
  device_account: {
6
9
  did: string;
7
10
  deviceId: DeviceId;
@@ -1 +1 @@
1
- {"version":3,"file":"005-oauth-account-management.d.ts","sourceRoot":"","sources":["../../../../src/account-manager/db/migrations/005-oauth-account-management.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAC5D,OAAO,EAAE,OAAO,EAAE,WAAW,EAAa,MAAM,aAAa,CAAA;AAE7D,wBAAsB,EAAE,CACtB,EAAE,EAAE,MAAM,CAAC;IACT,cAAc,EAAE;QACd,GAAG,EAAE,MAAM,CAAA;QACX,QAAQ,EAAE,QAAQ,CAAA;QAElB,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAA;QACf,eAAe,EAAE,MAAM,CAAA;QACvB,iBAAiB,EAAE,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAA;KAC3C,CAAA;IACD,cAAc,EAAE;QACd,GAAG,EAAE,MAAM,CAAA;QACX,QAAQ,EAAE,QAAQ,CAAA;QAElB,SAAS,EAAE,OAAO,CAAA;QAClB,SAAS,EAAE,OAAO,CAAA;KACnB,CAAA;CACF,CAAC,GACD,OAAO,CAAC,IAAI,CAAC,CAmFf;AAED,wBAAsB,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAG7D"}
1
+ {"version":3,"file":"005-oauth-account-management.d.ts","sourceRoot":"","sources":["../../../../src/account-manager/db/migrations/005-oauth-account-management.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAC5D,OAAO,EAAE,OAAO,EAAE,WAAW,EAAa,MAAM,aAAa,CAAA;AAU7D,wBAAsB,EAAE,CACtB,EAAE,EAAE,MAAM,CAAC;IACT,OAAO,EAAE;QACP,GAAG,EAAE,MAAM,CAAA;KACZ,CAAA;IACD,cAAc,EAAE;QACd,GAAG,EAAE,MAAM,CAAA;QACX,QAAQ,EAAE,QAAQ,CAAA;QAElB,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAA;QACf,eAAe,EAAE,MAAM,CAAA;QACvB,iBAAiB,EAAE,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAA;KAC3C,CAAA;IACD,cAAc,EAAE;QACd,GAAG,EAAE,MAAM,CAAA;QACX,QAAQ,EAAE,QAAQ,CAAA;QAElB,SAAS,EAAE,OAAO,CAAA;QAClB,SAAS,EAAE,OAAO,CAAA;KACnB,CAAA;CACF,CAAC,GACD,OAAO,CAAC,IAAI,CAAC,CA+Ff;AAED,wBAAsB,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAG7D"}
@@ -4,16 +4,26 @@ exports.up = up;
4
4
  exports.down = down;
5
5
  const common_1 = require("@atproto/common");
6
6
  const db_1 = require("../../../db");
7
+ // @NOTE this migration has been updated to be idempotent through
8
+ // the insertInto('account_device') step. this allows users to roll
9
+ // forward if the migration partially succeeded on first run, failing
10
+ // on a fk constraint during the insertInto('account_device') step.
11
+ // this previously occurred under the following conditions:
12
+ // a. a user was deleted
13
+ // b. this user used oauth functionality with "remember me" selected.
7
14
  async function up(db) {
8
15
  // Security: Delete any leftover device accounts that are not remembered
16
+ // @NOTE idempotent, see note at top of migration.
9
17
  await db
10
18
  .deleteFrom('device_account')
11
19
  .where('remember', '=', 0)
12
20
  .where('authenticatedAt', '<', (0, db_1.toDateISO)(new Date(Date.now() - common_1.HOUR)))
13
21
  .execute();
14
22
  // replaces "device_account"
23
+ // @NOTE idempotent from ifNotExists(), see note at top of migration.
15
24
  await db.schema
16
25
  .createTable('account_device')
26
+ .ifNotExists()
17
27
  .addColumn('did', 'varchar', (col) => col.notNull())
18
28
  .addColumn('deviceId', 'varchar', (col) => col.notNull())
19
29
  .addColumn('createdAt', 'varchar', (col) => col.notNull())
@@ -30,6 +40,7 @@ async function up(db) {
30
40
  (qb) => qb.onDelete('cascade').onUpdate('cascade'))
31
41
  .execute();
32
42
  // Migrate "device_account" to "account_device"
43
+ // @NOTE idempotent from onConflict(): see note at top of migration.
33
44
  await db
34
45
  .insertInto('account_device')
35
46
  .columns(['did', 'deviceId', 'createdAt', 'updatedAt'])
@@ -39,7 +50,14 @@ async function up(db) {
39
50
  .select('deviceId')
40
51
  .select('authenticatedAt as createdAt') // Best we can do
41
52
  .select('authenticatedAt as updatedAt')
42
- .where('remember', '=', 1))
53
+ .where('remember', '=', 1)
54
+ .whereExists((qb) =>
55
+ // device_account does not have fkey on account.did,
56
+ // so we satisfy account_device_did_fk with this condition.
57
+ qb
58
+ .selectFrom('account')
59
+ .selectAll()
60
+ .whereRef('account.did', '=', 'device_account.did')))
43
61
  .onConflict((oc) => oc.doNothing())
44
62
  .execute();
45
63
  // @NOTE No need to create an index on "deviceId" for "account_device" because
@@ -1 +1 @@
1
- {"version":3,"file":"005-oauth-account-management.js","sourceRoot":"","sources":["../../../../src/account-manager/db/migrations/005-oauth-account-management.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"005-oauth-account-management.js","sourceRoot":"","sources":["../../../../src/account-manager/db/migrations/005-oauth-account-management.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atproto/pds",
3
- "version": "0.4.135",
3
+ "version": "0.4.136",
4
4
  "license": "MIT",
5
5
  "description": "Reference implementation of atproto Personal Data Server (PDS)",
6
6
  "keywords": [
@@ -79,7 +79,7 @@
79
79
  "ws": "^8.12.0",
80
80
  "@atproto/api": "^0.15.6",
81
81
  "@atproto/bsky": "^0.0.148",
82
- "@atproto/dev-env": "^0.3.129",
82
+ "@atproto/dev-env": "^0.3.130",
83
83
  "@atproto/lex-cli": "^0.8.1",
84
84
  "@atproto/oauth-client-browser-example": "0.0.3"
85
85
  },
@@ -3,8 +3,19 @@ import { HOUR } from '@atproto/common'
3
3
  import { ClientId, DeviceId } from '@atproto/oauth-provider'
4
4
  import { DateISO, JsonEncoded, toDateISO } from '../../../db'
5
5
 
6
+ // @NOTE this migration has been updated to be idempotent through
7
+ // the insertInto('account_device') step. this allows users to roll
8
+ // forward if the migration partially succeeded on first run, failing
9
+ // on a fk constraint during the insertInto('account_device') step.
10
+ // this previously occurred under the following conditions:
11
+ // a. a user was deleted
12
+ // b. this user used oauth functionality with "remember me" selected.
13
+
6
14
  export async function up(
7
15
  db: Kysely<{
16
+ account: {
17
+ did: string
18
+ }
8
19
  device_account: {
9
20
  did: string
10
21
  deviceId: DeviceId
@@ -23,6 +34,7 @@ export async function up(
23
34
  }>,
24
35
  ): Promise<void> {
25
36
  // Security: Delete any leftover device accounts that are not remembered
37
+ // @NOTE idempotent, see note at top of migration.
26
38
  await db
27
39
  .deleteFrom('device_account')
28
40
  .where('remember', '=', 0)
@@ -30,8 +42,10 @@ export async function up(
30
42
  .execute()
31
43
 
32
44
  // replaces "device_account"
45
+ // @NOTE idempotent from ifNotExists(), see note at top of migration.
33
46
  await db.schema
34
47
  .createTable('account_device')
48
+ .ifNotExists()
35
49
  .addColumn('did', 'varchar', (col) => col.notNull())
36
50
  .addColumn('deviceId', 'varchar', (col) => col.notNull())
37
51
  .addColumn('createdAt', 'varchar', (col) => col.notNull())
@@ -59,6 +73,7 @@ export async function up(
59
73
  .execute()
60
74
 
61
75
  // Migrate "device_account" to "account_device"
76
+ // @NOTE idempotent from onConflict(): see note at top of migration.
62
77
  await db
63
78
  .insertInto('account_device')
64
79
  .columns(['did', 'deviceId', 'createdAt', 'updatedAt'])
@@ -69,7 +84,15 @@ export async function up(
69
84
  .select('deviceId')
70
85
  .select('authenticatedAt as createdAt') // Best we can do
71
86
  .select('authenticatedAt as updatedAt')
72
- .where('remember', '=', 1),
87
+ .where('remember', '=', 1)
88
+ .whereExists((qb) =>
89
+ // device_account does not have fkey on account.did,
90
+ // so we satisfy account_device_did_fk with this condition.
91
+ qb
92
+ .selectFrom('account')
93
+ .selectAll()
94
+ .whereRef('account.did', '=', 'device_account.did'),
95
+ ),
73
96
  )
74
97
  .onConflict((oc) => oc.doNothing())
75
98
  .execute()