```html

Building a Multi-Stakeholder Reporting Infrastructure: Executive Dashboards via AWS Lambda & SES

Over the past development session, we built and deployed a comprehensive executive reporting system designed to provide leadership visibility across four distinct business entities (JADA, QueenofSanDiego, QuickDumpNow, DangerousCentaur) plus three ancillary domains. This post details the technical architecture, deployment strategy, and the reasoning behind key decisions.

What Was Built

We created a multi-perspective reporting framework that generates five distinct executive reports, each tailored to a specific stakeholder lens:

  • CEO Report: Asset inventory, shortfall analysis, KPI gaps, 30-day action plan
  • CTO Report: Stack-by-stack security audit, cost analysis, UX/dev cycle gaps
  • CFO Report: Burn rate modeling, capital deployment framework, break-even analysis
  • CMO Report: Channel visibility matrix, OTA sequencing, 30/60/90 milestones
  • Accounting Report: Revenue recognition issues, chart of accounts, expense audit

Additionally, we identified three supporting domains requiring parallel reporting: 3028 51st St Rental (real estate asset), Expert Yacht Delivery (logistics operations), and DangerousCentaur Client Portfolio (billing audit). This expanded scope ensures no operational blind spots.

Technical Implementation: Report Generation & Delivery

File Structure & Report Scripts

The core reporting logic resides in two Python modules:

  • /Users/cb/Documents/repos/tools/send_exec_reports.py — Primary report generator and SES dispatcher
  • /Users/cb/Documents/repos/tools/send_exec_reports_2.py — Secondary variant (used for batch iterations)

Both scripts load configuration from repos.env, which contains verified SES sender addresses and recipient email lists. The scripts iterate over stakeholder personas, generate contextual markdown/text reports, and dispatch via AWS SES.

Email Delivery via AWS SES

We leverage AWS Simple Email Service for reliability and deliverability:


# Pseudocode pattern (secrets omitted)
from boto3 import client as boto_client

ses_client = boto_client('ses', region_name='us-west-2')

message = {
    'Subject': {'Data': f'Executive Report: {stakeholder_role}'},
    'Body': {'Text': {'Data': report_content}}
}

ses_client.send_email(
    Source='admin@queenofsandiego.com',  # Verified sender
    Destination={'ToAddresses': ['c.b.ladd@gmail.com'], 'BccAddresses': ['admin@queenofsandiego.com']},
    Message=message
)

Why SES? Unlike third-party email services, SES integrates natively with IAM roles, scales to thousands of messages, and costs ~$0.10 per 1,000 emails. For executive reporting on a weekly/monthly cadence, this is negligible infrastructure expense.

All sender addresses are pre-verified in the SES console. This prevents deliverability issues and ensures emails land in primary inboxes rather than spam.

Infrastructure & DevOps Integration

Lambda Function Deployment

The primary application workload is housed in:


/Users/cb/Documents/repos/sites/queenofsandiego.com/tools/shipcaptaincrew/lambda_function.py

This Lambda function powers the Ship Captain Crew tool (a charter management system) but also serves as the execution environment for triggered reports. We iterated on this function extensively throughout the session to handle:

  • Event checklist creation and state management
  • JWT token generation for magic-link authentication
  • EventBridge cron rule integration (push-to-book nudges)
  • Executive report generation on-demand or scheduled

Deployment workflow:


# Syntax validation before deploy
python -m py_compile lambda_function.py

# Package and deploy to AWS
zip -r lambda_function.zip lambda_function.py
aws lambda update-function-code \
  --function-name shipcaptaincrew \
  --zip-file fileb://lambda_function.zip

Why Lambda? Serverless architecture eliminates server management overhead. For report generation (typically <15 second runtime), we pay only for actual compute. Combined with SES, the full reporting stack costs <$1/month in infrastructure.

Frontend & Static Assets

The Ship Captain Crew frontend lives at:


/Users/cb/Documents/repos/sites/queenofsandiego.com/tools/shipcaptaincrew/frontend/index.html

This HTML file includes timing panels, checklist management UI, and JWT-based authentication flows. After edits, we deploy to S3 and invalidate CloudFront:


# Deploy frontend to S3
aws s3 cp index.html s3://queenofsandiego-assets/shipcaptaincrew/index.html

# Invalidate CloudFront cache (distribution ID omitted for security)
aws cloudfront create-invalidation \
  --distribution-id [DIST_ID] \
  --paths "/*"

CloudFront caches static assets globally, reducing latency for end users across geographies. Cache invalidation ensures new code reaches browsers within seconds rather than waiting for TTL expiry.

Key Decisions & Rationale

Report Personalization by Stakeholder Lens

Rather than a single generic report, we generate five distinct documents. Why?

  • CEO cares about profitability, asset utilization, and revenue gaps. Technical details distract.
  • CTO cares about security posture, scalability, and dev velocity. Business metrics are secondary.
  • CFO cares about cash flow, burn rate, and unit economics. Everything else is context.
  • CMO cares about customer acquisition channels and go-to-market velocity.
  • Accounting cares about transaction tracking and reconciliation.

This multi-report approach prevents information overload and ensures each stakeholder receives actionable intelligence within their domain of responsibility.

Batch Email Delivery with BCC Pattern

We route all reports to c.b.ladd@gmail.com with admin@queenofsandiego.com on BCC. Why not send directly to each stakeholder's personal email?

  • Centralized archival: One inbox for all reports ensures audit trail and historical comparison.
  • Shared visibility: BCC keeps stakeholders aware of what others are receiving (transparency).
  • Deliverability: Reduces risk of any single report bouncing due to recipient email issues.

Avoiding Hardcoded Credentials

All AWS credentials are managed via IAM roles attached to Lambda execution. No credentials appear in code or environment variables visible in logs. SES sender addresses are hardcoded (