Stratify
Legal and compliance

Incident Response Procedure — Dual-Clock Decision Tree

docs/compliance/isms/procedures/PRO-08-incident-response.md

Source updated 03. Aug. 2026

Incident Response Procedure — Dual-Clock Decision Tree

Why this is the highest-priority Tier 2 procedure

Stratify has exactly one real, executed-in-writing precedent for incident response: the audit-chain-corruption runbook in docs/runbooks/db-recovery.md §3.3 ("P0 Compliance" — forensic snapshot, service-role lockdown, Slack incident channel, counsel notification within 24h, DPO note re: GDPR Art. 33). This procedure generalizes that single precedent into the general incident-response process every other kind of security or privacy incident should follow, and adds what §3.3 doesn't fully spell out: the fact that Stratify faces two independent notification clocks simultaneously on any incident involving personal data, with different triggers and no shared deadline.

1. Detection and reporting — informal today, stated honestly

There is no dedicated monitoring/alerting pipeline for security incidents specifically. Detection today happens through one of:

  • Sentry (server-side error telemetry, tracesSampleRate: 0.1) surfacing an anomalous error

spike — this is how the audit-chain-corruption scenario is expected to first show up (db-recovery.md:73, "Symptome: verifyChain liefert { ok: false, firstBadId: N }" would typically be noticed via a failed scheduled check or a manual investigation prompted by something else looking wrong).

  • Direct observation by the ISMS Owner during normal operation or a deploy.
  • A report from Antonios, Philipp, a partner, or (eventually) a subscriber — there is no

dedicated incident-reporting inbox or form today; a report arrives as a direct message.

  • A future pentest finding (PRO-14, once run) — a discovered-not-yet-exploited vulnerability

is handled by this same triage step even though it isn't (yet) an active incident.

Gap, stated plainly: there is no formal "how to report a suspected incident" channel beyond contacting Toby directly. Until one is defined, whoever notices something wrong should treat direct contact with the ISMS Owner as the reporting path. This should be revisited once the team grows past one engineer.

On detection: the person who notices something wrong reports it to the ISMS Owner (Toby) immediately — do not wait to investigate fully before reporting; triage (step 2) is the place for that investigation, not a precondition for raising the flag.

2. Triage and severity classification

Proposed P0–P3 scale, applied at first report:

SeverityDefinitionExamples
P0Confirmed compromise of personal data, or a broken integrity guarantee this ISMS relies on as structuralAudit-chain corruption (verifyChain() returns ok: false); confirmed unauthorized access to subscriber, partner, or signal-delivery data; service-role key confirmed leaked
P1Serious suspected issue, not yet confirmed, or confirmed but narrowly containedSuspected (not yet confirmed) unauthorized access; an RLS policy found misconfigured but no evidence of exploitation; a partner key confirmed compromised but scoped only to signals:read
P2A real security weakness with no evidence of exploitation and limited blast radiusA dependency vulnerability found via manual audit (pending PRO-06 tooling); a misconfigured but non-data-bearing service
P3Hygiene issue, no immediate exposureA stale credential that should be rotated on principle; a documentation gap that could mislead (e.g. the stale-hosting-doc issue already tracked as RISK-001)

Automatic P0, no judgment call required: audit-chain corruption (verifyChain() failure) and any confirmed unauthorized access to personal data are classified P0 immediately on confirmation — this matches db-recovery.md §3.3's own framing of audit-chain corruption as "P0 Compliance" and is extended here to cover confirmed data-access incidents generally, since both trigger the same notification-clock analysis in §4.

Severity can be revised as more is learned (a P1 upgraded to P0 once confirmed, or downgraded once scoped) — triage is not a one-time classification, it's revisited as the incident is understood.

3. Containment

Proportionate to severity; P0/P1 containment steps, adapted from the real precedent in db-recovery.md §3.3 and §3.4:

  1. Service-role key rotation — if the service-role key is implicated at all (leaked, used

anomalously, or containment requires cutting off the admin-bypass path), rotate it immediately via the manual deploy path (infra/hetzner/deploy-web-hetzner.sh), following docs/secrets.md's rotation table ("Audit-chain divergence → Treat as P0; freeze service-role until forensics complete").

  1. Host lockdown via Tailscale, if the host itself is implicated — the production host is

already firewalled to Tailscale-only access for all inbound traffic (docs/runbooks/deploy.md); containment here means restricting *which* Tailscale identities retain access, not adding a new perimeter that doesn't exist yet. Revoke any Tailscale node whose credentials are in question.

  1. Stop writes, if data integrity is at risk: docker stop stratify-web or set

STRATIFY_READ_ONLY=1 and redeploy (db-recovery.md:40-41).

  1. Forensic snapshot before remediation — for anything touching audit_log specifically,

pg_dump --table=audit_log to forensic storage *before* any restore or mutation, per db-recovery.md:77. This preserves the evidence a later legal or regulatory inquiry might need, independent of whatever gets restored operationally afterward.

  1. Incident channel — open a dedicated Slack channel (#incident-<short-slug>, matching the

existing #incident-audit-XXXX pattern from db-recovery.md:79) with Toby and Antonios as a minimum; add Philipp if the incident touches anything under his ownership.

Containment steps for P2/P3 are typically just "fix it in the normal PR/deploy cycle" — this procedure's weight is concentrated on P0/P1.

4. The dual notification clock — decision tree

Any P0 or P1 incident involving personal data of an EEA or Swiss data subject starts two independent clocks at once, with different triggers and no shared deadline. Both must be evaluated for every qualifying incident — satisfying one does not satisfy the other.

GDPR Art. 33 (EEA subjects)revDSG Art. 24 (Swiss controller entity)
TriggerA personal data breach — confirmed, not merely suspectedA data security breach that is likely to result in a high risk to the data subject's personality or fundamental rights
Deadline72 hours from becoming aware, to the competent supervisory authority"As soon as possible" — no fixed deadline, but delay itself can be scrutinized
Who decidesDPO/Privacy Owner (Antonios) is Accountable for the notification decision and content (per GOV-03's RACI); ISMS Owner (Toby) is Responsible for assembling the technical factsSame split — Antonios accountable, Toby responsible for facts
What starts the clockThe moment Stratify becomes aware — not the moment it's fully understood. A P0 classification (step 2) should be treated as the awareness trigger by default, even before full scoping is completeSame trigger point, though the "as soon as possible" standard is less mechanically clock-driven — the practical read is: don't wait for the GDPR 72h deadline to also decide the revDSG notification, evaluate both at the same moment
Documentation required regardless of notification decisionYes — Art. 33(5) requires documenting every breach, including ones assessed as not requiring notification (low risk to rights/freedoms)Yes — same principle under revDSG; a reasoned no-notify decision needs to be recorded, not just a notify decision

Decision procedure, applied at P0/P1 declaration:

  1. Does the incident involve personal data of any data subject? If no — this is a security

incident without a breach-notification dimension; skip to post-incident review (§5). If yes, continue.

  1. **Evaluate both clocks independently, at the same time, by the same person (Antonios,

Accountable).** Do not evaluate GDPR first and revDSG second as sequential steps — they run in parallel from the moment of awareness.

  1. GDPR path: assess whether the incident is a "personal data breach" under Art. 4(12) (any

breach of confidentiality, integrity, or availability). If yes, the 72h clock is running from awareness; either notify the competent supervisory authority within 72h, or document the reasoned basis for assessing the breach as unlikely to result in a risk to rights and freedoms (Art. 33(1) exception) — the reasoning itself is the evidence, not just the outcome.

  1. revDSG path: assess whether the breach is likely to result in a high risk to the data

subject's personality or fundamental rights (revDSG Art. 24 threshold, higher bar than GDPR's). If yes, notify the EDÖB "as soon as possible" — there is no benefit to delaying to align with the GDPR 72h window; if the revDSG threshold is met, notify promptly on its own timeline even if the GDPR assessment is still ongoing.

  1. Counsel notification within 24h for any P0 — this is already the stated practice for

audit-chain corruption specifically (db-recovery.md:80) and is extended here as the general P0 rule: legal counsel should be looped in well before either regulatory clock's deadline, since counsel's input often shapes whether the GDPR/revDSG thresholds above are actually met.

  1. Data-subject notification (GDPR Art. 34 / revDSG Art. 24 subject-notification limb) is a

separate decision from the authority notification above, triggered by a higher bar (high risk to the individual specifically) — evaluate it explicitly rather than assuming authority notification automatically implies subject notification, or vice versa.

Both clocks apply simultaneously, not sequentially — a single incident (e.g. the audit-chain corruption scenario, if the corrupted entries touched personal data) can require a GDPR supervisory-authority notification within 72h *and* an EDÖB notification "as soon as possible," decided by the same person, from the same facts, on two different legal bases. Treat this as one combined analysis producing two outputs, not two separate processes run one after the other.

5. Post-incident review

Every P0 and P1 incident gets a post-incident review, regardless of whether notification was ultimately required:

  1. What happened — timeline from detection to containment to resolution.
  2. What was the root cause — technical and, where relevant, process (e.g. "no dependency

scanning existed" is a valid root cause for a P1 that traces back to RISK-003).

  1. What worked / what didn't in the response itself.
  2. Corrective actions, each with an owner and a date — feeds directly into

GOV-13 (nonconformity and corrective action log) as a new entry, and into GOV-11's internal-audit programme as an input for what the next audit cycle should specifically check.

  1. Update this procedure if the incident revealed a gap in the process itself (e.g. the

informal detection/reporting path in §1 turning out to be too slow) — this document should evolve from real incidents, not stay static.

6. Future extension: a third clock at Phase C

The FMA Liechtenstein licensing roadmap (docs/compliance/regulatory-roadmap-ch-eea.md) means a third notification clock — a financial-regulator notification obligation, DORA-equivalent in shape (4h/24h-style clocks per PLAN.md §4) — becomes live once Phase C is reached (structured wrapper + execution, KYC, Stripe Connect payouts, MiFID-II suitability). This is flagged here as a future extension, not something to build now: Stratify operates in a pre-license research-publication posture today (register/facts.md), and no financial-regulator notification obligation applies yet. When Phase C planning begins, this procedure should be revised to add the third clock to the decision tree in §4, following the same "evaluate independently, document regardless of outcome" pattern established above.

Evidence

Every incident (P0/P1 minimum; P2/P3 at the ISMS Owner's discretion) produces:

  • A dated markdown record under docs/compliance/isms/evidence/

(e.g. evidence/2026-MM-DD-incident-<slug>.md) covering detection, triage, containment, notification-clock analysis (even if the answer was "does not apply"), and the post-incident review.

  • The Slack incident-channel transcript, retained for the incident's record.
  • Any forensic snapshot taken during containment.
  • The audit_log entries generated during the incident and response (recovery actions,

role/key changes) — these are already tamper-evident by construction.

Review

This procedure has been exercised exactly once in substance — the audit-chain-corruption runbook it generalizes from (db-recovery.md §3.3) — and never as a standalone, generalized process. Review after every real P0/P1 incident (§5 above already requires this), and otherwise at least annually, or immediately if Phase C planning begins (see §6).