skip to content

A rule defaults audit-log retention to 30 days; another denies anything under 90. How do you fix this?

level: seniorimportance: should knowfreq 47%

answer

  1. the denied value came from your own rule
  2. validation judges the rewritten input
  3. absent-only, or unconditional overwrite?
  4. one writer per field
  5. unit tests pass, composition fails

basics

~20 s

Two rules own the same field with different intents: validation judges the value the defaulting rule just wrote. Give the field one authority - make the default compliant - and test the two rules together rather than separately.

solid answer

~50 s

The symptom is the giveaway: developers are denied over a value none of them wrote. Validation judges the post-mutation input, so the author of the rejected 30 is our own defaulting rule - and if that rule overwrites present values rather than only filling absent ones, no edit the developer makes will help. That is the first thing I check. The fix is to give the field one authority: if the platform sets a default, the default must satisfy the standard, so raise it to what the requirement actually says; if the value legitimately varies, default only when the field is absent and let the validating rule own the bound. Then add a composition fixture - each rule passes its own unit tests, and the contradiction exists only when they run together. I treat a denial citing a value no user supplied as a policy-set bug, routed to the policy owner rather than the blocked team.

go deeper

for a junior

Understand that a policy set can change a submitted value before another rule inspects it, so a rejected value is not always one the author typed.

for a middle

Explain why validation sees the post-mutation input, and what changes when a defaulting rule fills only absent fields versus overwriting values that are already set.

for a senior

Diagnose the pair from the symptom, choose a resolution that gives the field one authority, and describe the composition fixture that would have caught it before release.

for a principal

Own the boundary case: a platform default and a security rule owned by different teams that disagree. Decide who arbitrates, how field ownership is recorded, and what makes a self-inflicted denial an incident.

## What the developer sees, and why it is unfixable from their side A change is submitted with no retention set, or with retention set to something the team chose. The gate returns a denial saying retention must be at least 90 days, current value 30. The team searches their own configuration for 30 and does not find it. If they add 90 explicitly and the defaulting rule overwrites present values rather than only filling absent ones, they get the identical denial again. From the outside this is indistinguishable from a broken gate, and it burns exactly the credibility that guardrails run on. The mechanism is simple once stated: when a policy set both rewrites and judges, the judging rules see the rewritten input. The value being rejected was written by a peer rule, not by the submitter. ## The diagnostic questions, in order 1. **Does the mutation apply unconditionally, or only when the field is absent?** This single fact decides whether the blocked team has any path forward at all. Unconditional overwrite means no self-service fix exists, and it should be treated as a production incident in the policy set. 2. **Which rule is right about the requirement?** Somebody wrote 30 and somebody wrote 90, and at least one of them is not reading the current standard. Frequently the default was correct under an older requirement and was never revisited when the number moved. 3. **Do the two rules have the same owner?** A contradiction between two rules from one team is a bug. A contradiction between a platform default and a security rule is a boundary problem, and the fix has to be agreed rather than merged. 4. **How many other fields are written by one rule and judged by another?** This pair is rarely alone. The same shape produces the same outage the next time a threshold moves. ## Fixing it There is no ordering knob that resolves this. In almost every gate design a single denial is final, so no arrangement lets the mutating rule 'win'; precedence has to be authored, not configured. Three durable resolutions, in decreasing order of preference: - **Make the default compliant.** If the platform is going to set the value, it must set one that passes. A default that manufactures violations is a bug in the default. This also collapses the two rules' disagreement into one recorded number. - **Make the mutation fill only what is absent, and let validation own the bound.** The defaulting rule supplies a compliant starting value for teams that express no opinion; teams that do express one keep it, and the validating rule is the single authority on what is acceptable. This is the right shape when the value legitimately varies by workload. - **Delete one of them.** If the default is the only thing that ever sets the field and it is compliant, the validating rule may be a candidate for retirement - but only after you have established that nothing else can write that field. ## Why your tests missed it Because they tested rules, and this is a property of the set. Each rule is individually correct: the defaulting rule reliably writes 30, the validating rule reliably rejects anything below 90. The defect exists only in composition. The test that catches it evaluates the whole policy set against a realistic input and asserts the final outcome - and it must include the input that carries **no** value for the field, because that is the one that triggers the mutation. Add the case where the field is present and non-default, too: that is how you assert the mutation does not overwrite. ## Preventing the class, not the instance - **Record field ownership.** For each field the policy set writes, name the one rule allowed to write it. A second writer needs a decision, not a merge. - **Test the set, not the rules.** Every change to the policy set runs composition fixtures. Unit tests per rule stay useful; they are just not sufficient. - **Surface the provenance in the message.** A denial that says the value was supplied by a platform default, rather than presenting it as the submitter's, turns an unfixable mystery into an actionable report. The message is part of the control. - **Route the report correctly.** A denial whose cited value the submitter never wrote is not their problem to debug. Treat it as a defect against the policy set's owner, with the same urgency as any other gate malfunction, because that is what it is. ## The judgment being tested Interviewers ask this to see whether you distinguish a rule that is wrong from a policy set that is inconsistent. The instinct to raise 30 to 90 and move on fixes today's denial; the answer they are looking for also explains why the pair could exist, what test would have caught it, and how you stop the next field with two writers from doing it again.

  • The blocked team asks how to unblock themselves today. What do you tell them?
    That depends on the first diagnostic: if the mutation only fills an absent field, setting a compliant value in their own configuration works immediately. If it overwrites, nothing they can do will help, and I say so plainly rather than sending them to try edits - then the unblock is a change to the policy set, owned by us, on the same clock as any other gate outage.
  • Would you resolve this by giving the validating rule precedence over the mutating one?
    Precedence does not exist in the way that question implies - a denial is terminal, so the validating rule already wins, and its win is the outage. What is missing is authorship, not ordering: one rule must own the field's value. Configurable priority between them would only move the argument into configuration.
  • What test would have caught this before it reached anyone?
    A fixture that runs the whole policy set against an input with no retention field set and asserts the final decision is allow. Both rules pass their own tests; only the composed evaluation of an input that triggers the default reveals the contradiction. I would add the field-already-present case in the same fixture to pin the mutation's behaviour.

saying these in an interview costs you the question

  • Blames the submitting team for a value a rule wrote
  • Proposes an ordering or priority setting as the fix
  • Assumes per-rule unit tests would have caught a composition defect
  • Raises the default without asking which number the standard requires
  • Leaves two rules writing and judging the same field with no owner

context