# 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](https://github.com/Infisical/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_ ``` Example: `CAST_API_KEY_q5LZDBHiJ9BsY9Vge5De` #### 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