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
"Credible exit means you can always leave — and take yourself with you. Not just your data. Your identity. Your reputation. Your relationships. Your history."
This issue tracks the Credible Exit ladder as it lands in JSS. Each rung is optional. Each rung is independently shippable. Users climb at their own pace; JSS supports them at every level.
The ladder
Level 6 ──▶ Hardware Wallet Maximum sovereignty
Level 5 ──▶ Blocktrails Anchored, rotatable, recoverable
Level 4 ──▶ DID (Self-Sovereign) You control the keys. Portable.
Level 3 ──▶ Passkeys Better security, still platform-bound
Level 2 ──▶ 2FA / OTP Second factor, still captive
Level 1 ──▶ OAuth / Social "Login with X." Convenient cage
Level 0 ──▶ Password Where everyone starts
The journey is one-way upward and never destructive: same identity, same reputation, same followers, same history. Only the security improves and only the lock-in disappears.
The mechanics for Level 4 are already on disk — JSS 0.0.190+ provisions a Schnorr secp256k1 keypair and lands its public side in the WebID profile. The substrate exists. What's missing is the user-facing journey up the ladder, and the supporting infrastructure (recovery, anchoring, hardware) at the upper rungs.
Backup runs through every level
Backup isn't its own rung — it's the load-bearing companion at every level. As the user climbs, the backup payload grows:
Level
What needs backing up
0–3
pod data (#353 — tar.gz export of <root>/<podName>/...)
4
+ /private/privkey.jsonld (the secret) + signed handoff attestations
Identity claim handoff (new issue) — the L3→L4 step. Endpoint that returns a platform-signed attestation { from: alice@example.com, to: did:nostr:..., signed: example.com }. Single API call; user takes the JSON and walks. The Credible Exit moment.
Backup hooks (new issue) — JSS exposes lifecycle hooks (onWrite, onAclChange, onKeyRotation) so adjacent CLIs (jss-backup, jss-anchor) can subscribe without bloating the server. Foundation for the borg / gitmark integration that follows.
🟡 Next 1-2 months — meaningful design
jss-backup companion CLI — wraps borg-style snapshots of the data dir + key + handoffs. Encrypted, dedup'd, push to remote. Restore = decrypt + verify chain. Lives outside JSS; consumes the lifecycle hooks above.
Pod-as-git — opt-in mode where every LDP write auto-commits to a git repo in (or alongside) the data dir. Foundation for jss-anchor. Ships as --track flag in JSS; the anchoring lives in the companion.
jss-anchor companion — wraps gitmark. Anchors the pod-as-git history to Bitcoin via Nostr keys at configurable cadence. Verifiable from outside: "this commit existed at block H."
Key rotation flow (jss rotate-keys) — mints a new key chained from the old one via blocktrails. Updates WebID profile VM, NIP-05 mapping, did:nostr index in one transaction. Ships the L4 → L5 step end-to-end.
Encrypted-at-rest store — for environments where filesystem-level FDE isn't an option. Wraps every secret-tagged write transparently.
🔵 Future — when there's an ask
jss-restore — composes jss-backup + jss-anchor + key-chain verification end-to-end. Pulls a snapshot, proves it's the same identity at the same point-in-time, brings up a working pod on fresh infrastructure.
Cross-server pod migration — Solid pod portability spec. Hand a tar.gz to a different JSS, end up with the same WebID resolving to the new host. Big spec problem; defer until the ecosystem aligns.
Federated handoff verification — clients verify "alice@cool.com really did become did:nostr:abc..." without trusting JSS. Pure cryptographic verification of the handoff chain.
Ladder, not waterfall. Every level ships independently. Operators run JSS at any rung. Users climb when they're ready.
Same identity, every rung. Going from L4 to L5 doesn't mint a new identity — it adds an anchored chain to the existing one. No "migrate your followers" moment.
Backup tier follows identity tier. Don't backup more than the identity warrants. L0-3 = bytes. L4+ = bytes + key + handoffs. L5+ = + chain + anchors.
Companions, not core. Anchoring, encryption, hardware integration live in adjacent CLIs that consume JSS hooks. JSS stays focused on the protocol surface.
Honest about disk. A key on disk is a key on disk. We document filesystem-level threats (FDE, OS keyring, restrictive umask) at every level until L6 takes the secret out of disk entirely.
Out of scope for this umbrella
The financial / business side of the Credible Exit framing (platform competition dynamics, regulatory positioning) — useful framing but JSS is the substrate, not the policy argument.
The reputation-portability problem (followers, social graph) — distinct from identity portability; happens upstream in the apps that use JSS pods.
Cross-platform attestation standards — the L3→L4 handoff format will likely emerge from the broader DID community; JSS implements whatever wins.
This issue tracks the Credible Exit ladder as it lands in JSS. Each rung is optional. Each rung is independently shippable. Users climb at their own pace; JSS supports them at every level.
The ladder
The journey is one-way upward and never destructive: same identity, same reputation, same followers, same history. Only the security improves and only the lock-in disappears.
Where JSS stands today
/idp/register+--idp--idp-issuer--provision-keys) + Phase 2 (#443: VM in profile +did:nostr:controller)The mechanics for Level 4 are already on disk — JSS 0.0.190+ provisions a Schnorr secp256k1 keypair and lands its public side in the WebID profile. The substrate exists. What's missing is the user-facing journey up the ladder, and the supporting infrastructure (recovery, anchoring, hardware) at the upper rungs.
Backup runs through every level
Backup isn't its own rung — it's the load-bearing companion at every level. As the user climbs, the backup payload grows:
<root>/<podName>/...)/private/privkey.jsonld(the secret) + signed handoff attestationsEach backup tier is restorable end-to-end: encrypted snapshot + verifiable chain + provable anchors → the same Alice on a fresh server.
Phased plan
Grouped by realistic timeline. Each phase is a small, independently shippable issue + PR.
🟢 This week — already in flight
🟢 This month — small, well-scoped
--key-passphrase— wrap the on-disk secret with scrypt+aes-gcm. Operator picks a passphrase; secret on disk is no longer plaintext. Closes the "filesystem reads bypass WAC" hole from Phase 1 docs without needing hardware.{ from: alice@example.com, to: did:nostr:..., signed: example.com }. Single API call; user takes the JSON and walks. The Credible Exit moment.onWrite,onAclChange,onKeyRotation) so adjacent CLIs (jss-backup,jss-anchor) can subscribe without bloating the server. Foundation for the borg / gitmark integration that follows.🟡 Next 1-2 months — meaningful design
jss-backupcompanion CLI — wraps borg-style snapshots of the data dir + key + handoffs. Encrypted, dedup'd, push to remote. Restore = decrypt + verify chain. Lives outside JSS; consumes the lifecycle hooks above.--key-passphraseas orthogonal recovery options.jss-anchor. Ships as--trackflag in JSS; the anchoring lives in the companion.🟠 Months out — bigger pieces
jss-anchorcompanion — wraps gitmark. Anchors the pod-as-git history to Bitcoin via Nostr keys at configurable cadence. Verifiable from outside: "this commit existed at block H."jss rotate-keys) — mints a new key chained from the old one via blocktrails. Updates WebID profile VM, NIP-05 mapping, did:nostr index in one transaction. Ships the L4 → L5 step end-to-end.🔵 Future — when there's an ask
jss-restore— composesjss-backup+jss-anchor+ key-chain verification end-to-end. Pulls a snapshot, proves it's the same identity at the same point-in-time, brings up a working pod on fresh infrastructure.Cross-cutting principles
Out of scope for this umbrella
Tracking