@happyvertical/smrt-users 0.53.4 → 0.53.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 (61) hide show
  1. package/AGENTS.md +43 -2
  2. package/README.md +185 -2
  3. package/agents/retention.md +14 -7
  4. package/dist/chunks/{TerminalAuthService-BtjXxw6J.js → TerminalAuthService-XQFMjUmW.js} +3373 -2121
  5. package/dist/chunks/TerminalAuthService-XQFMjUmW.js.map +1 -0
  6. package/dist/collections/CliAuthApproveLimitCollection.d.ts +4 -0
  7. package/dist/collections/CliAuthApproveLimitCollection.d.ts.map +1 -1
  8. package/dist/collections/CliAuthRequestCollection.d.ts.map +1 -1
  9. package/dist/collections/LoginAttemptCollection.d.ts +105 -0
  10. package/dist/collections/LoginAttemptCollection.d.ts.map +1 -0
  11. package/dist/collections/LoginAuditEventCollection.d.ts +19 -0
  12. package/dist/collections/LoginAuditEventCollection.d.ts.map +1 -0
  13. package/dist/collections/PinCredentialCollection.d.ts +26 -0
  14. package/dist/collections/PinCredentialCollection.d.ts.map +1 -0
  15. package/dist/collections/SessionCollection.d.ts +33 -1
  16. package/dist/collections/SessionCollection.d.ts.map +1 -1
  17. package/dist/collections/index.d.ts +3 -0
  18. package/dist/collections/index.d.ts.map +1 -1
  19. package/dist/index.d.ts +4 -4
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +144 -31
  22. package/dist/index.js.map +1 -1
  23. package/dist/manifest.json +3245 -1990
  24. package/dist/models/CliAuthApproveLimit.d.ts +8 -1
  25. package/dist/models/CliAuthApproveLimit.d.ts.map +1 -1
  26. package/dist/models/LoginAttempt.d.ts +59 -0
  27. package/dist/models/LoginAttempt.d.ts.map +1 -0
  28. package/dist/models/LoginAuditEvent.d.ts +49 -0
  29. package/dist/models/LoginAuditEvent.d.ts.map +1 -0
  30. package/dist/models/PinCredential.d.ts +31 -0
  31. package/dist/models/PinCredential.d.ts.map +1 -0
  32. package/dist/models/Session.d.ts +69 -1
  33. package/dist/models/Session.d.ts.map +1 -1
  34. package/dist/models/index.d.ts +4 -1
  35. package/dist/models/index.d.ts.map +1 -1
  36. package/dist/retention.d.ts +7 -1
  37. package/dist/retention.d.ts.map +1 -1
  38. package/dist/services/DeviceCredentialService.d.ts +348 -0
  39. package/dist/services/DeviceCredentialService.d.ts.map +1 -0
  40. package/dist/services/LoginAttemptLimiter.d.ts +227 -0
  41. package/dist/services/LoginAttemptLimiter.d.ts.map +1 -0
  42. package/dist/services/MobileAuthService.d.ts.map +1 -1
  43. package/dist/services/OperationPermissionService.d.ts.map +1 -1
  44. package/dist/services/SessionPermissionContext.d.ts.map +1 -1
  45. package/dist/services/SessionService.d.ts +56 -1
  46. package/dist/services/SessionService.d.ts.map +1 -1
  47. package/dist/services/TerminalAuthService.d.ts +18 -3
  48. package/dist/services/TerminalAuthService.d.ts.map +1 -1
  49. package/dist/services/index.d.ts +4 -2
  50. package/dist/services/index.d.ts.map +1 -1
  51. package/dist/smrt-knowledge.json +679 -9
  52. package/dist/sveltekit/device-credential-handlers.d.ts +60 -0
  53. package/dist/sveltekit/device-credential-handlers.d.ts.map +1 -0
  54. package/dist/sveltekit/index.d.ts +10 -0
  55. package/dist/sveltekit/index.d.ts.map +1 -1
  56. package/dist/sveltekit/types.d.ts +6 -0
  57. package/dist/sveltekit/types.d.ts.map +1 -1
  58. package/dist/sveltekit.js +184 -4
  59. package/dist/sveltekit.js.map +1 -1
  60. package/package.json +12 -12
  61. package/dist/chunks/TerminalAuthService-BtjXxw6J.js.map +0 -1
@@ -4,7 +4,14 @@
4
4
  * @packageDocumentation
5
5
  */
6
6
  import { SmrtObject } from '@happyvertical/smrt-core';
7
- /** Private database arbiter shared by every terminal-auth process. */
7
+ /**
8
+ * Private database arbiter shared by every terminal-auth process.
9
+ *
10
+ * @deprecated Since #3273 `TerminalAuthService` draws from the shared
11
+ * {@link UsersLoginAttempt} budget instead; this table is no longer written.
12
+ * The class stays exported so existing schemas and cleanup scripts keep
13
+ * resolving; it will be removed in a future major.
14
+ */
8
15
  export declare class UsersCliAuthApproveLimit extends SmrtObject {
9
16
  /** Approving browser user whose budget this row protects. */
10
17
  userId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"CliAuthApproveLimit.d.ts","sourceRoot":"","sources":["../../src/models/CliAuthApproveLimit.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAqB,UAAU,EAAQ,MAAM,0BAA0B,CAAC;AAE/E,sEAAsE;AACtE,qBAMa,wBAAyB,SAAQ,UAAU;IACtD,6DAA6D;IAE7D,MAAM,SAAM;IAEZ,0EAA0E;IAE1E,YAAY,SAAK;IAEjB,sDAAsD;IAEtD,eAAe,OAAc;CAC9B"}
1
+ {"version":3,"file":"CliAuthApproveLimit.d.ts","sourceRoot":"","sources":["../../src/models/CliAuthApproveLimit.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAqB,UAAU,EAAQ,MAAM,0BAA0B,CAAC;AAE/E;;;;;;;GAOG;AACH,qBAMa,wBAAyB,SAAQ,UAAU;IACtD,6DAA6D;IAE7D,MAAM,SAAM;IAEZ,0EAA0E;IAE1E,YAAY,SAAK;IAEjB,sDAAsD;IAEtD,eAAe,OAAc;CAC9B"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Durable, shared-storage login attempt budget — one row per limiter key.
3
+ *
4
+ * Every credential-based sign-in (terminal approve, PIN, and any host-side
5
+ * password or passkey flow) reserves an attempt here before doing credential
6
+ * work, so the budget is enforced across every replica that shares the
7
+ * database (#3273). The row is the arbiter; nothing is cached in-process.
8
+ *
9
+ * Keys are hashes, never raw identifiers: a subject key is derived from the
10
+ * identifier the client *submitted* (an email key or user id), and a source
11
+ * key from the client address or device, so the table never becomes a
12
+ * plaintext index of emails and IPs, and an unknown subject costs exactly the
13
+ * same row as a known one.
14
+ *
15
+ * @packageDocumentation
16
+ */
17
+ import { SmrtObject } from '@happyvertical/smrt-core';
18
+ /** The two independent budgets a sign-in attempt draws from. */
19
+ export type LoginAttemptScope = 'subject' | 'source';
20
+ /** Private database arbiter shared by every process that authenticates. */
21
+ export declare class UsersLoginAttempt extends SmrtObject {
22
+ /** `sha256(scope:normalizedKey)` — the UPSERT arbiter. */
23
+ limiterKey: string;
24
+ /** Which budget this row protects. Informational; the key already encodes it. */
25
+ scope: LoginAttemptScope;
26
+ /** Failed attempts plus currently reserved attempts inside the window. */
27
+ attemptCount: number;
28
+ /** Beginning of the current failed-attempt window. */
29
+ windowStartedAt: Date;
30
+ /**
31
+ * Consecutive failures that were not interrupted by a success. Drives the
32
+ * exponential lockout: each exhausted budget lengthens the next lockout.
33
+ */
34
+ failureStreak: number;
35
+ /**
36
+ * While set and in the future, every reservation for this key is refused
37
+ * regardless of the window. Null when the key is not locked out.
38
+ *
39
+ * Indexed: the retention sweep prunes idle rows by this and `retain_until`.
40
+ */
41
+ lockedUntil: Date | null;
42
+ /**
43
+ * When this key last failed. The whole streak is forgiven once this is
44
+ * older than the limiter's streak horizon — measured from the last
45
+ * FAILURE, not the last activity. A source key (a tablet, an office
46
+ * address) additionally sheds one failure per `sourceStreakDecaySeconds`
47
+ * since this time, so spaced-out mistakes on a busy shared device never
48
+ * accumulate.
49
+ */
50
+ lastFailedAt: Date | null;
51
+ /**
52
+ * When the limiter that last wrote this row stops reasoning about it (its
53
+ * own window and streak-forgiveness horizon). The retention sweep deletes
54
+ * only rows past this, so it honours each limiter's configuration rather
55
+ * than a process-wide default.
56
+ */
57
+ retainUntil: Date;
58
+ }
59
+ //# sourceMappingURL=LoginAttempt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoginAttempt.d.ts","sourceRoot":"","sources":["../../src/models/LoginAttempt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAS,UAAU,EAAQ,MAAM,0BAA0B,CAAC;AAEnE,gEAAgE;AAChE,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,QAAQ,CAAC;AAErD,2EAA2E;AAC3E,qBASa,iBAAkB,SAAQ,UAAU;IAC/C,0DAA0D;IAE1D,UAAU,SAAM;IAEhB,iFAAiF;IAEjF,KAAK,EAAE,iBAAiB,CAAa;IAErC,0EAA0E;IAE1E,YAAY,SAAK;IAEjB,sDAAsD;IAEtD,eAAe,OAAc;IAE7B;;;OAGG;IAEH,aAAa,SAAK;IAElB;;;;;OAKG;IAEH,WAAW,EAAE,IAAI,GAAG,IAAI,CAAQ;IAEhC;;;;;;;OAOG;IAEH,YAAY,EAAE,IAAI,GAAG,IAAI,CAAQ;IAEjC;;;;;OAKG;IAEH,WAAW,OAAc;CAC1B"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Durable record of a credential sign-in outcome (#3273).
3
+ *
4
+ * This is the default {@link LoginAuditSink} target: one row per decision
5
+ * the {@link LoginAttemptLimiter} makes, written through the collection so it
6
+ * is visible to the change feed and the retention sweep like any other smrt
7
+ * object. Hosts with their own audit log supply a sink instead.
8
+ *
9
+ * @packageDocumentation
10
+ */
11
+ import { SmrtObject } from '@happyvertical/smrt-core';
12
+ /** What happened to a sign-in attempt. */
13
+ export type LoginAuditOutcome =
14
+ /** Refused before credential work: budget exhausted or key locked out. */
15
+ 'denied'
16
+ /** Credential work ran and the credential was wrong. */
17
+ | 'failed'
18
+ /** Credential work ran and succeeded. */
19
+ | 'succeeded'
20
+ /** A failure exhausted the budget and the key is now locked out. */
21
+ | 'locked'
22
+ /** A credential was set, reset, or cleared (administrative). */
23
+ | 'managed';
24
+ export declare class UsersLoginAuditEvent extends SmrtObject {
25
+ /** Credential kind: `terminal-approve`, `pin`, `password`, `passkey`, … */
26
+ kind: string;
27
+ outcome: LoginAuditOutcome;
28
+ /** Hashed subject key, or null when the attempt had no subject. */
29
+ subjectKeyHash: string | null;
30
+ /** Hashed source key (IP or device), or null when the attempt had no source. */
31
+ sourceKeyHash: string | null;
32
+ /** Set on `denied`/`locked`: how long the client was told to wait. */
33
+ retryAfterSeconds: number | null;
34
+ /**
35
+ * When the decision was made.
36
+ *
37
+ * Indexed: the retention sweep prunes by this column.
38
+ */
39
+ occurredAt: Date;
40
+ /**
41
+ * Free-form JSON the caller attached. Never credentials or session ids;
42
+ * subjects stay hashed. The one identifier that belongs here is the acting
43
+ * administrator on a `managed` event, since accountability is its purpose.
44
+ */
45
+ metadata: string;
46
+ getMetadata(): Record<string, unknown>;
47
+ setMetadata(value: Record<string, unknown>): void;
48
+ }
49
+ //# sourceMappingURL=LoginAuditEvent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoginAuditEvent.d.ts","sourceRoot":"","sources":["../../src/models/LoginAuditEvent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAS,UAAU,EAAQ,MAAM,0BAA0B,CAAC;AAEnE,0CAA0C;AAC1C,MAAM,MAAM,iBAAiB;AAC3B,0EAA0E;AACxE,QAAQ;AACV,wDAAwD;GACtD,QAAQ;AACV,yCAAyC;GACvC,WAAW;AACb,oEAAoE;GAClE,QAAQ;AACV,gEAAgE;GAC9D,SAAS,CAAC;AAEd,qBASa,oBAAqB,SAAQ,UAAU;IAClD,2EAA2E;IAE3E,IAAI,SAAM;IAGV,OAAO,EAAE,iBAAiB,CAAY;IAEtC,mEAAmE;IAEnE,cAAc,EAAE,MAAM,GAAG,IAAI,CAAQ;IAErC,gFAAgF;IAEhF,aAAa,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEpC,sEAAsE;IAEtE,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAQ;IAExC;;;;OAIG;IAEH,UAAU,OAAc;IAExB;;;;OAIG;IAEH,QAAQ,SAAQ;IAEhB,WAAW,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAWtC,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;CAGlD"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Per-person PIN credential, usable only on an enrolled device (#3276).
3
+ *
4
+ * Deliberately its own object rather than a column on `User`, so the hash is
5
+ * never selected by the many existing user reads and never serialized by
6
+ * accident. One row per user.
7
+ *
8
+ * The hash is scrypt over `pepper || pin` with a per-row random salt. A PIN is
9
+ * a 4–8 digit secret: without a server-side pepper a leaked table would be
10
+ * brute-forced in seconds, and even with one the PIN is only accepted behind
11
+ * a live device bearer session and the login limiter — see
12
+ * {@link DeviceCredentialService}.
13
+ *
14
+ * @packageDocumentation
15
+ */
16
+ import { SmrtObject } from '@happyvertical/smrt-core';
17
+ export declare class UsersPinCredential extends SmrtObject {
18
+ /** The person this PIN signs in. */
19
+ userId: string;
20
+ /** Encoded hash: `scrypt$N$r$p$saltB64$hashB64`. */
21
+ pinHash: string;
22
+ /** Bumped on every set/reset so audits and sessions can reference a generation. */
23
+ version: number;
24
+ /** Set by an administrative reset; the person must choose a new PIN on next use. */
25
+ mustReset: boolean;
26
+ /** When the current hash was written. */
27
+ rotatedAt: Date | null;
28
+ /** `self`, or the user id of the administrator who last set it. */
29
+ rotatedBy: string | null;
30
+ }
31
+ //# sourceMappingURL=PinCredential.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PinCredential.d.ts","sourceRoot":"","sources":["../../src/models/PinCredential.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAqB,UAAU,EAAQ,MAAM,0BAA0B,CAAC;AAE/E,qBAQa,kBAAmB,SAAQ,UAAU;IAChD,oCAAoC;IAEpC,MAAM,SAAM;IAEZ,oDAAoD;IAEpD,OAAO,SAAM;IAEb,mFAAmF;IAEnF,OAAO,SAAK;IAEZ,oFAAoF;IAEpF,SAAS,UAAS;IAElB,yCAAyC;IAEzC,SAAS,EAAE,IAAI,GAAG,IAAI,CAAQ;IAE9B,mEAAmE;IAEnE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAQ;CACjC"}
@@ -18,11 +18,37 @@ export interface SessionOptions extends SmrtObjectOptions {
18
18
  /** Accepts a Date or any value the Date constructor can coerce. */
19
19
  lastAccessedAt?: Date | string | number;
20
20
  data?: Record<string, unknown>;
21
+ authMethod?: SessionAuthMethod | null;
22
+ parentSessionId?: string | null;
21
23
  }
24
+ /**
25
+ * How a session was established. Server-set at mint time, never trusted from
26
+ * the client. Hosts may use any string for their own flows; these are the
27
+ * values this package mints.
28
+ */
29
+ export type SessionAuthMethod = 'oidc' | 'magic-link' | 'terminal' | 'mobile' | 'pin' | (string & {});
22
30
  /**
23
31
  * Default session TTL: 7 days in seconds
24
32
  */
25
33
  export declare const DEFAULT_SESSION_TTL: number;
34
+ /**
35
+ * Reserved {@link Session.data} keys this package writes at mint time and
36
+ * enforces on every load (#3276). Server-set only: never copy client input
37
+ * into them, and do not overwrite them through `setSessionData`.
38
+ */
39
+ export declare const SESSION_DATA_KEYS: {
40
+ /** `string[]` of permission slugs the session's resolved set is intersected with. */
41
+ readonly permissionCeiling: "permissionCeiling";
42
+ /** ISO timestamp after which the session is invalid whatever its activity. */
43
+ readonly absoluteExpiresAt: "absoluteExpiresAt";
44
+ /** Sliding idle timeout in seconds, applied on every recorded activity. */
45
+ readonly idleSeconds: "idleSeconds";
46
+ };
47
+ /**
48
+ * Expiry for a session minted or extended now: `ttlSeconds` ahead, bounded by
49
+ * an absolute cap in `data` (an unreadable cap fails closed as already past).
50
+ */
51
+ export declare function resolveSessionExpiry(ttlSeconds: number, data: Record<string, unknown> | undefined): Date;
26
52
  /**
27
53
  * Generate a cryptographically secure session ID
28
54
  */
@@ -82,9 +108,51 @@ export declare class Session extends SmrtObject {
82
108
  * Custom session data (JSON serializable)
83
109
  */
84
110
  data: Record<string, unknown>;
111
+ /**
112
+ * Authentication channel that established this session (#3276, #2944).
113
+ * Null for sessions minted before this column existed or by hosts that do
114
+ * not set it.
115
+ */
116
+ authMethod: SessionAuthMethod | null;
117
+ /**
118
+ * Session this one is layered on — the enrolled device's bearer session
119
+ * under a per-person PIN session, for instance. A child is valid only while
120
+ * its parent is, so revoking the device signs out everyone on it.
121
+ *
122
+ * A native UUID column where the engine has one, like every other session
123
+ * id reference, but deliberately not a foreign key: a self-referencing FK would cascade
124
+ * the retention sweep's parent deletes, and the liveness rule in
125
+ * `SessionService.loadSessionContext` already makes an orphan invalid.
126
+ *
127
+ * Sensitive: the value IS the parent's (longer-lived) bearer credential,
128
+ * so public serialization of a child must never reveal it — otherwise a
129
+ * stolen person credential could be traded up for the device's.
130
+ *
131
+ * Indexed: `SessionCollection.findChildren()` and the sign-out cascade
132
+ * query by this column.
133
+ */
134
+ parentSessionId: string | null;
85
135
  constructor(options?: SessionOptions);
136
+ /** True when this session is layered on another one. */
137
+ isLayered(): boolean;
138
+ /**
139
+ * Absolute expiry cap (`data.absoluteExpiresAt`), or null when the session
140
+ * has none. An unreadable value fails closed as "already passed".
141
+ */
142
+ getAbsoluteExpiry(): Date | null;
143
+ /**
144
+ * Sliding idle timeout (`data.idleSeconds`), or null when the session uses
145
+ * the resolving service's TTL policy.
146
+ */
147
+ getIdleSeconds(): number | null;
148
+ /**
149
+ * Permission ceiling (`data.permissionCeiling`), or null when the session
150
+ * has none. A present but malformed value fails closed as an empty ceiling.
151
+ */
152
+ getPermissionCeiling(): string[] | null;
86
153
  /**
87
- * Check if the session is currently valid (active and not expired)
154
+ * Check if the session is currently valid (active, not expired, and not
155
+ * past its absolute cap)
88
156
  */
89
157
  isValid(): boolean;
90
158
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"Session.d.ts","sourceRoot":"","sources":["../../src/models/Session.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAGL,UAAU,EACV,KAAK,iBAAiB,EAEvB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD;;GAEG;AACH,MAAM,WAAW,cAAe,SAAQ,iBAAiB;IACvD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,mEAAmE;IACnE,SAAS,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,cAAc,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;IACxC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED;;GAEG;AACH,eAAO,MAAM,mBAAmB,QAAmB,CAAC;AAEpD;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAG1C;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAUa,OAAQ,SAAQ,UAAU;IACrC;;OAEG;IAEH,MAAM,EAAE,MAAM,CAAM;IAEpB;;;OAGG;IAEH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B;;OAEG;IAEH,MAAM,EAAE,aAAa,CAAwB;IAE7C;;;;;OAKG;IAEH,SAAS,EAAE,IAAI,CAAc;IAE7B;;OAEG;IACH,SAAS,EAAE,MAAM,CAAM;IAEvB;;OAEG;IACH,SAAS,EAAE,MAAM,CAAM;IAEvB;;OAEG;IACH,cAAc,EAAE,IAAI,CAAc;IAElC;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAM;gBAEvB,OAAO,GAAE,cAAmB;IAsBxC;;OAEG;IACH,OAAO,IAAI,OAAO;IAIlB;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,MAAM,CAAC,UAAU,GAAE,MAA4B,GAAG,IAAI;IAKtD,4EAA4E;IACtE,cAAc,CAClB,SAAS,UAAQ,EACjB,UAAU,GAAE,MAA4B,GACvC,OAAO,CAAC,OAAO,CAAC;YAoBL,wBAAwB;IAQtC;;OAEG;IACH,MAAM,IAAI,IAAI;IAId;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAIxC;;OAEG;IACH,OAAO,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAItC;;OAEG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI;IAI1C;;OAEG;IACH,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;CAG9B"}
1
+ {"version":3,"file":"Session.d.ts","sourceRoot":"","sources":["../../src/models/Session.ts"],"names":[],"mappings":"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"}
@@ -8,14 +8,17 @@ export { CliAuthRequest, type CliAuthRequestStatus, UsersCliAuthRequest, } from
8
8
  export { Group } from './Group.js';
9
9
  export { GroupMember } from './GroupMember.js';
10
10
  export { GroupRole } from './GroupRole.js';
11
+ export { type LoginAttemptScope, UsersLoginAttempt } from './LoginAttempt.js';
12
+ export { type LoginAuditOutcome, UsersLoginAuditEvent, } from './LoginAuditEvent.js';
11
13
  export { DEFAULT_TOKEN_EXPIRY_SECONDS, MagicLinkToken, UsersMagicLinkToken, } from './MagicLinkToken.js';
12
14
  export { Membership } from './Membership.js';
13
15
  export { MembershipOverride } from './MembershipOverride.js';
14
16
  export { isValidPermissionSlug, type ParsedPermissionSlug, Permission, parsePermissionSlug, } from './Permission.js';
17
+ export { UsersPinCredential } from './PinCredential.js';
15
18
  export { ResourceGrant, type ResourceGrantEffect, type ResourceGrantOptions, } from './ResourceGrant.js';
16
19
  export { Role } from './Role.js';
17
20
  export { RolePermission } from './RolePermission.js';
18
- export { DEFAULT_SESSION_TTL, generateSessionId, Session, } from './Session.js';
21
+ export { DEFAULT_SESSION_TTL, generateSessionId, SESSION_DATA_KEYS, Session, type SessionAuthMethod, } from './Session.js';
19
22
  export { MAX_TENANT_HIERARCHY_DEPTH, Tenant } from './Tenant.js';
20
23
  export { TenantIntegration, type TenantIntegrationCheckSummary, type TenantIntegrationOptions, type TenantIntegrationProvider, type TenantIntegrationStatus, } from './TenantIntegration.js';
21
24
  export { TenantPermissionOverride } from './TenantPermissionOverride.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/models/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE9E,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EACL,cAAc,EACd,KAAK,oBAAoB,EACzB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,OAAO,EACL,4BAA4B,EAC5B,cAAc,EACd,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EACL,qBAAqB,EACrB,KAAK,oBAAoB,EACzB,UAAU,EACV,mBAAmB,GACpB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,aAAa,EACb,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,GAC1B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,OAAO,GACR,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,0BAA0B,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EACL,iBAAiB,EACjB,KAAK,6BAA6B,EAClC,KAAK,wBAAwB,EAC7B,KAAK,yBAAyB,EAC9B,KAAK,uBAAuB,GAC7B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAEzE,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/models/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE9E,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,EACL,cAAc,EACd,KAAK,oBAAoB,EACzB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,OAAO,EAAE,KAAK,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC9E,OAAO,EACL,KAAK,iBAAiB,EACtB,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,4BAA4B,EAC5B,cAAc,EACd,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EACL,qBAAqB,EACrB,KAAK,oBAAoB,EACzB,UAAU,EACV,mBAAmB,GACpB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EACL,aAAa,EACb,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,GAC1B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,EACjB,OAAO,EACP,KAAK,iBAAiB,GACvB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,0BAA0B,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EACL,iBAAiB,EACjB,KAAK,6BAA6B,EAClC,KAAK,wBAAwB,EAC7B,KAAK,yBAAyB,EAC9B,KAAK,uBAAuB,GAC7B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAEzE,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC"}
@@ -28,8 +28,14 @@ export declare const SESSIONS_RETENTION_TASK = "users-sessions";
28
28
  export declare const MAGIC_LINK_RETENTION_TASK = "users-magic-link-tokens";
29
29
  /** Retention task name for expired CLI device-code requests. */
30
30
  export declare const CLI_AUTH_RETENTION_TASK = "users-cli-auth-requests";
31
+ /** Retention task name for idle login-attempt limiter rows (#3273). */
32
+ export declare const LOGIN_ATTEMPTS_RETENTION_TASK = "users-login-attempts";
33
+ /** Retention task name for login audit events (#3273). */
34
+ export declare const LOGIN_AUDIT_RETENTION_TASK = "users-login-audit-events";
35
+ /** How long login audit events are kept by default. */
36
+ export declare const DEFAULT_LOGIN_AUDIT_RETENTION_DAYS = 90;
31
37
  /** Every task name {@link registerUserRetentionTasks} installs. */
32
- export declare const USER_RETENTION_TASKS: readonly ["users-sessions", "users-magic-link-tokens", "users-cli-auth-requests"];
38
+ export declare const USER_RETENTION_TASKS: readonly ["users-sessions", "users-magic-link-tokens", "users-cli-auth-requests", "users-login-attempts", "users-login-audit-events"];
33
39
  /**
34
40
  * Register session and token expiry with the framework retention sweep.
35
41
  *
@@ -1 +1 @@
1
- {"version":3,"file":"retention.d.ts","sourceRoot":"","sources":["../src/retention.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAUH,4DAA4D;AAC5D,eAAO,MAAM,uBAAuB,mBAAmB,CAAC;AAExD,yDAAyD;AACzD,eAAO,MAAM,yBAAyB,4BAA4B,CAAC;AAEnE,gEAAgE;AAChE,eAAO,MAAM,uBAAuB,4BAA4B,CAAC;AAEjE,mEAAmE;AACnE,eAAO,MAAM,oBAAoB,mFAIvB,CAAC;AAEX;;;;;;;;;;GAUG;AACH,wBAAgB,0BAA0B,IAAI,IAAI,CA4BjD;AAED,sEAAsE;AACtE,wBAAgB,4BAA4B,IAAI,IAAI,CAInD"}
1
+ {"version":3,"file":"retention.d.ts","sourceRoot":"","sources":["../src/retention.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAYH,4DAA4D;AAC5D,eAAO,MAAM,uBAAuB,mBAAmB,CAAC;AAExD,yDAAyD;AACzD,eAAO,MAAM,yBAAyB,4BAA4B,CAAC;AAEnE,gEAAgE;AAChE,eAAO,MAAM,uBAAuB,4BAA4B,CAAC;AAEjE,uEAAuE;AACvE,eAAO,MAAM,6BAA6B,yBAAyB,CAAC;AAEpE,0DAA0D;AAC1D,eAAO,MAAM,0BAA0B,6BAA6B,CAAC;AAErE,uDAAuD;AACvD,eAAO,MAAM,kCAAkC,KAAK,CAAC;AAErD,mEAAmE;AACnE,eAAO,MAAM,oBAAoB,uIAMvB,CAAC;AAEX;;;;;;;;;;GAUG;AACH,wBAAgB,0BAA0B,IAAI,IAAI,CAmDjD;AAED,sEAAsE;AACtE,wBAAgB,4BAA4B,IAAI,IAAI,CAInD"}