跳到內容

API Surface Boundary

本頁內容尚未翻譯。

Status: Accepted

Date: 2026-07-24

Route prefixes are caller and compatibility contracts, not only URL organization. More-specific prefixes take precedence over the general /api/** Web convention.

SurfaceIntended callersAuthentication and compatibility
/api/v1/**CLI, SDK, agents, MCP, and external integrationsEach endpoint documents its supported public identity: CallerIdentity, API key, bot token, or an explicit user-only v1 exception. The schema, errors, pagination, idempotency, and rate-limit behavior are backward-compatible public contracts.
/api/public/**Anonymous or token-bearing delivery consumersAuthentication is resource-specific. These routes are public delivery contracts, not Web aliases and not API v1 resources.
/api/admin/**First-party operators and admin toolsRoutes require AuthAdmin or an equivalent admin guard. They are not made public by living under /api.
/api/auth/**Browser authentication and session bootstrapAuthentication routes follow their own bootstrap and session rules. They are not deprecated as a group.
Other /api/**The first-party Web applicationRoutes use AuthUser or an equivalent session-oriented guard. Frontend and backend deploy together, so request and response shapes may evolve through a coordinated change.
/ws, /ws/agent, /ws/voiceFirst-party realtime clients and supported agent clientsTheir handshake and message protocols are governed separately from HTTP route deprecation.
/healthz, /readyz, /metricsInfrastructure and diagnosticsThese paths are operational surfaces and are outside API route deprecation.

An existing Web route that still admits an API key through a shared AuthUser extractor is transitional compatibility debt. It does not make /api/** a public SDK surface, and new external consumers must not depend on it.

API v1 may include deliberately documented user-only exceptions, but its route shape is still a public compatibility contract. Moving the Web away from a v1 route does not authorize deleting, redirecting, or behavior-changing that route. API v1 remains operational for CLI, SDK, agent, MCP, and external callers.

The product-by-product Office ownership, supported identities, Action families, public delivery routes, and intentional Scene/Insights exclusions are pinned in Office Web, API v1, and Action surface compatibility.

For Web-owned /api/** routes:

  • The Web client and backend change together.
  • A breaking payload change must update all in-repository Web callers in the same delivery unit.
  • A Web route is not implicitly promised to third-party callers.

For /api/v1/** routes:

  • Additive changes must preserve existing callers.
  • Existing field names, stable error codes and statuses, pagination semantics, idempotency behavior, and rate-limit behavior remain compatible.
  • Breaking changes require a new API version or the exception process in API v1 lifecycle.
  • The Web migration must not remove or weaken any supported v1 authentication mode.

Public delivery, admin, authentication, infrastructure, and websocket surfaces keep their own contracts. They must not inherit lifecycle headers merely because their path begins with /api.

Web and v1 routes may expose the same product capability without duplicating its implementation. The allowed patterns are:

  1. Mount the same handler at two roots only when authentication and response contracts are identical.
  2. Use two thin route adapters when authentication, input, or response shapes differ.
  3. Put database access and business rules in a shared service or domain function called by those adapters.

The following patterns are forbidden:

  • Copying a route module and changing only its prefix.
  • A Web handler making an HTTP request to /api/v1.
  • A v1 handler calling a Web handler.
  • Changing a v1 response solely to satisfy a Web-only need.
  • Weakening v1 authentication so a Web alias is easier to mount.

apps/rust-server/src/middleware/deprecation.rs uses a reviewed registry of exact paths or segment-bounded prefixes. A route not in that registry receives neither Deprecation nor Sunset from the global middleware. The middleware also preserves more-specific lifecycle headers supplied by a route handler.

Every global registry entry must have an owner, a successor or migration path, and an approved sunset recorded here:

MatchOwnerSuccessorSunset
Exact /api/creator/payoutCreator API (routes/creator.rs)POST /api/creator/earnings/convert-to-creditThu, 31 Dec 2026 23:59:59 GMT

The creator route already emits its route-owned sunset. Until that instant it continues to delegate to the successor for compatibility. At the sunset the deprecation middleware stops the request before authentication, body parsing, or mutation and returns 410 CREATOR_PAYOUT_RETIRED with the successor in the Link header and error details. The request-time boundary is covered with a fixed clock, and the test also proves the reviewed HTTP date and epoch cannot drift apart.

There is no global sunset fallback. Every registry entry owns its reviewed HTTP date, retirement epoch, successor link, and retirement response in the same typed policy. A route cannot be registered without those values.

Method-specific deprecations may remain in their owning handler when a path-level middleware rule would be too broad. Adding either kind of deprecation requires route-specific migration documentation and tests; a namespace-wide rule is not acceptable.

Production Web code must stop requesting /api/v1/**. The only intended v1 string remnants are:

  • apps/web/src/lib/image-assets/url.ts parsing historical /api/v1/image-assets/** stored URLs.
  • apps/web/src/lib/image-assets/external.ts rejecting historical managed image URLs when validating an external URL.
  • apps/web/src/app/(rail)/office/webhooks/webhook-types.ts displaying /api/v1/webhooks/inbound/{id} for external senders.

The first two are compatibility recognition, not API calls. The webhook URL is an external integration contract and is displayed rather than invoked by the Web application.

The five vertical migrations moved 77 normalized frontend route templates (100 method/path combinations) to their Web surfaces:

  • File Center and workbooks.
  • Memories, notes, memo, search, resolution, and action history.
  • Managed images, external images, and image projects.
  • Autopilot, workflows, Cron, triggers, and webhook management.
  • Skills, image edit, and Web analytics.

scripts/check-web-api-boundary.cjs scans production files under apps/web/src and rejects unapproved /api/v1/** string or template construction. Tests, specs, fixtures, generated output, and e2e mocks are excluded. The allowlist is exact by file and route prefix, so an approved compatibility file cannot introduce another v1 route family or a second literal for the approved family.

Run the guard directly with:

Terminal window
pnpm run check:web-api-boundary

It is also part of the Web check:ci-static command. Backend inventory generation covers the migrated Web routes and the retained action route table; all pre-migration v1 method/path entries remain present for public callers.

Build a7f47a5ca54ddcf7806cd48b81ce1b9827042766