Skip to content

Permission/resource API rough edges: DeleteProjectResource 500, CreatePermission silent no-op and 500 on short names #1693

Description

@whoAbhishekSah

Summary

While testing permission deletion (PR #1685) end-to-end against a local server (ConnectRPC + SpiceDB), three pre-existing rough edges surfaced in the permission/resource APIs. None are caused by #1685 — they live in CreatePermission and DeleteProjectResource — but they make working with custom permission namespaces awkward and can return a 500 where a clean client error is expected. Filing together for triage.


1. DeleteProjectResource returns 500 for a custom-namespace resource that has no delete verb

A permission namespace created via CreatePermission (e.g. compute/machine) only gets the verbs you define. DeleteProjectResource runs an authorization precheck for the delete permission on the resource's type, so if the namespace never defined a delete verb, the check fails inside SpiceDB and the call 500s.

Repro

  1. CreatePermission with key lab.sample.scan (creates namespace lab/sample with only a scan verb).
  2. CreateProjectResource with namespace lab/sample under some project.
  3. DeleteProjectResource for that resource.

Actual: 500 internal. Server log:

IsAuthorized.CheckAuthz operation failed ...
error: rpc error: code = FailedPrecondition desc = relation/permission `delete` not found under definition `lab/sample`
method: /raystack.frontier.v1beta1.FrontierService/DeleteProjectResource

Expected: the resource can be deleted (or a clear client error), regardless of which verbs its namespace happens to define.

Why it matters: this collides with the new permission-delete guard, which refuses to delete the last permission of a namespace while relationships of that type still exist and advises "remove the resources first." For a namespace without a delete verb, you can't remove the resource through the API at all — the only way out is direct DB/SpiceDB cleanup.


2. CreatePermission silently no-ops in the core app/* namespaces

Creating a permission whose namespace is one of the built-in app namespaces (e.g. key app.organization.somenewverb) returns 200 with an empty body and creates nothing — those namespaces are filtered out server-side.

Repro

  • CreatePermission with key app.organization.zzcustom.

Actual: 200 {}, no permission created, no error.

Expected: either create it, or reject with a clear error explaining that core app namespaces are reserved. A silent success that does nothing is confusing.


3. CreatePermission returns 500 (not 400) when the service or verb is shorter than 3 characters

The service and verb segments of a permission key become SpiceDB relation/definition identifiers, which must match ^[a-z][a-z0-9_]{1,62}[a-z0-9]$ (minimum 3 characters). A shorter segment passes API validation but fails at schema-compile time, returning a 500.

Repro (each 500s)

  • key foo.bar.go (verb go, 2 chars)
  • key zoo.animal.it (verb it, 2 chars)
  • key r2.widget.read (service r2, 2 chars)

For comparison, abc.widget.read and zoo.animal.use (all segments ≥3 chars) succeed.

Actual: 500 internal. Server log:

CreatePermission.AppendSchema operation failed ...
error: ... compile: failed to compile authz schema: ... invalid Relation.Name:
value does not match regex pattern "^[a-z][a-z0-9_]{1,62}[a-z0-9]$"

Expected: validate the key segments at the API and reject with a 400 InvalidArgument describing the constraint, instead of letting it reach SpiceDB and 500.


Found while manually testing PR #1685. The permission-delete behavior in that PR works correctly; these are separate, pre-existing API issues.

Metadata

Metadata

Assignees

No one assigned

    Labels

    authzbugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions