diff --git a/enterprise-admin-alert-escalation-guard/README.md b/enterprise-admin-alert-escalation-guard/README.md
new file mode 100644
index 00000000..8e468008
--- /dev/null
+++ b/enterprise-admin-alert-escalation-guard/README.md
@@ -0,0 +1,48 @@
+# Enterprise Admin Alert Escalation Guard
+
+This module is a dependency-free, synthetic-data-only guard for SCIBASE
+Enterprise Tooling. It validates whether enterprise admin alerts can safely be
+muted, digested, throttled, or routed through webhooks without hiding
+compliance, security, export, or integration obligations.
+
+## What It Checks
+
+- Critical or high-severity alerts delayed by digest settings.
+- Urgent alerts muted by owner preferences.
+- Quiet-hours overrides for compliance and security alerts.
+- Alerts routed to inactive owners or admins on leave.
+- Required webhook routes with unhealthy failure rates.
+- Duplicate suppression near compliance or export deadlines.
+- Missing delivery channels for admin dashboard events.
+
+## Local Commands
+
+```bash
+npm run check
+npm test
+npm run demo
+```
+
+The demo writes reviewer artifacts under `reports/`:
+
+- `admin-alert-escalation-packet.json`
+- `admin-alert-escalation-report.md`
+- `summary.svg`
+- `demo.mp4`
+
+## Requirements Map
+
+| Issue #19 capability | Coverage in this slice |
+| --- | --- |
+| Admin dashboards | Emits dashboard badges for digest bypass, owner fallback, webhook fallback, and visible deadlines. |
+| Compliance tracking | Keeps compliance, security, IRB, and export obligations visible until acknowledged. |
+| API and webhooks | Emits webhook-ready event summaries without delivering live webhooks. |
+| Enterprise governance | Enforces owner fallback, quiet-hours override, and duplicate-suppression safety for institutional admins. |
+
+## Safety Boundaries
+
+- Uses only synthetic fixtures in `sample-data.js`.
+- Does not deliver live email, SMS, Slack, webhook, or external provider
+ notifications.
+- Does not include real institutional alerts, private users, credentials, or
+ project data.
diff --git a/enterprise-admin-alert-escalation-guard/demo.js b/enterprise-admin-alert-escalation-guard/demo.js
new file mode 100644
index 00000000..f24d083a
--- /dev/null
+++ b/enterprise-admin-alert-escalation-guard/demo.js
@@ -0,0 +1,136 @@
+'use strict';
+
+const fs = require('fs');
+const path = require('path');
+const { spawnSync } = require('child_process');
+const sampleAlerts = require('./sample-data');
+const { evaluateAlerts } = require('./index');
+
+const reportDir = path.join(__dirname, 'reports');
+const asOfDate = '2026-05-22';
+
+fs.mkdirSync(reportDir, { recursive: true });
+
+const portfolio = evaluateAlerts(sampleAlerts, { asOfDate });
+const jsonPath = path.join(reportDir, 'admin-alert-escalation-packet.json');
+const markdownPath = path.join(reportDir, 'admin-alert-escalation-report.md');
+const svgPath = path.join(reportDir, 'summary.svg');
+const mp4Path = path.join(reportDir, 'demo.mp4');
+
+fs.writeFileSync(jsonPath, `${JSON.stringify(portfolio, null, 2)}\n`);
+fs.writeFileSync(markdownPath, renderMarkdown(portfolio));
+fs.writeFileSync(svgPath, renderSvg(portfolio));
+renderVideo(portfolio, mp4Path);
+
+console.log(`Wrote ${path.relative(process.cwd(), jsonPath)}`);
+console.log(`Wrote ${path.relative(process.cwd(), markdownPath)}`);
+console.log(`Wrote ${path.relative(process.cwd(), svgPath)}`);
+console.log(`Wrote ${path.relative(process.cwd(), mp4Path)}`);
+
+function renderMarkdown(portfolio) {
+ return [
+ '# Enterprise Admin Alert Escalation Guard Report',
+ '',
+ `As of: ${portfolio.asOfDate}`,
+ `Alert digest: \`${portfolio.auditDigest}\``,
+ '',
+ '## Summary',
+ '',
+ `- Alerts reviewed: ${portfolio.alertCount}`,
+ `- Findings: ${portfolio.findingCount}`,
+ `- Escalated alerts: ${portfolio.escalatedAlerts.join(', ') || 'none'}`,
+ `- Actions: ${Object.entries(portfolio.byAction).map(([action, count]) => `${action}=${count}`).join(', ')}`,
+ '',
+ '## Alert Decisions',
+ '',
+ '| Alert | Category | Severity | Action | Findings | Dashboard badges |',
+ '| --- | --- | --- | --- | ---: | --- |',
+ ...portfolio.packets.map((packet) => `| ${packet.alertId} | ${packet.category} | ${packet.severity} | ${packet.action} | ${packet.findingCount} | ${packet.dashboardBadges.join(', ') || 'none'} |`),
+ '',
+ '## Guardrails',
+ '',
+ '- Uses synthetic enterprise alert, owner, routing, digest, and webhook metadata only.',
+ '- Does not deliver live email, SMS, Slack, webhook, or external provider notifications.',
+ '- Keeps critical compliance/security alerts visible even when muted, digested, quiet-hours, duplicated, or routed to unavailable owners.',
+ '- Emits deterministic dashboard badges, webhook-ready event summaries, and audit digests.',
+ ''
+ ].join('\n');
+}
+
+function renderSvg(portfolio) {
+ const actions = Object.entries(portfolio.byAction)
+ .map(([action, count]) => `${escapeXml(action)} (${count})`)
+ .join(' / ');
+
+ return `
+
+`;
+}
+
+function renderVideo(portfolio, outputPath) {
+ const font = '/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf';
+ const filters = [
+ drawText(font, 'SCIBASE #19 Enterprise Tooling', 64, 72, 40, 'white'),
+ drawText(font, 'Admin notification escalation guard', 64, 136, 36, 'white'),
+ drawText(font, `Reviewed ${portfolio.alertCount} synthetic admin alerts`, 84, 238, 33, '0xdbeafe'),
+ drawText(font, `${portfolio.escalatedAlerts.length} alerts escalated before mute or digest`, 84, 304, 32, '0xfecaca'),
+ drawText(font, `${portfolio.findingCount} findings with dashboard badges and webhook summaries`, 84, 370, 28, '0xdcfce7'),
+ drawText(font, 'Checks quiet hours owner fallback webhook health duplicates and digest delays', 84, 462, 25, '0xe0f2fe'),
+ drawText(font, 'No live notification delivery email SMS Slack webhooks or external providers', 84, 522, 25, '0xfef3c7'),
+ drawText(font, `Audit digest ${portfolio.auditDigest.slice(0, 24)}`, 84, 596, 24, '0xcbd5e1')
+ ].join(',');
+
+ const result = spawnSync('ffmpeg', [
+ '-y',
+ '-f', 'lavfi',
+ '-i', 'color=c=0x233142:s=1280x720:d=4:r=25',
+ '-vf', filters,
+ '-c:v', 'libx264',
+ '-pix_fmt', 'yuv420p',
+ outputPath
+ ], { encoding: 'utf8' });
+
+ if (result.status !== 0) {
+ const message = [result.stdout, result.stderr].filter(Boolean).join('\n');
+ throw new Error(`ffmpeg failed to render demo.mp4:\n${message}`);
+ }
+}
+
+function drawText(font, text, x, y, size, color) {
+ return `drawtext=fontfile='${font}':text='${escapeDrawText(text)}':x=${x}:y=${y}:fontsize=${size}:fontcolor=${color}`;
+}
+
+function escapeDrawText(value) {
+ return String(value)
+ .replace(/\\/g, '\\\\')
+ .replace(/:/g, '\\:')
+ .replace(/'/g, "\\'")
+ .replace(/,/g, '\\,')
+ .replace(/&/g, '\\&');
+}
+
+function escapeXml(value) {
+ return String(value)
+ .replace(/&/g, '&')
+ .replace(//g, '>')
+ .replace(/"/g, '"');
+}
diff --git a/enterprise-admin-alert-escalation-guard/index.js b/enterprise-admin-alert-escalation-guard/index.js
new file mode 100644
index 00000000..d4b2e9f1
--- /dev/null
+++ b/enterprise-admin-alert-escalation-guard/index.js
@@ -0,0 +1,242 @@
+'use strict';
+
+const crypto = require('crypto');
+
+const DEFAULT_POLICY = Object.freeze({
+ asOfDate: '2026-05-22',
+ criticalSeverities: ['critical', 'high'],
+ urgentCategories: ['compliance_deadline', 'security_integration', 'export_failure', 'irb_risk'],
+ maxDigestDelayHours: 4,
+ maxWebhookFailureRate: 0.15,
+ maxDuplicateWindowHours: 24,
+ quietHoursOverrideSeverities: ['critical', 'high']
+});
+
+function stableStringify(value) {
+ if (Array.isArray(value)) return `[${value.map(stableStringify).join(',')}]`;
+ if (value && typeof value === 'object') {
+ return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${stableStringify(value[key])}`).join(',')}}`;
+ }
+ return JSON.stringify(value);
+}
+
+function digest(value) {
+ return crypto.createHash('sha256').update(stableStringify(value)).digest('hex');
+}
+
+function normalizeToken(value) {
+ return String(value || '').trim().toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_+|_+$/g, '');
+}
+
+function addFinding(findings, code, severity, message, remediation) {
+ findings.push({ code, severity, message, remediation });
+}
+
+function hoursUntil(dueAt, asOfDate) {
+ if (!dueAt) return null;
+ const due = new Date(dueAt);
+ const asOf = new Date(`${asOfDate}T00:00:00Z`);
+ if (Number.isNaN(due.getTime())) throw new Error(`Invalid dueAt: ${dueAt}`);
+ return Math.round((due.getTime() - asOf.getTime()) / (60 * 60 * 1000));
+}
+
+function evaluateAlert(alert, options = {}) {
+ const policy = Object.assign({}, DEFAULT_POLICY, options.policy || {}, {
+ asOfDate: options.asOfDate || (options.policy && options.policy.asOfDate) || DEFAULT_POLICY.asOfDate
+ });
+ const severity = normalizeToken(alert.severity || 'low');
+ const category = normalizeToken(alert.category || 'general');
+ const routing = alert.routing || {};
+ const owner = alert.owner || {};
+ const webhook = alert.webhook || {};
+ const digestSettings = routing.digest || {};
+ const findings = [];
+ const urgent = policy.criticalSeverities.includes(severity) || policy.urgentCategories.includes(category);
+ const dueInHours = hoursUntil(alert.dueAt, policy.asOfDate);
+
+ if (urgent && digestSettings.enabled && Number(digestSettings.delayHours || 0) > policy.maxDigestDelayHours) {
+ addFinding(
+ findings,
+ 'urgent_alert_delayed_by_digest',
+ 'critical',
+ `${alert.id} is urgent but digest delay is ${digestSettings.delayHours} hours`,
+ 'bypass digest and deliver immediately to primary plus escalation owners'
+ );
+ }
+
+ if (urgent && routing.muted === true) {
+ addFinding(
+ findings,
+ 'urgent_alert_muted',
+ 'critical',
+ `${alert.id} is urgent but owner preferences mute the route`,
+ 'override mute for compliance-critical alert and log preference bypass'
+ );
+ }
+
+ if (routing.quietHours === true && policy.quietHoursOverrideSeverities.includes(severity)) {
+ addFinding(
+ findings,
+ 'quiet_hours_override_required',
+ severity === 'critical' ? 'critical' : 'high',
+ `${alert.id} falls in quiet hours but severity is ${severity}`,
+ 'use emergency channel and record quiet-hours override justification'
+ );
+ }
+
+ if (owner.active === false || owner.onLeave === true) {
+ addFinding(
+ findings,
+ 'inactive_owner_route',
+ 'high',
+ `${alert.id} is routed to inactive or unavailable owner ${owner.id || 'unknown'}`,
+ 'route to delegated owner group and update dashboard ownership metadata'
+ );
+ }
+
+ if (webhook.required && Number(webhook.failureRate || 0) > policy.maxWebhookFailureRate) {
+ addFinding(
+ findings,
+ 'webhook_health_fallback_required',
+ urgent ? 'high' : 'medium',
+ `${alert.id} webhook failure rate ${(Number(webhook.failureRate) * 100).toFixed(1)}% exceeds policy`,
+ 'fallback to admin inbox and include webhook repair action in the packet'
+ );
+ }
+
+ if (routing.duplicateSuppressed === true && dueInHours !== null && dueInHours <= policy.maxDuplicateWindowHours) {
+ addFinding(
+ findings,
+ 'duplicate_suppression_near_deadline',
+ 'high',
+ `${alert.id} is deduplicated with ${dueInHours} hours before deadline`,
+ 'show one canonical alert and keep deadline badge visible until acknowledged'
+ );
+ }
+
+ if (!routing.channels || routing.channels.length === 0) {
+ addFinding(
+ findings,
+ 'missing_delivery_channel',
+ urgent ? 'high' : 'medium',
+ `${alert.id} has no delivery channel`,
+ 'assign admin inbox channel and require owner acknowledgement'
+ );
+ }
+
+ const selected = selectAction(findings);
+ const packet = {
+ alertId: alert.id,
+ category,
+ severity,
+ dueInHours,
+ urgent,
+ action: selected.action,
+ decisionSeverity: selected.severity,
+ reason: selected.reason,
+ ownerId: owner.id || null,
+ routedChannels: routing.channels || [],
+ webhookRequired: Boolean(webhook.required),
+ findingCount: findings.length,
+ findings,
+ dashboardBadges: buildDashboardBadges(alert, findings),
+ webhookEvent: buildWebhookEvent(alert, selected, findings)
+ };
+
+ packet.auditDigest = digest(Object.assign({}, packet, { auditDigest: undefined }));
+ return packet;
+}
+
+function selectAction(findings) {
+ if (findings.some((finding) => finding.severity === 'critical')) {
+ return {
+ action: 'deliver_now_and_escalate',
+ severity: 'critical',
+ reason: 'urgent enterprise alert would otherwise be muted, delayed, or hidden'
+ };
+ }
+
+ if (findings.some((finding) => finding.severity === 'high')) {
+ return {
+ action: 'hold_digest_and_route_owner_fallback',
+ severity: 'high',
+ reason: 'alert requires owner fallback or visible escalation before digesting'
+ };
+ }
+
+ if (findings.some((finding) => finding.severity === 'medium')) {
+ return {
+ action: 'warn_and_repair_delivery_path',
+ severity: 'medium',
+ reason: 'delivery path should be repaired while alert remains visible'
+ };
+ }
+
+ return {
+ action: 'allow_digest_or_standard_delivery',
+ severity: 'low',
+ reason: 'alert routing satisfies admin notification policy'
+ };
+}
+
+function buildDashboardBadges(alert, findings) {
+ const badges = [];
+ if (findings.some((finding) => finding.code.includes('digest') || finding.code.includes('muted'))) badges.push('bypass-digest');
+ if (findings.some((finding) => finding.code.includes('owner'))) badges.push('owner-fallback');
+ if (findings.some((finding) => finding.code.includes('webhook'))) badges.push('webhook-fallback');
+ if (findings.some((finding) => finding.code.includes('deadline'))) badges.push('deadline-visible');
+ if (badges.length === 0 && normalizeToken(alert.severity) === 'low') badges.push('standard-delivery');
+ return badges;
+}
+
+function buildWebhookEvent(alert, selected, findings) {
+ return {
+ eventType: 'enterprise.alert.routing.reviewed',
+ alertId: alert.id,
+ action: selected.action,
+ findingCodes: findings.map((finding) => finding.code),
+ requiresAcknowledgement: selected.severity === 'critical' || selected.severity === 'high',
+ eventDigest: digest({
+ alertId: alert.id,
+ action: selected.action,
+ findingCodes: findings.map((finding) => finding.code)
+ })
+ };
+}
+
+function evaluateAlerts(alerts, options = {}) {
+ const packets = alerts.map((alert) => evaluateAlert(alert, options));
+ const summary = packets.reduce((acc, packet) => {
+ acc.byAction[packet.action] = (acc.byAction[packet.action] || 0) + 1;
+ acc.bySeverity[packet.decisionSeverity] = (acc.bySeverity[packet.decisionSeverity] || 0) + 1;
+ if (packet.decisionSeverity === 'critical' || packet.decisionSeverity === 'high') acc.escalatedAlerts.push(packet.alertId);
+ acc.findingCount += packet.findingCount;
+ return acc;
+ }, {
+ byAction: {},
+ bySeverity: {},
+ escalatedAlerts: [],
+ findingCount: 0
+ });
+
+ const portfolio = {
+ asOfDate: options.asOfDate || DEFAULT_POLICY.asOfDate,
+ alertCount: packets.length,
+ findingCount: summary.findingCount,
+ escalatedAlerts: summary.escalatedAlerts,
+ byAction: summary.byAction,
+ bySeverity: summary.bySeverity,
+ packets
+ };
+
+ portfolio.auditDigest = digest(portfolio);
+ return portfolio;
+}
+
+module.exports = {
+ DEFAULT_POLICY,
+ digest,
+ evaluateAlert,
+ evaluateAlerts,
+ hoursUntil
+};
diff --git a/enterprise-admin-alert-escalation-guard/package.json b/enterprise-admin-alert-escalation-guard/package.json
new file mode 100644
index 00000000..74abe3f3
--- /dev/null
+++ b/enterprise-admin-alert-escalation-guard/package.json
@@ -0,0 +1,13 @@
+{
+ "name": "enterprise-admin-alert-escalation-guard",
+ "version": "1.0.0",
+ "private": true,
+ "description": "Synthetic enterprise admin notification escalation guard for SCIBASE enterprise tooling.",
+ "main": "index.js",
+ "scripts": {
+ "check": "node --check index.js && node --check sample-data.js && node --check test.js && node --check demo.js",
+ "test": "node test.js",
+ "demo": "node demo.js"
+ },
+ "license": "MIT"
+}
diff --git a/enterprise-admin-alert-escalation-guard/reports/admin-alert-escalation-packet.json b/enterprise-admin-alert-escalation-guard/reports/admin-alert-escalation-packet.json
new file mode 100644
index 00000000..395ab803
--- /dev/null
+++ b/enterprise-admin-alert-escalation-guard/reports/admin-alert-escalation-packet.json
@@ -0,0 +1,202 @@
+{
+ "asOfDate": "2026-05-22",
+ "alertCount": 4,
+ "findingCount": 8,
+ "escalatedAlerts": [
+ "ALERT-COMPLIANCE-001",
+ "ALERT-WEBHOOK-022"
+ ],
+ "byAction": {
+ "deliver_now_and_escalate": 1,
+ "hold_digest_and_route_owner_fallback": 1,
+ "warn_and_repair_delivery_path": 1,
+ "allow_digest_or_standard_delivery": 1
+ },
+ "bySeverity": {
+ "critical": 1,
+ "high": 1,
+ "medium": 1,
+ "low": 1
+ },
+ "packets": [
+ {
+ "alertId": "ALERT-COMPLIANCE-001",
+ "category": "compliance_deadline",
+ "severity": "critical",
+ "dueInHours": 18,
+ "urgent": true,
+ "action": "deliver_now_and_escalate",
+ "decisionSeverity": "critical",
+ "reason": "urgent enterprise alert would otherwise be muted, delayed, or hidden",
+ "ownerId": "research-office-primary",
+ "routedChannels": [
+ "admin_digest"
+ ],
+ "webhookRequired": true,
+ "findingCount": 6,
+ "findings": [
+ {
+ "code": "urgent_alert_delayed_by_digest",
+ "severity": "critical",
+ "message": "ALERT-COMPLIANCE-001 is urgent but digest delay is 12 hours",
+ "remediation": "bypass digest and deliver immediately to primary plus escalation owners"
+ },
+ {
+ "code": "urgent_alert_muted",
+ "severity": "critical",
+ "message": "ALERT-COMPLIANCE-001 is urgent but owner preferences mute the route",
+ "remediation": "override mute for compliance-critical alert and log preference bypass"
+ },
+ {
+ "code": "quiet_hours_override_required",
+ "severity": "critical",
+ "message": "ALERT-COMPLIANCE-001 falls in quiet hours but severity is critical",
+ "remediation": "use emergency channel and record quiet-hours override justification"
+ },
+ {
+ "code": "inactive_owner_route",
+ "severity": "high",
+ "message": "ALERT-COMPLIANCE-001 is routed to inactive or unavailable owner research-office-primary",
+ "remediation": "route to delegated owner group and update dashboard ownership metadata"
+ },
+ {
+ "code": "webhook_health_fallback_required",
+ "severity": "high",
+ "message": "ALERT-COMPLIANCE-001 webhook failure rate 32.0% exceeds policy",
+ "remediation": "fallback to admin inbox and include webhook repair action in the packet"
+ },
+ {
+ "code": "duplicate_suppression_near_deadline",
+ "severity": "high",
+ "message": "ALERT-COMPLIANCE-001 is deduplicated with 18 hours before deadline",
+ "remediation": "show one canonical alert and keep deadline badge visible until acknowledged"
+ }
+ ],
+ "dashboardBadges": [
+ "bypass-digest",
+ "owner-fallback",
+ "webhook-fallback",
+ "deadline-visible"
+ ],
+ "webhookEvent": {
+ "eventType": "enterprise.alert.routing.reviewed",
+ "alertId": "ALERT-COMPLIANCE-001",
+ "action": "deliver_now_and_escalate",
+ "findingCodes": [
+ "urgent_alert_delayed_by_digest",
+ "urgent_alert_muted",
+ "quiet_hours_override_required",
+ "inactive_owner_route",
+ "webhook_health_fallback_required",
+ "duplicate_suppression_near_deadline"
+ ],
+ "requiresAcknowledgement": true,
+ "eventDigest": "699c9912707d495d6a9b34fd099859ed00df5a8ced1cbd78fa74d1b738caa1f5"
+ },
+ "auditDigest": "0e910b57e1e875b89e998e647ee6871aa620caabc4422ee34f80d1b170e48f4d"
+ },
+ {
+ "alertId": "ALERT-WEBHOOK-022",
+ "category": "security_integration",
+ "severity": "high",
+ "dueInHours": 57,
+ "urgent": true,
+ "action": "hold_digest_and_route_owner_fallback",
+ "decisionSeverity": "high",
+ "reason": "alert requires owner fallback or visible escalation before digesting",
+ "ownerId": "integration-admin",
+ "routedChannels": [
+ "slack",
+ "admin_inbox"
+ ],
+ "webhookRequired": true,
+ "findingCount": 1,
+ "findings": [
+ {
+ "code": "webhook_health_fallback_required",
+ "severity": "high",
+ "message": "ALERT-WEBHOOK-022 webhook failure rate 24.0% exceeds policy",
+ "remediation": "fallback to admin inbox and include webhook repair action in the packet"
+ }
+ ],
+ "dashboardBadges": [
+ "webhook-fallback"
+ ],
+ "webhookEvent": {
+ "eventType": "enterprise.alert.routing.reviewed",
+ "alertId": "ALERT-WEBHOOK-022",
+ "action": "hold_digest_and_route_owner_fallback",
+ "findingCodes": [
+ "webhook_health_fallback_required"
+ ],
+ "requiresAcknowledgement": true,
+ "eventDigest": "851c86c5b4962302b9f916a8dcbf79812b6bd3a7b0e102f3d0830635e11f0940"
+ },
+ "auditDigest": "3b59e442a407076677b3e19f2b7a9332da97a5f637707eeaf4e22b461ac7fe7a"
+ },
+ {
+ "alertId": "ALERT-DASHBOARD-077",
+ "category": "usage_anomaly",
+ "severity": "medium",
+ "dueInHours": 180,
+ "urgent": false,
+ "action": "warn_and_repair_delivery_path",
+ "decisionSeverity": "medium",
+ "reason": "delivery path should be repaired while alert remains visible",
+ "ownerId": "department-chair",
+ "routedChannels": [],
+ "webhookRequired": false,
+ "findingCount": 1,
+ "findings": [
+ {
+ "code": "missing_delivery_channel",
+ "severity": "medium",
+ "message": "ALERT-DASHBOARD-077 has no delivery channel",
+ "remediation": "assign admin inbox channel and require owner acknowledgement"
+ }
+ ],
+ "dashboardBadges": [],
+ "webhookEvent": {
+ "eventType": "enterprise.alert.routing.reviewed",
+ "alertId": "ALERT-DASHBOARD-077",
+ "action": "warn_and_repair_delivery_path",
+ "findingCodes": [
+ "missing_delivery_channel"
+ ],
+ "requiresAcknowledgement": false,
+ "eventDigest": "6d6746d55dc430be4bc450358fc95d10cab304a7959aa2160d26c5151fdf7da2"
+ },
+ "auditDigest": "61e2358f2125cb99be6c435441e7613b1b264faff6bad4b94f899e46e26b798f"
+ },
+ {
+ "alertId": "ALERT-INFO-100",
+ "category": "weekly_summary",
+ "severity": "low",
+ "dueInHours": 348,
+ "urgent": false,
+ "action": "allow_digest_or_standard_delivery",
+ "decisionSeverity": "low",
+ "reason": "alert routing satisfies admin notification policy",
+ "ownerId": "research-ops",
+ "routedChannels": [
+ "admin_digest"
+ ],
+ "webhookRequired": false,
+ "findingCount": 0,
+ "findings": [],
+ "dashboardBadges": [
+ "standard-delivery"
+ ],
+ "webhookEvent": {
+ "eventType": "enterprise.alert.routing.reviewed",
+ "alertId": "ALERT-INFO-100",
+ "action": "allow_digest_or_standard_delivery",
+ "findingCodes": [],
+ "requiresAcknowledgement": false,
+ "eventDigest": "04a40a820e3ad0ed259e8c05153cdb1c53b3e4aec11230d167095bf898da5f02"
+ },
+ "auditDigest": "d50f57932c5a1a13a3ce187053be1b8a88b57cf8546250db2ed605a27ab009c7"
+ }
+ ],
+ "auditDigest": "828b10bdaf88976168cd68d7b4b5506a0565b681bfd2d5d0f25395bfcb4254bc"
+}
diff --git a/enterprise-admin-alert-escalation-guard/reports/admin-alert-escalation-report.md b/enterprise-admin-alert-escalation-guard/reports/admin-alert-escalation-report.md
new file mode 100644
index 00000000..bc2340ab
--- /dev/null
+++ b/enterprise-admin-alert-escalation-guard/reports/admin-alert-escalation-report.md
@@ -0,0 +1,27 @@
+# Enterprise Admin Alert Escalation Guard Report
+
+As of: 2026-05-22
+Alert digest: `828b10bdaf88976168cd68d7b4b5506a0565b681bfd2d5d0f25395bfcb4254bc`
+
+## Summary
+
+- Alerts reviewed: 4
+- Findings: 8
+- Escalated alerts: ALERT-COMPLIANCE-001, ALERT-WEBHOOK-022
+- Actions: deliver_now_and_escalate=1, hold_digest_and_route_owner_fallback=1, warn_and_repair_delivery_path=1, allow_digest_or_standard_delivery=1
+
+## Alert Decisions
+
+| Alert | Category | Severity | Action | Findings | Dashboard badges |
+| --- | --- | --- | --- | ---: | --- |
+| ALERT-COMPLIANCE-001 | compliance_deadline | critical | deliver_now_and_escalate | 6 | bypass-digest, owner-fallback, webhook-fallback, deadline-visible |
+| ALERT-WEBHOOK-022 | security_integration | high | hold_digest_and_route_owner_fallback | 1 | webhook-fallback |
+| ALERT-DASHBOARD-077 | usage_anomaly | medium | warn_and_repair_delivery_path | 1 | none |
+| ALERT-INFO-100 | weekly_summary | low | allow_digest_or_standard_delivery | 0 | standard-delivery |
+
+## Guardrails
+
+- Uses synthetic enterprise alert, owner, routing, digest, and webhook metadata only.
+- Does not deliver live email, SMS, Slack, webhook, or external provider notifications.
+- Keeps critical compliance/security alerts visible even when muted, digested, quiet-hours, duplicated, or routed to unavailable owners.
+- Emits deterministic dashboard badges, webhook-ready event summaries, and audit digests.
diff --git a/enterprise-admin-alert-escalation-guard/reports/demo.mp4 b/enterprise-admin-alert-escalation-guard/reports/demo.mp4
new file mode 100644
index 00000000..f765f58e
Binary files /dev/null and b/enterprise-admin-alert-escalation-guard/reports/demo.mp4 differ
diff --git a/enterprise-admin-alert-escalation-guard/reports/summary.svg b/enterprise-admin-alert-escalation-guard/reports/summary.svg
new file mode 100644
index 00000000..ea1fa50b
--- /dev/null
+++ b/enterprise-admin-alert-escalation-guard/reports/summary.svg
@@ -0,0 +1,20 @@
+
+
diff --git a/enterprise-admin-alert-escalation-guard/sample-data.js b/enterprise-admin-alert-escalation-guard/sample-data.js
new file mode 100644
index 00000000..d26ac24e
--- /dev/null
+++ b/enterprise-admin-alert-escalation-guard/sample-data.js
@@ -0,0 +1,64 @@
+'use strict';
+
+module.exports = [
+ {
+ id: 'ALERT-COMPLIANCE-001',
+ category: 'compliance_deadline',
+ severity: 'critical',
+ dueAt: '2026-05-22T18:00:00Z',
+ owner: { id: 'research-office-primary', active: false, onLeave: true },
+ routing: {
+ channels: ['admin_digest'],
+ muted: true,
+ quietHours: true,
+ duplicateSuppressed: true,
+ digest: { enabled: true, delayHours: 12 }
+ },
+ webhook: { required: true, failureRate: 0.32 }
+ },
+ {
+ id: 'ALERT-WEBHOOK-022',
+ category: 'security_integration',
+ severity: 'high',
+ dueAt: '2026-05-24T09:00:00Z',
+ owner: { id: 'integration-admin', active: true, onLeave: false },
+ routing: {
+ channels: ['slack', 'admin_inbox'],
+ muted: false,
+ quietHours: false,
+ duplicateSuppressed: false,
+ digest: { enabled: false, delayHours: 0 }
+ },
+ webhook: { required: true, failureRate: 0.24 }
+ },
+ {
+ id: 'ALERT-DASHBOARD-077',
+ category: 'usage_anomaly',
+ severity: 'medium',
+ dueAt: '2026-05-29T12:00:00Z',
+ owner: { id: 'department-chair', active: true, onLeave: false },
+ routing: {
+ channels: [],
+ muted: false,
+ quietHours: false,
+ duplicateSuppressed: false,
+ digest: { enabled: true, delayHours: 2 }
+ },
+ webhook: { required: false, failureRate: 0 }
+ },
+ {
+ id: 'ALERT-INFO-100',
+ category: 'weekly_summary',
+ severity: 'low',
+ dueAt: '2026-06-05T12:00:00Z',
+ owner: { id: 'research-ops', active: true, onLeave: false },
+ routing: {
+ channels: ['admin_digest'],
+ muted: false,
+ quietHours: false,
+ duplicateSuppressed: false,
+ digest: { enabled: true, delayHours: 2 }
+ },
+ webhook: { required: false, failureRate: 0 }
+ }
+];
diff --git a/enterprise-admin-alert-escalation-guard/test.js b/enterprise-admin-alert-escalation-guard/test.js
new file mode 100644
index 00000000..b9883f9a
--- /dev/null
+++ b/enterprise-admin-alert-escalation-guard/test.js
@@ -0,0 +1,98 @@
+'use strict';
+
+const assert = require('assert');
+const sampleAlerts = require('./sample-data');
+const { evaluateAlert, evaluateAlerts, hoursUntil } = require('./index');
+
+const asOfDate = '2026-05-22';
+
+function testHoursUntil() {
+ assert.equal(hoursUntil('2026-05-22T18:00:00Z', asOfDate), 18);
+}
+
+function testCriticalAlertBypassesMuteDigestAndQuietHours() {
+ const packet = evaluateAlert(sampleAlerts[0], { asOfDate });
+
+ assert.equal(packet.action, 'deliver_now_and_escalate');
+ assert.equal(packet.decisionSeverity, 'critical');
+ assert.ok(packet.findings.some((finding) => finding.code === 'urgent_alert_muted'));
+ assert.ok(packet.findings.some((finding) => finding.code === 'urgent_alert_delayed_by_digest'));
+ assert.ok(packet.findings.some((finding) => finding.code === 'quiet_hours_override_required'));
+ assert.ok(packet.dashboardBadges.includes('bypass-digest'));
+ assert.equal(packet.webhookEvent.requiresAcknowledgement, true);
+}
+
+function testWebhookFailureFallbackForHighSeverity() {
+ const packet = evaluateAlert(sampleAlerts[1], { asOfDate });
+
+ assert.equal(packet.action, 'hold_digest_and_route_owner_fallback');
+ assert.equal(packet.decisionSeverity, 'high');
+ assert.ok(packet.findings.some((finding) => finding.code === 'webhook_health_fallback_required'));
+ assert.ok(packet.dashboardBadges.includes('webhook-fallback'));
+}
+
+function testMissingChannelWarnsMediumAlert() {
+ const packet = evaluateAlert(sampleAlerts[2], { asOfDate });
+
+ assert.equal(packet.action, 'warn_and_repair_delivery_path');
+ assert.equal(packet.decisionSeverity, 'medium');
+ assert.ok(packet.findings.some((finding) => finding.code === 'missing_delivery_channel'));
+}
+
+function testStandardDigestAllowed() {
+ const packet = evaluateAlert(sampleAlerts[3], { asOfDate });
+
+ assert.equal(packet.action, 'allow_digest_or_standard_delivery');
+ assert.equal(packet.findingCount, 0);
+ assert.ok(packet.dashboardBadges.includes('standard-delivery'));
+}
+
+function testDuplicateSuppressionNearDeadline() {
+ const packet = evaluateAlert({
+ id: 'ALERT-DEDUPE',
+ category: 'export_failure',
+ severity: 'high',
+ dueAt: '2026-05-22T20:00:00Z',
+ owner: { id: 'export-admin', active: true, onLeave: false },
+ routing: {
+ channels: ['admin_inbox'],
+ muted: false,
+ quietHours: false,
+ duplicateSuppressed: true,
+ digest: { enabled: false, delayHours: 0 }
+ },
+ webhook: { required: false, failureRate: 0 }
+ }, { asOfDate });
+
+ assert.equal(packet.action, 'hold_digest_and_route_owner_fallback');
+ assert.ok(packet.findings.some((finding) => finding.code === 'duplicate_suppression_near_deadline'));
+ assert.ok(packet.dashboardBadges.includes('deadline-visible'));
+}
+
+function testPortfolioSummary() {
+ const portfolio = evaluateAlerts(sampleAlerts, { asOfDate });
+
+ assert.equal(portfolio.alertCount, 4);
+ assert.equal(portfolio.byAction.deliver_now_and_escalate, 1);
+ assert.equal(portfolio.byAction.hold_digest_and_route_owner_fallback, 1);
+ assert.equal(portfolio.byAction.warn_and_repair_delivery_path, 1);
+ assert.equal(portfolio.byAction.allow_digest_or_standard_delivery, 1);
+ assert.ok(portfolio.escalatedAlerts.includes('ALERT-COMPLIANCE-001'));
+ assert.equal(portfolio.auditDigest.length, 64);
+}
+
+const tests = [
+ testHoursUntil,
+ testCriticalAlertBypassesMuteDigestAndQuietHours,
+ testWebhookFailureFallbackForHighSeverity,
+ testMissingChannelWarnsMediumAlert,
+ testStandardDigestAllowed,
+ testDuplicateSuppressionNearDeadline,
+ testPortfolioSummary
+];
+
+for (const test of tests) {
+ test();
+}
+
+console.log(`${tests.length} enterprise admin alert escalation guard tests passed`);