Skip to content

feat: add user feed centric subscription endpoints - #1807

Merged
davidgamez merged 4 commits into
mainfrom
feat_feed_focus_subscriptions
Aug 27, 2026
Merged

feat: add user feed centric subscription endpoints#1807
davidgamez merged 4 commits into
mainfrom
feat_feed_focus_subscriptions

Conversation

@davidgamez

@davidgamez davidgamez commented Aug 19, 2026

Copy link
Copy Markdown
Member

Summary:

Closes MobilityData/product-tasks#212

Adds two feed-centric read endpoints to the User Service API, so clients can ask "which feeds am I subscribed to?" instead of listing subscriptions and grouping client-side.

  • GET /v1/user/subscriptions/feeds — the feeds the caller has at least one
    notification subscription targeting, each with the subscriptions that target it.
  • GET /v1/user/subscriptions/feeds/{id} — same shape for a single feed stable ID
    (note: {id} here is a feed stable ID, e.g. mdb-1, not a subscription UUID
    like every other /v1/user/subscriptions/{id} path).

Both are read-only and additive; no existing endpoint, response shape, or DB column changes.

Changes

Spec (docs/UserServiceAPI.yaml, +128)

  • New paths getUserSubscriptionFeeds / getUserSubscriptionFeedById.
  • New schemas SubscriptionFeedGroup (feed_id + resolved metadata + nested
    subscriptions) and FeedSubscriptionSummary (trimmed subscription view that omits
    user_id and feeds, both redundant in this context).

Implementation

  • api/src/user_service/impl/users_api_impl.py — the two handlers plus a shared
    _query_subscription_feed_groups helper that joins
    notification_subscription_feednotification_subscription, filters by the
    authenticated user, orders by (feed_stable_id, created_at), and groups in Python.
  • api/src/shared/db_models/subscription_feed_group_impl.py — new impl wrapper
    building the grouped view from ORM rows.

Behavior notes

Expected behavior:

  • Subscriptions of any active state are included, matching
    GET /v1/user/subscriptions.
  • Feed metadata (data_type, provider, feed_name) is resolved from the feeds DB
    at read time via resolve_feed_metadata, not persisted. A feed that no longer
    exists there still appears, with those fields null.
  • 404 on the by-ID endpoint deliberately collapses "feed doesn't exist" and "user
    has no subscription targeting it" — both are just "no matching join rows", so no
    separate feeds-DB existence check is made.
  • Guests get 403; results are scoped to the caller's user_id.
  • One subscription targeting N feeds appears under each of the N feed groups.

Testing tips:

This can be tested locally or in DEV. Below the response from dev(my account)

Request:

curl --request GET \
  --url https://api-dev.mobilitydatabase.org/v1/user/subscriptions/feeds/mdb-1 \
  --header 'Authorization: Bearer .....'

Response

{
  "feed_id": "mdb-1",
  "data_type": "gtfs",
  "provider": "Casco Bay Lines",
  "feed_name": "",
  "subscriptions": [
    {
      "id": "f91224e8-9466-4825-a44f-bf78eec1813a",
      "notification_id": "feed.url_updated",
      "active": true,
      "created_at": "2026-07-28T19:03:45.301170Z"
    }
  ]
}

Request:

curl --request GET \
  --url https://api-dev.mobilitydatabase.org/v1/user/subscriptions/feeds \
  --header 'Authorization: Bearer ....'

Response

[
  {
    "feed_id": "mdb-1",
    "data_type": "gtfs",
    "provider": "Casco Bay Lines",
    "feed_name": "",
    "subscriptions": [
      {
        "id": "f91224e8-9466-4825-a44f-bf78eec1813a",
        "notification_id": "feed.url_updated",
        "active": true,
        "created_at": "2026-07-28T19:03:45.301170Z"
      }
    ]
  },
  {
    "feed_id": "mdb-101",
    "data_type": "gtfs",
    "provider": "Foothill Transit",
    "feed_name": "",
    "subscriptions": [
      {
        "id": "f91224e8-9466-4825-a44f-bf78eec1813a",
        "notification_id": "feed.url_updated",
        "active": true,
        "created_at": "2026-07-28T19:03:45.301170Z"
      }
    ]
  }
]

Request:

curl --request GET \
  --url https://api-dev.mobilitydatabase.org/v1/user/subscriptions/feeds/no_valid_id \
  --header 'Authorization: Bearer ......'

Response

{
  "detail": "Feed not found, or no subscription targets it."
}

Please make sure these boxes are checked before submitting your pull request - thanks!

  • 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)

Copilot AI 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.

Pull request overview

Adds “feed-centric” subscription read endpoints to the User Service so clients can retrieve notification subscriptions grouped by feed_stable_id, with feed metadata resolved at read time (and nullable when no longer resolvable).

Changes:

  • Extended the User Service OpenAPI spec with GET /v1/user/subscriptions/feeds and GET /v1/user/subscriptions/feeds/{id}, plus new response schemas for feed-grouped subscriptions.
  • Implemented the query/grouping logic in UsersApiImpl and introduced a SubscriptionFeedGroupImpl model builder to assemble API models from ORM rows + resolved feed metadata.
  • Added unit + DB-backed tests for the new endpoints; updated documentation and performed minor Operations API spec formatting cleanup.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
docs/UserServiceAPI.yaml Adds the two new endpoints and introduces FeedSubscriptionSummary / SubscriptionFeedGroup schemas.
docs/OperationsAPI.yaml Reflows/cleans up description formatting in several schema fields.
docs/notifications-subscription-flows.md Documents that {id} means “feed stable ID” for the new .../feeds/{id} endpoints.
api/tests/unittest/user_service/test_users_api_impl.py Adds mock-based unit tests for feed-grouped subscription queries.
api/tests/unittest/user_service/test_subscription_feeds.py Adds DB-backed tests validating grouping behavior, isolation per user, and null-metadata behavior.
api/src/user_service/impl/users_api_impl.py Implements the two new endpoints and shared query/grouping helper.
api/src/shared/db_models/subscription_feed_group_impl.py New helper model to construct SubscriptionFeedGroup responses from ORM subscriptions + metadata.
api/.openapi-generator/FILES Tracks newly generated model files for OpenAPI generator output.
Suppressed comments (1)

docs/UserServiceAPI.yaml:239

  • This endpoint can return 403 for guest users (the implementation calls _require_user_id()), but the OpenAPI responses only document 401/404. Also, since the implementation returns 404 based on “no subscription targets this feed” (not feeds-DB existence), the 404 description should avoid implying a feeds-DB existence check.
        "401":
          description: Unauthorized.
        "404":
          description: Feed not found, or the user has no subscription targeting it.


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread docs/UserServiceAPI.yaml Outdated
Comment thread docs/UserServiceAPI.yaml Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@davidgamez davidgamez changed the title add feed centric subscription endpoints feat: add user feed centric subscription endpoints Aug 20, 2026
@davidgamez
davidgamez marked this pull request as ready for review August 20, 2026 15:26
@Alessandro100
Alessandro100 self-requested a review August 21, 2026 11:49
Comment thread docs/UserServiceAPI.yaml
"401":
description: Unauthorized.

/v1/user/subscriptions/feeds:

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.

[question] aren't these endpoints duplicating what's in the user description endpoint? is it only to avoid having the ui group the information from /v1/user/subscriptions?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It's the same information, but the response helps the consumer to get all the subscriptions from a specific feed without having to iterate over all subscriptions.

@cka-y cka-y 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

@davidgamez
davidgamez merged commit 59d4072 into main Aug 27, 2026
23 of 24 checks passed
@davidgamez
davidgamez deleted the feat_feed_focus_subscriptions branch August 27, 2026 18:59
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.

4 participants