Skip to content

Annotate ledger-api protos with google.api.http for proto-derived OpenAPI (3.5.9 baseline) - #4

Open
monsieurleberre wants to merge 5 commits into
release-line-3.5from
experiment/google-api-http-full-coverage
Open

Annotate ledger-api protos with google.api.http for proto-derived OpenAPI (3.5.9 baseline)#4
monsieurleberre wants to merge 5 commits into
release-line-3.5from
experiment/google-api-http-full-coverage

Conversation

@monsieurleberre

Copy link
Copy Markdown

Re-opens the annotation work from #2 against a pristine release-line-3.5 base.

#2 was squash-merged by accident on 2026-07-26 — auto-merge had been armed on it since 2026-07-10 and fired the moment a base retarget made it mergeable. That left release-line-3.5 carrying our annotations instead of mirroring upstream. The branch has since been reset to pristine upstream 1f9a483455307cfb7875ff120ff803500663eeac; the pre-reset head is preserved at archive/release-line-3.5-at-cc150af.

This PR is the same work, presented as a reviewable diff. Auto-merge is deliberately off.

Base and scope

Base release-line-3.5 @ 1f9a4834 — proto tree byte-identical to Maven 3.5.9
Head experiment/google-api-http-full-coverage @ 472b36a (archived at archive/google-api-http-full-coverage-3.5.9)
Diff 5 commits, 59 files, merge base 1f9a4834, behind_by: 0

Content is metadata only: option go_package on 34 protos, plus import "google/api/annotations.proto" and option (google.api.http) on the 14 service protos — 52 annotated RPCs, zero new RPCs, messages, or fields.

What changed relative to #2

The branch is rebased from its 3.4.11-era base onto release-line-3.5 @ 1f9a4834. At that baseline GetUpdatesPage and GetActiveContractsPage exist and are annotated, so all 52 RPCs are live — under the 3.4.11 pin a consumer could only carry 50.

The design, the intentional deviations, and the deliberate omissions are otherwise unchanged from #2, which remains the reference for the rationale.

Known deviation

StateService.GetActiveContractsPage is annotated POST while Canton's own JSON Ledger API exposes it as GET. GET-with-body is rejected by grpc-ecosystem/openapiv2 and disallowed by OpenAPI generally, and the request carries a required EventFormat message that does not flatten to query params. This is the only verb deviation in the spec.

Why this fork exists

Advocacy-only; never fetched by any build. peacefulstudio/canton-ledger-api-csharp exports these annotations as a standalone patch set over the range 1f9a4834..472b36a and applies them to SHA-256-pinned Maven artifacts, so its supply chain depends on those two commit SHAs rather than on whether this branch is merged.

Supersedes #2.

…e options

Demonstrates Option 4 from the C# SDK proposal appendix: annotate Canton's
.proto files with google.api.http so the JSON HTTP surface can be derived
from the protos directly, bypassing tapir's translation layer.

Scope (one service end-to-end):

- community/ledger-api-proto/.../v2/command_service.proto: imports
  google/api/annotations.proto and adds an option (google.api.http) block
  to each of the three RPCs (SubmitAndWait, SubmitAndWaitForTransaction,
  SubmitAndWaitForReassignment), matching the existing tapir routes.

- All v2 .proto files (22) plus value.proto: add option go_package next to
  the existing csharp_namespace/java_package options. Required by every
  off-the-shelf OpenAPI generator in the ecosystem. Harmless to existing
  C#/Java/Scala codegen, which does not read this option.

Verified with `buf build`: clean compile. Verified end-to-end OpenAPI
generation with buf.build/grpc-ecosystem/openapiv2:v2.28.0: the output
fixes all four type-system defects catalogued in the C# SDK proposal
(numbered duplicate schemas, single-key oneOf wrappers, inline duplicated
enums, untyped DAML payload fields).

See peacefulstudio/documentation/dev-funding/openApi/upstream-fork-experiment.md
for the full write-up.
Builds on the CommandService experiment by annotating every other v2 RPC
the JSON API exposes over HTTP, plus adding go_package to the admin/,
testing/, and interactive/ sub-packages so off-the-shelf OpenAPI
generators can resolve the full proto closure.

Annotated services (route source: community/ledger/ledger-json-api Js*Service.scala):

v2/
- CommandSubmissionService:      Submit, SubmitReassignment
- CommandCompletionService:      CompletionStream
- ContractService:               GetContract
- EventQueryService:             GetEventsByContractId
- PackageService:                ListPackages, GetPackage,
                                 GetPackageStatus, ListVettedPackages
- StateService:                  GetActiveContracts, GetActiveContractsPage,
                                 GetConnectedSynchronizers, GetLedgerEnd,
                                 GetLatestPrunedOffsets
- UpdateService:                 GetUpdates, GetUpdateByOffset,
                                 GetUpdateById, GetUpdatesPage
- VersionService:                GetLedgerApiVersion

v2/admin/
- IdentityProviderConfigService: 5 RPCs
- PackageManagementService:      UploadDarFile, ValidateDarFile,
                                 UpdateVettedPackages
- PartyManagementService:        7 HTTP-exposed RPCs
- UserManagementService:         9 RPCs

v2/interactive/
- InteractiveSubmissionService:  6 RPCs

Each annotation matches the existing tapir route (method + path + body
mapping) so the proto-derived OpenAPI is comparable to the current
tapir-emitted document.

Scope notes:
- Server-streaming RPCs (CompletionStream, GetActiveContracts,
  GetUpdates) get only the canonical POST/list mapping; the WebSocket
  GET form is a JSON-API-only convenience that has no representation in
  google.api.http and remains in the AsyncAPI doc.
- Legacy JSON-only paths (/v2/updates/flats|trees|transaction-*,
  /v2/authenticated-user, /v2/definitions/*) are not annotated — they
  either lack a 1:1 proto RPC or are non-gRPC custom endpoints.
- Non-HTTP-exposed RPCs (TimeService, CommandInspectionService,
  ParticipantPruningService, PackageManagementService.ListKnownPackages,
  PartyManagementService.UpdatePartyIdentityProviderId) are deliberately
  left unannotated.

Verified locally with `buf build community/ledger-api-proto/src/main/protobuf`:
clean compile.
The JSON API exposes this as GET with a JSON body containing a required
EventFormat message — non-standard REST, and rejected by
grpc-ecosystem/openapiv2 ("must not set request body when http method
is GET"). Switching to POST is the canonical mapping for a request
with a non-trivial body, and is the single intentional deviation from
the existing tapir route for the proto-derived OpenAPI.
Mirrors the experiment-evidence pattern from the single-service
experiment, scaled to the full HTTP API:

- openapi-3.0/openapi.yaml — OpenAPI 3.0.3 YAML generated via
  buf.build/community/google-gnostic-openapi:v0.7.0; same major version
  as the existing community/ledger/ledger-json-api/.../openapi.yaml, so
  the two can be diffed directly.
- swagger-2.0/canton-ledger-api.swagger.yaml — Swagger 2.0 YAML via
  buf.build/grpc-ecosystem/openapiv2:v2.28.0; same plugin as the
  upstream CommandService experiment, merged across every annotated
  service.
- coverage-comparison/ — sorted path inventories and the diff between
  the JSON API spec and the proto-derived spec, after normalizing
  path-parameter names (proto field names ↔ tapir placeholder names).
  9 paths-only-in-JSON-API (all deliberate skips: 1 custom JSON-only
  endpoint + 8 deprecated legacy aliases), 0 paths-only-in-proto.
- reproduce.sh — one-shot regen of every artefact in this directory.

Internal to the Peaceful Studio fork. To be deleted before any upstream
PR to digital-asset/canton.
…ranch

Carries over the go_package-harmlessness proof bundle (before/after
descriptor diffs showing the option is inert for existing codegen) and
the CommandService openapi POC from #1, so this branch is self-contained
once #1 closes as superseded.
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