@nacre.work/core 0.0.0 → 0.1.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 (72) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +9 -0
  3. package/dist/authz/filter.d.ts +54 -3
  4. package/dist/authz/filter.d.ts.map +1 -1
  5. package/dist/authz/filter.js +45 -9
  6. package/dist/authz/filter.js.map +1 -1
  7. package/dist/authz/index.d.ts +2 -2
  8. package/dist/authz/index.d.ts.map +1 -1
  9. package/dist/authz/index.js +1 -1
  10. package/dist/authz/index.js.map +1 -1
  11. package/dist/config.d.ts +33 -0
  12. package/dist/config.d.ts.map +1 -1
  13. package/dist/config.js +137 -3
  14. package/dist/config.js.map +1 -1
  15. package/dist/db/client.d.ts +39 -0
  16. package/dist/db/client.d.ts.map +1 -1
  17. package/dist/db/client.js +82 -0
  18. package/dist/db/client.js.map +1 -1
  19. package/dist/db/migrate.d.ts.map +1 -1
  20. package/dist/db/migrate.js +49 -0
  21. package/dist/db/migrate.js.map +1 -1
  22. package/dist/index.d.ts +15 -3
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +9 -3
  25. package/dist/index.js.map +1 -1
  26. package/dist/lifecycle.d.ts +57 -0
  27. package/dist/lifecycle.d.ts.map +1 -0
  28. package/dist/lifecycle.js +97 -0
  29. package/dist/lifecycle.js.map +1 -0
  30. package/dist/metadata.d.ts +50 -0
  31. package/dist/metadata.d.ts.map +1 -0
  32. package/dist/metadata.js +127 -0
  33. package/dist/metadata.js.map +1 -0
  34. package/dist/metrics.d.ts +18 -1
  35. package/dist/metrics.d.ts.map +1 -1
  36. package/dist/metrics.js +77 -2
  37. package/dist/metrics.js.map +1 -1
  38. package/dist/migrations/0008_authenticating_lookup.sql +124 -0
  39. package/dist/migrations/0009_refresh_tokens.sql +73 -0
  40. package/dist/migrations/0010_definer_search_path.sql +22 -0
  41. package/dist/migrations/0011_sweep_lease.sql +36 -0
  42. package/dist/migrations/0012_prune.sql +118 -0
  43. package/dist/migrations/0013_reindex.sql +65 -0
  44. package/dist/oauth.d.ts +45 -0
  45. package/dist/oauth.d.ts.map +1 -0
  46. package/dist/oauth.js +53 -0
  47. package/dist/oauth.js.map +1 -0
  48. package/dist/observability.d.ts.map +1 -1
  49. package/dist/observability.js +81 -13
  50. package/dist/observability.js.map +1 -1
  51. package/dist/passwords.d.ts +37 -0
  52. package/dist/passwords.d.ts.map +1 -0
  53. package/dist/passwords.js +234 -0
  54. package/dist/passwords.js.map +1 -0
  55. package/dist/redis.d.ts +46 -0
  56. package/dist/redis.d.ts.map +1 -0
  57. package/dist/redis.js +234 -0
  58. package/dist/redis.js.map +1 -0
  59. package/dist/reindex.d.ts +87 -0
  60. package/dist/reindex.d.ts.map +1 -0
  61. package/dist/reindex.js +97 -0
  62. package/dist/reindex.js.map +1 -0
  63. package/dist/tsconfig.tsbuildinfo +1 -1
  64. package/dist/vector/query.d.ts +49 -4
  65. package/dist/vector/query.d.ts.map +1 -1
  66. package/dist/vector/query.js +43 -10
  67. package/dist/vector/query.js.map +1 -1
  68. package/dist/vector/search.d.ts +109 -4
  69. package/dist/vector/search.d.ts.map +1 -1
  70. package/dist/vector/search.js +166 -7
  71. package/dist/vector/search.js.map +1 -1
  72. package/package.json +26 -8
package/dist/config.js CHANGED
@@ -14,6 +14,45 @@
14
14
  * obviously right value — and never fine for anything naming a host or
15
15
  * carrying a credential.
16
16
  */
17
+ export function loadJwtKeys(env = process.env) {
18
+ // Development uses a symmetric secret. Production is meant to load an Ed25519
19
+ // key through NACRE_JWT_PRIVATE_KEY_REF; until that lands, refusing is the
20
+ // honest behaviour — a hardcoded fallback here would be a signing key anyone
21
+ // reading the source can forge tokens with.
22
+ const secret = env.NACRE_JWT_SECRET;
23
+ if (secret === undefined || secret.length < 32) {
24
+ throw new ConfigError([
25
+ 'NACRE_JWT_SECRET is not set, or is shorter than 32 bytes. ' +
26
+ 'Asymmetric keys through NACRE_JWT_PRIVATE_KEY_REF are not implemented yet; ' +
27
+ 'until they are, this is required and there is no default.',
28
+ ]);
29
+ }
30
+ const previous = env.NACRE_JWT_SECRET_PREVIOUS;
31
+ if (previous === undefined || previous === '') {
32
+ return { key: new TextEncoder().encode(secret), alsoAccept: [] };
33
+ }
34
+ if (previous.length < 32) {
35
+ throw new ConfigError([
36
+ 'NACRE_JWT_SECRET_PREVIOUS is set but shorter than 32 bytes. It holds the ' +
37
+ 'key being rotated out, so it is held to the same floor as the one ' +
38
+ 'replacing it. Unset it to finish the rotation.',
39
+ ]);
40
+ }
41
+ if (previous === secret) {
42
+ // Refused rather than deduplicated. Setting both to the same value is what
43
+ // an operator does when they mean to rotate and copy the wrong line, and
44
+ // it leaves an installation that believes it has rotated and has not.
45
+ throw new ConfigError([
46
+ 'NACRE_JWT_SECRET_PREVIOUS is the same value as NACRE_JWT_SECRET. That is ' +
47
+ 'not a rotation: it accepts one key twice. Set NACRE_JWT_SECRET to the ' +
48
+ 'new key and NACRE_JWT_SECRET_PREVIOUS to the one it replaces.',
49
+ ]);
50
+ }
51
+ return {
52
+ key: new TextEncoder().encode(secret),
53
+ alsoAccept: [new TextEncoder().encode(previous)],
54
+ };
55
+ }
17
56
  export class ConfigError extends Error {
18
57
  problems;
19
58
  constructor(problems) {
@@ -42,6 +81,23 @@ class Reader {
42
81
  const value = this.env[key]?.trim();
43
82
  return value === undefined || value === '' ? undefined : value;
44
83
  }
84
+ /**
85
+ * An optional secret with a floor on its length.
86
+ *
87
+ * Unset is fine and means the feature is off. Set to something short is not:
88
+ * a short token reads as protection and is a moment's guessing, which is
89
+ * worse than no token because it stops anyone looking again.
90
+ */
91
+ secret(key, minLength) {
92
+ const value = this.optional(key);
93
+ if (value === undefined)
94
+ return undefined;
95
+ if (value.length < minLength) {
96
+ this.problems.push(`${key} must be at least ${minLength} characters, or unset`);
97
+ return undefined;
98
+ }
99
+ return value;
100
+ }
45
101
  /** A default is allowed here: a tunable has an obviously right value. */
46
102
  number(key, fallback, { min = 1, max = Number.MAX_SAFE_INTEGER } = {}) {
47
103
  const raw = this.env[key]?.trim();
@@ -90,6 +146,7 @@ export function loadConfig(env = process.env) {
90
146
  const config = {
91
147
  env: r.oneOf('NACRE_ENV', ['development', 'production'], 'development'),
92
148
  canonicalUrl: r.url('NACRE_CANONICAL_URL'),
149
+ oauthAuthorizationServer: r.url('NACRE_OAUTH_AUTHORIZATION_SERVER', { required: false }),
93
150
  logLevel: r.oneOf('NACRE_LOG_LEVEL', ['debug', 'info', 'warn', 'error'], 'info'),
94
151
  logFormat: r.oneOf('NACRE_LOG_FORMAT', ['json', 'text'], 'json'),
95
152
  pgUrl: r.required('NACRE_PG_URL'),
@@ -106,12 +163,21 @@ export function loadConfig(env = process.env) {
106
163
  // False, and it was true. `minimal` has no reranker by definition — the
107
164
  // profile exists to run on a laptop without a GPU — so a default of true
108
165
  // meant the documented starting profile refused to boot until the operator
109
- // turned off a feature they had not asked for. It is also not implemented
110
- // on the search path yet, so the refusal bought nothing at all.
166
+ // turned off a feature they had not asked for.
111
167
  rerankerEnabled: r.boolean('NACRE_RERANKER_ENABLED', false),
168
+ // The candidate set a cross-encoder reorders. 50 is what
169
+ // docs/architecture.md specifies. The maximum is bounded because every
170
+ // candidate is a row hydrated from Postgres and a text sent to the model:
171
+ // this is the one tunable here that trades latency for quality directly,
172
+ // and there is a value at which a search stops answering in time.
173
+ rerankCandidates: r.number('NACRE_RERANK_CANDIDATES', 50, { min: 1, max: 500 }),
112
174
  jwtIssuer: r.required('NACRE_JWT_ISSUER'),
113
175
  jwtAudience: r.required('NACRE_JWT_AUDIENCE'),
114
176
  accessTokenTtl: r.number('NACRE_ACCESS_TOKEN_TTL', 900, { min: 60, max: 86_400 }),
177
+ // 30 days. The upper bound is a year rather than unbounded: a refresh token
178
+ // is the credential a stolen laptop still holds, and "never expires" is a
179
+ // choice nobody makes deliberately.
180
+ refreshTokenTtl: r.number('NACRE_REFRESH_TOKEN_TTL', 2_592_000, { min: 300, max: 31_536_000 }),
115
181
  aclCacheTtl: r.number('NACRE_ACL_CACHE_TTL', 60, { min: 0, max: 3600 }),
116
182
  aclPropagationSla: r.number('NACRE_ACL_PROPAGATION_SLA', 60, { min: 1, max: 3600 }),
117
183
  gcGrace: r.number('NACRE_GC_GRACE', 3600, { min: 0, max: 2_592_000 }),
@@ -124,8 +190,49 @@ export function loadConfig(env = process.env) {
124
190
  aclTagHashBytes: r.number('NACRE_ACL_TAG_HASH_BYTES', 8, { min: 4, max: 32 }),
125
191
  rateSearchPerMin: r.number('NACRE_RATE_SEARCH_PER_MIN', 60, { min: 1 }),
126
192
  rateIngestPerHour: r.number('NACRE_RATE_INGEST_PER_HOUR', 600, { min: 1 }),
193
+ // Ten attempts per quarter hour, counted per email address. Low enough that
194
+ // guessing is not a strategy, high enough that someone who genuinely cannot
195
+ // remember which password they used is not locked out for the afternoon.
196
+ rateLoginPer15Min: r.number('NACRE_RATE_LOGIN_PER_15MIN', 10, { min: 1, max: 1000 }),
197
+ // The same window, counted per client instead of per address, because the
198
+ // per-address limit does not bound the attack people actually run: one
199
+ // password against ten thousand addresses never repeats a key. Six times
200
+ // looser, because a whole office behind one NAT is one source here and the
201
+ // job of this limit is to stop a directory being ground down, not to make
202
+ // shared egress unusable.
203
+ rateLoginSourcePer15Min: r.number('NACRE_RATE_LOGIN_SOURCE_PER_15MIN', 60, {
204
+ min: 1,
205
+ max: 10_000,
206
+ }),
207
+ // How many proxies sit in front of this process. Zero — the default — means
208
+ // X-Forwarded-For is ignored entirely and the socket address is the client.
209
+ //
210
+ // Neither default is safe, which is why this is configuration rather than a
211
+ // guess. Trusting the header unconditionally keys the limit above on a
212
+ // string the attacker picks, which is worse than having no limit: a fresh
213
+ // value per request costs a Redis round trip and accomplishes nothing.
214
+ // Ignoring it unconditionally means that behind an ingress every request
215
+ // carries the proxy's address, so one bad client rate-limits everybody.
216
+ trustProxy: r.number('NACRE_TRUST_PROXY', 0, { min: 0, max: 8 }),
217
+ // Optional, and off by default. Requiring a token would break every
218
+ // existing scrape config for a product people self-host, and the default is
219
+ // right for the deployment this is designed around — the port is on an
220
+ // internal network. It stops being right the moment somebody puts the API
221
+ // behind a public ingress without carving /metrics out, so the operator who
222
+ // knows they are in that situation has a way to say so.
223
+ //
224
+ // A minimum length, because a two-character scrape token is worse than none
225
+ // — it reads as protection and is a moment's guessing.
226
+ metricsToken: r.secret('NACRE_METRICS_TOKEN', 16),
127
227
  maxDocumentBytes: r.number('NACRE_MAX_DOCUMENT_BYTES', 52_428_800, { min: 1024 }),
128
- auditRetentionDays: r.number('NACRE_AUDIT_RETENTION_DAYS', 400, { min: 1 }),
228
+ // The floor is 30 and it is not a tunable. Retention is now enforced —
229
+ // `prune_audit_events` deletes past this horizon — and the database refuses
230
+ // anything shorter, because below a month "retention" stops meaning
231
+ // retention and becomes a way to make recent events go away, which is the
232
+ // thing the append-only grant exists to prevent. Refused here rather than
233
+ // raised hourly by the worker: a value the deployment can never act on
234
+ // should stop the deployment, not fill a log.
235
+ auditRetentionDays: r.number('NACRE_AUDIT_RETENTION_DAYS', 400, { min: 30 }),
129
236
  auditQueryText: r.boolean('NACRE_AUDIT_QUERY_TEXT', false),
130
237
  };
131
238
  // Cross-field checks. Each one is a combination that parses fine and is
@@ -135,6 +242,33 @@ export function loadConfig(env = process.env) {
135
242
  'Turning reranking on is worth more than any chunking tuning, and it ' +
136
243
  'needs somewhere to send the request — the full profile provides one.');
137
244
  }
245
+ // ─── settings that would silently do nothing ───
246
+ //
247
+ // Eight variables were validated here and read nowhere. Most of those are
248
+ // quality-of-life and are documented as unimplemented; these two are not,
249
+ // because ignoring them changes something an operator is relying on.
250
+ //
251
+ // Refusing at startup rather than warning: an operator who sets these has
252
+ // made a decision about isolation or about collision probability, and a
253
+ // process that starts anyway has silently overruled them. `docs/config.md`
254
+ // already says a silent default is how a deployment talks to nothing and
255
+ // reports success — this is the same failure with a value supplied.
256
+ if (config.vectorTenancy !== 'collection') {
257
+ r.problems.push('NACRE_VECTOR_TENANCY=shared is not implemented. Every collection is named ' +
258
+ 'per organization (org_{slug}) and there is no code path that shares one, ' +
259
+ 'so accepting this would give you a single-collection deployment that ' +
260
+ 'believes it is isolated. Use `collection`, which is the default.');
261
+ }
262
+ if (config.aclTagHashBytes !== 8) {
263
+ r.problems.push('NACRE_ACL_TAG_HASH_BYTES is not implemented: the tag width is fixed at 8 ' +
264
+ 'bytes in the code that writes and matches tags. Setting it changes the ' +
265
+ 'collision probability you think you have and nothing else. Leave it at 8.');
266
+ }
267
+ if (config.refreshTokenTtl <= config.accessTokenTtl) {
268
+ r.problems.push('NACRE_REFRESH_TOKEN_TTL is not longer than NACRE_ACCESS_TOKEN_TTL. A refresh ' +
269
+ 'token that expires no later than the access token it renews cannot renew ' +
270
+ 'anything, so every session would end at the first refresh.');
271
+ }
138
272
  if (config.aclCacheTtl > config.aclPropagationSla) {
139
273
  // The cache would still be serving a revoked grant after the SLA has
140
274
  // passed, and nacre_acl_propagation_lag_seconds would report compliance.
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AA6DH,MAAM,OAAO,WAAY,SAAQ,KAAK;IAC3B,QAAQ,CAAmB;IAEpC,YAAY,QAA2B;QACrC,KAAK,CACH,iCAAiC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;YAC7E,gEAAgE,CACnE,CAAA;QACD,IAAI,CAAC,IAAI,GAAG,aAAa,CAAA;QACzB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;IAC1B,CAAC;CACF;AAID,MAAM,MAAM;IAEmB;IADpB,QAAQ,GAAa,EAAE,CAAA;IAChC,YAA6B,GAAQ;QAAR,QAAG,GAAH,GAAG,CAAK;IAAG,CAAC;IAEzC,+EAA+E;IAC/E,QAAQ,CAAC,GAAW;QAClB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,CAAA;QACnC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;YACxC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,GAAG,aAAa,CAAC,CAAA;YACvC,OAAO,EAAE,CAAA;QACX,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC;IAED,QAAQ,CAAC,GAAW;QAClB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,CAAA;QACnC,OAAO,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAA;IAChE,CAAC;IAED,yEAAyE;IACzE,MAAM,CAAC,GAAW,EAAE,QAAgB,EAAE,EAAE,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,MAAM,CAAC,gBAAgB,EAAE,GAAG,EAAE;QACnF,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,CAAA;QACjC,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,EAAE;YAAE,OAAO,QAAQ,CAAA;QAEpD,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAA;QACzB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,GAAG,IAAI,KAAK,GAAG,GAAG,EAAE,CAAC;YACtF,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,GAAG,+BAA+B,GAAG,QAAQ,GAAG,SAAS,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;YACrG,OAAO,QAAQ,CAAA;QACjB,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC;IAED,OAAO,CAAC,GAAW,EAAE,QAAiB;QACpC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;QAC/C,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,EAAE;YAAE,OAAO,QAAQ,CAAA;QACpD,IAAI,GAAG,KAAK,MAAM,IAAI,GAAG,KAAK,OAAO;YAAE,OAAO,GAAG,KAAK,MAAM,CAAA;QAC5D,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,GAAG,+BAA+B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QAC9E,OAAO,QAAQ,CAAA;IACjB,CAAC;IAED,KAAK,CAAmB,GAAW,EAAE,OAAqB,EAAE,QAAW;QACrE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,CAAA;QACjC,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,EAAE;YAAE,OAAO,QAAQ,CAAA;QACpD,IAAK,OAA6B,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,OAAO,GAAQ,CAAA;QACjE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,GAAG,mBAAmB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QAC7F,OAAO,QAAQ,CAAA;IACjB,CAAC;IAED,GAAG,CAAC,GAAW,EAAE,EAAE,QAAQ,GAAG,IAAI,EAAE,GAAG,EAAE;QACvC,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAA;QACtE,IAAI,GAAG,KAAK,EAAE;YAAE,OAAO,EAAE,CAAA;QACzB,IAAI,CAAC;YACH,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;QACd,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,GAAG,kBAAkB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACnE,CAAC;QACD,OAAO,GAAG,CAAA;IACZ,CAAC;CACF;AAED,MAAM,UAAU,UAAU,CAAC,MAAW,OAAO,CAAC,GAAG;IAC/C,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,GAAG,CAAC,CAAA;IAEzB,MAAM,MAAM,GAAW;QACrB,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,aAAa,EAAE,YAAY,CAAU,EAAE,aAAa,CAAC;QAChF,YAAY,EAAE,CAAC,CAAC,GAAG,CAAC,qBAAqB,CAAC;QAC1C,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,iBAAiB,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAU,EAAE,MAAM,CAAC;QACzF,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,kBAAkB,EAAE,CAAC,MAAM,EAAE,MAAM,CAAU,EAAE,MAAM,CAAC;QAEzE,KAAK,EAAE,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC;QACjC,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,mBAAmB,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;QACnE,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,kBAAkB,CAAC;QACpC,YAAY,EAAE,CAAC,CAAC,QAAQ,CAAC,sBAAsB,CAAC;QAChD,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,sBAAsB,EAAE,CAAC,YAAY,EAAE,QAAQ,CAAU,EAAE,YAAY,CAAC;QAC/F,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,iBAAiB,CAAC;QAEvC,iBAAiB,EAAE,CAAC,CAAC,GAAG,CAAC,kCAAkC,CAAC;QAC5D,cAAc,EAAE,CAAC,CAAC,QAAQ,CAAC,+BAA+B,CAAC;QAC3D,YAAY,EAAE,CAAC,CAAC,MAAM,CAAC,6BAA6B,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;QACnF,cAAc,EAAE,CAAC,CAAC,GAAG,CAAC,uBAAuB,CAAC;QAC9C,gBAAgB,EAAE,CAAC,CAAC,QAAQ,CAAC,yBAAyB,CAAC;QACvD,wEAAwE;QACxE,yEAAyE;QACzE,2EAA2E;QAC3E,0EAA0E;QAC1E,gEAAgE;QAChE,eAAe,EAAE,CAAC,CAAC,OAAO,CAAC,wBAAwB,EAAE,KAAK,CAAC;QAE3D,SAAS,EAAE,CAAC,CAAC,QAAQ,CAAC,kBAAkB,CAAC;QACzC,WAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,oBAAoB,CAAC;QAC7C,cAAc,EAAE,CAAC,CAAC,MAAM,CAAC,wBAAwB,EAAE,GAAG,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;QAEjF,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,qBAAqB,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;QACvE,iBAAiB,EAAE,CAAC,CAAC,MAAM,CAAC,2BAA2B,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;QACnF,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,gBAAgB,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC;QACrE,2EAA2E;QAC3E,4EAA4E;QAC5E,uEAAuE;QACvE,sEAAsE;QACtE,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC,mBAAmB,EAAE,GAAG,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;QACxE,gBAAgB,EAAE,CAAC,CAAC,MAAM,CAAC,0BAA0B,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;QAC/E,eAAe,EAAE,CAAC,CAAC,MAAM,CAAC,0BAA0B,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC;QAE7E,gBAAgB,EAAE,CAAC,CAAC,MAAM,CAAC,2BAA2B,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;QACvE,iBAAiB,EAAE,CAAC,CAAC,MAAM,CAAC,4BAA4B,EAAE,GAAG,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;QAC1E,gBAAgB,EAAE,CAAC,CAAC,MAAM,CAAC,0BAA0B,EAAE,UAAU,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;QAEjF,kBAAkB,EAAE,CAAC,CAAC,MAAM,CAAC,4BAA4B,EAAE,GAAG,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;QAC3E,cAAc,EAAE,CAAC,CAAC,OAAO,CAAC,wBAAwB,EAAE,KAAK,CAAC;KAC3D,CAAA;IAED,wEAAwE;IACxE,uEAAuE;IAEvE,IAAI,MAAM,CAAC,eAAe,IAAI,MAAM,CAAC,gBAAgB,KAAK,SAAS,EAAE,CAAC;QACpE,CAAC,CAAC,QAAQ,CAAC,IAAI,CACb,yEAAyE;YACvE,sEAAsE;YACtE,sEAAsE,CACzE,CAAA;IACH,CAAC;IAED,IAAI,MAAM,CAAC,WAAW,GAAG,MAAM,CAAC,iBAAiB,EAAE,CAAC;QAClD,qEAAqE;QACrE,yEAAyE;QACzE,CAAC,CAAC,QAAQ,CAAC,IAAI,CACb,wBAAwB,MAAM,CAAC,WAAW,mBAAmB;YAC3D,8BAA8B,MAAM,CAAC,iBAAiB,qBAAqB;YAC3E,kDAAkD,CACrD,CAAA;IACH,CAAC;IAED,IAAI,MAAM,CAAC,GAAG,KAAK,YAAY,IAAI,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7E,uEAAuE;QACvE,oEAAoE;QACpE,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,yEAAyE,CAAC,CAAA;IAC5F,CAAC;IAED,IAAI,MAAM,CAAC,GAAG,KAAK,YAAY,IAAI,kCAAkC,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC;QAChG,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,uDAAuD,CAAC,CAAA;IAC1E,CAAC;IAED,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,IAAI,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAA;IAC5D,OAAO,MAAM,CAAA;AACf,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../config.ts"],"names":[],"mappings":"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"}
@@ -34,5 +34,44 @@ export interface WithOrgOptions {
34
34
  */
35
35
  readonly role?: string;
36
36
  }
37
+ /**
38
+ * Run a lookup that resolves a credential, which cannot be scoped to an
39
+ * organization because the credential is what says which organization it is.
40
+ *
41
+ * `app.authenticating` opens a second row-level security policy on
42
+ * `service_accounts` for the length of the transaction — see migration 0008.
43
+ * Without it the query raises `unrecognized configuration parameter` on any
44
+ * connection that is subject to row-level security, which is every connection
45
+ * a deployment following `docs/config.md` will make.
46
+ *
47
+ * **This is the one path in the system that reads across tenants, and it must
48
+ * stay the only one.** Two things keep it narrow, and both are load-bearing:
49
+ * the flag is `SET LOCAL`, so it cannot outlive the transaction or come back
50
+ * on a pooled connection, and the policy it opens is `FOR SELECT`, so this
51
+ * cannot write a row into an organization it has not identified yet.
52
+ *
53
+ * Read the credential and nothing else. Anything joined from tenant data here
54
+ * is a cross-tenant read with the guard rail switched off.
55
+ */
56
+ export declare function whileAuthenticating<T>(pool: Pool, fn: (client: PoolClient) => Promise<T>, options?: WithOrgOptions): Promise<T>;
57
+ /**
58
+ * Run a query that legitimately spans every tenant, under the role the schema
59
+ * gives BYPASSRLS.
60
+ *
61
+ * The worker's queue is the only thing that needs this: claiming the next
62
+ * document to index means looking at all of them, which is what a queue is.
63
+ * `0001_init.sql` has said "background worker jobs run under a separate role
64
+ * with BYPASSRLS" since the beginning and no migration created that role until
65
+ * 0008, so these queries ran with no organization set and raised
66
+ * `unrecognized configuration parameter` on any connection subject to
67
+ * row-level security — every connection a deployment following
68
+ * `docs/config.md` makes. Indexing stopped entirely, and the Compose stack
69
+ * never showed it because `POSTGRES_USER` connects as a superuser.
70
+ *
71
+ * **This turns the second line of defence off.** Every query run inside it
72
+ * names `org_id` explicitly, because with row-level security bypassed that is
73
+ * the only line left.
74
+ */
75
+ export declare function acrossOrganizations<T>(pool: Pool, fn: (client: PoolClient) => Promise<T>, role?: string): Promise<T>;
37
76
  export declare function withOrg<T>(pool: Pool, orgId: string, fn: (client: PoolClient) => Promise<T>, options?: WithOrgOptions): Promise<T>;
38
77
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../db/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,KAAK,UAAU,EAAE,MAAM,IAAI,CAAA;AAE1C,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAA;IACjC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,SAAS,GAAG,IAAI,CAEnD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;;;;;;OASG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,wBAAsB,OAAO,CAAC,CAAC,EAC7B,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,MAAM,EACb,EAAE,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC,EACtC,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,CAAC,CAAC,CA0BZ"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../db/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,KAAK,UAAU,EAAE,MAAM,IAAI,CAAA;AAE1C,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAA;IACjC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,SAAS,GAAG,IAAI,CAEnD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;;;;;;OASG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CACvB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,mBAAmB,CAAC,CAAC,EACzC,IAAI,EAAE,IAAI,EACV,EAAE,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC,EACtC,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,CAAC,CAAC,CAsBZ;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,mBAAmB,CAAC,CAAC,EACzC,IAAI,EAAE,IAAI,EACV,EAAE,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC,EACtC,IAAI,SAAiB,GACpB,OAAO,CAAC,CAAC,CAAC,CAiBZ;AAED,wBAAsB,OAAO,CAAC,CAAC,EAC7B,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,MAAM,EACb,EAAE,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC,EACtC,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,CAAC,CAAC,CA0BZ"}
package/dist/db/client.js CHANGED
@@ -2,6 +2,88 @@ import { Pool } from 'pg';
2
2
  export function createPool(options) {
3
3
  return new Pool({ connectionString: options.connectionString, max: options.max ?? 20 });
4
4
  }
5
+ /**
6
+ * Run a lookup that resolves a credential, which cannot be scoped to an
7
+ * organization because the credential is what says which organization it is.
8
+ *
9
+ * `app.authenticating` opens a second row-level security policy on
10
+ * `service_accounts` for the length of the transaction — see migration 0008.
11
+ * Without it the query raises `unrecognized configuration parameter` on any
12
+ * connection that is subject to row-level security, which is every connection
13
+ * a deployment following `docs/config.md` will make.
14
+ *
15
+ * **This is the one path in the system that reads across tenants, and it must
16
+ * stay the only one.** Two things keep it narrow, and both are load-bearing:
17
+ * the flag is `SET LOCAL`, so it cannot outlive the transaction or come back
18
+ * on a pooled connection, and the policy it opens is `FOR SELECT`, so this
19
+ * cannot write a row into an organization it has not identified yet.
20
+ *
21
+ * Read the credential and nothing else. Anything joined from tenant data here
22
+ * is a cross-tenant read with the guard rail switched off.
23
+ */
24
+ export async function whileAuthenticating(pool, fn, options = {}) {
25
+ const client = await pool.connect();
26
+ try {
27
+ await client.query('BEGIN');
28
+ if (options.role !== undefined) {
29
+ if (!/^[a-z_][a-z0-9_]*$/i.test(options.role)) {
30
+ throw new Error(`refusing to set an unrecognizable role name: ${options.role}`);
31
+ }
32
+ await client.query(`SET LOCAL ROLE ${options.role}`);
33
+ }
34
+ // `true` is the local flag: it goes away with the transaction, so a pooled
35
+ // connection cannot hand it to the next caller.
36
+ await client.query('SELECT set_config($1, $2, true)', ['app.authenticating', 'on']);
37
+ const result = await fn(client);
38
+ await client.query('COMMIT');
39
+ return result;
40
+ }
41
+ catch (cause) {
42
+ await client.query('ROLLBACK').catch(() => { });
43
+ throw cause;
44
+ }
45
+ finally {
46
+ client.release();
47
+ }
48
+ }
49
+ /**
50
+ * Run a query that legitimately spans every tenant, under the role the schema
51
+ * gives BYPASSRLS.
52
+ *
53
+ * The worker's queue is the only thing that needs this: claiming the next
54
+ * document to index means looking at all of them, which is what a queue is.
55
+ * `0001_init.sql` has said "background worker jobs run under a separate role
56
+ * with BYPASSRLS" since the beginning and no migration created that role until
57
+ * 0008, so these queries ran with no organization set and raised
58
+ * `unrecognized configuration parameter` on any connection subject to
59
+ * row-level security — every connection a deployment following
60
+ * `docs/config.md` makes. Indexing stopped entirely, and the Compose stack
61
+ * never showed it because `POSTGRES_USER` connects as a superuser.
62
+ *
63
+ * **This turns the second line of defence off.** Every query run inside it
64
+ * names `org_id` explicitly, because with row-level security bypassed that is
65
+ * the only line left.
66
+ */
67
+ export async function acrossOrganizations(pool, fn, role = 'nacre_worker') {
68
+ const client = await pool.connect();
69
+ try {
70
+ await client.query('BEGIN');
71
+ if (!/^[a-z_][a-z0-9_]*$/i.test(role)) {
72
+ throw new Error(`refusing to set an unrecognizable role name: ${role}`);
73
+ }
74
+ await client.query(`SET LOCAL ROLE ${role}`);
75
+ const result = await fn(client);
76
+ await client.query('COMMIT');
77
+ return result;
78
+ }
79
+ catch (cause) {
80
+ await client.query('ROLLBACK').catch(() => { });
81
+ throw cause;
82
+ }
83
+ finally {
84
+ client.release();
85
+ }
86
+ }
5
87
  export async function withOrg(pool, orgId, fn, options = {}) {
6
88
  const client = await pool.connect();
7
89
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../db/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAmB,MAAM,IAAI,CAAA;AAO1C,MAAM,UAAU,UAAU,CAAC,OAAkB;IAC3C,OAAO,IAAI,IAAI,CAAC,EAAE,gBAAgB,EAAE,OAAO,CAAC,gBAAgB,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC,CAAA;AACzF,CAAC;AAiCD,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,IAAU,EACV,KAAa,EACb,EAAsC,EACtC,UAA0B,EAAE;IAE5B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAA;IACnC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QAC3B,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC/B,uEAAuE;YACvE,+DAA+D;YAC/D,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC9C,MAAM,IAAI,KAAK,CAAC,gDAAgD,OAAO,CAAC,IAAI,EAAE,CAAC,CAAA;YACjF,CAAC;YACD,MAAM,MAAM,CAAC,KAAK,CAAC,kBAAkB,OAAO,CAAC,IAAI,EAAE,CAAC,CAAA;QACtD,CAAC;QACD,MAAM,MAAM,CAAC,KAAK,CAAC,iCAAiC,EAAE,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAC,CAAA;QACjF,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,MAAM,CAAC,CAAA;QAC/B,MAAM,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;QAC5B,OAAO,MAAM,CAAA;IACf,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;YACxC,2EAA2E;YAC3E,0EAA0E;YAC1E,iEAAiE;QACnE,CAAC,CAAC,CAAA;QACF,MAAM,KAAK,CAAA;IACb,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,OAAO,EAAE,CAAA;IAClB,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../db/client.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../db/migrate.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CACrB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAuB,GAAG,SAAS,SAAS,EAAE,CAyBjF;AAeD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;IACnC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;CACpC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,OAAO,CAC3B,gBAAgB,EAAE,MAAM,EACxB,UAAU,GAAE,SAAS,SAAS,EAAqB,GAClD,OAAO,CAAC,aAAa,CAAC,CAmDxB"}
1
+ {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../db/migrate.ts"],"names":[],"mappings":"AAsBA,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CACrB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAuB,GAAG,SAAS,SAAS,EAAE,CAyBjF;AAeD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;IACnC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;CACpC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,OAAO,CAC3B,gBAAgB,EAAE,MAAM,EACxB,UAAU,GAAE,SAAS,SAAS,EAAqB,GAClD,OAAO,CAAC,aAAa,CAAC,CA4FxB"}
@@ -3,6 +3,19 @@ import { join } from 'node:path';
3
3
  import { fileURLToPath } from 'node:url';
4
4
  import { Client } from 'pg';
5
5
  const MIGRATIONS_DIR = fileURLToPath(new URL('../migrations/', import.meta.url));
6
+ /**
7
+ * How long a migration may wait for a lock before giving up. See the call site.
8
+ *
9
+ * A migration that needs longer can say so: `SET LOCAL lock_timeout` inside the
10
+ * file overrides this for the rest of that transaction, and it is the right
11
+ * place for the exception because the migration is what knows it is unusual.
12
+ *
13
+ * `statement_timeout` is deliberately not touched. Some managed platforms set
14
+ * one globally and a long index build will hit it — but that is the operator's
15
+ * configuration, the failure rolls back cleanly, and quietly overriding a bound
16
+ * somebody chose is worse than failing where they can see it.
17
+ */
18
+ const LOCK_TIMEOUT = '10s';
6
19
  /**
7
20
  * Migrations in filename order. Numbered prefixes are compared as numbers, so
8
21
  * `0010` sorts after `0009` rather than between `0001` and `0002`.
@@ -81,6 +94,30 @@ export async function migrate(connectionString, migrations = loadMigrations()) {
81
94
  }
82
95
  await client.query('BEGIN');
83
96
  try {
97
+ // Bounded waiting, set inside the transaction so it reverts on its own.
98
+ //
99
+ // `ALTER TABLE` takes ACCESS EXCLUSIVE, which conflicts with everything
100
+ // including a plain SELECT. With no timeout the sequence on a busy
101
+ // database is: the ALTER waits behind one long-running query, and every
102
+ // statement arriving afterwards queues behind the ALTER — because a
103
+ // lock request is not overtaken by weaker ones. One slow reporting
104
+ // query therefore stops the entire application for as long as it runs,
105
+ // and the migration that appeared to be "just adding a column" is what
106
+ // the outage gets blamed on.
107
+ //
108
+ // `lock_timeout`, not `statement_timeout`: the two failures are not
109
+ // alike. Waiting for a lock is a scheduling problem and retrying in a
110
+ // quieter minute fixes it, so failing fast is free. Doing the work is
111
+ // not — a backfill or an index build on a large table legitimately
112
+ // takes longer than any bound worth setting, and killing it halfway
113
+ // achieves nothing except a rollback. So the wait is capped and the
114
+ // work is not.
115
+ //
116
+ // Ten seconds because it is far longer than any lock this schema takes
117
+ // when the queue is empty, and far shorter than a deploy timeout — the
118
+ // migration fails with `55P03 lock_not_available`, which names the
119
+ // problem, instead of hanging until someone kills it and has to guess.
120
+ await client.query(`SET LOCAL lock_timeout = '${LOCK_TIMEOUT}'`);
84
121
  await client.query(migration.sql);
85
122
  await client.query('INSERT INTO schema_migrations (name, checksum) VALUES ($1, $2)', [
86
123
  migration.name,
@@ -91,6 +128,18 @@ export async function migrate(connectionString, migrations = loadMigrations()) {
91
128
  }
92
129
  catch (cause) {
93
130
  await client.query('ROLLBACK');
131
+ // 55P03 is `lock_not_available`, and it is worth naming: it is the one
132
+ // failure here that says nothing about the migration. The SQL is fine,
133
+ // something else was holding the table, and the fix is to look at
134
+ // pg_stat_activity rather than at the file.
135
+ if (cause.code === '55P03') {
136
+ throw new Error(`migration ${migration.name} gave up waiting for a lock after ${LOCK_TIMEOUT} ` +
137
+ 'and was rolled back. Something else is holding the table — a long query, an ' +
138
+ 'idle-in-transaction session, another migration — so this is not a problem with ' +
139
+ 'the migration itself and re-running it once the holder is gone will work. ' +
140
+ 'The wait is capped deliberately: an ALTER queued behind one slow query blocks ' +
141
+ 'every statement that arrives after it, which takes the application down.', { cause });
142
+ }
94
143
  throw new Error(`migration ${migration.name} failed and was rolled back`, { cause });
95
144
  }
96
145
  }
@@ -1 +1 @@
1
- {"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../db/migrate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../db/migrate.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,16 +1,28 @@
1
1
  export * from './types.js';
2
2
  export * from './authz/index.js';
3
- export { loadConfig, ConfigError } from './config.js';
3
+ export { parseFilters, parseMetadata, MetadataError, MAX_METADATA_KEYS, MAX_METADATA_KEY_LENGTH, MAX_METADATA_LIST, MAX_METADATA_VALUE_LENGTH, } from './metadata.js';
4
+ export type { Metadata } from './metadata.js';
5
+ export { loadConfig, loadJwtKeys, ConfigError } from './config.js';
6
+ export { protectedResourceMetadata, PROTECTED_RESOURCE_PATH } from './oauth.js';
7
+ export type { ProtectedResourceMetadata } from './oauth.js';
8
+ export type { JwtKeys } from './config.js';
4
9
  export type { Config } from './config.js';
5
- export { createPool, withOrg } from './db/client.js';
10
+ export { acrossOrganizations, createPool, whileAuthenticating, withOrg } from './db/client.js';
6
11
  export type { DbOptions, WithOrgOptions } from './db/client.js';
7
12
  export { migrate, loadMigrations } from './db/migrate.js';
8
13
  export { loadGrants, loadGroupsVersion, loadScopeTree, PostgresGroupGraph } from './authz/store.js';
9
- export { VectorStore } from './vector/search.js';
14
+ export { explainQdrant, VectorStore } from './vector/search.js';
10
15
  export type { Hit, SearchRequest, VectorStoreOptions } from './vector/search.js';
11
16
  export { buildHybridQuery, collectionConfig, collectionName, PAYLOAD_INDEXES, vectorName } from './vector/query.js';
12
17
  export type { Branch, HybridQuery } from './vector/query.js';
13
18
  export { Counter, Gauge, Histogram, Registry, createMetrics } from './metrics.js';
14
19
  export type { Labels, Metrics } from './metrics.js';
15
20
  export { collectDatabaseGauges } from './observability.js';
21
+ export { Redis, RedisError } from './redis.js';
22
+ export type { RedisOptions } from './redis.js';
23
+ export { reindexProgress, toStateJson, fromStateJson } from './reindex.js';
24
+ export type { ReindexState } from './reindex.js';
25
+ export { hashingLoad, hashPassword, needsRehash, spendVerificationTime, TooBusy, verifyPassword, } from './passwords.js';
26
+ export { installGuards, onListenError } from './lifecycle.js';
27
+ export type { Guards } from './lifecycle.js';
16
28
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,cAAc,kBAAkB,CAAA;AAChC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACrD,YAAY,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AACpD,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC/D,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AACzD,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACnG,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,YAAY,EAAE,GAAG,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAChF,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,cAAc,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACnH,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC5D,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AACjF,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,cAAc,kBAAkB,CAAA;AAChC,OAAO,EACL,YAAY,EACZ,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,uBAAuB,EACvB,iBAAiB,EACjB,yBAAyB,GAC1B,MAAM,eAAe,CAAA;AACtB,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAC7C,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAClE,OAAO,EAAE,yBAAyB,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAA;AAC/E,YAAY,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAA;AAC3D,YAAY,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAC1C,YAAY,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAC9F,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC/D,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AACzD,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACnG,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAC/D,YAAY,EAAE,GAAG,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAChF,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,cAAc,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACnH,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC5D,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AACjF,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAA;AAC1D,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAC9C,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC1E,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAChD,OAAO,EACL,WAAW,EACX,YAAY,EACZ,WAAW,EACX,qBAAqB,EACrB,OAAO,EACP,cAAc,GACf,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAC7D,YAAY,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA"}
package/dist/index.js CHANGED
@@ -1,11 +1,17 @@
1
1
  export * from './types.js';
2
2
  export * from './authz/index.js';
3
- export { loadConfig, ConfigError } from './config.js';
4
- export { createPool, withOrg } from './db/client.js';
3
+ export { parseFilters, parseMetadata, MetadataError, MAX_METADATA_KEYS, MAX_METADATA_KEY_LENGTH, MAX_METADATA_LIST, MAX_METADATA_VALUE_LENGTH, } from './metadata.js';
4
+ export { loadConfig, loadJwtKeys, ConfigError } from './config.js';
5
+ export { protectedResourceMetadata, PROTECTED_RESOURCE_PATH } from './oauth.js';
6
+ export { acrossOrganizations, createPool, whileAuthenticating, withOrg } from './db/client.js';
5
7
  export { migrate, loadMigrations } from './db/migrate.js';
6
8
  export { loadGrants, loadGroupsVersion, loadScopeTree, PostgresGroupGraph } from './authz/store.js';
7
- export { VectorStore } from './vector/search.js';
9
+ export { explainQdrant, VectorStore } from './vector/search.js';
8
10
  export { buildHybridQuery, collectionConfig, collectionName, PAYLOAD_INDEXES, vectorName } from './vector/query.js';
9
11
  export { Counter, Gauge, Histogram, Registry, createMetrics } from './metrics.js';
10
12
  export { collectDatabaseGauges } from './observability.js';
13
+ export { Redis, RedisError } from './redis.js';
14
+ export { reindexProgress, toStateJson, fromStateJson } from './reindex.js';
15
+ export { hashingLoad, hashPassword, needsRehash, spendVerificationTime, TooBusy, verifyPassword, } from './passwords.js';
16
+ export { installGuards, onListenError } from './lifecycle.js';
11
17
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,cAAc,kBAAkB,CAAA;AAChC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAErD,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAEpD,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AACzD,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACnG,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAEhD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,cAAc,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAEnH,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAEjF,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,cAAc,kBAAkB,CAAA;AAChC,OAAO,EACL,YAAY,EACZ,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,uBAAuB,EACvB,iBAAiB,EACjB,yBAAyB,GAC1B,MAAM,eAAe,CAAA;AAEtB,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAClE,OAAO,EAAE,yBAAyB,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAA;AAI/E,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAE9F,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AACzD,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACnG,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAE/D,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,cAAc,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAEnH,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAEjF,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAA;AAC1D,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAE9C,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAE1E,OAAO,EACL,WAAW,EACX,YAAY,EACZ,WAAW,EACX,qBAAqB,EACrB,OAAO,EACP,cAAc,GACf,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * What every process does when it is asked to stop, and when it is about to
3
+ * die for a reason nobody wrote down.
4
+ *
5
+ * Three processes ship here — api, mcp, worker — and none of them had any of
6
+ * this. The consequences were all of the same shape: a failure that produced no
7
+ * log line, so the operator saw a container restart and had nothing to read.
8
+ *
9
+ * - **No `unhandledRejection` handler.** Node terminates the process on one,
10
+ * with a raw stack on stderr and no service name, no timestamp in the format
11
+ * every other line uses, and nothing to join to a request.
12
+ * - **No `error` listener on `listen`.** `EADDRINUSE` is emitted on the server
13
+ * *after* `main()` has already resolved, so `main().catch` never sees it and
14
+ * the careful ConfigError path — which exits 2 with an explanation — is
15
+ * bypassed by the one startup failure an operator hits most.
16
+ * - **No deadline on shutdown.** `server.close()` waits for in-flight requests
17
+ * with no upper bound. One request blocked on a slow dependency means the
18
+ * callback never runs, the pool is never released, and the orchestrator
19
+ * SIGKILLs at the end of its grace period — turning every rolling deploy into
20
+ * an abrupt one, silently.
21
+ */
22
+ export interface Guards {
23
+ /** Named in every line, so two processes in one log stream are tellable apart. */
24
+ readonly service: string;
25
+ /**
26
+ * Release what the process holds. Called once, with a deadline.
27
+ *
28
+ * Whatever it does, it must not be the only thing standing between the
29
+ * process and exiting: if it hangs, the deadline below exits anyway.
30
+ */
31
+ readonly shutdown?: () => Promise<void> | void;
32
+ /** How long `shutdown` gets. Shorter than any orchestrator's grace period. */
33
+ readonly graceMs?: number;
34
+ /** Injected in tests. Nothing else should be replacing this. */
35
+ readonly exit?: (code: number) => void;
36
+ }
37
+ /**
38
+ * Install the handlers. Returns a `stop` to call from a signal handler.
39
+ *
40
+ * Idempotent: a second SIGTERM while shutting down is ignored rather than
41
+ * starting a second shutdown, because an orchestrator that sends one and then
42
+ * loses patience sends another.
43
+ */
44
+ export declare function installGuards(guards: Guards): {
45
+ stop: (signal: string) => void;
46
+ };
47
+ /**
48
+ * Fail a `listen` the way every other startup failure fails.
49
+ *
50
+ * `server.listen(port, cb)` reports a bound port through the callback and a
51
+ * refusal through an `error` event — which arrives after `main()` has resolved,
52
+ * so nothing was catching it.
53
+ */
54
+ export declare function onListenError(server: {
55
+ on(event: 'error', listener: (error: NodeJS.ErrnoException) => void): unknown;
56
+ }, service: string, port: number, exit?: (code: number) => void): void;
57
+ //# sourceMappingURL=lifecycle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../lifecycle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,MAAM,WAAW,MAAM;IACrB,kFAAkF;IAClF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IAC9C,8EAA8E;IAC9E,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;IACzB,gEAAgE;IAChE,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CACvC;AAMD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,CAmDhF;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE;IAAE,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,cAAc,KAAK,IAAI,GAAG,OAAO,CAAA;CAAE,EACzF,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAmC,GAC1D,IAAI,CAWN"}