Building a Self-Contained Payment Logging System: Divorcing Tenant Infrastructure from Corporate Branding
What Was Done
We implemented a complete tenant portal and payment logging infrastructure isolated within the dangerouscentaur.com domain, eliminating cross-domain email sends that were tying tenant communications to corporate branding. The system now supports:
- Tenant hub portal at
3028fiftyfirststreet.92105.dangerouscentaur.comwith credential management - Zelle payment email forwarding integrated into a Google Apps Script command pipeline
- AWS Lambda-based payment logging with admin token protection
- SES domain verification and email alias configuration for
dangerouscentaur.com - CloudFront cache invalidation for instant credential updates
Technical Details
Portal Infrastructure and Credential Management
The tenant hub lives in /Users/cb/Documents/repos/sites/dangerouscentaur/demos/3028fiftyfirststreet.92105.dangerouscentaur.com/. The index.html file contains embedded tenant credentials that are regenerated and redeployed whenever tenants need access. The workflow:
1. Generate fresh temporary passwords (cryptographically random, base64-encoded)
2. Hash passwords using PBKDF2 (10,000 iterations, SHA-256)
3. Update index.html with new hashed credentials
4. Deploy to S3 bucket backing the CloudFront distribution
5. Invalidate CloudFront cache for immediate propagation
6. Send credentials via SES from dangerouscentaur.com domain
The portal serves as both the web interface and the credential store. When tenants log in, the JavaScript authentication logic in index.html validates input against the embedded hashed credentials. This eliminates the need for a separate authentication database while keeping credentials opaque in transit.
Payment Logging System Architecture
The payment logging system consists of two Lambda functions deployed within the dangerouscentaur infrastructure:
lambda-receipt-action: Handles payment submission with admin token validation. Located at/scripts/lambda-receipt-action/lambda_function.pylambda-email-parser: Processes inbound Zelle forwarding emails. Located at/scripts/lambda-email-parser/lambda_function.py
The receipt-action Lambda maintains a receipts.json file in S3 that tracks all payments. The Lambda function signature:
POST /log_payment
Headers: Authorization: Bearer {ADMIN_TOKEN}
Body: {
"tenant_id": "3028_51st",
"amount": 1500.00,
"date": "2024-01-15",
"method": "zelle",
"reference": "email-message-id"
}
The environment variable ADMIN_TOKEN is set on the Lambda function itself and validated before any database writes occur. This keeps the token out of source control while enabling the GAS pipeline to authenticate requests.
Google Apps Script Command Pipeline
The WarmLeadResponder.gs file in the queenofsandiego.com project handles incoming emails but now includes conditional logic to detect Zelle payment forwards and route them to the dangerouscentaur infrastructure:
if (emailSubject.includes("Zelle") || emailBody.includes("Zelle payment")) {
// Extract payment details from email body
// Call dangerouscentaur Lambda with admin token
// Log response for audit trail
}
This approach keeps the centralized email handler (which processes multiple domains) but adds tenant-specific routing logic. When a Zelle forward arrives, the GAS script parses the email for transaction details (amount, timestamp, recipient), formats it into the Lambda payload, and submits it with the admin token.
Infrastructure Changes
SES Domain Verification
Initiated SES verification for dangerouscentaur.com to ensure tenant emails don't originate from corporate domains. The verification process generated DKIM tokens for DNS configuration at the domain registrar (Namecheap). This prevents recipient spam filters from flagging tenant communications as corporate mass-mail.
Email Alias Configuration
Created ImprovMX aliases for dangerouscentaur.com to provide a receiving endpoint for Zelle forwards. The alias routes incoming payment emails to a monitored inbox that feeds into Google Apps Script's email trigger. This eliminates manual copy-paste of payment details.
CloudFront and S3 Setup
The tenant portal is served via CloudFront distribution (obtained via AWS CLI) backed by S3. When credentials are updated:
aws s3 cp index.html s3://dangerouscentaur-sites/demos/3028fiftyfirststreet.92105/
aws cloudfront create-invalidation --distribution-id {DIST_ID} --paths "/*"
The invalidation ensures tenants immediately receive updated credentials without waiting for cache TTL expiration.
Key Architectural Decisions
Why Embedded Credentials in HTML
Rather than maintaining a separate user database, credentials are embedded as hashed values in the deployed HTML. This approach:
- Eliminates database operational overhead for a small number of tenants
- Makes credentials non-extractable from network traffic (HTTPS + hashing)
- Allows instant credential rotation by redeploying HTML
- Keeps authentication logic client-side, reducing Lambda invocations
Why Admin Token on Lambda Instead of GAS
The Lambda function validates an admin token rather than exposing it in GAS source code. This pattern:
- Keeps the secret in AWS environment variables, not in version control
- Allows token rotation without redeploying GAS code
- Enables audit logging of payment submissions by Lambda
- Isolates infrastructure credentials from application logic
Why Domain Separation Matters
Divorcing tenant infrastructure from queenofsandiego.com:
- Prevents email authentication issues (SPF/DKIM) from one domain affecting another
- Allows future multi-property tenant systems without cross-contamination
- Improves security isolation if one domain is compromised
- Enables independent SES sending limits per domain
Deployment Commands Reference
# Update credentials and redeploy portal
python3 generate_tenant_creds.py --property 3028_51st --output index.html
aws s3 cp index.html s3://dangerouscentaur-sites/demos/3028fiftyfirststreet.92105/
aws cloudfront create-invalidation --distribution-id XXXXX --paths "/*"
# Send credential emails via SES
aws ses send-email --from creds@dangerouscentaur.com \
--to tenant@example.com \
--subject "Tenant Portal Credentials" \
--html file://credential-email.html
# Deploy updated Lambda
cd scripts/lambda-receipt-action
pip install -r requirements.txt -t .
zip -r function.zip .
aws lambda update-function-code --function-name log-payment \
--zip-file fileb://function.zip
# Test payment logging
curl