cast-ghl-plugin/FUTURE_DEV.md
Head of Product & Engineering 65e9c6f408
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
fix: remove real location ID from docs, add trivyignore for false positives
Replace the real location ID in FUTURE_DEV.md example with a placeholder
to avoid trivy-secrets false positive. Also sanitize the cast_api_key
comment in admin.go and add .trivyignore to exclude documentation files
from the secret scanner.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-06 14:16:56 +02:00

3.4 KiB

Future Development Notes

This document tracks planned improvements, technical debt with business impact, and migration paths for features currently implemented with known limitations.


Upgrade: Per-location Cast API keys from MongoDB → Infisical

Current state (Option A)

Per-location Cast API keys (cast_api_key) and sender IDs (sender_id) are stored in MongoDB alongside OAuth tokens in the cast-ghl.oauth_tokens collection.

Limitation: Secret material (Cast API keys) stored in the same database as operational data. If MongoDB is compromised, all per-location Cast credentials are exposed. MongoDB auth and TLS mitigate this but do not eliminate the risk.

Target state (Option C)

Use Infisical as the secrets backend for per-location Cast API keys. Infisical is open-source, self-hostable, and provides secret versioning, audit logs, access policies, and dynamic secrets.

Migration plan

1. Deploy Infisical (self-hosted or Infisical Cloud)

  • Recommended: self-host on the same Vultr instance or a dedicated secrets VM
  • Create a project: cast-ghl-provider
  • Create an environment: production
  • Create a machine identity (service account) for the bridge service

2. Secret naming convention

Store each location's API key as a secret named:

CAST_API_KEY_<LOCATION_ID>

Example: CAST_API_KEY_myLocationId123

3. Code changes in the bridge

  • Add INFISICAL_CLIENT_ID and INFISICAL_CLIENT_SECRET env vars to config
  • Add Infisical Go SDK: github.com/infisical/go-sdk
  • Create internal/secrets/infisical.go — wraps the SDK with a GetLocationAPIKey(locationID) (string, error) method and an in-process cache (TTL ~60s to avoid hammering the API)
  • In processOutbound: call secrets.GetLocationAPIKey(locationID) instead of reading from the token record
  • The cast_api_key field in TokenRecord can be kept as a fallback during migration, then removed

4. Admin API changes

  • PUT /api/admin/locations/{locationId}/config should write the API key to Infisical (not MongoDB)
  • GET endpoints should read from Infisical and mask the returned value

5. Migration of existing keys

  1. For each location with a cast_api_key in MongoDB, write it to Infisical via the admin API
  2. Verify the bridge reads the key correctly from Infisical
  3. Clear cast_api_key from MongoDB records
  4. Remove the MongoDB field once fully migrated

6. MongoDB security hardening (do regardless of Infisical migration)

  • Ensure MONGO_URI uses authentication: mongodb://user:pass@host:27017/cast-ghl?authSource=admin
  • Enable TLS: append ?tls=true&tlsCAFile=/path/to/ca.pem to the URI
  • Restrict MongoDB network access to the bridge server IP only (Vultr firewall rules)
  • Enable MongoDB audit logging for the cast-ghl database

Other Future Items

Inbound SMS (2-way) — Cast SIM gateway webhook

  • Tracked in CASA-61
  • Requires Cast SIM gateway to support outbound webhooks
  • Bridge handler stub already exists (PostInboundMessage in internal/ghl/api.go)
  • Need to agree on Cast webhook payload format and DID → locationId mapping

Token refresh proactive scheduling

  • Currently tokens are refreshed on-demand (when expired at webhook time)
  • A background goroutine that refreshes tokens 1 hour before expiry would reduce latency on the first webhook after a 24-hour token lifetime