Real key pattern is at.<domain>.<name> (e.g. at.ios.only, at.promo). The fc. prefix in the BFF README and API_Mobile_App.md was incorrect. - API_Mobile_App.md: updated request keys, response raw examples, flag table, and Swift usage examples to at. prefix - API_Mobile_App.md: clarified that app uses raw["at.key"] not simplified flags object (FeatureFlagsState.isEnabled reads raw) - feature-control-bff/README.md: updated DEFAULTS_JSON example, request keys, response flags/raw examples, added note about raw usage
2.7 KiB
2.7 KiB
Feature Control BFF
BFF mínimo para expor flags ao app sem expor Atomenta-Token no cliente.
Endpoint
POST /feature-control/bootstrapPOST /feature-control/telemetry/exposureGET /health
Notificações
No momento este BFF cobre apenas Feature Control (bootstrap + exposure).
Para notificações segmentadas por audiência (todos, feature:fc.ios), precisamos adicionar o contrato de endpoint de notificações do Atomenta para integrar no app.
Variáveis de ambiente
PORT(default:8787)ATOMENTA_ORIGIN(default:https://atomenta.com.br)FEATURE_CONTROL_MODULE_TOKEN(ouATOMENTA_FEATURE_CONTROL_MODULE_ID) obrigatórioFEATURE_CONTROL_ENVIRONMENT(default:production)FEATURE_CONTROL_CACHE_TTL_MS(default:60000)FEATURE_CONTROL_TIMEOUT_MS(default:2000)FEATURE_CONTROL_DEFAULTS_JSON(opcional, JSON com defaults de fallback)
Exemplo de FEATURE_CONTROL_DEFAULTS_JSON:
{
"at.ios.only": { "enabled": true, "variant": "on" },
"at.android.only": { "enabled": true, "variant": "on" },
"at.promo": { "enabled": true, "variant": "on" },
"at.city.aguai": { "enabled": true, "variant": "on" }
}
Request (App -> BFF)
{
"environment": "production",
"keys": ["at.ios.only", "at.android.only", "at.promo", "at.city.aguai"],
"context": {
"subjectType": "customer",
"subjectId": "cust_123",
"storeId": "store_001",
"platform": "ios",
"appVersion": "2.3.1",
"attributes": {
"city": "Aguaí"
}
}
}
Se o app enviar Authorization: Bearer <JWT>, o BFF tenta extrair subjectId do JWT (sub/customerId/id) quando context.subjectId não vier.
Response (BFF -> App)
{
"ok": true,
"source": "live",
"configVersion": 7,
"evaluatedAt": "2026-04-16T12:00:00.000Z",
"flags": {
"atiosonly": true,
"atandroidonly": false,
"atpromo": true,
"atcityaguai": true
},
"raw": {
"at.ios.only": {
"enabled": true,
"variant": "on",
"payload": null,
"reason": "rollout"
},
"at.promo": {
"enabled": true,
"variant": "on",
"payload": null,
"reason": "rollout"
}
}
}
O app Swift usa o campo
rawindexado pela chave original (ex:raw["at.promo"]). O campoflagsé uma versão simplificada gerada mecanicamente (pontos removidos).
Quando o upstream falha (ex.: `429`, `500`, timeout), o BFF devolve `fallback` com defaults estáticos.
## Execução local
```bash
cd feature-control-bff
FEATURE_CONTROL_MODULE_TOKEN="550e8400-e29b-41d4-a716-44665544000b" npm start
Testes
cd feature-control-bff
npm test
Autor: Daniel Arantes Loverde