#!/usr/bin/env python3 """Seed source_file + code_smell artifacts per Code Analysis page.""" import json import urllib.request import urllib.error HEADERS = { "Content-Type": "application/json", "X-ASF-Tenant-Id": "t-demo-003", "X-ASF-User-Id": "u-mario", } BASE = "http://localhost:8000/api/v1" def req(method, path, body=None): data = json.dumps(body).encode() if body is not None else None r = urllib.request.Request( BASE + path, data=data, headers=HEADERS, method=method, ) try: with urllib.request.urlopen(r, timeout=15) as resp: return resp.status, json.loads(resp.read().decode() or "null") except urllib.error.HTTPError as e: txt = e.read().decode() try: payload = json.loads(txt) except Exception: payload = {"raw": txt} return e.code, payload if __name__ == "__main__": # 1. list projects code, projects = req("GET", "/projects?limit=10") assert code == 200, f"projects {code} {projects}" pid = projects[0]["id"] print(f"project_id={pid} name={projects[0]['name']}") # 2. list existing to dedupe by external_id code, arts = req("GET", "/artifacts?limit=200") existing_external = { a["external_id"] for a in arts if a.get("external_id") } existing_types = { (a["type"], a["title"]) for a in arts } print(f"existing artifacts total: {len(arts)} ext_ids: {len(existing_external)} type/titles: {len(existing_types)}") SOURCE_FILES = [ { "external_id": "SRC-CORE-MW", "type": "source_file", "title": "asf-core/app/middleware/correlation.py", "status": "active", "source": "git", "content": ( "\"\"\"Tenant & correlation middleware.\n\n" "Adds X-ASF-Correlation-Id and coerces X-ASF-Tenant-Id to UUID5.\n\"\"\"\n" "import uuid\nfrom fastapi import Request, Response\nfrom starlette.middleware.base import BaseHTTPMiddleware\n\n" "TENANT_NS = uuid.UUID('6ba7b812-9dad-11d1-80b4-00c04fd430c8')\n\n" "def _coerce_uuid(val):\n" " try:\n" " return uuid.UUID(val)\n" " except Exception:\n" " return uuid.uuid5(TENANT_NS, val or 'default')\n\n" "class CorrelationMiddleware(BaseHTTPMiddleware):\n" " async def dispatch(self, request: Request, call_next):\n" " cid = request.headers.get('X-ASF-Correlation-Id') or str(uuid.uuid4())\n" " request.state.correlation_id = cid\n" " tid = _coerce_uuid(request.headers.get('X-ASF-Tenant-Id'))\n" " request.state.tenant_id = tid\n" " response: Response = await call_next(request)\n" " response.headers['X-ASF-Correlation-Id'] = cid\n" " return response\n" ), "metadata": { "language": "python", "path": "services/asf-core/app/middleware/correlation.py", "repo": "git@github.com:azurian/asf.git", "branch": "main", "loc": 36, "lines": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36], "commit_sha": "a1f22c33", }, }, { "external_id": "SRC-WEB-REQ", "type": "source_file", "title": "asf-web/app/requirements/page.tsx", "status": "active", "source": "git", "content": ( "\"use client\";\n" "import React, { useMemo, useState } from \"react\";\n" "import { useQuery } from \"@tanstack/react-query\";\n" "import { ClipboardList, Search } from \"lucide-react\";\n" "import { artifacts, projects } from \"@/lib/api\";\n" "import { Card, CardBody, CardHeader, CardTitle } from \"@/components/ui/Card\";\n" "\n" "export default function RequirementsPage() {\n" " const [projectFilter, setProjectFilter] = useState('all');\n" " const [statusFilter, setStatusFilter] = useState('all');\n" " const projectsQ = useQuery({ queryKey: ['req-projects'], queryFn: () => projects.list({ limit: 50 }) });\n" " const listQ = useQuery({\n" " queryKey: ['req-list', projectFilter, statusFilter],\n" " queryFn: () => artifacts.list({\n" " status: statusFilter !== 'all' ? statusFilter : undefined,\n" " project_id: projectFilter !== 'all' ? projectFilter : undefined,\n" " type: 'requirement',\n" " limit: 200,\n" " }),\n" " });\n" " return (...);\n" "}\n" ), "metadata": { "language": "typescript", "path": "frontend/asf-web/app/requirements/page.tsx", "repo": "git@github.com:azurian/asf.git", "branch": "main", "loc": 394, "framework": "nextjs14", "commit_sha": "a1f22c33", }, }, { "external_id": "SRC-WORKER-CB", "type": "source_file", "title": "asf-worker/app/worker/consumer.py", "status": "active", "source": "git", "content": ( "\"\"\"RabbitMQ consumer factory + sync callbacks for DIRECT job queues.\"\"\"\n" "import asyncio\nimport structlog\nfrom aio_pika import IncomingMessage\n\n" "log = structlog.get_logger(__name__)\n\n" "def _make_consumer_callback(handler):\n" " def _cb(message: IncomingMessage):\n" " loop = asyncio.new_event_loop()\n" " try:\n" " loop.run_until_complete(handler(message))\n" " except Exception as exc:\n" " log.exception('consumer_handler_error', err=exc)\n" " finally:\n" " loop.close()\n" " return _cb\n" ), "metadata": { "language": "python", "path": "services/asf-worker/app/worker/consumer.py", "repo": "git@github.com:azurian/asf.git", "branch": "main", "loc": 18, "commit_sha": "b4812a01", }, }, ] # code smells stored as type=ai_analysis with metadata.kind = "code_smell" # (to keep ArtifactType enum closed — no tests break) SMELLS = [ { "external_id": "CS-001", "type": "ai_analysis", "title": "Bare except clause in CorrelationMiddleware.dispatch", "status": "open", "source": "ruff:EM102", "content": ( "Rule Ruff E722 — bare `except Exception` without narrow clause may swallow " "cancellation errors unrelated to UUID parse. Prefer explicit ValueError/AttributeError " "or log.exception with correlation_id bound.\n" "Lines affected: 14-16." ), "metadata": { "kind": "code_smell", "language": "python", "severity": "medium", "rule_id": "E722", "engine": "ruff 0.5.0", "path": "services/asf-core/app/middleware/correlation.py", "lines": [14, 15, 16], "fingerprint": "corr_mw_except_001", "confidence_pct": 98, }, }, { "external_id": "CS-002", "type": "ai_analysis", "title": "Missing N+1 query guard in requirements listQ (no select limit on projects)", "status": "open", "source": "eslint:perf-nplus1", "content": ( "Requirements page fetches all 50 projects and maps via projectsQ even when a single project filter is selected. " "Consider deriving projectNameById lazily and paginating projects lookup.\n" "Affected page.tsx lines 78-89." ), "metadata": { "kind": "code_smell", "language": "typescript", "severity": "low", "rule_id": "asf-perf-003", "engine": "eslint custom", "path": "frontend/asf-web/app/requirements/page.tsx", "lines": [78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89], "fingerprint": "req_list_nplus1_002", "confidence_pct": 75, }, }, { "external_id": "CS-003", "type": "ai_analysis", "title": "Coroutine leak risk: event loop not shared re-created per message", "status": "open", "source": "pytype:event-loop", "content": ( "Worker consumer factory _cb spawns asyncio.new_event_loop() per IncomingMessage. " "Long-lived handlers under high volume may accumulate GC pressure from leftover loop objects. " "Recommendation: pass the shared running event loop to handler() via q.consume() and make handler truly async.\n" "Severity HIGH — affects every DIRECT job 24/7." ), "metadata": { "kind": "code_smell", "language": "python", "severity": "high", "rule_id": "ASF-SEC-203", "engine": "pytype + manual review", "path": "services/asf-worker/app/worker/consumer.py", "lines": [8, 9, 10, 11, 12, 13, 14, 15, 16], "fingerprint": "worker_loop_per_msg_003", "confidence_pct": 88, "cwe": "CWE-772", }, }, ] created = 0 for body in SOURCE_FILES + SMELLS: if (body["type"], body["title"]) in existing_types or body.get("external_id") in existing_external: print(f" SKIP exists ext_id={body.get('external_id')} type={body['type']} title={body['title'][:60]}") continue body_full = {"project_id": pid, **body} code, resp = req("POST", "/artifacts", body_full) if code in (201, 200): created += 1 print(f" OK [{code}] type={body['type']} id={str(resp['id'])[:8]} title={body['title'][:60]}") else: print(f" FAIL [{code}] type={body['type']} body={resp}") print(f"\nDONE: created={created} new code artifacts") # print summary counts per type code, arts2 = req("GET", "/artifacts?limit=200") from collections import Counter cnt = Counter(a["type"] for a in arts2) for t, c in cnt.items(): print(f" count {t}: {c}")