@frontmcp/skills 1.0.4 → 1.1.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 (133) hide show
  1. package/catalog/frontmcp-authorities/SKILL.md +272 -0
  2. package/catalog/frontmcp-authorities/references/authority-profiles.md +262 -0
  3. package/catalog/frontmcp-authorities/references/claims-mapping.md +266 -0
  4. package/catalog/frontmcp-authorities/references/custom-evaluators.md +420 -0
  5. package/catalog/frontmcp-authorities/references/rbac-abac-rebac.md +391 -0
  6. package/catalog/frontmcp-channels/SKILL.md +122 -0
  7. package/catalog/frontmcp-channels/examples/channel-sources/agent-notify.md +70 -0
  8. package/catalog/frontmcp-channels/examples/channel-sources/app-errors.md +71 -0
  9. package/catalog/frontmcp-channels/examples/channel-sources/file-watcher.md +102 -0
  10. package/catalog/frontmcp-channels/examples/channel-sources/job-completion.md +79 -0
  11. package/catalog/frontmcp-channels/examples/channel-sources/replay-buffer.md +106 -0
  12. package/catalog/frontmcp-channels/examples/channel-sources/service-connector.md +136 -0
  13. package/catalog/frontmcp-channels/examples/channel-sources/webhook-github.md +85 -0
  14. package/catalog/frontmcp-channels/examples/channel-two-way/whatsapp-bridge.md +133 -0
  15. package/catalog/frontmcp-channels/references/channel-sources.md +214 -0
  16. package/catalog/frontmcp-channels/references/channel-two-way.md +195 -0
  17. package/catalog/frontmcp-config/SKILL.md +20 -18
  18. package/catalog/frontmcp-config/examples/configure-auth/multi-app-auth.md +1 -2
  19. package/catalog/frontmcp-config/examples/configure-auth/public-mode-setup.md +1 -2
  20. package/catalog/frontmcp-config/examples/configure-auth/remote-oauth-with-vault.md +1 -2
  21. package/catalog/frontmcp-config/examples/configure-auth-modes/local-self-signed-tokens.md +1 -2
  22. package/catalog/frontmcp-config/examples/configure-auth-modes/remote-enterprise-oauth.md +1 -2
  23. package/catalog/frontmcp-config/examples/configure-auth-modes/transparent-jwt-validation.md +1 -2
  24. package/catalog/frontmcp-config/examples/configure-deployment-targets/distributed-ha-config.md +121 -0
  25. package/catalog/frontmcp-config/examples/configure-deployment-targets/json-schema-ide-support.md +64 -0
  26. package/catalog/frontmcp-config/examples/configure-deployment-targets/multi-target-with-security.md +113 -0
  27. package/catalog/frontmcp-config/examples/configure-elicitation/basic-confirmation-gate.md +1 -2
  28. package/catalog/frontmcp-config/examples/configure-elicitation/distributed-elicitation-redis.md +1 -2
  29. package/catalog/frontmcp-config/examples/configure-http/entry-path-reverse-proxy.md +1 -2
  30. package/catalog/frontmcp-config/examples/configure-http/unix-socket-local.md +1 -2
  31. package/catalog/frontmcp-config/examples/configure-security-headers/csp-report-only.md +69 -0
  32. package/catalog/frontmcp-config/examples/configure-security-headers/full-production-headers.md +91 -0
  33. package/catalog/frontmcp-config/examples/configure-throttle/distributed-redis-throttle.md +1 -2
  34. package/catalog/frontmcp-config/examples/configure-throttle/per-tool-rate-limit.md +1 -2
  35. package/catalog/frontmcp-config/examples/configure-throttle/server-level-rate-limit.md +1 -2
  36. package/catalog/frontmcp-config/examples/configure-transport/custom-protocol-flags.md +1 -2
  37. package/catalog/frontmcp-config/examples/configure-transport/distributed-sessions-redis.md +1 -2
  38. package/catalog/frontmcp-config/examples/configure-transport/stateless-serverless.md +1 -2
  39. package/catalog/frontmcp-config/examples/configure-transport-protocol-presets/legacy-preset-nodejs.md +1 -2
  40. package/catalog/frontmcp-config/examples/configure-transport-protocol-presets/stateless-api-serverless.md +1 -2
  41. package/catalog/frontmcp-config/references/configure-deployment-targets.md +214 -0
  42. package/catalog/frontmcp-config/references/configure-elicitation.md +1 -2
  43. package/catalog/frontmcp-config/references/configure-security-headers.md +198 -0
  44. package/catalog/frontmcp-deployment/SKILL.md +1 -0
  45. package/catalog/frontmcp-deployment/examples/build-for-cli/cli-binary-build.md +1 -2
  46. package/catalog/frontmcp-deployment/examples/build-for-cli/unix-socket-daemon.md +1 -2
  47. package/catalog/frontmcp-deployment/examples/build-for-mcpb/mcpb-bundle-build.md +117 -0
  48. package/catalog/frontmcp-deployment/examples/build-for-sdk/connect-openai.md +1 -3
  49. package/catalog/frontmcp-deployment/examples/build-for-sdk/create-flat-config.md +1 -2
  50. package/catalog/frontmcp-deployment/examples/build-for-sdk/multi-platform-connect.md +3 -3
  51. package/catalog/frontmcp-deployment/examples/deploy-to-cloudflare/basic-worker-deploy.md +1 -2
  52. package/catalog/frontmcp-deployment/examples/deploy-to-cloudflare/worker-custom-domain.md +1 -2
  53. package/catalog/frontmcp-deployment/examples/deploy-to-cloudflare/worker-with-kv-storage.md +1 -2
  54. package/catalog/frontmcp-deployment/examples/deploy-to-lambda/lambda-handler-with-cors.md +1 -2
  55. package/catalog/frontmcp-deployment/examples/deploy-to-vercel/vercel-with-kv.md +1 -2
  56. package/catalog/frontmcp-deployment/examples/mcp-client-integration/http-remote.md +106 -0
  57. package/catalog/frontmcp-deployment/examples/mcp-client-integration/stdio-binary-with-env.md +107 -0
  58. package/catalog/frontmcp-deployment/examples/mcp-client-integration/stdio-npx.md +89 -0
  59. package/catalog/frontmcp-deployment/references/build-for-mcpb.md +209 -0
  60. package/catalog/frontmcp-deployment/references/build-for-sdk.md +1 -2
  61. package/catalog/frontmcp-deployment/references/mcp-client-integration.md +225 -0
  62. package/catalog/frontmcp-development/examples/create-agent/basic-agent-with-tools.md +3 -6
  63. package/catalog/frontmcp-development/examples/create-agent/custom-multi-pass-agent.md +1 -2
  64. package/catalog/frontmcp-development/examples/create-agent/nested-agents-with-swarm.md +2 -4
  65. package/catalog/frontmcp-development/examples/create-agent-llm-config/anthropic-config.md +1 -2
  66. package/catalog/frontmcp-development/examples/create-agent-llm-config/openai-config.md +1 -2
  67. package/catalog/frontmcp-development/examples/create-job/basic-report-job.md +1 -2
  68. package/catalog/frontmcp-development/examples/create-job/job-with-permissions.md +2 -3
  69. package/catalog/frontmcp-development/examples/create-job/job-with-retry.md +1 -2
  70. package/catalog/frontmcp-development/examples/create-plugin-hooks/tool-level-hooks-and-stage-replacement.md +2 -5
  71. package/catalog/frontmcp-development/examples/create-provider/basic-database-provider.md +4 -3
  72. package/catalog/frontmcp-development/examples/create-skill-with-tools/directory-skill-with-tools.md +2 -3
  73. package/catalog/frontmcp-development/examples/create-tool/basic-class-tool.md +1 -2
  74. package/catalog/frontmcp-development/examples/create-tool/tool-with-di-and-errors.md +2 -2
  75. package/catalog/frontmcp-development/examples/create-tool/tool-with-rate-limiting-and-progress.md +1 -2
  76. package/catalog/frontmcp-development/examples/create-tool-annotations/destructive-delete-tool.md +2 -4
  77. package/catalog/frontmcp-development/examples/create-tool-annotations/readonly-query-tool.md +1 -2
  78. package/catalog/frontmcp-development/examples/create-tool-output-schema-types/primitive-and-media-outputs.md +3 -6
  79. package/catalog/frontmcp-development/examples/create-tool-output-schema-types/zod-raw-shape-output.md +1 -2
  80. package/catalog/frontmcp-development/examples/create-tool-output-schema-types/zod-schema-advanced-output.md +2 -4
  81. package/catalog/frontmcp-development/examples/decorators-guide/agent-skill-job-workflow.md +3 -5
  82. package/catalog/frontmcp-development/examples/decorators-guide/basic-server-with-app-and-tools.md +5 -5
  83. package/catalog/frontmcp-development/examples/decorators-guide/multi-app-with-plugins-and-providers.md +4 -6
  84. package/catalog/frontmcp-development/examples/official-plugins/cache-and-feature-flags.md +3 -5
  85. package/catalog/frontmcp-development/examples/official-plugins/production-multi-plugin-setup.md +4 -5
  86. package/catalog/frontmcp-development/examples/official-plugins/remember-plugin-session-memory.md +3 -5
  87. package/catalog/frontmcp-development/references/create-agent.md +4 -7
  88. package/catalog/frontmcp-development/references/create-job.md +3 -6
  89. package/catalog/frontmcp-development/references/create-plugin-hooks.md +12 -16
  90. package/catalog/frontmcp-development/references/create-skill-with-tools.md +2 -3
  91. package/catalog/frontmcp-development/references/create-tool.md +93 -23
  92. package/catalog/frontmcp-development/references/create-workflow.md +2 -3
  93. package/catalog/frontmcp-development/references/decorators-guide.md +32 -36
  94. package/catalog/frontmcp-extensibility/examples/vectoriadb/product-catalog-search.md +4 -4
  95. package/catalog/frontmcp-extensibility/examples/vectoriadb/semantic-search-with-persistence.md +4 -4
  96. package/catalog/frontmcp-extensibility/examples/vectoriadb/tfidf-keyword-search.md +4 -3
  97. package/catalog/frontmcp-guides/SKILL.md +3 -3
  98. package/catalog/frontmcp-guides/examples/example-knowledge-base/agent-and-plugin.md +4 -5
  99. package/catalog/frontmcp-guides/examples/example-knowledge-base/vector-search-and-resources.md +4 -3
  100. package/catalog/frontmcp-guides/examples/example-task-manager/auth-and-crud-tools.md +4 -4
  101. package/catalog/frontmcp-guides/examples/example-weather-api/weather-tool-with-schemas.md +1 -2
  102. package/catalog/frontmcp-guides/references/example-knowledge-base.md +22 -17
  103. package/catalog/frontmcp-guides/references/example-task-manager.md +16 -11
  104. package/catalog/frontmcp-guides/references/example-weather-api.md +6 -3
  105. package/catalog/frontmcp-observability/examples/telemetry-api/tool-custom-spans.md +2 -3
  106. package/catalog/frontmcp-observability/examples/tracing-setup/basic-tracing.md +4 -3
  107. package/catalog/frontmcp-observability/references/telemetry-api.md +2 -3
  108. package/catalog/frontmcp-production-readiness/examples/common-checklist/observability-setup.md +1 -2
  109. package/catalog/frontmcp-production-readiness/examples/common-checklist/security-hardening.md +3 -4
  110. package/catalog/frontmcp-production-readiness/examples/distributed-ha/ha-kubernetes-3-replicas.md +229 -0
  111. package/catalog/frontmcp-production-readiness/examples/production-browser/cross-platform-crypto.md +2 -3
  112. package/catalog/frontmcp-production-readiness/examples/production-cli-binary/stdio-transport-error-handling.md +1 -2
  113. package/catalog/frontmcp-production-readiness/examples/production-cloudflare/durable-objects-state.md +2 -4
  114. package/catalog/frontmcp-production-readiness/examples/production-cloudflare/workers-runtime-constraints.md +2 -3
  115. package/catalog/frontmcp-production-readiness/examples/production-lambda/cold-start-connection-reuse.md +3 -2
  116. package/catalog/frontmcp-production-readiness/examples/production-vercel/cold-start-optimization.md +2 -2
  117. package/catalog/frontmcp-production-readiness/examples/production-vercel/stateless-serverless-design.md +3 -3
  118. package/catalog/frontmcp-production-readiness/references/distributed-ha.md +194 -0
  119. package/catalog/frontmcp-setup/SKILL.md +11 -11
  120. package/catalog/frontmcp-setup/examples/project-structure-standalone/feature-folder-organization.md +5 -3
  121. package/catalog/frontmcp-setup/examples/project-structure-standalone/minimal-standalone-layout.md +4 -2
  122. package/catalog/frontmcp-setup/examples/setup-project/basic-node-server.md +4 -2
  123. package/catalog/frontmcp-setup/examples/setup-project/vercel-serverless-server.md +4 -2
  124. package/catalog/frontmcp-setup/examples/setup-redis/hybrid-vercel-kv-with-pubsub.md +8 -7
  125. package/catalog/frontmcp-setup/references/setup-project.md +10 -9
  126. package/catalog/frontmcp-setup/references/setup-redis.md +19 -16
  127. package/catalog/frontmcp-testing/examples/test-direct-client/basic-create-test.md +1 -3
  128. package/catalog/frontmcp-testing/examples/test-direct-client/openai-claude-format-test.md +1 -3
  129. package/catalog/frontmcp-testing/examples/test-tool-unit/schema-validation-test.md +2 -2
  130. package/catalog/frontmcp-testing/references/test-direct-client.md +1 -3
  131. package/catalog/frontmcp-testing/references/test-tool-unit.md +2 -2
  132. package/catalog/skills-manifest.json +325 -3
  133. package/package.json +1 -1
@@ -0,0 +1,272 @@
1
+ ---
2
+ name: frontmcp-authorities
3
+ description: 'Use when implementing authorization, access control, RBAC, ABAC, or ReBAC for tools, resources, or prompts. Covers JWT claims mapping, authority profiles, and policy enforcement.'
4
+ tags: [authorization, rbac, abac, rebac, security, permissions, roles, access-control, authorities, jwt]
5
+ category: development
6
+ targets: [all]
7
+ bundle: [full]
8
+ priority: 9
9
+ visibility: both
10
+ license: Apache-2.0
11
+ metadata:
12
+ docs: https://docs.agentfront.dev/frontmcp/authentication/authorities
13
+ ---
14
+
15
+ # FrontMCP Authorities
16
+
17
+ Built-in RBAC/ABAC/ReBAC authorization system for FrontMCP entry types. Each flow has native `checkEntryAuthorities` and `filterByAuthorities` stages that enforce access control policies declared via the `authorities` field on entry decorators. Configured via `@FrontMcp({ authorities: { claimsMapping, profiles, scopeMapping } })` — no plugin needed. Flow stages handle enforcement, and developers can hook into them with `Will`, `Did`, and `Around` decorators. Supports named profiles for reuse, JWT claims mapping for any identity provider, inline policies with roles/permissions/attributes/relationships, and composable combinators (`allOf`, `anyOf`, `not`).
18
+
19
+ ## When to Use This Skill
20
+
21
+ ### Must Use
22
+
23
+ - Adding role-based or permission-based access control to tools, resources, or prompts
24
+ - Restricting MCP entry visibility based on the caller's JWT claims
25
+ - Enforcing tenant isolation (ABAC) or relationship checks (ReBAC) on entries
26
+
27
+ ### Recommended
28
+
29
+ - Setting up a multi-tenant server where different tenants see different tools
30
+ - Building an admin vs. user distinction across your MCP surface
31
+ - Combining multiple authorization models (e.g., RBAC + ABAC) on the same entry
32
+
33
+ ### Skip When
34
+
35
+ - You only need authentication (login/token validation) without authorization (see `frontmcp-config` / `configure-auth`)
36
+ - You are building a public server with no access restrictions (use `mode: 'public'`)
37
+ - You need OAuth scopes at the transport level, not entry-level policies (see `configure-auth-modes`)
38
+
39
+ > **Decision:** Use this skill whenever you need to control **who can access which entries** based on roles, permissions, attributes, or relationships.
40
+
41
+ ## CRITICAL: Ask About JWT Shape First
42
+
43
+ Before writing any authorities configuration, the coding agent **MUST** ask the developer:
44
+
45
+ > "What identity provider (IdP) are you using, and what does your JWT payload look like? I need to know where roles, permissions, and tenant ID are located in the claims."
46
+
47
+ **Why this matters:** Every IdP places roles and permissions in different JWT claim paths. Auth0 uses namespaced URIs (`https://myapp.com/roles`), Keycloak nests them under `realm_access.roles`, Okta uses `groups`, Cognito uses `cognito:groups`, and Frontegg uses flat `roles`/`permissions`. Writing `claimsMapping` without knowing the actual token shape will produce silent authorization failures where every user is denied.
48
+
49
+ **What to collect before proceeding:**
50
+
51
+ 1. Identity provider name (Auth0, Keycloak, Okta, Cognito, Frontegg, custom)
52
+ 2. A sample decoded JWT payload (redacted sensitive values)
53
+ 3. The claim path for roles (e.g., `realm_access.roles`)
54
+ 4. The claim path for permissions (e.g., `permissions` or `scope`)
55
+ 5. The claim path for tenant/org ID if multi-tenant (e.g., `org_id`, `tenantId`)
56
+
57
+ See `references/claims-mapping.md` for IdP-specific claim paths.
58
+
59
+ ## Prerequisites
60
+
61
+ - FrontMCP SDK installed (`@frontmcp/sdk`)
62
+ - `@frontmcp/auth` available (peer dependency of SDK, provides all authorities types)
63
+ - An authentication mode configured (see `frontmcp-config` / `configure-auth-modes`) so that `authInfo` is populated on incoming requests
64
+ - Knowledge of the developer's JWT token structure (see critical section above)
65
+
66
+ ## Steps
67
+
68
+ ### Step 1: Add the Authorities Config
69
+
70
+ Add the `authorities` field to your `@FrontMcp` decorator. No plugin import needed — authorities is a built-in framework feature.
71
+
72
+ ```typescript
73
+ import { FrontMcp } from '@frontmcp/sdk';
74
+
75
+ @FrontMcp({
76
+ name: 'my-server',
77
+ authorities: {
78
+ // configured in next steps
79
+ },
80
+ })
81
+ export class MyServer {}
82
+ ```
83
+
84
+ ### Step 2: Configure JWT Claims Mapping
85
+
86
+ Set `claimsMapping` to tell the engine where roles, permissions, and user/tenant identifiers live in your IdP's JWT. Each value is a dot-path into the decoded JWT claims object.
87
+
88
+ ```typescript
89
+ // Keycloak example — in @FrontMcp({ authorities: { ... } })
90
+ authorities: {
91
+ claimsMapping: {
92
+ roles: 'realm_access.roles',
93
+ permissions: 'resource_access.my-client.roles',
94
+ tenantId: 'org_id',
95
+ userId: 'sub',
96
+ },
97
+ }
98
+
99
+ // Auth0 example
100
+ authorities: {
101
+ claimsMapping: {
102
+ roles: 'https://myapp.com/roles',
103
+ permissions: 'permissions',
104
+ tenantId: 'org_id',
105
+ },
106
+ }
107
+ ```
108
+
109
+ If no `claimsMapping` is provided, the engine falls back to `authInfo.user.roles` and `authInfo.user.permissions`. For non-standard token shapes, use `claimsResolver` instead (see Common Patterns below).
110
+
111
+ ### Step 3: Register Named Profiles
112
+
113
+ Profiles let you define reusable authorization policies and reference them by name in decorators. Register them in the `profiles` field.
114
+
115
+ ```typescript
116
+ // In @FrontMcp({ authorities: { ... } })
117
+ authorities: {
118
+ claimsMapping: { roles: 'realm_access.roles', permissions: 'scope' },
119
+ profiles: {
120
+ admin: {
121
+ roles: { any: ['admin', 'superadmin'] },
122
+ },
123
+ authenticated: {
124
+ attributes: {
125
+ conditions: [{ path: 'user.sub', op: 'exists', value: true }],
126
+ },
127
+ },
128
+ matchTenant: {
129
+ attributes: {
130
+ conditions: [
131
+ { path: 'claims.org_id', op: 'eq', value: { fromInput: 'tenantId' } },
132
+ ],
133
+ },
134
+ },
135
+ editor: {
136
+ permissions: { any: ['content:write', 'content:publish'] },
137
+ },
138
+ },
139
+ }
140
+ ```
141
+
142
+ For type-safe profile names, augment the global interface:
143
+
144
+ ```typescript
145
+ declare global {
146
+ interface FrontMcpAuthorityProfiles {
147
+ admin: true;
148
+ authenticated: true;
149
+ matchTenant: true;
150
+ editor: true;
151
+ }
152
+ }
153
+ ```
154
+
155
+ ### Step 4: Add Authorities to Entries
156
+
157
+ Use the `authorities` field on any entry decorator (`@Tool`, `@Resource`, `@Prompt`, `@Skill`). Three forms are supported:
158
+
159
+ **String (profile reference):**
160
+
161
+ ```typescript
162
+ @Tool({ name: 'delete_user', authorities: 'admin' })
163
+ export default class DeleteUserTool extends ToolContext { ... }
164
+ ```
165
+
166
+ **String array (multiple profiles, AND semantics):**
167
+
168
+ ```typescript
169
+ @Tool({ name: 'update_tenant_settings', authorities: ['authenticated', 'matchTenant'] })
170
+ export default class UpdateTenantSettingsTool extends ToolContext { ... }
171
+ ```
172
+
173
+ **Inline policy object:**
174
+
175
+ ```typescript
176
+ @Tool({
177
+ name: 'publish_content',
178
+ authorities: {
179
+ roles: { any: ['editor', 'admin'] },
180
+ permissions: { all: ['content:publish'] },
181
+ },
182
+ })
183
+ export default class PublishContentTool extends ToolContext { ... }
184
+ ```
185
+
186
+ **Combinators for complex policies:**
187
+
188
+ ```typescript
189
+ @Tool({
190
+ name: 'sensitive_action',
191
+ authorities: {
192
+ allOf: [
193
+ { roles: { any: ['admin'] } },
194
+ { attributes: { conditions: [{ path: 'env.NODE_ENV', op: 'eq', value: 'production' }] } },
195
+ ],
196
+ },
197
+ })
198
+ export default class SensitiveActionTool extends ToolContext { ... }
199
+ ```
200
+
201
+ ## Scenario Routing Table
202
+
203
+ | Scenario | Approach | Reference |
204
+ | ------------------------------------- | ---------------------------------------------------------------- | ---------------------------------- |
205
+ | Simple role gate (admin-only tool) | `authorities: 'admin'` profile | `references/authority-profiles.md` |
206
+ | Permission-based access | `authorities: { permissions: { all: ['x'] } }` | `references/rbac-abac-rebac.md` |
207
+ | Tenant isolation | ABAC with `{ fromInput: 'tenantId' }` | `references/rbac-abac-rebac.md` |
208
+ | Resource ownership check | ReBAC with relationship resolver | `references/rbac-abac-rebac.md` |
209
+ | IP allowlist or custom logic | Custom evaluator via `custom.*` | `references/custom-evaluators.md` |
210
+ | Different IdP (Auth0/Keycloak/Okta) | Configure `claimsMapping` | `references/claims-mapping.md` |
211
+ | Admin OR (editor AND same-tenant) | `anyOf` / `allOf` combinators | `references/authority-profiles.md` |
212
+ | Custom pre/post authority logic | Hook with `Will`/`Did`/`Around` on `checkEntryAuthorities` stage | `references/custom-evaluators.md` |
213
+ | Replace built-in check with OPA/Cedar | `Around('checkEntryAuthorities')` hook | `references/custom-evaluators.md` |
214
+ | Audit authority decisions | `Did('checkEntryAuthorities')` hook for logging/metrics | `references/custom-evaluators.md` |
215
+ | Tenant allowlist in Redis/DB | Async custom evaluator with `custom.*` field | `references/custom-evaluators.md` |
216
+ | Subscription check before tool runs | Async custom evaluator or `Will('checkEntryAuthorities')` hook | `references/custom-evaluators.md` |
217
+ | Feature flag gate on a tool | Async custom evaluator checking flag service | `references/custom-evaluators.md` |
218
+
219
+ ## Common Patterns
220
+
221
+ | Pattern | Correct | Incorrect | Why |
222
+ | ----------------- | ------------------------------------------------- | -------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
223
+ | Claims mapping | `claimsMapping: { roles: 'realm_access.roles' }` | `claimsMapping: { roles: 'roles' }` (for Keycloak) | Keycloak nests roles under `realm_access.roles`; using the wrong path silently resolves to `[]` |
224
+ | Profile reference | `authorities: 'admin'` | `authorities: { profile: 'admin' }` | Profiles are referenced as plain strings, not nested objects |
225
+ | Multiple profiles | `authorities: ['authenticated', 'matchTenant']` | `authorities: 'authenticated, matchTenant'` | Use an array, not a comma-separated string |
226
+ | Inline RBAC | `{ roles: { any: ['admin'] } }` | `{ roles: ['admin'] }` | `roles` expects an object with `all` and/or `any` arrays |
227
+ | Dynamic value ref | `{ fromInput: 'tenantId' }` | `'{{ tenantId }}'` | Use `DynamicValueRef` objects, not template strings |
228
+ | OR combinator | `{ anyOf: [policy1, policy2] }` | `{ operator: 'OR', ...policy1, ...policy2 }` | Use `anyOf` for clarity; `operator` applies to top-level fields within a single policy |
229
+ | ReBAC resolver | Register `relationshipResolver` in plugin options | Inline the DB query in the policy | The resolver is a separate interface; policies only declare the relationship to check |
230
+
231
+ ## Verification Checklist
232
+
233
+ ### Configuration
234
+
235
+ - [ ] `authorities: { ... }` is set on the `@FrontMcp` decorator
236
+ - [ ] `claimsMapping` paths match the actual JWT token structure from your IdP
237
+ - [ ] All profile names referenced in `authorities: 'name'` are registered in `profiles`
238
+ - [ ] Authentication mode is configured (not `public`) so `authInfo` is populated
239
+ - [ ] If using ReBAC, `relationshipResolver` is provided in plugin options
240
+
241
+ ### Runtime
242
+
243
+ - [ ] Unauthenticated requests to protected entries receive a denial error
244
+ - [ ] Users with the correct roles/permissions can access their entries
245
+ - [ ] `tools/list` response omits entries the caller is not authorized to see
246
+ - [ ] ABAC conditions with `{ fromInput: ... }` resolve correctly from tool arguments
247
+ - [ ] Custom evaluators return proper `AuthoritiesResult` objects
248
+
249
+ ### Type Safety
250
+
251
+ - [ ] `FrontMcpAuthorityProfiles` is augmented for type-safe profile references
252
+ - [ ] `@frontmcp/auth` is imported so the `authorities` field is available on decorators
253
+
254
+ ## Troubleshooting
255
+
256
+ | Problem | Cause | Solution |
257
+ | ----------------------------------------------- | --------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
258
+ | `profile 'admin' is not registered` | Profile used in decorator but not in `authorities.profiles` config | Add the profile to the `profiles` field in `@FrontMcp({ authorities })` |
259
+ | All users denied despite correct roles | `claimsMapping.roles` path does not match the actual JWT claim path | Decode a real JWT and verify the dot-path resolves to the roles array |
260
+ | `authorities` field not recognized on decorator | `@frontmcp/auth` not imported (metadata augmentation not active) | Add `import '@frontmcp/auth'` or import any type from `@frontmcp/auth/authorities` |
261
+ | ABAC condition always fails | `{ fromInput: 'tenantId' }` but tool input field is named `tenant_id` | The `fromInput` key must exactly match the tool's input schema field name |
262
+ | ReBAC always denies | No `relationshipResolver` provided | Implement `RelationshipResolver` and pass it to plugin options |
263
+ | Custom evaluator not found | Key in `custom.*` policy does not match registered evaluator name | Ensure the evaluator is registered with the same key used in the policy |
264
+ | List endpoints show all entries | No `authorities` config in `@FrontMcp()` or hook priority conflict | Verify `authorities: { ... }` is set on `@FrontMcp()` decorator |
265
+ | `AuthorityDeniedError` has no detail | `deniedBy` field shows generic message | Check the `evaluatedPolicies` array on the error for which policy type failed |
266
+
267
+ ## Reference
268
+
269
+ - [Auth Architecture](https://docs.agentfront.dev/frontmcp/authentication/architecture) — Full three-layer model: server auth, auth providers, authorities, vault, scope challenges
270
+ - [Authorities Documentation](https://docs.agentfront.dev/frontmcp/authentication/authorities) — RBAC/ABAC/ReBAC details, profiles, combinators, hooking
271
+ - Source: `libs/auth/src/authorities/` (engine, types, evaluators), flow stages in `libs/sdk/src/tool/flows/`, `libs/sdk/src/resource/flows/`, `libs/sdk/src/prompt/flows/`, `libs/sdk/src/agent/flows/`
272
+ - Related skills: `frontmcp-config`, `frontmcp-development`, `frontmcp-extensibility`
@@ -0,0 +1,262 @@
1
+ ---
2
+ name: authority-profiles
3
+ description: Registering, composing, and using named authority profiles for reusable authorization policies
4
+ ---
5
+
6
+ # Authority Profiles
7
+
8
+ Named authority profiles let you define reusable authorization policies once and reference them by name in entry decorators. Instead of repeating inline policy objects across dozens of tools, you register profiles in `@FrontMcp({ authorities: { profiles } })` and use `authorities: 'profileName'` on entries.
9
+
10
+ ## Registering Profiles
11
+
12
+ Profiles are registered in the `profiles` field of the `authorities` config. Each key is the profile name, and the value is an `AuthoritiesPolicyMetadata` object.
13
+
14
+ ```typescript
15
+ import { FrontMcp } from '@frontmcp/sdk';
16
+
17
+ @FrontMcp({
18
+ name: 'my-server',
19
+ authorities: {
20
+ claimsMapping: { roles: 'realm_access.roles', permissions: 'scope' },
21
+ profiles: {
22
+ // RBAC: user must have at least one of these roles
23
+ admin: {
24
+ roles: { any: ['admin', 'superadmin'] },
25
+ },
26
+
27
+ // ABAC: user must be authenticated (sub exists)
28
+ authenticated: {
29
+ attributes: {
30
+ conditions: [{ path: 'user.sub', op: 'exists', value: true }],
31
+ },
32
+ },
33
+
34
+ // ABAC: tenant from JWT must match the tenantId input argument
35
+ matchTenant: {
36
+ attributes: {
37
+ conditions: [
38
+ { path: 'claims.org_id', op: 'eq', value: { fromInput: 'tenantId' } },
39
+ ],
40
+ },
41
+ },
42
+
43
+ // RBAC: permission-based
44
+ canPublish: {
45
+ permissions: { all: ['content:publish'] },
46
+ },
47
+
48
+ // Combined: role AND permission
49
+ editorWithPublish: {
50
+ roles: { any: ['editor'] },
51
+ permissions: { all: ['content:publish'] },
52
+ // operator defaults to 'AND', so both must pass
53
+ },
54
+ },
55
+ },
56
+ },
57
+ })
58
+ export class MyServer {}
59
+ ```
60
+
61
+ ## Using Profiles in Decorators
62
+
63
+ ### Single Profile (String)
64
+
65
+ The simplest form. The named profile's policy is evaluated. If the profile is not registered, the request is denied with `"profile 'name' is not registered"`.
66
+
67
+ ```typescript
68
+ @Tool({ name: 'delete_user', authorities: 'admin' })
69
+ export default class DeleteUserTool extends ToolContext {
70
+ async execute(input: { userId: string }) {
71
+ // only admin or superadmin can reach here
72
+ }
73
+ }
74
+
75
+ @Resource({
76
+ name: 'internal-metrics',
77
+ uri: 'metrics://internal',
78
+ authorities: 'admin',
79
+ })
80
+ export default class InternalMetricsResource extends ResourceContext {
81
+ async read() {
82
+ // only admin can read this resource
83
+ }
84
+ }
85
+
86
+ @Prompt({
87
+ name: 'admin-report',
88
+ authorities: 'admin',
89
+ })
90
+ export default class AdminReportPrompt extends PromptContext {
91
+ async execute() {
92
+ // only admin can use this prompt
93
+ }
94
+ }
95
+ ```
96
+
97
+ ### Multiple Profiles (String Array)
98
+
99
+ When an array of profile names is provided, they are evaluated with AND semantics -- all profiles must pass.
100
+
101
+ ```typescript
102
+ @Tool({
103
+ name: 'update_tenant_billing',
104
+ authorities: ['authenticated', 'matchTenant', 'admin'],
105
+ })
106
+ export default class UpdateTenantBillingTool extends ToolContext {
107
+ async execute(input: { tenantId: string; plan: string }) {
108
+ // user must be: authenticated AND in the matching tenant AND admin
109
+ }
110
+ }
111
+ ```
112
+
113
+ ### Inline Policy (Object)
114
+
115
+ For one-off policies that do not need to be reused, pass an `AuthoritiesPolicyMetadata` object directly.
116
+
117
+ ```typescript
118
+ @Tool({
119
+ name: 'view_own_profile',
120
+ authorities: {
121
+ attributes: {
122
+ conditions: [{ path: 'user.sub', op: 'exists', value: true }],
123
+ },
124
+ },
125
+ })
126
+ export default class ViewOwnProfileTool extends ToolContext {
127
+ async execute() {
128
+ // any authenticated user
129
+ }
130
+ }
131
+ ```
132
+
133
+ ## Composing Profiles with Combinators
134
+
135
+ For complex authorization logic, use `allOf`, `anyOf`, and `not` combinators within inline policies. Profiles and inline policies can be mixed.
136
+
137
+ ### allOf (AND)
138
+
139
+ All nested policies must pass.
140
+
141
+ ```typescript
142
+ @Tool({
143
+ name: 'deploy_to_production',
144
+ authorities: {
145
+ allOf: [
146
+ { roles: { any: ['deployer', 'admin'] } },
147
+ { attributes: { conditions: [{ path: 'env.NODE_ENV', op: 'eq', value: 'production' }] } },
148
+ { permissions: { all: ['deployments:create'] } },
149
+ ],
150
+ },
151
+ })
152
+ export default class DeployTool extends ToolContext { ... }
153
+ ```
154
+
155
+ ### anyOf (OR)
156
+
157
+ At least one nested policy must pass.
158
+
159
+ ```typescript
160
+ @Tool({
161
+ name: 'manage_content',
162
+ authorities: {
163
+ anyOf: [
164
+ { roles: { any: ['admin'] } },
165
+ {
166
+ // editor who is in the same tenant
167
+ roles: { any: ['editor'] },
168
+ attributes: {
169
+ conditions: [
170
+ { path: 'claims.org_id', op: 'eq', value: { fromInput: 'tenantId' } },
171
+ ],
172
+ },
173
+ },
174
+ ],
175
+ },
176
+ })
177
+ export default class ManageContentTool extends ToolContext { ... }
178
+ ```
179
+
180
+ ### not (Negation)
181
+
182
+ Inverts a nested policy.
183
+
184
+ ```typescript
185
+ @Tool({
186
+ name: 'public_read_only',
187
+ authorities: {
188
+ not: { roles: { any: ['blocked', 'suspended'] } },
189
+ },
190
+ })
191
+ export default class PublicReadOnlyTool extends ToolContext { ... }
192
+ ```
193
+
194
+ ### operator Field
195
+
196
+ The `operator` field controls how top-level fields within a single policy are combined. It defaults to `'AND'`.
197
+
198
+ ```typescript
199
+ // Both roles AND permissions must pass (default AND)
200
+ authorities: {
201
+ roles: { any: ['editor'] },
202
+ permissions: { all: ['content:write'] },
203
+ operator: 'AND',
204
+ }
205
+
206
+ // Either roles OR permissions must pass
207
+ authorities: {
208
+ roles: { any: ['admin'] },
209
+ permissions: { any: ['content:admin'] },
210
+ operator: 'OR',
211
+ }
212
+ ```
213
+
214
+ **Important:** `operator` applies to the fields within a single `AuthoritiesPolicyMetadata` object. For composing multiple independent policies, use `allOf`/`anyOf`.
215
+
216
+ ## Type-Safe Profile Names
217
+
218
+ Augment the global `FrontMcpAuthorityProfiles` interface to get compile-time checks on profile name strings.
219
+
220
+ ```typescript
221
+ // types/authorities.d.ts
222
+ declare global {
223
+ interface FrontMcpAuthorityProfiles {
224
+ admin: true;
225
+ authenticated: true;
226
+ matchTenant: true;
227
+ canPublish: true;
228
+ editorWithPublish: true;
229
+ }
230
+ }
231
+
232
+ export {};
233
+ ```
234
+
235
+ With this augmentation, `authorities: 'nonexistent'` will produce a TypeScript error.
236
+
237
+ ## List Filtering Behavior
238
+
239
+ The authorities system does not only enforce on execution. The built-in `filterByAuthorities` flow stages in `list-tools`, `list-resources`, and `list-prompts` flows filter out entries the caller is not authorized to see. This means:
240
+
241
+ - `tools/list` only returns tools the current user is authorized to call
242
+ - `resources/list` only returns resources the current user can read
243
+ - `prompts/list` only returns prompts the current user can get
244
+
245
+ This filtering happens automatically. No additional configuration is needed. Entries without an `authorities` field are always visible.
246
+
247
+ ## Profile Design Guidelines
248
+
249
+ | Guideline | Example |
250
+ | --- | --- |
251
+ | Name profiles after the role or intent, not the technical check | `admin` not `hasAdminRole` |
252
+ | Keep profiles single-purpose | `matchTenant` does tenant check only; combine with `['authenticated', 'matchTenant']` |
253
+ | Use `allOf`/`anyOf` for complex compositions in inline policies | Do not create profiles that duplicate combinator logic |
254
+ | Document your profiles in a central file | `types/authorities.d.ts` with augmentation and comments |
255
+ | Test profiles with both authorized and unauthorized users | See `frontmcp-testing` skill for auth testing patterns |
256
+
257
+ ## Reference
258
+
259
+ - Type: `AuthoritiesPolicyMetadata` in `libs/auth/src/authorities/authorities.types.ts`
260
+ - Registry: `AuthoritiesProfileRegistry` in `libs/auth/src/authorities/authorities.registry.ts`
261
+ - Engine: `AuthoritiesEngine` in `libs/auth/src/authorities/authorities.engine.ts`
262
+ - Related: `references/claims-mapping.md`, `references/rbac-abac-rebac.md`, `references/custom-evaluators.md`