Skip to content

feat(apidocs): Name the internal spec's inline responses - #129824

Open
billyvg wants to merge 9 commits into
billyvg/feat/apidocs-internal-specfrom
billyvg/feat/apidocs-name-inline-responses
Open

billyvg wants to merge 9 commits into
billyvg/feat/apidocs-internal-specfrom
billyvg/feat/apidocs-name-inline-responses

Conversation

@billyvg

@billyvg billyvg commented Nov 3, 2026

Copy link
Copy Markdown
Member

Why?

The frontend API contracts generated from the internal spec spell out any response the spec inlines, which review on the contracts PR flagged. The generator now declares each one as <OperationId>Response, but the names are better where the backend declares them. 22 of the responses the contracts map weren't components:

  • 15 came from the hand-written api-docs/ JSON, which the internal build appended over every unpublished method's generated operation. For service hooks, tag values, Sentry App installations and external issues, that hid named components drf-spectacular had already read from the backend's types.
  • The rest were undocumented handlers, or @extend_schema responses given as dict or as a raw JSON schema.

Stacked on:

For:

How?

In the internal build, a generated operation that declares a success body now stands over the hand-written one, which still stands in where the generated response is undocumented. The endpoints behind the rest now declare their responses as components. Symbol sources, whose responses are JSON schemas, use a new inline_sentry_response_schema, the JSON-schema counterpart to inline_sentry_response_serializer.

20 of the 22 are now components. The four service-hook responses share ServiceHook. The published operations are unchanged; the published spec gains the SymbolSource and ListSymbolSources components they now refer to.

Decisions

  • Release deploys and custom inbound filters are left alone. Their lists are already arrays of named components (DeployResponse[], CustomInboundFilter[]). Naming the list itself would mean replacing their documented DRF serializers with TypedDicts and losing the public field descriptions.
  • track_slo_response now uses functools.wraps. Without it, the internal build couldn't read the annotations of the issue handlers it wraps. The published spec built with it is byte-identical.

Generated with Claude Code

🤖 Generated with Claude Code

billyvg and others added 9 commits November 3, 2026 15:37
The published spec describes only published methods, so it can't serve as a contract for the
private and experimental endpoints the frontend calls. sentry.apidocs.internal builds one that
does, reading undeclared responses from Response[T] annotations and omitting nothing. Its
generator switches this on for its own build through hook parameters and a type-hint policy
whose defaults are the published build's, so the published spec is unchanged.

Extracted from the internal-spec half of #129315.
Consumers that filter operations by the permissions guarding them need the class names, which
only the view classes have. Each operation the internal build admits now carries its view's
permission_classes as x-sentry-permissions, with ones composed by &, | and ~ unwrapped to the
classes they compose.
…s view

DRF's ViewInspector.__set__ binds an assigned schema to the view instance,
the same way drf-spectacular's create_view swaps in @extend_schema classes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Issue endpoints declare IssueParams.ISSUES_OR_GROUPS, a `var` path
parameter for the published build's `{var}` spelling of (?:issues|groups),
which the published postprocessing drops along with the `{var}`. The
internal build spells the path `issues/` and kept the parameter, so 16
issue operations declared a required `var` that is not in their path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ations

drf-spectacular appends APPEND_PATHS over whole path items, so a hand-written
path item dropped every method its view serves that the item does not
describe. The published build only describes the hand-written ones anyway;
the internal one dropped POST on organization sentry-app-installations.
The internal build now appends them method by method, hand-written still
winning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nd-written one

The published build appends APPEND_PATHS, then _fix_issue_paths moves the
generated issue operations onto the hand-written paths, so the published
reference describes GET issues/{issue_id}/tags/{key}/values/ with its
generated operation. The internal build spells that path issues/ up front,
and the hand-written operation won instead, with another operationId,
parameters and response schema. A published method's generated operation
now wins here too; hand-written ones still stand in for the rest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… over a hand-written one

The internal build appended the hand-written api-docs operations over every
unpublished method's generated one, so their inlined response bodies hid
the named components drf-spectacular reads from the backend's own types:
ListServiceHooks and ServiceHook, ListTagValuesResponse,
ListSentryAppInstallations and PlatformExternalIssueResponse.

A generated operation that declares a success body now stands over the
hand-written one too. The hand-written one still stands in where the
generated response is undocumented. The published build is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Give every response the internal spec spelled out inline a named component,
so the generated frontend contracts can name it too:

- The service hook details GET and PUT declare the ServiceHook component
  registering one already returns, so all four service hook responses
  share it.
- The project user feedback, project issues GET and project issues PUT
  handlers declare what they return, with Response[T] annotations or, for
  the issues GET, whose @extend_schema declared only errors, a 200.
- track_slo_response keeps the handler it wraps visible, so the internal
  build can read the issues handlers' annotations.
- The uptime response capture endpoints describe their bodies with
  TypedDicts instead of `dict`.
- Symbol sources, whose responses are JSON schemas, name them with
  inline_sentry_response_schema, a JSON-schema counterpart to
  inline_sentry_response_serializer.

The published operations are unchanged; the published spec gains the
SymbolSource and ListSymbolSources components they now refer to.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@billyvg
billyvg requested review from a team as code owners November 3, 2026 23:20
@github-actions github-actions Bot added the Scope: Backend Automatically applied to PRs that change backend components label Nov 3, 2026
@billyvg
billyvg force-pushed the billyvg/feat/apidocs-internal-spec branch from 1aa8b71 to fca4a0c Compare November 5, 2026 16:55
@billyvg
billyvg requested review from a team as code owners November 5, 2026 16:55

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Backend Automatically applied to PRs that change backend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant