Skip to content

feat(mpg): show customer roles and limit custom users to databases - #5379

Open
miguel-fly wants to merge 7 commits into
masterfrom
miguel/mpg-users-roles
Open

miguel-fly wants to merge 7 commits into
masterfrom
miguel/mpg-users-roles

Conversation

@miguel-fly

@miguel-fly miguel-fly commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

Issue

  • superfly/mpg#572

Problem

  • fly mpg users list shows only each user's built-in role. Roles made with SQL, and which databases a user can reach, don't show anywhere in flyctl
  • There's no way to create a custom user, who gets only what an admin grants, or to limit a user to some databases
  • fly mpg attach can write a DATABASE_URL for a database the chosen user can't reach

Solution

  • fly mpg users list shows each user's roles and databases, and new fly mpg roles commands list roles and their members
  • fly mpg users create and the new fly mpg users set-databases make custom users and limit them to some databases
  • fly mpg attach offers only databases the chosen user can reach

Details

  • fly mpg users list gains ROLES and DATABASES
    • ROLES: the user's roles made with SQL, - for none, blank when the cluster doesn't report them yet, with a note on stderr
    • DATABASES: all, the list, none, or unknown for a user with no built-in role, whose access comes from SQL grants
    • ROLE shows - for a user with no built-in role
    • --json adds roles, databases_limited and databases
  • fly mpg users create takes -r custom and -d <database>, repeatable
    • -d alone picks custom, the only role that can be limited
    • -d with another role is refused before any call
    • interactive -r custom asks which databases
  • New fly mpg users set-databases
    • --database (repeatable) or --all-databases; interactive runs ask
    • limiting asks for confirmation first, since it ends the user's sessions in databases it loses. --yes skips it
    • if the call fails after the change may have applied, it says so, and that running it again is safe
  • New fly mpg roles list and fly mpg roles members -r <role>
  • fly mpg attach:
    • for a limited user, it offers only that user's databases, and refuses one outside them
    • it doesn't offer custom for a new user, since a new custom user can't read anything
  • A 501 from a cluster that isn't updated yet gets a hint: It arrives with a scheduled update in the cluster's maintenance window.
  • The fallback to postgresv2 on a flaps 404 stays for list, create without -d, set-role and delete. Create with -d, set-databases and the roles commands call flaps only

Examples

Example 1: list users

$ fly mpg users list my-cluster-id
 NAME      │ ROLE   │ ROLES             │ DATABASES
 analyst   │ custom │ Team B, analytics │ app1, app2
 app_user  │ writer │ -                 │ all
 sql_login │ -      │ analytics         │ unknown
  • sql_login has no built-in role. Its access comes from SQL grants, so DATABASES says unknown

Example 2: create a custom user limited to two databases

$ fly mpg users create my-cluster-id -u analyst -r custom -d app1 -d app2
Creating user analyst with role custom in cluster my-cluster-id...
User created successfully!
  Name: analyst
  Role: custom
  Databases: app1, app2
custom users can't read or write anything until an admin user grants access with SQL.

Example 3: limit a user to one database

$ fly mpg users set-databases my-cluster-id -u analyst -d app1 --yes
Updating databases for user analyst in cluster my-cluster-id...
User databases updated successfully!
  Name: analyst
  Databases: app1
  • Without --yes, it asks: Limit analyst to app1 in cluster my-cluster-id? Its sessions in other databases will be ended.

Example 4: list roles

$ fly mpg roles list my-cluster-id
 NAME      │ MEMBERS
 Team B    │ 1
 analytics │ 3

Example 5: list a role's members

$ fly mpg roles members my-cluster-id -r "Team B"
 NAME
 analyst
 writer
  • The role name is sent as typed, spaces and case included

Example 6: -d with a built-in role (error)

$ fly mpg users create my-cluster-id -u etl -r writer -d app1
Error: --database needs --role custom: only custom users can be limited to databases

Example 7: a cluster that isn't updated yet (error)

$ fly mpg roles list my-cluster-id
Error: failed to list roles for cluster my-cluster-id: failed to list Managed Postgres roles: Customer roles are not available on this cluster yet
It arrives with a scheduled update in the cluster's maintenance window.

Example 8: attach a limited user to a database it can't reach (error)

$ fly mpg attach my-cluster-id -a my-app --username analyst --database appdb
Error: user analyst can't connect to database appdb; it is limited to app1
Pick one of those with --database, or change its databases with fly mpg users set-databases.

Notes

  • fly mpg attach --username now lists the cluster's users to check the user's limits. If that list fails, attach fails instead of writing a URL that may not connect
  • users list --json and roles commands with --json need the cluster id, so they never prompt
  • No pty tests for the interactive pickers (role, custom user, database multi-select). The flag paths are covered by table tests
  • Old flyctl keeps working on the new API: it ignores the new fields, shows custom as text, and refuses -r custom locally

Rollout

  • Needs the fly-go release from miguel/managed-postgres-roles (likely v0.11.10). go.mod still needs that bump
  • Ships after:
    • ui-ex miguel/mpg-list-roles-api and miguel/mpg-user-databases-api are deployed
    • the flaps rollout with nomad-firecracker miguel/flaps-mpg-roles and miguel/flaps-mpg-user-databases has finished. Hosts not yet updated answer 404 for the new routes, and flyctl doesn't fall back for them

@miguel-fly
miguel-fly requested a review from a team as a code owner November 6, 2026 19:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant