carlos / platform Public

svcrole: a run role that only an exact set reaches, never Admin (PRO-6214)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Paul Campbell pushed by claude agent, operated by paul@keymail.dev 1dad1680143952ca909b7d5d8104356c36574900 parent 2f81583
2 files changed, +101 −4
  • internal/svcrole/svcrole.go +33 −4
  • internal/svcrole/svcrole_test.go +68 −0
diff --git a/internal/svcrole/svcrole.go b/internal/svcrole/svcrole.go
index 9c0820a95..a6f4da0b7 100644
--- a/internal/svcrole/svcrole.go
+++ b/internal/svcrole/svcrole.go
@@ -55,14 +55,22 @@ const (
// TestInstanceRoleMatchesTodaysAppTokenReach pins Instance to exactly the
// doors it reaches today, and this role exists so that pin can hold.
Service Role = "service"
- // Admin is the union of the five above plus ledgers, store and place.
- // It is NOT "everything harmless": store grant mints a path-scoped IAM
- // user, which is a real handover.
+ // Run is a credential that starts `carlos run` runs: one-off commands on
+ // the platform's own hosts. It is deliberately outside the union Admin
+ // stands for. Allow never adds it to a set, and nothing that lists
+ // Admin reaches it; a door admits it only by being registered through
+ // Exactly (spec 2026-10-24-service-runs-design.md § 1).
+ Run Role = "run"
+ // Admin is the union of every role except Run, plus ledgers, store and
+ // place. It is NOT "everything harmless": store grant mints a
+ // path-scoped IAM user, which is a real handover. Run is reachable only
+ // through Exactly, so an Admin principal cannot start a run by being
+ // Admin.
Admin Role = "admin"
)
// catalogue is the whole vocabulary, in the order All returns it.
-var catalogue = []Role{Publish, Deploy, Instance, Operate, Service, Admin}
+var catalogue = []Role{Publish, Deploy, Instance, Operate, Service, Run, Admin}
// All returns the catalogue. The slice is copied so a caller cannot edit the
// vocabulary by writing through it.
@@ -127,6 +135,27 @@ func Allow(roles ...Role) Set {
return s
}
+// Exactly builds the Set for a door that admits ONLY the roles listed. Unlike
+// Allow it does not add Admin: this is how a role outside Admin's union (Run)
+// is granted to a door, and how a door says "no administrator either".
+//
+// Like Allow, it panics on an unparseable role, for the same reason: a
+// dropped role would be a door silently narrowed. Called with no arguments it
+// returns the empty, closed Set.
+func Exactly(roles ...Role) Set {
+ if len(roles) == 0 {
+ return Set{}
+ }
+ s := Set{roles: make(map[Role]bool, len(roles))}
+ for _, r := range roles {
+ if _, ok := Parse(string(r)); !ok {
+ panic("svcrole: Exactly called with an unknown role " + strconv.Quote(string(r)))
+ }
+ s.roles[r] = true
+ }
+ return s
+}
+
// Permits reports whether a principal holding r may pass this door.
func (s Set) Permits(r Role) bool {
if s.roles == nil {
diff --git a/internal/svcrole/svcrole_test.go b/internal/svcrole/svcrole_test.go
index a5775141f..180566e06 100644
--- a/internal/svcrole/svcrole_test.go
+++ b/internal/svcrole/svcrole_test.go
@@ -32,6 +32,74 @@ func TestAdminPermitsEveryNonEmptySet(t *testing.T) {
t.Errorf("Allow(%v).Permits(Admin) = false; want true", s.Roles())
}
}
+ // Admin is the union of every role EXCEPT Run, so an Allow set never
+ // carries Run on Admin's account either.
+ if Allow(Publish).Permits(Run) {
+ t.Error("Allow(Publish).Permits(Run) = true; want false")
+ }
+ // An Exactly set admits only its listed roles, Admin included.
+ for _, s := range []Set{Exactly(Run), Exactly(Run, Publish), Exactly(Publish)} {
+ for _, r := range All() {
+ listed := false
+ for _, l := range s.Roles() {
+ listed = listed || l == r
+ }
+ if s.Permits(r) != listed {
+ t.Errorf("Exactly set %v: Permits(%q) = %v; want %v", s.Roles(), r, s.Permits(r), listed)
+ }
+ }
+ }
+}
+
+func TestRunIsInTheCatalogue(t *testing.T) {
+ got, ok := Parse("run")
+ if !ok || got != Run {
+ t.Fatalf(`Parse("run") = %q, %v; want %q, true`, got, ok, Run)
+ }
+ found := false
+ for _, r := range All() {
+ found = found || r == Run
+ }
+ if !found {
+ t.Errorf("All() = %v; want it to contain run", All())
+ }
+}
+
+func TestExactlyDoesNotAddAdmin(t *testing.T) {
+ s := Exactly(Run)
+ if !s.Permits(Run) {
+ t.Error("Exactly(Run).Permits(Run) = false; want true")
+ }
+ for _, r := range All() {
+ if r != Run && s.Permits(r) {
+ t.Errorf("Exactly(Run).Permits(%q) = true; want false", r)
+ }
+ }
+ if s.Permits(Admin) {
+ t.Error("Exactly(Run).Permits(Admin) = true; want false")
+ }
+ if got := s.Roles(); !reflect.DeepEqual(got, []Role{Run}) {
+ t.Errorf("Exactly(Run).Roles() = %v; want [run]", got)
+ }
+}
+
+func TestExactlyPanicsOnAnUnknownRole(t *testing.T) {
+ for _, bad := range []Role{"", "rnu", "Run"} {
+ func() {
+ defer func() {
+ if recover() == nil {
+ t.Errorf("Exactly(%q) did not panic", bad)
+ }
+ }()
+ Exactly(bad)
+ }()
+ }
+ defer func() {
+ if recover() == nil {
+ t.Error("Exactly(Run, invalid) did not panic")
+ }
+ }()
+ Exactly(Run, Role("rnu"))
}
func TestAllowIsExactForNonAdmin(t *testing.T) {