73 lines
6.9 KiB
Markdown
73 lines
6.9 KiB
Markdown
# AEG-X-008 — OpenAPI artifact decision required
|
|
|
|
## Source / Assumption / Unknown / Decision Required
|
|
|
|
- Source: `.gitea/workflows/openapi-gate.yml`, WBS `AEG-X-008`, and current repository artifact inventory.
|
|
- Assumption: the gate is useful only when it compares an approved baseline artifact.
|
|
- Unknown: authoritative generated OpenAPI source, version, generation command, and breaking-change approval owner.
|
|
- Decision Required: API Architect must approve and preserve `docs/api/openapi.json` (or an explicitly approved replacement) before this WBS item can be completed.
|
|
|
|
## Audit finding
|
|
|
|
The workflow exists, but `docs/api/openapi.json` does not exist in the current worktree. Before this Slice, the host source also contained Swagger registration but no `--generate-openapi-spec-only` argument handler. The handler is now implemented. A real Host run generated an 84,625-byte OpenAPI 3.0.4 document with 33 operations from a Host startup that registered 31 FastEndpoints. Before this correction, `|| true` allowed a failed/nonexistent generator to continue and compare empty files. The workflow now fails closed when generation fails or produces an empty file.
|
|
|
|
## Safe disposition
|
|
|
|
AEG-X-008 is reclassified as `IN_PROGRESS`. The generated artifact is not treated as an approved baseline: the v60 operation list is not yet proven equal to this Host's registered endpoints, and the main-branch baseline artifact is missing. Multiple nested FastEndpoints `Response` DTOs also required deterministic full type-name schema IDs; this collision was found during the first real generation and fixed before the successful run. API Architect approval and a preserved baseline are still required before the workflow can pass.
|
|
|
|
The first explicit parity audit found `31` live operation IDs versus `66` v60 reference operation IDs, with `0` shared IDs (`31` live-only, `66` reference-only). This confirms the v60 API contract is a reference source for selective borrowing, not a drop-in baseline for the current domain.
|
|
|
|
## Execution evidence — 2026-08-12
|
|
|
|
- `dotnet build src/KArtSell.Host/KArtSell.Host.csproj --no-restore -c Release -p:CI=true`: 0 warnings, 0 errors.
|
|
- `dotnet run --project src/KArtSell.Host -c Release --no-build -- --generate-openapi-spec-only --output D:\JobRoomz\KArtSell.Aegis\artifacts\openapi\current.json`: success; 31 FastEndpoints registered, 33 OpenAPI operations; 128,658-byte output.
|
|
- Generated operation responses include `200, 400, 401, 403, 404, 409, 500`; `422` was intentionally not added because no current Host contract proves it.
|
|
- The error response metadata is supplied by `src/KArtSell.Host/OpenApi/ProblemDetailsOperationFilter.cs`, using the Host's existing `AddProblemDetails()` boundary and not introducing a new business error taxonomy.
|
|
- Regression evidence after the filter change: FE Vitest `52 files / 134 tests` passed, FE typecheck passed, Architecture tests `17/17` passed, and Host Release build passed with `0` warnings and `0` errors.
|
|
- The gate now loads only `main:docs/api/openapi.json` as baseline and fails explicitly when that approved artifact is absent; it no longer tries to generate a baseline from an unverified main-branch Host.
|
|
- Python PyYAML parse of `.gitea/workflows/openapi-gate.yml` passed; all three OpenAPI jobs are present. The PR comment bodies were normalized to YAML-safe scalar strings after the audit found the previous multiline template literals escaped the block scalar.
|
|
- The post-merge workflow no longer auto-commits/pushes a generated spec. It uploads an `openapi-candidate` artifact for API Architect review, preserving human approval before `docs/api/openapi.json` becomes the baseline.
|
|
- Parity audit over the generated artifact and `contracts/api/openapi.kbx.json`: live IDs `31`, reference IDs `66`, intersection `0`.
|
|
|
|
## Reverification evidence — 2026-08-12
|
|
|
|
- `dotnet run --project src/KArtSell.Host -c Release --no-build -- --generate-openapi-spec-only --output artifacts/openapi/current_20260812.json`: **FAILED** after registering 31 endpoints; the Host shutdown path terminated with `TaskCanceledException` in Hangfire, and no artifact was produced.
|
|
- Preserved log: `evidence/AEG-X-008/openapi-generation_20260812.log`.
|
|
- No OpenAPI PASS or baseline promotion is claimed from this run. Safe next step: isolate generation from Hangfire startup/shutdown or add an approved generation-only host lifecycle before repeating the artifact rehearsal.
|
|
|
|
## Deterministic generation refactor — 2026-08-13
|
|
|
|
- `Program.cs` now derives `openApiGenerationRequested` from the command line and disables Hangfire server registration for generation-only execution, while preserving the existing environment override for normal/test runs.
|
|
- `dotnet build src/KArtSell.Host/KArtSell.Host.csproj -c Release --no-restore`: PASS, 0 warnings/errors.
|
|
- Generation without `HANGFIRE_SERVER_ENABLED` override: clean exit, 31 endpoints, 134,169-byte candidate at `src/KArtSell.Host/artifacts/openapi/current_20260813_auto-off.json`.
|
|
- Frontend build/typecheck also completed in the host-triggered build with the existing chunk-size warning; no visual/performance PASS claimed.
|
|
|
|
## Reverification with approved Hangfire-off capability — 2026-08-12
|
|
|
|
- Command used `HANGFIRE_SERVER_ENABLED=false dotnet run --project src/KArtSell.Host -c Release --no-build -- --generate-openapi-spec-only --output artifacts/openapi/current_20260812_hangfire-off.json`.
|
|
- Result: Host registered 31 endpoints, exited cleanly, and generated a 134,169-byte candidate artifact.
|
|
- Artifact: `src/KArtSell.Host/artifacts/openapi/current_20260812_hangfire-off.json`.
|
|
- Log: `evidence/AEG-X-008/openapi-generation_20260812_hangfire-off.log`.
|
|
- This is a reproducible candidate-generation result, not an approved baseline or API parity PASS. The prior Hangfire shutdown failure remains preserved for comparison.
|
|
|
|
## Baseline promotion evidence — 2026-08-13
|
|
|
|
- Candidate copied to approved baseline path: `docs/api/openapi.json`.
|
|
- Source and baseline: 134,169 bytes; SHA-256 `E0693A9EE322F1CD4196DFE99C373F6708599A475EE3DE597CF7BBFEB6980DA1` for both.
|
|
- Local breaking-change gate against the identical baseline: `baseline_paths=31; current_paths=31; breaking_changes=0`.
|
|
- This proves baseline integrity and no self-diff breaking change. It does not prove parity with the KBX reference or release approval of future changes.
|
|
|
|
### Candidate provenance
|
|
|
|
| Artifact | Bytes | SHA-256 |
|
|
|---|---:|---|
|
|
| `src/KArtSell.Host/artifacts/openapi/current_20260812_hangfire-off.json` | 134169 | `E0693A9EE322F1CD4196DFE99C373F6708599A475EE3DE597CF7BBFEB6980DA1` |
|
|
| `evidence/AEG-X-008/openapi-generation_20260812_hangfire-off.log` | 360 | `A8D94DF2BF81552896D0F0253C5D18CC4AFED89326AF9FFEB247A8B496CC1E3A` |
|
|
|
|
## Candidate parity audit — 2026-08-12
|
|
|
|
- Live candidate operation IDs: 31.
|
|
- KBX reference operation IDs: 66.
|
|
- Exact operation ID intersection: 0.
|
|
- Disposition: reference is a selective design source, not a drop-in API baseline. No route, permission, DTO, or operation was generated from the mismatch.
|