adobe / adobe/spacecat-shared

Publish a Python client + types for the User Manager API (transport parity with the TS client)

Open
#1,807 0 comments 0 reactions 0 assignees View on GitHub
enhancement tech debt
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.