@shipfox/api-auth 17.0.0 → 19.0.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.
Files changed (99) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +44 -0
  3. package/README.md +24 -9
  4. package/dist/core/administration.d.ts +15 -0
  5. package/dist/core/administration.d.ts.map +1 -1
  6. package/dist/core/administration.js +44 -2
  7. package/dist/core/administration.js.map +1 -1
  8. package/dist/core/auth.d.ts.map +1 -1
  9. package/dist/core/auth.js +5 -3
  10. package/dist/core/auth.js.map +1 -1
  11. package/dist/core/entities/agent-access.d.ts +75 -0
  12. package/dist/core/entities/agent-access.d.ts.map +1 -0
  13. package/dist/core/entities/agent-access.js +3 -0
  14. package/dist/core/entities/agent-access.js.map +1 -0
  15. package/dist/core/errors.d.ts +3 -0
  16. package/dist/core/errors.d.ts.map +1 -1
  17. package/dist/core/errors.js +6 -0
  18. package/dist/core/errors.js.map +1 -1
  19. package/dist/core/runner-session-token.d.ts.map +1 -1
  20. package/dist/core/runner-session-token.js +2 -1
  21. package/dist/core/runner-session-token.js.map +1 -1
  22. package/dist/db/admin-user-moderation.d.ts.map +1 -1
  23. package/dist/db/admin-user-moderation.js +30 -26
  24. package/dist/db/admin-user-moderation.js.map +1 -1
  25. package/dist/db/admin-user-summary.d.ts +22 -0
  26. package/dist/db/admin-user-summary.d.ts.map +1 -1
  27. package/dist/db/admin-user-summary.js +75 -1
  28. package/dist/db/admin-user-summary.js.map +1 -1
  29. package/dist/db/admin-users.d.ts +11 -0
  30. package/dist/db/admin-users.d.ts.map +1 -1
  31. package/dist/db/admin-users.js +4 -1
  32. package/dist/db/admin-users.js.map +1 -1
  33. package/dist/db/agent-access.d.ts +159 -0
  34. package/dist/db/agent-access.d.ts.map +1 -0
  35. package/dist/db/agent-access.js +267 -0
  36. package/dist/db/agent-access.js.map +1 -0
  37. package/dist/db/db.d.ts +2604 -238
  38. package/dist/db/db.d.ts.map +1 -1
  39. package/dist/db/db.js +7 -0
  40. package/dist/db/db.js.map +1 -1
  41. package/dist/db/schema/agent-access.d.ts +1204 -0
  42. package/dist/db/schema/agent-access.d.ts.map +1 -0
  43. package/dist/db/schema/agent-access.js +267 -0
  44. package/dist/db/schema/agent-access.js.map +1 -0
  45. package/dist/db/schema/users.d.ts.map +1 -1
  46. package/dist/db/schema/users.js +8 -3
  47. package/dist/db/schema/users.js.map +1 -1
  48. package/dist/index.d.ts +3 -2
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/index.js +2 -2
  51. package/dist/index.js.map +1 -1
  52. package/dist/metrics/instance.d.ts +1 -1
  53. package/dist/metrics/instance.d.ts.map +1 -1
  54. package/dist/metrics/instance.js.map +1 -1
  55. package/dist/presentation/routes/administration.d.ts.map +1 -1
  56. package/dist/presentation/routes/administration.js +123 -20
  57. package/dist/presentation/routes/administration.js.map +1 -1
  58. package/dist/presentation/routes/email-verification/verify-email-resend.d.ts.map +1 -1
  59. package/dist/presentation/routes/email-verification/verify-email-resend.js +6 -1
  60. package/dist/presentation/routes/email-verification/verify-email-resend.js.map +1 -1
  61. package/dist/presentation/routes/rate-limit.d.ts.map +1 -1
  62. package/dist/presentation/routes/rate-limit.js +10 -0
  63. package/dist/presentation/routes/rate-limit.js.map +1 -1
  64. package/dist/presentation/routes/registration/signup.d.ts.map +1 -1
  65. package/dist/presentation/routes/registration/signup.js +59 -50
  66. package/dist/presentation/routes/registration/signup.js.map +1 -1
  67. package/dist/tsconfig.test.tsbuildinfo +1 -1
  68. package/drizzle/0003_brainy_luckman.sql +6 -0
  69. package/drizzle/0004_yummy_runaways.sql +110 -0
  70. package/drizzle/meta/0003_snapshot.json +844 -0
  71. package/drizzle/meta/0004_snapshot.json +1751 -0
  72. package/drizzle/meta/_journal.json +14 -0
  73. package/package.json +7 -7
  74. package/src/core/admin-role.test.ts +70 -0
  75. package/src/core/administration.ts +78 -1
  76. package/src/core/auth.ts +3 -5
  77. package/src/core/entities/agent-access.ts +80 -0
  78. package/src/core/errors.ts +7 -0
  79. package/src/core/runner-session-token.test.ts +2 -0
  80. package/src/core/runner-session-token.ts +1 -0
  81. package/src/db/admin-user-moderation.ts +53 -45
  82. package/src/db/admin-user-summary.test.ts +228 -0
  83. package/src/db/admin-user-summary.ts +143 -1
  84. package/src/db/admin-users.ts +21 -1
  85. package/src/db/agent-access.test.ts +370 -0
  86. package/src/db/agent-access.ts +629 -0
  87. package/src/db/db.ts +14 -0
  88. package/src/db/schema/agent-access.ts +273 -0
  89. package/src/db/schema/users.ts +9 -3
  90. package/src/index.ts +6 -0
  91. package/src/metrics/instance.ts +1 -0
  92. package/src/presentation/routes/administration.test.ts +359 -2
  93. package/src/presentation/routes/administration.ts +142 -20
  94. package/src/presentation/routes/email-verification/verify-email-resend.ts +7 -1
  95. package/src/presentation/routes/rate-limit.ts +4 -0
  96. package/src/presentation/routes/registration/signup.ts +52 -41
  97. package/test/globalSetup.ts +1 -1
  98. package/test/routes.ts +3 -1
  99. package/tsconfig.build.tsbuildinfo +1 -1
@@ -1,4 +1,6 @@
1
+ import { type TimestampIdCursor } from '@shipfox/node-drizzle';
1
2
  import type { AdministratorUserSummary } from '#core/entities/administrator-read-model.js';
3
+ import type { UserStatus } from '#core/entities/user.js';
2
4
  import type { db } from './db.js';
3
5
  type Tx = Parameters<Parameters<ReturnType<typeof db>['transaction']>[0]>[0];
4
6
  export type AdministratorUserSummaryExecutor = ReturnType<typeof db> | Tx;
@@ -9,6 +11,26 @@ type AdministratorUserLookup = {
9
11
  email: string;
10
12
  id?: never;
11
13
  };
14
+ export interface ListAdministratorUserSummariesParams {
15
+ actorId: string;
16
+ limit: number;
17
+ cursor?: TimestampIdCursor | undefined;
18
+ search?: string | undefined;
19
+ status?: UserStatus | undefined;
20
+ eligible?: boolean | undefined;
21
+ }
22
+ export interface ListAdministratorUserSummariesResult {
23
+ rows: AdministratorUserSummary[];
24
+ nextCursor: TimestampIdCursor | null;
25
+ }
12
26
  export declare function findAdministratorUserSummary(executor: AdministratorUserSummaryExecutor, params: AdministratorUserLookup): Promise<AdministratorUserSummary | undefined>;
27
+ /**
28
+ * Lists a live directory view using keyset pagination.
29
+ *
30
+ * Pages are not a consistent snapshot. Each page reads current account and grant state, so
31
+ * inserts and account or grant changes can make consecutive pages differ. Re-run the listing
32
+ * before acting on a row.
33
+ */
34
+ export declare function listAdministratorUserSummaries(executor: AdministratorUserSummaryExecutor, params: ListAdministratorUserSummariesParams): Promise<ListAdministratorUserSummariesResult>;
13
35
  export {};
14
36
  //# sourceMappingURL=admin-user-summary.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"admin-user-summary.d.ts","sourceRoot":"","sources":["../../src/db/admin-user-summary.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,wBAAwB,EAAC,MAAM,4CAA4C,CAAC;AACzF,OAAO,KAAK,EAAC,EAAE,EAAC,MAAM,SAAS,CAAC;AAIhC,KAAK,EAAE,GAAG,UAAU,CAAC,UAAU,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7E,MAAM,MAAM,gCAAgC,GAAG,UAAU,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,CAAC;AAE1E,KAAK,uBAAuB,GAAG;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,KAAK,CAAA;CAAC,GAAG;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,KAAK,CAAA;CAAC,CAAC;AAEzF,wBAAsB,4BAA4B,CAChD,QAAQ,EAAE,gCAAgC,EAC1C,MAAM,EAAE,uBAAuB,GAC9B,OAAO,CAAC,wBAAwB,GAAG,SAAS,CAAC,CAmC/C"}
1
+ {"version":3,"file":"admin-user-summary.d.ts","sourceRoot":"","sources":["../../src/db/admin-user-summary.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,iBAAiB,EAEvB,MAAM,uBAAuB,CAAC;AAe/B,OAAO,KAAK,EAAC,wBAAwB,EAAC,MAAM,4CAA4C,CAAC;AACzF,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,wBAAwB,CAAC;AACvD,OAAO,KAAK,EAAC,EAAE,EAAC,MAAM,SAAS,CAAC;AAIhC,KAAK,EAAE,GAAG,UAAU,CAAC,UAAU,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7E,MAAM,MAAM,gCAAgC,GAAG,UAAU,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,CAAC;AAE1E,KAAK,uBAAuB,GAAG;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,KAAK,CAAA;CAAC,GAAG;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,KAAK,CAAA;CAAC,CAAC;AAKzF,MAAM,WAAW,oCAAoC;IACnD,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;IACvC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,MAAM,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IAChC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAChC;AAED,MAAM,WAAW,oCAAoC;IACnD,IAAI,EAAE,wBAAwB,EAAE,CAAC;IACjC,UAAU,EAAE,iBAAiB,GAAG,IAAI,CAAC;CACtC;AA2CD,wBAAsB,4BAA4B,CAChD,QAAQ,EAAE,gCAAgC,EAC1C,MAAM,EAAE,uBAAuB,GAC9B,OAAO,CAAC,wBAAwB,GAAG,SAAS,CAAC,CAmC/C;AAED;;;;;;GAMG;AACH,wBAAsB,8BAA8B,CAClD,QAAQ,EAAE,gCAAgC,EAC1C,MAAM,EAAE,oCAAoC,GAC3C,OAAO,CAAC,oCAAoC,CAAC,CAqD/C"}
@@ -1,7 +1,36 @@
1
- import { and, eq, isNull } from 'drizzle-orm';
1
+ import { paginateTimestampIdRows, timestampIdCursorWhere } from '@shipfox/node-drizzle';
2
+ import { and, desc, eq, isNotNull, isNull, ne, not, or, sql } from 'drizzle-orm';
2
3
  import { highestAdminRole } from '#core/admin-role-model.js';
3
4
  import { adminGrants } from './schema/admin-grants.js';
4
5
  import { users } from './schema/users.js';
6
+ const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
7
+ const SEARCH_TERM_SEPARATOR = /\s+/;
8
+ function escapeLikeTerm(term) {
9
+ return term.replace(/[\\%_]/g, (character)=>`\\${character}`);
10
+ }
11
+ function isUuid(value) {
12
+ return UUID_PATTERN.test(value);
13
+ }
14
+ function containsTerm(column, term) {
15
+ return sql`${column} ILIKE ${`%${escapeLikeTerm(term)}%`}`;
16
+ }
17
+ function addEligibilityCondition(conditions, params, activeAdminRoleUserId) {
18
+ const eligibleCondition = and(eq(users.status, 'active'), isNotNull(users.emailVerifiedAt), isNull(activeAdminRoleUserId), ne(users.id, params.actorId));
19
+ if (eligibleCondition && params.eligible === true) conditions.push(eligibleCondition);
20
+ if (eligibleCondition && params.eligible === false) conditions.push(not(eligibleCondition));
21
+ }
22
+ function addSearchConditions(conditions, search) {
23
+ const normalizedSearch = search?.trim() ?? '';
24
+ if (!normalizedSearch) return;
25
+ if (isUuid(normalizedSearch)) {
26
+ conditions.push(eq(users.id, normalizedSearch));
27
+ return;
28
+ }
29
+ for (const term of normalizedSearch.split(SEARCH_TERM_SEPARATOR)){
30
+ const termCondition = or(containsTerm(users.name, term), containsTerm(users.email, term));
31
+ if (termCondition) conditions.push(termCondition);
32
+ }
33
+ }
5
34
  export async function findAdministratorUserSummary(executor, params) {
6
35
  const identifier = 'id' in params ? eq(users.id, params.id) : eq(users.email, params.email);
7
36
  const rows = await executor.select({
@@ -27,5 +56,50 @@ export async function findAdministratorUserSummary(executor, params) {
27
56
  ] : []))
28
57
  };
29
58
  }
59
+ /**
60
+ * Lists a live directory view using keyset pagination.
61
+ *
62
+ * Pages are not a consistent snapshot. Each page reads current account and grant state, so
63
+ * inserts and account or grant changes can make consecutive pages differ. Re-run the listing
64
+ * before acting on a row.
65
+ */ export async function listAdministratorUserSummaries(executor, params) {
66
+ // Aggregate grants in a subquery so pagination is over users, not grants.
67
+ const activeAdminRoles = executor.select({
68
+ userId: adminGrants.userId,
69
+ roles: sql`json_agg(${adminGrants.role})`.as('roles')
70
+ }).from(adminGrants).where(isNull(adminGrants.revokedAt)).groupBy(adminGrants.userId).as('active_admin_roles');
71
+ const conditions = [];
72
+ const cursorCondition = timestampIdCursorWhere({
73
+ timestampColumn: users.createdAt,
74
+ idColumn: users.id,
75
+ cursor: params.cursor
76
+ });
77
+ if (cursorCondition) conditions.push(cursorCondition);
78
+ if (params.status) conditions.push(eq(users.status, params.status));
79
+ addEligibilityCondition(conditions, params, activeAdminRoles.userId);
80
+ addSearchConditions(conditions, params.search);
81
+ const rows = await executor.select({
82
+ id: users.id,
83
+ email: users.email,
84
+ name: users.name,
85
+ emailVerifiedAt: users.emailVerifiedAt,
86
+ status: users.status,
87
+ createdAt: users.createdAt,
88
+ adminRoles: activeAdminRoles.roles
89
+ }).from(users).leftJoin(activeAdminRoles, eq(activeAdminRoles.userId, users.id)).where(and(...conditions)).orderBy(desc(users.createdAt), desc(users.id)).limit(params.limit + 1);
90
+ const mappedRows = rows.map(({ adminRoles, ...row })=>({
91
+ ...row,
92
+ adminRole: row.status === 'active' ? highestAdminRole(adminRoles ?? []) : null
93
+ }));
94
+ const page = paginateTimestampIdRows({
95
+ rows: mappedRows,
96
+ limit: params.limit,
97
+ timestampKey: 'createdAt'
98
+ });
99
+ return {
100
+ rows: page.pageRows,
101
+ nextCursor: page.nextCursor
102
+ };
103
+ }
30
104
 
31
105
  //# sourceMappingURL=admin-user-summary.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/db/admin-user-summary.ts"],"sourcesContent":["import {and, eq, isNull} from 'drizzle-orm';\nimport {highestAdminRole} from '#core/admin-role-model.js';\nimport type {AdministratorUserSummary} from '#core/entities/administrator-read-model.js';\nimport type {db} from './db.js';\nimport {adminGrants} from './schema/admin-grants.js';\nimport {users} from './schema/users.js';\n\ntype Tx = Parameters<Parameters<ReturnType<typeof db>['transaction']>[0]>[0];\nexport type AdministratorUserSummaryExecutor = ReturnType<typeof db> | Tx;\n\ntype AdministratorUserLookup = {id: string; email?: never} | {email: string; id?: never};\n\nexport async function findAdministratorUserSummary(\n executor: AdministratorUserSummaryExecutor,\n params: AdministratorUserLookup,\n): Promise<AdministratorUserSummary | undefined> {\n const identifier = 'id' in params ? eq(users.id, params.id) : eq(users.email, params.email);\n const rows = await executor\n .select({\n id: users.id,\n email: users.email,\n name: users.name,\n emailVerifiedAt: users.emailVerifiedAt,\n status: users.status,\n createdAt: users.createdAt,\n adminRole: adminGrants.role,\n })\n .from(users)\n .leftJoin(\n adminGrants,\n and(\n eq(adminGrants.userId, users.id),\n isNull(adminGrants.revokedAt),\n eq(users.status, 'active'),\n ),\n )\n .where(identifier);\n\n const first = rows[0];\n if (!first) return undefined;\n\n return {\n id: first.id,\n email: first.email,\n name: first.name,\n emailVerifiedAt: first.emailVerifiedAt,\n status: first.status,\n createdAt: first.createdAt,\n adminRole: highestAdminRole(rows.flatMap(({adminRole}) => (adminRole ? [adminRole] : []))),\n } satisfies AdministratorUserSummary;\n}\n"],"names":["and","eq","isNull","highestAdminRole","adminGrants","users","findAdministratorUserSummary","executor","params","identifier","id","email","rows","select","name","emailVerifiedAt","status","createdAt","adminRole","role","from","leftJoin","userId","revokedAt","where","first","undefined","flatMap"],"mappings":"AAAA,SAAQA,GAAG,EAAEC,EAAE,EAAEC,MAAM,QAAO,cAAc;AAC5C,SAAQC,gBAAgB,QAAO,4BAA4B;AAG3D,SAAQC,WAAW,QAAO,2BAA2B;AACrD,SAAQC,KAAK,QAAO,oBAAoB;AAOxC,OAAO,eAAeC,6BACpBC,QAA0C,EAC1CC,MAA+B;IAE/B,MAAMC,aAAa,QAAQD,SAASP,GAAGI,MAAMK,EAAE,EAAEF,OAAOE,EAAE,IAAIT,GAAGI,MAAMM,KAAK,EAAEH,OAAOG,KAAK;IAC1F,MAAMC,OAAO,MAAML,SAChBM,MAAM,CAAC;QACNH,IAAIL,MAAMK,EAAE;QACZC,OAAON,MAAMM,KAAK;QAClBG,MAAMT,MAAMS,IAAI;QAChBC,iBAAiBV,MAAMU,eAAe;QACtCC,QAAQX,MAAMW,MAAM;QACpBC,WAAWZ,MAAMY,SAAS;QAC1BC,WAAWd,YAAYe,IAAI;IAC7B,GACCC,IAAI,CAACf,OACLgB,QAAQ,CACPjB,aACAJ,IACEC,GAAGG,YAAYkB,MAAM,EAAEjB,MAAMK,EAAE,GAC/BR,OAAOE,YAAYmB,SAAS,GAC5BtB,GAAGI,MAAMW,MAAM,EAAE,YAGpBQ,KAAK,CAACf;IAET,MAAMgB,QAAQb,IAAI,CAAC,EAAE;IACrB,IAAI,CAACa,OAAO,OAAOC;IAEnB,OAAO;QACLhB,IAAIe,MAAMf,EAAE;QACZC,OAAOc,MAAMd,KAAK;QAClBG,MAAMW,MAAMX,IAAI;QAChBC,iBAAiBU,MAAMV,eAAe;QACtCC,QAAQS,MAAMT,MAAM;QACpBC,WAAWQ,MAAMR,SAAS;QAC1BC,WAAWf,iBAAiBS,KAAKe,OAAO,CAAC,CAAC,EAACT,SAAS,EAAC,GAAMA,YAAY;gBAACA;aAAU,GAAG,EAAE;IACzF;AACF"}
1
+ {"version":3,"sources":["../../src/db/admin-user-summary.ts"],"sourcesContent":["import type {AdminRole} from '@shipfox/api-auth-dto';\nimport {\n paginateTimestampIdRows,\n type TimestampIdCursor,\n timestampIdCursorWhere,\n} from '@shipfox/node-drizzle';\nimport {\n and,\n desc,\n eq,\n isNotNull,\n isNull,\n ne,\n not,\n or,\n type SQL,\n type SQLWrapper,\n sql,\n} from 'drizzle-orm';\nimport {highestAdminRole} from '#core/admin-role-model.js';\nimport type {AdministratorUserSummary} from '#core/entities/administrator-read-model.js';\nimport type {UserStatus} from '#core/entities/user.js';\nimport type {db} from './db.js';\nimport {adminGrants} from './schema/admin-grants.js';\nimport {users} from './schema/users.js';\n\ntype Tx = Parameters<Parameters<ReturnType<typeof db>['transaction']>[0]>[0];\nexport type AdministratorUserSummaryExecutor = ReturnType<typeof db> | Tx;\n\ntype AdministratorUserLookup = {id: string; email?: never} | {email: string; id?: never};\n\nconst UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\nconst SEARCH_TERM_SEPARATOR = /\\s+/;\n\nexport interface ListAdministratorUserSummariesParams {\n actorId: string;\n limit: number;\n cursor?: TimestampIdCursor | undefined;\n search?: string | undefined;\n status?: UserStatus | undefined;\n eligible?: boolean | undefined;\n}\n\nexport interface ListAdministratorUserSummariesResult {\n rows: AdministratorUserSummary[];\n nextCursor: TimestampIdCursor | null;\n}\n\nfunction escapeLikeTerm(term: string): string {\n return term.replace(/[\\\\%_]/g, (character) => `\\\\${character}`);\n}\n\nfunction isUuid(value: string): boolean {\n return UUID_PATTERN.test(value);\n}\n\nfunction containsTerm(column: SQLWrapper, term: string): SQLWrapper {\n return sql`${column} ILIKE ${`%${escapeLikeTerm(term)}%`}`;\n}\n\nfunction addEligibilityCondition(\n conditions: SQL[],\n params: Pick<ListAdministratorUserSummariesParams, 'actorId' | 'eligible'>,\n activeAdminRoleUserId: SQLWrapper,\n): void {\n const eligibleCondition = and(\n eq(users.status, 'active'),\n isNotNull(users.emailVerifiedAt),\n isNull(activeAdminRoleUserId),\n ne(users.id, params.actorId),\n );\n if (eligibleCondition && params.eligible === true) conditions.push(eligibleCondition);\n if (eligibleCondition && params.eligible === false) conditions.push(not(eligibleCondition));\n}\n\nfunction addSearchConditions(conditions: SQL[], search: string | undefined): void {\n const normalizedSearch = search?.trim() ?? '';\n if (!normalizedSearch) return;\n if (isUuid(normalizedSearch)) {\n conditions.push(eq(users.id, normalizedSearch));\n return;\n }\n\n for (const term of normalizedSearch.split(SEARCH_TERM_SEPARATOR)) {\n const termCondition = or(containsTerm(users.name, term), containsTerm(users.email, term));\n if (termCondition) conditions.push(termCondition);\n }\n}\n\nexport async function findAdministratorUserSummary(\n executor: AdministratorUserSummaryExecutor,\n params: AdministratorUserLookup,\n): Promise<AdministratorUserSummary | undefined> {\n const identifier = 'id' in params ? eq(users.id, params.id) : eq(users.email, params.email);\n const rows = await executor\n .select({\n id: users.id,\n email: users.email,\n name: users.name,\n emailVerifiedAt: users.emailVerifiedAt,\n status: users.status,\n createdAt: users.createdAt,\n adminRole: adminGrants.role,\n })\n .from(users)\n .leftJoin(\n adminGrants,\n and(\n eq(adminGrants.userId, users.id),\n isNull(adminGrants.revokedAt),\n eq(users.status, 'active'),\n ),\n )\n .where(identifier);\n\n const first = rows[0];\n if (!first) return undefined;\n\n return {\n id: first.id,\n email: first.email,\n name: first.name,\n emailVerifiedAt: first.emailVerifiedAt,\n status: first.status,\n createdAt: first.createdAt,\n adminRole: highestAdminRole(rows.flatMap(({adminRole}) => (adminRole ? [adminRole] : []))),\n } satisfies AdministratorUserSummary;\n}\n\n/**\n * Lists a live directory view using keyset pagination.\n *\n * Pages are not a consistent snapshot. Each page reads current account and grant state, so\n * inserts and account or grant changes can make consecutive pages differ. Re-run the listing\n * before acting on a row.\n */\nexport async function listAdministratorUserSummaries(\n executor: AdministratorUserSummaryExecutor,\n params: ListAdministratorUserSummariesParams,\n): Promise<ListAdministratorUserSummariesResult> {\n // Aggregate grants in a subquery so pagination is over users, not grants.\n const activeAdminRoles = executor\n .select({\n userId: adminGrants.userId,\n roles: sql<AdminRole[]>`json_agg(${adminGrants.role})`.as('roles'),\n })\n .from(adminGrants)\n .where(isNull(adminGrants.revokedAt))\n .groupBy(adminGrants.userId)\n .as('active_admin_roles');\n\n const conditions: SQL[] = [];\n const cursorCondition = timestampIdCursorWhere({\n timestampColumn: users.createdAt,\n idColumn: users.id,\n cursor: params.cursor,\n });\n if (cursorCondition) conditions.push(cursorCondition);\n if (params.status) conditions.push(eq(users.status, params.status));\n\n addEligibilityCondition(conditions, params, activeAdminRoles.userId);\n addSearchConditions(conditions, params.search);\n\n const rows = await executor\n .select({\n id: users.id,\n email: users.email,\n name: users.name,\n emailVerifiedAt: users.emailVerifiedAt,\n status: users.status,\n createdAt: users.createdAt,\n adminRoles: activeAdminRoles.roles,\n })\n .from(users)\n .leftJoin(activeAdminRoles, eq(activeAdminRoles.userId, users.id))\n .where(and(...conditions))\n .orderBy(desc(users.createdAt), desc(users.id))\n .limit(params.limit + 1);\n\n const mappedRows = rows.map(\n ({adminRoles, ...row}): AdministratorUserSummary => ({\n ...row,\n adminRole: row.status === 'active' ? highestAdminRole(adminRoles ?? []) : null,\n }),\n );\n const page = paginateTimestampIdRows({\n rows: mappedRows,\n limit: params.limit,\n timestampKey: 'createdAt',\n });\n\n return {rows: page.pageRows, nextCursor: page.nextCursor};\n}\n"],"names":["paginateTimestampIdRows","timestampIdCursorWhere","and","desc","eq","isNotNull","isNull","ne","not","or","sql","highestAdminRole","adminGrants","users","UUID_PATTERN","SEARCH_TERM_SEPARATOR","escapeLikeTerm","term","replace","character","isUuid","value","test","containsTerm","column","addEligibilityCondition","conditions","params","activeAdminRoleUserId","eligibleCondition","status","emailVerifiedAt","id","actorId","eligible","push","addSearchConditions","search","normalizedSearch","trim","split","termCondition","name","email","findAdministratorUserSummary","executor","identifier","rows","select","createdAt","adminRole","role","from","leftJoin","userId","revokedAt","where","first","undefined","flatMap","listAdministratorUserSummaries","activeAdminRoles","roles","as","groupBy","cursorCondition","timestampColumn","idColumn","cursor","adminRoles","orderBy","limit","mappedRows","map","row","page","timestampKey","pageRows","nextCursor"],"mappings":"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"}
@@ -1,4 +1,6 @@
1
+ import type { TimestampIdCursor } from '@shipfox/node-drizzle';
1
2
  import type { AdministratorUserSummary } from '#core/entities/administrator-read-model.js';
3
+ import { type ListAdministratorUserSummariesResult } from './admin-user-summary.js';
2
4
  export type AdministratorUserRecord = AdministratorUserSummary;
3
5
  type AdministratorUserLookup = {
4
6
  id: string;
@@ -8,5 +10,14 @@ type AdministratorUserLookup = {
8
10
  id?: never;
9
11
  };
10
12
  export declare function findAdministratorUser(params: AdministratorUserLookup): Promise<AdministratorUserRecord | undefined>;
13
+ export interface ListAdministratorUsersParams {
14
+ actorId: string;
15
+ limit: number;
16
+ cursor?: TimestampIdCursor | undefined;
17
+ search?: string | undefined;
18
+ status?: AdministratorUserSummary['status'] | undefined;
19
+ eligible?: boolean | undefined;
20
+ }
21
+ export declare function listAdministratorUsers(params: ListAdministratorUsersParams): Promise<ListAdministratorUserSummariesResult>;
11
22
  export {};
12
23
  //# sourceMappingURL=admin-users.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"admin-users.d.ts","sourceRoot":"","sources":["../../src/db/admin-users.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,wBAAwB,EAAC,MAAM,4CAA4C,CAAC;AAIzF,MAAM,MAAM,uBAAuB,GAAG,wBAAwB,CAAC;AAE/D,KAAK,uBAAuB,GAAG;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,KAAK,CAAA;CAAC,GAAG;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,KAAK,CAAA;CAAC,CAAC;AAEzF,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,uBAAuB,GAC9B,OAAO,CAAC,uBAAuB,GAAG,SAAS,CAAC,CAE9C"}
1
+ {"version":3,"file":"admin-users.d.ts","sourceRoot":"","sources":["../../src/db/admin-users.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAC,wBAAwB,EAAC,MAAM,4CAA4C,CAAC;AACzF,OAAO,EAEL,KAAK,oCAAoC,EAE1C,MAAM,yBAAyB,CAAC;AAGjC,MAAM,MAAM,uBAAuB,GAAG,wBAAwB,CAAC;AAE/D,KAAK,uBAAuB,GAAG;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,KAAK,CAAA;CAAC,GAAG;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,KAAK,CAAA;CAAC,CAAC;AAEzF,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,uBAAuB,GAC9B,OAAO,CAAC,uBAAuB,GAAG,SAAS,CAAC,CAE9C;AAED,MAAM,WAAW,4BAA4B;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;IACvC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,MAAM,CAAC,EAAE,wBAAwB,CAAC,QAAQ,CAAC,GAAG,SAAS,CAAC;IACxD,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAChC;AAED,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,4BAA4B,GACnC,OAAO,CAAC,oCAAoC,CAAC,CAE/C"}
@@ -1,7 +1,10 @@
1
- import { findAdministratorUserSummary } from './admin-user-summary.js';
1
+ import { findAdministratorUserSummary, listAdministratorUserSummaries } from './admin-user-summary.js';
2
2
  import { db } from './db.js';
3
3
  export async function findAdministratorUser(params) {
4
4
  return await findAdministratorUserSummary(db(), params);
5
5
  }
6
+ export async function listAdministratorUsers(params) {
7
+ return await listAdministratorUserSummaries(db(), params);
8
+ }
6
9
 
7
10
  //# sourceMappingURL=admin-users.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/db/admin-users.ts"],"sourcesContent":["import type {AdministratorUserSummary} from '#core/entities/administrator-read-model.js';\nimport {findAdministratorUserSummary} from './admin-user-summary.js';\nimport {db} from './db.js';\n\nexport type AdministratorUserRecord = AdministratorUserSummary;\n\ntype AdministratorUserLookup = {id: string; email?: never} | {email: string; id?: never};\n\nexport async function findAdministratorUser(\n params: AdministratorUserLookup,\n): Promise<AdministratorUserRecord | undefined> {\n return await findAdministratorUserSummary(db(), params);\n}\n"],"names":["findAdministratorUserSummary","db","findAdministratorUser","params"],"mappings":"AACA,SAAQA,4BAA4B,QAAO,0BAA0B;AACrE,SAAQC,EAAE,QAAO,UAAU;AAM3B,OAAO,eAAeC,sBACpBC,MAA+B;IAE/B,OAAO,MAAMH,6BAA6BC,MAAME;AAClD"}
1
+ {"version":3,"sources":["../../src/db/admin-users.ts"],"sourcesContent":["import type {TimestampIdCursor} from '@shipfox/node-drizzle';\nimport type {AdministratorUserSummary} from '#core/entities/administrator-read-model.js';\nimport {\n findAdministratorUserSummary,\n type ListAdministratorUserSummariesResult,\n listAdministratorUserSummaries,\n} from './admin-user-summary.js';\nimport {db} from './db.js';\n\nexport type AdministratorUserRecord = AdministratorUserSummary;\n\ntype AdministratorUserLookup = {id: string; email?: never} | {email: string; id?: never};\n\nexport async function findAdministratorUser(\n params: AdministratorUserLookup,\n): Promise<AdministratorUserRecord | undefined> {\n return await findAdministratorUserSummary(db(), params);\n}\n\nexport interface ListAdministratorUsersParams {\n actorId: string;\n limit: number;\n cursor?: TimestampIdCursor | undefined;\n search?: string | undefined;\n status?: AdministratorUserSummary['status'] | undefined;\n eligible?: boolean | undefined;\n}\n\nexport async function listAdministratorUsers(\n params: ListAdministratorUsersParams,\n): Promise<ListAdministratorUserSummariesResult> {\n return await listAdministratorUserSummaries(db(), params);\n}\n"],"names":["findAdministratorUserSummary","listAdministratorUserSummaries","db","findAdministratorUser","params","listAdministratorUsers"],"mappings":"AAEA,SACEA,4BAA4B,EAE5BC,8BAA8B,QACzB,0BAA0B;AACjC,SAAQC,EAAE,QAAO,UAAU;AAM3B,OAAO,eAAeC,sBACpBC,MAA+B;IAE/B,OAAO,MAAMJ,6BAA6BE,MAAME;AAClD;AAWA,OAAO,eAAeC,uBACpBD,MAAoC;IAEpC,OAAO,MAAMH,+BAA+BC,MAAME;AACpD"}
@@ -0,0 +1,159 @@
1
+ import type { AgentAuthorizationCode, AgentAuthorizationRequest, AgentClient, AgentGrant, AgentPersonalAccessToken, AgentRefreshToken } from '#core/entities/agent-access.js';
2
+ import { db } from './db.js';
3
+ export type AgentAccessTx = Parameters<Parameters<ReturnType<typeof db>['transaction']>[0]>[0];
4
+ type AgentAccessExecutor = ReturnType<typeof db> | AgentAccessTx;
5
+ export interface CreateAgentClientParams {
6
+ clientId: string;
7
+ name: string;
8
+ redirectUris: string[];
9
+ kind: 'registered' | 'cimd';
10
+ }
11
+ export declare function createAgentClient(params: CreateAgentClientParams): Promise<AgentClient>;
12
+ export declare function createAgentClientTx(tx: AgentAccessTx, params: CreateAgentClientParams): Promise<AgentClient>;
13
+ export declare function findAgentClientByClientId(params: {
14
+ clientId: string;
15
+ executor?: AgentAccessExecutor;
16
+ }): Promise<AgentClient | undefined>;
17
+ export declare function markAgentClientReferenced(tx: AgentAccessTx, params: {
18
+ clientUuid: string;
19
+ }): Promise<void>;
20
+ export declare function markAgentClientUnreferenced(tx: AgentAccessTx, params: {
21
+ clientUuid: string;
22
+ }): Promise<void>;
23
+ export interface CreateAgentAuthorizationRequestParams {
24
+ /** Internal `auth_agent_clients.id`, not the public OAuth `client_id`. */
25
+ clientId: string;
26
+ redirectUri: string;
27
+ resource: string;
28
+ scopes: string[];
29
+ codeChallenge: string;
30
+ state: string | null;
31
+ expiresAt: Date;
32
+ }
33
+ export declare function createAgentAuthorizationRequest(params: CreateAgentAuthorizationRequestParams): Promise<AgentAuthorizationRequest>;
34
+ export declare function createAgentAuthorizationRequestTx(tx: AgentAccessTx, params: CreateAgentAuthorizationRequestParams): Promise<AgentAuthorizationRequest>;
35
+ export declare function findPendingAgentAuthorizationRequest(params: {
36
+ id: string;
37
+ executor?: AgentAccessExecutor;
38
+ }): Promise<AgentAuthorizationRequest | undefined>;
39
+ export declare function consumeAgentAuthorizationRequest(params: {
40
+ id: string;
41
+ }): Promise<AgentAuthorizationRequest | undefined>;
42
+ /**
43
+ * Claims a pending request in the caller's transaction. The expiry and
44
+ * consumed-at predicates are part of the update so concurrent approval and
45
+ * denial can have only one winner.
46
+ */
47
+ export declare function consumeAgentAuthorizationRequestTx(tx: AgentAccessTx, params: {
48
+ id: string;
49
+ }): Promise<AgentAuthorizationRequest | undefined>;
50
+ export interface CreateAgentGrantParams {
51
+ userId: string;
52
+ workspaceId: string;
53
+ /** Internal `auth_agent_clients.id`, not the public OAuth `client_id`. */
54
+ clientId: string;
55
+ scopes: string[];
56
+ }
57
+ export declare function createAgentGrant(params: CreateAgentGrantParams): Promise<AgentGrant>;
58
+ export declare function createAgentGrantTx(tx: AgentAccessTx, params: CreateAgentGrantParams): Promise<AgentGrant>;
59
+ export declare function findAgentGrant(params: {
60
+ id: string;
61
+ executor?: AgentAccessExecutor;
62
+ }): Promise<AgentGrant | undefined>;
63
+ /**
64
+ * Locks one grant row until the surrounding transaction ends. Code exchange
65
+ * and lifecycle transitions must use this same primitive before inspecting or
66
+ * changing grant state. Callers must keep the transaction database-only while
67
+ * this lock is held; external I/O must happen after commit.
68
+ */
69
+ export declare function lockAgentGrant(tx: AgentAccessTx, params: {
70
+ grantId: string;
71
+ }): Promise<AgentGrant | undefined>;
72
+ export interface CreateAgentAuthorizationCodeParams {
73
+ grantId: string;
74
+ hashedCode: string;
75
+ codeChallenge: string;
76
+ redirectUri: string;
77
+ resource: string;
78
+ expiresAt: Date;
79
+ }
80
+ export declare function createAgentAuthorizationCode(params: CreateAgentAuthorizationCodeParams): Promise<AgentAuthorizationCode>;
81
+ export declare function createAgentAuthorizationCodeTx(tx: AgentAccessTx, params: CreateAgentAuthorizationCodeParams): Promise<AgentAuthorizationCode>;
82
+ export declare function findAgentAuthorizationCodeByHash(params: {
83
+ hashedCode: string;
84
+ executor?: AgentAccessExecutor;
85
+ }): Promise<AgentAuthorizationCode | undefined>;
86
+ export declare function findActiveAgentAuthorizationCodeByHash(params: {
87
+ hashedCode: string;
88
+ executor?: AgentAccessExecutor;
89
+ }): Promise<AgentAuthorizationCode | undefined>;
90
+ export declare function consumeAgentAuthorizationCode(params: {
91
+ hashedCode: string;
92
+ }): Promise<AgentAuthorizationCode | undefined>;
93
+ /** Claims an authorization code exactly once, including its 60-second TTL. */
94
+ export declare function consumeAgentAuthorizationCodeTx(tx: AgentAccessTx, params: {
95
+ hashedCode: string;
96
+ }): Promise<AgentAuthorizationCode | undefined>;
97
+ export interface CreateAgentRefreshTokenParams {
98
+ grantId: string;
99
+ hashedToken: string;
100
+ expiresAt: Date;
101
+ }
102
+ export declare function createAgentRefreshToken(params: CreateAgentRefreshTokenParams): Promise<AgentRefreshToken>;
103
+ export declare function createAgentRefreshTokenTx(tx: AgentAccessTx, params: CreateAgentRefreshTokenParams): Promise<AgentRefreshToken>;
104
+ export declare function findAgentRefreshTokenByHash(params: {
105
+ hashedToken: string;
106
+ executor?: AgentAccessExecutor;
107
+ }): Promise<AgentRefreshToken | undefined>;
108
+ export declare function findActiveAgentRefreshTokenByHash(params: {
109
+ hashedToken: string;
110
+ executor?: AgentAccessExecutor;
111
+ }): Promise<AgentRefreshToken | undefined>;
112
+ /** Rotates a refresh token atomically; a concurrent rotation cannot win twice. */
113
+ export declare function rotateAgentRefreshToken(params: {
114
+ hashedToken: string;
115
+ replacementHashedToken: string;
116
+ replacementExpiresAt: Date;
117
+ }): Promise<AgentRefreshToken | undefined>;
118
+ export declare function rotateAgentRefreshTokenTx(tx: AgentAccessTx, params: {
119
+ hashedToken: string;
120
+ replacementHashedToken: string;
121
+ replacementExpiresAt: Date;
122
+ }): Promise<AgentRefreshToken | undefined>;
123
+ export declare function revokeAgentRefreshToken(params: {
124
+ id: string;
125
+ }): Promise<AgentRefreshToken | undefined>;
126
+ export interface CreateAgentPersonalAccessTokenParams {
127
+ userId: string;
128
+ workspaceId: string;
129
+ hashedToken: string;
130
+ prefix: string;
131
+ name: string;
132
+ scopes: string[];
133
+ expiresAt: Date;
134
+ }
135
+ export declare function createAgentPersonalAccessToken(params: CreateAgentPersonalAccessTokenParams): Promise<AgentPersonalAccessToken>;
136
+ export declare function createAgentPersonalAccessTokenTx(tx: AgentAccessTx, params: CreateAgentPersonalAccessTokenParams): Promise<AgentPersonalAccessToken>;
137
+ export declare function findAgentPersonalAccessTokenByHash(params: {
138
+ hashedToken: string;
139
+ executor?: AgentAccessExecutor;
140
+ }): Promise<AgentPersonalAccessToken | undefined>;
141
+ export declare function findActiveAgentPersonalAccessTokenByHash(params: {
142
+ hashedToken: string;
143
+ executor?: AgentAccessExecutor;
144
+ }): Promise<AgentPersonalAccessToken | undefined>;
145
+ export declare function markAgentPersonalAccessTokenUsed(params: {
146
+ id: string;
147
+ }): Promise<AgentPersonalAccessToken | undefined>;
148
+ export declare function revokeAgentPersonalAccessToken(params: {
149
+ id: string;
150
+ }): Promise<AgentPersonalAccessToken | undefined>;
151
+ export interface PruneAgentAccessParams {
152
+ retentionDays?: number;
153
+ limit?: number;
154
+ now?: Date;
155
+ }
156
+ /** Deletes terminal credentials and ephemeral authorization rows in bounded batches. */
157
+ export declare function pruneAgentAccess(params?: PruneAgentAccessParams): Promise<number>;
158
+ export {};
159
+ //# sourceMappingURL=agent-access.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-access.d.ts","sourceRoot":"","sources":["../../src/db/agent-access.ts"],"names":[],"mappings":"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"}