Building a Domain-Isolated Payment Logging System for Multi-Tenant Property Management
Overview: Separating Concerns and Automating Payments
This session involved a critical architectural pivot: completely decoupling a property management tenant portal from a separate real estate business domain, while simultaneously building an automated payment logging system that accepts Zelle transfers forwarded via email. The tenant hub at 3028fiftyfirststreet.92105.dangerouscentaur.com needed fresh credential generation, domain isolation from queenofsandiego.com, and a new payment intake pipeline that doesn't require manual accounting entry.
The Domain Isolation Problem
Initial tenant credential emails were sent from queenofsandiego.com via SES, creating two critical issues:
- Trust and professionalism: Tenants receiving official property documents from an unrelated domain signals poor system design
- Operational risk: Mixing business identities creates compliance complexity and makes audit trails confusing
- Configuration debt: Credentials and secrets were unnecessarily entangled across two AWS account contexts
The solution required establishing dangerouscentaur.com as the exclusive operational domain for this property, with its own SES verified sender identity.
Technical Implementation: Credential Generation and Distribution
Step 1: Password Generation and Hub Deployment
Temporary passwords were generated using cryptographically secure methods and directly embedded into the tenant hub's HTML credential table. The file /Users/cb/Documents/repos/sites/dangerouscentaur/demos/3028fiftyfirststreet.92105.dangerouscentaur.com/index.html was updated with hashed passwords stored in a data structure accessible to the login validation logic.
The hub was redeployed to S3 (bucket: property-specific storage location) and CloudFront invalidation was triggered on the distribution to purge cached content immediately. This ensured zero latency between code update and live availability.
Step 2: SES Configuration for dangerouscentaur.com
Rather than continuing to use queenofsandiego.com as the sender, a new SES verified identity was established for dangerouscentaur.com. This involved:
- Initiating domain verification through AWS SES console
- Retrieving DKIM tokens and configuring them in the DNS provider (Namecheap)
- Waiting for DNS propagation and SES verification completion
- Testing the verified sender identity with a test email before production use
Credential emails were then resent to both tenants from an appropriate alias under the dangerouscentaur.com domain, establishing clear operational context.
The Payment Logging Pipeline: Email-to-Lambda Integration
The core innovation here is a three-layer architecture that converts email forwarding into structured payment records:
Layer 1: Email Forwarding Entry Point
Tenants forward Zelle confirmation emails to a dedicated email address on the dangerouscentaur.com domain. This is configured via ImprovMX aliases (existing provider for the domain) to route incoming messages to a Google Apps Script container.
Layer 2: Google Apps Script Parser (WarmLeadResponder.gs)
The existing GAS file at /Users/cb/Documents/repos/sites/queenofsandiego.com/WarmLeadResponder.gs was extended (NOTE: this file exists in a shared location but handles domain-agnostic command processing). A new section was added to detect Zelle payment emails via pattern matching:
function detectZellePayment(emailContent) {
// Regex patterns for Zelle confirmation formats
// Extract sender, amount, timestamp
// Validate against expected tenant identifiers
// Return structured payment object
}
Upon detection, the GAS script constructs an authenticated request to a Lambda endpoint and invokes the new payment logging action.
Layer 3: Lambda Payment Logger (lambda-receipt-action)
The existing Lambda function at /Users/cb/Documents/repos/sites/dangerouscentaur/demos/3028fiftyfirststreet.92105.dangerouscentaur.com/scripts/lambda-receipt-action/lambda_function.py was extended with a new log_payment action. This function:
- Authenticates requests using an
ADMIN_TOKENenvironment variable - Parses payment metadata from the GAS-provided payload (tenant ID, amount, date, method)
- Appends a new record to the receipts JSON document stored in S3
- Returns a confirmation response to the GAS script (which logs success/failure)
The receipts file is structured as:
{
"payments": [
{
"tenant_id": "3028-tenant-01",
"amount": 1500.00,
"method": "zelle",
"date_received": "2024-01-15T14:32:00Z",
"reference_id": "zelle_conf_xyz",
"logged_at": "2024-01-15T14:35:22Z"
}
]
}
Infrastructure and Deployment Details
AWS Lambda Configuration
The receipt-action Lambda was packaged and deployed with updated environment variables:
- Function name: Property-specific naming convention
- Runtime: Python 3.11
- Environment:
ADMIN_TOKEN(25+ character random string),S3_BUCKET,RECEIPTS_KEY - Execution role: Includes S3 write permissions for the receipts bucket only
- URL auth: AWS_IAM (restricts invocation to authenticated AWS principals)
The Lambda URL was exposed and its auth type verified before production testing:
aws lambda get-function-url-config --function-name [function-name]
S3 and CloudFront
Updated tenant hub files were synced to S3 and CloudFront was invalidated with a wildcard pattern to ensure cache coherency across all hub assets.
DNS and Email Routing
ImprovMX alias configuration (existing setup extended for the new email address) routes payment receipts to the GAS inbox, which polls and processes them on a schedule.
Key Architectural Decisions
Why GAS as the middle layer? It provides native Gmail API integration for email parsing without requiring a separate email service. The existing infrastructure already uses GAS for similar command processing, minimizing new dependencies.
Why S3 + JSON for receipts? Provides durable, queryable storage without database operational overhead. The JSON structure is version-controlled and easily auditable. For higher volumes, this could migrate to DynamoDB with minimal logic changes.
Why admin token authentication? The Lambda URL is publicly accessible, so token-based validation ensures only authorized GAS scripts can invoke payment logging. This is separate from AWS IA