Account erasure and export, and the 0.6 behaviour changes around it - #11
Merged
Merged
Conversation
…d it Adds the Account Deletion & Export page (Art. 17 / Art. 15) and moves the feature from Planned to Shipped. Also documents four things decided late enough that the surrounding pages still described the old behaviour: - Step-up confirmations are bound to the session that earned them. The confirmation page's diagram and prose both said "bound to this user", and account-deletion.md repeated it as the reason step-up alone can't keep a machine token out. That reason changed: a pin carrying `lukk.account` can still earn its own. Documents the new 423 `confirmation_session_mismatch`, why rotation doesn't invalidate a confirmation, and why strict matching keeps the co-issuer topology. - The `passkeys` guard column, on passkeys, multiple-guards and upgrading. The assertion lookup takes a credential id and no user, so it is the authentication decision — this is the sharpest of the guard-scoping guarantees, not a tidiness one. Both backfill directions are covered, including that removing a guard fails open. - `features.gate_auth_routes` does not switch off the erasure gate. - `existsByCredentialId` must stay unscoped in a replacement repository, since the unique index it backstops is global. Adds a third Known limitation: an erased identifier survives briefly as a rate-limiter cache key, bounded by `rate_limits.login.decay_seconds`. lukk doesn't sweep it because the per-address bucket can't be reconstructed, and a partial sweep would imply a completeness it doesn't have. Warns that a queued `AccountDeleting` listener escapes the erasure rollback, and that queueing the event serializes the subject's password hash into `jobs` and `failed_jobs`.
SQL has no cross-connection transaction without two-phase commit, so a user model on a different connection than lukk's tables gets its own. lukk nests the disposal there, which covers anything that throws during erasure, but a failure during the commit itself can leave the user erased and lukk's rows restored. The page promised all-or-nothing without qualification. It now says what actually holds, and why the surviving state is the direction lukk prefers anyway.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Docs for stsepelin/lukk#30 and stsepelin/lukk-js#51.
Adds the Account Deletion & Export page and moves the feature from Planned to Shipped.
Four things the surrounding pages still described wrongly
These were decided late enough that the existing pages had drifted:
account-deletion.mdrepeated it as the reason step-up alone can't keep a machine token out. That reason changed — a pin carryinglukk.accountcan still earn its own. Now documents the423 confirmation_session_mismatch, why rotation doesn't invalidate a confirmation, and why strict matching keeps the co-issuer topology working.passkeysguard column, across passkeys / multiple-guards / upgrading. Framed as the sharpest of the guard-scoping guarantees rather than a tidiness one: the assertion lookup takes a credential id and no user, so it is the authentication decision. Both backfill directions are covered, including that removing a guard fails open.features.gate_auth_routesdoes not switch off the erasure gate — that flag restores pre-0.6 reach, and these routes have no pre-0.6 behaviour to restore.existsByCredentialIdmust stay unscoped in a replacement repository, since the unique index it backstops is global.A third Known limitation
An erased identifier survives briefly as a rate-limiter cache key, bounded by
rate_limits.login.decay_seconds. lukk doesn't sweep it: the per-address bucket can't be reconstructed after the fact, so a partial sweep would clear the tidy half and imply a completeness it doesn't have. Says so, and points at the two levers.A trap worth its own callout
A queued
AccountDeletinglistener escapes the erasure rollback — it's pushed at dispatch, not at commit, so its work is on the wire when the transaction rolls back. Your domain data is gone and the account still exists. Queueing the event itself also serializes the subject's email, password hash and encrypted TOTP secret intojobsandfailed_jobs, which nothing prunes.Also fixed while here
#features→#feature-toggles,#denylist-store→#denylist.[!DANGER]alert — not in the GFM/VitePress set, would have rendered as a plain blockquote. Now[!CAUTION].pnpm docs:buildclean. Anchors verified by slugifying every heading rather than trusting the build, which doesn't check them. No semicolons in the edited mermaid block.Greptile Summary
Adds comprehensive documentation for account deletion and export and records the associated 0.6 behavior changes.
Confidence Score: 4/5
The PR appears safe to merge after minor documentation-reference inconsistencies are corrected.
The substantive documentation is internally coherent, but the feature-toggle table and shipped-composable inventory do not include newly documented public capabilities.
Files Needing Attention: docs/configuration.md, docs/roadmap.md
Important Files Changed
useLukkAccountout of the shipped composable inventory.Sequence Diagram
sequenceDiagram participant Client participant API participant AppListener as AccountDeleting listener participant Database Client->>API: DELETE /auth/account API->>API: Validate ability and session confirmation API->>API: Revoke all sessions API->>Database: Begin erasure transaction API->>AppListener: Dispatch AccountDeleting synchronously AppListener->>Database: Erase application-owned data API->>Database: Erase auth artifacts and user Database-->>API: Commit API->>API: Dispatch AccountDeleted API-->>Client: Successful deletionComments Outside Diff (2)
docs/configuration.md, line 194-206 (link)The example introduces
account_deletion,abilities, andgate_auth_routes, but the adjacent feature-reference table omits all three. Readers therefore cannot find their defaults and behavior in the reference table, including how to disable the newly default-enabled deletion route.Prompt To Fix With AI
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
docs/roadmap.md, line 50 (link)The account-deletion page presents
useLukkAccount()as the supported client API, but this inventory of shipped composables omits it. That makes the roadmap incorrectly suggest that account deletion and export lack a shipped Nuxt composable.Prompt To Fix With AI
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Prompt To Fix All With AI
Reviews (1): Last reviewed commit: "docs: account erasure and export, and th..." | Re-trigger Greptile