Metadata-Version: 2.4
Name: mobius-operations-trace-py
Version: 1.0.0
Summary: Request-flow reconstruction and HUMAN_API replay for Mobius Python (FastAPI) services, built on the span/parent-span action-log fields written by mobius-tracer-py and mobius-auditlog-py.
Author: Mobius Platform
Keywords: tracing,replay,request-flow,fastapi,mobius
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: pydantic>=2.0
Requires-Dist: httpx>=0.24
Requires-Dist: fastapi>=0.100
Provides-Extra: dev
Requires-Dist: pytest>=7.4; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
Requires-Dist: httpx>=0.24; extra == "dev"

# mobius-operations-trace-py

Request-flow reconstruction and `HUMAN_API` replay for Mobius Python (FastAPI)
services. Python port of `platform-artifact-lifecycle-lib` +
`platform-artifact-lifecycle-web` (`MPH-926` / `MPH-928`), verified against
the Java source (`OperationTraceServiceImpl`, `LifecycleOperationsExceptionHandler`).

Relies on action-log rows carrying `spanid` / `parentservicespanid` /
`requestid` / `httpmethod` / `httpurl` / `requesterid` / `actionsource`, written
by [mobius-tracer-py](../mobius-tracer-py) +
[mobius-auditlog-py](../mobius-auditlog-py).

## What it does

- `get_request_flow(txnid, requestid)` — queries action logs (either
  identifier alone is enough) and rebuilds the causal call tree (`HUMAN_API`
  entry point first, then each service hop it triggered, in call order) from
  the `spanid` / `parentservicespanid` fields.
- `replay_request(txnid, requestid)` — finds the originating `HUMAN_API` call,
  exchanges the original requester's identity for a bearer token, and
  re-issues that exact HTTP call (method/URL/body).

Both are exposed as FastAPI endpoints:

- `GET /v1/operations/request-flows?txnid=...&requestid=...`
- `POST /v1/operations/request-replays?txnid=...&requestid=...`

Error handling mirrors the Java REST layer:

- Internal failures (missing identifiers, PI lookup failure, missing
  `HUMAN_API` fields, replay connectivity failure) → HTTP 400 with the same
  envelope `LifecycleOperationsExceptionHandler` emits (`timestamp`, `origin`,
  `errorCode`, `errorMessage`, `httpStatusCode`, `actionsRequired`).
- A replayed target's own response — even a 4xx/5xx — is forwarded verbatim
  instead of raised, with the outer HTTP status set to match the target's.

## Usage

This package has no hard dependency on a specific action-log store or IAM
client — you supply small adapters:

```python
from mobius_operations_trace import setup_operations_trace

setup_operations_trace(
    app,
    token_provider=my_token_provider,  # TokenProvider protocol
    instances_list_url="http://pi-service/v2.0/schemas/{schemaId}/instances/list",
    schema_id="action-log-schema-id",
)
```

`instances_list_url` must contain a literal `{schemaId}` placeholder — PI
takes the schema id as a URL path variable, not a body field (matches
`lifecycle.operations.trace.instances-list-url` on the Java side). Pass
`action_log_source` instead of `instances_list_url`/`schema_id` to bypass the
built-in PI-backed source entirely.

`TokenProvider` has a single method, `retrieve_token_from_tenant_id(tenant_id)`
— used both to authenticate the PI query (with the fixed
`PI_SERVICE_TENANT_ID`) and to authenticate a replay as the original requester
(with the `HUMAN_API` row's `requesterid`), matching the Java side's single
`IamVaultUtils.retrieveTokenFromTenantId` method.

See `mobius_operations_trace.pi_client.ActionLogSource` and
`mobius_operations_trace.tokens.TokenProvider` for the full adapter contracts.
