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

Pattern items

Principle item