@happyvertical/smrt-users 0.55.23 → 0.56.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 (43) hide show
  1. package/AGENTS.md +8 -0
  2. package/README.md +129 -0
  3. package/agents/permissions.md +14 -0
  4. package/dist/chunks/{TerminalAuthService-C8zxBkNB.js → TerminalAuthService-BQjH5_bB.js} +366 -135
  5. package/dist/chunks/TerminalAuthService-BQjH5_bB.js.map +1 -0
  6. package/dist/collections/GroupMemberCollection.d.ts +6 -2
  7. package/dist/collections/GroupMemberCollection.d.ts.map +1 -1
  8. package/dist/collections/MembershipOverrideCollection.d.ts +9 -2
  9. package/dist/collections/MembershipOverrideCollection.d.ts.map +1 -1
  10. package/dist/collections/TenantPermissionOverrideCollection.d.ts +8 -2
  11. package/dist/collections/TenantPermissionOverrideCollection.d.ts.map +1 -1
  12. package/dist/index.d.ts +2 -1
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +84 -29
  15. package/dist/index.js.map +1 -1
  16. package/dist/manifest.json +75 -45
  17. package/dist/migrations/deduplicateAuthorityPairs.d.ts +27 -0
  18. package/dist/migrations/deduplicateAuthorityPairs.d.ts.map +1 -0
  19. package/dist/migrations/deduplicateRolePermissions.d.ts +3 -10
  20. package/dist/migrations/deduplicateRolePermissions.d.ts.map +1 -1
  21. package/dist/migrations/natural-key-dedup.d.ts +32 -0
  22. package/dist/migrations/natural-key-dedup.d.ts.map +1 -0
  23. package/dist/models/GroupMember.d.ts.map +1 -1
  24. package/dist/models/LoginAuditEvent.d.ts +5 -0
  25. package/dist/models/LoginAuditEvent.d.ts.map +1 -1
  26. package/dist/models/MembershipOverride.d.ts.map +1 -1
  27. package/dist/models/Session.d.ts +9 -0
  28. package/dist/models/Session.d.ts.map +1 -1
  29. package/dist/models/TenantPermissionOverride.d.ts.map +1 -1
  30. package/dist/services/LoginAttemptLimiter.d.ts +62 -11
  31. package/dist/services/LoginAttemptLimiter.d.ts.map +1 -1
  32. package/dist/services/PasswordCredentialService.d.ts +83 -1
  33. package/dist/services/PasswordCredentialService.d.ts.map +1 -1
  34. package/dist/services/PermissionCatalogService.d.ts.map +1 -1
  35. package/dist/services/index.d.ts +2 -2
  36. package/dist/services/index.d.ts.map +1 -1
  37. package/dist/smrt-knowledge.json +16 -9
  38. package/dist/sveltekit/password-handlers.d.ts +7 -0
  39. package/dist/sveltekit/password-handlers.d.ts.map +1 -1
  40. package/dist/sveltekit.js +13 -1
  41. package/dist/sveltekit.js.map +1 -1
  42. package/package.json +13 -13
  43. package/dist/chunks/TerminalAuthService-C8zxBkNB.js.map +0 -1
@@ -33,6 +33,10 @@
33
33
  * - `resetPassword`: an administrator replaces someone else's and, by
34
34
  * default, flags `mustChange`. Ends every session of theirs.
35
35
  * - `clearPassword`: an administrator, or the person proving the current one.
36
+ * - `replaceForgottenPassword`: the person replaces their own WITHOUT the
37
+ * current one, from a fresh session the host minted after verifying an
38
+ * out-of-band proof (#3905). Off unless `recovery` is configured. Ends every
39
+ * session of theirs, this one included, so the proof is single use.
36
40
  *
37
41
  * A layered (device PIN) session never manages passwords, and an
38
42
  * administrator may only manage people whose every active membership is in
@@ -41,7 +45,7 @@
41
45
  *
42
46
  * @packageDocumentation
43
47
  */
44
- import type { SmrtClassOptions } from '@happyvertical/smrt-core';
48
+ import { type SmrtClassOptions } from '@happyvertical/smrt-core';
45
49
  import { type SessionAuthMethod } from '../models/Session.js';
46
50
  import { type ScryptParams } from './credential-hash.js';
47
51
  import { InvalidCredentialsError, LoginAttemptLimiter, type LoginAttemptLimiterOptions } from './LoginAttemptLimiter.js';
@@ -57,6 +61,10 @@ export declare const DEFAULT_PASSWORD_MIN_LENGTH = 10;
57
61
  export declare const DEFAULT_PASSWORD_MAX_LENGTH = 256;
58
62
  /** No configuration may raise the maximum above this: it bounds hashing work. */
59
63
  export declare const PASSWORD_MAX_LENGTH_CEILING = 1024;
64
+ /** Default freshness bound for an out-of-band recovery proof (10 minutes). */
65
+ export declare const DEFAULT_PASSWORD_RECOVERY_MAX_AGE_SECONDS: number;
66
+ /** No configuration may accept an out-of-band proof older than this (1 hour). */
67
+ export declare const PASSWORD_RECOVERY_MAX_AGE_CEILING_SECONDS: number;
60
68
  /**
61
69
  * Built-in denylist: a few of the most common passwords that pass a
62
70
  * 10-character minimum. Deliberately small — extend it through
@@ -123,6 +131,48 @@ export interface PasswordPolicyOptions {
123
131
  */
124
132
  scrypt?: Partial<ScryptParams>;
125
133
  }
134
+ /**
135
+ * Session data a host's recovery flow passes to `createSession({ data })`
136
+ * after it has verified an out-of-band proof (#3905): it stamps when the
137
+ * proof was verified, which `replaceForgottenPassword` checks for freshness.
138
+ * Never derive `provenAt` from client input.
139
+ */
140
+ export declare function outOfBandProofSessionData(provenAt?: Date): Record<string, string>;
141
+ /** What the host's recovery assertion is shown. */
142
+ export interface PasswordRecoveryProofContext {
143
+ /** The actor the call was made with; its session row has already passed every check. */
144
+ actor: SessionContext;
145
+ /** When the out-of-band proof was verified (the session's stamp). */
146
+ provenAt: Date;
147
+ }
148
+ /**
149
+ * Self-service replacement of a forgotten password (#3905). Every condition
150
+ * must hold, and any doubt refuses:
151
+ *
152
+ * - the actor's stored session is first-class (not layered, no permission
153
+ * ceiling), still valid, and belongs to the person;
154
+ * - its server-set `authMethod` is one of `authMethods`, which the host mints
155
+ * ONLY after verifying an out-of-band proof (never `password` or `pin`);
156
+ * - it carries a `SESSION_DATA_KEYS.outOfBandProofAt` stamp (see
157
+ * {@link outOfBandProofSessionData}) no older than `maxAgeSeconds`;
158
+ * - `assertProof`, when given, returns true.
159
+ */
160
+ export interface PasswordRecoveryOptions {
161
+ /** Session `authMethod`s the host mints only from an out-of-band proof. */
162
+ authMethods: readonly SessionAuthMethod[];
163
+ /**
164
+ * Oldest accepted proof, in seconds. Default
165
+ * {@link DEFAULT_PASSWORD_RECOVERY_MAX_AGE_SECONDS}; at most
166
+ * {@link PASSWORD_RECOVERY_MAX_AGE_CEILING_SECONDS}.
167
+ */
168
+ maxAgeSeconds?: number;
169
+ /**
170
+ * Optional host check run after the package's own, e.g. that the proof was
171
+ * a recovery link rather than an ordinary sign-in link. Anything but
172
+ * `true` refuses.
173
+ */
174
+ assertProof?: (context: PasswordRecoveryProofContext) => boolean | Promise<boolean>;
175
+ }
126
176
  export interface PasswordCredentialServiceOptions extends SmrtClassOptions {
127
177
  /** Lifetime of a password session in seconds. Default seven days. */
128
178
  sessionTtl?: number;
@@ -138,6 +188,12 @@ export interface PasswordCredentialServiceOptions extends SmrtClassOptions {
138
188
  managePermission?: string;
139
189
  /** Password policy. */
140
190
  password?: PasswordPolicyOptions;
191
+ /**
192
+ * Enables {@link PasswordCredentialService.replaceForgottenPassword}.
193
+ * Omitted: there is no way to replace a password without the current one
194
+ * except an administrator's reset.
195
+ */
196
+ recovery?: PasswordRecoveryOptions;
141
197
  }
142
198
  export interface PasswordSignInInput {
143
199
  /** What the person typed as their email; normalized like `User.emailKey`. */
@@ -194,6 +250,12 @@ export interface ResetPasswordInput {
194
250
  mustChange?: boolean;
195
251
  ipAddress?: string;
196
252
  }
253
+ export interface ReplaceForgottenPasswordInput {
254
+ /** The person's own session, minted by the host's recovery flow. */
255
+ actor: SessionContext;
256
+ newPassword: string;
257
+ ipAddress?: string;
258
+ }
197
259
  export interface ClearPasswordInput {
198
260
  actor: SessionContext;
199
261
  userId: string;
@@ -206,13 +268,16 @@ export declare class PasswordCredentialService {
206
268
  private readonly sessionTtl;
207
269
  private readonly managePermission;
208
270
  private readonly policy;
271
+ private readonly recovery;
209
272
  private sessionService;
273
+ private sessionRows;
210
274
  private memberships;
211
275
  private users;
212
276
  private credentials;
213
277
  private limiter;
214
278
  private dummyHash;
215
279
  constructor(options: PasswordCredentialServiceOptions);
280
+ private static resolveRecovery;
216
281
  static create(options: PasswordCredentialServiceOptions): Promise<PasswordCredentialService>;
217
282
  initialize(): Promise<void>;
218
283
  /** The limiter in use (shared or private). */
@@ -260,6 +325,23 @@ export declare class PasswordCredentialService {
260
325
  clearPassword(input: ClearPasswordInput): Promise<{
261
326
  revokedSessions: number;
262
327
  }>;
328
+ /**
329
+ * The person replaces a forgotten password from a fresh session the host
330
+ * minted after verifying an out-of-band proof (#3905); see
331
+ * {@link PasswordRecoveryOptions} for every condition. Works whether or not
332
+ * a password exists, clears `mustChange`, and ends EVERY session of the
333
+ * person before and after the write. The recovery session is consumed by a
334
+ * conditional update in the same transaction as the guarded credential
335
+ * write, so of any concurrent uses of one proof exactly one can succeed
336
+ * (and a failed write leaves the proof unconsumed). Refusals are
337
+ * {@link PasswordCredentialForbiddenError};
338
+ * a write that lost a race with another change is
339
+ * {@link PasswordCredentialError}.
340
+ */
341
+ replaceForgottenPassword(input: ReplaceForgottenPasswordInput): Promise<{
342
+ revokedSessions: number;
343
+ endedCurrentSession: true;
344
+ }>;
263
345
  /** Whether the person has a password (for admin UIs; never for sign-in responses). */
264
346
  hasPassword(userId: string): Promise<boolean>;
265
347
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"PasswordCredentialService.d.ts","sourceRoot":"","sources":["../../src/services/PasswordCredentialService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"PasswordCredentialService.d.ts","sourceRoot":"","sources":["../../src/services/PasswordCredentialService.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"PermissionCatalogService.d.ts","sourceRoot":"","sources":["../../src/services/PermissionCatalogService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAIL,KAAK,gBAAgB,EACtB,MAAM,0BAA0B,CAAC;AAUlC,MAAM,MAAM,uBAAuB,GAAG,UAAU,GAAG,QAAQ,GAAG,SAAS,CAAC;AAExE,MAAM,MAAM,wBAAwB,GAChC,QAAQ,GACR,QAAQ,GACR,QAAQ,GACR,QAAQ,CAAC;AAEb,MAAM,WAAW,yBAAyB;IACxC,MAAM,EAAE,SAAS,CAAC,wBAAwB,CAAC,GAAG,wBAAwB,CAAC;IACvE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE;QACT,QAAQ,CAAC,EAAE,yBAAyB,EAAE,CAAC;KACxC,CAAC;IACF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,uBAAuB,CAAC;CAClC;AAED,MAAM,WAAW,iBAAiB;IAChC,iBAAiB,EAAE,oBAAoB,EAAE,CAAC;IAC1C,mBAAmB,EAAE,oBAAoB,EAAE,CAAC;IAC5C,WAAW,EAAE,oBAAoB,EAAE,CAAC;IACpC,kBAAkB,EAAE,oBAAoB,EAAE,CAAC;CAC5C;AAED,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,iBAAiB,CAAC;IAC3B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,WAAY,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC1D,WAAW,CAAC,EAAE;QACZ,MAAM,CAAC,EAAE,oBAAoB,EAAE,CAAC;QAChC,QAAQ,CAAC,EAAE;YACT,QAAQ,CAAC,EAAE,yBAAyB,EAAE,CAAC;YACvC,OAAO,CAAC,EAAE,OAAO,CAAC;SACnB,CAAC;KACH,CAAC;CACH;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,YAAY,CAAC,EAAE,MAAM,eAAe,CAAC;CACtC;AAED,MAAM,MAAM,kCAAkC,GAC1C,MAAM,GACN,eAAe,GACf,cAAc,GACd,MAAM,CAAC;AAEX,OAAO,CAAC,MAAM,CAAC;IAEb,IAAI,kCAAkC,EAClC,GAAG,CAAC,MAAM,EAAE,oBAAoB,EAAE,CAAC,GACnC,SAAS,CAAC;IAEd,IAAI,wCAAwC,EAAE,MAAM,GAAG,SAAS,CAAC;CAClE;AAsED,wBAAgB,kCAAkC,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAkBzE;AAmCD,wBAAgB,uCAAuC,CACrD,KAAK,EAAE,kCAAkC,GACxC,MAAM,CAiCR;AAED,wBAAgB,6BAA6B,CAC3C,UAAU,EAAE,kCAAkC,EAC9C,MAAM,EAAE,MAAM,GACb,MAAM,CAQR;AAofD,wBAAgB,6BAA6B,CAC3C,WAAW,EAAE,oBAAoB,EAAE,GAClC,MAAM,IAAI,CASZ;AAcD,qBAAa,wBAAwB;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,GAAE,gBAAqB;IAE3D,cAAc,IAAI,WAAW;IAI7B,+BAA+B,IAAI,oBAAoB,EAAE;IAIzD,8BAA8B,IAAI,oBAAoB,EAAE;IAIxD,UAAU,IAAI,iBAAiB;IA0B/B,6BAA6B,CAC3B,UAAU,EAAE,kCAAkC,EAC9C,MAAM,EAAE,MAAM,GACb,MAAM;IAIT,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAMlC,qBAAqB,IAAI,OAAO,CAAC,2BAA2B,CAAC;IA0FnE,OAAO,CAAC,gCAAgC;IAsJxC,MAAM,CAAC,MAAM,CAAC,OAAO,GAAE,gBAAqB,GAAG,wBAAwB;CAGxE;AAED,wBAAsB,qBAAqB,CACzC,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,2BAA2B,CAAC,CAEtC"}
1
+ {"version":3,"file":"PermissionCatalogService.d.ts","sourceRoot":"","sources":["../../src/services/PermissionCatalogService.ts"],"names":[],"mappings":"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"}
@@ -5,14 +5,14 @@
5
5
  export { ACCESS_REQUEST_CAPABILITIES, type AccessRequestAuthorizationContext, type AccessRequestAuthorizer, type AccessRequestCapability, AccessRequestError, type AccessRequestErrorCode, type AccessRequestEvent, type AccessRequestEventHandler, type AccessRequestEventType, AccessRequestService, type AccessRequestServiceOptions, type ApproveAccessRequestOptions, type CancelAccessRequestOptions, type CreateAccessRequestInput, type DeclineAccessRequestOptions, type GraduateAccessRequestOptions, type GraduateAccessRequestResult, type GraduateExistingTenantOption, type GraduateNewTenantOption, type GraduateTenantOption, type ListAccessRequestsFilter, } from './AccessRequestService.js';
6
6
  export { ANCESTOR_READ_ACTION, type AncestorReadPackageConfig, type AncestorReadPolicy, DEFAULT_ANCESTOR_READ_MAX_DEPTH, getConfiguredAncestorReadPolicy, isAncestorReadableSlug, type NormalizedAncestorReadPolicy, normalizeAncestorReadPolicy, } from './AncestorReadPolicy.js';
7
7
  export { type ClearPinInput, DEFAULT_DEVICE_PERSON_IDLE_SECONDS, DEFAULT_PIN_MANAGE_PERMISSION, DeviceCredentialError, DeviceCredentialForbiddenError, DeviceCredentialPolicyError, DeviceCredentialService, type DeviceCredentialServiceOptions, type DeviceCredentialVerification, type DeviceCredentialVerifier, type DeviceSignInContext, type DeviceSignInInput, type DeviceSignInResult, ensurePinPermissionsRegistered, PIN_LOGIN_KIND, PIN_PERMISSION_DEFINITIONS, type PinPolicyOptions, type PinSignInInput, PinVerifier, type ResetPinInput, type SetPinInput, } from './DeviceCredentialService.js';
8
- export { DEFAULT_LOGIN_ATTEMPT_WINDOW_SECONDS, DEFAULT_LOGIN_LOCKOUT_BASE_SECONDS, DEFAULT_LOGIN_LOCKOUT_FACTOR, DEFAULT_LOGIN_LOCKOUT_MAX_SECONDS, DEFAULT_LOGIN_MAX_ATTEMPTS, DurableLoginAuditSink, InvalidCredentialsError, type LoginAttemptDecision, type LoginAttemptDenied, type LoginAttemptLease, LoginAttemptLimiter, type LoginAttemptLimiterOptions, type LoginAuditEntry, type LoginAuditSink, type LoginFailureOutcome, type LoginLockoutOptions, LoginRateLimitError, type ReserveLoginAttemptOptions, } from './LoginAttemptLimiter.js';
8
+ export { DEFAULT_LOGIN_ATTEMPT_WINDOW_SECONDS, DEFAULT_LOGIN_LOCKOUT_BASE_SECONDS, DEFAULT_LOGIN_LOCKOUT_FACTOR, DEFAULT_LOGIN_LOCKOUT_MAX_SECONDS, DEFAULT_LOGIN_MAX_ATTEMPTS, DEFAULT_SOURCE_LOCKOUT_AUDIT_SECONDS, DurableLoginAuditSink, InvalidCredentialsError, type LoginAttemptDecision, type LoginAttemptDenied, type LoginAttemptLease, LoginAttemptLimiter, type LoginAttemptLimiterOptions, type LoginAuditEntry, type LoginAuditSink, type LoginBudgetOptions, type LoginFailureOutcome, type LoginLockoutOptions, LoginRateLimitError, type ReserveLoginAttemptOptions, } from './LoginAttemptLimiter.js';
9
9
  export { MagicLinkError, type MagicLinkResult, MagicLinkService, type MagicLinkServiceOptions, type MagicLinkVerifyResult, } from './MagicLinkService.js';
10
10
  export { MobileAuthError, type MobileAuthErrorCode, MobileAuthService, type MobileAuthServiceOptions, type MobileBootstrapContext, type MobileLoginContext, type MobileLogoutResult, type MobileRequestMeta, type MobileResolvedUser, type MobileTenantContext, readMobileBearerToken, validateMobileRedirectUri, } from './MobileAuthService.js';
11
11
  export { SmrtOAuthAuthorizationService, type SmrtOAuthAuthorizationServiceOptions, type SmrtOAuthGrantSummary, } from './OAuthAuthorizationService.js';
12
12
  export { SMRT_OAUTH_GRANT_CLAIM, SmrtOAuthAuthorizationStorage, type SmrtOAuthAuthorizationStorageOptions, } from './OAuthAuthorizationStorage.js';
13
13
  export { type CreateAuthorizationUrlOptions, decodeOidcTransaction, encodeOidcTransaction, getUsersOidcConfig, type OidcCallbackResult, OidcLoginError, type OidcLoginResult, OidcLoginService, type OidcLoginServiceOptions, type OidcProviderConfig, type OidcProviderKind, type OidcProviderMetadata, type OidcProviderResolution, type OidcProviderResolutionOptions, type OidcTokenEndpointAuthMethod, type OidcTokenSet, type OidcTransaction, type ResolvedOidcProviderConfig, resolveOidcProviderConfig, type UsersOidcConfig, } from './OidcLoginService.js';
14
14
  export { assertOperationPermission, checkOperationPermission, hasOperationPermission, type OperationPermissionAllowReason, type OperationPermissionDecision, type OperationPermissionDenyReason, OperationPermissionError, type OperationPermissionOptions, } from './OperationPermissionService.js';
15
- export { type ChangePasswordInput, type ClearPasswordInput, DEFAULT_PASSWORD_DENYLIST, DEFAULT_PASSWORD_MANAGE_PERMISSION, DEFAULT_PASSWORD_MAX_LENGTH, DEFAULT_PASSWORD_MIN_LENGTH, ensurePasswordPermissionsRegistered, PASSWORD_LOGIN_KIND, PASSWORD_MAX_LENGTH_CEILING, PASSWORD_PERMISSION_DEFINITIONS, PasswordCredentialError, PasswordCredentialForbiddenError, PasswordCredentialService, type PasswordCredentialServiceOptions, type PasswordPolicyContext, PasswordPolicyError, type PasswordPolicyOptions, type PasswordSignInInput, type PasswordSignInResult, type ResetPasswordInput, type SetPasswordInput, } from './PasswordCredentialService.js';
15
+ export { type ChangePasswordInput, type ClearPasswordInput, DEFAULT_PASSWORD_DENYLIST, DEFAULT_PASSWORD_MANAGE_PERMISSION, DEFAULT_PASSWORD_MAX_LENGTH, DEFAULT_PASSWORD_MIN_LENGTH, DEFAULT_PASSWORD_RECOVERY_MAX_AGE_SECONDS, ensurePasswordPermissionsRegistered, outOfBandProofSessionData, PASSWORD_LOGIN_KIND, PASSWORD_MAX_LENGTH_CEILING, PASSWORD_PERMISSION_DEFINITIONS, PASSWORD_RECOVERY_MAX_AGE_CEILING_SECONDS, PasswordCredentialError, PasswordCredentialForbiddenError, PasswordCredentialService, type PasswordCredentialServiceOptions, type PasswordPolicyContext, PasswordPolicyError, type PasswordPolicyOptions, type PasswordRecoveryOptions, type PasswordRecoveryProofContext, type PasswordSignInInput, type PasswordSignInResult, type ReplaceForgottenPasswordInput, type ResetPasswordInput, type SetPasswordInput, } from './PasswordCredentialService.js';
16
16
  export { deriveOperationPermissionCollectionName, deriveOperationPermissionSlug, normalizeOperationPermissionAction, type OperationPermissionCollectionInput, type PermissionCatalog, PermissionCatalogService, type PermissionCatalogSource, type PermissionCatalogSyncResult, type PermissionDefinition, type PostgresPermissionAction, type PostgresPermissionBinding, registerPermissionDefinitions, syncPermissionCatalog, type UsersConfig, } from './PermissionCatalogService.js';
17
17
  export { type PermissionResolutionOptions, type PermissionResolutionResult, PermissionResolver, type PermissionResolverOptions, type TenantPermissionInheritanceResult, } from './PermissionResolver.js';
18
18
  export { applyPostgresPermissionPolicies, type GeneratePostgresPermissionSqlResult, generatePostgresPermissionSql, type PostgresPermissionPolicyReportItem, type PostgresPermissionPolicyTarget, } from './PostgresPermissionPolicies.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":"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"}
@@ -3,14 +3,14 @@
3
3
  "sensitiveFieldsExcluded": true,
4
4
  "generatedAt": "1970-01-01T00:00:00.000Z",
5
5
  "packageName": "@happyvertical/smrt-users",
6
- "packageVersion": "0.55.23",
6
+ "packageVersion": "0.56.0",
7
7
  "sourceManifestPath": "dist/manifest.json",
8
8
  "agentDocPath": "AGENTS.md",
9
9
  "sourceHashes": {
10
- "manifest": "ec80a88ec39d214e62fed8ecc7ac33f9f8fac94de6d5df9a0533336e41e67a61",
11
- "packageJson": "051f6c1e2ae4ebebe373c6cdf130ccabe08da54daf0f8462ede6fbc21d081941",
12
- "agents": "eb74cdf8186c27e8721515cff653c688567284015ce9845a9b7714ac898620bc",
13
- "moduleDoc:agents/permissions.md": "832a684513d831d3cb9bd8d0c73295d756ca7cf9bc32de1ca3254691160371b1",
10
+ "manifest": "c8fc0427cb898349fd4716a71c5e91d07230ba21fcb91f8b889ab88bf043d2a5",
11
+ "packageJson": "7e315019dcf37e84f1ad0aef50122f292495038f8410bedff95f549d30aa6935",
12
+ "agents": "c4ab6a1aae24c0fb687d4d02ef25dcb5e6942ad7e8318e9d0dd8d03d5750b788",
13
+ "moduleDoc:agents/permissions.md": "02b2f03f0e057721369d9c693a624a6fdb3df4935401531a4373ff18229a64be",
14
14
  "moduleDoc:agents/oidc-provisioning.md": "b73f3fdaf61136720132a614c7e14237b7bd35f7bf5d43eabb29f565485803b9",
15
15
  "moduleDoc:agents/mobile-auth.md": "25e85e83f43e3a46383a92fa809f3a003b4545c3026e78dbe1bccbbc35161e18",
16
16
  "moduleDoc:agents/terminal-auth-testing.md": "8a84c16a19e381427aed81d3b1882344c427fe22a70e87f5ac2db836b1a6822d",
@@ -5031,6 +5031,10 @@
5031
5031
  }
5032
5032
  ],
5033
5033
  "methods": [],
5034
+ "conflictColumns": [
5035
+ "group_id",
5036
+ "user_id"
5037
+ ],
5034
5038
  "surfaces": [
5035
5039
  {
5036
5040
  "kind": "api",
@@ -5612,6 +5616,10 @@
5612
5616
  "returns": "boolean"
5613
5617
  }
5614
5618
  ],
5619
+ "conflictColumns": [
5620
+ "membership_id",
5621
+ "permission_id"
5622
+ ],
5615
5623
  "surfaces": [
5616
5624
  {
5617
5625
  "kind": "api",
@@ -7670,8 +7678,7 @@
7670
7678
  ],
7671
7679
  "conflictColumns": [
7672
7680
  "tenant_id",
7673
- "slug",
7674
- "context"
7681
+ "permission_id"
7675
7682
  ],
7676
7683
  "surfaces": [
7677
7684
  {
@@ -10829,12 +10836,12 @@
10829
10836
  "polymorphicAssociations": 0,
10830
10837
  "uuidColumns": 116
10831
10838
  },
10832
- "agentDoc": "# @happyvertical/smrt-users\n\nMulti-tenant identity, RBAC, hierarchical tenants, sessions, and SvelteKit auth.\n\n## Modules\n\nRead only the module relevant to the change; protocol and provisioning details\nare not prerequisites for unrelated user-package work.\n\n| Module | Scope | Module doc |\n|---|---|---|\n| `src/services/PermissionResolver.ts` | permission precedence, inherited memberships, guards, RLS, role seeding | [agents/permissions.md](agents/permissions.md) |\n| `src/services/OidcLoginService.ts`, collections and OIDC handlers | identity reconciliation, transaction boundaries, migration readiness | [agents/oidc-provisioning.md](agents/oidc-provisioning.md) |\n| `src/services/MobileAuthService.ts` | mobile handshake, bearer sessions, bootstrap extension boundary | [agents/mobile-auth.md](agents/mobile-auth.md) |\n| `src/services/TerminalAuthService.ts`, `src/services/LoginAttemptLimiter.ts`, `src/collections/LoginAttemptCollection.ts` | terminal approval concurrency, shared login budget and lockout (#3273), retry-safe database fixtures | [agents/terminal-auth-testing.md](agents/terminal-auth-testing.md) |\n| `src/services/DeviceCredentialService.ts` | per-person PIN layered on a device session (#3276), verifier seam for other credential kinds | this file, \"Security boundaries\" |\n| `src/services/PasswordCredentialService.ts`, `src/sveltekit/password-handlers.ts` | email + password sign-in and password lifecycle (#3274); shared scrypt in `credential-hash.ts` | this file, \"Security boundaries\"; README \"Password sign-in\" |\n| `src/retention.ts` | expired session/token/CLI-auth reaping and retention sweep wiring | [agents/retention.md](agents/retention.md) |\n\n## Models and authority\n\n- Users are global; tenant access comes through Membership (unique user/tenant).\n User email is normalized and globally unique through readonly nullable\n `emailKey`. `profileId` is a unique cross-package reference: at most one User\n owns each non-null Profile.\n- Tenant uses STI and a materialized hierarchy, maximum depth 10.\n `hierarchyPath`/`hierarchyLevel` are derived from `parentTenantId` by\n `Tenant.save()` on every save (any caller-supplied value is recomputed) and\n descendants are re-materialized when they change; never hand-maintain them.\n Legacy rows are backfilled with `smrt db:materialize-tenant-hierarchy`\n (`materializeTenantHierarchy()`). Tests that need a corrupt path must write it\n with raw SQL (#3036).\n- Role with `tenantId = null` is available to all tenants; `isSystem` prevents\n deletion. `inheritsToDescendants` is opt-in. Seed owner/admin/member/viewer\n through `RoleCollection.seedSystemRoles()` at application initialization.\n- Group roles apply only in their own tenant. Use `getGroupIdsForTenant()`,\n never cross-tenant `getGroupIds()`, for authorization.\n- Upward visibility is opt-in and read-only: `permissions.ancestorRead`\n ({ roles, collections, maxDepth? }) lets a DESCENDANT membership contribute\n declared `<collection>.read` at an ancestor, only when no membership resolved\n there, intersected with BOTH the role's own catalog grants and the\n principal's effective permissions in that descendant, and only for SYSTEM\n roles (a tenant-scoped role sharing a declared slug is ignored). Off by default, never\n write, never lateral, and never row visibility — sibling rows stay scoped by\n tenancy/RLS. Read the permissions module before changing it.\n- Membership DENY always wins. Direct inactive membership blocks inherited\n authority; a direct active membership pins resolution instead of unioning it\n with ancestors. Read the permissions module before changing these rules.\n- AccessRequest has no generated API/MCP/CLI operations; access it through\n `AccessRequestService`. Its JSON field is `requestContext`, not reserved\n slug-scoping `context`.\n\n## Security boundaries\n\n- Generated REST/MCP operations on identity/RBAC models are list/get only.\n Route authentication does not authorize authority mutations, and these models\n are not tenant-scoped. Use permission-gated services or explicitly checked\n consumer handlers. Generated CLI is list/get or closed (`cli: false` for\n credential/grant models) because agents shell out to it; a `cli` without\n `include` is full CRUD (#3742). Their catalog slugs stay full via\n `USERS_AUTHORITY_CATALOG_MODELS`. Preserve the registry assertions in\n `security-audit-1400.test.ts` and `issue-3742-cli-surface-lockdown.test.ts`.\n- Resource guards take the resource tenant, not the session tenant. Omit a\n session membership when targeting a different tenant; mismatches fail closed.\n `loadSessionContext().tenantAuthorization` must be checked by required-tenant\n consumers: null membership can represent inherited authority.\n- Sessions use secure UUIDs; TTL is seconds (default seven days). Access marks\n expired sessions EXPIRED. Magic-link tokens are single use.\n- `Session.authMethod` is server-set at mint time and never read from the\n client; every mint site in this package sets it. A session with\n `parentSessionId` is valid only while its parent validates\n (`loadSessionContext` enforces this; there is no FK cascade by design), may\n not switch to a tenant other than the parent's, and is revoked with its\n parent by `destroySession`.\n- Credential sign-ins reserve through `LoginAttemptLimiter` BEFORE credential\n work and key the subject on the submitted identifier, never a resolved user,\n so unknown and wrong take the same path. Reservations are fail-closed: keep\n them on failure, release on success or abort, never skip the reserve.\n Limiter writes are raw SQL and bypass the change feed; the audit sink is the\n observability seam, and it must never throw into the sign-in path.\n- `DeviceCredentialService` accepts a person credential only from a\n first-class session whose `authMethod` is a device-enrollment method\n (`terminal` by default) and that the host's `assertEnrolledDevice` confirms.\n A layered or PIN session can never administer PINs regardless of\n permissions. PIN hashes carry a per-row salt and the configured pepper;\n treat an unset pepper as a production misconfiguration.\n- A person session carries the PERSON's authority (resolved from their own\n membership on every load), never the device account's. `Session.data` keys\n in `SESSION_DATA_KEYS` are server-set controls enforced by the model:\n `permissionCeiling` only ever intersects (malformed fails closed to none)\n and suppresses `superAdminBypass`/`systemContext`; `absoluteExpiresAt`\n bounds `extend()` and `isValid()`; `idleSeconds` overrides the resolving\n service's TTL policy. Never write them from client input. The ceiling is a\n sign-in snapshot; `singleOccupant` revokes other children only AFTER a\n successful mint. A `mustReset` sign-in mints with an empty ceiling and\n `setPin` ends that session; do not grant it authority another way.\n- `UsersPasswordCredential` is one row per person, sensitive, with no\n generated surface; `PasswordCredentialService` and its handlers are its only\n read/write paths. Sign-in normalizes the email like `emailKey`, reserves\n before work, always runs one scrypt verify (dummy hash when absent), never\n creates a user, and maps every non-rate-limit refusal to one\n `PasswordCredentialError`. It re-checks the credential after the mint (a\n rehash that keeps row and version is confirmed by re-verifying); the\n parameter-upgrade write is a guarded UPDATE that must never replace a\n rotated password, and verification against a weaker stored hash is padded\n to the policy's scrypt cost. Self-service writes are guarded on the proven\n credential (first set insert-only); session sweeps run before and after\n each write. Self-service needs the current password except for a first\n set; `users.password.manage` follows the PIN's single-tenant target\n rule and never resets the actor's own. Layered sessions never manage\n passwords; a `mustChange` sign-in mints an empty ceiling.\n- A layered session whose tenant differs from its parent's never loads (null\n is allowed: narrower). Limiter rows carry `retain_until`; retention must\n not fall back to a process-wide horizon.\n- `Session.parentSessionId` is the parent's bearer: sensitive, never a\n `list()` filter (raw-SQL id reads, which also keep revocation sweeps free of\n caller list bounds), never serialized to clients. `users.pin.manage` reaches\n only people whose every active membership is in the actor's tenant (the PIN\n is global per person). A sign-in re-checks the verified\n credential generation AFTER the mint (`stillValid`); keep that ordering.\n Operation guards deny outside a session's ceiling; `loadPersonSession`\n re-checks device enrollment.\n- Tenant switching verifies active membership before writing and rotates the\n session ID for non-null targets, revoking the old session. Persist the returned\n `SwitchTenantResult.sessionId`; `switchSessionTenant()` updates the cookie and\n preserves its security settings. Failed switches mutate nothing; null clears\n do not rotate, and layered sessions never rotate (a replacement would escape\n the revocation sweeps they depend on). Layers do not nest. `SessionCollection.setSessionTenant()` is unguarded and must\n never receive an untrusted tenant ID.\n- OIDC provisioning is atomic and fail-closed. Preserve exact issuer/subject\n identifiers, claim-source email verification, unique global Person ownership,\n and transaction-bound reconciliation. Read the OIDC module and canonical\n scenario matrix before changing any provisioning path.\n\n## Entry points and validation\n\n`src/sveltekit/` owns `createSessionHandler`, `createSessionCookie`,\n`destroySessionCookie`, and `switchSessionTenant`. Use README integration examples\nrather than copying application setup into these instructions.\n\nFrom the repository root:\n\n```bash\npnpm --filter @happyvertical/smrt-users test\npnpm --filter @happyvertical/smrt-users typecheck\npnpm --filter @happyvertical/smrt-users test:postgres\n```\n\nStart with the relevant test file via `test -- src/__tests__/<file>.test.ts`.\nRun `test:postgres` for RLS, principal context, OIDC, or terminal-auth database\nchanges. `typecheck` includes Svelte accessibility checks; plain `tsc` is\ninsufficient. Follow root knowledge freshness checks before shipping.\n",
10839
+ "agentDoc": "# @happyvertical/smrt-users\n\nMulti-tenant identity, RBAC, hierarchical tenants, sessions, and SvelteKit auth.\n\n## Modules\n\nRead only the module relevant to the change; protocol and provisioning details\nare not prerequisites for unrelated user-package work.\n\n| Module | Scope | Module doc |\n|---|---|---|\n| `src/services/PermissionResolver.ts` | permission precedence, inherited memberships, guards, RLS, role seeding | [agents/permissions.md](agents/permissions.md) |\n| `src/services/OidcLoginService.ts`, collections and OIDC handlers | identity reconciliation, transaction boundaries, migration readiness | [agents/oidc-provisioning.md](agents/oidc-provisioning.md) |\n| `src/services/MobileAuthService.ts` | mobile handshake, bearer sessions, bootstrap extension boundary | [agents/mobile-auth.md](agents/mobile-auth.md) |\n| `src/services/TerminalAuthService.ts`, `src/services/LoginAttemptLimiter.ts`, `src/collections/LoginAttemptCollection.ts` | terminal approval concurrency, shared login budget and lockout (#3273), retry-safe database fixtures | [agents/terminal-auth-testing.md](agents/terminal-auth-testing.md) |\n| `src/services/DeviceCredentialService.ts` | per-person PIN layered on a device session (#3276), verifier seam for other credential kinds | this file, \"Security boundaries\" |\n| `src/services/PasswordCredentialService.ts`, `src/sveltekit/password-handlers.ts` | email + password sign-in and password lifecycle (#3274); shared scrypt in `credential-hash.ts` | this file, \"Security boundaries\"; README \"Password sign-in\" |\n| `src/retention.ts` | expired session/token/CLI-auth reaping and retention sweep wiring | [agents/retention.md](agents/retention.md) |\n\n## Models and authority\n\n- Users are global; tenant access comes through Membership (unique user/tenant).\n User email is normalized and globally unique through readonly nullable\n `emailKey`. `profileId` is a unique cross-package reference: at most one User\n owns each non-null Profile.\n- Tenant uses STI and a materialized hierarchy, maximum depth 10.\n `hierarchyPath`/`hierarchyLevel` are derived from `parentTenantId` by\n `Tenant.save()` on every save (any caller-supplied value is recomputed) and\n descendants are re-materialized when they change; never hand-maintain them.\n Legacy rows are backfilled with `smrt db:materialize-tenant-hierarchy`\n (`materializeTenantHierarchy()`). Tests that need a corrupt path must write it\n with raw SQL (#3036).\n- Role with `tenantId = null` is available to all tenants; `isSystem` prevents\n deletion. `inheritsToDescendants` is opt-in. Seed owner/admin/member/viewer\n through `RoleCollection.seedSystemRoles()` at application initialization.\n- Group roles apply only in their own tenant. Use `getGroupIdsForTenant()`,\n never cross-tenant `getGroupIds()`, for authorization.\n- Upward visibility is opt-in and read-only: `permissions.ancestorRead`\n ({ roles, collections, maxDepth? }) lets a DESCENDANT membership contribute\n declared `<collection>.read` at an ancestor, only when no membership resolved\n there, intersected with BOTH the role's own catalog grants and the\n principal's effective permissions in that descendant, and only for SYSTEM\n roles (a tenant-scoped role sharing a declared slug is ignored). Off by default, never\n write, never lateral, and never row visibility — sibling rows stay scoped by\n tenancy/RLS. Read the permissions module before changing it.\n- Membership DENY always wins. Direct inactive membership blocks inherited\n authority; a direct active membership pins resolution instead of unioning it\n with ancestors. Read the permissions module before changing these rules.\n- AccessRequest has no generated API/MCP/CLI operations; access it through\n `AccessRequestService`. Its JSON field is `requestContext`, not reserved\n slug-scoping `context`.\n\n## Security boundaries\n\n- Generated REST/MCP operations on identity/RBAC models are list/get only.\n Route authentication does not authorize authority mutations, and these models\n are not tenant-scoped. Use permission-gated services or explicitly checked\n consumer handlers. Generated CLI is list/get or closed (`cli: false` for\n credential/grant models) because agents shell out to it; a `cli` without\n `include` is full CRUD (#3742). Their catalog slugs stay full via\n `USERS_AUTHORITY_CATALOG_MODELS`. Preserve the registry assertions in\n `security-audit-1400.test.ts` and `issue-3742-cli-surface-lockdown.test.ts`.\n- Resource guards take the resource tenant, not the session tenant. Omit a\n session membership when targeting a different tenant; mismatches fail closed.\n `loadSessionContext().tenantAuthorization` must be checked by required-tenant\n consumers: null membership can represent inherited authority.\n- Sessions use secure UUIDs; TTL is seconds (default seven days). Access marks\n expired sessions EXPIRED. Magic-link tokens are single use.\n- `Session.authMethod` is server-set at mint time and never read from the\n client; every mint site in this package sets it. A session with\n `parentSessionId` is valid only while its parent validates\n (`loadSessionContext` enforces this; there is no FK cascade by design), may\n not switch to a tenant other than the parent's, and is revoked with its\n parent by `destroySession`.\n- Credential sign-ins reserve through `LoginAttemptLimiter` BEFORE credential\n work and key the subject on the submitted identifier, never a resolved user,\n so unknown and wrong take the same path. Reservations are fail-closed: keep\n them on failure, release on success or abort, never skip the reserve.\n Limiter writes are raw SQL and bypass the change feed; the audit sink is the\n observability seam, and it must never throw into the sign-in path.\n Subject and source budgets are sized independently (#3531); `source: false`\n ignores the source key, so a reservation then needs a subject (fail closed).\n The `source-locked` audit entry never carries a subject or caller metadata.\n- `DeviceCredentialService` accepts a person credential only from a\n first-class session whose `authMethod` is a device-enrollment method\n (`terminal` by default) and that the host's `assertEnrolledDevice` confirms.\n A layered or PIN session can never administer PINs regardless of\n permissions. PIN hashes carry a per-row salt and the configured pepper;\n treat an unset pepper as a production misconfiguration.\n- A person session carries the PERSON's authority (resolved from their own\n membership on every load), never the device account's. `Session.data` keys\n in `SESSION_DATA_KEYS` are server-set controls enforced by the model:\n `permissionCeiling` only ever intersects (malformed fails closed to none)\n and suppresses `superAdminBypass`/`systemContext`; `absoluteExpiresAt`\n bounds `extend()` and `isValid()`; `idleSeconds` overrides the resolving\n service's TTL policy. Never write them from client input. The ceiling is a\n sign-in snapshot; `singleOccupant` revokes other children only AFTER a\n successful mint. A `mustReset` sign-in mints with an empty ceiling and\n `setPin` ends that session; do not grant it authority another way.\n- `UsersPasswordCredential` is one row per person, sensitive, with no\n generated surface; `PasswordCredentialService` and its handlers are its only\n read/write paths. Sign-in normalizes the email like `emailKey`, reserves\n before work, always runs one scrypt verify (dummy hash when absent), never\n creates a user, and maps every non-rate-limit refusal to one\n `PasswordCredentialError`. It re-checks the credential after the mint (a\n rehash that keeps row and version is confirmed by re-verifying); the\n parameter-upgrade write is a guarded UPDATE that must never replace a\n rotated password, and verification against a weaker stored hash is padded\n to the policy's scrypt cost. Self-service writes are guarded on the proven\n credential (first set insert-only); session sweeps run before and after\n each write. Self-service needs the current password except for a first\n set; `users.password.manage` follows the PIN's single-tenant target\n rule and never resets the actor's own. Layered sessions never manage\n passwords; a `mustChange` sign-in mints an empty ceiling.\n `replaceForgottenPassword` (#3905, opt-in `recovery`) is the only\n self-service write without the current password: it decides on the stored\n session row (owner, first-class, no ceiling, listed non-password/pin\n `authMethod`, fresh `outOfBandProofAt` stamp) and ends every session,\n its own included. Never set that stamp from client input.\n- A layered session whose tenant differs from its parent's never loads (null\n is allowed: narrower). Limiter rows carry `retain_until`; retention must\n not fall back to a process-wide horizon.\n- `Session.parentSessionId` is the parent's bearer: sensitive, never a\n `list()` filter (raw-SQL id reads, which also keep revocation sweeps free of\n caller list bounds), never serialized to clients. `users.pin.manage` reaches\n only people whose every active membership is in the actor's tenant (the PIN\n is global per person). A sign-in re-checks the verified\n credential generation AFTER the mint (`stillValid`); keep that ordering.\n Operation guards deny outside a session's ceiling; `loadPersonSession`\n re-checks device enrollment.\n- Tenant switching verifies active membership before writing and rotates the\n session ID for non-null targets, revoking the old session. Persist the returned\n `SwitchTenantResult.sessionId`; `switchSessionTenant()` updates the cookie and\n preserves its security settings. Failed switches mutate nothing; null clears\n do not rotate, and layered sessions never rotate (a replacement would escape\n the revocation sweeps they depend on). Layers do not nest. `SessionCollection.setSessionTenant()` is unguarded and must\n never receive an untrusted tenant ID.\n- OIDC provisioning is atomic and fail-closed. Preserve exact issuer/subject\n identifiers, claim-source email verification, unique global Person ownership,\n and transaction-bound reconciliation. Read the OIDC module and canonical\n scenario matrix before changing any provisioning path.\n\n## Entry points and validation\n\n`src/sveltekit/` owns `createSessionHandler`, `createSessionCookie`,\n`destroySessionCookie`, and `switchSessionTenant`. Use README integration examples\nrather than copying application setup into these instructions.\n\nFrom the repository root:\n\n```bash\npnpm --filter @happyvertical/smrt-users test\npnpm --filter @happyvertical/smrt-users typecheck\npnpm --filter @happyvertical/smrt-users test:postgres\n```\n\nStart with the relevant test file via `test -- src/__tests__/<file>.test.ts`.\nRun `test:postgres` for RLS, principal context, OIDC, or terminal-auth database\nchanges. `typecheck` includes Svelte accessibility checks; plain `tsc` is\ninsufficient. Follow root knowledge freshness checks before shipping.\n",
10833
10840
  "moduleDocs": [
10834
10841
  {
10835
10842
  "path": "agents/permissions.md",
10836
10843
  "module": "permissions",
10837
- "content": "# Permissions and tenant inheritance\n\nRead for `src/services/PermissionResolver.ts`, operation guards, role seeding,\nRLS, and tenant-hierarchy changes. Integration examples live in README's\nmanifest-derived permission catalog and PostgreSQL RLS sections.\n\n## Membership selection\n\n1. A direct target-tenant membership pins resolution: active resolves normally;\n pending/suspended returns empty. Never union direct and ancestor roles.\n2. Otherwise walk hierarchyPath nearest-first for the nearest active ancestor\n membership whose role has inheritsToDescendants. Skip inactive/unflagged\n ancestors; they neither grant nor block. No qualifying ancestor means empty.\n3. Run later layers against the target tenant. Only target-tenant groups apply;\n membership overrides travel with the chosen ancestor membership.\n inheritedFromTenantId reports that ancestor, null for direct resolution.\n\nVerify hierarchyPath link-by-link against loaded parentTenantId rows before\ntrusting it: excess depth, self-reference, duplicates or inconsistent paths\nfail closed. Bound traversal by MAX_TENANT_HIERARCHY_DEPTH. Tenant status is not\nconsulted, matching direct resolution. Long-lived user/tenant caches must\ninvalidate ancestor membership changes and inheritsToDescendants flips;\nrequest-scoped caches do not survive those requests.\n\n`loadSessionContext().tenantAuthorization` is authoritative for required-tenant\nconsumers; membership null can mean inherited authority.\n\n4. If no membership resolved at all, apply the opt-in ancestor-read policy\n (smrt#2939): the user's ACTIVE memberships on VERIFIED DESCENDANTS of the\n target, whose role slug is declared in `permissions.ancestorRead.roles` and\n within `maxDepth` hops, contribute `<collection>.read` for declared\n collections, intersected with BOTH that role's own catalog grants (so a\n descendant-side tenant GRANT, group role, or membership GRANT cannot widen\n it) AND the principal's effective permissions in that descendant (so its\n DENY cascade and membership DENY apply). Only a SYSTEM\n role (`tenantId` null, `isSystem: true`) matches a declared slug: slugs are\n not unique across a hierarchy, so a tenant-scoped custom role of the same\n name must not opt its tenant in. Off by default;\n read-only; never lateral; never reached when a direct or inherited\n membership already decided. The target tenant's DENY still subtracts.\n `ancestorReadFromTenantIds` reports the contributing descendants. The grant\n carries no membership, so `membershipId`/`tenantAuthorization.membershipId`\n stay null and a consumer requiring a non-empty membership still refuses.\n\n## Permission precedence\n\nApply these layers in order, later layers overriding earlier ones:\n\n1. Ancestor TenantPermissionOverride cascade (GRANT adds, DENY removes).\n2. Selected membership role permissions.\n3. Target-tenant group-role permissions.\n4. Tenant cascade's net DENY removes role/group grants.\n5. Membership GRANT may re-add a tenant-denied slug.\n6. Membership DENY removes last and always wins.\n\nThe tenant block is the cascade's net result, not the union of historical DENYs:\na child's more-specific GRANT can override a parent DENY. Use a direct child\nmembership or tenant DENY to attenuate inherited role authority.\n`getGroupIdsForTenant(userId, tenantId)` is required; getGroupIds is cross-tenant.\n\n## Hierarchies and seeding\n\n- `Tenant.save()` derives hierarchyPath/hierarchyLevel from the REAL\n parentTenantId chain on every save (never from an ancestor's stored path),\n refuses missing parents, cycles and over-depth before writing, and\n re-materializes descendants by raw column update (so STI subclass columns\n are never clobbered). createChild/moveToParent/makeRoot are thin wrappers.\n `materializeTenantHierarchy(db, { dryRun })` / `smrt\n db:materialize-tenant-hierarchy` backfills legacy rows: idempotent, one\n transaction, refuses a broken chain without writing (#3036). A NEW or\n CHANGED parent link is authority-bearing, so `Tenant.save()` first loads the\n parent through TenantCollection (the caller's tenancy scope) and refuses an\n invisible one on every path — helpers, `create({ parentTenantId })`, or a\n plain assignment + save; system context bypasses as usual, and an unchanged\n link is never re-checked. getTree(rootId?)\n returns UI structure. Maximum depth is 10.\n- Tenant override cascade requires parent cascadePermissions and child\n inheritPermissions. These flags do not gate the independent, per-role\n inheritsToDescendants membership flow.\n- `permissions.ancestorRead` in the `users` package config declares upward,\n read-only visibility: `{ roles, collections, maxDepth? }`. Both lists are\n required and non-empty and `maxDepth >= 1`, else the policy is OFF — there is\n no partially valid declaration. `isAncestorReadableSlug()` is the single place\n the read-only bound is enforced; only a two-segment `<collection>.<action>`\n slug whose action normalizes to `read` on a declared collection passes.\n `PermissionResolver.create(options, { ancestorReadPolicy })` binds one\n resolver; `null` forces it off. It grants the OPERATION at the ancestor, never\n row visibility — sibling rows stay scoped by the tenancy interceptor and RLS.\n- seedSystemRoles({ inheritsToDescendants: ['owner', 'admin'] }) flags listed\n slugs additively, never unflags omitted ones, and rejects unknown slugs.\n Default seeds are exact-tenant.\n- RolePermissionCollection.seedRolePermissions() or\n seedSystemRoles({ seedPermissions: true }) maps owner/admin to all catalog\n permissions, member to ordinary-resource read/create, viewer to read. Member\n create excludes identity/RBAC/security resources and their joins/overrides.\n Seeding is additive/idempotent; removal requires prune: true. Catalog sync\n and grants plan from one read, then commit in `SEEDING_BATCH_SIZE` batches\n (#3323): never one durable commit per row (an fsync each on local SQLite),\n and never one catalog-wide transaction (`@happyvertical/sql` transaction\n scopes cost superlinearly per statement). Pass a caller transaction's handle.\n- When a package adds built-in self-personalization permissions after role\n creation, explicitly call seedDefaultRolePersonalizationPermissions(). It\n upgrades owner/admin/member/viewer idempotently and never grants custom roles.\n The built-in self-personalization slugs are `fields.policy.personalize`,\n `overviews.personalize` and `shell.personalize`, each seeded only once its\n package registered it.\n\n## Guards and RLS\n\nPermissionCatalogService derives collection.action slugs from manifests,\nincluding custom actions; list/get map to read. Guards derive a class's slug\nthrough the same resolution (explicit `collection`, manifest entry, then its\nSTI base's), so an STI subtype resolves its STI base's collection\n(`Network extends Tenant` -> `tenants.update`) in every build, including a\nbundle decorated before its manifest loads (#3125). Hand-written mutations in form\nhandlers, endpoints, CLI and jobs use assertOperationPermission(). It requires\ncatalog presence then resolves permissions, throwing fail-closed by default.\nUse onDeny: 'return', checkOperationPermission or hasOperationPermission only\nwhen the caller handles a structured/boolean denial.\n\nGenerated SvelteKit write routes (POST/PUT/PATCH/DELETE CRUD and mutating\ncustom actions) enforce the same `collection.action` slug (custom actions use\n`collection.<method>`; actions hosted on a collection class use the item collection, which the catalog now emits) after authentication: the slug must be in the request's\nsession permission snapshot (`locals.permissions`/`permissionSet`/\n`smrtPermissions` or `locals.tenantContext.permissions`), otherwise 403. Only\n`locals.tenantContext.superAdminBypass` skips it; `api.public: true` stays open.\n\nResource-anchored guards receive the resource tenant ID. When it differs from\nthe session tenant, omit the session membership so the resolver selects the\nappropriate authority; mismatched supplied membership/tenant fails closed.\nInherited root-admin authority can then authorize descendant resources without\napplication-side membership fan-out.\n\nResolution cost must not scale with catalog size in objects (#3047): role →\npermission ids and ids → slugs are `list({ select })` projection reads (the\ncollections' beforeList interceptors still run; no RolePermission/Permission\nis hydrated), so an owner mapped to the whole catalog costs two queries and\nno per-permission objects. Keep new resolver reads projections when only ids\nor slugs are needed, and do not add public collection methods for them — each\nbecomes a custom-action slug in the manifest-derived catalog. The resolver's\ncollections never inherit `defaultListLimit`/`maxListLimit` from the caller's\noptions, and id-list reads chunk at `IN_LIST_CHUNK_SIZE` with an explicit\nlimit: a truncated authorization read would narrow the result silently.\n`issue-3047-permission-resolution-cost-postgres.test.ts` pins the hydration\nbudget and a golden equivalence matrix recorded on the hydrating resolver.\n\nThe same rule holds for every framework-internal authorization read (#3048):\ncollections that back a decision — the resolver's, the ResourceGrant exact-tuple\nread in `checkResourceOperationPermission()` (DENY wins only if every row is\nread), and TenantService's owned-tenant quota count — are created through\n`withoutListBounds()` (`src/services/authorization-read-options.ts`), which\nstrips only the caller's list bounds. Use it for any new decision read;\n`issue-3048-authorization-list-bounds-postgres.test.ts` pins it.\n\nPermissionResolver runs every resolution inside smrt-tenancy's system context\n(#3036). Its reads are deliberately cross-tenant and framework-owned — the\nancestor TenantPermissionOverride batch, ancestor memberships for\ninheritsToDescendants, descendant memberships for ancestor-read — and are keyed\nby the explicit (userId, tenantId); with those classes registered tenant-scoped\n(`autoFilter`) the consumer's filter otherwise threw TenantIsolationError or\nsilently narrowed them. It returns slugs and ids only, never rows, and the\ncaller's own reads stay filtered. Do not move a resolver read back under the\nambient tenant; the Postgres regression suite\n`issue-3036-hierarchy-resolution-postgres.test.ts` pins this. Because nothing\nbackstops those reads any more, the tenant-override cascade verifies its chain\ntoo: it uses hierarchyPath only when it agrees link-by-link with\nparentTenantId, otherwise walks the real parent links (so a forged path cannot\ncascade an unrelated tenant in, and a never-materialized row still gets its real\nancestors' DENYs — and GRANTs), and throws TenantHierarchyError on a broken\nreal chain: a per-request failure for that tenant's whole subtree, which\n`smrt db:materialize-tenant-hierarchy --dry-run` reports ahead of time (see\nREADME \"Upgrading an existing fleet\").\n`getTenantInheritanceChain()` returns Tenant rows, so it is NOT run in system\ncontext; it reports the same verified chain the cascade applies when the\ncaller can read every ancestor. Otherwise it never reports PARENT_NOT_FOUND\nfor a row the caller simply cannot see: an interceptor refusal surfaces as\nTenantIsolationError, and a silently filtered row (e.g. RLS) ends the chain at\nthe nearest readable ancestor. Descendant path rewrites are raw column updates recorded through\n`bumpChangeFeed`; `updated_at` is intentionally not bumped (derived columns;\nevery save recomputes them). They are not atomic with the moving row's save —\nan interrupted subtree fails closed until re-saved or backfilled.\n\nSystem context and super-admin bypass are honored. Pass\nallowSuperAdminBypass: false for money or separation-of-duties operations that\nrequire an explicit grant.\n\ngeneratePostgresPermissionSql/applyPostgresPermissionPolicies enforce generated\nRLS using smrt.permissions and smrt.tenant_id, installed with set_config by\nwithSessionPermissionContext. This bounds REST, MCP and in-process database\naccess once principal context is set. Child-tenant sessions receive resolved\ninherited permissions automatically, but RLS row filtering remains bound to the\nsession tenant: a root session's app-level guard authorization does not itself\npermit child rows through RLS. Preserve this distinction.\n\nRolePermission's natural key is `(role_id, permission_id)` (#3329); repeated or\nconcurrent inserts converge without changing the grant ID. Existing deployments\nmust run `deduplicateRolePermissions()` with stopped writers before ordinary\nschema migration; see README's \"Upgrade duplicate role grants\". It keeps the\noldest row and installs uniqueness atomically. Runtime seeding never performs\nthis schema repair.\n"
10844
+ "content": "# Permissions and tenant inheritance\n\nRead for `src/services/PermissionResolver.ts`, operation guards, role seeding,\nRLS, and tenant-hierarchy changes. Integration examples live in README's\nmanifest-derived permission catalog and PostgreSQL RLS sections.\n\n## Membership selection\n\n1. A direct target-tenant membership pins resolution: active resolves normally;\n pending/suspended returns empty. Never union direct and ancestor roles.\n2. Otherwise walk hierarchyPath nearest-first for the nearest active ancestor\n membership whose role has inheritsToDescendants. Skip inactive/unflagged\n ancestors; they neither grant nor block. No qualifying ancestor means empty.\n3. Run later layers against the target tenant. Only target-tenant groups apply;\n membership overrides travel with the chosen ancestor membership.\n inheritedFromTenantId reports that ancestor, null for direct resolution.\n\nVerify hierarchyPath link-by-link against loaded parentTenantId rows before\ntrusting it: excess depth, self-reference, duplicates or inconsistent paths\nfail closed. Bound traversal by MAX_TENANT_HIERARCHY_DEPTH. Tenant status is not\nconsulted, matching direct resolution. Long-lived user/tenant caches must\ninvalidate ancestor membership changes and inheritsToDescendants flips;\nrequest-scoped caches do not survive those requests.\n\n`loadSessionContext().tenantAuthorization` is authoritative for required-tenant\nconsumers; membership null can mean inherited authority.\n\n4. If no membership resolved at all, apply the opt-in ancestor-read policy\n (smrt#2939): the user's ACTIVE memberships on VERIFIED DESCENDANTS of the\n target, whose role slug is declared in `permissions.ancestorRead.roles` and\n within `maxDepth` hops, contribute `<collection>.read` for declared\n collections, intersected with BOTH that role's own catalog grants (so a\n descendant-side tenant GRANT, group role, or membership GRANT cannot widen\n it) AND the principal's effective permissions in that descendant (so its\n DENY cascade and membership DENY apply). Only a SYSTEM\n role (`tenantId` null, `isSystem: true`) matches a declared slug: slugs are\n not unique across a hierarchy, so a tenant-scoped custom role of the same\n name must not opt its tenant in. Off by default;\n read-only; never lateral; never reached when a direct or inherited\n membership already decided. The target tenant's DENY still subtracts.\n `ancestorReadFromTenantIds` reports the contributing descendants. The grant\n carries no membership, so `membershipId`/`tenantAuthorization.membershipId`\n stay null and a consumer requiring a non-empty membership still refuses.\n\n## Permission precedence\n\nApply these layers in order, later layers overriding earlier ones:\n\n1. Ancestor TenantPermissionOverride cascade (GRANT adds, DENY removes).\n2. Selected membership role permissions.\n3. Target-tenant group-role permissions.\n4. Tenant cascade's net DENY removes role/group grants.\n5. Membership GRANT may re-add a tenant-denied slug.\n6. Membership DENY removes last and always wins.\n\nThe tenant block is the cascade's net result, not the union of historical DENYs:\na child's more-specific GRANT can override a parent DENY. Use a direct child\nmembership or tenant DENY to attenuate inherited role authority.\n`getGroupIdsForTenant(userId, tenantId)` is required; getGroupIds is cross-tenant.\n\n## Hierarchies and seeding\n\n- `Tenant.save()` derives hierarchyPath/hierarchyLevel from the REAL\n parentTenantId chain on every save (never from an ancestor's stored path),\n refuses missing parents, cycles and over-depth before writing, and\n re-materializes descendants by raw column update (so STI subclass columns\n are never clobbered). createChild/moveToParent/makeRoot are thin wrappers.\n `materializeTenantHierarchy(db, { dryRun })` / `smrt\n db:materialize-tenant-hierarchy` backfills legacy rows: idempotent, one\n transaction, refuses a broken chain without writing (#3036). A NEW or\n CHANGED parent link is authority-bearing, so `Tenant.save()` first loads the\n parent through TenantCollection (the caller's tenancy scope) and refuses an\n invisible one on every path — helpers, `create({ parentTenantId })`, or a\n plain assignment + save; system context bypasses as usual, and an unchanged\n link is never re-checked. getTree(rootId?)\n returns UI structure. Maximum depth is 10.\n- Tenant override cascade requires parent cascadePermissions and child\n inheritPermissions. These flags do not gate the independent, per-role\n inheritsToDescendants membership flow.\n- `permissions.ancestorRead` in the `users` package config declares upward,\n read-only visibility: `{ roles, collections, maxDepth? }`. Both lists are\n required and non-empty and `maxDepth >= 1`, else the policy is OFF — there is\n no partially valid declaration. `isAncestorReadableSlug()` is the single place\n the read-only bound is enforced; only a two-segment `<collection>.<action>`\n slug whose action normalizes to `read` on a declared collection passes.\n `PermissionResolver.create(options, { ancestorReadPolicy })` binds one\n resolver; `null` forces it off. It grants the OPERATION at the ancestor, never\n row visibility — sibling rows stay scoped by the tenancy interceptor and RLS.\n- seedSystemRoles({ inheritsToDescendants: ['owner', 'admin'] }) flags listed\n slugs additively, never unflags omitted ones, and rejects unknown slugs.\n Default seeds are exact-tenant.\n- RolePermissionCollection.seedRolePermissions() or\n seedSystemRoles({ seedPermissions: true }) maps owner/admin to all catalog\n permissions, member to ordinary-resource read/create, viewer to read. Member\n create excludes identity/RBAC/security resources and their joins/overrides.\n Seeding is additive/idempotent; removal requires prune: true. Catalog sync\n and grants plan from one read, then commit in `SEEDING_BATCH_SIZE` batches\n (#3323): never one durable commit per row (an fsync each on local SQLite),\n and never one catalog-wide transaction (`@happyvertical/sql` transaction\n scopes cost superlinearly per statement). Pass a caller transaction's handle.\n- When a package adds built-in self-personalization permissions after role\n creation, explicitly call seedDefaultRolePersonalizationPermissions(). It\n upgrades owner/admin/member/viewer idempotently and never grants custom roles.\n The built-in self-personalization slugs are `fields.policy.personalize`,\n `overviews.personalize` and `shell.personalize`, each seeded only once its\n package registered it.\n\n## Guards and RLS\n\nPermissionCatalogService derives collection.action slugs from manifests,\nincluding custom actions; list/get map to read. Guards derive a class's slug\nthrough the same resolution (explicit `collection`, manifest entry, then its\nSTI base's), so an STI subtype resolves its STI base's collection\n(`Network extends Tenant` -> `tenants.update`) in every build, including a\nbundle decorated before its manifest loads (#3125). Hand-written mutations in form\nhandlers, endpoints, CLI and jobs use assertOperationPermission(). It requires\ncatalog presence then resolves permissions, throwing fail-closed by default.\nUse onDeny: 'return', checkOperationPermission or hasOperationPermission only\nwhen the caller handles a structured/boolean denial.\n\nGenerated SvelteKit write routes (POST/PUT/PATCH/DELETE CRUD and mutating\ncustom actions) enforce the same `collection.action` slug (custom actions use\n`collection.<method>`; actions hosted on a collection class use the item collection, which the catalog now emits) after authentication: the slug must be in the request's\nsession permission snapshot (`locals.permissions`/`permissionSet`/\n`smrtPermissions` or `locals.tenantContext.permissions`), otherwise 403. Only\n`locals.tenantContext.superAdminBypass` skips it; `api.public: true` stays open.\n\nResource-anchored guards receive the resource tenant ID. When it differs from\nthe session tenant, omit the session membership so the resolver selects the\nappropriate authority; mismatched supplied membership/tenant fails closed.\nInherited root-admin authority can then authorize descendant resources without\napplication-side membership fan-out.\n\nResolution cost must not scale with catalog size in objects (#3047): role →\npermission ids and ids → slugs are `list({ select })` projection reads (the\ncollections' beforeList interceptors still run; no RolePermission/Permission\nis hydrated), so an owner mapped to the whole catalog costs two queries and\nno per-permission objects. Keep new resolver reads projections when only ids\nor slugs are needed, and do not add public collection methods for them — each\nbecomes a custom-action slug in the manifest-derived catalog. The resolver's\ncollections never inherit `defaultListLimit`/`maxListLimit` from the caller's\noptions, and id-list reads chunk at `IN_LIST_CHUNK_SIZE` with an explicit\nlimit: a truncated authorization read would narrow the result silently.\n`issue-3047-permission-resolution-cost-postgres.test.ts` pins the hydration\nbudget and a golden equivalence matrix recorded on the hydrating resolver.\n\nThe same rule holds for every framework-internal authorization read (#3048):\ncollections that back a decision — the resolver's, the ResourceGrant exact-tuple\nread in `checkResourceOperationPermission()` (DENY wins only if every row is\nread), and TenantService's owned-tenant quota count — are created through\n`withoutListBounds()` (`src/services/authorization-read-options.ts`), which\nstrips only the caller's list bounds. Use it for any new decision read;\n`issue-3048-authorization-list-bounds-postgres.test.ts` pins it.\n\nPermissionResolver runs every resolution inside smrt-tenancy's system context\n(#3036). Its reads are deliberately cross-tenant and framework-owned — the\nancestor TenantPermissionOverride batch, ancestor memberships for\ninheritsToDescendants, descendant memberships for ancestor-read — and are keyed\nby the explicit (userId, tenantId); with those classes registered tenant-scoped\n(`autoFilter`) the consumer's filter otherwise threw TenantIsolationError or\nsilently narrowed them. It returns slugs and ids only, never rows, and the\ncaller's own reads stay filtered. Do not move a resolver read back under the\nambient tenant; the Postgres regression suite\n`issue-3036-hierarchy-resolution-postgres.test.ts` pins this. Because nothing\nbackstops those reads any more, the tenant-override cascade verifies its chain\ntoo: it uses hierarchyPath only when it agrees link-by-link with\nparentTenantId, otherwise walks the real parent links (so a forged path cannot\ncascade an unrelated tenant in, and a never-materialized row still gets its real\nancestors' DENYs — and GRANTs), and throws TenantHierarchyError on a broken\nreal chain: a per-request failure for that tenant's whole subtree, which\n`smrt db:materialize-tenant-hierarchy --dry-run` reports ahead of time (see\nREADME \"Upgrading an existing fleet\").\n`getTenantInheritanceChain()` returns Tenant rows, so it is NOT run in system\ncontext; it reports the same verified chain the cascade applies when the\ncaller can read every ancestor. Otherwise it never reports PARENT_NOT_FOUND\nfor a row the caller simply cannot see: an interceptor refusal surfaces as\nTenantIsolationError, and a silently filtered row (e.g. RLS) ends the chain at\nthe nearest readable ancestor. Descendant path rewrites are raw column updates recorded through\n`bumpChangeFeed`; `updated_at` is intentionally not bumped (derived columns;\nevery save recomputes them). They are not atomic with the moving row's save —\nan interrupted subtree fails closed until re-saved or backfilled.\n\nSystem context and super-admin bypass are honored. Pass\nallowSuperAdminBypass: false for money or separation-of-duties operations that\nrequire an explicit grant.\n\ngeneratePostgresPermissionSql/applyPostgresPermissionPolicies enforce generated\nRLS using smrt.permissions and smrt.tenant_id, installed with set_config by\nwithSessionPermissionContext. This bounds REST, MCP and in-process database\naccess once principal context is set. Child-tenant sessions receive resolved\ninherited permissions automatically, but RLS row filtering remains bound to the\nsession tenant: a root session's app-level guard authorization does not itself\npermit child rows through RLS. Preserve this distinction.\n\nRolePermission's natural key is `(role_id, permission_id)` (#3329); repeated or\nconcurrent inserts converge without changing the grant ID. Existing deployments\nmust run `deduplicateRolePermissions()` with stopped writers before ordinary\nschema migration; see README's \"Upgrade duplicate role grants\". It keeps the\noldest row and installs uniqueness atomically. Runtime seeding never performs\nthis schema repair.\n\nMembershipOverride `(membership_id, permission_id)`, TenantPermissionOverride\n`(tenant_id, permission_id)` and GroupMember `(group_id, user_id)` are natural\nkeys too (#3375): `setOverride()` upserts (last effect wins), removal deletes by\nthe pair, and their FKs declare `onDelete: 'NO ACTION'` so the natural key does\nnot turn them into CASCADE. Existing deployments run\n`deduplicateAuthorityPairs()` in the same stopped-writer window; it keeps the\neffective override (DENY > GRANT > INHERIT) so authority never widens.\n\nCustom methods can declare `operationPermissions` aliases to the same\ncollection's CRUD grants (#3878); `deriveOperationPermissionSlug()` resolves\nthem for class and catalog-slug callers. Catalog generation merges optional\n`databaseActions` into the target grant's PostgreSQL bindings. CRUD grants\ncannot themselves be aliased. See core's [generator contract](../../core/agents/generators.md#custom-action-permission-aliases-3878).\n"
10838
10845
  },
10839
10846
  {
10840
10847
  "path": "agents/oidc-provisioning.md",
@@ -18,6 +18,7 @@
18
18
  * // routes/account/password/+server.ts → export const PUT = passwordAuth.changePassword;
19
19
  * // export const POST = passwordAuth.setPassword;
20
20
  * // export const DELETE = passwordAuth.clearPassword;
21
+ * // routes/account/password/recover/+server.ts → export const POST = passwordAuth.replaceForgottenPassword;
21
22
  * // routes/admin/password-reset/+server.ts → export const POST = passwordAuth.resetPassword;
22
23
  * ```
23
24
  *
@@ -83,6 +84,12 @@ export interface PasswordCredentialHandlers {
83
84
  changePassword: (event: PasswordRequestEvent) => Promise<Response>;
84
85
  resetPassword: (event: PasswordRequestEvent) => Promise<Response>;
85
86
  clearPassword: (event: PasswordRequestEvent) => Promise<Response>;
87
+ /**
88
+ * Replace a forgotten password from a fresh out-of-band recovery session
89
+ * (#3905). Needs `recovery` configured; ends every session, this one too,
90
+ * and clears the cookie.
91
+ */
92
+ replaceForgottenPassword: (event: PasswordRequestEvent) => Promise<Response>;
86
93
  /** The lazily created service, for form actions and admin screens. */
87
94
  service: () => Promise<PasswordCredentialService>;
88
95
  }
@@ -1 +1 @@
1
- {"version":3,"file":"password-handlers.d.ts","sourceRoot":"","sources":["../../src/sveltekit/password-handlers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AAGH,OAAO,yBAAyB,CAAC;AAIjC,OAAO,EAGL,yBAAyB,EACzB,KAAK,gCAAgC,EAEtC,MAAM,0CAA0C,CAAC;AAKlD,KAAK,OAAO,GAAG;IACb,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IAC1C,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAC9E,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;CACnE,CAAC;AAEF,kEAAkE;AAClE,MAAM,MAAM,oBAAoB,GAAG;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,MAAM,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,GAAG,CAAC;CACV,CAAC;AAEF,MAAM,WAAW,uCACf,SAAQ,gCAAgC;IACxC;;;;OAIG;IACH,QAAQ,CAAC,EACL,MAAM,GACN,IAAI,GACJ,CAAC,CACC,KAAK,EAAE,oBAAoB,KACxB,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC;IACzE,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iDAAiD;IACjD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,cAAc,CAAC,EAAE,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;CAC5C;AAED,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC3D,WAAW,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAChE,cAAc,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnE,aAAa,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAClE,aAAa,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAClE,sEAAsE;IACtE,OAAO,EAAE,MAAM,OAAO,CAAC,yBAAyB,CAAC,CAAC;CACnD;AAuHD,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE,uCAAuC,GAC/C,0BAA0B,CAyI5B"}
1
+ {"version":3,"file":"password-handlers.d.ts","sourceRoot":"","sources":["../../src/sveltekit/password-handlers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AAGH,OAAO,yBAAyB,CAAC;AAIjC,OAAO,EAGL,yBAAyB,EACzB,KAAK,gCAAgC,EAEtC,MAAM,0CAA0C,CAAC;AAKlD,KAAK,OAAO,GAAG;IACb,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IAC1C,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAC9E,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;CACnE,CAAC;AAEF,kEAAkE;AAClE,MAAM,MAAM,oBAAoB,GAAG;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,MAAM,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,GAAG,CAAC;CACV,CAAC;AAEF,MAAM,WAAW,uCACf,SAAQ,gCAAgC;IACxC;;;;OAIG;IACH,QAAQ,CAAC,EACL,MAAM,GACN,IAAI,GACJ,CAAC,CACC,KAAK,EAAE,oBAAoB,KACxB,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC;IACzE,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iDAAiD;IACjD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,cAAc,CAAC,EAAE,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;CAC5C;AAED,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC3D,WAAW,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAChE,cAAc,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnE,aAAa,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAClE,aAAa,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAClE;;;;OAIG;IACH,wBAAwB,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC7E,sEAAsE;IACtE,OAAO,EAAE,MAAM,OAAO,CAAC,yBAAyB,CAAC,CAAC;CACnD;AAuHD,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE,uCAAuC,GAC/C,0BAA0B,CAmJ5B"}
package/dist/sveltekit.js CHANGED
@@ -1,4 +1,4 @@
1
- import { A as readMobileBearerToken, D as withSessionPermissionContext, F as encodeOidcTransaction, H as DeviceCredentialForbiddenError, I as getUsersOidcConfig, L as resolveOidcProviderConfig, M as OidcLoginError, N as OidcLoginService, O as MobileAuthError, P as decodeOidcTransaction, U as DeviceCredentialPolicyError, V as DeviceCredentialError, W as DeviceCredentialService, Y as SessionService, _ as PasswordCredentialService, a as TerminalAuthError, at as LoginRateLimitError, b as OperationPermissionError, g as PasswordCredentialForbiddenError, h as PasswordCredentialError, j as validateMobileRedirectUri, k as MobileAuthService, o as TerminalAuthRateLimitError, s as TerminalAuthService, v as PasswordPolicyError } from "./chunks/TerminalAuthService-C8zxBkNB.js";
1
+ import { A as withSessionPermissionContext, B as resolveOidcProviderConfig, C as OperationPermissionError, F as OidcLoginError, G as DeviceCredentialForbiddenError, I as OidcLoginService, K as DeviceCredentialPolicyError, L as decodeOidcTransaction, M as MobileAuthService, N as readMobileBearerToken, P as validateMobileRedirectUri, Q as SessionService, R as encodeOidcTransaction, W as DeviceCredentialError, _ as PasswordCredentialError, a as TerminalAuthError, b as PasswordPolicyError, j as MobileAuthError, lt as LoginRateLimitError, o as TerminalAuthRateLimitError, q as DeviceCredentialService, s as TerminalAuthService, v as PasswordCredentialForbiddenError, y as PasswordCredentialService, z as getUsersOidcConfig } from "./chunks/TerminalAuthService-BQjH5_bB.js";
2
2
  import { DiscoveryArtifactValidationError, SMRT_APP_RESULT_CONTRACT, SMRT_APP_RESULT_SCHEMA, SMRT_APP_RESULT_VERSION, SMRT_DISCOVERY_CONFORMANCE_ARTIFACT_SCHEMA, SMRT_DISCOVERY_CONFORMANCE_SCHEMA, SMRT_DISCOVERY_CONFORMANCE_VERSION, SMRT_MCP_RESULT_METADATA_KEY, canonicalizeDiscoveryArtifact, createDiscoveryConformanceArtifact, deriveCommandRequirements, validateDiscoveryConformanceArtifact } from "./app-contract.js";
3
3
  import { ObjectRegistry, createClassNamePredicate, resolveCustomActionMetadata, resolveEffectiveActionMetadata } from "@happyvertical/smrt-core";
4
4
  import { createLogger } from "@happyvertical/logger";
@@ -512,6 +512,18 @@ function createPasswordCredentialHandlers(options) {
512
512
  mustChange: typeof input.mustChange === "boolean" ? input.mustChange : input.mustChange === "false" ? false : void 0,
513
513
  ipAddress: event.getClientAddress?.()
514
514
  })),
515
+ replaceForgottenPassword: management(async (svc, actor, input, event) => {
516
+ const result = await svc.replaceForgottenPassword({
517
+ actor,
518
+ newPassword: str(input.newPassword) || str(input.password),
519
+ ipAddress: event.getClientAddress?.()
520
+ });
521
+ clearCookie(event);
522
+ return {
523
+ revokedSessions: result.revokedSessions,
524
+ signedOut: true
525
+ };
526
+ }),
515
527
  clearPassword: management((svc, actor, input, event) => svc.clearPassword({
516
528
  actor,
517
529
  userId: str(input.userId).trim() || (actor.user.id ?? ""),