/** * rVote Automerge document schemas. * * Granularity: one Automerge document per proposal. * DocId format: {space}:vote:proposals:{proposalId} * * Vote tallying uses the Intent/Claim pattern: * clients submit vote intents, server validates and writes claims. */ import type { DocSchema } from '../../shared/local-first/document'; // ── Document types ── export interface VoteItem { id: string; userId: string; proposalId: string; weight: number; creditCost: number; createdAt: number; decaysAt: number; } export interface FinalVoteItem { id: string; userId: string; proposalId: string; vote: 'YES' | 'NO' | 'ABSTAIN'; createdAt: number; } export interface SpaceConfig { slug: string; name: string; description: string; ownerDid: string; visibility: string; promotionThreshold: number | null; votingPeriodDays: number | null; creditsPerDay: number | null; maxCredits: number | null; startingCredits: number | null; createdAt: number; updatedAt: number; } export interface ProposalMeta { id: string; spaceSlug: string; authorId: string; title: string; description: string; status: string; score: number; votingEndsAt: number; finalYes: number; finalNo: number; finalAbstain: number; createdAt: number; updatedAt: number; } export interface ProposalDoc { meta: { module: string; collection: string; version: number; spaceSlug: string; createdAt: number; }; spaceConfig: SpaceConfig | null; proposal: ProposalMeta; votes: Record; finalVotes: Record; } // ── Schema registration ── export const proposalSchema: DocSchema = { module: 'vote', collection: 'proposals', version: 1, init: (): ProposalDoc => ({ meta: { module: 'vote', collection: 'proposals', version: 1, spaceSlug: '', createdAt: Date.now(), }, spaceConfig: null, proposal: { id: '', spaceSlug: '', authorId: '', title: '', description: '', status: 'RANKING', score: 0, votingEndsAt: 0, finalYes: 0, finalNo: 0, finalAbstain: 0, createdAt: Date.now(), updatedAt: Date.now(), }, votes: {}, finalVotes: {}, }), }; // ── Helpers ── export function proposalDocId(space: string, proposalId: string) { return `${space}:vote:proposals:${proposalId}` as const; }