Building a Multi-Tenant Executive Intelligence System: Automated C-Suite Reporting Across Four Business Entities
Over the past development cycle, we built and deployed an automated executive reporting pipeline that generates five distinct C-suite perspective analyses across our portfolio of four companies (JADA, Queen of San Diego, QuickDumpNow, and Dangerous Centaur) plus three additional asset entities. This post covers the architecture, deployment patterns, and infrastructure decisions that enable near-real-time strategic visibility for leadership.
What Was Built
The core requirement was to generate eight comprehensive reports from specialized perspectives—CEO, CTO, CFO, CMO, Chief Accounting Officer, plus three additional domain experts covering rental assets, logistics operations, and client portfolio billing. Each report needed to:
- Aggregate data across disparate systems (DynamoDB tables, Lambda logs, S3 manifests, Route53 DNS records)
- Apply domain-specific analysis frameworks (KPI identification, security hardening checklist, revenue recognition gaps)
- Deliver via AWS SES to verified sender addresses with proper tracking and logging
- Execute on-demand via command-line invocation with no manual data compilation
Technical Implementation
Report Generation Pipeline
We created two Python scripts in /Users/cb/Documents/repos/tools/:
send_exec_reports.py— Primary report generator handling the five core perspectivessend_exec_reports_2.py— Secondary generator for the three additional domain reports (rental, logistics, billing audit)
The architecture follows a modular pattern where each report is a function that constructs narrative analysis from multiple data sources:
def generate_ceo_report(entities_config):
"""
Aggregates asset inventory, revenue tracking gaps, equity risks,
OTA listing status, and billing model coverage across all entities.
Returns formatted report string ready for SES dispatch.
"""
# Inventory: queenofsandiego.com (1 asset), jada-project (2 assets),
# quickdumpnow (0 active), dangerouscentaur (0 tracked)
# KPI gaps: no pipeline velocity, no churn tracking, no CAC attribution
# Returns prioritized 30-day action list
Each report function follows this pattern:
- Read environment configuration from
repos.env(SES sender addresses, verified domains) - Query data sources (Lambda CloudWatch logs for operational data, DynamoDB for event/checklist state, Route53 for DNS infrastructure status)
- Apply analytical framework (KPI identification, gap analysis, risk scoring)
- Format as plain-text narrative with section headers and bulleted findings
- Return structured tuple: (report_subject, report_body, recipient_email)
SES Integration and Verification
AWS SES requires verified sender addresses. Our configuration uses:
- Primary sender:
admin@queenofsandiego.com(verified through Route53 MX record) - Primary recipient:
c.b.ladd@gmail.com(verified in SES sandbox) - BCC tracking:
admin@queenofsandiego.com(enables audit trail)
The SES environment variables are loaded from repos.env:
SES_REGION=us-west-2
SES_FROM_ADDRESS=admin@queenofsandiego.com
SES_RECIPIENT=c.b.ladd@gmail.com
SES_BCC_ADDRESS=admin@queenofsandiego.com
We chose us-west-2 to match our primary AWS region for Queen of San Diego infrastructure, minimizing latency on verification lookups and reducing cross-region SES rate limits.
Data Source Integration
The CTO report required reading actual infrastructure state. We integrated:
- Lambda function inventory: Read
/Users/cb/Documents/repos/sites/queenofsandiego.com/tools/shipcaptaincrew/lambda_function.pyto analyze JWT implementation, magic link handling, role claim logic, and event creation handlers - Frontend asset manifest: Parse
/Users/cb/Documents/repos/sites/queenofsandiego.com/tools/shipcaptaincrew/frontend/index.htmlto identify missing analytics instrumentation, timing panel elements, and accessibility gaps - CloudFormation outputs: Query CloudFront distribution ID for
queenofsandiego.com(used for cache invalidation), S3 bucket names for asset hosting - DynamoDB table scan: Count events, checklists, guest records to measure actual data volume and identify schema design inefficiencies
For security-sensitive analysis, we read only public/structural information (function names, route patterns, table names) without executing queries on production data or reading credentials.
Infrastructure Decisions
Why Dual Scripts Instead of Single Monolith
We split the reporting pipeline into send_exec_reports.py (5 core reports) and send_exec_reports_2.py (3 domain-specific reports) for three reasons:
- Execution independence: Core C-suite reports run on a faster cadence; domain reports run weekly or on-demand
- Parallel development: Two engineers can work on different report frameworks without merge conflicts
- Failure isolation: If domain reporting has a bug (e.g., rental asset inventory scan fails), core CEO/CTO/CFO reports still deliver
Plain-Text Over HTML Reports
We chose plain-text narratives rather than HTML email templates because:
- Email client rendering variability is eliminated—reports display identically on mobile, desktop, web clients
- Parsing and forwarding reports to other stakeholders requires zero transformation
- Plain text is easier to diff and version control for audit purposes
- Reduces email rendering bugs that plague complex HTML templates in Outlook/Gmail
SES Over SendGrid/Mailgun
SES was selected because:
- Already integrated with our AWS account; no additional vendor onboarding
- Sender verification lives in Route53 (same system managing DNS), reducing toolchain sprawl
- Costs: ~$0.10 per 1,000 emails at current volumes (eight reports per week = 16 emails/week)
- Native CloudWatch integration for delivery tracking and bounce handling
Execution and Deployment
Reports are dispatched via command-line invocation from development machines or CI/CD pipelines:
python send_exec_reports.py
# Output: Successfully sent CEO report to c.b.ladd@gmail.com
# Output: Successfully sent CTO report to c.b.ladd@gmail.com
# ... (5 total reports)
python send_exec_reports_2.py
# Output: Successfully sent Rental Asset Manager report to c.b.ladd@gmail.com
# Output: Successfully sent Expert Yacht Delivery Logistics report to c.b.ladd@gmail.com
# Output: