Skip to content

Add self-service data export — download all my pod data #353

Description

@melvincarvalho

Summary

Round out the user-rights trio (alongside #351 self-service password change and #352 self-service account deletion) with a way for an authenticated user to download all their data as a single archive.

This is the export side of the same picture: an end user should be able to walk away with what they own without operator help and without shell access.

Current state

Proposed shape

Endpoint

GET /idp/account/export
Authorization: <existing session / DPoP>
Accept: application/x-tar+gzip

→ 200
Content-Type: application/x-tar+gzip
Content-Disposition: attachment; filename="jss-export-<webid-slug>-<isodate>.tar.gz"
<streamed tar.gz>
  • Owner-only — caller's WebID must match the account's WebID.
  • Streamed (no temp file, no full pod load into memory) so a multi-GB pod doesn't OOM the server.
  • 401 unauthenticated; 403 cross-account.

Archive contents

jss-export/
├── manifest.json          # webId, username, email, createdAt, exportedAt, jss version
├── account.json           # full account record minus passwordHash
└── pod/                   # pod tree, exact filesystem layout including dotfiles
    ├── .acl
    ├── profile/card.jsonld
    ├── public/...
    └── ...

manifest.json lets a future "import to a fresh JSS" path reconstruct enough to get a usable pod.

UI

A "Download my data" button on the /idp/account settings page. Single click → triggers the streamed download. No password re-entry needed (this is a read, not a destructive action — auth is sufficient).

Out of scope

  • Re-import — separate feature, separate issue when there's demand. Decoupling export from import keeps this issue small.
  • Cross-server pod migration (Solid pod portability) — bigger spec problem, separate.
  • Periodic / scheduled backups — operator concern, not a per-user right.
  • Per-resource selection / partial export — defer until someone asks. The 80% case is "give me everything".

Acceptance

  • New endpoint streams a tar.gz of the user's pod data plus an account.json and manifest.json.
  • Authenticated owner gets 200 + the archive.
  • Unauthenticated → 401; cross-account attempt → 403.
  • Output is a valid tar.gz — tar -tzf lists all expected files; tar -xzf reconstructs the tree exactly (including dotfiles like .acl, .meta, .quota.json).
  • manifest.json includes WebID, username, email, account createdAt, server-side exportedAt timestamp, and the JSS version that produced the archive.
  • passwordHash is not included in account.json (security — bcrypt is per-server, no portability value, and a leaked dump would let an attacker brute-force).
  • New /idp/account UI exposes a "Download my data" button that triggers the export.
  • Tests cover happy path, the two auth failure modes, dotfile preservation, and a roundtrip extraction sanity check.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions