HOMEGOVERNANCEAI INCIDENT LOG — KB
ai-incident-log.html · Phase 0
KNOWLEDGE BASE // GOVERNANCE // AI INCIDENT & ANOMALY LOG
AI Incident & Anomaly Log
Complete reference for using, configuring, and deploying the AI incident tracking console. This document covers the end-user workflow and the full SharePoint integration build in a single guide.
GOVERNANCE PHASE 0 — DEMO MODE SP READY USER GUIDE CONFIG GUIDE
FILE
ai-incident-log.html
DATA SOURCE
Mock → SharePoint Phase 1
AUDIENCE
All AI Stakeholders + Implementers
LIST NAME
AI Incident Log
SP AUTH
Cookie / No App Reg Required
01
WHAT THIS TOOL DOES

The AI Incident & Anomaly Log is the primary tracking console for AI-related security events, policy violations, and operational anomalies across the environment. It is part of the AI Governance suite and is designed to be reviewed at each AI Steering Committee meeting.

The console is a single self-contained HTML file. It runs in the browser, requires no backend server or build process, and in Phase 1 reads from and writes to a SharePoint list using the user's existing browser session for authentication.

📊
LIVE KPI CARDS
Four stat cards showing Open High Severity, Total Open/Investigating, Month-to-Date incidents, and overall resolution rate. Auto-update on every new submission.
📈
THREE CHARTS
Rolling 6-month bar/line combo (total vs high severity), category breakdown donut, and current status donut. All calculated from the full dataset.
📋
INCIDENT REGISTER
Sortable, filterable table with live search across all fields. Click any row to open the full detail modal. Export filtered results to CSV at any time.
✏️
LOG NEW INCIDENTS
Built-in form with date, category, severity, owner, description, and resolution notes. Submissions update all cards and charts instantly.
⚠️
EVENT
AI anomaly detected
✏️
LOG
Fill the form
📊
UPDATE
Cards & charts refresh
🔍
REVIEW
Filter, search, drill in
📤
EXPORT
CSV for committee
02
HOW IT WORKS

The console has two operating modes controlled by a single flag in the script. Switching from demo to live requires no UI changes — only the data layer swaps.

DEMO MODE (PHASE 0 — CURRENT)

The page loads a hardcoded dataset of 15 seed incidents directly from the script. No network calls are made. All filtering, sorting, form submissions, and chart rendering work identically to production — the only difference is that new records are not persisted between page refreshes. This mode lets teams use and evaluate the tool immediately without any SharePoint setup.

DEMO MODE INDICATOR The orange dot labeled DEMO MODE in the top-right of the console signals that the SP connection is not active. The orange banner across the top of the page is the Phase 1 wiring note — remove it when you go live.
LIVE MODE (PHASE 1 — TARGET)

On page load, the console calls the SharePoint REST API to fetch all items from the AI Incident Log list. When a new incident is logged, it fires a POST to create a new list item. Authentication is handled automatically by the user's existing SharePoint browser session — no API keys, no app registrations, no OAuth configuration required.

LAYERPHASE 0 (DEMO)PHASE 1 (LIVE)
Data SourcegetMockData() — 15 seed records in scriptSharePoint REST GET on list items
WriteIn-memory push to ALL_INCIDENTS arraySharePoint REST POST to list
AuthNone requiredBrowser session cookie + X-RequestDigest
PersistenceLost on page refreshPermanent in SharePoint list
UI / ChartsIdentical in both modes — no changes required
KEY SCRIPT OBJECTS
SP_CONFIG
Object at the top of the script containing siteUrl, listName, and demoMode. The only values that need editing before go-live.
fetchIncidents()
Async function that returns the incident array. In demo mode calls getMockData(). In Phase 1, this calls the SharePoint REST GET endpoint — the commented production block is already written and just needs to be uncommented.
submitIncident()
Handles form submission. In demo mode pushes to the in-memory array. In Phase 1, fetches a request digest and fires a REST POST. The production code block is pre-written and commented inline.
mapSPItem(r)
Transforms a raw SharePoint list item into the flat object the UI expects. Column name mapping lives here. If your SharePoint column names differ from the defaults, this is the only place to update them.
getRequestDigest()
Helper function that fetches the X-RequestDigest token from /_api/contextinfo. Required for authenticated POST calls to SharePoint. Already active in the script — no changes needed.
03
STAT CARDS

Four cards sit across the top of the console. They calculate against the full dataset regardless of any active table filters and update automatically when new incidents are logged.

OPEN HIGH SEVERITY
Count of incidents where Severity is HIGH and Status is not RESOLVED. Shows "ACTION REQUIRED" in red when above zero. This is the first metric reviewed in any committee meeting — a nonzero value means something is unresolved and needs an owner today.
TOTAL OPEN / INVESTIGATING
Combined count of OPEN and INVESTIGATING incidents. The sub-label breaks the count into both statuses. This is the pipeline size — how many incidents are actively in motion.
MTD INCIDENTS
Count of incidents logged in the current calendar month based on the Incident Date field (not the log date). Shows the full month name below. Use this to track monthly volume trends.
% RESOLVED (ALL TIME)
Percentage of all incidents across all time with Status set to RESOLVED. The sub-label shows the raw fraction. A healthy register trends toward 90%+ resolved over time.
04
CHARTS

Three charts sit below the stat cards. All three calculate against the full dataset and do not respond to table filters — they always show the complete picture.

INCIDENTS BY MONTH
Rolling 6-month combo chart. Cyan bars show total incident count per month. The red line shows High Severity incidents only. Hover over any month to see both values in a tooltip. Use this to spot volume trends and high-severity spikes.
BY CATEGORY
Donut chart showing the proportion of incidents per category across all time. Hover a segment for the exact count. Use this to identify which incident types are most frequent and where policy controls may need tuning.
STATUS BREAKDOWN
Donut showing the current ratio of OPEN, INVESTIGATING, and RESOLVED. A healthy register shows the green Resolved segment as the dominant slice. A large Open or Investigating slice signals backlog buildup.
05
LOGGING AN INCIDENT

The Log New Incident form sits directly above the register table. The Date field auto-fills to today on page load. Required fields are Date, Category, Severity, and Description — Owner and Resolution Notes can be filled in later.

DATE FIELD Always enter the date the incident occurred, not the date you are logging it. If you are catching up on a past incident, adjust the date backward before submitting.
  • 1
    Confirm or adjust the Date.Defaults to today. Change it if logging a past incident.
  • 2
    Select a Category.Pick the type that best fits. See Section 10 for full category definitions. If nothing fits, use Other and explain in the Description field.
  • 3
    Select a Severity.High for confirmed data exposure, active bypass, unauthorized production changes, or any client impact. Medium for policy violations without confirmed exposure. Low for benign anomalies or near-misses. See Section 11 for the full matrix.
  • 4
    Enter the Owner.The engineer or lead responsible for driving this to resolution. Can be left blank at log time and assigned during triage.
  • 5
    Write a factual one-line Description.What happened, where, and which AI tool or workflow was involved. No speculation — stick to what is confirmed at time of logging.
  • 6
    Add initial Resolution Notes if available.Paste any immediate containment steps already taken. This can be left blank and updated later directly in SharePoint once Phase 1 is live.
  • 7
    Click LOG INCIDENT.The record appears at the top of the register immediately. All four stat cards and all three charts update. A green confirmation toast appears in the bottom-right corner with the assigned Incident ID.
PHASE 0 PERSISTENCE In demo mode, new incidents exist only in memory. They are lost if the page refreshes. In Phase 1, every submission writes directly to the SharePoint list and persists permanently.
06
FILTERING & SEARCHING

The toolbar above the register table has four controls that work simultaneously. Filtering is instant — no button press required. The export always reflects the current filtered view.

SEARCH BAR
Full-text search across Incident ID, Description, Category, Owner, and Resolution Notes. Type a tool name, engineer name, or any keyword to find matching records across all fields at once.
SEVERITY FILTER
Narrows to HIGH, MEDIUM, or LOW only. Combine with Status filter to quickly surface all open high-severity items.
STATUS FILTER
Narrows to OPEN, INVESTIGATING, or RESOLVED. Set to Open to see only active incidents requiring attention.
CATEGORY FILTER
Narrows by incident type. Use this to pull all DLP Block incidents for a policy review or all Cost Spike incidents for a budget review.

Clicking any column header sorts by that column. Clicking the same header again reverses direction. The sorted column header is highlighted in cyan.

USEFUL FILTER COMBINATIONS Severity: High + Status: Open — all unresolved critical items.
Category: DLP Block — full DLP trend for policy review.
Search: [engineer name] — all incidents assigned to a specific owner.
Status: Investigating — everything currently in active triage.
07
INCIDENT DETAIL VIEW

Clicking any row in the register opens the Incident Detail modal. The modal shows all fields for that record in full — Description and Resolution Notes are not truncated as they are in the table view.

  • 1
    Click any rowin the register. The modal appears centered on screen.
  • 2
    Review all fieldsincluding the full Resolution Notes block at the bottom of the modal panel.
  • 3
    Close by clicking ✕in the top-right of the modal, or by clicking anywhere outside the modal panel.
EDITING IN PHASE 1 To update an existing incident's Status or Resolution Notes, open the SharePoint list directly and edit the item there. The console will reflect the updated values on next page load. A future iteration of the detail modal will include an inline edit button.
08
EXPORTING TO CSV

The ↓ CSV button in the table toolbar exports the rows currently visible after all active filters are applied. The file is generated entirely in the browser — no server call is made. The filename includes today's date automatically.

  • 1
    Apply filters if needed.The export reflects exactly what is shown in the table. Set no filters to export the full register.
  • 2
    Click ↓ CSV.File downloads as AI-Incident-Log-YYYY-MM-DD.csv immediately.
  • 3
    Open in Excelfor committee reporting, pivot analysis, or pasting into a quarterly review document.
FOR COMMITTEE REPORTS Export the full unfiltered register for the monthly committee packet. For the executive summary, filter to High severity + Open/Investigating, export that view, and paste it as the "Active Critical Incidents" table in the report.
09
FIELD DEFINITIONS
FIELDREQUIREDSP COLUMNNOTES
Incident IDAutoSP Item IDGenerated from SharePoint item ID on read. Format INC-0001. No dedicated column needed in the list.
DateYesIncidentDateDate the incident occurred — not the date logged. Date and Time column type; date-only format is sufficient.
CategoryYesCategoryChoice column. See Section 10 for allowed values and definitions.
DescriptionYesTitle (renamed)Rename the default SharePoint Title column to Description. Single line of text. Factual one-liner — what happened, what tool, what impact.
SeverityYesSeverityChoice column: High, Medium, Low. See Section 11 for the severity decision matrix.
StatusAutoStatusChoice column: Open, Investigating, Resolved. Default value Open. Set during triage and updated as the incident progresses.
OwnerNoOwnerSingle line of text. Engineer or lead responsible for resolution. Can be blank at log time.
Resolution NotesNoResolutionNotesMultiple lines of text, plain text. Containment steps, root cause, follow-up actions. Required before marking Resolved.
10
CATEGORIES

These are the allowed values for the Category field in both the console form and the SharePoint list. Use the most specific category that fits. If none fit, use Other and explain in the Description.

DLP BLOCK
A Data Loss Prevention policy intercepted an AI-driven action involving sensitive data. Examples: Copilot attempting to summarize an email containing SSNs, Power Automate attaching a PII-labeled file via a Copilot action.
JAILBREAK ATTEMPT
A user submitted a prompt designed to bypass guardrails, safety filters, or system prompt constraints. Includes role-play framing, instruction injection, chained prompts intended to extract restricted output, or attempts to reveal system prompts.
COST SPIKE
AI token usage or API spend exceeded expected thresholds in a way that was not planned. Examples: recursive agent loop in dev, batch document generation exceeding monthly caps, unrestricted API key in a personal project.
UNAUTHORIZED DEPLOY
An AI agent, model, or tool was deployed to a production or client environment without completing the required intake form and approval process. Includes third-party vendor deployments inside a client tenant.
DATA EXFILTRATION
Sensitive or client data was submitted to or processed by an AI tool outside of approved boundaries. Examples: submitting a client AD export to ChatGPT, a browser extension accessing internal SharePoint links through an unapproved AI service.
POLICY VIOLATION
An AI-related action violated documented acceptable use, data handling, or governance policy without fitting another specific category. Examples: AI-generated client report published without human review, meeting summary sent to an external non-participant.
OTHER
Any AI-related incident that does not fit the above categories. Always describe what happened in the Description field so the incident can be re-categorized if a pattern emerges later.
11
SEVERITY & STATUS REFERENCE
SEVERITY DECISION MATRIX
LEVELCRITERIARESPONSE SLA
HIGH Confirmed or probable data exposure. Active policy bypass in production. Unauthorized agent or tool deployed to client environment. Any incident with client impact or regulatory implication. Acknowledge within 2 hours. Escalate to InfoSec lead same day. Post-incident review required before closing.
MEDIUM Policy violation with no confirmed data exposure. Cost spike traced to a specific workflow but no external impact. Jailbreak attempt that did not succeed in extracting restricted output. Acknowledge within 24 hours. Assign owner within 48 hours. Review at next weekly team meeting.
LOW Benign anomaly, near-miss, or informational observation with no external impact. Incidents that are fully self-contained. Log and monitor. No immediate action required. Review in monthly AI Steering Committee meeting.
STATUS LIFECYCLE
STATUSMEANINGWHEN TO SETWHO SETS IT
OPENLogged but not yet assigned or actively investigated.Default on creation — set by the system.System
INVESTIGATINGOwner assigned, active triage or remediation underway.As soon as an owner picks it up.Assigned owner
RESOLVEDRoot cause confirmed, containment complete, follow-up actions documented.Only after Resolution Notes are populated. Never close without documenting what was done.Assigned owner + InfoSec review for High
CONFIGURATION GUIDE
C1
PREREQUISITES

Phase 0 (demo) has no prerequisites — open the file in any browser and it runs. Phase 1 (live SharePoint) requires the following before you start.

SP Permissions
Site Owner or Site Collection Administrator on the destination SharePoint site. Site Member is not enough — list creation requires owner-level access.
Site URL
The full site URL in the format https://TENANT.sharepoint.com/sites/SITENAME. Navigate to the site in your browser and copy from the address bar — stop before any page path or query string.
Document Library
Any document library on that site where the HTML file will live. Shared Documents is fine. If you want a subfolder (e.g. pages/) create it before uploading.
Browser Session
The user opening the console must be signed into SharePoint in the same browser. The REST API calls piggyback on the existing session cookie — no separate login is triggered.
Text or Code Editor
VS Code, Notepad++, or any plain-text editor. Do not open or save ai-incident-log.html in Microsoft Word or any rich-text editor — it will corrupt the file silently.
NO APP REGISTRATION REQUIRED This console authenticates via the browser's existing SharePoint session cookie. You do not need an Entra ID app registration, a client secret, or an OAuth flow for standard list read/write operations. If your tenant enforces conditional access policies that block cookie-based REST calls from HTML files in document libraries, contact your SharePoint admin before proceeding.
C2
DEPLOY THE FILE TO SHAREPOINT

The console is a single self-contained HTML file. No dependencies to install, no build step, no backend server. Upload it and it runs.

  • 1
    Navigate to your document libraryon the destination SharePoint site.
  • 2
    Upload ai-incident-log.htmlusing the Upload button or drag-and-drop directly into the library.
  • 3
    Click the file nameto open it. SharePoint renders the HTML inline. You should see the console in demo mode with the orange DEMO MODE badge top-right.
  • 4
    Copy the URL from the address bar.This is the link you will share with users: https://TENANT.sharepoint.com/sites/SITE/Shared%20Documents/ai-incident-log.html
IF THE FILE DOWNLOADS INSTEAD OF OPENING Some tenants are configured to force-download HTML files. A Site Collection Admin must go to SharePoint Admin Center → Settings and enable Custom Script, or the file must be converted to .aspx before upload. See the ASPX Conversion KB for that process. The content and functionality are identical in either format.
RENAMING THE FILE You can rename the file before upload. incident-log.html, ai-incidents.html — the name has no effect on functionality. Update your nav.js entry to match whatever you choose.
C3
CREATE THE SHAREPOINT LIST

The console reads and writes to a SharePoint list named AI Incident Log on the same site. The list name must match exactly — the REST call references it by title.

  • 1
    Go to Site Contents.Gear icon → Site Contents, or navigate to /sites/SITENAME/_layouts/15/viewlsts.aspx
  • 2
    Click + New → List → Blank list.Name it exactly: AI Incident Log. No description needed. Click Create.
  • 3
    Rename the default Title column to Description.Click the Title column header → Column Settings → Rename → type Description → Save.
  • 4
    Add the following columnsusing + Add Column in the list view:
COLUMN NAMETYPEALLOWED VALUES / NOTES
IncidentDateDate and TimeDate only. No time component needed.
CategoryChoiceDLP Block · Jailbreak Attempt · Cost Spike · Unauthorized Deploy · Data Exfiltration · Policy Violation · Other
SeverityChoiceHigh · Medium · Low
StatusChoiceOpen · Investigating · Resolved — set default value to Open
OwnerSingle line of textFree text. No validation.
ResolutionNotesMultiple lines of textPlain text. No rich text or enhanced formatting.
COLUMN NAMES ARE SET AT CREATION — GET THEM RIGHT The internal REST API name for each column is fixed when the column is first created, not when it is renamed in the UI. If you create a column called "incident date" and rename it to "IncidentDate" afterward, the REST API will still see it as incident_x0020_date and the field mapping will break. Create each column using the exact names in the table above.
HOW TO VERIFY INTERNAL COLUMN NAMES Go to List Settings → click the column name → look at the URL. The Field= parameter shows the internal name. Compare against the table above. If there is a mismatch, delete the column and recreate it with the correct name.
C4
UPDATE SP_CONFIG IN THE FILE

Open ai-incident-log.html in a text editor. Near the top of the <script> section, find the SP_CONFIG block:

CURRENT (DEMO MODE)
const SP_CONFIG = { siteUrl: 'https://YOUR-TENANT.sharepoint.com/sites/YOUR-SITE', listName: 'AI Incident Log', demoMode: true, // PHASE 1: set to false after wiring };
  • 1
    Replace siteUrlwith your actual SharePoint site URL. Example: https://cyberadvisors.sharepoint.com/sites/AIHub. No trailing slash. No page path after the site name.
  • 2
    Confirm listNamematches the exact name you gave the list in C3 — including spaces and capitalization. If you named it differently, update this value.
  • 3
    Leave demoMode: true for now.You will flip this to false in C5 after the REST code blocks are uncommented and the list is confirmed to exist.
  • 4
    Save the fileas .html. Do not allow your editor to save it as .txt or any other format.
C5
ACTIVATE LIVE MODE

With the list created and SP_CONFIG updated, activate the SharePoint connection by making three changes in the script and re-uploading the file. All changes are commented inline and clearly marked.

CHANGE 1 — UNCOMMENT THE GET BLOCK

Inside fetchIncidents(), find the block labeled "Production path (uncomment in Phase 1)". Remove the // prefix from each line of the REST GET fetch block. This replaces the getMockData() call with a live SharePoint read.

WHAT THE UNCOMMENTED BLOCK LOOKS LIKE
const endpoint = `${SP_CONFIG.siteUrl}/_api/web/lists/getbytitle('${encodeURIComponent(SP_CONFIG.listName)}')/items` + `?$select=Id,Title,IncidentDate,Category,Description,Severity,Status,Owner,ResolutionNotes` + `&$orderby=IncidentDate desc&$top=500`; const res = await fetch(endpoint, { headers:{ Accept:'application/json;odata=verbose' } }); const json = await res.json(); return json.d.results.map(mapSPItem);
CHANGE 2 — UNCOMMENT THE POST BLOCK

Inside submitIncident(), find the block labeled "PHASE 1: Replace this block with the SP POST call below". Remove the // prefix from each line of the REST POST block. The getRequestDigest() helper at the bottom of the script is already active — no changes needed there.

THE POST BLOCK SENDS THIS PAYLOAD
{ __metadata: { type: 'SP.Data.AI_x0020_Incident_x0020_LogListItem' }, Title: desc, // maps to Description column IncidentDate: date, Category: category, Severity: severity, Status: 'Open', Owner: owner, ResolutionNotes: notes }
CHANGE 3 — FLIP THE FLAG & CLEAN UP
  • 1
    Set demoMode: falsein SP_CONFIG.
  • 2
    Delete the orange wiring banner.Find <div class="wire-banner" id="wireBanner"> in the HTML body and delete the entire element including its closing </div>.
  • 3
    Save the fileand re-upload to SharePoint, replacing the previous version. Confirm the overwrite when prompted.
  • 4
    Open the file in your browser.The status badge should show a solid green dot and read SP CONNECTED. Demo seed data will be replaced by the actual contents of your SharePoint list.
METADATA TYPE — IF YOUR LIST HAS A DIFFERENT NAME The __metadata.type value SP.Data.AI_x0020_Incident_x0020_LogListItem is derived from the list name with spaces encoded as _x0020_. If you named your list something other than AI Incident Log, this value must be updated to match. Confirm the correct value by fetching: /_api/web/lists/getbytitle('YOUR LIST NAME')?$select=ListItemEntityTypeFullName in your browser while logged into SharePoint.
CORS / 403 ON LOAD If you see a CORS error or 403 in the browser console after going live, the page is not being served from the same SharePoint tenant that the REST API is calling. Verify the URL in the address bar matches the tenant in SP_CONFIG.siteUrl. If you are opening the file locally from your desktop (e.g. a C:\ path), the session cookie will not be present and all calls will fail. The file must be opened from SharePoint.
C6
VERIFY & TROUBLESHOOT

Run through each item below after going live. Do not share the console URL with users until all items pass.

  • SP badge is green. Top-right shows solid green dot and reads SP CONNECTED. If still orange, demoMode was not set to false or the file was not re-uploaded.
  • No JS errors on load. Open browser console (F12 → Console tab). No errors should be present. Stat cards show real numbers — zeros are fine for an empty list, dashes (—) mean the fetch failed.
  • Log a test incident. Fill the form, submit. Confirm the toast appears, the row appears in the table, and the stat cards update. Then open the SharePoint list directly and confirm the item is there.
  • Open the detail modal. Click the test row. Confirm all fields display correctly including Description and Resolution Notes.
  • Test all filters. Apply severity, status, and category filters individually and together. Confirm they narrow the table correctly and that clearing them restores all rows.
  • Test CSV export. Click ↓ CSV. Confirm the file downloads with correct columns and the test row is present.
  • Test as a non-owner user. Have a technician without Site Owner permissions open the page and log an incident. If they get a 403 on the POST, check list permissions — the user needs at least Contribute. The list inherits from the site by default.
  • Delete the test incident. Open the SharePoint list directly and delete the test row. Refresh the console and confirm it is gone. The list is the source of truth.
TROUBLESHOOTING QUICK REFERENCE
SYMPTOMLIKELY CAUSEFIX
Badge still orange after uploaddemoMode still true, or browser cached old fileConfirm demoMode: false in script. Hard-refresh: Ctrl+Shift+R.
Stat cards show — on loadfetchIncidents() threw an errorCheck F12 Console for the error. Usually a 403 (permissions) or wrong siteUrl.
403 on GETUser not signed into SP, or list does not existConfirm user is signed in. Confirm list name matches SP_CONFIG.listName exactly including case and spaces.
403 on POST (log incident)Request digest failed, or list permissions deny writeConfirm POST block is uncommented. Check list permissions — user needs Contribute minimum.
Items appear in SP list but not consoleBrowser showing cached pageHard-refresh. The console fetches fresh data on every page load.
Metadata type error on POSTList name in __metadata.type does not match actual list nameFetch /_api/web/lists/getbytitle('AI Incident Log')?$select=ListItemEntityTypeFullName and update the type value to match.
File downloads instead of openingTenant blocks HTML rendering in document librariesEnable Custom Script in SharePoint Admin Center, or convert file to .aspx.
AFTER GO-LIVE CHECKLIST Add the console URL to nav.js under the Governance section — recommended label: AI Incident Log.
Update the breadcrumb link in this KB file's topbar to point to your governance index.
Add the SharePoint list URL to your internal tool register so admins can find it without opening the console.