@venizia/ignis-docs 0.0.6-2 → 0.0.6-3

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 (57) hide show
  1. package/dist/mcp-server/index.js +1 -0
  2. package/dist/mcp-server/index.js.map +1 -1
  3. package/dist/mcp-server/tools/base.tool.d.ts +4 -8
  4. package/dist/mcp-server/tools/base.tool.d.ts.map +1 -1
  5. package/dist/mcp-server/tools/base.tool.js +1 -1
  6. package/dist/mcp-server/tools/base.tool.js.map +1 -1
  7. package/dist/mcp-server/tools/docs/get-document-content.tool.d.ts +8 -2
  8. package/dist/mcp-server/tools/docs/get-document-content.tool.d.ts.map +1 -1
  9. package/dist/mcp-server/tools/docs/get-document-content.tool.js +1 -1
  10. package/dist/mcp-server/tools/docs/get-document-content.tool.js.map +1 -1
  11. package/dist/mcp-server/tools/docs/get-document-metadata.tool.d.ts +13 -2
  12. package/dist/mcp-server/tools/docs/get-document-metadata.tool.d.ts.map +1 -1
  13. package/dist/mcp-server/tools/docs/get-document-metadata.tool.js +1 -1
  14. package/dist/mcp-server/tools/docs/get-document-metadata.tool.js.map +1 -1
  15. package/dist/mcp-server/tools/docs/get-package-overview.tool.d.ts +16 -2
  16. package/dist/mcp-server/tools/docs/get-package-overview.tool.d.ts.map +1 -1
  17. package/dist/mcp-server/tools/docs/get-package-overview.tool.js +1 -1
  18. package/dist/mcp-server/tools/docs/get-package-overview.tool.js.map +1 -1
  19. package/dist/mcp-server/tools/docs/list-categories.tool.d.ts +5 -2
  20. package/dist/mcp-server/tools/docs/list-categories.tool.d.ts.map +1 -1
  21. package/dist/mcp-server/tools/docs/list-categories.tool.js +1 -1
  22. package/dist/mcp-server/tools/docs/list-categories.tool.js.map +1 -1
  23. package/dist/mcp-server/tools/docs/list-documents.tool.d.ts +11 -2
  24. package/dist/mcp-server/tools/docs/list-documents.tool.d.ts.map +1 -1
  25. package/dist/mcp-server/tools/docs/list-documents.tool.js +1 -1
  26. package/dist/mcp-server/tools/docs/list-documents.tool.js.map +1 -1
  27. package/dist/mcp-server/tools/docs/search-documents.tool.d.ts +13 -2
  28. package/dist/mcp-server/tools/docs/search-documents.tool.d.ts.map +1 -1
  29. package/dist/mcp-server/tools/docs/search-documents.tool.js +1 -1
  30. package/dist/mcp-server/tools/docs/search-documents.tool.js.map +1 -1
  31. package/dist/mcp-server/tools/github/list-project-files.tool.d.ts +9 -2
  32. package/dist/mcp-server/tools/github/list-project-files.tool.d.ts.map +1 -1
  33. package/dist/mcp-server/tools/github/list-project-files.tool.js +1 -1
  34. package/dist/mcp-server/tools/github/list-project-files.tool.js.map +1 -1
  35. package/dist/mcp-server/tools/github/search-code.tool.d.ts +16 -2
  36. package/dist/mcp-server/tools/github/search-code.tool.d.ts.map +1 -1
  37. package/dist/mcp-server/tools/github/search-code.tool.js +1 -1
  38. package/dist/mcp-server/tools/github/search-code.tool.js.map +1 -1
  39. package/dist/mcp-server/tools/github/verify-dependencies.tool.d.ts +19 -2
  40. package/dist/mcp-server/tools/github/verify-dependencies.tool.d.ts.map +1 -1
  41. package/dist/mcp-server/tools/github/verify-dependencies.tool.js +1 -1
  42. package/dist/mcp-server/tools/github/verify-dependencies.tool.js.map +1 -1
  43. package/dist/mcp-server/tools/github/view-source-file.tool.d.ts +8 -2
  44. package/dist/mcp-server/tools/github/view-source-file.tool.d.ts.map +1 -1
  45. package/dist/mcp-server/tools/github/view-source-file.tool.js +1 -1
  46. package/dist/mcp-server/tools/github/view-source-file.tool.js.map +1 -1
  47. package/package.json +68 -54
  48. package/wiki/guides/reference/mcp-docs-server.md +0 -134
  49. package/wiki/references/base/controllers.md +11 -8
  50. package/wiki/references/components/authentication/usage.md +3 -3
  51. package/wiki/references/components/authorization/api.md +1213 -0
  52. package/wiki/references/components/authorization/errors.md +387 -0
  53. package/wiki/references/components/authorization/index.md +712 -0
  54. package/wiki/references/components/authorization/usage.md +696 -0
  55. package/wiki/references/components/index.md +2 -0
  56. package/wiki/references/helpers/index.md +1 -0
  57. package/wiki/references/helpers/kafka/index.md +305 -0
@@ -0,0 +1,387 @@
1
+ # Authorization -- Error Reference
2
+
3
+ > Complete error messages and troubleshooting for the authorization module. See [Setup & Configuration](./) for initial setup.
4
+
5
+ ## Error Flow Diagram
6
+
7
+ ```mermaid
8
+ flowchart TD
9
+ Req([Request arrives]) --> S1{"Step 1: SKIP?"}
10
+ S1 -->|Yes| OK1([No error - skip])
11
+ S1 -->|No| S2{"Step 2: User?"}
12
+ S2 -->|No| E401[/"401: No authenticated user found"/]
13
+ S2 -->|Yes| S3{"Step 3: Role shortcuts"}
14
+ S3 -->|Match| OK2([No error - bypass])
15
+ S3 -->|No match| S4{"Step 4: Voters"}
16
+ S4 -->|DENY| E403a[/"403: Authorization denied by voter"/]
17
+ S4 -->|ALLOW/ABSTAIN| S5{"Step 5: Resolve enforcer"}
18
+
19
+ S5 -->|Registry empty| E500a[/"500: No items registered"/]
20
+ S5 -->|Name not found| E500b[/"500: Descriptor not found"/]
21
+ S5 -->|DI fails| E500c[/"500: Failed to resolve"/]
22
+ S5 -->|OK| S6{"Step 6: Build rules"}
23
+
24
+ S6 -->|No principalType| E400a[/"400: principalType required"/]
25
+ S6 -->|Not initialized| E500d[/"500: Enforcer not initialized"/]
26
+ S6 -->|No FilteredAdapter| E500e[/"500: Adapter does not support loadFilteredPolicy"/]
27
+ S6 -->|Bad cache driver| E500f[/"500: Invalid cached.driver"/]
28
+ S6 -->|Empty Redis key| E400b[/"400: Invalid cachedKey"/]
29
+ S6 -->|OK| S7{"Step 7: Evaluate"}
30
+
31
+ S7 -->|No action/resource| E500g[/"500: request.action and resource required"/]
32
+ S7 -->|ALLOW| OK3([Authorized])
33
+ S7 -->|DENY| E403b[/"403: Authorization denied"/]
34
+ ```
35
+
36
+ ## Complete Error Reference
37
+
38
+ All error messages from the authorization module, organized by source:
39
+
40
+ ### Component Errors (AuthorizeComponent)
41
+
42
+ | Error Message | Status | Method |
43
+ |---------------|--------|--------|
44
+ | `[AuthorizeComponent] No authorize options found. Bind options to AuthorizeBindingKeys.OPTIONS before registering the component.` | 500 | `binding` |
45
+
46
+ ### Authorization Provider Errors
47
+
48
+ | Error Message | Status | Step |
49
+ |---------------|--------|------|
50
+ | `Authorization failed: No authenticated user found` | 401 | Step 2 -- User check |
51
+ | `Authorization failed: user.principalType is required for enforcer-based authorization` | 400 | Step 6 -- Build rules |
52
+ | <code v-pre>Authorization denied by voter &#124; action: {{action}} &#124; resource: {{resource}}</code> | 403 | Step 4 -- Voter DENY |
53
+ | <code v-pre>Authorization denied &#124; action: {{action}} &#124; resource: {{resource}}</code> | 403 | Step 7 -- Enforcer denied |
54
+
55
+ ### Enforcer Registry Errors (AuthorizationEnforcerRegistry)
56
+
57
+ | Error Message | Status | Method |
58
+ |---------------|--------|--------|
59
+ | <code v-pre>[getKey] Invalid name &#124; name: {{name}}</code> | 500 | `getKey` |
60
+ | `[AuthorizationEnforcerRegistry] No items registered` | 500 | `getDefaultName` |
61
+ | <code v-pre>[AuthorizationEnforcerRegistry] Duplicate enforcer name(s): {{names}}</code> | 500 | `register` |
62
+ | <code v-pre>[AuthorizationEnforcerRegistry] Enforcer already registered: {{name}}</code> | 500 | `register` |
63
+ | <code v-pre>[AuthorizationEnforcerRegistry] Descriptor not found: {{name}}</code> | 500 | `resolveDescriptor` |
64
+ | <code v-pre>[AuthorizationEnforcerRegistry] Failed to resolve: {{name}}</code> | 500 | `resolveDescriptor` |
65
+
66
+ ### Casbin Enforcer Errors (CasbinAuthorizationEnforcer)
67
+
68
+ | Error Message | Status | Method |
69
+ |---------------|--------|--------|
70
+ | `[CasbinAuthorizationEnforcer] "casbin" is not installed` | 500 | `configure` |
71
+ | `[CasbinAuthorizationEnforcer] options.model is required.` | 500 | `configure` |
72
+ | `[CasbinAuthorizationEnforcer] Enforcer not initialized. Call configure() first.` | 500 | `evaluate`, `buildRules` |
73
+ | `[CasbinAuthorizationEnforcer] Adapter does not support loadFilteredPolicy.` | 500 | `buildRules` |
74
+ | `[CasbinAuthorizationEnforcer] request.action and request.resource are required.` | 500 | `evaluate` |
75
+ | <code v-pre>[CasbinAuthorizationEnforcer] cached.options.expiresIn must be >= 10000 (ms) &#124; Received: {{value}}</code> | 500 | `configure` (via `validateExpiresIn`) |
76
+ | <code v-pre>[buildRules] Invalid cached.driver &#124; Valids: [in-memory, redis]</code> | 500 | `buildRules` |
77
+ | <code v-pre>[resolveCasbinEnforcer] Invalid cached.driver &#124; Valids: [in-memory, redis]</code> | 500 | `configure` (via `resolveCasbinEnforcer`) |
78
+ | <code v-pre>[resolveModel] Invalid model.driver &#124; Valids: [file, text]</code> | 500 | `configure` (via `resolveModel`) |
79
+
80
+ ### Policy Loading Errors (CasbinAuthorizationEnforcer internals)
81
+
82
+ | Error Message | Status | Method |
83
+ |---------------|--------|--------|
84
+ | `[loadPoliciesWithRedisCache] Invalid cachedKey to start validate user authorization!` | 400 | `loadPoliciesWithRedisCache` |
85
+ | `[loadPoliciesFromAdapter] Invalid state of enforcer` | 500 | `loadPoliciesFromAdapter` |
86
+ | `[extractPolicyLines] Invalid state of enforcer` | 500 | `extractPolicyLines` |
87
+ | `[loadPolicyLinesIntoModel] Enforcer not initialized. Call configure() first.` | 500 | `loadPolicyLinesIntoModel` |
88
+
89
+ ## Troubleshooting
90
+
91
+ ### "[AuthorizeComponent] No authorize options found"
92
+
93
+ **Cause:** `AuthorizeComponent` was registered but `IAuthorizeOptions` was not bound to the container.
94
+
95
+ **Fix:** Bind options **before** registering the component:
96
+
97
+ ```typescript
98
+ // 1. Bind options first
99
+ this.bind<IAuthorizeOptions>({ key: AuthorizeBindingKeys.OPTIONS }).toValue({
100
+ defaultDecision: 'deny',
101
+ alwaysAllowRoles: ['999_super-admin'],
102
+ });
103
+
104
+ // 2. Then register the component
105
+ this.component(AuthorizeComponent);
106
+ ```
107
+
108
+ ### "Authorization failed: No authenticated user found"
109
+
110
+ **Cause:** The authorization middleware runs after authentication, but no user was found on the context (`Authentication.CURRENT_USER` is undefined). This happens when:
111
+ - The route has `authorize` but no `authenticate` config
112
+ - Authentication middleware failed silently
113
+ - Authentication was skipped but authorization was not
114
+
115
+ **Fix:** Ensure routes with `authorize` also have `authenticate`:
116
+
117
+ ```typescript
118
+ this.defineRoute({
119
+ configs: {
120
+ path: '/',
121
+ method: 'get',
122
+ authenticate: { strategies: [Authentication.STRATEGY_JWT] }, // Must be present
123
+ authorize: { action: AuthorizationActions.READ, resource: 'Article' },
124
+ // ...
125
+ },
126
+ handler: async (context) => { ... },
127
+ });
128
+ ```
129
+
130
+ ### "Authorization failed: user.principalType is required"
131
+
132
+ **Cause:** The authenticated user object does not have a `principalType` field. This is required for enforcer-based authorization because the enforcer uses `principalType` to construct the casbin subject (e.g., `user_123`, `service_456`).
133
+
134
+ **Fix:** Ensure your authentication service sets `principalType` on the user object:
135
+
136
+ ```typescript
137
+ // In your JWT token service or authentication service:
138
+ return {
139
+ userId: '123',
140
+ principalType: 'user', // Required for authorization
141
+ roles: [...],
142
+ };
143
+ ```
144
+
145
+ > [!NOTE]
146
+ > `principalType` is accessed via the `IAuthUser` index signature (`[extra: string | symbol]: any`), not a dedicated field. It must be set as a property on the returned user object.
147
+
148
+ ### "Authorization denied by voter | action: ... | resource: ..."
149
+
150
+ **Cause:** A voter function explicitly returned `AuthorizationDecisions.DENY` for the request.
151
+
152
+ **Fix:** Check the voter logic. Review which voter denied the request by examining the action and resource in the error message. Common causes:
153
+ - Voter checking ownership and user is not the owner
154
+ - Voter checking time window and request is outside allowed hours
155
+ - Voter checking resource state (e.g., locked, archived)
156
+
157
+ ### "Authorization denied | action: ... | resource: ..."
158
+
159
+ **Cause:** The enforcer's `evaluate()` returned `DENY` or `ABSTAIN` (which fell back to `defaultDecision`) for the requested action/resource. This means:
160
+ - No matching policies were found for the user
161
+ - Matching policies exist but deny the action
162
+ - The casbin model does not cover the requested action/resource combination
163
+
164
+ **Fix:** Debug by checking:
165
+
166
+ 1. **Policies are loaded correctly** -- verify your adapter is returning the right policy definitions for the user
167
+ 2. **Subject format matches** -- the `normalizePayloadFn` must produce subjects matching your policy definitions (e.g., `user_123` must match what's in the database)
168
+ 3. **Casbin model covers the request** -- your `.conf` file must define matchers for the action/resource/domain pattern you're using
169
+ 4. **Set defaultDecision explicitly:**
170
+ ```typescript
171
+ this.bind<IAuthorizeOptions>({ key: AuthorizeBindingKeys.OPTIONS }).toValue({
172
+ defaultDecision: 'deny', // Explicit is better
173
+ // ...
174
+ });
175
+ ```
176
+
177
+ ### "[AuthorizationEnforcerRegistry] Duplicate enforcer name(s): ..."
178
+
179
+ **Cause:** Two or more enforcers in the same `register()` call have the same name.
180
+
181
+ **Fix:** Ensure each enforcer has a unique name:
182
+
183
+ ```typescript
184
+ AuthorizationEnforcerRegistry.getInstance().register({
185
+ container: this,
186
+ enforcers: [
187
+ { enforcer: CasbinEnforcer, name: 'casbin', type: 'casbin', ... },
188
+ { enforcer: CustomEnforcer, name: 'custom', type: 'custom', ... }, // Different name
189
+ ],
190
+ });
191
+ ```
192
+
193
+ ### "[AuthorizationEnforcerRegistry] Enforcer already registered: ..."
194
+
195
+ **Cause:** An enforcer with this name was already registered in a previous `register()` call. The registry does not allow overwriting.
196
+
197
+ **Fix:** Ensure you only register each enforcer name once. If you need to re-register, call `registry.reset()` first (typically only in tests).
198
+
199
+ ### "[AuthorizationEnforcerRegistry] No items registered"
200
+
201
+ **Cause:** Tried to get the default enforcer name but no enforcers are registered. This usually means `AuthorizationEnforcerRegistry.register()` was never called.
202
+
203
+ **Fix:** Register enforcers after registering the component:
204
+
205
+ ```typescript
206
+ // 1. Bind options and register component
207
+ this.bind<IAuthorizeOptions>({ key: AuthorizeBindingKeys.OPTIONS }).toValue({ ... });
208
+ this.component(AuthorizeComponent);
209
+
210
+ // 2. Register enforcers
211
+ AuthorizationEnforcerRegistry.getInstance().register({
212
+ container: this,
213
+ enforcers: [{ enforcer: CasbinAuthorizationEnforcer, name: 'casbin', type: 'casbin', options: { ... } }],
214
+ });
215
+ ```
216
+
217
+ ### "[AuthorizationEnforcerRegistry] Descriptor not found: ..."
218
+
219
+ **Cause:** Tried to resolve an enforcer by a name that was never registered. This happens when `enforcerName` is specified in the `authorize()` call but doesn't match any registered enforcer.
220
+
221
+ **Fix:** Ensure the enforcer name matches what was registered. The default enforcer name is the first one registered.
222
+
223
+ ### "[AuthorizationEnforcerRegistry] Failed to resolve: ..."
224
+
225
+ **Cause:** The enforcer class was registered in the descriptor Map but DI container resolution returned `null`. This typically means the enforcer class has unsatisfied dependencies.
226
+
227
+ **Fix:** Check that all `@inject` dependencies in your enforcer's constructor are bound in the same container.
228
+
229
+ ### "[CasbinAuthorizationEnforcer] casbin is not installed"
230
+
231
+ **Cause:** The Casbin enforcer dynamically imports `casbin` at configure time, but the package is not installed.
232
+
233
+ **Fix:** Install casbin as a dependency:
234
+
235
+ ```bash
236
+ bun add casbin
237
+ ```
238
+
239
+ ### "[CasbinAuthorizationEnforcer] options.model is required"
240
+
241
+ **Cause:** The Casbin enforcer's options do not include a `model` field. The model defines the casbin RBAC/ABAC rules structure.
242
+
243
+ **Fix:** Provide `model` in the enforcer options:
244
+
245
+ ```typescript
246
+ AuthorizationEnforcerRegistry.getInstance().register({
247
+ container: this,
248
+ enforcers: [{
249
+ enforcer: CasbinAuthorizationEnforcer,
250
+ name: 'casbin',
251
+ type: 'casbin',
252
+ options: {
253
+ model: {
254
+ driver: 'file',
255
+ definition: path.resolve(__dirname, './security/model.conf'),
256
+ },
257
+ cached: { use: false },
258
+ },
259
+ }],
260
+ });
261
+ ```
262
+
263
+ ### "[CasbinAuthorizationEnforcer] Adapter does not support loadFilteredPolicy"
264
+
265
+ **Cause:** The adapter provided to the Casbin enforcer does not implement the `loadFilteredPolicy` method from casbin's `FilteredAdapter` interface. The authorization system always uses filtered policy loading.
266
+
267
+ **Fix:** Use an adapter that implements `FilteredAdapter`, such as `DrizzleCasbinAdapter` or a custom adapter extending `BaseFilteredAdapter`:
268
+
269
+ ```typescript
270
+ import { DrizzleCasbinAdapter } from '@venizia/ignis';
271
+
272
+ const adapter = new DrizzleCasbinAdapter({
273
+ dataSource,
274
+ entities: { ... },
275
+ });
276
+ ```
277
+
278
+ ### "[CasbinAuthorizationEnforcer] cached.options.expiresIn must be >= 10000"
279
+
280
+ **Cause:** The `expiresIn` value for the cache TTL is too small. Minimum is 10,000 ms (10 seconds), enforced by the `MIN_EXPIRES_IN` constant.
281
+
282
+ **Fix:** Increase the expiration time:
283
+
284
+ ```typescript
285
+ cached: {
286
+ use: true,
287
+ driver: 'redis',
288
+ options: {
289
+ connection: redisHelper,
290
+ expiresIn: 5 * 60 * 1000, // 5 minutes (minimum: 10,000 ms)
291
+ keyFn: ({ user }) => `authz:policies:${user.userId}`,
292
+ },
293
+ },
294
+ ```
295
+
296
+ ### "[CasbinAuthorizationEnforcer] Enforcer not initialized"
297
+
298
+ **Cause:** The Casbin enforcer's `evaluate()`, `buildRules()`, or internal methods were called before `configure()`. This should not happen when using `resolveEnforcer()` (which auto-configures), but can occur if the enforcer is resolved manually via the DI container.
299
+
300
+ **Fix:** Always resolve enforcers through the registry's `resolveEnforcer()` method, which handles configure-once automatically:
301
+
302
+ ```typescript
303
+ const enforcer = await AuthorizationEnforcerRegistry.getInstance().resolveEnforcer({ name: 'casbin' });
304
+ // configure() is called automatically on first resolve
305
+ ```
306
+
307
+ ### "[loadPoliciesWithRedisCache] Invalid cachedKey"
308
+
309
+ **Cause:** The `keyFn` in Redis cache options returned a falsy value (empty string, null, undefined). The cache key is required to store/retrieve policies from Redis.
310
+
311
+ **Fix:** Ensure your `keyFn` always returns a non-empty string:
312
+
313
+ ```typescript
314
+ keyFn: ({ user }) => {
315
+ if (!user.userId) {
316
+ throw new Error('User ID is required for cache key');
317
+ }
318
+ return `authz:policies:${user.userId}`;
319
+ },
320
+ ```
321
+
322
+ ### "[loadPoliciesFromAdapter] Invalid state of enforcer"
323
+
324
+ **Cause:** `loadPoliciesFromAdapter()` was called but the internal casbin enforcer is null. This is an internal state error.
325
+
326
+ **Fix:** This should not occur in normal usage. If it does, ensure `configure()` completed successfully before any policy loading operations.
327
+
328
+ ### "[extractPolicyLines] Invalid state of enforcer"
329
+
330
+ **Cause:** `extractPolicyLines()` was called but the internal casbin enforcer is null. This method is called during Redis cache miss flow.
331
+
332
+ **Fix:** Same as above -- ensure `configure()` completed before policy operations.
333
+
334
+ ### "[loadPolicyLinesIntoModel] Enforcer not initialized"
335
+
336
+ **Cause:** `loadPolicyLinesIntoModel()` was called but the internal casbin enforcer is null. This method is called during Redis cache hit flow to load cached lines.
337
+
338
+ **Fix:** Same as above -- ensure `configure()` completed before policy operations.
339
+
340
+ ### Invalid driver errors
341
+
342
+ **Messages:**
343
+ - `[buildRules] Invalid cached.driver | Valids: [in-memory, redis]`
344
+ - `[resolveCasbinEnforcer] Invalid cached.driver | Valids: [in-memory, redis]`
345
+ - `[resolveModel] Invalid model.driver | Valids: [file, text]`
346
+
347
+ **Cause:** An unsupported driver string was passed in the options.
348
+
349
+ **Fix:** Use one of the valid values:
350
+ - Cache drivers: `CasbinEnforcerCachedDrivers.IN_MEMORY` (`'in-memory'`) or `CasbinEnforcerCachedDrivers.REDIS` (`'redis'`)
351
+ - Model drivers: `CasbinEnforcerModelDrivers.FILE` (`'file'`) or `CasbinEnforcerModelDrivers.TEXT` (`'text'`)
352
+
353
+ ## Common Patterns
354
+
355
+ ### Authorization Is Not Running
356
+
357
+ Check middleware injection order:
358
+ 1. Verify `authorize` is set on the route config (not just `authenticate`)
359
+ 2. Verify `authenticate` is not set to `{ skip: true }` (which also skips authorization in CRUD factory)
360
+ 3. Verify the component is registered and enforcers are registered via the registry
361
+
362
+ ### Rules Are Built On Every Request
363
+
364
+ Check that rules are being cached correctly. The middleware caches on `Authorization.RULES`:
365
+ - Cached per-request (each new request starts fresh)
366
+ - Multiple authorization specs on the same route share the cache
367
+ - If rules are `undefined` or `null`, they will be rebuilt
368
+
369
+ ### Casbin Policies Not Loading
370
+
371
+ 1. **Check adapter entities** -- ensure `tableName` and `principalType` match your database schema
372
+ 2. **Check variant column** -- policy rows must have `variant = 'policy'` (`CasbinRuleVariants.POLICY`), role assignments must have `variant = 'group'` (`CasbinRuleVariants.GROUP`)
373
+ 3. **Check subject/target types** -- the SQL queries filter by `subject_type` and `target_type`
374
+ 4. **Check the model file** -- ensure your `.conf` file matches the policy format (e.g., domain-aware vs simple)
375
+
376
+ ### Redis Cache Not Working
377
+
378
+ 1. **Check Redis connection** -- verify `DefaultRedisHelper` is properly connected
379
+ 2. **Check keyFn** -- ensure it returns a unique, non-empty key per user
380
+ 3. **Check expiresIn** -- must be >= 10,000 ms (`MIN_EXPIRES_IN`)
381
+ 4. **Verify cache hit** -- check logs for `"Loaded CACHED Policies"` vs `"Loaded ADAPTER + CACHED Policies"`
382
+
383
+ ## See Also
384
+
385
+ - [Setup & Configuration](./) -- Binding keys, options interfaces, and initial setup
386
+ - [Usage & Examples](./usage) -- Securing routes, voters, patterns, and CRUD integration
387
+ - [API Reference](./api) -- Architecture, enforcer internals, provider, registry, and adapters