Description
The ultimate goal is to split the single HTTP server into two servers, each serving a different audience with its own OpenAPI specification:
|
Management API |
Public / Protocol API |
| Audience |
Operators, back-office systems |
Wallets, browsers, external verifiers |
| Routes |
/v0/* (all management endpoints) |
/.well-known/*, /openid4vci/*, /auth/*, /request/*, /redirect, /credential_offer, /linked-verifiable-presentations/*, /healthz, /info, /version |
| Spec file |
openapi-generated.yaml (auto-generated via utoipa) |
openapi-full.yaml (or the current openapi.yaml until protocol endpoints are annotated) |
| Port |
Separate, operator-controlled (e.g. UNICORE__MANAGEMENT_URL) |
Current UNICORE__APPLICATION_URL |
| Standard |
Internal convention |
OpenID4VCI, SIOPv2, OID4VP, OAuth 2.0 |
Why
Protocol endpoints (well-known, openid4vci, auth/token, OID4VP redirect, etc.) must be reachable by external parties and are governed by open standards. Management endpoints deal with sensitive operations (credential issuance, identity configuration, key management) and should be firewalled from the public internet. Running them on separate ports makes network-level access control (firewall rules, Kubernetes NetworkPolicy, etc.) straightforward.
What needs to change
-
Router split — agent_api_http/src/lib.rs: Extract a management_router(state) function that composes only the /v0/* domain routers. Keep app(state) as the full router used for backward compatibility. The protocol/public routes remain in app().
-
Second port — agent_application/src/lib.rs: Add a management_url (or management_api_port) field to the application config (agent_shared). Spawn a second start_server task alongside the existing one — start_server() already accepts any Router + port, so the wiring is minimal.
-
OpenAPI specs:
openapi-generated.yaml is already the management spec — no changes needed once the gaps listed above are resolved.
openapi-full.yaml (public/protocol spec): either maintain it as a renamed openapi.yaml, or progressively annotate the protocol handlers with utoipa::path attributes and generate it from a second #[derive(OpenApi)] struct (e.g. FullApiDoc).
-
Config — agent_shared/src/config: Add an optional management_url: Option<Url>. When not set, the management API is not exposed on a separate port (preserves backward compatibility).
Prerequisite
All items in the gap tables above should be resolved (or deliberately scoped out) before the two-spec split is finalised, so that openapi-generated.yaml is a complete and accurate description of the management surface.
Motivation
- Reduce exposure of management API
- Clean split between "standardized" and "Impierce-driven" APIs
Requirements
see Description
Open Questions
No response
Are you planning to contribute this in a PR?
Yes
Description
The ultimate goal is to split the single HTTP server into two servers, each serving a different audience with its own OpenAPI specification:
/v0/*(all management endpoints)/.well-known/*,/openid4vci/*,/auth/*,/request/*,/redirect,/credential_offer,/linked-verifiable-presentations/*,/healthz,/info,/versionopenapi-generated.yaml(auto-generated viautoipa)openapi-full.yaml(or the currentopenapi.yamluntil protocol endpoints are annotated)UNICORE__MANAGEMENT_URL)UNICORE__APPLICATION_URLWhy
Protocol endpoints (well-known, openid4vci, auth/token, OID4VP redirect, etc.) must be reachable by external parties and are governed by open standards. Management endpoints deal with sensitive operations (credential issuance, identity configuration, key management) and should be firewalled from the public internet. Running them on separate ports makes network-level access control (firewall rules, Kubernetes
NetworkPolicy, etc.) straightforward.What needs to change
Router split —
agent_api_http/src/lib.rs: Extract amanagement_router(state)function that composes only the/v0/*domain routers. Keepapp(state)as the full router used for backward compatibility. The protocol/public routes remain inapp().Second port —
agent_application/src/lib.rs: Add amanagement_url(ormanagement_api_port) field to the application config (agent_shared). Spawn a secondstart_servertask alongside the existing one —start_server()already accepts anyRouter+ port, so the wiring is minimal.OpenAPI specs:
openapi-generated.yamlis already the management spec — no changes needed once the gaps listed above are resolved.openapi-full.yaml(public/protocol spec): either maintain it as a renamedopenapi.yaml, or progressively annotate the protocol handlers withutoipa::pathattributes and generate it from a second#[derive(OpenApi)]struct (e.g.FullApiDoc).Config —
agent_shared/src/config: Add an optionalmanagement_url: Option<Url>. When not set, the management API is not exposed on a separate port (preserves backward compatibility).Prerequisite
All items in the gap tables above should be resolved (or deliberately scoped out) before the two-spec split is finalised, so that
openapi-generated.yamlis a complete and accurate description of the management surface.Motivation
Requirements
see Description
Open Questions
No response
Are you planning to contribute this in a PR?
Yes