@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,126 @@
1
+ # IGA Admin Governance Panel
2
+
3
+ ## What this is
4
+
5
+ An admin-facing dashboard for managing TideCloak's Identity Governance & Administration (IGA) change requests. Realm admins use this panel to review, approve, reject, and commit proposed changes to users, roles, groups, clients, policies, and realm settings. Every admin mutation in an IGA-enabled realm creates a draft change request. No change takes effect until quorum-signed and committed.
6
+
7
+ This is a governance tool, not an end-user application. It sits alongside the app that triggered the admin changes.
8
+
9
+ ---
10
+
11
+ ## When to use this scenario
12
+
13
+ Use when the app needs:
14
+ - A custom admin UI for reviewing and approving IGA change requests (instead of or alongside the built-in TideCloak Admin Console)
15
+ - Multi-admin quorum governance workflow embedded in a custom dashboard
16
+ - Visibility into policy management, Forseti contracts, and role-policy attachments
17
+ - Activity tracking (approvals, rejections, comments) on change requests
18
+
19
+ Do NOT use when:
20
+ - The built-in TideCloak Admin Console is sufficient for governance
21
+ - The app only needs end-user authentication (use standard auth playbooks)
22
+ - The app needs data encryption (use `organisation-password-manager` or `setup-forseti-e2ee`)
23
+ - The app needs cryptographic signing (use `policy-governed-signing`)
24
+
25
+ ---
26
+
27
+ ## Core Tide capabilities used
28
+
29
+ | Capability | Role in this scenario |
30
+ |-----------|----------------------|
31
+ | IGA change-set API | Core: list, sign, commit, cancel change requests |
32
+ | Multi-admin quorum | Core: approval threshold enforced cryptographically |
33
+ | Enclave signing | Core: MultiAdmin mode triggers enclave challenge popup |
34
+ | Forseti contract management | Supporting: view and manage contracts attached to role policies |
35
+ | Realm policy lifecycle | Supporting: create, approve, commit realm-level policies |
36
+ | Policy template CRUD | Supporting: manage reusable policy templates |
37
+ | SSH/role policy management | Supporting: attach contracts to roles, set thresholds |
38
+ | DPoP authentication | Required: admin API calls must be DPoP-bound |
39
+ | Server-side JWT verification | Required: governance API routes must verify admin identity |
40
+
41
+ ---
42
+
43
+ ## What must exist before first admin use
44
+
45
+ 1. TideCloak running with a licensed, IGA-enabled realm
46
+ 2. At least one admin user with `tide-realm-admin` (client role on `realm-management`)
47
+ 3. Admin user has completed Tide account linking (invite flow)
48
+ 4. Adapter JSON exported with `jwk` field (IGA must be enabled for `jwk` to be present)
49
+ 5. App deployed with DPoP-enabled provider and server-side JWT verification
50
+ 6. For quorum governance: at least two linked admin users
51
+
52
+ ---
53
+
54
+ ## Bootstrap-only steps
55
+
56
+ These happen before any admin uses the governance panel:
57
+
58
+ 1. Start TideCloak container
59
+ 2. Create realm from template (with `_tide_enabled`, `tidebrowser` flow, protocol mappers)
60
+ 3. License realm (`setUpTideRealm`)
61
+ 4. Enable IGA (`toggle-iga`)
62
+ 5. Create first admin user, assign `tide-realm-admin`, generate invite link
63
+ 6. First admin completes account linking
64
+ 7. Approve/commit initial change requests (user, role, client)
65
+ 8. Sign IDP settings (`sign-idp-settings`)
66
+ 9. Export adapter JSON
67
+ 10. Create second admin user (for quorum) and repeat invite/link/approve cycle
68
+
69
+ ---
70
+
71
+ ## Runtime admin flow
72
+
73
+ Once bootstrap is complete, the governance panel operates as follows:
74
+
75
+ 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
+ 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
86
+
87
+ ---
88
+
89
+ ## Default playbook sequence
90
+
91
+ 1. `start-tidecloak-dev`
92
+ 2. `bootstrap-realm-from-template`
93
+ 3. `initialize-admin-and-link-account`
94
+ 4. `add-auth-nextjs-fresh` (or `add-auth-nextjs-existing`)
95
+ 5. `protect-routes-nextjs`
96
+ 6. `protect-api-nextjs`
97
+ 7. `verify-jwt-server-side`
98
+ 8. `setup-iga-admin-panel`
99
+ 9. `add-rbac-nextjs`
100
+
101
+ ---
102
+
103
+ ## Key diagnostics
104
+
105
+ | Symptom | Likely cause | Fix |
106
+ |---------|-------------|-----|
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 |
111
+ | add-review returns 415 | Wrong content-type | Use `multipart/form-data`, not JSON |
112
+ | Counts don't update after commit | Stale data | Refresh counts after every mutation |
113
+ | Policy change requests don't appear | Realm policy not in pending state | Create pending realm policy first via `/tide-admin/realm-policy/pending` |
114
+ | Forseti contracts tab empty | No contracts registered | Contracts deploy via SDK signing flow, not REST API |
115
+ | 120s delay after commit before roles appear | Token refresh delay | Expected behavior; re-login or wait |
116
+
117
+ ---
118
+
119
+ ## Intentionally configurable
120
+
121
+ - **Admin role name**: `tide-realm-admin` is the default, but apps may check additional app-specific admin roles for UI-level filtering
122
+ - **Quorum threshold**: Determined by `max(1, floor(TotalAdmins * 0.7))` at the TideCloak level; not app-configurable
123
+ - **Change-set types**: The panel can filter which types to show based on app needs (e.g., only users and roles, not clients)
124
+ - **Activity features**: Comments and activity history are optional; core governance works without them
125
+ - **Policy management tabs**: Forseti contracts and realm policy management are optional features; a minimal panel needs only change-set list/approve/commit
126
+ - **Custom admin domain**: `CustomAdminUIDomain` must be set and `sign-idp-settings` called if the panel is hosted separately from TideCloak's built-in Admin Console
@@ -0,0 +1,71 @@
1
+ # Anti-Patterns — Organisation Password Manager
2
+
3
+ Scenario-specific mistakes. Each defeats a security property or causes a setup failure.
4
+
5
+ ## AP-S01: Skipping IGA before role creation
6
+
7
+ Creating self-encryption roles before enabling IGA means those role changes are not governed. Enable IGA first, then create roles so they go through the change-set approval flow.
8
+
9
+ ## AP-S02: Missing self-encryption roles in default composite
10
+
11
+ If `_tide_<tag>.selfencrypt` and `_tide_<tag>.selfdecrypt` are not included in the default-roles composite, new users cannot encrypt or decrypt until an admin manually assigns roles. This breaks the expected first-use experience.
12
+
13
+ ## AP-S03: Treating the server as a decryption endpoint
14
+
15
+ The server must never decrypt vault data. Decryption happens client-side via doken + ORK threshold + crypto policy. If the server decrypts, the entire E2EE guarantee is void. The server stores and returns ciphertext only.
16
+
17
+ ## AP-S04: Storing plaintext credentials server-side
18
+
19
+ Vault entries must be encrypted before leaving the client. If the app sends plaintext to the server "for later encryption", the server sees secrets in the clear. Encrypt client-side, transmit ciphertext.
20
+
21
+ ## AP-S05: Omitting DPoP on protected API routes
22
+
23
+ DPoP binds the access token to the device/session. Without DPoP verification on API routes, a stolen access token can be replayed from a different device. Verify DPoP proof on every protected endpoint.
24
+
25
+ ## AP-S06: Using `createRemoteJWKSet` for JWT verification
26
+
27
+ Use `createLocalJWKSet(config.jwk)` only. Remote JWKS fetch introduces a network dependency and a potential MITM vector. If `jwk` is missing from the adapter JSON, re-export with IGA enabled.
28
+
29
+ ## AP-S07: Forgetting `sign-idp-settings` after config changes
30
+
31
+ Any change to IDP settings (logo, origins, admin domain) must be followed by `sign-idp-settings`. Without it, the ORK enclave rejects the settings as unsigned. Login and encryption will fail silently.
32
+
33
+ ## AP-S08: Lazy runtime creation of encryption roles
34
+
35
+ Do not create `_tide_<tag>.selfencrypt` / `_tide_<tag>.selfdecrypt` roles at app startup or on first user request. These roles must exist and be approved via IGA change-sets before the app is available to users.
36
+
37
+ ## AP-S09: Using wrong adapter provider ID
38
+
39
+ The provider ID is `keycloak-oidc-keycloak-json`. The string `tidecloak-oidc-keycloak-json` does not exist. Using the wrong ID returns an error or a generic adapter without Tide fields.
40
+
41
+ ## AP-S10: Assuming roles appear instantly after IGA commit
42
+
43
+ After a change-set is committed, roles appear in JWT/doken on the next token refresh. This can take up to 120 seconds. Do not treat immediate post-commit token checks as authoritative.
44
+
45
+ ## AP-S11: Hiding vault UI without protecting the API
46
+
47
+ Hiding the "decrypt" button for unauthorized users is UI gating only. The API endpoint that handles decryption must independently verify JWT signature, claims, roles, and DPoP. A hidden button is not a security boundary.
48
+
49
+ ## AP-S12: Skipping change-set approval during bootstrap
50
+
51
+ After IGA is enabled, client and user mutations create draft change-sets. If these are not signed and committed, the changes remain in draft state. The realm appears configured but clients and users are not fully active.
52
+
53
+ ## AP-S13: Caching decrypted credentials on the server
54
+
55
+ Decrypted vault data must exist only in client memory. Do not cache decrypted values in server-side sessions, databases, or logs. Each decryption request must go through the ORK threshold path.
56
+
57
+ ## AP-S14: Not committing appUser PolicyApproval before user access
58
+
59
+ The `appUser` PolicyApproval must be committed with non-empty `signed_policy_data` before encryption works. If uncommitted, the crypto policy endpoint returns null and client-side encryption silently fails or errors.
60
+
61
+ ## AP-S15: Skipping orgOwner PolicyApproval
62
+
63
+ The `orgOwner` PolicyApproval with its Forseti contract (VVK verification, org-scope validation) must be committed before org admin operations work. Without it, user context signing fails and org-level policy enforcement is absent.
64
+
65
+ ## AP-S16: Hardcoding org role names without UUID
66
+
67
+ Org-scoped client roles must follow the `org:{uuid}:{suffix}` pattern. Hardcoding role names without the org UUID breaks multi-org support and causes the Forseti contract's `TryExtractOrgId` validation to fail.
68
+
69
+ ## AP-S17: Serving crypto policy without verifying commitment status
70
+
71
+ The crypto policy endpoint should only return `signed_policy_data` from committed PolicyApprovals. Serving policy data from pending or draft approvals means the policy has not been validated by the required quorum.
@@ -0,0 +1,127 @@
1
+ # Bootstrap Sequence — Organisation Password Manager
2
+
3
+ All steps must complete before users can safely use the app. Order matters.
4
+
5
+ ## Phase 1: TideCloak infrastructure
6
+
7
+ 1. **Start TideCloak container**
8
+ - Use `tidecloak-dev` (development) or `tidecloak-stg-dev` (staging with ORK env vars).
9
+ - Dev image has built-in defaults. Staging requires `SYSTEM_HOME_ORK`, `USER_HOME_ORK`, `THRESHOLD_T`, `THRESHOLD_N`.
10
+ - Wait for readiness: `curl http://localhost:8080/health/ready` returns 200.
11
+
12
+ 2. **Obtain bootstrap admin token**
13
+ - `POST /realms/master/protocol/openid-connect/token` with `KC_BOOTSTRAP_ADMIN_USERNAME` / `KC_BOOTSTRAP_ADMIN_PASSWORD`.
14
+
15
+ ## Phase 2: Realm and client setup
16
+
17
+ 3. **Import realm template**
18
+ - `POST /admin/realms` with `realm.json`.
19
+ - Template must declare: realm name, OIDC client, `_tide_enabled` role, self-encryption roles (`_tide_<tag>.selfencrypt`, `_tide_<tag>.selfdecrypt`), default-roles composite, protocol mappers.
20
+ - Template should include redirect URIs for all clients (web app, browser extension if applicable).
21
+
22
+ 4. **License the realm**
23
+ - `POST /admin/realms/{realm}/vendorResources/setUpTideRealm` with admin email.
24
+ - Content-Type: `application/x-www-form-urlencoded`. Body: `email=admin@example.com`.
25
+ - Returns licensing JSON as `text/plain`.
26
+
27
+ 5. **Enable IGA**
28
+ - `POST /admin/realms/{realm}/tide-admin/toggle-iga` with form-urlencoded `isIGAEnabled=true`.
29
+ - Must happen after licensing. Enables change-set governance for role/user mutations.
30
+
31
+ ## Phase 3: Admin user setup
32
+
33
+ 6. **Create admin user**
34
+ - `POST /admin/realms/{realm}/users` with username, email, enabled=true.
35
+
36
+ 7. **Assign `tide-realm-admin` role**
37
+ - Get role ID: `GET /admin/realms/{realm}/clients/{realm-mgmt-client-id}/roles` and find `tide-realm-admin`.
38
+ - Assign: `POST /admin/realms/{realm}/users/{userId}/role-mappings/clients/{realm-mgmt-client-id}`.
39
+
40
+ 8. **Generate account-linking invite**
41
+ - `PUT /admin/realms/{realm}/users/{userId}/execute-actions-email` with `["link-tide-account-action"]`.
42
+ - Or: `GET /admin/realms/{realm}/tide-admin/get-required-action-link?userId={userId}` for a direct URL.
43
+ - Admin must complete this link in a browser to bind their identity to the Tide Fabric.
44
+
45
+ 9. **Wait for account linking**
46
+ - Poll `GET /admin/realms/{realm}/users/{userId}` until `attributes.tideUserKey` and `attributes.vuid` are present.
47
+ - Do not proceed until both attributes exist.
48
+
49
+ ## Phase 4: Change-set approval
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`.
57
+ - Without this step, client and user changes are in draft state and not active.
58
+
59
+ ## Phase 5: IDP settings and adapter export
60
+
61
+ 11. **Configure IDP settings (optional)**
62
+ - Upload branding (logo, background) if desired.
63
+ - Set `CustomAdminUIDomain` if a separate app hosts the approval UI.
64
+
65
+ 12. **Sign IDP settings**
66
+ - `POST /admin/realms/{realm}/identity-provider/instances/tide` (PUT to update, then sign).
67
+ - Required after any IDP config change. Without it, the enclave rejects settings as unsigned.
68
+
69
+ 13. **Export adapter JSON**
70
+ - `GET /admin/realms/{realm}/vendorResources/get-installations-provider?clientId={clientUuid}&providerId=keycloak-oidc-keycloak-json`.
71
+ - Do NOT use the standard Keycloak path (`/clients/{id}/installation/providers/...`) — it returns a minimal adapter missing `jwk`, `vendorId`, `homeOrkUrl`.
72
+ - Save to app config path (e.g., `data/tidecloak.json`).
73
+ - Verify `jwk`, `vendorId`, `homeOrkUrl`, `client-origin-auth-*` fields are present.
74
+ - If `jwk` is missing: IGA was not enabled before export. Re-enable IGA and re-export.
75
+
76
+ ## Phase 6: Policy setup (app-level)
77
+
78
+ 14. **Seed Forseti contract template**
79
+ - On first org access, the app seeds a default `PolicyTemplate` with C# `IAccessPolicy` contract code.
80
+ - Contract implements `ValidateData` (VVK signature verification), `ValidateApprovers` (tide-realm-admin check), `ValidateExecutor` (org-scoped role check).
81
+ - This is app-level logic, not a TideCloak admin step.
82
+
83
+ 15. **Create and approve policy roles (BROWSER-ONLY — cannot be scripted)**
84
+ - App creates pending PolicyApprovals for `appUser` and `orgOwner` during org membership sync.
85
+ - Admin must approve and commit these PolicyApprovals so `signed_policy_data` is populated.
86
+ - Until `appUser` is committed with `signed_policy_data`, the crypto policy endpoint returns null and **shared encryption is completely non-functional**. VERIFIED (session-002).
87
+ - Until `orgOwner` is committed, org admin operations requiring VVK-verified user context fail.
88
+ - **This step requires the admin's browser** — it cannot be automated from a bootstrap script. The signing ceremony involves `IAMService._tc.createTideRequest()`, operator approval popup, admin-policy fetch (CORS-proxied), and `executeSignRequest()`.
89
+ - **The app must include an admin signing page** (or equivalent UI) for this step. Without it, shared encryption is broken by default. The init script cannot complete this phase.
90
+ - **Anti-pattern**: Silently falling back from shared encryption to self-encryption when the policy is unsigned. Self-encrypted data can never be shared. Block the shared mode entirely until the policy is signed and show a clear admin setup CTA. VERIFIED (session-002).
91
+
92
+ 16. **Create org-scoped client roles**
93
+ - App creates `org:{uuid}:{owner|admin|user|manager|accessAll}` client roles in TideCloak during org sync.
94
+ - These go through IGA change-sets and must be approved.
95
+ - `appUser` is added as composite to `org:{uuid}:user` so standard members get encryption capability.
96
+
97
+ ## Phase 7: App readiness
98
+
99
+ 17. **Place adapter JSON in app**
100
+ - Next.js: `data/tidecloak.json`
101
+ - React/Vite or Vanilla: `public/tidecloak.json`
102
+
103
+ 18. **Configure CSP**
104
+ - Add `frame-src '*'` to Content-Security-Policy. Required for ORK enclave iframe.
105
+
106
+ 19. **Start app server**
107
+ - App must be able to reach TideCloak at the URL in `auth-server-url`.
108
+ - App must serve the redirect handler at the configured `redirectUri` path.
109
+ - App must serve `silent-check-sso.html` in `public/` for session refresh.
110
+
111
+ ## Pre-user checklist
112
+
113
+ Before any user accesses the app, verify:
114
+
115
+ - [ ] TideCloak healthy (`/health/ready` returns 200)
116
+ - [ ] Realm licensed and IGA enabled
117
+ - [ ] At least one admin with linked Tide account
118
+ - [ ] All pending change-sets approved and committed
119
+ - [ ] Self-encryption roles exist and are in default-roles composite
120
+ - [ ] `appUser` PolicyApproval committed with non-empty `signed_policy_data`
121
+ - [ ] `orgOwner` PolicyApproval committed with non-empty `signed_policy_data`
122
+ - [ ] Forseti contract template seeded
123
+ - [ ] Adapter JSON exported with `jwk`, `vendorId`, `homeOrkUrl`
124
+ - [ ] `sign-idp-settings` called
125
+ - [ ] App server running and reachable
126
+ - [ ] Redirect handler present at `redirectUri` path
127
+ - [ ] CSP includes `frame-src '*'`
@@ -0,0 +1,86 @@
1
+ # Organisation Password Manager — Scenario Manifest
2
+
3
+ id: organisation-password-manager
4
+ title: Organisation Password Manager
5
+ category: credential-vault
6
+ description: Shared credential vault with self-encryption plus policy-governed encryption via Forseti contracts
7
+
8
+ frameworks:
9
+ - nextjs
10
+ - react-vite
11
+ - rust
12
+ - vanilla
13
+
14
+ core_patterns:
15
+ - self-encryption
16
+ - self-decryption
17
+ - policy-governed-encryption
18
+ - forseti
19
+ - doken
20
+ - dpop
21
+ - iga
22
+ - oidc
23
+ - vvk
24
+ - credential-vault
25
+ - password-manager
26
+ - e2ee
27
+ - org-scoped-roles
28
+
29
+ match_keywords:
30
+ - password manager
31
+ - credential vault
32
+ - shared secrets
33
+ - team vault
34
+ - org vault
35
+ - shared password store
36
+ - secret store
37
+ - vaultwarden
38
+ - bitwarden
39
+ - encrypted sharing
40
+ - share encrypted data
41
+ - cross-user decryption
42
+ - shared encryption
43
+ - encrypt and share
44
+ - chosen recipients
45
+ - selective sharing
46
+ - encrypt for others
47
+ - sharing of encrypted
48
+ - sharing encrypted
49
+ - people can decrypt
50
+ - others can decrypt
51
+ - secure data sharing
52
+ - data sharing
53
+ - share selectively
54
+
55
+ bootstrap_required: true
56
+ requires_admin_preapproval: true
57
+ requires_iga: true
58
+ requires_e2ee: true
59
+ encryption_mode: self-encryption + policy-governed
60
+
61
+ default_roles:
62
+ - _tide_enabled
63
+ - _tide_<tag>.selfencrypt
64
+ - _tide_<tag>.selfdecrypt
65
+
66
+ policy_roles:
67
+ - appUser
68
+ - orgOwner
69
+
70
+ org_role_pattern: "org:{uuid}:{owner|admin|user|manager}"
71
+
72
+ default_playbooks:
73
+ - start-tidecloak-dev
74
+ - bootstrap-realm-from-template
75
+ - initialize-admin-and-link-account
76
+ - configure-e2ee-roles-and-policies
77
+ - add-auth-nextjs-fresh
78
+ - protect-routes-nextjs
79
+ - protect-api-nextjs
80
+ - verify-jwt-server-side
81
+ - add-rbac-nextjs
82
+
83
+ discriminating_question: Do multiple users need to encrypt/decrypt the same data (shared credentials, team secrets)? If only the encrypting user decrypts, use self-encryption instead of this scenario.
84
+ valid_only_when: Cross-user decryptability is required. At least two users share encrypted data.
85
+
86
+ notes: Two encryption layers. Self-encryption for per-user vault data. Policy-governed encryption via appUser/orgOwner Forseti contracts for org-scoped access control. Replace <tag> with app name.
@@ -0,0 +1,59 @@
1
+ # Role-Policy Matrix — Organisation Password Manager
2
+
3
+ ## Tide bootstrap roles
4
+
5
+ | Role | Purpose | Attached policy | Created by | Approved by | Required before first use | Default / optional | Notes |
6
+ |------|---------|----------------|------------|-------------|--------------------------|-------------------|-------|
7
+ | `_tide_enabled` | Enables Tide operations for user | None (gate role) | Realm template | N/A (declared in realm.json) | Yes | Default | Must be in realm.json. Not auto-created. |
8
+ | `_tide_<tag>.selfencrypt` | Allows user to encrypt data with own key | Voucher gate: selfencrypt | Admin via IGA | Tide realm admin(s) | Yes | Default | Include in default-roles composite so all users get it. |
9
+ | `_tide_<tag>.selfdecrypt` | Allows user to decrypt own encrypted data | Voucher gate: selfdecrypt | Admin via IGA | Tide realm admin(s) | Yes | Default | Include in default-roles composite so all users get it. |
10
+ | `tide-realm-admin` | Full realm administration | N/A | Bootstrap script | N/A (first admin) | Yes (at least one) | Required | Client role on `realm-management`, not a realm role. |
11
+
12
+ ## Policy-governed roles (Forseti contract-backed)
13
+
14
+ | Role | Purpose | Attached policy | Created by | Approved by | Required before first use | Default / optional | Notes |
15
+ |------|---------|----------------|------------|-------------|--------------------------|-------------------|-------|
16
+ | `appUser` | Crypto policy for encrypt/decrypt operations | Forseti contract; `signed_policy_data` served as active crypto policy | App on first org sync | Tide realm admin(s) via IGA | Yes (for encryption) | Default | PolicyApproval must be committed with non-empty `signed_policy_data` before encryption works. |
17
+ | `orgOwner` | User-context signing with VVK verification | Forseti contract with VVK public key validation | App on first org sync | Tide realm admin(s) via IGA | Yes (for org admin ops) | Default | Contract validates `org:{uuid}:{role}` pattern and verifies user context signature against VVK. |
18
+
19
+ ## Org-scoped client roles (per organisation)
20
+
21
+ | Role pattern | Purpose | Attached policy | Created by | Approved by | Required before first use | Default / optional | Notes |
22
+ |-------------|---------|----------------|------------|-------------|--------------------------|-------------------|-------|
23
+ | `org:{uuid}:owner` | Org owner (highest privilege) | Inherits `orgOwner` composites + `accessAll` | App on org creation | IGA change-set | No (created per org) | Per-org | Maps to Bitwarden Owner membership type. |
24
+ | `org:{uuid}:admin` | Org administrator | None beyond membership | App on member invite | IGA change-set | No | Per-org | Maps to Bitwarden Admin membership type. |
25
+ | `org:{uuid}:user` | Org member (standard) | Inherits `appUser` composite | App on member invite | IGA change-set | No | Per-org | Maps to Bitwarden User membership type. Gets encryption capability via `appUser`. |
26
+ | `org:{uuid}:manager` | Org manager | None beyond membership | App on member invite | IGA change-set | No | Per-org | Maps to Bitwarden Manager membership type. |
27
+ | `org:{uuid}:accessAll` | Full collection access within org | None | App on org creation | IGA change-set | No | Per-org | Composite of owner role. Grants access to all collections. |
28
+
29
+ ## Key rules
30
+
31
+ 1. `_tide_enabled` must be declared in `realm.json`. It is not auto-created by `setUpTideRealm`.
32
+ 2. Self-encryption roles must exist and be assigned before any user attempts to encrypt or decrypt.
33
+ 3. `appUser` PolicyApproval must be committed with `signed_policy_data` before the crypto policy endpoint returns usable data.
34
+ 4. `orgOwner` PolicyApproval must be committed before org admin operations that require VVK-verified user context.
35
+ 5. Role assignment changes go through IGA change-sets when IGA is enabled. Roles appear in JWT after next token refresh (up to 120s delay).
36
+ 6. `tide-realm-admin` is a client role on `realm-management`, not a realm role.
37
+ 7. All role changes after IGA is enabled require change-set approval (draft -> sign -> commit).
38
+ 8. Org-scoped roles use the pattern `org:{uuid}:{suffix}`. The Forseti contract validates this pattern and extracts the org UUID for scope enforcement.
39
+
40
+ ## Forseti contract structure (default template)
41
+
42
+ The default seeded contract implements `IAccessPolicy` with three validators:
43
+
44
+ | Validator | What it checks |
45
+ |-----------|---------------|
46
+ | `ValidateData` | Extracts org UUID from executor role. Validates user context array from draft against previous signed user context. Verifies VVK public key signature. |
47
+ | `ValidateApprovers` | Checks that approvers hold `tide-realm-admin` role. |
48
+ | `ValidateExecutor` | Checks that executor holds an `org:{uuid}:{role}` role matching the allowed org. |
49
+
50
+ ## Encryption role naming convention
51
+
52
+ | Pattern | Mode | Use case |
53
+ |---------|------|----------|
54
+ | `_tide_<tag>.selfencrypt` | Self-encryption | User encrypts with own key. No sharing. |
55
+ | `_tide_<tag>.selfdecrypt` | Self-decryption | User decrypts own data via ORK threshold. |
56
+ | `appUser` | Policy-governed | Crypto policy for encrypt/decrypt. `signed_policy_data` served to clients. |
57
+ | `orgOwner` | Policy-governed | User-context signing with VVK verification for org admin operations. |
58
+
59
+ This scenario uses both self-encryption and policy-governed encryption.
@@ -0,0 +1,107 @@
1
+ # Organisation Password Manager
2
+
3
+ ## What this is
4
+
5
+ A shared credential vault where organisation members store, encrypt, and retrieve passwords and secrets. Uses two Tide encryption layers:
6
+
7
+ 1. **Self-encryption** — each user's vault data is encrypted with their own Tide-managed key via `_tide_<tag>.selfencrypt` / `_tide_<tag>.selfdecrypt` roles.
8
+ 2. **Policy-governed encryption** — org-scoped `appUser` and `orgOwner` roles carry Forseti contracts with `signed_policy_data`. The `appUser` crypto policy governs who can perform encryption/decryption operations. The `orgOwner` contract enforces user-context signing with VVK verification.
9
+
10
+ No server, admin, or single ORK can read stored credentials.
11
+
12
+ ## When to use this scenario
13
+
14
+ Use when the user describes:
15
+ - a team or organisation password manager
16
+ - a shared credential vault or secret store
17
+ - a Vaultwarden/Bitwarden-style self-hosted vault with Tide
18
+ - any app where multiple users each store encrypted credentials with org-scoped access control
19
+
20
+ Do NOT use when:
21
+ - the user describes a single-user private vault with no org structure
22
+ - the user needs only basic auth without encryption
23
+
24
+ ## Core Tide capabilities used
25
+
26
+ 1. **TideCloak OIDC authentication** — zero-knowledge login, no master password stored
27
+ 2. **DPoP token binding** — access tokens bound to device/session
28
+ 3. **Self-encryption / self-decryption** — per-user E2EE via `_tide_<tag>.selfencrypt` / `_tide_<tag>.selfdecrypt` roles
29
+ 4. **Policy-governed encryption** — `appUser` role with Forseti contract and `signed_policy_data` as the active crypto policy for encrypt/decrypt operations
30
+ 5. **User-context signing** — `orgOwner` role with Forseti contract that validates user context against VVK public key
31
+ 6. **Doken** — delegation token for ORK-mediated crypto operations
32
+ 7. **IGA (Identity Governance)** — role/policy changes require multi-admin approval via change-sets
33
+ 8. **Forseti contracts** — C# smart contracts enforce role-assignment approval thresholds, org-scoped access, and VVK signature verification
34
+ 9. **Org-scoped client roles** — `org:{uuid}:{owner|admin|user|manager}` pattern for per-org membership mapping
35
+
36
+ ## What must exist before first user access
37
+
38
+ 1. TideCloak running with a realm for the app
39
+ 2. Realm licensed (`setUpTideRealm`) and IGA enabled (`toggle-iga`)
40
+ 3. Admin user created, Tide account linked, `tide-realm-admin` role assigned
41
+ 4. Initial client and user change-sets approved and committed
42
+ 5. Self-encryption roles (`_tide_<tag>.selfencrypt`, `_tide_<tag>.selfdecrypt`) created and included in the default role composite
43
+ 6. `appUser` and `orgOwner` PolicyApprovals created, approved, and committed with `signed_policy_data`
44
+ 7. Forseti contract template seeded (default `IAccessPolicy` with org-scoped validation and VVK verification)
45
+ 8. `sign-idp-settings` called after any IDP config changes
46
+ 9. Adapter JSON exported to app (`tidecloak.json`) with `jwk`, `vendorId`, `homeOrkUrl`, `client-origin-auth-*`
47
+ 10. App server running and able to reach TideCloak
48
+
49
+ ## Admin/bootstrap-only steps
50
+
51
+ - Start TideCloak container
52
+ - Import realm template
53
+ - Call `setUpTideRealm` and `toggle-iga`
54
+ - Create admin user and generate account-linking invite
55
+ - Approve pending change-sets (client, user)
56
+ - Create self-encryption roles if not in realm template
57
+ - Seed default Forseti contract template
58
+ - Upload branding / configure IDP settings + `sign-idp-settings`
59
+ - Export adapter JSON
60
+
61
+ ## Runtime user flow
62
+
63
+ 1. User visits app (web vault or browser extension)
64
+ 2. App redirects to TideCloak for OIDC login
65
+ 3. TideCloak authenticates via threshold PRISM (zero-knowledge)
66
+ 4. TideCloak returns access token + refresh token + doken + id token
67
+ 5. App server validates JWT (signature + claims + DPoP)
68
+ 6. On first org access, app syncs membership to TideCloak: creates org-scoped client roles (`org:{uuid}:{role}`), creates pending PolicyApprovals for `orgOwner` and `appUser`
69
+ 7. User creates vault entries: client fetches crypto policy (`signed_policy_data` from committed `appUser` approval), encrypts fields client-side, sends ciphertext to server
70
+ 8. User retrieves entries: client requests decryption via doken + ORK threshold + crypto policy
71
+ 9. Plaintext exists only in client memory, never stored server-side
72
+
73
+ ## Default playbook sequence
74
+
75
+ 1. `start-tidecloak-dev`
76
+ 2. `bootstrap-realm-from-template`
77
+ 3. `initialize-admin-and-link-account`
78
+ 4. `configure-e2ee-roles-and-policies` (self-encryption mode + policy-governed mode)
79
+ 5. `add-auth-nextjs-fresh` (or framework-appropriate equivalent)
80
+ 6. `protect-routes-nextjs`
81
+ 7. `protect-api-nextjs`
82
+ 8. `verify-jwt-server-side`
83
+ 9. `add-rbac-nextjs`
84
+
85
+ ## Key diagnostics
86
+
87
+ | Symptom | Likely cause |
88
+ |---------|-------------|
89
+ | Login hangs or blank screen | CSP missing `frame-src '*'`, or redirect handler missing |
90
+ | Encryption fails silently | Self-encryption roles not assigned, or doken expired, or `appUser` crypto policy not committed |
91
+ | `get_crypto_policy` returns null | `appUser` PolicyApproval not committed or has empty `signed_policy_data` |
92
+ | Roles missing from JWT | IGA change-set not committed, or token not refreshed (up to 120s delay) |
93
+ | Adapter JSON missing `jwk` | IGA not enabled on realm before export |
94
+ | `client-origin-auth-*` mismatch | `sign-idp-settings` not called after origin change |
95
+ | Decryption returns error | User lacks `_tide_<tag>.selfdecrypt` role, or ORK threshold not met, or crypto policy missing |
96
+ | Org membership sync fails | Client roles not created in TideCloak, or `org:{uuid}:{role}` pattern mismatch |
97
+ | VVK verification fails in contract | VVK public key not available, or user context signature invalid |
98
+
99
+ ## Intentionally configurable
100
+
101
+ - **Encryption tag name**: `<tag>` in `_tide_<tag>.selfencrypt` is app-specific (e.g., `vaultwarden`, `vault`)
102
+ - **Org-scoped roles**: Apps define org role patterns (e.g., `org:{uuid}:owner`, `org:{uuid}:admin`)
103
+ - **Forseti contract logic**: Default template validates org scope and VVK signatures; apps can customize validation rules
104
+ - **Approval thresholds**: IGA admin quorum and Forseti contract thresholds are deployment-configurable
105
+ - **Browser extension support**: Optional. Requires adding extension redirect URIs to OIDC client config
106
+ - **Database backend**: App-specific choice (SQLite, PostgreSQL, MySQL)
107
+ - **Per-field vs whole-record encryption**: App decides granularity; Tide encrypts whatever the client sends
@@ -0,0 +1,67 @@
1
+ # Anti-Patterns — Policy-Governed Signing
2
+
3
+ Scenario-specific mistakes. Each defeats a security property or causes a setup failure.
4
+
5
+ ## AP-PS01: Skipping IGA before role creation
6
+
7
+ Creating signing roles before enabling IGA means those role changes are not governed. Enable IGA first, then create roles so they go through the change-set approval flow.
8
+
9
+ ## AP-PS02: Using signing without a committed policy
10
+
11
+ The signing role must have a committed PolicyApproval with non-empty `signed_policy_data` before ORKs will accept signing requests. If the policy is not committed, `executeSignRequest` will fail. Do not assume signing works immediately after role creation.
12
+
13
+ ## AP-PS03: Hardcoding the signing key
14
+
15
+ The entire point of this pattern is that no single entity holds the signing key. Do not generate, store, or manage signing keys in the app. The key exists only as threshold shares across independent ORKs.
16
+
17
+ ## AP-PS04: Omitting DPoP on protected API routes
18
+
19
+ DPoP binds the access token to the device/session. Without DPoP verification on API routes, a stolen access token can be replayed from a different device. Verify DPoP proof on every protected endpoint.
20
+
21
+ ## AP-PS05: Using `createRemoteJWKSet` for JWT verification
22
+
23
+ Use `createLocalJWKSet(config.jwk)` only. Remote JWKS fetch introduces a network dependency and a potential MITM vector. If `jwk` is missing from the adapter JSON, re-export with IGA enabled.
24
+
25
+ ## AP-PS06: Forgetting `sign-idp-settings` after config changes
26
+
27
+ Any change to IDP settings (logo, origins, admin domain) must be followed by `sign-idp-settings`. Without it, the ORK enclave rejects the settings as unsigned. Login and signing will fail silently.
28
+
29
+ ## AP-PS07: Weak or missing `ValidateData` in the Forseti contract
30
+
31
+ The `ValidateData` method is the primary safety gate. If it accepts arbitrary data, the ORKs will sign anything the executor submits. Validate the data structure, size, format, and semantics. For SSH: parse the SSHv2 publickey challenge. For documents: check hash format and size. Never return `PolicyDecision.Allow()` unconditionally.
32
+
33
+ ## AP-PS08: Skipping `ValidateExecutor` in the Forseti contract
34
+
35
+ The `ValidateExecutor` method must check that the executor's doken contains the required signing role and is not expired. Without it, any authenticated user can request signatures for any role.
36
+
37
+ ## AP-PS09: Using wrong adapter provider ID
38
+
39
+ The provider ID is `keycloak-oidc-keycloak-json`. The string `tidecloak-oidc-keycloak-json` does not exist. Using the wrong ID returns an error or a generic adapter without Tide fields.
40
+
41
+ ## AP-PS10: Assuming roles appear instantly after IGA commit
42
+
43
+ After a change-set is committed, roles appear in JWT/doken on the next token refresh. This can take up to 120 seconds. Do not treat immediate post-commit token checks as authoritative.
44
+
45
+ ## AP-PS11: Hiding signing UI without protecting the API
46
+
47
+ Hiding the "Sign" button for unauthorized users is UI gating only. The API endpoint that handles signing must independently verify JWT signature, claims, roles, and DPoP. A hidden button is not a security boundary.
48
+
49
+ ## AP-PS12: Skipping change-set approval during bootstrap
50
+
51
+ After IGA is enabled, client and user mutations create draft change-sets. If these are not signed and committed, the changes remain in draft state. The realm appears configured but clients and users are not fully active.
52
+
53
+ ## AP-PS13: Creating policies with wrong model ID
54
+
55
+ The model ID in the policy must match the request pattern used by the client. `BasicCustom<SSH>:BasicCustom<1>` is for `BasicCustomRequest`. `DynamicCustom<SSH>:DynamicCustom<1>` is for `DynamicCustomRequest`. A mismatch causes ORK rejection.
56
+
57
+ ## AP-PS14: Omitting contract transport from PolicySignRequest
58
+
59
+ The PolicySignRequest draft must include both the serialized policy bytes and the contract transport (source code + entry type). Without the contract transport, ORKs cannot compile and execute the Forseti contract. The contract ID (SHA-512 of source) must match.
60
+
61
+ ## AP-PS15: Using blocked namespaces in Forseti contracts
62
+
63
+ The ORK Forseti sandbox blocks: `System.IO`, `System.Net`, `System.Diagnostics`, `System.Threading`, `System.Reflection`, `System.Runtime.InteropServices`, `System.Reflection.Emit`, `Microsoft.Win32`. Hard-blocked: `System.Console`, `System.Runtime.CompilerServices.Unsafe`. Using any blocked namespace causes `BadPolicy.ForbiddenCall`.
64
+
65
+ ## AP-PS16: Not setting custom expiry on PolicySignRequest
66
+
67
+ `PolicySignRequest.setCustomExpiry()` controls how long the policy remains valid. If not set or set too short, policies expire and signing stops working. The keylessh exemplar uses 604800 seconds (7 days). Choose an appropriate TTL for your use case.