Validation Policy
Which inputs are accepted, rejected, normalized, or allowed to fall back.
31 items in this guidance cluster.
Tagged guidance
Guide item
Boundary rules
Choose Resource Identity ModelBOUNDARY-CHOOSE-RESOURCE-IDENTITY-MODELDecide whether the boundary mutates records, sets, files, sessions, handles, or whole documents before designing reconciliation. The chosen unit controls idempotency, matching, conflict handling, and the cost of later migration.Distinguish Input ClassesBOUNDARY-DISTINGUISH-INPUT-CLASSESKeep unknown, unsupported, denied, and preserved inputs in separate result or error paths. The distinction protects compatibility, authorization messaging, and recovery behavior while allowing small internal parsers to stay simpler.Ground Integrations In Primary SourcesBOUNDARY-GROUND-INTEGRATIONS-IN-PRIMARY-SOURCESBase adapter behavior on provider docs, specs, or captured API responses before encoding local assumptions. When primary sources are incomplete, label observations and inferences so guesses do not become fake guarantees.Make Ambient Inputs ExplicitBOUNDARY-MAKE-AMBIENT-INPUTS-EXPLICITPass time, randomness, environment, locale, terminal size, network clients, and process state through visible inputs when they affect behavior. Injecting only the relevant ambient values improves tests and portability without spreading oversized context objects.Make Dynamic Conflicts DeterministicBOUNDARY-MAKE-DYNAMIC-CONFLICTS-DETERMINISTICDefine stable ordering, duplicate handling, priority, or override policy for dynamic registrations. Deterministic conflict behavior prevents hash order or load timing from changing which plugin, guest, generated item, or handler wins.Make Policy Boundaries ExplicitBOUNDARY-MAKE-POLICY-BOUNDARIES-EXPLICITRoute writes, network calls, shell execution, publication, telemetry, redaction, and credential use through a visible policy decision before effects run. Callers can then understand allowed, denied, redacted, fallback, preserved, and unsupported outcomes.Model Real Upstream SurfaceBOUNDARY-MODEL-REAL-UPSTREAM-SURFACEShape local integration APIs around the providers actual records, pages, permissions, rate limits, and consistency behavior. Wrappers may simplify common paths, but they should not promise capabilities the upstream cannot provide.Parse Uncertainty At EdgeBOUNDARY-PARSE-UNCERTAINTY-AT-EDGEParse and validate raw strings, JSON, CLI args, provider responses, and user input at the boundary before passing values inward. Core logic receives typed invariants, while domain-specific checks that require later context remain explicit policy decisions.Read Normalize Compare MutateBOUNDARY-READ-NORMALIZE-COMPARE-MUTATEReconcile external state by reading the current provider view, normalizing it, comparing intent, and mutating only the real difference. The loop avoids destructive or noisy writes when formatting, defaults, ordering, or outside actors create drift.Reject Unsupported ShapesBOUNDARY-REJECT-UNSUPPORTED-SHAPESFail unsupported names, values, TTLs, targets, record families, protocols, or modes at the boundary with clear errors. Preserve unknown data only when compatibility requires round-tripping and the system can do so safely.
Refactoring rules
Rust rules
Document Public Panic ContractsRUST-DOCUMENT-PUBLIC-PANIC-CONTRACTSDocument when public APIs can panic and what callers can do to avoid it. Panic contracts keep recoverable errors, invariants, and misuse boundaries explicit.Name Auditable IntermediatesRUST-NAME-AUDITABLE-INTERMEDIATESIntroduce named locals where parsing, validation, rendering, ownership, or side-effect decisions need review. Avoid naming every trivial expression when it would add ceremony without clarifying the boundary.Prefer Constructors And Conversion TraitsRUST-PREFER-CONSTRUCTORS-AND-CONVERSION-TRAITSUse inherent constructors and standard conversion traits to show whether construction builds, validates, converts, borrows, allocates, or can fail. Prefer public fields only when direct construction is truly part of the contract.Shape Expressions For AuditabilityRUST-SHAPE-EXPRESSIONS-FOR-AUDITABILITYShape complex expressions so ownership, validation, error handling, and side effects can be audited at the point they occur. Break chains or introduce names when density hides a decision readers must verify.Use Builders For Optional Or Validated FieldsRUST-USE-BUILDERS-FOR-OPTIONAL-OR-VALIDATED-FIELDSUse builders when construction has many optional inputs or cross-field validation that would make constructors hard to read. Avoid builder APIs for simple values where direct construction communicates the contract better.Use Debug Assert For Internal InvariantsRUST-USE-DEBUG-ASSERT-FOR-INTERNAL-INVARIANTSUse debug assertions for internal invariants that should hold if nearby code is correct. Do not use them for caller validation or safety requirements that must be enforced in release builds.Use Meaningful Standard TypesRUST-USE-MEANINGFUL-STANDARD-TYPESPrefer standard or ecosystem types that encode ownership, units, paths, durations, optionality, and invariants better than raw strings or integers. Use domain newtypes when the standard type cannot prevent meaningful mixups.Validate Builders On BuildRUST-VALIDATE-BUILDERS-ON-BUILDValidate cross-field builder invariants in build where partial configuration becomes a usable value. Keep build infallible only when defaults and setters make invalid states impossible.
Testing rules
Check Important Feature CombinationsTEST-CHECK-IMPORTANT-FEATURE-COMBINATIONSExercise default, disabled-default, all-feature, and important feature-pair builds. Feature flags change APIs and compile paths, so use a risk-based matrix instead of every combo.Choose Validation by RiskTEST-CHOOSE-VALIDATION-BY-RISKMatch the amount and kind of validation to the changed surface and failure cost. Cheap checks come first, but risky or uncertain behavior needs targeted evidence.Cover Policy OutcomesTEST-COVER-POLICY-OUTCOMESTest allowed, denied, redacted, fallback, and unsupported policy outcomes. Policy value lives at decision boundaries, so assert caller-visible behavior instead of internals.Fuzz Parsers, Formatters, and State MachinesTEST-FUZZ-PARSERS-FORMATTERS-AND-STATE-MACHINESUse fuzzing or property tests for input-heavy parsers, formatters, and state machines. Large input spaces hide failures, so keep long fuzzing outside PR gates unless it is stable.Use Realistic Parser SamplesTEST-USE-REALISTIC-PARSER-SAMPLESTest parsers with representative input, malformed cases, and safe degradation examples. Real samples catch compatibility failures, but fixtures should be minimized and scrubbed.
Pattern items
Avoid Boolean Flag Parametersavoid-boolean-flag-parametersBehavioral boolean flags make call sites depend on hidden ordering and branch semantics. Distinguish them from boolean domain data, then prefer named operations, enums, options types, or builders when the caller selects behavior.Make Invalid States Hard To Expressmake-invalid-states-hard-to-expressRepeated validation spreads invariants across callers and lets unchecked values travel too far. Move the rule into a construction boundary or precise type when that reduces downstream reasoning without adding local ceremony.Make Validation Policy Explicitmake-validation-policy-explicitValidation rules often differ by workflow even when they touch the same field. Name the policy at the boundary with distinct constructors, modes, policy types, or parsed values once real competing rules exist.Parse Dont Validateparse-dont-validateValidation that returns raw values forces callers to remember which invariants already hold. Parse uncertain input into types that carry those invariants, using constructors or standard parsing traits that honestly match the boundary.Prefer Standard Conversionsprefer-standard-conversionsProject-specific conversion names make APIs harder to predict when standard traits already describe the relationship. Use standard conversions only when their semantics are honest, and choose explicit domain methods for lossy, contextual, or surprising operations.