4.9 KiB
4.9 KiB
rVote — Decision Engine
Module ID: rvote
Domain: rvote.online
Version: 0.1.0
Framework: Next.js 16 / React 19 / Prisma / PostgreSQL
Status: Active
Purpose
Credit-weighted conviction voting engine for collaborative governance. Spaces can run ranked proposals with configurable parameters — daily credit allocation, promotion thresholds, voting periods — and binary final votes. Integrates with the r*.online ecosystem via EncryptID passkey authentication.
Data Model
Core Entities (Prisma)
| Model | Key Fields | Relationships |
|---|---|---|
| User | id, did (EncryptID DID), username, totalCredits | has many SpaceMember, Proposal, Vote, FinalVote |
| Space | slug, name, visibility, promotionsThreshold, votingPeriodHours, dailyCredits, maxCredits, startingCredits | has many SpaceMember, SpaceInvite |
| SpaceMember | userId, spaceSlug, role (ADMIN/MEMBER), credits, lastCreditUpdate | belongs to User, Space |
| SpaceInvite | spaceSlug, email, token, role, expiresAt, maxUses, useCount | belongs to Space |
| Proposal | id, title, description, spaceSlug, authorId, status, voteCount, finalYes/No/Abstain | belongs to Space, User; has many Vote, FinalVote |
| Vote | userId, proposalId, weight, credits, decayTime | ranking phase vote |
| FinalVote | userId, proposalId, vote (YES/NO/ABSTAIN) | binary phase vote |
Proposal Status Flow
RANKING → (crosses threshold) → VOTING → (period expires) → PASSED / FAILED
→ ARCHIVED (manual)
Permission Model
Space Integration
- SpaceVisibility: All four levels supported (public, public_read, authenticated, members_only)
- Default role for open spaces: PARTICIPANT (can view proposals and vote)
Capabilities
| Capability | Required SpaceRole | AuthLevel | Description |
|---|---|---|---|
view_proposals |
VIEWER | BASIC | See proposal list and details |
create_proposal |
PARTICIPANT | STANDARD | Submit new proposals |
cast_vote |
PARTICIPANT | STANDARD | Vote on ranking and final phases |
moderate_proposals |
MODERATOR | STANDARD | Edit/archive others' proposals |
configure_voting |
ADMIN | ELEVATED | Change space voting parameters |
Module-Specific Overrides
Currently uses SpaceRole { ADMIN, MEMBER } in Prisma. Migration path:
MEMBER→PARTICIPANT- Add
VIEWERandMODERATORto the Prisma enum - Replace
requireSpaceMembership()/requireSpaceAdmin()withhasCapability()from SDK
Current Auth Implementation
- NextAuth 5 (beta) + EncryptID session
requireSpaceMembership(slug, session)checks SpaceMember tablerequireSpaceAdmin(slug, session)checks SpaceMember.role === ADMIN
API Endpoints
| Method | Path | Auth Required | Capability | Description |
|---|---|---|---|---|
| GET | /api/spaces | No | — | List public spaces |
| POST | /api/spaces | Yes | — | Create a new space |
| GET | /api/spaces/[slug] | Depends | view_proposals | Get space info |
| PUT | /api/spaces/[slug] | Yes | configure_voting | Update space settings |
| GET | /api/spaces/[slug]/members | Yes | view_proposals | List space members |
| POST | /api/spaces/[slug]/members | Yes | configure_voting | Add member |
| GET | /api/proposals | Depends | view_proposals | List proposals in space |
| POST | /api/proposals | Yes | create_proposal | Create proposal |
| POST | /api/proposals/[id]/vote | Yes | cast_vote | Submit ranking vote |
| POST | /api/proposals/[id]/final-vote | Yes | cast_vote | Submit final vote |
| GET/POST | /api/spaces/[slug]/invites | Yes | configure_voting | Manage invites |
Canvas Integration
rVote can embed as a demo-poll shape in the rSpace canvas:
- Shape type:
demo-poll - Displays question + vote counts inline on canvas
- Click to expand into full voting interface
- Real-time vote count sync via Automerge
Cross-Module Dependencies
| Module | Integration |
|---|---|
| rSpace | Embedded poll shapes on canvas |
| rFunds | Proposals can trigger funding flows when passed |
| rNetwork | Voter graph visualization |
| canvas-website | Tldraw integration via shape system |
Local-First / Offline Support
- Currently server-authoritative (Prisma/PostgreSQL)
- No offline vote caching
- Future: CRDT proposal state for offline draft proposals, sync on reconnect
Migration Plan
- Add
VIEWERandMODERATORto PrismaSpaceRoleenum (migration) - Rename existing
MEMBERdata toPARTICIPANT(data migration) - Import
SpaceRolefrom@encryptid/sdktypes for client-side use - Replace
requireSpaceMembership()withhasCapability(role, cap, RVOTE_PERMISSIONS) - Replace
requireSpaceAdmin()withhasCapability(role, 'configure_voting', RVOTE_PERMISSIONS) - Add
resolveSpaceRole()call in API route middleware