Skip to content

docs: open api docs utoipa #2023

Merged
taddes merged 19 commits into
masterfrom
docs/open-api-docs-utoipa-STOR-381
Feb 6, 2026
Merged

docs: open api docs utoipa #2023
taddes merged 19 commits into
masterfrom
docs/open-api-docs-utoipa-STOR-381

Conversation

@taddes
Copy link
Copy Markdown
Collaborator

@taddes taddes commented Jan 26, 2026

Description

OpenAPI docs would be useful to collect and publish to clarify our API.

The utopia crate w/ the actix_extras feature can parse our actix-web route definitions to produce OpenAPI docs, and its accompanying utoipa-swagger-ui crate can serve those docs via actix-web.

This PR imports utoipa and swagger to support the OpenAPI spec and annotates the web handlers for tokenserver and sync to introduce the API documentation. This requires special proc macros that are recognized by OpenAPI

For consistency and simplicity, I have added to the github actions to generate and publish the swagger docs as well. The documentation page also lays out ways to see the documentation locally using Docker and a few other methods. Just follow the instructions to test for yourself. There is also an example script that generates the openapi.json file that is required first.

Screenshot 2026-01-28 at 2 22 06 PM

Also resolves cargo-audit CVE related to time create

Issue(s)

Closes STOR-381.

@taddes taddes self-assigned this Jan 26, 2026
@taddes taddes force-pushed the docs/open-api-docs-utoipa-STOR-381 branch from 4d40a9b to 98b3ece Compare January 28, 2026 19:24
@taddes taddes changed the title WIP: docs: open api docs utoipa docs: open api docs utoipa Jan 28, 2026
@taddes taddes marked this pull request as ready for review January 28, 2026 19:28
Comment thread docs/src/open-api-docs.md Outdated
cargo run --example generate_openapi_spec > openapi.json
```

### Viewing the Spec Locally (Without Running the Server)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think of the idea of creating a make target that can generate and preview the swagger docs?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great idea, I'll add that 👍

@taddes taddes requested a review from pjenvey January 28, 2026 22:49
Comment thread Cargo.toml
[workspace.package]
version = "0.21.1"
authors = [
"Ben Bangert <ben@groovie.org>",
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That seems harsh.

Copy link
Copy Markdown
Collaborator Author

@taddes taddes Jan 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know, I too am sad Ben left Mozilla... His was the first name that came up so I updated it to Phil. What we really need is a mail group for the sync/storage team. I can put it back for posterity if you feel strongly.

Copy link
Copy Markdown
Member

@pjenvey pjenvey Jan 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't put too much importance in these author fields but if anything I'd rather add more to them than remove.

However we apparently have a sync-backend@mozilla.com that you made in 2024, so we could make that the sole authors if you want (and add Barry to this mailing list).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thx, moved us to that and added Barry!

summary = "Get collection timestamps",
description = "Returns an object mapping collection names associated with the account to the last-modified time for each collection.",
params(
("uid" = String, Path, description = "User ID")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we explain how the user can get this uid value? Presumably we want people to interact with the endpoints.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Folks would have to probably use the about:sync extension to get their uid


#[utoipa::path(
get,
path = "/1.0/{application}/{version}",
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think application and version should be params below?

(status = 401, description = "Unauthorized - Invalid authentication"),
(status = 503, description = "Service unavailable - No nodes available"),
)
)]
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is nothing here about authorization. And the UI doesn't offer a way to pass anything in through headers.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'll have to dig a little deeper on how to deal with this for the configuration for the live preview mode.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be fine merging this pretty much as is, we can log a separate issue for supporting Auth headers

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good @pjenvey , can file an additional ticket as I explore that a bit and we see how it looks when deployed.

(status = 200, description = "Collection timestamps retrieved successfully", content_type = "application/json"),
(status = 401, description = "Unauthorized"),
)
)]
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no way to authorize these syncserver requests. The only param I can enter on the UI is the uid but that isn't enough.

summary = "Get sync token",
description = "Allocates a sync storage node and returns authentication credentials for accessing it. This is the main Tokenserver endpoint used by Firefox Sync clients.",
responses(
(status = 200, description = "Token generated successfully", body = TokenserverResult, content_type = "application/json"),
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without making a successful request, readers wouldn't know the shape of TokenserverResult. It would be nice if there's a response schema.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the 200 response, there is actually a TokenserverResult that can be seen, whether the request is successful or not. Really glad you mentioned this though, because I hadn't added the Tokenserver stage & prod references to the Api doc config and also made sure to add to the documentation.
Screenshot 2026-01-30 at 5 59 53 PM

Comment thread syncserver/src/web/handlers.rs Outdated
("uid" = String, Path, description = "User ID"),
("collection" = String, Path, description = "Collection name"),
("ids" = Option<String>, Query, description = "Comma-separated list of BSO IDs to return (max 100)"),
("newer" = Option<f64>, Query, description = "Return only items with modified time strictly greater than this timestamp"),
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be good to mention the resolution of the timestamps.

@taddes taddes force-pushed the docs/open-api-docs-utoipa-STOR-381 branch from f925335 to 91adafd Compare January 29, 2026 18:47
Comment thread syncserver/src/server/mod.rs Outdated
description = "OpenAPI documentation for Syncstorage and Tokenserver endpoints."
),
servers(
(url = "https://sync-1-us-west1-g.sync.services.mozilla.com", description = "US West Production"),
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
(url = "https://sync-1-us-west1-g.sync.services.mozilla.com", description = "US West Production"),
(url = "https://sync-us-west1-g.sync.services.allizom.org", description = "US West Stage"),
(url = "https://sync-1-us-west1-g.sync.services.mozilla.com", description = "US West Production"),

(if anyone wants to play around with test traffic, maybe encourage stage)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call with stage, can add a suggestion in docs.

Comment thread docs/src/open-api-docs.md Outdated
```
Then open http://localhost:8080

2. **Generate the spec on a compatible machine** (or use CI):
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems a little confusing with 1) mentioning this command but really 1/3/4 all need it (should 2 be removed and 1)'s mention of the command moved ahead of all these sections?)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, that makes sense.

@taddes taddes force-pushed the docs/open-api-docs-utoipa-STOR-381 branch from 4e53172 to ed6d5f9 Compare January 30, 2026 22:30
@taddes taddes requested review from chenba and pjenvey January 30, 2026 23:05
@taddes
Copy link
Copy Markdown
Collaborator Author

taddes commented Jan 30, 2026

Note: once we finally cut a new release with this feature, we may go back and make some adjustments to the URL we point to and see if the generated swagger docs (which eventually end up as part of the compiled and deployed Syncstorage) are more feature-rich than the current state.

Comment thread Makefile
OPENAPI_FILE := openapi.json

.PHONY: api-prev
api-prev: ## Generate live preview of OpenAPI Swagger Docs and open in browser (port 8080).
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried this and the server stops as soon as it's started.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is your Docker daemon/Docker desktop running? Works fine for me.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

docker container ls showed the expected output so it appears to be running.

@chenba
Copy link
Copy Markdown
Collaborator

chenba commented Feb 2, 2026

Thanks @taddes for this work.

I think I need to understand the goal of this effort better. If it is to allow people to interact with the API endpoints, then it is not quite there. The UI for the very first step of exchanging an FxA OAuth access token for a Sync auth token does not have a way for the user to input the access token. (Presuming the user know how to grab an FxA access token that's authorized to access Sync.)

If we only want to list the API endpoints, then let's remove the interactivity. We still should list the header(s) for the endpoints, however.

@taddes
Copy link
Copy Markdown
Collaborator Author

taddes commented Feb 2, 2026

Thanks @taddes for this work.

I think I need to understand the goal of this effort better. If it is to allow people to interact with the API endpoints, then it is not quite there. The UI for the very first step of exchanging an FxA OAuth access token for a Sync auth token does not have a way for the user to input the access token. (Presuming the user know how to grab an FxA access token that's authorized to access Sync.)

If we only want to list the API endpoints, then let's remove the interactivity. We still should list the header(s) for the endpoints, however.

This was a very old ticket to basically just add the OpenAPI support. There isn't an explicit necessary goal of it being interactive, though that's a nice plus. I had mentioned before that the auth parts of this may make it tricky, and we're not going to know more until we actually cut a new version of Sync with this feature that exposes the API as part of the compiled Sync. We can file an additional ticket to expand that as needed. It might in the end be a bridge too far to have it fully interactive. However, the endpoints still have response codes and the shapes of some of the returned data.

@taddes taddes force-pushed the docs/open-api-docs-utoipa-STOR-381 branch from bdafc7e to ac9e11f Compare February 2, 2026 19:58
Comment thread syncserver/Cargo.toml Outdated
validator = "0.20"
validator_derive = "0.20"
woothee = "0.13"
utoipa = "5.4.0"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's move this into the root Cargo.toml w/ tokenserver-common also using it

(status = 401, description = "Unauthorized - Invalid authentication"),
(status = 503, description = "Service unavailable - No nodes available"),
)
)]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be fine merging this pretty much as is, we can log a separate issue for supporting Auth headers

@taddes taddes force-pushed the docs/open-api-docs-utoipa-STOR-381 branch from ac9e11f to ff7837f Compare February 5, 2026 03:28
@taddes taddes requested a review from pjenvey February 5, 2026 03:28
@taddes taddes force-pushed the docs/open-api-docs-utoipa-STOR-381 branch from ff7837f to 5045c96 Compare February 6, 2026 20:33
pjenvey
pjenvey previously approved these changes Feb 6, 2026
@taddes taddes requested a review from pjenvey February 6, 2026 21:23
@taddes
Copy link
Copy Markdown
Collaborator Author

taddes commented Feb 6, 2026

Also resolves cargo-audit CVE related to time create:

Version:   0.3.41
Title:     Denial of Service via Stack Exhaustion
Date:      2026-02-05
ID:        RUSTSEC-2026-0009
URL:       https://rustsec.org/advisories/RUSTSEC-2026-0009
Severity:  6.8 (medium)
Solution:  Upgrade to >=0.3.47
Dependency tree:
time 0.3.41
├── syncstorage-settings 0.21.1
│   ├── syncstorage-spanner 0.21.1
│   │   └── syncstorage-db 0.21.1
│   │       └── syncserver 0.21.1
│   ├── syncstorage-postgres 0.21.1
│   │   └── syncstorage-db 0.21.1
│   ├── syncstorage-mysql 0.21.1
│   │   └── syncstorage-db 0.21.1
│   ├── syncstorage-db 0.21.1
│   ├── syncserver-settings 0.21.1
│   │   ├── tokenserver-db 0.21.1
│   │   │   └── syncserver 0.21.1
│   │   ├── syncstorage-mysql 0.21.1
│   │   ├── syncstorage-db 0.21.1
│   │   └── syncserver 0.21.1
│   └── syncserver 0.21.1
├── syncserver 0.21.1
├── slog-term 2.9.2
│   ├── syncserver 0.21.1
│   └── slog-envlogger 2.2.0
│       └── syncserver 0.21.1
├── sentry-types 0.42.0
│   └── sentry-core 0.42.0
│       ├── sentry-tracing 0.42.0
│       │   └── sentry 0.42.0
│       │       ├── syncserver-common 0.21.1
│       │       │   ├── tokenserver-postgres 0.21.1
│       │       │   │   └── tokenserver-db 0.21.1
│       │       │   ├── tokenserver-mysql 0.21.1
│       │       │   │   └── tokenserver-db 0.21.1
│       │       │   ├── tokenserver-db-common 0.21.1
│       │       │   │   ├── tokenserver-postgres 0.21.1
│       │       │   │   ├── tokenserver-mysql 0.21.1
│       │       │   │   └── tokenserver-db 0.21.1
│       │       │   ├── tokenserver-db 0.21.1
│       │       │   ├── tokenserver-common 0.21.1
│       │       │   │   ├── tokenserver-settings 0.21.1
│       │       │   │   │   ├── tokenserver-postgres 0.21.1
│       │       │   │   │   ├── tokenserver-mysql 0.21.1
│       │       │   │   │   ├── tokenserver-db 0.21.1
│       │       │   │   │   ├── tokenserver-auth 0.21.1
│       │       │   │   │   │   └── syncserver 0.21.1
│       │       │   │   │   ├── syncserver-settings 0.21.1
│       │       │   │   │   └── syncserver 0.21.1
│       │       │   │   ├── tokenserver-postgres 0.21.1
│       │       │   │   ├── tokenserver-mysql 0.21.1
│       │       │   │   ├── tokenserver-db-common 0.21.1
│       │       │   │   ├── tokenserver-auth 0.21.1
│       │       │   │   └── syncserver 0.21.1
│       │       │   ├── tokenserver-auth 0.21.1
│       │       │   ├── syncstorage-spanner 0.21.1
│       │       │   ├── syncstorage-settings 0.21.1
│       │       │   ├── syncstorage-postgres 0.21.1
│       │       │   ├── syncstorage-mysql 0.21.1
│       │       │   ├── syncstorage-db-common 0.21.1
│       │       │   │   ├── syncstorage-spanner 0.21.1
│       │       │   │   ├── syncstorage-postgres 0.21.1
│       │       │   │   ├── syncstorage-mysql 0.21.1
│       │       │   │   └── syncstorage-db 0.21.1
│       │       │   ├── syncstorage-db 0.21.1
│       │       │   ├── syncserver-settings 0.21.1
│       │       │   ├── syncserver-db-common 0.21.1
│       │       │   │   ├── tokenserver-postgres 0.21.1
│       │       │   │   ├── tokenserver-mysql 0.21.1
│       │       │   │   ├── tokenserver-db-common 0.21.1
│       │       │   │   ├── tokenserver-db 0.21.1
│       │       │   │   ├── syncstorage-spanner 0.21.1
│       │       │   │   ├── syncstorage-postgres 0.21.1
│       │       │   │   ├── syncstorage-mysql 0.21.1
│       │       │   │   ├── syncstorage-db-common 0.21.1
│       │       │   │   ├── syncstorage-db 0.21.1
│       │       │   │   └── syncserver 0.21.1
│       │       │   └── syncserver 0.21.1
│       │       └── syncserver 0.21.1
│       ├── sentry-debug-images 0.42.0
│       │   └── sentry 0.42.0
│       ├── sentry-contexts 0.42.0
│       │   └── sentry 0.42.0
│       ├── sentry-backtrace 0.42.0
│       │   ├── syncserver-common 0.21.1
│       │   ├── sentry-tracing 0.42.0
│       │   └── sentry 0.42.0
│       └── sentry 0.42.0
├── plist 1.7.4
│   └── os_info 3.12.0
│       └── sentry-contexts 0.42.0
└── actix-web 4.11.0
    ├── utoipa-swagger-ui 9.0.2
    │   └── syncserver 0.21.1
    ├── tokenserver-common 0.21.1
    ├── syncstorage-spanner 0.21.1
    ├── syncserver-common 0.21.1
    ├── syncserver 0.21.1
    └── actix-cors 0.7.1
        └── syncserver 0.21.1

@taddes taddes merged commit 62bd7d2 into master Feb 6, 2026
32 checks passed
@taddes taddes deleted the docs/open-api-docs-utoipa-STOR-381 branch February 6, 2026 22:05
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.

3 participants