Skip to content

feat(governance): schema v2 + domain core — humans and agents as first-class voting members - #65

Merged
github-actions[bot] merged 2 commits into
mainfrom
feat/solon-v1-governance-core
Aug 7, 2026
Merged

feat(governance): schema v2 + domain core — humans and agents as first-class voting members#65
github-actions[bot] merged 2 commits into
mainfrom
feat/solon-v1-governance-core

Conversation

@catomean

@catomean catomean commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

S1+S2 of the Solon v1 plan (see #64 for S0). The facade data model is replaced with an honest one, and the governance logic goes under test for the first time (0 → 25 unit tests).

Schema v2

  • Member carries memberType HUMAN|AGENT, its own bitcoinAddress + publicKeyHex, votingWeight, and optional ocActorId (OrangeCat identity link). Solon never holds private keys.
  • VotingSession snapshots its rules at open — electorate, threshold, quorum, eligibleCount, eligibleWeight — so past decisions stay explainable even after the rules change.
  • Vote stores the exact signedMessage + signature: every tally is independently re-verifiable.
  • Policy versions unique per (org, key, version); only an APPROVED session can mint v2+ (approvedBySessionId IS NULL reserved for the bootstrap v1).
  • Append-only AuditEvent, watch-only TreasurySource, sha256-hashed AgentApiKey.
  • Idempotent seed migration: org orangecat + allocation_policy v1 ACTIVE + genesis audit events.
  • Prod note: the bitbaum solon DB was verified empty (0 rows in every table) and its schema pre-reset, so the regenerated baseline applies cleanly on deploy.

Domain layer (lib/domain, no HTTP/UI)

  • config/governance.ts — electorate SSOT: agents vote in ALLOCATION_POLICY / TREASURY_SPEND / OPERATIONS; AID_DISBURSEMENT / MEMBERSHIP / SAFETY / GOVERNANCE_RULES are HUMANS_ONLY (red lines: agents can never vote money to people or expand their own suffrage).
  • tally.ts — pure tally + decideOutcome: abstain counts toward quorum but not threshold; below-quorum sessions EXPIRE (silence is not consent).
  • voting.ts — openSession (gate + snapshot at open), submitVote (signature → member → electorate check → weighted upsert + audit event), closeSession (outcome from snapshots; APPROVED policy proposals supersede + mint the next ACTIVE version — the only path that creates governed policy versions).
  • treasury.ts — live mempool.space balances per source; null on failure, never a guessed number.

Bitcoin message layer (load-bearing for real wallets)

  • BIP137 headers 27–42 accepted; the claimed address is matched against P2PKH, P2WPKH (bech32), and P2SH-P2WPKH derivations — Sparrow/Electrum/Core signatures all verify, including Electrum's legacy-header-on-segwit quirk.
  • proposalMessage() canonical form added alongside voteMessage().

Verification

  • npm run verify green: lint clean, tsc --noEmit clean, 25/25 vitest tests (golden message strings, tamper/replay rejection, segwit derivations + header re-banding, tally/threshold/quorum matrix, config completeness over every DecisionCategory).
  • npm run build green, all routes compile.

🤖 Generated with Claude Code

catomean and others added 2 commits August 7, 2026 21:12
…t-class voting members

S1+S2 of the Solon v1 plan: replace the facade data model with an honest one
and put the governance logic under test for the first time.

Schema v2 (drop-and-rebuild baseline; prod schema was verified empty and
pre-reset on bitbaum so the new baseline applies cleanly):
- Member carries memberType HUMAN|AGENT, its own bitcoinAddress + publicKeyHex,
  votingWeight, and optional ocActorId (OrangeCat identity link)
- VotingSession snapshots its rules at open (electorate, threshold, quorum,
  eligibleCount, eligibleWeight) so past decisions stay explainable forever
- Vote stores the exact signedMessage + signature — every tally is re-verifiable
- Policy versions are unique per (org, key, version); only an APPROVED session
  can create v2+ (approvedBySessionId null is reserved for the v1 bootstrap)
- Append-only AuditEvent, watch-only TreasurySource, sha256-hashed AgentApiKey
- Idempotent seed migration: org `orangecat` + allocation_policy v1 ACTIVE

Domain layer (lib/domain, no HTTP, no UI):
- config/governance.ts is the electorate SSOT: agents vote in ALLOCATION_POLICY /
  TREASURY_SPEND / OPERATIONS; AID_DISBURSEMENT / MEMBERSHIP / SAFETY /
  GOVERNANCE_RULES are HUMANS_ONLY (red lines: agents can never vote money to
  people or expand their own suffrage)
- tally.ts: pure tally + decideOutcome (abstain counts toward quorum, not
  threshold; silence is not consent — below-quorum sessions EXPIRE)
- voting.ts: openSession (gate + snapshot at open), submitVote (signature →
  member → electorate check → weighted upsert + audit), closeSession (outcome
  from snapshots; APPROVED policy proposals mint the next ACTIVE version)
- treasury.ts: live mempool.space balances, null on failure — never a guess

Bitcoin message layer extended (load-bearing for real wallets):
- BIP137 headers 27-42 accepted; claimed address matched against P2PKH,
  P2WPKH (bech32), and P2SH-P2WPKH derivations, so Sparrow/Electrum/Core
  signatures all verify — including Electrum's legacy-header-on-segwit quirk
- proposalMessage() canonical form alongside voteMessage()

Vitest wired into verify (lint + typecheck + test); 25 tests cover golden
message strings, sign/verify roundtrips incl. tamper/replay, segwit derivation
and header re-banding, the tally/threshold/quorum matrix, and config
completeness over every DecisionCategory.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ation

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions
github-actions Bot merged commit 740b192 into main Aug 7, 2026
1 check passed
@github-actions
github-actions Bot deleted the feat/solon-v1-governance-core branch August 7, 2026 19:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant