Skip to content

feat(dpp)!: $moderatedAt and $moderatedBy record the last moderator's write (PV14) - #5161

Merged
QuantumExplorer merged 8 commits into
v4.2-devfrom
claude/moderated-at-by-system-fields
Sep 29, 2026
Merged

QuantumExplorer merged 8 commits into
v4.2-devfrom
claude/moderated-at-by-system-fields

Conversation

@QuantumExplorer

@QuantumExplorer QuantumExplorer commented Sep 28, 2026 •

Copy link
Copy Markdown
Member

Basic explanation

What this does: When a moderator writes the fields a document type keeps for its moderators (the changeFields of #5158), the document now records who did it and when, in two new system properties: $moderatedAt (the block time) and $moderatedBy (the moderator's identity). They always hold the last moderator's write. Applications can index them, for example to list the reports a given moderator handled, newest first.

Value: Yappr (and any app with reports, flags or tickets) can show "handled by X at Y" and build a moderator's history from the documents themselves, without a separate log and without trusting the client.

Risks: Consensus change at protocol version 14, which is not yet on mainnet. It adds two optional fields to document serialization format 3 behind two unused flag bits, so every document stored without them keeps exactly the same bytes (devnet data included). Nothing sets them on a document type without changeFields. A few shipped code paths gained arms for the two names; each is reached only through a protocol-version-14 document type (listed below).

Issue being fixed or feature implemented

Follows #5158, now merged; this PR targets v4.2-dev. Sam asked for $moderatedAt and $moderatedBy keywords holding the last moderator to change a document's moderator fields. The defaults agreed before building:

  • only a field change sets them; a deletion already leaves a removal record with who and when, and a restore must return the document byte for byte;
  • a document owner who moderates the contract and writes a moderator field in a normal create or replace is stamped too;
  • automatic on every type with changeFields, not opt-in through required (a document has no $moderatedAt until someone moderates it);
  • no block-height variants.

What was done?

The stamp

Before, a report after a moderator handled it:

{ "$id": "...", "$ownerId": "<reporter>", "$revision": 2, "$createdAt": 1700000000000,
  "postId": "...", "reason": 1, "status": 2 }

After:

{ "$id": "...", "$ownerId": "<reporter>", "$revision": 2, "$createdAt": 1700000000000,
  "$moderatedAt": 1700000500000, "$moderatedBy": "<moderator>",
  "postId": "...", "reason": 1, "status": 2 }
Event $moderatedAt / $moderatedBy
changeDocumentFields block time / signer
create setting a moderator field, by an owner who moderates block time / owner
replace changing, adding or removing a moderator field, by an owner who moderates block time / owner
replace leaving the moderator fields alone, transfer, purchase, price update kept
restore put back with the rest of the bytes
anything on a type without changeFields never set

$updatedAt does not move, as in #5158.

Where it is set

  • DocumentV0 gains moderated_at: Option<TimestampMillis> and moderated_by: Option<Identifier> (serde $moderatedAt / $moderatedBy, skipped when absent, so JSON and value output of every other document is unchanged), with getters and setters on DocumentV0Getters / DocumentV0Setters. About 100 DocumentV0 literals across the workspace (most in tests) gained moderated_at: None, moderated_by: None.
  • The moderation transform (transform_document_fields_change_v0) stamps the changed document.
  • Batch transformer v0: judge_moderator_field_write (was moderator_field_refusal) still refuses a non-moderator's write (41124) and, for a moderator's, stamps the action. It is the only place a create or replace is stamped: an action built without that judgement is written unstamped.
  • DocumentCreateTransitionActionV0 gains moderated: bool (the conversion stamps the owner at the block's time when set). The create action is the largest BatchedTransitionAction variant and sat at clippy's large-variant limit, so its should_store_contest_info (set only by a create that opens a contest) is now boxed to make room.
  • DocumentReplaceTransitionActionV0 gains moderated_at and moderated_by, each carried over from the stored document as it is, and set together when the transformer stamps the replace.

Stored bytes

Format 3 (protocol version 14 only) writes $moderatedAt (8 bytes) behind bit 512 and $moderatedBy (32 bytes) behind bit 1024 of its time field flags. Formats 0 to 2 never meet a stamped document: changeFields needs the config's moderation, which only config version 2 has, whose documents are always written in format 3.

Indexes and queries

"indices": [
  { "name": "byModerator", "properties": [{ "$moderatedBy": "asc" }, { "$moderatedAt": "asc" }] }
]
where $moderatedBy == <moderator> orderBy $moderatedAt   -> the reports that moderator handled last
where $moderatedAt > t                                    -> the reports moderated since t
  • Parser generation 3 admits the two names in an index (ParserGeneration::admit_moderation_stamp_indexes); apply_moderator_abilities refuses them (10231) on a type without changeFields and in a unique index (a moderator's change would be refused because another document holds the same stamp). Generations 1 and 2 keep refusing them as undefined (10209).
  • get_raw_for_document_type v0, serialize_value_for_key / deserialize_value_for_key v0, Drive's estimated key sizes and the query layer's system field types know both names.
  • Not added: propertyConstraints operands, timeRange.on, required, lookup keys. Nothing but indexes and queries reads them.

Proof and SDK

  • verify_contract_document_change_execution does not compare the stamp: a later moderator's write to another field of the document moves it without undoing the change being verified.
  • serialize_specific_version refuses a stamped document in formats 0 to 2 (NotSupported) instead of dropping the stamp.
  • Replace and create proofs compare only id, owner, properties and revision (is_equal_ignoring_time_based_fields), so a carried stamp does not disturb them.
  • wasm-dpp2 Document gains moderatedAt / moderatedBy getters and the two keys in DocumentObject / DocumentJSON. Swift, Kotlin and the FFI document struct do not expose them yet; they decode such documents fine.

Book

System Properties (new section, table rows), Document Serialization (flag bits), Moderator Abilities, Contract Moderation, Indexes, the keyword index, and v14.rs item 58.

In-place changes to shipped generations

Each reached only through a document type of protocol version 14 (one listing changeFields, which only meta-schema v3 admits), so output-identical for every earlier version:

  • Batch transformer v0: stamps a moderator's create or replace of a moderator field (the refusal was already in feat(dpp)!: moderator-only document fields and deletion record and refund options (PV14) #5158).
  • DocumentReplaceTransitionActionV0 carries the stored stamp (None on every document before 14) and its conversion writes it; the create action's conversion (v0) stamps only when the transformer set moderated. The create action's should_store_contest_info is boxed: an in-memory layout change, the same value.
  • serialize_specific_version refuses a stamped document in formats 0 to 2; no document carries a stamp before 14, and consensus serializes through serialize, which is unchanged.
  • get_raw_for_document_type v0 and serialize_value_for_key / deserialize_value_for_key v0: arms for $moderatedAt / $moderatedBy. Before, the two names fell through to the properties, where no $ name is, or failed as unknown fields; only an index naming them reaches the arms, and only parser generation 3 admits such an index.
  • Drive's estimated key sizes (document_info.rs) and the query layer's meta_field_property_type: the same two arms.
  • Document serialization format 3 is protocol version 14's own format: two flag bits that were never set gain a meaning.

How Has This Been Tested?

  • drive-abci contract_user_moderation/tests/moderator_fields.rs: should_stamp_the_moderator_who_last_wrote_the_fields (stamp set, proved, restamped by a later moderator, both indexes queried and moved) and should_stamp_a_moderator_who_writes_the_fields_in_their_own_documents (a moderator's create stamped, a create without moderator fields not, an owner's replace keeping the stamp, a moderator's own replace restamping and a later title-only replace keeping it) and should_keep_the_stamp_through_a_transfer_and_a_restore (a graded card given away, a handled report deleted and restored). The unmoderated report is checked to stay unstamped. Moderation, batch and contract create/update suites: 1077 passed.
  • rs-dpp: full unit suite, 5105 passed at the first commit; after the review fixes, the document, serialization and moderator abilities tests, 648 passed. New: format 3 round trip of each half of the stamp and without it (40 bytes more, nothing else moved); format 2 refusing a stamped document; JSON and value round trips; index key extraction; parser admits the stamp index, refuses it without changeFields, in a unique index, and before protocol version 14.
  • rs-drive: query, document, verify, prove, moderation, structure and batch tests, 2372 passed.
  • cargo clippy --workspace --all-targets and cargo clippy --target wasm32-unknown-unknown -p wasm-dpp2 -p wasm-sdk: clean. cargo fmt --all.
  • Not run locally: the wasm-dpp2 mocha spec (a new moderatedAt / moderatedBy case added; no node_modules in the worktree), rs-sdk offline vectors, Swift and Kotlin.

Breaking Changes

Consensus, protocol version 14 (unreleased): two new document system properties in serialization format 3, set by moderator field writes, indexable on types with changeFields. Rust API: DocumentV0 gains two public fields and the accessor traits two methods each; DocumentReplaceTransitionActionV0 gains moderated_at and moderated_by, DocumentCreateTransitionActionV0 gains moderated and boxes should_store_contest_info (its accessor now returns Option<&ContestedDocumentVotePollStoredInfo>). Code that builds DocumentV0 or the replace action with a struct literal must add them.

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: the stamp indexes are ordinary document indexes)

For repository code-owners and collaborators only

  • I have assigned this pull request to a milestone

🤖 Generated with Claude Code

PR Hygiene · 5c4db3c

  • Bots — coderabbitai not yet · thepastaclaw not yet — /skip-bots proceeds without the ones not yet reported
  • Self-review — post /self-reviewed once the bots are done
  • Within your 5 open PRs — this one is beyond the limit; it waits until one merges
  • Build running
  • Approvals
    • files with no dedicated owner — you own it
    • dpp — you own it
    • rs-drive-abci — you own it
    • rs-drive — you own it
    • rs-platform-wallet-ffi (packages/rs-platform-wallet-ffi/src/document.rs) — HashEngineering or ZocoLini or llbartekll or romchornyi
    • rs-platform-wallet (packages/rs-platform-wallet/src/wallet/identity/network/contact_info.rs, packages/rs-platform-wallet/src/wallet/identity/network/contact_requests.rs, packages/rs-platform-wallet/src/wallet/identity/network/profile.rs) — HashEngineering or ZocoLini or llbartekll or romchornyi
    • rust-sdk-ffi (packages/rs-sdk-ffi/src/document/create.rs, packages/rs-sdk-ffi/src/document/delete.rs, packages/rs-sdk-ffi/src/document/price.rs and 5 more) — lklimek or shumkov
    • rust-sdk (packages/rs-sdk/src/platform/dashpay/contact_request.rs, packages/rs-sdk/src/platform/documents/transitions/delete.rs, packages/rs-sdk/src/platform/documents/transitions/purchase.rs and 3 more) — lklimek or shumkov

When every box is checked the PR Hygiene check passes and this can merge.

QuantumExplorer and others added 4 commits September 29, 2026 04:17
…m (PV14)

A document type's moderator abilities become one object,
`moderatorAbilities` (meta-schema v3): `delete` and `deleteWithin` replace
`canBeDeletedByModerators` and `canBeDeletedByModeratorsFor`, and
`changeFields` names top-level properties only the contract's moderators
write. A report can then be marked handled instead of deleted.

- `ContractUserModeration` gains `ChangeDocumentFields`: a moderator sets
  or removes those fields on any document of the type. The changed document
  is judged as a replace judges one (schema, propertyConstraints with their
  totals, distinctFrom, encryptedFor shapes, unique indexes) and stored with
  the replace's update, `$revision` one higher and `$updatedAt` untouched.
  Its references are not checked again, so the parser keeps references,
  their sources, generated fields, required, transient, immutable and
  contested-index properties out of the list. Proved by the document.
- A document's owner sets, changes or removes such a field in a create or a
  replace only when it moderates the contract (41124). A seated team needs
  the new `changeDocumentFields` ability on the type.
- A type listing fields keeps `$revision` even when `documentsMutable` is
  false; the whole object is fixed with the type.
- New errors 10905, 41123 and 41124; `validate_restored_document_uniqueness`
  becomes `validate_moderated_document_uniqueness` with the changed fields.
- rs-sdk `change_contract_document_fields`, wasm-sdk
  `contractChangeDocumentFields`, js-evo-sdk `moderatorChangeDocumentFields`,
  wasm-dpp2 action parts; book page "Moderator Abilities".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ilities docs

- wasm-dpp2 `ContractUserModeration.fields` returns `null` for a field the
  change removes (the property conversion read it as `undefined`), and
  integers as bigints like `Document.properties`; the spec expects both.
- Book: `deleteWithin` only beside `delete: true`; 41203 in the
  changeFields errors; `$revision` on types keeping moderator fields in
  System Properties and Mutability; the `$createdAt` fallback of
  `deleteWithin`; field changes in the no-list case and the elected
  ability, reason and action-share summaries; BasicError range to 10949.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…efund the owner (PV14)

Two new keys beside `moderatorAbilities.delete`, both frozen with the type:

- `deleteKeepsRecord` (default true). With false a deletion writes no
  removal record and the type gets no records tree; the removals query
  refuses the type, a restore is refused (41119) before any read, and the
  deletion is proved by the document's absence. rs-sdk
  `delete_contract_document` now returns `Option<ContractDocumentRemoval>`
  and wasm-sdk `contractDeleteDocument` resolves `undefined` for such a type.
- `deleteRefundsOwner` (default false). With true the owner is refunded
  its storage as for its own deletion (the batch omits
  `ForfeitStorageRefunds`).

Review fixes to the moderator fields in the same change:

- a field change that changes nothing is refused (10905), and field
  changes no longer count toward a seated team's action share;
- the create/replace gate on moderator fields moved from batch state
  validation into transformer v0, so check_tx refuses 41124 too;
- an elected declaration must give `changeDocumentFields` on every type
  that lists `changeFields` (10900);
- the deletion verifier needs the contract only for a type that keeps no
  records;
- wasm-dpp2/wasm-sdk read `fields` through js_value_to_platform_value, so
  a BigInt stays an integer;
- `SingleDocumentDriveQuery::latest_not_contested` shared by the prover
  and verifier, `top_level_property` shared by the parser and the
  reference rules, imports moved to the top;
- lookup and list-element refusals give a hint that fits moderator fields;
- the field change runs its schema, distinctFrom and encryptedFor checks
  one after another, stopping at the first refusal;
- tests: no-op change, ttl and propertyConstraints refusals, a contract
  whose config forbids deletion.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… write (PV14)

Documents of a type that keeps fields for its moderators
(`moderatorAbilities.changeFields`) record who last wrote those fields
and when:

- a `changeDocumentFields` stamps the document with the block time and
  the signer;
- a create or replace by an owner who moderates the contract and writes
  such a field stamps the owner (the create action derives it from the
  fields it sets; the batch transformer stamps the replace action, which
  otherwise carries the stored stamp over, boxed);
- transfers, purchases, price updates and restores keep the stamp.

Document serialization format 3 (protocol version 14) records the two
behind bits 512 and 1024 of its time field flags, so a document without
them is written as before. Parser generation 3 lets an index name them
on such a type, never in a unique index (10231). Index keys, query
values, Drive size estimates and the query layer know both names. The
field change's proof must name the signer as `$moderatedBy`. wasm-dpp2
Document gains `moderatedAt` / `moderatedBy`.

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

coderabbitai Bot commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Important

Review skipped

Too many files!

This PR contains 106 files, which is 6 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.

Check out review usage here.

⚙️ Run configuration

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

Review profile: CHILL

Plan: Advanced

Run ID: 1cde408d-0f58-47da-afb0-71db3b50b22f

📥 Commits

Reviewing files that changed from the base of the PR and between c5128f0 and 5c4db3c.

📒 Files selected for processing (106)
  • book/src/contract-keywords.md
  • book/src/contract-keywords/indexes.md
  • book/src/contract-keywords/moderator-abilities.md
  • book/src/contract-keywords/system-properties.md
  • book/src/data-model/contract-moderation.md
  • book/src/serialization/document-serialization.md
  • packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/common/mod.rs
  • packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v1/mod.rs
  • packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v3/mod.rs
  • packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v3/moderator_abilities_tests.rs
  • packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v3/typed_array_tests.rs
  • packages/rs-dpp/src/data_contract/document_type/methods/versioned_methods.rs
  • packages/rs-dpp/src/data_contract/document_type/property/byte_array_encoding_flip_tests.rs
  • packages/rs-dpp/src/data_contract/document_type/random_document.rs
  • packages/rs-dpp/src/document/accessors/mod.rs
  • packages/rs-dpp/src/document/accessors/v0/mod.rs
  • packages/rs-dpp/src/document/document_event.rs
  • packages/rs-dpp/src/document/document_factory/v0/mod.rs
  • packages/rs-dpp/src/document/document_methods/get_raw_for_document_type/v0/mod.rs
  • packages/rs-dpp/src/document/document_methods/is_equal_ignoring_timestamps/v0/mod.rs
  • packages/rs-dpp/src/document/extended_document/mod.rs
  • packages/rs-dpp/src/document/fields.rs
  • packages/rs-dpp/src/document/mod.rs
  • packages/rs-dpp/src/document/serialization_traits/platform_value_conversion/mod.rs
  • packages/rs-dpp/src/document/v0/accessors.rs
  • packages/rs-dpp/src/document/v0/cbor_conversion.rs
  • packages/rs-dpp/src/document/v0/mod.rs
  • packages/rs-dpp/src/document/v0/platform_value_conversion.rs
  • packages/rs-dpp/src/document/v0/serialize/mod.rs
  • packages/rs-dpp/src/document/v0/serialize/tests.rs
  • packages/rs-dpp/src/document/v0/serialize/v0.rs
  • packages/rs-dpp/src/document/v0/serialize/v1.rs
  • packages/rs-dpp/src/document/v0/serialize/v2.rs
  • packages/rs-dpp/src/document/v0/serialize/v3.rs
  • packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_create_transition/v0/mod.rs
  • packages/rs-dpp/src/state_transition/state_transitions/document/batch_transition/batched_transition/document_replace_transition/v0/mod.rs
  • packages/rs-dpp/src/tests/json_document.rs
  • packages/rs-dpp/src/tokens/token_event.rs
  • packages/rs-dpp/src/withdrawal/document_try_into_asset_unlock_base_transaction_info/v1/mod.rs
  • packages/rs-drive-abci/src/execution/platform_events/initialization/create_genesis_state/common.rs
  • packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/action_validation/document/document_create_transition_action/advanced_structure_v1/mod.rs
  • packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/distinct_from.rs
  • packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/encrypted_for.rs
  • packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/generated_from.rs
  • packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/max_bytes.rs
  • packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/property_constraints.rs
  • packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/transformer/v0/mod.rs
  • packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/transformer/v0/moderator_fields.rs
  • packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/state/v0/mod.rs
  • packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/tests/moderator_fields.rs
  • packages/rs-drive-abci/src/query/document_query/v0/mod.rs
  • packages/rs-drive-abci/src/query/document_query/v1/tests.rs
  • packages/rs-drive-abci/src/test/helpers/fee_pools.rs
  • packages/rs-drive/benches/document_average_worst_case.rs
  • packages/rs-drive/benches/document_count_worst_case.rs
  • packages/rs-drive/benches/document_sum_worst_case.rs
  • packages/rs-drive/src/drive/contract/insert/add_description/v0/mod.rs
  • packages/rs-drive/src/drive/contract/insert/add_new_keywords/v0/mod.rs
  • packages/rs-drive/src/drive/document/cost/document.rs
  • packages/rs-drive/src/drive/document/index_uniqueness/mod.rs
  • packages/rs-drive/src/drive/document/update/mod.rs
  • packages/rs-drive/src/query/conditions.rs
  • packages/rs-drive/src/query/drive_document_average_query/drive_dispatcher.rs
  • packages/rs-drive/src/query/drive_document_count_query/tests.rs
  • packages/rs-drive/src/query/drive_document_sum_query/tests.rs
  • packages/rs-drive/src/query/mod.rs
  • packages/rs-drive/src/state_transition_action/action_convert_to_operations/address_funds/address_credit_withdrawal_transition.rs
  • packages/rs-drive/src/state_transition_action/action_convert_to_operations/identity/identity_credit_withdrawal_transition.rs
  • packages/rs-drive/src/state_transition_action/action_convert_to_operations/shielded/shielded_withdrawal_transition.rs
  • packages/rs-drive/src/state_transition_action/address_funds/address_credit_withdrawal/mod.rs
  • packages/rs-drive/src/state_transition_action/address_funds/address_credit_withdrawal/v0/transformer.rs
  • packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/mod.rs
  • packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/v0/mod.rs
  • packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/v0/transformer.rs
  • packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_replace_transition_action/mod.rs
  • packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_replace_transition_action/v0/mod.rs
  • packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_replace_transition_action/v0/transformer.rs
  • packages/rs-drive/src/state_transition_action/batch/tests.rs
  • packages/rs-drive/src/state_transition_action/identity/identity_credit_withdrawal/mod.rs
  • packages/rs-drive/src/state_transition_action/identity/identity_credit_withdrawal/v0/transformer.rs
  • packages/rs-drive/src/state_transition_action/shielded/shielded_withdrawal/mod.rs
  • packages/rs-drive/src/state_transition_action/shielded/shielded_withdrawal/v0/transformer.rs
  • packages/rs-drive/src/util/object_size_info/document_info.rs
  • packages/rs-drive/src/verify/state_transition/verify_state_transition_was_executed_with_proof/v0/mod.rs
  • packages/rs-drive/tests/drive_storage_ops_coverage.rs
  • packages/rs-platform-version/src/version/v14.rs
  • packages/rs-platform-wallet-ffi/src/document.rs
  • packages/rs-platform-wallet/src/wallet/identity/network/contact_info.rs
  • packages/rs-platform-wallet/src/wallet/identity/network/contact_requests.rs
  • packages/rs-platform-wallet/src/wallet/identity/network/profile.rs
  • packages/rs-sdk-ffi/src/document/create.rs
  • packages/rs-sdk-ffi/src/document/delete.rs
  • packages/rs-sdk-ffi/src/document/price.rs
  • packages/rs-sdk-ffi/src/document/purchase.rs
  • packages/rs-sdk-ffi/src/document/put.rs
  • packages/rs-sdk-ffi/src/document/replace.rs
  • packages/rs-sdk-ffi/src/document/transfer.rs
  • packages/rs-sdk-ffi/src/document/util.rs
  • packages/rs-sdk/src/platform/dashpay/contact_request.rs
  • packages/rs-sdk/src/platform/documents/transitions/delete.rs
  • packages/rs-sdk/src/platform/documents/transitions/purchase.rs
  • packages/rs-sdk/src/platform/documents/transitions/set_price.rs
  • packages/rs-sdk/src/platform/documents/transitions/transfer.rs
  • packages/rs-sdk/src/platform/dpns_usernames/mod.rs
  • packages/wasm-dpp2/src/data_contract/document/model.rs
  • packages/wasm-dpp2/tests/unit/Document.spec.ts

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


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.

@thepastaclaw

thepastaclaw commented Sep 28, 2026 •

Copy link
Copy Markdown
Collaborator

🔍 Review in progress — actively reviewing now (commit 5c4db3c) · triage: critical

@github-actions

github-actions Bot commented Sep 29, 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-29T03:52:07.530Z

QuantumExplorer and others added 3 commits September 29, 2026 07:24
Review fixes for the moderation stamp:

- the batch transformer stamps a moderator's create through a new
  `DocumentCreateTransitionActionV0::moderated` flag, as it stamps the
  replace; the conversion no longer infers it from the fields set. The
  create action's `should_store_contest_info` is boxed to keep
  `BatchedTransitionAction` under clippy's large-variant limit;
- the replace action carries `moderated_at` and `moderated_by` as plain
  fields, each as stored, instead of a boxed pair that dropped a half;
- the field change's proof no longer compares `$moderatedBy`: a later
  moderator's write to another field moves it without undoing the change;
- `serialize_specific_version` refuses a stamped document in formats 0
  to 2 instead of dropping the stamp;
- tests: the stamp survives a transfer and a delete then restore, an
  unmoderated report stays unstamped, and test names start with should.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- the field change proof compares each value in the form the document
  type stores it (a whole number set on a `number` property reads back
  as a float);
- a type that requires a transient property can not list
  `moderatorAbilities.changeFields` (10231): the value is never stored,
  so every moderator's change would fail the schema;
- field values read from an object or JSON are put in a canonical form
  (`ContractUserModerationAction::canonical_field_value`), and rs-sdk
  and wasm-dpp2 build them in it, so a transition read back signs the
  same bytes;
- wasm-dpp2 `fields`: an `undefined` value is left out rather than
  removing the field, and the getter defines own properties, so a field
  named `__proto__` stays a field;
- the no-record deletion verifier keeps the contract lookup's answer and
  reports a failed lookup, or a missing contract or type, when no record
  proves the deletion either;
- the batch transformer returns before walking the fields of a type
  that keeps no moderator fields;
- the version table comment names `validate_moderated_document_uniqueness`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ilities-771d75' into claude/moderated-at-by-system-fields

# Conflicts:
#	packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v3/moderator_abilities_tests.rs
#	packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/transformer/v0/moderator_fields.rs
#	packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/tests/moderator_fields.rs
Base automatically changed from claude/yappr-report-moderator-abilities-771d75 to v4.2-dev September 29, 2026 03:30
@github-actions github-actions Bot added this to the v4.2.0 milestone Sep 29, 2026
@github-actions github-actions Bot added the waiting-bots Waiting for the review bots to report on this head label Sep 29, 2026
…by-system-fields

Resolved by applying this branch's own changes (da83e20..0d25b60)
onto v4.2-dev, plus the stamp fields on the DocumentV0 literal of the new
drive/document/cost/document.rs.

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

@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.

Approved

@QuantumExplorer
QuantumExplorer merged commit 7f513f5 into v4.2-dev Sep 29, 2026
49 of 50 checks passed
@QuantumExplorer
QuantumExplorer deleted the claude/moderated-at-by-system-fields branch September 29, 2026 04:35
QuantumExplorer added a commit that referenced this pull request Sep 29, 2026
…oupings-93dcc1

Brings in $moderatedAt/$moderatedBy (#5161) and skipIfAbsent at any
position (#5162).

Conflicts resolved:
- try_from_schema common: resolve the integerRange key type and the
  skipIfAbsent set on every parse.
- insert/delete walkers v2: import both bucket_index_keys and
  level_reaches_entry.
- update walker v1: the bucketed set diff keeps skipIfAbsent's empty
  side for a version the index skips, for time and integer grids.
- layout: skip notes read the bucketing source.
- indexOnly synthesis: upstream's index_admissible_for_query already
  keeps bucketed indexes off the terminal route.
- v14 notes: skipIfAbsent 59 (it shared 58 with $moderatedAt),
  integer-range indexes 60.

Adds an e2e test of a listing moving into and out of every window of a
skipIfAbsent integer-range index, and book text for the combination.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
QuantumExplorer added a commit that referenced this pull request Sep 29, 2026
Conflict: v14.rs changelog. #5161 took item 58 (so skipIfAbsent is now
59) and #5170 / #5041 took 60 and 61; the null-flags item becomes 62.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

waiting-bots Waiting for the review bots to report on this head

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants