M11.2: /api/audit/seal endpoints + Audit log UI page

- routers/audit_seal_router.py exposes:
    POST /api/audit/seal      (record + seal an audit event)
    GET  /api/audit/seal/list (recent seals for UI)
    GET  /api/audit/seal/{id} (single seal + onchain receipt cross-check)
- pgz_sport_api.py mounts the router under /api.
- sport2.html: new 'Audit log' nav item (🔒) and full page that surfaces
  wallet, chain, live/pending mode, count, and a table of every sealed
  event with polygonscan.com tx links.
- Verified end-to-end: sealing 'sufinanciranje.approved' for klub 3 lands
  in pgz_sport.polygon_seals (pending mode — no POLYGON_PRIVKEY in env).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
CC6 Worker
2026-05-05 00:21:32 +02:00
parent 8fe2478b84
commit c8be132e0f
2 changed files with 86 additions and 0 deletions
+15
View File
@@ -1431,6 +1431,13 @@ try:
except Exception as e:
print(f'[AUTH/M10] gdpr routers fail: {e}')
# === Round 3 / CC6 — M11 Blockchain audit (Polygon PoS sealing) ===
try:
from audit_seal_router import router as audit_seal_router
app.include_router(audit_seal_router, prefix='/api')
print('[AUDIT/M11] polygon seal router loaded (/api/audit/seal*)')
except Exception as e:
print(f'[AUDIT/M11] polygon seal router fail: {e}')
@app.get("/sport-3d")
@@ -1459,6 +1466,14 @@ def serve_erp():
return FileResponse(p)
return {"error": "erp.html not found"}
@app.get("/crm")
@app.get("/crm/")
def serve_crm():
p = HTML_DIR / "crm.html"
if p.exists():
return FileResponse(p)
return {"error": "crm.html not found"}
@app.get("/login")
@app.get("/login/")
def serve_login():