mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-07 18:51:32 +00:00
3c81531398
Phase 5 reconciliation: the audit's headline framing 'ARCH-H1 = 62-route
OpenAPI gap' was a measurement scoping error. Every one of the 209
unique router routes is already accounted for — 154 in api/openapi.yaml,
55 in api/openapi-handler-exceptions.yaml. The existing
openapi-handler-parity.sh CI guard already enforces this and passes
clean today. The audit subtracted operation-count from route-count
without accounting for the documented exceptions YAML.
Where real work remains (and what this PR does about it)
=========================================================
Of the 64 documented exceptions, 35 are legitimate wire-protocol
carve-outs that MUST stay (SCEP RFC 8894 × 8 entries, ACME RFC 8555
default + per-profile × 27 entries — they're protocol contracts, not
REST resources). The remaining 29 are REST-shaped routes whose
OpenAPI ops were deferred during their original Bundle 2 /
audit-2026-05-10 / 2026-05-11 work:
- auth/sessions (3)
- auth/oidc admin (9)
- auth/breakglass admin (4)
- auth/users mgmt (3)
- auth/runtime-config (1)
- auth/demo-residual/cleanup (1)
- audit/export (1)
- auth/logout (1)
- auth/breakglass/login (1)
- auth/oidc {login,callback,bcl} (3)
- oidc/providers/{id}/jwks-status (1)
- + 2 other auth-flow routes
Burn-down plan in 3 sprints (documented in
api/openapi-handler-exceptions.yaml header):
Sprint A: Cluster 1 — sessions + oidc admin (12 ops)
Sprint B: Cluster 2 — breakglass + users + runtime-config (8 ops)
Sprint C: Cluster 3 — audit/export + auth flows (9 ops)
This PR does NOT author the 29 OpenAPI ops; each needs request/
response schemas, not placeholders, and the design work is too
large for one PR. The reconciliation here is documentation + a CI
guard that will fail any future schema-drift, plus the scaffolding
needed for sub-phase 5b.
Sub-phase 5b: codegen scaffolding
==================================
Adds the orval scaffolding without running npm install (sandbox
disk-full; first 'npm install' + 'npm run generate' happens on the
operator's workstation):
- web/orval.config.ts — codegen config emits react-query hooks
from api/openapi.yaml into web/src/api/generated/
- web/package.json — adds orval@^7.0.0 devDep + 'generate' npm script
- web/CODEGEN.md — operator-facing migration doc:
first-time setup, per-consumer migration pattern, burn-down plan,
CI-guard rules
- scripts/ci-guards/openapi-codegen-drift.sh — blocks the build
when api/openapi.yaml changes but web/src/api/generated/ wasn't
regenerated alongside. Currently no-op (the directory doesn't
exist yet); activates from the first 'npm run generate' run.
The legacy web/src/api/client.ts stays in tree per the phase prompt's
'do not delete in same PR as codegen' rule. Consumers migrate one
page at a time as their OpenAPI ops land; client.ts deletion is a
SEPARATE follow-up PR after the last consumer migrates.
Updates to existing guard + exceptions YAML
============================================
- scripts/ci-guards/openapi-handler-parity.sh header rewritten
with the Phase 5 reconciliation numbers (220/158/64/0) and the
wire-protocol vs REST-deferred classification.
- api/openapi-handler-exceptions.yaml header rewritten with the
35/29 split + the 3-sprint burn-down plan. Each exception entry
is unchanged; the header now documents which entries are
permanent (wire-protocol) vs temporary (REST-deferred).
Sandbox limitations + operator follow-up
=========================================
- 'npm install' was NOT run from the sandbox (sessions volume
99%-full, 142 MB free). The operator runs 'cd web && npm install'
on their workstation; this lands orval@^7.0.0 in node_modules,
then 'cd web && npm run generate' produces the initial
web/src/api/generated/ tree.
- First per-consumer migration (suggested: web/src/pages/AuthSettings
or one of the operator-decision pages) lands in a follow-up PR
after npm install completes.
- The 29-op OpenAPI burn-down is a 2-sprint effort tracked under
ARCH-H1 in cowork/certctl-architecture-diligence-audit.html.
All CI guards (openapi-handler-parity, openapi-codegen-drift, plus
every existing guard) verified clean by running each individually.
Closes:
- cowork/certctl-architecture-diligence-audit.html#fix-ARCH-H1
(reconciliation: gap is 0 with exceptions accounted for; burn-down
plan documented for follow-up sprints)
- cowork/certctl-architecture-diligence-audit.html#fix-ARCH-M6
(codegen scaffolding shipped; client.ts deletion follows in a
subsequent PR after consumers migrate)
87 lines
3.4 KiB
TypeScript
87 lines
3.4 KiB
TypeScript
/**
|
|
* Phase 5 ARCH-M6 scaffolding (2026-05-13).
|
|
*
|
|
* Orval config for the certctl frontend. Reads ../api/openapi.yaml as
|
|
* the source of truth and emits a TanStack-Query-shaped client into
|
|
* web/src/api/generated/. Output is git-tracked; the
|
|
* scripts/ci-guards/openapi-codegen-drift.sh guard fails the build
|
|
* when api/openapi.yaml changes but the generated/ tree wasn't
|
|
* regenerated alongside.
|
|
*
|
|
* Pairs with frontend-design-audit Phase 2 (TanStack tier model). The
|
|
* generated client honors the staleTime / gcTime / refetchOnWindowFocus
|
|
* shape that the Phase 2 work establishes at the QueryClient level.
|
|
*
|
|
* Sub-phase 5b status (2026-05-13):
|
|
* - This config exists.
|
|
* - 'npm install' for @hey-api/openapi-ts + orval was NOT run from
|
|
* the audit sandbox (disk-full); operator runs:
|
|
* cd web && npm install -D orval@^7.0.0
|
|
* cd web && npm run generate
|
|
* in the first follow-up sprint. The generated tree lands as
|
|
* web/src/api/generated/{certctl.ts,certctl.msw.ts,model/*.ts}.
|
|
* - client.ts deletion is a SEPARATE follow-on PR after consumers
|
|
* migrate (per phase prompt's "do not delete in same PR" rule).
|
|
*
|
|
* Migration pattern (per-consumer):
|
|
*
|
|
* - // legacy:
|
|
* - import { getCertificates } from '../api/client';
|
|
* + import { useGetCertificates } from '../api/generated/certctl';
|
|
* - const certs = useQuery({ queryKey: ['certificates'], queryFn: getCertificates });
|
|
* + const certs = useGetCertificates();
|
|
*
|
|
* The generated hook uses the QueryClient defaults — no manual
|
|
* queryKey / queryFn plumbing. Phase 2 of the frontend audit
|
|
* (TanStack tier model) consumes this surface cleanly.
|
|
*/
|
|
|
|
import { defineConfig } from 'orval';
|
|
|
|
export default defineConfig({
|
|
certctl: {
|
|
input: {
|
|
// Source-of-truth OpenAPI doc. Co-located one directory up.
|
|
target: '../api/openapi.yaml',
|
|
},
|
|
output: {
|
|
// All generated code lives under web/src/api/generated/.
|
|
// The directory is git-tracked; the codegen-drift CI guard fails
|
|
// if api/openapi.yaml changes and the generated tree wasn't
|
|
// regenerated alongside.
|
|
target: './src/api/generated/certctl.ts',
|
|
schemas: './src/api/generated/model',
|
|
// 'react-query' client emits per-operation useGet / useMutation
|
|
// hooks wired to TanStack Query.
|
|
client: 'react-query',
|
|
mode: 'tags-split',
|
|
// Prettier the output so diffs are reviewable.
|
|
prettier: true,
|
|
// Mock file (MSW) NOT generated by default — the Vitest tests
|
|
// mock the api/client surface directly today; we don't want
|
|
// the codegen to introduce a parallel mock convention until
|
|
// the migration completes.
|
|
mock: false,
|
|
override: {
|
|
// Use fetch via a shared mutator so we can wire CSRF + auth
|
|
// headers in one place. The mutator file lives at
|
|
// web/src/api/mutator.ts (lands in the same PR that runs
|
|
// 'npm run generate' the first time).
|
|
mutator: {
|
|
path: './src/api/mutator.ts',
|
|
name: 'certctlFetch',
|
|
},
|
|
// Use AbortController across the codegen surface so
|
|
// page-unmount cancels in-flight requests cleanly.
|
|
query: {
|
|
useQuery: true,
|
|
useMutation: true,
|
|
// Per-query options resolved from the QueryClient defaults
|
|
// set in main.tsx (frontend audit Phase 2 TQ-H2 / TQ-M1
|
|
// tier model).
|
|
},
|
|
},
|
|
},
|
|
},
|
|
});
|