Lesson 16 / 22
Communication and Notification Obligations
Measuring notification as time and stakeholder count: five of twelve stakeholders being external, the 4,320-minute window of the obligation type that requires notification within a fixed time, the scope estimate dropping from 48,000 to 6,200 without ever settling, early notification over-notifying 14,800 subscribers and producing 46 corrections against staying at 29,967 uninformed subscriber-hours, and late notification exceeding the window by 64,540 minutes across five external stakeholders while producing 1,793,247 subscriber-hours.
Published Updated
In this lesson
- Splits the stakeholder set into internal and external, and models each stakeholder's notification threshold and prep time
- Runs four notification policies against the same incident and works out the window overrun and correction count
- Counts both sides of the decision: uninformed subscriber-hours against over-notified subscribers
Contents
The previous lesson counted five of sixteen review questions staying unanswered; one of them was which subscriber records were read, and it was unanswered because the data access log was never turned on at all. That gap turns directly into a decision in this lesson, because notification wants exactly this number: how many subscribers to tell what.
Notification’s unit of measure is time and stakeholder count. How many stakeholders there are, at what threshold each one is informed, how many minutes it takes to prepare the notification, and what the delay costs. A portion of the external stakeholders are subject to an obligation type that requires notification within a fixed time; that obligation’s window starts from the moment of detection and is fixed. What the measurement will show is this: staying inside the window and reporting the correct number cannot both be achieved at once.
Stakeholders, Thresholds and the Window
IR41: There are twelve stakeholders; five external, seven internal. Each stakeholder has a notification threshold, and the threshold corresponds to a moment from the previous lessons: verification at 216, scope at 370, containment at 393, recovery at 1,363, and review at 17,280 minutes. IR42: For each stakeholder, preparing and approving the notification takes a set number of minutes; the notification moment is the threshold plus the prep time. IR43: The window of the obligation type that external stakeholders are subject to, which requires notification within a fixed time, is 4,320 minutes and starts from the moment of detection; the limit is minute 4,506. IR44: The affected-subscriber count is an estimate and narrows over time: 48,000, 21,000, 9,400, 7,100, and 6,200. Because there is no data access log, the number never settles; the final value is also an estimate. IR45: Once a stakeholder has been notified, every time the estimate changes, a correction notice is required, and a correction adds an extra load equal to 0.35 of the stakeholder’s prep person-hours. IR46: Uninformed subscriber-hours are the final estimate’s subscriber count multiplied by the time between detection and the subscriber notification. IR47: Over-notified subscribers are the difference between the estimate at the notification moment and the final estimate.
// notification/model.mjs — communication and notification model: no real institution, // regulation or incident involved. Stakeholders, thresholds and the scope estimate are // data structures; the durations are fictional data. export const DETECTION = 186; // the minute the alert fired export const WINDOW = 4320; // the window, in minutes, of the obligation type // that requires notification within a fixed time // threshold: name -> the minute it occurs at (carried over from the previous lessons) export const THRESHOLD = { verification: 216, scope: 370, containment: 393, recovery: 1363, review: 17280 }; // stakeholder: name, internal/external, threshold, notification prep minutes, prep person-hours export const STAKEHOLDERS = [ ["shift lead", "internal", "verification", 5, 0.3], ["information security manager", "internal", "verification", 8, 0.5], ["service-owning teams", "internal", "verification", 12, 1.5], ["external response support", "external", "verification", 15, 1.0], ["executive leadership", "internal", "scope", 35, 2.0], ["legal department", "internal", "scope", 25, 1.5], ["notification-obligation contact", "external", "scope", 180, 8.0], ["business continuity team", "internal", "containment", 18, 1.0], ["corporate communications", "internal", "containment", 40, 3.0], ["enterprise customers", "external", "containment", 120, 6.0], ["affected subscribers", "external", "recovery", 260, 14.0], ["insurance provider", "external", "recovery", 95, 4.0], ]; // scope estimate: [minute, affected-subscriber count to notify at that moment] (data). // The number never firms up, because the previous lesson found no data access log. export const ESTIMATE = [[216, 48000], [370, 21000], [1363, 9400], [4506, 7100], [17280, 6200]]; export const estimate = (min) => [...ESTIMATE].reverse().find(([t]) => t <= min)?.[1] ?? ESTIMATE[0][1]; export const corrections = (min) => ESTIMATE.filter(([t]) => t > min).length; export const FINAL = ESTIMATE[ESTIMATE.length - 1][1]; // policy: the moment notification starts for a stakeholder export const POLICY = { "early": () => THRESHOLD.verification, "by threshold": (p) => THRESHOLD[p[2]], "at window's end": (p) => p[1] === "external" ? DETECTION + WINDOW - p[3] : THRESHOLD[p[2]], "late": () => THRESHOLD.review, }; export function measure(policyName) { const f = POLICY[policyName]; const rows = STAKEHOLDERS.map((p) => { const start = f(p), moment = start + p[3]; const external = p[1] === "external"; return { name: p[0], external, moment, delay: external ? Math.max(0, moment - (DETECTION + WINDOW)) : 0, corrections: corrections(moment), notified: estimate(moment), hours: p[4] }; }); const subscriber = rows.find((s) => s.name === "affected subscribers"); return { rows, lateExternal: rows.filter((s) => s.external && s.delay > 0).length, excess: Math.max(0, subscriber.notified - FINAL), notified: subscriber.notified, subscriberMoment: subscriber.moment, delay: rows.reduce((a, s) => a + s.delay, 0), corrections: rows.reduce((a, s) => a + s.corrections, 0), hours: rows.reduce((a, s) => a + s.hours * (1 + s.corrections * 0.35), 0), subscriberHours: Math.round(FINAL * (subscriber.moment - DETECTION) / 60) }; }
The measurement file first sorts stakeholders by threshold, then runs the four notification policies against the same incident.
// notification/measure.mjs — how many stakeholders there are, at what threshold notification // begins, how many corrections a notification made before scope is finalized produces, and // how many subscriber-hours the delay costs. import { DETECTION, WINDOW, THRESHOLD, STAKEHOLDERS, ESTIMATE, FINAL, POLICY, estimate, corrections, measure } from "./model.mjs"; const write = (g, ...s) => console.log(s.map((v, i) => (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join("")); const t0 = process.hrtime.bigint(); const LIMIT = DETECTION + WINDOW; console.log(`${STAKEHOLDERS.length} stakeholders (${STAKEHOLDERS.filter((p) => p[1] === "external").length} external); ` + `detection at minute ${DETECTION}, notification window ${WINDOW} min, limit at minute ${LIMIT}`); console.log("\n1. stakeholders and their threshold-based notification moment"); const A = [-32, 9, 13, 10, 14, 13, 12]; write(A, "stakeholder", "type", "threshold", "prep", "notify moment", "in window", "notified"); for (const p of STAKEHOLDERS) { const moment = THRESHOLD[p[2]] + p[3]; write(A, p[0], p[1], p[2], p[3] + " min", moment, p[1] === "external" ? (moment <= LIMIT ? "yes" : "no") : "-", p[0] === "affected subscribers" ? estimate(moment) : "-"); } console.log("\n2. scope estimate (never firms up for lack of a data access log)"); const B = [-10, 10, 13, 18]; write(B, "minute", "estimate", "vs. final", "corrections left"); for (const [min, v] of ESTIMATE) write(B, min, v, (v / FINAL).toFixed(2) + "x", corrections(min)); console.log("\n3. four notification policies"); const C = [-18, 18, 12, 10, 14, 12, 12, 12]; write(C, "policy", "subscriber moment", "notified", "excess", "late external", "delay min", "corrections", "person-h"); const R = {}; for (const k of Object.keys(POLICY)) { const r = R[k] = measure(k); write(C, k, r.subscriberMoment, r.notified, r.excess, r.lateExternal, r.delay, r.corrections, r.hours.toFixed(1)); } console.log("\n4. the two sides of the decision"); const D = [-18, 21, 18, 21]; write(D, "policy", "uninformed sub-hours", "over-notified", "correction notices"); for (const [k, r] of Object.entries(R)) write(D, k, r.subscriberHours, r.excess, r.corrections); const e = R["early"], g = R["late"]; console.log(` early vs. late: ${g.subscriberHours - e.subscriberHours} subscriber-hours apart, against ` + `${e.excess - g.excess} over-notified subscribers and ${e.corrections - g.corrections} corrections`); console.log("\n5. external stakeholders past the window under the late policy"); for (const s of R["late"].rows.filter((x) => x.external && x.delay > 0)) write([-4, -32, 10, 12], "", s.name, s.moment, `+${s.delay} min`); const ms = Number(process.hrtime.bigint() - t0) / 1e6; // the raw measurement is not printed, only the band is checked console.log(`\nfour policies and ${STAKEHOLDERS.length} stakeholders within the 500 ms band: ${ms < 500 ? "yes" : "no"}`);
12 stakeholders (5 external); detection at minute 186, notification window 4320 min, limit at minute 4506
1. stakeholders and their threshold-based notification moment
stakeholder type threshold prep notify moment in window notified
shift lead internal verification 5 min 221 - -
information security manager internal verification 8 min 224 - -
service-owning teams internal verification 12 min 228 - -
external response support external verification 15 min 231 yes -
executive leadership internal scope 35 min 405 - -
legal department internal scope 25 min 395 - -
notification-obligation contact external scope 180 min 550 yes -
business continuity team internal containment 18 min 411 - -
corporate communications internal containment 40 min 433 - -
enterprise customers external containment 120 min 513 yes -
affected subscribers external recovery 260 min 1623 yes 9400
insurance provider external recovery 95 min 1458 yes -
2. scope estimate (never firms up for lack of a data access log)
minute estimate vs. final corrections left
216 48000 7.74x 4
370 21000 3.39x 3
1363 9400 1.52x 2
4506 7100 1.15x 1
17280 6200 1.00x 0
3. four notification policies
policy subscriber moment notified excess late external delay min corrections person-h
early 476 21000 14800 0 0 46 95.0
by threshold 1623 9400 3200 0 0 38 82.6
at window's end 4506 7100 900 0 0 29 65.4
late 17540 6200 0 5 64540 0 42.8
4. the two sides of the decision
policy uninformed sub-hours over-notified correction notices
early 29967 14800 46
by threshold 148490 3200 38
at window's end 446400 900 29
late 1793247 0 0
early vs. late: 1763280 subscriber-hours apart, against 14800 over-notified subscribers and 46 corrections
5. external stakeholders past the window under the late policy
external response support 17295 +12789 min
notification-obligation contact 17460 +12954 min
enterprise customers 17400 +12894 min
affected subscribers 17540 +13034 min
insurance provider 17375 +12869 min
four policies and 12 stakeholders within the 500 ms band: yes
The numbers belong to the measurement class; their inputs are the assumptions above.
Twelve Stakeholders
The first table converts stakeholders’ thresholds into notification moments. The seven internal stakeholders are informed between minutes 221 and 433; their prep times range from 5 to 40 minutes. For external stakeholders, prep stretches out noticeably: 180 minutes for the notification- obligation contact, 120 for enterprise customers, 260 for affected subscribers. This difference is not a delay — it is the fact that the notification itself is work: text gets written, legal reads it, a channel gets prepared.
Under the by-threshold policy, all five external stakeholders stay inside the window; the latest notification goes to affected subscribers at minute 1,623, and the limit is minute 4,506. The window is not tight in this incident. What is tight is something else.
The distribution of thresholds is also a decision. Three internal stakeholders are informed at the verification threshold — that is, the moment the alert is understood to be real; legal and executive leadership wait for the scope threshold. This order is not arbitrary: an executive notification made before scope is determined cannot say how many assets were affected, and it produces no decision in return. None of the external stakeholders sit before the verification threshold; the sole exception is external response support, and that is not a notification but a call.
The Number That Never Settles
The second table gives the scope estimate over time. At minute 216, the estimate is 48,000 — 7.74 times the final estimate. It drops to 21,000 at minute 370, to 9,400 at minute 1,363, to 7,100 at minute 4,506, and settles at 6,200 at minute 17,280. The last column gives how many corrections come after each moment.
This table’s meaning was already established in the previous lesson: because the data access log was never turned on at all, the question of which subscriber records were read is unanswered. The number is therefore not a measurement but a narrowing estimate; 6,200 is not certain either, only the value that stops narrowing further. Notification has to be made on the basis of a number that never settles, and this turns the choice of notification moment into a question of estimate accuracy.
Four Policies
The third table runs the four policies. Under the early policy, every stakeholder is informed at the moment of verification; subscriber notification goes out at minute 476 with the count 21,000, 14,800 subscribers are over-notified, 46 corrections are required, and the total load is 95.0 person-hours. Under the by-threshold policy, subscriber notification shifts to minute 1,623, notified drops to 9,400 and over-notified to 3,200, and corrections fall to 38. The at-window’s-end policy places external notifications right before the limit: minute 4,506, 7,100 subscribers, 900 over-notified, 29 corrections, and 65.4 person-hours.
The late policy waits until the review is complete. The notified count is 6,200, over-notified is zero, and no corrections are needed at all — at 42.8 person-hours, it is the lowest. Its counterpart is in the fifth table: all five external stakeholders exceed the window, the total delay is 64,540 minutes, and the largest overrun is with affected subscribers, at 13,034 minutes.
The person-hours column is misleading on its own. Most of the early policy’s 95.0 person-hours comes not from the notification itself but from the 46 corrections that follow it; each correction brings back a third of the stakeholder’s prep load. As the policy is delayed, the correction count drops from 46 to 38, to 29, and to zero. The policy that looks cheapest in this column is the one that notifies affected subscribers nine days after the window; its cost is paid not in person-hours but in minutes. Choosing a notification policy by prep load alone means making a delayed notification look cheap.
Two Sides of the Decision
The fourth table places two columns side by side. Under the early policy, uninformed subscriber-hours is 29,967 and over-notified subscribers is 14,800. Under the late policy, over-notified is zero and uninformed subscriber-hours is 1,793,247. The difference between the two extremes is 1,763,280 subscriber-hours against 14,800 over-notified subscribers and 46 corrections.
The two policies in between show how this curve bends. Compared to early, the by-threshold policy adds 118,523 subscriber-hours to bring over-notified down from 14,800 to 3,200 — roughly ten subscriber-hours per subscriber. The at-window’s-end policy adds a further 297,910 subscriber-hours to bring 3,200 down to 900; this time, a hundred thirty subscriber-hours per subscriber. Accuracy gets more expensive as it goes. The at-window’s-end policy sits at the last moment the obligation’s window allows, and past that point accuracy can only be increased by exceeding the window — which is exactly what the late policy does.
The over-notified subscriber count is innocent enough as a number, but its counterpart is telling 14,800 people that their own data may have been seen; a later correction does not take back that first notification. Uninformed subscriber-hours is also a number, and its counterpart is the time the 6,200 people who were genuinely affected spent not knowing it. The model counts both and cannot convert one into the other; whoever makes the decision has to write down, by their own measure, which column weighs more.
Summary
- Five of the twelve stakeholders are external; internal notifications go out at minutes 221–433, external notifications go out at minutes 231–1,623 under the by-threshold policy, and prep times range from 5 to 260 minutes.
- The window of the obligation type that requires notification within a fixed time is 4,320 minutes and the limit is minute 4,506; under the by-threshold policy, all five external stakeholders stay inside the window.
- The affected-subscriber estimate narrows from 48,000 to 6,200 but never settles for lack of a data access log; notification is made on the basis of a number that has not settled.
- The early policy over-notifies 14,800 subscribers and produces 46 corrections, with 29,967 uninformed subscriber-hours; the late policy never over-notifies but exceeds the window by 64,540 minutes across five external stakeholders and produces 1,793,247 subscriber-hours.
- Accuracy gets more expensive as it goes: bringing over-notified down from 14,800 to 3,200 costs ten subscriber-hours per subscriber, and from 3,200 to 900 costs a hundred thirty subscriber-hours.
Next Step
The incident is closed: access was stopped, footholds were cleaned up, the service was brought back, and stakeholders were informed. Every decision measured across seven lessons was tied to a number. One could not be tied down, and it kept coming back in every lesson: most of the items that would prove what happened had already been deleted at the moment of containment. Assets were pulled off the network before a memory dump was taken, three configuration hooks could never be found again, two review questions stayed unanswered, and the subscriber count remained an estimate. The next topic takes on these items on their own terms: what shows the evidence’s integrity, which items are volatile and vanish if not collected, how many items are lost when the collection order is wrong, and at how many items the chain of custody breaks.
To keep your progress and take notes, Log in
My notes
Log in to take notes.