{"id":"a8f34e4c765af38bfea169988fb46ba0eb110a6ccd6d287497028cee7ba61252","pubkey":"da19f1cd34beca44be74da4b306d9d1dd86b6343cef94ce22c49c6f59816e5bd","created_at":1774618408,"kind":30817,"tags":[["title","NIP-COMMUNITY-GOVERNANCE: Community Governance (Composition Guide)"],["k","composition-guide"],["d","nip-community-governance"]],"content":"NIP-COMMUNITY-GOVERNANCE\n=========================\n\nCommunity Governance & Collective Resource Management (Composition Guide)\n--------------------------------------------------------------------------\n\n`draft` `optional` `composition-guide`\n\nThis document shows how to model community governance on Nostr using existing NIPs. No new event kinds are required.\n\n> **Design principle:** Governance events record collective structure, proposals, votes, and resource movements. They do not enforce outcomes. The consuming application decides how to act on governance decisions.\n\n## Motivation\n\nMany real-world groups need **ongoing governance**: persistent structures with rotating roles, shared treasuries, evolving rules, and democratic processes that outlive any single vote.\n\nConsider the difference:\n\n- **NIP-CONSENSUS:** \"Should we allocate 500,000 sats to relay hosting?\", vote, done.\n- **Community Governance:** \"We are a collective. We have members, roles, a treasury, and rules for how decisions get made. This month's proposal is relay hosting. Next month it might be membership changes. The collective persists.\"\n\nNIP-02 contact lists are flat. NIP-51 lists provide flexible grouping but no governance machinery. NIP-CONSENSUS handles one-off decisions but not persistent democratic structures. NIP-CONSENSUS and NIP-EVIDENCE are currently draft NIPs. This composition guide will be most useful once those NIPs are accepted.\n\nBy composing NIP-51 lists (member rosters with governance metadata), NIP-CONSENSUS proposals and votes (democratic decision-making), and NIP-EVIDENCE records (treasury audit trails), applications can build full governance systems for:\n\n- **DAOs and cooperatives** with transparent voting and treasury management\n- **Community land trusts** with democratic stewardship decisions\n- **Mutual aid networks** with shared emergency funds and collective legal support\n- **Open-source project governance** with release decisions, fund allocation, and maintainer rotation\n- **Housing cooperatives** with maintenance fund management and rule changes\n- **Worker-owned collectives** with profit sharing and role rotation\n\n## Composition Summary\n\n| Concept | Kind | Source NIP | `d` tag pattern |\n| ------- | ---- | ---------- | --------------- |\n| Collective Definition | 30000 | NIP-51 | `collective:<name>` |\n| Governance Proposal | 30574 | NIP-CONSENSUS | `<collective>:governance:<slug>` |\n| Governance Vote | 30575 | NIP-CONSENSUS | `<collective>:governance:<slug>:vote:<voter>` |\n| Treasury Ledger Entry | 30578 | NIP-EVIDENCE | `<collective>:treasury:<sequence>` |\n\n---\n\n## Collectives with NIP-51\n\n> **NIP-51 extension note:** This guide extends NIP-51 lists with governance-specific tags (`governance_model`, `voting_threshold`, `charter`, `rotation_period`, `treasury_pubkey`). These tags are application-level conventions; NIP-51 lists without governance tags continue to function normally.\n\nA collective IS a NIP-51 list (`kind:30000`) of members with governance metadata tags. The list's `p` tags carry role positions; additional tags declare the governance model, quorum threshold, charter, and treasury key.\n\n```json\n{\n    \"kind\": 30000,\n    \"pubkey\": \"<founder-hex-pubkey>\",\n    \"created_at\": 1709280000,\n    \"tags\": [\n        [\"d\", \"collective:southwark-mutual-aid\"],\n        [\"alt\", \"Collective: Southwark Mutual Aid Network\"],\n        [\"title\", \"Southwark Mutual Aid Network\"],\n        [\"governance_model\", \"direct_democracy\"],\n        [\"voting_threshold\", \"0.6\"],\n        [\"charter\", \"https://example.com/charter.md\"],\n        [\"rotation_period\", \"P3M\"],\n        [\"treasury_pubkey\", \"<treasury-hex-pubkey>\"],\n        [\"p\", \"<founder-hex-pubkey>\", \"steward\"],\n        [\"p\", \"<member-2-hex-pubkey>\", \"treasurer\"],\n        [\"p\", \"<member-3-hex-pubkey>\", \"member\"],\n        [\"p\", \"<member-4-hex-pubkey>\", \"member\"],\n        [\"p\", \"<member-5-hex-pubkey>\", \"member\"],\n        [\"expiration\", \"1740902400\"]\n    ],\n    \"content\": \"A mutual aid network for Southwark residents. Pooled emergency fund, collective legal support, and shared resources for members in need.\",\n    \"id\": \"<32-bytes lowercase hex>\",\n    \"sig\": \"<64-bytes lowercase hex>\"\n}\n```\n\nTags:\n\n* `d` (REQUIRED): MUST use `collective:<name>` prefix. The name portion SHOULD be a human-readable slug.\n* `title` (REQUIRED): Human-readable collective name.\n* `governance_model` (RECOMMENDED): One of `direct_democracy`, `delegated`, `consensus_threshold`, `supermajority`. If omitted, applications SHOULD assume `direct_democracy`.\n* `voting_threshold` (RECOMMENDED): Minimum participation threshold as a decimal between 0.0 and 1.0. A threshold of `0.6` means at least 60% of members must vote in favour for a proposal to pass. If omitted, applications SHOULD assume `0.5`.\n* `p` (REQUIRED, repeatable): Member pubkey with role in position 2. At least one member is required.\n* `treasury_pubkey` (OPTIONAL): Pubkey controlling the collective's shared treasury. Multi-sig or threshold keys are RECOMMENDED.\n* `charter` (OPTIONAL): URI linking to the collective's governance charter document.\n* `rotation_period` (OPTIONAL): ISO 8601 duration for role rotation (e.g. `P3M` for quarterly, `P6M` for biannual). When set, steward and treasurer roles rotate among members at the specified interval.\n* `expiration` (OPTIONAL): NIP-40 timestamp. Collectives MAY set an expiration to force periodic renewal.\n\n**Content:** Plain text description of the collective's purpose and mission.\n\n### Governance Models\n\n| Model | Description |\n| ----- | ----------- |\n| `direct_democracy` | Every member votes on every proposal. Threshold applies. |\n| `delegated` | Members may delegate their vote to another member. |\n| `consensus_threshold` | Proposals pass when `agree` votes reach the threshold. No `disagree` count. |\n| `supermajority` | Proposals require a supermajority (typically 67%+) of participating members to pass. |\n\n### Member Roles\n\n| Role | Permissions |\n| ---- | ----------- |\n| `steward` | Publish updated collective definitions, manage membership proposals, represent the collective |\n| `treasurer` | Publish treasury ledger entries (NIP-EVIDENCE), manage treasury operations |\n| `member` | Create proposals, cast votes, contribute to treasury |\n\nA member MAY hold multiple roles. At least one `steward` is REQUIRED. Roles are defined in the collective definition and changed via governance proposals; no single member can unilaterally alter roles.\n\n### REQ Filters\n\n```json\n[\n    {\"kinds\": [30000], \"#d\": [\"collective:southwark-mutual-aid\"]},\n    {\"kinds\": [30000], \"#p\": [\"<member-pubkey>\"]}\n]\n```\n\n---\n\n## Proposals with NIP-CONSENSUS\n\nA governance proposal IS a NIP-CONSENSUS proposal (`kind:30574`) scoped to a collective via a `collective_id` tag. Any collective member can publish a proposal.\n\n```json\n{\n    \"kind\": 30574,\n    \"pubkey\": \"<proposing-member-hex-pubkey>\",\n    \"created_at\": 1709283600,\n    \"tags\": [\n        [\"d\", \"southwark-mutual-aid:governance:emergency-fund-allocation\"],\n        [\"t\", \"consensus-proposal\"],\n        [\"alt\", \"Governance proposal: emergency fund allocation\"],\n        [\"collective_id\", \"collective:southwark-mutual-aid\"],\n        [\"proposal_type\", \"treasury_allocation\"],\n        [\"p\", \"<member-2-hex-pubkey>\"],\n        [\"p\", \"<member-3-hex-pubkey>\"],\n        [\"p\", \"<member-4-hex-pubkey>\"],\n        [\"p\", \"<member-5-hex-pubkey>\"],\n        [\"threshold\", \"3\"],\n        [\"expiration\", \"1709884800\"],\n        [\"consensus_type\", \"governance\"]\n    ],\n    \"content\": \"Proposal: Allocate 50,000 sats from the collective treasury to establish an emergency hardship fund. Any member facing sudden financial difficulty can request up to 10,000 sats with approval from two other members. Remaining funds roll over quarterly.\",\n    \"id\": \"<32-bytes lowercase hex>\",\n    \"sig\": \"<64-bytes lowercase hex>\"\n}\n```\n\nTags (in addition to standard NIP-CONSENSUS tags):\n\n* `collective_id` (REQUIRED): The `d` tag value of the NIP-51 collective list this proposal belongs to.\n* `proposal_type` (REQUIRED): Category of proposal. One of the defined types below.\n* `consensus_type` (RECOMMENDED): SHOULD be `\"governance\"` to distinguish from non-governance consensus proposals.\n* `threshold` (REQUIRED): Integer string; minimum `agree` votes needed. Derived from the collective's `voting_threshold` and member count.\n* `expiration` (REQUIRED): Unix timestamp; voting deadline. Votes after this timestamp MUST be ignored.\n* `p` (REQUIRED, multiple): One `p` tag per voter. SHOULD match the collective's member list (excluding the proposer if they are not voting).\n\n### Proposal Types\n\n| Type | Description | Recommended Threshold |\n| ---- | ----------- | --------------------- |\n| `membership_add` | Add a new member to the collective | Default |\n| `membership_remove` | Remove an existing member | Supermajority |\n| `treasury_allocation` | Allocate funds from the shared treasury | Default |\n| `policy_change` | Change a collective rule or policy | Supermajority |\n| `role_rotation` | Rotate steward, treasurer, or other roles | Default |\n| `dissolution` | Dissolve the collective entirely | Supermajority |\n\nCollectives MAY configure supermajority requirements for sensitive proposal types (`membership_remove`, `policy_change`, `dissolution`). Enforcement is an application concern.\n\n### REQ Filters\n\n> **Note:** Tags such as `collective_id`, `proposal_type`, and `evidence_type` are multi-letter tags and therefore not relay-indexed per NIP-01. The filters below show the intended query semantics; clients MUST post-filter results client-side for multi-letter tag matches.\n\n```json\n[\n    {\"kinds\": [30574], \"#collective_id\": [\"collective:southwark-mutual-aid\"]},\n    {\"kinds\": [30574], \"#proposal_type\": [\"treasury_allocation\"]}\n]\n```\n\n---\n\n## Voting with NIP-CONSENSUS\n\nA governance vote IS a NIP-CONSENSUS vote (`kind:30575`) with a `collective_id` tag for efficient filtering.\n\n```json\n{\n    \"kind\": 30575,\n    \"pubkey\": \"<voting-member-hex-pubkey>\",\n    \"created_at\": 1709370000,\n    \"tags\": [\n        [\"d\", \"southwark-mutual-aid:governance:emergency-fund-allocation:vote:voter1\"],\n        [\"t\", \"consensus-vote\"],\n        [\"alt\", \"Governance vote: agree on emergency fund allocation\"],\n        [\"a\", \"30574:<proposer-pubkey>:southwark-mutual-aid:governance:emergency-fund-allocation\", \"wss://relay.example.com\"],\n        [\"collective_id\", \"collective:southwark-mutual-aid\"],\n        [\"vote\", \"agree\"]\n    ],\n    \"content\": \"Fully support this. Emergency funds are exactly what mutual aid is about.\",\n    \"id\": \"<32-bytes lowercase hex>\",\n    \"sig\": \"<64-bytes lowercase hex>\"\n}\n```\n\nTags (in addition to standard NIP-CONSENSUS tags):\n\n* `a` (REQUIRED): Addressable event coordinate of the `kind:30574` governance proposal being voted on.\n* `collective_id` (REQUIRED): The `d` tag value of the NIP-51 collective list. Redundant with the proposal's collective reference but included for efficient relay filtering.\n* `vote` (REQUIRED): The member's decision. One of `\"agree\"`, `\"disagree\"`, or `\"abstain\"`.\n\n### Vote Tallying Rules\n\n1. Only votes from pubkeys listed in the collective's `p` tags are counted.\n2. `abstain` votes count towards quorum (participation) but not towards approval.\n3. For `direct_democracy` and `consensus_threshold`: proposal passes when `agree` votes meet or exceed the `threshold` value.\n4. For `supermajority`: proposal passes when `agree` votes divided by participating voters (excluding abstentions) meets or exceeds 0.67.\n5. For `delegated`: a delegated vote counts as the delegator's vote. If a member both delegates and votes directly, the direct vote takes precedence.\n6. Votes after the `expiration` timestamp MUST be ignored.\n\n### REQ Filters\n\n```json\n{\"kinds\": [30575], \"#a\": [\"30574:<proposer-pubkey>:southwark-mutual-aid:governance:emergency-fund-allocation\"]}\n```\n\n---\n\n## Treasury with NIP-EVIDENCE\n\nA treasury ledger entry IS a NIP-EVIDENCE record (`kind:30578`) with `evidence_type: treasury_movement`. The append-only nature of evidence records makes them ideal for financial audit trails.\n\n```json\n{\n    \"kind\": 30578,\n    \"pubkey\": \"<treasurer-hex-pubkey>\",\n    \"created_at\": 1709456400,\n    \"tags\": [\n        [\"d\", \"southwark-mutual-aid:treasury:2026-03-emergency-fund\"],\n        [\"t\", \"evidence-record\"],\n        [\"alt\", \"Treasury ledger: 50000 SAT debit for emergency fund\"],\n        [\"evidence_type\", \"treasury_movement\"],\n        [\"collective_id\", \"collective:southwark-mutual-aid\"],\n        [\"amount\", \"50000\"],\n        [\"currency\", \"SAT\"],\n        [\"direction\", \"debit\"],\n        [\"balance_after\", \"150000\"],\n        [\"authorised_by\", \"<kind-30574-proposal-event-id>\"],\n        [\"p\", \"<recipient-pubkey>\"]\n    ],\n    \"content\": \"Emergency hardship fund allocation as approved by proposal southwark-mutual-aid:governance:emergency-fund-allocation. Quarterly rollover applies.\",\n    \"id\": \"<32-bytes lowercase hex>\",\n    \"sig\": \"<64-bytes lowercase hex>\"\n}\n```\n\nTags (in addition to standard NIP-EVIDENCE tags):\n\n* `evidence_type` (REQUIRED): MUST be `\"treasury_movement\"`.\n* `collective_id` (REQUIRED): The `d` tag value of the NIP-51 collective list.\n* `amount` (REQUIRED): Amount in the smallest unit of the specified currency.\n* `currency` (REQUIRED): Currency code. Common values: `SAT`, `GBP`, `USD`, `EUR`.\n* `direction` (REQUIRED): One of `\"credit\"` (funds in) or `\"debit\"` (funds out).\n* `balance_after` (RECOMMENDED): Treasury balance after this movement. Enables clients to verify ledger consistency.\n* `authorised_by` (RECOMMENDED): Event ID of the approved `kind:30574` governance proposal authorising this movement. REQUIRED for debits to maintain an audit trail.\n* `p` (OPTIONAL): Pubkey of the contributor (for credits) or recipient (for debits).\n\n### Auditability\n\nClients SHOULD validate that debit entries reference an approved proposal (`authorised_by`). Entries without proposal references MAY be flagged for review. The ledger is append-only; entries are never deleted, only corrected by publishing new entries with explanatory content.\n\n### REQ Filters\n\n```json\n[\n    {\"kinds\": [30578], \"#collective_id\": [\"collective:southwark-mutual-aid\"]},\n    {\"kinds\": [30578], \"#evidence_type\": [\"treasury_movement\"]}\n]\n```\n\n---\n\n## Governance Workflow\n\n\n![Governance Workflow](https://raw.githubusercontent.com/forgesworn/nip-drafts/main/images/community_governance-1.png)\n\n```mermaid\nflowchart TD\n    A[Founders publish NIP-51 list\\nkind 30000 with governance tags] --> B[Members contribute to treasury\\nkind 30578 evidence, direction: credit]\n    B --> C[Member creates governance proposal\\nkind 30574 with collective_id]\n    C --> D[Members cast votes\\nkind 30575 with collective_id]\n    D --> E{Threshold\\nreached?}\n    E -->|Yes| F[Proposal approved]\n    E -->|No| G[Proposal rejected]\n    F --> H{Proposal type?}\n    H -->|treasury_allocation| I[Treasurer publishes ledger entry\\nkind 30578, direction: debit]\n    H -->|membership / policy| J[Steward publishes updated collective\\nkind 30000 with new members or rules]\n    I --> K[Collective continues\\nNew proposals as needed]\n    J --> K\n    G --> K\n    K --> C\n```\n\n### Step by step\n\n1. **Formation.** Founders publish a `kind:30000` NIP-51 list defining the collective: its governance model, voting threshold, initial members, and optional treasury key.\n2. **Treasury seeding.** Members publish `kind:30578` evidence records with `direction: credit` to build the shared treasury.\n3. **Proposal.** Any member publishes a `kind:30574` NIP-CONSENSUS proposal with a `collective_id` tag, listing voters and a threshold derived from the collective's rules.\n4. **Voting.** Members publish `kind:30575` NIP-CONSENSUS votes. Clients tally votes against the threshold.\n5. **Resolution.** The proposal passes when `agree` votes meet the threshold, or fails when the deadline passes without meeting it.\n6. **Execution.** If approved, the relevant action is taken. The treasurer publishes a `kind:30578` ledger entry for financial decisions, or the steward publishes an updated `kind:30000` collective list for membership and policy changes.\n7. **Continuous governance.** The collective persists. New proposals are created as needed. The cycle repeats indefinitely.\n\n## Use Cases\n\n### Community Land Trusts\n\nA neighbourhood group collectively owns land. The NIP-51 collective list defines all trustees with roles. Policy changes (building permissions, lease terms) go through NIP-CONSENSUS proposals with supermajority requirements. The NIP-EVIDENCE ledger tracks maintenance contributions and expenditure.\n\n### Open-Source Project Governance\n\nAn open-source project with multiple maintainers uses community governance for release decisions and fund allocation. The collective list defines maintainers with `steward` roles. Bounty allocations go through proposals. Role rotation ensures no single maintainer has permanent control.\n\n### Mutual Aid Networks\n\nNeighbours pool emergency funds. Any member can propose an allocation for a member in hardship. The threshold ensures collective agreement. The evidence ledger provides full transparency on contributions and withdrawals.\n\n## Security Considerations\n\n* **Sybil attacks on voting.** Membership is explicit in the NIP-51 collective list. Only votes from listed member pubkeys are counted. An attacker cannot inject votes without first being added through a governance proposal.\n* **Treasury key management.** A single-key treasury is a trust risk. Multi-sig or threshold keys (e.g. 2-of-3 steward/treasurer signatures) are RECOMMENDED. Applications SHOULD warn users when a collective's treasury relies on a single key.\n* **Governance capture.** A majority faction could add sympathetic members and remove dissenters. Collectives MAY configure supermajority requirements for `membership_remove`, `policy_change`, and `dissolution` proposal types. Enforcement is an application concern.\n* **Vote privacy.** Votes are public by default. For sensitive proposals, vote content MAY be NIP-44 encrypted. Collectives SHOULD document their transparency expectations in the charter.\n* **Proposal spam.** Only collective members can create proposals, but a disruptive member could flood the collective with frivolous proposals. Clients SHOULD implement rate limiting and collectives MAY include proposal rate limits in their charter.\n* **Stale collectives.** Collectives without activity for extended periods may have abandoned treasuries. Clients SHOULD flag collectives with no proposals or ledger entries for more than 6 months. The `expiration` tag on the NIP-51 list provides a mechanism for forced renewal.\n* **Deadline enforcement.** Votes published after the `expiration` timestamp MUST be ignored. Clients MUST check timestamps when tallying votes to prevent late-vote manipulation.\n\n## Dependencies\n\n* [NIP-51](https://github.com/nostr-protocol/nips/blob/master/51.md): Lists (collective definition as `kind:30000`)\n* [NIP-CONSENSUS](./NIP-CONSENSUS.md): Multi-party consensus (`kind:30574` proposals, `kind:30575` votes)\n* [NIP-EVIDENCE](./NIP-EVIDENCE.md): Timestamped evidence recording (`kind:30578` treasury ledger entries)\n* [NIP-40](https://github.com/nostr-protocol/nips/blob/master/40.md): Expiration timestamps (collective renewal, proposal deadlines)\n* [NIP-44](https://github.com/nostr-protocol/nips/blob/master/44.md): Versioned encrypted payloads (sensitive proposal content, encrypted votes)","sig":"a48e949ed648bad92d0b42e14fabfcca05e056e89c276af09a5d6f4d45f998748c88ead44ae8fb3e735038298e5c1fba9b1dfcbd4242f8e5d37e4123f3c56a1b"}