Repository navigation
feat(doctor): judge a solution's permissions, and report a shell with no app - #1221
Merged
Merged
Conversation
… them The missing-permission class — a role promising authority nothing backs — is already caught by core: reading the contract through modulecontract .Load refuses "role installer grants documents:read, which is neither within the module's own scope ceilings nor a scope one of its bindings spells out". Nothing was running that over solutions, so it was found at the first refused call instead of before install. It runs here now, and a test pins the message. Adds consumed_module_without_binding as a WARNING: a module in api.consumes the contract declares no binding for. Correct when the module is reached with the viewer's own credential — wiki reaches robin, tracing and annotations that way and says so — and a bug when the solution calls it on a person's behalf. The two are indistinguishable from these documents, so it is surfaced rather than failed. A first draft also failed any binding no role named by id. It reported wiki and proposals — the two longest-running solutions — as broken, which is how the second mechanism was found: a role reaches another module's authority by declaring that module's resource KINDS, with no RoleBinding at all. That check is gone, and the source says what cannot be answered from a directory: the authoritative version needs Contract.Resolve(values) against a composition. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Conforming the fleet to one shape added the `web` shell's MANIFEST to solutions whose page had never been written — writing one would have been inventing product in a conforming change. lastlogin-go and robin-nest are in that state on main today: correctly shaped, and `codefly run service web` has nothing to start. A declared service with no source is invisible to every other reading. Each manifest is valid, every gate passes, and the first sign is a run that does nothing. So it is reported — as a warning, because the solution is not wrong and nothing breaks until someone runs the shell. wiki, proposals and robin-builder ship real shells and are silent. 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.
Follow-up to #1218. Two checks, both found by running the tool against the real fleet rather than by design.
1. Permissions — Core already catches the class; nothing was running it
The missing-permission bug — a role promising authority nothing backs — is caught by Core today. Reading the contract through
modulecontract.Loadrefuses:Nothing was running that over solutions, so it surfaced at the first refused call instead of before install.
doctor solutionruns it now, andTestARoleGrantingAnUnbackedScopeIsReportedpins the message. This is the payoff of reading every document through the reader that owns it rather than parsing YAML here: all 69 of Core's contract rules come along.Adds
consumed_module_without_bindingas a warning — a module inapi.consumesthe contract declares no binding for. On wiki it namesrobin, annotations, tracing, and wiki's own contract says why that is right:Correct there, a bug elsewhere, and the two are indistinguishable from these documents — so it is surfaced, not failed.
A check I wrote and deleted
The first draft failed any binding no role named by id. It reported wiki and proposals — the two longest-running solutions — as broken. A role also reaches another module's authority by declaring that module's resource kinds, with no
RoleBindingat all, which is exactly how both do it:The check is gone and the source records why, including what cannot be answered from a directory at all: the authoritative version needs
Contract.Resolve(values)against a composition's configuration, which is a composition-scoped check and a separate piece of work.2.
page_shell_has_no_appConforming the fleet to one shape added the
webshell's manifest to solutions whose page had never been written — writing one would have been inventing product in a conforming change. On main todaylastlogin-goandrobin-nestare in that state: correctly shaped, withcodefly run service webhaving nothing to start.A declared service with no source is invisible to every other reading. Each manifest is valid, every gate passes, and the first sign is a run that does nothing. A warning, because the solution is not wrong and nothing breaks until someone runs the shell.
Verified against main:
wiki,proposalsandrobin-buildership real shells and are silent;lastlogin-goandrobin-nestreport it.Verification
Five of nine conform on core-solutions main, up from two when this started. The four failures each have a PR in flight.
go build ./...,go test ./pkg/solutionshape ./cmdpass,golangci-lint0 issues,docs/cli-reference.mdregenerated.What I did not verify
Nothing was booted or rendered. The composition-resolved half of permissions — what a binding's audience and resource-kind slots resolve to under a real composition — is explicitly not judged, and the source says so where someone will look for it.
🤖 Generated with Claude Code