Repository navigation
fix(accounts): the three role vocabularies are one table; a fixture continues only a pending attempt; authority at fab9ea74 - #1302
Merged
Conversation
…eads from its sources The "Three vocabularies" section of AUTHZ_MATRIX.md was prose typed into the generator. It is now rendered from RoleVocabularies(), one table whose words come from the code that defines each vocabulary: the organisation roles from the OrgRole enum, the catalogue built-ins from the roles the permission vocabulary grants, the installation roles from the shared authority core's declaration rule. A test holds each word to its source and the rendered section to the matrix; the generated file is unchanged. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… longer holds its installation After an uninstall, the fixture kept presenting the stored plan's approval, whose receipt the core refuses for good once the installation's revision moved, so it never installed again (module-saas-starter#1275, item 7). The stored approval now continues an installation the core holds pending or active (a same-operation replay is idempotent, and the host's plan guard refuses a fresh operation id against an active record); a revoked or absent record takes the fresh review's approval. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
authority-client, authority-core, conformance, delivery and resources move from dea37afac (authority#65) to fab9ea74a58b, the merge commit of codefly-dev/authority#69: a dropped role drops its grants, a module page's roles name what it serves, review finds the installation issuance decides on, and one installation per target. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
antoinetoussaint-byte
force-pushed
the
fix/permission-audit-followups
branch
from
November 4, 2026 04:30
30bd7ee to
cb8d0b1
Compare
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.
Permission-layer follow-ups of the module-page audit (the handbook's
design/module-page-permission-audit.md), after #1282, #1284, #1285 and #1298. Three commits, each a fix at the owning place.1. The three role vocabularies are one table the matrix reads from its sources (audit finding 1)
AUTHZ_MATRIX.md's "Three vocabularies" section was prose typed into the generator (rpc_policy_matrix.go). It is now rendered frombusiness.RoleVocabularies()(pkg/business/role_vocabularies.go), one table whose words are read from the code that defines each vocabulary: the organisation roles from theOrgRoleenum, the catalogue built-ins from the rolesservicePermissionVocabularygrants, the installation roles from the shared authority core's declaration rule (domain.InstallerRole).TestRoleVocabulariesAreReadFromTheirSourcesholds every word to its source, refuses a platform role in any of the three, and holds the rendered section toRenderRPCPolicyMatrix;TestRPCPolicyMatrixIsCurrentholds the generated file to it. The generated file is byte-for-byte unchanged, sogo generate ./pkg/businessproduces no diff.2. A fixture takes a fresh approval only once the core no longer holds its installation (#1275 item 7)
fixtures/installations.goreused the stored plan's approval on every pass. After an uninstall the receipt names an operation the core refuses for good (INSTALLATION_APPROVAL_REVISION_CHANGED: the installation's revision moved), so the fixture never installed again. It now continues a stored approval while the core holds the installation pending or active (a same-operation replay is idempotent, and the host's plan guard refuses a fresh operation id against an active record, which the first cut of this change got wrong and the independent review caught); a revoked or absent record takes the fresh review's approval.attemptContinuesis pure and tested over pending/active/revoked/another's/absent.3. Authority pinned at fab9ea74 (codefly-dev/authority#69)
authority-client,authority-core,conformance,deliveryandresourcesmove from dea37afac (#65) to the merge commit of authority#69, which closes the code items of authority#60: a redelivery that drops a role drops its grants (solutions too, the review note on #1282); a module page's roles are held to what it serves; a module page's offer review on this host finds the active installation this host named, never a record the core retired under its own id; one active installation per target, and no empty-organisation lookup. No adoption is needed here beyond the pin: this host links the core.Reused, not built
The matrix generator and its currency test;
servicePermissionVocabulary, theOrgRoleenum anddomain.InstallerRoleas the sources; the core'sInstallationsread and the host'sSolutionInstallationPlanstore for the fixture. No new permission, no new role word, no new store method, no proto change.Classification
Fixes at the owning place: the vocabulary table lives beside the matrix generator that renders it; the fixture's convergence rule lives in the fixture; the core's rules live in the core and this host takes them by pin.
Tests
go test -tags pure ./pkg/business/ ./fixtures/,go vet,gofmt: green.TestAccountsPassesTheHostInterfaceConformanceSuiteon the pinned commit, Postgres-backed, with the CI-pinned CLI 0.1.221 on PATH:okin 201 s, 294 subtests passed, 0 failed. (Under the development CLI on this machine the SDK's dependency start failed on the control socket before the suite ran; that is the toolchain, not the suite, and the run with the pinned CLI is the evidence.) The same suite was also run against the authority branch before its merge through a temporary, uncommittedreplace:okin 170 s.module/toolstests,scripts/check-boundaries.sh,naming-gate.mjs check,commit-identity-gate.mjs,generated-pins-gate.mjs check: clean.Audit findings, as they stand on main after this (for the handbook's Status)
canonicalSolutionEntitlementslists everyRoleGatedinstallation; adapters end-to-end test)./s/<id>unguarded: closed by feat: shared module and solution pages with declared gateway routing #1120'sSolutionLivePagegate, restated and tested in feat(accounts): a module page's roles are accepted and gate its page like a solution's #1282 (unentitled viewer gets not-found).WhenRolesDeclared).roles:writewhere the API checksorg_admin: the two sets are equal (permissionsByRoleowner/admin/*:*vsrequireOrgAdminowner/admin/super_admin), proven by the six-combination "organization administration boundary" test and stated in the matrix table; only the word differs, and naming the API's tier needs anorg_adminaccess level in the published plugin contract, which is a contract move not made here.pkg/cataloggen/frontend_plugins.go(admin,admin/platform,admin/teams); the navigation items declareaccess:infrontend.bindings.codefly.yamland the authz-coverage gate refuses widening. Making routes take their level from a declaration is a generator change argued separately.Issues
throughSolutions(authorityissue.go), proven by the solution-principal conformance target this host runs (RunSolutionPrincipalTarget: "a viewer reads exactly what the principal owns" issuesViewer, who holds nothing atStore, throughA's binding). A person's own call to a bare module goes through the hop and is decided by organisation roles (held). The legacy team-grant path the issue was filed against is no longer how a solution grants access.TestCanonicalRetryReauthorizesOriginalConsentBeforeReplaying/different_administrator); item 7 here; item 2 (mountDeliveryRoutesinconnect_gen.go) belongs to the generator; items 3, 4, 5, 6, 8 are design or operational notes, stated in the follow-up comment.SolutionRegistrationand regenerated contracts and kits.🤖 Generated with Claude Code