@kurdel/auth 0.1.0-beta.5 → 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 (74) hide show
  1. package/README.md +28 -24
  2. package/lib/domain/auth-context.d.ts +16 -1
  3. package/lib/domain/auth-event-sink-provider.d.ts +10 -0
  4. package/lib/domain/auth-event.d.ts +34 -3
  5. package/lib/domain/auth-event.js +8 -1
  6. package/lib/domain/auth-event.js.map +1 -1
  7. package/lib/domain/auth-strategy-provider.d.ts +17 -0
  8. package/lib/domain/auth-strategy.d.ts +17 -7
  9. package/lib/domain/authorization-policy-composition.d.ts +20 -3
  10. package/lib/domain/authorization-policy-composition.js +24 -3
  11. package/lib/domain/authorization-policy-composition.js.map +1 -1
  12. package/lib/domain/authorization-policy-provider.d.ts +17 -0
  13. package/lib/domain/authorization-policy.d.ts +39 -3
  14. package/lib/domain/authorization-policy.js +8 -2
  15. package/lib/domain/authorization-policy.js.map +1 -1
  16. package/lib/domain/permission.d.ts +12 -2
  17. package/lib/domain/permission.js +16 -3
  18. package/lib/domain/permission.js.map +1 -1
  19. package/lib/infra/in-memory/in-memory-api-key-repository.d.ts +11 -1
  20. package/lib/infra/in-memory/in-memory-api-key-repository.js +11 -1
  21. package/lib/infra/in-memory/in-memory-api-key-repository.js.map +1 -1
  22. package/lib/infra/in-memory/in-memory-auth-user-repository.d.ts +11 -1
  23. package/lib/infra/in-memory/in-memory-auth-user-repository.js +11 -1
  24. package/lib/infra/in-memory/in-memory-auth-user-repository.js.map +1 -1
  25. package/lib/infra/in-memory/in-memory-jwt-repository.d.ts +5 -1
  26. package/lib/infra/in-memory/in-memory-jwt-repository.js +5 -1
  27. package/lib/infra/in-memory/in-memory-jwt-repository.js.map +1 -1
  28. package/lib/password/password-authentication-service.d.ts +29 -0
  29. package/lib/password/password-authentication-service.js +31 -1
  30. package/lib/password/password-authentication-service.js.map +1 -1
  31. package/lib/password/password-hasher.d.ts +18 -0
  32. package/lib/password/scrypt-password-hasher.d.ts +46 -1
  33. package/lib/password/scrypt-password-hasher.js +33 -1
  34. package/lib/password/scrypt-password-hasher.js.map +1 -1
  35. package/lib/repositories/api-key/api-key-repository.d.ts +22 -12
  36. package/lib/repositories/api-key/api-key-usage-recorder.d.ts +12 -1
  37. package/lib/repositories/jwt/jwt-repository.d.ts +7 -1
  38. package/lib/repositories/jwt/jwt-session-repository.d.ts +27 -3
  39. package/lib/repositories/password/password-credential-repository.d.ts +25 -1
  40. package/lib/repositories/user/auth-user-repository.d.ts +16 -4
  41. package/lib/runtime/auth-module.d.ts +32 -28
  42. package/lib/runtime/auth-module.js +26 -12
  43. package/lib/runtime/auth-module.js.map +1 -1
  44. package/lib/runtime/auth-strategy-registry.d.ts +24 -7
  45. package/lib/runtime/auth-strategy-registry.js +24 -7
  46. package/lib/runtime/auth-strategy-registry.js.map +1 -1
  47. package/lib/runtime/authorization-policy-registry.d.ts +35 -1
  48. package/lib/runtime/authorization-policy-registry.js +35 -1
  49. package/lib/runtime/authorization-policy-registry.js.map +1 -1
  50. package/lib/runtime/create-auth-middleware.d.ts +32 -0
  51. package/lib/runtime/create-auth-middleware.js +41 -2
  52. package/lib/runtime/create-auth-middleware.js.map +1 -1
  53. package/lib/strategies/api-key/api-key-strategy-provider.d.ts +18 -0
  54. package/lib/strategies/api-key/api-key-strategy-provider.js +30 -0
  55. package/lib/strategies/api-key/api-key-strategy-provider.js.map +1 -0
  56. package/lib/strategies/api-key/api-key-strategy.d.ts +39 -1
  57. package/lib/strategies/api-key/api-key-strategy.js +34 -1
  58. package/lib/strategies/api-key/api-key-strategy.js.map +1 -1
  59. package/lib/strategies/api-key/index.d.ts +1 -0
  60. package/lib/strategies/api-key/index.js +1 -0
  61. package/lib/strategies/api-key/index.js.map +1 -1
  62. package/lib/strategies/jwt/index.d.ts +1 -0
  63. package/lib/strategies/jwt/index.js +1 -0
  64. package/lib/strategies/jwt/index.js.map +1 -1
  65. package/lib/strategies/jwt/jwt-service.d.ts +61 -10
  66. package/lib/strategies/jwt/jwt-service.js +38 -9
  67. package/lib/strategies/jwt/jwt-service.js.map +1 -1
  68. package/lib/strategies/jwt/jwt-strategy-provider.d.ts +18 -0
  69. package/lib/strategies/jwt/jwt-strategy-provider.js +27 -0
  70. package/lib/strategies/jwt/jwt-strategy-provider.js.map +1 -0
  71. package/lib/strategies/jwt/jwt-strategy.d.ts +43 -4
  72. package/lib/strategies/jwt/jwt-strategy.js +26 -2
  73. package/lib/strategies/jwt/jwt-strategy.js.map +1 -1
  74. package/package.json +4 -4
package/README.md CHANGED
@@ -15,30 +15,31 @@ npm install @kurdel/auth
15
15
 
16
16
  ## Configure authentication
17
17
 
18
- Register one or more named strategies with `AuthModule`. A strategy instance
19
- can be supplied directly or created from the application container:
18
+ Register one or more named strategies with `AuthModule`. Built-in provider
19
+ helpers resolve their framework dependencies from the application container:
20
20
 
21
21
  ```ts
22
- import { ApiKeyStrategy, AUTH_TOKENS, AuthModule } from '@kurdel/auth';
22
+ import { apiKeyStrategy, AuthModule, jwtStrategy } from '@kurdel/auth';
23
23
 
24
24
  const auth = new AuthModule({
25
- strategies: [
26
- {
27
- name: 'api-key',
28
- useFactory: ioc =>
29
- new ApiKeyStrategy({
30
- header: 'x-api-key',
31
- credentials: ioc.get(AUTH_TOKENS.ApiKeyRepository),
32
- users: ioc.get(AUTH_TOKENS.UserRepository),
33
- usage: ioc.get(AUTH_TOKENS.ApiKeyUsageRecorder),
34
- }),
35
- },
36
- ],
25
+ strategies: [apiKeyStrategy({ usage: true }), jwtStrategy({ sessions: true })],
37
26
  });
38
27
  ```
39
28
 
29
+ This example assumes the application container already provides `JwtService`,
30
+ the user and credential repositories, `JwtSessionRepository`, and
31
+ `ApiKeyUsageRecorder`. `AuthDatabaseModule` supplies the repository-backed
32
+ dependencies; applications using `@kurdel/auth` alone must register their own
33
+ implementations. Omit `sessions` or `usage` when those optional services are
34
+ not needed.
35
+
40
36
  `AuthModule` registers the authentication middleware automatically. Strategy
41
- names are application-defined and are referenced by route metadata.
37
+ names are referenced by route metadata. `apiKeyStrategy()` uses `x-api-key` by
38
+ default; `usage: true` resolves the registered usage recorder. `jwtStrategy()`
39
+ uses the standard Bearer header; `sessions: true` resolves the registered JWT
40
+ session repository. Both options also accept explicit repository instances for
41
+ custom integrations. Applications can still register custom names and manual
42
+ strategy instances or factories through `AuthStrategyProvider`.
42
43
 
43
44
  ## Protect routes
44
45
 
@@ -226,18 +227,21 @@ the repository credential ID when one exists. The JWT strategy exposes
226
227
  `credential.type` as `jwt`, uses the `jti` claim as its optional ID, and places
227
228
  the verified payload in `claims`.
228
229
 
229
- To make JWTs revocable before their cryptographic expiration, configure a
230
- `JwtSessionRepository` on the strategy. Session-backed JWTs must contain a
231
- `jti`; authentication then verifies that the referenced session exists, belongs
232
- to the token subject, has not been revoked, and has not expired:
230
+ To make JWTs revocable before their cryptographic expiration, enable a
231
+ registered `JwtSessionRepository`. Session-backed JWTs must contain a `jti`;
232
+ authentication then verifies that the referenced session exists, belongs to
233
+ the token subject, has not been revoked, and has not expired:
233
234
 
234
235
  ```ts
235
- new JwtStrategy(jwtService, users, {
236
- sessions: jwtSessions,
237
- });
236
+ jwtStrategy({ sessions: true });
238
237
  ```
239
238
 
240
- Without `sessions`, JWT verification remains stateless and backward compatible.
239
+ An explicit repository instance may be supplied instead of `true`. Without
240
+ `sessions`, JWT verification remains stateless and backward compatible.
241
+ Database-backed applications can pair short-lived access JWTs with rotating
242
+ opaque refresh tokens through `DatabaseJwtSessionService` from
243
+ `@kurdel/auth-db`. Refresh tokens are not JWTs and should never be placed in
244
+ authorization headers or persisted in plaintext by an application.
241
245
 
242
246
  ## User and credential repositories
243
247
 
@@ -1,8 +1,23 @@
1
1
  import type { AuthCredential, AuthUser } from '@kurdel/common';
2
2
  export type { AuthContext, AuthCredential } from '@kurdel/common';
3
- /** Data produced by a strategy before middleware attaches the strategy name. */
3
+ /**
4
+ * ## AuthenticationResult
5
+ *
6
+ * Result returned by an authentication strategy after successful
7
+ * credential validation.
8
+ *
9
+ * The authentication middleware enriches this result with the strategy
10
+ * name before exposing it through `ctx.auth`.
11
+ */
4
12
  export interface AuthenticationResult<TUser extends AuthUser = AuthUser> {
13
+ /** Authenticated application user. */
5
14
  user: TUser;
15
+ /** Metadata describing the authenticated credential. */
6
16
  credential?: AuthCredential;
17
+ /**
18
+ * Optional authentication claims produced by the strategy.
19
+ *
20
+ * For example, JWT strategies may expose verified token claims.
21
+ */
7
22
  claims?: Record<string, unknown>;
8
23
  }
@@ -1,5 +1,15 @@
1
1
  import type { Container } from '@kurdel/ioc';
2
2
  import type { AuthEventSink } from './auth-event.js';
3
+ /**
4
+ * ## AuthEventSinkProvider
5
+ *
6
+ * Describes how an authentication event sink is supplied to
7
+ * {@link AuthModule}.
8
+ *
9
+ * Applications may provide either:
10
+ * - an existing event sink instance
11
+ * - a factory that resolves the sink from the IoC container
12
+ */
3
13
  export type AuthEventSinkProvider = {
4
14
  use: AuthEventSink;
5
15
  } | {
@@ -1,9 +1,23 @@
1
1
  import type { AuthCredential, AuthUser } from '@kurdel/common';
2
+ /**
3
+ * Common properties shared by every authentication lifecycle event.
4
+ */
2
5
  type AuthEventBase = {
6
+ /** Time at which the event occurred. */
3
7
  occurredAt: Date;
8
+ /** Authenticated user, when known. */
4
9
  userId?: AuthUser['id'];
10
+ /** Credential involved in the event, when applicable. */
5
11
  credential?: AuthCredential;
6
12
  };
13
+ /**
14
+ * ## AuthEvent
15
+ *
16
+ * Represents a sanitized authentication or authorization lifecycle event.
17
+ *
18
+ * Events intentionally exclude secrets and raw credentials so they can be
19
+ * safely persisted, logged, or forwarded to external audit systems.
20
+ */
7
21
  export type AuthEvent = (AuthEventBase & {
8
22
  type: 'authentication.succeeded';
9
23
  strategy: string;
@@ -20,13 +34,30 @@ export type AuthEvent = (AuthEventBase & {
20
34
  }) | (AuthEventBase & {
21
35
  type: 'api-key.issued' | 'api-key.revoked';
22
36
  }) | (AuthEventBase & {
23
- type: 'jwt-session.created' | 'jwt-session.revoked';
37
+ type: 'jwt-session.created' | 'jwt-session.refreshed' | 'jwt-session.revoked';
24
38
  });
25
- /** Receives sanitized authentication and authorization lifecycle events. */
39
+ /**
40
+ * ## AuthEventSink
41
+ *
42
+ * Receives sanitized authentication lifecycle events.
43
+ *
44
+ * Implementations may persist events, write them to logs, publish them to
45
+ * message brokers, or forward them to external audit systems.
46
+ */
26
47
  export interface AuthEventSink {
48
+ /**
49
+ * Reports an authentication lifecycle event.
50
+ */
27
51
  report(event: AuthEvent): Promise<void> | void;
28
52
  }
29
- /** Default sink used when an application does not configure event reporting. */
53
+ /**
54
+ * ## NoopAuthEventSink
55
+ *
56
+ * Default {@link AuthEventSink} implementation that silently ignores all
57
+ * reported events.
58
+ *
59
+ * Used when an application does not configure audit reporting.
60
+ */
30
61
  export declare class NoopAuthEventSink implements AuthEventSink {
31
62
  report(_event: AuthEvent): void;
32
63
  }
@@ -1,4 +1,11 @@
1
- /** Default sink used when an application does not configure event reporting. */
1
+ /**
2
+ * ## NoopAuthEventSink
3
+ *
4
+ * Default {@link AuthEventSink} implementation that silently ignores all
5
+ * reported events.
6
+ *
7
+ * Used when an application does not configure audit reporting.
8
+ */
2
9
  export class NoopAuthEventSink {
3
10
  report(_event) { }
4
11
  }
@@ -1 +1 @@
1
- {"version":3,"file":"auth-event.js","sourceRoot":"","sources":["../../src/domain/auth-event.ts"],"names":[],"mappings":"AAqCA,gFAAgF;AAChF,MAAM,OAAO,iBAAiB;IAC5B,MAAM,CAAC,MAAiB,IAAS,CAAC;CACnC"}
1
+ {"version":3,"file":"auth-event.js","sourceRoot":"","sources":["../../src/domain/auth-event.ts"],"names":[],"mappings":"AA+DA;;;;;;;GAOG;AACH,MAAM,OAAO,iBAAiB;IAC5B,MAAM,CAAC,MAAiB,IAAS,CAAC;CACnC"}
@@ -1,9 +1,26 @@
1
1
  import type { Container } from '@kurdel/ioc';
2
2
  import type { AuthStrategy } from '../domain/index.js';
3
+ /**
4
+ * ## AuthStrategyProvider
5
+ *
6
+ * Describes how an authentication strategy is supplied to
7
+ * {@link AuthModule}.
8
+ *
9
+ * Applications may provide either:
10
+ * - an existing strategy instance
11
+ * - a factory that resolves the strategy from the IoC container
12
+ *
13
+ * Each strategy is registered under the specified name and can later be
14
+ * referenced from route authentication metadata.
15
+ */
3
16
  export type AuthStrategyProvider = {
17
+ /** Strategy name used by route metadata. */
4
18
  name: string;
19
+ /** Existing strategy instance. */
5
20
  use: AuthStrategy;
6
21
  } | {
22
+ /** Strategy name used by route metadata. */
7
23
  name: string;
24
+ /** Factory that resolves the strategy from the IoC container. */
8
25
  useFactory: (c: Container) => AuthStrategy;
9
26
  };
@@ -3,15 +3,25 @@ import type { AuthenticationResult } from './auth-context.js';
3
3
  /**
4
4
  * ## AuthStrategy
5
5
  *
6
- * A pluggable authentication mechanism.
7
- * Each strategy decides how to extract and validate credentials
8
- * from the incoming HTTP request.
6
+ * Contract implemented by every authentication strategy.
9
7
  *
10
- * The strategy:
11
- * - returns an AuthenticationResult on success
12
- * - returns null if authentication fails
13
- * - must NOT throw on invalid credentials
8
+ * A strategy is responsible for extracting credentials from an incoming
9
+ * HTTP request, validating them, and resolving the authenticated
10
+ * application identity.
11
+ *
12
+ * Guarantees:
13
+ * - returns an {@link AuthenticationResult} after successful authentication
14
+ * - returns `null` when authentication cannot be established
15
+ * - does not throw for invalid or missing credentials
16
+ *
17
+ * Strategies remain independent of storage. User identities and
18
+ * credential metadata are resolved through repository contracts.
14
19
  */
15
20
  export interface AuthStrategy {
21
+ /**
22
+ * Attempts to authenticate the incoming request.
23
+ *
24
+ * Returns `null` when the request does not contain valid credentials.
25
+ */
16
26
  authenticate(req: HttpRequest): Promise<AuthenticationResult | null>;
17
27
  }
@@ -1,7 +1,24 @@
1
1
  import { type AuthorizationPolicy } from './authorization-policy.js';
2
- /** Grants access only when every nested policy grants access. */
2
+ /**
3
+ * Combines multiple authorization policies using logical AND.
4
+ *
5
+ * Access is granted only when every nested policy grants access.
6
+ * Evaluation stops at the first denial.
7
+ */
3
8
  export declare function allOf(...policies: AuthorizationPolicy[]): AuthorizationPolicy;
4
- /** Grants access when at least one nested policy grants access. */
9
+ /**
10
+ * Combines multiple authorization policies using logical OR.
11
+ *
12
+ * Access is granted when any nested policy grants access.
13
+ * When every policy denies access, the most informative denial
14
+ * reason is preserved.
15
+ */
5
16
  export declare function anyOf(...policies: AuthorizationPolicy[]): AuthorizationPolicy;
6
- /** Inverts a nested policy and uses the supplied reason when inversion denies access. */
17
+ /**
18
+ * Inverts the result of an authorization policy.
19
+ *
20
+ * When the wrapped policy grants access, the returned policy denies
21
+ * access. An optional denial reason may be supplied for the inverted
22
+ * decision.
23
+ */
7
24
  export declare function not(policy: AuthorizationPolicy, reason?: string): AuthorizationPolicy;
@@ -1,8 +1,17 @@
1
1
  import { authorizationDecision, } from './authorization-policy.js';
2
+ /**
3
+ * Evaluates a policy and normalizes its result into an
4
+ * {@link AuthorizationDecision}.
5
+ */
2
6
  async function evaluate(policy, auth, ctx) {
3
7
  return authorizationDecision(await policy.authorize(auth, ctx));
4
8
  }
5
- /** Grants access only when every nested policy grants access. */
9
+ /**
10
+ * Combines multiple authorization policies using logical AND.
11
+ *
12
+ * Access is granted only when every nested policy grants access.
13
+ * Evaluation stops at the first denial.
14
+ */
6
15
  export function allOf(...policies) {
7
16
  return {
8
17
  async authorize(auth, ctx) {
@@ -15,7 +24,13 @@ export function allOf(...policies) {
15
24
  },
16
25
  };
17
26
  }
18
- /** Grants access when at least one nested policy grants access. */
27
+ /**
28
+ * Combines multiple authorization policies using logical OR.
29
+ *
30
+ * Access is granted when any nested policy grants access.
31
+ * When every policy denies access, the most informative denial
32
+ * reason is preserved.
33
+ */
19
34
  export function anyOf(...policies) {
20
35
  return {
21
36
  async authorize(auth, ctx) {
@@ -31,7 +46,13 @@ export function anyOf(...policies) {
31
46
  },
32
47
  };
33
48
  }
34
- /** Inverts a nested policy and uses the supplied reason when inversion denies access. */
49
+ /**
50
+ * Inverts the result of an authorization policy.
51
+ *
52
+ * When the wrapped policy grants access, the returned policy denies
53
+ * access. An optional denial reason may be supplied for the inverted
54
+ * decision.
55
+ */
35
56
  export function not(policy, reason) {
36
57
  return {
37
58
  async authorize(auth, ctx) {
@@ -1 +1 @@
1
- {"version":3,"file":"authorization-policy-composition.js","sourceRoot":"","sources":["../../src/domain/authorization-policy-composition.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,qBAAqB,GAGtB,MAAM,2BAA2B,CAAC;AAEnC,KAAK,UAAU,QAAQ,CACrB,MAA2B,EAC3B,IAA2B,EAC3B,GAAgB;IAEhB,OAAO,qBAAqB,CAAC,MAAM,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;AAClE,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,KAAK,CAAC,GAAG,QAA+B;IACtD,OAAO;QACL,KAAK,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG;YACvB,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;gBAC9B,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;gBACnD,IAAI,CAAC,QAAQ,CAAC,OAAO;oBAAE,OAAO,QAAQ,CAAC;YACzC,CAAC;YACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3B,CAAC;KACF,CAAC;AACJ,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,KAAK,CAAC,GAAG,QAA+B;IACtD,OAAO;QACL,KAAK,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG;YACvB,IAAI,MAAM,GAA0B,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;YACvD,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;gBAC9B,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;gBACnD,IAAI,QAAQ,CAAC,OAAO;oBAAE,OAAO,QAAQ,CAAC;gBACtC,IAAI,QAAQ,CAAC,MAAM;oBAAE,MAAM,GAAG,QAAQ,CAAC;YACzC,CAAC;YACD,OAAO,MAAM,CAAC;QAChB,CAAC;KACF,CAAC;AACJ,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,GAAG,CAAC,MAA2B,EAAE,MAAe;IAC9D,OAAO;QACL,KAAK,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG;YACvB,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;YACnD,OAAO,QAAQ,CAAC,OAAO;gBACrB,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE;gBACnD,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QACxB,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"authorization-policy-composition.js","sourceRoot":"","sources":["../../src/domain/authorization-policy-composition.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,qBAAqB,GAGtB,MAAM,2BAA2B,CAAC;AAEnC;;;GAGG;AACH,KAAK,UAAU,QAAQ,CACrB,MAA2B,EAC3B,IAA2B,EAC3B,GAAgB;IAEhB,OAAO,qBAAqB,CAAC,MAAM,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC;AAClE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,KAAK,CAAC,GAAG,QAA+B;IACtD,OAAO;QACL,KAAK,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG;YACvB,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;gBAC9B,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;gBACnD,IAAI,CAAC,QAAQ,CAAC,OAAO;oBAAE,OAAO,QAAQ,CAAC;YACzC,CAAC;YACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3B,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,KAAK,CAAC,GAAG,QAA+B;IACtD,OAAO;QACL,KAAK,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG;YACvB,IAAI,MAAM,GAA0B,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;YAEvD,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;gBAC9B,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;gBAEnD,IAAI,QAAQ,CAAC,OAAO;oBAAE,OAAO,QAAQ,CAAC;gBACtC,IAAI,QAAQ,CAAC,MAAM;oBAAE,MAAM,GAAG,QAAQ,CAAC;YACzC,CAAC;YAED,OAAO,MAAM,CAAC;QAChB,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,GAAG,CACjB,MAA2B,EAC3B,MAAe;IAEf,OAAO;QACL,KAAK,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG;YACvB,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;YAEnD,OAAO,QAAQ,CAAC,OAAO;gBACrB,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE;gBACnD,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QACxB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -1,9 +1,26 @@
1
1
  import type { Container } from '@kurdel/ioc';
2
2
  import type { AuthorizationPolicy } from './authorization-policy.js';
3
+ /**
4
+ * ## AuthorizationPolicyProvider
5
+ *
6
+ * Describes how an authorization policy is supplied to
7
+ * {@link AuthModule}.
8
+ *
9
+ * Applications may provide either:
10
+ * - an existing policy instance
11
+ * - a factory that resolves the policy from the IoC container
12
+ *
13
+ * Each policy is registered under the specified name and can later be
14
+ * referenced from route authorization metadata.
15
+ */
3
16
  export type AuthorizationPolicyProvider = {
17
+ /** Policy name used by route metadata. */
4
18
  name: string;
19
+ /** Existing policy instance. */
5
20
  use: AuthorizationPolicy;
6
21
  } | {
22
+ /** Policy name used by route metadata. */
7
23
  name: string;
24
+ /** Factory that resolves the policy from the IoC container. */
8
25
  useFactory: (container: Container) => AuthorizationPolicy;
9
26
  };
@@ -1,14 +1,50 @@
1
1
  import type { AuthContext } from '@kurdel/common';
2
2
  import type { HttpContext } from '@kurdel/core/http';
3
+ /**
4
+ * ## AuthorizationDecision
5
+ *
6
+ * Result of an authorization policy evaluation.
7
+ */
3
8
  export type AuthorizationDecision = {
9
+ /** Indicates whether access is granted. */
4
10
  allowed: boolean;
5
- /** Safe, non-sensitive reason code suitable for authorization audit events. */
11
+ /**
12
+ * Safe, non-sensitive reason code suitable for audit events.
13
+ *
14
+ * This value is intended for diagnostics and should not expose
15
+ * confidential application details.
16
+ */
6
17
  reason?: string;
7
18
  };
19
+ /**
20
+ * Result returned by an authorization policy.
21
+ *
22
+ * Policies may return either a simple boolean or a richer
23
+ * {@link AuthorizationDecision}.
24
+ */
8
25
  export type AuthorizationPolicyResult = boolean | AuthorizationDecision;
9
- /** Performs an application-specific authorization check for a request. */
26
+ /**
27
+ * ## AuthorizationPolicy
28
+ *
29
+ * Contract implemented by application authorization policies.
30
+ *
31
+ * Policies evaluate an authenticated request and decide whether it
32
+ * should be allowed to proceed.
33
+ *
34
+ * Policies should:
35
+ * - remain deterministic
36
+ * - avoid observable side effects
37
+ * - return diagnostic reasons only when they are safe to expose
38
+ */
10
39
  export interface AuthorizationPolicy {
40
+ /**
41
+ * Evaluates whether the authenticated request is authorized.
42
+ */
11
43
  authorize(auth: Readonly<AuthContext>, ctx: HttpContext): AuthorizationPolicyResult | Promise<AuthorizationPolicyResult>;
12
44
  }
13
- /** Converts a boolean-compatible policy result into a diagnostic decision. */
45
+ /**
46
+ * Normalizes a policy result into an {@link AuthorizationDecision}.
47
+ *
48
+ * Boolean results are converted into the equivalent decision object.
49
+ */
14
50
  export declare function authorizationDecision(result: AuthorizationPolicyResult): AuthorizationDecision;
@@ -1,5 +1,11 @@
1
- /** Converts a boolean-compatible policy result into a diagnostic decision. */
1
+ /**
2
+ * Normalizes a policy result into an {@link AuthorizationDecision}.
3
+ *
4
+ * Boolean results are converted into the equivalent decision object.
5
+ */
2
6
  export function authorizationDecision(result) {
3
- return typeof result === 'boolean' ? { allowed: result } : result;
7
+ return typeof result === 'boolean'
8
+ ? { allowed: result }
9
+ : result;
4
10
  }
5
11
  //# sourceMappingURL=authorization-policy.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"authorization-policy.js","sourceRoot":"","sources":["../../src/domain/authorization-policy.ts"],"names":[],"mappings":"AAmBA,8EAA8E;AAC9E,MAAM,UAAU,qBAAqB,CAAC,MAAiC;IACrE,OAAO,OAAO,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;AACpE,CAAC"}
1
+ {"version":3,"file":"authorization-policy.js","sourceRoot":"","sources":["../../src/domain/authorization-policy.ts"],"names":[],"mappings":"AAsDA;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CACnC,MAAiC;IAEjC,OAAO,OAAO,MAAM,KAAK,SAAS;QAChC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE;QACrB,CAAC,CAAC,MAAM,CAAC;AACb,CAAC"}
@@ -1,6 +1,16 @@
1
1
  import type { AuthUser } from '@kurdel/common';
2
2
  import type { AuthorizationPolicy } from './authorization-policy.js';
3
- /** Returns whether an authenticated user has a resolved capability. */
3
+ /**
4
+ * Determines whether a user has a resolved permission.
5
+ *
6
+ * Permissions are expected to be precomputed during authentication and
7
+ * attached to the authenticated user.
8
+ */
4
9
  export declare function hasPermission(user: Readonly<AuthUser>, permission: string): boolean;
5
- /** Creates a policy that requires one resolved permission. */
10
+ /**
11
+ * Creates an authorization policy that requires a specific permission.
12
+ *
13
+ * Access is granted only when the authenticated user has the specified
14
+ * resolved permission.
15
+ */
6
16
  export declare function permissionPolicy(permission: string): AuthorizationPolicy;
@@ -1,13 +1,26 @@
1
- /** Returns whether an authenticated user has a resolved capability. */
1
+ /**
2
+ * Determines whether a user has a resolved permission.
3
+ *
4
+ * Permissions are expected to be precomputed during authentication and
5
+ * attached to the authenticated user.
6
+ */
2
7
  export function hasPermission(user, permission) {
3
8
  return user.permissions?.includes(permission) ?? false;
4
9
  }
5
- /** Creates a policy that requires one resolved permission. */
10
+ /**
11
+ * Creates an authorization policy that requires a specific permission.
12
+ *
13
+ * Access is granted only when the authenticated user has the specified
14
+ * resolved permission.
15
+ */
6
16
  export function permissionPolicy(permission) {
7
17
  return {
8
18
  authorize: auth => hasPermission(auth.user, permission)
9
19
  ? { allowed: true }
10
- : { allowed: false, reason: `missing-permission:${permission}` },
20
+ : {
21
+ allowed: false,
22
+ reason: `missing-permission:${permission}`,
23
+ },
11
24
  };
12
25
  }
13
26
  //# sourceMappingURL=permission.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"permission.js","sourceRoot":"","sources":["../../src/domain/permission.ts"],"names":[],"mappings":"AAIA,uEAAuE;AACvE,MAAM,UAAU,aAAa,CAAC,IAAwB,EAAE,UAAkB;IACxE,OAAO,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,UAAU,CAAC,IAAI,KAAK,CAAC;AACzD,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,gBAAgB,CAAC,UAAkB;IACjD,OAAO;QACL,SAAS,EAAE,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC;YACrD,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE;YACnB,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,sBAAsB,UAAU,EAAE,EAAE;KACnE,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"permission.js","sourceRoot":"","sources":["../../src/domain/permission.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAC3B,IAAwB,EACxB,UAAkB;IAElB,OAAO,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,UAAU,CAAC,IAAI,KAAK,CAAC;AACzD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAC9B,UAAkB;IAElB,OAAO;QACL,SAAS,EAAE,IAAI,CAAC,EAAE,CAChB,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC;YAClC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE;YACnB,CAAC,CAAC;gBACE,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,sBAAsB,UAAU,EAAE;aAC3C;KACR,CAAC;AACJ,CAAC"}
@@ -1,7 +1,17 @@
1
1
  import type { ApiKeyCredential, ApiKeyRepository } from '../../repositories/index.js';
2
- /** In-memory credential source intended for tests, demos and bootstrap code. */
2
+ /**
3
+ * ## InMemoryApiKeyRepository
4
+ *
5
+ * In-memory implementation of {@link ApiKeyRepository}.
6
+ *
7
+ * Intended for tests, examples, and small applications where
8
+ * credential data is managed directly in memory.
9
+ */
3
10
  export declare class InMemoryApiKeyRepository implements ApiKeyRepository {
4
11
  private readonly keys;
5
12
  constructor(keys: Record<string, ApiKeyCredential>);
13
+ /**
14
+ * Resolves the credential associated with an API key.
15
+ */
6
16
  findByKey(key: string): ApiKeyCredential | null;
7
17
  }
@@ -1,8 +1,18 @@
1
- /** In-memory credential source intended for tests, demos and bootstrap code. */
1
+ /**
2
+ * ## InMemoryApiKeyRepository
3
+ *
4
+ * In-memory implementation of {@link ApiKeyRepository}.
5
+ *
6
+ * Intended for tests, examples, and small applications where
7
+ * credential data is managed directly in memory.
8
+ */
2
9
  export class InMemoryApiKeyRepository {
3
10
  constructor(keys) {
4
11
  this.keys = keys;
5
12
  }
13
+ /**
14
+ * Resolves the credential associated with an API key.
15
+ */
6
16
  findByKey(key) {
7
17
  return this.keys[key] ?? null;
8
18
  }
@@ -1 +1 @@
1
- {"version":3,"file":"in-memory-api-key-repository.js","sourceRoot":"","sources":["../../../src/infra/in-memory/in-memory-api-key-repository.ts"],"names":[],"mappings":"AAEA,gFAAgF;AAChF,MAAM,OAAO,wBAAwB;IACnC,YAA6B,IAAsC;QAAtC,SAAI,GAAJ,IAAI,CAAkC;IAAG,CAAC;IAEvE,SAAS,CAAC,GAAW;QACnB,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;IAChC,CAAC;CACF"}
1
+ {"version":3,"file":"in-memory-api-key-repository.js","sourceRoot":"","sources":["../../../src/infra/in-memory/in-memory-api-key-repository.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,MAAM,OAAO,wBAAwB;IACnC,YAA6B,IAAsC;QAAtC,SAAI,GAAJ,IAAI,CAAkC;IAAG,CAAC;IAEvE;;OAEG;IACH,SAAS,CAAC,GAAW;QACnB,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;IAChC,CAAC;CACF"}
@@ -1,8 +1,18 @@
1
1
  import type { AuthUser } from '@kurdel/common';
2
2
  import type { AuthUserRepository } from '../../repositories/index.js';
3
- /** In-memory identity source intended for tests, demos and bootstrap code. */
3
+ /**
4
+ * ## InMemoryAuthUserRepository
5
+ *
6
+ * In-memory implementation of {@link AuthUserRepository}.
7
+ *
8
+ * Intended for tests, examples, and small applications where user
9
+ * identities are managed directly in memory.
10
+ */
4
11
  export declare class InMemoryAuthUserRepository implements AuthUserRepository {
5
12
  private readonly users;
6
13
  constructor(users: AuthUser[]);
14
+ /**
15
+ * Resolves the current user by identifier.
16
+ */
7
17
  findById(id: string | number): AuthUser | null;
8
18
  }
@@ -1,8 +1,18 @@
1
- /** In-memory identity source intended for tests, demos and bootstrap code. */
1
+ /**
2
+ * ## InMemoryAuthUserRepository
3
+ *
4
+ * In-memory implementation of {@link AuthUserRepository}.
5
+ *
6
+ * Intended for tests, examples, and small applications where user
7
+ * identities are managed directly in memory.
8
+ */
2
9
  export class InMemoryAuthUserRepository {
3
10
  constructor(users) {
4
11
  this.users = users;
5
12
  }
13
+ /**
14
+ * Resolves the current user by identifier.
15
+ */
6
16
  findById(id) {
7
17
  return this.users.find(user => user.id === id) ?? null;
8
18
  }
@@ -1 +1 @@
1
- {"version":3,"file":"in-memory-auth-user-repository.js","sourceRoot":"","sources":["../../../src/infra/in-memory/in-memory-auth-user-repository.ts"],"names":[],"mappings":"AAIA,8EAA8E;AAC9E,MAAM,OAAO,0BAA0B;IACrC,YAA6B,KAAiB;QAAjB,UAAK,GAAL,KAAK,CAAY;IAAG,CAAC;IAElD,QAAQ,CAAC,EAAmB;QAC1B,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,IAAI,IAAI,CAAC;IACzD,CAAC;CACF"}
1
+ {"version":3,"file":"in-memory-auth-user-repository.js","sourceRoot":"","sources":["../../../src/infra/in-memory/in-memory-auth-user-repository.ts"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AACH,MAAM,OAAO,0BAA0B;IACrC,YAA6B,KAAiB;QAAjB,UAAK,GAAL,KAAK,CAAY;IAAG,CAAC;IAElD;;OAEG;IACH,QAAQ,CAAC,EAAmB;QAC1B,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,IAAI,IAAI,CAAC;IACzD,CAAC;CACF"}
@@ -1,7 +1,11 @@
1
1
  import type { AuthUser } from '@kurdel/common';
2
2
  import type { JwtRepository } from '../../repositories/index.js';
3
3
  import { InMemoryAuthUserRepository } from './in-memory-auth-user-repository.js';
4
- /** @deprecated Use InMemoryAuthUserRepository. */
4
+ /**
5
+ * @deprecated Use {@link InMemoryAuthUserRepository} instead.
6
+ *
7
+ * Compatibility alias for the previous repository name.
8
+ */
5
9
  export declare class InMemoryJwtRepository extends InMemoryAuthUserRepository implements JwtRepository {
6
10
  constructor(users: AuthUser[]);
7
11
  }
@@ -1,5 +1,9 @@
1
1
  import { InMemoryAuthUserRepository } from './in-memory-auth-user-repository.js';
2
- /** @deprecated Use InMemoryAuthUserRepository. */
2
+ /**
3
+ * @deprecated Use {@link InMemoryAuthUserRepository} instead.
4
+ *
5
+ * Compatibility alias for the previous repository name.
6
+ */
3
7
  export class InMemoryJwtRepository extends InMemoryAuthUserRepository {
4
8
  constructor(users) {
5
9
  super(users);
@@ -1 +1 @@
1
- {"version":3,"file":"in-memory-jwt-repository.js","sourceRoot":"","sources":["../../../src/infra/in-memory/in-memory-jwt-repository.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,0BAA0B,EAAE,MAAM,qCAAqC,CAAC;AAEjF,kDAAkD;AAClD,MAAM,OAAO,qBACX,SAAQ,0BAA0B;IAElC,YAAY,KAAiB;QAC3B,KAAK,CAAC,KAAK,CAAC,CAAC;IACf,CAAC;CACF"}
1
+ {"version":3,"file":"in-memory-jwt-repository.js","sourceRoot":"","sources":["../../../src/infra/in-memory/in-memory-jwt-repository.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,0BAA0B,EAAE,MAAM,qCAAqC,CAAC;AAEjF;;;;GAIG;AACH,MAAM,OAAO,qBACX,SAAQ,0BAA0B;IAElC,YAAY,KAAiB;QAC3B,KAAK,CAAC,KAAK,CAAC,CAAC;IACf,CAAC;CACF"}