# Gauge.S Portal — agent and site operation guide > Gauge.S community catalogue, design publishing, account library and marketplace. > Updated 2026-10-08. Public site: https://portal.sorek.uk ## Start with the task - Discover approved designs at [/gallery](https://portal.sorek.uk/gallery). Search, creator-defined tags, free/points filters, sort and time windows compose as query parameters. [/sitemap.xml](https://portal.sorek.uk/sitemap.xml) lists public pages. - Read a design at `/designs/{slug}`. Its browser preview is public. `GET /designs/{slug}/pack.json` is preview data for the player, **not** the original `.ogp` download. - Install at [/getting-started](https://portal.sorek.uk/getting-started). The real dashboard flow is Gauges → Add → Import from file → Active. Keep and import the complete `.ogp`; copying the unopened container to an SD card does not import it. - Open an entitled pack in the hosted editor with **Open in editor** on its design page. The portal issues a short-lived, one-use capability; no session cookie is sent to the editor. Do not copy the capability into URLs, logs or later requests. - Publish by hand: choose **Publish to portal** in the editor. It attaches the complete pack to an authenticated portal form using an exact-origin/window/nonce bridge. Review the listing, license and Terms, then submit. The bridge never auto-submits or transfers cookies/reusable credentials. - Manage existing work at **My designs**. Open a project for preview, edit, history, visibility, listing revisions, pack updates and private drafts. An approved predecessor stays public while a replacement is reviewed. - My designs supports batches of up to 50 displayed versions: publish/submit (with Terms), make private, discard working drafts, or delete eligible never-published private projects. Discard retains the project and any published predecessor. Delete uses the same tombstone/reference rules as the project API. Results identify changed/skipped items; stale or unauthorized selections do not change other versions. - Account closure is administrator-managed, never an agent-key scope. Original user IDs, usernames and design attribution remain on a read-only Former creator profile; published designs and existing purchases survive. Private work stays private. Login/contact data is removed and sessions/keys/editor/review capabilities are invalidated. New paid purchases from a closed creator are paused. Account closure and private-project deletion are separate actions. - Share saved work without publishing from **Project → Visibility → Unpublished**. Anonymous preview and signed-in complete-OGP download are independent choices; the same review URL follows the latest saved draft. Its fragment capability is exchanged into a scoped HttpOnly cookie, never placed in request URLs or browser storage. Submission, discard, making private, removal and publication holds revoke access. Review links do not grant API/editor/workspace rights; paid-source private copies cannot use them. ## Machine-assisted authoring The hosted editor uses the same WASM renderer as Gauge.S. For schema, assets, customs/presets, licenses and the complete `.ogp` format, start with the [Gauge authoring guide](https://editor.sorek.uk/gauge-guide.md), including its Design best practices section (ship customs presets, layer 0 + drawOnce for static art, as few sprite layers as possible, group elements that share a parameter). The complete element field/default list is machine-readable at [ogs_editor_schema.js](https://editor.sorek.uk/sim/ogs_editor_schema.js). The guide's [headless agent section](https://editor.sorek.uk/gauge-guide.md#16-for-ai-agents-headless-testing-and-ogp-export) documents the browser `GaugeAgent` API and `agent-render.cjs` recipe. After `GaugeAgent.ready()` returns `true`, an agent can: - `loadDesign(jsonText, assets)` for JSON plus separately supplied named assets. - `loadOgpB64(b64, name, sourceInfo?)` to import an entire source pack without losing its sidecar presets, assets or auxiliary files. - `getDesignJson()` / `setDesignJson(jsonText)` to inspect and change the gauge while retaining imported pack context. - `setParam`, `listParams`, `listFonts`, `screenshotPng` and `exportOgpB64` to test/export. For WebGL, screenshot the browser element; `screenshotPng()` may be blank. Portal-side checks remain authoritative. `portal-source.json` and `X-Gauge-Source` metadata are attribution/version hints, never authorization. ## Persistent agent API keys Create and revoke keys at [/my/api-keys](https://portal.sorek.uk/my/api-keys). Key issuance requires a signed-in active, email-verified account and the current password. A key is shown once, stored as a hash, optionally expires, can be revoked, and is invalidated by account security/session-epoch changes. At most five current keys may be active. Store keys in a local secret manager or process environment; **never put one in a URL, browser storage, source code, prompt transcript or log**. Four independent design-authoring scopes are available: - `design:read`: inspect owned projects and retrieve exact saved versions, plus retrieve the complete currently downloadable `.ogp` by slug using normal author/free/purchase/staff entitlement and daily limits. - `design:submit`: create a private draft or submit a new design/linked fork. Issuing this scope requires explicit consent to the current submission Terms. Public requests must send `terms:true`; a key with stale Terms consent must be reissued. - `design:update`: append a version to an existing owned project. Issuance also requires explicit current-Terms consent. Private updates stay private; public submissions use the normal Terms/render/review rules. - `design:delete`: permanently remove eligible owned never-published private projects from active access, preserving immutable history and shared files. Existing read/submit keys do not acquire new scopes. Issue a replacement at /my/api-keys with the desired scopes; revoke the old key. Keys do not buy designs, spend points, change account/security settings, set prices, follow/comment/review, or moderate. They grant no rights beyond the account owner and do not bypass download quotas, licensing, validation, rendering, publication holds or review. For an existing-project authoring session, choose `design:read` and `design:update`; add `design:delete` only when removing confirmed duplicate private projects. `design:submit` is not needed to update an existing project. Choose a key name and expiry, enter the current password and accept current submission Terms, then copy the newly issued key once into the client secret store. Save the canonical design ID in the client receipt; do not infer it from a later duplicate. ## Fetch a source pack for an authorized edit/fork ```http GET /api/designs/{slug}/source.ogp Authorization: Bearer $GAUGE_S_API_KEY ``` The response body is the exact original `.ogp`, with `Cache-Control: private, no-store`. Decode the base64 `X-Gauge-Source` header as JSON; it includes the pinned `version_id`, SHA-256, license and public source URL. Use `version_id` as `fork_source_version` when submitting a linked fork. A source read uses the normal counted-download path. Do not infer permission from the header: the portal rechecks access and source eligibility on submission. For an agent editing in the hosted browser, pass the fetched pack bytes and decoded metadata to `GaugeAgent.loadOgpB64(b64, "source.ogp", sourceInfo)`. Keep the API key in the agent process; pass only the pack and public attribution metadata to the editor page. Call `getDesignJson()` / `setDesignJson()` to make JSON changes, then `exportOgpB64()` to get the complete modified pack while preserving source assets and customs. ## Submit a new design or fork ```json { "title": "My design fork", "description": "Adapted for my vehicle", "car_tags": "E46, track", "license": "cc-by-nc", "terms": true, "fork_source_version": 123, "fork_changes": "Changed the layout and labels.", "pack_b64": "" } ``` ```http POST /api/designs Authorization: Bearer $GAUGE_S_API_KEY Content-Type: application/json ``` Use `fork_source_version` and a clear `fork_changes` note only for a source-linked fork. A successful `201` returns `{ "id", "version_id", "slug", "url", "status" }`; retain the design ID for subsequent updates. Status may be `pending`, `draft` or `approved` according to the normal render/review and trusted-creator policy. The API never provides a moderation/approval operation. - A linked public fork must use a source version that is still approved, published and free when submitted. The portal rechecks it, inherits its license and keeps the child free. - A paid source is readable only after the account owns it. Save a paid-source adaptation with `"private": true`; its source license is retained and it cannot be published or priced as a linked fork. - `"private": true` creates a private workspace without publication Terms. It stays private until its owner explicitly submits it. - `pack_b64` must contain the complete OGP (maximum 20 MiB); JSON request bodies are capped at 32 MiB. Public submissions require current Terms consent and the key's submission scope. - Duplicate pack bytes return `409`. There is no idempotency key: after an ambiguous timeout, check **My designs** before retrying. - The ordinary validation/upload limit and the per-account daily download cap still apply. A key is not a purchase or additional quota. The existing one-use integration remains available at `GET /my/link-editor`: it requires a portal session, displays a token once, expires in 10 minutes and authorizes one API submission. It is useful for a short editor handoff, not ongoing agents. ## Create once, update that project - `GET /api/designs/{id}` (`design:read`, owner-only) returns id, slug, workspace_url, listing status/private/public, and separate latest_version/current_published_version objects. Version fields include id, number, sha256, bytes, title, description, car_tags, license, review_state, render_state, private, source_url. The published version is nullable and can remain public while the latest draft is private. - `POST /api/designs/{id}/versions` (`design:update`, owner-only) appends using the required current `base_version_id`, complete `pack_b64`, title, description, car_tags, license, changelog and explicit `private` boolean. `private:false` additionally requires `terms:true` and current key consent. Body/pack limits remain 32/20 MiB. It returns 201 with id, unchanged slug, workspace_url, saved-version status/private and a pinned version object. Project identity and immutable earlier versions remain. - Example private update: `{ "base_version_id":123, "title":"My revised design", "description":"Changes", "car_tags":"retro, digital", "license":"cc-by-nc", "changelog":"Revised layout", "private":true, "pack_b64":"" }`. - Compare-and-append: concurrent/identical replay requests using the same base yield at most one saved version; further requests return 409 `stale_base`. No idempotency-key header or automatic POST replay. After an ambiguous response, inspect/read back the existing project. Never advance the base silently or fall back to the create endpoint on failure. - For exact bytes already stored in another owned private project, explicitly add `reuse_from_version_id` for that project's latest draft. Reuse is private-update-only, byte-identical, same license and same immediate fork/private-only relationship; no other-owner/private hash lookup is authorized. Source must still be active, private and never published. The immutable reuse reference survives later source-project removal. Normal global dedupe still applies without this authorization. - `GET /api/designs/{id}/versions/{version_id}/source.ogp` (`design:read`, owner-only) returns the exact complete saved version, including private history, without waiting for rendering. Verify the actual bytes' SHA-256. Headers: X-Gauge-Pack-SHA256, X-Gauge-Version-ID. It is no-store, uses the normal daily download cap and does not affect public ranking. The slug source route still returns the published pack, not a newer private draft. ## Remove an accidental private project `DELETE /api/designs/{id}` requires `design:delete`, ownership and `If-Match: ""`. Only never-published private projects with never-submitted private versions and no protected purchase/community references qualify. Same-owner immutable pack reuse references are retained and allowed. Unsupported removal returns 409 `deletion_not_eligible`; a changed latest version returns 409 `stale_base`; missing If-Match is 428 and malformed is 400. Success: `{ "id":23, "deleted":true, "already_deleted":false, "latest_version_id":125 }`. Repeat DELETE with the same pinned version returns 200 and already_deleted:true. My designs and normal workspace/API/version access exclude the tombstone (404). This is whole-project soft deletion, not draft discard: immutable history, audits, source references and shared blobs remain. Review links revoke; queued/late renderer work cannot resurrect the project. Recommended consolidation: inspect canonical and duplicate IDs → private update canonical with the duplicate's explicit reuse_from_version_id → read that exact saved version and verify SHA-256 → delete only confirmed duplicates with pinned versions → read canonical again and verify duplicate 404s. Update local receipts/handoffs only from these verified results. Never include keys/.env in handoff archives. Project route errors are JSON `{code,error,problems?}`: 400 invalid input, 401 invalidated key/account, 403 missing scope/current public Terms, 404 unknown/not-owned/removed, 409 conflict, 413 size cap, 422 validation, 428 deletion precondition missing, 429 daily limit, 503 unavailable. All API mutations revalidate authorization in their transactions. CORS remains only the configured editor origin without cookies; methods GET/POST/DELETE/OPTIONS, headers Authorization/Content-Type/If-Match. ## Limits and references - The editor's browser publish bridge is the easiest human workflow; API keys are for an explicitly configured local/server-side agent. - Portal keys authenticate only the scoped design-authoring routes documented above. There is no API-key access to purchases, account actions, prices, comments, reviews or moderation. - The physical device HTTP API is a separate unauthenticated LAN/AP interface. Do not expose it to the public internet; see the [device/editor guide](https://editor.sorek.uk/gauge-guide.md#12-deploying-to-a-device-over-http). - [Editor and headless authoring guide](https://editor.sorek.uk/gauge-guide.md) - [Terms](https://portal.sorek.uk/terms) · [Privacy](https://portal.sorek.uk/privacy) · [Licenses](https://portal.sorek.uk/licenses)