Implementation pattern

Making content governance executable, not advisory

A written claims policy does not survive contact with a deadline. Here is the pattern that made it a build failure instead — a typed register, a single rendering path, and a verifier that refuses to ship an unapproved figure.

Every organisation that publishes client results has a rule about which ones it is allowed to publish. Almost none of those rules are enforced by anything. They are enforced by a person remembering, on the day the page is built, under time pressure — which is the exact condition under which a rule is most likely to be missed and least likely to be noticed afterwards.

Why a document is not a control

A governance document has no failure mode. It cannot be violated, because violating it produces no signal — the page simply publishes, and nothing distinguishes the compliant build from the non-compliant one. A control has to be able to fail visibly and stop something, or it is a description of intent rather than a constraint.

The test is simple: if someone published an unapproved figure tomorrow, what happens? If the honest answer is "somebody might notice", the policy is advisory regardless of how well it is written.

The pattern: a register with an approval record

Each publishable claim becomes a typed record carrying the claim text, its evidence class, its source, and an explicit approval. The approval names who authorised it, on what date, and on what basis — because an approval that exists only in a conversation is indistinguishable from an oversight when someone reviews the code a year later.

A claim record. `approved` is the switch; `approval` is the audit trail
                      export interface ClaimRecord {
  id: string;
  /** The claim as it would be published. */
  text: string;
  /** Evidence class — public, internal, or unverified. */
  class: ClaimClass;
  /** Where it came from, so a reviewer can check it. */
  source: string;
  /** Whether it may render its figure today. */
  approved: boolean;
  /**
   * Who cleared it, when, and on what basis. Not optional in practice: an
   * approval with no record cannot be distinguished from a mistake later.
   */
  approval?: { by: string; on: string; basis: string };
  note?: string;
}
                    

The pattern: one rendering path

The register only works if there is exactly one way for a number to reach a page. If a figure can be typed directly into a component, the register is decorative. So the rendering component takes the claim ID, asks the register, and renders either the figure or a description of what was measured — never both, and never a raw string.

The gate. Unknown IDs return false, so a typo removes a number rather than publishing one
                      export function isApproved(claimId: string): boolean {
  // Safe default: a typo in a claim ID hides a figure rather than revealing one.
  return CLAIMS[claimId]?.approved === true;
}

/**
 * Render the value, or the fallback when the claim is not cleared.
 * Every metric on the site goes through this — there is no other path.
 */
export function metricValue(metric: Metric): string {
  return isApproved(metric.claim) ? metric.value : metric.fallback;
}
                    

The pattern: verify in CI, not in review

A build step asserts things a reviewer would have to check by hand: that no page emits a figure whose claim is unapproved, that no metric is simultaneously gated and cleared, and that a forbidden schema type appears nowhere. This is what converts the policy from advice into a build failure.

The verifier earns its place the first time it blocks a change that looked correct. It also changes the review conversation — instead of asking whether a number is approved, a reviewer asks whether the build passes, which is a question with an answer rather than an opinion.

What this buys you beyond compliance

  • Approving a claim is one line, with an audit trail — so it happens quickly rather than becoming a project.
  • Withdrawing a figure is also one line, and the fallback copy is already written.
  • A reader can see what is gated and what is not, because the rendering differs visibly.
  • The register becomes the place to look when someone asks why a number is missing.
  • Editorial pressure to publish an unapproved figure produces a build error, which is a much easier conversation than a judgement call.

The pattern is not specific to marketing claims. The same shape applies to any assertion that needs a gate — regulatory statements, security posture, performance figures. What it requires is that the assertion has an identity, that one place renders it, and that something fails when the gate is closed.

Where this applies

If this is the problem you are looking at

The procedure is more useful applied than read. Tell us what you are seeing and we will say whether it sounds like the same fault.