Summary
RuleDocumentation cannot express an object property allowlist — a fixed set of permitted keys with additionalProperties: false. A SelfDocumentingRule for a rule that constrains an object's shape (allowed keys, an enum of keys) can therefore only degrade to a description-only type: object.
Motivation (dogfooding: a private consumer app)
Implementing SelfDocumentingRule on the app's custom rules (rule.unknown 128 → 9) surfaced this. App\Rules\KeysIn (used 26 times) validates that an object contains only a fixed set of keys:
readonly class KeysIn implements ValidationRule
{
public function __construct(protected array $values, ...) {}
// passes when array_diff_key($value, array_flip($this->values)) === []
}
The faithful schema is { type: object, additionalProperties: false, properties: { <key>: {}, … } } (or at least the allowed key set), but RuleDocumentation has no field for it, so the best achievable is:
new RuleDocumentation(
description: 'An object limited to these keys: a, b, c.',
type: 'object',
);
The constraint survives only as prose.
Proposed enhancement
Add optional fields to RuleDocumentation for object-shape constraints, applied by the same "write only when the descriptor has no value yet" merge policy as the existing fields:
additionalProperties: bool|null (emit additionalProperties: false).
propertyNames: list<string>|null — the allowed key set. Either materialise properties: { key: {} } for each, or emit a JSON-Schema propertyNames: { enum: [...] }.
(Naming/shape open to design — the point is a first-class way to express "these keys, nothing else".)
Scope
Small, additive VO change plus the write path in ValidationRulesToSchema (or wherever RuleDocumentation is applied to a field descriptor). No behavioural change for rules that don't set the new fields.
Notes
Found while implementing SelfDocumentingRule across 8 real custom rules; KeysIn was the only one the VO could not represent faithfully.
Summary
RuleDocumentationcannot express an object property allowlist — a fixed set of permitted keys withadditionalProperties: false. ASelfDocumentingRulefor a rule that constrains an object's shape (allowed keys, an enum of keys) can therefore only degrade to a description-onlytype: object.Motivation (dogfooding: a private consumer app)
Implementing
SelfDocumentingRuleon the app's custom rules (rule.unknown 128 → 9) surfaced this.App\Rules\KeysIn(used 26 times) validates that an object contains only a fixed set of keys:The faithful schema is
{ type: object, additionalProperties: false, properties: { <key>: {}, … } }(or at least the allowed key set), butRuleDocumentationhas no field for it, so the best achievable is:The constraint survives only as prose.
Proposed enhancement
Add optional fields to
RuleDocumentationfor object-shape constraints, applied by the same "write only when the descriptor has no value yet" merge policy as the existing fields:additionalProperties: bool|null(emitadditionalProperties: false).propertyNames: list<string>|null— the allowed key set. Either materialiseproperties: { key: {} }for each, or emit a JSON-SchemapropertyNames: { enum: [...] }.(Naming/shape open to design — the point is a first-class way to express "these keys, nothing else".)
Scope
Small, additive VO change plus the write path in
ValidationRulesToSchema(or whereverRuleDocumentationis applied to a field descriptor). No behavioural change for rules that don't set the new fields.Notes
Found while implementing
SelfDocumentingRuleacross 8 real custom rules;KeysInwas the only one the VO could not represent faithfully.