From 7adcec3309b195a67a04f67d915c23972914ec0c Mon Sep 17 00:00:00 2001 From: CC1 Date: Tue, 5 May 2026 08:29:04 +0200 Subject: [PATCH] =?UTF-8?q?CC1:=203-subagent=20deep=20audit=20=E2=80=94=20?= =?UTF-8?q?Frontend=20/=20API=20gap=20/=20DB=20integrity?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reports in _audit/: audit_FRONTEND_COVERAGE.md — SA-1 (Explore): 9 HTML files, 0 orphan handlers (clean) audit_API_GAP.md — SA-2 (Explore): 356 backend routes vs 54 frontend paths 23 missing routes / 39 call sites audit_DB_INTEGRITY.md — SA-3 (general-purpose): 8 SQL probes, FKs/NULLs clean, 48 dup-OIB clusters, 518 low-cov klubovi audit_CONSOLIDATED.md — top 10 critical with owner matrix (cc1/cc4/cc5/cc6) Headlines: Frontend: clean (post-R3 refactors landed) API gap: CRM module systemic — 16 of 23 missing routes need /crm prefix in crm.html 6 missing routes are trailing-slash bugs in crm.html DB: 48 OIB dup clusters in klubovi (~100 rows) need merge+unique-index 518/2244 klubovi (23%) <33% coverage → enrichment_worker target list 14 scoreboard-string klubovi rows (RK ... HRL Zapad od X) → DELETE ~30 backup tables (~97k rows) cluttering pgz_sport schema Owner allocation: cc1 → #6 backup-table archival, #8 verify, #9 sportas trailing-slash cc4 → #1 OIB dedup script, #4 scoreboard DELETE, #10 schema CHECKs cc5 → #2 /crm prefix sweep on crm.html, #3 trailing-slash sweep, #7 notif endpoint cc6 → #5 enrichment_worker batch on filled<4 klubovi Co-Authored-By: Claude Opus 4.7 (1M context) --- _audit/audit_API_GAP.md | 183 +++++++++++++ _audit/audit_CONSOLIDATED.md | 72 +++++ _audit/audit_DB_INTEGRITY.md | 437 ++++++++++++++++++++++++++++++ _audit/audit_FRONTEND_COVERAGE.md | 103 +++++++ 4 files changed, 795 insertions(+) create mode 100644 _audit/audit_API_GAP.md create mode 100644 _audit/audit_CONSOLIDATED.md create mode 100644 _audit/audit_DB_INTEGRITY.md create mode 100644 _audit/audit_FRONTEND_COVERAGE.md diff --git a/_audit/audit_API_GAP.md b/_audit/audit_API_GAP.md new file mode 100644 index 0000000..d72637c --- /dev/null +++ b/_audit/audit_API_GAP.md @@ -0,0 +1,183 @@ +# SA-2 API Gap Analysis + +**Generated:** 2026-05-05T06:25:39.772966Z +**Backend routes:** 356 +**Frontend unique paths:** 54 +**Missing or misconfigured (frontend calls without correct backend):** 23 + +## MISSING ROUTES + +### Routes with Trailing Slashes (6 issues) + +#### `GET /api/forms/` +- Called from: `static/crm.html:L957` +- Actual call: `api('/forms/' + code)` +- Method: GET +- Backend equivalent: `/api/crm/forms/{code_or_id}` +- Fix: Remove trailing slash, add `/crm` prefix. Frontend should call `/crm/forms/{code}` (API base is `/sport/api/crm`) + +#### `GET|POST /api/forms/submissions/` +- Called from: `static/crm.html:L1039`, `static/crm.html:L1087`, `static/crm.html:L1126`, `static/crm.html:L1135`, `static/crm.html:L1144` +- Method: GET/POST (mixed) +- Backend equivalent: `/api/crm/forms/submissions/{sid}` +- Fix: Remove trailing slash when accessing specific submission by ID + +#### `POST /api/notifications/` +- Called from: `static/crm.html:L1652` +- Method: POST +- Backend equivalent: `/api/crm/notifications/{nid}/read` +- Fix: Remove trailing slash, use full path `/crm/notifications/{nid}/read` + +#### `GET /api/sportas/` +- Called from: `static/sport2.html:L1582`, `static/sport2_new.html:L907` +- Method: GET +- Backend equivalent: `/api/sportas/{clan_id}/profil` +- Fix: Remove trailing slash, include full path `/sportas/{clan_id}/profil` + +#### `POST /api/v2/enrich/` +- Called from: `static/sport2.html:L376` +- Actual call: `await apiPost('/v2/enrich/'+kind+'/'+id)` +- Method: POST +- Backend equivalent: `/api/v2/enrich/{kind}/{eid}/apply` +- Fix: Append `/apply` to complete the route (e.g., `/v2/enrich/klub/{eid}/apply`) + +#### `POST /api/v2/forensic/findings/` +- Called from: `static/sport2.html:L2873` +- Actual call: `await apiPost('/v2/forensic/findings/'+findingId+'/enrich')` +- Method: POST +- Backend equivalent: `/api/v2/forensic/findings/{finding_id}/enrich` +- Fix: Parameter name in backend is `finding_id`, ensure frontend passes correct ID + +### Routes Missing /crm Prefix (16 issues) + +#### `GET|POST /api/clanarine/` +- Called from: `static/crm.html:L503`, `static/crm.html:L571` +- Method: GET/POST (mixed) +- Correct path: `/api/crm/clanarine` (no trailing slash) +- Fix: Add `/crm` to path; frontend base is `/sport/api/crm` so call `/clanarine` instead of `/clanarine/` + +#### `POST /api/clanarine/bulk/notify` +- Called from: `static/crm.html:L417` +- Method: POST +- Correct path: `/api/crm/clanarine/bulk/notify` +- Fix: Add `/crm` prefix; frontend base is `/sport/api/crm` so call `/clanarine/bulk/notify` + +#### `POST /api/clanarine/bulk/uplatnice` +- Called from: `static/crm.html:L456` +- Method: POST +- Correct path: `/api/crm/clanarine/bulk/uplatnice` +- Fix: Add `/crm` prefix + +#### `POST /api/clanarine/notify-bulk` +- Called from: `static/crm.html:L631` +- Method: POST +- Correct path: `/api/crm/clanarine/notify-bulk` +- Fix: Add `/crm` prefix + +#### `GET|POST /api/email-templates` +- Called from: `static/crm.html:L1675`, `static/crm.html:L1824` +- Method: GET/POST (mixed) +- Correct path: `/api/crm/email-templates` +- Fix: Add `/crm` prefix + +#### `GET /api/forms` +- Called from: `static/crm.html:L900`, `static/crm.html:L1846` +- Method: GET +- Correct path: `/api/crm/forms` +- Fix: Add `/crm` prefix + +#### `GET|POST /api/forms/submissions` +- Called from: `static/crm.html:L901`, `static/crm.html:L1035`, `static/crm.html:L1053` +- Method: GET/POST (mixed) +- Correct path: `/api/crm/forms/submissions` +- Fix: Add `/crm` prefix + +#### `GET /api/klubovi/` +- Called from: `static/app.html:L508`, `static/sport2.html:L1294`, `static/sport2_new.html:L702` +- Method: GET +- Correct path: `/api/klubovi` (no trailing slash) +- Fix: Remove trailing slash (frontend base is `/sport/api` so path becomes `/sport/api/klubovi` → `/api/klubovi` after nginx rewrite) + +#### `GET|POST /api/lijecnicki/` +- Called from: `static/crm.html:L794`, `static/crm.html:L808` +- Method: GET/POST (mixed) +- Correct path: `/api/crm/lijecnicki` (no trailing slash) +- Fix: Add `/crm` prefix, remove trailing slash + +#### `POST /api/lijecnicki/notify-scan` +- Called from: `static/crm.html:L1644` +- Method: POST +- Correct path: `/api/crm/lijecnicki/notify-scan` +- Fix: Add `/crm` prefix + +#### `GET /api/notifications` +- Called from: `static/crm.html:L1591`, `static/crm.html:L1848` +- Method: GET +- Correct path: `/api/crm/notifications` +- Fix: Add `/crm` prefix + +#### `POST /api/notifications/mark-all-read` +- Called from: `static/crm.html:L1661` +- Method: POST +- Correct path: `/api/crm/notifications/mark-all-read` +- Fix: Add `/crm` prefix + +#### `GET /api/savezi/` +- Called from: `static/app.html:L488`, `static/sport2.html:L1146`, `static/sport2_new.html:L558` +- Method: GET +- Correct path: `/api/savezi` (no trailing slash) +- Fix: Remove trailing slash (frontend base is `/sport/api` so path becomes `/sport/api/savezi` → `/api/savezi` after nginx rewrite) + +#### `GET /api/stats` +- Called from: `static/crm.html:L1517` +- Method: GET +- Correct path: `/api/crm/stats` +- Fix: Add `/crm` prefix + +#### `GET /api/zzjz/info` +- Called from: `static/crm.html:L721` +- Method: GET +- Correct path: `/api/crm/zzjz/info` +- Fix: Add `/crm` prefix + +#### `GET /api/zzjz/termini` +- Called from: `static/crm.html:L722` +- Method: GET +- Correct path: `/api/crm/zzjz/termini` +- Fix: Add `/crm` prefix + +### Parameter Mismatch (1 issue) + +#### `POST /api/crm/notifications/{nid}/read` +- Called from: `static/app.html:L1310` +- Issue: Frontend passes `{n.id}` but backend expects `{nid}` +- Fix: Update template variable in frontend to match backend parameter name, or update backend to accept `id` instead of `nid` + +## SUMMARY TABLE + +| Category | Count | +|---|---:| +| Total unique frontend paths checked | 54 | +| Successfully matched to backend | 31 | +| Missing routes with issues | 23 | +| - Trailing slash issues | 6 | +| - Missing /crm prefix | 16 | +| - Parameter mismatches | 1 | +| **Total call locations with problems** | **39** | + +## ROOT CAUSE ANALYSIS + +1. **Trailing slashes:** Frontend code constructs paths dynamically using template variables (e.g., `/api/forms/` + code), but leaves trailing slash in base path +2. **Missing /crm prefix:** CRM module endpoints require `/crm/` prefix in API path, but some frontend files are calling the base `/api/` version instead of going through the CRM submodule +3. **Parameter name mismatch:** Template variable names in frontend don't match backend parameter names (e.g., `{n.id}` vs `{nid}`) + +## RECOMMENDATIONS + +1. Audit all `api()`, `apiAuth()`, and `apiPost()` calls in frontend to ensure correct base paths and prefixes +2. Review nginx rewrite rules to confirm `/sport/api/crm/*` → `/api/crm/*` mapping +3. Add linting rule or static analysis to catch trailing slashes in API calls +4. Document API path conventions for each HTML file (which use `/api`, `/sport/api`, `/sport/api/crm`, etc.) +5. Consider normalizing frontend API call helpers to automatically handle path prefixes consistently + +--- +**Generated by SA-2 API Gap Analysis Agent** diff --git a/_audit/audit_CONSOLIDATED.md b/_audit/audit_CONSOLIDATED.md new file mode 100644 index 0000000..d76fc45 --- /dev/null +++ b/_audit/audit_CONSOLIDATED.md @@ -0,0 +1,72 @@ +# CC1 Consolidated Audit — 3 subagents +**Generated:** 2026-05-05T08:30:00Z +**Source reports:** +- `_audit/audit_FRONTEND_COVERAGE.md` (SA-1, 9 files scanned, 0 issues) +- `_audit/audit_API_GAP.md` (SA-2, 23 missing routes / 39 call sites) +- `_audit/audit_DB_INTEGRITY.md` (SA-3, 48 dup-OIB clusters, 518 low-coverage klubovi) + +## Executive summary + +| Area | Verdict | Headline finding | +|---|---|---| +| Frontend coverage | **CLEAN** | 200+ onclick handlers, 9 forms, 8 modals, 28 tabs all wired correctly. No orphans. | +| API gap | **NEEDS WORK** | 23 unique missing routes (39 call sites). Two systemic patterns: trailing slashes (6) and missing `/crm` prefix (16). | +| DB integrity | **NEEDS WORK** | FKs/NULLs/audit-chain clean. 48 duplicate-OIB clusters in klubovi (~100 rows). 518/2244 klubovi (23%) have <33% coverage. | + +## TOP 10 critical (sorted by user-impact + fix-ease) + +### 1. Klubovi 48 duplicate-OIB clusters (DB) +**Impact:** confuses joins, breaks unique business identity. **Fix:** run a `dedup_klubovi_by_oib.py --dry-run` then merge children (clanovi.klub_id, klub_sezona.klub_id, hns_klubovi_natjecanje.klub_id) onto the row with highest coverage and DELETE the duplicates. Then `CREATE UNIQUE INDEX CONCURRENTLY klubovi_oib_unique_valid ON klubovi(oib) WHERE oib ~ '^[0-9]{11}$'`. — owner: cc4 (DB) + +### 2. CRM frontend missing /crm prefix on 16 endpoints (API) +**Impact:** crm.html buttons silently fail. **Fix:** in `static/crm.html`, change `api('/clanarine/...')` → `api('/crm/clanarine/...')` (and lijecnicki, forms, notifications, email-templates, zzjz). — owner: cc5 (CRM) + +### 3. CRM forms 5 trailing-slash 404s (API) +**Impact:** form submissions fail. **Fix:** in `crm.html` L1039/1087/1126/1135/1144 strip trailing `/` from `/forms/submissions/${sid}` and `/forms/${code}`. — owner: cc5 (CRM) + +### 4. 14 scoreboard-string klubovi rows (DB) +**Impact:** garbage in klubovi.naziv (e.g. `RK ... N. u II HRL Zapad od X` strings). **Fix:** `DELETE FROM pgz_sport.klubovi WHERE naziv ~ '\d+\. u (I{1,3}|IV) HRL .* od \d+'` (verify COUNT first). — owner: cc4 (DB) + +### 5. 518 klubovi <33% coverage (DB) +**Impact:** worst panel UX, low-info entities. **Fix:** `python3 scripts/enrichment_worker.py --filter "filled<4" --limit 100 --concurrency 4` (existing CC6 module). — owner: cc6 (enrich) + +### 6. ~30 backup tables in pgz_sport schema (DB hygiene) +**Impact:** ~97k rows of stale data, accidental queries against snapshots. **Fix:** `pg_dump --schema-only` snapshot then `DROP TABLE` each `*_backup_*`/`*_premerge_*`/`*_pre_*`/`*_dedup_*`. Move to `pgz_sport_archive` schema if cold storage preferred. — owner: cc1/dba + +### 7. /api/notifications/{nid}/read trailing slash (API) +**Impact:** mark-as-read buttons fail. **Fix:** `crm.html:L1652` POST URL — strip trailing `/`, full path `/crm/notifications/{nid}/read`. — owner: cc5 (CRM) + +### 8. 3 [VERIFY]/[UNRESOLVED] klubovi (DB) +**Impact:** placeholder names visible in UI. **Fix:** ids 2619, 2630, 4426 already flagged `metadata->>'manual_review'='true'`. Surface them in `/audit` UI for triage; or hard-link via Sportilus / sport-pgz manual lookup. — owner: cc1/cc6 + +### 9. /api/sportas/{id}/profil — frontend trailing slash (API) +**Impact:** sport2.html `openSportas` may 404 in some code paths. **Fix:** verify `static/sport2.html` doesn't construct URL with extra `/`; backend route is `/api/sportas/{id}/profil` (no trailing slash). — owner: cc1 + +### 10. ALTER TABLE constraints to prevent regression (DB) +**Impact:** prevents future garbage. **Fix:** add `CHECK (naziv = btrim(regexp_replace(naziv, '\s+', ' ', 'g')))` on klubovi/clanovi naziv columns; add unique index on klubovi.oib; document `sys_audit` retention (7d → 30d?). — owner: cc4 + +## Owner allocation matrix + +| CC | Tasks | +|---|---| +| cc1 (orchestrator) | #6 backup-table cleanup, #8/9 verify, #10 schema constraints PR review | +| cc4 (DB/ERP) | #1 OIB dedup, #4 scoreboard-string DELETE, #10 DDL | +| cc5 (CRM) | #2 /crm prefix sweep on crm.html, #3 trailing-slash sweep, #7 notifications | +| cc6 (enrichment) | #5 enrichment_worker batch, possibly co-own #8 | + +## Reports verbatim +- Read full SA-1 detail: `_audit/audit_FRONTEND_COVERAGE.md` +- Read full SA-2 detail: `_audit/audit_API_GAP.md` (each missing path with file:line + suggested fix) +- Read full SA-3 detail: `_audit/audit_DB_INTEGRITY.md` (each query + result + fix SQL) + +## Methodology +- SA-1 walked every `