Repository navigation
fixture-composition: one fragment per module, merged by the run - #42
Merged
Merged
Conversation
…fixture fragments Each composed module now states what the fixture's standard roles may do at its kinds in a fragment next to its code, and a composition states only what is its own. libraries/fixture-composition/go is the document's one parser (Decode) and its merge (Merge): every grant on a (organization, role, kind), every installation and every stand-in module has exactly one source, and a second source is refused naming both. The run (codefly-dev/cli) merges the fragments into the workspace document the local authority reads; the local authority decodes it with the same library and checks it against its fixture. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ture/module-fragments
antoinetoussaint-byte
added a commit
to codefly-dev/cli
that referenced
this pull request
Oct 27, 2026
codefly-dev/authority#42 merged as bfe4876a. The pseudo-version this PR carried, e2fba9d058e1, exists only on that PR's branch: a squash-merge and branch delete would orphan it and break `go mod download` here. The library tree is byte-identical between the two. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
crisfiorini-oss
pushed a commit
to crisfiorini-oss/cli
that referenced
this pull request
Oct 27, 2026
…ered where no module is named (codefly-dev#1197) * feat(run): merge every composed module's fixture-composition fragment before the local authority boots Each module states once, next to its code, what the local authority's standard fixture roles may do at its kinds (configurations/<profile>/fixture-composition.yaml in the module); a composition's own module states only what is its own. `codefly run` now merges those fragments into the workspace's fixture-composition document before anything reads the configuration, when a composed service declares the group, and `codefly generate fixture-composition --env local` does the same on its own. The merge rules are the authority's (codefly-dev/authority libraries/fixture-composition): every grant on one (organization, role, kind), installation and stand-in module has one source, and a second is refused naming both. The written file says it is generated; a hand-written one is never overwritten (generate refuses it; a run reads it as it stands and warns that no module's fragment is applied). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(generate): fixture-composition materializes pinned modules first, as a run does Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(fixture-composition): the lint gate's four findings on the new code golangci-lint v2.14.0 (`make lint`): the generated document is written 0600 like every other file the run writes, the three shadowed `err` declarations are named for what they report, and the unused cobra parameter is `_`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(orchestration): a service declaring hop-routes with no module named gets the group empty, not nothing A host that stands a hop on some compositions and not others declares `hop-routes` always — saas's auth-gateway is the hop on a cell and stands none where the composition names no module. `generatedHopRoutes` returned no group at all for that composition, and core's reader (GetWorkspaceDependenciesConfigurations) refuses a declared group that resolves to nothing: the service failed at runtime-init, from the declaration, before any of its code ran, so it could not degrade — and it could not stop declaring the group either, since generation requires a declaring service. The group is now delivered with an empty ROUTES. Nothing decodes it: the gateway stands its hop only where `hop/MODULES` names modules, and freezeDeliveredHopAddresses skips an empty value, so DecodeRouting is never reached. The routing snapshot of an empty value equals that of no group, so no run is told its routes changed. A composition that names modules still gets its generated routes, and a workspace no service of which declares the group still gets nothing. `codefly doctor workspace` is the same seam, not a second fix: it takes generated groups from this inventory ("never from a name exemption"), so it now reports the group as supplied by the invocation instead of `configuration_missing`. The baselined refusal that asserted the old failure ("no selected modules") is replaced by a test of the new behaviour rather than kept green. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * chore: drop the go.sum entries a local golangci-lint install added Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * build: pin the fixture-composition library to its merged commit codefly-dev/authority#42 merged as bfe4876a. The pseudo-version this PR carried, e2fba9d058e1, exists only on that PR's branch: a squash-merge and branch delete would orphan it and break `go mod download` here. The library tree is byte-identical between the two. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * build: drop the orphaned fixture-composition pseudo-version from go.sum The branch-only e2fba9d058e1 is no longer required; only the merged bfe4876a is. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * build: pin the fixture-composition library past authority#43 codefly-dev/authority#43 merged as 5178f016, adding the intra-document half of the one-statement-one-source rule: Decode refuses the same (organisation, role, kind), installation or stand-in module stated twice within ONE fragment. The bump is about the diagnostic, not correctness. Without it a duplicate inside one fragment is still refused — but at the authority's boot-time Decode of the MERGED document, which names the merged file. The developer is then told the wrong file is wrong: the generated workspace document rather than the module fragment that owns the duplicate. With this pin the merge refuses it where it is written, naming that fragment. The orphaned bfe4876a pseudo-version is dropped from go.sum: `go get` leaves it behind, and it names a ref that is no longer required. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Antoine Toussaint <312536060+antoinetoussaint-byte@users.noreply.github.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.
What
One definition per module for the local fixture. Each composed module ships a fragment of the
fixture-compositiondocument next to its code (<module>/configurations/<profile>/fixture-composition.yaml): the grants of the fixture's standard roles at that module's kinds. A composition's own module ships only what is truly its own (a seeded collection's id). The run merges them (codefly-dev/cli,codefly run/codefly generate fixture-composition); this repository owns the document and the merge rules.libraries/fixture-composition/go(new): the document's one parser (Decode) and its merge (Merge). Every statement has exactly one source: a role's grant on one(organization, role, kind), one installation(organization, target), one stand-in module. A second source isErrConflict, naming both, even when the two agree (a composition narrowing a module's grant to a seeded id must not be silently widened by it; a module's grant copied into a playground is the drift this ends). The merge is order-independent (sources sorted by name; duplicate names refused).state.ApplyCompositiondecodes with the library (the olddecodeComposition/checkScope/grammar are gone); the fixture typesScope,ResourceMatch,FixtureModule,FixtureInstallationare aliases of the library's, so the fixture and the document share one spelling. Fixture-dependent checks (role defined, developer role, organisation/owner) stay in the host.services/local/README.md"What a composition adds to the fixture", root README, the authority module's own (empty) fragment,service.codefly.yamlandwork.gocomments.Reuse: the delivery is core's existing composition of every module's
configurations/<profile>/*; the CLI's generated workspace document resolves the name through core's existing precedence (the workspace's own declaration). No new delivery path, no schema change (v1 unchanged).Evidence
libraries/fixture-composition/go:go vet+go test -race— merge of two module fragments + a composition's own (order-independent, round-trips through Encode/Decode, keeps the\x1fid); conflict refused naming both sources (narrowed grant, agreeing grant, installation, stand-in, duplicate source name); every refusal names the fragment.modules/authority/services/local/code:go vet ./...,go test -race ./...all green;tools/noproxygate,tools/packagegategreen.de0deb68, which reads the merged v1 document unchanged): see the document-store and robin PRs.Fix or hack
Fix at the owner: the merge rules live with the schema's owner; the CLI only finds fragments.
Follow-ups
playground/configurations/local/fixture-composition.yamlin this repo (and core-solutions wiki/proposals) to module fragments; until then a run reads a hand-written copy as it stands and warns.🤖 Generated with Claude Code