preview API
Table of Contents
upsquad/preview/v1/preview.proto
EndAllPreviewsRequest
EndAllPreviewsRequest is the org-scoped kill-switch trigger (no fields — the org is the ambient scope).
EndAllPreviewsResponse
EndAllPreviewsResponse reports how many previews were revoked.
| Field | Type | Label | Description |
|---|---|---|---|
| revoked_count | int32 | revoked_count is the number of live sessions flipped to ended for the org. |
EndPreviewRequest
EndPreviewRequest revokes one preview.
| Field | Type | Label | Description |
|---|---|---|---|
| preview_id | string | preview_id identifies the preview to revoke. Must belong to the caller's org (RLS-enforced); a foreign preview_id is a non-row and is a no-op. |
EndPreviewResponse
EndPreviewResponse reports the revocation outcome.
| Field | Type | Label | Description |
|---|---|---|---|
| revoked | bool | revoked is true when a live session was flipped to ended; false when the preview was already ended/unknown (idempotent no-op). |
MintPreviewURLRequest
MintPreviewURLRequest asks for an authenticated preview URL for a run.
| Field | Type | Label | Description |
|---|---|---|---|
| run_id | string | run_id is the serve-mode run whose review-window preview is requested. The org is ALWAYS the ambient JWT scope, never carried in this message — a cross-org run_id resolves to no session row under RLS and fails closed. |
MintPreviewURLResponse
MintPreviewURLResponse carries the authenticated preview URL.
| Field | Type | Label | Description |
|---|---|---|---|
| preview_url | string | preview_url is the per-preview subdomain URL with the one-time handoff token: https://preview-{previewID}.upsquad.ai/__preview/auth?tk=<token>. | |
| preview_id | string | preview_id is the 22-char unguessable base62 id naming the subdomain. | |
| expires_at | google.protobuf.Timestamp | expires_at is the review-window hard TTL — the cookie the router mints is capped at min(this, now+30m) and every preview is dead after this instant. |
PreviewService
PreviewService is the AUTH plane of the Live Build Experience preview ingress
(ADR-0028 D2, HLD #2234 §3). It mints the one-time, HMAC-signed handoff token
the preview-router exchanges for a host-only __upsq_prev cookie, and it owns
the kill-switch RPCs that revoke previews (D7).
SECURITY POSTURE (ADR-0028): every RPC runs behind the authenticated /rpc
gateway → Clerk authctx → org-scope GUC (app.org_id) → RLS. MintPreviewURL
checks, in order: org membership of the caller for the run's org (RLS makes a
cross-org run a non-row), caller clearance ≥ 4 (the founder-ratified code_exec
floor), session state ready|active, org preview quota, and the preview.enabled
kill-switch + per-env org allowlist. It NEVER trusts an org_id from the request
body — the org is the ambient JWT scope. Any check failure is a fail-closed
error; no URL is minted.
This service is dark until the founder flips preview.enabled per-env AND the
caller's org is on the per-env allowlist (§12.4). It is registered gated at the
gateway so an accidental deploy does not expose it.
| Method Name | Request Type | Response Type | Description |
|---|---|---|---|
| MintPreviewURL | MintPreviewURLRequest | MintPreviewURLResponse | MintPreviewURL issues an authenticated preview URL for a serve-mode run's review window. Returns https://preview-{previewID}.upsquad.ai/__preview/auth?tk=<token> where <token> is a single-use, 60s-TTL, HMAC-signed handoff the router exchanges for a host-only cookie. The token is useless for any other preview, after first use, or after 60s. |
| EndPreview | EndPreviewRequest | EndPreviewResponse | EndPreview revokes a single preview for the caller's org: it flips the session to ended so the router's ≤5s-TTL cache serves 410 on the next request and the reaper stops the sandbox. Idempotent. |
| EndAllPreviews | EndAllPreviewsRequest | EndAllPreviewsResponse | EndAllPreviews is the org-scoped kill-switch (ADR-0028 D7 layer 3): it revokes EVERY live preview for the caller's org in one pass. The platform-wide feature-flag kill-switch (preview.enabled=false) is the env-wide layer; this is the per-org operator lever. |
Scalar Value Types
| .proto Type | Notes | C++ | Java | Python | Go | C# | PHP | Ruby |
|---|---|---|---|---|---|---|---|---|
| double | double | double | float | float64 | double | float | Float | |
| float | float | float | float | float32 | float | float | Float | |
| int32 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) |
| int64 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. | int64 | long | int/long | int64 | long | integer/string | Bignum |
| uint32 | Uses variable-length encoding. | uint32 | int | int/long | uint32 | uint | integer | Bignum or Fixnum (as required) |
| uint64 | Uses variable-length encoding. | uint64 | long | int/long | uint64 | ulong | integer/string | Bignum or Fixnum (as required) |
| sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) |
| sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long | int64 | long | integer/string | Bignum |
| fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int | uint32 | uint | integer | Bignum or Fixnum (as required) |
| fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long | uint64 | ulong | integer/string | Bignum |
| sfixed32 | Always four bytes. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) |
| sfixed64 | Always eight bytes. | int64 | long | int/long | int64 | long | integer/string | Bignum |
| bool | bool | boolean | boolean | bool | bool | boolean | TrueClass/FalseClass | |
| string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode | string | string | string | String (UTF-8) |
| bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str | []byte | ByteString | string | String (ASCII-8BIT) |