Blog · 2026-06-10 · ~12 min read
The security ADR: how to document decisions that affect threat model, data handling, or compliance scope
A Series A startup begins SOC 2 Type II audit prep. The auditor asks a reasonable question: what is your decision record for storing customer PII, what encryption decisions were made, and who reviewed those decisions before they went to production? The answer from the engineering team is honest and common: there isn't a formal record. The engineer who made the original data model decision moved on eight months ago. The choices about what to store, how long to keep it, and how to protect it at rest were made over a series of late-night Claude sessions during the initial build sprint. The reasoning was sound. Nobody wrote it down in a form that survives the engineer's departure and stands up to an external review. The startup now has two options: (1) document the decisions retrospectively, which means their accuracy depends on the memories of people who weren't in the room, or (2) recover the decision history from AI chat exports, which is what the original engineer's sessions actually contain. This is not an edge case. Every engineering team that reaches compliance audit stage has some version of this problem. The decisions that get reconstructed most painfully in the room with an auditor are the ones that were made carefully, by engineers who thought deeply about the trade-offs — in AI chat sessions that nobody ever exported.
TL;DR
Security decisions — those affecting threat model, data handling, encryption, access controls, or compliance scope — require a different ADR format than standard service-local decisions. The standard Nygard template's Consequences section doesn't distinguish accepted risks from desired outcomes, has no security reviewer field, no compliance scope annotation, and no review cadence. A security ADR adds five fields: threat model scope, data classification, compliance scope, security reviewers, and review triggers. It also has a classification problem: some security ADR content reveals attack surface and belongs in a private record, not a public ADR repository. The WhyChose extractor recovers the compliance research and security deliberation that engineers conducted in AI chat — the sessions where the actual trade-offs were worked out — before that reasoning is lost entirely.
What makes a decision security-relevant
Most architecture decisions don't have a compliance footprint. Choosing a background job library, picking a caching strategy, deciding how to structure the internal domain model — these are consequential decisions, but they don't implicate regulatory frameworks or create obligations for external review. Security decisions are different in kind.
Four categories reliably produce security-relevant decisions:
- Threat model decisions. Who the system trusts, what it treats as untrusted input, where the trust boundary sits, and what attack classes the system is designed to resist. A decision to move from internal-only to external-facing traffic is a threat model decision. A decision to treat authenticated sessions as fully trusted for all operations is a threat model decision. A decision to accept rate-limiting via API gateway rather than per-endpoint logic is a threat model decision. These don't look like "security decisions" when you're writing them — they look like system design choices — but they define the envelope inside which every other security control operates.
- Data handling decisions. What data is stored, for how long, in what form, and who can access it. Data handling decisions are the most audit-visible category because they appear directly in data processing registers, privacy policies, and compliance control listings. Storing email addresses for billing purposes is a data handling decision. Storing user-generated content indefinitely by default is a data handling decision. Sending PII to a third-party analytics service is a data handling decision that likely has a regulatory implication even if the engineering team thinks of it as a product choice.
- Compliance scope decisions. Any decision that expands or contracts which regulatory frameworks apply to a system's data processing. Adding a field for date of birth to a user profile may bring processing into age-verification regulatory scope. Integrating with a health-adjacent data source may bring PHI into scope under HIPAA. Expanding sales to EU residents makes every subsequent data processing decision a potential GDPR Article 6 question. These scope-expansion decisions are particularly expensive when undocumented, because auditors ask not just "what are your current controls?" but "when did you become aware this data type was in scope, and what decision did you make at that point?"
- Access control architecture. Who can read, write, or administer which resources, and how that access is enforced and audited. RBAC vs. ABAC, the decision about which roles have production database access, the decision to log versus not log certain access events, the decision about service-to-service authentication — all of these are access control decisions with audit implications. The compliance question for access controls is almost always: "what is the principle of least privilege decision here, and how was it arrived at?"
The practical test: if a hypothetical auditor — for SOC 2, GDPR, HIPAA, or an internal security review — would ask "what was the decision and what was the review process for it?", the decision needs a security ADR. When in doubt, err toward documenting it. An over-documented security decision log creates mild overhead; an under-documented one creates real liability at exactly the moment you can least afford it.
Why the standard ADR template falls short for security decisions
The standard Nygard ADR format — Title, Status, Context, Decision, Consequences — is purpose-built for technical decisions. Its Consequences section is designed to capture what becomes easier, what becomes harder, and what technical debt is accepted. This is the right structure for a background job library choice. It is incomplete for a security decision for three specific reasons.
First, the Consequences section conflates desired outcomes with accepted risks. When a security decision accepts a known risk — "we chose not to implement per-operation audit logging because the performance overhead is unacceptable at our current query volume; this means we cannot reconstruct exact read histories for audit purposes" — that accepted risk needs to be explicitly labeled as such, separated from the positive outcomes. In a standard Consequences section, it gets buried in a bullet point alongside "reduces database CPU by 12%." Auditors look for explicit risk acceptance statements, not inferred ones buried in trade-off lists.
Second, the standard template has no security reviewer field. The author and the technical decision-maker are the same person. For compliance purposes, the review by the security function is part of what the ADR needs to document — not just what was decided, but who reviewed it before it went to production. A SOC 2 auditor asking about your encryption-at-rest decision will want to know whether that decision was reviewed by someone other than the engineer who implemented it. The standard ADR format has no place to record this.
Third, most ADRs are written once and considered done. The lifecycle model for standard ADRs treats Accepted status as stable until the decision is explicitly superseded or deprecated. Security decisions don't work this way — their validity depends on external conditions that the engineering team doesn't control. An access control decision that was correct in 2023 may be wrong in 2026 if the threat model changed, the regulatory guidance updated, or the third-party processor you rely on for GDPR Article 28 compliance was acquired and changed their DPA. The standard ADR template has no mechanism for encoding when a security decision should be revisited.
The standard Markdown ADR template and MADR share these same gaps — they're both extensions of the Nygard model optimized for technical decision documentation, not compliance documentation. The additional fields a security ADR requires have to be added as a team-level convention; no standard template includes them by default.
The five fields a security ADR adds
These five fields are what distinguish an audit-ready security ADR from a general-purpose one. They sit below the standard Consequences section and above any Further Reading or related ADRs:
- Threat model scope. What threats does this decision address, and what threats does it explicitly accept or defer? This is different from the Context section, which describes the technical situation. The threat model scope section answers: what is the attack class this decision is designed to resist, and what remains in-scope as accepted risk? Example: "This decision addresses server-side injection attacks and CSRF. It does not address client-side session theft (mitigated at the browser layer by HttpOnly cookie flags, addressed in ADR-0019) or supply chain attacks on npm dependencies (not in scope for this decision)."
- Data classification. What is the sensitivity level of the data this decision affects? Use whatever classification tiers your organization has defined (public, internal, confidential, restricted; or public, PII, PHI, payment data). If no organizational classification exists, define it in the ADR. Naming the data classification makes compliance scope questions answerable in thirty seconds rather than requiring a review of the full Context section to infer what kind of data is involved.
- Compliance scope. Which regulatory frameworks does this decision implicate, and does the decision expand or reduce the organization's scope under those frameworks? This field should be explicit about what it doesn't cover: if the team has reviewed the decision against GDPR and concluded it doesn't expand PHI scope, saying so creates an auditable record of that review, not just silence that an auditor might interpret as unawareness.
- Security reviewers. Who from outside the implementing team reviewed this decision before production deployment? This is the field auditors look for when they ask about the "four eyes principle" for security-sensitive changes. The reviewer should be named (not just "security team") with a link to their written sign-off — a GitHub PR review, a comment on the RFC document, or a dated email. If no external review occurred (which is common for early-stage startups), that should be explicitly stated, with a note on when external review will be introduced into the process. Honest gaps are better than silent ones.
- Review triggers. When should this decision be revisited, and what changes in the environment would require re-evaluation? Review triggers come in two forms: time-based ("review by 2027-Q2") and event-based ("review if service becomes externally accessible" or "review if we add a data processing agreement with a new third party"). Both can coexist in the same ADR. The time-based trigger handles the case where external conditions change and nobody notices; the event-based trigger handles the case where a known decision node arrives. At minimum, every security ADR should have one review trigger that would force it back into consideration when the threat model changes.
These five fields add roughly a paragraph each to the typical ADR. For a decision record that an auditor may review multiple years later, that overhead is trivially small relative to the value of having the record be self-contained and answerable without requiring the original author to be present.
The classification problem
Security ADRs have a structural tension that other ADR types don't: some of the information that makes them accurate and useful is also information that should not be in a public or broadly-accessible document. An ADR that documents "we do not validate X input parameter at the service layer because we rely on the API gateway to reject malformed requests" is operationally honest and important for future engineers to understand. It is also a statement about where a potential attack vector exists if the API gateway assumption ever breaks.
Two approaches handle this at different scales. For most engineering teams with small, trusted engineering organizations, the right approach is abstraction in the public ADR with a private operational record. The public ADR documents the decision at the class level: "Input validation is handled at the API gateway layer. Service-layer validation is scoped to business logic constraints, not security constraints. See SECURITY-RUNBOOK-007 for the operational specifics." The runbook lives in a private repository with access controls matching the team's data classification policy. Auditors get access to the runbook during the audit; the public ADR remains honest without being a roadmap.
For larger organizations with a dedicated security function, security ADRs may be designated as internal-only from creation — not in the engineering team's public ADR repository but in a security-controlled decision log with appropriate access controls. A public summary ADR can reference the internal record by ID: "See SECURITY-ADR-0042 (internal, security-team access) for the full decision record on access control architecture." This approach provides the audit trail without the exposure risk, and the ADR governance model for the organization can codify which decision types go to which repository.
The worst outcome is splitting the decision across both places without a clear link — public ADR that documents the positive framing without the accepted risks, private runbook that has the operational specifics but no connection back to the decision record. Auditors who find this pattern during preparation will ask which document is authoritative, and the honest answer ("neither, you have to read both") is the worst possible one. The link between the public summary and the private record should be explicit and bidirectional.
Compliance documentation as the primary value
For most engineering teams, the day-to-day value of a security ADR is the same as any ADR: future engineers understand why the system is built the way it is, and revisiting decisions doesn't require finding and interviewing the original author. But there is a secondary, episodic value that is orders of magnitude larger: the security ADR is compliance documentation.
SOC 2 audits ask whether security controls were deliberately designed and formally reviewed. The question isn't just "do you have encryption at rest?" — any auditor can check that by looking at the infrastructure configuration. The question is "what was the decision process for choosing this encryption approach, who reviewed it, and what alternatives were considered and rejected?" A security ADR answers this question in one document. The absence of such a record means reconstructing the decision in the audit room from memory, which is the most expensive and least reliable way to make the case that the decision was made thoughtfully.
GDPR compliance documentation follows the same pattern. Article 5's accountability principle requires organizations to be able to demonstrate compliance with GDPR principles — not just implement them. A decision record for every significant data processing choice (what data is stored, under which legal basis, for how long, with which processors) is the documentation layer that makes "demonstrating compliance" feasible. Without it, a data subject access request or a regulator inquiry requires the engineering team to reconstruct which decisions expanded what scope, when, and why — typically from code commits and whatever Slack threads survived the retention window.
The pattern is consistent: the value of compliance documentation is zero until the audit, and then it is extremely high. This is why security ADRs tend to be written after the compliance event rather than before it — the organizational motivation only arrives at the worst possible time. The quarterly decision review is the right structural intervention: it forces security decision documentation before the audit clock starts, as a regular cadence rather than a crisis response.
The review cadence requirement
Standard ADR lifecycle management treats most decisions as stable once Accepted, revisited only when explicitly superseded by a new decision. A security ADR that documents encryption choices from 2023 is not necessarily valid in 2026 — not because the decision was wrong at the time, but because the conditions that made it right may have changed without anyone having a mechanism to notice.
Four categories of change invalidate security ADR assumptions:
- Threat model evolution. A service designed for internal-only traffic has a dramatically different threat model than the same service after a decision to expose it externally. If the threat model change is documented as a separate ADR (as it should be per the cross-team ADR model — exposing a service externally is a cross-cutting decision that affects every downstream consumer), then security ADRs that carry "scope: internal traffic only" in their threat model section are automatically flagged for review. If the threat model change isn't documented, those ADRs continue to be referenced without anyone noticing the mismatch.
- Compliance requirement changes. Regulatory guidance updates. Enforcement interpretations shift after a landmark ruling. A new regulation comes into effect that applies to processing the team is already doing. These changes are invisible inside the ADR repository — the original decision remains marked Accepted even though the compliance basis has changed. Only an explicit time-based review trigger causes someone to re-read the decision with current regulatory knowledge.
- Cryptographic standard evolution. Algorithm deprecations are predictable but not self-executing. A decision to use SHA-256 for a specific purpose doesn't automatically become a problem the day SHA-256 is downgraded in a new NIST publication — but it does become a problem on the day someone exploits the weakness, and the ADR is still marked Accepted. Event-based review triggers wired to the organization's cryptography policy review cadence are the right mechanism.
- Third-party processor changes. A GDPR Article 28 decision to use a specific data processor is valid until that processor is acquired, changes their DPA, or has a security incident that changes their compliance posture. The original security ADR documents the processor selection decision; the review trigger should be "re-evaluate if processor DPA changes or processor is acquired."
Review triggers don't require the team to redo the decision every time they fire. Most security ADRs will be re-reviewed and confirmed as still valid — the threat model hasn't changed, the compliance basis is still sound, the cryptographic choice is still current. The value of the trigger is the forced re-read: someone with current knowledge of the threat landscape and regulatory environment confirms that the decision's conditions haven't changed. When they have changed, the review trigger is what surfaces that before it becomes a liability.
What AI chat reveals about security decisions
Security decisions have disproportionately rich AI chat footprints. When engineers are working out security and compliance trade-offs, they tend to use AI chat as a research and thinking partner for longer than they do for purely technical decisions — because the domain is broader, less certain, and more dependent on interpreting regulatory language that isn't resolved by reading the code.
The specific sessions worth extracting for security decision recovery:
- Compliance research sessions. Sessions where an engineer is asking "is this GDPR compliant?", "what legal basis applies to storing X?", or "what does SOC 2 require for encryption at rest?" These sessions contain the original compliance thinking — the questions the engineer had, the interpretations they received, the uncertainty they worked through. The extractor captures these as high-confidence decision records because they contain explicit question shapes ("which should we choose?") and trade-off markers ("the advantage of X is compliance-coverage, the disadvantage is Y user friction").
- Threat modeling sessions. Sessions where an engineer is working through what an attacker could do, what they're designing against, and what they're accepting as out-of-scope. These look less like formal threat model documents and more like "okay so if someone could do X, what stops them?" followed by "we're relying on Y to handle Z." The extractor's commit phrase patterns ("we'll rely on," "the assumption is," "we trust the gateway to") are strong signals for threat model decisions.
- Pre-launch security review sessions. Many engineering teams do an informal security pass before launch — working through their own threat model with an AI assistant rather than a formal security review. These sessions often produce the most comprehensive record of what was considered and what was decided, because the engineer is explicitly trying to find gaps. If this session happened, the extractor will surface multiple high-confidence records from a concentrated date window just before the launch commit.
The startup in the opening scenario — going into SOC 2 prep without documented security decisions — typically finds that all of the material decisions are present in the founding engineer's AI chat history. The PII storage decision, the encryption choice, the access control architecture, the accepted risks — these were worked out in Claude or ChatGPT sessions that still exist in the export. Recovery protocol: export ChatGPT history and Claude conversations for each engineer who was involved in the early system design; run the extractor; look specifically for the compliance-research-pattern records (question shapes + regulatory terms + trade-off markers); write up the recovered reasoning as security ADRs with a note that the original decision was made contemporaneously but the formal record is being written retrospectively from recovered AI chat deliberation. Most SOC 2 auditors accept retrospective documentation when it can be corroborated by code commit dates and deployment history.
A security ADR template
The following template extends the standard Markdown ADR format with the five security-specific sections. All standard fields are preserved for compatibility with existing ADR tooling that parses by section heading:
# ADR-0019: Authentication — JWT with short-lived tokens, HttpOnly cookies for session state
**Date:** 2026-01-15
**Status:** Accepted
**Deciders:** Backend lead, mobile lead (reviewer)
**Security reviewer:** @securitylead — review on file at [link to PR comment]
## Context
The system needs to authenticate API requests from web and mobile clients. Options evaluated:
(1) Long-lived API keys with manual rotation, (2) OAuth 2.0 with third-party IdP,
(3) JWT with server-side validation and short-lived tokens, (4) Session cookies only.
## Decision
JWT with 15-minute access tokens and 7-day HttpOnly secure cookie for refresh state.
Server-side token invalidation via a deny-list in Redis (O(1) lookup per request).
## Consequences
Access tokens expire after 15 minutes, limiting the blast radius of token theft.
The Redis deny-list adds ~2ms per authenticated request (acceptable at current scale).
Mobile clients handle token refresh automatically via the refresh-token flow.
The deny-list grows unbounded until pruned; a scheduled job clears expired entries nightly.
## Threat model scope
**Addressed:** Session hijacking via XSS (mitigated by HttpOnly; JS cannot read the
refresh cookie). Token theft via network interception (mitigated by HTTPS-only
with HSTS; token lifetime limits blast radius). Replay attacks (mitigated by
deny-list invalidation on logout and token rotation on refresh).
**Accepted risk:** Compromised refresh token valid for up to 7 days if deny-list
is bypassed (e.g., Redis unavailable during outage — fail-open configuration).
Mitigation: fail-closed option documented in SECURITY-RUNBOOK-004 for future review.
**Out of scope:** Credential stuffing (handled at rate-limiting layer, ADR-0022).
Social engineering (out of technical scope).
## Data classification
Authentication tokens are classified as **Confidential** (internal). Refresh cookies
contain no PII; access tokens contain user ID and role claims only.
## Compliance scope
This decision does not expand GDPR personal data scope (user ID is a pseudonym;
role claims are internal system data). This decision satisfies SOC 2 CC6.1
(logical access controls) and CC6.3 (user identity management). No HIPAA scope.
## Security reviewers
- @securitylead: reviewed 2026-01-13, approved — [link to review comment]
- Architecture review board: reviewed 2026-01-14, no objections — [link to meeting notes]
## Review triggers
- **Time-based:** Review by 2027-Q1 for algorithm currency and library dependency audit.
- **Event-based:** Review if system expands to handle PHI (HIPAA scope implication).
- **Event-based:** Review if Redis is removed from the stack (deny-list assumption broken).
- **Event-based:** Review if any JWT library CVE is issued against our dependency version.
The accepted risk block in the Threat model scope section is the most practically important addition. It creates an explicit, readable statement of what the team accepted rather than requiring an auditor to infer accepted risks from absence of coverage. When the startup in the opening scenario recovers their original security decisions from AI chat, the accepted risk reasoning is almost always present — engineers naturally articulate what they're accepting in AI sessions, because that's the framing they use when working through trade-offs with an AI assistant. The recovery-to-ADR pipeline for this section is usually direct.
The compliance scope section should err toward over-specificity. Saying "no HIPAA scope" when the team has verified this is different from simply not mentioning HIPAA — the explicit statement creates an auditable record of review, not just an inference from silence. This distinction matters when the system's data handling expands in scope later: an ADR that explicitly says "no HIPAA scope as of 2026-01-15" combined with a later ADR that says "HIPAA scope added as of 2027-03-01" creates a clear timeline. An ADR that never mentioned HIPAA combined with a later ADR that adds HIPAA scope leaves a gap in the record that auditors will ask about.
Security ADRs and the quarterly review
The quarterly decision review is the right cadence for auditing the security ADR log for stale threat model assumptions and elapsed review triggers. Two questions identify security ADRs that need re-evaluation in the quarterly pass:
- "Has the threat model scope in this ADR's threat model section changed since the decision was made?" The most common signal: a decision that says "scope: internal services only" for a service that has since been exposed externally. If the threat model expansion was documented as a separate decision (as it should be), the link between the two ADRs surfaces the stale security ADR automatically. If it wasn't documented separately — which is why cross-cutting decisions need their own records — the quarterly review is the safety net.
- "Have any event-based triggers in this ADR fired since the last review?" Review triggers only work if someone checks them. The quarterly review is the check. A team that has documented good review triggers but never reads them has the same outcome as a team with no triggers at all.
Security ADRs promoted from AI chat recovery during the quarterly review should note their recovery provenance. This matters for audit purposes: "Decision made 2024-03-12, formal record written 2026-Q1 from recovered AI chat history (ChatGPT export sessions 2024-03-10 to 2024-03-14, confirmed by deployment timestamps in git history)" is an honest and defensible record. Auditors who understand how engineering actually works — which most do — accept this provenance. What they don't accept is a record written after an audit inquiry without any provenance statement at all.
Recover your security decision history before the audit call
The compliance research and threat-modeling deliberation that happened in AI chat sessions is the most complete record of why your security decisions were made. The WhyChose open-source extractor surfaces these from your ChatGPT and Claude exports — look for the compliance-research pattern (question shapes + regulatory terms + trade-off markers) and the pre-launch security review session cluster (high-confidence records concentrated in the date window before your first production deployment). Running the extractor before SOC 2 or GDPR documentation prep is substantially faster than reconstructing decisions from memory with an auditor on the call.
Join the waitlist for the hosted service — the Pro tier's cross-session linking connects scattered compliance research sessions to the same decision topic across months of chat history.
Further reading
- Nygard ADR template — the standard format that security ADRs extend with five additional fields
- ADR template in Markdown — the Markdown variant that the security ADR template above builds on
- ADR governance pattern — who has authority to accept security ADRs and how that authority interacts with the security function
- When to supersede vs. deprecate an ADR — lifecycle management for security ADRs whose threat model assumptions have become invalid
- The quarterly decision review — the cadence for checking security ADR review triggers and surfacing stale threat model assumptions
- Cross-team decisions — when a security decision has downstream compliance implications for other teams' data handling
- Decisions that never get written down — the "we decided not to implement X security control" records that are especially important to preserve
- How to export ChatGPT history — first step for recovering compliance research sessions
- How to export Claude conversations — first step for recovering Claude-side security deliberation