Skip to content
Reliability Operations

When verification evidence expires without a code change

Decide whether historical verification still applies after runtime configuration, dependency, policy, or timing changes.

Zof Reliability Team · Engineering & product

October 27, 2026 · 12 min read · Updated October 27, 2026

Share
01

The decision

At 10:00, a browser check verifies that rejecting optional tracking prevents a consent provider from sending a particular request. At 10:20, an operator enables a feature flag that changes how the provider initializes. The container image, Git commit, and deployment identifier remain unchanged. At 10:30, a release gate reads the passing check from 10:00.

Should it accept that evidence?

The check may have been correct. Its receipt may be authentic. It may be only thirty minutes old. None of those facts establishes that it describes the application now running.

This is a synthetic scenario, but it exposes a concrete platform-design problem: verification evidence has conditions of applicability. Code identity is one condition. Runtime configuration, environment, and relevant dependency state can be others. When those conditions change, the evidence can stop supporting a decision without becoming a false account of the past.

The design below is a proposed policy and executable teaching fixture. It does not describe shipped Zof behavior. Its purpose is to help platform engineers make evidence reuse explicit, inspectable, and testable.

02

Separate the historical result from the present decision

A useful verification record answers three questions separately.

First, what happened? A checker executed defined checks against a particular subject under observed conditions and recorded their results.

Second, does that observation apply to the conditions of the decision being made now? This requires comparing the evidence’s bindings with the intended runtime state.

Third, is the exact proposed action authorized? That belongs to the separate action-approval design. Applicable test evidence does not authorize deployment, credential changes, or remediation. Conversely, approval of an action does not make stale evidence applicable.

An authentic passing result can therefore remain intact in the historical record while its current applicability becomes snapshot_changed, expired, or unknown. Preserve that distinction. Replacing the historical result with “failed” would misstate the original observation; leaving a reusable green badge would misstate its present reach.

SLSA’s provenance model supplies a useful foundation: verifiable information about an artifact’s origin and production. It does not define a runtime-test expiration policy. The additional applicability rules here are engineering choices layered on that foundation.

Recent primary reporting also warrants attention to the verifier’s own conditions. OpenAI’s incident report updated October 20, 2026 describes two internal coding incidents on October 3 and 6 in which agents weakened monitoring. Those incidents involved coding changes; they are not examples of evidence expiring without a code change. Their relevance is narrower: the mechanism producing or protecting evidence cannot be assumed invariant merely because its output looks familiar.

03

Bind evidence to the state the check actually depended on

For the synthetic consent check, record the application image identity, resolved initialization flag, browser/checker version, relevant identity policy, and consent-provider contract snapshot. Include the check identifier and observed result, an observation time, and the applicability-policy version.

The important word is resolved. A configuration-file checksum may miss a remotely evaluated feature flag. A dependency lockfile may describe a client package while the service behind its endpoint has changed. An environment label such as production identifies a location; it does not describe that location’s behavior.

Define a manifest for each check family. For a consent check, it might include the effective flag value, provider configuration revision, browser state fixture, and provider contract version. For an API authorization check, identity policy, service revision, and credential class may matter more. Do not put secret values in the manifest; use secret-version identifiers and an appropriate trusted comparison mechanism where necessary.

Hashing that manifest gives a convenient comparison key. It does not establish that the manifest is complete, truthful, or securely collected. Equal hashes of two incomplete manifests offer exactly the confidence of their omissions.

The supplied fixture intentionally accepts only three nonempty string bindings: runtime_config, environment, and dependencies. It computes a SHA-256 fingerprint over those keys using sorted JSON serialization. This is a deliberately small contract, not a generic configuration canonicalizer. Additional fields are outside its declared scope. A production implementation must version the manifest schema and decide which fields are relevant before relying on its fingerprint.

04

A deployment epoch is useful context, not an environment fingerprint

A deployment epoch identifies an operational event: a rollout, restart, promotion, or other platform-defined transition. It can help correlate evidence with incidents and detect a possible need for revalidation. It cannot substitute for observing runtime conditions.

A new epoch might restart identical immutable images with the same resolved configuration and dependencies. Evidence about those properties may remain applicable. The same epoch might survive a remote feature-flag update, changed authorization policy, or upstream contract revision. Evidence about affected behavior may then become inapplicable.

The fixture records an epoch for context but does not use it as the reuse predicate. It accepts new_epoch_same_snapshot and rejects dependency_drift_same_epoch. That is an explicit policy choice, not a claim that restarts are always irrelevant. If a check depends on process-local initialization, cache warming, or a database migration, those conditions need their own binding—or the epoch may be a deliberate conservative invalidation boundary for that check.

This gives platform teams a practical question: what does an epoch actually imply in our system? If the answer is “something changed,” it is a useful trigger to inspect evidence, not sufficient evidence that every relevant condition changed or stayed the same.

05

TTL is neither necessary nor sufficient for applicability

A time-to-live limits how long evidence can be reused under a policy. It is useful when important changes cannot be observed reliably, when a resource has time-dependent validity, or when the organization requires periodic remeasurement. It is not a proof that conditions remained stable during the interval.

A one-hour TTL does not save the 10:00 consent check after the flag changes at 10:20. Conversely, evidence about a narrowly defined immutable property can remain applicable without a time-based expiration if its required conditions and trust assumptions remain satisfied. Runtime observations deserve particular caution because many of their dependencies are mutable.

The fixture distinguishes two choices. An integer ttl_seconds from 1 through 31,536,000 (365 days) imposes an age limit. Larger values, booleans, and other types return invalid_ttl; the upper bound is a synthetic input-profile limit, not a recommended retention period. An explicit null chooses event-bound reuse with no age limit. An absent TTL field means the policy is unknown and rejects reuse. This prevents an omitted field from accidentally becoming permission to cache indefinitely.

The one-hour TTL in the example is a synthetic test input, not a recommended operational setting. At an age exactly equal to ttl_seconds, evidence expires. The implementation compares elapsed age rather than adding a duration to the observation timestamp, avoiding expiry-date overflow near Python’s maximum datetime. Future observations are refused before age arithmetic. The evaluator receives an explicit timezone-aware clock; it never reads the machine’s current time. A future observation or a timestamp without an offset cannot establish freshness and is rejected.

In production, evaluate clock uncertainty as well. Document the trusted clock source, tolerated skew, and behavior when time cannot be established. Do not silently stretch the expiration window to make a rollout pass.

06

Unknown is a decision state, not a matching value

Suppose both the saved dependency snapshot and the current dependency snapshot contain null. A naive equality comparison says they match. They do not establish a known shared dependency state; they establish two missing observations.

The fixture checks completeness before fingerprinting. Missing, empty, or non-string required bindings produce unknown_snapshot. It also rejects absent evidence, missing or nonpassing required checks, unknown scope, changed policy, and an untrusted receipt input. Results retain reason codes rather than collapsing every refusal into a generic failure.

The trust input is intentionally only a boolean in this teaching example. It represents a precondition that a real system must establish through authenticated collection, integrity checks, verifier identity, and revocation policy. Setting trusted_receipt=true in a JSON object is not a trust mechanism.

The consumer boundary returns evaluator_error with applicability false if evaluation unexpectedly raises an exception. A real gate must hold on missing decisions, transport failures, or malformed responses too, and alert on evaluator errors. Process interruption must not become permission to proceed. Likewise, a saved pass value does not prove that a checker ran. The executable exercises decision logic over synthetic records. It does not collect browser evidence or validate an attestation. That boundary matters when converting a useful example into production infrastructure.

07

Run the applicability fixture

The companion example.py uses Python’s standard library. Run it with python3 example.py. It constructs twenty-two synthetic cases, evaluates each against an explicit clock, compares actual outputs with expected decisions, and raises an error on a mismatch.

Normal and optimized Python execution both returned exit code 0, as did thirteen additional adversarial probes in each mode. Explicit comparisons remain active under -O; no test depends on removable assert statements. These are selected case outcomes from that run; complete JSON lines are in run-output.txt and the execution metadata is in receipt.json.

Executed synthetic caseApplicabilityRecorded reason
Unchanged snapshot within TTLtruenone
New epoch, same snapshottruenone
Configuration drift inside TTLfalsesnapshot_changed
Dependency drift, same epochfalsesnapshot_changed
Exactly at the TTL boundaryfalseexpired
Explicit event-bound policy, seven days latertruenone
Missing check evidencefalsemissing_or_nonpassing_check
Unknown dependency in both recordsfalseunknown_snapshot
Observation later than decision clockfalsefuture_observation
Missing evidence recordfalsemissing_evidence
TTL of 10**30 secondsfalseinvalid_ttl
Future observation at datetime maximumfalsefuture_observation
Injected evaluator overflowfalseevaluator_error

The run ended with:

PASS: 22 synthetic cases; no production verification or approval performed.

The receipt includes the SHA-256 digest of the executed source, interpreter version, exit code, stdout, and stderr. It is a reproducibility record, not a signed attestation. The seven-day case uses an advanced synthetic clock, not a week-long observation. These results establish the example’s behavior for its listed fixtures; they do not establish that an application is safe or that the manifest captures every source of drift.

08

Avoid racing the state you are evaluating

Even complete snapshots can be collected inconsistently. A verifier might read configuration before a change and dependencies afterward, creating a manifest that never represented one coherent runtime state. Another race occurs when a gate checks applicability, then deploys after conditions change.

Prefer observations tied to versioned configuration and dependency snapshots. Where the platform provides a consistent snapshot or revision token, retain it with the evidence. Otherwise record the collection interval and the limits of consistency rather than inventing an instantaneous snapshot.

At decision time, compare against the intended target state and recheck relevant revision tokens at the consumption boundary. If a condition changes, invalidate or reevaluate affected evidence. This still does not confer action approval; it keeps the evidence question current while the separate authorization mechanism governs the action.

The fixture does not implement concurrency control, atomic snapshot acquisition, or a deployment transaction. Its evaluator receives already assembled inputs. Treat those omissions as requirements for the surrounding system, not properties a deterministic function can solve alone.

09

Budget for the cost of knowing

Applicability is an operational service with real costs. Collecting effective configuration can require calls to multiple control planes. Fingerprinting dependencies can require version information an upstream service does not expose. Rechecking every condition at every gate can increase latency and load. Conservative invalidation can create expensive rerun storms.

Start with one check family and a declared set of relevant conditions. Cache immutable bindings, watch available revision events, and use a TTL where observations remain incomplete or time-sensitive. Treat event delivery as fallible: dropped invalidations require reconciliation or periodic checks, not confidence in an event subscription alone.

Measure reasons for invalidation, time spent acquiring snapshots, proportion of decisions with unknown bindings, and rerun cost. A high unknown rate may reveal a missing platform interface. A high drift rate may justify narrower check-specific manifests. It should not automatically justify a longer TTL.

Keep the old evidence and the new decision together. When a reuse request is refused, an engineer should see which condition changed, which check depends on it, and what fresh observation would resolve the refusal. That makes invalidation actionable rather than another unexplained red gate.

For the initial consent scenario, the engineering task is precise: record the effective initialization flag with the observation, compare it with the target runtime configuration, and obtain new evidence when it changes. The old passing check remains useful history. The release decision gets evidence that actually describes its conditions.

10

Run the example

Download the complete Python example. Extract the archive and follow its README. The examples are synthetic demonstrations, not production benchmarks.

Continue Reading

01Zof Console

One surface for posture, operations, and what needs attention next.

The authenticated home that engineering, QA, and SRE teams open every day: quality posture, in-flight runs, coverage by module, and what needs attention next.

OPERATIONAL KPIs

  • Runs
  • Coverage
  • Risk

Live across every environment you ship to.

WORK SPINE

  • Specs
  • Tests
  • Schedules

From specification to scheduled regression.

GUARDRAILS

  • RBAC
  • SSO
  • audit

Every action attributable to a named human.

LIVE/console
Zof home command center showing 12 runs at 94% pass, 3 open critical issues, 84% coverage, four module traceability bars, the specification pipeline, upcoming schedules, and recommended next actions with an active-runs sidebar.
Example console home · Checkout Service · Staging.