@kurdel/auth-db 0.1.0-beta.4 → 0.1.0-beta.6

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 (50) hide show
  1. package/README.md +192 -96
  2. package/lib/api-key-hasher.d.ts +15 -0
  3. package/lib/api-key-hasher.js +6 -0
  4. package/lib/api-key-hasher.js.map +1 -1
  5. package/lib/auth-database-module.d.ts +28 -0
  6. package/lib/auth-database-module.js +23 -0
  7. package/lib/auth-database-module.js.map +1 -1
  8. package/lib/auth-database-tables.d.ts +26 -0
  9. package/lib/auth-database-tables.js +28 -1
  10. package/lib/auth-database-tables.js.map +1 -1
  11. package/lib/database-api-key-repository.d.ts +29 -0
  12. package/lib/database-api-key-repository.js +29 -0
  13. package/lib/database-api-key-repository.js.map +1 -1
  14. package/lib/database-api-key-service.d.ts +33 -0
  15. package/lib/database-api-key-service.js +33 -0
  16. package/lib/database-api-key-service.js.map +1 -1
  17. package/lib/database-api-key-usage-recorder.d.ts +25 -1
  18. package/lib/database-api-key-usage-recorder.js +25 -1
  19. package/lib/database-api-key-usage-recorder.js.map +1 -1
  20. package/lib/database-auth-event-sink-provider.d.ts +8 -0
  21. package/lib/database-auth-event-sink-provider.js +15 -0
  22. package/lib/database-auth-event-sink-provider.js.map +1 -0
  23. package/lib/database-auth-event-store.d.ts +28 -1
  24. package/lib/database-auth-event-store.js +37 -1
  25. package/lib/database-auth-event-store.js.map +1 -1
  26. package/lib/database-auth-user-repository.d.ts +28 -0
  27. package/lib/database-auth-user-repository.js +28 -0
  28. package/lib/database-auth-user-repository.js.map +1 -1
  29. package/lib/database-jwt-session-repository.d.ts +27 -1
  30. package/lib/database-jwt-session-repository.js +27 -1
  31. package/lib/database-jwt-session-repository.js.map +1 -1
  32. package/lib/database-jwt-session-service.d.ts +55 -1
  33. package/lib/database-jwt-session-service.js +182 -1
  34. package/lib/database-jwt-session-service.js.map +1 -1
  35. package/lib/database-password-credential-repository.d.ts +27 -0
  36. package/lib/database-password-credential-repository.js +27 -0
  37. package/lib/database-password-credential-repository.js.map +1 -1
  38. package/lib/database-password-service.d.ts +31 -0
  39. package/lib/database-password-service.js +31 -0
  40. package/lib/database-password-service.js.map +1 -1
  41. package/lib/database-user-service.d.ts +47 -13
  42. package/lib/database-user-service.js +273 -190
  43. package/lib/database-user-service.js.map +1 -1
  44. package/lib/index.d.ts +1 -0
  45. package/lib/index.js +1 -0
  46. package/lib/index.js.map +1 -1
  47. package/lib/tokens.d.ts +8 -0
  48. package/lib/tokens.js +8 -0
  49. package/lib/tokens.js.map +1 -1
  50. package/package.json +5 -5
@@ -13,14 +13,55 @@ export class ActiveJwtSessionUserNotFoundError extends Error {
13
13
  this.userId = userId;
14
14
  }
15
15
  }
16
- /** Creates and revokes the server-side state referenced by JWT `jti` claims. */
16
+ export class InvalidRefreshTokenError extends Error {
17
+ constructor() {
18
+ super('Refresh token is invalid or expired');
19
+ }
20
+ }
21
+ /**
22
+ * ## DatabaseJwtSessionService
23
+ *
24
+ * Application service responsible for managing persistent JWT sessions
25
+ * backed by a relational database through the `Database` abstraction.
26
+ *
27
+ * Responsibilities:
28
+ * - create server-side JWT sessions
29
+ * - issue and rotate refresh tokens
30
+ * - list active and historical sessions
31
+ * - revoke individual or all user sessions
32
+ * - emit JWT session audit events
33
+ *
34
+ * Guarantees:
35
+ * - validates that sessions belong to active users
36
+ * - stores refresh tokens as SHA-256 hashes only
37
+ * - rotates refresh tokens atomically
38
+ * - performs all state changes inside database transactions
39
+ * - remains database-agnostic (SQLite/PostgreSQL)
40
+ *
41
+ * Non-responsibilities:
42
+ * - JWT signing or verification
43
+ * - access token generation
44
+ * - authorization policy evaluation
45
+ * - HTTP request handling
46
+ */
17
47
  export class DatabaseJwtSessionService {
48
+ /**
49
+ * Creates a new database-backed JWT session service.
50
+ *
51
+ * @param db Database abstraction used for persistence.
52
+ * @param tables Optional table name overrides.
53
+ * @param events Optional transactional audit event sink.
54
+ * @param now Time provider used for expiration checks and timestamps.
55
+ */
18
56
  constructor(db, tables = {}, events, now = () => new Date()) {
19
57
  this.db = db;
20
58
  this.events = events;
21
59
  this.now = now;
22
60
  this.tables = resolveAuthDatabaseTables(tables);
23
61
  }
62
+ // ---------------------------------------------------------------------
63
+ // JWT session lyfecycle
64
+ // ---------------------------------------------------------------------
24
65
  async create(userId, expiresAt) {
25
66
  const expirationTime = expiresAt.getTime();
26
67
  if (!Number.isFinite(expirationTime) || expirationTime <= this.now().getTime()) {
@@ -50,6 +91,137 @@ export class DatabaseJwtSessionService {
50
91
  });
51
92
  return { id, userId, expiresAt: expiresAt.toISOString() };
52
93
  }
94
+ async createRefreshable(userId, refreshExpiresAt) {
95
+ const expirationTime = refreshExpiresAt.getTime();
96
+ if (!Number.isFinite(expirationTime) || expirationTime <= this.now().getTime()) {
97
+ throw new RangeError('JWT refresh session expiration must be in the future');
98
+ }
99
+ const id = crypto.randomUUID();
100
+ const refreshToken = this.generateRefreshToken();
101
+ await this.db.transaction(async (transaction) => {
102
+ const user = await transaction.get({
103
+ sql: `SELECT id FROM ${this.tables.users} WHERE id = ? AND status = 'active';`,
104
+ params: [userId],
105
+ });
106
+ if (!user)
107
+ throw new ActiveJwtSessionUserNotFoundError(userId);
108
+ await transaction.run({
109
+ sql: [
110
+ `INSERT INTO ${this.tables.jwtSessions}`,
111
+ '(id, user_id, status, expires_at) VALUES (?, ?, ?, ?);',
112
+ ].join(' '),
113
+ params: [id, userId, 'active', refreshExpiresAt.toISOString()],
114
+ });
115
+ await transaction.run({
116
+ sql: [
117
+ `INSERT INTO ${this.tables.jwtRefreshTokens}`,
118
+ '(session_id, token_hash, expires_at) VALUES (?, ?, ?);',
119
+ ].join(' '),
120
+ params: [id, this.hashRefreshToken(refreshToken), refreshExpiresAt.toISOString()],
121
+ });
122
+ await this.events?.report({
123
+ type: 'jwt-session.created',
124
+ occurredAt: this.now(),
125
+ userId,
126
+ credential: { type: 'jwt', id },
127
+ }, transaction);
128
+ });
129
+ return {
130
+ id,
131
+ userId,
132
+ expiresAt: refreshExpiresAt.toISOString(),
133
+ refreshToken,
134
+ refreshExpiresAt: refreshExpiresAt.toISOString(),
135
+ };
136
+ }
137
+ async refresh(refreshToken) {
138
+ const nextRefreshToken = this.generateRefreshToken();
139
+ const now = this.now();
140
+ return this.db.transaction(async (transaction) => {
141
+ const record = await transaction.get({
142
+ sql: [
143
+ 'SELECT sessions.id, sessions.user_id, sessions.status,',
144
+ 'refresh_tokens.expires_at AS refresh_expires_at',
145
+ `FROM ${this.tables.jwtRefreshTokens} AS refresh_tokens`,
146
+ `INNER JOIN ${this.tables.jwtSessions} AS sessions ON sessions.id = refresh_tokens.session_id`,
147
+ `INNER JOIN ${this.tables.users} AS users ON users.id = sessions.user_id`,
148
+ "WHERE refresh_tokens.token_hash = ? AND users.status = 'active';",
149
+ ].join(' '),
150
+ params: [this.hashRefreshToken(refreshToken)],
151
+ });
152
+ const expiresAt = record ? new Date(record.refresh_expires_at) : undefined;
153
+ if (!record ||
154
+ record.status !== 'active' ||
155
+ !expiresAt ||
156
+ !Number.isFinite(expiresAt.getTime()) ||
157
+ expiresAt.getTime() <= now.getTime()) {
158
+ throw new InvalidRefreshTokenError();
159
+ }
160
+ await transaction.run({
161
+ sql: [
162
+ `UPDATE ${this.tables.jwtRefreshTokens}`,
163
+ 'SET token_hash = ?, last_used_at = ? WHERE session_id = ?;',
164
+ ].join(' '),
165
+ params: [this.hashRefreshToken(nextRefreshToken), now.toISOString(), record.id],
166
+ });
167
+ await this.events?.report({
168
+ type: 'jwt-session.refreshed',
169
+ occurredAt: now,
170
+ userId: Number(record.user_id),
171
+ credential: { type: 'jwt', id: record.id },
172
+ }, transaction);
173
+ return {
174
+ id: record.id,
175
+ userId: Number(record.user_id),
176
+ expiresAt: expiresAt.toISOString(),
177
+ refreshToken: nextRefreshToken,
178
+ refreshExpiresAt: expiresAt.toISOString(),
179
+ };
180
+ });
181
+ }
182
+ // ---------------------------------------------------------------------
183
+ // Session management
184
+ // ---------------------------------------------------------------------
185
+ async list(userId) {
186
+ const now = this.now().getTime();
187
+ const records = await this.db.all({
188
+ sql: [
189
+ 'SELECT id, user_id, status, expires_at, created_at',
190
+ `FROM ${this.tables.jwtSessions} WHERE user_id = ?`,
191
+ 'ORDER BY created_at DESC, id DESC;',
192
+ ].join(' '),
193
+ params: [userId],
194
+ });
195
+ return records.map(record => ({
196
+ id: record.id,
197
+ userId: Number(record.user_id),
198
+ status: record.status !== 'active'
199
+ ? 'revoked'
200
+ : new Date(record.expires_at).getTime() <= now ? 'expired' : 'active',
201
+ expiresAt: new Date(record.expires_at).toISOString(),
202
+ createdAt: new Date(record.created_at).toISOString(),
203
+ }));
204
+ }
205
+ async revokeAll(userId) {
206
+ await this.db.transaction(async (transaction) => {
207
+ const sessions = await transaction.all({
208
+ sql: `SELECT id FROM ${this.tables.jwtSessions} WHERE user_id = ? AND status = 'active';`,
209
+ params: [userId],
210
+ });
211
+ await transaction.run({
212
+ sql: `UPDATE ${this.tables.jwtSessions} SET status = 'revoked' WHERE user_id = ? AND status = 'active';`,
213
+ params: [userId],
214
+ });
215
+ for (const session of sessions) {
216
+ await this.events?.report({
217
+ type: 'jwt-session.revoked',
218
+ occurredAt: this.now(),
219
+ userId,
220
+ credential: { type: 'jwt', id: session.id },
221
+ }, transaction);
222
+ }
223
+ });
224
+ }
53
225
  async revoke(userId, sessionId) {
54
226
  await this.db.transaction(async (transaction) => {
55
227
  const session = await transaction.get({
@@ -70,5 +242,14 @@ export class DatabaseJwtSessionService {
70
242
  }, transaction);
71
243
  });
72
244
  }
245
+ // ---------------------------------------------------------------------
246
+ // Security helpers
247
+ // ---------------------------------------------------------------------
248
+ generateRefreshToken() {
249
+ return `kdl_rt_${crypto.randomBytes(32).toString('base64url')}`;
250
+ }
251
+ hashRefreshToken(token) {
252
+ return crypto.createHash('sha256').update(token).digest('hex');
253
+ }
73
254
  }
74
255
  //# sourceMappingURL=database-jwt-session-service.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"database-jwt-session-service.js","sourceRoot":"","sources":["../src/database-jwt-session-service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"database-jwt-session-service.js","sourceRoot":"","sources":["../src/database-jwt-session-service.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,36 @@
1
1
  import type { PasswordCredential, PasswordCredentialRepository } from '@kurdel/auth';
2
2
  import type { Database } from '@kurdel/db';
3
3
  import { type AuthDatabaseTables } from './auth-database-tables.js';
4
+ /**
5
+ * ## DatabasePasswordCredentialRepository
6
+ *
7
+ * Database-backed repository for password authentication credentials.
8
+ *
9
+ * Responsibilities:
10
+ * - locate password credentials by login identifier
11
+ * - map database records to `PasswordCredential`
12
+ * - isolate authentication from the underlying database schema
13
+ *
14
+ * Guarantees:
15
+ * - returns `null` when no matching credentials exist
16
+ * - performs case-insensitive login lookup
17
+ * - remains database-agnostic (SQLite/PostgreSQL)
18
+ *
19
+ * Non-responsibilities:
20
+ * - password verification
21
+ * - password hashing
22
+ * - user management
23
+ * - authentication workflows
24
+ */
4
25
  export declare class DatabasePasswordCredentialRepository implements PasswordCredentialRepository {
5
26
  private readonly db;
6
27
  private readonly tables;
28
+ /**
29
+ * Creates a new database-backed password credential repository.
30
+ *
31
+ * @param db Database abstraction used for persistence.
32
+ * @param tables Optional table name overrides.
33
+ */
7
34
  constructor(db: Database, tables?: Partial<AuthDatabaseTables>);
8
35
  findByLogin(login: string): Promise<PasswordCredential | null>;
9
36
  }
@@ -1,5 +1,32 @@
1
1
  import { resolveAuthDatabaseTables } from './auth-database-tables.js';
2
+ /**
3
+ * ## DatabasePasswordCredentialRepository
4
+ *
5
+ * Database-backed repository for password authentication credentials.
6
+ *
7
+ * Responsibilities:
8
+ * - locate password credentials by login identifier
9
+ * - map database records to `PasswordCredential`
10
+ * - isolate authentication from the underlying database schema
11
+ *
12
+ * Guarantees:
13
+ * - returns `null` when no matching credentials exist
14
+ * - performs case-insensitive login lookup
15
+ * - remains database-agnostic (SQLite/PostgreSQL)
16
+ *
17
+ * Non-responsibilities:
18
+ * - password verification
19
+ * - password hashing
20
+ * - user management
21
+ * - authentication workflows
22
+ */
2
23
  export class DatabasePasswordCredentialRepository {
24
+ /**
25
+ * Creates a new database-backed password credential repository.
26
+ *
27
+ * @param db Database abstraction used for persistence.
28
+ * @param tables Optional table name overrides.
29
+ */
3
30
  constructor(db, tables = {}) {
4
31
  this.db = db;
5
32
  this.tables = resolveAuthDatabaseTables(tables);
@@ -1 +1 @@
1
- {"version":3,"file":"database-password-credential-repository.js","sourceRoot":"","sources":["../src/database-password-credential-repository.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,yBAAyB,EAA2B,MAAM,2BAA2B,CAAC;AAI/F,MAAM,OAAO,oCAAoC;IAG/C,YACmB,EAAY,EAC7B,SAAsC,EAAE;QADvB,OAAE,GAAF,EAAE,CAAU;QAG7B,IAAI,CAAC,MAAM,GAAG,yBAAyB,CAAC,MAAM,CAAC,CAAC;IAClD,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,KAAa;QAC7B,MAAM,MAAM,GAAG,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC;YAChC,GAAG,EAAE;gBACH,8DAA8D,IAAI,CAAC,MAAM,CAAC,mBAAmB,cAAc;gBAC3G,cAAc,IAAI,CAAC,MAAM,CAAC,KAAK,0CAA0C;gBACzE,sCAAsC;aACvC,CAAC,IAAI,CAAC,GAAG,CAAC;YACX,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;SACvB,CAAC,CAAiC,CAAC;QACpC,OAAO,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,YAAY,EAAE,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IACxF,CAAC;CACF"}
1
+ {"version":3,"file":"database-password-credential-repository.js","sourceRoot":"","sources":["../src/database-password-credential-repository.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,yBAAyB,EAA2B,MAAM,2BAA2B,CAAC;AAI/F;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,OAAO,oCAAoC;IAG/C;;;;;OAKG;IACH,YACmB,EAAY,EAC7B,SAAsC,EAAE;QADvB,OAAE,GAAF,EAAE,CAAU;QAG7B,IAAI,CAAC,MAAM,GAAG,yBAAyB,CAAC,MAAM,CAAC,CAAC;IAClD,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,KAAa;QAC7B,MAAM,MAAM,GAAG,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC;YAChC,GAAG,EAAE;gBACH,8DAA8D,IAAI,CAAC,MAAM,CAAC,mBAAmB,cAAc;gBAC3G,cAAc,IAAI,CAAC,MAAM,CAAC,KAAK,0CAA0C;gBACzE,sCAAsC;aACvC,CAAC,IAAI,CAAC,GAAG,CAAC;YACX,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;SACvB,CAAC,CAAiC,CAAC;QACpC,OAAO,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,YAAY,EAAE,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IACxF,CAAC;CACF"}
@@ -5,10 +5,41 @@ export declare class PasswordUserNotFoundError extends Error {
5
5
  readonly userId: number;
6
6
  constructor(userId: number);
7
7
  }
8
+ /**
9
+ * ## DatabasePasswordService
10
+ *
11
+ * Application service responsible for managing user password credentials
12
+ * backed by a relational database through the `Database` abstraction.
13
+ *
14
+ * Responsibilities:
15
+ * - set or replace user password credentials
16
+ * - hash passwords before persisting them
17
+ * - ensure the target user exists
18
+ *
19
+ * Guarantees:
20
+ * - never stores plaintext passwords
21
+ * - delegates password hashing to the configured `PasswordHasher`
22
+ * - performs updates atomically using a database transaction
23
+ * - remains database-agnostic (SQLite/PostgreSQL)
24
+ *
25
+ * Non-responsibilities:
26
+ * - password verification
27
+ * - password policy enforcement
28
+ * - password reset workflows
29
+ * - authentication
30
+ * - HTTP request handling
31
+ */
8
32
  export declare class DatabasePasswordService {
9
33
  private readonly db;
10
34
  private readonly hasher;
11
35
  private readonly tables;
36
+ /**
37
+ * Creates a new database-backed password management service.
38
+ *
39
+ * @param db Database abstraction used for persistence.
40
+ * @param hasher Password hasher used to derive secure password hashes.
41
+ * @param tables Optional table name overrides.
42
+ */
12
43
  constructor(db: Database, hasher: PasswordHasher, tables?: Partial<AuthDatabaseTables>);
13
44
  set(userId: number, password: string): Promise<void>;
14
45
  }
@@ -5,7 +5,38 @@ export class PasswordUserNotFoundError extends Error {
5
5
  this.userId = userId;
6
6
  }
7
7
  }
8
+ /**
9
+ * ## DatabasePasswordService
10
+ *
11
+ * Application service responsible for managing user password credentials
12
+ * backed by a relational database through the `Database` abstraction.
13
+ *
14
+ * Responsibilities:
15
+ * - set or replace user password credentials
16
+ * - hash passwords before persisting them
17
+ * - ensure the target user exists
18
+ *
19
+ * Guarantees:
20
+ * - never stores plaintext passwords
21
+ * - delegates password hashing to the configured `PasswordHasher`
22
+ * - performs updates atomically using a database transaction
23
+ * - remains database-agnostic (SQLite/PostgreSQL)
24
+ *
25
+ * Non-responsibilities:
26
+ * - password verification
27
+ * - password policy enforcement
28
+ * - password reset workflows
29
+ * - authentication
30
+ * - HTTP request handling
31
+ */
8
32
  export class DatabasePasswordService {
33
+ /**
34
+ * Creates a new database-backed password management service.
35
+ *
36
+ * @param db Database abstraction used for persistence.
37
+ * @param hasher Password hasher used to derive secure password hashes.
38
+ * @param tables Optional table name overrides.
39
+ */
9
40
  constructor(db, hasher, tables = {}) {
10
41
  this.db = db;
11
42
  this.hasher = hasher;
@@ -1 +1 @@
1
- {"version":3,"file":"database-password-service.js","sourceRoot":"","sources":["../src/database-password-service.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,yBAAyB,EAA2B,MAAM,2BAA2B,CAAC;AAE/F,MAAM,OAAO,yBAA0B,SAAQ,KAAK;IAClD,YAAqB,MAAc;QACjC,KAAK,CAAC,SAAS,MAAM,iBAAiB,CAAC,CAAC;QADrB,WAAM,GAAN,MAAM,CAAQ;IAEnC,CAAC;CACF;AAED,MAAM,OAAO,uBAAuB;IAGlC,YACmB,EAAY,EACZ,MAAsB,EACvC,SAAsC,EAAE;QAFvB,OAAE,GAAF,EAAE,CAAU;QACZ,WAAM,GAAN,MAAM,CAAgB;QAGvC,IAAI,CAAC,MAAM,GAAG,yBAAyB,CAAC,MAAM,CAAC,CAAC;IAClD,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,MAAc,EAAE,QAAgB;QACxC,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACtD,MAAM,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,KAAK,EAAC,WAAW,EAAC,EAAE;YAC5C,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,GAAG,CAAC;gBACjC,GAAG,EAAE,kBAAkB,IAAI,CAAC,MAAM,CAAC,KAAK,gBAAgB;gBACxD,MAAM,EAAE,CAAC,MAAM,CAAC;aACjB,CAAC,CAAC;YACH,IAAI,CAAC,IAAI;gBAAE,MAAM,IAAI,yBAAyB,CAAC,MAAM,CAAC,CAAC;YACvD,MAAM,WAAW,CAAC,GAAG,CAAC;gBACpB,GAAG,EAAE;oBACH,eAAe,IAAI,CAAC,MAAM,CAAC,mBAAmB,uCAAuC;oBACrF,kCAAkC;oBAClC,4GAA4G;iBAC7G,CAAC,IAAI,CAAC,GAAG,CAAC;gBACX,MAAM,EAAE,CAAC,MAAM,EAAE,YAAY,CAAC;aAC/B,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
1
+ {"version":3,"file":"database-password-service.js","sourceRoot":"","sources":["../src/database-password-service.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,yBAAyB,EAA2B,MAAM,2BAA2B,CAAC;AAE/F,MAAM,OAAO,yBAA0B,SAAQ,KAAK;IAClD,YAAqB,MAAc;QACjC,KAAK,CAAC,SAAS,MAAM,iBAAiB,CAAC,CAAC;QADrB,WAAM,GAAN,MAAM,CAAQ;IAEnC,CAAC;CACF;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,OAAO,uBAAuB;IAGlC;;;;;;OAMG;IACH,YACmB,EAAY,EACZ,MAAsB,EACvC,SAAsC,EAAE;QAFvB,OAAE,GAAF,EAAE,CAAU;QACZ,WAAM,GAAN,MAAM,CAAgB;QAGvC,IAAI,CAAC,MAAM,GAAG,yBAAyB,CAAC,MAAM,CAAC,CAAC;IAClD,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,MAAc,EAAE,QAAgB;QACxC,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACtD,MAAM,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,KAAK,EAAC,WAAW,EAAC,EAAE;YAC5C,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,GAAG,CAAC;gBACjC,GAAG,EAAE,kBAAkB,IAAI,CAAC,MAAM,CAAC,KAAK,gBAAgB;gBACxD,MAAM,EAAE,CAAC,MAAM,CAAC;aACjB,CAAC,CAAC;YACH,IAAI,CAAC,IAAI;gBAAE,MAAM,IAAI,yBAAyB,CAAC,MAAM,CAAC,CAAC;YACvD,MAAM,WAAW,CAAC,GAAG,CAAC;gBACpB,GAAG,EAAE;oBACH,eAAe,IAAI,CAAC,MAAM,CAAC,mBAAmB,uCAAuC;oBACrF,kCAAkC;oBAClC,4GAA4G;iBAC7G,CAAC,IAAI,CAAC,GAAG,CAAC;gBACX,MAAM,EAAE,CAAC,MAAM,EAAE,YAAY,CAAC;aAC/B,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -89,36 +89,70 @@ export declare class RoleInUseError extends Error {
89
89
  readonly userCount: number;
90
90
  constructor(roleId: number, userCount: number);
91
91
  }
92
+ /**
93
+ * ## DatabaseUserService
94
+ *
95
+ * Application service responsible for user, role and permission management
96
+ * backed by a relational database through the `Database` abstraction.
97
+ *
98
+ * Responsibilities:
99
+ * - manage users and their lifecycle
100
+ * - assign and revoke user roles
101
+ * - manage roles and role permissions
102
+ * - provide paginated user listings
103
+ * - execute bulk user operations
104
+ * - expose dashboard statistics
105
+ *
106
+ * Guarantees:
107
+ * - validates referenced roles and permissions before persisting changes
108
+ * - keeps user-role relationships consistent using database transactions
109
+ * - translates database constraint violations into domain-specific errors
110
+ * - remains database-agnostic (SQLite/PostgreSQL)
111
+ *
112
+ * Non-responsibilities:
113
+ * - authentication
114
+ * - authorization policy evaluation
115
+ * - password management
116
+ * - JWT or API key validation
117
+ * - HTTP request handling
118
+ */
92
119
  export declare class DatabaseUserService {
93
120
  private readonly db;
94
121
  private readonly tables;
122
+ /**
123
+ * Creates a new database-backed user management service.
124
+ *
125
+ * @param db Database abstraction used for all persistence operations.
126
+ * @param tables Optional table name overrides.
127
+ */
95
128
  constructor(db: Database, tables?: Partial<AuthDatabaseTables>);
96
- listRoles(): Promise<string[]>;
97
- listRoleSummaries(): Promise<RoleSummary[]>;
98
- listPermissions(): Promise<string[]>;
99
- setRolePermissions(roleId: number, names: string[]): Promise<RoleSummary>;
100
- createRole(name: string): Promise<RoleSummary>;
101
- renameRole(roleId: number, name: string): Promise<RoleSummary>;
102
- deleteRole(roleId: number): Promise<void>;
103
129
  create(input: CreateUserInput): Promise<ManagedUser>;
104
- list(input: ListUsersInput): Promise<UserList>;
105
- bulkUpdate(input: BulkUpdateUsersInput): Promise<ManagedUser[]>;
106
- bulkDelete(userIds: number[]): Promise<void>;
107
- dashboardStats(): Promise<AdminDashboardStats>;
108
- findById(userId: number): Promise<ManagedUser>;
109
130
  update(userId: number, input: UpdateUserInput): Promise<ManagedUser>;
110
131
  delete(userId: number): Promise<void>;
132
+ findById(userId: number): Promise<ManagedUser>;
111
133
  private findRecord;
134
+ list(input: ListUsersInput): Promise<UserList>;
135
+ bulkUpdate(input: BulkUpdateUsersInput): Promise<ManagedUser[]>;
136
+ bulkDelete(userIds: number[]): Promise<void>;
137
+ createRole(name: string): Promise<RoleSummary>;
138
+ renameRole(roleId: number, name: string): Promise<RoleSummary>;
139
+ deleteRole(roleId: number): Promise<void>;
140
+ listRoles(): Promise<string[]>;
141
+ listRoleSummaries(): Promise<RoleSummary[]>;
112
142
  private findRole;
143
+ listPermissions(): Promise<string[]>;
144
+ setRolePermissions(roleId: number, names: string[]): Promise<RoleSummary>;
145
+ dashboardStats(): Promise<AdminDashboardStats>;
113
146
  private ensureUsersExist;
114
147
  private resolveRoles;
115
148
  private resolvePermissions;
116
149
  private loadRolePermissions;
117
- private replaceRoles;
118
150
  private loadRoles;
151
+ private replaceRoles;
119
152
  private mapUser;
120
153
  private normalizeEmail;
121
154
  private rethrowEmailConflict;
122
155
  private rethrowRoleConflict;
123
156
  private isUniqueConstraintError;
157
+ private toCount;
124
158
  }