feat(F-143): completed feature

This commit is contained in:
chattie
2026-08-22 11:43:42 +02:00
parent fb015932b2
commit 3cc51477aa
22 changed files with 1328 additions and 127 deletions

View File

@@ -0,0 +1,55 @@
{
"feature_id": "F-143",
"agent": "qa",
"stage": "qa_gate",
"verdict": "APPROVED",
"summary": "F-143 verified green. tsc --noEmit = 0 errors; full vitest = 229 passed | 57 skipped (DB itests skip without TEST_DATABASE_URL), reporting adds +22 tests (15 unit + 7 route) with zero regression vs the F-138 baseline (209 passed); lint:boundaries reports 0 NEW violations for reporting. Acceptance criteria AC1-AC7 are exercised end-to-end on both fresh tsc and via route+unit tests (mirroring security.routes.test.ts, no DB needed).",
"checks": [
{
"item": "AC1 — /reporting/filters/schema contract (200, modes, rangeBounds, dataAvailability baseline, filter fields)",
"ok": true,
"evidence": "routes.test 'admin receives the schema contract + own grants'; filterSchema.comparison.modes=[none,previous_equal,previous_calendar]; rangeBounds inclusive_start_exclusive_end; grossSales=available/netSales=unavailable; storeId/compare/channel/groupBy/page/pageSize present"
},
{
"item": "AC2 — RBAC backend-authority (customer 403; admin/editor 200 schema; admin/editor/pos_manager/pos_cashier 200 validate; customer no perms)",
"ok": true,
"evidence": "routes.test customer->403 on /schema and /validate; permissions.test matrix (admin all, pos_cashier VIEW+SALES, customer none)"
},
{
"item": "AC3 — parse + [from,to) range, comparison invariants, defaults (pageSize/page)",
"ok": true,
"evidence": "routes.test AC3 structural: comparison.range.to===range.from; comparison.range.from<range.from; duration preserved; defaults page=1/pageSize=50 (filters.test default test)"
},
{
"item": "AC4 — validation (from>to->400; single/repeated uuid->array; invalid uuid->400)",
"ok": true,
"evidence": "routes.test 'returns 400 on inverted range' + '400 on missing from/to'; filters.test 'accepts repeated and single storeId' + 'rejects invalid UUIDs'"
},
{
"item": "AC5 — comparisonRange unit (none->null; previous_equal to_prev===from/duration; previous_calendar UTC-aligned to_prev<=from)",
"ok": true,
"evidence": "filters.test comparisonRange 3 tests: none, previous_equal (to===start), previous_calendar (to===thisStart, from<thisStart)"
},
{
"item": "AC6 — REPORTING_FINANCIAL admin-only; requireReportingPermission 403 otherwise",
"ok": true,
"evidence": "permissions.test 'REPORTING_FINANCIAL is admin-only': editor/pos_manager/pos_cashier throw, admin ok"
},
{
"item": "AC7 — >=8 unit + >=6 route; tsc 0; npm test no regression; boundaries no new violations",
"ok": true,
"evidence": "22 reporting tests (15 unit>=8, 7 route>=6); tsc --noEmit 0 errors; vitest 229 passed/57 skipped no regression; check-module-boundaries 0 NEW reporting violations"
},
{
"item": "full-suite no regression",
"ok": true,
"evidence": "npx vitest run (all) -> 229 passed | 57 skipped; 0 failed"
},
{
"item": "lint:boundaries no NEW violations",
"ok": true,
"evidence": "check-module-boundaries.mjs: reporting/ clean; only pre-existing security.routes.ts->log-broadcaster R1 remains (F-154, out of scope)"
}
],
"issues": []
}