Repository navigation
feat(gitops): derive a composed solution's authority document from its scoped api.consumes - #972
Merged
Merged
Conversation
…s scoped api.consumes The render derived an authority document only from module.contract.codefly.yaml. A composed solution declares what it consumes in solution.codefly.yaml and never in a contract, so it got no authority document, and a host that bounds a delegated person's capability by the consumer's declaration had nothing for it. A module's authority request now comes from exactly one source: its contract, or its solution manifest's scoped api.consumes, derived through core's Manifest.ConsumptionAuthority. Each scoped entry becomes an invoke unit addressed to the consumed module. The manifest is read strictly here, unlike the run path's lenient read, because an authority document is derived from it. Asking from both sources is refused. The existing rules apply unchanged: one module-identity service, a presence, and the solution's composed name as its principal. A solution that asks for scopes with no presence is refused instead of being dropped. Pins core at codefly-dev/core#784's commit until that is tagged. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This was referenced Oct 12, 2026
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…esolve its audience like a contract From review: - The render reads a solution manifest through core's LoadConsumption: the schema version and api.consumes, strictly, and nothing else. A solution whose manifest the strict loader refuses for an unrelated section (no agent block, a section core does not model), and which asks for no authority, renders as before. - A solution's consumption is a module contract (core's ConsumptionContract), resolved through the same Resolve as a published one. Its audience is the composition's, not the composed module name. - The render refuses a scoped entry for a module the workspace does not compose, and one addressed to the solution itself, by module or by a resolved audience equal to its principal. The host could never install either. - A contract plus scoped consumption is still refused by name, including a destinations-only contract, until merging the two is decided. - Fixtures use structural names. Adds the review's tests. Pins core at codefly-dev/core#784's head as a pseudo-version. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The PR-head pseudo-version named a commit the squash merge does not keep. This one is the commit core main carries, with an identical tree. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
go.mod pins core main at codefly-dev/core#784 by pseudo-version, which is the v0.19.2 release line, so the matrix declares that line in the same change (docs/supported-matrix.md, "Updating the core pin"). The line has no release yet, and the docs say so. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This was referenced Oct 12, 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.
The delivery half of codefly-dev/module-saas-starter#1083, rendered. Depends on codefly-dev/core#784. core#784 is merged; this branch pins its merge commit on core
mainas a pseudo-version (v0.19.2-0.20261012184621-7ab1214c1f03,7ab1214c), whose tree is identical to the PR head reviewed. The host half is codefly-dev/module-saas-starter#1084.What changes
pkg/gitops/authority.go: a module's authority request is a module contract either way. It is the contract the module publishes, or, for a composed solution, the one its scopedapi.consumesamounts to (core'sConsumptionContract). Both go through the sameResolveagainst the composition, so a solution's audience is whatever the composition says that module verifies, exactly as for a module.LoadConsumption: the schema version andapi.consumes, strictly, and nothing else. An invalid or unknown field in a consumption fails the render. A section the strict loader refuses for reasons unrelated to consumption, such as no agent block or a section core doesn't model, never fails the render of a solution that asks for no authority. Those solutions render exactly as before this PR; none of them needs a new tag. The run path's lenient read is unchanged.module-identityservice presents the request; a presence is required, and the no-presence path refuses either source; the principal is the composed name; the unit is<presence binding>:<entry id>:invoke.Classification: fix, at the owner. The renderer consumes core's derivation and resolution, and reimplements neither.
Tests
pkg/gitops/solution_consumption_authority_test.go, with structural fixtures intestdata/consumption/:modelresolves tomodel-gateway, from the reviewer's case;Loadrefuses still render (agentless, undeclared section), from the reviewer's B1 case;module-identityis refused;Mutation: putting back the strict
Loadfails both B1 subtests.pkg/solutionrun's test comparesConsumedAPIwithreflect.DeepEqual, because core#784 made it non-comparable.Docs updated
docs/solution-host-bindings.md: the record table and the composed-solution section.Verified, and not
go build ./...;go vet ./pkg/gitops ./pkg/solutionrun;golangci-lint run ./pkg/gitops/... ./pkg/solutionrun/...(0 issues, after fixing two gocriticrangeValCopyfindings CI reported);go test ./pkg/gitops(full package),./pkg/solutionrun,./cmd/sync/....pkg/conformance/matrix.jsoncore, decided by the coordinator).TestMatrixCoreMatchesGoModrequires it to equal the release line of go.mod's pin, and the pin is a pseudo-version onv0.19.2. No generator exists for this field. The repository's documented procedure (docs/supported-matrix.md, "Updating the core pin") edits it in the same change, and I followed it. The line has no release yet.docs/supported-matrix.mdnow states that the pin is an unreleased main commit, and that the matrix declares a line ahead of its release until corev0.19.2is cut.go test ./pkg/conformance/... ./pkg/gitops/...passes.What a solution needs to reach the host's ceiling:
audienceandscopeson the entries it calls on a person's behalf;module-identity: trueon the service that presents it;🤖 Generated with Claude Code