You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A logged-in user has no way to delete their own account through the running JSS. The data-layer function (deleteAccount(id) in src/idp/accounts.js) and the CLI (jss account delete <user>, #292) both exist, but neither is reachable by the account holder over HTTP, and there's no confirmation UI for what is — by design — a destructive action.
This is the deletion analogue of #351 (self-service password change). Same auth shape, plus a confirmation step because the action is irreversible.
purgeData: true mirrors the CLI's --purge — also removes the pod's filesystem data after revoking the account.
Response: 204 on success, all sessions for the rotated account invalidated, the bearer token used for this request is the last valid one and dies with the account record.
Authenticated HTML form, owner-only, with explicit warning copy:
"This permanently deletes account <username> and revokes all sessions and tokens. It cannot be undone."
Checkbox: "Also delete my pod data (<root>/<podName>/...) — this destroys all my files on this server." Off by default.
Required field: re-enter current password.
Optional field: type the username/WebID as a second confirmation (typical destructive-action ergonomic pattern).
Server-side, the form posts to the DELETE /idp/account endpoint above (HTML form → JS → DELETE, or a POST /idp/account/delete shim that internally maps to the DELETE handler).
Out of scope
Self-service operator → admin elevation (operator deleting other users' accounts via HTTP). Stays CLI-only for now; not the same risk profile.
Single-user mode self-deletion: in single-user mode there's exactly one account, deleting it bricks the server until restart re-seeds. We probably want to either disable the endpoint in single-user mode, or surface an extra warning about the consequences. Decide as part of implementation; the safe default is to disable.
Federation / Solid-OIDC ripple effects — type indexes, ActivityPub follows, nostr relays etc. that reference the dead WebID. The deletion endpoint can't reach those; document that the URI becomes a tombstone.
Acceptance
New endpoint accepts a valid {currentPassword} from the authenticated owner and removes the account record + indexes; returns 204.
purgeData: true additionally removes the pod's filesystem data.
Summary
A logged-in user has no way to delete their own account through the running JSS. The data-layer function (
deleteAccount(id)insrc/idp/accounts.js) and the CLI (jss account delete <user>, #292) both exist, but neither is reachable by the account holder over HTTP, and there's no confirmation UI for what is — by design — a destructive action.This is the deletion analogue of #351 (self-service password change). Same auth shape, plus a confirmation step because the action is irreversible.
Current state
jss account delete <user>(closed CLI: add 'jss account delete' (and refactor 'passwd' to use the same wrapper) #292) — operator-only, shell required. Supports a--purgeflag that also wipes the pod's filesystem data.deleteAccount(id)exists; removes account JSON and prunes username/email/webId indexes./idpUI to initiate deletion.Proposed shape
Endpoint
currentPasswordis required as proof (matches the password-change pattern in Add HTTP endpoint for end users to change their own password #351).purgeData: truemirrors the CLI's--purge— also removes the pod's filesystem data after revoking the account.UI:
/idp/account/delete(or/idp/settings#delete)Authenticated HTML form, owner-only, with explicit warning copy:
<username>and revokes all sessions and tokens. It cannot be undone."<root>/<podName>/...) — this destroys all my files on this server." Off by default.Server-side, the form posts to the
DELETE /idp/accountendpoint above (HTML form → JS → DELETE, or aPOST /idp/account/deleteshim that internally maps to the DELETE handler).Out of scope
Acceptance
{currentPassword}from the authenticated owner and removes the account record + indexes; returns 204.purgeData: trueadditionally removes the pod's filesystem data.currentPassword→ 401, account untouched./idp/account/delete(or equivalent) HTML page, behind auth, with the warning copy and re-entry of password.