@lenne.tech/nest-server 11.27.5 → 11.27.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/.claude/rules/architecture.md +66 -0
  2. package/.claude/rules/better-auth.md +88 -2
  3. package/.claude/rules/configurable-features.md +2 -2
  4. package/.claude/rules/package-management.md +23 -14
  5. package/.claude/rules/testing.md +27 -9
  6. package/CLAUDE.md +12 -4
  7. package/FRAMEWORK-API.md +1 -1
  8. package/bin/migrate.js +84 -25
  9. package/dist/core/common/decorators/restricted.decorator.d.ts +4 -4
  10. package/dist/core/common/decorators/restricted.decorator.js +21 -22
  11. package/dist/core/common/decorators/restricted.decorator.js.map +1 -1
  12. package/dist/core/common/helpers/clone.helper.d.ts +6 -0
  13. package/dist/core/common/helpers/clone.helper.js +67 -0
  14. package/dist/core/common/helpers/clone.helper.js.map +1 -0
  15. package/dist/core/common/helpers/cookies.helper.d.ts +1 -0
  16. package/dist/core/common/helpers/cookies.helper.js +33 -16
  17. package/dist/core/common/helpers/cookies.helper.js.map +1 -1
  18. package/dist/core/common/helpers/db.helper.d.ts +2 -14
  19. package/dist/core/common/helpers/db.helper.js +13 -106
  20. package/dist/core/common/helpers/db.helper.js.map +1 -1
  21. package/dist/core/common/helpers/id.helper.d.ts +15 -0
  22. package/dist/core/common/helpers/id.helper.js +104 -0
  23. package/dist/core/common/helpers/id.helper.js.map +1 -0
  24. package/dist/core/common/helpers/input.helper.d.ts +1 -6
  25. package/dist/core/common/helpers/input.helper.js +11 -70
  26. package/dist/core/common/helpers/input.helper.js.map +1 -1
  27. package/dist/core/common/inputs/combined-filter.input.d.ts +1 -12
  28. package/dist/core/common/inputs/combined-filter.input.js +2 -51
  29. package/dist/core/common/inputs/combined-filter.input.js.map +1 -1
  30. package/dist/core/common/inputs/filter.input.d.ts +10 -1
  31. package/dist/core/common/inputs/filter.input.js +40 -5
  32. package/dist/core/common/inputs/filter.input.js.map +1 -1
  33. package/dist/core/common/services/config.service.js +5 -5
  34. package/dist/core/common/services/config.service.js.map +1 -1
  35. package/dist/core/modules/ai/core-ai.constants.d.ts +22 -0
  36. package/dist/core/modules/ai/core-ai.constants.js +26 -0
  37. package/dist/core/modules/ai/core-ai.constants.js.map +1 -0
  38. package/dist/core/modules/ai/index.d.ts +1 -0
  39. package/dist/core/modules/ai/index.js +1 -0
  40. package/dist/core/modules/ai/index.js.map +1 -1
  41. package/dist/core/modules/ai/interfaces/ai-interaction-record.interface.d.ts +17 -0
  42. package/dist/core/modules/ai/interfaces/ai-interaction-record.interface.js +3 -0
  43. package/dist/core/modules/ai/interfaces/ai-interaction-record.interface.js.map +1 -0
  44. package/dist/core/modules/ai/services/core-ai-budget.service.d.ts +1 -2
  45. package/dist/core/modules/ai/services/core-ai-budget.service.js +7 -5
  46. package/dist/core/modules/ai/services/core-ai-budget.service.js.map +1 -1
  47. package/dist/core/modules/ai/services/core-ai-connection-preference.service.d.ts +1 -2
  48. package/dist/core/modules/ai/services/core-ai-connection-preference.service.js +7 -5
  49. package/dist/core/modules/ai/services/core-ai-connection-preference.service.js.map +1 -1
  50. package/dist/core/modules/ai/services/core-ai-connection.service.d.ts +1 -2
  51. package/dist/core/modules/ai/services/core-ai-connection.service.js +7 -5
  52. package/dist/core/modules/ai/services/core-ai-connection.service.js.map +1 -1
  53. package/dist/core/modules/ai/services/core-ai-conversation.service.d.ts +1 -2
  54. package/dist/core/modules/ai/services/core-ai-conversation.service.js +7 -5
  55. package/dist/core/modules/ai/services/core-ai-conversation.service.js.map +1 -1
  56. package/dist/core/modules/ai/services/core-ai-interaction.service.d.ts +2 -3
  57. package/dist/core/modules/ai/services/core-ai-interaction.service.js +7 -5
  58. package/dist/core/modules/ai/services/core-ai-interaction.service.js.map +1 -1
  59. package/dist/core/modules/ai/services/core-ai-mode.service.d.ts +1 -2
  60. package/dist/core/modules/ai/services/core-ai-mode.service.js +7 -5
  61. package/dist/core/modules/ai/services/core-ai-mode.service.js.map +1 -1
  62. package/dist/core/modules/ai/services/core-ai-prompt-hint.service.d.ts +1 -3
  63. package/dist/core/modules/ai/services/core-ai-prompt-hint.service.js +7 -5
  64. package/dist/core/modules/ai/services/core-ai-prompt-hint.service.js.map +1 -1
  65. package/dist/core/modules/ai/services/core-ai-prompt.service.d.ts +1 -2
  66. package/dist/core/modules/ai/services/core-ai-prompt.service.js +7 -5
  67. package/dist/core/modules/ai/services/core-ai-prompt.service.js.map +1 -1
  68. package/dist/core/modules/ai/services/core-ai-slot.service.d.ts +1 -2
  69. package/dist/core/modules/ai/services/core-ai-slot.service.js +7 -5
  70. package/dist/core/modules/ai/services/core-ai-slot.service.js.map +1 -1
  71. package/dist/core/modules/ai/services/core-ai-tool-grant.service.d.ts +1 -2
  72. package/dist/core/modules/ai/services/core-ai-tool-grant.service.js +7 -5
  73. package/dist/core/modules/ai/services/core-ai-tool-grant.service.js.map +1 -1
  74. package/dist/core/modules/ai/services/core-ai-tool-policy.service.d.ts +1 -2
  75. package/dist/core/modules/ai/services/core-ai-tool-policy.service.js +7 -5
  76. package/dist/core/modules/ai/services/core-ai-tool-policy.service.js.map +1 -1
  77. package/dist/core/modules/ai/services/core-ai.service.d.ts +2 -17
  78. package/dist/core/modules/ai/services/core-ai.service.js.map +1 -1
  79. package/dist/core/modules/better-auth/better-auth-roles.guard.js +2 -2
  80. package/dist/core/modules/better-auth/better-auth-roles.guard.js.map +1 -1
  81. package/dist/core/modules/better-auth/better-auth.config.js +12 -8
  82. package/dist/core/modules/better-auth/better-auth.config.js.map +1 -1
  83. package/dist/core/modules/better-auth/core-better-auth.constants.d.ts +3 -0
  84. package/dist/core/modules/better-auth/core-better-auth.constants.js +7 -0
  85. package/dist/core/modules/better-auth/core-better-auth.constants.js.map +1 -0
  86. package/dist/core/modules/better-auth/core-better-auth.module.d.ts +1 -2
  87. package/dist/core/modules/better-auth/core-better-auth.module.js +23 -20
  88. package/dist/core/modules/better-auth/core-better-auth.module.js.map +1 -1
  89. package/dist/core/modules/better-auth/core-better-auth.registry.d.ts +4 -0
  90. package/dist/core/modules/better-auth/core-better-auth.registry.js +16 -0
  91. package/dist/core/modules/better-auth/core-better-auth.registry.js.map +1 -0
  92. package/dist/core/modules/better-auth/core-better-auth.service.d.ts +1 -2
  93. package/dist/core/modules/better-auth/core-better-auth.service.js +7 -6
  94. package/dist/core/modules/better-auth/core-better-auth.service.js.map +1 -1
  95. package/dist/core/modules/better-auth/index.d.ts +1 -0
  96. package/dist/core/modules/better-auth/index.js +1 -0
  97. package/dist/core/modules/better-auth/index.js.map +1 -1
  98. package/dist/core/modules/migrate/migration-runner.d.ts +1 -0
  99. package/dist/core/modules/migrate/migration-runner.js +3 -2
  100. package/dist/core/modules/migrate/migration-runner.js.map +1 -1
  101. package/dist/core/modules/tus/tus.constants.d.ts +1 -0
  102. package/dist/core/modules/tus/tus.constants.js +5 -0
  103. package/dist/core/modules/tus/tus.constants.js.map +1 -0
  104. package/dist/core/modules/tus/tus.module.d.ts +1 -1
  105. package/dist/core/modules/tus/tus.module.js +8 -6
  106. package/dist/core/modules/tus/tus.module.js.map +1 -1
  107. package/dist/tsconfig.build.tsbuildinfo +1 -1
  108. package/docs/REQUEST-LIFECYCLE.md +17 -4
  109. package/migration-guides/11.27.5-to-11.27.6.md +359 -0
  110. package/migration-guides/11.27.6-to-11.27.7.md +374 -0
  111. package/package.json +11 -104
  112. package/src/core/common/decorators/restricted.decorator.ts +33 -8
  113. package/src/core/common/helpers/clone.helper.ts +110 -0
  114. package/src/core/common/helpers/cookies.helper.ts +101 -26
  115. package/src/core/common/helpers/db.helper.ts +14 -161
  116. package/src/core/common/helpers/id.helper.ts +198 -0
  117. package/src/core/common/helpers/input.helper.ts +12 -84
  118. package/src/core/common/inputs/combined-filter.input.ts +10 -57
  119. package/src/core/common/inputs/filter.input.ts +92 -1
  120. package/src/core/common/interfaces/server-options.interface.ts +35 -6
  121. package/src/core/common/services/config.service.ts +4 -1
  122. package/src/core/modules/ai/core-ai.constants.ts +92 -0
  123. package/src/core/modules/ai/index.ts +1 -0
  124. package/src/core/modules/ai/interfaces/ai-interaction-record.interface.ts +34 -0
  125. package/src/core/modules/ai/services/core-ai-budget.service.ts +8 -4
  126. package/src/core/modules/ai/services/core-ai-connection-preference.service.ts +8 -4
  127. package/src/core/modules/ai/services/core-ai-connection.service.ts +5 -6
  128. package/src/core/modules/ai/services/core-ai-conversation.service.ts +5 -6
  129. package/src/core/modules/ai/services/core-ai-interaction.service.ts +6 -7
  130. package/src/core/modules/ai/services/core-ai-mode.service.ts +8 -2
  131. package/src/core/modules/ai/services/core-ai-prompt-hint.service.ts +7 -4
  132. package/src/core/modules/ai/services/core-ai-prompt.service.ts +8 -2
  133. package/src/core/modules/ai/services/core-ai-slot.service.ts +7 -4
  134. package/src/core/modules/ai/services/core-ai-tool-grant.service.ts +8 -4
  135. package/src/core/modules/ai/services/core-ai-tool-policy.service.ts +8 -4
  136. package/src/core/modules/ai/services/core-ai.service.ts +8 -11
  137. package/src/core/modules/better-auth/README.md +10 -4
  138. package/src/core/modules/better-auth/better-auth-roles.guard.ts +11 -5
  139. package/src/core/modules/better-auth/better-auth.config.ts +90 -15
  140. package/src/core/modules/better-auth/core-better-auth.constants.ts +73 -0
  141. package/src/core/modules/better-auth/core-better-auth.module.ts +34 -8
  142. package/src/core/modules/better-auth/core-better-auth.registry.ts +53 -0
  143. package/src/core/modules/better-auth/core-better-auth.service.ts +19 -12
  144. package/src/core/modules/better-auth/index.ts +9 -0
  145. package/src/core/modules/migrate/migration-runner.ts +16 -2
  146. package/src/core/modules/tus/tus.constants.ts +25 -0
  147. package/src/core/modules/tus/tus.module.ts +7 -2
@@ -20,6 +20,7 @@ export * from './inputs/core-ai-slot-update.input';
20
20
  export * from './inputs/core-ai-prompt.input';
21
21
  export * from './hooks/ai-hook.base';
22
22
  export * from './hooks/ai-hook.registry';
23
+ export * from './interfaces/ai-interaction-record.interface';
23
24
  export * from './interfaces/ai-hook.interface';
24
25
  export * from './interfaces/ai-placeholder.interface';
25
26
  export * from './interfaces/ai-tool.interface';
@@ -0,0 +1,34 @@
1
+ /**
2
+ * The record passed to `CoreAiService.audit()` for each prompt run.
3
+ *
4
+ * It lives here, in an import-free leaf, rather than in `core-ai.service.ts` — and that is
5
+ * load-bearing, not tidiness.
6
+ *
7
+ * `core-ai.service` imports `core-ai-interaction.service` (it needs the class), and
8
+ * `core-ai-interaction.service` needs this type back. Declared in the service, that pair forms an
9
+ * import cycle. It never crashed for exactly one reason: the type was pulled in with `import type`,
10
+ * which both tsc and SWC erase, so no `require()` was emitted and the cycle was never real at
11
+ * runtime.
12
+ *
13
+ * That is a single keyword of protection, on a file where `core-ai.service` has a constructor
14
+ * `@Inject`, so `emitDecoratorMetadata` emits `design:paramtypes` at module-evaluation time — the
15
+ * exact eval-time dereference that turns a cycle fatal. An IDE "organize imports" or a lint autofix
16
+ * widening `import type` to a plain `import` would have armed it silently, and `tsc`, `pnpm test`
17
+ * and `oxlint` are ALL blind to that (vitest runs SWC through Vite's cycle-tolerant module runner).
18
+ * Only `pnpm run check:swc-tdz` would have caught it — after the fact.
19
+ *
20
+ * Moving the type out removes the edge entirely, so the cycle no longer exists rather than merely
21
+ * being disarmed. `core-ai.service` re-exports it, so every existing import path still resolves.
22
+ *
23
+ * See .claude/rules/architecture.md → "DI Token Placement (SWC-Safe)".
24
+ */
25
+ export interface AiInteractionRecord {
26
+ actions: { name: string; success: boolean }[];
27
+ connectionId: string;
28
+ iterations: number;
29
+ prompt: string;
30
+ responseText: string;
31
+ tenantId?: string;
32
+ usage?: { completionTokens?: number; promptTokens?: number; totalTokens?: number };
33
+ userId?: string;
34
+ }
@@ -11,10 +11,14 @@ import { CoreAiBudgetLimitInput } from '../inputs/core-ai-budget-limit.input';
11
11
  import { AiBudgetLimitDocument, CoreAiBudgetLimit } from '../models/core-ai-budget-limit.model';
12
12
  import { CoreAiBudgetSummary, CoreAiUsageInfo, CoreAiUsageScope } from '../models/core-ai-usage-info.model';
13
13
 
14
- /** Mongoose injection token for the budget-limit model. */
15
- export const AI_BUDGET_LIMIT_MODEL = 'AiBudgetLimit';
16
- /** DI token for the budget-limit model constructor. */
17
- export const AI_BUDGET_LIMIT_CLASS = 'AI_BUDGET_LIMIT_CLASS';
14
+ import { AI_BUDGET_LIMIT_CLASS, AI_BUDGET_LIMIT_MODEL } from '../core-ai.constants';
15
+
16
+ /**
17
+ * @deprecated Import from `../core-ai.constants` instead. Re-exported only so existing deep imports
18
+ * keep working; the tokens are declared in an import-free leaf so no cycle can form around them
19
+ * (SWC-safe — see core-ai.constants.ts).
20
+ */
21
+ export { AI_BUDGET_LIMIT_CLASS, AI_BUDGET_LIMIT_MODEL } from '../core-ai.constants';
18
22
 
19
23
  /** Resolved effective limit for a scope. */
20
24
  export interface ResolvedAiBudgetLimit {
@@ -10,10 +10,14 @@ import {
10
10
  CoreAiConnectionPreference,
11
11
  } from '../models/core-ai-connection-preference.model';
12
12
 
13
- /** Mongoose injection token for the connection-preference model. */
14
- export const AI_CONNECTION_PREFERENCE_MODEL = 'AiConnectionPreference';
15
- /** DI token for the connection-preference model constructor. */
16
- export const AI_CONNECTION_PREFERENCE_CLASS = 'AI_CONNECTION_PREFERENCE_CLASS';
13
+ import { AI_CONNECTION_PREFERENCE_CLASS, AI_CONNECTION_PREFERENCE_MODEL } from '../core-ai.constants';
14
+
15
+ /**
16
+ * @deprecated Import from `../core-ai.constants` instead. Re-exported only so existing deep imports
17
+ * keep working; the tokens are declared in an import-free leaf so no cycle can form around them
18
+ * (SWC-safe — see core-ai.constants.ts).
19
+ */
20
+ export { AI_CONNECTION_PREFERENCE_CLASS, AI_CONNECTION_PREFERENCE_MODEL } from '../core-ai.constants';
17
21
 
18
22
  /**
19
23
  * CRUD + lookup for {@link CoreAiConnectionPreference} (tenant/user connection
@@ -23,15 +23,14 @@ import { LlmProviderFactory } from '../providers/llm-provider.factory';
23
23
  import { AiCryptoService } from './ai-crypto.service';
24
24
  import { CoreAiConnectionPreferenceService } from './core-ai-connection-preference.service';
25
25
 
26
- /**
27
- * Mongoose injection token for the AI connection model.
28
- */
29
- export const AI_CONNECTION_MODEL = 'AiConnection';
26
+ import { AI_CONNECTION_CLASS, AI_CONNECTION_MODEL } from '../core-ai.constants';
30
27
 
31
28
  /**
32
- * DI token for the AI connection model constructor (used by CrudService mapping).
29
+ * @deprecated Import from `../core-ai.constants` instead. Re-exported only so existing deep imports
30
+ * keep working; the tokens are declared in an import-free leaf so no cycle can form around them
31
+ * (SWC-safe — see core-ai.constants.ts).
33
32
  */
34
- export const AI_CONNECTION_CLASS = 'AI_CONNECTION_CLASS';
33
+ export { AI_CONNECTION_CLASS, AI_CONNECTION_MODEL } from '../core-ai.constants';
35
34
 
36
35
  /**
37
36
  * CRUD service for {@link CoreAiConnection} — the database-backed LLM
@@ -8,15 +8,14 @@ import { CoreAiConversationCreateInput } from '../inputs/core-ai-conversation-cr
8
8
  import { CoreAiConversationInput } from '../inputs/core-ai-conversation.input';
9
9
  import { AiConversationDocument, CoreAiConversation } from '../models/core-ai-conversation.model';
10
10
 
11
- /**
12
- * Mongoose injection token for the AI conversation model.
13
- */
14
- export const AI_CONVERSATION_MODEL = 'AiConversation';
11
+ import { AI_CONVERSATION_CLASS, AI_CONVERSATION_MODEL } from '../core-ai.constants';
15
12
 
16
13
  /**
17
- * DI token for the AI conversation model constructor.
14
+ * @deprecated Import from `../core-ai.constants` instead. Re-exported only so existing deep imports
15
+ * keep working; the tokens are declared in an import-free leaf so no cycle can form around them
16
+ * (SWC-safe — see core-ai.constants.ts).
18
17
  */
19
- export const AI_CONVERSATION_CLASS = 'AI_CONVERSATION_CLASS';
18
+ export { AI_CONVERSATION_CLASS, AI_CONVERSATION_MODEL } from '../core-ai.constants';
20
19
 
21
20
  /**
22
21
  * CRUD service for multi-turn {@link CoreAiConversation}s.
@@ -5,17 +5,16 @@ import { Model } from 'mongoose';
5
5
  import { CrudService } from '../../../common/services/crud.service';
6
6
  import { CoreModelConstructor } from '../../../common/types/core-model-constructor.type';
7
7
  import { AiInteractionDocument, CoreAiInteraction } from '../models/core-ai-interaction.model';
8
- import type { AiInteractionRecord } from './core-ai.service';
8
+ import type { AiInteractionRecord } from '../interfaces/ai-interaction-record.interface';
9
9
 
10
- /**
11
- * Mongoose injection token for the AI interaction model.
12
- */
13
- export const AI_INTERACTION_MODEL = 'AiInteraction';
10
+ import { AI_INTERACTION_CLASS, AI_INTERACTION_MODEL } from '../core-ai.constants';
14
11
 
15
12
  /**
16
- * DI token for the AI interaction model constructor.
13
+ * @deprecated Import from `../core-ai.constants` instead. Re-exported only so existing deep imports
14
+ * keep working; the tokens are declared in an import-free leaf so no cycle can form around them
15
+ * (SWC-safe — see core-ai.constants.ts).
17
16
  */
18
- export const AI_INTERACTION_CLASS = 'AI_INTERACTION_CLASS';
17
+ export { AI_INTERACTION_CLASS, AI_INTERACTION_MODEL } from '../core-ai.constants';
19
18
 
20
19
  /**
21
20
  * CRUD + write service for {@link CoreAiInteraction} audit records.
@@ -6,8 +6,14 @@ import { CrudService } from '../../../common/services/crud.service';
6
6
  import { CoreModelConstructor } from '../../../common/types/core-model-constructor.type';
7
7
  import { AiModeDocument, CoreAiMode } from '../models/core-ai-mode.model';
8
8
 
9
- export const AI_MODE_MODEL = 'AiMode';
10
- export const AI_MODE_CLASS = 'AI_MODE_CLASS';
9
+ import { AI_MODE_CLASS, AI_MODE_MODEL } from '../core-ai.constants';
10
+
11
+ /**
12
+ * @deprecated Import from `../core-ai.constants` instead. Re-exported only so existing deep imports
13
+ * keep working; the tokens are declared in an import-free leaf so no cycle can form around them
14
+ * (SWC-safe — see core-ai.constants.ts).
15
+ */
16
+ export { AI_MODE_CLASS, AI_MODE_MODEL } from '../core-ai.constants';
11
17
 
12
18
  /**
13
19
  * Named-mode store. See {@link CoreAiMode}. Override via
@@ -9,11 +9,14 @@ import { CoreAiPromptHintCreateInput } from '../inputs/core-ai-prompt-hint-creat
9
9
  import { CoreAiPromptHintInput } from '../inputs/core-ai-prompt-hint.input';
10
10
  import { AiPromptHintDocument, CoreAiPromptHint } from '../models/core-ai-prompt-hint.model';
11
11
 
12
- /** Mongoose injection token for the prompt-hint model. */
13
- export const AI_PROMPT_HINT_MODEL = 'AiPromptHint';
12
+ import { AI_PROMPT_HINT_CLASS, AI_PROMPT_HINT_MODEL } from '../core-ai.constants';
14
13
 
15
- /** DI token for the prompt-hint model constructor. */
16
- export const AI_PROMPT_HINT_CLASS = 'AI_PROMPT_HINT_CLASS';
14
+ /**
15
+ * @deprecated Import from `../core-ai.constants` instead. Re-exported only so existing deep imports
16
+ * keep working; the tokens are declared in an import-free leaf so no cycle can form around them
17
+ * (SWC-safe — see core-ai.constants.ts).
18
+ */
19
+ export { AI_PROMPT_HINT_CLASS, AI_PROMPT_HINT_MODEL } from '../core-ai.constants';
17
20
 
18
21
  /** A failure signal recorded by the orchestrator for the learning loop. */
19
22
  export interface AiPromptFeedbackSignal {
@@ -10,8 +10,14 @@ import { CoreAiPromptCreateInput } from '../inputs/core-ai-prompt-create.input';
10
10
  import { CoreAiPromptUpdateInput } from '../inputs/core-ai-prompt-update.input';
11
11
  import { AiPromptDocument, CoreAiPrompt } from '../models/core-ai-prompt.model';
12
12
 
13
- export const AI_PROMPT_MODEL = 'AiPrompt';
14
- export const AI_PROMPT_CLASS = 'AI_PROMPT_CLASS';
13
+ import { AI_PROMPT_CLASS, AI_PROMPT_MODEL } from '../core-ai.constants';
14
+
15
+ /**
16
+ * @deprecated Import from `../core-ai.constants` instead. Re-exported only so existing deep imports
17
+ * keep working; the tokens are declared in an import-free leaf so no cycle can form around them
18
+ * (SWC-safe — see core-ai.constants.ts).
19
+ */
20
+ export { AI_PROMPT_CLASS, AI_PROMPT_MODEL } from '../core-ai.constants';
15
21
 
16
22
  const VALID_SCOPES = new Set(['tenant', 'user']);
17
23
 
@@ -11,11 +11,14 @@ import { CoreAiSlotCreateInput } from '../inputs/core-ai-slot-create.input';
11
11
  import { CoreAiSlotUpdateInput } from '../inputs/core-ai-slot-update.input';
12
12
  import { AiSlotDocument, CoreAiSlot } from '../models/core-ai-slot.model';
13
13
 
14
- /** Mongoose injection token for the slot model. */
15
- export const AI_SLOT_MODEL = 'AiSlot';
14
+ import { AI_SLOT_CLASS, AI_SLOT_MODEL } from '../core-ai.constants';
16
15
 
17
- /** DI token for the slot model constructor. */
18
- export const AI_SLOT_CLASS = 'AI_SLOT_CLASS';
16
+ /**
17
+ * @deprecated Import from `../core-ai.constants` instead. Re-exported only so existing deep imports
18
+ * keep working; the tokens are declared in an import-free leaf so no cycle can form around them
19
+ * (SWC-safe — see core-ai.constants.ts).
20
+ */
21
+ export { AI_SLOT_CLASS, AI_SLOT_MODEL } from '../core-ai.constants';
19
22
 
20
23
  /** A resolved prompt fragment ready for placeholder rendering + assembly. */
21
24
  export interface ResolvedPromptFragment {
@@ -6,10 +6,14 @@ import { CrudService } from '../../../common/services/crud.service';
6
6
  import { CoreModelConstructor } from '../../../common/types/core-model-constructor.type';
7
7
  import { AiToolGrantDocument, CoreAiToolGrant } from '../models/core-ai-tool-grant.model';
8
8
 
9
- /** Mongoose injection token. */
10
- export const AI_TOOL_GRANT_MODEL = 'AiToolGrant';
11
- /** DI token for the model constructor. */
12
- export const AI_TOOL_GRANT_CLASS = 'AI_TOOL_GRANT_CLASS';
9
+ import { AI_TOOL_GRANT_CLASS, AI_TOOL_GRANT_MODEL } from '../core-ai.constants';
10
+
11
+ /**
12
+ * @deprecated Import from `../core-ai.constants` instead. Re-exported only so existing deep imports
13
+ * keep working; the tokens are declared in an import-free leaf so no cycle can form around them
14
+ * (SWC-safe — see core-ai.constants.ts).
15
+ */
16
+ export { AI_TOOL_GRANT_CLASS, AI_TOOL_GRANT_MODEL } from '../core-ai.constants';
13
17
 
14
18
  /** Scope of a persisted permission decision. */
15
19
  export type AiToolGrantScope = 'conversation' | 'tenant' | 'user';
@@ -6,10 +6,14 @@ import { CrudService } from '../../../common/services/crud.service';
6
6
  import { CoreModelConstructor } from '../../../common/types/core-model-constructor.type';
7
7
  import { AiToolPolicyDocument, CoreAiToolPolicy } from '../models/core-ai-tool-policy.model';
8
8
 
9
- /** Mongoose injection token. */
10
- export const AI_TOOL_POLICY_MODEL = 'AiToolPolicy';
11
- /** DI token for the model constructor. */
12
- export const AI_TOOL_POLICY_CLASS = 'AI_TOOL_POLICY_CLASS';
9
+ import { AI_TOOL_POLICY_CLASS, AI_TOOL_POLICY_MODEL } from '../core-ai.constants';
10
+
11
+ /**
12
+ * @deprecated Import from `../core-ai.constants` instead. Re-exported only so existing deep imports
13
+ * keep working; the tokens are declared in an import-free leaf so no cycle can form around them
14
+ * (SWC-safe — see core-ai.constants.ts).
15
+ */
16
+ export { AI_TOOL_POLICY_CLASS, AI_TOOL_POLICY_MODEL } from '../core-ai.constants';
13
17
 
14
18
  export interface AiToolPolicyDecision {
15
19
  /** Final decision: 'allow', 'deny' or 'ask'. */
@@ -27,20 +27,17 @@ import { AiPromptFeedbackSignal, CoreAiPromptHintService } from './core-ai-promp
27
27
  import { AiToolGrantScope, CoreAiToolGrantService } from './core-ai-tool-grant.service';
28
28
  import { CoreAiToolPolicyService } from './core-ai-tool-policy.service';
29
29
  import { CoreAiModeService } from './core-ai-mode.service';
30
+ import type { AiInteractionRecord } from '../interfaces/ai-interaction-record.interface';
30
31
 
31
32
  /**
32
- * Record passed to {@link CoreAiService.audit} for each prompt run.
33
+ * @deprecated Import from `../interfaces/ai-interaction-record.interface` instead. Re-exported only
34
+ * so existing imports keep working.
35
+ *
36
+ * The type was moved out of this file because `core-ai-interaction.service` needs it while this file
37
+ * imports THAT service — an import cycle held apart only by an `import type`. See the interface's
38
+ * docblock.
33
39
  */
34
- export interface AiInteractionRecord {
35
- actions: { name: string; success: boolean }[];
36
- connectionId: string;
37
- iterations: number;
38
- prompt: string;
39
- responseText: string;
40
- tenantId?: string;
41
- usage?: { completionTokens?: number; promptTokens?: number; totalTokens?: number };
42
- userId?: string;
43
- }
40
+ export type { AiInteractionRecord } from '../interfaces/ai-interaction-record.interface';
44
41
 
45
42
  /**
46
43
  * Event emitted by {@link CoreAiService.promptStream} over SSE.
@@ -262,10 +262,10 @@ Read the security section below for production deployments.
262
262
 
263
263
  **Global server-level settings that affect BetterAuth behavior (since v11.25.0):**
264
264
 
265
- | Setting (top-level `IServerOptions`) | Technical Purpose | Impact of Wrong Value |
266
- | ----------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
267
- | `cookies` (`boolean \| ICookiesConfig`, default: `true`) | Controls cookie-parser middleware and session cookie setting. `cookies.exposeTokenInBody` additionally returns the token in the response body (test-only; **forbidden in production**) | Tokens missing from response body surprises test clients; `exposeTokenInBody` in prod = XSS-risk, framework throws at startup |
268
- | `cors` (`boolean \| ICorsConfig`, default: enabled with auto-derived origins) | Unified CORS config — propagates to GraphQL (Apollo), REST (Express), and BetterAuth `trustedOrigins` from a single source | `cors.enabled: false` disables all three layers; `cors.allowAll` allows any origin (dev only) |
265
+ | Setting (top-level `IServerOptions`) | Technical Purpose | Impact of Wrong Value |
266
+ | ----------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
267
+ | `cookies` (`boolean \| ICookiesConfig`, default: `true`) | Controls cookie-parser middleware and session cookie setting. `cookies.exposeTokenInBody` additionally returns the token in the response body (test-only; **forbidden in production**) | Tokens missing from response body surprises test clients; `exposeTokenInBody` in prod = XSS-risk, framework throws at startup |
268
+ | `cors` (`boolean \| ICorsConfig`, default: enabled with auto-derived origins) | Unified CORS config — propagates to GraphQL (Apollo), REST (Express), and BetterAuth `trustedOrigins` from a single source | `cors.enabled: false` disables the REST/GraphQL layers; `cors.allowAll` mirrors any request origin for REST/GraphQL (dev only) but BetterAuth keeps restricting to `appUrl` (its origin check has no "allow all" mode) |
269
269
 
270
270
  **For Development:** The defaults (`http://localhost:3000`, `/iam`) are correct.
271
271
 
@@ -725,6 +725,12 @@ const config = {
725
725
  },
726
726
  advanced: {
727
727
  cookiePrefix: 'my-app',
728
+ // Since v11.27.6 the framework pins `useSecureCookies: false` so Better-Auth's native
729
+ // handlers read the same UNPREFIXED cookie the nest-server helper writes (the `Secure`
730
+ // attribute is still applied on https via `advanced.defaultCookieAttributes`). Only set
731
+ // `true` if Better-Auth manages your cookies entirely — otherwise its native handlers
732
+ // look for a `__Secure-`-prefixed cookie that is never written and answer 401 on
733
+ // 2FA / passkey / `/token`.
728
734
  useSecureCookies: true,
729
735
  },
730
736
  },
@@ -13,7 +13,7 @@ import { ErrorCode } from '../error-code';
13
13
  import { isMultiTenancyActive, isSystemRole, mergeRolesMetadata } from '../tenant/core-tenant.helpers';
14
14
  import { BetterAuthTokenService } from './better-auth-token.service';
15
15
  import { BetterAuthenticatedUser } from './better-auth.types';
16
- import { CoreBetterAuthModule } from './core-better-auth.module';
16
+ import { getBetterAuthTokenService } from './core-better-auth.registry';
17
17
 
18
18
  /**
19
19
  * BetterAuth Roles Guard
@@ -33,7 +33,8 @@ import { CoreBetterAuthModule } from './core-better-auth.module';
33
33
  * IMPORTANT: This guard has NO constructor dependencies. This is intentional because
34
34
  * NestJS DI has issues resolving Reflector/ModuleRef for APP_GUARD providers in dynamic modules.
35
35
  * Instead, we use Reflect.getMetadata directly to read decorator metadata, and access
36
- * BetterAuthTokenService via CoreBetterAuthModule static reference.
36
+ * BetterAuthTokenService via the core-better-auth.registry leaf module — NOT via
37
+ * CoreBetterAuthModule, which would make guard and module import each other.
37
38
  */
38
39
  @Injectable()
39
40
  export class BetterAuthRolesGuard implements CanActivate {
@@ -41,12 +42,17 @@ export class BetterAuthRolesGuard implements CanActivate {
41
42
  private tokenService: BetterAuthTokenService | null = null;
42
43
 
43
44
  /**
44
- * Get BetterAuthTokenService lazily from CoreBetterAuthModule
45
- * This avoids DI issues while still allowing token verification
45
+ * Get BetterAuthTokenService lazily from the better-auth registry.
46
+ * This avoids DI issues while still allowing token verification.
47
+ *
48
+ * The lookup goes through core-better-auth.registry.ts rather than
49
+ * CoreBetterAuthModule on purpose: importing the module here would make guard
50
+ * and module import each other, and that cycle is one decorator away from the
51
+ * SWC temporal-dead-zone crash documented in core-better-auth.constants.ts.
46
52
  */
47
53
  private getTokenService(): BetterAuthTokenService | null {
48
54
  if (!this.tokenService) {
49
- this.tokenService = CoreBetterAuthModule.getTokenServiceInstance();
55
+ this.tokenService = getBetterAuthTokenService();
50
56
  }
51
57
  return this.tokenService;
52
58
  }
@@ -7,7 +7,7 @@ import * as crypto from 'crypto';
7
7
  import * as fs from 'fs';
8
8
  import * as path from 'path';
9
9
 
10
- import { resolveServerUrls } from '../../common/helpers/cookies.helper';
10
+ import { resolveServerUrls, strippedApiHostname } from '../../common/helpers/cookies.helper';
11
11
  import { IBetterAuth, ICorsConfig } from '../../common/interfaces/server-options.interface';
12
12
  import { detectCookiePrefixDrift, resolveBetterAuthCookiePrefix } from './better-auth-cookie-prefix.helper';
13
13
 
@@ -380,15 +380,47 @@ export function createBetterAuthInstance(options: CreateBetterAuthOptions): Crea
380
380
  );
381
381
  }
382
382
 
383
+ // Better-Auth base URL (resolved localhost defaults → explicit config → fallback).
384
+ const betterAuthBaseUrl = resolvedUrls.baseUrl || config.baseUrl || 'http://localhost:3000';
385
+ // The `Secure` attribute Better-Auth WOULD derive for its cookies if `useSecureCookies`
386
+ // were not pinned below: an `https://` baseURL is Better-Auth's own signal
387
+ // (createCookieGetter → `baseURLString.startsWith('https://')`). We keep exactly this value so
388
+ // the pinned `useSecureCookies: false` (needed for name alignment, see below) does not silently
389
+ // strip `Secure` from the cookies Better-Auth's native handlers forward.
390
+ const secureCookies = betterAuthBaseUrl.startsWith('https://');
391
+
383
392
  const betterAuthConfig: Record<string, unknown> = {
384
393
  advanced: {
385
394
  cookiePrefix,
386
395
  ...(crossSubDomain.enabled && {
387
396
  crossSubDomainCookies: { domain: crossSubDomain.domain, enabled: true },
388
397
  }),
398
+ // Keep Better-Auth's NATIVE handlers on the SAME cookie name the
399
+ // nest-server cookie helpers actually write. Those helpers always emit
400
+ // the UNPREFIXED `<cookiePrefix>.session_token`. Better-Auth, left to its
401
+ // own devices on an `https://` baseURL, auto-enables secure cookies AND
402
+ // prefixes the name with `__Secure-`, so its native handlers (2FA
403
+ // enable/disable, passkey register/list, backup codes, `/token`) look for
404
+ // `__Secure-<cookiePrefix>.session_token` — a cookie that is never written
405
+ // — and return `401 UNAUTHORIZED`, while the project's own session
406
+ // resolver (which reads the unprefixed cookie) still returns a session: a
407
+ // split-brain where `GET /iam/get-session` is 200 but every sensitive
408
+ // Better-Auth endpoint is 401. Pinning `useSecureCookies: false` keeps the
409
+ // native read path aligned with the cookie helper.
410
+ useSecureCookies: false,
411
+ // …BUT `useSecureCookies: false` also forces `secure: false` on EVERY cookie
412
+ // Better-Auth sets (createCookieGetter → `secure: !!secureCookiePrefix`), and the
413
+ // native handlers forward their `Set-Cookie` VERBATIM via `sendWebResponse`
414
+ // (2FA verify, social callback, magic link, passkey) WITHOUT passing through the
415
+ // cookie helper — so those session cookies would ship without `Secure` in
416
+ // production. Restore the exact Secure flag Better-Auth itself would have derived
417
+ // (an `https://` baseURL), keeping the unprefixed NAME while preserving the
418
+ // `Secure` TRANSPORT flag. Only injected on https so http/local and a consumer's
419
+ // own `options.advanced.useSecureCookies` override are left untouched.
420
+ ...(secureCookies && { defaultCookieAttributes: { secure: true } }),
389
421
  },
390
422
  basePath,
391
- baseURL: resolvedUrls.baseUrl || config.baseUrl || 'http://localhost:3000',
423
+ baseURL: betterAuthBaseUrl,
392
424
  database: mongodbAdapter(db),
393
425
  // Enable email/password authentication by default (required by Better-Auth 1.x)
394
426
  // Can be disabled by setting config.emailAndPassword.enabled = false
@@ -444,6 +476,22 @@ export function createBetterAuthInstance(options: CreateBetterAuthOptions): Crea
444
476
  finalConfig.advanced = {
445
477
  ...(betterAuthConfig.advanced as Record<string, unknown>),
446
478
  ...(optionsAdvanced as Record<string, unknown>),
479
+ // `defaultCookieAttributes` needs a DEEP merge, not the shallow spread above.
480
+ // It is the key that carries our restored `secure: true` (see the `useSecureCookies: false`
481
+ // block), so a consumer setting it for an entirely unrelated reason — `{ partitioned: true }`,
482
+ // `{ domain: … }` — would wholesale-replace the object and silently strip `Secure` from every
483
+ // session cookie the native handlers forward (2FA verify, social callback, magic link) on an
484
+ // https deployment. Session-establishing cookies, in the clear, with no error anywhere.
485
+ // Re-apply `secure: true` as the BASE and let the consumer's keys spread over it, so an
486
+ // EXPLICIT `secure: false` still wins while an unrelated key can no longer clobber it.
487
+ ...(secureCookies && {
488
+ defaultCookieAttributes: {
489
+ secure: true,
490
+ ...((optionsAdvanced as Record<string, unknown>).defaultCookieAttributes as
491
+ | Record<string, unknown>
492
+ | undefined),
493
+ },
494
+ }),
447
495
  };
448
496
  }
449
497
  } else {
@@ -681,12 +729,20 @@ function buildSocialProviders(config: IBetterAuth): Record<string, SocialProvide
681
729
  *
682
730
  * Behavior (in priority order):
683
731
  * 1. Explicit betterAuth.trustedOrigins → use those (always takes precedence)
684
- * 2. Server CORS disabled → empty array (BetterAuth CORS also disabled)
685
- * 3. Server CORS allowAll undefined (BetterAuth allows all origins)
732
+ * 2. Server CORS disabled → empty array (adds no extra trusted origins beyond BetterAuth's own
733
+ * baseURL see NOTE; it does NOT switch BetterAuth's origin check off)
734
+ * 3. Server CORS allowAll → fall through to rules 4-7 (see below)
686
735
  * 4. Server CORS allowedOrigins → merge with appUrl/baseUrl
687
736
  * 5. Passkey trustedOrigins → use from normalizePasskeyConfig()
688
737
  * 6. Fallback to resolved appUrl
689
- * 7. Otherwise → undefined (allows all origins via Better-Auth's default)
738
+ * 7. Otherwise → undefined (Better-Auth then trusts only its own baseURL)
739
+ *
740
+ * NOTE on rules 2 and 7: neither an empty array (rule 2) nor `undefined` (rule 7) means "any
741
+ * origin is allowed", and neither disables BetterAuth's origin check. In both cases BetterAuth
742
+ * still derives and trusts its own `baseURL` origin (see `getTrustedOrigins()` in
743
+ * `better-auth/context`, which unconditionally pushes `new URL(baseURL).origin` before appending
744
+ * `options.trustedOrigins`), so `[]` and `undefined` are behaviorally identical here: a
745
+ * separately hosted frontend is still rejected by every origin-checked endpoint.
690
746
  *
691
747
  * @param config - Better-auth configuration
692
748
  * @param options - Passkey normalization, resolved URLs, and server CORS context
@@ -706,15 +762,25 @@ export function buildTrustedOrigins(
706
762
  return config.trustedOrigins;
707
763
  }
708
764
 
709
- // 2. Server CORS disabled → BetterAuth CORS also disabled
765
+ // 2. Server CORS disabled → add no extra trusted origins. BetterAuth still trusts its own
766
+ // baseURL (see the NOTE above), so this does NOT turn its origin check off — it only means
767
+ // "no separately hosted frontend is trusted". Behaviorally identical to rule 7's undefined.
710
768
  if (serverCorsConfig === false || (typeof serverCorsConfig === 'object' && serverCorsConfig?.enabled === false)) {
711
769
  return [];
712
770
  }
713
771
 
714
- // 3. Server CORS allowAll → BetterAuth allows all origins
715
- if (typeof serverCorsConfig === 'object' && serverCorsConfig?.allowAll) {
716
- return undefined;
717
- }
772
+ // 3. Server CORS allowAll → fall through to the appUrl / passkey rules below.
773
+ //
774
+ // This used to `return undefined` in the belief that BetterAuth then "allows all
775
+ // origins". It does not: without trustedOrigins BetterAuth trusts only its own
776
+ // baseURL, so the *app* origin is rejected and every origin-checked endpoint
777
+ // (two-factor/enable, passkey) answers 403 INVALID_ORIGIN. That silently broke
778
+ // 2FA and passkeys in exactly the setups that use allowAll — local dev and CI.
779
+ //
780
+ // An origin check has no meaningful "allow everything" mode — that is the very
781
+ // thing it defends against — so allowAll now yields the known-good origins
782
+ // (appUrl, passkey) instead of none. Projects that really do want to accept
783
+ // arbitrary origins can still set `betterAuth.trustedOrigins` explicitly (rule 1).
718
784
 
719
785
  // 4. Server allowedOrigins → merge with appUrl/baseUrl.
720
786
  // Order (appUrl, baseUrl, allowedOrigins) mirrors buildCorsConfig() in cookies.helper.ts
@@ -1183,6 +1249,17 @@ export function resolveCrossSubDomainCookies(
1183
1249
  * 3. Use baseUrl hostname as-is
1184
1250
  *
1185
1251
  * Returns undefined for localhost (cross-subdomain not meaningful there).
1252
+ *
1253
+ * The `api.` strip reuses {@link strippedApiHostname} so it shares that helper's guard against
1254
+ * bogus results: `api.dev` → `dev` would set a public-suffix cookie domain that browsers reject
1255
+ * outright (dropping every session cookie), so `api.dev` is kept as-is instead.
1256
+ *
1257
+ * KNOWN LIMITATION (fails closed, no leak): the single-label guard cannot recognise a MULTI-label
1258
+ * public suffix — `api.co.uk` still strips to `co.uk`, a Public-Suffix-List entry browsers also
1259
+ * reject, so cross-subdomain auth would break (cookie dropped) rather than over-scope. A full PSL
1260
+ * check would need a dependency, which this security-critical module deliberately avoids; for such
1261
+ * apex domains set `betterAuth.crossSubDomainCookies.domain` explicitly instead of relying on
1262
+ * derivation. See migration guide 11.27.5 → 11.27.6.
1186
1263
  */
1187
1264
  function deriveCookieDomainFromUrls(appUrl?: string, baseUrl?: string): string | undefined {
1188
1265
  // Priority 1: appUrl hostname (this IS the parent domain in typical setups)
@@ -1204,11 +1281,9 @@ function deriveCookieDomainFromUrls(appUrl?: string, baseUrl?: string): string |
1204
1281
  if (hostname === 'localhost' || hostname === '127.0.0.1') {
1205
1282
  return undefined;
1206
1283
  }
1207
- // Strip api. prefix to get parent domain
1208
- if (hostname.startsWith('api.')) {
1209
- return hostname.substring(4);
1210
- }
1211
- return hostname;
1284
+ // Strip api. prefix to get parent domain — but keep the host unchanged when stripping
1285
+ // would leave a bare TLD (`api.dev`) or empty host (`api.`).
1286
+ return strippedApiHostname(hostname) ?? hostname;
1212
1287
  } catch {
1213
1288
  return undefined;
1214
1289
  }
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Dependency-injection tokens of the better-auth module.
3
+ *
4
+ * These live in a dedicated file — instead of core-better-auth.module.ts /
5
+ * core-better-auth.service.ts — so that module and service never have to import
6
+ * each other. The tokens used to be split across both files
7
+ * (BETTER_AUTH_INSTANCE in the module, BETTER_AUTH_CONFIG /
8
+ * BETTER_AUTH_COOKIE_DOMAIN in the service), which made the two files import
9
+ * each other in a cycle. That cycle happened to work under tsc/CommonJS by
10
+ * evaluation-order luck, but crashed SWC-compiled builds (`nest start -b swc`)
11
+ * with a temporal-dead-zone error:
12
+ *
13
+ * ReferenceError: Cannot access 'BETTER_AUTH_INSTANCE' before initialization
14
+ *
15
+ * The lethal ingredient is not the cycle by itself — it is a cycle PLUS a read of
16
+ * the cyclic binding at module-evaluation time. `@Inject(BETTER_AUTH_INSTANCE)` is
17
+ * a constructor-parameter decorator, and decorator arguments are evaluated when the
18
+ * class is defined, i.e. while the module is still initializing. On a cycle the
19
+ * importing side then reads a `const` that has not been initialized yet.
20
+ *
21
+ * This file imports nothing, so it can never be mid-evaluation when someone
22
+ * imports it — in any module system, under any compiler. That makes the
23
+ * initialization order of the tokens deterministic everywhere.
24
+ *
25
+ * WHY THIS MATTERS FOR FUTURE CHANGES
26
+ * -----------------------------------
27
+ * `tsc` does NOT catch a regression here, and neither does the test suite: vitest
28
+ * runs SWC through Vite's module runner, whose getter-based live bindings tolerate
29
+ * cycles. Only the SWC → CommonJS → `require()` path fails, which is exactly what
30
+ * `pnpm run check:swc-tdz` exercises. If you move a token back into the module or
31
+ * the service, everything stays green locally and breaks for consumers.
32
+ *
33
+ * The rule, in short: **DI tokens belong in an import-free leaf file.**
34
+ * See .claude/rules/better-auth.md §6.
35
+ */
36
+
37
+ /**
38
+ * Token for injecting the better-auth instance.
39
+ *
40
+ * Injected type: `BetterAuthInstance | null` — null when better-auth is disabled.
41
+ * Declared `@Optional()` in the CoreBetterAuthService constructor.
42
+ *
43
+ * @example
44
+ * ```typescript
45
+ * import { Inject, Injectable, Optional } from '@nestjs/common';
46
+ * import { BETTER_AUTH_INSTANCE, BetterAuthInstance } from '@lenne.tech/nest-server';
47
+ *
48
+ * @Injectable()
49
+ * export class MyService {
50
+ * constructor(
51
+ * @Optional() @Inject(BETTER_AUTH_INSTANCE) private readonly auth: BetterAuthInstance | null,
52
+ * ) {}
53
+ * }
54
+ * ```
55
+ */
56
+ export const BETTER_AUTH_INSTANCE = 'BETTER_AUTH_INSTANCE';
57
+
58
+ /**
59
+ * Injection token for the resolved BetterAuth configuration.
60
+ *
61
+ * Injected type: `IBetterAuth | null` — null when better-auth is disabled.
62
+ * Declared `@Optional()` in the CoreBetterAuthService constructor.
63
+ */
64
+ export const BETTER_AUTH_CONFIG = 'BETTER_AUTH_CONFIG';
65
+
66
+ /**
67
+ * Injection token for the resolved cross-subdomain cookie domain.
68
+ * Set during Better-Auth instance creation, undefined if disabled.
69
+ *
70
+ * Injected type: `string | null | undefined`.
71
+ * Declared `@Optional()` in the CoreBetterAuthService constructor.
72
+ */
73
+ export const BETTER_AUTH_COOKIE_DOMAIN = 'BETTER_AUTH_COOKIE_DOMAIN';