KB // AI RISK HEATMAP
AI RISK & EXPOSURE HEATMAP
Complete reference — how to read every visual, how the scoring system works, all 18 seed risks, the filter and drill-through system, and full configuration guide for SharePoint list setup, live data wiring, and Power BI integration.
18
Seed Risks Loaded
8
Risk Categories
4
Live Charts
25
Max Risk Score
01 // What It Is
Purpose
The AI Risk & Exposure Heatmap is a single-file, browser-based risk governance dashboard designed to track, visualize, and manage AI-specific risks across your MSP and client environments. It replaces static spreadsheet risk registers with a live, interactive view that updates all four charts simultaneously when you filter, add, or modify risks.
It maps directly to the AI Governance Kickoff deliverables — the risk register you start during client onboarding becomes the live data source for this dashboard. Every risk is a compliance artifact: the ID, score, owner, mitigation %, and notes are exactly what auditors ask for during SOC 2, CMMC, and HIPAA reviews.
It maps directly to the AI Governance Kickoff deliverables — the risk register you start during client onboarding becomes the live data source for this dashboard. Every risk is a compliance artifact: the ID, score, owner, mitigation %, and notes are exactly what auditors ask for during SOC 2, CMMC, and HIPAA reviews.
Who Uses It and When
AI Committee & CISO — monthly governance reviews. The category donut and trend line tell the story in seconds without needing to explain the data.
Compliance leads — SOC 2 / CMMC / HIPAA evidence gathering. Filter to the relevant category, export the table or print the report.
Engineers (MK) — adding new risks discovered during client assessments, updating mitigation % as controls are deployed, managing the register week-to-week.
Executive briefings — the Critical Hero bar at the top gives a single number that needs no explanation. If that number is above zero, the briefing starts there.
Compliance leads — SOC 2 / CMMC / HIPAA evidence gathering. Filter to the relevant category, export the table or print the report.
Engineers (MK) — adding new risks discovered during client assessments, updating mitigation % as controls are deployed, managing the register week-to-week.
Executive briefings — the Critical Hero bar at the top gives a single number that needs no explanation. If that number is above zero, the briefing starts there.
02 // Architecture
File Structure
Single HTML file — zero build step, no server required.
Chart.js 4.4.1 via cdnjs CDN (bubble, line, doughnut, bar).
Google Fonts via CDN (Orbitron, Share Tech Mono, Rajdhani).
All JS inline. No React, no framework, no bundler.
Fully self-contained for SharePoint or static hosting.
Chart.js 4.4.1 via cdnjs CDN (bubble, line, doughnut, bar).
Google Fonts via CDN (Orbitron, Share Tech Mono, Rajdhani).
All JS inline. No React, no framework, no bundler.
Fully self-contained for SharePoint or static hosting.
Data Flow
var RISKS array → getFiltered() → all 4 charts + hero + table.Every filter change, add, or sort calls
renderAll() which rebuilds all outputs simultaneously.No page reload needed — all state lives in JS memory for the session.
Chart System
Matrix — Chart.js bubble chart (X=Likelihood, Y=Impact, r=Mitigation%)
Trend — Chart.js dual-axis line (avg score + critical open count)
Category — Chart.js doughnut (risk count by category)
Status/Mitigation — Chart.js bar (Open/Mitigated/Closed) + HTML bars by category
Trend — Chart.js dual-axis line (avg score + critical open count)
Category — Chart.js doughnut (risk count by category)
Status/Mitigation — Chart.js bar (Open/Mitigated/Closed) + HTML bars by category
Key Functions
getRiskScore(r) — returns L × IgetTier(s) — CRITICAL / HIGH / MEDIUM / LOWgetFiltered() — applies cat + status filtersrenderAll() — rebuilds all 4 charts + hero + tableopenDrawer(id) — shows detail panelsaveRisk() — adds risk, calls renderAll()sortTable(col) — toggles sort direction
03 // Critical Hero Bar
The Single Most Important Number
The full-width red panel at the very top shows Critical Risks Open — the count of risks with Score > 15 AND Status = Open. This is intentionally the largest element on the page. If this number is above zero, everything else is secondary.
Right side stats: High Risk Open (Score 11–15, Open), % Mitigated (all statuses), Average Risk Score (filtered set).
Border color shifts: Deep red when critical count > 3, orange when > 0, green when all clear. The rail badge in the top bar mirrors the critical count so it's visible from any scroll position.
Right side stats: High Risk Open (Score 11–15, Open), % Mitigated (all statuses), Average Risk Score (filtered set).
Border color shifts: Deep red when critical count > 3, orange when > 0, green when all clear. The rail badge in the top bar mirrors the critical count so it's visible from any scroll position.
Element
What it shows
Large red number
Count of risks where Score > 15 AND Status = Open. Uses active filter — if you filter to PII category, it shows only PII critical risks.
High Risk Open
Count where Score > 10 AND Score ≤ 15 AND Status = Open. Orange color. Priority review within 1 week.
% Mitigated
Count of Mitigated + Closed risks ÷ total RISKS (unfiltered). Shows overall program velocity regardless of current filter.
Avg Risk Score
Mean of getRiskScore() across the current filtered set. The trend chart tracks this number over time — it should be declining month over month.
04 // Filter Bar
How Filters Work
The filter bar has two independent filter sets — Category (8 options) and Status (3 options). Both can be active simultaneously. Clicking any button immediately calls
Practical use: filter to PII + Open before a HIPAA review. Filter to Governance + All statuses to show AI committee leadership only their domain. Filter to All + Open for the default working view. The active filter state is reflected visually — each category button has its own accent color when active.
renderAll() — all four charts, the hero bar, and the table update in under 100ms.Practical use: filter to PII + Open before a HIPAA review. Filter to Governance + All statuses to show AI committee leadership only their domain. Filter to All + Open for the default working view. The active filter state is reflected visually — each category button has its own accent color when active.
Category
Color
Covers
PII
■ RED
Personally identifiable data exposure — prompt injection, Copilot oversharing, graph permission leaks, PHI handling.
Agent
■ ORANGE
Copilot Studio and autonomous agent risks — hallucination, scope creep, privilege escalation, AI-generated code vulnerabilities.
Vendor
■ PURPLE
Third-party AI model and plugin risks — data retention post-session, M365 store plugins, vendor BAA gaps.
Governance
■ CYAN
Policy, process, and oversight gaps — shadow AI, no audit trail, no AUP, no human approval gate on automated actions.
Identity
■ YELLOW
Entra ID and IAM risks — over-permissioned service principals, AI integrations using Global Admin scope.
Cloud
■ BLUE
M365 and cloud AI risks — phishing bypass, non-compliant log storage, AI workloads in untested regions.
Data
■ GREEN
Training data and model integrity risks — data poisoning, bias in HR/hiring workflows, data lineage gaps.
Compliance
■ PINK
Regulatory risks — HIPAA PHI handling without BAA, CMMC AI controls, sector-specific AI regulations.
05 // Risk Matrix — Bubble Chart
How to Read It
X-axis = Likelihood (1–5). How probable is this risk? 1 = Rare, 3 = Possible, 5 = Almost Certain.
Y-axis = Impact (1–5). How severe if it occurs? 1 = Negligible, 3 = Moderate, 5 = Catastrophic.
Bubble size = Mitigation % complete. A large bubble means significant work is already done — active mitigation in progress. A small bubble means the risk has little or no control coverage.
Bubble color = Score tier. Red (Critical >15), Orange (High >10), Yellow (Medium >5), Green (Low ≤5).
The danger zone is top-right — high likelihood AND high impact. A small red bubble in that corner is your most urgent risk: severe if it happens, likely to happen, and barely started on mitigation. Click any bubble to open its full detail drawer.
Y-axis = Impact (1–5). How severe if it occurs? 1 = Negligible, 3 = Moderate, 5 = Catastrophic.
Bubble size = Mitigation % complete. A large bubble means significant work is already done — active mitigation in progress. A small bubble means the risk has little or no control coverage.
Bubble color = Score tier. Red (Critical >15), Orange (High >10), Yellow (Medium >5), Green (Low ≤5).
The danger zone is top-right — high likelihood AND high impact. A small red bubble in that corner is your most urgent risk: severe if it happens, likely to happen, and barely started on mitigation. Click any bubble to open its full detail drawer.
Zone
What you're seeing
Required action
Top-right · Small
Most urgent. High Likelihood × High Impact + low mitigation. Open, almost certainly going to cause harm, and nothing meaningful is in place.
ESCALATE NOW
Top-right · Large
Controlled critical. Same danger zone but mitigation is underway. Maintain momentum — don't let this stall.
MONITOR
Bottom-left · Any
Managed zone. Low likelihood × low impact. Acceptable residual risk if ownership and review cadence are in place.
QUARTERLY
Anywhere moving left
Good signal. Likelihood dropping as controls reduce attack surface. Aim to move all bubbles toward bottom-left while growing their size.
PROGRESS
06 // Risk Score Trend — Line Chart
Two Lines, Two Stories
Orange solid line (left axis) = Average Risk Score across all non-closed risks. This is the primary governance metric. It should trend downward over time as mitigation closes out risk. If it rises, you're adding more risk than you're resolving.
Red dashed line (right axis) = Critical Open Count. The number of Score > 15 open risks per month. Should reach zero and stay there. Any month it rises above the previous month is a governance failure — new critical risk entered without sufficient controls.
The current month is always live — populated from the actual
Red dashed line (right axis) = Critical Open Count. The number of Score > 15 open risks per month. Should reach zero and stay there. Any month it rises above the previous month is a governance failure — new critical risk entered without sufficient controls.
The current month is always live — populated from the actual
RISKS array in real time. Historical months (Oct 2025 – Feb 2026) are static baseline values. Once connected to SharePoint with date-tracking, all months can be historical.
Month
Avg Score
Crit Open
Interpretation
Oct 2025
14.2
5
Baseline — program starting, many unmitigated risks
Nov 2025
13.8
5
Slight score drop, crit count holds — mitigation starting
Dec 2025
12.1
4
Good progress — controls closing out high-severity risks
Jan 2026
13.4
6
Red flag — score and crit count both rose. New risks added (Lateral Movement, BGP Route Flap) without compensating closures.
Feb 2026
11.9
5
Recovery — AUP published (AR-016 mitigated), S1 rules deployed (AR-007 mitigated)
Mar 2026
Live
Live
Calculated in real time from current RISKS array. Updates immediately when risks are added, closed, or mitigation % changes.
07 // Category Donut
Risk Distribution by Category
Each slice represents one category — slice size proportional to number of risks in that category from the current filtered set. The legend below it shows exact counts. This is your governance attention map.
A large PII slice means data handling controls are under-developed. A large Governance slice means policy hasn't caught up to tooling. A large Agent slice — Copilot Studio agent oversight is your gap.
Use this chart in exec briefings without needing to explain any numbers. The visual tells the story: if one color dominates, that's where investment is needed. As mitigation and closures happen, slices should equalize and shrink.
A large PII slice means data handling controls are under-developed. A large Governance slice means policy hasn't caught up to tooling. A large Agent slice — Copilot Studio agent oversight is your gap.
Use this chart in exec briefings without needing to explain any numbers. The visual tells the story: if one color dominates, that's where investment is needed. As mitigation and closures happen, slices should equalize and shrink.
08 // Mitigation Progress Panel
Two Views of Progress
Top bar chart: Open / Mitigated / Closed counts as bars. Red, Yellow, Green. This shows velocity — you want the Mitigated and Closed bars growing each month. If Open keeps growing while Mitigated stays flat, risk is accumulating faster than it's being addressed.
Horizontal bars below: Average mitigation % per category. Uneven bars reveal exactly where work is concentrated and where it's stalled. If Governance is at 55% but Vendor is at 22%, you know the next sprint's focus.
Use this panel side-by-side with last month's screenshot in committee reporting. Progress — or lack of it — is immediately visible without any explanation required.
Horizontal bars below: Average mitigation % per category. Uneven bars reveal exactly where work is concentrated and where it's stalled. If Governance is at 55% but Vendor is at 22%, you know the next sprint's focus.
Use this panel side-by-side with last month's screenshot in committee reporting. Progress — or lack of it — is immediately visible without any explanation required.
09 // Risk Table
Sorted, Color-Coded, Fully Clickable
Default sort is Score descending — highest risk at the top. Click any column header to re-sort; click again to reverse direction. The active sort column shows a directional arrow.
Row backgrounds: Red rows = Critical (Score > 15) + Open. Orange rows = High (Score > 10) + Open. No background = Medium, Low, or already Mitigated/Closed.
Every row is clickable — opens the detail drawer on the right. The inline mitigation progress bar shows the % at a glance without opening the drawer.
Best sort for triage: Sort by Score descending (default) to work top-to-bottom by urgency. Best sort for sprint planning: Sort by Mitigation % ascending to find the highest-score risks with the least progress — those are your fastest governance wins.
Row backgrounds: Red rows = Critical (Score > 15) + Open. Orange rows = High (Score > 10) + Open. No background = Medium, Low, or already Mitigated/Closed.
Every row is clickable — opens the detail drawer on the right. The inline mitigation progress bar shows the % at a glance without opening the drawer.
Best sort for triage: Sort by Score descending (default) to work top-to-bottom by urgency. Best sort for sprint planning: Sort by Mitigation % ascending to find the highest-score risks with the least progress — those are your fastest governance wins.
Column
Type
Sortable
L
I
Mitigation
Status
ID
AR-001 format
YES
Columns: ID (sortable) · Description (plain text) · Category (sortable, color badge) · Score (sortable, color-coded large number) · L (Likelihood 1–5) · I (Impact 1–5) · Mitigation (inline bar + %) · Status (badge) · Owner · Updated
10 // Detail Drawer
Full Risk Record — Slides in from Right
Clicking any table row or matrix bubble opens the detail drawer. It shows: Risk Score (large, color-glowing number), tier badge + status badge, full description, category, Likelihood × Impact breakdown (
At the bottom of each drawer is a SharePoint sync placeholder — once the SP list is wired, this area will show the live list item link and last sync timestamp.
Close with the ✕ Close button or press Escape. The drawer does not block the rest of the page — you can still interact with filters and the table while it's open.
3 × 5 = 15), mitigation progress bar, owner, last updated, and the full notes / mitigation plan text.At the bottom of each drawer is a SharePoint sync placeholder — once the SP list is wired, this area will show the live list item link and last sync timestamp.
Close with the ✕ Close button or press Escape. The drawer does not block the rest of the page — you can still interact with filters and the table while it's open.
11 // Risk Score Reference
Score
Range
Tier
Required Action
Review Cadence
20–25
L×I > 15
CRITICAL
Immediate escalation. Owner presents mitigation plan within 48 hours. Appears in hero count. Red bubble in matrix top-right. Red row in table.
48 hours
11–15
L×I > 10
HIGH
Priority review within 1 week. Owner updates mitigation % and notes. Orange row in table.
Weekly
6–10
L×I > 5
MEDIUM
Track mitigation progress. No immediate escalation but must have an active owner and a plan.
Monthly
1–5
L×I ≤ 5
LOW
Document and monitor. Acceptable residual risk if mitigation plan exists and is documented.
Quarterly
12 // 18 Seed Risks
Pre-Loaded Risk Register
The dashboard ships with 18 real AI governance risks drawn from MSP client assessments. These are not placeholder data — they reflect actual exposure patterns seen across M365, Copilot Studio, third-party AI tools, and identity configurations. Replace or supplement them with your specific client risks using the + Add Risk modal.
ID
Category
L
I
Score
Status
AR-001
PII
4
5
20
OPEN
PII exposure via Copilot prompt injection — Engineers pasting client data into Copilot chat without sanitization. Mitigation: 20%
AR-002
GOVERN.
5
4
20
OPEN
Unapproved AI tool usage (Shadow AI) — Staff using ChatGPT, Claude, Gemini without approval. Mitigation: 15%
AR-003
AGENT
4
4
16
OPEN
Agent hallucination producing incorrect client output — Copilot Studio agents generating recommendations without human-in-the-loop review. Mitigation: 35%
AR-004 – AR-018
M365 oversharing, no audit trail, vendor data retention, AI phishing, agent privilege escalation, HIPAA BAA gap, scope creep, no human approval gate, HR bias, identity over-permission, data poisoning, third-party plugins, no AUP, non-compliant storage, AI-generated code vulns.
MIXED
13 // Category Distribution in Seed Data
Category
Count
Status
IDs
Governance
4
2 Open, 2 Mitigated
AR-002, AR-005, AR-011, AR-016
Agent
4
All Open
AR-003, AR-008, AR-010, AR-018
PII
2
Both Open
AR-001, AR-004
Vendor
2
1 Open, 1 Mitigated
AR-006, AR-015
Cloud
2
1 Open, 1 Mitigated
AR-007, AR-017
Data
2
Both Open
AR-012, AR-014
Compliance
1
Open
AR-009 (HIPAA PHI / BAA)
Identity
1
Open
AR-013 (Entra over-permission)
14 // Adding a New Risk
+ Add Risk Modal
Click + ADD RISK in the top-right of the rail. The modal opens with a form: Description, Category (dropdown), Owner, Likelihood (1–5), Impact (1–5), Mitigation % (0–100), Status, and Notes.
Live Score Preview — as you type Likelihood and Impact, the Score Preview box updates immediately with the calculated score and color-coded tier badge (red for Critical before you even save). This gives instant feedback on how serious the risk is before committing it to the register.
Saving calls
Live Score Preview — as you type Likelihood and Impact, the Score Preview box updates immediately with the calculated score and color-coded tier badge (red for Critical before you even save). This gives instant feedback on how serious the risk is before committing it to the register.
Saving calls
saveRisk() which pushes the new object into RISKS, assigns the next AR-XXX ID, and immediately calls renderAll() — all four charts update without a page reload. Press Escape or Cancel to close without saving.
Field
Type
Notes
Description
Text
Keep under 120 chars for table readability. Plain language.
Category
Dropdown
PII / Agent / Vendor / Governance / Identity / Cloud / Data / Compliance
Owner
Text
Name or team. Examples: MK, Legal, Security, AI Comm., IAM, HR, Cloud Ops, Eng.
Likelihood
1–5
1 = Rare (once in 5+ years), 3 = Possible (once a year), 5 = Almost Certain (active/ongoing)
Impact
1–5
1 = Negligible (no client impact), 3 = Moderate (client service affected), 5 = Catastrophic (data breach, regulatory action)
Mitigation %
0–100
Estimated % of controls in place. 0 = nothing started. 100 = all controls deployed (consider closing). Drives bubble size in matrix.
Status
Dropdown
Open = active risk with no or partial controls. Mitigated = controls deployed, risk reduced but still monitored. Closed = accepted or fully resolved.
Notes
Text
Mitigation plan, control description, audit notes. This text is the compliance artifact — write it as if an auditor will read it.
15 // Deployment
Path
Auth
Notes
SharePoint (Recommended)
SP SESSION
Upload as
.aspx. Add <%@ Page Language="C#" %> before DOCTYPE. Remove Google Fonts link, replace font-family with Segoe UI, Consolas, system-ui. Add type="text/javascript" to script tags. Save UTF-8 no BOM, LF endings. Restrict via Entra security group.krawczyk.city
OPEN
Drop in
demos/ folder. Works immediately. Keep demo data only — do not put real client risk data on a public host.Azure Static Web App
EASY AUTH
Deploy via GitHub Actions. Add Entra Easy Auth as gate. Best for committee members outside your SP tenant who need access.
CDN Block on SharePoint
SharePoint may block
cdnjs.cloudflare.com via tenant CSP. Download Chart.js 4.4.1 (chart.umd.min.js) and upload to the same SP document library. Update the <script src> to the SP-relative path.16 // SharePoint List — "AI Risk Register"
Required SP List Columns
Create a new SharePoint list called "AI Risk Register" (or clone your existing one). Every column maps directly to a field already in the dashboard. Once the backend fetch is wired, the dashboard replaces its
var RISKS demo array with live data from this list.Risk ID — Single line text · Unique
Description — Single line text
Category — Choice (8 options)
Likelihood — Number (1–5, integer)
Impact — Number (1–5, integer)
Risk Score — Calculated: =Likelihood*Impact
Owner — Person or text
Status — Choice (Open, Mitigated, Closed)
Mitigation % — Number (0–100)
Last Updated — Date and Time
Notes — Multiple lines of text
17 // Wiring Live Data
Replace var RISKS with a SP REST Fetch
In the dashboard HTML, find
var RISKS = [...]. Replace the static array initialization with a fetch call on page load that pulls from the SP list. If the dashboard is hosted on the same SP site as the list, the user's existing session handles authentication — no token code needed.
// Replace static var RISKS = [...] with this fetch on DOMContentLoaded
var RISKS = []; // start empty, populate from SP
var siteUrl = 'https://TENANT.sharepoint.com/sites/YOURSITE';
var listName = 'AI Risk Register';
var endpoint = siteUrl + "/_api/web/lists/getbytitle('" + listName + "')/items"
+ "?$select=RiskID,Description,Category,Likelihood,Impact,MitigationPct,Status,Owner,LastUpdated,Notes"
+ "&$orderby=RiskScore desc&$top=500";
fetch(endpoint, { headers: { 'Accept': 'application/json;odata=verbose' } })
.then(function(r) { return r.json(); })
.then(function(data) {
RISKS = data.d.results.map(mapSPItem);
renderAll(); // rebuild all 4 charts with live data
})
.catch(function(err) { console.error('SP fetch failed:', err); });
// Field mapping — SP internal names → dashboard schema
function mapSPItem(item) {
return {
id: item.RiskID,
desc: item.Description,
category: item.Category,
likelihood: parseInt(item.Likelihood),
impact: parseInt(item.Impact),
mitigation: parseInt(item.MitigationPct || 0),
status: item.Status,
owner: item.Owner?.Title || item.Owner || 'Unassigned',
updated: new Date(item.LastUpdated).toLocaleDateString('en-US',{month:'short',day:'numeric'}),
notes: item.Notes || ''
};
}
Write-Back — Save New Risks to SP
To write the + Add Risk modal back to the SP list (instead of only in-memory), replace the
RISKS.push() call inside saveRisk() with a POST to the SP REST API. Requires the X-RequestDigest header (fetch from /_api/contextinfo) and the correct list item type name.
// Get form digest for POST auth
async function getDigest() {
const r = await fetch(siteUrl + '/_api/contextinfo', {
method: 'POST', headers: { 'Accept': 'application/json;odata=verbose' }
});
const d = await r.json();
return d.d.GetContextWebInformation.FormDigestValue;
}
// POST new risk item to SP list
fetch(siteUrl + "/_api/web/lists/getbytitle('AI Risk Register')/items", {
method: 'POST',
headers: {
'Accept': 'application/json;odata=verbose',
'Content-Type': 'application/json;odata=verbose',
'X-RequestDigest': await getDigest()
},
body: JSON.stringify({
'__metadata': { 'type': 'SP.Data.AI_x0020_Risk_x0020_RegisterListItem' },
RiskID: id, Description: desc, Category: cat,
Likelihood: l, Impact: imp, MitigationPct: mit,
Status: status, Notes: notes
})
});
18 // Power BI Integration Path
Step
Action
1
Connect to SP list: Power BI Desktop → Home → Get Data → SharePoint Online List. Enter site URL, select "AI Risk Register". Load all columns. In Power Query, set Likelihood and Impact as Whole Number, Mitigation% as Decimal, Risk Score as Whole Number.
2
Create DAX measures:
Risk Score = AVERAGE('AI Risk Register'[Likelihood] * 'AI Risk Register'[Impact])Critical Count = CALCULATE(COUNTROWS('AI Risk Register'), 'AI Risk Register'[Risk Score] > 15, 'AI Risk Register'[Status] = "Open")Mitigation Avg = AVERAGE('AI Risk Register'[Mitigation %])
3
Conditional formatting on table: Format → Conditional formatting → Background color → Rules.
Rule 1: Risk Score > 15 → Background
Rule 2: Risk Score > 10 → Background
Rule 3: Risk Score > 5 → Background
Rule 1: Risk Score > 15 → Background
#4d1010, Font #ff4444Rule 2: Risk Score > 10 → Background
#4d2800, Font #ff8800Rule 3: Risk Score > 5 → Background
#4d4400, Font #ffe600
4
Publish & embed in SharePoint: Publish to a Power BI workspace. In SharePoint, add a Power BI web part. Set default filter to Status = Open. Pin the Critical Count card to a Dashboard and embed that — it shows one number, always live.
19 // Data Schema Reference
Risk Object
id — string, format AR-001desc — plain language stringcategory — one of 8 category stringslikelihood — integer 1–5impact — integer 1–5mitigation — integer 0–100status — Open / Mitigated / Closedowner — string (name or team)updated — date string (e.g. "Mar 22")notes — plain text string
Computed Values (never stored)
getRiskScore(r) = r.likelihood × r.impactgetTier(s) = CRITICAL / HIGH / MEDIUM / LOWgetTierColor(s) = hex color stringgetTierBadgeClass(s) = CSS class namegetCatBadgeClass(c) = CSS class for categorygetMitColor(pct) = green/yellow/orange based on %Score is always calculated live — never hardcode it. If Likelihood or Impact changes, Score auto-updates on next
renderAll().
20 // Trend Data — Historical Baselines
TREND_DATA Array
The line chart uses a
To add a month: push a new object
var TREND_DATA array of monthly snapshots. The last entry is always populated live from the current RISKS array before each chart rebuild. Historical months are static — update them manually each month as you close the governance period, or pull them from SP list version history once the integration is live.To add a month: push a new object
{'month': 'Apr 2026', avg: null, open: null, crit: null} to TREND_DATA. The null values tell the chart to leave that month blank until it becomes current.
21 // Go-Live Checklist
ALL MUST PASS BEFORE FIRST COMMITTEE REVIEW
Dashboard file deployed to SharePoint or hosting target. Accessible via Entra security group (AI-RiskDashboard-Access minimum).
All 4 charts render on first load — matrix, trend, category donut, status/mitigation bars. No blank panels or JS console errors.
Critical Hero bar shows correct count. Manually verify it matches the count of Score >15 + Open risks in the table.
Filters tested in all combinations — each category button, all status buttons, combined category + status. All 4 charts update simultaneously.
Every table row click opens the correct detail drawer with matching risk data. Bubble clicks in the matrix also open the drawer.
+ Add Risk tested — add one risk, verify score preview updates live as L and I are typed, save, and confirm all 4 charts rebuild with the new risk included.
Sort tested on all sortable columns — ID, Category, Score, Likelihood, Impact, Status. Verify ascending and descending both work.
Seed risks reviewed — replace or augment the 18 seed risks with real risks from your current AI governance assessments. At minimum, assign real owners to each open risk.
SharePoint "AI Risk Register" list created with all required columns and correct types. Risk Score calculated column formula confirmed:
=Likelihood*Impact.SP REST fetch wired (or Power BI embedded) — dashboard shows live data, not seed data, before sharing with committee.
Owners notified — each open risk has an assigned owner who knows they're responsible for updating Mitigation % and Notes monthly.
Monthly review cadence confirmed — first committee review scheduled. Each review: update mitigation %, close resolved risks, add newly discovered risks, capture a screenshot for trend baseline.
22 // Known Items & Notes
Fully Stateless — No localStorage
The dashboard uses no localStorage or sessionStorage. All risk data lives in
var RISKS in JS memory for the session. No SharePoint storage concerns, no cross-tab conflicts. Page refresh resets to seed data until the SP live fetch is wired.Score Never Stored — Always Derived
Risk Score is never persisted in the risk object. It's always calculated live as
getRiskScore(r) = r.likelihood × r.impact. The SharePoint calculated column (=Likelihood*Impact) exists for list-view filtering only — the dashboard always recalculates independently.Chart.js CDN Dependency
All 4 charts require Chart.js 4.4.1 from
cdnjs.cloudflare.com. If this CDN is blocked by SharePoint's Content Security Policy, download chart.umd.min.js locally and upload to the same SP document library. Update the <script src> to the SP-relative path.Trend Data is Partially Static
The historical months in
TREND_DATA (Oct 2025 – Feb 2026) are static baseline values. Only the current month is live. Until the SP integration includes date-tracking, update historical months manually at the end of each governance period by editing the TREND_DATA array directly in the file.Add Risk Only Saves to Memory
The + Add Risk modal writes to the in-memory RISKS array only. The data does not persist on page refresh. To make new risks permanent, either wire the SP write-back (Phase 3 of live data wiring) or manually add the risk to the SP list and re-fetch.
Bubble Click Requires Exact Hit
Chart.js bubble click detection uses a small hit radius. If a bubble is very small (low mitigation %), it can be hard to click. Sort the table by Score descending and click the row instead — it opens the same detail drawer. Increasing the minimum bubble radius in
buildMatrix() (the Math.max(5, ...) call) makes small bubbles easier to hit.