Repository navigation
feat(contracts/module): a role's installation_owned_scopes - #839
Merged
Merged
Conversation
A role can now grant a scope only on what the installation it is held on owns, mirroring the authority's RoleV1.installation_owned_scopes (field 3, codefly-dev/authority#7): roles: - name: viewer scopes: [...] installation_owned_scopes: - {resource_kind: documents.collection, actions: [read]} Each entry is a kind and actions and never ids (CeilingScope has no field for them, so resource_ids is refused as an unknown field). It is held to every rule a role scope is, under the same rule names with "installation-owned" in the message: kind and action grammar, each kind once per list, at least one action, within the unit's own ceilings or a scope a binding spells out for invoke or lookup. A role may grant through it alone. Resolve addresses it like a literal scope, into ResolvedRole.InstallationOwnedGrants, and refuses one two audiences underwrite. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.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.
Refresh against main (2026-10-26)
Merged current main without rebasing. Refreshed head:
b13bccb1718836c18e165685df54135343cf9ac5. No PR has been merged.go vet ./...passed. The full localgo test -race ./... -timeout 10mpassed every package except two pre-existingrunners/golangworkspace tests: the requiredGOFLAGS=-mod=modis inherited by their nested Go workspace commands, where Go refuses that flag. Contract, solution, solutionhost and CI-guard race tests passed. GitHub CI runs independently; its current result is recorded on this head.What we are trying to do
Let a solution declare, in its module contract, a role scope that the authority limits to what the installation owns. codefly-dev/authority#7 adds
RoleV1.installation_owned_scopes(field 3) and resolves each such scope per installation into the same scope limited to the ids that installation owns of the kind (never the whole kind). Core's contractRolehad onlyname,scopesandbindings, so nothing in YAML could reach that field.The change
modulecontract.RolegainsInstallationOwnedScopes []CeilingScope(yaml:"installation_owned_scopes"):Validation mirrors the authority PR's semantics and reuses core's existing role rules (no new rule names). Each refusal says "installation-owned":
CeilingScopehas no id field, soresource_idsis refused as an unknown field (known-fields)scopesrole-within-request: within the unit's own ceilings or a scope a binding spells out for invoke or lookupscopesnor owned scopes grants nothingrole-grants: a role may grant through owned scopes alonerole-kind-name,role-kind-unique(per list; a kind may appear in both lists with its own actions),role-kind-has-action,action-name/action-uniquerolesResolveaddresses each installation-owned scope the same way it addresses a literal role scope, into the newResolvedRole.InstallationOwnedGrants(nil when the role declares none). It refuses one that two audiences underwrite, naming both. The addressing loop is shared, not duplicated.Fixtures: one accepted (
roles-installation-owned) and four refused (role-installation-owned-ids,-beyond-consumption,-kind-without-action,-kind-named-twice). The kit goes from 125 to 130 documents; the documented count and the pinned name list are updated.docs/module-contract.mddocuments the field.There is no proto: the module contract has none in core, so nothing is regenerated.
Reuse
CeilingScope, the existing role rules (extended through oneRole.scopeLists()helper),actionLists,grantable, and theunderwritersaddressing inresolveRoles.Classification
This is a fix at the owner: core's module contract is where a unit's roles are declared, and the CLI carries them from there.
Verification
go test ./contracts/... ./solution/... ./solutionhost/... ./internal/ciguard/...andgo veton those packages pass locally.scopeListsreturnscopesonly, and the three owned-scope refusal fixtures failed. Restoring it made them pass.go test ./...,-race, the sandbox/nix-tagged suite and coverage thresholds. CI runs those.Follow-ups
bindingsinto the authority document.gitops.Rolesreadscontract.Roles, notResolved.Roles. That gap predates this PR.🤖 Generated with Claude Code