2.0 KiB
2.0 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
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:
{
"fc.checkout_v2": { "enabled": false, "variant": "off" },
"fc.search_ranking_v3": { "enabled": true, "variant": "on", "payload": { "model": "v3" } }
}
Request (App -> BFF)
{
"environment": "production",
"keys": ["fc.checkout_v2", "fc.search_ranking_v3"],
"context": {
"subjectType": "customer",
"subjectId": "cust_123",
"storeId": "store_001",
"platform": "ios",
"appVersion": "2.3.1",
"attributes": {
"city": "Belo Horizonte",
"tier": "gold"
}
}
}
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": {
"checkoutV2": true,
"searchRankingV3": "off"
},
"raw": {
"fc.checkout_v2": {
"enabled": true,
"variant": "on",
"payload": null,
"reason": "rollout"
}
}
}
Quando o upstream falha (ex.: 429, 500, timeout), o BFF devolve fallback com defaults estáticos.
Execução local
cd feature-control-bff
FEATURE_CONTROL_MODULE_TOKEN="550e8400-e29b-41d4-a716-44665544000b" npm start
Testes
cd feature-control-bff
npm test