From 31425db1522484ac2889ad43501572362e6d8efa Mon Sep 17 00:00:00 2001 From: tegwick Date: Sun, 26 Apr 2026 09:30:05 +0200 Subject: [PATCH] Added OpenAPI examples --- src/repo_registry/web_api/schemas.py | 168 +++++++++++++++++++++++++++ tests/test_web_api.py | 10 ++ 2 files changed, 178 insertions(+) diff --git a/src/repo_registry/web_api/schemas.py b/src/repo_registry/web_api/schemas.py index 164728e..aca6570 100644 --- a/src/repo_registry/web_api/schemas.py +++ b/src/repo_registry/web_api/schemas.py @@ -5,6 +5,35 @@ from typing import Any from pydantic import BaseModel, Field +REPOSITORY_EXAMPLE = { + "id": 1, + "name": "MailRouter", + "url": "https://github.com/example/mail-router.git", + "description": "Routes incoming customer email.", + "branch": "main", + "status": "indexed", +} + +ANALYSIS_RUN_EXAMPLE = { + "id": 1, + "repository_id": 1, + "snapshot_id": 1, + "status": "completed", + "started_at": "2026-04-26T09:00:00Z", + "completed_at": "2026-04-26T09:00:03Z", + "error_message": None, + "scanner_version": "deterministic-v1", +} + +SOURCE_REFERENCE_EXAMPLE = { + "fact_id": 12, + "path": "src/routes/classify_email.py", + "kind": "api_route", + "name": "POST /api/classify-email", + "line": 42, +} + + class RepositoryCreate(BaseModel): url: str name: str | None = None @@ -292,6 +321,12 @@ class RepositoryResponse(BaseModel): branch: str status: str + model_config = { + "json_schema_extra": { + "examples": [REPOSITORY_EXAMPLE], + } + } + class RepositorySnapshotResponse(BaseModel): id: int @@ -410,6 +445,66 @@ class CandidateGraphResponse(BaseModel): analysis_run: AnalysisRunResponse abilities: list[CandidateAbilityResponse] + model_config = { + "json_schema_extra": { + "examples": [ + { + "repository": { + **REPOSITORY_EXAMPLE, + "status": "reviewing", + }, + "analysis_run": ANALYSIS_RUN_EXAMPLE, + "abilities": [ + { + "id": 1, + "name": "Business Email Routing", + "description": "Route inbound messages to the right team.", + "confidence": 0.82, + "confidence_label": "high", + "status": "pending", + "source_refs": [SOURCE_REFERENCE_EXAMPLE], + "capabilities": [ + { + "id": 1, + "name": "Classify Incoming Email", + "description": "Classify messages by intent.", + "inputs": ["subject", "body"], + "outputs": ["intent", "confidence"], + "confidence": 0.78, + "confidence_label": "medium", + "status": "pending", + "source_refs": [SOURCE_REFERENCE_EXAMPLE], + "features": [ + { + "id": 1, + "name": "POST /api/classify-email", + "type": "REST endpoint", + "location": "src/routes/classify_email.py", + "confidence": 0.84, + "confidence_label": "high", + "status": "pending", + "source_refs": [SOURCE_REFERENCE_EXAMPLE], + } + ], + "evidence": [ + { + "id": 1, + "type": "unit_test", + "reference": "tests/test_email_classification.py", + "strength": "strong", + "status": "pending", + "source_refs": [SOURCE_REFERENCE_EXAMPLE], + } + ], + } + ], + } + ], + } + ] + } + } + class EvidenceResponse(BaseModel): id: int @@ -454,6 +549,56 @@ class RepositoryAbilityMapResponse(BaseModel): repository: RepositoryResponse abilities: list[AbilityResponse] + model_config = { + "json_schema_extra": { + "examples": [ + { + "repository": REPOSITORY_EXAMPLE, + "abilities": [ + { + "id": 1, + "name": "Business Email Routing", + "description": "Route inbound messages to the right team.", + "confidence": 0.92, + "confidence_label": "high", + "capabilities": [ + { + "id": 1, + "name": "Classify Incoming Email", + "description": "Classify messages by intent.", + "inputs": ["subject", "body"], + "outputs": ["intent", "confidence"], + "confidence": 0.88, + "confidence_label": "high", + "features": [ + { + "id": 1, + "name": "POST /api/classify-email", + "type": "REST endpoint", + "location": "src/routes/classify_email.py", + "confidence": 0.84, + "confidence_label": "high", + "source_refs": [SOURCE_REFERENCE_EXAMPLE], + } + ], + "evidence": [ + { + "id": 1, + "type": "unit_test", + "reference": "tests/test_email_classification.py", + "strength": "strong", + "source_refs": [SOURCE_REFERENCE_EXAMPLE], + } + ], + } + ], + } + ], + } + ] + } + } + class IdResponse(BaseModel): id: int @@ -475,6 +620,29 @@ class SearchResultResponse(BaseModel): evidence_level: str | None = None source_reference: str | None = None + model_config = { + "json_schema_extra": { + "examples": [ + { + "repository_id": 1, + "repository_name": "MailRouter", + "match_type": "capability", + "match_name": "Classify Incoming Email", + "confidence": 0.88, + "confidence_label": "high", + "match_description": "Classify messages by intent.", + "matched_field": "capability.description", + "ability_id": 1, + "ability_name": "Business Email Routing", + "capability_id": 1, + "capability_name": "Classify Incoming Email", + "evidence_level": None, + "source_reference": None, + } + ] + } + } + class AbilitySummaryResponse(BaseModel): id: int diff --git a/tests/test_web_api.py b/tests/test_web_api.py index c19f7e9..9b49553 100644 --- a/tests/test_web_api.py +++ b/tests/test_web_api.py @@ -32,6 +32,16 @@ def test_openapi_groups_agent_facing_endpoints(): "get" ]["responses"]["200"]["content"]["application/json"]["schema"] assert ability_map_response["$ref"].endswith("/RepositoryAbilityMapResponse") + components = schema["components"]["schemas"] + assert components["SearchResultResponse"]["examples"][0]["match_type"] == ( + "capability" + ) + assert components["RepositoryAbilityMapResponse"]["examples"][0]["abilities"][0][ + "confidence_label" + ] == "high" + assert components["CandidateGraphResponse"]["examples"][0]["abilities"][0][ + "status" + ] == "pending" def test_api_manual_registry_loop(tmp_path):