test(cms): close the acceptance list of the dynamic per-path access control - #6753
Open
delchev wants to merge 1 commit into
Open
test(cms): close the acceptance list of the dynamic per-path access control#6753delchev wants to merge 1 commit into
delchev wants to merge 1 commit into
Conversation
…ontrol The design of #6563 shipped in #6566 and #6571; what never shipped is the acceptance list the issue names - three of its five required tests. A grant that restricts a folder must not restrict the platform's own writes: content seeding, a scheduled job, a workflow delegate minting a print snapshot and a message listener storing an attachment all reach the CMS with no user and no roles behind them. That is three branches of one condition - no request, anonymous mode, the kill switch - and no test touched any of them. Each is now asserted against a service that denies everything, so a passing case can only be the escape; the anonymous case asserts the enforcing answer first so the stubbing cannot carry the assertion after it. Grants are tenant data, which is the defect the design was written to fix: the mechanism it replaced kept them in the global DIRIGIBLE_SECURITY_ACCESS while every CMS path is tenant-resolved. The isolation is now asserted in both directions across two provisioned tenants, re-reading rather than trusting the cache so it asserts an absent row and not a stale answer. And the kill switch is asserted end to end, over both the Documents API and the raw content path. CmisSessionFactory still injected AccessVerifier - the .access / scope: CMIS path this design removed - and never used it. It was engine-cms's only reference to engine-security, so the module dependency goes with it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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 #6563.
Why this issue is still open
Its design shipped in #6566 (the store, the resolver, the guard, the endpoint, the dialog in both
Documents surfaces) and #6571 (the raw content path). #6566's body named both this issue and #6562
in a single closing sentence — a form GitHub only reads for the first reference, so this one was
never linked and never closed.
What is genuinely missing is the part of the issue nobody ships by accident: the acceptance list
it names — "Tests that must exist, because these are the failure modes of what is being replaced".
Three of the five were never written, and the two that guard the escapes and the kill switch guard
exactly the behaviour that keeps a restrictive rule from taking the platform down with it.
CmsAccessControlITCmsAccessControlITCmsAccessControlIT.a_grant_in_one_tenant_does_not_govern_anotherDocumentAccessEvaluatorTestDIRIGIBLE_CMS_ROLES_ENABLED=falsedisables enforcement wholesaleDocumentAccessEvaluatorTest+CmsAccessControlIT.the_kill_switch_disables_enforcement_wholesaleThe three escapes
Content seeding, a scheduled job, a workflow delegate minting a print snapshot and a message
listener storing an attachment all write to the CMS with no user and no roles behind them.
Denying them the moment an administrator restricts one folder would break seeding rather than
secure it — so enforcement engages only for a request, never in anonymous mode, and never when the
kill switch is off. That is three branches of an
||that no test touched; each is now assertedagainst a service that denies everything, so a passing case can only be the escape. The
anonymous case additionally asserts the enforcing answer first, so the static-mock setup cannot
carry the assertion after it.
Tenant isolation
The mechanism this replaced kept grants in the global
DIRIGIBLE_SECURITY_ACCESSwhile every CMSpath is tenant-resolved, so one tenant's rule governed every tenant's like-named folder. The test
grants over HTTP in the default tenant, then asserts the same path is untouched inside a second,
provisioned tenant — and the reverse, a grant written inside that tenant that the default tenant
never sees, re-reading rather than trusting the cache so it asserts an absent row and not a stale
answer.
The last residue of the replaced mechanism
CmisSessionFactorystill injectedAccessVerifier— the.access/scope: CMISpath that thisdesign removed — and never used it; it was
engine-cms's only reference toengine-security, sothe module dependency goes with it.
Deliberately not included
The legacy importer. The issue asks for a one-shot import of
__internal/roles-access.jsonandof
scope: CMISrows on first start per tenant. #6566 left it out with the reason stated there: theonly writer of that file was
api/constraints.js, which nothing called, so the loop maintained anempty
{"constraints":[]}— the issue says so itself. Adding an importer now would be a code pathreading a file the platform no longer writes, for rows that in practice do not exist. Say the word
if an installation is known to carry rules and it is a small addition.
The
CMISoption in the.accesseditor's scope dropdown. Nothing consults that scope anymore, so the option authors a rule that silently does nothing — but removing it would leave an
existing file's scope unmatched by any option in the select, which is a worse failure than the one
it fixes. Worth its own change, not this one.
Verification
DocumentAccessEvaluatorTest5/5,CmsAccessResolutionTest11/11 green onengine-cms.CmsAccessControlIT7/7 andDocumentsApiITgreen, headless.mvn clean install -P quick-buildgreen after the dependency removal.mvn formatter:validateclean.🤖 Generated with Claude Code