Repository navigation
Check agent scopes on content and the calls-per-period cap - #2512
Merged
Merged
Conversation
# Conflicts: # src/FluentCMS.Core/Agents/IAgentPermissions.cs
This was referenced Oct 19, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #2507
What
The scope checks on content and the calls-per-period cap, both failing closed (MCP-05, SEC-04). They build on
IAgentPermissionsfrom #2503 and on the tool call log from #2490.IAgentPermissions,AgentPermissions):CheckContentAsync(type, operation, fields?)checks the operation on the content type and, for a write, the fields it changes.CheckDefinitionAsync(type, operation)checks a type's definition, which also needs a scope that does not narrow the type to some of its fields.ReadableTypesAsyncfilters lists.CheckToolCallAsyncapplies the calls cap.agent_scope_deniedand names the part of the scope that refused: the operation, with what the scope allows; the type, with the types in scope; or the fields, with the fields allowed.readon the type, including:ValueDiff.Compare.CheckDefinitionAsync.ToolCallRecording):CheckToolCallAsync, which counts the credential's calls in its period throughIAgentActivity.ToolCallsSinceAsync.agent.calls_per_period_exceededis appended (SEC-08), and the call is recorded with the new outcomeRefused.Refusedneeds no schema change.Why
MCP-05 gives each credential a scope of types, fields, operations and sites. SEC-04 says a call past a cap fails closed. ADR-0007 puts both in Core, so tools and forms cannot diverge. The epic's acceptance needs an agent that creates types, entries and entities within its scope and nothing outside it.
Choices worth a look:
IContentTypeDirectory, soreadon the type is part of writing. The refusal says so.product.pricecannot create, revise or propose theproductdefinition, but it can for types its field list leaves whole.Tests
Integration, each on SQLite and PostgreSQL:
categoryis refused 11 reads and writes ofproductand its entries, each withagent_scope_deniednaming the type and the types in scope.categoryworks, and the type list, the site schema document and deleted entries leaveproductout.readalone is refused create, update, delete, restore, type create and type revise, each naming the operation, and nothing is written. An agent withcreatealone sees no types and is told a write needsread. With every operation all of these succeed.product.price:categoryin full, and revises thecategorydefinitionproductdefinition and proposing it in a change setagent.calls_per_period_exceededfor the credential and is recorded asRefused.The #2503 permission tests, the change set and entry tests, and the tool call tests pass unchanged.
dotnet build -warnaserror, the full suite against apostgres:17container as well as SQLite, and markdownlint pass locally. No migration, no new package and no new project reference.Checklist
v2