Skip to main content

preview API

Table of Contents

Top

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.

FieldTypeLabelDescription
revoked_countint32revoked_count is the number of live sessions flipped to ended for the org.

EndPreviewRequest

EndPreviewRequest revokes one preview.

FieldTypeLabelDescription
preview_idstringpreview_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.

FieldTypeLabelDescription
revokedboolrevoked 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.

FieldTypeLabelDescription
run_idstringrun_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.

FieldTypeLabelDescription
preview_urlstringpreview_url is the per-preview subdomain URL with the one-time handoff token: https://preview-{previewID}.upsquad.ai/__preview/auth?tk=<token>.
preview_idstringpreview_id is the 22-char unguessable base62 id naming the subdomain.
expires_atgoogle.protobuf.Timestampexpires_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 NameRequest TypeResponse TypeDescription
MintPreviewURLMintPreviewURLRequestMintPreviewURLResponseMintPreviewURL issues an authenticated preview URL for a serve-mode run's review window. Returns https://preview-{previewID}.upsquad.ai/__preview/auth?tk=&lt;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.
EndPreviewEndPreviewRequestEndPreviewResponseEndPreview 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.
EndAllPreviewsEndAllPreviewsRequestEndAllPreviewsResponseEndAllPreviews 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 TypeNotesC++JavaPythonGoC#PHPRuby
doubledoubledoublefloatfloat64doublefloatFloat
floatfloatfloatfloatfloat32floatfloatFloat
int32Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead.int32intintint32intintegerBignum or Fixnum (as required)
int64Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead.int64longint/longint64longinteger/stringBignum
uint32Uses variable-length encoding.uint32intint/longuint32uintintegerBignum or Fixnum (as required)
uint64Uses variable-length encoding.uint64longint/longuint64ulonginteger/stringBignum or Fixnum (as required)
sint32Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s.int32intintint32intintegerBignum or Fixnum (as required)
sint64Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s.int64longint/longint64longinteger/stringBignum
fixed32Always four bytes. More efficient than uint32 if values are often greater than 2^28.uint32intintuint32uintintegerBignum or Fixnum (as required)
fixed64Always eight bytes. More efficient than uint64 if values are often greater than 2^56.uint64longint/longuint64ulonginteger/stringBignum
sfixed32Always four bytes.int32intintint32intintegerBignum or Fixnum (as required)
sfixed64Always eight bytes.int64longint/longint64longinteger/stringBignum
boolboolbooleanbooleanboolboolbooleanTrueClass/FalseClass
stringA string must always contain UTF-8 encoded or 7-bit ASCII text.stringStringstr/unicodestringstringstringString (UTF-8)
bytesMay contain any arbitrary sequence of bytes.stringByteStringstr[]byteByteStringstringString (ASCII-8BIT)