Skip to content

feat: per-feed config endpoints in the Operations API - #1890

Merged
davidgamez merged 3 commits into
mainfrom
feat/feed-config-ops
Nov 11, 2026
Merged

davidgamez merged 3 commits into
mainfrom
feat/feed-config-ops

Conversation

@davidgamez

@davidgamez davidgamez commented Nov 9, 2026 •

Copy link
Copy Markdown
Member

Summary:

Adds Operations API endpoints to read and set per-feed config overrides for any registered config_key, so per-feed settings no longer need hotfix Liquibase PRs (e.g. #1889). Also adds an endpoint that shows the headers the nightly download sends for a GTFS feed. Creating, editing or deleting keys themselves is out of scope.

Expected behavior:

  • GET /v1/operations/config/keys lists the registered keys.
  • GET /v1/operations/feeds/{id}/config returns, for each key, the default, the override, the value in effect and where it comes from.
  • PUT /v1/operations/feeds/{id}/config/{namespace}/{key} creates (201) or replaces (200) an override. DELETE on the same path removes it (204). An unknown feed or key returns 404, an invalid value 422, and a stale expected_updated_at 409.
  • Values are checked against JSON Schemas kept in code (config_value_schemas.py). feed_download/http_headers refuses credential headers.
  • GET /v1/operations/gtfs_feeds/{id}/download_headers returns the headers the download sends today, where they come from (override / config_default / built_in), the built-in headers, and the name of the API key header (never its value). It uses the same helper as the download, and download behavior is unchanged.
  • One migration adds config_value_feed.updated_by, which records who made the change.

Testing tips:

Run ./scripts/api-tests.sh --folder functions-python/operations_api. For a GTFS feed, call GET on download_headers, then PUT an http_headers override and call GET on download_headers again to see the override reported. Then DELETE the override to return the feed to its previous headers.

  • Run the unit tests with ./scripts/api-tests.sh to make sure you didn't break anything
  • Add or update any needed documentation to the repo
  • Format the title like "feat: [new feature short description]". Title must follow the Conventional Commit Specification(https://www.conventionalcommits.org/en/v1.0.0/).
  • Linked all relevant issues
  • Include screenshot(s) showing how this pull request works and fixes the issue(s)

Generated with Claude Code

@davidgamez
davidgamez requested a review from ianktc November 9, 2026 17:34

@ianktc ianktc left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

lgtm. Tested the following requests on local:

GET /v1/operations/config/keys which returns the two schemas feed_download and parquet_builder (this is for Garage i think...?)

GET /v1/operations/gtfs_feeds/{id}/download_headers which shows "source": "built_in" and the default "built_in_headers"

PUT /v1/operations/feeds/{id}/config/{namespace}/{key} on a feed with example payload changing the User Agent Header: "User-Agent":"curl/8.0"

GET /v1/operations/gtfs_feeds/{id}/download_headers to confirm that the source changed to override and the headers: {"User-Agent":"curl/8.0"}

PUT /v1/operations/feeds/{id}/config/{namespace}/{key} with payload {"value":{"Authorization":"Bearer x"}} to confirm response 422

DELETE /v1/operations/feeds/{id}/config/{namespace}/{key} to confirm response 204.

GET /v1/operations/gtfs_feeds/{id}/download_headers to confirm that "source": "built_in" once again and the default "built_in_headers"

@davidgamez
davidgamez merged commit 94acc34 into main Nov 11, 2026
25 checks passed
@davidgamez
davidgamez deleted the feat/feed-config-ops branch November 11, 2026 00:43
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.

2 participants