Users

{#if banner} {/if} {#if loadError}
{loadError}
{:else if admins.length === 0}

No users yet. Invite one to get started.

{:else}
Username
Role
Email
Status
Created
Last login
{#each filtered as row (row.id)}
{row.username} {#if me && me.id === row.id} (you) {/if}
{#if row.is_active} ● Active {:else} ○ Inactive {/if}
{shortDate(row.created_at)}
{relative(row.last_login_at)}
openEdit(row) }, { label: row.is_active ? 'Deactivate' : 'Reactivate', onClick: () => row.is_active ? askDeactivate(row) : reactivate(row) }, { label: 'Delete', danger: true, disabled: !canDelete(row), onClick: () => openDelete(row) } ]} />
{/each} {#if filtered.length === 0 && admins.length > 0}
No matches for "{search}".
{/if}
{/if} {#if inviteOpen} {/if} {#if editTarget} {@const target = editTarget} {/if} {#if revealPassword} {/if} {#if deactivateTarget} {@const dt = deactivateTarget} (deactivateTarget = null)} >

Deactivating signs {dt.username} out immediately and expires every API key they hold. Their sessions and keys won't come back if you reactivate — they'll need to log in again and mint new keys.

Reactivation is one click — this isn't permanent.

{/if} {#if deleteTarget} {@const dt = deleteTarget} (deleteTarget = null)} > {#if me && me.id === dt.id}

You're about to delete your own account. You'll be signed out immediately and won't be able to sign back in.

{:else}

This permanently removes {dt.username}, all their sessions, and all their API keys. This cannot be undone.

{/if}

If they're the only remaining owner or active admin the server will reject the request with a 422 — promote/activate someone else first.

{/if}