storebound/docs/credential-broker.md

5.2 KiB

Google access through a credential broker

A credential broker is a server of yours that holds the Google service-account keys, the Cloud project facts and the Play permission grants. With one configured, storebound keeps no Google key on the machine: it asks the broker for a short-lived access token for each Google API call and reads the package's Play permissions from it before a command writes anything. The local key (PLAY_SERVICE_ACCOUNT) keeps working and is the fallback.

Setup

~/.storebound/broker.json:

{
  "url": "https://broker.example.com",
  "apiKeyFile": "~/.storebound/broker.key",
  "account": "play-publisher@example.com"
}
  • url: the broker's base URL. Only https:// (plain http:// only for localhost, a local test broker).
  • apiKeyFile: a file with one scoped API key on one line, with the scopes google:read and google:token. On macOS and Linux it must be chmod 600: storebound refuses a key file that the group or others can read. Default: broker.key next to broker.json. The key is never printed, never written into a config or a log.
  • account (optional): the service account e-mail the broker mints tokens for. A credential profile or the project can name its own with PLAY_SERVICE_ACCOUNT_EMAIL (env, ~/.storebound/credentials/<profile>.json, .storebound/credentials.json); without either, the client_email of a local key is used, and for Play commands the account the broker names for the package.

Overrides: STOREBOUND_BROKER_URL, STOREBOUND_BROKER_KEY_FILE (env wins over the file), STOREBOUND_BROKER_CONFIG (another broker.json). Off: STOREBOUND_BROKER=off for one run, "broker": false in a credential profile (that profile keeps its key file), or env STOREBOUND_PROFILE_<NAME>_BROKER=off.

What storebound calls

call when
POST /api/google/token { "account", "scopes": ["androidpublisher"] } -> { "accessToken", "expiresAt" } before Google calls. Kept in memory until 5 minutes before expiresAt; parallel calls share one request
GET /api/google/play/<package>/storebound storebound validate, the preflight of Play write commands, apps check and the desktop's Accounts view

Scopes: androidpublisher for the Play Developer API, cloud-platform.read-only for Play statistics exports and Play Games configuration reads. The broker hands out no scope for the Play Developer Reporting API (vitals, the app list of apps list) or for Play Games configuration writes: those use the local key, and say so when there is none.

Fallback and failures

  • Broker not configured: the local key, as before.
  • Broker not answering (network error, timeout, 5xx) or not knowing the account (400 / 404 on a token): the local key, with one warning per run. No local key: the error names the broker.
  • Broker refusing the API key (401 / 403): storebound stops with "the key lacks google:token" and does not retry or fall back. Give the key its scopes on the broker.
  • A package the broker does not know (404 on /storebound): a warning to register it there. It is not a missing Play access; the command still runs and Google answers for itself.

Permission checks

The broker's answer lists the service account's Play permissions for the package and the APIs enabled in its Cloud projects. Before a Play command writes, storebound compares them with what the command needs and stops before any Play call, naming the exact permission or API and the link to fix it:

work Play permission commands
uploads, releases, rollouts CAN_MANAGE_TRACK_APKS play upload, play release, play rollout, play share
store listing and images CAN_MANAGE_PUBLIC_LISTING play listing, play images
products and subscriptions CAN_MANAGE_ORDERS play products, play subscriptions
Data safety, app content CAN_MANAGE_APP_CONTENT play data-safety
review replies CAN_REPLY_TO_REVIEWS (listed in the checks)
Play Games Services API gamesconfiguration.googleapis.com play games

Every Play call also needs androidpublisher.googleapis.com enabled. A dry run (--dry) and reads only warn. storebound validate reports the same gaps as blockers, the permissions and APIs the broker lists, and SDK config files (google-services.json, GoogleService-Info.plist) the broker reports as drifted or whose sha256 differs from the repo's copy.

When Google itself answers 403 SERVICE_DISABLED or PERMISSION_DENIED, the error names the API (with its enable link) or the missing app access (with the Users and permissions link), adds what the broker lists for the package, and is never retried.

Where it shows

  • storebound doctor: Play: tokens from the credential broker <url> for p***@... (or the local key, and why the broker is not usable). --json: play.source is "broker" or "file".
  • storebound accounts: a "Play via" column (credential broker / key file) per profile.
  • storebound validate --json (and MCP validate): credentials.play.source.
  • storebound apps check --store play --json and the desktop's Accounts view: source and, per Play app of the machine, the permissions and APIs the broker lists and what is missing.