Publish API documentation for consumers #124
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/publish-openapi-docs"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Task 119.
Already existed (ADR-0029, ticket #60): the API describes itself at
/openapi/v1.json, Swagger UI at/swagger, everywhere except Production; the bearer scheme and per-operation security requirement, proved against the shipped API.Gap found: the document said nothing about ADR-0043's group-role requirements — an endpoint filter, not
IAuthorizeData, so it never reached the document.GroupCapabilityDescriptionTransformerappends a role-requirement sentence to the operation description wherever.RequireGroupCapability(...)/.RequireGroupCapabilityForPlace(...)is attached. Proved against the shipped API the same way as the existing security-requirement test; both directions mutation-tested (transformer unregistered → sweep test reddens; transformer over-declaring → the unprotected-probe test reddens).Gap found: "accessible to the team" isn't met by the live document alone any more. ADR-0104/0106's full-stack Compose container doesn't set
ASPNETCORE_ENVIRONMENT, which defaults to Production, so/openapiand/swagger404 on the one shared instance this repo can stand up — confirmed against the running container. Exported a snapshot todocs/openapi/v1.json, committed, regenerated by hand — ADR-0108 argues the mechanism and states plainly that nothing checks it against the live document yet.Full suite (Domain/Contracts/Infrastructure/Api/Architecture/WebUI) and coverage ratchet green on the pinned SDK;
dotnet format --verify-no-changesclean.Verdict: mergeable
CI #543 green on
2a4b115, head unchanged. Full test suite anddotnet format --verify-no-changesre-run locally, clean.The sweep test's coverage claim, checked precisely.
GetOpenApiDocument_EveryShippedEndpointCarryingAGroupCapabilityRequirement_StatesTheRoleItNeedsbuilds its expectations fromendpoint.Metadata.GetMetadata<GroupCapabilityMetadata>(), filtering out any endpoint that doesn't carry it — so in isolation it only proves "every endpoint carrying the metadata is documented correctly," not "every endpoint that should be role-gated is." That narrower reading is real. It stops short of being a gap becauseGroupScopedEndpointAuthorisationTests(pre-existing, ADR-0043) independently guards the other half: every route under/api/groups/{groupId}/...or/api/places/{id}/...must carry the metadata, with exactly two named, tested carve-outs (the invitation accept/decline routes). Checked that this combination actually coversGroupEndpoints' own routes too, not justPlaceEndpoints' —PlaceEndpoints.RoutePrefixandGroupEndpoints.RoutePrefixare both literally/api/groups, so the shared prefix match catches both families. The two tests together do deliver "the spec matches enforcement" for every group-scoped route; neither one alone does. Minor: this composition isn't stated anywhere a reader of just the new test would see it — the private helper's doc comment mentionsGroupScopedEndpointAuthorisationTestsonly in passing, not why it closes the gap. Worth a line, not a blocker.Both mutation directions confirmed independently, not trusted from the PR description: unregistering
GroupCapabilityDescriptionTransformerinOpenApiDocumentationExtensionsreddened the sweep test (GET /api/groups/{groupId}: expected the document to state its Member requirement); making the transformer describe every operation regardless of metadata (defaulting toOwner) reddenedGetOpenApiDocument_UnprotectedProbe_StatesNoGroupRoleRequirementagainst/health/live. Both restored clean.Snapshot honesty, confirmed. ADR-0108 states plainly that nothing checks
docs/openapi/v1.jsonagainst the live document ("a materially weaker guarantee than every other generated artefact this repository commits... a known, accepted gap, not an oversight left unstated"), and the README repeats it ("treat it as a point-in-time export rather than a live one"). Spot-checked the committed snapshot is a real export, not stale or hand-typed: its path list matches the live-document test's expected 26 paths exactly, andDELETE /api/groups/{groupId}carries the new "Requires the Owner role in this group" sentence.ASPNETCORE_ENVIRONMENTnot touched. No changes todocker-compose.ymlor either Dockerfile in this PR; ADR-0108 explicitly considers and rejects setting it on the Composeapiservice, for the right reason (nothing today distinguishes "the full-stack Compose profile" from "a real Production deployment" except that variable).Nothing else to flag.