nebari-dev / nebari-dev/nebari-frames

Track membership provenance so default-provisioned rows are distinguishable

Open
#66 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

needs: discussion 💬 type: enhancement 💅🏼
Dominant language
Go
Stars
2
Forks
1
Avg merge
10h 55m
Merged PRs (30d)
9

Description

Problem

With auth.defaultRole set (#22), a user who merely signed in gets a persisted membership row that is byte-for-byte indistinguishable from one an admin deliberately created. Several behaviors have to guess as a result:

  • seed.Run cannot tell "already configured" from "just signed in". #22 works around this by promoting the configured admin only when CountAdmins returns zero. That is a targeted fix for the break-glass case, not a general answer.
  • AddOrgMember fails instead of upgrading. Adding a user who has already signed in returns AlreadyExists ("a member with that email already exists"), which reads like a duplicate-invite error rather than "this person is already here at the baseline, change their role." Documented as a caveat in the README today.
  • A pending invite created after first login can never activate. ResolveCaller only consults the invite table when there is no sub-keyed membership. Worst case is a token with no email claim: the baseline row stores email NULL, so AddOrgMember does not even detect the collision, and the admin sees an invite that will silently never apply.

Suggested direction

Add provenance to org_memberships, e.g. source TEXT NOT NULL DEFAULT 'explicit' with values explicit (admin invite, seed, or an admin-set role) and default (auto-provisioned by auth.defaultRole). Then:

  • seed.Run can promote a default row unconditionally, and leave explicit rows alone - no CountAdmins heuristic.
  • AddOrgMember can upgrade a default row in place instead of erroring.
  • ResolveCaller can let a later invite win over a default row, restoring the "an invite always outranks the baseline" contract even when the baseline row already exists.
  • Unsetting auth.defaultRole could optionally prune default rows, making the setting genuinely reversible.

Notes

This preserves the property that motivated persisting the row in the first place (baseline users appear in ListOrgMembers and are promotable) while removing the ambiguity it introduced. Needs a migration, which is why it was deliberately kept out of #22.

Raised by review of #22.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing seed.Run, AddOrgMember, and ResolveCaller, then inspect the org_memberships schema and existing migration approach. Define how provenance affects default rows, explicit memberships, later invites, and optional pruning; done means the migration and all three flows preserve the stated precedence and upgrade behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
authentication, backend, databases
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
47/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.