Training module · Draft
Module 7: Routing to owners
Status — Draft
This page is still being written. Expect gaps and changes; it is not part of the workbook's production guidance. Last reviewed 2026-11-09.
Part of the Provider Notices learning path. Gate G6 Routing. Workbook Chapter 06. About 65 minutes.
The narrated deck for this module, and the chapter’s narrated tour, come later.
Introduction (3 minutes)
A notice nobody owns is the problem this path started with. Routing is where each notice that needs action gets an owner: a typed task in the service desk’s front door, with a severity, a response window and the provider’s own date kept beside it. The rest go in the weekly digest. Providers repeat the same notice every week, so the router remembers what it has routed and writes nothing for a notice that hasn’t changed. And a provider closing its notice isn’t the agency’s work being done: a retirement can close on the provider’s side while the agency still runs the retired version.
In this module you check the lab’s routing, route two fictional weeks from all five providers as a dry run, read one payload in full, and watch a re-run write nothing.
The federal requirement. Gate G6 supports SI-5 c and d, CM-3 b and f, CM-4 and CP-2 e. The gate’s output is evidence for these controls; your organization still sets their parameters, policy and procedures, and the assessor decides whether each is satisfied. The guide’s Step 6 names them, and the workbook chapter’s Federal requirements and evidence table has a row for every lab step.
| Requirement | KSI | Evidence |
|---|---|---|
| CM-3 b (review proposed changes): the routing checked before it runs | KSI-CMT-LMC, KSI-CMT-RVP | Read-PnRouting on the agency’s routing file |
| SI-5 c and d: disseminate to the people who act, and implement in the established time frames | KSI-SCR-MON | tasks/, tasks.json, routing.csv |
| CM-3 b and f; CM-4 (impact analyses) | KSI-CMT-LMC, KSI-CMT-RVP | The payloads for change, retirement and maintenance, and the change records they open |
| CP-2 e | KSI-RPL-ARP | Payloads with contingency_review: true |
| SI-5 d; CM-3 f: routed once, re-runs write nothing, closure asks for the re-read | KSI-SCR-MON, KSI-CMT-LMC | state.json, routing.csv |
No KSI cites base CM-4; KSI-CMT-LMC and KSI-CMT-VTD cite CM-4(2), as the guide records. KSIs are FedRAMP 20x indicators for cloud service providers. The agency lines this evidence up with what its providers report against them; it doesn’t report KSIs itself. Which file supports which indicator is the program’s mapping (design guidance). The guide’s Evidence section explains both.
Learning objectives (1 minute)
After this module, you’ll be able to:
- write routing rules in the right order, and say why security advisories and retirements come before the general action-required rule;
- route a collection as a dry run and read what each payload is for: create, update or close;
- read a task payload: severity, priority, response window, the provider’s own date, the contingency review flag and the five clauses;
- explain why a re-run writes nothing, and why a provider’s closure asks for the re-read instead of closing the task;
- say where the agency’s routing is written and kept.
Prerequisites (1 minute)
- At least one of Modules 2 to 6.
- Book 13, Appendix B: the typed task, its lanes and the five-clause request chain.
Unit 1: The operating model and the gate (10 minutes)
Read:
- Book 15’s From notice to task to closure: rules tried in order, a task is a typed task, close on the re-read, changes go through change control.
- The guide’s Step 6: write the routing at work, check it, route as a dry run, and send only once the endpoint exists. Then its Interim path and the Validate (G6) callout: every security advisory and retirement routes to a task, and a second run on the same collection writes no payload.
Unit 2: The router (12 minutes)
Read the workbook chapter in this order:
- What the program gives you and What it leaves to you: the finding contract’s severities (P1 immediate, P2 one hour, P3 24 hours, P4 72 hours; program design) and what notices need on top.
- The routing file, The payload and Runs and state.
- Dangers.
- The kit’s Copilot prompts: how the agency drafts and reviews its own routing at work, in Microsoft 365 Copilot Chat.
Exercise: Lab 1, fixtures, no tenant (25 minutes)
This is the workbook’s Chapter 06, Lab 1, which explains each result. Work in examples/provider-notices, in PowerShell 7. The teams in the lab’s routing are fictional. Step 9 also reads the finding contract in examples/servicenow-sailpoint.
Every command in this lab, in order, from examples/provider-notices. Each step below says what it does and what to look for.
# Step 1: Check the lab's routing
Import-Module ./powershell/ProviderNotices/ProviderNotices.psm1
(Read-PnRouting -Path config/routing.json).rules | ForEach-Object { [pscustomobject]@{ id = $_.id; route = $_.route; severity = $_.severity; group = $_.assignmentGroup } } | Format-Table
# Step 2: Try the template as it ships
Read-PnRouting -Path templates/routing.template.json
# Step 3: Collect every provider from the day-one fixtures
./Invoke-PnCollect.ps1 -SettingsPath tests/fixtures/settings.lab.json -FixturePath tests/fixtures/day1 -AsOf 2026-11-09T12:00:00Z -OutputPath out/day1
# Step 4: Route them, as a dry run
./Invoke-PnRoute.ps1 -NoticesPath out/day1/notices.json -RoutingPath config/routing.json -StatePath out/state.json -OutputPath out/day1-route -AsOf 2026-11-09T12:00:00Z
# Step 5: Read one payload
$p = Read-PnJson -Path out/day1-route/tasks/create-azure-RT5J-6KL.json
[pscustomobject]$p | Format-List action, dedupe_key, severity, priority, response_window_seconds, response_due, action_required, action_due, assignment_group, contingency_review, controls, ksis
[pscustomobject]$p.ticket_to_machine | Format-List lane, c1_origin, c2_approver_role, c3_action, c4_reread_check, c5_evidence_kept
# Step 6: Route the same collection again, on a copy of the state
Copy-Item out/state.json out/state-rerun.json
./Invoke-PnRoute.ps1 -NoticesPath out/day1/notices.json -RoutingPath config/routing.json -StatePath out/state-rerun.json -OutputPath out/day1-rerun -AsOf 2026-11-09T13:00:00Z
# Step 7: Collect and route the second week
./Invoke-PnCollect.ps1 -SettingsPath tests/fixtures/settings.lab.json -FixturePath tests/fixtures/day2 -AsOf 2026-11-16T12:00:00Z -OutputPath out/day2
./Invoke-PnRoute.ps1 -NoticesPath out/day2/notices.json -RoutingPath config/routing.json -StatePath out/state.json -OutputPath out/day2-route -AsOf 2026-11-16T12:00:00Z
# Step 8: Read what each payload is for
Import-Csv out/day2-route/routing.csv | Where-Object action | Format-Table change, ruleId, action, severity, noticeId
# Step 9: Run the router's tests
Invoke-Pester -Path tests/Router.Tests.ps1 -Output None -PassThru | Select-Object PassedCount, FailedCount
# After the steps
Remove-Item -Recurse -Force outCheck the lab’s routing:
Import-Module ./powershell/ProviderNotices/ProviderNotices.psm1 (Read-PnRouting -Path config/routing.json).rules | ForEach-Object { [pscustomobject]@{ id = $_.id; route = $_.route; severity = $_.severity; group = $_.assignmentGroup } } | Format-Tableid route severity group -- ----- -------- ----- R01 task P2 Security Operations (example) R02 task P3 Cloud Platform Engineering (example) R03 task P3 Cloud Platform Engineering (example) R04 task P2 Service Desk (example) R05 task P3 Cloud Operations (example) R06 ignoreSix rules, in the order they are tried.
Try the template as it ships:
Read-PnRouting -Path templates/routing.template.jsonExpect an error:
Exception: Routing templates/routing.template.json still has a <placeholder>.It runs only once every value is filled in at work.Collect every provider from the day-one fixtures:
./Invoke-PnCollect.ps1 -SettingsPath tests/fixtures/settings.lab.json -FixturePath tests/fixtures/day1 -AsOf 2026-11-09T12:00:00Z -OutputPath out/day122 notices from five providers, as in Module 1.
Route them, as a dry run:
./Invoke-PnRoute.ps1 -NoticesPath out/day1/notices.json -RoutingPath config/routing.json -StatePath out/state.json -OutputPath out/day1-route -AsOf 2026-11-09T12:00:00ZNotices: 22 new, 0 changed, 0 unchanged, 0 no longer listed Routes: 12 task, 9 digest only, 1 ignored Payloads: 12 create, 0 update, 0 closeThen one line per payload, and
Dry run: 12 payloads written to out/day1-route/tasks, nothing sent.The Microsoft Viva post is ignored by R06; the rest that need no task go to the digest.Read one payload:
$p = Read-PnJson -Path out/day1-route/tasks/create-azure-RT5J-6KL.json [pscustomobject]$p | Format-List action, dedupe_key, severity, priority, response_window_seconds, response_due, action_required, action_due, assignment_group, contingency_review, controls, ksis [pscustomobject]$p.ticket_to_machine | Format-List lane, c1_origin, c2_approver_role, c3_action, c4_reread_check, c5_evidence_keptThe Azure retirement:
severity : P3withresponse_window_seconds : 86400, soresponse_due : 2026-11-10T12:00:00Z; Microsoft’s retirement date kept apart inaction_due : 2027-09-30T00:00:00Z;contingency_review : True; andlane : Human decision, withc4_reread_check : The next collection shows the notice closed or no longer listed, or the named resources no longer affected.Route the same collection again, on a copy of the state:
Copy-Item out/state.json out/state-rerun.json ./Invoke-PnRoute.ps1 -NoticesPath out/day1/notices.json -RoutingPath config/routing.json -StatePath out/state-rerun.json -OutputPath out/day1-rerun -AsOf 2026-11-09T13:00:00ZExpect
Notices: 0 new, 0 changed, 22 unchanged, 0 no longer listed,Payloads: 0 create, 0 update, 0 closeandNo payloads: nothing new or changed needs a task.Collect and route the second week:
./Invoke-PnCollect.ps1 -SettingsPath tests/fixtures/settings.lab.json -FixturePath tests/fixtures/day2 -AsOf 2026-11-16T12:00:00Z -OutputPath out/day2 ./Invoke-PnRoute.ps1 -NoticesPath out/day2/notices.json -RoutingPath config/routing.json -StatePath out/state.json -OutputPath out/day2-route -AsOf 2026-11-16T12:00:00ZNotices: 2 new, 6 changed, 15 unchanged, 1 no longer listed Routes: 12 task, 10 digest only, 1 ignored Payloads: 1 create, 4 update, 1 closeRead what each payload is for:
Import-Csv out/day2-route/routing.csv | Where-Object action | Format-Table change, ruleId, action, severity, noticeIdSix rows. The Azure and OCI rescheduled maintenance windows and the updated Microsoft 365 post are
changedupdates; the Azure incident the provider no longer lists is anabsentupdate asking for the re-read; the new Microsoft 365 postm365:MC900005is anewcreate; and the AWS security notification AWS closed is aclosethat also asks for the re-read.Run the router’s tests, including the one that reads the finding contract:
Invoke-Pester -Path tests/Router.Tests.ps1 -Output None -PassThru | Select-Object PassedCount, FailedCountExpect
PassedCount 31,FailedCount 0.
Delete out when you’re done:
Remove-Item -Recurse -Force outExercise: Lab 2, a ServiceNow developer instance (5 minutes to read)
Not run by the authors. Follow the workbook’s Chapter 06, Lab 2. It has the exact commands.
- You need: a ServiceNow Personal Developer Instance or a sub-production instance, never production, with an endpoint you build to accept the payload (its shape is the agency’s and not yet specified), and a token for a test integration user; Lab 1’s steps 3 and 4 run first.
- What you do: put the token in the environment for this session only, never in a file; send one payload through the kit’s sender; and check the record’s assignment group, priority, description and five clauses in the instance.
- Back-out: step 3 deletes the test record in the instance, clears the token and deletes
out.
Knowledge check (5 minutes)
- Why do the security and retirement rules come before the general action-required rule?
- Alphabetical order
- Rules are tried in order and the first match wins, and a retirement is often also marked action required; the retirement rule carries the contingency review
- The router sorts rules by severity
- The order doesn’t matter
- A task’s
response_dueis tomorrow and itsaction_dueis in ten months. Which is right?- One of them is a mistake
- Both: the response window says how fast the owner picks the task up; the provider’s date says when the work must be done
action_dueoverridesresponse_due- The kit should set both to the provider’s date
- You route the same collection twice. What does the second run write?
- The same 12 payloads again
- Nothing: the state holds each notice’s fingerprint, and unchanged notices write no payload
- 12 update payloads
- 12 close payloads
- AWS closes its security notification. What does the router do?
- Closes the task
- Deletes the task
- Writes a
closepayload that asks for the re-read (C4); the task is resolved on the agency’s own check - Ignores it
- Where is the agency’s own routing written and kept?
- In the public repository, beside the kit
- At work, from the kit’s template, with the Copilot prompts in Microsoft 365 Copilot Chat if that helps, and kept inside the agency’s boundary
- In the provider’s portal
- In the digest
- b. Taught in Book 15’s From notice to task to closure and The routing file.
- b. Taught in What it leaves to you and the chapter’s Dangers.
- b. Taught in Runs and state.
- c. Taught in What it leaves to you and the guide’s Step 6.
- b. Taught in the guide’s prerequisites and The routing file.
Summary (2 minutes)
You checked six routing rules, saw the template refused, routed 22 notices into 12 task payloads, read one with both its dates and its five clauses, watched a re-run write nothing, and read the second week’s create, updates and close.
The evidence an ISSO keeps for G6 from this module: each routing run’s tasks/, tasks.json, routing.csv, state.json and manifest, dated; the reviewed routing file’s SHA-256; and the change records the payloads open. Before shipping, work through the chapter’s Checklist.