fix(dashboard): F-U-018 allow owners to invite owners directly

The invite-user modal offered only admin/member radios. Owner could
only be granted by editing an existing user — asymmetric with
editRoleOptions which lets owners assign owner directly. The original
intention was preventing the first-owner footgun but the asymmetry
was confusing.

Show the Owner radio only when me?.instance_role === 'owner'. The
help text ("Owners can't be created here — promote via Edit") still
shows for non-owner admins so the friction is preserved where it
matters.

AUDIT.md anchor: F-U-018.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-06-07 21:06:02 +02:00
parent 73d3befb06
commit cd0cd8464c

View File

@@ -50,7 +50,10 @@
// Invite (create) modal -------------------------------------------------- // Invite (create) modal --------------------------------------------------
let inviteOpen = $state(false); let inviteOpen = $state(false);
let inviteForm = $state<{ username: string; email: string; instance_role: 'admin' | 'member' }>({ // F-U-018: Owner is selectable for the bootstrap case (owners can
// always create more owners; the asymmetry with editRoleOptions
// was unnecessary friction).
let inviteForm = $state<{ username: string; email: string; instance_role: InstanceRole }>({
username: '', username: '',
email: '', email: '',
instance_role: 'admin' instance_role: 'admin'
@@ -449,6 +452,12 @@
</label> </label>
<fieldset class="field"> <fieldset class="field">
<legend>Role</legend> <legend>Role</legend>
{#if me?.instance_role === 'owner'}
<label class="radio">
<input type="radio" bind:group={inviteForm.instance_role} value="owner" />
<span>Owner — full instance control (irrevocable except by another owner).</span>
</label>
{/if}
<label class="radio"> <label class="radio">
<input type="radio" bind:group={inviteForm.instance_role} value="admin" /> <input type="radio" bind:group={inviteForm.instance_role} value="admin" />
<span>Admin — can manage users, scripts, and all apps.</span> <span>Admin — can manage users, scripts, and all apps.</span>
@@ -457,9 +466,9 @@
<input type="radio" bind:group={inviteForm.instance_role} value="member" /> <input type="radio" bind:group={inviteForm.instance_role} value="member" />
<span>Member — only sees apps they're added to.</span> <span>Member — only sees apps they're added to.</span>
</label> </label>
<small> {#if me?.instance_role !== 'owner'}
Owners can't be created here — promote via Edit after creation. <small>Owners can't be created here — promote via Edit after creation.</small>
</small> {/if}
</fieldset> </fieldset>
{#if inviteError} {#if inviteError}
<div class="error">{inviteError}</div> <div class="error">{inviteError}</div>