conexus 6.2.0__tar.gz → 6.3.0__tar.gz

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 (543) hide show
  1. {conexus-6.2.0 → conexus-6.3.0}/PKG-INFO +1 -1
  2. {conexus-6.2.0 → conexus-6.3.0}/mcpb/pyproject.toml +2 -2
  3. {conexus-6.2.0 → conexus-6.3.0}/pyproject.toml +1 -1
  4. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/db/CatalogRepository.java +50 -0
  5. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/db/ChashRepository.java +81 -15
  6. conexus-6.3.0/service/src/main/java/dev/nexus/service/db/CollectionRegistry.java +104 -0
  7. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/db/TenantScope.java +85 -0
  8. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/db/TokenCache.java +12 -2
  9. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/http/AspectHandler.java +8 -21
  10. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/http/CatalogHandler.java +4 -16
  11. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/http/ChashHandler.java +7 -2
  12. conexus-6.3.0/service/src/main/java/dev/nexus/service/http/HttpUtil.java +159 -0
  13. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/http/MemoryHandler.java +7 -2
  14. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/http/PlanHandler.java +7 -2
  15. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/http/ScratchHandler.java +7 -2
  16. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/http/SessionTokenHandler.java +7 -2
  17. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/http/TaxonomyHandler.java +4 -13
  18. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/http/TelemetryHandler.java +7 -2
  19. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/http/TokenAdminHandler.java +7 -2
  20. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/http/VectorHandler.java +7 -2
  21. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/vectors/PgVectorRepository.java +92 -34
  22. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/BridgeAddressFieldsTest.java +4 -4
  23. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/CatalogDeleteCollectionCascadeTest.java +6 -0
  24. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/CatalogRenameCollectionTest.java +7 -0
  25. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/CatalogRepositoryTest.java +30 -0
  26. conexus-6.3.0/service/src/test/java/dev/nexus/service/ChashVectorConcurrencyTest.java +367 -0
  27. conexus-6.3.0/service/src/test/java/dev/nexus/service/db/CollectionRegistryTest.java +328 -0
  28. conexus-6.3.0/service/src/test/java/dev/nexus/service/db/TenantScopeAdmissionTest.java +179 -0
  29. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/catalog/http_catalog_client.py +114 -16
  30. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/scratch.py +47 -0
  31. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/daemon/binary_install.py +1 -1
  32. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/__init__.py +56 -0
  33. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/http_scratch_store.py +17 -0
  34. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/http_vector_client.py +421 -0
  35. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/t1.py +9 -0
  36. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/doc_indexer.py +81 -4
  37. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/mcp_infra.py +27 -3
  38. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/scoring.py +24 -11
  39. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/search_engine.py +46 -3
  40. conexus-6.2.0/service/src/main/java/dev/nexus/service/http/HttpUtil.java +0 -87
  41. {conexus-6.2.0 → conexus-6.3.0}/.beads/README.md +0 -0
  42. {conexus-6.2.0 → conexus-6.3.0}/.gitignore +0 -0
  43. {conexus-6.2.0 → conexus-6.3.0}/LICENSE +0 -0
  44. {conexus-6.2.0 → conexus-6.3.0}/README.md +0 -0
  45. {conexus-6.2.0 → conexus-6.3.0}/conexus/README.md +0 -0
  46. {conexus-6.2.0 → conexus-6.3.0}/conexus/agents/_shared/README.md +0 -0
  47. {conexus-6.2.0 → conexus-6.3.0}/conexus/daemon/com.nexus.service.plist +0 -0
  48. {conexus-6.2.0 → conexus-6.3.0}/conexus/daemon/com.nexus.t2.plist +0 -0
  49. {conexus-6.2.0 → conexus-6.3.0}/conexus/daemon/com.nexus.t3.plist +0 -0
  50. {conexus-6.2.0 → conexus-6.3.0}/conexus/daemon/nexus-service.service +0 -0
  51. {conexus-6.2.0 → conexus-6.3.0}/conexus/daemon/nexus-t2.service +0 -0
  52. {conexus-6.2.0 → conexus-6.3.0}/conexus/daemon/nexus-t3.service +0 -0
  53. {conexus-6.2.0 → conexus-6.3.0}/conexus/hooks/scripts/routing/README.md +0 -0
  54. {conexus-6.2.0 → conexus-6.3.0}/conexus/plans/builtin/abstract-themes.yml +0 -0
  55. {conexus-6.2.0 → conexus-6.3.0}/conexus/plans/builtin/analyze-default.yml +0 -0
  56. {conexus-6.2.0 → conexus-6.3.0}/conexus/plans/builtin/citation-traversal.yml +0 -0
  57. {conexus-6.2.0 → conexus-6.3.0}/conexus/plans/builtin/debug-default.yml +0 -0
  58. {conexus-6.2.0 → conexus-6.3.0}/conexus/plans/builtin/document-default.yml +0 -0
  59. {conexus-6.2.0 → conexus-6.3.0}/conexus/plans/builtin/find-by-author.yml +0 -0
  60. {conexus-6.2.0 → conexus-6.3.0}/conexus/plans/builtin/hybrid-factual-lookup.yml +0 -0
  61. {conexus-6.2.0 → conexus-6.3.0}/conexus/plans/builtin/plan-author-default.yml +0 -0
  62. {conexus-6.2.0 → conexus-6.3.0}/conexus/plans/builtin/plan-inspect-default.yml +0 -0
  63. {conexus-6.2.0 → conexus-6.3.0}/conexus/plans/builtin/plan-inspect-dimensions.yml +0 -0
  64. {conexus-6.2.0 → conexus-6.3.0}/conexus/plans/builtin/plan-promote-propose.yml +0 -0
  65. {conexus-6.2.0 → conexus-6.3.0}/conexus/plans/builtin/research-default.yml +0 -0
  66. {conexus-6.2.0 → conexus-6.3.0}/conexus/plans/builtin/review-default.yml +0 -0
  67. {conexus-6.2.0 → conexus-6.3.0}/conexus/plans/builtin/traverse-then-generate.yml +0 -0
  68. {conexus-6.2.0 → conexus-6.3.0}/conexus/plans/builtin/type-scoped-search.yml +0 -0
  69. {conexus-6.2.0 → conexus-6.3.0}/conexus/plans/dimensions.yml +0 -0
  70. {conexus-6.2.0 → conexus-6.3.0}/conexus/plans/purposes.yml +0 -0
  71. {conexus-6.2.0 → conexus-6.3.0}/data/calibration/rdr-109/README.md +0 -0
  72. {conexus-6.2.0 → conexus-6.3.0}/docs/README.md +0 -0
  73. {conexus-6.2.0 → conexus-6.3.0}/docs/migration/README.md +0 -0
  74. {conexus-6.2.0 → conexus-6.3.0}/docs/rdr/README.md +0 -0
  75. {conexus-6.2.0 → conexus-6.3.0}/dt/scripts/Index Current Group in nx.applescript +0 -0
  76. {conexus-6.2.0 → conexus-6.3.0}/dt/scripts/Index Selection in nx (Knowledge).applescript +0 -0
  77. {conexus-6.2.0 → conexus-6.3.0}/dt/scripts/Index Selection in nx.applescript +0 -0
  78. {conexus-6.2.0 → conexus-6.3.0}/mcpb/src/server.py +0 -0
  79. {conexus-6.2.0 → conexus-6.3.0}/scripts/cron/README.md +0 -0
  80. {conexus-6.2.0 → conexus-6.3.0}/scripts/launchd/README.md +0 -0
  81. {conexus-6.2.0 → conexus-6.3.0}/scripts/rdr152-sandbox/README.md +0 -0
  82. {conexus-6.2.0 → conexus-6.3.0}/scripts/spikes/s04-build/src/main/java/dev/nexus/spike/s04/Main.java +0 -0
  83. {conexus-6.2.0 → conexus-6.3.0}/scripts/spikes/s04-build/src/main/resources/META-INF/native-image/reachability-metadata.json +0 -0
  84. {conexus-6.2.0 → conexus-6.3.0}/scripts/spikes/s04-build/src/main/resources/db/changelog/db.changelog-master.xml +0 -0
  85. {conexus-6.2.0 → conexus-6.3.0}/scripts/spikes/s04-build/src/main/resources/logback.xml +0 -0
  86. {conexus-6.2.0 → conexus-6.3.0}/service/README.md +0 -0
  87. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/Main.java +0 -0
  88. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/NexusService.java +0 -0
  89. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/db/AspectRepository.java +0 -0
  90. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/db/MemoryRepository.java +0 -0
  91. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/db/MigrationJobRepository.java +0 -0
  92. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/db/PlanRepository.java +0 -0
  93. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/db/PoolerModeCheck.java +0 -0
  94. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/db/SchemaMigrator.java +0 -0
  95. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/db/ScratchRepository.java +0 -0
  96. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/db/SessionPrincipal.java +0 -0
  97. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/db/TaxonomyRepository.java +0 -0
  98. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/db/TelemetryRepository.java +0 -0
  99. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/db/TenantConstants.java +0 -0
  100. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/db/TokenHashing.java +0 -0
  101. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/db/TokenStore.java +0 -0
  102. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/http/AuthFilter.java +0 -0
  103. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/http/HealthHandler.java +0 -0
  104. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/http/MigrationHandler.java +0 -0
  105. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/http/RequestContext.java +0 -0
  106. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/http/VersionHandler.java +0 -0
  107. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/http/WhoamiHandler.java +0 -0
  108. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/nativeimage/JooqRecordReflectionFeature.java +0 -0
  109. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/resolver/ChromaSchemeHandler.java +0 -0
  110. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/resolver/ChunkTextFetcher.java +0 -0
  111. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/resolver/HttpsSchemeHandler.java +0 -0
  112. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/resolver/ResolveResult.java +0 -0
  113. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/resolver/UnknownSchemeException.java +0 -0
  114. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/resolver/UriSchemeHandler.java +0 -0
  115. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/resolver/UriSchemeResolverRegistry.java +0 -0
  116. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/vectors/Bge768Embedder.java +0 -0
  117. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/vectors/CceEmbedder.java +0 -0
  118. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/vectors/ChromaQuotaValidator.java +0 -0
  119. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/vectors/ChromaRestClient.java +0 -0
  120. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/vectors/EgressProxy.java +0 -0
  121. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/vectors/EmbedResult.java +0 -0
  122. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/vectors/Embedder.java +0 -0
  123. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/vectors/EmbedderRouter.java +0 -0
  124. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/vectors/EmbeddingModelUnavailableException.java +0 -0
  125. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/vectors/LocalChromaServer.java +0 -0
  126. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/vectors/OnnxEmbedder.java +0 -0
  127. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/vectors/TaxonomyCentroidRepository.java +0 -0
  128. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/vectors/VectorRepository.java +0 -0
  129. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/java/dev/nexus/service/vectors/VoyageEmbedder.java +0 -0
  130. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/META-INF/native-image/native-image.properties +0 -0
  131. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/META-INF/native-image/reflect-config.json +0 -0
  132. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/META-INF/native-image/resource-config.json +0 -0
  133. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/META-INF/native-image/traced/reachability-metadata.json +0 -0
  134. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/META-INF/nexus/release.properties +0 -0
  135. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/aspects-001-baseline.xml +0 -0
  136. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/aspects-002-next-retry-at.xml +0 -0
  137. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/catalog-001-baseline.xml +0 -0
  138. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/catalog-002-hygiene.xml +0 -0
  139. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/catalog-003-soft-delete.xml +0 -0
  140. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/catalog-004-manifest-functions.xml +0 -0
  141. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/catalog-005-collection-vector-stats.xml +0 -0
  142. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/catalog-006-combined-query-functions.xml +0 -0
  143. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/catalog-007-graph-hop-functions.xml +0 -0
  144. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/catalog-008-combined-query-extensions.xml +0 -0
  145. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/catalog-009-read-shape-views.xml +0 -0
  146. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/catalog-011-collection-health-stale-age.xml +0 -0
  147. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/chash-001-baseline.xml +0 -0
  148. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/db.changelog-master.xml +0 -0
  149. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/fk-001-catalog-cross-store.xml +0 -0
  150. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/fk-002-collection-registry.xml +0 -0
  151. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/fk-002-validate.xml +0 -0
  152. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/fk-003-collection-registry-extra.xml +0 -0
  153. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/fk-003-validate.xml +0 -0
  154. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/grants-nexus-svc.xml +0 -0
  155. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/memory-001-baseline.xml +0 -0
  156. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/migration-001-baseline.xml +0 -0
  157. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/perf-001-rename-collection-indexes.xml +0 -0
  158. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/plans-001-baseline.xml +0 -0
  159. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/role-001-nexus-svc.xml +0 -0
  160. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/service-tokens-001-baseline.xml +0 -0
  161. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/service-tokens-002-single-root-index.xml +0 -0
  162. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/t1-001-baseline.xml +0 -0
  163. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/taxonomy-001-baseline.xml +0 -0
  164. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/taxonomy-002-centroids.xml +0 -0
  165. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/taxonomy-003-doc-count-trigger.xml +0 -0
  166. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/taxonomy-004-dedup-root-topics.xml +0 -0
  167. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/telemetry-001-baseline.xml +0 -0
  168. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/updated-at-001-triggers.xml +0 -0
  169. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/vectors-001-baseline.xml +0 -0
  170. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/db/changelog/vectors-002-trgm-index.xml +0 -0
  171. {conexus-6.2.0 → conexus-6.3.0}/service/src/main/resources/logback.xml +0 -0
  172. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/AspectOperatorQueryTest.java +0 -0
  173. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/AspectRepositoryTest.java +0 -0
  174. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/AuthFilterTest.java +0 -0
  175. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/Bge768ParityTest.java +0 -0
  176. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/Bge768ServiceEmbedIntegrationTest.java +0 -0
  177. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/CatalogDocumentCascadeTest.java +0 -0
  178. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/CatalogHandlerDeleteTest.java +0 -0
  179. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/CatalogHandlerRenameTest.java +0 -0
  180. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/CatalogSchemaLiquibaseTest.java +0 -0
  181. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/ChashRepositoryTest.java +0 -0
  182. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/ChunksRlsBehavioralTest.java +0 -0
  183. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/CollectionRegistryFkExtraTest.java +0 -0
  184. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/CollectionRegistryFkTest.java +0 -0
  185. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/CollectionVectorStatsTest.java +0 -0
  186. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/CombinedQueryParityIntegrationTest.java +0 -0
  187. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/CombinedQueryParityTest.java +0 -0
  188. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/DualRunHarnessIntegrationTest.java +0 -0
  189. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/EmbedParityTest.java +0 -0
  190. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/EmbeddingModeFailLoudTest.java +0 -0
  191. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/ForeignKeyConstraintTest.java +0 -0
  192. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/GraphHopParityIntegrationTest.java +0 -0
  193. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/GraphHopParityTest.java +0 -0
  194. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/HybridParityIntegrationTest.java +0 -0
  195. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/HybridSelectiveGateTest.java +0 -0
  196. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/ManifestFunctionsTest.java +0 -0
  197. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/MemoryHandlerTest.java +0 -0
  198. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/MemoryRepositoryTest.java +0 -0
  199. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/MemorySchemaLiquibaseTest.java +0 -0
  200. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/PgBouncerTenantIsolationTest.java +0 -0
  201. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/PgContainerHelper.java +0 -0
  202. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/PgVectorCombinedQueryContractTest.java +0 -0
  203. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/PgVectorHybridSearchContractTest.java +0 -0
  204. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/PgVectorRepositoryContractTest.java +0 -0
  205. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/PgVectorServingContractTest.java +0 -0
  206. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/PlanHandlerTest.java +0 -0
  207. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/PlanRepositoryTest.java +0 -0
  208. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/PlansSchemaLiquibaseTest.java +0 -0
  209. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/ReadShapeViewsTest.java +0 -0
  210. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/ReferenceOnlyChunkUpsertTest.java +0 -0
  211. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/SchemaMigratorIntegrationTest.java +0 -0
  212. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/ScratchHandlerTest.java +0 -0
  213. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/ScratchRepositoryTest.java +0 -0
  214. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/ScratchSchemaLiquibaseTest.java +0 -0
  215. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/ServiceBindHostTest.java +0 -0
  216. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/ServiceIntegrationTest.java +0 -0
  217. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/ServiceTokenSchemaLiquibaseTest.java +0 -0
  218. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/SessionTokenHandlerTest.java +0 -0
  219. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/SoftDeleteTest.java +0 -0
  220. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/TaxonomyCentroidHandlerTest.java +0 -0
  221. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/TaxonomyCentroidRepositoryTest.java +0 -0
  222. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/TaxonomyCentroidSchemaLiquibaseTest.java +0 -0
  223. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/TaxonomyPersistHandlerTest.java +0 -0
  224. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/TaxonomyRepositoryTest.java +0 -0
  225. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/TaxonomySchemaLiquibaseTest.java +0 -0
  226. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/TelemetryRepositoryTest.java +0 -0
  227. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/TelemetrySchemaLiquibaseTest.java +0 -0
  228. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/TenantPoolingIsolationTest.java +0 -0
  229. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/TokenAdminHandlerTest.java +0 -0
  230. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/TokenBoundaryAdversarialTest.java +0 -0
  231. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/UpdatedAtTriggerTest.java +0 -0
  232. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/VectorHandlerEmbeddingModeTest.java +0 -0
  233. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/VectorHandlerTokenUsageTest.java +0 -0
  234. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/VectorHybridHttpTest.java +0 -0
  235. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/VectorIntegrationTest.java +0 -0
  236. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/db/PoolerModeCheckTest.java +0 -0
  237. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/db/TenantScopeGucAllowlistTest.java +0 -0
  238. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/http/AspectHandlerEnqueueErrorTest.java +0 -0
  239. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/http/CatalogHandlerImportEmptyBodyTest.java +0 -0
  240. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/http/CatalogHandlerManifestFkTest.java +0 -0
  241. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/http/MigrationHandlerIngestCloudTest.java +0 -0
  242. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/http/TaxonomyHandlerAssignFkTest.java +0 -0
  243. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/http/VersionHandlerReleaseVersionTest.java +0 -0
  244. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/nativeimage/JooqRecordReflectionFeatureTest.java +0 -0
  245. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/resolver/ChromaSchemeHandlerTest.java +0 -0
  246. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/resolver/HttpsSchemeHandlerTest.java +0 -0
  247. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/resolver/UriSchemeResolverRegistryTest.java +0 -0
  248. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/vectors/Bge768EmbedderMathTest.java +0 -0
  249. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/vectors/EgressProxyTest.java +0 -0
  250. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/vectors/EmbedderRouterBge768Test.java +0 -0
  251. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/vectors/EmbedderRouterVoyageOnlyTest.java +0 -0
  252. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/vectors/PgVectorRepositoryWherePredicateTest.java +0 -0
  253. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/java/dev/nexus/service/vectors/ReferenceOnlySqlShapeTest.java +0 -0
  254. {conexus-6.2.0 → conexus-6.3.0}/service/src/test/resources/bge768/parity_reference.json +0 -0
  255. {conexus-6.2.0 → conexus-6.3.0}/sn/README.md +0 -0
  256. {conexus-6.2.0 → conexus-6.3.0}/sn/hooks/scripts/routing/README.md +0 -0
  257. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/__init__.py +0 -0
  258. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/_git_hooks_meta.py +0 -0
  259. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/_locking.py +0 -0
  260. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/_mineru_pid.py +0 -0
  261. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/_session_end_launcher.py +0 -0
  262. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/aspect_extractor.py +0 -0
  263. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/aspect_promotion.py +0 -0
  264. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/aspect_readers.py +0 -0
  265. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/aspect_worker.py +0 -0
  266. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/bib_enricher.py +0 -0
  267. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/bib_enricher_openalex.py +0 -0
  268. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/bib_extractor.py +0 -0
  269. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/catalog/AGENTS.md +0 -0
  270. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/catalog/__init__.py +0 -0
  271. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/catalog/auto_linker.py +0 -0
  272. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/catalog/catalog.py +0 -0
  273. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/catalog/catalog_backup.py +0 -0
  274. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/catalog/catalog_db.py +0 -0
  275. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/catalog/catalog_docs.py +0 -0
  276. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/catalog/catalog_git.py +0 -0
  277. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/catalog/catalog_links.py +0 -0
  278. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/catalog/catalog_owners.py +0 -0
  279. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/catalog/catalog_protocol.py +0 -0
  280. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/catalog/catalog_spans.py +0 -0
  281. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/catalog/catalog_sync.py +0 -0
  282. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/catalog/catalog_writes.py +0 -0
  283. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/catalog/collection_name.py +0 -0
  284. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/catalog/collections_owner_backfill.py +0 -0
  285. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/catalog/consolidation.py +0 -0
  286. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/catalog/dedupe.py +0 -0
  287. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/catalog/dt_link_generator.py +0 -0
  288. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/catalog/event_log.py +0 -0
  289. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/catalog/events.py +0 -0
  290. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/catalog/factory.py +0 -0
  291. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/catalog/link_generator.py +0 -0
  292. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/catalog/manifest_backfill.py +0 -0
  293. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/catalog/orphan_backfill.py +0 -0
  294. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/catalog/projector.py +0 -0
  295. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/catalog/store_hook.py +0 -0
  296. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/catalog/synthesizer.py +0 -0
  297. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/catalog/tumbler.py +0 -0
  298. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/catalog/types.py +0 -0
  299. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/catalog/write_priority.py +0 -0
  300. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/checkpoint.py +0 -0
  301. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/chunk_identity.py +0 -0
  302. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/chunker.py +0 -0
  303. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/classifier.py +0 -0
  304. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/cli.py +0 -0
  305. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/code_indexer.py +0 -0
  306. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/collection_audit.py +0 -0
  307. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/collection_health.py +0 -0
  308. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/collection_rename.py +0 -0
  309. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/__init__.py +0 -0
  310. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/_helpers.py +0 -0
  311. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/_migration_prompt.py +0 -0
  312. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/_provision.py +0 -0
  313. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/aspects.py +0 -0
  314. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/catalog.py +0 -0
  315. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/catalog_cmds/__init__.py +0 -0
  316. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/catalog_cmds/backfill.py +0 -0
  317. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/catalog_cmds/backups.py +0 -0
  318. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/catalog_cmds/collections.py +0 -0
  319. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/catalog_cmds/doctor.py +0 -0
  320. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/catalog_cmds/integrity.py +0 -0
  321. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/catalog_cmds/links.py +0 -0
  322. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/catalog_cmds/maintenance.py +0 -0
  323. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/catalog_cmds/migration.py +0 -0
  324. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/catalog_cmds/orphan_backfill.py +0 -0
  325. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/catalog_cmds/owners.py +0 -0
  326. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/catalog_cmds/remediation.py +0 -0
  327. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/catalog_cmds/report.py +0 -0
  328. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/collection.py +0 -0
  329. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/command_context.py +0 -0
  330. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/config_cmd.py +0 -0
  331. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/console.py +0 -0
  332. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/context_cmd.py +0 -0
  333. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/daemon.py +0 -0
  334. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/doc.py +0 -0
  335. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/doctor.py +0 -0
  336. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/dt.py +0 -0
  337. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/enrich.py +0 -0
  338. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/guided_upgrade_cmd.py +0 -0
  339. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/hook.py +0 -0
  340. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/hooks.py +0 -0
  341. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/index.py +0 -0
  342. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/init.py +0 -0
  343. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/memory.py +0 -0
  344. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/migrate_cmd.py +0 -0
  345. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/migration_cmd.py +0 -0
  346. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/mineru.py +0 -0
  347. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/plan.py +0 -0
  348. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/rdr.py +0 -0
  349. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/search_cmd.py +0 -0
  350. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/service_cmd.py +0 -0
  351. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/storage_cmd.py +0 -0
  352. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/store.py +0 -0
  353. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/t3.py +0 -0
  354. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/taxonomy_cmd.py +0 -0
  355. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/tenant_cmd.py +0 -0
  356. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/tier_status.py +0 -0
  357. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/uninstall.py +0 -0
  358. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/commands/upgrade.py +0 -0
  359. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/config.py +0 -0
  360. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/console/__init__.py +0 -0
  361. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/console/app.py +0 -0
  362. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/console/config.py +0 -0
  363. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/console/routes/__init__.py +0 -0
  364. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/console/routes/activity.py +0 -0
  365. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/console/routes/campaigns.py +0 -0
  366. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/console/routes/health.py +0 -0
  367. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/console/routes/partials.py +0 -0
  368. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/console/static/alpine.min.js +0 -0
  369. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/console/static/console.css +0 -0
  370. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/console/static/htmx.min.js +0 -0
  371. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/console/static/pico.min.css +0 -0
  372. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/console/templates/activity/_detail.html +0 -0
  373. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/console/templates/activity/_stream.html +0 -0
  374. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/console/templates/activity/index.html +0 -0
  375. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/console/templates/base.html +0 -0
  376. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/console/templates/campaigns/detail.html +0 -0
  377. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/console/templates/campaigns/index.html +0 -0
  378. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/console/templates/health/_cards.html +0 -0
  379. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/console/templates/health/index.html +0 -0
  380. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/console/watchers.py +0 -0
  381. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/context.py +0 -0
  382. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/corpus.py +0 -0
  383. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/cross_encoder.py +0 -0
  384. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/daemon/AGENTS.md +0 -0
  385. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/daemon/T2_DAEMON_WIP.md +0 -0
  386. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/daemon/__init__.py +0 -0
  387. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/daemon/aspect_worker_daemon.py +0 -0
  388. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/daemon/binary_lifecycle.py +0 -0
  389. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/daemon/catalog_write_shim.py +0 -0
  390. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/daemon/discovery.py +0 -0
  391. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/daemon/installer.py +0 -0
  392. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/daemon/service_registry.py +0 -0
  393. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/daemon/spin_guard.py +0 -0
  394. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/daemon/storage_service_daemon.py +0 -0
  395. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/daemon/t1_lease.py +0 -0
  396. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/daemon/t2_client.py +0 -0
  397. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/daemon/t2_daemon.py +0 -0
  398. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/daemon/t3_daemon.py +0 -0
  399. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/AGENTS.md +0 -0
  400. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/chroma_quotas.py +0 -0
  401. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/collection_purge.py +0 -0
  402. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/embed_migrate.py +0 -0
  403. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/local_ef.py +0 -0
  404. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/managed_endpoint.py +0 -0
  405. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/migrations.py +0 -0
  406. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/pg_bundle.py +0 -0
  407. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/pg_provision.py +0 -0
  408. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/service_bge_model.py +0 -0
  409. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/service_endpoint.py +0 -0
  410. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/storage_mode.py +0 -0
  411. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/t2/__init__.py +0 -0
  412. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/t2/_raw_handle_guard.py +0 -0
  413. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/t2/_tuning.py +0 -0
  414. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/t2/aspect_extraction_queue.py +0 -0
  415. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/t2/aspects_etl.py +0 -0
  416. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/t2/catalog.py +0 -0
  417. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/t2/catalog_etl.py +0 -0
  418. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/t2/catalog_taxonomy.py +0 -0
  419. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/t2/chash_etl.py +0 -0
  420. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/t2/chash_index.py +0 -0
  421. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/t2/document_aspects.py +0 -0
  422. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/t2/document_highlights.py +0 -0
  423. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/t2/http_aspect_queue.py +0 -0
  424. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/t2/http_centroid_store.py +0 -0
  425. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/t2/http_chash_index.py +0 -0
  426. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/t2/http_document_aspects_store.py +0 -0
  427. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/t2/http_document_highlights_store.py +0 -0
  428. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/t2/http_memory_store.py +0 -0
  429. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/t2/http_plan_library.py +0 -0
  430. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/t2/http_taxonomy_store.py +0 -0
  431. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/t2/http_telemetry_store.py +0 -0
  432. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/t2/http_token_store.py +0 -0
  433. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/t2/memory_etl.py +0 -0
  434. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/t2/memory_store.py +0 -0
  435. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/t2/plan_etl.py +0 -0
  436. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/t2/plan_library.py +0 -0
  437. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/t2/taxonomy_compute.py +0 -0
  438. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/t2/taxonomy_etl.py +0 -0
  439. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/t2/telemetry.py +0 -0
  440. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/t2/telemetry_etl.py +0 -0
  441. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/t3.py +0 -0
  442. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/db/t3_reidentify.py +0 -0
  443. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/devonthink.py +0 -0
  444. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/doc/__init__.py +0 -0
  445. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/doc/_common.py +0 -0
  446. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/doc/citations.py +0 -0
  447. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/doc/ref_scanner.py +0 -0
  448. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/doc/render.py +0 -0
  449. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/doc/resolvers.py +0 -0
  450. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/doc/resolvers_corpus.py +0 -0
  451. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/doc/tokens.py +0 -0
  452. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/doctor_search.py +0 -0
  453. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/dropped_writes.py +0 -0
  454. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/dt_writeback.py +0 -0
  455. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/errors.py +0 -0
  456. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/exporter.py +0 -0
  457. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/filters.py +0 -0
  458. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/formatters.py +0 -0
  459. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/frecency.py +0 -0
  460. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/glossary.py +0 -0
  461. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/health.py +0 -0
  462. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/hook_registry.py +0 -0
  463. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/hooks.py +0 -0
  464. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/index_context.py +0 -0
  465. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/indexer.py +0 -0
  466. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/indexer_utils.py +0 -0
  467. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/languages.py +0 -0
  468. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/logging_setup.py +0 -0
  469. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/mcp/AGENTS.md +0 -0
  470. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/mcp/__init__.py +0 -0
  471. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/mcp/_first_run.py +0 -0
  472. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/mcp/_t1_state.py +0 -0
  473. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/mcp/catalog.py +0 -0
  474. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/mcp/core.py +0 -0
  475. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/mcp/devonthink.py +0 -0
  476. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/mcp/plan_cache_registry.py +0 -0
  477. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/mcp_client/__init__.py +0 -0
  478. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/mcp_client/core.py +0 -0
  479. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/mcp_client/devonthink.py +0 -0
  480. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/mcp_server.py +0 -0
  481. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/md_chunker.py +0 -0
  482. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/merge_candidates.py +0 -0
  483. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/metadata_schema.py +0 -0
  484. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/migration/__init__.py +0 -0
  485. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/migration/banner.py +0 -0
  486. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/migration/chroma_read.py +0 -0
  487. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/migration/detection.py +0 -0
  488. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/migration/driver.py +0 -0
  489. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/migration/etl_registry.py +0 -0
  490. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/migration/guided_upgrade.py +0 -0
  491. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/migration/manifest_check.py +0 -0
  492. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/migration/migration_report.py +0 -0
  493. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/migration/orchestrator.py +0 -0
  494. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/migration/pregate.py +0 -0
  495. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/migration/quiesce.py +0 -0
  496. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/migration/route_coverage.py +0 -0
  497. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/migration/sequencer.py +0 -0
  498. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/migration/state.py +0 -0
  499. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/migration/validation.py +0 -0
  500. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/migration/vector_etl.py +0 -0
  501. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/migration/verify_fill.py +0 -0
  502. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/name_canaries.py +0 -0
  503. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/operators/aspect_sql.py +0 -0
  504. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/operators/dispatch.py +0 -0
  505. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/pdeathsig.py +0 -0
  506. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/pdf_chunker.py +0 -0
  507. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/pdf_extractor.py +0 -0
  508. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/phase_review_sentinel.py +0 -0
  509. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/pipeline_buffer.py +0 -0
  510. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/pipeline_stages.py +0 -0
  511. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/plans/__init__.py +0 -0
  512. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/plans/bundle.py +0 -0
  513. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/plans/loader.py +0 -0
  514. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/plans/match.py +0 -0
  515. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/plans/matcher.py +0 -0
  516. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/plans/promote.py +0 -0
  517. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/plans/purposes.py +0 -0
  518. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/plans/repair.py +0 -0
  519. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/plans/runner.py +0 -0
  520. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/plans/schema.py +0 -0
  521. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/plans/scope.py +0 -0
  522. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/plans/seed_loader.py +0 -0
  523. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/plans/session_cache.py +0 -0
  524. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/prose_indexer.py +0 -0
  525. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/registry.py +0 -0
  526. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/repo_identity.py +0 -0
  527. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/repos.py +0 -0
  528. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/retry.py +0 -0
  529. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/ripgrep_cache.py +0 -0
  530. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/routing_stats.py +0 -0
  531. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/salience.py +0 -0
  532. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/search_clusterer.py +0 -0
  533. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/session.py +0 -0
  534. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/stage_timers.py +0 -0
  535. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/storage_boundary_lint.py +0 -0
  536. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/taxonomy.py +0 -0
  537. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/taxonomy_backfill.py +0 -0
  538. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/ttl.py +0 -0
  539. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/types.py +0 -0
  540. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/util/__init__.py +0 -0
  541. {conexus-6.2.0 → conexus-6.3.0}/src/nexus/util/process_group.py +0 -0
  542. {conexus-6.2.0 → conexus-6.3.0}/tests/cc-validation/README.md +0 -0
  543. {conexus-6.2.0 → conexus-6.3.0}/tests/e2e/t2-migration-sqlite/README.md +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: conexus
3
- Version: 6.2.0
3
+ Version: 6.3.0
4
4
  Summary: Self-hosted semantic search and knowledge management for LLM-driven development
5
5
  Project-URL: Homepage, https://github.com/Hellblazer/nexus
6
6
  Project-URL: Repository, https://github.com/Hellblazer/nexus
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "conexus-mcpb"
3
- version = "6.2.0"
3
+ version = "6.3.0"
4
4
  description = "Conexus packaged as Claude Desktop .mcpb (Desktop Extension)"
5
5
  requires-python = ">=3.12"
6
6
  dependencies = [
@@ -10,7 +10,7 @@ dependencies = [
10
10
  # while collections are indexed at 768/1024-dim, so every T3 search hits a
11
11
  # dimension mismatch and returns zero results. The .mcpb cannot run the
12
12
  # interactive `nx init` embedder choice, so it must pin [local] explicitly.
13
- "conexus[local]>=6.2.0",
13
+ "conexus[local]>=6.3.0",
14
14
  ]
15
15
 
16
16
  [tool.uv]
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "conexus"
7
- version = "6.2.0"
7
+ version = "6.3.0"
8
8
  description = "Self-hosted semantic search and knowledge management for LLM-driven development"
9
9
  readme = { file = "README.md", content-type = "text/markdown" }
10
10
  requires-python = ">=3.12,<3.14"
@@ -531,8 +531,35 @@ public final class CatalogRepository {
531
531
  * Silently strips {@code deleted_at} from the input map — callers must use
532
532
  * {@code document_trash} / {@code document_restore} to manage the tombstone column.
533
533
  */
534
+ /**
535
+ * Settable columns for {@link #updateDocument} (wave review, SQL audit CRITICAL):
536
+ * request JSON keys become SET targets via {@code DSL.field(DSL.name(...))}, so
537
+ * WITHOUT this whitelist any body key was an arbitrary-column write from
538
+ * {@code POST /v1/catalog/update} — including {@code tenant_id} (re-homing a
539
+ * document across tenants) and lifecycle columns like {@code created_at}.
540
+ * The set mirrors the local {@code Catalog.update} mutable surface
541
+ * ({@link #documentFields()} minus the identity/lifecycle columns:
542
+ * tumbler, tenant_id, deleted_at, created_at). Unknown keys fail loud with
543
+ * {@code IllegalArgumentException} → 400, never a silent skip.
544
+ */
545
+ private static final Set<String> UPDATABLE_DOC_COLUMNS = Set.of(
546
+ "title", "author", "year", "content_type", "file_path", "corpus",
547
+ "physical_collection", "chunk_count", "head_hash", "indexed_at",
548
+ "meta", "metadata", "source_mtime", "alias_of", "source_uri",
549
+ "bib_year", "bib_authors", "bib_venue", "bib_citation_count",
550
+ "bib_semantic_scholar_id", "bib_openalex_id", "bib_doi", "bib_enriched_at");
551
+
534
552
  public int updateDocument(String tenant, String tumbler, Map<String, Object> fields) {
535
553
  if (fields.isEmpty()) return 0;
554
+ for (String key : fields.keySet()) {
555
+ // deleted_at keeps its documented silent-strip contract (callers must use
556
+ // trash/restore); every OTHER unknown key is a caller error — fail loud.
557
+ if (!"deleted_at".equals(key) && !UPDATABLE_DOC_COLUMNS.contains(key)) {
558
+ throw new IllegalArgumentException(
559
+ "updateDocument: column not updatable: '" + key
560
+ + "' (allowed: " + UPDATABLE_DOC_COLUMNS + ")");
561
+ }
562
+ }
536
563
  return tenantScope.withTenant(tenant, ctx -> {
537
564
  var step = ctx.update(T_DOCS);
538
565
  UpdateSetMoreStep<?> more = null;
@@ -1420,6 +1447,16 @@ public final class CatalogRepository {
1420
1447
  * streaming buffer and the entire local-mode (sqlite/Chroma) cascade.
1421
1448
  */
1422
1449
  public Map<String, Integer> deleteCollection(String tenant, String name) {
1450
+ Map<String, Integer> counts = deleteCollectionTxn(tenant, name);
1451
+ // Post-commit (nexus-h8rf6 wave review): the registry row is gone; a stale
1452
+ // CollectionRegistry entry would make later writers silently skip
1453
+ // re-registration if the name is reused. Same post-commit discipline as
1454
+ // markKnown — see CollectionRegistry.evict.
1455
+ CollectionRegistry.evict(tenant, name);
1456
+ return counts;
1457
+ }
1458
+
1459
+ private Map<String, Integer> deleteCollectionTxn(String tenant, String name) {
1423
1460
  return tenantScope.withTenant(tenant, ctx -> {
1424
1461
  Map<String, Integer> counts = new LinkedHashMap<>();
1425
1462
  // 1. T3 chunk vectors (registry children, fk-002 RESTRICT).
@@ -1516,6 +1553,19 @@ public final class CatalogRepository {
1516
1553
  * rows untouched — preserving pre-RDR-164 RDR-162 behavior.
1517
1554
  */
1518
1555
  public Map<String, Integer> renameCollection(String tenant, String oldName, String newName) {
1556
+ Map<String, Integer> counts = renameCollectionTxn(tenant, oldName, newName);
1557
+ // Post-commit (nexus-h8rf6 wave review): the canonical branch DELETEs the
1558
+ // old registry row — evict it so a later same-named collection re-registers.
1559
+ // The cross-model COPY branch leaves both registry rows untouched (no key
1560
+ // in counts), so nothing is evicted there.
1561
+ if (counts.containsKey("catalog_collections_deleted")) {
1562
+ CollectionRegistry.evict(tenant, oldName);
1563
+ CollectionRegistry.markKnown(tenant, newName);
1564
+ }
1565
+ return counts;
1566
+ }
1567
+
1568
+ private Map<String, Integer> renameCollectionTxn(String tenant, String oldName, String newName) {
1519
1569
  return tenantScope.withTenant(tenant, ctx -> {
1520
1570
  Map<String, Integer> counts = new LinkedHashMap<>();
1521
1571
  boolean targetExists = ctx.fetchExists(
@@ -1,6 +1,8 @@
1
1
  package dev.nexus.service.db;
2
2
 
3
3
  import org.jooq.DSLContext;
4
+
5
+ import static dev.nexus.service.jooq.nexus.Tables.CATALOG_COLLECTIONS;
4
6
  import org.jooq.Field;
5
7
  import org.jooq.Record3;
6
8
  import org.jooq.impl.DSL;
@@ -72,16 +74,71 @@ public final class ChashRepository {
72
74
  * error — fail loud rather than silently skipping the registration step and letting the
73
75
  * subsequent INSERT fail with a cryptic FK violation.
74
76
  *
77
+ * <p>Bead nexus-h8rf6.2 (contention relief): skips the INSERT entirely when
78
+ * {@link CollectionRegistry} already knows this {@code (tenant, collection)} pair is
79
+ * registered. See {@link CollectionRegistry} class doc for why the repeated
80
+ * {@code ON CONFLICT DO NOTHING} was a same-row lock-wait convoy under concurrent
81
+ * indexing, and why callers (not this method) are responsible for marking the cache
82
+ * only after the enclosing transaction commits.
83
+ *
75
84
  * @throws IllegalArgumentException if collection is null or blank
76
85
  */
77
86
  private static void ensureCollectionRegistered(DSLContext ctx, String tenant, String collection) {
78
87
  if (collection == null || collection.isBlank()) {
79
88
  throw new IllegalArgumentException("physical_collection must not be blank");
80
89
  }
81
- ctx.execute(
82
- "INSERT INTO nexus.catalog_collections (tenant_id, name) VALUES (?, ?) " +
83
- "ON CONFLICT (tenant_id, name) DO NOTHING",
84
- tenant, collection);
90
+ if (CollectionRegistry.isKnown(tenant, collection)) {
91
+ return;
92
+ }
93
+ ctx.insertInto(CATALOG_COLLECTIONS,
94
+ CATALOG_COLLECTIONS.TENANT_ID, CATALOG_COLLECTIONS.NAME)
95
+ .values(tenant, collection)
96
+ .onConflict(CATALOG_COLLECTIONS.TENANT_ID, CATALOG_COLLECTIONS.NAME)
97
+ .doNothing()
98
+ .execute();
99
+ }
100
+
101
+ /**
102
+ * Register {@code collection} in its OWN short committed transaction, then mark
103
+ * the {@link CollectionRegistry} cache.
104
+ *
105
+ * <p>Bounded first-burst convoy (v0.1.21, ChashVectorConcurrencyTest full-suite
106
+ * failure): with registration inside the batch transaction, the FIRST writer to
107
+ * a brand-new collection holds the {@code catalog_collections} ON CONFLICT value
108
+ * lock for its ENTIRE batch — every concurrent racer blocks for the winner's
109
+ * whole batch duration, and on a loaded host that exceeds the pool's
110
+ * connectionTimeout, surfacing typed 503s the cache was built to prevent. The
111
+ * CollectionRegistry cache bounds convoy COUNT (one per process lifetime);
112
+ * this bounds convoy DURATION (a single-statement micro-transaction, committed
113
+ * before the batch begins).
114
+ *
115
+ * <p>Trade-off, accepted: if the subsequent batch rolls back, the stub row
116
+ * persists — a zero-chunk registry stub is benign (collection existence is
117
+ * live-chunk-count-based everywhere: {@code collection_exists}, {@code /stats};
118
+ * {@code deleteCollection} removes stubs) and the pre-registration is exactly
119
+ * what any retry would recreate. Batch paths use this; {@code renameCollection}
120
+ * keeps in-transaction {@link #ensureCollectionRegistered} because its
121
+ * registration must be atomic with the re-point.
122
+ */
123
+ private void registerCollectionShortTxn(String tenant, String collection) {
124
+ if (collection == null || collection.isBlank()) {
125
+ throw new IllegalArgumentException("physical_collection must not be blank");
126
+ }
127
+ if (CollectionRegistry.isKnown(tenant, collection)) {
128
+ return;
129
+ }
130
+ tenantScope.withTenant(tenant, ctx -> {
131
+ ctx.insertInto(CATALOG_COLLECTIONS,
132
+ CATALOG_COLLECTIONS.TENANT_ID, CATALOG_COLLECTIONS.NAME)
133
+ .values(tenant, collection)
134
+ .onConflict(CATALOG_COLLECTIONS.TENANT_ID, CATALOG_COLLECTIONS.NAME)
135
+ .doNothing()
136
+ .execute();
137
+ return null;
138
+ });
139
+ // Post-commit discipline per CollectionRegistry class doc: the registration
140
+ // transaction above has committed by the time withTenant returns.
141
+ CollectionRegistry.markKnown(tenant, collection);
85
142
  }
86
143
 
87
144
  // ── upsert ─────────────────────────────────────────────────────────────────
@@ -100,9 +157,10 @@ public final class ChashRepository {
100
157
  if (collection == null || collection.isBlank()) throw new IllegalArgumentException("collection must not be empty");
101
158
 
102
159
  OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC);
160
+ // Own short committed txn — bounds the first-registration convoy DURATION
161
+ // (see registerCollectionShortTxn doc); also handles markKnown post-commit.
162
+ registerCollectionShortTxn(tenant, collection);
103
163
  tenantScope.withTenant(tenant, ctx -> {
104
- // RDR-156 P0.2: ensure catalog_collections has a stub row before the chash write.
105
- ensureCollectionRegistered(ctx, tenant, collection);
106
164
  ctx.insertInto(CHASH_INDEX,
107
165
  F_TENANT, F_CHASH, F_COLLECTION, F_CREATED_AT)
108
166
  .values(tenant, chash, collection, now)
@@ -131,9 +189,10 @@ public final class ChashRepository {
131
189
  .toList();
132
190
  if (valid.isEmpty()) return;
133
191
 
192
+ // Own short committed txn — bounds the first-registration convoy DURATION
193
+ // (see registerCollectionShortTxn doc); also handles markKnown post-commit.
194
+ registerCollectionShortTxn(tenant, collection);
134
195
  tenantScope.withTenant(tenant, ctx -> {
135
- // RDR-156 P0.2: ensure catalog_collections has a stub row before the chash writes.
136
- ensureCollectionRegistered(ctx, tenant, collection);
137
196
  var insert = ctx.insertInto(CHASH_INDEX,
138
197
  F_TENANT, F_CHASH, F_COLLECTION, F_CREATED_AT);
139
198
  var step = insert.values(tenant, valid.get(0), collection, now);
@@ -221,7 +280,7 @@ public final class ChashRepository {
221
280
  * via {@code withTenant}.
222
281
  */
223
282
  public int renameCollection(String tenant, String oldCollection, String newCollection) {
224
- return tenantScope.withTenant(tenant, ctx -> {
283
+ int updated = tenantScope.withTenant(tenant, ctx -> {
225
284
  // RDR-156 P0.2: ensure the new collection is registered before renaming.
226
285
  ensureCollectionRegistered(ctx, tenant, newCollection);
227
286
  // Drop rows in new that would collide with the rename
@@ -239,6 +298,9 @@ public final class ChashRepository {
239
298
  .where(F_COLLECTION.eq(oldCollection))
240
299
  .execute();
241
300
  });
301
+ // Post-commit (nexus-h8rf6.2): see upsert()'s comment / CollectionRegistry doc.
302
+ CollectionRegistry.markKnown(tenant, newCollection);
303
+ return updated;
242
304
  }
243
305
 
244
306
  // ── delete_stale ───────────────────────────────────────────────────────────
@@ -351,9 +413,10 @@ public final class ChashRepository {
351
413
  }
352
414
 
353
415
  final OffsetDateTime ts = createdAt;
416
+ // Own short committed txn — bounds the first-registration convoy DURATION
417
+ // (see registerCollectionShortTxn doc); also handles markKnown post-commit.
418
+ registerCollectionShortTxn(tenant, collection);
354
419
  tenantScope.withTenant(tenant, ctx -> {
355
- // RDR-156 P0.2: ensure catalog_collections has a stub row before the chash write.
356
- ensureCollectionRegistered(ctx, tenant, collection);
357
420
  ctx.insertInto(CHASH_INDEX,
358
421
  F_TENANT, F_CHASH, F_COLLECTION, F_CREATED_AT)
359
422
  .values(tenant, chash, collection, ts)
@@ -405,11 +468,13 @@ public final class ChashRepository {
405
468
  }
406
469
  final List<ImportRow> deduped = List.copyOf(unique.values());
407
470
 
408
- return tenantScope.withTenant(tenant, ctx -> {
409
- Set<String> collections = new java.util.LinkedHashSet<>();
410
- for (ImportRow r : deduped) collections.add(r.collection());
411
- for (String c : collections) ensureCollectionRegistered(ctx, tenant, c);
471
+ Set<String> collections = new java.util.LinkedHashSet<>();
472
+ for (ImportRow r : deduped) collections.add(r.collection());
412
473
 
474
+ // Own short committed txns — bounds the first-registration convoy DURATION
475
+ // (see registerCollectionShortTxn doc); also handles markKnown post-commit.
476
+ for (String c : collections) registerCollectionShortTxn(tenant, c);
477
+ int landed = tenantScope.withTenant(tenant, ctx -> {
413
478
  var insert = ctx.insertInto(CHASH_INDEX,
414
479
  F_TENANT, F_CHASH, F_COLLECTION, F_CREATED_AT);
415
480
  for (ImportRow r : deduped) {
@@ -429,5 +494,6 @@ public final class ChashRepository {
429
494
  .execute();
430
495
  return deduped.size();
431
496
  });
497
+ return landed;
432
498
  }
433
499
  }
@@ -0,0 +1,104 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ // Copyright (c) 2026 Hal Hildebrand. All rights reserved.
3
+ package dev.nexus.service.db;
4
+
5
+ import java.util.Set;
6
+ import java.util.concurrent.ConcurrentHashMap;
7
+
8
+ /**
9
+ * Bead nexus-h8rf6.2 — in-process cache of {@code (tenant, collection)} pairs KNOWN
10
+ * to already have a row in {@code nexus.catalog_collections}.
11
+ *
12
+ * <p><strong>Why this exists.</strong> Both {@code ChashRepository
13
+ * .ensureCollectionRegistered} and {@code PgVectorRepository.upsertChunksInternal}
14
+ * issue {@code INSERT INTO nexus.catalog_collections ... ON CONFLICT (tenant_id,
15
+ * name) DO NOTHING} on EVERY batch write, so the collection stub exists before the
16
+ * chash/chunk row lands. PostgreSQL's {@code ON CONFLICT} clause takes a value lock
17
+ * on the conflicting unique-index entry to safely decide whether to apply DO
18
+ * NOTHING; when two concurrent transactions target the SAME {@code (tenant_id,
19
+ * name)} row — the ordinary case for one repo's indexing run, which writes chash
20
+ * and vector batches for ONE physical collection over and over — the second
21
+ * transaction BLOCKS until the first commits or rolls back, even though the
22
+ * eventual outcome is a no-op. Because the winning transaction typically keeps
23
+ * its connection open for the rest of its own batch (chunk/chash writes), every
24
+ * other concurrent writer to that collection sits blocked HOLDING its own pooled
25
+ * connection for that whole window. Under sustained concurrent indexing this
26
+ * convoy exhausts the shared HikariCP pool: unrelated requests then fail
27
+ * {@code dataSource.getConnection()} with {@code SQLTransientConnectionException}
28
+ * ("Connection is not available, request timed out"), which surfaces as an
29
+ * opaque 500 (reproduced by {@code ChashVectorConcurrencyTest}).
30
+ *
31
+ * <p><strong>Fix shape.</strong> Once a {@code (tenant, collection)} pair is known
32
+ * to be registered, every subsequent write skips the redundant
33
+ * {@code INSERT ... ON CONFLICT} entirely — eliminating the repeated same-row
34
+ * lock-wait for the remainder of the process's lifetime. Only the FIRST
35
+ * registration (racing among whichever concurrent requests reach it first) still
36
+ * pays the lock-wait cost; that window is small and bounded by however many
37
+ * requests happen to race at that exact instant, not by the length of the run.
38
+ *
39
+ * <p><strong>Correctness: mark-known only after commit.</strong> Callers MUST call
40
+ * {@link #markKnown} only after the transaction that performed the (possibly
41
+ * skipped) registration has committed successfully — never from inside the
42
+ * {@code TenantScope.withTenant} lambda itself. If the enclosing transaction later
43
+ * rolls back (e.g. an unrelated error later in the same batch), the
44
+ * {@code catalog_collections} row was never actually persisted; marking the cache
45
+ * eagerly would cause every subsequent writer to skip re-registration forever,
46
+ * silently starving the row. Marking post-commit means a rollback simply leaves
47
+ * the pair unmarked, so the next writer retries registration as usual.
48
+ *
49
+ * <p>Process-local and unbounded by design: {@code (tenant, collection)} pairs are
50
+ * low-cardinality relative to write volume (one entry per physical collection ever
51
+ * touched by this process), so an unbounded {@link ConcurrentHashMap}-backed set is
52
+ * the right trade-off — no eviction complexity, no cache-miss storms.
53
+ */
54
+ public final class CollectionRegistry {
55
+
56
+ private static final Set<String> KNOWN = ConcurrentHashMap.newKeySet();
57
+
58
+ private CollectionRegistry() {}
59
+
60
+ private static String key(String tenant, String collection) {
61
+ // Printable delimiter on purpose (wave review): the original '\0' made git
62
+ // treat this FILE as binary, so every diff rendered as "Bin N -> M bytes"
63
+ // and logic changes were invisible to text review. '|' is not legal in
64
+ // tenant ids or conformant collection names, so keys cannot collide.
65
+ return tenant + '|' + collection;
66
+ }
67
+
68
+ /** True when {@code (tenant, collection)} is known-registered — safe to skip the INSERT. */
69
+ public static boolean isKnown(String tenant, String collection) {
70
+ return KNOWN.contains(key(tenant, collection));
71
+ }
72
+
73
+ /**
74
+ * Record {@code (tenant, collection)} as registered. Callers MUST only invoke
75
+ * this AFTER the enclosing transaction has committed (see class doc).
76
+ */
77
+ public static void markKnown(String tenant, String collection) {
78
+ KNOWN.add(key(tenant, collection));
79
+ }
80
+
81
+ /**
82
+ * Forget {@code (tenant, collection)} — MUST be called after any commit that
83
+ * DELETEs the {@code catalog_collections} row ({@code CatalogRepository
84
+ * .deleteCollection}; the canonical branch of {@code CatalogRepository
85
+ * .renameCollection}, which deletes the OLD row). A stale entry would make
86
+ * every subsequent writer skip re-registration for a later same-named
87
+ * collection, landing chash/chunk rows with no registry stub — the exact
88
+ * silent-skip failure the fail-loud registration design exists to prevent.
89
+ *
90
+ * <p>Same post-commit discipline as {@link #markKnown}: evict only after the
91
+ * deleting transaction has committed. The small window between commit and
92
+ * eviction is fail-loud, not silent — a concurrent writer that skips
93
+ * registration in that window hits the {@code ON DELETE RESTRICT} FK and
94
+ * errors rather than writing orphaned rows.
95
+ */
96
+ public static void evict(String tenant, String collection) {
97
+ KNOWN.remove(key(tenant, collection));
98
+ }
99
+
100
+ /** Test-only: clears all cached entries. */
101
+ static void clearForTests() {
102
+ KNOWN.clear();
103
+ }
104
+ }
@@ -9,7 +9,13 @@ import org.slf4j.LoggerFactory;
9
9
  import javax.sql.DataSource;
10
10
  import java.sql.Connection;
11
11
  import java.sql.SQLException;
12
+ import java.sql.SQLTransientConnectionException;
13
+ import java.util.Collections;
14
+ import java.util.IdentityHashMap;
15
+ import java.util.Map;
12
16
  import java.util.Set;
17
+ import java.util.concurrent.Semaphore;
18
+ import java.util.concurrent.TimeUnit;
13
19
  import java.util.function.Function;
14
20
 
15
21
  /**
@@ -63,10 +69,61 @@ public final class TenantScope {
63
69
  */
64
70
  private static final Set<String> PERMITTED_GUCS = Set.of(DEFAULT_TENANT_GUC, T1_TENANT_GUC);
65
71
 
72
+ /**
73
+ * Per-DataSource admission semaphores (wave review, Java-tree audit High-1).
74
+ *
75
+ * <p>The HTTP layer is virtual-thread-per-request with NO inherent bound on how
76
+ * many requests concurrently attempt DB work against the fixed HikariCP pool.
77
+ * Every convoy fix so far (batched INSERTs, embed-before-borrow,
78
+ * registration-in-own-txn) is per-call-site; this is the SYSTEMIC backpressure:
79
+ * at most {@code 2 * maximumPoolSize} callers may be inside {@link #withTenant}
80
+ * at once (poolSize active + poolSize queued), everyone else gets the same
81
+ * typed retryable pool-exhaustion signal HikariCP's connectionTimeout produces
82
+ * ({@link SQLTransientConnectionException} in the cause chain →
83
+ * {@code HttpUtil.isPoolExhausted} → 503) — without first burning a
84
+ * connectionTimeout wait per surplus caller.
85
+ *
86
+ * <p>Identity-keyed and static because production constructs MULTIPLE
87
+ * TenantScope instances over the SAME DataSource (NexusService + Main's
88
+ * PgVectorRepository) — a per-instance semaphore would multiply the bound.
89
+ * Fair, so a burst cannot starve early arrivals.
90
+ */
91
+ private static final Map<DataSource, Semaphore> ADMISSION =
92
+ Collections.synchronizedMap(new IdentityHashMap<>());
93
+
94
+ private static final int DEFAULT_POOL_SIZE = 10;
95
+ private static final long DEFAULT_TIMEOUT_MS = 30_000L;
96
+
66
97
  private final DataSource dataSource;
98
+ private final Semaphore admission;
99
+ private final long admissionTimeoutMs;
67
100
 
68
101
  public TenantScope(DataSource dataSource) {
69
102
  this.dataSource = dataSource;
103
+ int poolSize = DEFAULT_POOL_SIZE;
104
+ long timeoutMs = DEFAULT_TIMEOUT_MS;
105
+ if (dataSource instanceof com.zaxxer.hikari.HikariDataSource hikari) {
106
+ int configured = hikari.getMaximumPoolSize();
107
+ if (configured > 0) {
108
+ poolSize = configured;
109
+ }
110
+ long ct = hikari.getConnectionTimeout();
111
+ if (ct > 0) {
112
+ timeoutMs = ct;
113
+ }
114
+ }
115
+ this.admissionTimeoutMs = timeoutMs;
116
+ final int permits = poolSize * 2;
117
+ this.admission = ADMISSION.computeIfAbsent(
118
+ dataSource, ds -> new Semaphore(permits, true));
119
+ }
120
+
121
+ /** Test-only: admission bound + timeout injected directly (stub DataSource path). */
122
+ TenantScope(DataSource dataSource, int admissionPermits, long admissionTimeoutMs) {
123
+ this.dataSource = dataSource;
124
+ this.admissionTimeoutMs = admissionTimeoutMs;
125
+ this.admission = ADMISSION.computeIfAbsent(
126
+ dataSource, ds -> new Semaphore(admissionPermits, true));
70
127
  }
71
128
 
72
129
  /**
@@ -124,6 +181,34 @@ public final class TenantScope {
124
181
  "gucName not permitted: " + gucName + " (allowed: " + PERMITTED_GUCS + ")");
125
182
  }
126
183
 
184
+ // Admission control (see ADMISSION doc): bound concurrent DB work BEFORE
185
+ // borrowing a connection. Rejection surfaces as the SAME typed retryable
186
+ // signal as HikariCP connectionTimeout (SQLTransientConnectionException in
187
+ // the cause chain), so every handler's sendTypedDbError ladder maps it to
188
+ // a 503 with zero new error-mapping surface.
189
+ boolean admitted;
190
+ try {
191
+ admitted = admission.tryAcquire(admissionTimeoutMs, TimeUnit.MILLISECONDS);
192
+ } catch (InterruptedException ie) {
193
+ Thread.currentThread().interrupt();
194
+ throw new RuntimeException("interrupted awaiting DB admission for tenant: " + tenant, ie);
195
+ }
196
+ if (!admitted) {
197
+ log.warn("event=tenant_scope_admission_timeout tenant={} guc={} timeout_ms={}",
198
+ tenant, gucName, admissionTimeoutMs);
199
+ throw new RuntimeException(
200
+ "DB admission queue full for tenant: " + tenant,
201
+ new SQLTransientConnectionException(
202
+ "admission queue full after " + admissionTimeoutMs + "ms (retryable)"));
203
+ }
204
+ try {
205
+ return stampAndRun(tenant, gucName, work);
206
+ } finally {
207
+ admission.release();
208
+ }
209
+ }
210
+
211
+ private <T> T stampAndRun(String tenant, String gucName, Function<DSLContext, T> work) {
127
212
  Connection conn = null;
128
213
  try {
129
214
  conn = dataSource.getConnection();
@@ -125,8 +125,18 @@ public final class TokenCache {
125
125
  return Optional.empty(); // expired — do not cache
126
126
  }
127
127
  if (map.size() >= maxEntries) {
128
- log.warn("event=token_cache_overflow max={} action=clear", maxEntries);
129
- map.clear();
128
+ // Wave review: was map.clear() evicting EVERY cached principal at once
129
+ // meant the next request from every active tenant paid a synchronous
130
+ // TokenStore round-trip simultaneously (a self-inflicted thundering herd
131
+ // right when the system is busiest). Evict ~25% instead: the flood
132
+ // backstop still bounds memory, but hot tokens survive the trim.
133
+ int toEvict = Math.max(1, maxEntries / 4);
134
+ log.warn("event=token_cache_overflow max={} action=evict count={}", maxEntries, toEvict);
135
+ var it = map.keySet().iterator();
136
+ for (int i = 0; i < toEvict && it.hasNext(); i++) {
137
+ it.next();
138
+ it.remove();
139
+ }
130
140
  }
131
141
  map.put(tokenHash, new Entry(st.tenantId(), st.isRoot(), st.expiresAt(), now));
132
142
  return Optional.of(new Resolved(st.tenantId(), st.isRoot()));
@@ -144,28 +144,15 @@ public final class AspectHandler implements HttpHandler {
144
144
  } catch (IllegalArgumentException e) {
145
145
  HttpUtil.send(exchange, 400, "{\"error\":" + HttpUtil.jsonString(e.getMessage()) + "}");
146
146
  } catch (Exception e) {
147
- String sqlState = sqlState23(e);
148
- if (sqlState != null) {
149
- // RDR-172 P3.1 (nexus-gfl3y): a SQLSTATE class-23 integrity violation —
150
- // e.g. the aspect_extraction_queue.doc_id FK rejecting a non-blank but
151
- // UNREGISTERED doc_id (bug nexus-ov0sw) — is a CLIENT error, not a server
152
- // fault. Map it to a typed 409 AHEAD of the generic 500 so the caller sees
153
- // a loud, actionable failure instead of an opaque 500 (and never a silent
154
- // 200). jOOQ wraps the driver PSQLException in a DataAccessException, so the
155
- // violation surfaces as a cause, not the top-level throwable. RF-5 / RF-8.
156
- // Full driver message (the parameterised SQL + PG detail) goes to the
157
- // server log for operators; the client body is sanitised to a fixed
158
- // message + the sqlstate. The 409 is client-triggerable (a bad doc_id),
159
- // so echoing the raw jOOQ SQL would leak schema/constraint shape to any
160
- // caller — return only the programmatic signal (sqlstate).
161
- log.warn("event=aspects_handler_integrity_violation op={} sqlstate={} error={}",
162
- op, sqlState, e.getMessage());
163
- HttpUtil.send(exchange, 409,
164
- "{\"error\":\"integrity constraint violation\",\"sqlstate\":"
165
- + HttpUtil.jsonString(sqlState) + "}");
166
- } else {
147
+ // Shared typed-DB-error ladder: pool-exhaustion 503 + class-23 409
148
+ // (nexus-h8rf6.2 / nexus-7e057) — see HttpUtil.sendTypedDbError.
149
+ // (RDR-172 P3.1 / nexus-gfl3y history preserved on HttpUtil.sendTypedDbError.)
150
+ if (!HttpUtil.sendTypedDbError(exchange, e, log, "aspects_handler",
151
+ "op=" + op)) {
167
152
  log.error("event=aspects_handler_error op={} error={}", op, e.getMessage(), e);
168
- HttpUtil.send(exchange, 500, "{\"error\":" + HttpUtil.jsonString(e.getMessage()) + "}");
153
+ // Wave review: fixed 500 body — the previous body echoed e.getMessage(),
154
+ // which can carry jOOQ SQL / schema shape to any caller.
155
+ HttpUtil.send(exchange, 500, "{\"error\":\"internal server error\"}");
169
156
  }
170
157
  }
171
158
  }
@@ -199,22 +199,10 @@ public final class CatalogHandler implements HttpHandler {
199
199
  } catch (IllegalArgumentException e) {
200
200
  HttpUtil.send(exchange, 400, "{\"error\":" + MAPPER.writeValueAsString(e.getMessage()) + "}");
201
201
  } catch (Exception e) {
202
- // nexus-7e057 (RDR-172 follow-up): a client-supplied doc_id that is
203
- // non-blank but UNREGISTERED violates fk_catalog_chunks_catalog_doc
204
- // on the manifest write/append path — same bug class as nexus-ov0sw
205
- // (AspectHandler's aspect_extraction_queue.doc_id FK). Map class-23
206
- // integrity violations to a typed 409 ahead of the generic 500. The
207
- // full driver message goes to the server log; the client body is
208
- // sanitised to a fixed message + the sqlstate (never the raw jOOQ
209
- // SQL, which would leak schema/constraint shape to any caller).
210
- String sqlState = HttpUtil.sqlState23(e);
211
- if (sqlState != null) {
212
- log.warn("event=catalog_handler_integrity_violation op={} tenant={} sqlstate={} error={}",
213
- op, tenant, sqlState, e.getMessage());
214
- HttpUtil.send(exchange, 409,
215
- "{\"error\":\"integrity constraint violation\",\"sqlstate\":"
216
- + HttpUtil.jsonString(sqlState) + "}");
217
- } else {
202
+ // Shared typed-DB-error ladder: pool-exhaustion 503 + class-23 409
203
+ // (nexus-h8rf6.2 / nexus-7e057) see HttpUtil.sendTypedDbError.
204
+ if (!HttpUtil.sendTypedDbError(exchange, e, log, "catalog_handler",
205
+ "op=" + op + " tenant=" + tenant)) {
218
206
  log.error("event=catalog_handler_error op={} tenant={} error={}", op, tenant, e.getMessage(), e);
219
207
  HttpUtil.send(exchange, 500, "{\"error\":\"internal server error\"}");
220
208
  }
@@ -91,8 +91,13 @@ public final class ChashHandler implements HttpHandler {
91
91
  } catch (IllegalArgumentException e) {
92
92
  HttpUtil.send(exchange, 400, "{\"error\":" + MAPPER.writeValueAsString(e.getMessage()) + "}");
93
93
  } catch (Exception e) {
94
- log.error("event=chash_handler_error op={} tenant={} error={}", op, tenant, e.getMessage(), e);
95
- HttpUtil.send(exchange, 500, "{\"error\":\"internal server error\"}");
94
+ // Shared typed-DB-error ladder: pool-exhaustion 503 + class-23 409
95
+ // (nexus-h8rf6.2 / nexus-7e057) see HttpUtil.sendTypedDbError.
96
+ if (!HttpUtil.sendTypedDbError(exchange, e, log, "chash_handler",
97
+ "op=" + op + " tenant=" + tenant)) {
98
+ log.error("event=chash_handler_error op={} tenant={} error={}", op, tenant, e.getMessage(), e);
99
+ HttpUtil.send(exchange, 500, "{\"error\":\"internal server error\"}");
100
+ }
96
101
  }
97
102
  }
98
103