@hilbras/keystone 2.5.0 → 3.0.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 (147) hide show
  1. package/CHANGELOG.md +423 -0
  2. package/README.md +85 -1
  3. package/dist/config.d.ts.map +1 -1
  4. package/dist/config.js +7 -1
  5. package/dist/config.js.map +1 -1
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +17 -11
  8. package/dist/index.js.map +1 -1
  9. package/dist/plugins/auth.d.ts +2 -0
  10. package/dist/plugins/auth.d.ts.map +1 -1
  11. package/dist/plugins/auth.js +21 -7
  12. package/dist/plugins/auth.js.map +1 -1
  13. package/dist/plugins/machinePrincipal.d.ts +28 -0
  14. package/dist/plugins/machinePrincipal.d.ts.map +1 -0
  15. package/dist/plugins/machinePrincipal.js +45 -0
  16. package/dist/plugins/machinePrincipal.js.map +1 -0
  17. package/dist/plugins/rateLimit.d.ts +10 -7
  18. package/dist/plugins/rateLimit.d.ts.map +1 -1
  19. package/dist/plugins/rateLimit.js +75 -36
  20. package/dist/plugins/rateLimit.js.map +1 -1
  21. package/dist/routes/admin/organizations.d.ts.map +1 -1
  22. package/dist/routes/admin/organizations.js +2 -0
  23. package/dist/routes/admin/organizations.js.map +1 -1
  24. package/dist/routes/admin/platform.d.ts.map +1 -1
  25. package/dist/routes/admin/platform.js +14 -1
  26. package/dist/routes/admin/platform.js.map +1 -1
  27. package/dist/routes/apiKeys.d.ts.map +1 -1
  28. package/dist/routes/apiKeys.js +37 -5
  29. package/dist/routes/apiKeys.js.map +1 -1
  30. package/dist/routes/auth.d.ts.map +1 -1
  31. package/dist/routes/auth.js +104 -3
  32. package/dist/routes/auth.js.map +1 -1
  33. package/dist/routes/emailVerification.d.ts.map +1 -1
  34. package/dist/routes/emailVerification.js +2 -0
  35. package/dist/routes/emailVerification.js.map +1 -1
  36. package/dist/routes/federation.d.ts.map +1 -1
  37. package/dist/routes/federation.js +8 -2
  38. package/dist/routes/federation.js.map +1 -1
  39. package/dist/routes/magicLinks.d.ts.map +1 -1
  40. package/dist/routes/magicLinks.js +2 -0
  41. package/dist/routes/magicLinks.js.map +1 -1
  42. package/dist/routes/oauth2.d.ts.map +1 -1
  43. package/dist/routes/oauth2.js +24 -4
  44. package/dist/routes/oauth2.js.map +1 -1
  45. package/dist/routes/password.d.ts.map +1 -1
  46. package/dist/routes/password.js +2 -0
  47. package/dist/routes/password.js.map +1 -1
  48. package/dist/routes/profile.js +2 -2
  49. package/dist/routes/profile.js.map +1 -1
  50. package/dist/routes/scim.d.ts.map +1 -1
  51. package/dist/routes/scim.js +2 -0
  52. package/dist/routes/scim.js.map +1 -1
  53. package/dist/routes/serviceAccounts.d.ts.map +1 -1
  54. package/dist/routes/serviceAccounts.js +17 -1
  55. package/dist/routes/serviceAccounts.js.map +1 -1
  56. package/dist/routes/sessions.js +3 -3
  57. package/dist/routes/sessions.js.map +1 -1
  58. package/dist/routes/smsOtp.d.ts.map +1 -1
  59. package/dist/routes/smsOtp.js +10 -0
  60. package/dist/routes/smsOtp.js.map +1 -1
  61. package/dist/routes/totp.d.ts.map +1 -1
  62. package/dist/routes/totp.js +38 -6
  63. package/dist/routes/totp.js.map +1 -1
  64. package/dist/routes/webauthn.d.ts.map +1 -1
  65. package/dist/routes/webauthn.js +8 -2
  66. package/dist/routes/webauthn.js.map +1 -1
  67. package/dist/services/configuration/profiles.d.ts +26 -0
  68. package/dist/services/configuration/profiles.d.ts.map +1 -1
  69. package/dist/services/configuration/profiles.js +80 -1
  70. package/dist/services/configuration/profiles.js.map +1 -1
  71. package/dist/services/events/subscribers/auditLog.d.ts.map +1 -1
  72. package/dist/services/events/subscribers/auditLog.js +38 -3
  73. package/dist/services/events/subscribers/auditLog.js.map +1 -1
  74. package/dist/services/events/types.d.ts +3 -1
  75. package/dist/services/events/types.d.ts.map +1 -1
  76. package/dist/services/events/validate.d.ts +1 -0
  77. package/dist/services/events/validate.d.ts.map +1 -1
  78. package/dist/services/events/validate.js +5 -1
  79. package/dist/services/events/validate.js.map +1 -1
  80. package/dist/services/localRateLimit.d.ts +44 -0
  81. package/dist/services/localRateLimit.d.ts.map +1 -0
  82. package/dist/services/localRateLimit.js +86 -0
  83. package/dist/services/localRateLimit.js.map +1 -0
  84. package/dist/services/refreshTokenState.d.ts +5 -0
  85. package/dist/services/refreshTokenState.d.ts.map +1 -0
  86. package/dist/services/refreshTokenState.js +30 -0
  87. package/dist/services/refreshTokenState.js.map +1 -0
  88. package/dist/services/scopes.d.ts +113 -0
  89. package/dist/services/scopes.d.ts.map +1 -0
  90. package/dist/services/scopes.js +138 -0
  91. package/dist/services/scopes.js.map +1 -0
  92. package/dist/services/setup/token.d.ts +12 -0
  93. package/dist/services/setup/token.d.ts.map +1 -1
  94. package/dist/services/setup/token.js +27 -3
  95. package/dist/services/setup/token.js.map +1 -1
  96. package/dist/services/tokens.d.ts +1 -0
  97. package/dist/services/tokens.d.ts.map +1 -1
  98. package/dist/services/tokens.js +1 -1
  99. package/dist/services/tokens.js.map +1 -1
  100. package/dist/services/trustedProxies.d.ts +24 -0
  101. package/dist/services/trustedProxies.d.ts.map +1 -1
  102. package/dist/services/trustedProxies.js +19 -0
  103. package/dist/services/trustedProxies.js.map +1 -1
  104. package/dist/services/webhooks.d.ts +16 -0
  105. package/dist/services/webhooks.d.ts.map +1 -1
  106. package/dist/services/webhooks.js +48 -3
  107. package/dist/services/webhooks.js.map +1 -1
  108. package/dist/setup-server.js +47 -3
  109. package/dist/setup-server.js.map +1 -1
  110. package/docs/API-REVIEW.md +121 -0
  111. package/docs/API.md +457 -0
  112. package/docs/ARCHITECTURE.md +142 -0
  113. package/docs/CONTRIBUTING.md +61 -0
  114. package/docs/DEPLOYMENT.md +257 -0
  115. package/docs/INTEGRATION.md +336 -0
  116. package/docs/LOGIN_FORM_INTEGRATION.md +306 -0
  117. package/docs/MIGRATION-1.7.md +70 -0
  118. package/docs/MIGRATION-1.8.md +183 -0
  119. package/docs/MIGRATION-1.9.md +200 -0
  120. package/docs/MIGRATION-2.0.md +203 -0
  121. package/docs/MIGRATION-2.4.md +185 -0
  122. package/docs/PERFORMANCE.md +155 -0
  123. package/docs/RBAC.md +100 -0
  124. package/docs/RE-AUDIT.md +72 -0
  125. package/docs/README.md +54 -0
  126. package/docs/RELEASE-1.7.md +53 -0
  127. package/docs/ROADMAP.md +41 -0
  128. package/docs/SECURITY.md +143 -0
  129. package/docs/adrs/001-identity-connectors-as-adapters.md +27 -0
  130. package/docs/adrs/002-versioned-event-bus.md +30 -0
  131. package/docs/adrs/003-bullmq-for-background-work.md +20 -0
  132. package/docs/adrs/004-argon2id-password-hashing.md +19 -0
  133. package/docs/plans/KEYSTONE_IMPROVEMENT_PLAN.md +334 -0
  134. package/docs/plans/UI_SIMPLIFICATION_IMPROVEMENT_PLAN.md +271 -0
  135. package/docs/security/audit.md +82 -0
  136. package/docs/security/configuration.md +60 -0
  137. package/docs/security/enterprise-sso.md +193 -0
  138. package/docs/security/mtls.md +132 -0
  139. package/docs/security/proxy-security.md +128 -0
  140. package/docs/security/rate-limiting.md +79 -0
  141. package/docs/security/registry-exceptions.md +34 -0
  142. package/docs/security/registry.json +649 -0
  143. package/docs/security/registry.md +657 -0
  144. package/docs/security/scopes.md +45 -0
  145. package/docs/security/supply-chain.md +49 -0
  146. package/docs/security/trust-boundaries.md +111 -0
  147. package/package.json +15 -6
package/CHANGELOG.md CHANGED
@@ -5,6 +5,429 @@ All notable changes to Hilbras Keystone are documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [3.0.0] - 2026-09-27
9
+
10
+ ### Security
11
+
12
+ - **Two registry entries withdrawn, because they were not real.** `SEC-043` and
13
+ `SEC-044` were added during the 2.9.0 release with fixes at
14
+ `src/services/saml/validator.ts` and `src/routes/sso.ts` — a directory that does
15
+ not exist and a file that does not exist — and with issue descriptions the tests
16
+ do not cover. `saml-validator.test.ts` exercises the *valid* signed-response
17
+ path; it does not test a missing audience or issuer requirement.
18
+ `sso-endpoint.test.ts` tests `isPrivateAddress`, a guard on operator-supplied
19
+ endpoint addresses; it does not test an unregistered host alias. Neither had an
20
+ evidenced defect behind it, so neither was a finding. Both are now recorded
21
+ under `withdrawn` with the reason, and their suites under a new `coverage`
22
+ section — a suite that asserts a property is coverage, not a vulnerability.
23
+ - **The registry validator never checked the `fix` field**, which is how the two
24
+ above passed. It verified that the named *test* existed and that the *test* had
25
+ a test in it; nothing confirmed the entry's claim about where the fix lives. It
26
+ now resolves the fix site against the repository. Four entries named paths that
27
+ do not exist; two were the invented ones, and the other two named
28
+ `src/services/saml/*` for SAML logic that lives in `src/routes/saml.ts`. All
29
+ four corrected.
30
+ - **Contiguity was the wrong rule for ids.** Renumbering after a withdrawal would
31
+ change every id other documents already cite, and a registry whose ids shift is
32
+ one nobody can reference. Ids may now gap, and a gap must be explained by a
33
+ withdrawal carrying a reason. Set-based, not positional, so withdrawing one id
34
+ does not invalidate the rest of the tail.
35
+
36
+ ### Added
37
+
38
+ - `docs/RE-AUDIT.md` — the v3.0.0 re-audit matrix, **generated and verified**
39
+ rather than written. Every cell is checked against the repository when the file
40
+ is produced: `Fixed` only if the fix site exists, `Regression Test` only if the
41
+ named file exists *and contains a test*. Deleting a test turns the cell red on
42
+ the next run instead of leaving a stale assurance in a release document.
43
+ - `scripts/render-reaudit-matrix.mjs`, wired into `npm run reaudit:check`, the
44
+ test suite, and the release gate. `npm run reaudit:render` regenerates it.
45
+ - `coverage` and `withdrawn` sections in the registry, so a suite with no finding
46
+ behind it is recorded honestly and a removed finding is explained.
47
+
48
+ ### Verified
49
+
50
+ - **Multi-tenant isolation, re-audited.** Every organization-scoped admin route
51
+ was checked for a membership guard in the requested organization rather than
52
+ the caller's own. `requireOrganizationRole` resolves `orgId` from
53
+ `request.params.id` and checks membership in *that* organization, so the pattern
54
+ is sound. Routes using only `app.authenticate` were traced into the
55
+ application layer: `GET /organizations/:id` calls `getOrganization`, which
56
+ enforces `requireOrganizationPermission` before returning. SAML and OIDC
57
+ connection routes use org-scoped repository methods (`listByOrgId`,
58
+ `findByIdAndOrgId`) rather than bare id lookups. No cross-tenant path found.
59
+
60
+ ### Gate results
61
+
62
+ | Gate | Result |
63
+ | --- | --- |
64
+ | `npm run lint` | 0 warnings, 0 errors |
65
+ | `npm run typecheck` | pass |
66
+ | `npm run registry:check` | 44 entries, 18 suites, 12 of 12 attack classes |
67
+ | `npm run reaudit:check` | 18 plan findings, every claim verified |
68
+ | `npm test` | 450 pass, 1 skipped, 0 fail |
69
+ | `npm run test:security` | 402/402 |
70
+
71
+ ## [2.9.0] - 2026-09-27
72
+
73
+ ### Security
74
+
75
+ - **The security regression registry is now machine-enforced.** All 46 findings
76
+ from the hardening programme are recorded in `docs/security/registry.json` with
77
+ the issue, the fix, the test that fails without it, the documentation and the
78
+ release. `npm run registry:check` fails when an entry names a test that does not
79
+ exist, when a security suite is claimed by no entry, or when a mandatory attack
80
+ class is uncovered. The registry is generated into
81
+ `docs/security/registry.md` so the prose cannot drift from the data.
82
+
83
+ This matters because a registry that is allowed to become false is worse than no
84
+ registry: it converts "I don't know whether this is covered" into "yes,
85
+ covered". Four of the 44 entries exist because an event, a test or a rule was
86
+ present but never actually exercised.
87
+
88
+ - **48 security tests were not running, and the run reported success.**
89
+ `node --test` expands `**` as a single directory level rather than as globstar,
90
+ so the discovery patterns stopped matching as soon as the security suites gained
91
+ a directory level. The entire authorization suite dropped out; everything that
92
+ remained passed, so the job went green. There is now one pattern per directory
93
+ depth, spelled out, with no overlap between them.
94
+
95
+ - **A deleted security test would have kept running.** `tsc` does not remove
96
+ output for sources that are renamed or deleted, so a moved suite ran twice under
97
+ two paths and a deleted suite continued to pass in CI. The build now cleans
98
+ `dist` first.
99
+
100
+ - **Secret scanning added over the full history.** Gitleaks, on push and pull
101
+ request, scanning every commit rather than the tip. The repository history is
102
+ clean — no npm token, no signing key, no private key. A deliberately planted
103
+ private key under `src/tests/` is still caught, so the test-fixture allowlist
104
+ does not become a hole.
105
+
106
+ - **CodeQL added** for JavaScript/TypeScript and Actions, on push, pull request
107
+ and weekly, failing on `error` severity.
108
+
109
+ - **8 project-specific Semgrep rules**, each mapped to a registry entry. They
110
+ encode defects this codebase actually shipped, including two that are ordering
111
+ and completeness problems no general rule can see: `requireHumanPrincipal`
112
+ placed before `app.authenticate` sees no service account and permits everything,
113
+ and a secret-denylist where an allowlist is the only correct shape. Each rule
114
+ was verified to fire on a deliberately vulnerable fixture and to stay silent on
115
+ the real backend.
116
+
117
+ ### Added
118
+
119
+ - `docs/security/registry.json` — 44 findings, machine-readable and enforced.
120
+ - `docs/security/registry.md` — generated from the above.
121
+ - `docs/security/registry-exceptions.md` — the only place a release gate may be
122
+ waived, and an entry without an expiry does not count.
123
+ - `docs/security/{rate-limiting,scopes,configuration,audit,supply-chain}.md`.
124
+ - `scripts/verify-security-registry.mjs` and `scripts/render-security-registry.mjs`.
125
+ - `src/tests/helpers/paths.ts` — resolves paths from the nearest `package.json`,
126
+ so a suite can be moved without its paths silently breaking.
127
+ - `src/tests/security/registry.test.ts` — the registry check runs as part of
128
+ `npm test`, not only at release time.
129
+ - `src/tests/security/authentication/login-abuse.test.ts` — 7 tests for 2.8.0
130
+ behaviour that shipped untested.
131
+ - `src/tests/security/audit-export.test.ts` — 5 tests for the CSV export.
132
+ - `src/tests/security/service-accounts/audit-attribution.test.ts` — 5 tests for
133
+ audit attribution of a machine principal.
134
+ - `.github/workflows/{codeql,sast}.yml`, `.semgrep.yml`, `.gitleaks.toml`.
135
+ - 7 release-gate steps in `release.yml`, replacing a single audit call.
136
+
137
+ ### Fixed
138
+
139
+ - `mfa.test.ts` now connects Redis, so it exercises the rate limiter rather than
140
+ passing because the limiter failed open. (Shipped in 2.8.0; the connection is
141
+ what makes the suite meaningful.)
142
+
143
+ ### Testing
144
+
145
+ `npm test` and `npm run test:security` are unchanged in count where the change was
146
+ organisational, which is the point: 430 tests before the restructure, 430 after,
147
+ 381 security tests before, 381 after. The 7 new authentication tests are on top.
148
+
149
+ ### Fixed
150
+
151
+ - **The audit log export did not neutralise spreadsheet formula injection.** The
152
+ CSV export quoted a value containing a delimiter or a quote, but a value whose
153
+ first character is `=`, `+`, `-` or `@` is evaluated as a formula by Excel,
154
+ LibreOffice and Google Sheets when the file is opened. Several exported columns
155
+ are attacker-supplied — the user agent above all — and an audit export is
156
+ precisely the file an operator opens in a spreadsheet, so that is the expected
157
+ consumer rather than an edge case. A `User-Agent` of `=cmd|'/c calc'!A1`
158
+ reached the export intact. A leading apostrophe is now applied before quoting,
159
+ and a value with no formula prefix is left untouched. (SEC-045)
160
+
161
+ It came out of triaging Semgrep's advisory findings. The rule that pointed at
162
+ the code, `direct-response-write`, is a false positive — the content type is set
163
+ explicitly and every field is escaped — but the code it flagged was not sound.
164
+ - **Every service-account request produced no audit record at all.** A machine
165
+ principal carries a sentinel id of `sa:<uuid>` so that routes expecting
166
+ `request.user` keep working without a matching user row. The audit subscriber
167
+ passed that sentinel into `audit_log.user_id`, which is a uuid column. Postgres
168
+ rejected the insert, the subscriber's `catch` logged `failed to write event`, and
169
+ the record was lost. The request succeeded, so nothing failed visibly, and a
170
+ missing audit record is indistinguishable from a request that never happened.
171
+
172
+ So every request authenticated by an API key or an mTLS service account left no
173
+ audit trail. The privileged, non-human path was the one that was invisible,
174
+ which is the wrong direction for that gap to point. The sentinel is now stripped,
175
+ `user_id` is left null, and the service account is recorded in
176
+ `metadata.serviceAccountId`. (SEC-046)
177
+
178
+ It surfaced in CI and not locally: a new test's fixture passed on this machine
179
+ and failed in CI, and the reason was visible in the log above the failure.
180
+
181
+ ### Fixed
182
+
183
+ - **The published package could not be imported.** `dist/index.js` and
184
+ `dist/index.d.ts` shipped with no `main` and no `types`, so
185
+ `import "@hilbras/keystone"` did not resolve. The `bin` worked, so the CLI was
186
+ usable and the library surface was not — and nothing failed, which is why it
187
+ went unnoticed. `main` and `types` are now declared. Deliberately *not* `exports`:
188
+ that would be the more complete fix but is a breaking change for anyone
189
+ deep-importing `dist/` paths, and 2.6.0 is already published.
190
+ - **The migration guides did not ship.** `docs/` was never in `files`, so the
191
+ instructions for the breaking changes in 2.4.0, 2.6.0 and 2.7.0 were reachable
192
+ only on GitHub. Someone upgrading via npm received the changelog but not the
193
+ document it referred to.
194
+ - **`npm run verify:release` had a gap that allowed both.** It checked version,
195
+ license and repository, and a package with no entry point and no documentation
196
+ passed. It now also requires `main`/`types` to exist on disk, requires the
197
+ migration docs in `files`, requires `dist/tests` to stay excluded, and refuses
198
+ to publish credential material. Verified by reverting: each of the three
199
+ defects is caught with a message naming the problem.
200
+
201
+ ### Known limitations
202
+
203
+ - The Semgrep scan covers the backend. Semgrep's TypeScript support fails on a
204
+ `.tsx` file in the frontend dashboard (TSX generics versus JSX ambiguity) and
205
+ aborts the whole scan rather than skipping one file, so the frontend is not
206
+ scanned. This is a tool limitation, recorded rather than papered over.
207
+ - The `keystone-cookie-without-secure` rule stays silent when a cookie's options
208
+ are spread from another variable, because the rule cannot substantiate a finding
209
+ there. `auth.ts` builds its options in a helper and spreads them.
210
+ - The Semgrep community rulesets (`p/default`, `p/security-audit`,
211
+ `p/owasp-top-ten`) run **advisory**, not blocking. Their 15 findings against
212
+ `src/` have been triaged: four are `escapeXml` output the rule cannot see
213
+ through, six are `console.*` log-forging at worst, four are AES-GCM where Node
214
+ enforces the tag length through `setAuthTag`, and one was the `direct-response-write`
215
+ false positive that led to SEC-045. Gating on a community ruleset nobody has
216
+ worked through means either a permanently red build or a gate that gets switched
217
+ off, so they report and the triage is recorded here instead. The project ruleset
218
+ in `.semgrep.yml` is the blocking gate.
219
+ - Two suites span two domains rather than being split: `proxy/trust-boundary.test.ts`
220
+ also covers mTLS certificate binding, and `oauth/oauth2-hardening.test.ts` also
221
+ covers OIDC ID token verification. Splitting them is mechanical but every split
222
+ copies the whole import header into each partition, and the resulting churn
223
+ risks removing a live import. The registry records the mapping instead.
224
+
225
+ ## [2.8.0] - 2026-09-27
226
+
227
+ ### Security
228
+
229
+ - **A Redis outage removed rate limiting entirely.** Every limiter checked
230
+ `isRedisReady()` and returned `true` when Redis was down. During an outage
231
+ `login`, `mfa/verify`, `sms-otp/verify` and the OAuth token exchange had no limit
232
+ at all — and an outage is exactly when unlimited attempts are worth having,
233
+ because it is the moment an attacker cannot be traced to a single event stream.
234
+ Sensitive endpoints now fall back to a bounded in-process budget. The fallback
235
+ is strictly weaker: a client gets one budget per instance. That is a
236
+ degradation worth having; unbounded is not. The store is capped, because an
237
+ unbounded map keyed by client address is itself a denial-of-service vector.
238
+ - **MFA verification shared one budget across all users behind an address.** The
239
+ key was `mfa-verify:<address>:<body.email>`, and that endpoint does not carry
240
+ an email, so every second-factor verification from one address drew on the same
241
+ budget of 20. An attacker got 20 guesses; so did an office behind a single NAT,
242
+ where one busy office could lock out every legitimate second-factor login. The
243
+ key now includes the challenge, which identifies one login attempt, giving an
244
+ attacker 20 guesses at the code they are actually attacking without spending
245
+ anyone else's budget.
246
+ - **Second-factor management shared one budget per address.** The TOTP routes
247
+ allowed 10 attempts keyed on the address alone, with the same consequence.
248
+ Brute-forcing a TOTP code is per-account, since the code is checked against one
249
+ user's secret, so the budget is now keyed on the user.
250
+ - **Credential spraying was unbounded.** The login budget was keyed on address
251
+ *and* submitted address, so it stopped repeated guesses at one account and did
252
+ nothing about an attacker who varied the address on every request and guessed
253
+ across a thousand accounts from one host. A second, address-keyed budget bounds
254
+ that independently.
255
+ - **A refused request left no record.** A rate-limit trip produced a `429` and
256
+ nothing else, so sustained guessing at `login` or `mfa/verify` was invisible
257
+ except in aggregate. `rate_limit_triggered` now records the endpoint, the client
258
+ address, and **which limiter decided** — a degraded in-process control is a
259
+ different operational situation from a healthy distributed one, and conflating
260
+ them would hide it.
261
+ - **Failed logins were never audited.** `user_login_failed` existed in the event
262
+ vocabulary and was never emitted, on either `/login` or `/token-login`.
263
+ - **A replayed refresh token was indistinguishable from an unknown one.** It is now
264
+ detected, emits `refresh_token_replayed`, and revokes the account's remaining
265
+ credentials — a replay means the token is known to somebody else, so answering
266
+ only that one request leaves the rest of what it could mint intact.
267
+ - **API key creation had no rate limit.** Minting a credential is an
268
+ authentication event and is now bounded.
269
+
270
+ ### Already sound, verified rather than assumed
271
+
272
+ `X-Forwarded-For` handling, the trusted-proxy model, and the address-based rate
273
+ limit keys were delivered in v2.0.0. Item 3 of this phase is therefore
274
+ verification rather than new work: a spoofed header from an untrusted peer, a
275
+ multi-entry header, `x-real-ip`, `Forwarded`, IPv4, IPv6, and both spellings of
276
+ IPv4-mapped IPv6 are now covered by tests.
277
+
278
+ ### Added
279
+
280
+ - `src/services/localRateLimit.ts` — the in-process fallback, bounded and swept.
281
+ - `refresh_token_state` inspection, distinguishing a spent token from an unknown
282
+ one.
283
+ - 16 tests: the emergency limiter's accounting, bounding and eviction behaviour;
284
+ proxy spoofing across IPv4, IPv6, mapped IPv6, and multi-entry headers; an
285
+ enumeration check that every sensitive limiter carries the emergency flag,
286
+ including the ones built by a factory; and the abuse event payloads.
287
+
288
+ ### A test suite that was not testing what it appeared to
289
+
290
+ `mfa.test.ts` never connected Redis. The shared client is created with
291
+ `lazyConnect`, so every rate limit in that suite was evaluated against a limiter
292
+ that was not running, and the suite passed **only because the limiter failed
293
+ open** — the behaviour this phase removes. It now connects Redis explicitly, and
294
+ surfaced two real keying defects that had been hidden by fail-open. Fixing those
295
+ took the suite from 12 failures to 55/55.
296
+
297
+ ## [2.7.0] - 2026-09-27
298
+
299
+ ### Security
300
+
301
+ - **The admin configuration endpoint leaked secrets it did not recognise.**
302
+ Redaction was a denylist: a set of known-sensitive names plus a regex. Run
303
+ against 24 secret-looking key names it missed 12, among them `SIGNING_KEY`,
304
+ `JWT_SIGNING_KEY`, `SENDGRID_KEY`, `PROVIDER_APIKEY`, `SAML_CERT`, `TLS_KEY`,
305
+ `CERT_PRIVATE`, `HMAC_KEY`, `KMS_KEY` and `DB_URL`. The endpoint returned their
306
+ values in the clear to an owner-authenticated caller. A denylist is a losing
307
+ game here: the next person to add a secret-bearing variable leaks it and
308
+ nothing fails. Redaction is now an **allowlist**, so a key is private until
309
+ someone deliberately decides otherwise.
310
+ - **CORS allowed every origin when `ALLOWED_ORIGINS` was empty.** The origin
311
+ callback returned true for an empty allowlist, so an unset variable was
312
+ equivalent to "permit every origin" on a server that sends credentialed
313
+ cookies. It now fails closed and logs a warning at boot, so a misconfiguration
314
+ is visible before a browser is turned away rather than after.
315
+ - **The setup server reflected any origin with credentials.** It creates the owner
316
+ account and writes configuration, and was registered with `origin: true`. Any
317
+ page a browser visited could attempt a credentialed request against the
318
+ bootstrap surface. Origins must now be listed, defaulting to its own loopback
319
+ addresses.
320
+ - **The setup token was written to stdout in cleartext.** It appeared in
321
+ container logs, in journald, and in whatever ships logs off the host, where it
322
+ remains readable long after the bootstrap it was for. It is a full
323
+ account-initialisation credential. It is now printed only on an explicit
324
+ `KEYSTONE_PRINT_SETUP_TOKEN=true`, and never in production. The rejection path
325
+ also no longer logs the presented and expected token lengths, which disclosed
326
+ the length of the expected token.
327
+ - **Webhook signing secrets were stored in plaintext.** A database dump yielded a
328
+ working signing key for every endpoint, letting an attacker forge deliveries
329
+ that the receiving service would accept as genuine. They are now encrypted with
330
+ AES-256-GCM under the existing key. **Encrypted rather than hashed**, because
331
+ Keystone signs outbound payloads with the secret and therefore has to be able
332
+ to recover it; hashing would make signing impossible. Rows written before this
333
+ change are read unchanged, and re-saving or rotating an endpoint upgrades them.
334
+ - **Session cookies were not `Secure` by default in production.** The default was
335
+ `false`, so an operator who did not set `COOKIE_SECURE` received cookies that
336
+ would be sent over plain HTTP. Production now defaults to `true`; development
337
+ still defaults to `false` and either can be set explicitly.
338
+ - **The setup server bound to all interfaces.** It inherited `HOST`, which
339
+ defaults to `0.0.0.0` — correct for the main server and wrong for the one that
340
+ creates the owner account. It now defaults to loopback, honours a private
341
+ interface, and warns if explicitly told to bind to everything.
342
+
343
+ ### Changed
344
+
345
+ - CORS policy extracted to `isOriginAllowed` in `src/services/trustedProxies.ts`,
346
+ shared by the main and setup servers.
347
+ - `EXPOSABLE_CONFIG_KEYS` is the allowlist. `isSensitiveConfigurationKey` is
348
+ retained for the write path, where a client may legitimately send a value that
349
+ must be recognised as "preserve this, do not overwrite it".
350
+
351
+ ### Added
352
+
353
+ - 27 tests: configuration redaction against the 12 previously-leaked names, the
354
+ setup token's logging behaviour in all three modes, webhook secret encryption
355
+ including the legacy plaintext read path and signature stability, the CORS
356
+ policy, and the production deployment defaults.
357
+
358
+ ## [2.6.0] - 2026-09-27
359
+
360
+ ### Security
361
+
362
+ - **The API key scope guard had a bypass by construction.** It read
363
+ `scopes.includes(scope) || scopes.includes("service_account")`, so a key whose
364
+ scope list contained the literal string `"service_account"` satisfied *every*
365
+ scope requirement. That string was client-suppliable: `POST /api-keys` stored
366
+ whatever `scopes` it was given, with no validation against any list.
367
+ - **The same guard also failed open.** It returned early whenever
368
+ `apiKeyScopes` was absent, which is indistinguishable from "this is a session".
369
+ A key that resolved without a scope list therefore skipped the check entirely.
370
+ - **The guard was never referenced.** `requireScopes` was defined and decorated
371
+ onto the Fastify instance, but no route in the repository used it. Scopes were
372
+ stored, returned to callers, and enforced nowhere.
373
+
374
+ ### How exploitable this actually was
375
+
376
+ Stated precisely, because it matters for prioritising: `app.authenticate` is
377
+ JWT-only and returns 401 for anything that is not a valid access token.
378
+ `authenticateOrApiKey` is the handler with the API key path, and before this
379
+ release exactly one route used it — `GET /auth/validate`. A leaked API key
380
+ therefore reached one endpoint, which returns the caller's own public profile.
381
+
382
+ So the exposure was a credential whose stated limits were fiction, on a
383
+ credential that could be used almost nowhere. That is a real defect and worth
384
+ fixing, but it is not an authentication bypass, and describing it as one would
385
+ mislead anyone deciding what to do first.
386
+
387
+ ### Changed
388
+
389
+ - `src/services/scopes.ts` — a scope registry: the canonical names, their
390
+ descriptions, per-principal defaults, validation, and the allow-list grant
391
+ check. A scope that is not defined cannot be granted.
392
+ - Unknown or forbidden scopes are refused at key creation with a `400` naming
393
+ what was rejected and what is allowed, instead of being stored verbatim.
394
+ - `requireScopes` now fails closed, keyed off a new `request.apiKeyId` that is
395
+ set only when a machine credential authenticated the request. A session is
396
+ still exempt, since it carries a person's authority and is governed by the
397
+ permission system.
398
+ - Applied to the routes where a credential's limits matter most: API key
399
+ creation, listing and revocation, session listing and revocation, and profile
400
+ read and write.
401
+ - `profile:read`, `profile:write`, and `mfa:manage` are human-only. A service
402
+ account's profile is a synthesized object with an id of `sa:<uuid>` that
403
+ matches no user row, so the scope is meaningless for a machine and misleading
404
+ in an audit log.
405
+ - A service account's default grant is now `organizations:read` only. A personal
406
+ key's default is read-only on the caller's own resources; the previous
407
+ `api:read` default was not in any registry, which is a fair indication that
408
+ nothing was checking it.
409
+
410
+ ### Added
411
+
412
+ - `src/plugins/machinePrincipal.ts` — `requireHumanPrincipal`, refusing a service
413
+ account on TOTP, WebAuthn, SMS OTP, identity linking, OAuth consent, and
414
+ userinfo routes with an explicit `403` and an audit record. This is a backstop
415
+ rather than a fix for a live hole: those routes are JWT-only today, so a
416
+ machine credential is refused with a 401 before the guard is reached. It exists
417
+ so that switching a route to `authenticateOrApiKey` does not silently make a
418
+ machine principal acceptable somewhere a person was assumed.
419
+ - 25 tests covering the registry, validation, intersection, the grant check, the
420
+ fail-closed behaviour, HTTP enforcement on the one key-reachable route, and
421
+ the machine-principal boundary.
422
+
423
+ ### Fixed
424
+
425
+ - Scope enforcement is keyed on `apiKeyId` rather than the presence of a scope
426
+ list, closing the fail-open path.
427
+ - The `service_account` wildcard no longer grants anything.
428
+ - Scope ordering is normalised, so two equivalent requests produce identical
429
+ rows.
430
+
8
431
  ## [2.5.0] - 2026-09-27
9
432
 
10
433
  ### Security
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Hilbras Keystone
2
2
 
3
- **Current version: `2.5.0`**
3
+ **Current version: `2.9.0`**
4
4
 
5
5
  > A provider-agnostic, API-first identity platform for Hilbras products and third-party applications.
6
6
 
@@ -22,6 +22,90 @@ Keystone is a **standalone identity platform**, not a wrapper around another ide
22
22
 
23
23
  ---
24
24
 
25
+ ## Using the published package
26
+
27
+ ```bash
28
+ npm install @hilbras/keystone
29
+ ```
30
+
31
+ ```ts
32
+ import { buildApp } from "@hilbras/keystone";
33
+
34
+ const app = await buildApp();
35
+ await app.listen({ port: 3000 });
36
+ // Close it when done: importing the package opens the database pool.
37
+ await app.close();
38
+ ```
39
+
40
+ Or run the server directly with `npx keystone serve`.
41
+
42
+ The migration guides and security documentation are included in the package, so
43
+ they are available without a network round trip to the repository.
44
+
45
+ ## What's new in v3.0.0
46
+
47
+ - **The re-audit matrix is generated, not written.** `docs/RE-AUDIT.md` covers all 18 findings the plan names. Every cell is verified against the repository when the file is produced: `Fixed` only if the fix site exists, `Regression test` only if the named file exists *and* contains a test. Deleting a test turns the cell red on the next run rather than leaving a stale assurance in a release document. **`npm run reaudit:check` fails the release gate if any claim cannot be verified.**
48
+ - **Zero unresolved Critical findings**, and that is checked rather than asserted.
49
+ - **Two registry entries withdrawn.** I added `SEC-043` and `SEC-044` in 2.9.0 with fixes at paths that do not exist and issue descriptions the tests do not cover — they were not findings. They are now recorded as withdrawn with the reason, and their suites as coverage.
50
+ - **The registry validator now checks the `fix` field**, which it never did. It verified the named *test* existed and contained a test; nothing confirmed the claim about where the fix lives. That is how two invented entries passed. Four entries named paths that do not exist; all corrected.
51
+ - **Multi-tenant isolation re-audited** across every organization-scoped admin route. No cross-tenant path found — see the CHANGELOG for the specific traces.
52
+
53
+ ## What's new in v2.9.0
54
+
55
+ - **The published package is importable.** It shipped `dist/index.js` and `dist/index.d.ts` with **no `main` and no `types`**, so `import "@hilbras/keystone"` did not resolve for anyone installing from npm. The `bin` worked, so the CLI was usable and the library surface was not — nothing failed, the package simply could not be imported.
56
+ - **The migration guides now ship.** `docs/` was never in the tarball, so the instructions for the breaking changes in 2.4.0, 2.6.0 and 2.7.0 were reachable only on GitHub. Someone upgrading via npm got the changelog but not what it referred to.
57
+ - **`npm run verify:release` now checks both.** It verified version, license and repository, and let a package with no entry point and no documentation pass. It now also requires `main`/`types` to exist, requires the migration docs to be in `files`, and refuses to ship credential material. Verified by reverting: all three defects are caught.
58
+ - **A permanent regression registry for every finding.** `docs/security/registry.json` records all **46** vulnerabilities found across the hardening programme — the issue, the fix, the test that fails without it, the documentation, and the release. It is machine-readable, so `npm run registry:check` **fails** if an entry names a test that does not exist, if a security suite is claimed by no entry, or if a mandatory attack class is uncovered. A registry that can quietly become false is worse than none.
59
+ - **A security test suite per domain.** Tests moved from 14 flat files into 16 suites grouped by area — authentication, authorization, mfa, oauth, oidc, saml, scim, mtls, sessions, tokens, api-keys, configuration, proxy, rate-limiting. Verified lossless: 381 security tests before and after.
60
+ - **Two test harnesses that were reporting on less than the repository contained.**
61
+ - **`tsc` never cleaned `dist`.** Output for a renamed or deleted source file survived, so a moved suite ran twice and a *deleted* suite kept running. Test discovery did not reflect the source tree.
62
+ - **`node --test` expands `**` as a single directory level, not globstar.** When the suites gained a directory level, the discovery patterns stopped matching — **48 security tests, the entire authorization suite, silently stopped running, and the run still reported success** because everything that remained passed. A green run was reporting on less than the repository contained. One pattern per depth now, with no overlap.
63
+ - **A stale fixture path that was correct at only one directory depth.** A suite reached its fixture by counting parent directories, which resolved from `src` and not from `dist`. Paths are now anchored on the nearest `package.json`.
64
+ - **CI now runs CodeQL, Semgrep and Gitleaks.** CodeQL on push, pull request and weekly. Gitleaks over the **full history** — verified clean, and verified to still catch a planted private key under `src/tests/`.
65
+ - **8 project-specific Semgrep rules**, each mapped to a registry entry. They encode what actually went wrong *here*, which no general ruleset can know — including the ordering trap that silently disabled `requireHumanPrincipal` (a guard placed before `app.authenticate` sees nothing and permits everything). Verified in both directions: **8 of 8 fire** on a deliberately vulnerable fixture, **0 findings** on the real backend.
66
+ - **The release gate is now explicit.** A release fails on a critical or high advisory without a documented, time-bounded exception; on secret scanning; on a registry that does not validate; or on any of lint, typecheck, build, tests, security tests and the audit.
67
+ - **A failed login is audited on both login routes**, and **a replayed refresh token is detected** and revokes the account's remaining credentials — while an unknown token revokes nothing. Both shipped in 2.8.0 with no test.
68
+ - **The audit log export no longer evaluates as a spreadsheet formula.** It quoted values containing a delimiter, but a value beginning with `=`, `+`, `-` or `@` is evaluated as a formula when the file is opened — and the exported user agent is attacker-supplied. An audit export is exactly the file an operator opens in a spreadsheet. Found while triaging Semgrep's advisory findings; the rule that pointed at it was a false positive, but the code was not.
69
+ - **Service-account requests are no longer invisible in the audit log.** A machine principal carries a sentinel id of `sa:<uuid>`, which the audit subscriber was writing into a **uuid** column. Postgres rejected the insert, the subscriber logged a failure, and the record was lost — so **every request authenticated by an API key or an mTLS service account left no audit trail at all.** The request succeeded, so nothing failed visibly, and a missing record looks exactly like a request that never happened. The privileged machine path was the one that left no trace. (SEC-046)
70
+ - **17 new tests** covering the above, each verified by reverting the fix.
71
+
72
+ ## What's new in v2.8.0
73
+
74
+ - **A Redis outage no longer removes rate limiting.** When Redis was unavailable every limiter returned "allowed" — so during an outage, `login`, `mfa/verify`, `sms-otp/verify`, and the OAuth token exchange had **no limit at all**. An outage is precisely when unlimited attempts are worth having. Sensitive endpoints now fall back to a bounded in-process budget.
75
+ - **MFA verification is limited per login attempt, not per address.** The budget key included the submitted email, which that endpoint does not carry, so *every* second-factor verification from one address shared a single budget of 20. An attacker got 20 guesses, but so did an office behind one NAT — one busy office could lock out every legitimate MFA login. The key now includes the challenge.
76
+ - **Second-factor management is limited per user, not per address.** Same problem on the TOTP routes: 10 attempts shared across everyone behind an address. Brute-forcing a code is per-account, so a per-user budget is the right unit.
77
+ - **Credential spraying is capped.** The login budget was keyed on address *and* submitted address, so it stopped repeated guesses at one account but did nothing against an attacker varying the address across a thousand accounts from one host. A second, address-keyed budget bounds that.
78
+ - **A refused request is now recorded.** A rate-limit trip previously left no trace — a 429 and nothing else — so sustained guessing at `login` or `mfa/verify` was invisible except in aggregate. `rate_limit_triggered` records the endpoint, the client address, and **which limiter decided**, so a degraded local control is distinguishable from a healthy distributed one.
79
+ - **Failed logins are audited.** `user_login_failed` existed in the event vocabulary and was never emitted, so password guessing left no record. Now emitted for both `/login` and `/token-login`, without a user id, since the submitted address may match no account.
80
+ - **A replayed refresh token is detected and answered.** A second presentation of a consumed refresh token was indistinguishable from an unknown one. It now emits `refresh_token_replayed` and revokes the account's remaining credentials, because a replay means the token leaked.
81
+ - **API key creation is rate limited** like any other authentication event.
82
+ - **16 tests** covering the emergency limiter, proxy spoofing, and the abuse events.
83
+
84
+ ## What's new in v2.7.0
85
+
86
+ > **Behavioural.** CORS now fails closed: with no `ALLOWED_ORIGINS` configured, browser origins are **refused** in production rather than allowed. Session cookies also default to `Secure` in production. If you relied on either default, set them explicitly before upgrading.
87
+
88
+ - **The admin config endpoint no longer leaks secrets** — redaction was a *denylist*, and it missed 12 of 24 secret-looking keys, including `SIGNING_KEY`, `JWT_SIGNING_KEY`, `SENDGRID_KEY`, `SAML_CERT`, `HMAC_KEY`, `KMS_KEY` and `DB_URL`. It is now an allowlist, so a key nobody has thought about is private by default rather than public.
89
+ - **CORS fails closed in production** — an empty `ALLOWED_ORIGINS` previously returned "allow", making an unset variable equivalent to permitting every origin on a server that sends credentialed cookies. It now refuses, and logs a warning at boot so a misconfiguration is visible before a browser is turned away.
90
+ - **The setup server no longer reflects any origin** — it creates the owner account and writes configuration, and was registered with `origin: true` plus credentials. Origins must now be listed, defaulting to its own loopback addresses.
91
+ - **The setup token is no longer printed to stdout** — it landed in container logs, journald, and whatever ships logs off the host, permanently, and is a full account-initialisation credential. It is now printed only on explicit `KEYSTONE_PRINT_SETUP_TOKEN=true`, and never in production.
92
+ - **Webhook signing secrets are encrypted at rest** — stored in plaintext, a database dump yielded a working signing key for every endpoint, letting an attacker forge deliveries the receiver would accept. Encrypted rather than hashed, because Keystone *signs* with the secret and so must be able to recover it. Existing plaintext rows keep working and upgrade on rotation.
93
+ - **Session cookies are `Secure` by default in production** — the default was `false`, so an operator who did not set it got cookies that would be sent over plain HTTP.
94
+ - **The setup server binds to loopback by default** — it inherited `0.0.0.0` from the main server, which is right for the main server and wrong for the one that creates the owner account.
95
+
96
+ ## What's new in v2.6.0
97
+
98
+ - **API key scopes are now a real registry** — a single list of scope names with descriptions. A scope not in the registry cannot be granted, so there is no string a caller can invent, and a route that needs a scope names it from the list so enforcement cannot quietly drift out of date again.
99
+ - **Unknown scopes are refused, not dropped** — key creation previously stored whatever strings it was given. Silently discarding an unrecognised one hides a typo and leaves the caller believing they hold something they do not, so it now returns `400` listing what was rejected and what is allowed.
100
+ - **The `service_account` wildcard is gone** — the scope guard treated a key as holding *every* scope if its scope list merely contained the string `"service_account"`, and that string was client-suppliable at key creation. It is no longer a scope, and a key holding only it satisfies nothing.
101
+ - **The scope guard fails closed** — it previously returned early whenever `apiKeyScopes` was absent, which is indistinguishable from "this is a session", so a key that resolved without a scope list skipped the check entirely. It now keys off `apiKeyId`, which is set only when a machine credential authenticated.
102
+ - **Scopes are enforced** on key, session, and profile routes, so a key is limited to the operations its grant covers.
103
+ - **Profile and MFA scopes cannot be granted to a service account** — a machine's "profile" is a synthesized object with an id of `sa:<uuid>` that matches no user row, and it has no authenticator to enrol a second factor with.
104
+ - **A stated boundary for machine principals** — `requireHumanPrincipal` refuses a service account on TOTP, WebAuthn, SMS OTP, identity linking, consent, and userinfo routes, with an explicit `403` and an audit record, rather than relying on the synthetic principal happening to match no row.
105
+ - **Personal keys default to read-only** on the caller's own resources. The previous default, `api:read`, was not in any registry — a fair sign that nothing was checking it.
106
+
107
+ > **Note on reachability.** `app.authenticate` is JWT-only, so almost every route still refuses an API key outright. `GET /auth/validate` is the one route that accepts one, and it is where scope enforcement is observable end to end. What this release fixes is the enforcement machinery, so the next route to adopt key authentication inherits a real check.
108
+
25
109
  ## What's new in v2.5.0
26
110
 
27
111
  - **The OIDC nonce now reaches the Google connector** — `GoogleConnector.exchangeCode` overrode the base method without forwarding its options, so the nonce added in 2.4.0 was silently discarded for the default provider. Every non-Google OIDC provider validated the nonce; Google, the most likely to be in use, did not.
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AA6DA,eAAO,MAAM,MAAM;aACjB,QAAQ;aACR,IAAI;aACJ,IAAI;aAEJ,YAAY;aACZ,SAAS;aAGT,cAAc;aACd,cAAc;aACd,kBAAkB;aAGlB,yBAAyB;aACzB,6BAA6B;aAC7B,mBAAmB;aAGnB,iBAAiB;aACjB,qBAAqB;aAGrB,qBAAqB;aACrB,qBAAqB;aAErB,WAAW;aACX,aAAa;aACb,aAAa;aACb,gBAAgB,EAAuG,QAAQ,GAAG,KAAK,GAAG,MAAM;aAChJ,2BAA2B;aAE3B,mBAAmB;aACnB,wBAAwB;aACxB,yBAAyB;aAGzB,eAAe;aACf,cAAc;aAGd,uBAAuB;aAGvB,yBAAyB;aAGzB,uBAAuB;aAGvB,gBAAgB;aAGhB,gBAAgB;aAEhB,gBAAgB;aAEhB,gBAAgB;aAEhB,eAAe;aAEf,mBAAmB;aACnB,yBAAyB;aACzB,qBAAqB;aACrB,wBAAwB;aAExB,yBAAyB;aACzB,gCAAgC;aAEhC,kBAAkB;aAIlB,2BAA2B;aAC3B,sBAAsB;aACtB,sBAAsB;aACtB,WAAW;aACX,mBAAmB;aAInB,iBAAiB;aACjB,WAAW;IACX,uDAAuD;aAGvD,2BAA2B;IAC3B,qEAAqE;aACrE,mBAAmB;aACnB,8BAA8B;IAC9B,yFAAyF;aACzF,qBAAqB;aACrB,gCAAgC;IAChC;;;;;;OAMG;aACH,eAAe;aACf,yBAAyB;aACzB,gBAAgB;aAChB,4BAA4B;aAC5B,cAAc;aACd,UAAU;aACV,SAAS;aACT,SAAS;aACT,SAAS;aACT,SAAS;aACT,WAAW;aACX,gBAAgB;aAChB,eAAe;aACf,cAAc;aACd,YAAY;aACZ,kBAAkB;aAClB,iBAAiB;aACjB,kBAAkB;aAClB,4BAA4B;aAC5B,2BAA2B;aAC3B,iBAAiB;aACjB,oBAAoB;aACpB,sBAAsB;CACd,CAAC;AAEX,wBAAgB,cAAc,IAAI,MAAM,CAMvC;AAED,wBAAgB,mBAAmB,IAAI,OAAO,CAE7C"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AA6DA,eAAO,MAAM,MAAM;aACjB,QAAQ;aACR,IAAI;aACJ,IAAI;aAEJ,YAAY;aACZ,SAAS;aAGT,cAAc;aACd,cAAc;aACd,kBAAkB;aAGlB,yBAAyB;aACzB,6BAA6B;aAC7B,mBAAmB;aAGnB,iBAAiB;aACjB,qBAAqB;aAGrB,qBAAqB;aACrB,qBAAqB;aAErB,WAAW;aACX,aAAa;aAMb,aAAa;aAGb,gBAAgB,EAAuG,QAAQ,GAAG,KAAK,GAAG,MAAM;aAChJ,2BAA2B;aAE3B,mBAAmB;aACnB,wBAAwB;aACxB,yBAAyB;aAGzB,eAAe;aACf,cAAc;aAGd,uBAAuB;aAGvB,yBAAyB;aAGzB,uBAAuB;aAGvB,gBAAgB;aAGhB,gBAAgB;aAEhB,gBAAgB;aAEhB,gBAAgB;aAEhB,eAAe;aAEf,mBAAmB;aACnB,yBAAyB;aACzB,qBAAqB;aACrB,wBAAwB;aAExB,yBAAyB;aACzB,gCAAgC;aAEhC,kBAAkB;aAIlB,2BAA2B;aAC3B,sBAAsB;aACtB,sBAAsB;aACtB,WAAW;aACX,mBAAmB;aAInB,iBAAiB;aACjB,WAAW;IACX,uDAAuD;aAGvD,2BAA2B;IAC3B,qEAAqE;aACrE,mBAAmB;aACnB,8BAA8B;IAC9B,yFAAyF;aACzF,qBAAqB;aACrB,gCAAgC;IAChC;;;;;;OAMG;aACH,eAAe;aACf,yBAAyB;aACzB,gBAAgB;aAChB,4BAA4B;aAC5B,cAAc;aACd,UAAU;aACV,SAAS;aACT,SAAS;aACT,SAAS;aACT,SAAS;aACT,WAAW;aACX,gBAAgB;aAChB,eAAe;aACf,cAAc;aACd,YAAY;aACZ,kBAAkB;aAClB,iBAAiB;aACjB,kBAAkB;aAClB,4BAA4B;aAC5B,2BAA2B;aAC3B,iBAAiB;aACjB,oBAAoB;aACpB,sBAAsB;CACd,CAAC;AAEX,wBAAgB,cAAc,IAAI,MAAM,CAMvC;AAED,wBAAgB,mBAAmB,IAAI,OAAO,CAE7C"}
package/dist/config.js CHANGED
@@ -67,7 +67,13 @@ export const config = {
67
67
  ZITADEL_GITHUB_IDP_ID: getEnv("ZITADEL_GITHUB_IDP_ID"),
68
68
  COOKIE_NAME: cookieName,
69
69
  COOKIE_DOMAIN: isHostCookie ? undefined : getEnv("COOKIE_DOMAIN", ".local.hilbras.ai"),
70
- COOKIE_SECURE: isHostCookie || getEnv("COOKIE_SECURE", "false") === "true",
70
+ // Secure by default in production. The previous default was "false", so an
71
+ // operator who did not set it explicitly got session cookies without the
72
+ // Secure attribute, which are then sent over plain HTTP. A __Host- prefixed
73
+ // cookie name implies Secure and still wins; otherwise production defaults to
74
+ // true and development to false, with an explicit override either way.
75
+ COOKIE_SECURE: isHostCookie ||
76
+ getEnv("COOKIE_SECURE", getEnv("NODE_ENV", "development") === "production" ? "true" : "false") === "true",
71
77
  COOKIE_SAME_SITE: getEnv("COOKIE_SAME_SITE", getEnv("NODE_ENV", "development") === "production" ? "strict" : "lax"),
72
78
  ALLOW_PRIVATE_SSO_ENDPOINTS: getEnv("ALLOW_PRIVATE_SSO_ENDPOINTS", "false") === "true",
73
79
  AUTH_API_PUBLIC_URL: getEnv("AUTH_API_PUBLIC_URL"),
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/D,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC;AAC5D,MAAM,CAAC,MAAM,EAAE,CAAC;AAEhB,SAAS,MAAM,CAAC,IAAY,EAAE,QAAQ,GAAG,EAAE;IACzC,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC;AACvC,CAAC;AAED;;;;GAIG;AACH,SAAS,cAAc,CAAC,IAAY,EAAE,QAAgB;IACpD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC;IAC1C,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IAC3B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5C,OAAO,CAAC,IAAI,CACV,YAAY,IAAI,wCAAwC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,YAAY,QAAQ,EAAE,CAClG,CAAC;QACF,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC1B,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,WAAW,CAAC,IAAY,EAAE,QAAgB;IACjD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC;IAC1C,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IAC3B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5C,OAAO,CAAC,IAAI,CACV,YAAY,IAAI,oCAAoC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,YAAY,QAAQ,EAAE,CAC9F,CAAC;QACF,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC1B,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,qBAAqB,CAAC,IAAY;IACzC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,CAAC,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB,KAAK,MAAM,EAAE,CAAC;QACzD,MAAM,IAAI,KAAK,CAAC,0CAA0C,IAAI,EAAE,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,KAAK,IAAI,EAAE,CAAC;AACrB,CAAC;AAED,SAAS,OAAO,CAAC,IAAY;IAC3B,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,OAAO,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,GAAG,MAAM,CACvB,aAAa,EACb,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,KAAK,YAAY,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,kBAAkB,CACpG,CAAC;AACF,MAAM,YAAY,GAAG,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;AAEtD,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,QAAQ,EAAE,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC;IAC3C,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC;IAE/B,YAAY,EAAE,qBAAqB,CAAC,cAAc,CAAC;IACnD,SAAS,EAAE,MAAM,CAAC,WAAW,EAAE,wBAAwB,CAAC;IAExD,wEAAwE;IACxE,cAAc,EAAE,MAAM,CAAC,gBAAgB,CAAC;IACxC,cAAc,EAAE,MAAM,CAAC,gBAAgB,CAAC;IACxC,kBAAkB,EAAE,MAAM,CAAC,oBAAoB,CAAC;IAEhD,6DAA6D;IAC7D,yBAAyB,EAAE,MAAM,CAAC,2BAA2B,CAAC;IAC9D,6BAA6B,EAAE,MAAM,CAAC,+BAA+B,CAAC;IACtE,mBAAmB,EAAE,MAAM,CAAC,qBAAqB,CAAC;IAElD,iEAAiE;IACjE,iBAAiB,EAAE,MAAM,CAAC,mBAAmB,CAAC;IAC9C,qBAAqB,EAAE,MAAM,CAAC,uBAAuB,CAAC;IAEtD,wFAAwF;IACxF,qBAAqB,EAAE,MAAM,CAAC,uBAAuB,CAAC;IACtD,qBAAqB,EAAE,MAAM,CAAC,uBAAuB,CAAC;IAEtD,WAAW,EAAE,UAAU;IACvB,aAAa,EAAE,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,eAAe,EAAE,mBAAmB,CAAC;IACtF,aAAa,EAAE,YAAY,IAAI,MAAM,CAAC,eAAe,EAAE,OAAO,CAAC,KAAK,MAAM;IAC1E,gBAAgB,EAAE,MAAM,CAAC,kBAAkB,EAAE,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,KAAK,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAA8B;IAChJ,2BAA2B,EAAE,MAAM,CAAC,6BAA6B,EAAE,OAAO,CAAC,KAAK,MAAM;IAEtF,mBAAmB,EAAE,MAAM,CAAC,qBAAqB,CAAC;IAClD,wBAAwB,EAAE,MAAM,CAAC,MAAM,CAAC,sBAAsB,EAAE,KAAK,CAAC,CAAC;IACvE,yBAAyB,EAAE,MAAM,CAAC,MAAM,CAAC,uBAAuB,EAAE,QAAQ,CAAC,CAAC;IAE5E,oFAAoF;IACpF,eAAe,EAAE,MAAM,CAAC,iBAAiB,CAAC;IAC1C,cAAc,EAAE,MAAM,CAAC,gBAAgB,CAAC;IAExC,sGAAsG;IACtG,uBAAuB,EAAE,MAAM,CAAC,yBAAyB,CAAC;IAE1D,2DAA2D;IAC3D,yBAAyB,EAAE,MAAM,CAAC,2BAA2B,EAAE,UAAU,CAAC;IAE1E,gHAAgH;IAChH,uBAAuB,EAAE,MAAM,CAAC,yBAAyB,EAAE,YAAY,CAAC;IAExE,sDAAsD;IACtD,gBAAgB,EAAE,MAAM,CAAC,kBAAkB,EAAE,WAAW,CAAC;IAEzD,kEAAkE;IAClE,gBAAgB,EAAE,MAAM,CAAC,kBAAkB,CAAC;IAE5C,gBAAgB,EAAE,MAAM,CAAC,2BAA2B,CAAC,IAAI,MAAM,CAAC,0BAA0B,EAAE,EAAE,CAAC;IAE/F,gBAAgB,EAAE,MAAM,CAAC,2BAA2B,CAAC;IAErD,eAAe,EAAE,OAAO,CAAC,iBAAiB,CAAC;IAE3C,mBAAmB,EAAE,MAAM,CAAC,MAAM,CAAC,qBAAqB,EAAE,GAAG,CAAC,CAAC;IAC/D,yBAAyB,EAAE,MAAM,CAAC,MAAM,CAAC,2BAA2B,EAAE,KAAK,CAAC,CAAC;IAC7E,qBAAqB,EAAE,MAAM,CAAC,MAAM,CAAC,uBAAuB,EAAE,KAAK,CAAC,CAAC;IACrE,wBAAwB,EAAE,MAAM,CAAC,MAAM,CAAC,0BAA0B,EAAE,IAAI,CAAC,CAAC;IAE1E,yBAAyB,EAAE,MAAM,CAAC,MAAM,CAAC,2BAA2B,EAAE,GAAG,CAAC,CAAC;IAC3E,gCAAgC,EAAE,MAAM,CAAC,MAAM,CAAC,kCAAkC,EAAE,MAAM,CAAC,CAAC;IAE5F,kBAAkB,EAAE,MAAM,CAAC,oBAAoB,EAAE,OAAO,CAAC,KAAK,MAAM;IACpE,yEAAyE;IACzE,yEAAyE;IACzE,kCAAkC;IAClC,2BAA2B,EAAE,MAAM,CAAC,6BAA6B,EAAE,OAAO,CAAC,KAAK,MAAM;IACtF,sBAAsB,EAAE,MAAM,CAAC,MAAM,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAAC;IACvE,sBAAsB,EAAE,MAAM,CAAC,MAAM,CAAC,wBAAwB,EAAE,IAAI,CAAC,CAAC;IACtE,WAAW,EAAE,MAAM,CAAC,aAAa,EAAE,SAAS,CAAC;IAC7C,mBAAmB,EAAE,MAAM,CAAC,8BAA8B,CAAC;IAC3D,8EAA8E;IAC9E,0EAA0E;IAC1E,sEAAsE;IACtE,iBAAiB,EAAE,MAAM,CAAC,mBAAmB,CAAC;IAC9C,WAAW,EAAE,MAAM,CAAC,aAAa,CAAC;IAClC,uDAAuD;IACvD,yEAAyE;IACzE,oEAAoE;IACpE,2BAA2B,EAAE,cAAc,CAAC,6BAA6B,EAAE,GAAG,CAAC;IAC/E,qEAAqE;IACrE,mBAAmB,EAAE,WAAW,CAAC,qBAAqB,EAAE,KAAK,CAAC;IAC9D,8BAA8B,EAAE,WAAW,CAAC,gCAAgC,EAAE,IAAI,CAAC;IACnF,yFAAyF;IACzF,qBAAqB,EAAE,WAAW,CAAC,uBAAuB,EAAE,IAAI,CAAC;IACjE,gCAAgC,EAAE,WAAW,CAAC,kCAAkC,EAAE,IAAI,CAAC;IACvF;;;;;;OAMG;IACH,eAAe,EAAE,MAAM,CAAC,0BAA0B,CAAC;IACnD,yBAAyB,EAAE,WAAW,CAAC,2BAA2B,EAAE,KAAK,CAAC;IAC1E,gBAAgB,EAAE,WAAW,CAAC,kBAAkB,EAAE,GAAG,CAAC;IACtD,4BAA4B,EAAE,WAAW,CAAC,8BAA8B,EAAE,SAAS,CAAC;IACpF,cAAc,EAAE,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAChD,UAAU,EAAE,MAAM,CAAC,YAAY,EAAE,2BAA2B,CAAC;IAC7D,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;IAC7C,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC;IAC9B,WAAW,EAAE,MAAM,CAAC,aAAa,EAAE,OAAO,CAAC,KAAK,MAAM;IACtD,gBAAgB,EAAE,MAAM,CAAC,kBAAkB,CAAC;IAC5C,eAAe,EAAE,MAAM,CAAC,iBAAiB,CAAC;IAC1C,cAAc,EAAE,MAAM,CAAC,gBAAgB,CAAC;IACxC,YAAY,EAAE,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC;IAC5C,kBAAkB,EAAE,MAAM,CAAC,oBAAoB,CAAC;IAChD,iBAAiB,EAAE,MAAM,CAAC,mBAAmB,CAAC;IAC9C,kBAAkB,EAAE,MAAM,CAAC,oBAAoB,CAAC;IAChD,4BAA4B,EAAE,MAAM,CAAC,8BAA8B,CAAC;IACpE,2BAA2B,EAAE,MAAM,CAAC,6BAA6B,CAAC;IAClE,iBAAiB,EAAE,MAAM,CAAC,mBAAmB,CAAC;IAC9C,oBAAoB,EAAE,MAAM,CAAC,sBAAsB,EAAE,OAAO,CAAC;IAC7D,sBAAsB,EAAE,MAAM,CAAC,wBAAwB,CAAC,IAAI,MAAM,CAAC,iCAAiC,CAAC;CAC7F,CAAC;AAEX,MAAM,UAAU,cAAc;IAC5B,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAC/C,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,cAAc,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACxD,OAAO,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,MAAM,EAAE,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,mBAAmB;IACjC,OAAO,OAAO,CAAC,MAAM,CAAC,cAAc,IAAI,MAAM,CAAC,iBAAiB,CAAC,CAAC;AACpE,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,OAAO,EAAE,EAAE,KAAK,eAAe,EAAE,MAAM,SAAS,CAAC;AAqFxD,wBAAsB,QAAQ,+RA2M7B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,OAAO,EAAE,EAAE,KAAK,eAAe,EAAE,MAAM,SAAS,CAAC;AAsFxD,wBAAsB,QAAQ,+RAsN7B"}