╔════════════════════════════════════════════════════════════════════════════╗
║           PANDASTACK PYTHON SDK - QUICK REFERENCE TABLE                    ║
╚════════════════════════════════════════════════════════════════════════════╝

SANDBOXES (38 methods)
─────────────────────────────────────────────────────────────────────────────
SandboxAPI              Sandbox Methods          Filesystem            Commands
─────────────────────   ─────────────────────    ──────────────────    ────────
create()                exec()                   read(path)            run()
list()                  run_code()               write(path, content)
get()                   logs()                   upload(src, dst)
delete()                kill()                   download(src, dst)
fork()                  pause()
fork_tree()             resume()
promote()               snapshot()
                        hibernate()
                        wake()
                        set_ttl()
                        set_persistent()
                        lifecycle()
                        signed_preview_url()
                        preview_url()
                        preview_urls()
                        refresh()
                        (context manager)

HTTP Endpoints          Typical Parameters       Return Type
─────────────────────────────────────────────────────────────────────────────
POST   /v1/sandboxes    template, ttl_seconds    Sandbox dataclass
GET    /v1/sandboxes                            List[Sandbox]
GET    /v1/sandboxes/{id}                       Sandbox
DELETE /v1/sandboxes/{id}                       None
POST   /v1/sandboxes/{id}/exec  cmd            ExecResult
PUT/GET /v1/sandboxes/{id}/fs   path           bytes / Dict
POST   /v1/sandboxes/{id}/fork  metadata       Sandbox
POST   /v1/sandboxes/{id}/fork-tree  count     List[Sandbox]

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

DATABASES (6 methods)
─────────────────────────────────────────────────────────────────────────────
Method              HTTP Call                   Timeout     Notes
─────────────────   ─────────────────────────   ───────     ──────────────
create()            POST /v1/databases          240s        Waits for PostgreSQL
list()              GET  /v1/databases                      List all DBs
get()               GET  /v1/databases/{id}                 Get with credentials
delete()            DELETE /v1/databases/{id}               Irreversible
connection()        GET  /v1/databases/{id}/connection      URLs only
failover()          POST /v1/databases/{id}/failover  300s  Recover from GCS

Connection Returns
  ├─ connection_url: postgres://pandastack:pw@{id}.db.pandastack.ai:5432/pandastack
  ├─ username: "pandastack"
  ├─ password: (auto-generated)
  ├─ broker_url: HTTP REST endpoint
  └─ broker_token: Auth token for broker

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

APPS (10 methods)
─────────────────────────────────────────────────────────────────────────────
CRUD                Deployment              Logs
────────            ──────────────────      ──────
create()            deploy()                deploy_logs()  [SSE Iterator, 900s]
list()              deployments()
get()               deployment()
update()            rollback()
delete()

create() Parameters (all optional except name, git_url):
  ├─ name: str                           [required]
  ├─ git_url: str                        [required]
  ├─ git_branch: str                     [default: main]
  ├─ framework: str                      [auto-detect if None]
  ├─ install_command: str                [override]
  ├─ build_command: str                  [override]
  ├─ start_command: str                  [override]
  ├─ root_directory: str                 [monorepo subdirectory]
  ├─ port: int                           [default: 3000]
  ├─ env: Dict[str, str]                 [build + runtime vars]
  ├─ template: str                       [default: node]
  ├─ cpu: int                            [default: 2]
  └─ memory_mb: int                      [default: 1024]

Frameworks Detected: next | vite | cra | node | python | static | generic

HTTP Endpoints
  POST   /v1/apps                          create
  GET    /v1/apps                          list
  GET    /v1/apps/{id}                     get (includes stable url)
  PATCH  /v1/apps/{id}                     update
  DELETE /v1/apps/{id}                     delete
  POST   /v1/apps/{id}/deploys             deploy (returns status: "queued")
  GET    /v1/apps/{id}/deploys             deployments list
  GET    /v1/apps/{id}/deploys/{depID}     deployment detail
  POST   /v1/apps/{id}/rollback            rollback
  GET    /v1/apps/{id}/deploys/{depID}/logs  deploy_logs (SSE)

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

VOLUMES (4 methods)
─────────────────────────────────────────────────────────────────────────────
Method              HTTP Call                   Notes
─────────────────   ─────────────────────────   ──────────────────────
create()            POST /v1/volumes            Plan quotas apply; 429 if exceeded
list()              GET  /v1/volumes            List all volumes
get()               GET  /v1/volumes/{name}     Get by name
delete()            DELETE /v1/volumes/{name}   Irreversible; rejected if attached

create(name, size_mb)
  ├─ name: str              [workspace-scoped]
  ├─ size_mb: int           [1-65536 (1 MB - 64 GiB)]
  └─ Plan quotas
      ├─ Free:   1 vol × 1 GiB
      ├─ Pro:    10 vol × 10 GiB each / 100 GiB total
      ├─ Team:   50 vol × 50 GiB each / 2.5 TiB total
      └─ Billing: $0.15/GiB-month for excess provisioned storage

Attachment at sandbox creation:
  sandbox = client.sandboxes.create(
      volumes=[{"name": "data", "read_only": False}]
  )

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

AUTHENTICATION
─────────────────────────────────────────────────────────────────────────────
Priority Order:
  1. api_key parameter in Client()
  2. $PANDASTACK_API_KEY environment variable
  3. ~/.config/pandastack/config.json → "token" or "api_key" field
  4. Raises AuthError if not found

Example:
  client = Client(api_key="pds_...")
  # or: PANDASTACK_API_KEY=pds_... python script.py
  # or: echo '{"token":"pds_..."}' > ~/.config/pandastack/config.json

API URL Resolution:
  1. api_url parameter
  2. $PANDASTACK_API environment variable
  3. Default: https://api.pandastack.ai

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

COMMON PATTERNS
─────────────────────────────────────────────────────────────────────────────
Create and execute:
  sandbox = client.sandboxes.create(template="code-interpreter")
  result = sandbox.exec("python3 -c 'print(1+1)'")
  print(result.stdout, result.exit_code)

File I/O:
  sandbox.filesystem.write("/tmp/data.txt", "hello")
  content = sandbox.filesystem.read("/tmp/data.txt")

Preview URL (HMAC-signed, no auth):
  url = sandbox.preview_url(3000)  # https://3000-{uuid}.pandastack.ai

Context manager (auto-cleanup if not persistent):
  with pandastack.Sandbox.create() as s:
      s.exec("whoami")

Fork parallel copies:
  children = sandbox.fork_tree(count=5)

Database connection:
  db = client.databases.create(label="prod")
  # Connect: psql postgres://pandastack:pw@{id}.db.pandastack.ai:5432/pandastack

App deployment pipeline:
  app = client.apps.create(
      name="myapp",
      git_url="https://github.com/me/app",
      framework="nextjs"
  )
  deploy = client.apps.deploy(app["id"])
  for log_line in client.apps.deploy_logs(app["id"], deploy["id"]):
      print(log_line)

Persistent volume:
  vol = client.volumes.create(name="data", size_mb=10240)
  sandbox = client.sandboxes.create(
      volumes=[{"name": "data", "read_only": False}]
  )
  sandbox.filesystem.write("/mnt/data/file.txt", "persistent")

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

DATA MODELS
─────────────────────────────────────────────────────────────────────────────
Sandbox (dataclass, 14 fields):
  id: str
  template: str
  cpu: int
  memory_mb: int
  status: str
  guest_ip: Optional[str]
  created_at: Optional[str]
  metadata: Dict[str, str]
  from_snapshot: Optional[str]
  boot_ms: Optional[int]
  boot_mode: Optional[str]
  persistent: bool
  _client: Client (internal)

ExecResult (dataclass, 4 fields, frozen=True):
  stdout: str
  stderr: str
  exit_code: int
  duration_ms: int

Other resources return Dict[str, Any] (untyped)

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

EXCEPTION TYPES
─────────────────────────────────────────────────────────────────────────────
AuthError              → 401 (missing/invalid token)
NotFoundError          → 404 (resource not found)
BadRequestError        → 4xx (validation, quotas, state errors)
ServerError            → 5xx (service error)
APIConnectionError     → Network/connection failure

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

TIMEOUTS (override default 30s)
─────────────────────────────────────────────────────────────────────────────
Operation                   Timeout     Reason
─────────────────────────   ───────     ──────────────────────────────
Database create             240s        PostgreSQL bootstrap + startup
Database failover           300s        GCS download + WAL replay
App deploy_logs stream      900s        Full build pipeline (up to 12 min)

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

SPECIAL BEHAVIORS
─────────────────────────────────────────────────────────────────────────────
404 Retry for GET/DELETE:
  After 200ms delay, GET/DELETE retries once on 404 to handle cross-edge
  database replication races.

Cross-region sandbox fork:
  For performance, forks default to parent's agent (same-host); cross-host
  fork available via explicit agent selection at API level (SDK creates
  on best-fit agent per scheduler scoring).

Snapshot restore optimization:
  Every create() restores from a baked Firecracker snapshot (~180ms);
  no warm pool of idle VMs.

Boot metrics:
  sandbox.boot_ms tracks restore duration; sandbox.boot_mode indicates
  snapshot restore vs. cold boot.

Preview URL format:
  https://{port}-{sandbox_id}.{suffix}
  ├─ suffix derived from api_url (api.pandastack.ai → pandastack.ai)
  ├─ or override via client.preview_host attribute
  ├─ HMAC signature in path (no token needed)
  └─ UUID acts as bearer credential

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

SOURCE FILES
─────────────────────────────────────────────────────────────────────────────
/sdks/python/src/pandastack/
  ├─ client.py           Client + SandboxAPI
  ├─ sandbox.py          Sandbox + SandboxFilesystem + SandboxCommands
  ├─ databases.py        DatabasesAPI
  ├─ apps.py             AppsAPI
  ├─ volumes.py          VolumesAPI
  ├─ __init__.py         Public exports
  ├─ exceptions.py       Exception types
  ├─ tokens.py           TokensAPI (not in scope)
  ├─ templates.py        TemplatesAPI (not in scope)
  ├─ functions.py        FunctionsAPI (not in scope)
  └─ schedules.py        SchedulesAPI (not in scope)

Documentation:
  ├─ SDK_SURFACE_MAP.md      Full 624-line reference
  ├─ SDK_SURFACE_INDEX.md    Quick reference & index
  └─ QUICK_REFERENCE.txt     This file

═══════════════════════════════════════════════════════════════════════════════
