feat: M19 API audit log + M16a notifier connectors (Slack, Teams, PagerDuty, OpsGenie)

M19: HTTP middleware records every API call to the immutable audit trail
with method, path, actor, SHA-256 body hash, status, and latency. Best-effort
async recording via goroutine. Health/ready probes excluded.

M16a: Four pluggable notifier connectors — Slack (incoming webhook), Teams
(MessageCard), PagerDuty (Events API v2), OpsGenie (Alert API v2). Each
enabled by config env var. 30 new tests across middleware and connectors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
shankar0123
2026-03-23 17:58:14 -04:00
parent b227502cef
commit 9b0ff37973
14 changed files with 1399 additions and 5 deletions
+24
View File
@@ -20,6 +20,20 @@ type Config struct {
CORS CORSConfig
Keygen KeygenConfig
CA CAConfig
Notifiers NotifierConfig
}
// NotifierConfig contains configuration for notification connectors.
// Each notifier is enabled by setting its required env var (webhook URL or API key).
type NotifierConfig struct {
SlackWebhookURL string
SlackChannel string
SlackUsername string
TeamsWebhookURL string
PagerDutyRoutingKey string
PagerDutySeverity string
OpsGenieAPIKey string
OpsGeniePriority string
}
// KeygenConfig controls where private keys are generated.
@@ -146,6 +160,16 @@ func Load() (*Config, error) {
CertPath: getEnv("CERTCTL_CA_CERT_PATH", ""),
KeyPath: getEnv("CERTCTL_CA_KEY_PATH", ""),
},
Notifiers: NotifierConfig{
SlackWebhookURL: getEnv("CERTCTL_SLACK_WEBHOOK_URL", ""),
SlackChannel: getEnv("CERTCTL_SLACK_CHANNEL", ""),
SlackUsername: getEnv("CERTCTL_SLACK_USERNAME", "certctl"),
TeamsWebhookURL: getEnv("CERTCTL_TEAMS_WEBHOOK_URL", ""),
PagerDutyRoutingKey: getEnv("CERTCTL_PAGERDUTY_ROUTING_KEY", ""),
PagerDutySeverity: getEnv("CERTCTL_PAGERDUTY_SEVERITY", "warning"),
OpsGenieAPIKey: getEnv("CERTCTL_OPSGENIE_API_KEY", ""),
OpsGeniePriority: getEnv("CERTCTL_OPSGENIE_PRIORITY", "P3"),
},
}
if err := cfg.Validate(); err != nil {