Skip to content

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

@whoAbhishekSah

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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions