Publish a Python client + types for the User Manager API (transport parity with the TS client)
- Dominant language
- JavaScript
- Stars
- 5
- Forks
- 2
- Avg merge
- 19h 55m
- Merged PRs (30d)
- 33
Description
## Summary
Provide a **published, CI-verified Python client + types** for the User Manager API in `@adobe/spacecat-shared-user-manager-client`, at transport parity with the TS client. This is the user-manager twin of https://github.com/adobe/spacecat-shared/issues/1805 (Project Engine): today the package generates Pydantic **models only**, they are not published (so nothing can depend on them), there is no Python transport client, and the generated Python is not drift-checked in CI. The concrete consumer needs **both** this and 1805 — see below.
## What exists today (v1.4.0)
`packages/spacecat-shared-user-manager-client`:
- Source spec `spec/usermanager_swagger.yaml` → `swagger2openapi` → `build/openapi3.json` → overlay → `generate:ts` (`src/generated/types.ts`) + `generate:pydantic` (`python/serenity_user_manager/`, Pydantic v2 models).
- The **TS client** (`src/client.js` + `src/internal.js`) exports only `createSerenityUserManagerApiClient` — a thin `openapi-fetch` wrapper that owns transport (Bearer auth `authMiddleware`, base-URL `resolveBaseUrl`, and a **method-aware** retry: `isIdempotent`/`isRetryableStatus`/`parseRetryAfterMs`, 20s clamp).
## The gap (identical to 1805)
1. **No Python transport client** — `datamodel-codegen` emits models, not a client. No Python equivalent of `src/client.js` (auth, retry, base-URL).
2. **Not consumable** — `package.json` `files: ['src']` excludes `python/`; no PyPI/git-branch distribution.
3. **No CI drift-check** — `generate:pydantic` is manual, so the committed Python surface can silently lag the spec.
## Consumer: the migration CLI needs BOTH clients
`mysticat-data-service` `scripts/serenity_migration/semrush_write.py` defines a single `SemrushWriteClient` that spans **both** Semrush APIs — the Project Engine (`/enterprise/projects/api`, tracked in 1805) **and** the User Manager (`/enterprise/users/api`). On the user-manager surface it hand-rolls: `create_child_workspace` (`POST /v2/workspaces/{parent}/child`), `workspace_status` + `wait_workspace_created` (readiness polling over the lifecycle states), `get_ai_resources` + `transfer_resources`, `delete_workspace`, `rename_workspace`, and `family` listing. Its retry (`_RETRY_STATUSES = {429, 502, 503, 504}`) is **not method-aware** — the same double-write-on-POST hazard called out in 1805, which this client's TS transport already avoids.
Because the hand-rolled client is one class over both APIs, retiring it requires the Python client from 1805 **and** this one. Filing them separately keeps each package's work self-contained; they should land together to fully unblock the consumer.
## Scope / tasks
- Add a thin Python **transport client** (over `httpx`) consuming the generated Pydantic models, replicating the TS client's behaviour: fixed `/enterprise/users/api` prefix + origin-only base-URL normalisation; `Authorization: Bearer` from a value-or-callable token source resolved once per request; method-aware retry (429 all methods; 5xx/network only for idempotent methods) with `Retry-After`, equal-jitter backoff, 20s clamp, safe body replay.
- Choose and implement **distribution** (PyPI, or a `types-py`-style orphan git branch, or `git+https` subdirectory) and stop excluding `python/` from what ships.
- Wire `generate:pydantic` (and the client) into **CI as a drift-check**, mirroring the TS surface.
- Minimal transport tests (auth, method-aware retry incl. `Retry-After`, base-URL) and, ideally, an e2e smoke against the existing user-manager mock (`mock/`).
- **Acceptance:** `mysticat-data-service` `SemrushWriteClient`'s `/enterprise/users/api` half is re-backed onto the shared Python client (the Project Engine half via 1805).
## Explicitly out of scope
- **A "real domain client" elevation is NOT proposed here** (unlike the Project Engine's https://github.com/adobe/spacecat-shared/issues/1806). That issue is justified by the dimension-root tag *domain model* being triplicated across api-service, elmo, and the migration CLI. The User Manager surface is workspace lifecycle + resource-transfer CRUD, whose only real domain logic (workspace-readiness state machine, resource-transfer shape) lives in the provisioning/migration path rather than being spread across multiple consumers — so a thin typed client is appropriate and there is little to consolidate. If a check later shows that readiness/transfer logic is in fact duplicated across consumers, a separate, smaller "own the workspace-readiness state machine" issue can be opened then.
## Pointers
- Package: `packages/spacecat-shared-user-manager-client` (`@adobe/spacecat-shared-user-manager-client`, v1.4.0); spec `spec/usermanager_swagger.yaml`.
- TS transport to mirror: `src/client.js`, `src/internal.js` (already method-aware — `isIdempotent`/`isRetryableStatus`/`parseRetryAfterMs`).
- Consumer: `mysticat-data-service` `scripts/serenity_migration/semrush_write.py` (`SemrushWriteClient`, `/enterprise/users/api` methods).
- Companion (Project Engine transport): https://github.com/adobe/spacecat-shared/issues/1805
- Related (Project Engine domain client): https://github.com/adobe/spacecat-shared/issues/1806
Contributor guide
Research direction
Start with packages/spacecat-shared-user-manager-client, spec/usermanager_swagger.yaml, src/client.js, and src/internal.js to compare the existing TS transport and generated Python models. Then inspect mysticat-data-service/scripts/serenity_migration/semrush_write.py and the mock/ user-manager surface. Done means a distributable, CI drift-checked Python client with auth, base-URL, retry, and transport tests that can replace the User Manager half of SemrushWriteClient.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, openapi, python
- Domain
- api, backend, build-system, ci-cd, testing
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100