@venizia/ignis-docs 0.0.8 → 0.2.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 (180) hide show
  1. package/README.md +7 -7
  2. package/content/best-practices/api-usage-examples.md +15 -12
  3. package/content/best-practices/architectural-patterns.md +70 -78
  4. package/content/best-practices/architecture-decisions.md +91 -60
  5. package/content/best-practices/code-style-standards/advanced-patterns.md +56 -44
  6. package/content/best-practices/code-style-standards/constants-configuration.md +11 -11
  7. package/content/best-practices/code-style-standards/control-flow.md +5 -2
  8. package/content/best-practices/code-style-standards/documentation.md +13 -13
  9. package/content/best-practices/code-style-standards/function-patterns.md +9 -10
  10. package/content/best-practices/code-style-standards/index.md +1 -1
  11. package/content/best-practices/code-style-standards/naming-conventions.md +10 -8
  12. package/content/best-practices/code-style-standards/route-definitions.md +30 -12
  13. package/content/best-practices/code-style-standards/tooling.md +8 -5
  14. package/content/best-practices/code-style-standards/type-safety.md +13 -12
  15. package/content/best-practices/common-pitfalls.md +56 -37
  16. package/content/best-practices/contribution-workflow.md +13 -14
  17. package/content/best-practices/data-modeling.md +46 -22
  18. package/content/best-practices/deployment-strategies.md +28 -27
  19. package/content/best-practices/error-handling.md +48 -24
  20. package/content/best-practices/index.md +5 -5
  21. package/content/best-practices/performance-optimization.md +40 -31
  22. package/content/best-practices/security-guidelines.md +52 -23
  23. package/content/best-practices/testing-strategies.md +65 -51
  24. package/content/best-practices/troubleshooting-tips.md +24 -24
  25. package/content/extensions/components/{swagger.md → api-reference.md} +40 -31
  26. package/content/extensions/components/authentication/api.md +19 -19
  27. package/content/extensions/components/authentication/errors.md +7 -7
  28. package/content/extensions/components/authentication/index.md +10 -8
  29. package/content/extensions/components/authentication/usage.md +101 -6
  30. package/content/extensions/components/authorization/api.md +45 -25
  31. package/content/extensions/components/authorization/errors.md +6 -6
  32. package/content/extensions/components/authorization/index.md +11 -10
  33. package/content/extensions/components/authorization/usage.md +21 -21
  34. package/content/extensions/components/health-check.md +1 -1
  35. package/content/extensions/components/index.md +5 -5
  36. package/content/extensions/components/mail/errors.md +15 -15
  37. package/content/extensions/components/mail/index.md +1 -2
  38. package/content/extensions/components/mail/usage.md +1 -1
  39. package/content/extensions/components/request-tracker.md +1 -1
  40. package/content/extensions/components/socket-io/api.md +9 -9
  41. package/content/extensions/components/socket-io/errors.md +5 -5
  42. package/content/extensions/components/socket-io/index.md +8 -8
  43. package/content/extensions/components/socket-io/usage.md +1 -1
  44. package/content/extensions/components/static-asset/api.md +17 -4
  45. package/content/extensions/components/static-asset/errors.md +4 -4
  46. package/content/extensions/components/static-asset/index.md +26 -28
  47. package/content/extensions/components/static-asset/usage.md +13 -12
  48. package/content/extensions/components/template/index.md +2 -2
  49. package/content/extensions/components/template/setup-page.md +1 -1
  50. package/content/extensions/components/websocket/api.md +3 -3
  51. package/content/extensions/components/websocket/errors.md +5 -5
  52. package/content/extensions/components/websocket/index.md +5 -5
  53. package/content/extensions/components/websocket/usage.md +3 -3
  54. package/content/extensions/helpers/cron/index.md +2 -2
  55. package/content/extensions/helpers/crypto/index.md +1 -1
  56. package/content/extensions/helpers/env/index.md +27 -12
  57. package/content/extensions/helpers/error/index.md +81 -25
  58. package/content/extensions/helpers/index.md +2 -3
  59. package/content/extensions/helpers/inversion/index.md +15 -7
  60. package/content/extensions/helpers/kafka/compile-binary.md +92 -0
  61. package/content/extensions/helpers/kafka/examples.md +1 -1
  62. package/content/extensions/helpers/kafka/index.md +3 -0
  63. package/content/extensions/helpers/logger/index.md +32 -2
  64. package/content/extensions/helpers/network/index.md +6 -0
  65. package/content/extensions/helpers/queue/index.md +14 -17
  66. package/content/extensions/helpers/redis/index.md +548 -323
  67. package/content/extensions/helpers/socket-io/index.md +14 -10
  68. package/content/extensions/helpers/storage/api.md +44 -8
  69. package/content/extensions/helpers/storage/index.md +43 -7
  70. package/content/extensions/helpers/template/index.md +6 -3
  71. package/content/extensions/helpers/types/index.md +11 -8
  72. package/content/extensions/helpers/websocket/api.md +9 -9
  73. package/content/extensions/helpers/websocket/index.md +7 -7
  74. package/content/extensions/helpers/worker-thread/index.md +2 -2
  75. package/content/extensions/index.md +3 -4
  76. package/content/extensions/src-details/mcp-server.md +18 -24
  77. package/content/guides/core-concepts/application/bootstrapping.md +11 -14
  78. package/content/guides/core-concepts/application/index.md +3 -3
  79. package/content/guides/core-concepts/components.md +19 -10
  80. package/content/guides/core-concepts/dependency-injection.md +6 -3
  81. package/content/guides/core-concepts/grpc-controllers.md +6 -5
  82. package/content/guides/core-concepts/persistent/datasources.md +42 -43
  83. package/content/guides/core-concepts/persistent/index.md +16 -7
  84. package/content/guides/core-concepts/persistent/models.md +24 -20
  85. package/content/guides/core-concepts/persistent/postgres-drivers.md +201 -0
  86. package/content/guides/core-concepts/persistent/repositories.md +40 -23
  87. package/content/guides/core-concepts/persistent/search-meilisearch.md +185 -0
  88. package/content/guides/core-concepts/persistent/search-typesense.md +431 -0
  89. package/content/guides/core-concepts/persistent/transactions.md +61 -25
  90. package/content/guides/core-concepts/rest-controllers.md +12 -9
  91. package/content/guides/core-concepts/services.md +330 -60
  92. package/content/guides/get-started/5-minute-quickstart.md +15 -15
  93. package/content/guides/get-started/philosophy.md +36 -36
  94. package/content/guides/get-started/setup.md +3 -3
  95. package/content/guides/index.md +3 -3
  96. package/content/guides/migrations/redis-helpers-migration.md +177 -0
  97. package/content/guides/migrations/scoped-rbac-migration.md +17 -17
  98. package/content/guides/migrations/unified-connectors-migration.md +113 -0
  99. package/content/guides/reference/glossary.md +19 -12
  100. package/content/guides/reference/mcp-docs-server.md +22 -18
  101. package/content/guides/tutorials/building-a-crud-api.md +37 -44
  102. package/content/guides/tutorials/complete-installation.md +17 -17
  103. package/content/guides/tutorials/ecommerce-api.md +163 -124
  104. package/content/guides/tutorials/realtime-chat.md +181 -135
  105. package/content/guides/tutorials/testing.md +65 -523
  106. package/content/index.md +2 -180
  107. package/content/public/apple-touch-icon.png +0 -0
  108. package/content/public/og-image.png +0 -0
  109. package/content/public/site.webmanifest +11 -0
  110. package/content/references/base/application.md +4 -5
  111. package/content/references/base/bootstrapping.md +18 -5
  112. package/content/references/base/components.md +149 -120
  113. package/content/references/base/connectors.md +178 -0
  114. package/content/references/base/controllers.md +41 -30
  115. package/content/references/base/datasources.md +163 -92
  116. package/content/references/base/dependency-injection.md +34 -22
  117. package/content/references/base/filter-system/application-usage.md +17 -14
  118. package/content/references/base/filter-system/array-operators.md +7 -2
  119. package/content/references/base/filter-system/comparison-operators.md +3 -0
  120. package/content/references/base/filter-system/default-filter.md +89 -71
  121. package/content/references/base/filter-system/fields-order-pagination.md +22 -22
  122. package/content/references/base/filter-system/index.md +6 -3
  123. package/content/references/base/filter-system/json-filtering.md +20 -1
  124. package/content/references/base/filter-system/list-operators.md +1 -1
  125. package/content/references/base/filter-system/logical-operators.md +33 -1
  126. package/content/references/base/filter-system/null-operators.md +30 -1
  127. package/content/references/base/filter-system/quick-reference.md +23 -4
  128. package/content/references/base/filter-system/tips.md +5 -5
  129. package/content/references/base/filter-system/use-cases.md +12 -12
  130. package/content/references/base/grpc-controllers.md +13 -13
  131. package/content/references/base/index.md +24 -12
  132. package/content/references/base/middlewares.md +265 -327
  133. package/content/references/base/models.md +63 -49
  134. package/content/references/base/providers.md +136 -130
  135. package/content/references/base/repositories/advanced.md +59 -58
  136. package/content/references/base/repositories/index.md +115 -91
  137. package/content/references/base/repositories/mixins.md +55 -291
  138. package/content/references/base/repositories/relations.md +54 -64
  139. package/content/references/base/repositories/soft-deletable.md +31 -30
  140. package/content/references/base/services.md +296 -93
  141. package/content/references/configuration/environment-variables.md +49 -31
  142. package/content/references/configuration/index.md +6 -6
  143. package/content/references/index.md +17 -12
  144. package/content/references/quick-reference.md +65 -106
  145. package/content/references/utilities/crypto.md +65 -23
  146. package/content/references/utilities/index.md +3 -3
  147. package/content/references/utilities/jsx.md +6 -4
  148. package/content/references/utilities/module.md +68 -20
  149. package/content/references/utilities/parse.md +4 -14
  150. package/content/references/utilities/promise.md +9 -7
  151. package/content/references/utilities/schema.md +5 -3
  152. package/dist/mcp-server/common/guards.d.ts +8 -0
  153. package/dist/mcp-server/common/guards.d.ts.map +1 -0
  154. package/dist/mcp-server/common/guards.js +14 -0
  155. package/dist/mcp-server/common/guards.js.map +1 -0
  156. package/dist/mcp-server/common/index.d.ts +1 -0
  157. package/dist/mcp-server/common/index.d.ts.map +1 -1
  158. package/dist/mcp-server/common/index.js +1 -0
  159. package/dist/mcp-server/common/index.js.map +1 -1
  160. package/dist/mcp-server/helpers/docs.helper.d.ts.map +1 -1
  161. package/dist/mcp-server/helpers/docs.helper.js +4 -2
  162. package/dist/mcp-server/helpers/docs.helper.js.map +1 -1
  163. package/dist/mcp-server/helpers/github.helper.js +1 -1
  164. package/dist/mcp-server/index.js +7 -2
  165. package/dist/mcp-server/index.js.map +1 -1
  166. package/dist/mcp-server/tools/base.tool.d.ts +6 -2
  167. package/dist/mcp-server/tools/base.tool.d.ts.map +1 -1
  168. package/dist/mcp-server/tools/base.tool.js.map +1 -1
  169. package/dist/mcp-server/tools/docs/search-documents.tool.d.ts +1 -1
  170. package/dist/mcp-server/tools/github/list-project-files.tool.d.ts +1 -1
  171. package/dist/mcp-server/tools/github/search-code.tool.d.ts +1 -1
  172. package/dist/mcp-server/tools/github/search-code.tool.d.ts.map +1 -1
  173. package/dist/mcp-server/tools/github/search-code.tool.js +4 -1
  174. package/dist/mcp-server/tools/github/search-code.tool.js.map +1 -1
  175. package/dist/mcp-server/tools/github/verify-dependencies.tool.d.ts.map +1 -1
  176. package/dist/mcp-server/tools/github/verify-dependencies.tool.js +3 -1
  177. package/dist/mcp-server/tools/github/verify-dependencies.tool.js.map +1 -1
  178. package/package.json +9 -9
  179. package/content/extensions/helpers/testing/index.md +0 -510
  180. package/content/references/base/middleware.md +0 -347
@@ -1,6 +1,6 @@
1
1
  # Philosophy: The Best of Two Worlds
2
2
 
3
- Ignis combines the structured, enterprise-grade development experience of **LoopBack 4** with the speed and simplicity of **Hono**.
3
+ IGNIS combines the structured, enterprise-grade development experience of **LoopBack 4** with the speed and simplicity of **Hono**.
4
4
 
5
5
  <div class="philosophy-hero">
6
6
  <div class="hero-content">
@@ -34,7 +34,7 @@ When building REST APIs and server applications with Node.js/Bun, developers cho
34
34
 
35
35
  <div class="landscape-card balanced">
36
36
  <div class="card-header">
37
- <h3>Ignis, Ts.ED</h3>
37
+ <h3>IGNIS, Ts.ED</h3>
38
38
  <span class="card-badge">Balanced</span>
39
39
  </div>
40
40
  <p class="card-motto">Structure with lighter footprint</p>
@@ -86,7 +86,7 @@ When building REST APIs and server applications with Node.js/Bun, developers cho
86
86
 
87
87
  <div class="perf-row highlight">
88
88
  <div class="perf-info">
89
- <span class="perf-name">Ignis</span>
89
+ <span class="perf-name">IGNIS</span>
90
90
  <span class="perf-meta">~30ms startup · ~30MB</span>
91
91
  </div>
92
92
  <div class="perf-bar-container">
@@ -162,7 +162,7 @@ When building REST APIs and server applications with Node.js/Bun, developers cho
162
162
  <th>Aspect</th>
163
163
  <th>Minimal (Hono/Express)</th>
164
164
  <th>Enterprise (NestJS/LoopBack)</th>
165
- <th class="highlight-col">Ignis</th>
165
+ <th class="highlight-col">IGNIS</th>
166
166
  </tr>
167
167
  </thead>
168
168
  <tbody>
@@ -221,7 +221,7 @@ When building REST APIs and server applications with Node.js/Bun, developers cho
221
221
  <th>Feature</th>
222
222
  <th>Minimal</th>
223
223
  <th>Enterprise</th>
224
- <th class="highlight-col">Ignis</th>
224
+ <th class="highlight-col">IGNIS</th>
225
225
  </tr>
226
226
  </thead>
227
227
  <tbody>
@@ -274,7 +274,7 @@ When building REST APIs and server applications with Node.js/Bun, developers cho
274
274
  <th>Aspect</th>
275
275
  <th>Hono</th>
276
276
  <th>NestJS</th>
277
- <th class="highlight-col">Ignis</th>
277
+ <th class="highlight-col">IGNIS</th>
278
278
  </tr>
279
279
  </thead>
280
280
  <tbody>
@@ -330,7 +330,7 @@ When building REST APIs and server applications with Node.js/Bun, developers cho
330
330
  </table>
331
331
  </div>
332
332
 
333
- ## The Ignis Synthesis
333
+ ## The IGNIS Synthesis
334
334
 
335
335
  <div class="synthesis">
336
336
 
@@ -359,7 +359,7 @@ When building REST APIs and server applications with Node.js/Bun, developers cho
359
359
  <div class="synthesis-operator">=</div>
360
360
 
361
361
  <div class="synthesis-box result">
362
- <h4>Ignis</h4>
362
+ <h4>IGNIS</h4>
363
363
  <ul>
364
364
  <li>DI + Speed</li>
365
365
  <li>Structure + Simplicity</li>
@@ -400,7 +400,7 @@ When building REST APIs and server applications with Node.js/Bun, developers cho
400
400
  </div>
401
401
 
402
402
  <div class="excel-card ignis">
403
- <h3>Ignis</h3>
403
+ <h3>IGNIS</h3>
404
404
  <p class="excel-subtitle">The balanced choice</p>
405
405
  <div class="excel-pros">
406
406
  <h4>Strengths</h4>
@@ -452,7 +452,7 @@ When building REST APIs and server applications with Node.js/Bun, developers cho
452
452
 
453
453
  </div>
454
454
 
455
- ## When Should You Use Ignis?
455
+ ## When Should You Use IGNIS?
456
456
 
457
457
  <div class="decision-matrix">
458
458
 
@@ -530,7 +530,7 @@ When building REST APIs and server applications with Node.js/Bun, developers cho
530
530
 
531
531
  <div class="perfect-card">
532
532
  <h4>Production APIs</h4>
533
- <p>10-100+ endpoints with enterprise patterns. Controllers, services, repositories all built-in and ready.</p>
533
+ <p>10-100+ endpoints with enterprise patterns. Controllers, services, repositories - all built-in and ready.</p>
534
534
  </div>
535
535
 
536
536
  <div class="perfect-card">
@@ -557,42 +557,42 @@ When building REST APIs and server applications with Node.js/Bun, developers cho
557
557
  <div class="choose-card">
558
558
  <h3>Use Hono/Fastify/Express When:</h3>
559
559
  <ul>
560
- <li><strong>Simple webhook handler</strong> No structure overhead needed</li>
561
- <li><strong>Edge/serverless functions</strong> Minimal cold start, tiny bundle</li>
562
- <li><strong>Rapid prototyping</strong> Get something running in minutes</li>
563
- <li><strong>1-5 endpoint microservices</strong> Structure adds complexity</li>
564
- <li><strong>Maximum control needed</strong> No conventions to follow</li>
565
- <li><strong>Learning web development</strong> Simpler mental model</li>
560
+ <li><strong>Simple webhook handler</strong> - No structure overhead needed</li>
561
+ <li><strong>Edge/serverless functions</strong> - Minimal cold start, tiny bundle</li>
562
+ <li><strong>Rapid prototyping</strong> - Get something running in minutes</li>
563
+ <li><strong>1-5 endpoint microservices</strong> - Structure adds complexity</li>
564
+ <li><strong>Maximum control needed</strong> - No conventions to follow</li>
565
+ <li><strong>Learning web development</strong> - Simpler mental model</li>
566
566
  </ul>
567
567
  </div>
568
568
 
569
569
  <div class="choose-card">
570
570
  <h3>Use NestJS/LoopBack When:</h3>
571
571
  <ul>
572
- <li><strong>Large team (10+ developers)</strong> Strong conventions prevent chaos</li>
573
- <li><strong>Enterprise with strict standards</strong> Mature, battle-tested, auditable</li>
574
- <li><strong>Extensive ecosystem needed</strong> Many official and community modules</li>
575
- <li><strong>Complex microservices</strong> Built-in support for messaging, CQRS</li>
576
- <li><strong>Hiring is a priority</strong> Large talent pool familiar with it</li>
577
- <li><strong>Long-term support critical</strong> Corporate backing, LTS versions</li>
572
+ <li><strong>Large team (10+ developers)</strong> - Strong conventions prevent chaos</li>
573
+ <li><strong>Enterprise with strict standards</strong> - Mature, battle-tested, auditable</li>
574
+ <li><strong>Extensive ecosystem needed</strong> - Many official and community modules</li>
575
+ <li><strong>Complex microservices</strong> - Built-in support for messaging, CQRS</li>
576
+ <li><strong>Hiring is a priority</strong> - Large talent pool familiar with it</li>
577
+ <li><strong>Long-term support critical</strong> - Corporate backing, LTS versions</li>
578
578
  </ul>
579
579
  </div>
580
580
 
581
581
  <div class="choose-card highlight">
582
- <h3>Use Ignis When:</h3>
582
+ <h3>Use IGNIS When:</h3>
583
583
  <ul>
584
- <li><strong>Any size API (10-100+ endpoints)</strong> Structure without heavy overhead</li>
585
- <li><strong>Any team size</strong> Scales from solo dev to enterprise teams</li>
586
- <li><strong>Performance matters</strong> Hono's speed with enterprise patterns</li>
587
- <li><strong>Modern stack preferred</strong> ESM native, Bun optimized, TypeScript-first</li>
588
- <li><strong>Coming from NestJS/LoopBack</strong> Familiar patterns, better performance</li>
589
- <li><strong>Need built-in features</strong> DI, validation, OpenAPI, auth ready to use</li>
584
+ <li><strong>Any size API (10-100+ endpoints)</strong> - Structure without heavy overhead</li>
585
+ <li><strong>Any team size</strong> - Scales from solo dev to enterprise teams</li>
586
+ <li><strong>Performance matters</strong> - Hono's speed with enterprise patterns</li>
587
+ <li><strong>Modern stack preferred</strong> - ESM native, Bun optimized, TypeScript-first</li>
588
+ <li><strong>Coming from NestJS/LoopBack</strong> - Familiar patterns, better performance</li>
589
+ <li><strong>Need built-in features</strong> - DI, validation, OpenAPI, auth ready to use</li>
590
590
  </ul>
591
591
  </div>
592
592
 
593
593
  </div>
594
594
 
595
- ## Why Choose Ignis
595
+ ## Why Choose IGNIS
596
596
 
597
597
  <div class="tradeoffs">
598
598
 
@@ -603,7 +603,7 @@ When building REST APIs and server applications with Node.js/Bun, developers cho
603
603
  <li><span class="highlight-text">Built-in DI</span>, validation, OpenAPI, auth</li>
604
604
  <li><span class="highlight-text">Structured codebase</span> from day one</li>
605
605
  <li><span class="highlight-text">Easier testing</span> with dependency injection</li>
606
- <li><span class="highlight-text">Single file build</span> compile to one executable with Bun</li>
606
+ <li><span class="highlight-text">Single file build</span> - compile to one executable with Bun</li>
607
607
  <li><span class="highlight-text">Scales</span> from solo dev to enterprise teams</li>
608
608
  </ul>
609
609
  </div>
@@ -611,10 +611,10 @@ When building REST APIs and server applications with Node.js/Bun, developers cho
611
611
  <div class="tradeoff cost">
612
612
  <h3>What's Growing</h3>
613
613
  <ul>
614
- <li><span class="highlight-text">Community</span> expanding every day</li>
615
- <li><span class="highlight-text">Documentation</span> continuously improving</li>
616
- <li><span class="highlight-text">Ecosystem</span> core features ready, plugins coming</li>
617
- <li><span class="highlight-text">LTS</span> planning for long-term support</li>
614
+ <li><span class="highlight-text">Community</span> - expanding every day</li>
615
+ <li><span class="highlight-text">Documentation</span> - continuously improving</li>
616
+ <li><span class="highlight-text">Ecosystem</span> - core features ready, plugins coming</li>
617
+ <li><span class="highlight-text">LTS</span> - planning for long-term support</li>
618
618
  </ul>
619
619
  </div>
620
620
 
@@ -1,6 +1,6 @@
1
1
  # Setup
2
2
 
3
- Everything you need to start building with Ignis. This guide covers installation for macOS, Linux, and Windows (via WSL2).
3
+ Everything you need to start building with IGNIS. This guide covers installation for macOS, Linux, and Windows (via WSL2).
4
4
 
5
5
  ## Requirements
6
6
 
@@ -153,5 +153,5 @@ sudo service postgresql start
153
153
 
154
154
  ## Next Steps
155
155
 
156
- - [5-Minute Quickstart](./5-minute-quickstart.md) Build your first API
157
- - [Complete Installation](../tutorials/complete-installation.md) Full project setup
156
+ - [5-Minute Quickstart](./5-minute-quickstart.md) - Build your first API
157
+ - [Complete Installation](../tutorials/complete-installation.md) - Full project setup
@@ -1,6 +1,6 @@
1
- # Getting Started with Ignis
1
+ # Getting Started with IGNIS
2
2
 
3
- Welcome to Ignis a TypeScript framework that combines enterprise architecture patterns with Hono's blazing performance. Whether you're building a SaaS backend, REST API, gRPC service, or microservice, these guides will take you from installation to production-ready code with type-safe database operations, auto-generated OpenAPI docs, and clean dependency injection.
3
+ Welcome to IGNIS - a TypeScript framework that combines enterprise architecture patterns with Hono's blazing performance. Whether you're building a SaaS backend, REST API, gRPC service, or microservice, these guides will take you from installation to production-ready code with type-safe database operations, auto-generated OpenAPI docs, and clean dependency injection.
4
4
 
5
5
  <div class="guide-cards">
6
6
 
@@ -31,7 +31,7 @@ Welcome to Ignis — a TypeScript framework that combines enterprise architectur
31
31
 
32
32
  <a href="./get-started/philosophy" class="guide-card">
33
33
  <h3>Philosophy</h3>
34
- <p>Why Ignis? Design decisions explained</p>
34
+ <p>Why IGNIS? Design decisions explained</p>
35
35
  </a>
36
36
 
37
37
  </div>
@@ -0,0 +1,177 @@
1
+ ---
2
+ title: Migrating to the new Redis Helper API
3
+ description: Breaking changes and migration steps for the IGNIS Redis helper refactor - folder-per-topology, AbstractRedisHelper, camelCase methods, Sentinel, and the createRedisHelper factory
4
+ ---
5
+
6
+ # Migrating to the new Redis Helper API
7
+
8
+ > **Audience:** any application upgrading `@venizia/ignis-helpers` (and `@venizia/ignis`) across the Redis helper refactor release. This guide describes exactly what breaks and how to migrate. It applies to every consumer - it is not specific to any one app.
9
+
10
+ ---
11
+
12
+ ## 0. TL;DR
13
+
14
+ The IGNIS Redis module was restructured into one base class plus three topologies (single / cluster / sentinel) behind a segregated `IRedisHelper` interface. Several public symbols were **renamed with no back-compat aliases (clean break)**, and the lowercase hash/multi methods were removed in favor of camelCase. Your project **will not compile** against the new version until you apply the renames in §1.
15
+
16
+ Nothing in your data or Redis server changes - this is a code-level rename plus a few additive features. The single and cluster connection behavior is byte-for-byte identical to before; only the new `RedisSentinelHelper` introduces new behavior.
17
+
18
+ | Effort | What |
19
+ |--------|------|
20
+ | **Low - mechanical renames** | Apply the rename table in §1 and the method renames in §1.2. Compiler-guided: every stale reference becomes a type error. |
21
+
22
+ ---
23
+
24
+ ## 1. What changed (breaking)
25
+
26
+ ### 1.1 Class and type renames (no aliases)
27
+
28
+ | Old (removed) | New |
29
+ |---------------|-----|
30
+ | `DefaultRedisHelper` | `AbstractRedisHelper` |
31
+ | `RedisHelper` | `RedisSingleHelper` |
32
+ | `IRedisHelperOptions` | `IRedisSingleHelperOptions` |
33
+ | `IRedisHelperProps` | `IRedisSingleHelperProps` |
34
+
35
+ `RedisClusterHelper` is **unchanged** in name and behavior.
36
+
37
+ `AbstractRedisHelper` is the base class (never constructed directly). Use it only where you need an `instanceof` check or a concrete-class binding; for plain typing prefer the `IRedisHelper` interface.
38
+
39
+ ### 1.2 Lowercase methods removed - use camelCase
40
+
41
+ The duplicate lowercase aliases were removed. The camelCase forms are now the only API.
42
+
43
+ | Old (removed) | New |
44
+ |---------------|-----|
45
+ | `.hset(...)` | `.hSet(...)` |
46
+ | `.hgetall(...)` | `.hGetAll(...)` |
47
+ | `.mset(...)` | `.mSet(...)` |
48
+ | `.mget(...)` | `.mGet(...)` |
49
+
50
+ Single-word methods (`get`, `set`, `del`, `keys`, `publish`, `subscribe`) are unchanged.
51
+
52
+ ### 1.3 Callback type narrowed
53
+
54
+ `IRedisHelperCallbacks.onError` now receives `error: unknown` (was `error: any`). This only affects you if you access properties on `error` without narrowing first.
55
+
56
+ ---
57
+
58
+ ## 2. Find every affected site
59
+
60
+ Run this in your project root. Every match is a site to migrate:
61
+
62
+ ```bash
63
+ grep -rnE 'DefaultRedisHelper|\bRedisHelper\b|IRedisHelper(Options|Props)\b|\.(hset|mset|hgetall|mget)\(' src
64
+ ```
65
+
66
+ `\bRedisHelper\b` matches the bare class only - it will not match `RedisClusterHelper` / `RedisSingleHelper`.
67
+
68
+ After migrating, re-run it; a clean result plus a green `tsc` means you are done.
69
+
70
+ ---
71
+
72
+ ## 3. Migration steps (before / after)
73
+
74
+ ### Constructing a single-node connection
75
+
76
+ ```typescript
77
+ // Before
78
+ import { RedisHelper } from '@venizia/ignis-helpers';
79
+ const redis = new RedisHelper({ name: 'cache', host, port, password });
80
+
81
+ // After
82
+ import { RedisSingleHelper } from '@venizia/ignis-helpers';
83
+ const redis = new RedisSingleHelper({ name: 'cache', host, port, password });
84
+ ```
85
+
86
+ ### Typing a Redis connection (config, fields, params)
87
+
88
+ Prefer the interface for plain typing:
89
+
90
+ ```typescript
91
+ // Before
92
+ import { DefaultRedisHelper } from '@venizia/ignis-helpers';
93
+ function useRedis(connection: DefaultRedisHelper) { /* ... */ }
94
+
95
+ // After
96
+ import type { IRedisHelper } from '@venizia/ignis-helpers';
97
+ function useRedis(connection: IRedisHelper) { /* ... */ }
98
+ ```
99
+
100
+ ### instanceof checks and concrete bindings
101
+
102
+ Use the concrete base class (you cannot `instanceof` an interface):
103
+
104
+ ```typescript
105
+ // Before
106
+ if (connection instanceof DefaultRedisHelper) { /* ... */ }
107
+
108
+ // After
109
+ import { AbstractRedisHelper } from '@venizia/ignis-helpers';
110
+ if (connection instanceof AbstractRedisHelper) { /* ... */ }
111
+ ```
112
+
113
+ ### Options type rename
114
+
115
+ ```typescript
116
+ // Before
117
+ import type { IRedisHelperOptions } from '@venizia/ignis-helpers';
118
+
119
+ // After
120
+ import type { IRedisSingleHelperOptions } from '@venizia/ignis-helpers';
121
+ ```
122
+
123
+ ### Hash and multi-key calls
124
+
125
+ ```typescript
126
+ // Before
127
+ await redis.hset({ key, value });
128
+ const all = await redis.hgetall({ key });
129
+ await redis.mset({ payload });
130
+ const many = await redis.mget({ keys });
131
+
132
+ // After
133
+ await redis.hSet({ key, value });
134
+ const all = await redis.hGetAll({ key });
135
+ await redis.mSet({ payload });
136
+ const many = await redis.mGet({ keys });
137
+ ```
138
+
139
+ ---
140
+
141
+ ## 4. Runtime behavior changes to verify
142
+
143
+ These compile unchanged but behave slightly differently. All are strictly safer; verify only if your code depended on the old behavior.
144
+
145
+ | Method | Old behavior | New behavior |
146
+ |--------|--------------|--------------|
147
+ | `subscribe` / `unsubscribe` | threw inside the ioredis callback on a subscription error (an unhandled async throw) | logs the error and returns; never throws |
148
+ | `del` / `mGet` / `mSet` | forwarded empty input to Redis, which throws "wrong number of arguments" | empty input is a no-op: returns `0` / `[]` / void without a Redis call |
149
+
150
+ If you wrapped `subscribe(...)` in a `try/catch` expecting it to throw, that branch no longer fires. If you relied on `del([])` throwing, it now returns `0`.
151
+
152
+ ---
153
+
154
+ ## 5. What you gain (additive - no action required)
155
+
156
+ These are new and do not break anything:
157
+
158
+ - **`RedisSentinelHelper`** - Redis Sentinel topology with automatic failover. See the [Redis Helper reference](/extensions/helpers/redis/) (Sentinel section).
159
+ - **`createRedisHelper({ mode })`** - a factory that builds the right helper from `RedisModes.SINGLE | CLUSTER | SENTINEL`, so you can pick a topology from config.
160
+ - **`RedisModes`** and **`RedisSentinelRoles`** - const-classes for the enumerable mode/role strings, with matching `TRedisMode` / `TRedisSentinelRole` types.
161
+ - **Expanded data API** - key lifecycle and counters (`exists`, `expire`, `expireAt`, `ttl`, `persist`, `incr`, `decr`, `incrBy`, `decrBy`), hash completion (`hGet`, `hDel`, `hExists`, `hKeys`, `hVals`, `hIncrBy`, `hLen`), sets (`sAdd`, `sRem`, `sMembers`, `sIsMember`, `sCard`), and lists (`lPush`, `rPush`, `lPop`, `rPop`, `lRange`, `lLen`).
162
+ - **`set` TTL option** - `set({ key, value, options: { expiresIn } })` where `expiresIn` is milliseconds (uses `PX`).
163
+ - **All three topologies are interchangeable** - anywhere an `IRedisHelper` is accepted (BullMQ, Socket.IO, WebSocket, the Casbin cache), you can now pass a single, cluster, or sentinel helper without changing the consumer.
164
+
165
+ ---
166
+
167
+ ## 6. Migration checklist
168
+
169
+ - [ ] Run the grep in §2; note every match.
170
+ - [ ] Apply the §1.1 class/type renames.
171
+ - [ ] Apply the §1.2 lowercase to camelCase method renames.
172
+ - [ ] Switch plain-typed connection references to `IRedisHelper`; keep `AbstractRedisHelper` for `instanceof` / concrete bindings.
173
+ - [ ] Narrow `onError` usage if you read fields off `error`.
174
+ - [ ] Review §4 if you relied on subscribe throwing or empty-input throwing.
175
+ - [ ] Re-run the grep (clean) and `tsc` (green); run your test suite.
176
+
177
+ When the grep is clean and the build is green, the migration is complete - there is no data or server-side change to perform.
@@ -16,8 +16,8 @@ You have two paths:
16
16
 
17
17
  | Path | Effort | When |
18
18
  |------|--------|------|
19
- | **B Bridge** (re-base your custom adapter on `BaseFilteredAdapter`, keep your flat model) | Low code only, **no data migration** | Do this first to unblock the upgrade |
20
- | **A Adopt scoped** (delete your custom adapter, use `ScopedCasbinAdapter` + scoped model) | High needs a **data migration** | The intended long-term target |
19
+ | **B - Bridge** (re-base your custom adapter on `BaseFilteredAdapter`, keep your flat model) | Low - code only, **no data migration** | Do this first to unblock the upgrade |
20
+ | **A - Adopt scoped** (delete your custom adapter, use `ScopedCasbinAdapter` + scoped model) | High - needs a **data migration** | The intended long-term target |
21
21
 
22
22
  Both are described below with exact before/after.
23
23
 
@@ -67,9 +67,9 @@ When you bump ignis, these stop compiling/working:
67
67
 
68
68
  ---
69
69
 
70
- ## 3. Path B Bridge (recommended first step, no data migration)
70
+ ## 3. Path B - Bridge (recommended first step, no data migration)
71
71
 
72
- Goal: compile against new ignis with **identical runtime behavior** keep your flat `CASBIN_RBAC_MODEL`,
72
+ Goal: compile against new ignis with **identical runtime behavior** - keep your flat `CASBIN_RBAC_MODEL`,
73
73
  your `group`/`policy` variant values, and all bespoke logic (global roles, HQ-owner expansion).
74
74
 
75
75
  ### 3.1 Define your own variant constants
@@ -147,24 +147,24 @@ Key swaps inside the class:
147
147
  - `filter.principalValue` → `filter.principal.id`; `filter.principalType` → `filter.principal.type`.
148
148
  - `this.entities.role.principalType` / `this.entities.permission.principalType` → from your own
149
149
  `entities` (pass the same values you pass today; drop the `tableName`/`policyDefinition` parts the
150
- base used to require you import the Drizzle tables directly already).
150
+ base used to require - you import the Drizzle tables directly already).
151
151
  - `CasbinRuleVariants.GROUP/.POLICY` → `PolicyDefinitionVariant.GROUP/.POLICY` (§3.1).
152
152
 
153
153
  ### 3.3 Fix the cache fallback in `verifier.ts`
154
154
 
155
155
  ```ts
156
- // BEFORE in-memory fallback (driver removed)
156
+ // BEFORE - in-memory fallback (driver removed)
157
157
  const cached: ICasbinEnforcerOptions['cached'] = redis
158
158
  ? { use: true, driver: CasbinEnforcerCachedDrivers.REDIS, options: { ... } }
159
159
  : { use: true, driver: CasbinEnforcerCachedDrivers.IN_MEMORY, options: { expiresIn: 5*60*1000 } };
160
160
 
161
- // AFTER Redis or no cache
161
+ // AFTER - Redis or no cache
162
162
  const cached: ICasbinEnforcerOptions['cached'] = redis
163
163
  ? { use: true, driver: CasbinEnforcerCachedDrivers.REDIS, options: { connection: redis, expiresIn: 5*60*1000, keyFn: ({ user }) => `casbin:${user.principalType}:${user.userId}` } }
164
164
  : { use: false };
165
165
  ```
166
166
 
167
- > **Decide:** in prod, **always provide Redis** without it every request rebuilds the policy from the
167
+ > **Decide:** in prod, **always provide Redis** - without it every request rebuilds the policy from the
168
168
  > DB (no per-user cache). The pool still protects you from the concurrency race, but you lose the line cache.
169
169
 
170
170
  ### 3.4 Adapter construction (`verifier.ts`)
@@ -187,7 +187,7 @@ stays. **Result: behavior identical, compiles on new ignis, zero data migration.
187
187
 
188
188
  ---
189
189
 
190
- ## 4. Path A Adopt the scoped model (target state)
190
+ ## 4. Path A - Adopt the scoped model (target state)
191
191
 
192
192
  This deletes `ApplicationCasbinAdapter` entirely and uses the generic `ScopedCasbinAdapter`. The
193
193
  bespoke logic moves from **code** into **data (edges)**. Do this once Path B has unblocked you.
@@ -221,7 +221,7 @@ const adapter = new ScopedCasbinAdapter({
221
221
  // pass the request domain via the provider's domain resolver instead)
222
222
  ```
223
223
 
224
- ### 4.2 Data migration the `variant` column
224
+ ### 4.2 Data migration - the `variant` column
225
225
 
226
226
  The scoped adapter filters on `AuthorizationPolicyVariants.*.action`, not `group`/`policy`. You must
227
227
  re-classify rows:
@@ -234,11 +234,11 @@ re-classify rows:
234
234
  | `policy` (role→perm or user→perm) | `grant` | permission grant |
235
235
 
236
236
  New edge types you may need to **add** (no equivalent today):
237
- - `domain_inherits` (Merchant ⊂ Organizer / HQ) **this replaces the bespoke `queryHqOwnerOrgMerchants`
237
+ - `domain_inherits` (Merchant ⊂ Organizer / HQ) - **this replaces the bespoke `queryHqOwnerOrgMerchants`
238
238
  JOIN**. Materialize one row per Merchant→Organizer (or →HQ-merchant) relationship; the scoped model's
239
239
  `g3` then cascades a grant on the parent domain to all child merchants automatically. Maintain these
240
240
  rows when merchants/organizers are created or moved.
241
- - `resource_inherits` (`g4`) / `action_inherits` (`g5`) only if you want resource/action hierarchies.
241
+ - `resource_inherits` (`g4`) / `action_inherits` (`g5`) - only if you want resource/action hierarchies.
242
242
 
243
243
  ### 4.3 Re-express bespoke behavior as data
244
244
 
@@ -249,7 +249,7 @@ New edge types you may need to **add** (no equivalent today):
249
249
  | HQ-owner expansion (live JOIN) | `domain_inherits` (`g3`) edges (see §4.2) |
250
250
  | Domain-agnostic role permissions (`p, Role, *, ...`) | Grant rows with domain `ANY_MEMBER` (default when `domain` is NULL) |
251
251
 
252
- ### 4.4 Behavioral caveat resource matching changes
252
+ ### 4.4 Behavioral caveat - resource matching changes
253
253
 
254
254
  Your flat model uses exact `r.obj == p.obj`. The scoped model uses **`objectMatch`** (dotted-prefix +
255
255
  wildcard): a grant on `Order` will now **also** match `Order.findById`, and `p.obj = '*'` matches any
@@ -277,20 +277,20 @@ the bespoke adapter and gain resource/action/domain hierarchies for free.
277
277
 
278
278
  ## 6. Verification checklist (either path)
279
279
 
280
- - [ ] `bun run build` (or `tsc -p .`) is clean no references to `DrizzleCasbinAdapter`,
280
+ - [ ] `bun run build` (or `tsc -p .`) is clean - no references to `DrizzleCasbinAdapter`,
281
281
  `IDrizzleCasbinAdapterOptions`, `CasbinRuleVariants.GROUP/.POLICY`, `CasbinEnforcerCachedDrivers.IN_MEMORY`,
282
282
  `IAuthorizationCacheInvalidator`.
283
283
  - [ ] `SELECT DISTINCT variant FROM identity."PolicyDefinition"` matches what your adapter filters on
284
284
  (`group`/`policy` for Path B; the new `*.action` set for Path A).
285
285
  - [ ] A request for a user with a role-inherited / per-merchant / global permission resolves the same
286
- ALLOW/DENY as before the upgrade (pick 34 representative users and diff).
286
+ ALLOW/DENY as before the upgrade (pick 3-4 representative users and diff).
287
287
  - [ ] If `cached.use: true`, Redis is reachable; if a permission changes, call
288
- `enforcer.invalidateUserCache({ user })` (or rely on TTL) see the ignis authorization docs.
288
+ `enforcer.invalidateUserCache({ user })` (or rely on TTL) - see the ignis authorization docs.
289
289
  - [ ] Super-admin / always-allow-roles still short-circuit (these run in the provider before the enforcer).
290
290
 
291
291
  ---
292
292
 
293
- ## 7. Reference current nx-seller wiring (before)
293
+ ## 7. Reference - current nx-seller wiring (before)
294
294
 
295
295
  For context, the current registration (`packages/core/src/application/verifier.ts`) uses:
296
296
  `ApplicationCasbinAdapter` (subclass of removed `DrizzleCasbinAdapter`), `CASBIN_RBAC_MODEL` (flat
@@ -0,0 +1,113 @@
1
+ ---
2
+ title: Upgrading to Unified Connectors (BANA Guide)
3
+ description: What changed in @venizia/ignis 0.0.11-0 / @venizia/ignis-helpers 0.0.10-0 and the exact steps a consumer application must take
4
+ ---
5
+
6
+ # Upgrading to Unified Connectors
7
+
8
+ **Target audience:** the BANA (nx-seller) team, and any application upgrading from `@venizia/ignis@0.0.10-x` / `@venizia/ignis-helpers@0.0.9-x`.
9
+
10
+ **Verification status:** every step below was validated against a full copy of BANA's `packages/core` source compiled against the release tarballs - the migration ends at **zero compile errors**. The search branch was additionally validated end to end against a live 3-node Typesense cluster.
11
+
12
+ ## What changed (summary)
13
+
14
+ IGNIS core was restructured around ONE engine-neutral repository family:
15
+
16
+ - `src/base` now holds a single `AbstractRepository` / `AbstractDataSource` / `AbstractEntity` family. Every engine implements it under `src/connectors/{postgres,typesense}`.
17
+ - Postgres remains re-exported from the root barrel - **your imports keep working unchanged**. Every connector is also addressable explicitly: `@venizia/ignis/postgres`, `@venizia/ignis/typesense` (typesense is subpath-only; its client is an optional peer).
18
+ - Canonical class names are the paradigm-family names (`BaseRelationalDataSource`, `BaseRelationalEntity`, `DefaultRelationalRepository`, ...); the engine name appears only at the concrete datasource (`TypesenseDataSource`) and the query dialect (`PostgresQueryOperators`). The historical names (`BaseDataSource`, `BaseEntity`, `BasePostgresDataSource`, `BasePostgresEntity`, `RDBQueryOperators`, `DefaultCRUDRepository`, ...) all remain as alias re-exports of the SAME classes - `instanceof`, metadata, and bindings are unaffected. No action required; prefer the family names in new code.
19
+ - New capabilities model: `dataSource.getCapabilities()` and a standardized NotSupported error (HTTP 501, messageCode `core.not_supported`) for engine gaps (e.g. transactions on search engines).
20
+ - New engine: the **Typesense search branch** (`BaseSearchEntity`, `defineSearchCollection`, typed `TSearchDocument`, `DefaultSearchRepository`). It does not affect existing postgres code.
21
+
22
+ ## Required migrations (in order)
23
+
24
+ ### 1. Transaction type rename - the only sweeping change
25
+
26
+ `ITransaction` is now the neutral base contract (no `connector` field). The postgres-rich types were renamed:
27
+
28
+ | Old | New |
29
+ |---|---|
30
+ | `ITransaction<Schema>` (with `.connector`) | `IDatabaseTransaction<Schema>` |
31
+ | `ITransactionOptions` (postgres isolation levels) | `IDatabaseTransactionOptions` |
32
+ | `IExtraOptions` used as the repository 4th generic | `IDatabaseExtraOptions` |
33
+
34
+ Measured impact on BANA: 398 files, one mechanical rewrite, proven zero-error:
35
+
36
+ ```bash
37
+ grep -rl 'ITransaction\|IExtraOptions' packages/*/src --include='*.ts' \
38
+ | xargs sed -i 's/\bITransaction\b/IDatabaseTransaction/g; s/\bIExtraOptions\b/IDatabaseExtraOptions/g'
39
+ ```
40
+
41
+ Note: `options?.transaction?.connector` inside `DefaultCRUDRepository` (alias of `DefaultRelationalRepository`) subclasses needs NO change - the postgres tiers now default their options generic to `IDatabaseExtraOptions`, so that path stays typed automatically.
42
+
43
+ ### 2. `applicationEnvironment.get` - options object
44
+
45
+ The second positional argument became an options object (and gained `transform`):
46
+
47
+ ```typescript
48
+ // Before
49
+ const port = applicationEnvironment.get<string>(Keys.PORT, '3000');
50
+
51
+ // After
52
+ const port = applicationEnvironment.get<string>(Keys.PORT, { defaultValue: '3000' });
53
+
54
+ // New capability - transform raw env values in one read:
55
+ const nodes = applicationEnvironment.get<string[], string>(Keys.NODES, {
56
+ defaultValue: [],
57
+ transform: value => toDelimitedArray(value),
58
+ });
59
+ ```
60
+
61
+ Measured impact on BANA: **5 call sites** use the positional form. They fail at compile time (not silently), so `tsc` will point at each one:
62
+
63
+ ```bash
64
+ grep -rnE "applicationEnvironment.get(<[^>]*>)?\([^,)]+, [^{]" packages/*/src --include='*.ts'
65
+ ```
66
+
67
+ New helpers: `toDelimitedArray(input, separator?)` (split + trim + drop empties) and `toTrimmed(input)` from `@venizia/ignis-helpers`.
68
+
69
+ ### 3. Purge stale TypeScript build info
70
+
71
+ The package's `exports` map changed; stale incremental caches replay phantom diagnostics for unchanged files (a page of bogus "missing property" errors while new files compile clean):
72
+
73
+ ```bash
74
+ find . -name '*.tsbuildinfo' -not -path '*/node_modules/*' -delete
75
+ ```
76
+
77
+ Run this once after the version bump, before trusting the first `tsc` run.
78
+
79
+ ### 4. Auth endpoint error contract (only if you assert on it)
80
+
81
+ The three auth endpoints backed by unimplemented service methods (`refreshToken`, `getUserInformation`) now return the standardized NotSupported error: HTTP 501 with messageCode `core.not_supported` and message `[AuthController] <feature> is not supported.` (previously a plain `Method not implemented`). BANA was scanned: no code asserts on the old string - listed for completeness.
82
+
83
+ ## Strongly recommended (not compile-blocking)
84
+
85
+ ### Declare decorator flags directly in every bun-run app
86
+
87
+ bun 1.3.14 silently DROPS `@inject` constructor-parameter decorators when the app's `tsconfig.json` only inherits `experimentalDecorators` through a package-style `extends` it fails to resolve. Symptom: the app boots normally, every route mounts, and then `this.repository` / injected services are `undefined` at request time. Protect every app that runs via `bun src/...`:
88
+
89
+ ```jsonc
90
+ // tsconfig.json - alongside your extends, not instead of it
91
+ {
92
+ "compilerOptions": {
93
+ "experimentalDecorators": true,
94
+ "emitDecoratorMetadata": true
95
+ }
96
+ }
97
+ ```
98
+
99
+ All IGNIS examples now declare these explicitly.
100
+
101
+ ## Rollout procedure (proven order)
102
+
103
+ 1. Bump `@venizia/ignis` -> `0.0.11-0` and `@venizia/ignis-helpers` -> `0.0.10-0` in ONE canary package first - `packages/commerce` is the recommended canary (heaviest transaction + ControllerFactory usage).
104
+ 2. Run migrations 1-3 on the canary; `tsc --noEmit` must be clean.
105
+ 3. Run the canary's test suite.
106
+ 4. Green -> apply migrations repo-wide, bump the remaining packages, full suite.
107
+
108
+ ## What you explicitly do NOT need to do
109
+
110
+ - No import-path changes: root-barrel imports of `BaseDataSource`, `BaseEntity`, `DefaultCRUDRepository`, decorators, etc. all keep working (dual-door export model + compatibility aliases).
111
+ - No repository/generic signature changes: `DefaultCRUDRepository<Schema, DataObject, PersistObject, ...>` call sites are unchanged (a 4th options generic was APPENDED with a default).
112
+ - No runtime behavior changes on the postgres path: the whole pre-existing RDB behavior suite runs unchanged inside the release gates, and every behavior delta was verified to have no trigger inside BANA (`@model` tableName divergence: 0 occurrences; message-string assertions: 0).
113
+ - Nothing search-related: BANA imports zero search symbols today.