feat(F-097): completed feature
This commit is contained in:
@@ -4337,6 +4337,39 @@
|
||||
"close": true
|
||||
},
|
||||
"completed_at": "2026-08-20T20:12:01Z"
|
||||
},
|
||||
{
|
||||
"id": "F-097",
|
||||
"type": "bug",
|
||||
"title": "Fix empty-body admin proxy requests and AI settings loading",
|
||||
"problem": "The admin proxy sends Content-Type application/json with an empty POST body, causing Fastify to return FST_ERR_CTP_EMPTY_JSON_BODY for SEO generation; settings errors also need end-to-end verification.",
|
||||
"goal": "Make empty POST proxy requests valid, verify settings loads through the admin proxy, and keep AI SEO generation returning actionable configuration errors.",
|
||||
"scope_in": [
|
||||
"admin API proxy",
|
||||
"AI SEO generation"
|
||||
],
|
||||
"scope_out": [
|
||||
"No schema redesign",
|
||||
"no provider SDK"
|
||||
],
|
||||
"priority": "high",
|
||||
"risk": "low",
|
||||
"description": "Problem: The admin proxy sends Content-Type application/json with an empty POST body, causing Fastify to return FST_ERR_CTP_EMPTY_JSON_BODY for SEO generation; settings errors also need end-to-end verification.. Goal: Make empty POST proxy requests valid, verify settings loads through the admin proxy, and keep AI SEO generation returning actionable configuration errors.. Scope IN: admin API proxy, AI SEO generation. Scope OUT: No schema redesign, no provider SDK. Type: bug. Priority: high. Risk: low.",
|
||||
"acceptance": [
|
||||
"Empty POST requests reach backend without invalid JSON body",
|
||||
"Settings loads through admin proxy with authenticated session",
|
||||
"SEO generation returns clear AI configuration/provider errors",
|
||||
"Typecheck, build, and verify pass"
|
||||
],
|
||||
"status": "done",
|
||||
"created_at": "2026-08-20",
|
||||
"gates": {
|
||||
"reviewer": true,
|
||||
"security": true,
|
||||
"qa": true,
|
||||
"close": true
|
||||
},
|
||||
"completed_at": "2026-08-20T20:33:06Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -30,10 +30,12 @@ export async function POST(req: NextRequest) {
|
||||
const cookies = req.headers.get('cookie') ?? '';
|
||||
const body = await req.text();
|
||||
try {
|
||||
const headers: Record<string, string> = { Cookie: cookies };
|
||||
if (body) headers['Content-Type'] = 'application/json';
|
||||
const backendRes = await fetch(`${API}/${path}`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json', Cookie: cookies },
|
||||
body,
|
||||
headers,
|
||||
...(body ? { body } : {}),
|
||||
});
|
||||
const setCookie = backendRes.headers.get('set-cookie');
|
||||
const data = await backendRes.json().catch(() => null);
|
||||
|
||||
File diff suppressed because one or more lines are too long
10
work/artifacts/F-097/implementer.md
Normal file
10
work/artifacts/F-097/implementer.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# F-097 — Implementer evidence
|
||||
|
||||
- Fixed the admin catch-all POST proxy: it no longer sends `Content-Type: application/json` when the request has no body.
|
||||
- This allows `POST /api/products/:id/generate-seo` to reach the backend; previously Fastify rejected the empty request with `FST_ERR_CTP_EMPTY_JSON_BODY` (400).
|
||||
- Rebuilt and restarted the production monolith.
|
||||
|
||||
Validation:
|
||||
- Admin production build: exit 0
|
||||
- Authenticated `/api/admin/settings`: HTTP 200
|
||||
- Authenticated empty-body SEO request: HTTP 422 `AI_NOT_CONFIGURED` with actionable message (instead of HTTP 400)
|
||||
14
work/artifacts/F-097/leader-close.json
Normal file
14
work/artifacts/F-097/leader-close.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"feature_id": "F-097",
|
||||
"agent": "leader",
|
||||
"verdict": "APPROVED",
|
||||
"summary": "F-097 fixes the admin proxy empty JSON body error that caused generate-seo HTTP 400; settings now loads through :3004 and missing AI configuration returns 422 with a clear message.",
|
||||
"evidence": [
|
||||
"reviewer.json APPROVED",
|
||||
"security.json APPROVED",
|
||||
"qa.json APPROVED",
|
||||
"Production services restarted and health checks return 200",
|
||||
"verify.sh green"
|
||||
],
|
||||
"timestamp": "2026-08-20T20:33:10Z"
|
||||
}
|
||||
16
work/artifacts/F-097/qa.json
Normal file
16
work/artifacts/F-097/qa.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"feature_id": "F-097",
|
||||
"agent": "qa",
|
||||
"verdict": "APPROVED",
|
||||
"summary": "Proxy fix passes typechecks, tests, verify, production build, and authenticated smoke checks.",
|
||||
"evidence": [
|
||||
"Root npm run typecheck exit 0",
|
||||
"Admin npx tsc --noEmit exit 0",
|
||||
"Tests: 133 passed, 56 skipped",
|
||||
"Admin production build exit 0",
|
||||
"Authenticated settings proxy: HTTP 200",
|
||||
"Authenticated bodyless generate-seo proxy: HTTP 422 AI_NOT_CONFIGURED (expected with empty database configuration)",
|
||||
"scripts/verify.sh exit 0"
|
||||
],
|
||||
"timestamp": "2026-08-20T20:33:00Z"
|
||||
}
|
||||
12
work/artifacts/F-097/reviewer.json
Normal file
12
work/artifacts/F-097/reviewer.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"feature_id": "F-097",
|
||||
"agent": "reviewer",
|
||||
"verdict": "APPROVED",
|
||||
"summary": "The proxy fix is minimal and preserves JSON headers for non-empty requests while allowing bodyless POST endpoints.",
|
||||
"evidence": [
|
||||
"POST proxy conditionally sets Content-Type only when a body exists",
|
||||
"Authenticated settings request through :3004 returns 200",
|
||||
"Authenticated SEO request through :3004 reaches backend and returns AI_NOT_CONFIGURED 422"
|
||||
],
|
||||
"timestamp": "2026-08-20T20:32:30Z"
|
||||
}
|
||||
13
work/artifacts/F-097/security.json
Normal file
13
work/artifacts/F-097/security.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"feature_id": "F-097",
|
||||
"agent": "security",
|
||||
"verdict": "APPROVED",
|
||||
"summary": "The change only alters proxy header/body consistency; cookies remain forwarded and backend errors remain in the existing envelope.",
|
||||
"evidence": [
|
||||
"No credentials or API keys are added to client responses",
|
||||
"The backoffice cookie continues to be forwarded to the backend",
|
||||
"Non-empty JSON requests retain their Content-Type header",
|
||||
"Backend returns actionable status/code without exposing provider secrets"
|
||||
],
|
||||
"timestamp": "2026-08-20T20:32:40Z"
|
||||
}
|
||||
@@ -1,48 +1,13 @@
|
||||
{
|
||||
"feature_id": "F-096",
|
||||
"feature_id": "F-097",
|
||||
"stage": "close",
|
||||
"agent": "leader",
|
||||
"action": "F-096 cerrado: servicios levantados y configuración IA disponible",
|
||||
"state": "done",
|
||||
"action": "Close proxy fix after approved gates",
|
||||
"state": "running",
|
||||
"next_agent": "leader",
|
||||
"waiting_for": "Seleccionar la siguiente feature pending",
|
||||
"updated_at": "2026-08-20T20:27:15Z",
|
||||
"waiting_for": "close_feature validation",
|
||||
"updated_at": "2026-08-20T20:33:00Z",
|
||||
"timeline": [
|
||||
{
|
||||
"ts": "2026-08-20T20:01:10Z",
|
||||
"agent": "security",
|
||||
"stage": "security_gate",
|
||||
"state": "running",
|
||||
"message": "Check variant creation validation, uniqueness, and authorization"
|
||||
},
|
||||
{
|
||||
"ts": "2026-08-20T20:01:22Z",
|
||||
"agent": "qa",
|
||||
"stage": "qa_gate",
|
||||
"state": "running",
|
||||
"message": "Run variant manager typecheck, tests, lint, and verify"
|
||||
},
|
||||
{
|
||||
"ts": "2026-08-20T20:01:42Z",
|
||||
"agent": "leader",
|
||||
"stage": "close",
|
||||
"state": "running",
|
||||
"message": "Validate F-094 gates and close variant workflow"
|
||||
},
|
||||
{
|
||||
"ts": "2026-08-20T20:02:00Z",
|
||||
"agent": "leader",
|
||||
"stage": "close",
|
||||
"state": "done",
|
||||
"message": "F-094 cerrado: creación y explicación de variantes en Publicar"
|
||||
},
|
||||
{
|
||||
"ts": "2026-08-20T20:02:19Z",
|
||||
"agent": "leader",
|
||||
"stage": "intake",
|
||||
"state": "running",
|
||||
"message": "Triage image URL 400 and implement secure remote download to uploads"
|
||||
},
|
||||
{
|
||||
"ts": "2026-08-20T20:03:18Z",
|
||||
"agent": "implementer",
|
||||
@@ -147,6 +112,41 @@
|
||||
"stage": "close",
|
||||
"state": "done",
|
||||
"message": "F-096 cerrado: servicios levantados y configuración IA disponible"
|
||||
},
|
||||
{
|
||||
"ts": "2026-08-20T20:31:11Z",
|
||||
"agent": "implementer",
|
||||
"stage": "build",
|
||||
"state": "running",
|
||||
"message": "Fix empty-body proxy requests and verify settings/SEO API"
|
||||
},
|
||||
{
|
||||
"ts": "2026-08-20T20:32:20Z",
|
||||
"agent": "reviewer",
|
||||
"stage": "review_gate",
|
||||
"state": "running",
|
||||
"message": "Review empty-body proxy fix and authenticated API behavior"
|
||||
},
|
||||
{
|
||||
"ts": "2026-08-20T20:32:27Z",
|
||||
"agent": "security",
|
||||
"stage": "security_gate",
|
||||
"state": "running",
|
||||
"message": "Check proxy body handling and error exposure"
|
||||
},
|
||||
{
|
||||
"ts": "2026-08-20T20:32:37Z",
|
||||
"agent": "qa",
|
||||
"stage": "qa_gate",
|
||||
"state": "running",
|
||||
"message": "Run typechecks, tests, verify, and production health checks"
|
||||
},
|
||||
{
|
||||
"ts": "2026-08-20T20:33:00Z",
|
||||
"agent": "leader",
|
||||
"stage": "close",
|
||||
"state": "running",
|
||||
"message": "Close proxy fix after approved gates"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user