resources carry their own kind and id, and authority is checked pair by pair #54
No reviewers
Labels
No labels
Compat/Breaking
Kind/Bug
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Security
Kind/Testing
Meta/Campaign
Meta/Epic
Meta/Session
Priority/Critical
Priority/High
Priority/Low
Priority/Medium
Reviewed/Confirmed
Reviewed/Curated
Reviewed/Duplicate
Reviewed/Invalid
Reviewed/Won't Fix
Scope/Campaign
Status/Abandoned
Status/Blocked
Status/Conflicted
Status/In Progress
Status/In Review
Status/Need Grooming
Status/Need More Info
Status/Ready
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Ting/Vedanta!54
Loading…
Reference in a new issue
No description provided.
Delete branch "tango/54-resource-kinds"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The consumer half of the freeholder's ruling (2026-09-06): "just update the structure, Vedanta is still pre v0.1." The producer already emits it — nixops4-providers#47, merged.
Why
DeployedGrantcarried two flat sets,repositoriesandoperations. A grant ofA/readplusB/writeflattened to{A,B} × {read,write}— which is write on A, an authority the grant never gave. The reviewer found it by construction, and the first fix was to refuse grants the flat schema could not represent. The freeholder ruled the structure should change instead, and then improved on the queen's proposal: carry the grant's own vocabulary rather than invent a pairing shape.What lands
ResourceGrant { kind, id, operations }replaces the flat pair onLifecycleCommand,DeployedProjectionandDeployedGrant.ProjectionFile::parserefuses an unknown kind and a duplicate(kind, id)at load, rather than at use.writeonAis denied even when the totals match — the exact case a union comparison passes.Projectionand its Resource and Operation stages are paired the same way, so OpenBao authorizes on the same footing Vedanta enforces.native.rsroutes by kind.forgejo.credentialandforgejo.repositoryto the Forge issuer,kanidm.credentialto the directory, and an unknown or mixed kind is refused, never defaulted.A bug this fixed on the way past
Routing used to key off emptiness: no repositories meant "directory credential".
Invalidatecarries no resources by design — so every invalidation silently went to the directory issuer regardless of which one had minted the token. A Forge token could not be invalidated through that path at all. Kind-based routing takes anInvalidate's kind from the predecessor token's own shape instead, and the class of bug disappears with the heuristic that caused it.Nobody was looking for that. It fell out of removing an implicit rule.
Evidence
fmt and clippy
-D warningsclean. 219 lib tests, 76 in the plugin, and the livebao_devacceptance test passing un-ignored against a realbao server -dev— re-run by the queen after the push. No estate service was touched.Three things a reviewer must settle
flake-ops#426's fixture here was hand-converted, because no live producer output was available to copy at the time. It needs verifying against that session's real renderer output — the same producer-consumer round-trip both other fixtures already have.kanidm.credentialis a name the worker chose. No producer emits it today. It may want ratification, or a different name.forgejo.repositorygrants still route through queen-only account resolution. The producer documents that kind as a direct-principal Forge token with no seat; minting one would fail until account resolution branches by kind too. No such grant exists yet, so nothing is broken — but the shape now permits one the code cannot serve.DeployedGrant/LifecycleCommand/DeployedProjection carried two flat sets (repositories, operations) instead of the grant's own {kind, id, operations} triple (ruling, Larandar 2026-09-06, lar.ad/nixops4- providers#47 finding 1 take 2). A flat union across resources could not tell "A: read, B: write" apart from "A: write, B: read" — both hashed to the same two sets. ResourceGrant replaces the pair; ProjectionFile::parse refuses an unknown kind and a duplicate (kind, id) at load; Validator::resources_match compares command against projection resource by resource, never as a union. The two vendored producer fixtures are updated to the shape the producer (illustrative-swarm-alpha-drone-forge) and the deployment renderer now emit. Co-Authored-By: Teyla <[email protected]>Projection::{permitted_repositories, permitted_operations} and IssueRequest::resource_repositories authorized the same way Vedanta's own LifecycleCommand used to: two flat sets, unioned across every resource the grant named. Projection now carries permitted_resources: Vec<ResourceGrant> (Vedanta's own type) and IssueRequest names one resource_kind/resource_id pair — a lease request always asks for exactly one resource — so authorize looks up that one (kind, id) entry and holds the requested operations to its own set, never the grant's total. build_command and the mirrored DeployedGrant/Delegation wire type (crate::vedanta) carry the same shape through to the signed command. The live bao_dev acceptance test still passes un-ignored. Co-Authored-By: Teyla <[email protected]>