What is a policy rule's input contract, and what does it pin down?
answer
- the document, not the template
- who produces it, what is guaranteed
- envelope, fields, version
- optional fields handled deliberately
- fixtures are instances of the contract
basics
~10 sThe input contract is the written agreement about the document a rule decides over: which step produces it, how it is wrapped, and which fields are guaranteed present. Agree it before writing the rule.
solid answer
~50 sA rule is a function over one document, so before writing it you write down what that document is. The contract names the producing step - for example the fully rendered manifest that the CI render step feeds the gate, not the template it came from - describes the envelope around it, and splits fields into guaranteed, optional, and producer-defaulted. The rule may only depend on the guaranteed ones; anything optional has to be handled deliberately. Fixtures are then written as valid instances of that same contract, so tests and the live gate see the same shape. For a rule that secrets must not reach a container as environment variables, the contract has to say that the input is a rendered workload manifest, that containers appear in more than one list, and that `env` and `envFrom` may each be absent.
go deeper
Be ready to say plainly that a rule decides over one document, and that the contract states which step produced it and which fields are always there. Name a concrete example of an optional field.
Explain the three buckets — guaranteed, optional, producer-defaulted — and why a rule may only lean on the first. Be able to walk the difference between a template, a rendered document and a live object.
Show how you make the contract executable: a conformance check over captured real output, so drift in the producer fails a build instead of quietly disabling a gate. Expect to be asked what you did when a rule turned out to never fire.
Own the contract as an interface between the team that produces the document and the team that writes rules, including who is allowed to change it, how the change is announced and what evidence exists that the rules kept matching.
## A rule is a function over one document A policy rule does not go looking for facts. It is a decision computed from a single document handed to it by whatever component enforces the gate. That document is the rule's **input**, and the **input contract** is the written statement of what it is — agreed before the rule is written, kept next to the rule, and changed together with it. A usable contract answers four questions. **1. Which step produces it.** Name the producer, not the artefact family. In a chart-based pipeline there are at least three documents in play: the template with its placeholders, the rendered output after values are applied, and the object that eventually lives in the cluster after defaulting. They do not have the same shape, and a rule written against one of them is wrong about the other two. "The manifest emitted by the render step in CI, before it is applied anywhere" is a contract; "the Kubernetes YAML" is not. **2. What the envelope is.** Is the rule handed a bare object, a list of objects, a multi-document stream, or an object nested under a key? Half of the "my rule matches nothing" reports are an envelope mismatch: the author tested against a single manifest and the gate feeds a list of everything the chart rendered. **3. Which fields are guaranteed.** This is the heart of it. Every field falls into one of three buckets: *guaranteed* (the producer emits it on every document), *optional* (it appears only when the author wrote it), and *defaulted* (the producer fills it in when absent, so the rule never sees it missing). For a rule about secrets reaching a process environment, the relevant fields are the container lists — `spec.template.spec.containers` plus `initContainers`, and `ephemeralContainers` where they can occur — and, inside each container, the `env` list, each entry's `value` or `valueFrom`, and `envFrom`. Nearly all of those are optional: a container that sets no environment simply has no `env` key. A rule that assumes the key exists carries an unstated dependency, and unstated dependencies are what make gates behave differently from their tests. **4. Which version of the document this contract describes**, so that a change to the producer's output is a visible change to a named thing rather than a surprise. ## Depend only on what the producer guarantees Renderers and pipelines emit conveniences — a normalised label, an annotation most charts happen to set, a summary block. Keying a rule off one is tempting because the rule gets shorter. It is also the quietest way to build a rule that never fires: a document that omits the convenience field simply does not match, no error is raised, and the gate reports green forever. The working rule of thumb is that if the producer does not promise a field on *every* document, the rule may not treat its absence as evidence of anything. ## Contract first, rule second Writing the rule first inverts the dependency: whatever happened to be in the author's editor buffer becomes the de facto contract, and it is discovered months later by whoever is debugging the gate. Writing the contract first forces the two decisions that actually matter — which producer, and which fields are safe to lean on — while they are still cheap to change. It also gives the reviewer something to review other than the rule's syntax. ## The contract is what makes the rule testable A fixture is just a document, and a fixture is only meaningful if it is a valid instance of the contract. Once the contract is written down, two things become possible that are not possible without it: fixtures can be checked for conformance rather than trusted, and a captured sample of real producer output can be validated against the declared shape in CI, so drift in the producer becomes a failing build rather than a silent hole in enforcement. ## What the contract is not It is not the list of things the rule denies — that is the rule. It is not the shape of the decision the rule returns, which is a separate agreement with whatever consumes the verdict and message. And it is not a wish list: anything the rule needs that the document does not carry is a negotiation with the producer, not something the rule can improvise around.
- Your pipeline has a chart, a rendered manifest and a live object. Which one does the contract name?Whichever document the gate actually hands the engine at the point you are enforcing. If the gate runs at the CI render step, the contract describes the rendered output after values and overlays are applied. Templates are not valid documents at all until rendered, and the live object has been through defaulting the render step never performed, so naming the wrong one gives you a rule whose fixtures can never match production.
- Besides field names, what else belongs in an input contract?The producing step and the point in the pipeline it runs at; the envelope, including whether the input is one document or a collection; for each field, whether it is guaranteed, optional or producer-defaulted; the encoding of values that are ambiguous, such as a quantity written as a string versus a number; and a version identifier for the shape itself, so a change to the producer is a visible event.
- How do you keep the contract from rotting once the rule ships?Store it beside the rule so a reviewer sees both in the same diff, and back it with an executable check: validate a captured sample of real producer output against the declared shape on every CI run. A contract nobody executes degrades into a comment. One that fails the build when the producer's output stops matching stays true.
It is the function signature you agree before writing the function body: caller, argument shape, which arguments are always supplied.
saying these in an interview costs you the question
- Treats the source template as the document the rule reads
- Assumes every optional field is always present
- Writes the rule first and infers the input shape later
- Thinks the contract is just a list of field names
- Depends on a convenience field the producer never promised