The Trinity Beast Infrastructure — Security Posture

Complete defensive security architecture — every layer, every rule, every path.

Account: 211998422884 Region: us-east-2 (Ohio) Document Date: October 11, 2026 Classification: Public

Table of Contents

  1. Security Architecture Overview
  2. Layer 1 — Edge Defense (CloudFront + Shield)
  3. Layer 2 — Web Application Firewall (WAF)
  4. Layer 3 — Application Security
  5. Layer 4 — Network Isolation (VPC + Peering)
  6. Layer 5 — Data Layer Protection
  7. Layer 6 — The Flame Path (UDP Security)
  8. Layer 7 — Threat Detection & Response
  9. Layer 8 — Autonomous Operations (AI Defense)
  10. Layer 9 — Audit Trail & Forensics
  11. Layer 10 — Identity & Access Management
  12. Layer 11 — Secrets & Key Management
  13. Security Summary & Posture Rating

List of Diagrams

  1. Diagram 1.1: Complete Security Architecture — All Layers
  2. Diagram 6.1: The Flame Path — UDP Security Flow
  3. Diagram 7.1: Threat Detection & Response Pipeline

1. Security Architecture Overview

The Trinity Beast Infrastructure implements defense-in-depth across 11 distinct security layers. No single layer is trusted to stop all threats — each layer assumes the one above it has been breached. Traffic must survive every gauntlet before reaching the data layer.

Design Philosophy: Assume breach at every boundary. Every layer operates independently. If CloudFront falls, WAF catches it. If WAF is bypassed, application rate limiting stops it. If rate limiting fails, network isolation contains it. If network isolation is compromised, encryption at rest protects the data. No single point of failure in the security chain.

The Security Stack (Outside → Inside)

#LayerTechnologyPurpose
1Edge CloudFront + ShieldCloudFront, Shield StandardDDoS absorption, TLS termination, geographic distribution
2Edge WAFAWS WAF v2 (2 WebACLs)IP reputation, rate limiting, SQL injection, known exploits, honeypot traps
3AppApplicationGo middleware stackAPI key auth, per-tier rate limiting, input validation, CORS, HMAC verification
4Network VPC Isolation2 VPCs + peeringCompute and data on separate networks, no public IPs on data layer
5DataData ProtectionAurora, ElastiCacheTLS in transit, encryption at rest, security groups, no public endpoints
6EdgeFlame Path (UDP)NLB + application protocolStateless UDP with cryptographic validation, no TCP overhead
7OpsDetectionGuardDuty, CloudWatchBehavioral anomaly detection, alarm-driven response
8Ops AutoOps AIBedrock + EventBridgeAI-powered threat correlation, auto-blocking, self-healing
9OpsAudit TrailCloudTrail, VPC Flow LogsComplete API audit, network flow forensics
10Network IAMAWS IAMLeast-privilege roles, no shared credentials, service-scoped policies
11DataSecretsSecrets ManagerRotatable credentials, no hardcoded secrets in code or environment
flowchart TB
    subgraph INTERNET["🌐 Public Internet"]
        USER["👤 Legitimate User"]
        ATTACKER["💀 Attacker"]
        SCANNER["🤖 Scanner/Bot"]
    end

    subgraph EDGE["Layer 1 — Edge Defense"]
        CF["CloudFront CDN
TLS 1.3 · Shield Standard
DDoS Absorption"] CFWAF["CloudFront WAF
IP Reputation · Common Rules
Known Bad Inputs"] end subgraph ALB_LAYER["Layer 2 — API Gateway"] ALB["Application Load Balancer
TCP :443 → :8080/:9090"] ALBWAF["ALB WAF
Rate Limit 2000/5min
Admin Rate 100/5min
SQL Injection · Honeypot"] NLB["Network Load Balancer
UDP :2679/:2680"] end subgraph APP["Layer 3 — Application (ECS Fargate)"] direction LR MAIN["BeastMain
2 vCPU · 6 GB"] MIRROR["BeastMirror
2 vCPU · 6 GB"] LRS["BeastLRS
2 vCPU · 6 GB"] WEBHOOK["BeastWebhook
Push Only · No Inbound"] end subgraph NETWORK["Layer 4 — Network Isolation"] ECSVPC["ECS VPC
10.0.0.0/16"] PEER["VPC Peering
pcx-0e988b7230cf451b8"] DATAVPC["Data VPC
172.31.0.0/16"] end subgraph DATA["Layer 5 — Data Layer"] AURORA["Aurora PostgreSQL 17.7
TLS · Encrypted at Rest
Private Subnet Only"] VALKEY["ElastiCache Serverless
Valkey 9.0 · TLS · AUTH Token
Private Subnet Only"] end subgraph DETECT["Layer 7–8 — Detection & Response"] GD["GuardDuty
VPC Flow · CloudTrail · DNS"] CW["CloudWatch
37 Alarms"] AUTOOPS["AutoOps AI
Bedrock Threat Analysis
Self-Heal · Auto-Block"] end USER --> CF ATTACKER --> CF SCANNER --> CF CF --> CFWAF CFWAF -->|"Static Assets"| USER USER -->|"API Requests"| ALB ATTACKER -->|"API Attacks"| ALB ALB --> ALBWAF ALBWAF -->|"Passed"| APP ALBWAF -->|"Blocked"| ATTACKER USER -->|"UDP Price Feed"| NLB NLB --> APP APP --> ECSVPC ECSVPC --> PEER PEER --> DATAVPC DATAVPC --> AURORA DATAVPC --> VALKEY GD -.->|"Monitors"| NETWORK CW -.->|"Monitors"| APP AUTOOPS -.->|"Auto-blocks"| ALBWAF linkStyle 0,1,2 stroke:#ef4444,stroke-width:2px linkStyle 7,8 stroke:#10b981,stroke-width:2px linkStyle 9 stroke:#ef4444,stroke-width:2px linkStyle 10 stroke:#f97316,stroke-width:2px linkStyle 11,12,13,14,15 stroke:#a855f7,stroke-width:2px

Diagram 1.1: Complete Security Architecture — All Layers

2. Layer 1 — Edge Defense (CloudFront + Shield)

The outermost perimeter. All website traffic enters through CloudFront — a globally distributed CDN with 450+ edge locations. API traffic hits the ALB directly (DNS-routed). Both paths are protected by AWS Shield Standard.

CloudFront Distribution

PropertyValue
Distribution IDE110PRKEIYQVLL
Domaincpmp-site.org / www.cpmp-site.org
OriginS3 bucket (trinity-beast-website-east2)
TLSTLS 1.2+ enforced (TLS 1.3 preferred)
HTTP → HTTPSRedirect all HTTP to HTTPS
WAF WebACLCreatedByCloudFront-449feaa5
ShieldStandard (automatic DDoS protection)
Geo RestrictionNone (global access)

Shield Standard Protection

AWS Shield Standard provides automatic protection against the most common Layer 3/4 DDoS attacks:

Shield Standard is free, automatic, and always-on. No configuration required. It protects both the CloudFront distribution and the ALB.

TLS Configuration

TLS Everywhere: Every connection in the system uses TLS. Browser → CloudFront (TLS 1.3). Browser → ALB (TLS 1.2+). ECS → Aurora (TLS). ECS → ElastiCache (TLS + AUTH). There is no unencrypted path anywhere in the infrastructure.

ConnectionProtocolCertificate
Browser → CloudFrontTLS 1.2/1.3ACM (auto-renewed)
Browser → ALB (API)TLS 1.2+ACM (auto-renewed)
ECS → AuroraTLS (rds-ca-rsa2048-g1)RDS CA bundle
ECS → ElastiCacheTLS + AUTH tokenElastiCache managed
Lambda → AWS APIsTLS 1.2+AWS SDK default

3. Layer 2 — Web Application Firewall (WAF)

Two separate WAF WebACLs protect different attack surfaces. The CloudFront WAF guards the static website. The ALB WAF guards the API — and carries the heavier rule set including rate limiting, SQL injection detection, and the honeypot trap system.

CloudFront WAF (CreatedByCloudFront-449feaa5)

RuleActionPurpose
AWS-AWSManagedRulesAmazonIpReputationListBlockKnown malicious IPs, botnets, compromised hosts
AWS-AWSManagedRulesCommonRuleSetBlockOWASP Top 10, path traversal, file inclusion, XSS
AWS-AWSManagedRulesKnownBadInputsRuleSetBlockLog4j, Spring4Shell, known exploit payloads

ALB WAF (trinity-beast-api-waf)

RulePriorityActionPurpose
AWS-AWSManagedRulesAmazonIpReputationList1BlockKnown malicious IPs
AWS-AWSManagedRulesCommonRuleSet2BlockOWASP Top 10 (SizeRestrictions_BODY excluded for /newsletter/*)
AWS-AWSManagedRulesKnownBadInputsRuleSet3BlockKnown exploits (excluded for /newsletter/*)
AWS-AWSManagedRulesSQLiRuleSet4BlockSQL injection patterns in query strings, body, headers
RateLimit-Global-20005BlockGlobal rate limit: 2000 requests per 5 minutes per IP
RateLimit-Admin-60006BlockAdmin endpoint rate limit: 6000 requests per 5 minutes per IP (renamed from RateLimit-Admin-100 2026-08-23 after raising the threshold)
AutoOps-BlockedIPs7BlockDynamic block list — IPs added by honeypot processor and manual blocks

WAF Exclusions

Newsletter Endpoints: /newsletter/* paths are excluded from SizeRestrictions_BODY (CommonRules) and KnownBadInputsRuleSet to allow base64-encoded HTML email content in POST bodies. These endpoints are admin-key protected — only the digest Lambda can call them.

Dynamic IP Block List

The tbi-autoops-blocked-ips IP set (ID: 8d55de25-8ba5-4982-8c41-f4316c9bd50d) is managed automatically by the honeypot processor Lambda. IPs are added when they hit honeypot trap endpoints. As of this writing the set holds 473 IPs (5% of the WAF IP set's 10,000-address cap) — 444 honeypot-dated (90-day expiry) and 29 unmanaged (manual/undated, never auto-expire).

90-Day Expiry for Honeypot Blocks

The honeypot-triggered portion of the block list ages out after 90 days rather than growing without bound. A WAF IP set caps at 10,000 addresses, and at the observed rate of new honeypot hits, an unmanaged list would fill that cap within roughly two years and then silently stop accepting new blocks — the failure mode of an "unbounded" design is not "the list gets big," it's "blocking eventually stops working."

Manual blocks made via block-ip are never auto-expired — those carry no honeypot evidence and are assumed to be intentional, permanent decisions. Only IPs positively attributed to the honeypot are dated and pruned.

Why a separate ledger, rather than trusting the per-IP honeypot:ip:<ip> Valkey hash directly: those records turned out to be inconsistent in practice — some carry a short TTL, some are permanent, and some blocked IPs have no record at all. Expiry logic built on top of that would silently mis-date or lose IPs. Instead, a dedicated sorted set (honeypot:blocklist:blocked_at, member=IP, score=block epoch) is written the moment the honeypot processor issues a block — before the flaky per-IP record can expire — and that ledger is what honeypot-prune reads to decide age.

The ledger itself is made durable across a Valkey wipe by three stores that agree with each other: the WAF IP set is membership truth (durable, AWS-managed), a private S3 JSON object (s3://aws-waf-logs-trinity-beast/honeypot/blocklist-ledger.json) is the durable timestamp record, and the Valkey sorted set is the fast working copy. BeastReconciler reconciles all three every night, and the honeypot processor Lambda writes to the ledger at block time — so a Valkey flush can never orphan a block's age.

Honeypot Trap System

12 decoy endpoints that no legitimate user would ever access. Any hit immediately identifies the source as a scanner or attacker:

Trap EndpointMimics
/wp-adminWordPress admin panel
/wp-login.phpWordPress login
/.envEnvironment file exposure
/.git/configGit repository exposure
/phpmyadminDatabase admin panel
/admin/loginGeneric admin login
/xmlrpc.phpWordPress XML-RPC
/actuatorSpring Boot actuator
/api/v1/adminGeneric API admin
/debug/varsGo debug endpoint
/server-statusApache status page
/telescopeLaravel Telescope

Behavior on hit: 2-second tarpit delay (wastes scanner time) → log IP, user-agent, path to Valkey → queue for WAF auto-block → daily digest includes all honeypot activity.

4. Layer 3 — Application Security

The Go application implements its own security stack independent of AWS infrastructure. Even if WAF is completely bypassed, the application enforces authentication, authorization, rate limiting, and input validation at every endpoint.

API Key Authentication

Every non-public endpoint requires a valid API key in the Authorization: Bearer header. Keys are validated against a multi-tier cache:

  1. Local cache (sync.Map) — sub-microsecond lookup, 5-minute TTL for standard tiers, 60-minute for partner/stress
  2. ElastiCache (Valkey) — millisecond lookup, populated by Aurora on first access
  3. Aurora (PostgreSQL) — source of truth, queried only on cache miss

Invalid keys receive an immediate 401 Unauthorized with full UME envelope. No information leakage about why the key failed.

Per-Tier Rate Limiting

TierQPS LimitBurstMonthly CapCache TTL
Free2510005 min
Pro1020500005 min
Enterprise501005000005 min
UnlimitedNoneNoneNone5 min
LifetimeNoneNoneNone5 min
PartnerNoneNoneNone60 min

Rate limiting is enforced per API key using a token bucket algorithm with ElastiCache-backed counters. Exceeding the limit returns 429 Too Many Requests.

Admin Endpoint Protection

All /admin/* endpoints require the admin API key (X-Admin-Key header). This key is:

CORS Policy

The CORS middleware echoes the requesting origin only for cpmp-site.org and www.cpmp-site.org with credentials: true. All other origins receive Access-Control-Allow-Origin: * (public API — no credentials). This prevents credential-bearing cross-origin requests from unauthorized domains.

Input Validation

Webhook HMAC Verification

Outbound webhook deliveries include an HMAC-SHA256 signature in the X-Signature header. Subscribers verify the signature using their webhook secret to confirm the payload originated from The Trinity Beast and was not tampered with in transit.

5. Layer 4 — Network Isolation (VPC + Peering)

Compute and data live on completely separate networks. There is no path from the public internet to the data layer. The only bridge is a VPC peering connection with strict security group rules.

Two-VPC Architecture

VPCCIDRPurposeInternet Access
vpc-03deaddb7083cd59c10.0.0.0/16ECS VPC — compute (Fargate tasks, Lambda)Yes (IGW for ECS, VPC endpoints for Lambda)
vpc-0876ee7be3a677f26172.31.0.0/16Data VPC — storage (Aurora, ElastiCache)None — completely private

Critical Design Decision: The Data VPC has NO internet gateway, NO NAT gateway, and NO public subnets. Aurora and ElastiCache are unreachable from the internet by network architecture — not just by security group rules. Even if every security group were misconfigured to allow 0.0.0.0/0, traffic still cannot route to the data layer from outside.

VPC Peering

Peering connection pcx-0e988b7230cf451b8 bridges the ECS VPC to the Data VPC. Route tables in the ECS subnets send 172.31.0.0/16 traffic through the peering connection. Only specific ports are allowed through security groups.

Security Groups

Security GroupVPCInbound RulesUsed By
sg-050b617f93b2388f6ECS VPCALB health checks, inter-containerECS tasks, queued-writer Lambda
sg-03fa8e2b34d54ffb0Data VPCTCP 5432 from 10.0.1.0/24, 10.0.2.0/24, 10.0.6.0/24 onlyAurora cluster
sg-0b0d55e13dad621a1ECS VPCTCP 443 + 5432 from ECS SGVPC endpoints (Secrets Manager, SQS)

Aurora's security group only accepts connections from the three ECS subnets — not from the entire ECS VPC CIDR, and certainly not from anywhere else. This is defense-in-depth: even if an attacker compromises an ECS task, they can only reach Aurora on port 5432 with valid credentials.

VPC Endpoints (Private AWS Service Access)

Lambda functions in the ECS VPC cannot reach AWS services over the internet (no public IP on Lambda ENIs). VPC endpoints provide private connectivity:

6. Layer 5 — Data Layer Protection

The crown jewels — Aurora PostgreSQL and ElastiCache (Valkey). Both are encrypted at rest, encrypted in transit, and accessible only from the ECS VPC via peering.

Aurora PostgreSQL

PropertyValue
EnginePostgreSQL 17.7 (Aurora Serverless v2)
Encryption at RestAES-256 (AWS KMS managed key)
Encryption in TransitTLS required (rds.force_ssl = 1)
Public AccessDisabled — no public endpoint
NetworkData VPC private subnets only
AuthenticationUsername/password via Secrets Manager
BackupAutomated daily snapshots, 7-day retention
I/O ModeOptimized I/O (no per-IOPS charges)

ElastiCache Serverless (Valkey)

PropertyValue
EngineValkey 9.0, Serverless (auto-scaling, no fixed nodes)
CapacityMax 30 GB storage / 10,000 ECPU/s configured limits
AvailabilityMulti-AZ, auto-heals across AZs — no manual intervention
Encryption at RestAES-256 (AWS managed)
Encryption in TransitTLS required (always-on)
AuthenticationAUTH token (stored in Secrets Manager)
Public AccessDisabled — VPC-only
NetworkData VPC private subnets only

ℹ️ Migrated from a fixed cache.r7g.2xlarge node to ElastiCache Serverless on July 2, 2026. The Serverless proxy layer handles cluster-mode routing transparently — no application-code change was needed.

Zero Public Surface: Neither Aurora nor ElastiCache has a public endpoint. They exist only within the Data VPC's private subnets. The only way to reach them is through the VPC peering connection from the ECS VPC — which requires being an ECS task or a VPC-attached Lambda with the correct security group.

7. Layer 6 — The Flame Path (UDP Security)

The UDP price feed is the fastest path into the system — raw speed with zero TCP handshake overhead. It's called the Flame Path because data travels at wire speed, burning through with no connection state, no retransmission, no negotiation. But speed without security is recklessness. The Flame Path has its own security model.

🔥 The Flame Path Philosophy: UDP is stateless by design. There are no connections to hijack, no sessions to steal, no handshakes to intercept. The security model is fundamentally different from TCP — it relies on cryptographic validation of every single packet rather than connection-level trust.

UDP Infrastructure

ComponentValue
Load BalancerTrinity-Beast-UDP-NLB (Network Load Balancer)
Ports2679 (primary), 2680 (secondary)
ProtocolUDP (stateless, connectionless)
DNSudp.cpmp-site.org
TargetECS Fargate tasks (same containers as TCP)
Health CheckTCP on port 8081 (dedicated health port — isolated from application traffic)

UDP Security Model

  1. API Key in Every Packet: Each UDP request includes the API key in the packet payload. There is no session — every packet is independently authenticated.
  2. Same Key Validation: The UDP handler uses the identical key validation pipeline as TCP (local cache → ElastiCache → Aurora). Invalid keys are rejected with zero response (silent drop — no error packet to confirm the endpoint exists).
  3. Rate Limiting: Per-tier rate limits apply identically to UDP and TCP. The token bucket doesn't care which protocol delivered the request.
  4. No Amplification: UDP responses are smaller than or equal to requests. The system cannot be used as a DDoS amplification vector.
  5. NLB Protection: The Network Load Balancer handles millions of packets per second at the network layer. It doesn't maintain connection state (unlike ALB), making it inherently resistant to state-exhaustion attacks.

Why UDP is Safe Here

Common UDP security concerns and how the Flame Path addresses them:

ConcernTCP RiskFlame Path Mitigation
IP SpoofingSYN cookies preventResponse goes to spoofed IP — attacker gains nothing (price data is public anyway)
AmplificationN/A (connection-based)Response ≤ request size. Cannot amplify.
Replay AttacksSequence numbersReplayed request returns current price — no state change, no harm
EavesdroppingTLS encryptsPrice data is public information. Nothing secret in the payload.
Flood AttacksConnection limitsNLB absorbs at wire speed + per-key rate limiting drops excess

Design Insight: The Flame Path works because the data it carries (cryptocurrency prices) is inherently public. There is no secret to protect in transit. The API key protects access metering and rate limiting — not data confidentiality. This is why UDP without TLS is acceptable here but would not be acceptable for private data.

flowchart LR
    subgraph CLIENT["Partner / Subscriber"]
        APP["Application
UDP Client"] end subgraph EDGE["Edge"] NLB["NLB
UDP :2679/:2680
Wire Speed"] end subgraph ECS["ECS Fargate"] UDP_HANDLER["UDP Handler
Zero-Alloc v6
Per-Packet Auth"] CACHE["sync.Map
Price Cache
Sub-μs Lookup"] RATE["Rate Limiter
Token Bucket
Per-Key"] end APP -->|"🔥 UDP Packet
[API_KEY + ASSET]"| NLB NLB -->|"Forward"| UDP_HANDLER UDP_HANDLER -->|"1. Validate Key"| RATE RATE -->|"2. Check Limit"| CACHE CACHE -->|"3. Price Response"| UDP_HANDLER UDP_HANDLER -->|"🔥 UDP Response
[PRICE_DATA]"| APP style NLB fill:#7f1d1d,stroke:#ef4444,color:#fca5a5 style UDP_HANDLER fill:#1a0f0a,stroke:#f97316,color:#fdba74 style CACHE fill:#064e3b,stroke:#10b981,color:#6ee7b7 style RATE fill:#1e3a5f,stroke:#60a5fa,color:#93c5fd linkStyle 0 stroke:#f97316,stroke-width:3px linkStyle 5 stroke:#f97316,stroke-width:3px

Diagram 6.1: The Flame Path — UDP Security Flow

Flame Path Performance Characteristics

8. Layer 7 — Threat Detection & Response

Passive monitoring that watches everything and alerts on anomalies. This layer doesn't block — it detects, correlates, and escalates.

Amazon GuardDuty

PropertyValue
Detector ID18ceef6f8dddcf6082473cc7016ee458
Data SourcesVPC Flow Logs, CloudTrail, DNS query logs
Finding TypesReconnaissance, instance compromise, credential compromise, data exfiltration
IntegrationSeverity ≥ 7 → EventBridge rule tbi-ops-guardduty-high-finding → Bedrock threat analysis Lambda

GuardDuty uses machine learning to establish behavioral baselines and detect deviations. It monitors:

ℹ️ There is no TrinityBeast-GuardDuty-Finding CloudWatch alarm — one existed briefly but was deleted 2026-07-30 because AWS/GuardDuty publishes no finding metric, so it could never actually fire. The EventBridge rule above is the real integration path and does not depend on a metric alarm.

CloudWatch Alarms (37 in us-east-2, 1 in us-east-1 = 38 account-wide)

Infrastructure Alarms (14)

AlarmThresholdAction
Trinity-Beast-ALB-UnhealthyTargets≥ 1 unhealthy targetSNS → self-heal
Trinity-Beast-Aurora-CPU-HighCPU > 80%SNS → notify
Trinity-Beast-Aurora-Connections-HighConnections > thresholdSNS → notify
Trinity-Beast-ECS-CPU-High / -LRS / -MirrorCPU > 80%SNS → notify
Trinity-Beast-ElastiCache-ECPU-HighECPU above 60% of the 10,000/s cap (360,000 per minute) for 15 minutesSNS → notify
Trinity-Beast-ElastiCache-Storage-HighStorage > 24 GB of 30 GB maxSNS → notify
Trinity-Beast-ElastiCache-ThrottledThrottledCmds > 0SNS → notify
Trinity-Beast-*-Service-Count-Low (Main/Mirror/LRS)Running tasks < desiredSNS → self-heal
Trinity-Beast-NLB-UnhealthyTargets≥ 1 unhealthy targetSNS → self-heal
Trinity-Beast-S3-Size-Unusual-GrowthUnusual growth rateSNS → notify

ℹ️ Migrated to ElastiCache Serverless: the previous -CPU-High / -Memory-High node-based alarms no longer apply — ElastiCache moved from a fixed cache.r7g.2xlarge node to Serverless on July 2, 2026, and the alarms above (ECPU, storage, throttled commands) are the Serverless-native replacements.

Target-Group Health Alarms (6 — full coverage, all 8 target groups alarmed across this table and the Webhook Test Receiver table below)

AlarmTarget GroupLoad Balancer
Trinity-Beast-ALB-UnhealthyTargetstrinity-beast-fargate-groupTCP-ALB
Trinity-Beast-LRS-TargetGroup-Unhealthytrinity-beast-lrs-9090TCP-ALB
Trinity-Beast-NLB-UnhealthyTargetsTrinity-Beast-UDP-2679-TGUDP-NLB
Trinity-Beast-UDP-2680-UnhealthyTrinity-Beast-UDP-2680-TGUDP-NLB
Trinity-Beast-PrivateLink-8080-Unhealthytrinity-beast-pl-tcp-8080TCP-NLB (internal)
Trinity-Beast-PrivateLink-9090-Unhealthytrinity-beast-pl-tcp-9090TCP-NLB (internal)

Webhook Test Receiver Alarms (2 — added 2026-08-07)

AlarmTarget GroupLoad Balancer
Trinity-Beast-Webhook-Test-8090-Unhealthytrinity-beast-webhook-test-tgTCP-ALB
Trinity-Beast-UDP-2681-UnhealthyTrinity-Beast-UDP-2681-TGUDP-NLB

Application-Log Metric Alarms (2 — added 2026-08-10)

The only alarms in the account sourced from CloudWatch Logs metric filters (on /aws/ecs/trinity-beast) rather than a native AWS service metric:

AlarmThresholdAction
Trinity-Beast-ParamLoad-AuroraFallback-Recurring≥ 3 in 1hSNS → notify
Trinity-Beast-Startup-MigrationFailure≥ 1 in 1hSNS → notify

Coverage Alarms (3 — added 2026-07-30, closing gaps alarm-audit found with no alarm of any kind)

AlarmThresholdAction
Trinity-Beast-Webhook-Service-Count-LowRunning tasks < 1SNS → self-heal
Trinity-Beast-Translate-Worker-Count-LowRunning tasks < 1SNS → self-heal
Trinity-Beast-Translation-DLQ-NotEmptyMessages visible > 0SNS → investigate

ℹ️ The webhook service is a paying product ($30–$420/mo push tiers) and could otherwise have stopped delivering silently — this is why it has its own dedicated task-count alarm rather than relying on the generic ECS alarms above.

Security Alarms (4)

AlarmThresholdAction
TrinityBeast-API-4xx-SpikeThreshold 300SNS → investigate
TrinityBeast-API-5xx-SpikeTarget 5xx, threshold 9SNS → self-heal
TrinityBeast-API-ELB-5xx-SpikeELB-generated 5xx, threshold 9SNS → self-heal
TrinityBeast-WAF-HighBlockRateBlock rate spikeSNS → investigate

Target-5xx and ELB-5xx are distinct signals: target-5xx means the container itself returned an error; ELB-5xx means the ALB couldn't get a usable response from any target at all (502/503/504).

Other Alarms (8 — not managed by us directly)

Anomaly Detection is fully retired — 0 anomaly alarms remain. All four original ML-based anomaly detectors (RequestRate, Latency, ErrorRate, CacheHitRate) were deleted by 2026-08-26. Each flapped repeatedly against genuinely healthy infrastructure — a 300-second Average of a ratio metric collapses on any window with a miss and no hit, and TargetResponseTime is bimodal enough (fast cached reads mixed with slower admin/report calls) that no anomaly band could sit still. They were also triggering no-op self-heal Step Function runs on every flap. The replacement for latency monitoring is a static p99 > 300ms alarm (queued, not yet built). Do not re-introduce ML anomaly detection on these metrics without a materially different approach — this was tried and it did not work.

flowchart TB
    subgraph SIGNALS["Detection Signals"]
        WAF_BLOCKS["WAF Block Events"]
        GD_FINDINGS["GuardDuty Findings"]
        CW_ALARMS["CloudWatch Alarms"]
        HONEYPOT["Honeypot Hits"]
        ANOMALY["Anomaly Detectors"]
    end

    subgraph ROUTING["Event Routing"]
        EB["EventBridge
Pattern Matching"] SNS["SNS
tbi-ops-notifications"] end subgraph RESPONSE["Automated Response"] SF["Step Function
tbi-ops-health-check-heal"] BEDROCK["Bedrock Analysis
Claude Sonnet 4.6
Threat Correlation"] HONEYPOT_PROC["Honeypot Processor
Every 5 min"] SELF_HEAL["Self-Heal Lambda
Restart · Redeploy"] WAF_ACTION["WAF Action Lambda
Block IP · Unblock"] NOTIFY["Notify Lambda
Formatted SES Email"] end subgraph ACTIONS["Outcomes"] BLOCK["🚫 WAF Block"] RESTART["🔄 ECS Restart"] EMAIL["📧 Alert Email"] ESCALATE["🚨 Page Cory"] end WAF_BLOCKS --> EB GD_FINDINGS --> EB CW_ALARMS --> SNS CW_ALARMS --> EB HONEYPOT --> HONEYPOT_PROC ANOMALY --> SNS SNS --> NOTIFY EB -->|"Alarm State Change"| SF EB -->|"Severity ≥ 7"| BEDROCK HONEYPOT_PROC --> WAF_ACTION SF --> SELF_HEAL SELF_HEAL --> RESTART BEDROCK -->|"HIGH/CRITICAL"| WAF_ACTION BEDROCK -->|"Report"| NOTIFY WAF_ACTION --> BLOCK NOTIFY --> EMAIL SF -->|"Unknown failure"| ESCALATE style BEDROCK fill:#1a0f2e,stroke:#a855f7,color:#c4b5fd style SF fill:#1e3a5f,stroke:#60a5fa,color:#93c5fd style NOTIFY fill:#064e3b,stroke:#10b981,color:#6ee7b7 style ESCALATE fill:#7f1d1d,stroke:#ef4444,color:#fca5a5

Diagram 7.1: Threat Detection & Response Pipeline

9. Layer 8 — Autonomous Operations (AI Defense)

The AI layer that turns raw signals into intelligent action. Amazon Bedrock (Claude Sonnet 4.6) correlates WAF blocks, honeypot hits, rate limit events, and usage anomalies to produce threat assessments and recommend actions.

How It Works

  1. Every 5 minutes: EventBridge triggers tbi-ops-bedrock-analyze Lambda
  2. Signal collection: Lambda gathers WAF block counts, honeypot hits, rate limit events, and GuardDuty findings from the last window
  3. Quiet check: If all signals are below threshold (infrastructure is quiet), Lambda exits immediately — no Bedrock invocation, no cost
  4. AI analysis: If signals are elevated, Lambda sends the correlated data to Bedrock for pattern analysis
  5. Threat report: Bedrock generates a plain-English threat assessment with severity rating (LOW/MEDIUM/HIGH/CRITICAL)
  6. Auto-action: For safe actions (IP blocks), the Lambda executes immediately. For destructive actions, it escalates to Cory.
  7. Storage: Threat report stored in Valkey (autoops:threats:daily) for the daily digest

Self-Healing Scenarios

TriggerDetectionAutomated ResponseNotification
Health check failureALB unhealthy target alarmIdentify failed task → restart → verify recovery[SELF-HEALED] email
Service count lowRunning tasks < desiredForce new deployment on affected service[SELF-HEALED] email
5xx spikeError rate alarmCheck if one node or all → restart single or escalate[WARNING] or [CRITICAL]
WebSocket feed deathStale price detectionWait 60s → recheck → force-deploy if still dead[SELF-HEALED] email
Honeypot hitTrap endpoint accessedQueue IP → WAF block (every 5 min batch)Included in daily digest
GuardDuty HIGHSeverity ≥ 7 findingBedrock analysis → auto-block if recommended[CRITICAL] email + assessment

Design Principles

Bedrock is advisory, not authoritative. The AI suggests actions. Step Functions decide whether to execute. Lambda performs the action. If the AI recommends something destructive (killing a service, revoking all keys), it escalates to Cory instead of acting. Safe actions (blocking a single IP) execute automatically.

Cost Consciousness

The system is designed to minimize Bedrock costs during quiet periods:

10. Layer 9 — Audit Trail & Forensics

Every action, every API call, every network flow is logged. When an incident occurs, the forensic trail is complete — who did what, when, from where.

CloudTrail

PropertyValue
Trail Nametrinity-beast-events-trail
ScopeMulti-region (all AWS API calls)
EventsManagement events + data events (S3, Lambda)
StorageS3 bucket with lifecycle rules
IntegrationGuardDuty reads CloudTrail for anomaly detection

CloudTrail captures every AWS API call made in the account — console, CLI, SDK, and service-to-service. This includes:

VPC Flow Logs

Active on both VPCs. Captures every network flow (accepted and rejected) with source/destination IP, port, protocol, bytes, and action. Used by:

Application-Level Logging

Log GroupContentRetention
/aws/ecs/trinity-beastAll application logs — BeastMain, BeastMirror, BeastLRS, BeastWebhook (single shared group, distinguished by CLUSTER_NODE in the log line)90 days
/aws/ecs/trinity-beast-syncBeastReconciler (nightly sync job)90 days
/aws/lambda/trinity-beast-receiptPayment processing90 days
/aws/lambda/trinity-beast-queued-writerUsage log batch inserts90 days
/aws/lambda/trinity-beast-email-senderAsync SES delivery90 days
/aws/lambda/tbi-ops-* (notify, self-heal, waf-action, honeypot-processor, bedrock-analyze, digest)AutoOps Lambda execution90 days
/aws/vpc/trinity-beast-flowlogsVPC Flow Logs, both VPCsLifecycle-managed (see Audit Trail below)

Forensic Commands (KCC)

Pre-built forensic routines for incident investigation:

11. Layer 10 — Identity & Access Management

Every service has its own IAM role with the minimum permissions required. No shared credentials. No wildcard policies. No cross-service privilege escalation paths.

Service Roles

RoleUsed ByKey PermissionsCannot Do
ecsTaskExecutionRoleECS task startupPull ECR images, write CloudWatch LogsCannot access Aurora, S3, or any data
ecsTaskRoleRunning ECS containersRead-only on exactly two secrets (named by full ARN), SQS send, S3 read/write, ElastiCache connectCannot write any secret, cannot read any other secret, cannot modify IAM, cannot access other accounts
tbi-autonomous-ops-roleThe 4 AutoOps Lambdas that read the admin keyECS update-service/stop-task, WAF update-ip-set, Bedrock invoke-model, SES send-email, SNS publish, SQS receive/delete, read the admin secret onlyCannot read the database or Stripe secret, cannot modify IAM, cannot access Aurora directly
tbi-autonomous-ops-noadmin-roletbi-ops-notify, tbi-ops-self-heal, tbi-ops-waf-actionThe same operational permissions, with no secret access of any kindCannot read any secret, cannot modify IAM
trinity-beast-queued-writer-roleQueued writer LambdaVPC access, Secrets Manager, SQS consumeCannot modify any infrastructure
trinity-beast-receipt-lambda-roleReceipt LambdaRead its own Stripe secret and the admin secret, SES send-emailCannot read the database secret, cannot modify infrastructure
tbi-translate-roleTranslation engine (worker + Lambdas)Bedrock invoke-model, S3 read/write, CloudFront invalidation, SES, SNSCannot access Aurora directly, cannot modify IAM

Least-Privilege Principles

Human Access

Single Operator: Cory is the sole human with AWS console/CLI access. There are no other IAM users. The root account has MFA enabled. Day-to-day operations use SSO via AWS Identity Center. ECS Exec provides emergency container access (IAM-protected, no admin key needed).

12. Layer 11 — Secrets & Key Management

Every secret this system uses lives in AWS Secrets Manager, and nowhere else. Not in code, not in an environment variable, not in the database, not in the cache. That became true for the last credential on 11 October 2026, when the admin key and the Stripe secret were moved out of the database and cache copies they had also been kept in.

The reason is worth stating plainly, because it is the lesson behind this whole layer: a secret kept in two places is only as safe as the least protected one. A copy in a database row or a cache field is readable by anything that can read rows or fields, it survives a rotation that only updated the original, and it can be exported into somewhere public without anyone noticing. One home means one thing to protect, one thing to rotate, and one place to audit.

What services carry instead is the name of a secret, never its value. DB_SECRET_NAME=trinity-beast-secrets in an environment variable is a label; reading it gets you nothing without an IAM role that is allowed to fetch that secret. The two ECS jobs that need the admin key get it through a task-definition secrets block, which means AWS injects the value at task start and it never appears in a task definition, a log or a process list.

Secrets Manager

SecretContentsRead By
trinity-beast-admin-secretsThe admin API key (ADMIN_KEY)The 4 ECS services, 6 Lambdas, the translation worker and sync job (task-definition secrets block), and the operator shell
trinity-beast-secretsAurora database credentials, Stripe keys, SES SMTP credentialsThe 4 ECS services (at boot) and the queued-writer Lambda
trinity-beast-receipt-secretsStripe keys for the receipt Lambda, deliberately isolated from the database credentialsThe receipt Lambda only
trinity-beast-ses-smtpSES SMTP credentialsThe email sender path
RDS-managed master secretThe Aurora master credential, managed by RDS itselfRDS

Who may read what is enforced by IAM, not by convention. The ECS services may read exactly two secrets and may write none — their policy names those two by full ARN, so a new secret added to the account is unreachable by them until someone grants it deliberately. The same principle split the AutoOps Lambdas on 11 October: the three that never need a key (tbi-ops-notify, tbi-ops-self-heal, tbi-ops-waf-action) now run on a role with no secret access at all, and the grant on the database-and-Stripe secret was removed from the whole AutoOps family, which 30 days of CloudTrail confirmed none of them had ever used.

Stripe Keys

Payment credentials follow the same one-home rule. Until 11 October 2026 the Stripe secret was also kept in a database parameter row and a cache field, and the servers read it from the cache. They now read it once at boot from AWS Secrets Manager and the copies are gone. The receipt Lambda keeps its own separate secret, so the component that handles payment webhooks never holds database credentials, and the component that talks to the database never needs the payment keys.

Admin API Key

The admin key (tbcc-admin-*) is the most sensitive application-level credential. Its security model:

Key Rotation Procedure

Because the key has one home, rotating it is one write. Everything else follows on its own, and the tool proves it rather than assuming it.

  1. Preflight — rotate-admin-key check reads the current state and refuses to go on if anything is wrong, including a stray copy anywhere it should not be.
  2. Rotate — a new 256-bit key is written as a new version of AWS Secrets Manager. It is generated in memory and never printed, logged, passed on a command line or stored in a file.
  3. Confirm — the tool sweeps every node twice: first that all of them accept the new key, then that all of them reject the old one. A rotation is not finished because a write succeeded; it is finished because the fleet was asked.
  4. Propagate — the servers refresh within 60 seconds, and immediately when they see a key they do not recognise. The 6 Lambdas pick it up within 30 seconds. The sync job reads it on its next run. The translation worker is redeployed by the tool, because its value is injected when the task starts. The operator shell fetches the current version every time it loads.
  5. Browser consoles — the one manual step: rotate-admin-key clipboard copies the key for pasting, without ever displaying it.

No part of this touches a Lambda environment variable, a task definition, a database row or a source file, because none of those holds the key.

Emergency Recovery

If a rotation leaves the admin API unreachable, recovery is a Secrets Manager operation and nothing else:

  1. rotate-admin-key rollback --yes — makes the previous version current again, then runs the same confirmation sweep.
  2. Or write a known value straight to the secret with a Secrets Manager PutSecretValue, which requires an IAM identity permitted to do it.

Editing the database no longer recovers anything, and that is deliberate. Older versions of this runbook said to connect to Aurora and fix a key row. Since 11 October 2026 the servers ignore that row entirely, so the edit would appear to succeed and change nothing — the most expensive kind of instruction to follow in an outage. The admin API also fails closed: a server with no key loaded refuses every administrative request rather than falling back to allowing them.

ECS Exec remains the side entrance, protected by IAM alone. All 4 services run with it enabled on purpose, so an operator with the right AWS identity can always get inside a container and read the live state, even when the application-level key is unusable. What changed is only what you do once you are in there: the fix lives in Secrets Manager, not in a table.

13. Security Summary & Posture Rating

The complete security posture of The Trinity Beast Infrastructure — assessed across all 11 layers.

Layer Status

LayerStatusMaturityNotes
1. Edge (CloudFront + Shield)ACTIVEProductionTLS 1.3, DDoS absorption, global CDN
2. WAF (2 WebACLs)ACTIVEProduction7 rules on ALB, 3 on CloudFront, dynamic block list
3. Application SecurityACTIVEProductionPer-key auth, per-tier rate limiting, input validation
4. Network IsolationACTIVEProduction2 VPCs, no public data endpoints, peering with SG rules
5. Data ProtectionACTIVEProductionEncryption at rest + in transit, private subnets only
6. Flame Path (UDP)ACTIVEProductionPer-packet auth, no amplification, NLB wire-speed
7. Detection (GuardDuty + CW)ACTIVEProduction37 alarms (us-east-2) + 1 (us-east-1) + GuardDuty ML. Anomaly detection retired 2026-08-26 — see Layer 7 note.
8. AutoOps AIACTIVEProductionSelf-heal, auto-block, Bedrock threat analysis every 5 min
9. Audit TrailACTIVEProductionCloudTrail multi-region, VPC flow logs both VPCs
10. IAMACTIVEProductionLeast-privilege, no cross-role trust, single operator
11. Secrets ManagementACTIVEProductionSecrets Manager, rotatable admin key, ECS Exec recovery

Attack Surface Summary

Entry PointProtection LayersRisk Level
Website (CloudFront)Shield → CloudFront WAF → S3 (static, no execution)Minimal
TCP API (ALB)Shield → ALB WAF → App Auth → Rate Limit → VPC → SGLow
UDP API (NLB)NLB → Per-Packet Auth → Rate Limit → No StateLow
Admin EndpointsWAF Rate Limit → Admin Key → IP Lockdown → RotationControlled
Data Layer (Aurora)No public endpoint → VPC peering only → SG → TLS → AuthMinimal
Data Layer (Valkey)No public endpoint → VPC only → TLS → AUTH tokenMinimal

What an Attacker Would Need

To reach the data layer, an attacker would need ALL of the following simultaneously:

  • Bypass CloudFront/ALB WAF (IP reputation, known exploits, rate limits)
  • Possess a valid API key (or the admin key — 2128 brute force space)
  • Bypass application-level rate limiting
  • Exploit a zero-day in the Go application to gain code execution
  • From inside the ECS container, discover the VPC peering route to 172.31.0.0/16
  • Obtain Aurora credentials from Secrets Manager (requires IAM role assumption)
  • Connect to Aurora on port 5432 with valid TLS and credentials

Each step is independently difficult. Combined, they represent a near-impossible chain. And at every step, GuardDuty, CloudTrail, and the AutoOps AI are watching.

Posture Rating

Overall Security Posture: STRONG

11 active defense layers. Zero public data endpoints. AI-powered threat detection. Automated self-healing. Single-operator access model. Encryption everywhere. Complete audit trail. The infrastructure is production-ready from a security perspective.

Assessment by Kiro — September 2, 2026. Based on current deployed configuration, not theoretical design.