package cabana import ( "net/http" "slices" "testing" "git.golem15.com/golem15/summercms/modules/backpack" "git.golem15.com/golem15/summercms/modules/pact" "git.golem15.com/golem15/summercms/modules/party" ) // TestScopeLimitForMethods (phase 19.7 D-22, the scope ceiling of an admin // personal token on the MCP endpoint): ScopeLimitFor filters a token's // stored scopes by the dispatched route's method exactly as the backend // guard does for a request. A GET-only scope limits GET and leaves no scope // for POST (known 1, method-allowed 0), "*" is full for every method, and // scopes the registry no longer knows count as none (unauthenticated). func TestScopeLimitForMethods(t *testing.T) { reg, err := compileTokenCatalog([]party.Plugin{scopePlugin{ id: "acme.demo", perms: []pact.Permission{{Code: "acme.demo.access", Roles: []string{"developer"}}}, scopes: []pact.TokenScope{{ Name: "demo-read", Label: "Demo", Description: "Reads the demo.", Permissions: []string{"acme.demo.access"}, Methods: []string{"GET", "HEAD"}, }}, }}) if err != nil { t.Fatal(err) } app := backpack.New(nil) if err := app.Publish(&backendResolver{guard: &compositeGuard{reg: reg}}); err != nil { t.Fatal(err) } limit, known, ok := ScopeLimitFor(app, []string{"demo-read"}, http.MethodGet) if limit == nil || limit.Full || known != 1 || ok != 1 || len(limit.Scopes) != 1 || !slices.Equal(limit.Scopes[0], []string{"acme.demo.access"}) { t.Fatalf("GET = %+v, %d, %d", limit, known, ok) } if limit, known, ok := ScopeLimitFor(app, []string{"demo-read"}, http.MethodPost); limit != nil || known != 1 || ok != 0 { t.Fatalf("POST = %+v, %d, %d, want no scope for the method", limit, known, ok) } if limit, known, ok := ScopeLimitFor(app, []string{"*"}, http.MethodDelete); limit == nil || !limit.Full || known != 1 || ok != 1 { t.Fatalf("* DELETE = %+v, %d, %d, want full", limit, known, ok) } if limit, known, ok := ScopeLimitFor(app, []string{"gone"}, http.MethodGet); limit != nil || known != 0 || ok != 0 { t.Fatalf("unknown scope = %+v, %d, %d", limit, known, ok) } }