Skip to content

feat(admin): deprecate the Admin API write path in favor of declarative configuration#776

Merged
moonming merged 1 commit into
mainfrom
feat/admin-write-deprecation
Jul 16, 2026
Merged

feat(admin): deprecate the Admin API write path in favor of declarative configuration#776
moonming merged 1 commit into
mainfrom
feat/admin-write-deprecation

Conversation

@moonming

Copy link
Copy Markdown
Collaborator

What

Admin API write endpoints (POST/PUT/DELETE across every resource collection, rotate included, on both the canonical api_keys and the former apikeys spelling) now signal in-band that they are deprecated in favor of the declarative configuration paths — a resources_file source (resources.yaml) or direct etcd writes. The endpoints remain fully functional: no request/response body, status code, or behavior changes — only the two response headers and the OpenAPI marking below.

Three surfaces:

  1. Runtime headers — every mutating /admin/v1/* response carries, per RFC 9745:
    • Deprecation: @1783929480
    • Link: <https://docs.api7.ai/ai-gateway/getting-started/self-hosted-quickstart>; rel="deprecation"
  2. OpenAPI — every write operation is marked deprecated: true with a description line pointing at the declarative paths; info.description explains the write-path deprecation once. Read operations are untouched.
  3. e2e smoke — the smoke test now boots the gateway the recommended way (file mode) instead of admin-write→proxy-read.

Header form: why Deprecation: @1783929480 and not true

RFC 9745 (the published IETF standard for this header) requires the value to be an RFC 9651 structured-field Date@<unix-timestamp>. The bare boolean true from earlier drafts is not valid in the final RFC. We deliberately promise no removal timeline, and the RFC supports exactly that: a past date means "the resource in context was deprecated at that date" and implies nothing about removal (that would be sunset signaling, a separate mechanism this PR intentionally does not emit). 1783929480 is the merge timestamp of 9b8b407, the change that shipped the file-based resource source — the factual point at which declarative configuration became the recommended standalone path.

The Link header uses the deprecation relation type registered by RFC 9745 §3, pointing at the published quickstart that documents the declarative configuration flow (the same docs URL family the README already references).

Chokepoint design

One router-level layer, deprecated_write_headers in crates/aisix-admin/src/lib.rs, stamps both headers. It shares a single is_admin_resource_write predicate with the existing file-managed write guard, so the two views of "a write" cannot drift. Properties:

  • Covers every current and future mutating /admin/v1/* route — a newly added write route cannot ship without the signal.
  • Wraps the file-managed guard, so file mode's 409 file-managed responses carry the headers too.
  • Status-independent: 200s, validation 4xxs, and the 409 all signal — the deprecation is a property of the endpoint, not of the outcome.
  • The read surface (GET/HEAD/OPTIONS, /admin/v1/models/status, /admin/v1/health, /admin/openapi.json) and non-resource endpoints (/playground/*, /livez, /readyz) are untouched. Link is appended, never inserted, so a handler-provided link relation can't be clobbered.

The OpenAPI marking mirrors the same idea: one programmatic pass (mark_admin_write_operations_deprecated) over the merged document instead of 29 hand-edited operations, running after the former-apikeys alias mirroring so those operations are covered too.

Smoke conversion

tests/e2e/src/cases/smoke.test.ts now boots from a declarative resources.yaml (the harness's file mode) and asserts the same observable contract as before: the file-defined model is visible on /v1/models, and a chat completion round-trips to the mock upstream exactly once at /v1/chat/completions. File mode is synchronous at boot, so the etcd-propagation polling scaffolding is gone, and the smoke no longer requires etcd at all.

Deliberate Admin-API-write coverage remains where it is marked: the seed-vs-admin characterization case and the two cases commented "Deliberately seeds via the Admin API" (openai-sdk-compat, datadog-exporter). openai-sdk-compat additionally pins the deprecation signal itself now: an admin write must answer with an RFC-9745-shaped Deprecation value (@<unix>) and a rel="deprecation" link, and an admin read must answer with neither.

Tests

  • Unit (aisix-admin): a representative create, a rotate, a former-spelling delete, and the file-managed 409 all carry both headers with the exact pinned values; GET reads, /admin/openapi.json, and the playground POST carry none; every OpenAPI write operation is deprecated: true with the declarative-paths description, and no read/non-resource operation is marked.
  • e2e: converted smoke (file mode) + the sdk-compat deprecation-signal case; full suite run locally.
  • cargo run -p aisix-admin --bin dump-openapi verified idempotent (two consecutive runs byte-identical); no checked-in artifacts change (resource schemas are untouched).
  • cargo fmt / cargo clippy --workspace --all-targets -- -D warnings / cargo test --workspace clean.

…ve configuration

Every mutating /admin/v1/* response now carries the RFC 9745
Deprecation header (@1783929480, the file-based resource source's
release timestamp) and a rel="deprecation" Link to the declarative-
configuration docs, stamped by one router-level layer that shares its
write predicate with the file-managed guard so new write routes can't
omit the signal and the file-mode 409 carries it too.

Write operations in the generated Admin OpenAPI are marked
deprecated: true via one programmatic pass, with descriptions pointing
at resources_file / direct etcd writes; reads are untouched.

The e2e smoke now boots from a declarative resources.yaml (file mode)
instead of admin-write -> proxy-read, and the openai-sdk-compat
deprecation-window case pins the header contract on a live admin
write.
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@moonming, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 7 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c63bd559-bb8e-4342-be05-f520ba2b140f

📥 Commits

Reviewing files that changed from the base of the PR and between 1f28acb and da8177d.

📒 Files selected for processing (4)
  • crates/aisix-admin/src/lib.rs
  • crates/aisix-admin/src/openapi.rs
  • tests/e2e/src/cases/openai-sdk-compat.test.ts
  • tests/e2e/src/cases/smoke.test.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/admin-write-deprecation

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@moonming moonming merged commit 6f7dfbc into main Jul 16, 2026
10 checks passed
@moonming moonming deleted the feat/admin-write-deprecation branch July 16, 2026 04:32
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