team query parameter for authentication context; team-scoped preparation should match
body.team_id. Billing-account invitations instead require billing_account_id and no
team_id; the query team is only authentication context. Reads and cancellation can use the selected current team even if
the original credential team has changed. This does not change the credential mode.
Prepare an action
Save a UUIDv4 before the first request. This synthetic example prepares a live/test API key pair for a team with no active API keys:409 operation_conflict. After a preparation
timeout, preserve and reuse the original ID and content; never generate a new ID as an
automatic retry.
A token name is trimmed and must contain 1–64 characters. Mode must be explicit.
Unknown fields, caller-supplied authority and agent terms acceptance are rejected.
A personal MCP token grants the user’s access across authorized teams;
team_id
is its initial context, not a security boundary limiting the resulting credential.
The new token does not change the calling credential’s mode.
Membership scope
Membership actions require the current team owner using a verified personal identity. They affect access across production and test.requested_modes: [] means that no
credential mode is being selected; it does not isolate the grant to test mode.
The frozen membership_change shows the target account ID, email and name from Auth,
previous role, current owner, and whether ownership changes. The target and owner
must still be active, and changed identity, roster, permissions or account state
requires a new review. Adding an admin is for an existing eligible user in the same
billing account; use invitations for someone outside that account.
Transfers keep the previous owner as an administrator and preserve billing-account
ownership. No membership action issues an API key, password or login link.
Read and cancel
The response is HTTP 200{success:true,data:approval,timestamp} with
Cache-Control: no-store. It includes a 64-character lowercase approval id,
operation_id, action, team identity, billing-account ID, normalized payload,
requested modes, effect scope, status, millisecond timestamps and review_url.
It never contains secrets or a review challenge.
GET /users/me/account-approvals/{id} and
DELETE /users/me/account-approvals/{id}. Reads and cancellation require the same
creator; MCP calls also require the same originating credential and mode. Cancellation
only affects a pending request. It cannot revoke issued credentials or undo completion.
The completed
receipt contains keys:[{key_id,type,livemode}],
revoked_count, and nullable membership, invitation, managed_identity, and managed_session. Membership receipts identify the action,
member, current and previous owner, resulting role, and whether a member was added.
They have keys: [] and revoked_count: 0. Credential receipts have membership: null and invitation: null. Invitation receipts have no keys or membership result. Every GET remains metadata-only, even after a lost execution response.
No endpoint retrieves a previously delivered secret.
Human browser confirmation
The person opensreview_url in the authenticated application and verifies its
configured environment, team, action, requested modes and consequences. The link is
not a bearer grant and contains no secret. Production uses https://app.gigstack.pro;
staging uses its separately configured application origin.
The application privately obtains a short-lived, intent-bound review challenge and
submits the person’s explicit confirmation. Those browser review and execution actions
are excluded from the public API reference and agent tools. They require recent real
Firebase sign-in, revocation checking, the same person, and enrolled MFA when applicable;
refreshing an old ID token is not recent authentication. Custom/anonymous sessions,
managed-user sessions and personal MCP/API credentials cannot perform them.
The server rechecks current membership, authority, origin-credential validity, relevant
key/account state and applicable entitlement before committing. API rotation revokes
only the reviewed key set; a state change invalidates review. MCP creation rechecks the
ten-token limit and the person’s explicit terms acceptance. The disclosure version is
the application’s review contract, not an independently verified legal PDF revision.
Only the first browser execution that commits returns new secrets to that browser.
Execution replay returns secrets:null; reads, cancellation and preparation never return
secrets or challenges. If that response was lost, inspect the metadata receipt and use
a separately reviewed replacement if needed. Do not automatically repeat issuance.
Migrating direct issuance and privileged membership changes
DirectPOST /api-keys, POST /api-keys/rotate and POST /users/me/mcp-tokens
return HTTP 403 account_approval_required. They no longer return HTTP 201 or credentials.
CLI api-keys create, api-keys rotate and me mcp-tokens create now prepare approvals
with required --operation-id. Their former --out and --accept-terms issuance options
are removed. MCP uses prepare_account_api_keys, prepare_account_api_key_rotation and
prepare_my_mcp_token, followed by get_account_approval or cancel_account_approval.
List and revoke commands remain available under their existing authority checks.
Direct POST /teams/{id}/transfer-ownership now returns 403 account_approval_required.
The same error applies to role: admin on member PATCH and add-member POST. Prepare
the corresponding action above; preparation itself does not change access. Non-admin
role changes, permitted module permissions, and member removal keep their existing
authority and direct routes. A completed transfer receipt remains readable by its
creator even after they become the previous owner, so a lost response does not require
repeating the transfer.
Invite an administrator
Prepare an invitation with an explicit delivery choice:POST /users/me/account-approvals, then open review_url. Only the
current canonical team owner can approve. For an administrator across the billing
account, use billing_account.invitations.create_admin, replace team_id with
billing_account_id, and have that account’s canonical owner review. Team ownership,
billing administrator status and master-admin flags do not substitute for billing
ownership. canonical_owner_required means support must resolve missing ownership.
The browser shows the frozen email address, scope, administrator role, invitation
expiry and delivery choice in invitation_change. The email address identifies the
intended recipient; it is not proof of an existing person’s identity. team is null
for billing-account invitations. Access applies across live and test.
Preparation expires after ten minutes. A new invitation’s seven-day expiry starts at
preparation and is frozen during review. Completion atomically records the approved
invitation and receipt.invitation, which contains safe identity/scope metadata.
It does not mean an email was delivered or the recipient joined. Only the first
committing browser execution may attempt the reviewed email delivery. Replaying
execution never sends another email.
Use these owner-scoped endpoints for the receipt’s invitation ID:
delivery.status=sent records provider acceptance, not recipient acceptance.
pending can represent a delivery in progress; an active five-minute lease rejects
resend with delivery_in_progress. An expired lease or uncertain provider result
requires {"acknowledge_unconfirmed_delivery":true} and can cause a duplicate email.
Read the status and obtain that explicit choice before resending. Resend is not an
idempotent request: repeating a completed resend can send again. Revocation does not
retract an already-sent email. Management responses never expose invitation tokens.
To approve an existing unexpired pending admin invitation, include
existing_invitation_id in the preparation payload and set send_email:false.
Recovery preserves its existing link and expiry. Unknown historical delivery remains
unknown. An already-approved or expired invitation cannot be adopted again; revoke
and prepare a new invitation when needed. approval_required on management metadata
reports missing proof, but acceptance and resend always validate the full proof and
current owner authority independently.
Direct admin invitation creation returns account_approval_required. Ordinary
editor/viewer invitations retain their direct workflow. Administrator acceptance
requires the intended recipient’s active Auth account, verified matching email, and
current valid owner approval. An existing team member is not silently promoted by accepting
a team invitation; use the separate promotion approval. A billing-account invitation
explicitly grants account administrator authority, including to someone already
associated with that account through an ordinary team seat.
Managed session actions
Prepare delegated access to an existing managed identity using a saved operation ID:review_url for the initiating person. Team API/OAuth keys cannot
prepare the action, and agents cannot review, execute, receive or redeem its credential.
To request refresh-token revocation instead, use managed_users.revoke_sessions
with the same payload shape and a new saved operation ID. It is a separate reviewed
action, not cancellation of a prepared request.
Both actions require the current canonical billing-account owner and the owner of
every reachable team to be the initiating person. The selected team must be within
the target’s authoritative access. Private managed provenance must match the current
Auth identity; historical from: api or managedBy labels alone are insufficient.
Foreign or ambiguous grants are refused. Issuance requires an active target;
reviewed revocation can apply to a disabled managed identity.
managed_session_change freezes the target ID, email, Auth creation time, billing
account, reachable teams/accounts and prior issuance/revocation attempts. Team roles
include inherited billing_account_admin and master_team_billing_access where
applicable. These disclose current access, not a lifetime restriction on the global
Firebase identity. effect_scope is managed_session, and requested_modes: []
means the access is not isolated to test mode.
managed_session_execution reports attempting, issued, revoked or unknown,
with the attempt timestamp, nullable custom_token_expires_at, and delivery status.
For issuance, delivery: not_observable means the backend cannot establish whether
the person received or used the credential. A safe completed receipt.managed_session
contains the target, approval ID, action and exchange deadline; it never contains a
credential. Session fields and this receipt variant are null for other actions.
The custom-token deadline limits exchange, not the life of a redeemed Firebase
session. A completed issuance does not prove sign-in. After an uncertain or lost
response, read this approval; do not replay its effect, automatically start another
intent, or treat elapsed token time as permission to issue again. Any new issuance
requires a separate human review acknowledging the exact frozen prior attempts.
Reviewed revocation invalidates refresh tokens. Already-issued ID tokens can remain
usable where consumers do not check revocation, and an outstanding custom token can
still be exchanged. A successful revocation does not resolve an earlier unknown
issuance. The receipt therefore says revocation_scope: refresh_tokens_only and
session_expiration: not_bounded_by_custom_token rather than promising an ended session.
The browser handles any first credential privately and deliberately, preserving the
owner’s existing session. Public preparation, GET and cancellation always return safe
metadata. There is no agent endpoint for recovering a lost credential.
Direct POST /users/login-link returns 403 account_approval_required. The legacy
Proserver loginUrl and redeem terminals are also retired; old opaque links cannot be
redeemed there. Prepare the reviewed action above instead.
Session preparation is disabled by default and unavailable in production until an
authoritative reverse-grant index with coordinated writers is implemented. It returns
503 managed_session_scope_unavailable before preparation reads when the strategy
is unavailable. Do not retry with new operation IDs to bypass this guard.
The staging prototype requires explicit GCLOUD_PROJECT=gigstackprodev and
MANAGED_SESSION_SCOPE_STRATEGY=prototype_scan. It permits at most 1000 teams,
1000 billing accounts and 100 previous attempts, reading one extra result to detect
overflow. 503 managed_session_scope_limit refuses incomplete scope before issuance;
a truncated result is never treated as authorized scope. This interim guard preserves
the intended reviewed workflow but does not complete production capability.
Configuration and rollout must be verified separately; documentation is not evidence
that a deployed environment enables the strategy.