@tideorg/mcp 1.4.1 → 1.9.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 (91) hide show
  1. package/CHANGELOG.md +81 -0
  2. package/GAP_REGISTER.md +19 -9
  3. package/PRIVACY.md +41 -0
  4. package/README.md +204 -120
  5. package/adapters/AGENTS.md +3 -2
  6. package/adapters/CLAUDE.md +1 -1
  7. package/adapters/replit.md +0 -0
  8. package/canon/anti-patterns.md +55 -62
  9. package/canon/concepts.md +46 -34
  10. package/canon/custom-contracts.md +12 -8
  11. package/canon/feature-mapping.md +27 -75
  12. package/canon/framework-matrix.md +69 -22
  13. package/canon/hosting-options.md +111 -0
  14. package/canon/iga-change-requests-api.md +211 -0
  15. package/canon/invariants.md +33 -35
  16. package/canon/redirect-handler.md +0 -0
  17. package/canon/security-gap-mapping.md +506 -0
  18. package/canon/security-runtime-probes.md +177 -0
  19. package/canon/tidecloak-bootstrap.md +84 -15
  20. package/canon/tidecloak-endpoints.md +60 -98
  21. package/canon/troubleshooting.md +201 -53
  22. package/canon/version-policy.md +8 -12
  23. package/mcp-server/dist/http.d.ts +2 -0
  24. package/mcp-server/dist/http.js +46 -0
  25. package/mcp-server/dist/index.d.ts +0 -0
  26. package/mcp-server/dist/index.js +2 -601
  27. package/mcp-server/dist/server.d.ts +2 -0
  28. package/mcp-server/dist/server.js +617 -0
  29. package/package.json +48 -45
  30. package/playbooks/add-auth-nextjs-existing.md +33 -17
  31. package/playbooks/add-auth-nextjs-fresh.md +1 -1
  32. package/playbooks/add-rbac-nextjs.md +7 -2
  33. package/playbooks/bootstrap-realm-from-template.md +33 -18
  34. package/playbooks/configure-e2ee-roles-and-policies.md +0 -0
  35. package/playbooks/deploy-tidecloak-docker.md +31 -28
  36. package/playbooks/diagnose-broken-login.md +0 -0
  37. package/playbooks/diagnose-missing-roles-or-claims.md +2 -2
  38. package/playbooks/initialize-admin-and-link-account.md +22 -19
  39. package/playbooks/migrate-from-existing-auth.md +0 -0
  40. package/playbooks/protect-api-nextjs.md +40 -1
  41. package/playbooks/protect-aspnet-core-asgard.md +313 -0
  42. package/playbooks/protect-routes-nextjs.md +24 -10
  43. package/playbooks/provision-tidecloak-skycloak.md +213 -0
  44. package/playbooks/setup-forseti-e2ee.md +32 -50
  45. package/playbooks/setup-iga-admin-panel.md +113 -171
  46. package/playbooks/start-tidecloak-dev.md +0 -0
  47. package/playbooks/verify-jwt-server-side.md +20 -1
  48. package/prompts/add-admin-approval-flow.md +0 -0
  49. package/prompts/build-private-customer-portal.md +1 -1
  50. package/prompts/migrate-generic-auth-to-tide.md +0 -0
  51. package/prompts/secure-existing-app.md +0 -0
  52. package/prompts/security-gap-analysis.md +55 -0
  53. package/reference-apps/INDEX.md +0 -0
  54. package/reference-apps/encrypted-communication/anti-patterns.md +3 -3
  55. package/reference-apps/encrypted-communication/bootstrap-sequence.md +2 -2
  56. package/reference-apps/encrypted-communication/manifest.yaml +0 -0
  57. package/reference-apps/encrypted-communication/role-policy-matrix.md +0 -0
  58. package/reference-apps/encrypted-communication/scenario.md +2 -2
  59. package/reference-apps/git-pr-signing-service/anti-patterns.md +0 -0
  60. package/reference-apps/git-pr-signing-service/bootstrap-sequence.md +8 -8
  61. package/reference-apps/git-pr-signing-service/manifest.yaml +0 -0
  62. package/reference-apps/git-pr-signing-service/role-policy-matrix.md +0 -0
  63. package/reference-apps/git-pr-signing-service/scenario.md +0 -0
  64. package/reference-apps/iga-admin-governance/anti-patterns.md +18 -16
  65. package/reference-apps/iga-admin-governance/bootstrap-sequence.md +10 -5
  66. package/reference-apps/iga-admin-governance/manifest.yaml +0 -0
  67. package/reference-apps/iga-admin-governance/role-policy-matrix.md +12 -13
  68. package/reference-apps/iga-admin-governance/scenario.md +15 -13
  69. package/reference-apps/organisation-password-manager/anti-patterns.md +0 -0
  70. package/reference-apps/organisation-password-manager/bootstrap-sequence.md +5 -6
  71. package/reference-apps/organisation-password-manager/manifest.yaml +0 -0
  72. package/reference-apps/organisation-password-manager/role-policy-matrix.md +0 -0
  73. package/reference-apps/organisation-password-manager/scenario.md +0 -0
  74. package/reference-apps/policy-governed-signing/anti-patterns.md +0 -0
  75. package/reference-apps/policy-governed-signing/bootstrap-sequence.md +9 -9
  76. package/reference-apps/policy-governed-signing/manifest.yaml +0 -0
  77. package/reference-apps/policy-governed-signing/role-policy-matrix.md +0 -0
  78. package/reference-apps/policy-governed-signing/scenario.md +0 -0
  79. package/skills/tide-diagnostics/SKILL.md +1 -1
  80. package/skills/tide-integration/SKILL.md +9 -18
  81. package/skills/tide-learning-capture/SKILL.md +0 -0
  82. package/skills/tide-mcp-qa/SKILL.md +139 -0
  83. package/skills/tide-rbac-and-e2ee/SKILL.md +5 -5
  84. package/skills/tide-reviewer/SKILL.md +1 -1
  85. package/skills/tide-route-and-api-protection/SKILL.md +0 -0
  86. package/skills/tide-scenario-resolver/SKILL.md +0 -0
  87. package/skills/tide-security-analyst/SKILL.md +182 -0
  88. package/skills/tide-setup/SKILL.md +1 -1
  89. package/skills/tide-solutions-architect/SKILL.md +0 -0
  90. package/canon/delegation.md +0 -195
  91. package/playbooks/setup-server-delegation.md +0 -142
@@ -0,0 +1,55 @@
1
+ # Prompt: Security Gap Analysis of an Existing System
2
+
3
+ Copy-paste this to an AI coding agent to audit an existing application for identity, key-management, authorization, and data-exposure gaps — and map each gap to the Tide capability that removes it. Works on systems with no Tide involvement at all.
4
+
5
+ This is an **advisory, read-only** analysis. It does not modify the target.
6
+
7
+ ---
8
+
9
+ ## The Prompt
10
+
11
+ > Perform a security gap analysis of this system. You are acting as the **Security Analyst** role from the Tide agent pack. Do not modify any code. Produce a report; do not begin remediation until I approve it.
12
+ >
13
+ > **First, confirm scope**: state exactly what you will inspect (repo, running instance, config) and that this is my own system or an authorized engagement. Read-only.
14
+ >
15
+ > **Load the doctrine**: read `canon/security-gap-mapping.md` (the SG-01 … SG-18 gap table) and `skills/tide-security-analyst/SKILL.md`. If you have the Tide MCP server, call `tide_security_analysis` to load them at once.
16
+ >
17
+ > **Two tiers**: run the **static** sweep (code/config/schema) always. Only run the **runtime confirmation** tier — sending live probes to confirm findings — if I confirm I own or am authorized to test the target, and then strictly per `canon/security-runtime-probes.md` (non-destructive, no exploitation, my own test account only). If I have not authorized live testing, stay static-only and keep findings tagged INFERRED.
18
+ >
19
+ > **Inventory the trust architecture first** (before pattern-matching), answering from the code/config:
20
+ > 1. Identity — how are users authenticated, where do credentials live?
21
+ > 2. Authority — how are tokens/sessions signed, who holds the signing key?
22
+ > 3. Authorization — where is the access decision made: client, server, or both?
23
+ > 4. Data — what sensitive data exists, and who can read it in the clear?
24
+ >
25
+ > **Run the full gap sweep**: work through SG-01 … SG-12 exhaustively. For each, run the detection commands from `canon/security-gap-mapping.md` against the target and record hits. Do NOT sample APIs (SG-05) — enumerate every route and diff against the routes that actually verify. Also collect anything matching the "Out of scope" table.
26
+ >
27
+ > **Every finding must have**:
28
+ > - A named **trust concentration** — the single party or artifact that, once compromised, defeats the control. "Uses passwords" is not a finding; "password verification collapses to one database + one server process" is.
29
+ > - **Evidence** — a file:line, config value, schema column, or HTTP observation — tagged VERIFIED (observed), INFERRED (implied by code), or ASSUMED (my statement, unconfirmed).
30
+ > - A **severity** (CRITICAL / HIGH / MEDIUM / INFO) based on blast radius under a single compromise.
31
+ > - The **Tide replacement**, cited from `canon/feature-mapping.md` or `canon/invariants.md`, with its sourcing tag.
32
+ > - The **remediation playbook sequence** (verify each playbook exists via `tide_list playbooks`).
33
+ > - The **limits** — the honesty note: what the Tide replacement does NOT cover.
34
+ >
35
+ > **Be honest**: include a non-empty "Not Addressed by Tide" section for anything you find that Tide doesn't fix (injection, XSS, CSRF, vulnerable dependencies, rate limiting, infra hardening). Never present Tide as fixing these. An honest analysis is more credible than an inflated one.
36
+ >
37
+ > **Report in the format** defined in `skills/tide-security-analyst/SKILL.md` (Report Format section): trust-architecture summary, findings most-severe-first, gap interactions, out-of-scope section, then a recommended remediation sequence with the execution role to engage first (per I-18).
38
+ >
39
+ > **Do not**: modify code, run TideCloak bootstrap, install the SDK, or start fixing anything. Report only. When I approve findings, hand off to the execution roles (Setup → Application → Security → IAM/Policy → Reviewer).
40
+
41
+ ---
42
+
43
+ ## Acceptance Criteria
44
+
45
+ - [ ] Scope and authorization confirmed before inspection
46
+ - [ ] Trust architecture (identity / authority / authorization / data) documented
47
+ - [ ] All of SG-01 … SG-18 checked, not sampled (or non-applicability stated per SG)
48
+ - [ ] Every finding names a trust concentration and carries evidence with a confidence tag
49
+ - [ ] Runtime tier run only if authorized; probed findings carry a Runtime confirmation line; unprobed findings stay INFERRED
50
+ - [ ] Every Tide-replacement claim cites `canon/feature-mapping.md` or `canon/invariants.md`
51
+ - [ ] Every remediation names a playbook that exists in `playbooks/`
52
+ - [ ] Non-empty "Not Addressed by Tide" section (or explicit "none found in scope")
53
+ - [ ] No finding claims Tide fixes an out-of-scope gap class
54
+ - [ ] Remediation sequence provided with first execution role named
55
+ - [ ] No code was modified; the analysis is read-only
File without changes
@@ -10,7 +10,7 @@ Scenario-specific mistakes for encrypted communication apps using the hybrid Tid
10
10
 
11
11
  **Why it fails**: The private key is the root of trust for all E2E operations. If stored in plaintext, a database breach or XSS attack exposes all encrypted communications.
12
12
 
13
- **Fix**: Always encrypt the private key with `doEncrypt(privateKeyBytes, tag)` before storing. Always decrypt with `doDecrypt()` on login. Never persist the decrypted private key outside of in-memory variables.
13
+ **Fix**: Always encrypt the private key with `doEncrypt([{ data: privateKeyBytes, tags: [tag] }])` before storing. Always decrypt with `doDecrypt()` on login. Never persist the decrypted private key outside of in-memory variables.
14
14
 
15
15
  ---
16
16
 
@@ -118,6 +118,6 @@ Scenario-specific mistakes for encrypted communication apps using the hybrid Tid
118
118
 
119
119
  **Mistake**: Installing a 0.99.x pre-release version of the Tide SDK.
120
120
 
121
- **Why it fails**: 0.99.x versions are unstable pre-releases. The stable version is 0.13.26 (per pack version policy).
121
+ **Why it fails**: 0.99.x versions are unstable pre-releases. The stable version is 0.13.33 (per pack version policy).
122
122
 
123
- **Fix**: Pin `@tidecloak/react` to `0.13.26`. See `canon/version-policy.md`.
123
+ **Fix**: Pin `@tidecloak/react` to `0.13.33`. See `canon/version-policy.md`.
@@ -117,12 +117,12 @@
117
117
 
118
118
  23. Implement first-login flow:
119
119
  - Generate keypair client-side
120
- - Encrypt private key with `doEncrypt(privateKeyBytes, tag)`
120
+ - Encrypt private key with `doEncrypt([{ data: privateKeyBytes, tags: [tag] }])`
121
121
  - Store encrypted private key + public key via protected API
122
122
 
123
123
  24. Implement returning-login flow:
124
124
  - Fetch encrypted key material via protected API
125
- - Decrypt private key with `doDecrypt(encryptedPrivateKey, tag)`
125
+ - Decrypt private key with `doDecrypt([{ encrypted: encryptedPrivateKey, tags: [tag] }])`
126
126
  - Private key available in memory for runtime E2E operations
127
127
 
128
128
  25. Implement runtime E2E operations using the external crypto library (not Tide).
@@ -77,14 +77,14 @@ On **first login** for a new user:
77
77
  1. User authenticates via TideCloak SSO
78
78
  2. App checks database for existing encrypted key material
79
79
  3. No keys found → app generates a new asymmetric keypair client-side (e.g., `crypto_box_keypair()`)
80
- 4. App encrypts the private key using `doEncrypt(privateKeyBytes, tag)` (Tide self-encryption)
80
+ 4. App encrypts the private key using `doEncrypt([{ data: privateKeyBytes, tags: [tag] }])` (Tide self-encryption)
81
81
  5. App stores the encrypted private key and the public key in the database via a protected API endpoint
82
82
  6. Private key is now available in memory for runtime E2E operations
83
83
 
84
84
  On **returning login**:
85
85
  1. User authenticates via TideCloak SSO
86
86
  2. App fetches encrypted key material from database
87
- 3. App decrypts the private key using `doDecrypt(encryptedPrivateKey, tag)` (Tide self-encryption)
87
+ 3. App decrypts the private key using `doDecrypt([{ encrypted: encryptedPrivateKey, tags: [tag] }])` (Tide self-encryption)
88
88
  4. Private key is now available in memory for runtime E2E operations
89
89
 
90
90
  **Runtime E2E operations** (not Tide — handled by external crypto library):
@@ -27,11 +27,11 @@ All steps must complete before the service can sign merge commits. Order matters
27
27
  - `POST /admin/realms/{realm}/tide-admin/toggle-iga` with form-urlencoded `isIGAEnabled=true`.
28
28
  - Must happen after licensing.
29
29
 
30
- ## Phase 3: Approve initial change-sets
30
+ ## Phase 3: Approve initial change requests
31
31
 
32
- 6. **Approve client change-sets**
33
- - List: `GET /admin/realms/{realm}/tide-admin/change-set/clients/requests`.
34
- - For each: sign (`POST .../change-set/sign`) then commit (`POST .../change-set/commit`).
32
+ 6. **Approve initial change requests** (current `/iga/change-requests/...` surface — see `canon/iga-change-requests-api.md`)
33
+ - List: `GET /admin/realms/{realm}/iga/change-requests?status=PENDING` (objects keyed by `id`).
34
+ - Approve: `POST .../iga/change-requests/bulk-authorize` (`{"actionTypeIn":["CREATE","DELETE"],"limit":100}`), then `POST .../iga/change-requests/{id}/commit` for each `readyToCommit` CR. FirstAdmin bootstrap signs server-side.
35
35
 
36
36
  ## Phase 4: Admin user setup
37
37
 
@@ -50,11 +50,11 @@ All steps must complete before the service can sign merge commits. Order matters
50
50
  10. **Wait for account linking**
51
51
  - Poll `GET /admin/realms/{realm}/users/{userId}` until `attributes.tideUserKey` and `attributes.vuid` are present for each admin.
52
52
 
53
- ## Phase 5: Approve user change-sets
53
+ ## Phase 5: Approve user change requests
54
54
 
55
- 11. **Approve user change-sets**
56
- - List: `GET /admin/realms/{realm}/tide-admin/change-set/users/requests`.
57
- - For each: sign then commit.
55
+ 11. **Approve user change requests**
56
+ - List: `GET /admin/realms/{realm}/iga/change-requests?status=PENDING`.
57
+ - Authorize then commit (see Phase 3 / `canon/iga-change-requests-api.md`).
58
58
 
59
59
  ## Phase 6: IDP settings and adapter export
60
60
 
File without changes
@@ -14,43 +14,45 @@ Scenario-specific mistakes for IGA admin governance panels. General Tide anti-pa
14
14
 
15
15
  ---
16
16
 
17
- ## AP-G02: Using JSON for add-review or add-rejection
17
+ > Endpoints use the current `/iga/change-requests/...` surface (GAP-065). Full spec: `canon/iga-change-requests-api.md`.
18
18
 
19
- **Mistake**: Sending `application/json` to `/tideAdminResources/add-review` or `/tideAdminResources/add-rejection`.
19
+ ## AP-G02: Treating authorize as commit
20
20
 
21
- **Why it fails**: These endpoints require `multipart/form-data`. JSON submissions return 415 or are silently ignored.
21
+ **Mistake**: Calling only `POST /iga/change-requests/{id}/authorize` and assuming the change is applied.
22
22
 
23
- **Fix**: Use `FormData` for add-review and add-rejection. All other mutation endpoints (sign/batch, commit/batch, cancel/batch) use JSON.
23
+ **Why it fails**: `authorize` records an approval. The change does not take effect until `POST /iga/change-requests/{id}/commit` is called, and commit returns **412** until `readyToCommit` (threshold met, dependencies committed).
24
+
25
+ **Fix**: After `authorize` succeeds, poll for `readyToCommit === true`, then `commit`. During bootstrap, `bulk-authorize` then commit ready CRs in dependency passes.
24
26
 
25
27
  ---
26
28
 
27
- ## AP-G03: Treating sign as commit
29
+ ## AP-G03: Re-signing the same CR with the same admin
28
30
 
29
- **Mistake**: Calling only `sign/batch` and assuming the change is applied.
31
+ **Mistake**: Retrying `authorize` on a CR the same admin already signed.
30
32
 
31
- **Why it fails**: Signing records an approval. The change does not take effect until `commit/batch` is called after the quorum threshold is met.
33
+ **Why it fails**: Four-eyes enforcement returns **409 Conflict** one admin cannot count twice toward the threshold.
32
34
 
33
- **Fix**: After sign succeeds and approval count >= threshold, call `commit/batch`.
35
+ **Fix**: Have a *different* admin authorize. If you get 409, refresh the CR (`GET /iga/change-requests/{id}`) — it may already be signed or no longer PENDING.
34
36
 
35
37
  ---
36
38
 
37
- ## AP-G04: Caching change-set counts across mutations
39
+ ## AP-G04: Stale pending list across mutations
38
40
 
39
- **Mistake**: Fetching counts once and not refreshing after sign, commit, or cancel.
41
+ **Mistake**: Fetching the pending list once and not refreshing after authorize/commit/deny.
40
42
 
41
- **Why it fails**: Counts change after every mutation. Stale counts cause the UI to show incorrect badge numbers and confuse admins.
43
+ **Why it fails**: `status` and `readyToCommit` change after every action. Stale data drives wrong badge counts and lets the UI offer commit on a CR that is not ready (→ 412).
42
44
 
43
- **Fix**: Refresh counts after every mutation (sign, commit, cancel, add-review, add-rejection).
45
+ **Fix**: Re-fetch `GET /iga/change-requests?status=PENDING` after every mutation and recompute counts/badges from it.
44
46
 
45
47
  ---
46
48
 
47
- ## AP-G05: Ignoring enclave challenge in MultiAdmin mode
49
+ ## AP-G05: Skipping the enclave step in Tide MultiAdmin mode
48
50
 
49
- **Mistake**: Not handling the enclave approval popup when multiple admins exist. The sign response indicates `requiresApprovalPopup: true` but the app treats it as a normal success.
51
+ **Mistake**: Calling a bare `authorize` in Tide MultiAdmin mode and treating the response as done.
50
52
 
51
- **Why it fails**: In MultiAdmin mode, `sign/batch` returns an enclave challenge (base64 `changeSetDraftRequests`). The admin must sign this in the enclave popup and submit via `add-review`. Without this, the approval is not recorded.
53
+ **Why it fails**: In Tide MultiAdmin mode the approval is cryptographic a bare `authorize` does not record it. The admin must complete the two-phase enclave exchange: `GET /iga/change-requests/{id}/approval-model` sign the `requestModel` in the enclave → `POST /iga/change-requests/{id}/approval-model` with `{ requestModel }`.
52
54
 
53
- **Fix**: Check the sign response for `requiresApprovalPopup`. If true, present the enclave challenge to the admin and submit the result via `add-review` (FormData).
55
+ **Fix**: In MultiAdmin mode, drive the `approval-model` exchange and confirm `recorded: true` / an increased `authCount`. FirstAdmin/Tideless mode signs server-side on `authorize` — no enclave step.
54
56
 
55
57
  ---
56
58
 
@@ -50,12 +50,17 @@
50
50
  -d "isIGAEnabled=true"
51
51
  ```
52
52
 
53
- 6. Approve/commit initial client change request:
53
+ 6. Approve/commit initial change requests (current `/iga/change-requests/...` surface; see `canon/iga-change-requests-api.md`):
54
54
  ```bash
55
- # Get pending client changes
56
- CLIENTS=$(curl -s "http://localhost:8080/admin/realms/$REALM/tide-admin/change-set/clients/requests" \
57
- -H "Authorization: Bearer $TOKEN")
58
- # Extract changeSets array, then sign and commit
55
+ # Authorize all pending, then commit ready ones (FirstAdmin bootstrap signs server-side)
56
+ curl -s -X POST "http://localhost:8080/admin/realms/$REALM/iga/change-requests/bulk-authorize" \
57
+ -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
58
+ -d '{"actionTypeIn":["CREATE","DELETE"],"limit":100}'
59
+ for id in $(curl -s "http://localhost:8080/admin/realms/$REALM/iga/change-requests?status=PENDING" \
60
+ -H "Authorization: Bearer $TOKEN" | jq -r '.[] | select(.readyToCommit==true) | .id'); do
61
+ curl -s -X POST "http://localhost:8080/admin/realms/$REALM/iga/change-requests/$id/commit" \
62
+ -H "Authorization: Bearer $TOKEN"
63
+ done
59
64
  ```
60
65
 
61
66
  ---
File without changes
@@ -49,19 +49,18 @@ The governance panel may optionally include policy management. These are NOT req
49
49
 
50
50
  ---
51
51
 
52
- ## Change-Set Endpoints (core governance)
52
+ ## Change-Request Endpoints (core governance)
53
+
54
+ Current `/iga/change-requests/...` surface (replaces legacy `/tide-admin/change-set/...`, GAP-065). **Full spec: `canon/iga-change-requests-api.md`.**
53
55
 
54
56
  | Operation | Endpoint | Method | Content-Type | Notes |
55
57
  |-----------|---------|--------|-------------|-------|
56
- | List counts | `/tide-admin/change-set/counts` | GET | — | Returns per-type counts |
57
- | List all requests | `/tide-admin/change-set/all/requests` | GET | — | Returns all pending changes grouped by type |
58
- | List by type | `/tide-admin/change-set/{type}/requests` | GET | | `{type}` = users, roles, clients, groups |
59
- | Sign (approve) | `/tide-admin/change-set/sign/batch` | POST | `application/json` | Body: `{ changeSets: [...] }` |
60
- | Commit | `/tide-admin/change-set/commit/batch` | POST | `application/json` | Body: `{ changeSets: [...] }` |
61
- | Cancel | `/tide-admin/change-set/cancel/batch` | POST | `application/json` | Body: `{ changeSets: [...] }` |
62
- | Add review (enclave) | `/tideAdminResources/add-review` | POST | **`multipart/form-data`** | Used after enclave challenge in MultiAdmin mode |
63
- | Add rejection | `/tideAdminResources/add-rejection` | POST | **`multipart/form-data`** | Content-type asymmetry: NOT JSON |
64
- | Activity | `/tide-admin/change-set/{id}/activity` | GET | | Returns approvals, rejections, comments |
65
- | Add comment | `/tide-admin/change-set/{id}/comments` | POST | `application/json` | |
66
- | Licensing requests | `/tideAdminResources/change-set/licensing/requests` | GET | — | Different path prefix from other types |
67
- | Ragnarok requests | `/ragnarok/change-set/offboarding/requests` | GET | — | Different path prefix |
58
+ | List | `/iga/change-requests?status=PENDING` | GET | — | Objects keyed by `id`; `status` = PENDING/APPROVED/DENIED/CANCELLED. Derive counts from the list. |
59
+ | Get one | `/iga/change-requests/{id}` | GET | — | Full CR (`entityType`, `readyToCommit`, `threshold`, `dependsOn`) |
60
+ | Authorize (approve) | `/iga/change-requests/{id}/authorize` | POST | `application/json` | Body `{}` optional. 409 = four-eyes re-sign |
61
+ | Bulk authorize | `/iga/change-requests/bulk-authorize` | POST | `application/json` | `{ "actionTypeIn": ["CREATE","DELETE"], "limit": 100 }`; 429 if a bulk run is active |
62
+ | Commit | `/iga/change-requests/{id}/commit` | POST | | 412 if under threshold / unmet dependency |
63
+ | Deny (reject) | `/iga/change-requests/{id}/deny` | POST | | 204 |
64
+ | Enclave sign (Tide MultiAdmin) | `/iga/change-requests/{id}/approval-model` | GET/POST | `application/json` | Two-phase: GET challenge POST `{ requestModel }` |
65
+ | Comments | `/iga/change-requests/{id}/comments` | GET/POST | `application/json` | `{ "comment": "..." }` (≤2000) |
66
+ | Manual ADOPT | `/iga/adopt` | POST | `application/json` | `{ "entityType": "USER", "entityId": "..." }` |
@@ -72,17 +72,18 @@ These happen before any admin uses the governance panel:
72
72
 
73
73
  Once bootstrap is complete, the governance panel operates as follows:
74
74
 
75
+ Endpoints use the current `/iga/change-requests/...` surface (replaces legacy `/tide-admin/change-set/...`, GAP-065; full spec `canon/iga-change-requests-api.md`).
76
+
75
77
  1. Admin logs in via TideCloak SSO (DPoP-bound)
76
- 2. Panel fetches change-set counts (`GET /tide-admin/change-set/counts`)
77
- 3. Panel lists pending requests by type (users, roles, groups, clients, settings, policies)
78
+ 2. Panel lists pending requests (`GET /iga/change-requests?status=PENDING`) and derives counts
79
+ 3. Panel groups pending CRs by `entityType` (users, roles, groups, clients, settings, policies)
78
80
  4. Admin reviews a change request's details, activity, and comments
79
- 5. Admin approves: `POST /tide-admin/change-set/sign/batch` (JSON body)
80
- - If MultiAdmin: enclave challenge popup appears; admin signs and submits via `POST /tideAdminResources/add-review` (**multipart/form-data**, not JSON)
81
- - If FirstAdmin: signed immediately with VRK
82
- 6. When approval count >= quorum threshold: `POST /tide-admin/change-set/commit/batch`
83
- 7. Admin can cancel pending requests: `POST /tide-admin/change-set/cancel/batch`
84
- 8. Admin can reject: `POST /tideAdminResources/add-rejection` (**multipart/form-data**)
85
- 9. Admin can add/edit/delete comments on change requests
81
+ 5. Admin approves: `POST /iga/change-requests/{id}/authorize` (body `{}`; 409 = four-eyes)
82
+ - If Tide MultiAdmin: complete the two-phase `GET`/`POST /iga/change-requests/{id}/approval-model` enclave exchange
83
+ - If FirstAdmin/Tideless: signed server-side immediately
84
+ 6. When `readyToCommit`: `POST /iga/change-requests/{id}/commit` (412 if under threshold)
85
+ 7. Admin can reject: `POST /iga/change-requests/{id}/deny`
86
+ 8. Admin can add/edit/delete comments on change requests
86
87
 
87
88
  ---
88
89
 
@@ -104,10 +105,11 @@ Once bootstrap is complete, the governance panel operates as follows:
104
105
 
105
106
  | Symptom | Likely cause | Fix |
106
107
  |---------|-------------|-----|
107
- | Sign returns 401 | Token expired or DPoP not attached | Re-login; ensure `secureFetch` with DPoP |
108
- | Sign returns enclave challenge (MultiAdmin) | Multiple admins exist | Handle popup flow via `add-review` endpoint |
109
- | Commit returns error | Not all required approvals met | Check approval count vs quorum threshold |
110
- | Change request stays PENDING after sign | Missing commit step | Call `commit/batch` after sign succeeds |
108
+ | Authorize returns 401 | Token expired or DPoP not attached | Re-login; ensure `secureFetch` with DPoP |
109
+ | Authorize returns 409 | Same admin re-signing (four-eyes) or CR not PENDING | Use a different admin; refresh the list |
110
+ | MultiAdmin: authorize does not record | Enclave step skipped | Complete `{id}/approval-model` two-phase exchange |
111
+ | Commit returns 412 | Under threshold / unmet dependency | Collect more approvals; commit `dependsOn` CR first |
112
+ | Change request stays PENDING after authorize | Missing commit step | Call `{id}/commit` once `readyToCommit` |
111
113
  | add-review returns 415 | Wrong content-type | Use `multipart/form-data`, not JSON |
112
114
  | Counts don't update after commit | Stale data | Refresh counts after every mutation |
113
115
  | Policy change requests don't appear | Realm policy not in pending state | Create pending realm policy first via `/tide-admin/realm-policy/pending` |
@@ -48,12 +48,11 @@ All steps must complete before users can safely use the app. Order matters.
48
48
 
49
49
  ## Phase 4: Change-set approval
50
50
 
51
- 10. **Approve pending change-sets**
52
- - IGA creates draft change-sets for client and user mutations made during setup.
53
- - List: `GET /admin/realms/{realm}/tide-admin/change-set/{type}/requests` for types `clients`, `users`.
54
- - For each pending change-set:
55
- - Sign: `POST /admin/realms/{realm}/tide-admin/change-set/sign` (requires admin doken).
56
- - Commit: `POST /admin/realms/{realm}/tide-admin/change-set/commit`.
51
+ 10. **Approve pending change requests** (current `/iga/change-requests/...` surface — see `canon/iga-change-requests-api.md`)
52
+ - IGA creates draft change requests for client and user mutations made during setup (each mutating write returns 202).
53
+ - List: `GET /admin/realms/{realm}/iga/change-requests?status=PENDING` (objects keyed by `id`).
54
+ - Approve: `POST /admin/realms/{realm}/iga/change-requests/bulk-authorize` (`{"actionTypeIn":["CREATE","DELETE"],"limit":100}`; FirstAdmin signs server-side).
55
+ - Commit: `POST /admin/realms/{realm}/iga/change-requests/{id}/commit` for each `readyToCommit` CR.
57
56
  - Without this step, client and user changes are in draft state and not active.
58
57
 
59
58
  ## Phase 5: IDP settings and adapter export
@@ -28,12 +28,12 @@ All steps must complete before users can safely use signing features. Order matt
28
28
  - `POST /admin/realms/{realm}/tide-admin/toggle-iga` with form-urlencoded `isIGAEnabled=true`.
29
29
  - Must happen after licensing. Enables change-set governance for role/user mutations.
30
30
 
31
- ## Phase 3: Approve initial change-sets
31
+ ## Phase 3: Approve initial change requests
32
32
 
33
- 6. **Approve client change-sets**
34
- - IGA creates draft change-sets for client mutations during realm import.
35
- - List: `GET /admin/realms/{realm}/tide-admin/change-set/clients/requests`.
36
- - For each: sign (`POST .../change-set/sign`) then commit (`POST .../change-set/commit`).
33
+ 6. **Approve initial change requests** (current `/iga/change-requests/...` surface — see `canon/iga-change-requests-api.md`)
34
+ - IGA creates draft change requests for client/role mutations during realm import (each mutating write returns 202).
35
+ - List: `GET /admin/realms/{realm}/iga/change-requests?status=PENDING` (objects keyed by `id`).
36
+ - Approve: `POST /admin/realms/{realm}/iga/change-requests/bulk-authorize` (`{"actionTypeIn":["CREATE","DELETE"],"limit":100}`), then `POST /admin/realms/{realm}/iga/change-requests/{id}/commit` for each `readyToCommit` CR. FirstAdmin bootstrap signs server-side.
37
37
 
38
38
  ## Phase 4: Admin user setup
39
39
 
@@ -52,11 +52,11 @@ All steps must complete before users can safely use signing features. Order matt
52
52
  - Poll `GET /admin/realms/{realm}/users/{userId}` until `attributes.tideUserKey` and `attributes.vuid` are present.
53
53
  - Do not proceed until both attributes exist.
54
54
 
55
- ## Phase 5: Approve user change-sets
55
+ ## Phase 5: Approve user change requests
56
56
 
57
- 11. **Approve user change-sets**
58
- - List: `GET /admin/realms/{realm}/tide-admin/change-set/users/requests`.
59
- - For each: sign then commit.
57
+ 11. **Approve user change requests**
58
+ - List: `GET /admin/realms/{realm}/iga/change-requests?status=PENDING`.
59
+ - Authorize then commit (see Phase 3 / `canon/iga-change-requests-api.md`).
60
60
 
61
61
  ## Phase 6: IDP settings and adapter export
62
62
 
@@ -54,7 +54,7 @@ Troubleshoot broken Tide integrations. Own login failures, missing roles/claims,
54
54
  |---------|-------------|----------|
55
55
  | Login hangs or blank screen | CSP missing `frame-src '*'`, redirect handler missing, DPoP auth page missing | `diagnose-broken-login` |
56
56
  | Login redirect loop | `@tidecloak/react` ESM alias missing (AP-42), provider not wired | `diagnose-broken-login` |
57
- | DPoP login fails | `tide_dpop_auth.html` missing or dynamic route not configured (I-12, L-07) | `diagnose-broken-login` |
57
+ | DPoP login fails | `tide_dpop_auth.html` missing, or its `app/tide_dpop/[...path]/route.ts` catch-all route handler / hash-pinned CSP / `Allow-CSP-From: *` header not configured (I-12, L-07) | `diagnose-broken-login` |
58
58
  | 401 on all API calls | JWT verification not implemented, or DPoP proof missing | `diagnose-missing-roles-or-claims` |
59
59
  | 403 on API calls | Role not assigned, IGA change-set not committed, or 120s refresh delay | `diagnose-missing-roles-or-claims` |
60
60
  | Roles missing from JWT | IGA change-set not committed, token not refreshed (up to 120s) | `diagnose-missing-roles-or-claims` |
@@ -17,11 +17,11 @@ Wire the Tide SDK into the application. Own SDK installation, provider setup, co
17
17
  | `tidecloak.json` placement and import | `tide-setup` if file doesn't exist and TideCloak not bootstrapped |
18
18
  | `silent-check-sso.html` in `public/` | — |
19
19
  | Post-auth redirect handler (`auth/redirect/page.tsx`) | — |
20
- | `tide_dpop_auth.html` + `next.config.ts` rewrites + DPoP headers (I-12) | — |
20
+ | `tide_dpop_auth.html` served via a `app/tide_dpop/[...path]/route.ts` catch-all route handler + DPoP headers (I-12) | — |
21
21
  | CSP (`frame-src '*'`) in `next.config` headers | — |
22
22
  | Webpack workarounds (`strictExportPresence`, `@tidecloak/react` ESM alias) | — |
23
23
  | Retrofit into existing apps | — |
24
- | Server-side delegation setup (`@tidecloak/server`, `createTideFetch`) | — |
24
+ | ASP.NET Core (.NET 10) backend via `Tide.Asgard.AspNetCore` SDK | Follow [playbooks/protect-aspnet-core-asgard.md](../../playbooks/protect-aspnet-core-asgard.md). Out of scope for the Next.js/React/Vanilla priority do not invent OIDC wiring; route to that playbook. |
25
25
  | Route/API protection | `tide-route-and-api-protection` |
26
26
  | Roles, RBAC, encryption | `tide-rbac-and-e2ee` |
27
27
  | TideCloak bootstrap, realm, licensing | `tide-setup` |
@@ -35,6 +35,7 @@ Wire the Tide SDK into the application. Own SDK installation, provider setup, co
35
35
  - `tide-setup` detected hardening gaps (Path D)
36
36
  - User asks to "add Tide to my app" or "add login"
37
37
  - Orchestrator routed here after bootstrap is confirmed
38
+ - User asks about adding Tide auth to an **ASP.NET Core / C# / .NET** API. Route directly to [playbooks/protect-aspnet-core-asgard.md](../../playbooks/protect-aspnet-core-asgard.md) — do not attempt to retrofit Node-side guidance.
38
39
 
39
40
  ### Scenario-disambiguation gate (I-17)
40
41
 
@@ -71,8 +72,8 @@ Follow playbook `add-auth-nextjs-fresh`:
71
72
  3. Place `tidecloak.json` at correct path (`data/` for Next.js, `public/` for React/Vite)
72
73
  4. Create `public/silent-check-sso.html`
73
74
  5. Create post-auth redirect handler at `auth/redirect/page.tsx`
74
- 6. Copy `tide_dpop_auth.html` to `public/` and add `rewrites()` + DPoP-specific `headers()` in `next.config.ts` (I-12). Do NOT use a route handler.
75
- 7. Configure CSP: `frame-src '*'` in `next.config` headers (global); `script-src 'unsafe-inline'` on `/tide_dpop/:path*` only
75
+ 6. Copy `tide_dpop_auth.html` to `public/` and serve it via a catch-all route handler at `app/tide_dpop/[...path]/route.ts` (matches the shipped `@tidecloak/create-nextjs` scaffold; I-12). The handler reads the single bundled `public/tide_dpop_auth.html` and returns it for any `/tide_dpop/...` path. Do NOT use `next.config.ts` rewrites for this.
76
+ 7. On that route handler's response, set a **sha256 hash-pinned** CSP (pin the file's inline `script`/`style` via `sha256-...` hashes — NOT `script-src 'unsafe-inline'`) plus an `Allow-CSP-From: *` header (lets the ORK embed the page cross-origin). Global CSP stays `frame-src '*'` in `next.config` headers.
76
77
  8. Add webpack workarounds to `next.config.ts`: `strictExportPresence = false` + `@tidecloak/react` ESM alias
77
78
 
78
79
  ### Existing app (has other auth)
@@ -82,16 +83,6 @@ Follow playbook `add-auth-nextjs-existing`:
82
83
  2. Replace existing auth provider with `TideCloakProvider`
83
84
  3. Remove old auth (NextAuth, Clerk, etc.) after Tide is working
84
85
 
85
- ### Server-side delegation
86
-
87
- Follow playbook `setup-server-delegation`:
88
- 1. Install `@tidecloak/server`
89
- 2. Create `TideDelegation` singleton with TideCloak config
90
- 3. Wire `/api/delegation` POST endpoint with `handleDelegation()`
91
- 4. Add `requireDelegation()` middleware to admin routes
92
- 5. Wrap browser fetch with `createTideFetch` from `@tidecloak/js`
93
- 6. Optionally scope delegation roles via `requireDelegation({ roles: { ... } })`
94
-
95
86
  ### Hardening gaps (from tide-setup Path D)
96
87
 
97
88
  Fix each missing item per the table in `tide-setup`.
@@ -105,11 +96,10 @@ Fix each missing item per the table in `tide-setup`.
105
96
  - [ ] `tidecloak.json` exists with `jwk`, `vendorId`, `homeOrkUrl`
106
97
  - [ ] `public/silent-check-sso.html` exists
107
98
  - [ ] Post-auth redirect handler exists at configured `redirectUri`
108
- - [ ] `public/tide_dpop_auth.html` exists + `next.config.ts` has `rewrites()` for `/tide_dpop/:path*` and DPoP-specific `headers()`
99
+ - [ ] `public/tide_dpop_auth.html` exists + `app/tide_dpop/[...path]/route.ts` catch-all route handler serves it with a sha256 hash-pinned CSP and `Allow-CSP-From: *`
109
100
  - [ ] CSP includes `frame-src '*'`
110
101
  - [ ] Webpack config has `strictExportPresence = false` + `@tidecloak/react` ESM alias
111
102
  - [ ] Login flow completes: redirect to Tide IdP -> auth -> callback -> app
112
- - [ ] If server-side admin calls needed: `@tidecloak/server` installed, delegation endpoints wired
113
103
 
114
104
  ---
115
105
 
@@ -132,5 +122,6 @@ Next: Security Engineer | STOP if integration incomplete
132
122
  - Do not create ad hoc auth wiring. Follow the playbook.
133
123
  - Do not use `NEXT_PUBLIC_TIDECLOAK_*` env vars. Use `tidecloak.json` directly. (AP-38)
134
124
  - Do not pass `useDPoP` as a JSX prop. It goes inside the config object. (AP-42, session-002)
135
- - Do not modify `tide_dpop_auth.html`. It is integrity-checked. (I-12, L-07)
136
- - Do not apply `script-src 'unsafe-inline'` globally. Only on the DPoP auth route. (L-07)
125
+ - Do not modify `tide_dpop_auth.html`. It is integrity-checked and its inline script/style are sha256-pinned in the route handler's CSP. (I-12, L-07)
126
+ - Do not serve the DPoP auth page with `script-src 'unsafe-inline'`. Pin its inline script/style with `sha256-...` hashes in the route handler's CSP instead. (L-07)
127
+ - Do not use `next.config.ts` `rewrites()` to serve the DPoP auth page. Use the `app/tide_dpop/[...path]/route.ts` catch-all route handler (the shipped `@tidecloak/create-nextjs` approach). (I-12)
File without changes