# Operator provisioning and entitlement ownership

Current local contract delta — 2026-10-05. This supersedes only the provisioning/entitlement availability details in the historical September reference. It does not regenerate or certify that edition's OpenAPI, HTML, PDF or portal.

## Endpoints and unchanged success semantics

| Endpoint | Required scope | Success and audit semantics |
| --- | --- | --- |
| `POST /operator/v1/accounts` | `wallet` | Creates a zero-balance account without a ledger entry or funding. HTTP 201 for creation; HTTP 200 for an existing `(operator, playerId, currency)` tuple. A duplicate preserves the account and does not append another `account.provision` action. The returned balance is the balance read for that account, not a permanently frozen original response. |
| `PUT /operator/v1/games/:gameCode` | `games` | HTTP 200 with `gameCode`, `enabled`, and sorted unique `currencies`. Each successful PUT remains a mutation and appends `game_entitlement.set`, including repeated equivalent PUTs. Unknown/inactive game remains HTTP 404 `GAME_NOT_FOUND`; malformed input remains HTTP 400. |

Both mutations commit their business state, generic actor audit and action audit together. No new request-id idempotency protocol, account funding operation or provider call is introduced. Authentication may independently update API-key usage metadata even if the later mutation is rejected.

## Availability and retry

After authentication, finite admission/checkout/SQL-owner unavailability returns:

```http
HTTP/1.1 503 Service Unavailable
Retry-After: 1
Content-Type: application/json

{"error":"CONTROL_PLANE_BUSY"}
```

This is not `MONEY_PATH_BUSY`: provisioning creates no money, and entitlement changes are control-plane work. Authentication and pre-authentication admission retain their own error contracts. An action-audit failure still rolls the mutation back and produces the existing sanitized HTTP 500 `INTERNAL_ERROR`, not false success.

A lost response or COMMIT acknowledgement is not proof that the mutation failed. Recover durable state before deciding whether to repeat a change. Retrying the same account tuple cannot create another account or a second creation audit. Entitlement PUT has last-successful-write semantics; retry can append another event and must not silently overwrite an intervening administrative decision.

## Ownership limits

- Resource identities are derived from the account-creation tuple or operator/game pair. They are not keyed by replaceable API credentials. Independent resources are not forced through one operator-wide mutation lock.
- The audited transaction reuses the existing control-plane owner: nominal **6000 ms** cumulative admission/checkout/SQL budget, **1000 ms** admission ceiling, **1500 ms** statement and **500 ms** lock limits, and **2000 ms** idle-transaction limit. A Pool must configure a finite acquisition timeout that fits the remaining budget.
- A pool-local resource queue is capped at **16** waiters, and the aggregate queue at **128**; existing active/fleet SQL limits also apply. These are resource-custody limits, not a throughput promise or a newly certified fleet limiter.
- Transaction work and client retirement are joined; a JavaScript response timeout alone is insufficient. PostgreSQL cancellation can have a bounded statement-timeout tail. Authentication precedes this owner and is not included in its cumulative clock. Arbitrary external-I/O callbacks are prohibited, not made cancellable by this wrapper.

Real restricted-login PostgreSQL and authenticated loopback HTTP coverage, source identities and exclusions are in [operator audit ownership](../workstreams/operator-audit-ownership.md). No migration, deployment, independent approval or production qualification follows from this local delta.
