{"api_version":"v1","app_ai_endpoint":{"auth":"same-origin browser request carrying the app's platform session (launch from auth.repo.box); no API key, no per-app credential","compatibility":"OpenAI chat.completions (subset)","defaults":{"app_daily_requests":2000,"default_model":"gpt-5.6-terra","enabled":true,"endpoint_path":"/_repo_box/ai/v1/chat/completions","max_input_chars":32000,"max_output_tokens":2048,"models":["gpt-5.6-terra","gpt-5.6-luna"],"provider":"chatmock","public_policy":null,"streaming":false,"user_daily_requests":200},"limits":{"app_daily_requests_ceiling":20000,"max_body_bytes":262144,"max_input_chars_ceiling":64000,"max_messages":64,"max_output_tokens_ceiling":4096,"user_daily_requests_ceiling":2000},"models":["gpt-5.6-terra","gpt-5.6-luna","gpt-5.6-sol","gpt-5.5"],"models_url":"https://<app>.repo.box/_repo_box/ai/v1/models","provider":"chatmock (via the platform broker; never exposed)","public_apps":"AI stays off unless the app declares public_policy 'signed-in-quota' with explicit quotas; even then only signed-in platform users with access can call it","streaming":false,"tools":false,"url":"https://<app>.repo.box/_repo_box/ai/v1/chat/completions"},"authentication":{"binding":"one owner; only that owner's apps, optionally narrowed to named apps; expires (<=90 days); revocable","issued_by":"an operator with `repobox-platform service-token create` (written once to a 0600 file)","never_granted":["SSH","Caddy apply/reload","database access","user/grant/session administration","provider (ChatMock/ChatGPT) credentials"],"oauth":"not implemented; a scoped OAuth client-credentials issuer is the remaining dependency. Do not treat this as OAuth.","scheme":"Authorization: Bearer rbp_<43 base64url chars>","scopes":[{"description":"List and inspect the owner's apps (registry fields, identity contract, AI policy).","name":"apps:read"},{"description":"File an app registration request; an operator approves it with the CLI.","name":"apps:request"},{"description":"Read an app's AI policy and today's usage counters.","name":"ai:read"},{"description":"Change an app's AI policy within platform ceilings (enable/disable, models, limits, quotas).","name":"ai:write"},{"description":"Preview the generated Caddy route of an app (read-only; applying routes stays operator-only).","name":"routes:read"},{"description":"Read the control plane release status (version, schema, AI broker reachability).","name":"release:read"}],"type":"service_token"},"docs":"https://auth.repo.box/docs","documentation":{"cli":"repobox-platform --help (operator host); every subcommand has --help","docs":"https://auth.repo.box/docs","openapi":"https://auth.repo.box/api/platform/v1/openapi.json","publisher_quickstart":"https://auth.repo.box/docs#publish","skill":"https://auth.repo.box/api/platform/v1/skill.md"},"endpoints":{"ai_policy":"GET|PATCH https://auth.repo.box/api/platform/v1/apps/{name}/ai","app":"GET https://auth.repo.box/api/platform/v1/apps/{name}","app_requests":"GET|POST https://auth.repo.box/api/platform/v1/app-requests","apps":"GET https://auth.repo.box/api/platform/v1/apps","discovery":"https://auth.repo.box/api/platform/v1","docs":"GET https://auth.repo.box/docs (HTML, public)","mcp":"POST https://auth.repo.box/api/platform/v1/mcp","release":"GET https://auth.repo.box/api/platform/v1/release","route_preview":"GET https://auth.repo.box/api/platform/v1/apps/{name}/route","whoami":"GET https://auth.repo.box/api/platform/v1/whoami"},"mcp":{"auth":"same bearer service token","endpoint":"https://auth.repo.box/api/platform/v1/mcp","protocol_version":"2025-06-18","tools":["whoami","list_apps","get_app","get_ai_policy","update_ai_policy","preview_route","request_app_registration","list_app_requests","release_status"],"transport":"streamable HTTP (JSON responses only, no SSE)"},"publishing":{"archive_formats":["docker save output (tar), optionally gzip-compressed (Docker 25+ writes Docker + OCI index metadata; both are read)","podman save --format docker-archive or --format oci-archive (tar)","OCI image layout tar, e.g. docker buildx build --platform linux/amd64 --provenance=false --output type=oci,dest=myapp.tar .","exactly one image, linux/amd64, at most 2 GiB uploaded"],"available":true,"credential":{"binding":"one publisher principal (immutable pub_… id + handle); it owns and can see only the apps it creates","issued_by":"an operator (`repobox-platform publisher token create`), written once to a 0600 file; expires within 30 days; revocable","not":"not a service token (rbp_…), not a browser session, not OAuth. OAuth client-credentials issuance is a possible future replacement.","scheme":"Authorization: Bearer rbpub_<43 base64url chars>","type":"publisher_token"},"docs":"https://auth.repo.box/docs#publish","endpoints":{"app":"GET https://auth.repo.box/api/platform/v1/publisher/apps/{name}","apps":"GET https://auth.repo.box/api/platform/v1/publisher/apps","deploy":"POST https://auth.repo.box/api/platform/v1/publisher/releases (multipart: manifest, image)","deploy_log":"GET https://auth.repo.box/api/platform/v1/publisher/releases/{id}/log","mcp":"POST https://auth.repo.box/api/platform/v1/mcp (same bearer; publisher tools)","release":"GET https://auth.repo.box/api/platform/v1/publisher/releases/{id}?wait=SECONDS","releases":"GET https://auth.repo.box/api/platform/v1/publisher/releases?app=NAME","restart":"POST https://auth.repo.box/api/platform/v1/publisher/apps/{name}/restart","rollback":"POST https://auth.repo.box/api/platform/v1/publisher/apps/{name}/rollback (optional JSON {\"release\": \"rel-…\"})","runtime_logs":"GET https://auth.repo.box/api/platform/v1/publisher/apps/{name}/logs?tail=200","whoami":"GET https://auth.repo.box/api/platform/v1/publisher/whoami"},"limits":{"apps_per_publisher":10,"releases_per_24h":100,"retained_releases_per_app":3,"upload_max_bytes":2147483648},"mcp_tools":["publisher_whoami","how_to_deploy","list_my_apps","get_my_app","list_releases","get_release","get_build_log","get_app_logs","rollback_app","restart_app"],"not_in_v1":["registry pulls or Git builds (upload the image instead)","secrets management (do not bake secrets into images)","custom domains","public visibility (operator decision)"],"recipe":["docker build --platform linux/amd64 -t myapp .   # any Dockerfile; the app listens on 0.0.0.0:$PORT (or the port you declare)","docker save myapp | gzip > myapp.tar.gz          # or: docker save -o myapp.tar myapp / podman save --format docker-archive -o myapp.tar myapp","curl -fsS -H \"Authorization: Bearer $REPOBOX_PUBLISHER_TOKEN\" -F 'manifest={\"name\":\"myapp\",\"title\":\"My app\",\"runtime\":{\"port\":8080,\"health_path\":\"/healthz\"}};type=application/json' -F image=@myapp.tar.gz \"https://auth.repo.box/api/platform/v1/publisher/releases?wait=300\"","read release.status (live/failed) and app.launcher_url from the answer; if still queued, GET release.links.self?wait=300","open app.launcher_url in a browser (platform sign-in); updates: repeat the upload with the same name; rollback/restart/logs via app.links"],"release_statuses":["queued","building (importing the image)","starting (health check)","live","superseded","failed","done (restart)"],"runtime_contract":{"ai":"same-origin POST /_repo_box/ai/v1/chat/completions from the app's pages (OpenAI chat.completions subset, non-streaming); no key; on by default","data":"a persistent volume at /data (env REPOBOX_DATA_DIR) survives updates and rollbacks","env":"PORT, REPOBOX_APP, REPOBOX_APP_URL, REPOBOX_LAUNCHER_URL, REPOBOX_AI_CHAT_PATH, REPOBOX_RELEASE, REPOBOX_DATA_DIR, plus runtime.env","health":"a release goes live only after GET runtime.health_path answers (2xx/3xx; any non-5xx when it is the default /) within 120 s; the previous release keeps serving until then","identity":"every request carries X-RepoBox-User-Id / X-RepoBox-User / X-RepoBox-Role / X-RepoBox-Auth injected by the edge; the app has no login of its own; key records on X-RepoBox-User-Id","limits":"memory_mb (64-1024, default 512), 1 CPU, 512 processes; no privileged mode, host network, host ports or host mounts","network":"the container is reachable only by the platform edge over the host loopback; listen on 0.0.0.0:$PORT inside the container","port":"runtime.port, else the image's single EXPOSEd TCP port, else 8080; passed as $PORT","visibility":"private: only people an operator grants (and admins) can open it; the publisher cannot change visibility or grants"},"summary":"Deploy your own private app to https://<name>.repo.box by uploading a Docker image archive (`docker save`) with a small JSON manifest in one HTTPS request. No registry, Git host, SSH or Docker access needed.","upload":{"content_type":"multipart/form-data","docs":"https://auth.repo.box/docs#publish","example":"docker build --platform linux/amd64 -t trip-planner . && docker save trip-planner | gzip > trip-planner.tar.gz && curl -fsS -H \"Authorization: Bearer $REPOBOX_PUBLISHER_TOKEN\" -F 'manifest={\"name\":\"trip-planner\",\"title\":\"Trip planner\",\"runtime\":{\"port\":3000,\"health_path\":\"/healthz\"}};type=application/json' -F image=@trip-planner.tar.gz 'https://auth.repo.box/api/platform/v1/publisher/releases?wait=300'","manifest":{"fields":{"ai":"boolean, default true (new apps only)","description":"optional, <= 500 chars","name":"DNS label a-z0-9- (becomes https://<name>.repo.box); required","provenance":"{repository, commit, note} recorded only","runtime":"{port: container port (default: the image's single EXPOSE, else 8080; also $PORT), health_path (default /), memory_mb 64-1024 (default 512), env {NAME: value} (non-secret)}","title":"1-80 chars; required","version":"optional label of your own"},"minimal":{"name":"trip-planner","title":"Trip planner"}},"method":"POST","parts":[{"content":"JSON release manifest (see manifest)","name":"manifest","order":1},{"content":"the output of `docker save <image>` (tar, or gzip-compressed tar), exactly one linux/amd64 image, at most 2 GiB","name":"image","order":2}],"url":"https://auth.repo.box/api/platform/v1/publisher/releases"}},"service":"repo.box platform control plane","software_version":"0.1.0"}