@tideorg/mcp 1.4.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 (76) hide show
  1. package/GAP_REGISTER.md +117 -0
  2. package/README.md +38 -0
  3. package/adapters/AGENTS.md +241 -0
  4. package/adapters/CLAUDE.md +146 -0
  5. package/adapters/replit.md +224 -0
  6. package/canon/anti-patterns.md +2133 -0
  7. package/canon/concepts.md +816 -0
  8. package/canon/custom-contracts.md +533 -0
  9. package/canon/delegation.md +195 -0
  10. package/canon/feature-mapping.md +637 -0
  11. package/canon/framework-matrix.md +1125 -0
  12. package/canon/invariants.md +851 -0
  13. package/canon/redirect-handler.md +254 -0
  14. package/canon/tidecloak-bootstrap.md +287 -0
  15. package/canon/tidecloak-endpoints.md +294 -0
  16. package/canon/troubleshooting.md +1494 -0
  17. package/canon/version-policy.md +89 -0
  18. package/mcp-server/dist/index.d.ts +2 -0
  19. package/mcp-server/dist/index.js +605 -0
  20. package/package.json +45 -0
  21. package/playbooks/add-auth-nextjs-existing.md +799 -0
  22. package/playbooks/add-auth-nextjs-fresh.md +654 -0
  23. package/playbooks/add-rbac-nextjs.md +190 -0
  24. package/playbooks/bootstrap-realm-from-template.md +170 -0
  25. package/playbooks/configure-e2ee-roles-and-policies.md +196 -0
  26. package/playbooks/deploy-tidecloak-docker.md +792 -0
  27. package/playbooks/diagnose-broken-login.md +234 -0
  28. package/playbooks/diagnose-missing-roles-or-claims.md +253 -0
  29. package/playbooks/initialize-admin-and-link-account.md +235 -0
  30. package/playbooks/migrate-from-existing-auth.md +198 -0
  31. package/playbooks/protect-api-nextjs.md +451 -0
  32. package/playbooks/protect-routes-nextjs.md +544 -0
  33. package/playbooks/setup-forseti-e2ee.md +756 -0
  34. package/playbooks/setup-iga-admin-panel.md +344 -0
  35. package/playbooks/setup-server-delegation.md +142 -0
  36. package/playbooks/start-tidecloak-dev.md +130 -0
  37. package/playbooks/verify-jwt-server-side.md +439 -0
  38. package/prompts/add-admin-approval-flow.md +50 -0
  39. package/prompts/build-private-customer-portal.md +85 -0
  40. package/prompts/migrate-generic-auth-to-tide.md +67 -0
  41. package/prompts/secure-existing-app.md +80 -0
  42. package/reference-apps/INDEX.md +87 -0
  43. package/reference-apps/encrypted-communication/anti-patterns.md +123 -0
  44. package/reference-apps/encrypted-communication/bootstrap-sequence.md +152 -0
  45. package/reference-apps/encrypted-communication/manifest.yaml +100 -0
  46. package/reference-apps/encrypted-communication/role-policy-matrix.md +80 -0
  47. package/reference-apps/encrypted-communication/scenario.md +134 -0
  48. package/reference-apps/git-pr-signing-service/anti-patterns.md +61 -0
  49. package/reference-apps/git-pr-signing-service/bootstrap-sequence.md +157 -0
  50. package/reference-apps/git-pr-signing-service/manifest.yaml +80 -0
  51. package/reference-apps/git-pr-signing-service/role-policy-matrix.md +99 -0
  52. package/reference-apps/git-pr-signing-service/scenario.md +169 -0
  53. package/reference-apps/iga-admin-governance/anti-patterns.md +133 -0
  54. package/reference-apps/iga-admin-governance/bootstrap-sequence.md +153 -0
  55. package/reference-apps/iga-admin-governance/manifest.yaml +87 -0
  56. package/reference-apps/iga-admin-governance/role-policy-matrix.md +67 -0
  57. package/reference-apps/iga-admin-governance/scenario.md +126 -0
  58. package/reference-apps/organisation-password-manager/anti-patterns.md +71 -0
  59. package/reference-apps/organisation-password-manager/bootstrap-sequence.md +127 -0
  60. package/reference-apps/organisation-password-manager/manifest.yaml +86 -0
  61. package/reference-apps/organisation-password-manager/role-policy-matrix.md +59 -0
  62. package/reference-apps/organisation-password-manager/scenario.md +107 -0
  63. package/reference-apps/policy-governed-signing/anti-patterns.md +67 -0
  64. package/reference-apps/policy-governed-signing/bootstrap-sequence.md +128 -0
  65. package/reference-apps/policy-governed-signing/manifest.yaml +78 -0
  66. package/reference-apps/policy-governed-signing/role-policy-matrix.md +62 -0
  67. package/reference-apps/policy-governed-signing/scenario.md +113 -0
  68. package/skills/tide-diagnostics/SKILL.md +99 -0
  69. package/skills/tide-integration/SKILL.md +136 -0
  70. package/skills/tide-learning-capture/SKILL.md +174 -0
  71. package/skills/tide-rbac-and-e2ee/SKILL.md +214 -0
  72. package/skills/tide-reviewer/SKILL.md +133 -0
  73. package/skills/tide-route-and-api-protection/SKILL.md +201 -0
  74. package/skills/tide-scenario-resolver/SKILL.md +81 -0
  75. package/skills/tide-setup/SKILL.md +218 -0
  76. package/skills/tide-solutions-architect/SKILL.md +130 -0
@@ -0,0 +1,234 @@
1
+ # Diagnose Broken Login
2
+
3
+ Symptom-led troubleshooting for login failures.
4
+
5
+ ---
6
+
7
+ ## Pre-Flight: Is Tide Actually Installed?
8
+
9
+ Before diagnosing specific symptoms, verify a real Tide integration exists:
10
+
11
+ ```bash
12
+ # 1. SDK installed?
13
+ grep '@tidecloak/nextjs' package.json
14
+ # If missing: npm install @tidecloak/nextjs
15
+
16
+ # 2. Provider in layout?
17
+ grep 'TideCloakProvider\|Providers' app/layout.tsx
18
+ # If missing: no Tide provider wrapping the app
19
+
20
+ # 3. Config file present?
21
+ test -f data/tidecloak.json && echo "Found" || echo "Missing"
22
+ # If missing: export adapter JSON from TideCloak Admin Console
23
+ ```
24
+
25
+ **If check 1 or 2 fails**, stop. The app does not have a Tide integration. Complete [add-auth-nextjs-fresh.md](add-auth-nextjs-fresh.md) (or [add-auth-nextjs-existing.md](add-auth-nextjs-existing.md) for existing apps) first, then return here.
26
+
27
+ **If only check 3 fails**, export the adapter JSON from TideCloak Admin Console and place it at `data/tidecloak.json`. DPoP is configured per-client in TideCloak Admin, not in the provider props. See [add-auth-nextjs-fresh.md Step 2](add-auth-nextjs-fresh.md#step-2-export-adapter-json-from-tidecloak).
28
+
29
+ ---
30
+
31
+ ## Pre-Flight: Is Adapter Config Present and Correctly Located?
32
+
33
+ Before symptom-specific debugging, verify the adapter config file:
34
+
35
+ ```bash
36
+ # Filename must be tidecloak.json (not adapter.json, not keycloak.json)
37
+
38
+ # Next.js (server-side):
39
+ test -f data/tidecloak.json && echo "Found data/tidecloak.json" || echo "Missing"
40
+
41
+ # React/Vite or Vanilla JS (client-side):
42
+ test -f public/tidecloak.json && echo "Found public/tidecloak.json" || echo "Missing"
43
+
44
+ # Wrong filename?
45
+ ls data/adapter.json data/keycloak.json public/adapter.json public/keycloak.json 2>/dev/null && echo "WRONG FILENAME — rename to tidecloak.json"
46
+
47
+ # Does code point to the right path?
48
+ grep -r 'configUrl\|tidecloak\.json\|adapter\.json' app/providers.tsx src/main.tsx public/auth.js 2>/dev/null
49
+ ```
50
+
51
+ **If file is missing**: Export from TideCloak admin console. See [add-auth-nextjs-fresh.md Step 2](add-auth-nextjs-fresh.md#step-2-export-adapter-json-from-tidecloak).
52
+
53
+ **If wrong filename**: Rename to `tidecloak.json`. The SDK does not look for `adapter.json` or `keycloak.json`.
54
+
55
+ **If wrong location**: Next.js server-side code reads from `data/tidecloak.json`. React/Vite/Vanilla JS client-side SDK fetches from `public/tidecloak.json` via `configUrl`. See [canon/invariants.md I-05](../canon/invariants.md#i-05-adapter-json-configuration-required).
56
+
57
+ ---
58
+
59
+ ## Symptom: Login Hangs Indefinitely
60
+
61
+ **What you see**: Click login, redirect to TideCloak, enter credentials, spinner forever.
62
+
63
+ **Diagnostic steps**:
64
+
65
+ ```bash
66
+ # 1. Check browser console
67
+ # Look for: "Refused to frame" CSP error
68
+
69
+ # 2. Check CSP headers
70
+ curl -I http://localhost:3000 | grep -i content-security-policy
71
+
72
+ # 3. Check silent SSO file
73
+ curl http://localhost:3000/silent-check-sso.html
74
+ # Should return HTML
75
+ ```
76
+
77
+ **Fix**: Add Tide domains to CSP. See [add-auth-nextjs-fresh.md Step 6](add-auth-nextjs-fresh.md#step-6-configure-csp-for-swe-iframe).
78
+
79
+ **Full guide**: [canon/troubleshooting.md T-01](../canon/troubleshooting.md#t-01-login-hangs-indefinitely).
80
+
81
+ ---
82
+
83
+ ## Symptom: Login Succeeds but User Lands on 404
84
+
85
+ **What you see**: Credentials accepted at TideCloak, but browser shows 404 or blank page after redirect.
86
+
87
+ **Diagnostic**:
88
+ ```bash
89
+ # Check redirect URI in adapter config
90
+ jq '.["auth-server-url"], .resource' data/tidecloak.json 2>/dev/null
91
+
92
+ # Check redirect handler exists
93
+ # App Router:
94
+ test -f app/auth/redirect/page.tsx && echo "Found" || echo "Missing"
95
+ # Pages Router:
96
+ test -f pages/auth/redirect.tsx && echo "Found" || echo "Missing"
97
+ ```
98
+
99
+ **Fix**: Create the redirect handler at the configured redirect path. See [canon/redirect-handler.md](../canon/redirect-handler.md) for framework-specific examples and [add-auth-nextjs-fresh.md Step 6](add-auth-nextjs-fresh.md#step-6-create-post-auth-redirect-handler).
100
+
101
+ ---
102
+
103
+ ## Symptom: Redirect URI Mismatch
104
+
105
+ **What you see**: TideCloak error page: "Invalid redirect_uri".
106
+
107
+ **Diagnostic**:
108
+ ```bash
109
+ # Check client config
110
+ # TideCloak Admin → Clients → {client} → Settings → Valid Redirect URIs
111
+ ```
112
+
113
+ **Fix**: Add app URL to valid redirect URIs:
114
+ - `http://localhost:3000/*` (dev)
115
+ - `https://app.example.com/*` (prod)
116
+
117
+ ---
118
+
119
+ ## Symptom: Cannot Find Module @tidecloak/nextjs
120
+
121
+ **What you see**: Import error on SDK package.
122
+
123
+ **Diagnostic**:
124
+ ```bash
125
+ cat package.json | grep tidecloak
126
+ # Should show: "@tidecloak/nextjs": "..."
127
+ ```
128
+
129
+ **Fix**:
130
+ ```bash
131
+ npm install @tidecloak/nextjs
132
+ ```
133
+
134
+ All `@tidecloak` packages are available on public npm registry.
135
+
136
+ ---
137
+
138
+ ## Symptom: Config Not Loading
139
+
140
+ **What you see**: Provider fails to initialize, or auth-server-url / realm / clientId are undefined.
141
+
142
+ **Diagnostic**:
143
+ ```bash
144
+ # Check tidecloak.json exists at the correct path
145
+ test -f data/tidecloak.json && echo "Found" || echo "MISSING — export from TideCloak admin"
146
+
147
+ # Check it has required Tide fields
148
+ node -e "const c=require('./data/tidecloak.json'); console.log('realm:', c.realm, 'url:', c['auth-server-url'], 'jwk:', !!c.jwk)"
149
+
150
+ # Check provider imports it
151
+ grep "tidecloak.json" app/providers.tsx src/app/providers.tsx 2>/dev/null
152
+ ```
153
+
154
+ **Fix**: The app should load config from `data/tidecloak.json`, not from `NEXT_PUBLIC_TIDECLOAK_*` env vars. If `providers.tsx` uses env vars instead of importing the JSON file, replace with:
155
+ ```typescript
156
+ import tcConfig from '../../data/tidecloak.json';
157
+ // ...
158
+ <TideCloakProvider config={tcConfig}>
159
+ ```
160
+
161
+ Do not create `NEXT_PUBLIC_TIDECLOAK_URL`, `NEXT_PUBLIC_TIDECLOAK_REALM`, `NEXT_PUBLIC_TIDECLOAK_CLIENT_ID`, or `NEXT_PUBLIC_TIDECLOAK_REDIRECT_URI` env vars. These values are in `tidecloak.json`.
162
+
163
+ ---
164
+
165
+ ## Symptom: Silent Refresh Fails
166
+
167
+ **What you see**: User logged out after 10 minutes.
168
+
169
+ **Diagnostic**:
170
+ ```bash
171
+ # Check silent SSO file
172
+ curl http://localhost:3000/silent-check-sso.html
173
+ # Should return HTML
174
+
175
+ # Check browser console for 404
176
+ # DevTools → Console → Filter: silent-check-sso
177
+ ```
178
+
179
+ **Fix**: Create `public/silent-check-sso.html`. See [add-auth-nextjs-fresh.md Step 5](add-auth-nextjs-fresh.md#step-5-create-silent-sso-file).
180
+
181
+ **Full guide**: [canon/troubleshooting.md T-04](../canon/troubleshooting.md#t-04-silent-token-refresh-fails).
182
+
183
+ ---
184
+
185
+ ## Symptom: Infinite Redirect Loop
186
+
187
+ **What you see**: Page redirects to login, login redirects to page, repeat forever.
188
+
189
+ **Diagnostic**: Check if login page has auth guard.
190
+
191
+ **Fix**: Remove auth guard from login/public pages:
192
+ ```typescript
193
+ // app/login/page.tsx
194
+ export default function LoginPage() {
195
+ // NO AuthGuard here
196
+ return <div>Login</div>;
197
+ }
198
+ ```
199
+
200
+ ---
201
+
202
+ ## Symptom: CORS Errors
203
+
204
+ **What you see**: Browser console: "CORS policy: No 'Access-Control-Allow-Origin'".
205
+
206
+ **Diagnostic**: Check TideCloak client Web Origins.
207
+
208
+ **Fix**:
209
+ 1. TideCloak Admin → Clients → {client} → Settings
210
+ 2. Web Origins: Add `http://localhost:3000` and `https://app.example.com`
211
+ 3. Save
212
+
213
+ ---
214
+
215
+ ## Quick Diagnostic Checklist
216
+
217
+ Run these in order:
218
+
219
+ - [ ] TideCloak reachable: `curl ${TIDECLOAK_URL}/.well-known/openid-configuration`
220
+ - [ ] Adapter config filename is `tidecloak.json` (not `adapter.json` or `keycloak.json`)
221
+ - [ ] Adapter config at correct location: `data/tidecloak.json` (Next.js) or `public/tidecloak.json` (React/Vite/Vanilla)
222
+ - [ ] Adapter JSON valid: `jq 'has("jwk") and has("vendorId") and has("homeOrkUrl")' data/tidecloak.json`
223
+ - [ ] Env vars set: `cat .env.local | grep NEXT_PUBLIC`
224
+ - [ ] CSP configured: `curl -I http://localhost:3000 | grep CSP`
225
+ - [ ] Silent SSO file: `curl http://localhost:3000/silent-check-sso.html`
226
+ - [ ] Redirect handler exists at configured redirectUri path
227
+ - [ ] Browser console clean (no errors)
228
+
229
+ ---
230
+
231
+ ## References
232
+
233
+ - [canon/troubleshooting.md](../canon/troubleshooting.md) - Complete troubleshooting
234
+ - [add-auth-nextjs-fresh.md](add-auth-nextjs-fresh.md) - Setup checklist
@@ -0,0 +1,253 @@
1
+ # Diagnose Missing Roles or Claims
2
+
3
+ Troubleshoot missing or incorrect JWT claims.
4
+
5
+ ---
6
+
7
+ ## Pre-Check: Is There a Real JWT?
8
+
9
+ Before inspecting claims, confirm the app is using real Tide JWTs, not fake auth:
10
+
11
+ ```bash
12
+ # Check for fake/hardcoded tokens
13
+ grep -r "auth_token\|fake.*token\|hardcoded\|FAKE_USERS" lib/ app/ --include="*.ts" --include="*.tsx"
14
+ # If matches: the app is using fake auth, not Tide. Fix the auth system first.
15
+
16
+ # Check for cookie-based auth instead of JWT
17
+ grep -r "cookies.*auth\|cookie.*token" app/api/ --include="*.ts"
18
+ # If matches: API reads auth from cookies, not Authorization header. See protect-api-nextjs.md.
19
+ ```
20
+
21
+ If the app has no real Tide integration (no `@tidecloak/nextjs` in package.json, no `TideCloakProvider` in layout), stop. Complete [add-auth-nextjs-fresh.md](add-auth-nextjs-fresh.md) first. Role diagnostics only apply to apps with working Tide auth.
22
+
23
+ ---
24
+
25
+ ## Symptom: Role Check Always Fails
26
+
27
+ **What you see**: `hasRealmRole('admin')` returns false even for admin users.
28
+
29
+ **Diagnostic steps**:
30
+
31
+ ### Step 1: Check JWT Contents
32
+
33
+ ```typescript
34
+ // Client-side
35
+ const { getValueFromToken, getValueFromIdToken } = useTideCloak();
36
+ console.log('User sub:', getValueFromToken("sub"));
37
+ console.log('Realm roles:', getValueFromToken("realm_access")?.roles);
38
+ console.log('Resource access:', getValueFromToken("resource_access"));
39
+ ```
40
+
41
+ Or decode JWT manually:
42
+ ```bash
43
+ # Get token from browser DevTools → Application → Local Storage
44
+ # Paste at jwt.io to decode
45
+ ```
46
+
47
+ ### Step 2: Verify Role Name
48
+
49
+ Common mismatches:
50
+ - Looking for `'admin'` but role is `'realm-admin'`
51
+ - Case sensitivity: `'Admin'` vs `'admin'`
52
+ - Client role vs realm role
53
+
54
+ ```typescript
55
+ // Check both realm and client roles
56
+ function hasAnyRole(user: any, role: string): boolean {
57
+ // Realm roles
58
+ const realmRoles = user?.realm_access?.roles || [];
59
+ if (realmRoles.includes(role)) return true;
60
+
61
+ // Client roles
62
+ const resourceAccess = user?.resource_access || {};
63
+ for (const client of Object.values(resourceAccess)) {
64
+ const clientRoles = (client as any)?.roles || [];
65
+ if (clientRoles.includes(role)) return true;
66
+ }
67
+
68
+ return false;
69
+ }
70
+ ```
71
+
72
+ ---
73
+
74
+ ## Symptom: User Has No Roles
75
+
76
+ **What you see**: `getValueFromToken("realm_access")?.roles` is empty array or undefined.
77
+
78
+ **Diagnostic**:
79
+
80
+ ```bash
81
+ # Check user in TideCloak Admin
82
+ # Admin Console → Users → {user} → Role Mappings
83
+ # Should show assigned roles
84
+ ```
85
+
86
+ **Causes**:
87
+
88
+ 1. **Roles not assigned**: Assign in TideCloak Admin
89
+ 2. **IGA pending**: If IGA enabled, role assignment needs quorum approval
90
+ 3. **Default roles missing**: Realm missing default composite role
91
+
92
+ **Fix (assign role)**:
93
+
94
+ 1. TideCloak Admin → Users → {user} → Role Mappings
95
+ 2. Assign role → {role-name}
96
+ 3. If IGA enabled: Approve change-set (requires quorum)
97
+ 4. User logout/login to get new token
98
+
99
+ **Fix (default roles)**:
100
+
101
+ 1. TideCloak Admin → Realm Settings → User Registration → Default Roles
102
+ 2. Add a `_tide_*` role (e.g., `_tide_enabled`) and application default role
103
+ 3. New users auto-receive these roles
104
+
105
+ ---
106
+
107
+ ## Symptom: Custom Claim Missing
108
+
109
+ **What you see**: `getValueFromToken("custom_field")` returns undefined.
110
+
111
+ **Diagnostic**:
112
+
113
+ Check if protocol mapper exists:
114
+
115
+ ```bash
116
+ # TideCloak Admin → Client Scopes → roles → Mappers
117
+ # Or: Clients → {client} → Client Scopes → roles → Mappers
118
+ ```
119
+
120
+ **Fix (add protocol mapper)**:
121
+
122
+ 1. Client Scopes → roles → Mappers → Create
123
+ 2. Mapper Type: "User Attribute"
124
+ 3. User Attribute: `customField` (user attribute name)
125
+ 4. Token Claim Name: `custom_field` (claim name in JWT)
126
+ 5. Claim JSON Type: String
127
+ 6. Add to ID token: ON
128
+ 7. Add to access token: ON
129
+ 8. Save
130
+
131
+ **Fix (set user attribute)**:
132
+
133
+ 1. Users → {user} → Attributes
134
+ 2. Key: `customField`, Value: `some-value`
135
+ 3. Save
136
+
137
+ User must logout/login to get updated token.
138
+
139
+ ---
140
+
141
+ ## Symptom: `tideuserkey` or `vuid` Missing
142
+
143
+ **What you see**: Tide-specific claims missing.
144
+
145
+ **Cause**: Protocol mappers not configured or account not linked.
146
+
147
+ **Diagnostic**:
148
+
149
+ ```bash
150
+ # Check user attributes
151
+ curl "${TIDECLOAK_URL}/admin/realms/${REALM}/users/${USER_ID}" | \
152
+ jq '.attributes | {tideUserKey, vuid}'
153
+ # Should show values
154
+
155
+ # Check protocol mappers
156
+ curl "${TIDECLOAK_URL}/admin/realms/${REALM}/clients/${CLIENT_ID}/protocol-mappers/models" | \
157
+ jq '.[] | select(.name | contains("tide"))'
158
+ ```
159
+
160
+ **Fix**: See [canon/troubleshooting.md T-07](../canon/troubleshooting.md#t-07-account-linking-stuck) for account linking.
161
+
162
+ ---
163
+
164
+ ## Symptom: Roles Change But Token Doesn't Update
165
+
166
+ **What you see**: Assigned new role in TideCloak, but `getValueFromToken("realm_access")?.roles` still shows old values.
167
+
168
+ **Cause**: Token cached. JWT claims frozen at issue time.
169
+
170
+ **Fix**:
171
+
172
+ ```bash
173
+ # User must logout/login to get fresh token
174
+ ```
175
+
176
+ Or force refresh:
177
+
178
+ ```typescript
179
+ // Client-side
180
+ const { logout, login } = useTideCloak();
181
+
182
+ async function forceTokenRefresh() {
183
+ await logout();
184
+ await login();
185
+ }
186
+ ```
187
+
188
+ ---
189
+
190
+ ## Symptom: E2EE Role Not Working
191
+
192
+ **What you see**: `doEncrypt('tag', data)` fails even though user has role.
193
+
194
+ **Diagnostic**:
195
+
196
+ ```bash
197
+ # Check exact role name
198
+ # Should be: _tide_{tag}.selfencrypt
199
+ # Not: _tide_encrypt or tide_{tag}
200
+ ```
201
+
202
+ **Fix**:
203
+
204
+ 1. TideCloak Admin → Roles → Create Role
205
+ 2. Name: `_tide_ssn.selfencrypt` (exact pattern)
206
+ 3. Assign to user
207
+ 4. Create matching decrypt role: `_tide_ssn.selfdecrypt`
208
+ 5. User logout/login
209
+
210
+ ---
211
+
212
+ ## Quick Diagnostic Script
213
+
214
+ ```typescript
215
+ // Add to app for debugging
216
+ function debugAuth() {
217
+ const { authenticated, getValueFromToken, getValueFromIdToken } = useTideCloak();
218
+
219
+ console.log('=== Auth Debug ===');
220
+ console.log('Authenticated:', authenticated);
221
+ console.log('User sub:', getValueFromToken("sub"));
222
+ console.log('User name:', getValueFromIdToken("preferred_username"));
223
+ console.log('Realm roles:', getValueFromToken("realm_access")?.roles);
224
+ console.log('Resource access:', getValueFromToken("resource_access"));
225
+ console.log('Tide claims:', {
226
+ tideuserkey: getValueFromToken("tideuserkey"),
227
+ vuid: getValueFromToken("vuid")
228
+ });
229
+ }
230
+
231
+ // Call from browser console
232
+ debugAuth();
233
+ ```
234
+
235
+ ---
236
+
237
+ ## Known Issues
238
+
239
+ ### `_tide_*` Role Required
240
+
241
+ **Required for all Tide operations**: Every user must have at least one role starting with `_tide_` (e.g., `_tide_enabled`). This role assignment enables the Tide Voucher system to fund user operations.
242
+
243
+ **Why**: The Vendor uses the `_tide_*` role to verify the user is Tide-enabled before assigning Vouchers. Without this role, Tide-related requests (including authorization) will be rejected.
244
+
245
+ **Fix**: Add a `_tide_*` role to realm default roles. Common convention: `_tide_enabled`.
246
+
247
+ ---
248
+
249
+ ## References
250
+
251
+ - [add-rbac-nextjs.md](add-rbac-nextjs.md) - RBAC implementation
252
+ - [canon/troubleshooting.md T-07](../canon/troubleshooting.md#t-07-account-linking-stuck) - Account linking
253
+ - [canon/concepts.md#tag-based-e2ee-roles](../canon/concepts.md#tag-based-e2ee-roles) - E2EE roles