@shipfox/api-auth 9.2.0 → 9.3.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 (71) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +21 -0
  3. package/README.md +25 -8
  4. package/dist/config.d.ts +1 -0
  5. package/dist/config.d.ts.map +1 -1
  6. package/dist/config.js +4 -0
  7. package/dist/config.js.map +1 -1
  8. package/dist/core/administration.d.ts +27 -0
  9. package/dist/core/administration.d.ts.map +1 -0
  10. package/dist/core/administration.js +122 -0
  11. package/dist/core/administration.js.map +1 -0
  12. package/dist/core/auth.d.ts.map +1 -1
  13. package/dist/core/auth.js +2 -5
  14. package/dist/core/auth.js.map +1 -1
  15. package/dist/core/errors.d.ts +15 -0
  16. package/dist/core/errors.d.ts.map +1 -1
  17. package/dist/core/errors.js +30 -0
  18. package/dist/core/errors.js.map +1 -1
  19. package/dist/db/admin-grants.d.ts +18 -0
  20. package/dist/db/admin-grants.d.ts.map +1 -1
  21. package/dist/db/admin-grants.js +145 -1
  22. package/dist/db/admin-grants.js.map +1 -1
  23. package/dist/db/db.d.ts +256 -0
  24. package/dist/db/db.d.ts.map +1 -1
  25. package/dist/db/db.js +2 -0
  26. package/dist/db/db.js.map +1 -1
  27. package/dist/db/schema/admin-command-results.d.ts +142 -0
  28. package/dist/db/schema/admin-command-results.d.ts.map +1 -0
  29. package/dist/db/schema/admin-command-results.js +21 -0
  30. package/dist/db/schema/admin-command-results.js.map +1 -0
  31. package/dist/index.d.ts +2 -1
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +11 -3
  34. package/dist/index.js.map +1 -1
  35. package/dist/metrics/instance.d.ts +1 -1
  36. package/dist/metrics/instance.d.ts.map +1 -1
  37. package/dist/metrics/instance.js.map +1 -1
  38. package/dist/presentation/routes/administration.d.ts +3 -0
  39. package/dist/presentation/routes/administration.d.ts.map +1 -0
  40. package/dist/presentation/routes/administration.js +186 -0
  41. package/dist/presentation/routes/administration.js.map +1 -0
  42. package/dist/presentation/routes/rate-limit.d.ts +1 -0
  43. package/dist/presentation/routes/rate-limit.d.ts.map +1 -1
  44. package/dist/presentation/routes/rate-limit.js +20 -1
  45. package/dist/presentation/routes/rate-limit.js.map +1 -1
  46. package/dist/tsconfig.test.tsbuildinfo +1 -1
  47. package/drizzle/0002_burly_whizzer.sql +12 -0
  48. package/drizzle/meta/0002_snapshot.json +791 -0
  49. package/drizzle/meta/_journal.json +7 -0
  50. package/package.json +10 -9
  51. package/src/config.ts +4 -0
  52. package/src/core/administration.ts +172 -0
  53. package/src/core/auth-default-signup-policy.test.ts +65 -0
  54. package/src/core/auth.test.ts +5 -0
  55. package/src/core/auth.ts +2 -3
  56. package/src/core/errors.ts +35 -0
  57. package/src/db/admin-grants.ts +258 -1
  58. package/src/db/db.ts +2 -0
  59. package/src/db/schema/admin-command-results.ts +41 -0
  60. package/src/index.test.ts +6 -2
  61. package/src/index.ts +20 -2
  62. package/src/metrics/instance.ts +1 -1
  63. package/src/presentation/auth/refresh-cookie.test.ts +4 -0
  64. package/src/presentation/e2eRoutes/index.test.ts +1 -0
  65. package/src/presentation/routes/administration.test.ts +253 -0
  66. package/src/presentation/routes/administration.ts +195 -0
  67. package/src/presentation/routes/index.test.ts +1 -0
  68. package/src/presentation/routes/rate-limit.ts +23 -2
  69. package/test/globalSetup.ts +6 -2
  70. package/test/routes.ts +7 -1
  71. package/tsconfig.build.tsbuildinfo +1 -1
@@ -79,6 +79,36 @@ export class LastAdminOwnerError extends Error {
79
79
  this.name = 'LastAdminOwnerError';
80
80
  }
81
81
  }
82
+ export class AdminGrantNotFoundError extends Error {
83
+ constructor(){
84
+ super('Administrator grant not found');
85
+ this.name = 'AdminGrantNotFoundError';
86
+ }
87
+ }
88
+ export class AdminGrantAlreadyExistsError extends Error {
89
+ constructor(){
90
+ super('Administrator grant already exists');
91
+ this.name = 'AdminGrantAlreadyExistsError';
92
+ }
93
+ }
94
+ export class AdminBootstrapClosedError extends Error {
95
+ constructor(){
96
+ super('First administrator owner has already been created');
97
+ this.name = 'AdminBootstrapClosedError';
98
+ }
99
+ }
100
+ export class InvalidAdminBootstrapTokenError extends Error {
101
+ constructor(){
102
+ super('Bootstrap token is invalid');
103
+ this.name = 'InvalidAdminBootstrapTokenError';
104
+ }
105
+ }
106
+ export class AdminIdempotencyKeyReuseError extends Error {
107
+ constructor(){
108
+ super('Idempotency key was already used for a different command');
109
+ this.name = 'AdminIdempotencyKeyReuseError';
110
+ }
111
+ }
82
112
  export class TokenInvalidError extends Error {
83
113
  constructor(reason){
84
114
  super(reason ? `Invalid token: ${reason}` : 'Invalid token');
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/errors.ts"],"sourcesContent":["export class WorkspaceNotFoundError extends Error {\n constructor(workspaceId: string) {\n super(`Workspace not found: ${workspaceId}`);\n this.name = 'WorkspaceNotFoundError';\n }\n}\n\nexport class ApiKeyNotFoundError extends Error {\n constructor(id: string) {\n super(`API key not found: ${id}`);\n this.name = 'ApiKeyNotFoundError';\n }\n}\n\nexport class InvitationNotFoundError extends Error {\n constructor(id: string) {\n super(`Invitation not found: ${id}`);\n this.name = 'InvitationNotFoundError';\n }\n}\n\nexport class InvitationWorkspaceMismatchError extends Error {\n constructor() {\n super('Invitation does not belong to this workspace');\n this.name = 'InvitationWorkspaceMismatchError';\n }\n}\n\nexport class MembershipNotFoundError extends Error {\n constructor(userId: string, workspaceId: string) {\n super(`Membership not found for user ${userId} in workspace ${workspaceId}`);\n this.name = 'MembershipNotFoundError';\n }\n}\n\nexport class UserNotFoundError extends Error {\n constructor(idOrEmail: string) {\n super(`User not found: ${idOrEmail}`);\n this.name = 'UserNotFoundError';\n }\n}\n\nexport class EmailTakenError extends Error {\n constructor(email: string) {\n super(`Email already registered: ${email}`);\n this.name = 'EmailTakenError';\n }\n}\n\nexport class SignupNotAllowedError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'SignupNotAllowedError';\n }\n}\n\nexport class InvalidCredentialsError extends Error {\n constructor() {\n super('Invalid credentials');\n this.name = 'InvalidCredentialsError';\n }\n}\n\nexport class EmailNotVerifiedError extends Error {\n constructor() {\n super('Email not verified');\n this.name = 'EmailNotVerifiedError';\n }\n}\n\nexport class AuthDependencyUnavailableError extends Error {\n readonly dependency: string;\n override readonly cause: unknown;\n\n constructor(dependency: string, cause: unknown) {\n super(`Authentication dependency unavailable: ${dependency}`);\n this.name = 'AuthDependencyUnavailableError';\n this.dependency = dependency;\n this.cause = cause;\n }\n}\n\nexport class AdminRoleRequiredError extends Error {\n readonly minimumRole: import('@shipfox/api-auth-dto').AdminRole;\n\n constructor(minimumRole: import('@shipfox/api-auth-dto').AdminRole) {\n super(`Administrator role required: ${minimumRole}`);\n this.name = 'AdminRoleRequiredError';\n this.minimumRole = minimumRole;\n }\n}\n\nexport class LastAdminOwnerError extends Error {\n constructor() {\n super('Cannot remove the final active administrator owner');\n this.name = 'LastAdminOwnerError';\n }\n}\n\nexport class TokenInvalidError extends Error {\n constructor(reason?: string) {\n super(reason ? `Invalid token: ${reason}` : 'Invalid token');\n this.name = 'TokenInvalidError';\n }\n}\n\nexport class TokenExpiredError extends Error {\n constructor() {\n super('Token has expired');\n this.name = 'TokenExpiredError';\n }\n}\n\nexport class TokenAlreadyUsedError extends Error {\n constructor() {\n super('Token has already been used');\n this.name = 'TokenAlreadyUsedError';\n }\n}\n\nexport class MembershipRequiredError extends Error {\n constructor(workspaceId: string) {\n super(`Membership required for workspace: ${workspaceId}`);\n this.name = 'MembershipRequiredError';\n }\n}\n\nexport class LastMemberError extends Error {\n constructor(workspaceId: string) {\n super(`Cannot remove the last member of workspace: ${workspaceId}`);\n this.name = 'LastMemberError';\n }\n}\n\nexport class InvitationEmailMismatchError extends Error {\n constructor() {\n super('Invitation email does not match authenticated user');\n this.name = 'InvitationEmailMismatchError';\n }\n}\n\nexport class OpenInvitationExistsError extends Error {\n constructor(email: string) {\n super(`An open invitation already exists for: ${email}`);\n this.name = 'OpenInvitationExistsError';\n }\n}\n"],"names":["WorkspaceNotFoundError","Error","workspaceId","name","ApiKeyNotFoundError","id","InvitationNotFoundError","InvitationWorkspaceMismatchError","MembershipNotFoundError","userId","UserNotFoundError","idOrEmail","EmailTakenError","email","SignupNotAllowedError","message","InvalidCredentialsError","EmailNotVerifiedError","AuthDependencyUnavailableError","dependency","cause","AdminRoleRequiredError","minimumRole","LastAdminOwnerError","TokenInvalidError","reason","TokenExpiredError","TokenAlreadyUsedError","MembershipRequiredError","LastMemberError","InvitationEmailMismatchError","OpenInvitationExistsError"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/core/errors.ts"],"sourcesContent":["export class WorkspaceNotFoundError extends Error {\n constructor(workspaceId: string) {\n super(`Workspace not found: ${workspaceId}`);\n this.name = 'WorkspaceNotFoundError';\n }\n}\n\nexport class ApiKeyNotFoundError extends Error {\n constructor(id: string) {\n super(`API key not found: ${id}`);\n this.name = 'ApiKeyNotFoundError';\n }\n}\n\nexport class InvitationNotFoundError extends Error {\n constructor(id: string) {\n super(`Invitation not found: ${id}`);\n this.name = 'InvitationNotFoundError';\n }\n}\n\nexport class InvitationWorkspaceMismatchError extends Error {\n constructor() {\n super('Invitation does not belong to this workspace');\n this.name = 'InvitationWorkspaceMismatchError';\n }\n}\n\nexport class MembershipNotFoundError extends Error {\n constructor(userId: string, workspaceId: string) {\n super(`Membership not found for user ${userId} in workspace ${workspaceId}`);\n this.name = 'MembershipNotFoundError';\n }\n}\n\nexport class UserNotFoundError extends Error {\n constructor(idOrEmail: string) {\n super(`User not found: ${idOrEmail}`);\n this.name = 'UserNotFoundError';\n }\n}\n\nexport class EmailTakenError extends Error {\n constructor(email: string) {\n super(`Email already registered: ${email}`);\n this.name = 'EmailTakenError';\n }\n}\n\nexport class SignupNotAllowedError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'SignupNotAllowedError';\n }\n}\n\nexport class InvalidCredentialsError extends Error {\n constructor() {\n super('Invalid credentials');\n this.name = 'InvalidCredentialsError';\n }\n}\n\nexport class EmailNotVerifiedError extends Error {\n constructor() {\n super('Email not verified');\n this.name = 'EmailNotVerifiedError';\n }\n}\n\nexport class AuthDependencyUnavailableError extends Error {\n readonly dependency: string;\n override readonly cause: unknown;\n\n constructor(dependency: string, cause: unknown) {\n super(`Authentication dependency unavailable: ${dependency}`);\n this.name = 'AuthDependencyUnavailableError';\n this.dependency = dependency;\n this.cause = cause;\n }\n}\n\nexport class AdminRoleRequiredError extends Error {\n readonly minimumRole: import('@shipfox/api-auth-dto').AdminRole;\n\n constructor(minimumRole: import('@shipfox/api-auth-dto').AdminRole) {\n super(`Administrator role required: ${minimumRole}`);\n this.name = 'AdminRoleRequiredError';\n this.minimumRole = minimumRole;\n }\n}\n\nexport class LastAdminOwnerError extends Error {\n constructor() {\n super('Cannot remove the final active administrator owner');\n this.name = 'LastAdminOwnerError';\n }\n}\n\nexport class AdminGrantNotFoundError extends Error {\n constructor() {\n super('Administrator grant not found');\n this.name = 'AdminGrantNotFoundError';\n }\n}\n\nexport class AdminGrantAlreadyExistsError extends Error {\n constructor() {\n super('Administrator grant already exists');\n this.name = 'AdminGrantAlreadyExistsError';\n }\n}\n\nexport class AdminBootstrapClosedError extends Error {\n constructor() {\n super('First administrator owner has already been created');\n this.name = 'AdminBootstrapClosedError';\n }\n}\n\nexport class InvalidAdminBootstrapTokenError extends Error {\n constructor() {\n super('Bootstrap token is invalid');\n this.name = 'InvalidAdminBootstrapTokenError';\n }\n}\n\nexport class AdminIdempotencyKeyReuseError extends Error {\n constructor() {\n super('Idempotency key was already used for a different command');\n this.name = 'AdminIdempotencyKeyReuseError';\n }\n}\n\nexport class TokenInvalidError extends Error {\n constructor(reason?: string) {\n super(reason ? `Invalid token: ${reason}` : 'Invalid token');\n this.name = 'TokenInvalidError';\n }\n}\n\nexport class TokenExpiredError extends Error {\n constructor() {\n super('Token has expired');\n this.name = 'TokenExpiredError';\n }\n}\n\nexport class TokenAlreadyUsedError extends Error {\n constructor() {\n super('Token has already been used');\n this.name = 'TokenAlreadyUsedError';\n }\n}\n\nexport class MembershipRequiredError extends Error {\n constructor(workspaceId: string) {\n super(`Membership required for workspace: ${workspaceId}`);\n this.name = 'MembershipRequiredError';\n }\n}\n\nexport class LastMemberError extends Error {\n constructor(workspaceId: string) {\n super(`Cannot remove the last member of workspace: ${workspaceId}`);\n this.name = 'LastMemberError';\n }\n}\n\nexport class InvitationEmailMismatchError extends Error {\n constructor() {\n super('Invitation email does not match authenticated user');\n this.name = 'InvitationEmailMismatchError';\n }\n}\n\nexport class OpenInvitationExistsError extends Error {\n constructor(email: string) {\n super(`An open invitation already exists for: ${email}`);\n this.name = 'OpenInvitationExistsError';\n }\n}\n"],"names":["WorkspaceNotFoundError","Error","workspaceId","name","ApiKeyNotFoundError","id","InvitationNotFoundError","InvitationWorkspaceMismatchError","MembershipNotFoundError","userId","UserNotFoundError","idOrEmail","EmailTakenError","email","SignupNotAllowedError","message","InvalidCredentialsError","EmailNotVerifiedError","AuthDependencyUnavailableError","dependency","cause","AdminRoleRequiredError","minimumRole","LastAdminOwnerError","AdminGrantNotFoundError","AdminGrantAlreadyExistsError","AdminBootstrapClosedError","InvalidAdminBootstrapTokenError","AdminIdempotencyKeyReuseError","TokenInvalidError","reason","TokenExpiredError","TokenAlreadyUsedError","MembershipRequiredError","LastMemberError","InvitationEmailMismatchError","OpenInvitationExistsError"],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import type { AdminRole } from '@shipfox/api-auth-dto';
2
+ import type { AdministrationActionEvent } from '@shipfox/api-common-dto';
2
3
  import type { AdminGrant } from '#core/entities/admin-grant.js';
3
4
  export interface CreateAdminGrantParams {
4
5
  userId: string;
@@ -12,4 +13,21 @@ export declare function findCurrentAdminRole(params: {
12
13
  export declare function revokeAdminGrant(params: {
13
14
  grantId: string;
14
15
  }): Promise<AdminGrant | undefined>;
16
+ interface AuditedAdminCommandParams {
17
+ actorId: string;
18
+ idempotencyKeyFingerprint: string;
19
+ requestFingerprint: string;
20
+ event: AdministrationActionEvent;
21
+ }
22
+ export declare function bootstrapFirstAdminOwner(params: AuditedAdminCommandParams & {
23
+ userId: string;
24
+ }): Promise<AdminGrant>;
25
+ export declare function grantAdminRoleWithAudit(params: AuditedAdminCommandParams & {
26
+ userId: string;
27
+ role: AdminRole;
28
+ }): Promise<AdminGrant>;
29
+ export declare function revokeAdminGrantWithAudit(params: AuditedAdminCommandParams & {
30
+ grantId: string;
31
+ }): Promise<AdminGrant>;
32
+ export {};
15
33
  //# sourceMappingURL=admin-grants.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"admin-grants.d.ts","sourceRoot":"","sources":["../../src/db/admin-grants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,uBAAuB,CAAC;AAGrD,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,+BAA+B,CAAC;AAM9D,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,SAAS,CAAC;CACjB;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAAC,UAAU,CAAC,CAQ1F;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAG7D;AAED,wBAAsB,oBAAoB,CAAC,MAAM,EAAE;IAAC,MAAM,EAAE,MAAM,CAAA;CAAC,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAc9F;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE;IAAC,OAAO,EAAE,MAAM,CAAA;CAAC,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAqCjG"}
1
+ {"version":3,"file":"admin-grants.d.ts","sourceRoot":"","sources":["../../src/db/admin-grants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,uBAAuB,CAAC;AACrD,OAAO,KAAK,EACV,yBAAyB,EAE1B,MAAM,yBAAyB,CAAC;AAIjC,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,+BAA+B,CAAC;AAqB9D,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,SAAS,CAAC;CACjB;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAAC,UAAU,CAAC,CAQ1F;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAG7D;AAED,wBAAsB,oBAAoB,CAAC,MAAM,EAAE;IAAC,MAAM,EAAE,MAAM,CAAA;CAAC,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAc9F;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE;IAAC,OAAO,EAAE,MAAM,CAAA;CAAC,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAqCjG;AAED,UAAU,yBAAyB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,yBAAyB,EAAE,MAAM,CAAC;IAClC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,KAAK,EAAE,yBAAyB,CAAC;CAClC;AAoFD,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,yBAAyB,GAAG;IAAC,MAAM,EAAE,MAAM,CAAA;CAAC,GACnD,OAAO,CAAC,UAAU,CAAC,CA6CrB;AAED,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,yBAAyB,GAAG;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,SAAS,CAAA;CAAC,GACpE,OAAO,CAAC,UAAU,CAAC,CA4CrB;AAED,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,yBAAyB,GAAG;IAAC,OAAO,EAAE,MAAM,CAAA;CAAC,GACpD,OAAO,CAAC,UAAU,CAAC,CA+CrB"}
@@ -1,8 +1,11 @@
1
+ import { writeOutboxEvent } from '@shipfox/node-outbox';
1
2
  import { and, asc, eq, isNull, sql } from 'drizzle-orm';
2
3
  import { highestAdminRole } from '#core/admin-role-model.js';
3
- import { LastAdminOwnerError } from '#core/errors.js';
4
+ import { AdminBootstrapClosedError, AdminGrantAlreadyExistsError, AdminGrantNotFoundError, AdminIdempotencyKeyReuseError, LastAdminOwnerError, UserNotFoundError } from '#core/errors.js';
4
5
  import { db } from './db.js';
6
+ import { adminCommandResults } from './schema/admin-command-results.js';
5
7
  import { adminGrants, toAdminGrant } from './schema/admin-grants.js';
8
+ import { authOutbox } from './schema/outbox.js';
6
9
  import { users } from './schema/users.js';
7
10
  export async function createAdminGrant(params) {
8
11
  const rows = await db().insert(adminGrants).values({
@@ -45,5 +48,146 @@ export async function revokeAdminGrant(params) {
45
48
  return row ? toAdminGrant(row) : undefined;
46
49
  });
47
50
  }
51
+ function toStoredAdminGrant(grant) {
52
+ return {
53
+ id: grant.id,
54
+ userId: grant.userId,
55
+ role: grant.role,
56
+ revokedAt: grant.revokedAt?.toISOString() ?? null,
57
+ createdAt: grant.createdAt.toISOString(),
58
+ updatedAt: grant.updatedAt.toISOString()
59
+ };
60
+ }
61
+ function fromStoredAdminGrant(grant) {
62
+ return {
63
+ id: grant.id,
64
+ userId: grant.userId,
65
+ role: grant.role,
66
+ revokedAt: grant.revokedAt ? new Date(grant.revokedAt) : null,
67
+ createdAt: new Date(grant.createdAt),
68
+ updatedAt: new Date(grant.updatedAt)
69
+ };
70
+ }
71
+ async function findCommandResult(tx, params) {
72
+ const rows = await tx.select().from(adminCommandResults).where(and(eq(adminCommandResults.actorId, params.actorId), eq(adminCommandResults.idempotencyKeyFingerprint, params.idempotencyKeyFingerprint))).limit(1);
73
+ const result = rows[0];
74
+ if (!result) return undefined;
75
+ if (result.command !== params.command || result.requestFingerprint !== params.requestFingerprint) {
76
+ throw new AdminIdempotencyKeyReuseError();
77
+ }
78
+ return fromStoredAdminGrant(result.result.grant);
79
+ }
80
+ async function storeCommandResult(tx, params, grant) {
81
+ await tx.insert(adminCommandResults).values({
82
+ actorId: params.actorId,
83
+ idempotencyKeyFingerprint: params.idempotencyKeyFingerprint,
84
+ command: params.event.command,
85
+ requestFingerprint: params.requestFingerprint,
86
+ result: {
87
+ grant: toStoredAdminGrant(grant)
88
+ }
89
+ });
90
+ }
91
+ async function writeAdminAction(tx, event) {
92
+ await writeOutboxEvent(tx, authOutbox, {
93
+ type: 'administration.action.performed',
94
+ payload: event
95
+ });
96
+ }
97
+ async function lockAdminCommand(tx, params) {
98
+ await tx.execute(sql`select pg_advisory_xact_lock(hashtext(${`auth_admin_command:${params.actorId}:${params.idempotencyKeyFingerprint}`}))`);
99
+ }
100
+ export async function bootstrapFirstAdminOwner(params) {
101
+ return await db().transaction(async (tx)=>{
102
+ await lockAdminCommand(tx, params);
103
+ await tx.execute(sql`select pg_advisory_xact_lock(hashtext('auth_admin_owner_grants'))`);
104
+ const existing = await findCommandResult(tx, {
105
+ ...params,
106
+ command: params.event.command
107
+ });
108
+ if (existing) return existing;
109
+ const activeOwners = await tx.select({
110
+ id: adminGrants.id
111
+ }).from(adminGrants).innerJoin(users, eq(adminGrants.userId, users.id)).where(and(eq(adminGrants.role, 'admin-owner'), isNull(adminGrants.revokedAt), eq(users.status, 'active'))).limit(1);
112
+ if (activeOwners.length > 0) throw new AdminBootstrapClosedError();
113
+ const userRows = await tx.select({
114
+ id: users.id,
115
+ status: users.status
116
+ }).from(users).where(eq(users.id, params.userId)).limit(1);
117
+ const user = userRows[0];
118
+ if (user?.status !== 'active') throw new UserNotFoundError(params.userId);
119
+ const rows = await tx.insert(adminGrants).values({
120
+ userId: params.userId,
121
+ role: 'admin-owner'
122
+ }).returning();
123
+ const row = rows[0];
124
+ if (!row) throw new Error('Bootstrap grant insert returned no rows');
125
+ const grant = toAdminGrant(row);
126
+ await writeAdminAction(tx, params.event);
127
+ await storeCommandResult(tx, params, grant);
128
+ return grant;
129
+ });
130
+ }
131
+ export async function grantAdminRoleWithAudit(params) {
132
+ return await db().transaction(async (tx)=>{
133
+ await lockAdminCommand(tx, params);
134
+ await tx.execute(sql`select pg_advisory_xact_lock(hashtext('auth_admin_owner_grants'))`);
135
+ const existing = await findCommandResult(tx, {
136
+ ...params,
137
+ command: params.event.command
138
+ });
139
+ if (existing) return existing;
140
+ const userRows = await tx.select({
141
+ id: users.id,
142
+ status: users.status
143
+ }).from(users).where(eq(users.id, params.userId)).limit(1);
144
+ const user = userRows[0];
145
+ if (user?.status !== 'active') throw new UserNotFoundError(params.userId);
146
+ const activeRows = await tx.select({
147
+ id: adminGrants.id
148
+ }).from(adminGrants).where(and(eq(adminGrants.userId, params.userId), eq(adminGrants.role, params.role), isNull(adminGrants.revokedAt))).limit(1);
149
+ if (activeRows.length > 0) throw new AdminGrantAlreadyExistsError();
150
+ const rows = await tx.insert(adminGrants).values({
151
+ userId: params.userId,
152
+ role: params.role
153
+ }).returning();
154
+ const row = rows[0];
155
+ if (!row) throw new Error('Administrator grant insert returned no rows');
156
+ const grant = toAdminGrant(row);
157
+ await writeAdminAction(tx, params.event);
158
+ await storeCommandResult(tx, params, grant);
159
+ return grant;
160
+ });
161
+ }
162
+ export async function revokeAdminGrantWithAudit(params) {
163
+ return await db().transaction(async (tx)=>{
164
+ await lockAdminCommand(tx, params);
165
+ await tx.execute(sql`select pg_advisory_xact_lock(hashtext('auth_admin_owner_grants'))`);
166
+ const existing = await findCommandResult(tx, {
167
+ ...params,
168
+ command: params.event.command
169
+ });
170
+ if (existing) return existing;
171
+ const rows = await tx.select().from(adminGrants).where(and(eq(adminGrants.id, params.grantId), isNull(adminGrants.revokedAt))).limit(1);
172
+ const grant = rows[0];
173
+ if (!grant) throw new AdminGrantNotFoundError();
174
+ if (grant.role === 'admin-owner') {
175
+ const activeOwners = await tx.select({
176
+ id: adminGrants.id
177
+ }).from(adminGrants).innerJoin(users, eq(adminGrants.userId, users.id)).where(and(eq(adminGrants.role, 'admin-owner'), isNull(adminGrants.revokedAt), eq(users.status, 'active')));
178
+ if (activeOwners.length <= 1) throw new LastAdminOwnerError();
179
+ }
180
+ const updated = await tx.update(adminGrants).set({
181
+ revokedAt: new Date(),
182
+ updatedAt: new Date()
183
+ }).where(and(eq(adminGrants.id, grant.id), isNull(adminGrants.revokedAt))).returning();
184
+ const updatedRow = updated[0];
185
+ if (!updatedRow) throw new AdminGrantNotFoundError();
186
+ const revoked = toAdminGrant(updatedRow);
187
+ await writeAdminAction(tx, params.event);
188
+ await storeCommandResult(tx, params, revoked);
189
+ return revoked;
190
+ });
191
+ }
48
192
 
49
193
  //# sourceMappingURL=admin-grants.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/db/admin-grants.ts"],"sourcesContent":["import type {AdminRole} from '@shipfox/api-auth-dto';\nimport {and, asc, eq, isNull, sql} from 'drizzle-orm';\nimport {highestAdminRole} from '#core/admin-role-model.js';\nimport type {AdminGrant} from '#core/entities/admin-grant.js';\nimport {LastAdminOwnerError} from '#core/errors.js';\nimport {db} from './db.js';\nimport {adminGrants, toAdminGrant} from './schema/admin-grants.js';\nimport {users} from './schema/users.js';\n\nexport interface CreateAdminGrantParams {\n userId: string;\n role: AdminRole;\n}\n\nexport async function createAdminGrant(params: CreateAdminGrantParams): Promise<AdminGrant> {\n const rows = await db()\n .insert(adminGrants)\n .values({userId: params.userId, role: params.role})\n .returning();\n const row = rows[0];\n if (!row) throw new Error('Insert returned no rows');\n return toAdminGrant(row);\n}\n\nexport async function listAdminGrants(): Promise<AdminGrant[]> {\n const rows = await db().select().from(adminGrants).orderBy(asc(adminGrants.createdAt));\n return rows.map(toAdminGrant);\n}\n\nexport async function findCurrentAdminRole(params: {userId: string}): Promise<AdminRole | null> {\n const rows = await db()\n .select({role: adminGrants.role})\n .from(adminGrants)\n .innerJoin(users, eq(adminGrants.userId, users.id))\n .where(\n and(\n eq(adminGrants.userId, params.userId),\n isNull(adminGrants.revokedAt),\n eq(users.status, 'active'),\n ),\n );\n\n return highestAdminRole(rows.map(({role}) => role));\n}\n\nexport async function revokeAdminGrant(params: {grantId: string}): Promise<AdminGrant | undefined> {\n return await db().transaction(async (tx) => {\n // All owner grant changes share one lock so concurrent revocations cannot\n // both observe the same final owner and leave the instance ownerless.\n await tx.execute(sql`select pg_advisory_xact_lock(hashtext('auth_admin_owner_grants'))`);\n\n const rows = await tx\n .select()\n .from(adminGrants)\n .where(and(eq(adminGrants.id, params.grantId), isNull(adminGrants.revokedAt)))\n .limit(1);\n const grant = rows[0];\n if (!grant) return undefined;\n\n if (grant.role === 'admin-owner') {\n const activeOwners = await tx\n .select({id: adminGrants.id})\n .from(adminGrants)\n .innerJoin(users, eq(adminGrants.userId, users.id))\n .where(\n and(\n eq(adminGrants.role, 'admin-owner'),\n isNull(adminGrants.revokedAt),\n eq(users.status, 'active'),\n ),\n );\n if (activeOwners.length <= 1) throw new LastAdminOwnerError();\n }\n\n const updated = await tx\n .update(adminGrants)\n .set({revokedAt: new Date(), updatedAt: new Date()})\n .where(and(eq(adminGrants.id, grant.id), isNull(adminGrants.revokedAt)))\n .returning();\n const row = updated[0];\n return row ? toAdminGrant(row) : undefined;\n });\n}\n"],"names":["and","asc","eq","isNull","sql","highestAdminRole","LastAdminOwnerError","db","adminGrants","toAdminGrant","users","createAdminGrant","params","rows","insert","values","userId","role","returning","row","Error","listAdminGrants","select","from","orderBy","createdAt","map","findCurrentAdminRole","innerJoin","id","where","revokedAt","status","revokeAdminGrant","transaction","tx","execute","grantId","limit","grant","undefined","activeOwners","length","updated","update","set","Date","updatedAt"],"mappings":"AACA,SAAQA,GAAG,EAAEC,GAAG,EAAEC,EAAE,EAAEC,MAAM,EAAEC,GAAG,QAAO,cAAc;AACtD,SAAQC,gBAAgB,QAAO,4BAA4B;AAE3D,SAAQC,mBAAmB,QAAO,kBAAkB;AACpD,SAAQC,EAAE,QAAO,UAAU;AAC3B,SAAQC,WAAW,EAAEC,YAAY,QAAO,2BAA2B;AACnE,SAAQC,KAAK,QAAO,oBAAoB;AAOxC,OAAO,eAAeC,iBAAiBC,MAA8B;IACnE,MAAMC,OAAO,MAAMN,KAChBO,MAAM,CAACN,aACPO,MAAM,CAAC;QAACC,QAAQJ,OAAOI,MAAM;QAAEC,MAAML,OAAOK,IAAI;IAAA,GAChDC,SAAS;IACZ,MAAMC,MAAMN,IAAI,CAAC,EAAE;IACnB,IAAI,CAACM,KAAK,MAAM,IAAIC,MAAM;IAC1B,OAAOX,aAAaU;AACtB;AAEA,OAAO,eAAeE;IACpB,MAAMR,OAAO,MAAMN,KAAKe,MAAM,GAAGC,IAAI,CAACf,aAAagB,OAAO,CAACvB,IAAIO,YAAYiB,SAAS;IACpF,OAAOZ,KAAKa,GAAG,CAACjB;AAClB;AAEA,OAAO,eAAekB,qBAAqBf,MAAwB;IACjE,MAAMC,OAAO,MAAMN,KAChBe,MAAM,CAAC;QAACL,MAAMT,YAAYS,IAAI;IAAA,GAC9BM,IAAI,CAACf,aACLoB,SAAS,CAAClB,OAAOR,GAAGM,YAAYQ,MAAM,EAAEN,MAAMmB,EAAE,GAChDC,KAAK,CACJ9B,IACEE,GAAGM,YAAYQ,MAAM,EAAEJ,OAAOI,MAAM,GACpCb,OAAOK,YAAYuB,SAAS,GAC5B7B,GAAGQ,MAAMsB,MAAM,EAAE;IAIvB,OAAO3B,iBAAiBQ,KAAKa,GAAG,CAAC,CAAC,EAACT,IAAI,EAAC,GAAKA;AAC/C;AAEA,OAAO,eAAegB,iBAAiBrB,MAAyB;IAC9D,OAAO,MAAML,KAAK2B,WAAW,CAAC,OAAOC;QACnC,0EAA0E;QAC1E,sEAAsE;QACtE,MAAMA,GAAGC,OAAO,CAAChC,GAAG,CAAC,iEAAiE,CAAC;QAEvF,MAAMS,OAAO,MAAMsB,GAChBb,MAAM,GACNC,IAAI,CAACf,aACLsB,KAAK,CAAC9B,IAAIE,GAAGM,YAAYqB,EAAE,EAAEjB,OAAOyB,OAAO,GAAGlC,OAAOK,YAAYuB,SAAS,IAC1EO,KAAK,CAAC;QACT,MAAMC,QAAQ1B,IAAI,CAAC,EAAE;QACrB,IAAI,CAAC0B,OAAO,OAAOC;QAEnB,IAAID,MAAMtB,IAAI,KAAK,eAAe;YAChC,MAAMwB,eAAe,MAAMN,GACxBb,MAAM,CAAC;gBAACO,IAAIrB,YAAYqB,EAAE;YAAA,GAC1BN,IAAI,CAACf,aACLoB,SAAS,CAAClB,OAAOR,GAAGM,YAAYQ,MAAM,EAAEN,MAAMmB,EAAE,GAChDC,KAAK,CACJ9B,IACEE,GAAGM,YAAYS,IAAI,EAAE,gBACrBd,OAAOK,YAAYuB,SAAS,GAC5B7B,GAAGQ,MAAMsB,MAAM,EAAE;YAGvB,IAAIS,aAAaC,MAAM,IAAI,GAAG,MAAM,IAAIpC;QAC1C;QAEA,MAAMqC,UAAU,MAAMR,GACnBS,MAAM,CAACpC,aACPqC,GAAG,CAAC;YAACd,WAAW,IAAIe;YAAQC,WAAW,IAAID;QAAM,GACjDhB,KAAK,CAAC9B,IAAIE,GAAGM,YAAYqB,EAAE,EAAEU,MAAMV,EAAE,GAAG1B,OAAOK,YAAYuB,SAAS,IACpEb,SAAS;QACZ,MAAMC,MAAMwB,OAAO,CAAC,EAAE;QACtB,OAAOxB,MAAMV,aAAaU,OAAOqB;IACnC;AACF"}
1
+ {"version":3,"sources":["../../src/db/admin-grants.ts"],"sourcesContent":["import type {AdminRole} from '@shipfox/api-auth-dto';\nimport type {\n AdministrationActionEvent,\n AdministrationActionEventMap,\n} from '@shipfox/api-common-dto';\nimport {writeOutboxEvent} from '@shipfox/node-outbox';\nimport {and, asc, eq, isNull, sql} from 'drizzle-orm';\nimport {highestAdminRole} from '#core/admin-role-model.js';\nimport type {AdminGrant} from '#core/entities/admin-grant.js';\nimport {\n AdminBootstrapClosedError,\n AdminGrantAlreadyExistsError,\n AdminGrantNotFoundError,\n AdminIdempotencyKeyReuseError,\n LastAdminOwnerError,\n UserNotFoundError,\n} from '#core/errors.js';\nimport {db} from './db.js';\nimport {\n type AdminCommandResultDb,\n adminCommandResults,\n type StoredAdminGrant,\n} from './schema/admin-command-results.js';\nimport {adminGrants, toAdminGrant} from './schema/admin-grants.js';\nimport {authOutbox} from './schema/outbox.js';\nimport {users} from './schema/users.js';\n\ntype Tx = Parameters<Parameters<ReturnType<typeof db>['transaction']>[0]>[0];\n\nexport interface CreateAdminGrantParams {\n userId: string;\n role: AdminRole;\n}\n\nexport async function createAdminGrant(params: CreateAdminGrantParams): Promise<AdminGrant> {\n const rows = await db()\n .insert(adminGrants)\n .values({userId: params.userId, role: params.role})\n .returning();\n const row = rows[0];\n if (!row) throw new Error('Insert returned no rows');\n return toAdminGrant(row);\n}\n\nexport async function listAdminGrants(): Promise<AdminGrant[]> {\n const rows = await db().select().from(adminGrants).orderBy(asc(adminGrants.createdAt));\n return rows.map(toAdminGrant);\n}\n\nexport async function findCurrentAdminRole(params: {userId: string}): Promise<AdminRole | null> {\n const rows = await db()\n .select({role: adminGrants.role})\n .from(adminGrants)\n .innerJoin(users, eq(adminGrants.userId, users.id))\n .where(\n and(\n eq(adminGrants.userId, params.userId),\n isNull(adminGrants.revokedAt),\n eq(users.status, 'active'),\n ),\n );\n\n return highestAdminRole(rows.map(({role}) => role));\n}\n\nexport async function revokeAdminGrant(params: {grantId: string}): Promise<AdminGrant | undefined> {\n return await db().transaction(async (tx) => {\n // All owner grant changes share one lock so concurrent revocations cannot\n // both observe the same final owner and leave the instance ownerless.\n await tx.execute(sql`select pg_advisory_xact_lock(hashtext('auth_admin_owner_grants'))`);\n\n const rows = await tx\n .select()\n .from(adminGrants)\n .where(and(eq(adminGrants.id, params.grantId), isNull(adminGrants.revokedAt)))\n .limit(1);\n const grant = rows[0];\n if (!grant) return undefined;\n\n if (grant.role === 'admin-owner') {\n const activeOwners = await tx\n .select({id: adminGrants.id})\n .from(adminGrants)\n .innerJoin(users, eq(adminGrants.userId, users.id))\n .where(\n and(\n eq(adminGrants.role, 'admin-owner'),\n isNull(adminGrants.revokedAt),\n eq(users.status, 'active'),\n ),\n );\n if (activeOwners.length <= 1) throw new LastAdminOwnerError();\n }\n\n const updated = await tx\n .update(adminGrants)\n .set({revokedAt: new Date(), updatedAt: new Date()})\n .where(and(eq(adminGrants.id, grant.id), isNull(adminGrants.revokedAt)))\n .returning();\n const row = updated[0];\n return row ? toAdminGrant(row) : undefined;\n });\n}\n\ninterface AuditedAdminCommandParams {\n actorId: string;\n idempotencyKeyFingerprint: string;\n requestFingerprint: string;\n event: AdministrationActionEvent;\n}\n\nfunction toStoredAdminGrant(grant: AdminGrant): StoredAdminGrant {\n return {\n id: grant.id,\n userId: grant.userId,\n role: grant.role,\n revokedAt: grant.revokedAt?.toISOString() ?? null,\n createdAt: grant.createdAt.toISOString(),\n updatedAt: grant.updatedAt.toISOString(),\n };\n}\n\nfunction fromStoredAdminGrant(grant: StoredAdminGrant): AdminGrant {\n return {\n id: grant.id,\n userId: grant.userId,\n role: grant.role,\n revokedAt: grant.revokedAt ? new Date(grant.revokedAt) : null,\n createdAt: new Date(grant.createdAt),\n updatedAt: new Date(grant.updatedAt),\n };\n}\n\nasync function findCommandResult(\n tx: Tx,\n params: Pick<\n AuditedAdminCommandParams,\n 'actorId' | 'idempotencyKeyFingerprint' | 'requestFingerprint'\n > & {\n command: string;\n },\n): Promise<AdminGrant | undefined> {\n const rows = await tx\n .select()\n .from(adminCommandResults)\n .where(\n and(\n eq(adminCommandResults.actorId, params.actorId),\n eq(adminCommandResults.idempotencyKeyFingerprint, params.idempotencyKeyFingerprint),\n ),\n )\n .limit(1);\n const result: AdminCommandResultDb | undefined = rows[0];\n if (!result) return undefined;\n if (\n result.command !== params.command ||\n result.requestFingerprint !== params.requestFingerprint\n ) {\n throw new AdminIdempotencyKeyReuseError();\n }\n return fromStoredAdminGrant(result.result.grant);\n}\n\nasync function storeCommandResult(\n tx: Tx,\n params: AuditedAdminCommandParams,\n grant: AdminGrant,\n): Promise<void> {\n await tx.insert(adminCommandResults).values({\n actorId: params.actorId,\n idempotencyKeyFingerprint: params.idempotencyKeyFingerprint,\n command: params.event.command,\n requestFingerprint: params.requestFingerprint,\n result: {grant: toStoredAdminGrant(grant)},\n });\n}\n\nasync function writeAdminAction(tx: Tx, event: AdministrationActionEvent): Promise<void> {\n await writeOutboxEvent<AdministrationActionEventMap>(tx, authOutbox, {\n type: 'administration.action.performed',\n payload: event,\n });\n}\n\nasync function lockAdminCommand(\n tx: Tx,\n params: {actorId: string; idempotencyKeyFingerprint: string},\n) {\n await tx.execute(\n sql`select pg_advisory_xact_lock(hashtext(${`auth_admin_command:${params.actorId}:${params.idempotencyKeyFingerprint}`}))`,\n );\n}\n\nexport async function bootstrapFirstAdminOwner(\n params: AuditedAdminCommandParams & {userId: string},\n): Promise<AdminGrant> {\n return await db().transaction(async (tx) => {\n await lockAdminCommand(tx, params);\n await tx.execute(sql`select pg_advisory_xact_lock(hashtext('auth_admin_owner_grants'))`);\n\n const existing = await findCommandResult(tx, {\n ...params,\n command: params.event.command,\n });\n if (existing) return existing;\n\n const activeOwners = await tx\n .select({id: adminGrants.id})\n .from(adminGrants)\n .innerJoin(users, eq(adminGrants.userId, users.id))\n .where(\n and(\n eq(adminGrants.role, 'admin-owner'),\n isNull(adminGrants.revokedAt),\n eq(users.status, 'active'),\n ),\n )\n .limit(1);\n if (activeOwners.length > 0) throw new AdminBootstrapClosedError();\n\n const userRows = await tx\n .select({id: users.id, status: users.status})\n .from(users)\n .where(eq(users.id, params.userId))\n .limit(1);\n const user = userRows[0];\n if (user?.status !== 'active') throw new UserNotFoundError(params.userId);\n\n const rows = await tx\n .insert(adminGrants)\n .values({userId: params.userId, role: 'admin-owner'})\n .returning();\n const row = rows[0];\n if (!row) throw new Error('Bootstrap grant insert returned no rows');\n\n const grant = toAdminGrant(row);\n await writeAdminAction(tx, params.event);\n await storeCommandResult(tx, params, grant);\n return grant;\n });\n}\n\nexport async function grantAdminRoleWithAudit(\n params: AuditedAdminCommandParams & {userId: string; role: AdminRole},\n): Promise<AdminGrant> {\n return await db().transaction(async (tx) => {\n await lockAdminCommand(tx, params);\n await tx.execute(sql`select pg_advisory_xact_lock(hashtext('auth_admin_owner_grants'))`);\n\n const existing = await findCommandResult(tx, {\n ...params,\n command: params.event.command,\n });\n if (existing) return existing;\n\n const userRows = await tx\n .select({id: users.id, status: users.status})\n .from(users)\n .where(eq(users.id, params.userId))\n .limit(1);\n const user = userRows[0];\n if (user?.status !== 'active') throw new UserNotFoundError(params.userId);\n\n const activeRows = await tx\n .select({id: adminGrants.id})\n .from(adminGrants)\n .where(\n and(\n eq(adminGrants.userId, params.userId),\n eq(adminGrants.role, params.role),\n isNull(adminGrants.revokedAt),\n ),\n )\n .limit(1);\n if (activeRows.length > 0) throw new AdminGrantAlreadyExistsError();\n\n const rows = await tx\n .insert(adminGrants)\n .values({userId: params.userId, role: params.role})\n .returning();\n const row = rows[0];\n if (!row) throw new Error('Administrator grant insert returned no rows');\n\n const grant = toAdminGrant(row);\n await writeAdminAction(tx, params.event);\n await storeCommandResult(tx, params, grant);\n return grant;\n });\n}\n\nexport async function revokeAdminGrantWithAudit(\n params: AuditedAdminCommandParams & {grantId: string},\n): Promise<AdminGrant> {\n return await db().transaction(async (tx) => {\n await lockAdminCommand(tx, params);\n await tx.execute(sql`select pg_advisory_xact_lock(hashtext('auth_admin_owner_grants'))`);\n\n const existing = await findCommandResult(tx, {\n ...params,\n command: params.event.command,\n });\n if (existing) return existing;\n\n const rows = await tx\n .select()\n .from(adminGrants)\n .where(and(eq(adminGrants.id, params.grantId), isNull(adminGrants.revokedAt)))\n .limit(1);\n const grant = rows[0];\n if (!grant) throw new AdminGrantNotFoundError();\n\n if (grant.role === 'admin-owner') {\n const activeOwners = await tx\n .select({id: adminGrants.id})\n .from(adminGrants)\n .innerJoin(users, eq(adminGrants.userId, users.id))\n .where(\n and(\n eq(adminGrants.role, 'admin-owner'),\n isNull(adminGrants.revokedAt),\n eq(users.status, 'active'),\n ),\n );\n if (activeOwners.length <= 1) throw new LastAdminOwnerError();\n }\n\n const updated = await tx\n .update(adminGrants)\n .set({revokedAt: new Date(), updatedAt: new Date()})\n .where(and(eq(adminGrants.id, grant.id), isNull(adminGrants.revokedAt)))\n .returning();\n const updatedRow = updated[0];\n if (!updatedRow) throw new AdminGrantNotFoundError();\n\n const revoked = toAdminGrant(updatedRow);\n await writeAdminAction(tx, params.event);\n await storeCommandResult(tx, params, revoked);\n return revoked;\n });\n}\n"],"names":["writeOutboxEvent","and","asc","eq","isNull","sql","highestAdminRole","AdminBootstrapClosedError","AdminGrantAlreadyExistsError","AdminGrantNotFoundError","AdminIdempotencyKeyReuseError","LastAdminOwnerError","UserNotFoundError","db","adminCommandResults","adminGrants","toAdminGrant","authOutbox","users","createAdminGrant","params","rows","insert","values","userId","role","returning","row","Error","listAdminGrants","select","from","orderBy","createdAt","map","findCurrentAdminRole","innerJoin","id","where","revokedAt","status","revokeAdminGrant","transaction","tx","execute","grantId","limit","grant","undefined","activeOwners","length","updated","update","set","Date","updatedAt","toStoredAdminGrant","toISOString","fromStoredAdminGrant","findCommandResult","actorId","idempotencyKeyFingerprint","result","command","requestFingerprint","storeCommandResult","event","writeAdminAction","type","payload","lockAdminCommand","bootstrapFirstAdminOwner","existing","userRows","user","grantAdminRoleWithAudit","activeRows","revokeAdminGrantWithAudit","updatedRow","revoked"],"mappings":"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"}
package/dist/db/db.d.ts CHANGED
@@ -109,6 +109,134 @@ export declare const schema: {
109
109
  };
110
110
  dialect: "pg";
111
111
  }>;
112
+ adminCommandResults: import("drizzle-orm/pg-core").PgTableWithColumns<{
113
+ name: "admin_command_results";
114
+ schema: undefined;
115
+ columns: {
116
+ id: import("drizzle-orm/pg-core").PgColumn<{
117
+ name: "id";
118
+ tableName: "admin_command_results";
119
+ dataType: "string";
120
+ columnType: "PgUUID";
121
+ data: string;
122
+ driverParam: string;
123
+ notNull: true;
124
+ hasDefault: true;
125
+ isPrimaryKey: true;
126
+ isAutoincrement: false;
127
+ hasRuntimeDefault: false;
128
+ enumValues: undefined;
129
+ baseColumn: never;
130
+ identity: undefined;
131
+ generated: undefined;
132
+ }, {}, {}>;
133
+ actorId: import("drizzle-orm/pg-core").PgColumn<{
134
+ name: "actor_id";
135
+ tableName: "admin_command_results";
136
+ dataType: "string";
137
+ columnType: "PgUUID";
138
+ data: string;
139
+ driverParam: string;
140
+ notNull: true;
141
+ hasDefault: false;
142
+ isPrimaryKey: false;
143
+ isAutoincrement: false;
144
+ hasRuntimeDefault: false;
145
+ enumValues: undefined;
146
+ baseColumn: never;
147
+ identity: undefined;
148
+ generated: undefined;
149
+ }, {}, {}>;
150
+ idempotencyKeyFingerprint: import("drizzle-orm/pg-core").PgColumn<{
151
+ name: "idempotency_key_fingerprint";
152
+ tableName: "admin_command_results";
153
+ dataType: "string";
154
+ columnType: "PgText";
155
+ data: string;
156
+ driverParam: string;
157
+ notNull: true;
158
+ hasDefault: false;
159
+ isPrimaryKey: false;
160
+ isAutoincrement: false;
161
+ hasRuntimeDefault: false;
162
+ enumValues: [string, ...string[]];
163
+ baseColumn: never;
164
+ identity: undefined;
165
+ generated: undefined;
166
+ }, {}, {}>;
167
+ command: import("drizzle-orm/pg-core").PgColumn<{
168
+ name: "command";
169
+ tableName: "admin_command_results";
170
+ dataType: "string";
171
+ columnType: "PgText";
172
+ data: string;
173
+ driverParam: string;
174
+ notNull: true;
175
+ hasDefault: false;
176
+ isPrimaryKey: false;
177
+ isAutoincrement: false;
178
+ hasRuntimeDefault: false;
179
+ enumValues: [string, ...string[]];
180
+ baseColumn: never;
181
+ identity: undefined;
182
+ generated: undefined;
183
+ }, {}, {}>;
184
+ requestFingerprint: import("drizzle-orm/pg-core").PgColumn<{
185
+ name: "request_fingerprint";
186
+ tableName: "admin_command_results";
187
+ dataType: "string";
188
+ columnType: "PgText";
189
+ data: string;
190
+ driverParam: string;
191
+ notNull: true;
192
+ hasDefault: false;
193
+ isPrimaryKey: false;
194
+ isAutoincrement: false;
195
+ hasRuntimeDefault: false;
196
+ enumValues: [string, ...string[]];
197
+ baseColumn: never;
198
+ identity: undefined;
199
+ generated: undefined;
200
+ }, {}, {}>;
201
+ result: import("drizzle-orm/pg-core").PgColumn<{
202
+ name: "result";
203
+ tableName: "admin_command_results";
204
+ dataType: "json";
205
+ columnType: "PgJsonb";
206
+ data: import("./schema/admin-command-results.js").StoredAdminCommandResult;
207
+ driverParam: unknown;
208
+ notNull: true;
209
+ hasDefault: false;
210
+ isPrimaryKey: false;
211
+ isAutoincrement: false;
212
+ hasRuntimeDefault: false;
213
+ enumValues: undefined;
214
+ baseColumn: never;
215
+ identity: undefined;
216
+ generated: undefined;
217
+ }, {}, {
218
+ $type: import("./schema/admin-command-results.js").StoredAdminCommandResult;
219
+ }>;
220
+ createdAt: import("drizzle-orm/pg-core").PgColumn<{
221
+ name: "created_at";
222
+ tableName: "admin_command_results";
223
+ dataType: "date";
224
+ columnType: "PgTimestamp";
225
+ data: Date;
226
+ driverParam: string;
227
+ notNull: true;
228
+ hasDefault: true;
229
+ isPrimaryKey: false;
230
+ isAutoincrement: false;
231
+ hasRuntimeDefault: false;
232
+ enumValues: undefined;
233
+ baseColumn: never;
234
+ identity: undefined;
235
+ generated: undefined;
236
+ }, {}, {}>;
237
+ };
238
+ dialect: "pg";
239
+ }>;
112
240
  users: import("drizzle-orm/pg-core").PgTableWithColumns<{
113
241
  name: "users";
114
242
  schema: undefined;
@@ -986,6 +1114,134 @@ export declare function db(): NodePgDatabase<{
986
1114
  };
987
1115
  dialect: "pg";
988
1116
  }>;
1117
+ adminCommandResults: import("drizzle-orm/pg-core").PgTableWithColumns<{
1118
+ name: "admin_command_results";
1119
+ schema: undefined;
1120
+ columns: {
1121
+ id: import("drizzle-orm/pg-core").PgColumn<{
1122
+ name: "id";
1123
+ tableName: "admin_command_results";
1124
+ dataType: "string";
1125
+ columnType: "PgUUID";
1126
+ data: string;
1127
+ driverParam: string;
1128
+ notNull: true;
1129
+ hasDefault: true;
1130
+ isPrimaryKey: true;
1131
+ isAutoincrement: false;
1132
+ hasRuntimeDefault: false;
1133
+ enumValues: undefined;
1134
+ baseColumn: never;
1135
+ identity: undefined;
1136
+ generated: undefined;
1137
+ }, {}, {}>;
1138
+ actorId: import("drizzle-orm/pg-core").PgColumn<{
1139
+ name: "actor_id";
1140
+ tableName: "admin_command_results";
1141
+ dataType: "string";
1142
+ columnType: "PgUUID";
1143
+ data: string;
1144
+ driverParam: string;
1145
+ notNull: true;
1146
+ hasDefault: false;
1147
+ isPrimaryKey: false;
1148
+ isAutoincrement: false;
1149
+ hasRuntimeDefault: false;
1150
+ enumValues: undefined;
1151
+ baseColumn: never;
1152
+ identity: undefined;
1153
+ generated: undefined;
1154
+ }, {}, {}>;
1155
+ idempotencyKeyFingerprint: import("drizzle-orm/pg-core").PgColumn<{
1156
+ name: "idempotency_key_fingerprint";
1157
+ tableName: "admin_command_results";
1158
+ dataType: "string";
1159
+ columnType: "PgText";
1160
+ data: string;
1161
+ driverParam: string;
1162
+ notNull: true;
1163
+ hasDefault: false;
1164
+ isPrimaryKey: false;
1165
+ isAutoincrement: false;
1166
+ hasRuntimeDefault: false;
1167
+ enumValues: [string, ...string[]];
1168
+ baseColumn: never;
1169
+ identity: undefined;
1170
+ generated: undefined;
1171
+ }, {}, {}>;
1172
+ command: import("drizzle-orm/pg-core").PgColumn<{
1173
+ name: "command";
1174
+ tableName: "admin_command_results";
1175
+ dataType: "string";
1176
+ columnType: "PgText";
1177
+ data: string;
1178
+ driverParam: string;
1179
+ notNull: true;
1180
+ hasDefault: false;
1181
+ isPrimaryKey: false;
1182
+ isAutoincrement: false;
1183
+ hasRuntimeDefault: false;
1184
+ enumValues: [string, ...string[]];
1185
+ baseColumn: never;
1186
+ identity: undefined;
1187
+ generated: undefined;
1188
+ }, {}, {}>;
1189
+ requestFingerprint: import("drizzle-orm/pg-core").PgColumn<{
1190
+ name: "request_fingerprint";
1191
+ tableName: "admin_command_results";
1192
+ dataType: "string";
1193
+ columnType: "PgText";
1194
+ data: string;
1195
+ driverParam: string;
1196
+ notNull: true;
1197
+ hasDefault: false;
1198
+ isPrimaryKey: false;
1199
+ isAutoincrement: false;
1200
+ hasRuntimeDefault: false;
1201
+ enumValues: [string, ...string[]];
1202
+ baseColumn: never;
1203
+ identity: undefined;
1204
+ generated: undefined;
1205
+ }, {}, {}>;
1206
+ result: import("drizzle-orm/pg-core").PgColumn<{
1207
+ name: "result";
1208
+ tableName: "admin_command_results";
1209
+ dataType: "json";
1210
+ columnType: "PgJsonb";
1211
+ data: import("./schema/admin-command-results.js").StoredAdminCommandResult;
1212
+ driverParam: unknown;
1213
+ notNull: true;
1214
+ hasDefault: false;
1215
+ isPrimaryKey: false;
1216
+ isAutoincrement: false;
1217
+ hasRuntimeDefault: false;
1218
+ enumValues: undefined;
1219
+ baseColumn: never;
1220
+ identity: undefined;
1221
+ generated: undefined;
1222
+ }, {}, {
1223
+ $type: import("./schema/admin-command-results.js").StoredAdminCommandResult;
1224
+ }>;
1225
+ createdAt: import("drizzle-orm/pg-core").PgColumn<{
1226
+ name: "created_at";
1227
+ tableName: "admin_command_results";
1228
+ dataType: "date";
1229
+ columnType: "PgTimestamp";
1230
+ data: Date;
1231
+ driverParam: string;
1232
+ notNull: true;
1233
+ hasDefault: true;
1234
+ isPrimaryKey: false;
1235
+ isAutoincrement: false;
1236
+ hasRuntimeDefault: false;
1237
+ enumValues: undefined;
1238
+ baseColumn: never;
1239
+ identity: undefined;
1240
+ generated: undefined;
1241
+ }, {}, {}>;
1242
+ };
1243
+ dialect: "pg";
1244
+ }>;
989
1245
  users: import("drizzle-orm/pg-core").PgTableWithColumns<{
990
1246
  name: "users";
991
1247
  schema: undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/db/db.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,cAAc,EAAC,MAAM,uBAAuB,CAAC;AASnE,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAOlB,CAAC;AAIF,wBAAgB,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAGjB;AAED,wBAAgB,OAAO,IAAI,IAAI,CAE9B"}
1
+ {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../../src/db/db.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,cAAc,EAAC,MAAM,uBAAuB,CAAC;AAUnE,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAQlB,CAAC;AAIF,wBAAgB,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAGjB;AAED,wBAAgB,OAAO,IAAI,IAAI,CAE9B"}
package/dist/db/db.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { drizzle } from '@shipfox/node-drizzle';
2
2
  import { pgClient } from '@shipfox/node-postgres';
3
+ import { adminCommandResults } from './schema/admin-command-results.js';
3
4
  import { adminGrants } from './schema/admin-grants.js';
4
5
  import { authOutbox } from './schema/outbox.js';
5
6
  import { passwordResets } from './schema/password-resets.js';
@@ -8,6 +9,7 @@ import { refreshTokens } from './schema/refresh-tokens.js';
8
9
  import { users } from './schema/users.js';
9
10
  export const schema = {
10
11
  adminGrants,
12
+ adminCommandResults,
11
13
  users,
12
14
  passwordResets,
13
15
  refreshTokens,
package/dist/db/db.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/db/db.ts"],"sourcesContent":["import {drizzle, type NodePgDatabase} from '@shipfox/node-drizzle';\nimport {pgClient} from '@shipfox/node-postgres';\nimport {adminGrants} from './schema/admin-grants.js';\nimport {authOutbox} from './schema/outbox.js';\nimport {passwordResets} from './schema/password-resets.js';\nimport {authRateLimits} from './schema/rate-limits.js';\nimport {refreshTokens} from './schema/refresh-tokens.js';\nimport {users} from './schema/users.js';\n\nexport const schema = {\n adminGrants,\n users,\n passwordResets,\n refreshTokens,\n authOutbox,\n authRateLimits,\n};\n\nlet _db: NodePgDatabase<typeof schema> | undefined;\n\nexport function db() {\n if (!_db) _db = drizzle(pgClient(), {schema});\n return _db;\n}\n\nexport function closeDb(): void {\n _db = undefined;\n}\n"],"names":["drizzle","pgClient","adminGrants","authOutbox","passwordResets","authRateLimits","refreshTokens","users","schema","_db","db","closeDb","undefined"],"mappings":"AAAA,SAAQA,OAAO,QAA4B,wBAAwB;AACnE,SAAQC,QAAQ,QAAO,yBAAyB;AAChD,SAAQC,WAAW,QAAO,2BAA2B;AACrD,SAAQC,UAAU,QAAO,qBAAqB;AAC9C,SAAQC,cAAc,QAAO,8BAA8B;AAC3D,SAAQC,cAAc,QAAO,0BAA0B;AACvD,SAAQC,aAAa,QAAO,6BAA6B;AACzD,SAAQC,KAAK,QAAO,oBAAoB;AAExC,OAAO,MAAMC,SAAS;IACpBN;IACAK;IACAH;IACAE;IACAH;IACAE;AACF,EAAE;AAEF,IAAII;AAEJ,OAAO,SAASC;IACd,IAAI,CAACD,KAAKA,MAAMT,QAAQC,YAAY;QAACO;IAAM;IAC3C,OAAOC;AACT;AAEA,OAAO,SAASE;IACdF,MAAMG;AACR"}
1
+ {"version":3,"sources":["../../src/db/db.ts"],"sourcesContent":["import {drizzle, type NodePgDatabase} from '@shipfox/node-drizzle';\nimport {pgClient} from '@shipfox/node-postgres';\nimport {adminCommandResults} from './schema/admin-command-results.js';\nimport {adminGrants} from './schema/admin-grants.js';\nimport {authOutbox} from './schema/outbox.js';\nimport {passwordResets} from './schema/password-resets.js';\nimport {authRateLimits} from './schema/rate-limits.js';\nimport {refreshTokens} from './schema/refresh-tokens.js';\nimport {users} from './schema/users.js';\n\nexport const schema = {\n adminGrants,\n adminCommandResults,\n users,\n passwordResets,\n refreshTokens,\n authOutbox,\n authRateLimits,\n};\n\nlet _db: NodePgDatabase<typeof schema> | undefined;\n\nexport function db() {\n if (!_db) _db = drizzle(pgClient(), {schema});\n return _db;\n}\n\nexport function closeDb(): void {\n _db = undefined;\n}\n"],"names":["drizzle","pgClient","adminCommandResults","adminGrants","authOutbox","passwordResets","authRateLimits","refreshTokens","users","schema","_db","db","closeDb","undefined"],"mappings":"AAAA,SAAQA,OAAO,QAA4B,wBAAwB;AACnE,SAAQC,QAAQ,QAAO,yBAAyB;AAChD,SAAQC,mBAAmB,QAAO,oCAAoC;AACtE,SAAQC,WAAW,QAAO,2BAA2B;AACrD,SAAQC,UAAU,QAAO,qBAAqB;AAC9C,SAAQC,cAAc,QAAO,8BAA8B;AAC3D,SAAQC,cAAc,QAAO,0BAA0B;AACvD,SAAQC,aAAa,QAAO,6BAA6B;AACzD,SAAQC,KAAK,QAAO,oBAAoB;AAExC,OAAO,MAAMC,SAAS;IACpBN;IACAD;IACAM;IACAH;IACAE;IACAH;IACAE;AACF,EAAE;AAEF,IAAII;AAEJ,OAAO,SAASC;IACd,IAAI,CAACD,KAAKA,MAAMV,QAAQC,YAAY;QAACQ;IAAM;IAC3C,OAAOC;AACT;AAEA,OAAO,SAASE;IACdF,MAAMG;AACR"}