stabilize tests

This commit is contained in:
master
2026-02-01 21:37:40 +02:00
parent 55744f6a39
commit 5d5e80b2e4
6435 changed files with 33984 additions and 13802 deletions

View File

@@ -1,6 +1,7 @@
using StellaOps.Notify.Models;
using System.Collections.Immutable;
using System.Text.Json.Serialization;
using StellaOps.Notify.Models;
namespace StellaOps.Notifier.WebService.Contracts;

View File

@@ -1,5 +1,6 @@
using System.Text.Json.Nodes;
using StellaOps.Notify.Models;
using System.Text.Json.Nodes;
namespace StellaOps.Notifier.WebService.Contracts;

View File

@@ -1,6 +1,7 @@
using Microsoft.AspNetCore.Mvc;
using StellaOps.Notifier.Worker.Escalation;
using StellaOps.Notifier.WebService.Extensions;
using StellaOps.Notifier.Worker.Escalation;
namespace StellaOps.Notifier.WebService.Endpoints;

View File

@@ -1,9 +1,10 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using StellaOps.Notifier.WebService.Extensions;
using StellaOps.Notify.Models;
using StellaOps.Notifier.Worker.Fallback;
using StellaOps.Notify.Models;
namespace StellaOps.Notifier.WebService.Endpoints;

View File

@@ -1,10 +1,11 @@
using System.Text.Json;
using System.Text.Json.Nodes;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using StellaOps.Notify.Models;
using StellaOps.Notifier.Worker.Storage;
using StellaOps.Notify.Models;
using System.Text.Json;
using System.Text.Json.Nodes;
namespace StellaOps.Notifier.WebService.Endpoints;

View File

@@ -1,11 +1,12 @@
using System.Collections.Concurrent;
using System.Net.WebSockets;
using System.Text;
using System.Text.Json;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using StellaOps.Notify.Models;
using System.Collections.Concurrent;
using System.Net.WebSockets;
using System.Text;
using System.Text.Json;
namespace StellaOps.Notifier.WebService.Endpoints;

View File

@@ -1,8 +1,9 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using StellaOps.Notifier.Worker.Localization;
using StellaOps.Notifier.WebService.Extensions;
using StellaOps.Notifier.Worker.Localization;
namespace StellaOps.Notifier.WebService.Endpoints;

View File

@@ -1,15 +1,16 @@
using System.Collections.Immutable;
using System.Text.Json;
using System.Text.Json.Nodes;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using StellaOps.Notifier.WebService.Contracts;
using StellaOps.Notifier.WebService.Extensions;
using StellaOps.Notifier.Worker.Dispatch;
using StellaOps.Notifier.Worker.Storage;
using StellaOps.Notifier.Worker.Templates;
using StellaOps.Notify.Models;
using StellaOps.Notifier.Worker.Storage;
using StellaOps.Notifier.WebService.Extensions;
using System.Collections.Immutable;
using System.Text.Json;
using System.Text.Json.Nodes;
namespace StellaOps.Notifier.WebService.Endpoints;

View File

@@ -1,10 +1,11 @@
using System.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using StellaOps.Notifier.Worker.Observability;
using StellaOps.Notifier.Worker.Retention;
using System.Linq;
namespace StellaOps.Notifier.WebService.Endpoints;

View File

@@ -1,6 +1,7 @@
using Microsoft.AspNetCore.Mvc;
using StellaOps.Notifier.Worker.Correlation;
using StellaOps.Notifier.WebService.Extensions;
using StellaOps.Notifier.Worker.Correlation;
namespace StellaOps.Notifier.WebService.Endpoints;

View File

@@ -1,6 +1,7 @@
using Microsoft.AspNetCore.Mvc;
using StellaOps.Notifier.Worker.Correlation;
using StellaOps.Notifier.WebService.Extensions;
using StellaOps.Notifier.Worker.Correlation;
namespace StellaOps.Notifier.WebService.Endpoints;

View File

@@ -1,12 +1,13 @@
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using StellaOps.Notify.Models;
using StellaOps.Notifier.Worker.Storage;
using StellaOps.Notifier.WebService.Contracts;
using StellaOps.Notifier.Worker.Storage;
using StellaOps.Notify.Models;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Nodes;
namespace StellaOps.Notifier.WebService.Endpoints;

View File

@@ -1,10 +1,11 @@
using Microsoft.AspNetCore.Mvc;
using StellaOps.Notifier.WebService.Extensions;
using StellaOps.Notifier.Worker.Simulation;
using StellaOps.Notify.Models;
using System.Collections.Immutable;
using System.Text.Json;
using System.Text.Json.Nodes;
using Microsoft.AspNetCore.Mvc;
using StellaOps.Notify.Models;
using StellaOps.Notifier.Worker.Simulation;
using StellaOps.Notifier.WebService.Extensions;
namespace StellaOps.Notifier.WebService.Endpoints;

View File

@@ -1,8 +1,9 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using StellaOps.Notifier.Worker.StormBreaker;
using StellaOps.Notifier.WebService.Extensions;
using StellaOps.Notifier.Worker.StormBreaker;
namespace StellaOps.Notifier.WebService.Endpoints;

View File

@@ -1,13 +1,14 @@
using System.Text.Json;
using System.Text.Json.Nodes;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using StellaOps.Notify.Models;
using StellaOps.Notifier.Worker.Storage;
using StellaOps.Notifier.WebService.Contracts;
using StellaOps.Notifier.Worker.Dispatch;
using StellaOps.Notifier.Worker.Storage;
using StellaOps.Notifier.Worker.Templates;
using StellaOps.Notify.Models;
using System.Text.Json;
using System.Text.Json.Nodes;
namespace StellaOps.Notifier.WebService.Endpoints;

View File

@@ -1,6 +1,7 @@
using Microsoft.AspNetCore.Mvc;
using StellaOps.Notifier.Worker.Correlation;
using StellaOps.Notifier.WebService.Extensions;
using StellaOps.Notifier.Worker.Correlation;
namespace StellaOps.Notifier.WebService.Endpoints;

View File

@@ -123,10 +123,6 @@ app.UseWebSockets(new WebSocketOptions
app.MapHealthChecks("/healthz");
// Tenant context middleware (extracts and validates tenant from headers/query)
app.UseTenantContext();
app.TryUseStellaRouter(routerOptions);
// Deprecation headers for retiring v1 APIs (RFC 8594 / IETF Sunset)
app.Use(async (context, next) =>
{
@@ -141,6 +137,10 @@ app.Use(async (context, next) =>
await next().ConfigureAwait(false);
});
// Tenant context middleware (extracts and validates tenant from headers/query)
app.UseTenantContext();
app.TryUseStellaRouter(routerOptions);
app.MapPost("/api/v1/notify/pack-approvals", async (
HttpContext context,
PackApprovalRequest request,

View File

@@ -1,10 +1,11 @@
using Microsoft.Extensions.Logging;
using StellaOps.Notify.Models;
using System.Text;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.RegularExpressions;
using System.Web;
using Microsoft.Extensions.Logging;
using StellaOps.Notify.Models;
namespace StellaOps.Notifier.WebService.Services;

View File

@@ -1,6 +1,7 @@
using Microsoft.Extensions.Logging;
using StellaOps.Notify.Models;
using StellaOps.Notifier.Worker.Storage;
using StellaOps.Notify.Models;
namespace StellaOps.Notifier.WebService.Services;

View File

@@ -1,5 +1,6 @@
using System.Text.Json.Nodes;
using StellaOps.Notify.Models;
using System.Text.Json.Nodes;
namespace StellaOps.Notifier.WebService.Services;

View File

@@ -1,5 +1,6 @@
using System.Text.Json.Nodes;
using StellaOps.Notify.Models;
using System.Text.Json.Nodes;
namespace StellaOps.Notifier.WebService.Services;

View File

@@ -1,7 +1,8 @@
using System.Text.Json.Nodes;
using Microsoft.Extensions.Logging;
using StellaOps.Notify.Models;
using StellaOps.Notifier.Worker.Storage;
using StellaOps.Notify.Models;
using System.Text.Json.Nodes;
namespace StellaOps.Notifier.WebService.Services;

View File

@@ -1,12 +1,13 @@
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using StellaOps.Notifier.Worker.Storage;
using StellaOps.Notify.Models;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Nodes;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using StellaOps.Notify.Models;
using StellaOps.Notifier.Worker.Storage;
namespace StellaOps.Notifier.WebService.Setup;

View File

@@ -1,7 +1,8 @@
using StellaOps.Notify.Queue;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using StellaOps.Notify.Queue;
namespace StellaOps.Notifier.WebService.Setup;

View File

@@ -1,3 +1,4 @@
using System.Text;
namespace StellaOps.Notifier.WebService.Setup;

View File

@@ -1,12 +1,13 @@
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Text.Json;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using StellaOps.Notify.Models;
using StellaOps.Notifier.Worker.Storage;
using StellaOps.Notify.Models;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
namespace StellaOps.Notifier.WebService.Setup;
@@ -172,7 +173,10 @@ public sealed class PackApprovalTemplateSeeder : IHostedService
var candidates = new[]
{
Path.Combine(contentRootPath, "StellaOps.Notifier.docs", "pack-approval-templates.json"),
Path.Combine(contentRootPath, "..", "StellaOps.Notifier.docs", "pack-approval-templates.json")
Path.Combine(contentRootPath, "..", "StellaOps.Notifier.docs", "pack-approval-templates.json"),
Path.Combine(contentRootPath, "StellaOps.Notifier", "StellaOps.Notifier.docs", "pack-approval-templates.json"),
Path.Combine(contentRootPath, "Notifier", "StellaOps.Notifier", "StellaOps.Notifier.docs", "pack-approval-templates.json"),
Path.Combine(contentRootPath, "src", "Notifier", "StellaOps.Notifier", "StellaOps.Notifier.docs", "pack-approval-templates.json")
};
foreach (var candidate in candidates)

View File

@@ -1,12 +1,13 @@
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using StellaOps.Notifier.Worker.Storage;
using StellaOps.Notify.Models;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Xml;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using StellaOps.Notify.Models;
using StellaOps.Notifier.Worker.Storage;
namespace StellaOps.Notifier.WebService.Setup;

View File

@@ -1,6 +1,7 @@
using StellaOps.Notify.Models;
using System.Collections.Concurrent;
using System.Linq;
using StellaOps.Notify.Models;
namespace StellaOps.Notifier.WebService.Storage.Compat;

View File

@@ -1,6 +1,7 @@
using StellaOps.Notify.Models;
using System.Collections.Concurrent;
using System.Linq;
using StellaOps.Notify.Models;
namespace StellaOps.Notifier.WebService.Storage.Compat;

View File

@@ -1,7 +1,8 @@
using StellaOps.Notify.Models;
using System.Collections.Concurrent;
using System.Collections.Immutable;
using System.Linq;
using StellaOps.Notify.Models;
namespace StellaOps.Notifier.WebService.Storage.Compat;

View File

@@ -1,5 +1,6 @@
using System.Collections.Concurrent;
using StellaOps.Notify.Models;
using System.Collections.Concurrent;
namespace StellaOps.Notifier.WebService.Storage.Compat;

View File

@@ -1,5 +1,6 @@
using System.Collections.Concurrent;
using StellaOps.Notify.Models;
using System.Collections.Concurrent;
namespace StellaOps.Notifier.WebService.Storage.Compat;

View File

@@ -1,6 +1,7 @@
using StellaOps.Notify.Models;
using System.Collections.Concurrent;
using System.Linq;
using StellaOps.Notify.Models;
namespace StellaOps.Notifier.WebService.Storage.Compat;

View File

@@ -1,5 +1,6 @@
using System.Collections.Concurrent;
using StellaOps.Notify.Models;
using System.Collections.Concurrent;
namespace StellaOps.Notifier.WebService.Storage.Compat;

View File

@@ -8,3 +8,4 @@ Source of truth: `docs-archived/implplan/2025-12-29-csproj-audit/SPRINT_20251229
| AUDIT-0395-M | DONE | Revalidated 2026-01-07; maintainability audit for StellaOps.Notifier.WebService. |
| AUDIT-0395-T | DONE | Revalidated 2026-01-07; test coverage audit for StellaOps.Notifier.WebService. |
| AUDIT-0395-A | TODO | Revalidated 2026-01-07 (open findings). |
| REMED-06 | DONE | SOLID review notes captured for SPRINT_20260130_002. |

View File

@@ -1,17 +1,17 @@
{
"templateId": "identity-matched-email",
"tenantId": "bootstrap",
"channelType": "email",
"channelType": "Email",
"key": "identity-matched",
"locale": "en-US",
"schemaVersion": "1.0.0",
"renderMode": "Markdown",
"renderMode": "Html",
"format": "Html",
"description": "Identity watchlist match alert for Email",
"description": "Email notification for identity watchlist matches",
"metadata": {
"category": "attestation",
"eventKind": "attestor.identity.matched",
"subject": "[{{ event.severity }}] Identity Watchlist Alert: {{ event.watchlistEntryName }}"
"category": "attestation",
"subject": "[{{ event.severity | upper }}] Identity Watchlist Alert: {{ event.watchlistEntryName }}"
},
"body": "# Identity Watchlist Alert\n\n**Watchlist Entry:** {{ event.watchlistEntryName }}\n\n**Severity:** {{ event.severity }}\n\n**Occurred:** {{ event.occurredAtUtc }}\n\n---\n\n## Matched Identity\n\n| Field | Value |\n|-------|-------|\n{% if event.matchedIdentity.issuer %}| Issuer | {{ event.matchedIdentity.issuer }} |{% endif %}\n{% if event.matchedIdentity.subjectAlternativeName %}| Subject Alternative Name | {{ event.matchedIdentity.subjectAlternativeName }} |{% endif %}\n{% if event.matchedIdentity.keyId %}| Key ID | {{ event.matchedIdentity.keyId }} |{% endif %}\n\n## Rekor Entry Details\n\n| Field | Value |\n|-------|-------|\n| UUID | {{ event.rekorEntry.uuid }} |\n| Log Index | {{ event.rekorEntry.logIndex }} |\n| Artifact SHA256 | {{ event.rekorEntry.artifactSha256 }} |\n| Integrated Time (UTC) | {{ event.rekorEntry.integratedTimeUtc }} |\n\n{% if event.suppressedCount > 0 %}\n---\n\n*Note: {{ event.suppressedCount }} similar alerts were suppressed within the deduplication window.*\n{% endif %}\n\n---\n\n*This alert was generated by Stella Ops identity watchlist monitoring.*"
"body": "<!DOCTYPE html>\n<html>\n<head><style>body{font-family:sans-serif;line-height:1.5;}.severity-critical{color:#dc3545;}.severity-warning{color:#ffc107;}.severity-info{color:#0dcaf0;}.section{margin:1em 0;padding:1em;background:#f8f9fa;border-radius:4px;}.label{font-weight:bold;color:#666;}.mono{font-family:monospace;background:#e9ecef;padding:2px 6px;border-radius:3px;}</style></head>\n<body>\n<h2 class=\"severity-{{ event.severity }}\">Identity Watchlist Alert</h2>\n<div class=\"section\">\n<p><span class=\"label\">Severity:</span> <strong>{{ event.severity }}</strong></p>\n<p><span class=\"label\">Watchlist Entry:</span> {{ event.watchlistEntryName }}</p>\n</div>\n<div class=\"section\">\n<h3>Matched Identity</h3>\n{{ #if event.matchedIdentity.issuer }}<p><span class=\"label\">Issuer:</span> <span class=\"mono\">{{ event.matchedIdentity.issuer }}</span></p>{{ /if }}\n{{ #if event.matchedIdentity.subjectAlternativeName }}<p><span class=\"label\">Subject Alternative Name:</span> <span class=\"mono\">{{ event.matchedIdentity.subjectAlternativeName }}</span></p>{{ /if }}\n{{ #if event.matchedIdentity.keyId }}<p><span class=\"label\">Key ID:</span> <span class=\"mono\">{{ event.matchedIdentity.keyId }}</span></p>{{ /if }}\n</div>\n<div class=\"section\">\n<h3>Rekor Entry</h3>\n<p><span class=\"label\">UUID:</span> <span class=\"mono\">{{ event.rekorEntry.uuid }}</span></p>\n<p><span class=\"label\">Log Index:</span> {{ event.rekorEntry.logIndex }}</p>\n<p><span class=\"label\">Artifact SHA-256:</span> <span class=\"mono\">{{ event.rekorEntry.artifactSha256 }}</span></p>\n<p><span class=\"label\">Integrated Time (UTC):</span> {{ event.rekorEntry.integratedTimeUtc }}</p>\n</div>\n{{ #if (gt event.suppressedCount 0) }}<p><em>{{ event.suppressedCount }} duplicate alerts suppressed</em></p>{{ /if }}\n<hr>\n<p style=\"font-size:0.85em;color:#666;\">Event ID: {{ event.eventId }} | Occurred: {{ event.occurredAtUtc }}</p>\n</body>\n</html>"
}

View File

@@ -1,16 +1,16 @@
{
"templateId": "identity-matched-slack",
"tenantId": "bootstrap",
"channelType": "slack",
"channelType": "Slack",
"key": "identity-matched",
"locale": "en-US",
"schemaVersion": "1.0.0",
"renderMode": "Markdown",
"format": "Json",
"description": "Identity watchlist match alert for Slack",
"description": "Slack notification for identity watchlist matches",
"metadata": {
"category": "attestation",
"eventKind": "attestor.identity.matched"
"eventKind": "attestor.identity.matched",
"category": "attestation"
},
"body": ":warning: *Identity Watchlist Alert*\n\n*Entry:* {{ event.watchlistEntryName }}\n*Severity:* {{ event.severity }}\n\n*Matched Identity:*\n{% if event.matchedIdentity.issuer %}• Issuer: `{{ event.matchedIdentity.issuer }}`{% endif %}\n{% if event.matchedIdentity.subjectAlternativeName %}• SAN: `{{ event.matchedIdentity.subjectAlternativeName }}`{% endif %}\n{% if event.matchedIdentity.keyId %}• Key ID: `{{ event.matchedIdentity.keyId }}`{% endif %}\n\n*Rekor Entry:*\n UUID: `{{ event.rekorEntry.uuid }}`\n Log Index: `{{ event.rekorEntry.logIndex }}`\n Artifact: `{{ event.rekorEntry.artifactSha256 }}`\n• Time: {{ event.rekorEntry.integratedTimeUtc }}\n\n{% if event.suppressedCount > 0 %}_({{ event.suppressedCount }} similar alerts suppressed)_{% endif %}"
"body": "{{ #if (eq event.severity \"critical\") }}:rotating_light:{{ else if (eq event.severity \"warning\") }}:warning:{{ else }}:information_source:{{ /if }} *Identity Watchlist Alert*\n\n*Severity:* `{{ event.severity }}`\n*Watchlist Entry:* {{ event.watchlistEntryName }}\n\n*Matched Identity:*\n{{ #if event.matchedIdentity.issuer }}> Issuer: `{{ event.matchedIdentity.issuer }}`\n{{ /if }}{{ #if event.matchedIdentity.subjectAlternativeName }}> SAN: `{{ event.matchedIdentity.subjectAlternativeName }}`\n{{ /if }}{{ #if event.matchedIdentity.keyId }}> Key ID: `{{ event.matchedIdentity.keyId }}`\n{{ /if }}\n*Rekor Entry:*\n> UUID: `{{ event.rekorEntry.uuid }}`\n> Log Index: {{ event.rekorEntry.logIndex }}\n> Artifact: `{{ event.rekorEntry.artifactSha256 }}`\n> Integrated: {{ event.rekorEntry.integratedTimeUtc }}\n\n{{ #if (gt event.suppressedCount 0) }}:mute: {{ event.suppressedCount }} duplicate alerts suppressed\n{{ /if }}---\n_Event ID: {{ event.eventId }}_"
}

View File

@@ -1,16 +1,17 @@
{
"templateId": "identity-matched-teams",
"tenantId": "bootstrap",
"channelType": "teams",
"channelType": "Teams",
"key": "identity-matched",
"locale": "en-US",
"schemaVersion": "1.0.0",
"renderMode": "Markdown",
"renderMode": "None",
"format": "Json",
"description": "Identity watchlist match alert for Microsoft Teams",
"description": "Microsoft Teams adaptive card for identity watchlist matches",
"metadata": {
"eventKind": "attestor.identity.matched",
"category": "attestation",
"eventKind": "attestor.identity.matched"
"contentType": "application/json"
},
"body": "{ \"@type\": \"MessageCard\", \"@context\": \"http://schema.org/extensions\", \"themeColor\": \"{% if event.severity == 'Critical' %}d13438{% elsif event.severity == 'Warning' %}ffb900{% else %}0078d4{% endif %}\", \"summary\": \"Identity Watchlist Alert: {{ event.watchlistEntryName }}\", \"sections\": [{ \"activityTitle\": \"⚠️ Identity Watchlist Alert\", \"activitySubtitle\": \"Entry: {{ event.watchlistEntryName }}\", \"facts\": [{ \"name\": \"Severity\", \"value\": \"{{ event.severity }}\" }, { \"name\": \"Occurred\", \"value\": \"{{ event.occurredAtUtc }}\" }{% if event.matchedIdentity.issuer %}, { \"name\": \"Issuer\", \"value\": \"{{ event.matchedIdentity.issuer }}\" }{% endif %}{% if event.matchedIdentity.subjectAlternativeName %}, { \"name\": \"SAN\", \"value\": \"{{ event.matchedIdentity.subjectAlternativeName }}\" }{% endif %}, { \"name\": \"Rekor UUID\", \"value\": \"{{ event.rekorEntry.uuid }}\" }, { \"name\": \"Log Index\", \"value\": \"{{ event.rekorEntry.logIndex }}\" }{% if event.suppressedCount > 0 %}, { \"name\": \"Suppressed Count\", \"value\": \"{{ event.suppressedCount }}\" }{% endif %}], \"markdown\": true }] }"
"body": "{\"type\":\"message\",\"attachments\":[{\"contentType\":\"application/vnd.microsoft.card.adaptive\",\"content\":{\"$schema\":\"http://adaptivecards.io/schemas/adaptive-card.json\",\"type\":\"AdaptiveCard\",\"version\":\"1.4\",\"body\":[{\"type\":\"TextBlock\",\"text\":\"Identity Watchlist Alert\",\"weight\":\"bolder\",\"size\":\"large\",\"color\":\"{{ #if (eq event.severity 'critical') }}attention{{ else if (eq event.severity 'warning') }}warning{{ else }}default{{ /if }}\"},{\"type\":\"FactSet\",\"facts\":[{\"title\":\"Severity\",\"value\":\"{{ event.severity }}\"},{\"title\":\"Watchlist Entry\",\"value\":\"{{ event.watchlistEntryName }}\"}]},{\"type\":\"TextBlock\",\"text\":\"Matched Identity\",\"weight\":\"bolder\",\"spacing\":\"medium\"},{\"type\":\"FactSet\",\"facts\":[{{ #if event.matchedIdentity.issuer }}{\"title\":\"Issuer\",\"value\":\"{{ event.matchedIdentity.issuer }}\"},{{ /if }}{{ #if event.matchedIdentity.subjectAlternativeName }}{\"title\":\"SAN\",\"value\":\"{{ event.matchedIdentity.subjectAlternativeName }}\"},{{ /if }}{{ #if event.matchedIdentity.keyId }}{\"title\":\"Key ID\",\"value\":\"{{ event.matchedIdentity.keyId }}\"},{{ /if }}{\"title\":\"\",\"value\":\"\"}]},{\"type\":\"TextBlock\",\"text\":\"Rekor Entry\",\"weight\":\"bolder\",\"spacing\":\"medium\"},{\"type\":\"FactSet\",\"facts\":[{\"title\":\"UUID\",\"value\":\"{{ event.rekorEntry.uuid }}\"},{\"title\":\"Log Index\",\"value\":\"{{ event.rekorEntry.logIndex }}\"},{\"title\":\"Artifact\",\"value\":\"{{ event.rekorEntry.artifactSha256 }}\"},{\"title\":\"Integrated\",\"value\":\"{{ event.rekorEntry.integratedTimeUtc }}\"}]}{{ #if (gt event.suppressedCount 0) }},{\"type\":\"TextBlock\",\"text\":\"{{ event.suppressedCount }} duplicate alerts suppressed\",\"isSubtle\":true,\"spacing\":\"small\"}{{ /if }}],\"msteams\":{\"width\":\"Full\"}}}]}"
}

View File

@@ -1,16 +1,17 @@
{
"templateId": "identity-matched-webhook",
"tenantId": "bootstrap",
"channelType": "webhook",
"channelType": "Webhook",
"key": "identity-matched",
"locale": "en-US",
"schemaVersion": "1.0.0",
"renderMode": "None",
"format": "Json",
"description": "Identity watchlist match alert for Webhook (SIEM/SOC integration)",
"description": "Webhook payload for identity watchlist matches",
"metadata": {
"eventKind": "attestor.identity.matched",
"category": "attestation",
"eventKind": "attestor.identity.matched"
"contentType": "application/json"
},
"body": "{ \"eventType\": \"attestor.identity.matched\", \"eventId\": \"{{ event.eventId }}\", \"tenantId\": \"{{ event.tenantId }}\", \"severity\": \"{{ event.severity }}\", \"occurredAtUtc\": \"{{ event.occurredAtUtc }}\", \"watchlist\": { \"entryId\": \"{{ event.watchlistEntryId }}\", \"entryName\": \"{{ event.watchlistEntryName }}\" }, \"matchedIdentity\": { \"issuer\": \"{{ event.matchedIdentity.issuer }}\", \"subjectAlternativeName\": \"{{ event.matchedIdentity.subjectAlternativeName }}\", \"keyId\": \"{{ event.matchedIdentity.keyId }}\" }, \"rekorEntry\": { \"uuid\": \"{{ event.rekorEntry.uuid }}\", \"logIndex\": {{ event.rekorEntry.logIndex }}, \"artifactSha256\": \"{{ event.rekorEntry.artifactSha256 }}\", \"integratedTimeUtc\": \"{{ event.rekorEntry.integratedTimeUtc }}\" }, \"suppressedCount\": {{ event.suppressedCount }} }"
"body": "{\"alertType\":\"identity-watchlist-match\",\"severity\":\"{{ event.severity }}\",\"watchlist\":{\"entryId\":\"{{ event.watchlistEntryId }}\",\"entryName\":\"{{ event.watchlistEntryName }}\"},\"matchedIdentity\":{\"issuer\":{{ #if event.matchedIdentity.issuer }}\"{{ event.matchedIdentity.issuer }}\"{{ else }}null{{ /if }},\"subjectAlternativeName\":{{ #if event.matchedIdentity.subjectAlternativeName }}\"{{ event.matchedIdentity.subjectAlternativeName }}\"{{ else }}null{{ /if }},\"keyId\":{{ #if event.matchedIdentity.keyId }}\"{{ event.matchedIdentity.keyId }}\"{{ else }}null{{ /if }}},\"rekorEntry\":{\"uuid\":\"{{ event.rekorEntry.uuid }}\",\"logIndex\":{{ event.rekorEntry.logIndex }},\"artifactSha256\":\"{{ event.rekorEntry.artifactSha256 }}\",\"integratedTimeUtc\":\"{{ event.rekorEntry.integratedTimeUtc }}\"},\"eventId\":\"{{ event.eventId }}\",\"occurredAtUtc\":\"{{ event.occurredAtUtc }}\",\"suppressedCount\":{{ event.suppressedCount }}}"
}

View File

@@ -0,0 +1,17 @@
{
"templateId": "tmpl-risk-profile-state-email",
"tenantId": "bootstrap",
"channelType": "Email",
"key": "tmpl-risk-profile-state",
"locale": "en-US",
"schemaVersion": "1.0.0",
"renderMode": "Html",
"format": "Html",
"description": "Email notification for risk profile state changes",
"metadata": {
"eventKind": "risk.profile.published",
"category": "risk",
"subject": "[Notify] Risk profile update: {{ event.profileName }}"
},
"body": "<!DOCTYPE html>\n<html>\n<head><style>body{font-family:sans-serif;line-height:1.5;}.section{margin:1em 0;padding:1em;background:#f8f9fa;border-radius:4px;}.label{font-weight:bold;color:#666;}.mono{font-family:monospace;background:#e9ecef;padding:2px 6px;border-radius:3px;}</style></head>\n<body>\n<h2>Risk Profile Update</h2>\n<div class=\"section\">\n<p><span class=\"label\">Profile:</span> <span class=\"mono\">{{ event.profileName }}</span></p>\n<p><span class=\"label\">State:</span> {{ event.state }}</p>\n<p><span class=\"label\">Owner:</span> {{ event.owner }}</p>\n<p><span class=\"label\">Summary:</span> {{ event.summary }}</p>\n{{ #if event.policyId }}<p><span class=\"label\">Policy:</span> {{ event.policyId }} (v{{ event.policyVersion }})</p>{{ /if }}\n</div>\n<hr>\n<p style=\"font-size:0.85em;color:#666;\">Event ID: {{ event.eventId }} | Occurred: {{ event.occurredAtUtc }}</p>\n</body>\n</html>"
}

View File

@@ -0,0 +1,16 @@
{
"templateId": "tmpl-risk-profile-state-slack",
"tenantId": "bootstrap",
"channelType": "Slack",
"key": "tmpl-risk-profile-state",
"locale": "en-US",
"schemaVersion": "1.0.0",
"renderMode": "Markdown",
"format": "Json",
"description": "Slack notification for risk profile state changes",
"metadata": {
"eventKind": "risk.profile.published",
"category": "risk"
},
"body": ":information_source: *Risk profile update*\n\n*Profile:* {{ event.profileName }}\n*State:* {{ event.state }}\n*Owner:* {{ event.owner }}\n*Summary:* {{ event.summary }}\n\n{{ #if event.policyId }}*Policy:* {{ event.policyId }} (v{{ event.policyVersion }})\n{{ /if }}---\n_Event ID: {{ event.eventId }} | {{ event.occurredAtUtc }}_"
}

View File

@@ -0,0 +1,17 @@
{
"templateId": "tmpl-risk-severity-change-email",
"tenantId": "bootstrap",
"channelType": "Email",
"key": "tmpl-risk-severity-change",
"locale": "en-US",
"schemaVersion": "1.0.0",
"renderMode": "Html",
"format": "Html",
"description": "Email notification for risk severity changes",
"metadata": {
"eventKind": "risk.profile.severity.changed",
"category": "risk",
"subject": "[Notify] Risk severity changed: {{ event.profileName }}"
},
"body": "<!DOCTYPE html>\n<html>\n<head><style>body{font-family:sans-serif;line-height:1.5;}.section{margin:1em 0;padding:1em;background:#f8f9fa;border-radius:4px;}.label{font-weight:bold;color:#666;}.mono{font-family:monospace;background:#e9ecef;padding:2px 6px;border-radius:3px;}</style></head>\n<body>\n<h2>Risk Severity Changed</h2>\n<div class=\"section\">\n<p><span class=\"label\">Profile:</span> <span class=\"mono\">{{ event.profileName }}</span></p>\n<p><span class=\"label\">Previous:</span> {{ event.previousSeverity }}</p>\n<p><span class=\"label\">Current:</span> {{ event.newSeverity }}</p>\n<p><span class=\"label\">Reason:</span> {{ event.reason }}</p>\n{{ #if event.referenceUrl }}<p><span class=\"label\">Reference:</span> <a href=\"{{ event.referenceUrl }}\">{{ event.referenceUrl }}</a></p>{{ /if }}\n</div>\n<hr>\n<p style=\"font-size:0.85em;color:#666;\">Event ID: {{ event.eventId }} | Occurred: {{ event.occurredAtUtc }}</p>\n</body>\n</html>"
}

View File

@@ -0,0 +1,16 @@
{
"templateId": "tmpl-risk-severity-change-slack",
"tenantId": "bootstrap",
"channelType": "Slack",
"key": "tmpl-risk-severity-change",
"locale": "en-US",
"schemaVersion": "1.0.0",
"renderMode": "Markdown",
"format": "Json",
"description": "Slack notification for risk severity changes",
"metadata": {
"eventKind": "risk.profile.severity.changed",
"category": "risk"
},
"body": ":rotating_light: *Risk severity changed*\n\n*Profile:* {{ event.profileName }}\n*Previous:* {{ event.previousSeverity }}\n*Current:* {{ event.newSeverity }}\n*Reason:* {{ event.reason }}\n\n{{ #if event.referenceUrl }}*Reference:* {{ event.referenceUrl }}\n{{ /if }}---\n_Event ID: {{ event.eventId }} | {{ event.occurredAtUtc }}_"
}