Skip to content

Add versioned v2 API with apps terminology#6741

Open
mdegat01 wants to merge 4 commits intomainfrom
supervisor-v2-api
Open

Add versioned v2 API with apps terminology#6741
mdegat01 wants to merge 4 commits intomainfrom
supervisor-v2-api

Conversation

@mdegat01
Copy link
Copy Markdown
Contributor

Proposed change

Introduce a versioned /v2 API for the Supervisor that uses apps terminology consistently, while keeping the v1 API fully backward-compatible. Builds on the internal code rename from PR #6717.

The rebranding of addons → apps requires breaking API changes (path and field renames). Rather than making these in-place and breaking existing clients, a versioned v2 API allows both old and new clients to work during a transition period.

Design

  • aiohttp sub-app mounted at /v2 — clean URL prefix with isolated routing and no code duplication
  • Feature flag gatedFeatureFlag.SUPERVISOR_V2_API must be enabled; v2 routes are registered at load() time only when the flag is set
  • Thin v1 wrappers — v1 endpoints delegate to v2 canonical methods, translating field names where needed (appsaddons)
  • Strict per-version security regexes_V1_PATTERNS and _V2_PATTERNS match only their respective paths; no cross-version fallback
  • Shared business logic helpers_rename_apps_to_addons_in_backups(), _process_location_in_body(), _all_store_apps_info(), _info_data() eliminate duplication

Path Mapping

v1 v2
/addons/{slug}/... /v2/apps/{slug}/...
/store/addons/{slug}/... /v2/store/apps/{slug}/...
/backups/... (addons field) /v2/backups/... (apps field)
/store (addons field) /v2/store (apps field)

Constant Split

  • ATTR_APPS = "apps" — v2 API responses/requests
  • ATTR_ADDONS = "addons" — v1 API responses and backup file format (must never change — old backups would be unreadable)

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New feature (which adds functionality to the supervisor)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Additional information

  • This PR is related to issue:
  • Link to documentation pull request:
  • Link to cli pull request:
  • Link to client library pull request:

Checklist

  • The code change is tested and works locally.
  • Local tests pass. Your PR cannot be merged unless tests pass
  • There is no commented out code in this PR.
  • I have followed the development checklist
  • The code has been formatted using Ruff (ruff format supervisor tests)
  • Tests have been added to verify that the new code works.

If API endpoints or add-on configuration are added/changed:

@mdegat01 mdegat01 added missing-documentation Added to pull requests that needs a docs, but none is linked needs-cli Pull requests needs CLI changes but none is linked needs-client-library Pull requests needs client library changes but none is linked labels Apr 15, 2026
@mdegat01 mdegat01 requested review from agners and sairon April 15, 2026 21:11
Copy link
Copy Markdown
Member

@agners agners left a comment

Choose a reason for hiding this comment

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

Looks good, looking forward to the new v2 API 😎


CORE_FRONTEND: Final = re.compile(
r"^(?:" + _CORE_FRONTEND_PATHS + r")$"
_V2_FRONTEND_PATHS: Final = (
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.

Hm, I think we can drop frontend from v2 from the getgo.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Hm. So here's the actual paths in here:

_V2_FRONTEND_PATHS: Final = (
    r"|/app/.*\.(?:js|gz|json|map|woff2)"
    r"|/v2/store/apps/" + RE_SLUG + r"/(logo|icon)"
)

/app is the app store panel. And yea I think you're right about that, that's gone now.

But what about the icons and logos? Are you sure frontend doesn't ask Supervisor for those in the new UI? Where else would they come from?

r"|/apps(?:/" + RE_SLUG + r"/(?!security).+|/reload)?"
r"|/audio/.+"
r"|/auth/cache"
r"|/available_updates"
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.

.. not sure if we should deprecate this one as well. From what I can see the Core isn't using it? 🤔

Copy link
Copy Markdown
Contributor Author

@mdegat01 mdegat01 Apr 16, 2026

Choose a reason for hiding this comment

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

Those are in the Manager role though, they aren't core only. The manager role is one that addons can declare they use so we'd need to check addons for usage of that.

However we can drop the |/reload bit. I just checked, that's there because there's a legacy route of /addons/reload that really maps to /store/reload. That path won't exist in v2. The others I expect to exist for now so I think we leave it as is unless we have a reason to deny apps access to these paths.

Comment thread supervisor/api/middleware/security.py Outdated
Comment thread supervisor/api/backups.py Outdated
@home-assistant
Copy link
Copy Markdown

Please take a look at the requested changes, and use the Ready for review button when you are done, thanks 👍

Learn more about our pull request process.

@home-assistant home-assistant bot marked this pull request as draft April 16, 2026 10:44
@agners agners requested a review from Copilot April 16, 2026 12:17
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces a feature-flagged, versioned /v2 Supervisor API that consistently uses apps terminology while keeping the existing v1 endpoints backward-compatible by delegating to shared handlers and translating field names where needed.

Changes:

  • Added a /v2 aiohttp sub-app (gated by FeatureFlag.SUPERVISOR_V2_API) and registered v2 routes for apps, backups, and store without duplicating handler logic.
  • Split API/backup terminology constants (ATTR_ADDONS vs ATTR_APPS) and updated v1/v2 response/request schemas to use the appropriate keys.
  • Expanded the test suite with fixtures and assertions to validate v1/v2 path behavior and key naming.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tests/conftest.py Updates backup test data to use the legacy addons key via ATTR_ADDONS.
tests/api/test_store.py Refactors store endpoint tests to run against both v1 and v2 roots; adds v2 key assertions.
tests/api/test_backups.py Refactors some tests to be v1/v2-prefix aware; adds v2-specific backup API tests.
tests/api/test_addons.py Refactors app management tests to run against both v1 /addons and v2 /v2/apps; adds v2 list-key test.
tests/api/conftest.py Adds api_client_v2 and shared (client, prefix/root) fixtures for dual-version testing.
supervisor/const.py Introduces ATTR_ADDONS = "addons" and changes ATTR_APPS to "apps" for v2 payloads.
supervisor/backups/validate.py Ensures backup validation schema continues to use the legacy addons key.
supervisor/backups/backup.py Keeps backup internal data keyed by legacy addons while exposing it via the apps property.
supervisor/api/supervisor.py Updates Supervisor info payload to keep returning legacy addons key.
supervisor/api/store.py Adds shared store data helper and v1/v2 variants that differ only by top-level key (addons vs apps).
supervisor/api/middleware/security.py Splits security regex patterns per API version (_V1_PATTERNS / _V2_PATTERNS) and selects based on path.
supervisor/api/backups.py Splits v1/v2 schemas and endpoints for backups; adds key-translation helpers and shared business-logic helpers.
supervisor/api/addons.py Adds shared list/info builders and v1/v2 list endpoints differing by response key.
supervisor/api/init.py Mounts a /v2 sub-app when feature flag is enabled; registers v1 wrappers and v2 canonical routes.
pyproject.toml Updates pylint configuration for re.Pattern members used in the new dataclass-based pattern set.

Comment thread supervisor/api/middleware/security.py Outdated
Comment thread supervisor/api/middleware/security.py Outdated
Comment thread supervisor/api/supervisor.py Outdated
Comment thread supervisor/backups/backup.py Outdated
Comment thread tests/api/test_backups.py
mdegat01 and others added 3 commits April 16, 2026 19:18
Introduce a v2 API sub-app mounted at /v2 that uses 'apps' terminology
throughout, while keeping v1 fully backward-compatible.

Key changes:
- Add ATTR_ADDONS = 'addons' constant alongside ATTR_APPS = 'apps' so
  backup file data (which must remain 'addons' for backward compat) and
  v2 API responses can use distinct constants
- Add FeatureFlag.SUPERVISOR_V2_API to gate v2 route registration
- Mount aiohttp sub-app at /v2 in RestAPI.load() when flag is enabled
- Add _AppSecurityPatterns frozen dataclass and _V1_PATTERNS/_V2_PATTERNS
  with strict per-version regex sets (no cross-version matching)
- Add _register_v2_apps, _register_v2_backups, _register_v2_store route
  registration methods
- Add v1 thin wrapper methods (*_v1) for all affected endpoints so
  business logic lives in the canonical v2 methods
- Extract _info_data() helper in APIApps so v1 closure can bypass
  @api_process and still catch APIAppNotInstalled for store routing
- Add _rename_apps_to_addons_in_backups(), _process_location_in_body(),
  _all_store_apps_info() shared helpers to eliminate duplication
- Add api_client_v2, api_client_with_prefix, app_api_client_with_root,
  store_app_api_client_with_root parameterized test fixtures
- Add test_v2_api_disabled_without_feature_flag
- Parameterize backup, addons, and store tests to cover both v1 and v2
  paths

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
re.Pattern methods (match, search, etc.) are C extension methods.
Pylint cannot detect them via static analysis when re.Pattern is used
as a type annotation in a dataclass field, producing false E1101
no-member errors. Add generated-members to inform pylint these members
exist.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@mdegat01 mdegat01 force-pushed the supervisor-v2-api branch from f9fbcf3 to 824a25a Compare April 16, 2026 19:18
@mdegat01 mdegat01 marked this pull request as ready for review April 16, 2026 19:28
@home-assistant home-assistant bot requested a review from agners April 16, 2026 19:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla-signed missing-documentation Added to pull requests that needs a docs, but none is linked needs-cli Pull requests needs CLI changes but none is linked needs-client-library Pull requests needs client library changes but none is linked

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants