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.toml through the CLI and must not be hand-edited.

For the full rules, see the process model.