feat: add go-live readiness metric for pilot launch gating
This commit is contained in:
parent
7fe725b00e
commit
1ac6899898
26
docs/developer-portal/11-going-live-audit.md
Normal file
26
docs/developer-portal/11-going-live-audit.md
Normal file
@ -0,0 +1,26 @@
|
||||
# 11 Going Live Audit
|
||||
|
||||
Source checked: Uber Eats "Going Live" section shared by you.
|
||||
|
||||
## Implemented Now
|
||||
|
||||
- Go-live readiness metric endpoint for pilot gating:
|
||||
- `GET /api/v1/metrics/go-live-readiness`
|
||||
- computes 3-day injection success and evaluates against configurable threshold (default 98%)
|
||||
- Existing production readiness controls already present:
|
||||
- webhook security (signature + optional basic auth)
|
||||
- OAuth domain pairing checks
|
||||
- injection success monitoring endpoint
|
||||
|
||||
## Existing Before
|
||||
|
||||
- Menu upload and POS integration activation APIs
|
||||
- Provisioning and de-provisioning flow endpoints
|
||||
- Webhook ingestion and order action APIs
|
||||
|
||||
## Pending (Operational / Process)
|
||||
|
||||
- Scheduling formal joint verification run with Uber support team
|
||||
- Production app creation and scope whitelisting workflow in dashboard
|
||||
- Pilot launch operational communication workflow outside API service
|
||||
|
||||
@ -7,3 +7,13 @@ Go-live readiness:
|
||||
- Alerting and log monitoring enabled
|
||||
- Token refresh and failure runbooks ready
|
||||
- Injection success rate monitoring enabled (`target >= 99%`)
|
||||
- Pilot launch metric check enabled (`>= 98%` over 3 days):
|
||||
- `GET /api/v1/metrics/go-live-readiness`
|
||||
|
||||
Pilot launch workflow:
|
||||
|
||||
1. Provision pilot store to production app.
|
||||
2. Upload menu (`PUT /api/v1/uber/menu/replace`).
|
||||
3. Enable POS integration (`PATCH /api/v1/uber/stores/{storeId}/pos-data` with `integration_enabled=true`).
|
||||
4. Monitor injection success and order response SLA.
|
||||
5. Continue launches after pilot stability target is met.
|
||||
|
||||
@ -246,6 +246,37 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/metrics/go-live-readiness": {
|
||||
"get": {
|
||||
"summary": "Check pilot go-live readiness based on 3-day injection success threshold",
|
||||
"tags": [
|
||||
"Metrics"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"in": "query",
|
||||
"name": "merchantId",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"in": "query",
|
||||
"name": "thresholdPercent",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "number"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Go-live readiness status"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/uber/request": {
|
||||
"post": {
|
||||
"summary": "Generic Uber passthrough for any Uber endpoint",
|
||||
|
||||
@ -549,6 +549,36 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Go Live Readiness Metric",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"header": [
|
||||
{
|
||||
"key": "x-api-key",
|
||||
"value": "{{apiKey}}"
|
||||
}
|
||||
],
|
||||
"url": {
|
||||
"raw": "{{baseUrl}}/api/v1/metrics/go-live-readiness?merchantId={{merchantId}}",
|
||||
"host": [
|
||||
"{{baseUrl}}"
|
||||
],
|
||||
"path": [
|
||||
"api",
|
||||
"v1",
|
||||
"metrics",
|
||||
"go-live-readiness"
|
||||
],
|
||||
"query": [
|
||||
{
|
||||
"key": "merchantId",
|
||||
"value": "{{merchantId}}"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Fetch Reporting CSV",
|
||||
"request": {
|
||||
|
||||
@ -63,7 +63,38 @@ async function getOrderResponseSla(req, res) {
|
||||
});
|
||||
}
|
||||
|
||||
async function getGoLiveReadiness(req, res) {
|
||||
const schema = z.object({
|
||||
merchantId: z.string().optional(),
|
||||
thresholdPercent: z.coerce.number().optional()
|
||||
});
|
||||
|
||||
const query = schema.parse(req.query);
|
||||
const sinceIso = toSinceIso("3");
|
||||
const stats = apiLogRepository.getInjectionSuccessStats({
|
||||
merchantId: query.merchantId,
|
||||
sinceIso
|
||||
});
|
||||
const threshold = query.thresholdPercent ?? 98;
|
||||
const hasData = stats.total > 0;
|
||||
const eligible = hasData && stats.successRate >= threshold;
|
||||
|
||||
return res.json({
|
||||
success: true,
|
||||
data: {
|
||||
metric: "go_live_readiness",
|
||||
merchantId: query.merchantId || "all",
|
||||
pilotWindowDays: 3,
|
||||
requiredInjectionSuccessPercent: threshold,
|
||||
hasData,
|
||||
eligible,
|
||||
...stats
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getInjectionSuccess,
|
||||
getOrderResponseSla
|
||||
getOrderResponseSla,
|
||||
getGoLiveReadiness
|
||||
};
|
||||
|
||||
@ -2,7 +2,8 @@ const express = require("express");
|
||||
const asyncHandler = require("../middleware/asyncHandler");
|
||||
const {
|
||||
getInjectionSuccess,
|
||||
getOrderResponseSla
|
||||
getOrderResponseSla,
|
||||
getGoLiveReadiness
|
||||
} = require("../modules/metrics/metrics.controller");
|
||||
|
||||
const router = express.Router();
|
||||
@ -55,4 +56,28 @@ router.get("/metrics/injection-success", asyncHandler(getInjectionSuccess));
|
||||
*/
|
||||
router.get("/metrics/order-response-sla", asyncHandler(getOrderResponseSla));
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /api/v1/metrics/go-live-readiness:
|
||||
* get:
|
||||
* summary: Check pilot go-live readiness based on 3-day injection success threshold
|
||||
* tags:
|
||||
* - Metrics
|
||||
* parameters:
|
||||
* - in: query
|
||||
* name: merchantId
|
||||
* required: false
|
||||
* schema:
|
||||
* type: string
|
||||
* - in: query
|
||||
* name: thresholdPercent
|
||||
* required: false
|
||||
* schema:
|
||||
* type: number
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Go-live readiness status
|
||||
*/
|
||||
router.get("/metrics/go-live-readiness", asyncHandler(getGoLiveReadiness));
|
||||
|
||||
module.exports = router;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user