Why must a policy rule carry a stable id and an owner, not just a title?
answer
- titles get reworded
- something else must be the handle
- waivers and suppressions point at it
- stable for the life of the rule
- owner and remediation link ride alongside
basics
~20 sA rule's id is the handle everything outside the rule keys on: waivers, suppressions, control maps, dashboards. Titles get reworded, so they cannot be that handle. The owner tells a blocked engineer who to ask.
solid answer
~40 sA title is prose for humans and gets reworded the moment somebody improves the wording. Everything machine-readable keys on the id instead: the waiver that exempts one repo, a suppression sitting in someone else's manifest, the row in a control map, the dashboard counting violations over a quarter. So the id has to be stable for the life of the rule - chosen once, never edited for cosmetics, and retired rather than reused when the rule dies. Alongside it every rule should carry a human title, a named owning team, a severity or class, and a remediation link. That metadata is what turns a denial from "the build failed" into "this rule, owned by these people, and here is the change that fixes it".
go deeper
Be ready to say what an id is for as opposed to a title, and to name the metadata a rule carries: id, title, owner, severity, remediation link.
Explain what breaks when an id changes - waivers, suppressions, control-map rows and violation trends all key on it, and none of them raise an error when the key stops matching.
Show you enforce it: the rule library's own checks reject a rule with no owner or remediation link, and an id change is handled as a breaking change with an alias and a deprecation window.
Own the position that rule ids are a published interface. Decide the naming scheme, who may mint or retire an id, and the deprecation policy every consuming team can rely on.
## A rule is referred to from places that do not contain it A policy rule is written once and then referenced from a dozen places that hold none of its logic. A waiver register says "this repository is exempt from that rule until the migration lands". A suppression sits in a manifest in a team's own repository. A row in a control map tells an auditor which running check stands behind which written control. A dashboard plots how often the rule fired last quarter. An alert routes its failures. A ticket template links to it. None of those hold the rule; all of them hold a **reference** to it. The id is that reference, and that is the entire argument for making it stable. ## Title versus id The **title** is one line of prose aimed at a person reading a build log. It is meant to be improved. "Container must not run as root" becomes "Containers must run as a non-root user" because somebody thought the second reads better. Nothing breaks, because nothing keys on it. The **id** is a machine-readable name - something like `licence-class` or `workload.runtime.non-root` - and it is the only thing other systems are allowed to match on. Change it and every reference breaks at once. The sharp part is that **most of those breakages are silent**: a waiver whose key matches no rule does not raise an error, it simply stops exempting anything; a control-map row pointing at an id nobody emits any more does not fail a build, it just stops describing reality; a dashboard filtered on the old id shows the violation count falling to zero, which reads like success. So the discipline is: the id is chosen once, never edited to fix a typo or improve wording, never reused for a different rule after the original is retired. Reuse is the worst of the three, because stale references do not merely stop matching - they start matching **different logic**, so an exemption written for one check silently begins excusing another. ## The metadata every rule carries A rule that is only logic is unusable at scale. The block around it typically carries: - **id** - stable, machine-readable, unique across the whole library, chosen with a namespacing scheme so two teams cannot mint the same name. - **title** - one line of human prose; free to change. - **description** - what the rule checks and, briefly, why the guardrail exists. - **owner** - a team handle, not an individual. This is the name a blocked engineer contacts and the name that answers when the rule turns out to be wrong. - **severity or class** - what the decision point does with the result, and how urgently anyone should care. - **remediation link** - a page that tells the person who was just blocked what to change. Not the rule source; the fix. A useful test for whether the metadata is real: can a developer who has never heard of the policy library read a single denial message and, without asking anyone, know what tripped, who owns it, and what to change? If the answer needs a Slack search, the metadata is decorative. ## Ids are an interface you publish Once a rule library has consumers - waivers, suppressions, control maps, reports - its ids are a published interface, exactly like a REST path or a column name. That has consequences a junior can already state: - Adding an id is safe. Changing one is a breaking change. - If an id genuinely has to change, the old one is kept as an alias for a deprecation window so both resolve, consumers are migrated, and only then is the old one retired. - Retirement is permanent. A retired id stays resolvable as "retired" rather than being handed to a new rule. ## Enforcing it in the library itself The rule repository's own checks are the cheapest place to hold the line: reject a rule with no owner, no remediation link, or an id that does not match the naming scheme; fail the build if two rules share an id; fail it if an id present in the previous release has vanished without a deprecation marker. That last check is what turns "please do not rename ids" from a convention people forget into something the library refuses to ship.
- A rule is retired. Can its id be handed to a new rule later?No. Old waivers, suppressions, dashboards and control-map rows still carry that id, and reuse silently re-points them at different logic - an exemption written for the retired check starts excusing the new one. Retire the id permanently, keep it resolvable as deprecated, and mint a fresh id for the new rule.
- Should the remediation link point at the rule's source or at a fix guide?At a fix guide written for the person who was blocked: what is wrong, what a compliant version looks like, and what to do if the rule is wrong here. The rule source is for the rule's owner and for reviewers; a developer reading policy code to work out what to change is a sign the metadata failed.
- What does the owner field actually have to promise?That someone answers. The owner triages "this blocked me and I think it is wrong", can approve a change to the rule, and is accountable for its false-positive rate. A team handle survives people leaving; a named individual does not, and an unowned rule is one nobody dares to change or delete.
The title is the label on a filing cabinet drawer; the id is the account number on every document inside. Relabel the drawer and nothing is lost - renumber the accounts and every cross-reference in the building points at nothing.
saying these in an interview costs you the question
- Says the rule's title is a good enough identifier
- Edits an id to fix a typo or improve the wording
- Reuses a retired rule's id for a new check
- Ships rules with no owner, so denials have nobody to ask
- Treats rule metadata as a scanner's output rather than part of the rule