Skip to content

feat(platform)!: elected moderation teams moderate from their stored charter - #4952

Merged
QuantumExplorer merged 8 commits into
v4.2-devfrom
feat/elected-moderation-seating-reads
Sep 24, 2026
Merged

QuantumExplorer merged 8 commits into
v4.2-devfrom
feat/elected-moderation-seating-reads

Conversation

@QuantumExplorer

@QuantumExplorer QuantumExplorer commented Sep 23, 2026 •

Copy link
Copy Markdown
Member

Issue being fixed or feature implemented

The seating step of the decentralized moderation teams plan (#4865), as decided on 2026-09-24: seating as reads, resignations as requests, interim moderators stopping at the award, and discounted fees checked only below the full price. Until now an awarded electedCharter was stored by the moderation charters contract but seated nobody: an elected contract stayed with its interim moderators forever, a notYetUsable contract's moderated types stayed blocked, nothing counted additions against maxAddedModerators, and a charter's moderatorsShare priced nothing.

Seating stays a read. Nothing is written when a contest is awarded: the charter seated on a contract is its electedCharter in the charter contract's storage, found through the contested unique index byTargetContract (only a contest's winner is ever written there, and in protocol version 14 a seat is never replaced). Its team is the leader (the charter's owner) plus its members and the memberId of every addedModerator for it, less the memberId of every removedModerator for it.

What was done?

One reader, in drive-abci (execution/validation/state_transition/common/seated_moderation_charter):

  • fetch_seated_moderation_charter(target): one query of electedCharter.byTargetContract.
  • SeatedModerationCharter::seats(identity): whether the identity is on the team, without listing the team. The leader costs nothing more, an elected member one point read of removedModerator, anyone else one point read of addedModerator and, when there is one, of removedModerator (both are unique on electedCharterId, memberId).
  • fetch_moderators_share(): the submittedCharter by id, its moderatorsShare (absent is 100).
  • count_added_moderators(charter, up_to): the additions, limited to the cap.

The charter contract comes from the system contract cache, and every read is a document query whose processing cost is billed to the transition (never a DataContractFetchInfo::fee). The reader is only reached for a contract with an elected declaration, which exists from protocol version 14 only, so it carries no version of its own, like fetch_document_through_lookup.

The seated team moderates: ContractUserModeration state v0 resolves who moderates (Moderators::{Declared, Seated}). An elected contract with no seated charter keeps its interim rules exactly as before. Once a charter is seated, only the leader and the active members moderate. The interim moderators, the owner among them, are refused with 41101.

Before, the owner of a contract with an AppointedModerators or ContractOwner interim bans after the award:

ContractUserModeration { owner_id: <interim moderator>, action: Ban { identity_id: <user> } }  -> executed
ContractUserModeration { owner_id: <charter leader>,    action: Ban { identity_id: <user> } }  -> 41101 IdentityNotContractModeratorError

After:

ContractUserModeration { owner_id: <interim moderator>, action: Ban { .. } }  -> 41101 IdentityNotContractModeratorError
ContractUserModeration { owner_id: <charter leader>,    action: Ban { .. } }  -> executed
ContractUserModeration { owner_id: <elected member>,    action: DeleteDocument { .. } }  -> executed
ContractUserModeration { owner_id: <added member>,      action: Warn { .. } }  -> executed
ContractUserModeration { owner_id: <removed member>,    action: Unban { .. } }  -> 41101

What the interim did stands (bans, suspensions, warnings, removals), and the team may lift it.

Abilities: the seated team holds the abilities the contract's declaration gives it and no others (now enforced, since no team acted before). A deletion or a restore needs deleteDocuments on the document type. A ban, a suspension or a warning, or lifting one, needs that ability on some moderated type, since the lists are contract-wide. The interim keeps every ability the contract backs, as before. New ContractModerationAbilityNotGrantedError (41201):

declaration: moderatedDocumentTypes: { "post": ["ban"] }
before: leader suspends -> 41101 (no team existed)
after:  leader bans     -> executed
        leader suspends -> 41201 ContractModerationAbilityNotGrantedError (suspend)
        leader deletes a post -> 41201 (deleteDocuments on post)

Protection (41102): once a charter is seated, the leader and the active members are protected from a ban, a suspension, a warning and the deletion of their documents, and the owner too when the declaration sets ownerProtected. The interim moderators lose the protection. Before: an elected member could be banned by the interim owner. After: Ban { identity_id: <elected member> } by the leader returns 41102, and the same ban of an interim moderator executes.

The interim block ends: contract_moderation_gate v0 reads whether a charter is seated, billed, only when a transition of the batch is on a type a notYetUsable interim blocks.

before (award or not): create post -> 41200 ContractModeratedDocumentTypeNotYetUsableError
after the award:       create post -> executed (mempool and block)

The cap on additions: an addedModerator create is refused, paid, when the charter already has the target's maxAddedModerators additions (ever filed, so a removal frees no slot). New ModerationCharterAddedModeratorLimitReachedError (41202). It is one inline hook in the batch's validate_state v0 loop, after the create's own state validation passed (its references proved the charter is seated, the writer is the leader and the member asked to join). It reads the charter by id, its target contract (billing the fee get_contract_with_fetch_info_and_fee returns) and at most the cap's number of additions. Additions an earlier create of the same batch was accepted for count too; that half is dormant while max_transitions_in_documents_batch is 1. With maxAddedModerators: 2:

before: addedModerator #1, #2, #3 -> executed, executed, executed
after:  addedModerator #1, #2     -> executed, executed
        addedModerator #3         -> 41202 ModerationCharterAddedModeratorLimitReachedError
        removedModerator #1, then addedModerator #3 -> still 41202

Discounted fees: a document action on a type an elected contract moderates whose $actionFeeAgreement names the full declared moderators amount is accepted without reading the charter and charged that amount, as today. One naming less (with the declared owner part and pricing) is checked against the seated charter. It must name exactly the proposal's moderatorsShare of the declared amount, and is charged the agreed amount, which is what the moderators pot receives. With no seated charter, any lower amount is refused.

  • The batch transformer (state v2) reads the charter and its proposal only for a contract some transition asks a discount on, billed, and records the share on the batch action (seated_moderators_shares).
  • validate_action_fee_agreements judges it from the action alone. It runs in advanced structure validation and on every recheck, which transforms anew.
  • DeclaredDocumentActionFee::agreed_fee is what resolved_action_fees charges.
  • New DocumentActionFeeModeratorsShareMismatchError (40139) names the share, or says no charter is seated.
  • A lower amount on a type the contract does not moderate, or on a contract that is not elected, stays the plain mismatch (40133).

Rounding (the open detail on the issue): the share is applied to the declared amount and rounded down to the credit, declared * share / 100 (moderation_charter::moderators_share_of). The team never charges a fraction of a credit more than its share, and a signer computes the one admissible amount with integer arithmetic. The alternative, admitting only shares that divide exactly, would make most shares unusable on odd amounts.

Declared post creation fee { owner: 10000000, moderators: 100000000 }, seated proposal moderatorsShare: 60:

agreement moderators 100000000 -> executed, pot +100000000, no charter read (gas identical before and after the award)
agreement moderators  60000000 -> before: 40133 mismatch; after: executed, pot +60000000, gas includes the charter lookup and the proposal fetch
agreement moderators  59999999 -> 40139 (share 60%)
agreement moderators  60000001 -> 40139
agreement moderators  60000000 with no seated charter -> 40139 ("the contract has no seated moderation charter")

The interim's claim: the interim team's ContractFeeClaim of the moderators pot is refused once a charter is seated (41113). The pot carries over to the seated team, unsettled, as it does under an interim that names nobody. The seated team's claim, split by rewardSplit, comes with the reward split work, which also changes what the claim's proof covers. Before: the owner of a contractOwner-interim contract claims the moderators pot after the award. After: 41113 ContractFeeClaimNotAllowedError, and the pot keeps its credits.

rs-dpp: three errors appended to StateError (discriminants 147 to 149, the frozen test pins the new tail), ElectedModerators::allows_on_any_type, DocumentActionFeeAgreement::discounts_moderators_of, moderation_charter::moderators_share_of, doc updates on ContractModerators::{may_moderate, protects, interim_blocks_document_type} and ContractFeePot::recipients. wasm-dpp maps the three errors generically.

Docs: book contract-moderation.md (the seated team, errors, what comes next), fees/overview.md (the discount), error-codes.md, docs/protocol/moderation-charters.md (a Seating section), the charter contract README and the v14 changelog item 40.

The claim's contract fetch billing is now #4954's, merged into this branch from v4.2-dev. This PR only adds the refusal after a seat to that function.

CI fix carried here: v4.2-dev's Rust workspace tests fail on moderation-charters-contract::should_load_the_schema_at_the_latest_platform_version. #4898 split the single charter document type into seven, but the crate's v1::document_types constants and that test still describe the old type. Because nextest stops at the first failure, no PR gets a full workspace run. The second commit updates the constants to the seven types and their indexes, and the test now checks all seven.

Not in this PR: the seated team's claim with the three-part split and action counters, forced settles before a membership change, the reason check (every action naming a reason the seated proposal lists), and the election parameters read from the target (the windows and the application fund). The proposal's own rules now live in the charter schema: the description's byte cap is maxBytes (#4957), and the reward split's sum is a propertyConstraints rule (#4962). The addition cap is judged in the block and not in the mempool, which runs no state validation for a batch, like a unique index conflict.

In-place changes to shipped generations

  • batch validate_state v0 (drive-abci, selected by every protocol version): the new AddedModeratorCap hook acts only on a create whose contract is the moderation charters system contract (MODERATION_CHARTERS_CONTRACT_ID) and whose type is addedModerator. That contract is in state from protocol version 14 only (genesis v1 behind the 14 branch, or transition_to_version_14). A create against a contract that is not in state fails in the batch transformer before this loop. So no batch of protocol version 13 or earlier reaches the hook, and for every such batch the loop does what it did. The same argument as the IndexOnlyBatchEntries tracker beside it.
  • BatchTransitionActionV0::validate_action_fee_agreements, BatchTransitionAction::declared_action_fees, DeclaredDocumentActionFee (rs-drive, unversioned): the new branches apply only to a transition whose document type declares actionFees, a v3 meta-schema keyword no protocol version before 14 admits. Before 14 every base action has declared_action_fee: None, so both methods return exactly what they did.

Every other edited generation is selected by protocol version 14 alone: ContractUserModeration state v0, ContractFeeClaim state v0, contract_moderation_gate v0 (None before 14) and batch transform_into_action v2. No version table moves.

How Has This Been Tested?

End to end in drive-abci (contract_user_moderation/tests/seated_team.rs). Each test files a proposal and an elected charter through the pipeline (join requests written to Drive), then awards the contest by ending its vote poll at the join window's end:

  • should_seat_the_winner_of_the_contest_and_let_its_team_moderate_instead_of_the_interim
  • should_follow_additions_and_removals_and_protect_the_team
  • should_cap_the_members_a_leader_adds_and_free_no_slot_on_a_removal
  • should_refuse_a_seated_team_an_ability_the_declaration_does_not_give_it
  • should_end_the_interim_block_once_a_charter_is_seated
  • should_charge_the_declared_moderators_part_without_a_read_and_a_discount_with_one
  • should_refuse_any_discount_but_the_seated_charters_share_and_agree_on_recheck
  • should_stop_the_interim_team_claiming_the_moderators_pot_once_a_charter_is_seated

rs-dpp unit tests: should_take_the_share_of_the_declared_moderators_part_rounded_down, should_ask_for_a_discount_only_below_the_declared_moderators_part, should_give_a_seated_team_the_abilities_of_any_moderated_type_on_the_lists_only, and the frozen StateError discriminants.

Run locally (targeted, as the conventions ask; CI runs the rest):

  • cargo test -p drive-abci --lib -- contract_user_moderation contract_fee_claim action_fee contract_moderation_gate check_tx_verification gas_sponsorship lookup_reference list_element_reference owner_reference reference_expression index_only: 198 passed, 1 failed. The failure was the gate's own read count in should_block_the_moderated_types_of_an_elected_contract_in_its_interim. The interim block now reads the charter contract once before it refuses, so the test now expects one more billed read: 2 with a type it lets through, 1 for the moderated type alone.
  • After that update, cargo test -p drive-abci --lib -- contract_moderation_gate seated_team: 12 passed.
  • cargo test -p drive --lib state_transition_action: 1158 passed.
  • cargo test -p dpp --lib --all-features for the charter, agreement, elected declaration and StateError tests: 29 passed.
  • cargo clippy -p dpp -p drive -p drive-abci --all-targets --all-features -- -D warnings: clean. cargo fmt --all: clean.
  • cargo check -p wasm-dpp (the three errors are mapped there): compiles.
  • After the review fixes: cargo test -p drive-abci --lib -- seated_team contract_moderation_gate contract_fee_claim contract_user_moderation action_fee: 109 passed (14 seated-team tests). The create-structure, encryptedFor and reference tests: 70 passed. cargo test -p drive --lib state_transition_action: 1158 passed. Clippy is clean again.

The fee test checks "no charter read" exactly. From the same seated state, the same post (same document, same nonce) is created once agreeing to the declared moderators part and once to the charter's share. The storage fees are equal, and the processing fees differ by exactly the cost of fetch_seated_moderation_charter plus fetch_moderators_share, measured on their own in a transaction (29,500 + 11,200 = 40,700 credits). Comparing the full-amount action before and after the award does not work: the award removes the contest's prefunded balance from the same sum tree the fee pots live in, which moves the pot write's cost by about 1,000 credits.

Breaking Changes

Consensus-breaking for protocol version 14 (unreleased): the moderation transition, the batch gate, the fee agreement and the claim decide differently once a charter is seated, and three consensus errors are appended (40139, 41201, 41202). Nothing changes at protocol version 13 or earlier.

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have added "!" to the title and described breaking changes in the corresponding section if my code contains any
  • I have made corresponding changes to the documentation if needed
  • If I added or changed GroveDB structure, I described it in the area's structure.rs, regenerated grovedb-structure.json, and checked the structure viewer link posted on this pull request (no structure change)

For repository code-owners and collaborators only

  • I have assigned this pull request to a milestone

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Seated elected moderation teams now replace interim moderators, with their abilities and protections governed by the contract’s declarations.
    • Eligible document actions can use a moderators’ fee discount based on the seated charter’s proposal.
  • Bug Fixes
    • The declared limit on added moderators is enforced, including for multiple additions in the same batch.
    • Interim moderators can no longer claim the moderators’ fee pot after a charter is seated.

…charter (moderation teams D74 to D77)

Seating writes nothing: the charter seated on an elected contract is the
electedCharter the moderation charters contract's byTargetContract index
finds, and the moderation paths read it (billed document queries):

- once a charter is seated only its leader and active members moderate
  (interim moderators get 41101), with the abilities the declaration gives
  the team (new 41201), and they are protected (41102);
- a notYetUsable interim stops blocking the moderated types;
- an addedModerator past the target's maxAddedModerators is refused, paid
  (new 41202), by an inline hook in the batch state validation;
- an action fee agreement may name the seated proposal's moderatorsShare of
  the declared moderators part (rounded down) and is charged that; any other
  lower amount, or one with no seated charter, is refused (new 40139); the
  declared amount reads no charter;
- the interim team's claim of the moderators pot is refused once a charter
  is seated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: dashpay/platform/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: cb719c73-58b9-4623-a289-85c2e8a52e8d

📥 Commits

Reviewing files that changed from the base of the PR and between 51afa87 and 1c17190.

📒 Files selected for processing (6)
  • docs/protocol/moderation-charters.md
  • packages/moderation-charters-contract/README.md
  • packages/rs-dpp/src/moderation_charter/mod.rs
  • packages/rs-dpp/src/moderation_charter/tests.rs
  • packages/rs-platform-version/src/version/v14.rs
  • packages/wasm-dpp/src/errors/consensus/consensus_error.rs
🚧 Files skipped from review as they are similar to previous changes (4)
  • packages/moderation-charters-contract/README.md
  • packages/rs-dpp/src/moderation_charter/mod.rs
  • packages/rs-platform-version/src/version/v14.rs
  • docs/protocol/moderation-charters.md

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

Elected moderation now uses a seated charter’s team for moderation authority and protection. The changes add state validation for moderator additions and action-fee discounts, introduce related consensus errors, and update tests and documentation.

Changes

Elected moderation seating

Layer / File(s) Summary
Moderation contracts and consensus errors
packages/rs-dpp/src/data_contract/config/moderation/*, packages/rs-dpp/src/moderation_charter/*, packages/rs-dpp/src/errors/consensus/*, packages/wasm-dpp/src/errors/consensus/consensus_error.rs, book/src/error-handling/error-codes.md
Adds ability and fee-share helpers, three consensus error types and codes, and WASM error conversions. Tests cover ability checks, fee-share calculations, and error discriminants.
Seated-charter lookup and moderation authority
packages/rs-drive-abci/src/execution/validation/state_transition/common/seated_moderation_charter/*, packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/*, packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/transformer/v0/contract_moderation_gate/*, packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_fee_claim/*, packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/tests/*, packages/rs-dpp/src/data_contract/config/moderation/mod.rs, docs/protocol/moderation-charters.md, packages/moderation-charters-contract/README.md, book/src/data-model/contract-moderation.md, packages/rs-platform-version/src/version/v14.rs
Validation reads seated charters and membership documents. Seated teams replace interim moderators, use declared abilities and protections, and end interim blocking. Interim moderators cannot claim the moderators pot after seating.
Batch moderator-addition cap
packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/state/v0/*, packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/mod.rs, packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/tests/seated_team.rs, docs/protocol/moderation-charters.md, packages/moderation-charters-contract/README.md
Batch state validation counts additions in state and earlier accepted creates in the batch. It refuses additions that exceed the target contract’s configured cap.
Charter-based moderator fee discounts
packages/rs-drive/src/state_transition_action/batch/*, packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/state/v2/mod.rs, packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/tests/seated_team.rs, book/src/fees/overview.md, docs/protocol/moderation-charters.md
Batch transformation reads a seated charter’s share when a fee agreement requests a moderator discount. Validation accepts the rounded share and refuses other discounted amounts.

Priority: ➖ Normal

Estimated code review effort: 4 (Complex) | ~60 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant BatchTransformer
  participant SeatedModerationCharter
  participant Drive
  participant ContractUserModeration
  BatchTransformer->>SeatedModerationCharter: fetch charter for target contract
  SeatedModerationCharter->>Drive: query elected charter
  Drive-->>SeatedModerationCharter: return charter or no result
  SeatedModerationCharter-->>BatchTransformer: return seated charter
  ContractUserModeration->>SeatedModerationCharter: check team membership
  SeatedModerationCharter->>Drive: query addition and removal documents
Loading

Suggested reviewers: lklimek

Merge Risk: ⚪ Minimal · up to 1c171

No actionable regression is identified in the supplied changes; the PR is mergeable after normal checks.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 74.04% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 104 functions across 31 files. (2 skipped… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely identifies the main change: elected moderation teams now moderate based on their stored charter.
Full details: Docstring Coverage

Explanation

Docstring coverage is 74.04% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 104 functions across 31 files. (2 skipped: 2 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added this to the v4.2.0 milestone Sep 23, 2026
@github-actions

github-actions Bot commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

📖 Book Preview built successfully.

Download the preview from the workflow artifacts.
To view locally: download the artifact, unzip, and open index.html.

Updated at 2026-09-24T04:18:19.798Z

@github-actions github-actions Bot added the waiting-bots Waiting for the review bots to report on this head label Sep 23, 2026
@thepastaclaw

thepastaclaw commented Sep 23, 2026 •

Copy link
Copy Markdown
Collaborator

🕓 Queued for automated review — 6th in line, estimated start in ~1.4 h (commit 6ead015)
Estimated review time once started: ~35 min (two-phase automated review; median of recent runs).

  • Request priority review — click to move this review to the front of the queue.

QuantumExplorer and others added 2 commits September 24, 2026 02:53
…in the contract crate

#4898 reshaped the charter contract's single `charter` type into seven
types, but the crate's `v1::document_types` constants and its schema test
still described the old type, so `should_load_the_schema_at_the_latest_platform_version`
fails on v4.2-dev and stops the Rust workspace tests of every pull request.
The constants now name each type's properties and indexes, and the test
checks all seven types, that there are no others, and that only the
elected charter's index is contested.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- the contract fee claim bills the contract fetch from the fee the fetch
  returns, not the cache-dependent one a fetch info carries, with a warm
  versus cold cache regression test;
- a submittedCharter create is judged by the proposal's own rules (reward
  split sums to 100, description byte cap) in document create structure
  validation 1, since seating runs nothing, so the mempool refuses too;
- the seated share is read from the proposal's moderatorsShare alone, and
  only for a transform result without errors;
- the unused `declared_action_fee` accessor is gone;
- the addition cap being judged in the block only, and the dpp helpers
  describing the interim only, are documented;
- tests: a seated team restoring and refused a restore, the owner flag
  under a seated team, a discount on an unmoderated type and on a fee
  priced by the multiplier, two additions in one batch, an addition at
  protocol version 13, and a proposal with a bad split.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
QuantumExplorer and others added 3 commits September 24, 2026 07:04
…ration-seating-reads

# Conflicts:
#	docs/protocol/moderation-charters.md
…ration-seating-reads

# Conflicts:
#	packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_fee_claim/state/v0/mod.rs
… to their own change

The submittedCharter create no longer runs validate_submitted_charter in
document create structure validation 1; that check is being handled
separately. The structure validation is back to what v4.2-dev has.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ration-seating-reads

# Conflicts:
#	docs/protocol/moderation-charters.md
#	packages/moderation-charters-contract/README.md
#	packages/rs-dpp/src/moderation_charter/mod.rs
#	packages/rs-platform-version/src/version/v14.rs
…ration-seating-reads

# Conflicts:
#	docs/protocol/moderation-charters.md
#	packages/moderation-charters-contract/README.md
#	packages/rs-dpp/src/moderation_charter/mod.rs
#	packages/rs-platform-version/src/version/v14.rs
@QuantumExplorer QuantumExplorer changed the title feat(platform)!: elected moderation teams moderate from their stored charter (moderation teams D74 to D77) feat(platform)!: elected moderation teams moderate from their stored charter Sep 24, 2026

@QuantumExplorer QuantumExplorer left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed

@QuantumExplorer
QuantumExplorer merged commit a033450 into v4.2-dev Sep 24, 2026
21 of 22 checks passed
@QuantumExplorer
QuantumExplorer deleted the feat/elected-moderation-seating-reads branch September 24, 2026 04:27
@github-actions github-actions Bot removed the waiting-bots Waiting for the review bots to report on this head label Sep 24, 2026
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.

2 participants