"""POST /onboarding/advisor-start — the runtime endpoint that exposes the existing Advisor. Exercises the router in isolation (no DB, no full app): scanner findings (ProducedSignal) -> normalize -> Silent Pass -> Advisor -> the advisory payload. No new reasoning logic — just the wiring. """ from __future__ import annotations from fastapi import FastAPI from fastapi.testclient import TestClient from compliance.api.onboarding_routes import router _app = FastAPI() _app.include_router(router) _client = TestClient(_app) _BODY = { "company": "synthetic", "industry": "machine_builder", "products": ["parking payment system"], "markets": ["EU"], "certifications": ["ISO27001", "ISO9001"], "known_evidence": ["CE process"], "target": "CRA", "scanner_findings": [ {"signal_id": "cyclonedx_found", "source_type": "repository", "evidence": "sbom", "provenance": "sbom.cdx.json"}, {"signal_id": "vdp_found", "source_type": "website", "provenance": "/.well-known/security.txt"}, {"signal_id": "risk_assessment_pdf", "source_type": "document", "provenance": "risk.pdf"}, {"signal_id": "cloud_hosted", "source_type": "product"}, ], } def test_targets_endpoint_lists_supported(): r = _client.get("/onboarding/targets") assert r.status_code == 200 assert "CRA" in r.json()["targets"] def test_advisor_start_returns_full_payload(): r = _client.post("/onboarding/advisor-start", json=_BODY) assert r.status_code == 200, r.text d = r.json() for field in ["silent_intake_summary", "inferred_assumptions", "rejected_assumptions", "top_5_questions", "capability_delta", "top_measures", "evidence_requests", "completeness_summary"]: assert field in d assert len(d["top_5_questions"]) <= 5 assert d["auto_detected"] # Silent Pass recognised things from the scanners assert "sbom_creation" not in {q["capability_id"] for q in d["top_5_questions"]} # detected -> not asked def test_unknown_target_is_404(): body = dict(_BODY, target="NOPE") r = _client.post("/onboarding/advisor-start", json=body) assert r.status_code == 404