Skip to content

The permission_policy OpenAPI fragment is copy-pasted five times in schemas.ex #1899

Description

@jhgaylor

Found while reviewing the stack:1635 set (#1852#1860) and deliberately not fixed there, because the fix is a contract decision rather than a cleanup.

What

FountainWeb.Schemas declares permission_policy inline in five places — AgentResponse, AgentRequest, AgentUpdateRequest, Conversation and ConversationCreateRequest. Each copy is now ~22 lines: the ask_timeout property with its minimum/maximum and an 8-line description, plus the additionalProperties oneOf union of the verdict enum and an integer.

The duplication predates #1852 — the additionalProperties enum was already five-way — but that PR roughly tripled the size of the copied fragment, and #1635's ceiling work then had to edit all five again. Any further change to the policy wire shape is a five-place edit with nothing to catch a missed one.

Why it was not fixed in the stack

The file's own idiom is a named nested schema module referenced by name (UsageTotal, and PendingPermissionRequest added in #1859). Applying it here is the obvious fix:

defmodule PermissionPolicy do
  OpenApiSpex.schema(%{title: "PermissionPolicy", ...})
end

But that turns the inline object into a $ref, which renames the generated TypeScript type — the five call sites stop producing an anonymous intersection and start producing components["schemas"]["PermissionPolicy"]. That is arguably better for SDK consumers, and it is a contract change that wants deciding on its own rather than riding along in a bug fix.

A module attribute would keep the emitted spec byte-identical, but attributes are lexically scoped to the module being defined, so one declared on FountainWeb.Schemas is not visible inside the nested defmodules — which is why there is no module-attribute precedent in the file.

Decide

  • Named schema module and accept the generated-type rename (one SDK minor, no runtime change), or
  • leave it and accept the five-place edit.

Either is fine; the point of the issue is that the current state is a silent five-way edit surface and nobody has chosen.

Related: #599 derived the enum lists to stop exactly this class of drift.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Opportunistic or low-urgency work; not a scheduling commitment.area:apiHTTP API, OpenAPI and CLI contracts.area:sdkClient SDKs, conformance, packaging and releases.type:featureAdds or improves product behavior.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions