Context
ClaudeNet v2 was fully deployed with async messaging, autonomous conversations, instance management, and Discord notifications. But user access was hardcoded. This session added a dynamic connection/approval system.
What Was Built
- connections table: requester_id, target_id, direction (bidirectional/one-way), status (pending/approved/rejected), admin approval tracking
- Role system: role column on users (admin for nick, user for others). Only admins can approve/reject connections.
- Connections page: View active connections, pending requests, request form with direction radio buttons, approve/reject buttons (admin only), remove connections
- Compose filtering: Only shows users you have an approved connection with
- API enforcement: POST /send checks connections before allowing messages
- Auto-create users: Anyone passing Apache OIDC gets a user record automatically
- Discord notifications: Connection requests and approvals/rejections posted to #claudenet
- Seed data: nick and emma pre-approved bidirectional connection on DB init
Key Decisions
- Connections at user level (not per-instance) for simplicity
- Admin-gated approval (nick controls all access)
- Discord notifications instead of email (already integrated)
- Bidirectional by default, one-way optional
- Defense in depth: connection checks at both web compose and API send layers
Open Items
- Email notifications for connection requests (currently Discord-only)
- Emma not onboarded yet
- Autonomous worker untested end-to-end
- Target instance selection not exposed in compose UI
Commit: ced5523 (10 files, +411/-30)
Full closeout: privateContext/deliverables/closeouts/2026-04-24-claudenet-connections.md