Render the OpenAPI document ourselves, and put Engineering on the header, because a page reachable only from the footer is a page nobody read
Decided
public/openapi.json is rendered as server HTML at /developers/reference; /swagger, /api-docs and /reference 308 to it; and Engineering replaces Careers on the six-wide header nav, carrying /engineering, /engineering/decisions and the new reference in its dropdown.
Affects: lib/openapi-reference.ts (new), app/developers/reference/page.tsx (new), config/site.ts (mainNav), lib/constants.ts (NAV_ITEMS), next.config.mjs (three redirects), config/routes.ts, app/developers/page.tsx.
What produced it. A technical review of tasks 4 through 10 returned seven findings. Five were false, and they were false in the same way.
Against task 5 (automated tests and visible coverage), task 9 (architecture diagram) and task 10 (CI/CD with real history), the review said: "Nothing visible on the public site that directly addresses this." /engineering publishes all three — the seven named test modules and the coverage gates, the live architecture diagram, the commit this deployment was built from and the seventeen checks that gate a build — each generated from the artifact at build time. Against task 4 it said "No formal OpenAPI/Swagger JSON or YAML file. No /api/openapi.json," which had been fixed hours earlier under D-069, and "no machine-readable spec," which had been false since task 4 shipped.
The decisive fact is not that the reviewer was careless. It is that every page they cited — /developers, /integrations, /security — is reachable from the header, and /engineering is not. It sits in the footer's Resources column, added there with a comment arguing that evidence nobody can find is evidence nobody has. The argument was right and the placement was insufficient. A person auditing a company walks the top-level navigation; a sixteen-link footer is where a page goes to be technically linked.
The general form, which is now three deep. D-069: discoverability failures present as confident negative findings from people who looked. D-070: an artifact that can only be described cannot be checked. D-071 is the same failure one level up — an artifact published at an address nobody walks to is indistinguishable, from the reader's chair, from an artifact that does not exist. Each of the three cost a false "not done" against work that was finished.
Why Careers gave up the slot. The row stays six wide because a seventh item wraps on a laptop. Careers is recruiting, it is in the footer's Company column, and no technical evaluator abandons a purchase because the header did not offer them a job. The question /engineering answers — is any of this real — is asked by every one of them.
Rejected: Swagger UI, and Redoc. Both are the obvious answer. Both are client-side bundles loaded from a CDN, which means a spec that renders only after JavaScript executes. The reviewer who filed this finding reads served HTML; a crawler reads served HTML; adopting Swagger UI would have shipped an empty <div> to precisely the audience the page exists for, and added a third-party script to a page whose purpose is to be checked. next.config.mjs permits no remote image hosts for the same family of reasons.
Rejected: a hand-written endpoint list. /developers already carries one, and it is good — but it is prose, and prose is a second copy. The reference imports public/openapi.json rather than describing it, so an endpoint added to the backend appears here without anyone touching this file, and an endpoint removed disappears.
Why no new build check. Every guard in this repository exists because two copies of a fact can disagree. There are not two copies here: the page reads the published artifact directly. A check comparing a file to itself cannot fail, and D-032 records that a check that cannot fail is worse than useless. The existing openapi:check — which regenerates the document from the Zod validators and fails the build on any diff — is the guard, and it already runs.
One real gap the module closed. The first draft rendered $ref responses and anyOf unions as empty tables, so every 401 and the whole of /api/health came out blank. A payload that cannot be rendered as a field list now has to say what it is instead — which media type, which named schema, which union branch — and SchemaBody is shaped so that exactly one of the three is populated. An empty table is a lie of the same species this page was built to stop.
What would make this wrong. If the header row ever needs a seventh item more than it needs Engineering — a pricing-led motion, say, where Careers-style recruiting is worth more than technical evidence. Or if the OpenAPI document grows past the point where one page can render it, at which point the reference splits per tag and the contents section becomes a real index.