studiomembers

package
v1.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 15, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package studiomembers resolves Studio capability from the project database.

Studio access lives in `_supatype.studio_members`, not in a JWT claim. `app_metadata` is the developer's namespace for their own application roles, so granting an app role must never hand out admin UI access; and `_supatype` is absent from PGRST_DB_SCHEMAS, so nothing reachable through the data plane can read or write the membership table.

Index

Constants

View Source
const RoleAdmin = "admin"

RoleAdmin is the role that may grant and revoke access. Duplicated from studioauth rather than imported, because studioauth depends on this package's lookup and the cycle would be worse than the constant.

Variables

View Source
var ErrLastAdmin = errors.New("this is the last Studio admin — promote someone else first")

ErrLastAdmin is returned when a change would leave the project with no admin.

View Source
var ErrUnknownUser = errors.New("no such user in this project")

ErrUnknownUser is returned when the target has no row in auth.users.

Functions

func Audit

func Audit(ctx context.Context, actorID, targetID, action, role string)

Audit records a membership change in `_supatype.studio_audit`.

Deliberately *not* inside SetRole/Revoke's transaction, and deliberately non-fatal. Refusing to revoke a compromised admin's access because the audit table is missing would be the worse failure; the write is logged at error level instead so a broken trail is noisy rather than silent.

`actorID` is empty when the change came from a path with no signed-in actor (the dev bypass, or the CLI against the database directly).

func AuditElevated

func AuditElevated(ctx context.Context, actorID, method, path string)

AuditElevated records a request that bypassed RLS with the service role.

No target: the record is about what the actor did, not about someone else. The method and path go in `detail` so the trail says *what* was reached, which is the whole point of making elevation visible.

func Available

func Available() bool

Available reports whether membership lookups can be performed at all. Used to decide between the membership path and the legacy claim path, so a deployment with no DSN configured is not locked out of its own Studio.

func Lookup

func Lookup(userID string) (string, bool)

Lookup returns the Studio role recorded for a verified user id.

The second result is false whenever access cannot be positively established — no membership row, no database, an unreadable table, a malformed id. Every such case is a denial: an admin UI that opens up when its authority is unreachable is worse than one that is briefly unavailable.

func Revoke

func Revoke(ctx context.Context, actingUserID, targetUserID string) error

Revoke removes a membership. Same self and last-admin protections as SetRole.

func SetRole

func SetRole(ctx context.Context, actingUserID, targetUserID, role string) error

SetRole grants or updates Studio access for one of the project's own users.

`actingUserID` is the caller. Two rules protect the project from its own admins: nobody may change their own role — self-demotion is a footgun and self-promotion is the escalation this whole design exists to prevent — and the last admin cannot be demoted, because there would then be nobody able to grant access to anyone.

Types

type Member

type Member struct {
	UserID    string `json:"userId"`
	Email     string `json:"email"`
	Role      string `json:"role"`
	CreatedAt string `json:"createdAt"`
	UpdatedAt string `json:"updatedAt"`
	// PlatformAccount marks a grant held by a Supatype Cloud account rather than
	// one of this project's own users. Those cannot sign in to a self-hosted
	// GoTrue, so self-host lists them read-only rather than pretending otherwise.
	PlatformAccount bool `json:"platformAccount"`
}

Member is one membership row, joined to the project user it belongs to.

func List

func List(ctx context.Context) ([]Member, error)

List returns every Studio membership for this project, project users first.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL