Configuration
This document provides an overview of the key dependencies and external services used in the platform.
Dependencies
Setup for external services:
- Twilio - Used to send SMS messages containing important notifications. These include alerts when produce is nearing the end of its shelf life, when a product is sold on the marketplace, or when inviting users to join the app.
- Sentry - Used for real-time error tracking and performance monitoring across both frontend and backend. Sentry helps developers quickly identify, triage, and resolve issues in production.
- Paystack - Integrated as the payment gateway for handling financial transactions. It enables secure payment processing for marketplace sales and other financial operations within the platform.
- Sendgrid - Used for sending transactional emails, such as operator notifications and invitations to join the app. It ensures reliable email delivery and provides analytics for engagement tracking.
All credentials for these services should be treated as deployment-time secrets. Checked-in configuration files should contain placeholders only.
Sensor Provider Settings
Inficold and Ecozen use server-side credentials. These are Base API settings, read by the web and Celery containers. They aren't mobile app settings: the app never receives them, and setting them in the mobile environment has no effect.
| Variable | Default | Purpose |
|---|---|---|
INFICOLD_API_URL |
https://infilog.com/api/coldtivate/get_scr_data.php |
Inficold's official history endpoint. Configurable so mock-server and staging runs can point elsewhere. |
INFICOLD_API_TOKEN |
(empty) | Secret. Coldtivate's bearer token for the Inficold history API. Required for Inficold setup and polling. |
ECOZEN_CLIENT_ID |
(empty) | Coldtivate's Ecozen OAuth2 client ID. Required for Ecozen connection tests and polling. Save verifies the successful-test ticket without requesting a token. |
ECOZEN_CLIENT_SECRET |
(empty) | Secret. Coldtivate's Ecozen OAuth2 client secret. |
If a provider's settings are empty, only that provider's setup and polling fail, with a configuration error. The rest of the platform is unaffected.
Ecozen OAuth2
Ecozen data requests use OAuth2 client credentials. The endpoints are fixed in the code:
- Token endpoint:
https://openid.ecozen.ai/realms/ecozen/protocol/openid-connect/token - Graph endpoint:
https://apis.ecozen.ai/dashboard/v3/ecofrost/graph/{machine_id}
The Base API requests a token with a form-encoded client_credentials grant (client_id, client_secret, grant_type=client_credentials), then sends Authorization: Bearer <access_token> on graph requests.
- Token reuse:
- Tokens are shared through the Base API's Redis cache until their reported expiry, minus a safety margin.
- One worker renews a token at a time, and a token is refreshed at most once if a graph request is rejected with
401. - A token without a reported expiry isn't shared.
- No stored tokens: tokens are never saved to the database, logs or app responses. Cache keys are HMACs, never the client ID or secret.
- Rate limits: a
429starts a cooldown shared by all workers, honouringRetry-After. See Ecozen rate limits.
The following optional environment variables are read directly by ecozen.py, which owns their defaults; they are not registered in Django settings. They apply only to Ecozen. The defaults are cautious placeholders, not confirmed Ecozen limits:
| Variable | Default | Purpose |
|---|---|---|
ECOZEN_MAX_CONCURRENT_REQUESTS |
2 |
Graph requests in flight per client across all workers. 0 disables the limit. |
ECOZEN_CONCURRENCY_RETRY_SECONDS |
60 |
When polls retry after finding every request slot busy. |
ECOZEN_RATE_LIMIT_BACKOFF_SECONDS |
60 |
First cooldown after a 429 without a usable Retry-After. It doubles per consecutive 429. |
ECOZEN_RATE_LIMIT_MAX_BACKOFF_SECONDS |
900 |
Longest such backoff. |
ECOZEN_POLL_RESCHEDULE_JITTER_SECONDS |
120 |
Random spread added when polls are rescheduled after a rate limit or cooldown. |
ECOZEN_POLL_MAX_RESCHEDULE_SECONDS |
3000 |
Longest single poll reschedule. Keep it below the Celery broker's visibility timeout (1 hour by default). Longer cooldowns become several shorter waits. |
The coordination needs the shared Redis cache (REDIS_*) to be reachable from the web and Celery containers.
Secret handling
- Keep
INFICOLD_API_TOKENandECOZEN_CLIENT_SECRETin deployment secret storage. Checked-in dotenv files contain empty placeholders only. - Both settings are read on every token request or poll, so a rotated value takes effect for the next request after the web and Celery containers restart. Polling history is kept.
- Never paste real tokens, client secrets, portal credentials, cookies or captured sessions into issues, logs or documentation.
For setup and troubleshooting, see the Ecozen Integration Guide and the Inficold Integration Guide.
Trusted Proxy Configuration
The Base API uses NUM_PROXIES to determine the client IP used by IP-based rate limits.
The default value of 2 matches the hosted production path:
Set the value to the number of trusted proxy hops in the deployment. For example, a direct local connection to Django has no trusted proxies, while a tunnel placed in front of the standard stack adds another hop. Do not copy the production default blindly into a topology with a different proxy chain: selecting the wrong address from X-Forwarded-For can make rate limits ineffective or cause unrelated clients to share a throttle bucket.