Stakeholder governance
mdBoard does not treat “the humans” as one undifferentiated group. The human side is a stakeholder board with a guardian, optional co-guardians and seat-holding stakeholders.
The guardian is the final authority. Stakeholders decide whether a pitched proposal is accepted. A guardian veto can stop it regardless of the seat count.
::: tip The one-paragraph model A proposal is pitched. A stakeholder vote opens. Each stakeholder result is recorded against their seats. A simple majority of available seats accepts or rejects the proposal. A tie needs a guardian tie-break; a guardian or co-guardian veto rejects it. Expired seats are recorded as expired, not as abstentions. If there are no stakeholder seats, proposals are accepted without a vote. :::
The roles
| Role | Authority |
|---|---|
| Guardian | Final veto, tie-break and guardian transfer. Exactly one. |
| Co-guardian | Shares veto, tie-break and transfer authority. Zero or more. |
| Stakeholder | Holds one or more seats and votes on pitched proposals. |
| Agent | Opens votes and records results when authorised; never votes. |
A stakeholder can hold more than one seat. A seat can expire. The number of seats, not the number of people, is the voting weight.
Configure the board
[stakeholders]
max_seats = 5
quorum_seats = 3
seat_term_days = 365
seat_warning_days = 90
[[stakeholders.members]]
name = "Alice"
email = "alice@example.com"
organisation = "Example Ltd"
seats = 2
seat_until = "2027-06-30"
[[stakeholders.members]]
name = "Bob"
email = "bob@example.com"
seats = 2
seat_until = "2027-06-30"
[guardian]
name = "The Owner"
email = "owner@example.com"
organisation = "Example Ltd"
[[guardian.co_guardians]]
name = "Deputy"
email = "deputy@example.com"
max_seats is the ceiling. quorum_seats is the configured quorum; it is capped at the seats still
available. seat_term_days is the default renewal term. seat_warning_days is the lead time for
renewal reminders.
The vote journey
1. Pitch the proposal
A proposal must be in pitch before a vote can open.
2. Open the vote
mdboard --actor agent vote open '#0042' \
--authorised-by owner \
--authorization "Open the stakeholder vote."
The agent can execute this after owner authorisation. The guardian can execute it directly.
3. Record results
mdboard --actor agent vote record '#0042' \
--email alice@example.com --choice approve
mdboard --actor agent vote record '#0042' \
--email bob@example.com --choice reject
Choices are approve, reject and abstain. Each result is recorded against all of that
stakeholder’s seats.
4. Resolve
mdboard --actor agent vote resolve '#0042'
Outcomes:
| Condition | Result |
|---|---|
| Approve is a majority of available seats | passed |
| Reject is a majority of available seats | rejected |
| Counted seats are below effective quorum | unresolved |
| A result is missing | unresolved |
| Tie | unresolved, until a guardian tie-break |
| Guardian or co-guardian veto | vetoed |
| All seats expired | passed automatically |
| No stakeholder seats | passed automatically |
A tie is resolved explicitly:
mdboard --actor agent vote resolve '#0042' --tie-break approve
5. Accept
When stakeholder seats exist, accept-idea requires a passed vote:
mdboard --actor agent accept-idea '#0042' \
--authorised-by owner \
--authorization "The stakeholder vote passed; accept."
Without stakeholder seats, the existing acceptance path continues without a vote.
Veto
The guardian or a co-guardian can veto an open vote:
mdboard --actor agent vote veto '#0042' \
--reason "This changes the licence model." \
--authorised-by owner \
--authorization "Veto the proposal."
The veto is recorded with the reason and cannot be counted as a normal rejection.
Seat expiry and renewal
A seat is expired when today is after seat_until. Expired seats are recorded as expired and are
not counted as abstentions. They reduce the available denominator and the effective quorum.
Renew a seat:
mdboard --actor agent stakeholder renew \
--email alice@example.com \
--until 2028-06-30 \
--authorised-by owner \
--authorization "Renew Alice's seat."
Without --until, the seat is renewed for seat_term_days.
List seats:
mdboard stakeholder list
Guardian and co-guardian management
mdboard guardian show
mdboard guardian co-list
mdboard --actor agent guardian co-add \
--name "Deputy" --email deputy@example.com \
--authorised-by owner --authorization "Add a co-guardian."
mdboard --actor agent guardian co-remove \
--email deputy@example.com \
--authorised-by owner --authorization "Remove the co-guardian."
mdboard --actor agent guardian transfer \
--name "New Owner" --email new@example.com \
--authorised-by owner --authorization "Transfer guardianship."
SSH key and fingerprint must be supplied together. A transfer preserves co-guardians.
What the board shows
The HTML board’s Governance panel shows:
- the guardian and co-guardian count;
- allocated seats, maximum seats and quorum;
- each stakeholder’s seats and expiry;
- the latest vote for the active batch.
The JSON API includes the same governance summary. Vote artifacts live under
.mdboard/votes/; the Markdown and HTML boards are views, and Git is the truth.
Limits
Governance is an alpha feature:
- the guardian and co-guardian are configured humans, but the current actor model still uses the owner actor for authorisation;
- SSH authentication is specified separately and is not part of the vote flow yet;
- a vote records human results transcribed by the agent; it is not a cryptographic ballot;
- seat renewal and guardian changes rewrite
mdboard.tomlthrough the CLI and must not be hand-edited.
For the full rules, see the process model.