Skip to content

feat(api): TRA-743 — single-source OpenAPI spec (remove contact.url, add Cache-Control)#357

Merged
mikestankavich merged 1 commit into
mainfrom
feat/tra-743-openapi-single-source
May 16, 2026
Merged

feat(api): TRA-743 — single-source OpenAPI spec (remove contact.url, add Cache-Control)#357
mikestankavich merged 1 commit into
mainfrom
feat/tra-743-openapi-single-source

Conversation

@mikestankavich
Copy link
Copy Markdown
Contributor

Summary

TRA-743 — platform side of the "eliminate docs-side mirror, single source on platform" pivot.

PR #356 (TRA-742) swapped the drifted info.contact.url value for https://docs.trakrf.id/ as a stop-gap. This PR removes the field entirely so docs.trakrf.id can redirect spec asset requests to the platform origin without re-introducing the same drift class TRA-742 patched.

The companion trakrf-docs PR (separate session, this user's feedback_docs_prs_separate_checkout convention) will land the Cloudflare _redirects file, delete the mirror scripts (refresh-openapi.sh, swap-openapi-env.mjs, generate-postman.mjs, check-spec-sync.sh, platform-meta.json), remove the static spec assets, and rewrite the Postman page to URL-import guidance.

Spec changes

  • Remove info.contact.url from apispec/postprocess.go's public-spec branch. info.contact.{name,email} remain authoritative for support routing; the bare-hostname servers[] block continues to differentiate preview vs prod.
  • Disable Zalando must-have-info-contact-url in .spectral.yaml with rationale linking back to this ticket. info.contact.name and info.contact.email continue to satisfy the broader rule 218 "MUST have API meta information" intent.

Cache-Control

  • Cache-Control: public, max-age=60, stale-while-revalidate=300 added to all four spec handlers (internal + public × json + yaml). Caps origin load during codegen / BB probe storms; the stale-while-revalidate window lets the CF edge serve briefly stale bytes while it refreshes in the background. The spec only changes on deploy, so the staleness window is bounded by deploy cadence.

Audit sweep

  • Single-entity finding: only the public spec ever set info.contact.urlpostprocessInternal doesn't touch contact at all. Field-removal scope is correctly limited to the public path.
  • No platform-side env-aware swap machinery remains; PR feat(api): TRA-742 — BB43 F1+F2 openapi hygiene (contact URL + asset/location field-doc symmetry) #356 already removed swaggerspec.resolvePublicSpec and its associated tests.
  • Cache-Control sweep covers all four serve handlers (previous test coverage only exercised the two public ones — backfilled TestServeJSON / TestServeYAML for the internal pair so the header assertion runs uniformly).

CORS — deferred

Per ticket, the 302 redirect path from docs.trakrf.idapp.{env}.trakrf.id/api/v1/openapi.{yaml,json} works for browser navigation, curl, and programmatic fetch without needing Access-Control-Allow-Origin on the spec endpoint. Revisit if the docs site adds browser-side spec rendering (Stoplight Elements, etc.) that would fetch the spec via XHR/fetch against a different origin.

Test plan

  • just backend api-spec regenerates clean; only diff in docs/api/openapi.public.{yaml,json} is the removed contact.url line
  • just backend lint (fmt + vet) clean
  • go test ./... — all 33 backend packages pass
  • just backend api-lint (Redocly) clean (2 pre-existing warnings unrelated to this change)
  • pnpm exec spectral lint docs/api/openapi.public.yaml --ruleset .spectral.yaml — 0 issues
  • Preview deploy: curl -I https://app.preview.trakrf.id/api/v1/openapi.yaml shows Cache-Control: public, max-age=60, stale-while-revalidate=300
  • Preview deploy: curl -s https://app.preview.trakrf.id/api/v1/openapi.yaml | grep -A3 'contact:' confirms url absent
  • Docs-side redirect PR lands separately and curl -L https://docs.preview.trakrf.id/api/openapi.yaml returns the preview platform spec (verified at ticket close, not in this PR)

Out of scope

  • Cloudflare _redirects file, mirror-script deletions, Postman page rewrite — separate trakrf-docs PR per the ticket's two-PR sequencing.
  • Monorepo collapse (folding trakrf/docs into trakrf/platform) — explicitly deferred in the ticket as a post-launch reconsideration.

🤖 Generated with Claude Code

…add Cache-Control)

Platform side of TRA-743's "eliminate docs-side mirror, single source on
platform" pivot. The TRA-742 PR (#356) traded the drifted contact.url
for the docs.trakrf.id homepage; this PR removes the field entirely so
docs.trakrf.id can redirect spec asset requests to the platform origin
without re-introducing the same drift class.

Changes:
- Drop the info.contact.url assignment from apispec/postprocess.go's
  public spec branch. info.contact.{name,email} remain authoritative
  for support routing; the bare-hostname servers[] block continues to
  differentiate preview vs prod.
- Disable the inherited Zalando must-have-info-contact-url Spectral
  rule with rationale referencing this ticket. info.contact.name +
  info.contact.email continue to satisfy the broader "MUST have
  contact info" intent (rule 218).
- Add `Cache-Control: public, max-age=60, stale-while-revalidate=300`
  to all four spec handlers (internal + public, json + yaml). Caps
  origin load during codegen/probe storms; stale-while-revalidate lets
  CF serve briefly stale bytes while it refreshes in the background.
- Backfill missing serve-handler tests for internal-spec endpoints so
  the Cache-Control sweep is covered uniformly across all four
  endpoints, not just the previously-tested public ones.

Audit-sweep finding: only the public spec ever set info.contact.url
(postprocessInternal doesn't touch contact at all), so the field-
removal scope is single-entity. No platform-side env-aware swap
machinery remains — PR #356 already removed swaggerspec.resolvePublicSpec.

CORS: deferred per ticket. The 302 redirect path from docs.trakrf.id
works for browser navigation, curl, and programmatic fetch without
needing Access-Control-Allow-Origin on the spec endpoint. Revisit if
docs.trakrf.id adds browser-side spec rendering against the platform
origin.

Out of scope (separate trakrf-docs PR): _redirects file, deleting
mirror scripts (refresh-openapi.sh, swap-openapi-env.mjs,
generate-postman.mjs, platform-meta.json, check-spec-sync.sh), static
spec asset removal, Postman page rewrite to URL-import guidance.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

🚀 Preview Deployment Update

✅ This PR has been successfully merged into the preview branch.

The preview environment will update shortly at: https://app.preview.trakrf.id

@railway-app railway-app Bot temporarily deployed to trakrf / production May 16, 2026 13:49 Inactive
@mikestankavich mikestankavich merged commit 87d67f3 into main May 16, 2026
16 checks passed
@mikestankavich mikestankavich deleted the feat/tra-743-openapi-single-source branch May 16, 2026 14:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant