@nacre.work/core 0.1.0 → 0.3.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 (78) hide show
  1. package/dist/audit.d.ts +41 -0
  2. package/dist/audit.d.ts.map +1 -0
  3. package/dist/audit.js +18 -0
  4. package/dist/audit.js.map +1 -0
  5. package/dist/authz/cache.d.ts +20 -0
  6. package/dist/authz/cache.d.ts.map +1 -1
  7. package/dist/authz/cache.js +29 -0
  8. package/dist/authz/cache.js.map +1 -1
  9. package/dist/authz/index.d.ts +1 -2
  10. package/dist/authz/index.d.ts.map +1 -1
  11. package/dist/authz/index.js +1 -2
  12. package/dist/authz/index.js.map +1 -1
  13. package/dist/config.d.ts +132 -5
  14. package/dist/config.d.ts.map +1 -1
  15. package/dist/config.js +439 -22
  16. package/dist/config.js.map +1 -1
  17. package/dist/db/migrate.d.ts +45 -0
  18. package/dist/db/migrate.d.ts.map +1 -1
  19. package/dist/db/migrate.js +61 -0
  20. package/dist/db/migrate.js.map +1 -1
  21. package/dist/extensions.d.ts +298 -0
  22. package/dist/extensions.d.ts.map +1 -0
  23. package/dist/extensions.js +246 -0
  24. package/dist/extensions.js.map +1 -0
  25. package/dist/index.d.ts +16 -6
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +9 -4
  28. package/dist/index.js.map +1 -1
  29. package/dist/lifecycle.d.ts.map +1 -1
  30. package/dist/lifecycle.js +13 -26
  31. package/dist/lifecycle.js.map +1 -1
  32. package/dist/logging.d.ts +46 -0
  33. package/dist/logging.d.ts.map +1 -0
  34. package/dist/logging.js +110 -0
  35. package/dist/logging.js.map +1 -0
  36. package/dist/metrics.d.ts +11 -7
  37. package/dist/metrics.d.ts.map +1 -1
  38. package/dist/metrics.js +32 -7
  39. package/dist/metrics.js.map +1 -1
  40. package/dist/migrations/0014_retired_collections.sql +68 -0
  41. package/dist/migrations/0015_reference_queries.sql +97 -0
  42. package/dist/migrations/0016_drop_acl_tag_cache.sql +62 -0
  43. package/dist/migrations/0017_drop_workspace_admin_role.sql +30 -0
  44. package/dist/migrations/0018_group_members_nulls_not_distinct.sql +46 -0
  45. package/dist/migrations/0019_embedding_provider_write_guard.sql +58 -0
  46. package/dist/multipart.d.ts +55 -0
  47. package/dist/multipart.d.ts.map +1 -0
  48. package/dist/multipart.js +158 -0
  49. package/dist/multipart.js.map +1 -0
  50. package/dist/oauth.d.ts +10 -0
  51. package/dist/oauth.d.ts.map +1 -1
  52. package/dist/oauth.js +10 -0
  53. package/dist/oauth.js.map +1 -1
  54. package/dist/observability.d.ts.map +1 -1
  55. package/dist/observability.js +43 -46
  56. package/dist/observability.js.map +1 -1
  57. package/dist/reindex.d.ts +44 -0
  58. package/dist/reindex.d.ts.map +1 -1
  59. package/dist/reindex.js +49 -0
  60. package/dist/reindex.js.map +1 -1
  61. package/dist/s3.d.ts +111 -0
  62. package/dist/s3.d.ts.map +1 -0
  63. package/dist/s3.js +242 -0
  64. package/dist/s3.js.map +1 -0
  65. package/dist/tsconfig.tsbuildinfo +1 -1
  66. package/dist/vector/query.d.ts +7 -9
  67. package/dist/vector/query.d.ts.map +1 -1
  68. package/dist/vector/query.js +7 -6
  69. package/dist/vector/query.js.map +1 -1
  70. package/dist/vector/search.d.ts +86 -1
  71. package/dist/vector/search.d.ts.map +1 -1
  72. package/dist/vector/search.js +185 -1
  73. package/dist/vector/search.js.map +1 -1
  74. package/package.json +1 -1
  75. package/dist/authz/tags.d.ts +0 -40
  76. package/dist/authz/tags.d.ts.map +0 -1
  77. package/dist/authz/tags.js +0 -48
  78. package/dist/authz/tags.js.map +0 -1
package/dist/index.d.ts CHANGED
@@ -2,16 +2,26 @@ export * from './types.js';
2
2
  export * from './authz/index.js';
3
3
  export { parseFilters, parseMetadata, MetadataError, MAX_METADATA_KEYS, MAX_METADATA_KEY_LENGTH, MAX_METADATA_LIST, MAX_METADATA_VALUE_LENGTH, } from './metadata.js';
4
4
  export type { Metadata } from './metadata.js';
5
- export { loadConfig, loadJwtKeys, ConfigError } from './config.js';
6
- export { protectedResourceMetadata, PROTECTED_RESOURCE_PATH } from './oauth.js';
5
+ export { loadConfig, loadJwtKeys, loadJwtVerification, keyFingerprint, ConfigError } from './config.js';
6
+ export { protectedResourceMetadata, PROTECTED_RESOURCE_PATH, JWKS_PATH } from './oauth.js';
7
+ export { activeResolver, admitIngest, ADMIN_PREFIX, adminRoutes, auditSinks, authProviders, loadModules, loadedExtensions, mountAdminRoutes, registerAuditSink, registerAuthProvider, registerAuthzResolver, registerIngestGate, resetExtensionsForTests, withAuditSinks, withLoadingModuleForTests, } from './extensions.js';
8
+ export type { AdminRequest, AdminResponse, AdminRoute, AuditEvent, AuditSink, AuditWriter, AuthProvider, AuthzResolver, IngestContext, IngestGate, IngestRefusal, IngestVerdict, ResolvedPrincipal, } from './extensions.js';
7
9
  export type { ProtectedResourceMetadata } from './oauth.js';
8
- export type { JwtKeys } from './config.js';
10
+ export type { JwtKeys, JwtVerification } from './config.js';
9
11
  export type { Config } from './config.js';
10
12
  export { acrossOrganizations, createPool, whileAuthenticating, withOrg } from './db/client.js';
11
13
  export type { DbOptions, WithOrgOptions } from './db/client.js';
12
14
  export { migrate, loadMigrations } from './db/migrate.js';
13
15
  export { loadGrants, loadGroupsVersion, loadScopeTree, PostgresGroupGraph } from './authz/store.js';
14
- export { explainQdrant, VectorStore } from './vector/search.js';
16
+ export { explainQdrant, MetadataIndexer, METADATA_INDEX_LIMIT, VectorStore } from './vector/search.js';
17
+ export { MAX_AUDITED_QUERY, queryAudit } from './audit.js';
18
+ export { MAX_PARTS, MAX_PART_HEADER_BYTES, MultipartError, multipartBoundary, parseMultipart, } from './multipart.js';
19
+ export type { MultipartPart } from './multipart.js';
20
+ export type { QueryAudit } from './audit.js';
21
+ export { configureLogging, createLogger, logger } from './logging.js';
22
+ export type { Logger, LoggerOptions, LogFormat, LogLevel } from './logging.js';
23
+ export { documentKey, S3, S3Error } from './s3.js';
24
+ export type { S3Options } from './s3.js';
15
25
  export type { Hit, SearchRequest, VectorStoreOptions } from './vector/search.js';
16
26
  export { buildHybridQuery, collectionConfig, collectionName, PAYLOAD_INDEXES, vectorName } from './vector/query.js';
17
27
  export type { Branch, HybridQuery } from './vector/query.js';
@@ -20,8 +30,8 @@ export type { Labels, Metrics } from './metrics.js';
20
30
  export { collectDatabaseGauges } from './observability.js';
21
31
  export { Redis, RedisError } from './redis.js';
22
32
  export type { RedisOptions } from './redis.js';
23
- export { reindexProgress, toStateJson, fromStateJson } from './reindex.js';
24
- export type { ReindexState } from './reindex.js';
33
+ export { reindexProgress, toStateJson, toCheckJson, fromStateJson } from './reindex.js';
34
+ export type { ReindexState, ReindexCheck } from './reindex.js';
25
35
  export { hashingLoad, hashPassword, needsRehash, spendVerificationTime, TooBusy, verifyPassword, } from './passwords.js';
26
36
  export { installGuards, onListenError } from './lifecycle.js';
27
37
  export type { Guards } from './lifecycle.js';
@@ -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,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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,17 +1,22 @@
1
1
  export * from './types.js';
2
2
  export * from './authz/index.js';
3
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';
4
+ export { loadConfig, loadJwtKeys, loadJwtVerification, keyFingerprint, ConfigError } from './config.js';
5
+ export { protectedResourceMetadata, PROTECTED_RESOURCE_PATH, JWKS_PATH } from './oauth.js';
6
+ export { activeResolver, admitIngest, ADMIN_PREFIX, adminRoutes, auditSinks, authProviders, loadModules, loadedExtensions, mountAdminRoutes, registerAuditSink, registerAuthProvider, registerAuthzResolver, registerIngestGate, resetExtensionsForTests, withAuditSinks, withLoadingModuleForTests, } from './extensions.js';
6
7
  export { acrossOrganizations, createPool, whileAuthenticating, withOrg } from './db/client.js';
7
8
  export { migrate, loadMigrations } from './db/migrate.js';
8
9
  export { loadGrants, loadGroupsVersion, loadScopeTree, PostgresGroupGraph } from './authz/store.js';
9
- export { explainQdrant, VectorStore } from './vector/search.js';
10
+ export { explainQdrant, MetadataIndexer, METADATA_INDEX_LIMIT, VectorStore } from './vector/search.js';
11
+ export { MAX_AUDITED_QUERY, queryAudit } from './audit.js';
12
+ export { MAX_PARTS, MAX_PART_HEADER_BYTES, MultipartError, multipartBoundary, parseMultipart, } from './multipart.js';
13
+ export { configureLogging, createLogger, logger } from './logging.js';
14
+ export { documentKey, S3, S3Error } from './s3.js';
10
15
  export { buildHybridQuery, collectionConfig, collectionName, PAYLOAD_INDEXES, vectorName } from './vector/query.js';
11
16
  export { Counter, Gauge, Histogram, Registry, createMetrics } from './metrics.js';
12
17
  export { collectDatabaseGauges } from './observability.js';
13
18
  export { Redis, RedisError } from './redis.js';
14
- export { reindexProgress, toStateJson, fromStateJson } from './reindex.js';
19
+ export { reindexProgress, toStateJson, toCheckJson, fromStateJson } from './reindex.js';
15
20
  export { hashingLoad, hashPassword, needsRehash, spendVerificationTime, TooBusy, verifyPassword, } from './passwords.js';
16
21
  export { installGuards, onListenError } from './lifecycle.js';
17
22
  //# 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,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"}
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,mBAAmB,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACvG,OAAO,EAAE,yBAAyB,EAAE,uBAAuB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAC1F,OAAO,EACL,cAAc,EACd,WAAW,EACX,YAAY,EACZ,WAAW,EACX,UAAU,EACV,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,oBAAoB,EACpB,qBAAqB,EACrB,kBAAkB,EAClB,uBAAuB,EACvB,cAAc,EACd,yBAAyB,GAC1B,MAAM,iBAAiB,CAAA;AAmBxB,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,eAAe,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACtG,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAC1D,OAAO,EACL,SAAS,EACT,qBAAqB,EACrB,cAAc,EACd,iBAAiB,EACjB,cAAc,GACf,MAAM,gBAAgB,CAAA;AAGvB,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAErE,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAGlD,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,WAAW,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAEvF,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"}
@@ -1 +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"}
1
+ {"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../lifecycle.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;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;AAkBD;;;;;;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"}
package/dist/lifecycle.js CHANGED
@@ -1,26 +1,13 @@
1
+ import { logger } from './logging.js';
1
2
  /**
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.
3
+ * Through the process logger, so `NACRE_LOG_FORMAT` reaches these too.
4
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.
5
+ * The level is a parameter rather than always `error`: a clean shutdown is not
6
+ * a failure, and reporting it as one is how a dashboard counting errors turns
7
+ * every deploy into an incident. What is an error stays an error.
21
8
  */
22
- const log = (service, msg, extra = {}) => {
23
- console.error(JSON.stringify({ msg, service, ...extra }));
9
+ const log = (level, service, msg, extra = {}) => {
10
+ logger[level](msg, { service, ...extra });
24
11
  };
25
12
  /**
26
13
  * Install the handlers. Returns a `stop` to call from a signal handler.
@@ -37,11 +24,11 @@ export function installGuards(guards) {
37
24
  // nobody awaited failing means the process is in a state its author did not
38
25
  // plan for, and continuing from there is how one bad request becomes a
39
26
  // corrupt one.
40
- log(service, 'unhandled rejection; exiting', { error: String(reason).slice(0, 500) });
27
+ log('error', service, 'unhandled rejection; exiting', { error: String(reason).slice(0, 500) });
41
28
  exit(1);
42
29
  });
43
30
  process.on('uncaughtException', (error) => {
44
- log(service, 'uncaught exception; exiting', {
31
+ log('error', service, 'uncaught exception; exiting', {
45
32
  error: String(error).slice(0, 500),
46
33
  stack: error.stack?.split('\n').slice(1, 6).join(' | '),
47
34
  });
@@ -51,11 +38,11 @@ export function installGuards(guards) {
51
38
  if (stopping)
52
39
  return;
53
40
  stopping = true;
54
- log(service, 'shutting down', { signal });
41
+ log('info', service, 'shutting down', { signal });
55
42
  // The deadline runs whatever happens, and `unref` keeps it from being the
56
43
  // thing that holds the process open once everything else has let go.
57
44
  const deadline = setTimeout(() => {
58
- log(service, 'shutdown did not finish in time; exiting anyway', { grace_ms: graceMs });
45
+ log('error', service, 'shutdown did not finish in time; exiting anyway', { grace_ms: graceMs });
59
46
  exit(1);
60
47
  }, graceMs);
61
48
  deadline.unref();
@@ -66,7 +53,7 @@ export function installGuards(guards) {
66
53
  exit(0);
67
54
  }
68
55
  catch (error) {
69
- log(service, 'shutdown failed', { error: String(error).slice(0, 500) });
56
+ log('error', service, 'shutdown failed', { error: String(error).slice(0, 500) });
70
57
  clearTimeout(deadline);
71
58
  exit(1);
72
59
  }
@@ -90,7 +77,7 @@ export function onListenError(server, service, port, exit = (code) => process.ex
90
77
  : error.code === 'EACCES'
91
78
  ? `port ${port} needs privileges this process does not have`
92
79
  : String(error);
93
- log(service, 'could not listen', { port, detail });
80
+ log('error', service, 'could not listen', { port, detail });
94
81
  exit(2);
95
82
  });
96
83
  }
@@ -1 +1 @@
1
- {"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../lifecycle.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../lifecycle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Logging, at the level and in the format the deployment asked for.
3
+ *
4
+ * `NACRE_LOG_LEVEL` and `NACRE_LOG_FORMAT` were validated at startup and read
5
+ * by nothing: every process wrote structured JSON at one level, so an operator
6
+ * setting `warn` still got every `info` line and one setting `text` still got
7
+ * JSON. Both are among the first variables anyone sets.
8
+ *
9
+ * ─── what does not go through here ───
10
+ *
11
+ * **Configuration errors.** They happen before a configuration exists, so there
12
+ * is nothing to ask about the level, and a process that cannot start must say
13
+ * why whatever anyone configured. Those stay on `console.error`.
14
+ *
15
+ * **`init` and `migrate` output.** Those are commands a person runs and reads —
16
+ * the printed org id, the applied migrations. That is program output, like
17
+ * `--help`, and putting it behind a level would mean `NACRE_LOG_LEVEL=warn`
18
+ * silently swallows the one line the command exists to produce.
19
+ *
20
+ * ─── what a field may hold ───
21
+ *
22
+ * The same rule as everywhere else in this repository: no document contents and
23
+ * no full query text. This module cannot enforce that — it takes what it is
24
+ * given — so it is stated where the fields are named rather than here.
25
+ */
26
+ export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
27
+ export type LogFormat = 'json' | 'text';
28
+ export interface Logger {
29
+ debug(message: string, fields?: Record<string, unknown>): void;
30
+ info(message: string, fields?: Record<string, unknown>): void;
31
+ warn(message: string, fields?: Record<string, unknown>): void;
32
+ error(message: string, fields?: Record<string, unknown>): void;
33
+ }
34
+ export interface LoggerOptions {
35
+ readonly level: LogLevel;
36
+ readonly format: LogFormat;
37
+ /** Injected so a test can assert on a line rather than on a moving timestamp. */
38
+ readonly now?: () => Date;
39
+ /** Injected for the same reason. Defaults to the console. */
40
+ readonly write?: (level: LogLevel, line: string) => void;
41
+ }
42
+ export declare function createLogger(options: LoggerOptions): Logger;
43
+ export declare function configureLogging(options: LoggerOptions): void;
44
+ /** Delegates on every call, so a module may hold this and still see the change. */
45
+ export declare const logger: Logger;
46
+ //# sourceMappingURL=logging.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logging.d.ts","sourceRoot":"","sources":["../logging.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;AAC1D,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,CAAA;AAIvC,MAAM,WAAW,MAAM;IACrB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;IAC9D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;IAC7D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;IAC7D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;CAC/D;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAA;IACxB,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAA;IAC1B,iFAAiF;IACjF,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,IAAI,CAAA;IACzB,6DAA6D;IAC7D,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CACzD;AA+BD,wBAAgB,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CA6B3D;AAiBD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAE7D;AAED,mFAAmF;AACnF,eAAO,MAAM,MAAM,EAAE,MAKpB,CAAA"}
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Logging, at the level and in the format the deployment asked for.
3
+ *
4
+ * `NACRE_LOG_LEVEL` and `NACRE_LOG_FORMAT` were validated at startup and read
5
+ * by nothing: every process wrote structured JSON at one level, so an operator
6
+ * setting `warn` still got every `info` line and one setting `text` still got
7
+ * JSON. Both are among the first variables anyone sets.
8
+ *
9
+ * ─── what does not go through here ───
10
+ *
11
+ * **Configuration errors.** They happen before a configuration exists, so there
12
+ * is nothing to ask about the level, and a process that cannot start must say
13
+ * why whatever anyone configured. Those stay on `console.error`.
14
+ *
15
+ * **`init` and `migrate` output.** Those are commands a person runs and reads —
16
+ * the printed org id, the applied migrations. That is program output, like
17
+ * `--help`, and putting it behind a level would mean `NACRE_LOG_LEVEL=warn`
18
+ * silently swallows the one line the command exists to produce.
19
+ *
20
+ * ─── what a field may hold ───
21
+ *
22
+ * The same rule as everywhere else in this repository: no document contents and
23
+ * no full query text. This module cannot enforce that — it takes what it is
24
+ * given — so it is stated where the fields are named rather than here.
25
+ */
26
+ const ORDER = { debug: 10, info: 20, warn: 30, error: 40 };
27
+ /**
28
+ * `warn` and `error` to stderr, the rest to stdout.
29
+ *
30
+ * Not a style choice: a container that pipes stdout into a log shipper and
31
+ * leaves stderr on the terminal is a real deployment, and a failure that went
32
+ * to stdout with everything else is a failure nobody saw at 3am.
33
+ */
34
+ function toConsole(level, line) {
35
+ if (level === 'warn')
36
+ console.warn(line);
37
+ else if (level === 'error')
38
+ console.error(line);
39
+ else
40
+ console.log(line);
41
+ }
42
+ /**
43
+ * `key=value`, with anything ambiguous quoted.
44
+ *
45
+ * Text format is for a person reading a terminal, so it is optimised for
46
+ * scanning rather than for parsing — but a value containing a space or a quote
47
+ * still has to survive, or two fields read as one.
48
+ */
49
+ function render(value) {
50
+ if (value === null)
51
+ return 'null';
52
+ if (typeof value === 'string') {
53
+ return /[\s"=]/.test(value) ? JSON.stringify(value) : value;
54
+ }
55
+ if (typeof value === 'number' || typeof value === 'boolean')
56
+ return String(value);
57
+ return JSON.stringify(value);
58
+ }
59
+ export function createLogger(options) {
60
+ const threshold = ORDER[options.level];
61
+ const now = options.now ?? (() => new Date());
62
+ const write = options.write ?? toConsole;
63
+ const emit = (level, message, fields) => {
64
+ if (ORDER[level] < threshold)
65
+ return;
66
+ const ts = now().toISOString();
67
+ if (options.format === 'json') {
68
+ // `msg` first and named the same as before, because every existing line
69
+ // was `{"msg": ...}` and anything already grepping for it should keep
70
+ // working. The level and timestamp are additions, not a replacement.
71
+ write(level, JSON.stringify({ level, ts, msg: message, ...fields }));
72
+ return;
73
+ }
74
+ const rest = Object.entries(fields ?? {})
75
+ .map(([key, value]) => ` ${key}=${render(value)}`)
76
+ .join('');
77
+ write(level, `${ts} ${level.toUpperCase().padEnd(5)} ${message}${rest}`);
78
+ };
79
+ return {
80
+ debug: (m, f) => emit('debug', m, f),
81
+ info: (m, f) => emit('info', m, f),
82
+ warn: (m, f) => emit('warn', m, f),
83
+ error: (m, f) => emit('error', m, f),
84
+ };
85
+ }
86
+ /**
87
+ * The process-wide logger.
88
+ *
89
+ * A module-level default that `configureLogging` replaces once the
90
+ * configuration is read. Deliberately the one piece of global state in this
91
+ * repository, and it is safe to be: it carries no authorization semantics, the
92
+ * worst a wrong one does is print at the wrong level, and the alternative —
93
+ * threading a logger through every adapter and port — buys nothing a reader of
94
+ * those signatures would want.
95
+ *
96
+ * The default is `info`/`json`, so a module that logs before `configureLogging`
97
+ * runs behaves exactly as the whole system did before this existed.
98
+ */
99
+ let current = createLogger({ level: 'info', format: 'json' });
100
+ export function configureLogging(options) {
101
+ current = createLogger(options);
102
+ }
103
+ /** Delegates on every call, so a module may hold this and still see the change. */
104
+ export const logger = {
105
+ debug: (m, f) => current.debug(m, f),
106
+ info: (m, f) => current.info(m, f),
107
+ warn: (m, f) => current.warn(m, f),
108
+ error: (m, f) => current.error(m, f),
109
+ };
110
+ //# sourceMappingURL=logging.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logging.js","sourceRoot":"","sources":["../logging.ts"],"names":[],"mappings":"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"}
package/dist/metrics.d.ts CHANGED
@@ -49,7 +49,7 @@ export declare class Registry {
49
49
  register<T extends Metric>(metric: T): T;
50
50
  /**
51
51
  * A function run before every scrape, for values that are queries rather than
52
- * counters — document counts, the propagation lag, pending tombstones.
52
+ * counters — document counts and pending tombstones.
53
53
  */
54
54
  collect(fn: () => Promise<void>): void;
55
55
  /**
@@ -72,22 +72,26 @@ export declare class Registry {
72
72
  /**
73
73
  * The metrics docs/config.md requires.
74
74
  *
75
- * `nacre_acl_propagation_lag_seconds` is the one with an alert on it, and the
76
- * reason is worth restating where the metric is defined: it is the only
77
- * external evidence that invariant I4 — a revoked grant reflected within the
78
- * SLA — still holds. Everything else here describes how the system is doing.
79
- * This one describes whether it is still correct.
75
+ * There is deliberately no `nacre_acl_propagation_lag_seconds` here. It was the
76
+ * one metric with an alert on it, back when invariant I4 was temporal — a
77
+ * revoked grant reflected *within an SLA*, with a cache the worker had to catch
78
+ * up. Migration 0016 removed that cache: the permitted set is computed per
79
+ * request from the grants, so I4 is structural now and there is no lag to
80
+ * measure. A gauge that reported one would be reporting on a subsystem that no
81
+ * longer exists.
80
82
  */
81
83
  export declare function createMetrics(registry: Registry): {
82
84
  searchDuration: Histogram;
83
85
  searchResults: Counter;
84
86
  aclDenials: Counter;
85
87
  authFailures: Counter;
86
- aclPropagationLag: Gauge;
88
+ rateLimitUnavailable: Counter;
87
89
  ingestDuration: Histogram;
88
90
  documents: Gauge;
89
91
  reindexProgress: Gauge;
90
92
  tombstonesPending: Gauge;
93
+ processingAge: Gauge;
94
+ collectionsRetired: Gauge;
91
95
  };
92
96
  export type Metrics = ReturnType<typeof createMetrics>;
93
97
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../metrics.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;AAgBrD,UAAU,MAAM;IACd,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,GAAG,WAAW,CAAA;IAChD,MAAM,IAAI,MAAM,EAAE,CAAA;CACnB;AAED,qBAAa,OAAQ,YAAW,MAAM;;IAKlC,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM;IALvB,QAAQ,CAAC,IAAI,EAAG,SAAS,CAAS;gBAIvB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM;IAKvB,GAAG,CAAC,MAAM,GAAE,MAAW,EAAE,EAAE,SAAI,GAAG,IAAI;IAOtC,MAAM,IAAI,MAAM,EAAE;CAOnB;AAED,qBAAa,KAAM,YAAW,MAAM;;IAKhC,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM;IALvB,QAAQ,CAAC,IAAI,EAAG,OAAO,CAAS;gBAIrB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM;IAKvB,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,GAAE,MAAW,GAAG,IAAI;IAI7C,KAAK,IAAI,IAAI;IAIb,MAAM,IAAI,MAAM,EAAE;CAInB;AAID,qBAAa,SAAU,YAAW,MAAM;;IAKpC,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE;IANrC,QAAQ,CAAC,IAAI,EAAG,WAAW,CAAS;gBAIzB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,SAAS,MAAM,EAAoB;IAKvD,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,GAAE,MAAW,GAAG,IAAI;IAgBnD,2EAA2E;IACrE,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAS/D,MAAM,IAAI,MAAM,EAAE;CAmBnB;AAED,qBAAa,QAAQ;;IAInB,QAAQ,CAAC,CAAC,SAAS,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC;IAQxC;;;OAGG;IACH,OAAO,CAAC,EAAE,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAItC;;;;;;;;;;;;;OAaG;IACH,MAAM,CAAC,QAAQ,CAAC,cAAc,SAAS;IAwCjC,MAAM,CAAC,GAAG,GAAE,MAAmB,GAAG,OAAO,CAAC,MAAM,CAAC;CAWxD;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,QAAQ;;;;;;;;;;EAgE/C;AAED,MAAM,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAA"}
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../metrics.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;AAgBrD,UAAU,MAAM;IACd,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,GAAG,WAAW,CAAA;IAChD,MAAM,IAAI,MAAM,EAAE,CAAA;CACnB;AAED,qBAAa,OAAQ,YAAW,MAAM;;IAKlC,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM;IALvB,QAAQ,CAAC,IAAI,EAAG,SAAS,CAAS;gBAIvB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM;IAKvB,GAAG,CAAC,MAAM,GAAE,MAAW,EAAE,EAAE,SAAI,GAAG,IAAI;IAOtC,MAAM,IAAI,MAAM,EAAE;CAOnB;AAED,qBAAa,KAAM,YAAW,MAAM;;IAKhC,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM;IALvB,QAAQ,CAAC,IAAI,EAAG,OAAO,CAAS;gBAIrB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM;IAKvB,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,GAAE,MAAW,GAAG,IAAI;IAI7C,KAAK,IAAI,IAAI;IAIb,MAAM,IAAI,MAAM,EAAE;CAInB;AAID,qBAAa,SAAU,YAAW,MAAM;;IAKpC,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE;IANrC,QAAQ,CAAC,IAAI,EAAG,WAAW,CAAS;gBAIzB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,SAAS,MAAM,EAAoB;IAKvD,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,GAAE,MAAW,GAAG,IAAI;IAgBnD,2EAA2E;IACrE,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAS/D,MAAM,IAAI,MAAM,EAAE;CAmBnB;AAED,qBAAa,QAAQ;;IAInB,QAAQ,CAAC,CAAC,SAAS,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC;IAQxC;;;OAGG;IACH,OAAO,CAAC,EAAE,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAItC;;;;;;;;;;;;;OAaG;IACH,MAAM,CAAC,QAAQ,CAAC,cAAc,SAAS;IAwCjC,MAAM,CAAC,GAAG,GAAE,MAAmB,GAAG,OAAO,CAAC,MAAM,CAAC;CAWxD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,QAAQ;;;;;;;;;;;;EAiG/C;AAED,MAAM,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAA"}
package/dist/metrics.js CHANGED
@@ -137,7 +137,7 @@ export class Registry {
137
137
  }
138
138
  /**
139
139
  * A function run before every scrape, for values that are queries rather than
140
- * counters — document counts, the propagation lag, pending tombstones.
140
+ * counters — document counts and pending tombstones.
141
141
  */
142
142
  collect(fn) {
143
143
  this.#collectors.push(fn);
@@ -208,11 +208,13 @@ _a = Registry;
208
208
  /**
209
209
  * The metrics docs/config.md requires.
210
210
  *
211
- * `nacre_acl_propagation_lag_seconds` is the one with an alert on it, and the
212
- * reason is worth restating where the metric is defined: it is the only
213
- * external evidence that invariant I4 — a revoked grant reflected within the
214
- * SLA — still holds. Everything else here describes how the system is doing.
215
- * This one describes whether it is still correct.
211
+ * There is deliberately no `nacre_acl_propagation_lag_seconds` here. It was the
212
+ * one metric with an alert on it, back when invariant I4 was temporal — a
213
+ * revoked grant reflected *within an SLA*, with a cache the worker had to catch
214
+ * up. Migration 0016 removed that cache: the permitted set is computed per
215
+ * request from the grants, so I4 is structural now and there is no lag to
216
+ * measure. A gauge that reported one would be reporting on a subsystem that no
217
+ * longer exists.
216
218
  */
217
219
  export function createMetrics(registry) {
218
220
  return {
@@ -232,7 +234,12 @@ export function createMetrics(registry) {
232
234
  // staying flat through the same window is the check that the rotation hit
233
235
  // only what it was meant to.
234
236
  authFailures: registry.register(new Counter('nacre_auth_failures_total', 'Rejected credentials, by the kind presented: missing, jwt, service_key. Never by reason — the 401 is deliberately one answer')),
235
- aclPropagationLag: registry.register(new Gauge('nacre_acl_propagation_lag_seconds', 'Age in seconds of the oldest document, per organization, whose ACL tags predate the current groups_version. Alert on max() over this. The only external evidence that invariant I4 holds')),
237
+ // Rate limiting fails open when Redis is unreachable, deliberately — it is
238
+ // availability protection, not an authorization control. That is the one
239
+ // degradation an operator has to be able to see, because the symptom is
240
+ // *silence*: requests keep flowing and nothing is being counted. Every
241
+ // increment here is a request that was let through unmetered.
242
+ rateLimitUnavailable: registry.register(new Counter('nacre_rate_limit_unavailable_total', 'Requests allowed because the rate-limit check could not run (Redis unreachable), by resource')),
236
243
  ingestDuration: registry.register(new Histogram('nacre_ingest_duration_seconds', 'Indexing latency, by stage')),
237
244
  documents: registry.register(new Gauge('nacre_documents_total', 'Documents, by organization and status')),
238
245
  // Specified in docs/config.md and registered by nothing until there was a
@@ -249,6 +256,24 @@ export function createMetrics(registry) {
249
256
  // rather than a layer at zero: a real layer always carries a `layer` label.
250
257
  reindexProgress: registry.register(new Gauge('nacre_reindex_progress_ratio', 'How far a layer is through a reindex, 0 to 1. Absent when no reindex has run; 0 means one started and has moved nothing')),
251
258
  tombstonesPending: registry.register(new Gauge('nacre_tombstones_pending_total', 'Deleted documents whose vectors are not yet purged. Climbing means garbage collection is losing')),
259
+ // The one thing a wedged worker leaves outside its own log. The worker
260
+ // serves no port and has no registry — by design, so that a liveness check
261
+ // is not a second surface with an auth story — so a worker stuck inside one
262
+ // document is invisible except in the log line that stopped. This is the
263
+ // age of the oldest document currently claimed for indexing, per
264
+ // organization, computed on the API's side from `documents.claimed_at`. A
265
+ // series appears only while something is in flight; one that climbs past
266
+ // NACRE_INDEX_LEASE is a worker wedged in a document, or gone with the
267
+ // reaper not reclaiming it — and either way the document behind it is not
268
+ // getting indexed.
269
+ processingAge: registry.register(new Gauge('nacre_document_processing_age_seconds', 'Age of the oldest document a worker is currently indexing, by organization. Absent when nothing is in flight; past the index lease means a worker is wedged or gone')),
270
+ // A gauge and not a counter, because the question an operator has is "how
271
+ // much disk is a finished migration still holding", not "how many have I
272
+ // reclaimed since this process started". Each one retained is a full copy
273
+ // of an organization's vectors, so a number that stays high is the signal —
274
+ // and a number that never falls means the sweep is not running at all,
275
+ // which is the state this whole table replaced.
276
+ collectionsRetired: registry.register(new Gauge('nacre_collections_retired_total', 'Superseded collections still held for the reindex rollback window, by organization. Each is a full copy of that organization vectors')),
252
277
  };
253
278
  }
254
279
  //# sourceMappingURL=metrics.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"metrics.js","sourceRoot":"","sources":["../metrics.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"metrics.js","sourceRoot":"","sources":["../metrics.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ -- The collections a reindex leaves behind.
2
+ --
3
+ -- Every model migration builds a new collection, copies every point across, and
4
+ -- moves `organizations.vector_collection` at the end. The old collection is
5
+ -- still there afterwards, holding a full copy of the organization's vectors,
6
+ -- and nothing has ever removed one. `runbooks/rollback-layer-reindex.md` says
7
+ -- so in as many words — "каждая переиндексация оставляет коллекцию … ничего их
8
+ -- не подчищает" — and hands the operator a shell loop.
9
+ --
10
+ -- That loop is also the wrong rule. It reads every collection Qdrant has,
11
+ -- subtracts the ones an organization points at, and calls the difference
12
+ -- orphaned. During a copy the *target* is exactly that: built, filling up, and
13
+ -- not yet pointed at by anything. Running the documented cleanup while a
14
+ -- migration is copying deletes the migration.
15
+ --
16
+ -- ─── so the record is kept, not derived ───
17
+ --
18
+ -- A row is written when the pointer moves, naming the collection it moved away
19
+ -- from. Nothing else is ever a candidate for deletion. A copy in progress has
20
+ -- no row, because the row is written by the same statement that supersedes it,
21
+ -- so the dangerous case is not merely avoided — it is unrepresentable.
22
+ --
23
+ -- The delay is the point of the window, not an implementation detail: D2 in the
24
+ -- rollback runbook is "move the pointer back", which is instant and only works
25
+ -- while the old collection still exists. `NACRE_COLLECTION_RETENTION_DAYS` is
26
+ -- how long that stays possible.
27
+ --
28
+ -- ─── what this does not cover ───
29
+ --
30
+ -- A copy that was abandoned — the reindex failed partway — leaves a target
31
+ -- collection with no row and no pointer, and the sweep will not touch it. That
32
+ -- is deliberate for now: the safe rule is "delete only what a successful
33
+ -- migration superseded", and widening it to "delete anything unreferenced"
34
+ -- brings back the race above. The runbook keeps its manual procedure for that
35
+ -- case alone.
36
+
37
+ CREATE TABLE retired_collections (
38
+ org_id uuid NOT NULL REFERENCES organizations (id) ON DELETE CASCADE,
39
+ -- The Qdrant collection name, which is the whole payload of a row. Not a
40
+ -- reference to anything: by the time this matters the collection may
41
+ -- already be gone, and a dangling name is the normal end state.
42
+ name text NOT NULL,
43
+ retired_at timestamptz NOT NULL DEFAULT now(),
44
+
45
+ -- One row per name per organization. A second migration away from the same
46
+ -- collection cannot happen — the pointer only ever leaves a name once — but
47
+ -- an idempotent insert is cheaper to reason about than a proof that it
48
+ -- cannot repeat.
49
+ PRIMARY KEY (org_id, name)
50
+ );
51
+
52
+ -- The sweep asks one question: which rows are older than the window. It asks it
53
+ -- across organizations, so the index is on the timestamp alone.
54
+ CREATE INDEX retired_collections_due ON retired_collections (retired_at);
55
+
56
+ -- Tenant data, so RLS, and FORCE because ENABLE alone does not apply to the
57
+ -- owner and migrations run as the owner.
58
+ ALTER TABLE retired_collections ENABLE ROW LEVEL SECURITY;
59
+ ALTER TABLE retired_collections FORCE ROW LEVEL SECURITY;
60
+
61
+ CREATE POLICY org_isolation ON retired_collections
62
+ USING (org_id = current_setting('app.current_org')::uuid);
63
+
64
+ -- `nacre_app` inserts, because the pointer moves under `withOrg` in the worker's
65
+ -- copy phase and that runs as the application role. `nacre_worker` deletes,
66
+ -- because the sweep runs across organizations.
67
+ GRANT SELECT, INSERT ON retired_collections TO nacre_app;
68
+ GRANT SELECT, INSERT, DELETE ON retired_collections TO nacre_worker;