Skip to content

feat(platform)!: string equality for enums in propertyConstraints rules (PV14) - #5042

Merged
QuantumExplorer merged 1 commit into
v4.2-devfrom
claude/property-constraints-strings
Sep 27, 2026
Merged

QuantumExplorer merged 1 commit into
v4.2-devfrom
claude/property-constraints-strings

Conversation

@QuantumExplorer

@QuantumExplorer QuantumExplorer commented Sep 27, 2026 •

Copy link
Copy Markdown
Member

Basic explanation

What this does: A propertyConstraints rule can now compare a string property with fixed strings, which is how enum-style properties like status are written: { "equal": ["status", { "const": "closed" }] }, notEqual, or { "in": ["status", ["open", "pending"]] }. Until now rules could only read numbers and booleans.

Value: Rules like "a closed order must have a closedAt" or "only a cancelled offer may carry a refund" become expressible for the many schemas that use string enums. When the property declares an enum, a misspelled constant ("closd") is refused when the contract registers. Without that check it would silently make the rule never hold.

Risks: Low. This changes consensus validation, but only in protocol version 14, which is not on mainnet. It only widens what is accepted: a string constant was refused everywhere before, and every rule that registered before evaluates the same way.

Issue being fixed or feature implemented

Follow-up to the propertyConstraints series (#4962, #5036, #5037, #5038, #5040). Conditional rules usually hinge on an enum-like status, and most schemas spell those as strings.

What was done?

Grammar

In an operand a string on its own is a property path, so a string constant needs a wrapper. const is JSON Schema's word for "exactly this value":

  • { "equal": [path, { "const": "closed" }] } or notEqual, with the constant on either side. The other side must be a property path, not an expression.
  • { "in": [path, ["open", "pending"]] }. The values an in lists are literals, so strings need no wrapper. There must be two or more, with no two alike and no mixing with integers.
  • Strings are compared only for equality: lessThan with a const, or a const inside arithmetic, is refused.

Before, this rule was refused when the contract registered (the meta-schema knew no const). Now it registers:

"closedNeedsClosedAt": {
  "anyOf": [{ "notEqual": ["status", { "const": "closed" }] }, { "present": "closedAt" }]
}
Document Result
{} accepted (a missing status equals no constant)
{ "status": "open" } accepted
{ "status": "closed", "closedAt": 1000 } accepted
{ "status": "closed" } refused, 10422 closedNeedsClosedAt NotMet

Semantics

  • Missing string: a string property the document leaves out, or sets to null, equals no constant. So notEqual holds for it, while equal and in do not. present and absent test for it directly. Unlike integers there is no default value.
  • No new errors: a string comparison never faults, so no new PropertyConstraintViolation is added.

Registration checks (on every parse)

  • The path must name a string property that is not transient.
  • Typo check: if the property declares an enum, every constant compared with it must be one of the enum's values: rule "r" compares "status" with "closd", which is not one of its enum values. Otherwise any string is allowed.
  • Hint for a missing const: { "equal": ["status", "closed"] } still means two paths. That read now points at the string forms: ... has type string, not integer or boolean: a string property is compared with a { "const": ... } by equal or notEqual, or with the strings an in lists.
  • Node cost: a const counts as one node, so equal of a path and a const costs 3 nodes, the same as comparing a path with a number. An in over strings costs 2 plus one per value.

Code

  • property_constraints/mod.rs:
    • PropertyConstraint::TextCompare { comparison, path, value } (the constant is normalised to one side, so either spelling is the same condition) and TextIn { path, values: BTreeSet<String> };
    • PropertyRead::Text and text_constants();
    • parsing via text_comparison and in_text_values;
    • evaluation via text_value.
  • try_from_schema/mod.rs:
    • the Text read check and the enum check;
    • is_key_id_schema's $ref-following schema walker extracted as schema_at_path, which both now use. Behaviour is unchanged, since it returns None exactly where the old code returned false.
  • Meta-schema v3: const (a string) as an operand key, and in values that are all integers or all strings, plus description updates.
  • Docs: v14 note 39, the book, the js-evo-sdk README, and the SystemLimits, DocumentTypeV2 and PROPERTY_CONSTRAINTS docs.

How Has This Been Tested?

  • property_constraints/tests.rs:
    • parsing both spellings and string in;
    • every refusal with its location: ordering with a const, a non-string const, two consts, a const against an expression, a const inside arithmetic, string in shape, mixed and duplicate values;
    • evaluation against a matching string, another string, a different case, the empty string, null, a non-string value and a missing property;
    • node counts, read kinds, text_constants, and the either-side repeat.
  • try_from_schema/v3/property_constraints_tests.rs (the order schema gains an enum state):
    • on both paths, string comparisons on an enum property, a property without an enum and a nested one;
    • enum typos in equal and in in refused;
    • wrong types refused (integer, boolean, missing, object), a transient string refused, and the string-read hint;
    • meta-schema refusals of a non-string const and bad string in lists.
  • drive-abci batch/tests/document/property_constraints.rs: the offer fixture gains an enum status and a closedAt, with closedNeedsClosedAt (notEqual/const) and closedAtOnlyWhenClosed (string in). should_compare_a_string_property_with_constants runs real creates (two refused with 10422, three accepted).
  • cargo test -p dpp --lib (4862 passed), cargo test -p drive-abci --lib property_constraints (13 passed), cargo clippy -p dpp --all-features --all-targets -- -D warnings, cargo clippy -p drive-abci --all-targets -- -D warnings.

Breaking Changes

Consensus, protocol version 14 only: contracts may now register rules comparing string properties with constants, which earlier 4.2 builds refuse. Meta-schema v3, parse_property_constraints 0 and validate_property_constraints 0 were introduced in protocol version 14, which is not released on mainnet, so they are extended in place. Every declaration valid before parses and evaluates identically. is_key_id_schema (the encryptedFor key id check) was refactored without behaviour change.

Rust API: PropertyConstraint gains TextCompare and TextIn, and PropertyRead gains Text.

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

For repository code-owners and collaborators only

  • I have assigned this pull request to a milestone

🤖 Generated with Claude Code

PR Hygiene · 4626038

  • Bots — coderabbitai ✓ · 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 failed
  • Approvals
    • files with no dedicated owner — you own it
    • js-wasm-sdk (packages/js-evo-sdk/README.md) — shumkov
    • dpp — you own it
    • rs-drive-abci — you own it

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

Summary by CodeRabbit

  • New Features
    • Property constraints can now compare string properties with string constants and check whether string properties match one of several distinct values.
    • String constants used with enum-constrained properties must be valid enum values. Missing or non-string properties do not match equality or membership conditions.
    • String comparisons support equality and inequality; membership checks support lists of at least two distinct values.
  • Documentation
    • Updated guidance and examples describe string constraints, validation rules, and their behavior.

…es (PV14)

A propertyConstraints rule may now compare a string property with string
constants: `{ "equal": [path, { "const": "closed" }] }` or notEqual,
either way round, and `{ "in": [path, ["open", "pending"]] }`. Strings are
only compared for equality; a string the document leaves out equals no
constant. When the property declares an enum, every constant compared
with it must be one of its values, so a typo is refused at registration.

is_key_id_schema's $ref-following walker is extracted as schema_at_path,
shared with the enum check, without behaviour change.

Extended in place in meta-schema v3 and parse_property_constraints 0:
every declaration valid before parses and evaluates as it did.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added this to the v4.2.0 milestone Sep 27, 2026
@github-actions

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-27T08:24:12.993Z

@coderabbitai

coderabbitai Bot commented Sep 27, 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: 7068f222-cc2c-4eda-bc03-dbeb8b000671

📥 Commits

Reviewing files that changed from the base of the PR and between 7a57518 and 4626038.

📒 Files selected for processing (12)
  • book/src/data-model/documents.md
  • packages/js-evo-sdk/README.md
  • packages/rs-dpp/schema/meta_schemas/document/v3/document-meta.json
  • packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/mod.rs
  • packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v3/property_constraints_tests.rs
  • packages/rs-dpp/src/data_contract/document_type/mod.rs
  • packages/rs-dpp/src/data_contract/document_type/property_constraints/mod.rs
  • packages/rs-dpp/src/data_contract/document_type/property_constraints/tests.rs
  • packages/rs-dpp/src/data_contract/document_type/v2/mod.rs
  • packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/property_constraints.rs
  • packages/rs-platform-version/src/version/system_limits/mod.rs
  • packages/rs-platform-version/src/version/v14.rs

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


📝 Walkthrough

Walkthrough

Property constraints now support string-property equality, inequality, and membership conditions. Schema validation checks property types and enum values. Tests and documentation cover the new forms and their behavior for missing or non-string values.

Changes

String property constraints

Layer / File(s) Summary
Parse and evaluate string constraints
packages/rs-dpp/src/data_contract/document_type/property_constraints/mod.rs, packages/rs-dpp/src/data_contract/document_type/property_constraints/tests.rs
The parser and model support string equality, inequality, and membership conditions. Evaluation, property-read tracking, node counts, and duplicate-condition detection include the new forms.
Validate string constraints against schemas
packages/rs-dpp/schema/meta_schemas/document/v3/document-meta.json, packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/...
The v3 meta-schema accepts string constraints. Document schema validation checks string property types and enum membership. Tests cover valid rules, invalid values and types, and malformed membership lists.
Exercise and document string constraints
packages/rs-drive-abci/src/execution/validation/.../property_constraints.rs, book/src/data-model/documents.md, packages/js-evo-sdk/README.md, packages/rs-dpp/src/data_contract/document_type/{mod.rs,v2/mod.rs}, packages/rs-platform-version/src/version/{system_limits/mod.rs,v14.rs}
Integration tests exercise status-dependent closedAt constraints. Documentation describes string rules, enum requirements, missing-value behavior, and node counts.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Feature

Suggested reviewers: shumkov

Merge Risk: ⚪ Minimal · up to 46260

The string constraints remain scoped to version 14, and enum constants are validated. No identified issue blocks merging after normal checks.

Security Architecture Review

Security architecture risk: 🟡 Moderate · up to 46260

String-based rules can now determine whether contracts and document writes are accepted. The inspected registration and validation paths retain type, enum, size, and protocol-version controls, and no concrete security bypass was established. Direct evidence for string rules on replacement and recovery paths remains limited, so the consensus impact warrants review.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The directly evidenced exposure is acceptance of contracts and document writes subject to their rules across consensus validators, rather than a new cross-service privilege path. The maximum downstream deployment exposure was not established.

Trust Boundaries and Controls

  • observed — Author-supplied rule paths and constants are checked at registration against property types, transient-property restrictions, and declared enums; transition-supplied values pass document-schema validation before a constraint failure is reported.

Resilience and Maintainability Implications

  • observed — The inspected replacement path invokes the same document-property validator as creation and returns an invalid result before subsequent replacement checks. Direct string-specific evidence for replacement, interruption, retry, and recovery outcomes remains limited.

Hardening Proposals

  • proposed — Before enabling this consensus behavior in a deployment, exercise string-rule rejection and retained state through protocol-14 replacement, repeated submissions, and recovery, alongside the existing creation coverage.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately identifies the main feature: string equality for enum properties in propertyConstraints rules for protocol version 14. It does not mention string membership checks, but the titl…
Docstring Coverage ✅ Passed Docstring coverage is 85.71% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 35 functions across 9 files. (3 skipped: 3 …
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.
✨ Finishing Touches
📝 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 the waiting-bots Waiting for the review bots to report on this head label Sep 27, 2026
@thepastaclaw

thepastaclaw commented Sep 27, 2026 •

Copy link
Copy Markdown
Collaborator

🕓 Queued for automated review — 2nd in line, estimated start in ~15 min (commit 4626038)
Estimated review time once started: ~1.0 h (two-phase automated review; median of recent runs).

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

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