Collapse the openapi-namespace per-app reads into one canonical endpoint
GET /openapi/v1/apps/<id>/describe[?fields=info,parameters,input_schema]
returning a single AppDescribeResponse with all blocks Optional and a new
JSON-Schema input_schema block derived server-side from user_input_form +
app mode.
- AppDescribeQuery (Pydantic, extra=forbid) parses the ?fields allow-list;
unknown member -> 422.
- _input_schema.build_input_schema(app) derives Draft 2020-12 JSON Schema:
chat-family modes carry top-level query (string, minLength=1, required);
workflow / completion only carry inputs. AppUnavailableError -> empty
sentinel (EMPTY_INPUT_SCHEMA).
- Drop AppByIdApi (/apps/<id>) and AppParametersApi (/apps/<id>/parameters)
route classes; delete app_info.py module + app_info_payload helper.
- AppDescribeResponse.{info,parameters,input_schema} now Optional[None].
Lock-step deploy with difyctl Phase B (/describe consumer migration).
- Shared conftest at tests/integration_tests/controllers/openapi/:
workspace_account, app_in_workspace, mint_token (factory + tracked
cleanup of OAuthAccessToken rows), account_token convenience fixture,
autouse disable_enterprise (default ENTERPRISE_ENABLED=False; tests
needing the EE branch override in-test), autouse _flush_auth_redis.
- test_auth.py covers Layer 0 + per-token rate limit + scope on /info.
other_workspace_app fixture is a generator that cleans up the second
tenant + app on teardown.
- test_apps.py covers the read surface: /apps list with pagination
envelope, /apps/<id>, /info, /parameters, /describe, /account/sessions
envelope migration, plus dfoe_ scope rejection on apps:read routes.