ump_sdk.service
module ump-sdk
FastAPI app factory shared by every UMP POC service.
create_app(name, version) gives you:
- CORS for the web front end (
http://localhost:5173and127.0.0.1:5173); GET /healthzandGET /v1/meta;- a
UMP-Spec-Versionheader (andX-UMP-Service) on every response; - RFC 9457
application/problem+jsonforUmpError, upstreamProblemError, validation errors (422SCHEMA_INVALIDwith a JSON pointer per issue),HTTPExceptionand crashes; get_principaldependency readingX-UMP-Principal(defaultuser:demo). OnGETrequests only, a?principal=query parameter is accepted when the header is absent, because browserEventSource(SSE) cannot send headers. Writes always need the header.
Classes
Section titled “Classes”Principal
Section titled “Principal”class
class PrincipalFields
| Name | Type | Default | Description |
|---|---|---|---|
id | str | ||
kind | str | ||
explicit | bool |
Methods and properties (3)
is_agent property
is_agent: boolis_human property
is_human: boolinit constructor
Principal(self, id: str, kind: str, explicit: bool) -> NoneSource: packages/ump-sdk/src/ump_sdk/service.py, line 51
Functions
Section titled “Functions”get_principal
Section titled “get_principal”function
def get_principal(request: Request) -> PrincipalFastAPI dependency: principal: Principal = Depends(get_principal).
Header X-UMP-Principal wins. On GET requests a ?principal= query parameter is the fallback
(EventSource cannot set headers). Neither present means user:demo with explicit=False.
Source: packages/ump-sdk/src/ump_sdk/service.py, line 66
is_json_content_type
Section titled “is_json_content_type”function
def is_json_content_type(request: Request) -> boolSource: packages/ump-sdk/src/ump_sdk/service.py, line 81
read_json_body
Section titled “read_json_body”function
async def read_json_body(request: Request) -> AnyRaw JSON body for routes that validate with ump_spec models themselves.
A non-empty body must be sent as Content-Type: application/json (or +json); otherwise 415
UNSUPPORTED_MEDIA_TYPE. Parsing text/plain would let any web page write through a CORS
“simple request”, which skips the preflight that the CORS allow-list blocks. An empty body reads
as None. Duplicate member names and non-finite numbers are refused with 422 SCHEMA_INVALID
(spec §18 canonical form).
Source: packages/ump-sdk/src/ump_sdk/service.py, line 86
set_gate_mode_echo
Section titled “set_gate_mode_echo”function
def set_gate_mode_echo( request: Request, effective: dict[str, GateFailMode] | GateFailMode,) -> NoneRecord the mode a route applied; create_app echoes it in UMP-On-Gate-Fail (spec §19).
Source: packages/ump-sdk/src/ump_sdk/service.py, line 141
get_gate_mode
Section titled “get_gate_mode”function
def get_gate_mode(request: Request) -> GateFailModeFastAPI dependency: the UMP-On-Gate-Fail header (X-UMP-On-Gate-Fail is the deprecated spelling),
else fallback. Any other value is 422 SCHEMA_INVALID. The mode is echoed on the response unless
the route records a stricter effective mode with set_gate_mode_echo.
Source: packages/ump-sdk/src/ump_sdk/service.py, line 146
request_gate_mode
Section titled “request_gate_mode”function
def request_gate_mode( request: Request, body_value: Any,) -> dict[str, GateFailMode] | NoneThe request’s on_gate_fail from the body member or the header (spec §19), as a per-gate map; None when
the request names none. Both present and different is 422 GATE_MODE_CONFLICT.
Source: packages/ump-sdk/src/ump_sdk/service.py, line 156
accept_profile
Section titled “accept_profile”function
def accept_profile(request: Request) -> NoneSpec §21 Negotiation: when Accept names a profile (application/json; profile="<base>/spec/2.3"),
at least one media range must fall in a supported MAJOR.MINOR range, else 406 SPEC_VERSION_NOT_ACCEPTABLE
listing the ranges. An Accept without a profile is not negotiated.
Source: packages/ump-sdk/src/ump_sdk/service.py, line 169
problem_response
Section titled “problem_response”function
def problem_response( problem: Problem, headers: dict[str, str] | None = None,) -> JSONResponseSource: packages/ump-sdk/src/ump_sdk/service.py, line 188
error_response
Section titled “error_response”function
def error_response(exc: UmpError, request: Request | None = None) -> JSONResponseSource: packages/ump-sdk/src/ump_sdk/service.py, line 193
install_problem_handlers
Section titled “install_problem_handlers”function
def install_problem_handlers(app: FastAPI) -> NoneSource: packages/ump-sdk/src/ump_sdk/service.py, line 205
create_app
Section titled “create_app”function
def create_app( name: str, version: str = '0.1.0', *, description: str = '', lifespan: Callable[..., Any] | None = None, stub: bool = False, meta: dict[str, Any] | None = None, conformance_classes: list[str] | None = None,) -> FastAPIBuild a FastAPI app with the UMP conventions. name should be a key of ports.PORTS.
conformance_classes are the spec §2 classes the service implements (Producer, Consumer,
Engine adapter, Gate engine, Agent host, Log verifier, Hosted endpoint). /v1/meta
lists them with conformance_proven: false: the POC has no conformance suite, so none is a claim.
Source: packages/ump-sdk/src/ump_sdk/service.py, line 238
mount_unavailable
Section titled “mount_unavailable”function
def mount_unavailable( app: FastAPI, operations: Mapping[str, str], *, engine: str, reason: str | None = None,) -> list[str]Spec §8 engine profile: mount POST /v1/<op> answering 501 OPERATION_UNAVAILABLE for every
ADAPTER_OPERATIONS request that operations (the adapter’s metadata) does not mark built_in,
unless the app already routes that path. The problem’s suggested_action names the nearest working
operation (ump_spec.adapter.unavailable_suggestion); reason is added to the detail. Returns the
requests mounted, in contract order. Call it after the app’s own routes.
Source: packages/ump-sdk/src/ump_sdk/service.py, line 297
function
def run( app: FastAPI | str, name: str, *, host: str = '127.0.0.1', reload: bool = False,) -> Nonepython -m <pkg> helper: serve on the registry port for name.
Source: packages/ump-sdk/src/ump_sdk/service.py, line 336
Constants
Section titled “Constants”| Name | Type | Value | Description |
|---|---|---|---|
PROBLEM_JSON | 'application/problem+json' | ||
DEFAULT_PRINCIPAL | 'user:demo' | ||
PRINCIPAL_QUERY_PARAM | 'principal' | Query fallback for the identity stub, honoured on GET only (SSE via EventSource). | |
CORS_ORIGINS | ['http://localhost:5173', 'http://127.0.0.1:5173'] | ||
HTTP_STATUS_CODES | dict[int, str] | {400: 'SCHEMA_INVALID', 401: 'UNAUTHORIZED', 403: 'FORBIDDEN', 404: 'NOT_FOUN... | Framework HTTP errors to UMP codes; the response then carries the code’s registered status (spec §19). |