A Type 2 sample is supposed to show the control operated during the observation window. What assessors still get is a folder of screenshots taken in month one, copied forward, and re-uploaded when the PBC list arrives. SOC 2 evidence freshness tracking is the small system we put in front of that folder: every artifact has a TTL, a collected_at, and a stale flag. If the sample is due on Friday, you do not discover on Thursday that the access-review export is ten months old.
This is not a new GRC product. It is a freshness layer on the store you already have — Drive, the GRC evidence locker, or the mapped store from SOC 2 ISO 27001 control mapping. AICPA SOC 2 Type 2 is about operating effectiveness over time. A single early screenshot is Type 1-shaped evidence wearing a Type 2 filename. See SOC 2 Type 1 vs Type 2 evidence.
Why SOC 2 Evidence Freshness Tracking Exists
Access reviews expire. Config drifts. A CloudTrail screenshot from the first month does not prove logging still worked in month nine. A terminated-user export from onboarding week does not prove CC6.3 removal still ran in the last quarter of the window.
Human coordinators remember some of this. They do not remember 80 artifacts across 20 systems. TTL is the reminder that does not take vacation.
The TTL Model We Attach
Each evidence type gets a default TTL. Each artifact instance gets collected_at and stale_at = collected_at + ttl.
| Evidence type | Typical TTL | Why |
|---|---|---|
| Quarterly access review packet | 1 quarter + grace | CC6.2 is periodic |
| Termination sample (rolling) | 30 days | Must reflect recent leavers |
| IdP / AWS config screenshot | 30 days | Config drifts |
| CI OIDC trust policy | 60 days | Changes with repos |
| Policy PDF | 1 year or next approval | Slow-moving; still has an expiry |
| Continuous log proof | 7–14 days | Point-in-time is weak; refresh often |
"Ten months" is the failure the search query is about: a screenshot that survived almost the entire Type 2 window without a refresh. We treat that as stale even if someone renamed the file final-final.
def freshness(artifact, as_of):
stale_at = artifact.collected_at + timedelta(days=artifact.ttl_days)
return {
"id": artifact.id,
"control": artifact.control_ids,
"collected_at": artifact.collected_at,
"stale_at": stale_at,
"is_stale": as_of >= stale_at,
"days_left": (stale_at - as_of).days,
}
A nightly job writes is_stale and opens a ticket (or a GRC task) when days_left drops under a threshold. The PBC export excludes stale artifacts by default. You can still attach one with an override reason. That override is visible. Silent reuse is the bug.
Sampling Across the Window, Not Once
Type 2 testers pick dates inside the window. Freshness tracking therefore stores more than the latest file. We keep dated generations: Q1 review, Q2 review, Q3 review. The stale flag applies per generation. "We have an access review" is not the same as "we have an access review in the sampled quarter."
For continuous controls (logging, backups), we prefer a job that emits a small proof on a schedule — "restore test passed," "log destination still accepting" — over a heroic screenshot. AWS-ready architecture already has the telemetry. Freshness is making sure the proof is in the locker and not only in CloudWatch.
What We Flag Besides Age
- Hash collision with a new filename — same bytes, new name, "updated" metadata. We hash on ingest.
- Wrong window — artifact collected outside the observation period tagged on the campaign.
- Wrong system — a staging screenshot filed under a production control. Owner + source_system on the record.
- Missing successor — TTL elapsed and no newer artifact for that control. That is a coverage hole, not just a stale row.
SOC 2 access review packets are the highest-volume stale source we see. Config screenshots are second. Policy PDFs are rarely the problem; they are the excuse for not refreshing the first two.
How This Sits Next to Gap Analysis
Gap analysis automation finds systems with no artifact. Freshness finds systems with an old artifact. Both write into the same backlog. Mixing them into one "red/yellow/green" without saying which is which makes engineers refresh a screenshot when they should have built logging.
We do not claim the control is effective because the file is fresh. Fresh means eligible for the sample. Effective is the assessor's call.
Delivery Shape
For a mid-market locker:
- Inventory existing evidence objects (or start from the mapped store)
- Tag type → TTL
- Backfill
collected_atfrom file timestamps where honest, else mark unknown (unknown is stale) - Turn on the nightly flag + PBC filter
- Wire refresh jobs for the types we already automate (access exports, CloudTrail proofs)
The ceiling is a scheduled scanner over a catalog, not a new platform. If the catalog is 10,000 objects of scanned PDFs with no type, the first week is classification. We will say that up front.
SOC 2 evidence freshness tracking is security automation on the compliance locker. Internal-tool artifacts still need evidence for internal tools before they can have a TTL.
Ask us what your GRC platform is not covering: rutagon.com/contact · 907-841-8407 · contact@rutagon.com.
Frequently Asked Questions
What TTL should a Type 2 config screenshot have?
Thirty days is the default we use unless the control is truly static and the assessor has agreed a longer cycle. A screenshot from the first month of a long window is the failure this article is about.
Can we keep a stale artifact "for history"?
Yes. It stays in the store with is_stale=true. It does not appear in the default PBC packet. History is not a sample.
Does freshness tracking prove operating effectiveness?
No. It proves you did not submit an out-of-date file. The assessor still tests whether the control operated.
How do you detect a renamed duplicate screenshot?
Content hash on ingest. Same bytes and a new name still counts as the old collection time.
What if we do not know when a Drive file was actually captured?
We mark collected_at unknown and treat the artifact as stale until someone recaptures it. Guessing a date from memory is how ten-month screenshots survive.