@simple-auth-kit/cli 1.5.1 → 1.6.1

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 (182) hide show
  1. package/package.json +1 -1
  2. package/registry/combos/express-drizzle/shared/src/{ability.ts → ability/ability.ts} +8 -2
  3. package/registry/combos/express-drizzle/shared/src/{permission-cache.ts → cache/permission-cache.ts} +25 -9
  4. package/registry/combos/express-drizzle/shared/src/{rate-limit.store.ts → cache/rate-limit.store.ts} +4 -1
  5. package/registry/combos/{express-prisma/shared/src → express-drizzle/shared/src/config}/auth.config.ts +1 -1
  6. package/registry/combos/express-drizzle/shared/src/{db.ts → config/db.ts} +1 -1
  7. package/registry/combos/express-drizzle/shared/src/{key-provider.ts → config/key-provider.ts} +6 -2
  8. package/registry/combos/express-drizzle/shared/src/{id.helper.ts → helpers/id.helper.ts} +6 -2
  9. package/registry/combos/{nestjs-drizzle/shared/src → express-drizzle/shared/src/helpers}/pagination.ts +17 -3
  10. package/registry/combos/express-drizzle/shared/src/middleware/auth-core-error.middleware.ts +6 -8
  11. package/registry/combos/express-drizzle/shared/src/middleware/auth.middleware.ts +6 -8
  12. package/registry/combos/{express-prisma/shared/src → express-drizzle/shared/src/openapi}/openapi-fragment.ts +13 -4
  13. package/registry/combos/express-drizzle/shared/src/{openapi-spec.ts → openapi/openapi-spec.ts} +251 -52
  14. package/registry/combos/express-drizzle/shared/src/repositories/oauth.repository.ts +2 -2
  15. package/registry/combos/express-drizzle/shared/src/repositories/password-reset.repository.ts +2 -4
  16. package/registry/combos/express-drizzle/shared/src/repositories/session.repository.ts +3 -3
  17. package/registry/combos/express-drizzle/shared/src/request-context.ts +1 -1
  18. package/registry/combos/express-drizzle/shared/src/route-tiers.ts +52 -11
  19. package/registry/combos/express-drizzle/shared/src/routers/auth.router.ts +2 -2
  20. package/registry/combos/express-drizzle/test/bootstrap.ts +4 -2
  21. package/registry/combos/express-drizzle/test/prove-cycle.ts +1095 -308
  22. package/registry/combos/express-drizzle/variants/base/src/create-auth-app.ts +5 -5
  23. package/registry/combos/express-drizzle/variants/base/src/index.ts +8 -0
  24. package/registry/combos/express-drizzle/variants/base/src/middleware/authz.middleware.ts +2 -2
  25. package/registry/combos/express-drizzle/variants/base/src/openapi/openapi-admin.ts +1082 -0
  26. package/registry/combos/express-drizzle/variants/base/src/rbac.defaults.ts +60 -17
  27. package/registry/combos/express-drizzle/variants/base/src/repositories/audit-log.repository.ts +2 -2
  28. package/registry/combos/express-drizzle/variants/base/src/repositories/rbac.repository.ts +5 -5
  29. package/registry/combos/express-drizzle/variants/base/src/routers/admin.router.ts +18 -22
  30. package/registry/combos/express-drizzle/variants/base/src/seed.ts +76 -17
  31. package/registry/combos/express-drizzle/variants/base/src/services/auth.service.ts +7 -9
  32. package/registry/combos/express-drizzle/variants/base/test/variant-hooks.ts +167 -45
  33. package/registry/combos/express-drizzle/variants/workspaces/src/create-auth-app.ts +5 -5
  34. package/registry/combos/express-drizzle/variants/workspaces/src/index.ts +8 -0
  35. package/registry/combos/express-drizzle/variants/workspaces/src/middleware/authz.middleware.ts +3 -3
  36. package/registry/combos/express-drizzle/variants/workspaces/src/openapi/openapi-admin.ts +1176 -0
  37. package/registry/combos/express-drizzle/variants/workspaces/src/openapi-workspace.ts +1 -1
  38. package/registry/combos/express-drizzle/variants/workspaces/src/rbac.defaults.ts +66 -19
  39. package/registry/combos/express-drizzle/variants/workspaces/src/repositories/audit-log.repository.ts +2 -2
  40. package/registry/combos/express-drizzle/variants/workspaces/src/repositories/rbac.repository.ts +5 -5
  41. package/registry/combos/express-drizzle/variants/workspaces/src/repositories/workspace.repository.ts +9 -11
  42. package/registry/combos/express-drizzle/variants/workspaces/src/routers/admin.router.ts +18 -22
  43. package/registry/combos/express-drizzle/variants/workspaces/src/routers/workspace.router.ts +1 -1
  44. package/registry/combos/express-drizzle/variants/workspaces/src/seed.ts +168 -35
  45. package/registry/combos/express-drizzle/variants/workspaces/src/services/auth.service.ts +7 -9
  46. package/registry/combos/express-drizzle/variants/workspaces/test/variant-hooks.ts +539 -133
  47. package/registry/combos/express-prisma/shared/src/{ability.ts → ability/ability.ts} +8 -2
  48. package/registry/combos/express-prisma/shared/src/{permission-cache.ts → cache/permission-cache.ts} +25 -9
  49. package/registry/combos/express-prisma/shared/src/{rate-limit.store.ts → cache/rate-limit.store.ts} +4 -1
  50. package/registry/combos/{express-drizzle/shared/src → express-prisma/shared/src/config}/auth.config.ts +1 -1
  51. package/registry/combos/express-prisma/shared/src/{key-provider.ts → config/key-provider.ts} +6 -2
  52. package/registry/combos/{nestjs-prisma/shared/src → express-prisma/shared/src/helpers}/id.helper.ts +6 -2
  53. package/registry/combos/{express-drizzle/shared/src → express-prisma/shared/src/helpers}/pagination.ts +17 -3
  54. package/registry/combos/express-prisma/shared/src/middleware/auth-core-error.middleware.ts +6 -8
  55. package/registry/combos/express-prisma/shared/src/middleware/auth.middleware.ts +6 -8
  56. package/registry/combos/{express-drizzle/shared/src → express-prisma/shared/src/openapi}/openapi-fragment.ts +13 -4
  57. package/registry/combos/express-prisma/shared/src/{openapi-spec.ts → openapi/openapi-spec.ts} +313 -55
  58. package/registry/combos/express-prisma/shared/src/repositories/oauth.repository.ts +2 -2
  59. package/registry/combos/express-prisma/shared/src/repositories/password-reset.repository.ts +2 -4
  60. package/registry/combos/express-prisma/shared/src/repositories/session.repository.ts +2 -2
  61. package/registry/combos/express-prisma/shared/src/request-context.ts +1 -1
  62. package/registry/combos/express-prisma/shared/src/route-tiers.ts +52 -11
  63. package/registry/combos/express-prisma/shared/src/routers/auth.router.ts +2 -2
  64. package/registry/combos/express-prisma/test/bootstrap.ts +7 -3
  65. package/registry/combos/express-prisma/test/prove-cycle.ts +1095 -308
  66. package/registry/combos/express-prisma/variants/base/src/create-auth-app.ts +6 -6
  67. package/registry/combos/express-prisma/variants/base/src/index.ts +8 -0
  68. package/registry/combos/express-prisma/variants/base/src/middleware/authz.middleware.ts +2 -2
  69. package/registry/combos/express-prisma/variants/base/src/openapi/openapi-admin.ts +1102 -0
  70. package/registry/combos/express-prisma/variants/base/src/rbac.defaults.ts +1 -1
  71. package/registry/combos/express-prisma/variants/base/src/repositories/audit-log.repository.ts +2 -2
  72. package/registry/combos/express-prisma/variants/base/src/repositories/rbac.repository.ts +4 -4
  73. package/registry/combos/express-prisma/variants/base/src/routers/admin.router.ts +18 -22
  74. package/registry/combos/express-prisma/variants/base/src/seed.ts +1 -1
  75. package/registry/combos/express-prisma/variants/base/src/services/auth.service.ts +6 -8
  76. package/registry/combos/express-prisma/variants/base/test/variant-hooks.ts +176 -47
  77. package/registry/combos/express-prisma/variants/workspaces/src/create-auth-app.ts +6 -6
  78. package/registry/combos/express-prisma/variants/workspaces/src/index.ts +8 -0
  79. package/registry/combos/express-prisma/variants/workspaces/src/middleware/authz.middleware.ts +3 -3
  80. package/registry/combos/express-prisma/variants/workspaces/src/openapi/openapi-admin.ts +1218 -0
  81. package/registry/combos/express-prisma/variants/workspaces/src/openapi-workspace.ts +1 -1
  82. package/registry/combos/express-prisma/variants/workspaces/src/rbac.defaults.ts +1 -1
  83. package/registry/combos/express-prisma/variants/workspaces/src/repositories/audit-log.repository.ts +2 -2
  84. package/registry/combos/express-prisma/variants/workspaces/src/repositories/rbac.repository.ts +4 -4
  85. package/registry/combos/express-prisma/variants/workspaces/src/repositories/workspace.repository.ts +2 -2
  86. package/registry/combos/express-prisma/variants/workspaces/src/routers/admin.router.ts +18 -22
  87. package/registry/combos/express-prisma/variants/workspaces/src/routers/workspace.router.ts +1 -1
  88. package/registry/combos/express-prisma/variants/workspaces/src/seed.ts +1 -1
  89. package/registry/combos/express-prisma/variants/workspaces/src/services/auth.service.ts +6 -8
  90. package/registry/combos/express-prisma/variants/workspaces/test/variant-hooks.ts +538 -134
  91. package/registry/combos/nestjs-drizzle/shared/src/{guards → ability}/ability.guard.ts +1 -1
  92. package/registry/combos/nestjs-drizzle/shared/src/{ability.ts → ability/ability.ts} +8 -2
  93. package/registry/combos/nestjs-drizzle/shared/src/{permission-cache.ts → cache/permission-cache.ts} +27 -10
  94. package/registry/combos/{nestjs-prisma/shared/src → nestjs-drizzle/shared/src/cache}/rate-limit.store.ts +4 -1
  95. package/registry/combos/nestjs-drizzle/shared/src/{auth.config.ts → config/auth.config.ts} +1 -1
  96. package/registry/combos/nestjs-drizzle/shared/src/{db.ts → config/db.ts} +1 -1
  97. package/registry/combos/nestjs-drizzle/shared/src/{key-provider.ts → config/key-provider.ts} +6 -2
  98. package/registry/combos/nestjs-drizzle/shared/src/controllers/auth.controller.ts +1 -1
  99. package/registry/combos/nestjs-drizzle/shared/src/guards/auth.guard.ts +1 -1
  100. package/registry/combos/nestjs-drizzle/shared/src/{id.helper.ts → helpers/id.helper.ts} +6 -2
  101. package/registry/combos/{express-prisma/shared/src → nestjs-drizzle/shared/src/helpers}/pagination.ts +17 -3
  102. package/registry/combos/nestjs-drizzle/shared/src/repositories/oauth.repository.ts +2 -2
  103. package/registry/combos/nestjs-drizzle/shared/src/repositories/password-reset.repository.ts +8 -12
  104. package/registry/combos/nestjs-drizzle/shared/src/repositories/session.repository.ts +3 -3
  105. package/registry/combos/nestjs-drizzle/shared/src/repositories/two-factor.repository.ts +1 -1
  106. package/registry/combos/nestjs-drizzle/shared/src/request-context.ts +1 -1
  107. package/registry/combos/nestjs-drizzle/test/bootstrap.ts +1 -1
  108. package/registry/combos/nestjs-drizzle/test/prove-cycle.ts +1 -1
  109. package/registry/combos/nestjs-drizzle/variants/base/src/auth.module.ts +10 -6
  110. package/registry/combos/nestjs-drizzle/variants/base/src/controllers/admin.controller.ts +1 -1
  111. package/registry/combos/nestjs-drizzle/variants/base/src/guards/authz.guard.ts +2 -2
  112. package/registry/combos/nestjs-drizzle/variants/base/src/index.ts +9 -0
  113. package/registry/combos/nestjs-drizzle/variants/base/src/rbac.defaults.ts +58 -16
  114. package/registry/combos/nestjs-drizzle/variants/base/src/repositories/audit-log.repository.ts +3 -3
  115. package/registry/combos/nestjs-drizzle/variants/base/src/repositories/rbac.repository.ts +4 -4
  116. package/registry/combos/nestjs-drizzle/variants/base/src/seed.ts +76 -17
  117. package/registry/combos/nestjs-drizzle/variants/base/src/services/auth.service.ts +7 -9
  118. package/registry/combos/nestjs-drizzle/variants/base/test/variant-hooks.ts +167 -45
  119. package/registry/combos/nestjs-drizzle/variants/workspaces/src/auth.module.ts +10 -6
  120. package/registry/combos/nestjs-drizzle/variants/workspaces/src/controllers/admin.controller.ts +1 -1
  121. package/registry/combos/nestjs-drizzle/variants/workspaces/src/controllers/workspace.controller.ts +1 -1
  122. package/registry/combos/nestjs-drizzle/variants/workspaces/src/guards/authz.guard.ts +2 -2
  123. package/registry/combos/nestjs-drizzle/variants/workspaces/src/index.ts +9 -0
  124. package/registry/combos/nestjs-drizzle/variants/workspaces/src/rbac.defaults.ts +64 -18
  125. package/registry/combos/nestjs-drizzle/variants/workspaces/src/repositories/audit-log.repository.ts +3 -3
  126. package/registry/combos/nestjs-drizzle/variants/workspaces/src/repositories/rbac.repository.ts +4 -4
  127. package/registry/combos/nestjs-drizzle/variants/workspaces/src/repositories/workspace.repository.ts +8 -10
  128. package/registry/combos/nestjs-drizzle/variants/workspaces/src/seed.ts +171 -36
  129. package/registry/combos/nestjs-drizzle/variants/workspaces/src/services/auth.service.ts +7 -9
  130. package/registry/combos/nestjs-drizzle/variants/workspaces/test/variant-hooks.ts +539 -133
  131. package/registry/combos/nestjs-prisma/shared/src/{guards → ability}/ability.guard.ts +1 -1
  132. package/registry/combos/nestjs-prisma/shared/src/{ability.ts → ability/ability.ts} +8 -2
  133. package/registry/combos/nestjs-prisma/shared/src/{permission-cache.ts → cache/permission-cache.ts} +27 -10
  134. package/registry/combos/{nestjs-drizzle/shared/src → nestjs-prisma/shared/src/cache}/rate-limit.store.ts +4 -1
  135. package/registry/combos/nestjs-prisma/shared/src/{auth.config.ts → config/auth.config.ts} +1 -1
  136. package/registry/combos/nestjs-prisma/shared/src/{key-provider.ts → config/key-provider.ts} +6 -2
  137. package/registry/combos/nestjs-prisma/shared/src/controllers/auth.controller.ts +1 -1
  138. package/registry/combos/nestjs-prisma/shared/src/guards/auth.guard.ts +1 -1
  139. package/registry/combos/{express-prisma/shared/src → nestjs-prisma/shared/src/helpers}/id.helper.ts +6 -2
  140. package/registry/combos/nestjs-prisma/shared/src/{pagination.ts → helpers/pagination.ts} +17 -3
  141. package/registry/combos/nestjs-prisma/shared/src/repositories/oauth.repository.ts +1 -1
  142. package/registry/combos/nestjs-prisma/shared/src/repositories/password-reset.repository.ts +2 -4
  143. package/registry/combos/nestjs-prisma/shared/src/repositories/session.repository.ts +2 -2
  144. package/registry/combos/nestjs-prisma/shared/src/request-context.ts +1 -1
  145. package/registry/combos/nestjs-prisma/test/bootstrap.ts +1 -1
  146. package/registry/combos/nestjs-prisma/test/prove-cycle.ts +1 -1
  147. package/registry/combos/nestjs-prisma/variants/base/src/auth.module.ts +10 -6
  148. package/registry/combos/nestjs-prisma/variants/base/src/controllers/admin.controller.ts +1 -1
  149. package/registry/combos/nestjs-prisma/variants/base/src/gateways/audit-log.gateway.ts +1 -1
  150. package/registry/combos/nestjs-prisma/variants/base/src/guards/authz.guard.ts +2 -2
  151. package/registry/combos/nestjs-prisma/variants/base/src/index.ts +9 -0
  152. package/registry/combos/nestjs-prisma/variants/base/src/{docs.ts → openapi/docs.ts} +23 -6
  153. package/registry/combos/nestjs-prisma/variants/base/src/rbac.defaults.ts +1 -1
  154. package/registry/combos/nestjs-prisma/variants/base/src/repositories/audit-log.repository.ts +2 -2
  155. package/registry/combos/nestjs-prisma/variants/base/src/repositories/country.repository.ts +2 -2
  156. package/registry/combos/nestjs-prisma/variants/base/src/repositories/customer.repository.ts +6 -5
  157. package/registry/combos/nestjs-prisma/variants/base/src/repositories/language.repository.ts +2 -2
  158. package/registry/combos/nestjs-prisma/variants/base/src/repositories/rbac.repository.ts +3 -3
  159. package/registry/combos/nestjs-prisma/variants/base/src/seed.ts +1 -1
  160. package/registry/combos/nestjs-prisma/variants/base/src/services/auth.service.ts +6 -8
  161. package/registry/combos/nestjs-prisma/variants/base/test/variant-hooks.ts +176 -47
  162. package/registry/combos/nestjs-prisma/variants/workspaces/src/auth.module.ts +10 -6
  163. package/registry/combos/nestjs-prisma/variants/workspaces/src/controllers/admin.controller.ts +1 -1
  164. package/registry/combos/nestjs-prisma/variants/workspaces/src/controllers/workspace.controller.ts +1 -1
  165. package/registry/combos/nestjs-prisma/variants/workspaces/src/guards/authz.guard.ts +2 -2
  166. package/registry/combos/nestjs-prisma/variants/workspaces/src/index.ts +9 -0
  167. package/registry/combos/nestjs-prisma/variants/workspaces/src/rbac.defaults.ts +1 -1
  168. package/registry/combos/nestjs-prisma/variants/workspaces/src/repositories/audit-log.repository.ts +2 -2
  169. package/registry/combos/nestjs-prisma/variants/workspaces/src/repositories/country.repository.ts +2 -2
  170. package/registry/combos/nestjs-prisma/variants/workspaces/src/repositories/customer.repository.ts +6 -5
  171. package/registry/combos/nestjs-prisma/variants/workspaces/src/repositories/language.repository.ts +2 -2
  172. package/registry/combos/nestjs-prisma/variants/workspaces/src/repositories/rbac.repository.ts +3 -3
  173. package/registry/combos/nestjs-prisma/variants/workspaces/src/repositories/workspace.repository.ts +1 -1
  174. package/registry/combos/nestjs-prisma/variants/workspaces/src/seed.ts +1 -1
  175. package/registry/combos/nestjs-prisma/variants/workspaces/src/services/auth.service.ts +6 -8
  176. package/registry/combos/nestjs-prisma/variants/workspaces/test/variant-hooks.ts +538 -134
  177. package/registry/combos/express-drizzle/variants/base/src/openapi-admin.ts +0 -565
  178. package/registry/combos/express-drizzle/variants/workspaces/src/openapi-admin.ts +0 -596
  179. package/registry/combos/express-prisma/variants/base/src/openapi-admin.ts +0 -569
  180. package/registry/combos/express-prisma/variants/workspaces/src/openapi-admin.ts +0 -601
  181. /package/registry/combos/express-drizzle/shared/src/{http-error.ts → errors/http-error.ts} +0 -0
  182. /package/registry/combos/express-prisma/shared/src/{http-error.ts → errors/http-error.ts} +0 -0
@@ -17,7 +17,11 @@
17
17
  // database, no `(action, subject)` pairing to get wrong, and no conditions — which in turn means
18
18
  // there is no such thing as a rule the route guard can only *partially* evaluate. What a slug
19
19
  // means is decided entirely by which routes name it.
20
- import { AbilityBuilder, createMongoAbility, type MongoAbility } from "@casl/ability";
20
+ import {
21
+ AbilityBuilder,
22
+ createMongoAbility,
23
+ type MongoAbility,
24
+ } from "@casl/ability";
21
25
 
22
26
  /**
23
27
  * The subject every rule is written against. CASL needs one; this model does not use subjects, so
@@ -37,7 +41,9 @@ export type AppAbility = MongoAbility<[string, typeof ABILITY_SUBJECT]>;
37
41
  * answer for "we could not resolve any permissions", and the same answer as "this user genuinely
38
42
  * has none". There is no default-allow branch anywhere in this file.
39
43
  */
40
- export function defineAbilitiesFor(permissions: readonly string[] = []): AppAbility {
44
+ export function defineAbilitiesFor(
45
+ permissions: readonly string[] = [],
46
+ ): AppAbility {
41
47
  const { can, build } = new AbilityBuilder<AppAbility>(createMongoAbility);
42
48
  for (const permission of permissions) can(permission, ABILITY_SUBJECT);
43
49
  return build();
@@ -35,7 +35,7 @@
35
35
  // reads this cache — so blocking a user or revoking a session cannot be defeated by a warm entry.
36
36
  // Negative results are not cached either: "not a member of this workspace" is re-read every time,
37
37
  // so being added to a workspace is effective immediately rather than after a TTL.
38
- import type { AuthConfig } from "./auth.config.js";
38
+ import type { AuthConfig } from "../config/auth.config.js";
39
39
 
40
40
  /** Every key this library writes starts here, so a shared Redis can be separated by prefix. */
41
41
  export const CACHE_NAMESPACE = "simpleauthkit:authz";
@@ -66,7 +66,10 @@ export interface PermissionCacheStore {
66
66
  */
67
67
  export class InMemoryPermissionCacheStore implements PermissionCacheStore {
68
68
  readonly stats = { hits: 0, misses: 0, writes: 0 };
69
- private readonly entries = new Map<string, { value: string; expiresAt: number }>();
69
+ private readonly entries = new Map<
70
+ string,
71
+ { value: string; expiresAt: number }
72
+ >();
70
73
 
71
74
  async get(key: string): Promise<string | undefined> {
72
75
  const entry = this.entries.get(key);
@@ -99,10 +102,14 @@ export class InMemoryPermissionCacheStore implements PermissionCacheStore {
99
102
 
100
103
  async bump(key: string): Promise<number> {
101
104
  const entry = this.entries.get(key);
102
- const next = Number(entry && entry.expiresAt > Date.now() ? entry.value : 0) + 1;
105
+ const next =
106
+ Number(entry && entry.expiresAt > Date.now() ? entry.value : 0) + 1;
103
107
  // Version counters outlive entries on purpose: a counter that expired back to 0 would make
104
108
  // every superseded entry reachable again.
105
- this.entries.set(key, { value: String(next), expiresAt: Number.MAX_SAFE_INTEGER });
109
+ this.entries.set(key, {
110
+ value: String(next),
111
+ expiresAt: Number.MAX_SAFE_INTEGER,
112
+ });
106
113
  return next;
107
114
  }
108
115
  }
@@ -114,8 +121,10 @@ export class InMemoryPermissionCacheStore implements PermissionCacheStore {
114
121
  * write is picked up when the entry expires (`permissionCacheTtlSeconds`), not immediately.
115
122
  */
116
123
  export const POLICY_VERSION_KEY = `${CACHE_NAMESPACE}:policy-version`;
117
- export const subjectVersionKey = (subject: string) => `${CACHE_NAMESPACE}:subject-version:${subject}`;
118
- const entryKey = (subject: string, policy: string, subjectVersion: string) => `${CACHE_NAMESPACE}:entry:${subject}:p${policy}:s${subjectVersion}`;
124
+ export const subjectVersionKey = (subject: string) =>
125
+ `${CACHE_NAMESPACE}:subject-version:${subject}`;
126
+ const entryKey = (subject: string, policy: string, subjectVersion: string) =>
127
+ `${CACHE_NAMESPACE}:entry:${subject}:p${policy}:s${subjectVersion}`;
119
128
 
120
129
  /**
121
130
  * Reads through to the database, once per (principal, policy version, subject version).
@@ -144,11 +153,17 @@ export class PermissionCache {
144
153
  * @param subject the identity these permissions belong to — the cache key's principal
145
154
  * @param load resolves from the database on a miss. Returning `null` is not cached.
146
155
  */
147
- async resolve<T>(subject: string, load: () => Promise<T | null>): Promise<T | null> {
156
+ async resolve<T>(
157
+ subject: string,
158
+ load: () => Promise<T | null>,
159
+ ): Promise<T | null> {
148
160
  const ttl = this.config.permissionCacheTtlSeconds;
149
161
  if (ttl <= 0) return load(); // caching off; the semantics are identical, only the cost differs
150
162
 
151
- const [policy = "0", version = "0"] = await this.store.getMany([POLICY_VERSION_KEY, subjectVersionKey(subject)]);
163
+ const [policy = "0", version = "0"] = await this.store.getMany([
164
+ POLICY_VERSION_KEY,
165
+ subjectVersionKey(subject),
166
+ ]);
152
167
  const key = entryKey(subject, policy, version);
153
168
 
154
169
  const cached = await this.store.get(key);
@@ -160,7 +175,8 @@ export class PermissionCache {
160
175
  const pending = (async () => {
161
176
  const resolved = await load();
162
177
  // A negative result is not written: see the module comment. Only a real answer is cached.
163
- if (resolved !== null) await this.store.set(key, JSON.stringify(resolved), ttl);
178
+ if (resolved !== null)
179
+ await this.store.set(key, JSON.stringify(resolved), ttl);
164
180
  return resolved;
165
181
  })();
166
182
 
@@ -6,7 +6,10 @@ import type { RateLimitDeps } from "@/lib/auth/core/rate-limit.js";
6
6
  * more than one instance; nothing above this layer needs to change.
7
7
  */
8
8
  export class InMemoryRateLimitStore implements RateLimitDeps {
9
- private readonly windows = new Map<string, { count: number; resetAt: number }>();
9
+ private readonly windows = new Map<
10
+ string,
11
+ { count: number; resetAt: number }
12
+ >();
10
13
 
11
14
  async increment(key: string, windowMs: number): Promise<number> {
12
15
  const now = Date.now();
@@ -1,5 +1,5 @@
1
1
  import type { RateLimitDeps } from "@/lib/auth/core/rate-limit.js";
2
- import type { PermissionCacheStore } from "./permission-cache.js";
2
+ import type { PermissionCacheStore } from "../cache/permission-cache.js";
3
3
 
4
4
  export interface GoogleOAuthCredentials {
5
5
  clientId: string;
@@ -9,11 +9,15 @@ const MIN_SECRET_BYTES = 32; // 256 bits, HS256's own minimum
9
9
  function loadSecret(): Uint8Array {
10
10
  const raw = process.env[ENV_VAR];
11
11
  if (!raw) {
12
- throw new Error(`${ENV_VAR} is not set. Generate one and set it before starting the app — e.g.: openssl rand -base64 32`);
12
+ throw new Error(
13
+ `${ENV_VAR} is not set. Generate one and set it before starting the app — e.g.: openssl rand -base64 32`,
14
+ );
13
15
  }
14
16
  const secret = Buffer.from(raw, "base64");
15
17
  if (secret.length < MIN_SECRET_BYTES) {
16
- throw new Error(`${ENV_VAR} decodes to ${secret.length} bytes — needs at least ${MIN_SECRET_BYTES} (256 bits) for HS256.`);
18
+ throw new Error(
19
+ `${ENV_VAR} decodes to ${secret.length} bytes — needs at least ${MIN_SECRET_BYTES} (256 bits) for HS256.`,
20
+ );
17
21
  }
18
22
  return secret;
19
23
  }
@@ -11,12 +11,16 @@ export function toId(value: string | number | bigint): bigint {
11
11
  }
12
12
  }
13
13
 
14
- export function toIdOrUndefined(value: string | number | bigint | null | undefined): bigint | undefined {
14
+ export function toIdOrUndefined(
15
+ value: string | number | bigint | null | undefined,
16
+ ): bigint | undefined {
15
17
  if (value === null || value === undefined || value === "") return undefined;
16
18
  return toId(value);
17
19
  }
18
20
 
19
- export function toIdOrNull(value: string | number | bigint | null | undefined): bigint | null {
21
+ export function toIdOrNull(
22
+ value: string | number | bigint | null | undefined,
23
+ ): bigint | null {
20
24
  if (value === null || value === undefined || value === "") return null;
21
25
  return toId(value);
22
26
  }
@@ -21,10 +21,24 @@ export function normalizePage(page: number | undefined): number {
21
21
  }
22
22
 
23
23
  export function normalizeLimit(limit: number | undefined): number {
24
- return Math.min(limit && limit > 0 ? Math.floor(limit) : DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE);
24
+ return Math.min(
25
+ limit && limit > 0 ? Math.floor(limit) : DEFAULT_PAGE_SIZE,
26
+ MAX_PAGE_SIZE,
27
+ );
25
28
  }
26
29
 
27
- export function buildPageMeta(page: number, limit: number, total: number): PageMeta {
30
+ export function buildPageMeta(
31
+ page: number,
32
+ limit: number,
33
+ total: number,
34
+ ): PageMeta {
28
35
  const pageCount = Math.ceil(total / limit);
29
- return { page, limit, total, pageCount, hasPreviousPage: page > 1, hasNextPage: page < pageCount };
36
+ return {
37
+ page,
38
+ limit,
39
+ total,
40
+ pageCount,
41
+ hasPreviousPage: page > 1,
42
+ hasNextPage: page < pageCount,
43
+ };
30
44
  }
@@ -1,6 +1,6 @@
1
1
  import type { NextFunction, Request, Response } from "express";
2
2
  import { AuthCoreError } from "@/lib/auth/core/types.js";
3
- import { HttpError } from "../http-error.js";
3
+ import { HttpError } from "../errors/http-error.js";
4
4
 
5
5
  /**
6
6
  * Replaces the reference combo's `AuthCoreErrorFilter` (a Nest global `@Catch` exception
@@ -30,13 +30,11 @@ export function authCoreErrorMiddleware(
30
30
  }
31
31
 
32
32
  if (err instanceof HttpError) {
33
- res
34
- .status(err.statusCode)
35
- .json({
36
- statusCode: err.statusCode,
37
- code: err.name,
38
- message: err.message,
39
- });
33
+ res.status(err.statusCode).json({
34
+ statusCode: err.statusCode,
35
+ code: err.name,
36
+ message: err.message,
37
+ });
40
38
  return;
41
39
  }
42
40
 
@@ -1,6 +1,6 @@
1
1
  import type { NextFunction, Request, Response } from "express";
2
2
  import { verifyAccessToken } from "@/lib/auth/core/token-service.js";
3
- import { KeyProviderService } from "../key-provider.js";
3
+ import { KeyProviderService } from "../config/key-provider.js";
4
4
  import "../request-context.js";
5
5
  import { SessionRepository } from "../repositories/session.repository.js";
6
6
 
@@ -26,13 +26,11 @@ export function createAuthMiddleware(deps: AuthMiddlewareDeps) {
26
26
  ): Promise<void> {
27
27
  const header = req.headers["authorization"];
28
28
  if (!header?.startsWith("Bearer ")) {
29
- res
30
- .status(401)
31
- .json({
32
- statusCode: 401,
33
- code: "UNAUTHORIZED",
34
- message: "missing bearer token",
35
- });
29
+ res.status(401).json({
30
+ statusCode: 401,
31
+ code: "UNAUTHORIZED",
32
+ message: "missing bearer token",
33
+ });
36
34
  return;
37
35
  }
38
36
 
@@ -4,7 +4,7 @@
4
4
  // routes plus the fragment `openapi-admin.ts` contributes, and both of those import from here,
5
5
  // so nothing imports in a circle. (`rbac.defaults.ts` below is a leaf too — it imports only a
6
6
  // Prisma type — so naming the permission catalog here keeps that property.)
7
- import type { PermissionSlug } from "./rbac.defaults.js";
7
+ import type { PermissionSlug } from "../rbac.defaults.js";
8
8
 
9
9
  /** One module's contribution to the assembled OpenAPI document — see openapi-spec.ts. */
10
10
  export interface OpenApiFragment {
@@ -23,7 +23,11 @@ export interface OpenApiFragment {
23
23
  export function errorResponse(description: string): Record<string, unknown> {
24
24
  return {
25
25
  description,
26
- content: { "application/json": { schema: { $ref: "#/components/schemas/ErrorResponse" } } },
26
+ content: {
27
+ "application/json": {
28
+ schema: { $ref: "#/components/schemas/ErrorResponse" },
29
+ },
30
+ },
27
31
  };
28
32
  }
29
33
 
@@ -44,6 +48,11 @@ export function requiresPermission(permission: PermissionSlug): string {
44
48
  * self-checks, and anything about the scope the request named, where this deployment has one
45
49
  * narrower than itself.
46
50
  */
47
- export function missingPermission(permission: PermissionSlug, ...alsoWhen: string[]): Record<string, unknown> {
48
- return errorResponse([`Missing the \`${permission}\` permission`, ...alsoWhen].join(", or "));
51
+ export function missingPermission(
52
+ permission: PermissionSlug,
53
+ ...alsoWhen: string[]
54
+ ): Record<string, unknown> {
55
+ return errorResponse(
56
+ [`Missing the \`${permission}\` permission`, ...alsoWhen].join(", or "),
57
+ );
49
58
  }