FID (Fediverse-ID) Unified Identity & Instance Passports β
TuneCamp uses a self-sovereign, decentralized identity model powered by FID (Fediverse-ID) (@scobru/fid), Zen SEA, and the P2P relay network (wss://delay.scobrudot.dev/zen).
This architecture allows users to unify their profiles across independent TuneCamp instances without relying on a centralized Single Sign-On (SSO) or shared database.
π Global Portal & Demo β
The official central SSO and identity portal is deployed at:
π https://fid-portal.vercel.app/ (or tunecamp.org)
π‘ Help the Network: Host a Zen Relay Node β
The decentralized graph sync and P2P communication in FID rely on open Zen P2P Relays.
You can help strengthen the network's resilience, speed, and decentralization by running your own Zen P2P Relay node!
π Host a Zen Relay Node: Visit the scobru/zen repository for instructions on spinning up a lightweight relay instance.
ποΈ Architecture Overview β
βββββββββββββββββββββββββββββ
β fid-portal.vercel.app β
β (Zen SEA Global Portal) β
βββββββββββββββ¬ββββββββββββββ
β WSS (Zen Graph)
βββββββββββββββΌββββββββββββββ
β wss://delay.scobrudot.devβ
β Zen P2P Relay β
βββββββββββββββ¬ββββββββββββββ
β
βββββββββββββββββββββββ΄ββββββββββββββββββββββ
β β
ββββββββββββββΌβββββββββββββ ββββββββββββββΌβββββββββββββ
β TuneCamp Instance A β β TuneCamp Instance B β
β (sudorecords.scobru...) β β (tunecamp.subterra...) β
βββββββββββββββββββββββββββ βββββββββββββββββββββββββββπ Two-Step Linking Handshake Workflow β
Step 1 (Instance $\rightarrow$ fid-portal.vercel.app):
- On local TuneCamp settings, user clicks "Genera Challenge di Vincolo" (
GET /api/auth/zen/challenge). - Instance generates a one-time challenge nonce
{ instanceDomain, username, nonce, timestamp }. - User copies the Challenge JSON.
- On local TuneCamp settings, user clicks "Genera Challenge di Vincolo" (
Step 2 (fid-portal.vercel.app $\rightarrow$ Instance):
- On
fid-portal.vercel.app/profile.html, user opens "Link Instance" $\rightarrow$ "Firma Challenge Istanza". - User pastes the Challenge JSON.
- Portal signs the challenge with the user's private Zen SEA key and generates a Passport JSON.
- User copies the Passport JSON and pastes it back into the local TuneCamp instance to activate the verified link.
- On
π Endpoints β
1. Generate Zen Challenge β
- Endpoint:
GET /api/auth/zen/challenge - Auth Required: Yes (
requireUser) - Response:
{
"success": true,
"challenge": {
"instanceDomain": "sudorecords.scobrudot.dev",
"username": "scobru",
"nonce": "a4f891b2c3d4e5f67890123456789abc",
"timestamp": 1721926658000
}
}2. Verify Challenge & Issue Passport Badge β
- Endpoint:
POST /api/auth/zen/link - Auth Required: Yes (
requireUser) - Body:
{
"zenPubKey": "QmZenPubKey...",
"challenge": { ... },
"seaSignature": "SEA.sign_signature_data"
}- Response:
{
"success": true,
"passport": {
"instanceDomain": "sudorecords.scobrudot.dev",
"localUsername": "scobru",
"zenPubKey": "QmZenPubKey...",
"issuedAt": 1721926658000,
"passportSignature": "HMAC_SHA256_SIGNATURE",
"publicDataEndpoint": "https://sudorecords.scobrudot.dev/api/auth/zen/user/scobru/public"
}
}3. Login with FID SSO β
- Endpoint:
POST /api/auth/zen/sso - Auth Required: No (Public Rate-Limited)
- Body:
{
"ssoToken": {
"clientId": "tunecamp-webapp",
"instanceDomain": "sudorecords.scobrudot.dev",
"username": "scobru",
"zenPubKey": "QmZenPubKey...",
"issuedAt": 1721926658000
},
"apSeed": "32_byte_hex_seed..."
}- Behavior:
- Validates
ssoTokenviaFidSsoHandler.validateSsoToken(). - Derives deterministic Ed25519 ActivityPub keys server-side from
apSeed. - Persists those keys on the account (
admin.ap_public_key/ap_private_key) when not already set, and on the linked artist when there is one. Without this the account would have no Fediverse actor at all: SSO never goes throughPOST /api/auth/login, which is where key generation is otherwise triggered. - New SSO users start as standard Listeners (
UserRole.NORMAL_USER) without auto-created artist profiles. - If promoted internally by instance admins, their instance-assigned role/artist link is respected.
- Validates
4. Public User Profile Export β
- Endpoint:
GET /api/auth/zen/user/:username/public - Auth Required: No (Public)
- Response: Returns only public profile info, public releases, and public playlists for cross-instance aggregation on
fid-portal.vercel.app.
5. Instance Discovery for Portal β
- Endpoint:
GET /api/auth/zen/instances - Auth Required: Yes (
requireUser) - Response: Returns the user's
fid_registryentries (linked instances with artist info, passport signatures, verification status). - Purpose: Allows the global portal to discover which instances a user has linked without querying every instance.
6. Cross-Instance Artist Linking (FID Registry) β
- Table:
fid_registry(per-instance, tracks linked instances per user) - Endpoints: Removed - cross-instance linking now handled externally at
tunecamp.org/profile.html - Flow: User authenticates on Instance A, gets passport from
tunecamp.org/profile.htmlvia FID portal, then links via external profile page.
7. MCP Server FID Authentication β
- Auth Header:
Authorization: FID <zen_pub_key> - Middleware:
requireFidAuthinauth.ts - Behavior: Looks up user by
zen_pubkey, derives context, grants access to MCP tools (search_music, list_recent_albums, scan_library, get_system_stats) without JWT. - Use Case: AI assistants (Claude Desktop, etc.) authenticate via user's FID identity to inspect/manage catalog across instances.
8. Unified Profile Aggregation (tunecamp-website/profile.html) β
- Data Source: Aggregates
publicReleases,publicLikes,publicPlaylistsfrom all linked instances via their/api/auth/zen/user/:username/publicendpoints. - Storage: Caches per-instance data in
localStorage(tunecamp_instance_data). - Tabs: Releases, Favorites (starred), Playlists β each shows instance badge.
- Auto-sync: On login,
loadLinkedInstances()fetches registry and auto-syncs verified instances. - Manual sync: "Sync" button per instance in the Linked Instances list.