openapi: 3.1.0

info:
    title: Bigscreen Admin API
    version: "0"
    summary: Internal admin API for Arda, factory tooling, and integration tests.
    description: |
        The **Bigscreen Admin API** powers Arda (the internal admin webapp), the factory floor
        (CNC machines, Fusion 360, pose-analysis tools), and the integration test suite. It is
        not a public API — production access is gated by an EC2 security group that admits only
        Bigscreen office and factory IPs.

        273 endpoints across four auth domains (`/admin/*`, `/fusion/*`, `/cnc/*`, `/pose/*`)
        plus an unauthenticated `/health` probe. Endpoints are grouped into 19 tags.

        ## Auth at a glance

        Every `/admin/*` request needs **two** headers:

        | Header | Value |
        |--------|-------|
        | `Authorization` | `Bearer <admin-api key>` |
        | `x-access-token` | A JWT obtained from the public auth API |

        And the access token's account must hold one of the **access policies** the endpoint
        requires (`Admin`, `Moderator`, `Fabricator`, `Inventory`, etc.). Policies are listed
        under each endpoint's `x-access-policies` extension.

        `/fusion/*`, `/cnc/*`, and `/pose/*` use their own per-domain bearer keys — Fusion has
        no per-user access token (LB-gated), CNC and Pose require an operator-account JWT.

        See `components.securitySchemes` below for the four API identities (`admin-api`,
        `fusion-api`, `cnc-machine-api`, `pose-api`) and the relationship between the
        bearer keys, access tokens, and per-endpoint access policies.

        ## Spec layout

        The OpenAPI source is split per handler module under `docs/openapi/modules/*.yaml`,
        joined by `$ref` from this root file. The bundled artifact at
        `docs/openapi/admin-api.bundled.yaml` is what the Scalar renderer reads — regenerate
        it with `npx -y @redocly/cli@latest bundle docs/openapi/admin-api.yaml -o docs/openapi/admin-api.bundled.yaml`
        after any edit.

servers:
    - url: http://localhost:3999
      description: Local dev (started by `yarn dev:admin-api`)
    - url: https://admin-api.internal.bigscreenvr.com
      description: Production (network-restricted)

tags:
    - name: Health
      description: |
          Unauthenticated liveness probe consumed by load balancers and uptime monitors.
    - name: Inventory
      description: |
          CRUD over individual inventory items. Items are created by the manufacturing pipeline
          (`POST /admin/inventory/item` is the entry point), consumed by the shipping pipeline
          (`PUT /admin/shipper/shipment/:id` with `action: PickInventoryItem`), and reported on
          via `/stats` and `/report`. The shipping pipeline mutates `status` automatically — most
          callers of this module do not need to write `status` directly.
    - name: Fusion
      description: |
          Toolpath generation handed to Fusion 360 workstations on the factory network.
          Authenticated by `fusionApiKey`; no per-user access token (LB-gated).
    - name: CNC
      description: |
          Toolpath delivery and state updates from CNC machines on the factory floor.
          Authenticated by `cncMachineApiKey` + a `CncMachine` access token for the operator.
    - name: Pose
      description: |
          Pose-analysis factory tool. Authenticated by `poseApiKey` + a `PoseAppUser` access token.
    - name: RDC
      description: |
          Bigscreen "RDC" build catalog (Rendering Data Container). Listing and selecting the
          build that runs in production.
    - name: Topics
      description: |
          Marketing topics — short editorial labels surfaced in the Bigscreen Unity app.
    - name: Workers
      description: |
          Live status of background worker threads spawned within `admin_api` (sync jobs,
          shipper queue refresh, KB ingest, CSV exports, etc.).
    - name: Knowledge Base
      description: |
          The internal knowledge base service — natural-language queries, search, document
          ingestion (Discord, GitHub, files), and feedback. Hosted by `apps/kb`.
    - name: Channels
      description: |
          Bigscreen TV — channels (collections of streams), channel groups, and stream entries.
    - name: Media
      description: |
          Media products, items, entitlements, categories, collections, and coupons surfaced
          to the Bigscreen Unity app.
    - name: Accounts
      description: |
          Bigscreen staff account creation, access-policy management, and the
          `GET /admin/access/*` probes used by Arda to gate UI.
    - name: Moderation
      description: |
          Account / room moderation: bans, reports, device history, IP allowlisting,
          notes, login tokens, and analytics for a target account.
    - name: OAuth
      description: |
          OAuth 2.0 admin: clients, grants, scopes, audit log, step-up authentication.
          Powers the OAuth provider that arda fronts.
    - name: Fabricator Scans
      description: |
          Customer face-scan ingestion and processing — scan requests, topology data,
          mesh files, and GDPR scan-data deletion.
    - name: Fabricator Jobs
      description: |
          Manufacturing job pipeline — creation from scan requests, the state machine,
          toolpaths, debug actions, and reports.
    - name: Fabricator Orders
      description: |
          Shopify order integration, order pairing (Beyond + lens inserts), Big Orders
          (Bigscreen's first-party order records mirrored to/from Shopify), bulk sync,
          reports, and Shopify webhook management.
    - name: Shipping
      description: |
          Shipment state machine (creation, picking, label purchase, dispatch), Shippo
          integration, and analytics. Sits at the end of the order pipeline.
    - name: DHL
      description: |
          DHL invoice + per-tracking-number charge ingestion, browsing, reconciliation,
          and flagging. Driven by manual MyBill CSV uploads.

security:
    - adminApiKey: []
      adminAccessToken: []

paths:
    /health:
        $ref: "./modules/health.yaml#/~1health"

    /fusion/whoami:
        $ref: "./modules/fusion.yaml#/~1fusion~1whoami"
    /fusion/next:
        $ref: "./modules/fusion.yaml#/~1fusion~1next"
    /fusion/{toolPathId}:
        $ref: "./modules/fusion.yaml#/~1fusion~1{toolPathId}"

    /cnc:
        $ref: "./modules/cnc.yaml#/~1cnc"
    /cnc/next:
        $ref: "./modules/cnc.yaml#/~1cnc~1next"
    /cnc/{toolPathId}:
        $ref: "./modules/cnc.yaml#/~1cnc~1{toolPathId}"

    /admin/rdc:
        $ref: "./modules/rdc.yaml#/~1admin~1rdc"
    /admin/rdc/active:
        $ref: "./modules/rdc.yaml#/~1admin~1rdc~1active"
    /admin/rdc/active/{build}:
        $ref: "./modules/rdc.yaml#/~1admin~1rdc~1active~1{build}"

    /admin/topic:
        $ref: "./modules/topics.yaml#/~1admin~1topic"
    /admin/topic/{id}:
        $ref: "./modules/topics.yaml#/~1admin~1topic~1{id}"
    /admin/topics:
        $ref: "./modules/topics.yaml#/~1admin~1topics"

    /admin/workers/status:
        $ref: "./modules/workers.yaml#/~1admin~1workers~1status"

    /pose/whoami:
        $ref: "./modules/pose.yaml#/~1pose~1whoami"
    /pose/schemas:
        $ref: "./modules/pose.yaml#/~1pose~1schemas"
    /pose/jobs:
        $ref: "./modules/pose.yaml#/~1pose~1jobs"
    /pose/job/{jobId}:
        $ref: "./modules/pose.yaml#/~1pose~1job~1{jobId}"
    /pose/job/{jobId}/scan:
        $ref: "./modules/pose.yaml#/~1pose~1job~1{jobId}~1scan"
    /pose/job/{jobId}/mesh:
        $ref: "./modules/pose.yaml#/~1pose~1job~1{jobId}~1mesh"
    /pose/job/{jobId}/debug_start_toolpath:
        $ref: "./modules/pose.yaml#/~1pose~1job~1{jobId}~1debug_start_toolpath"
    /pose/job/{jobId}/debug_upload_toolpath:
        $ref: "./modules/pose.yaml#/~1pose~1job~1{jobId}~1debug_upload_toolpath"
    /pose/job/{jobId}/toolpath:
        $ref: "./modules/pose.yaml#/~1pose~1job~1{jobId}~1toolpath"

    /admin/fabricator/schemas:
        $ref: "./modules/fabricator-scans.yaml#/~1admin~1fabricator~1schemas"
    /admin/fabricator/schemas2:
        $ref: "./modules/fabricator-scans.yaml#/~1admin~1fabricator~1schemas2"
    /admin/fabricator/scan_requests:
        $ref: "./modules/fabricator-scans.yaml#/~1admin~1fabricator~1scan_requests"
    /admin/fabricator/scan_requests/repair:
        $ref: "./modules/fabricator-scans.yaml#/~1admin~1fabricator~1scan_requests~1repair"
    /admin/fabricator/account/{bigscreenAccountId}/scan_requests:
        $ref: "./modules/fabricator-scans.yaml#/~1admin~1fabricator~1account~1{bigscreenAccountId}~1scan_requests"
    /admin/fabricator/account/{bigscreenAccountId}/scan_data:
        $ref: "./modules/fabricator-scans.yaml#/~1admin~1fabricator~1account~1{bigscreenAccountId}~1scan_data"
    /admin/fabricator/scan_request/{scanRequestId}:
        $ref: "./modules/fabricator-scans.yaml#/~1admin~1fabricator~1scan_request~1{scanRequestId}"
    /admin/fabricator/scan_request/{scanRequestId}/topology/{topologyPatientIdOverride}:
        $ref: "./modules/fabricator-scans.yaml#/~1admin~1fabricator~1scan_request~1{scanRequestId}~1topology~1{topologyPatientIdOverride}"
    /admin/fabricator/scan_request/{scanRequestId}/scan:
        $ref: "./modules/fabricator-scans.yaml#/~1admin~1fabricator~1scan_request~1{scanRequestId}~1scan"
    /admin/fabricator/scan_request/{scanRequestId}/verify:
        $ref: "./modules/fabricator-scans.yaml#/~1admin~1fabricator~1scan_request~1{scanRequestId}~1verify"
    /admin/fabricator/scan_request/{scanRequestId}/mesh:
        $ref: "./modules/fabricator-scans.yaml#/~1admin~1fabricator~1scan_request~1{scanRequestId}~1mesh"

    /admin/kb/query:
        $ref: "./modules/knowledge-base.yaml#/~1admin~1kb~1query"
    /admin/kb/search:
        $ref: "./modules/knowledge-base.yaml#/~1admin~1kb~1search"
    /admin/kb/ingest/document:
        $ref: "./modules/knowledge-base.yaml#/~1admin~1kb~1ingest~1document"
    /admin/kb/ingest/discord:
        $ref: "./modules/knowledge-base.yaml#/~1admin~1kb~1ingest~1discord"
    /admin/kb/ingest/github:
        $ref: "./modules/knowledge-base.yaml#/~1admin~1kb~1ingest~1github"
    /admin/kb/ingest/github/cleanup-commits:
        $ref: "./modules/knowledge-base.yaml#/~1admin~1kb~1ingest~1github~1cleanup-commits"
    /admin/kb/sync:
        $ref: "./modules/knowledge-base.yaml#/~1admin~1kb~1sync"
    /admin/kb/document/{sourceType}/{sourceId}:
        $ref: "./modules/knowledge-base.yaml#/~1admin~1kb~1document~1{sourceType}~1{sourceId}"
    /admin/kb/documents:
        $ref: "./modules/knowledge-base.yaml#/~1admin~1kb~1documents"
    /admin/kb/document/{documentId}:
        $ref: "./modules/knowledge-base.yaml#/~1admin~1kb~1document~1{documentId}"
    /admin/kb/clear:
        $ref: "./modules/knowledge-base.yaml#/~1admin~1kb~1clear"
    /admin/kb/stats:
        $ref: "./modules/knowledge-base.yaml#/~1admin~1kb~1stats"
    /admin/kb/logs:
        $ref: "./modules/knowledge-base.yaml#/~1admin~1kb~1logs"
    /admin/kb/feedback/{queryLogId}:
        $ref: "./modules/knowledge-base.yaml#/~1admin~1kb~1feedback~1{queryLogId}"

    /admin/tv/channel:
        $ref: "./modules/channels.yaml#/~1admin~1tv~1channel"
    /admin/tv/channel/{channelId}:
        $ref: "./modules/channels.yaml#/~1admin~1tv~1channel~1{channelId}"
    /admin/tv/Channels:
        $ref: "./modules/channels.yaml#/~1admin~1tv~1Channels"
    /admin/tv/stream:
        $ref: "./modules/channels.yaml#/~1admin~1tv~1stream"
    /admin/tv/stream/{channelId}/{streamIndex}:
        $ref: "./modules/channels.yaml#/~1admin~1tv~1stream~1{channelId}~1{streamIndex}"
    /admin/tv/channel_query/{name}:
        $ref: "./modules/channels.yaml#/~1admin~1tv~1channel_query~1{name}"
    /admin/tv/channel_group:
        $ref: "./modules/channels.yaml#/~1admin~1tv~1channel_group"
    /admin/tv/channel_group/{channelGroupId}:
        $ref: "./modules/channels.yaml#/~1admin~1tv~1channel_group~1{channelGroupId}"
    /admin/tv/rebuild_channel_group/{channelGroupId}:
        $ref: "./modules/channels.yaml#/~1admin~1tv~1rebuild_channel_group~1{channelGroupId}"
    /admin/tv/channel_groups:
        $ref: "./modules/channels.yaml#/~1admin~1tv~1channel_groups"

    /admin/oauth/lookup_client:
        $ref: "./modules/oauth.yaml#/~1admin~1oauth~1lookup_client"
    /admin/oauth/my_grant:
        $ref: "./modules/oauth.yaml#/~1admin~1oauth~1my_grant"
    /admin/oauth/codes:
        $ref: "./modules/oauth.yaml#/~1admin~1oauth~1codes"
    /admin/oauth/audit_event:
        $ref: "./modules/oauth.yaml#/~1admin~1oauth~1audit_event"
    /admin/oauth/clients/scopes:
        $ref: "./modules/oauth.yaml#/~1admin~1oauth~1clients~1scopes"
    /admin/oauth/clients:
        $ref: "./modules/oauth.yaml#/~1admin~1oauth~1clients"
    /admin/oauth/clients/{uniqueId}:
        $ref: "./modules/oauth.yaml#/~1admin~1oauth~1clients~1{uniqueId}"
    /admin/oauth/clients/{uniqueId}/rotate_secret:
        $ref: "./modules/oauth.yaml#/~1admin~1oauth~1clients~1{uniqueId}~1rotate_secret"
    /admin/oauth/clients/{uniqueId}/disable:
        $ref: "./modules/oauth.yaml#/~1admin~1oauth~1clients~1{uniqueId}~1disable"
    /admin/oauth/clients/{uniqueId}/enable:
        $ref: "./modules/oauth.yaml#/~1admin~1oauth~1clients~1{uniqueId}~1enable"
    /admin/oauth/clients/{uniqueId}/grants:
        $ref: "./modules/oauth.yaml#/~1admin~1oauth~1clients~1{uniqueId}~1grants"
    /admin/oauth/clients/{uniqueId}/audit:
        $ref: "./modules/oauth.yaml#/~1admin~1oauth~1clients~1{uniqueId}~1audit"
    /admin/oauth/clients/{uniqueId}/step-up/challenge:
        $ref: "./modules/oauth.yaml#/~1admin~1oauth~1clients~1{uniqueId}~1step-up~1challenge"
    /admin/oauth/clients/{uniqueId}/step-up/verify:
        $ref: "./modules/oauth.yaml#/~1admin~1oauth~1clients~1{uniqueId}~1step-up~1verify"
    /admin/oauth/clients/audit:
        $ref: "./modules/oauth.yaml#/~1admin~1oauth~1clients~1audit"
    /admin/oauth/clients/{uniqueId}/hard_delete:
        $ref: "./modules/oauth.yaml#/~1admin~1oauth~1clients~1{uniqueId}~1hard_delete"

    /admin/whoami:
        $ref: "./modules/accounts.yaml#/~1admin~1whoami"
    /admin/access/admin:
        $ref: "./modules/accounts.yaml#/~1admin~1access~1admin"
    /admin/access/community:
        $ref: "./modules/accounts.yaml#/~1admin~1access~1community"
    /admin/access/default:
        $ref: "./modules/accounts.yaml#/~1admin~1access~1default"
    /admin/access/fabricator:
        $ref: "./modules/accounts.yaml#/~1admin~1access~1fabricator"
    /admin/access/inventory:
        $ref: "./modules/accounts.yaml#/~1admin~1access~1inventory"
    /admin/access/moderator:
        $ref: "./modules/accounts.yaml#/~1admin~1access~1moderator"
    /admin/access/reporting:
        $ref: "./modules/accounts.yaml#/~1admin~1access~1reporting"
    /admin/access/superuser:
        $ref: "./modules/accounts.yaml#/~1admin~1access~1superuser"
    /admin/accounts/staff:
        $ref: "./modules/accounts.yaml#/~1admin~1accounts~1staff"
    /admin/account:
        $ref: "./modules/accounts.yaml#/~1admin~1account"
    /admin/onboarding/account:
        $ref: "./modules/accounts.yaml#/~1admin~1onboarding~1account"
    /admin/account/{bigscreenAccountId}/access_policy/{accessPolicy}:
        $ref: "./modules/accounts.yaml#/~1admin~1account~1{bigscreenAccountId}~1access_policy~1{accessPolicy}"
    /admin/account/{bigscreenAccountId}/security_groups:
        $ref: "./modules/accounts.yaml#/~1admin~1account~1{bigscreenAccountId}~1security_groups"
    /admin/account/{bigscreenAccountId}/security_groups/{ip}:
        $ref: "./modules/accounts.yaml#/~1admin~1account~1{bigscreenAccountId}~1security_groups~1{ip}"

    /admin/media/item:
        $ref: "./modules/media.yaml#/~1admin~1media~1item"
    /admin/media/items:
        $ref: "./modules/media.yaml#/~1admin~1media~1items"
    /admin/media/item/{id}:
        $ref: "./modules/media.yaml#/~1admin~1media~1item~1{id}"
    /admin/media/cdn/{cdn}/{cdnId}:
        $ref: "./modules/media.yaml#/~1admin~1media~1cdn~1{cdn}~1{cdnId}"
    /admin/media/schemas:
        $ref: "./modules/media.yaml#/~1admin~1media~1schemas"
    /admin/media/query:
        $ref: "./modules/media.yaml#/~1admin~1media~1query"
    /admin/media/product:
        $ref: "./modules/media.yaml#/~1admin~1media~1product"
    /admin/media/product/{id}:
        $ref: "./modules/media.yaml#/~1admin~1media~1product~1{id}"
    /admin/media/products:
        $ref: "./modules/media.yaml#/~1admin~1media~1products"
    /admin/media/product/{id}/sku:
        $ref: "./modules/media.yaml#/~1admin~1media~1product~1{id}~1sku"
    /admin/media/product/{id}/sku/{skuId}:
        $ref: "./modules/media.yaml#/~1admin~1media~1product~1{id}~1sku~1{skuId}"
    /admin/media/showings/{synchronizationInterval}/{past}/{future}:
        $ref: "./modules/media.yaml#/~1admin~1media~1showings~1{synchronizationInterval}~1{past}~1{future}"
    /admin/media/events/{productId}:
        $ref: "./modules/media.yaml#/~1admin~1media~1events~1{productId}"
    /admin/media/products/export:
        $ref: "./modules/media.yaml#/~1admin~1media~1products~1export"
    /admin/media/entitlement:
        $ref: "./modules/media.yaml#/~1admin~1media~1entitlement"
    /admin/media/entitlement/{id}:
        $ref: "./modules/media.yaml#/~1admin~1media~1entitlement~1{id}"
    /admin/media/entitlements/query:
        $ref: "./modules/media.yaml#/~1admin~1media~1entitlements~1query"
    /admin/media/entitlements:
        $ref: "./modules/media.yaml#/~1admin~1media~1entitlements"
    /admin/media/entitlements/export:
        $ref: "./modules/media.yaml#/~1admin~1media~1entitlements~1export"
    /admin/media/category:
        $ref: "./modules/media.yaml#/~1admin~1media~1category"
    /admin/media/categories:
        $ref: "./modules/media.yaml#/~1admin~1media~1categories"
    /admin/media/category/{id}:
        $ref: "./modules/media.yaml#/~1admin~1media~1category~1{id}"
    /admin/media/collection:
        $ref: "./modules/media.yaml#/~1admin~1media~1collection"
    /admin/media/collections:
        $ref: "./modules/media.yaml#/~1admin~1media~1collections"
    /admin/media/collection/{id}:
        $ref: "./modules/media.yaml#/~1admin~1media~1collection~1{id}"
    /admin/media/coupons:
        $ref: "./modules/media.yaml#/~1admin~1media~1coupons"
    /admin/media/coupon:
        $ref: "./modules/media.yaml#/~1admin~1media~1coupon"
    /admin/media/coupon/{id}:
        $ref: "./modules/media.yaml#/~1admin~1media~1coupon~1{id}"
    /admin/media/rebuild/category/{id}:
        $ref: "./modules/media.yaml#/~1admin~1media~1rebuild~1category~1{id}"
    /admin/media/rebuild/skus:
        $ref: "./modules/media.yaml#/~1admin~1media~1rebuild~1skus"

    /admin/inventory/hint:
        $ref: "./modules/inventory.yaml#/~1admin~1inventory~1hint"
    /admin/inventory/items:
        $ref: "./modules/inventory.yaml#/~1admin~1inventory~1items"
    /admin/inventory/stats:
        $ref: "./modules/inventory.yaml#/~1admin~1inventory~1stats"
    /admin/inventory/item:
        $ref: "./modules/inventory.yaml#/~1admin~1inventory~1item"
    /admin/inventory/item/{id}:
        $ref: "./modules/inventory.yaml#/~1admin~1inventory~1item~1{id}"
    /admin/inventory/item/{id}/history:
        $ref: "./modules/inventory.yaml#/~1admin~1inventory~1item~1{id}~1history"
    /admin/inventory/report:
        $ref: "./modules/inventory.yaml#/~1admin~1inventory~1report"
    /admin/inventory/sync:
        $ref: "./modules/inventory.yaml#/~1admin~1inventory~1sync"

    /admin/dhl/invoices:
        $ref: "./modules/dhl.yaml#/~1admin~1dhl~1invoices"
    /admin/dhl/invoices/summary:
        $ref: "./modules/dhl.yaml#/~1admin~1dhl~1invoices~1summary"
    /admin/dhl/invoices/{id}:
        $ref: "./modules/dhl.yaml#/~1admin~1dhl~1invoices~1{id}"
    /admin/dhl/invoices/upload-csv:
        $ref: "./modules/dhl.yaml#/~1admin~1dhl~1invoices~1upload-csv"
    /admin/dhl/charges:
        $ref: "./modules/dhl.yaml#/~1admin~1dhl~1charges"
    /admin/dhl/charges/flagged:
        $ref: "./modules/dhl.yaml#/~1admin~1dhl~1charges~1flagged"
    /admin/dhl/charges/{id}:
        $ref: "./modules/dhl.yaml#/~1admin~1dhl~1charges~1{id}"
    /admin/dhl/reconcile:
        $ref: "./modules/dhl.yaml#/~1admin~1dhl~1reconcile"
    /admin/dhl/all:
        $ref: "./modules/dhl.yaml#/~1admin~1dhl~1all"

    /admin/shipper/next:
        $ref: "./modules/shipping.yaml#/~1admin~1shipper~1next"
    /admin/shipper/next3:
        $ref: "./modules/shipping.yaml#/~1admin~1shipper~1next3"
    /admin/shipper/stats:
        $ref: "./modules/shipping.yaml#/~1admin~1shipper~1stats"
    /admin/shipper/shipments:
        $ref: "./modules/shipping.yaml#/~1admin~1shipper~1shipments"
    /admin/shipper/shipments/stats:
        $ref: "./modules/shipping.yaml#/~1admin~1shipper~1shipments~1stats"
    /admin/shipper/shipments/status:
        $ref: "./modules/shipping.yaml#/~1admin~1shipper~1shipments~1status"
    /admin/shipper/shipment:
        $ref: "./modules/shipping.yaml#/~1admin~1shipper~1shipment"
    /admin/shipper/shipment/{id}:
        $ref: "./modules/shipping.yaml#/~1admin~1shipper~1shipment~1{id}"
    /admin/shipper/shipment/{id}/shopify:
        $ref: "./modules/shipping.yaml#/~1admin~1shipper~1shipment~1{id}~1shopify"
    /admin/shipper/shipment/{id}/checklist:
        $ref: "./modules/shipping.yaml#/~1admin~1shipper~1shipment~1{id}~1checklist"
    /admin/shipper/shipment/{id}/customs-preview:
        $ref: "./modules/shipping.yaml#/~1admin~1shipper~1shipment~1{id}~1customs-preview"
    /admin/shipper/sync:
        $ref: "./modules/shipping.yaml#/~1admin~1shipper~1sync"
    /admin/shipper/cache_transactions:
        $ref: "./modules/shipping.yaml#/~1admin~1shipper~1cache_transactions"
    /admin/shippo/analytics:
        $ref: "./modules/shipping.yaml#/~1admin~1shippo~1analytics"
    /admin/shippo/analytics/transactions:
        $ref: "./modules/shipping.yaml#/~1admin~1shippo~1analytics~1transactions"
    /admin/shippo/analytics/cache-status:
        $ref: "./modules/shipping.yaml#/~1admin~1shippo~1analytics~1cache-status"
    /admin/shippo/analytics/refresh:
        $ref: "./modules/shipping.yaml#/~1admin~1shippo~1analytics~1refresh"

    /admin/fabricator/job:
        $ref: "./modules/fabricator-jobs.yaml#/~1admin~1fabricator~1job"
    /admin/fabricator/job/{jobId}:
        $ref: "./modules/fabricator-jobs.yaml#/~1admin~1fabricator~1job~1{jobId}"
    /admin/fabricator/job/{jobId}/test_preprocessor:
        $ref: "./modules/fabricator-jobs.yaml#/~1admin~1fabricator~1job~1{jobId}~1test_preprocessor"
    /admin/fabricator/job/{jobId}/extra:
        $ref: "./modules/fabricator-jobs.yaml#/~1admin~1fabricator~1job~1{jobId}~1extra"
    /admin/fabricator/jobs:
        $ref: "./modules/fabricator-jobs.yaml#/~1admin~1fabricator~1jobs"
    /admin/fabricator/job/{jobId}/scan:
        $ref: "./modules/fabricator-jobs.yaml#/~1admin~1fabricator~1job~1{jobId}~1scan"
    /admin/fabricator/job/{jobId}/mesh:
        $ref: "./modules/fabricator-jobs.yaml#/~1admin~1fabricator~1job~1{jobId}~1mesh"
    /admin/fabricator/job/{jobId}/debug_start_toolpath:
        $ref: "./modules/fabricator-jobs.yaml#/~1admin~1fabricator~1job~1{jobId}~1debug_start_toolpath"
    /admin/fabricator/job/{jobId}/debug_upload_toolpath:
        $ref: "./modules/fabricator-jobs.yaml#/~1admin~1fabricator~1job~1{jobId}~1debug_upload_toolpath"
    /admin/fabricator/job/{jobId}/debug_revert_history:
        $ref: "./modules/fabricator-jobs.yaml#/~1admin~1fabricator~1job~1{jobId}~1debug_revert_history"
    /admin/fabricator/job/{jobId}/toolpath:
        $ref: "./modules/fabricator-jobs.yaml#/~1admin~1fabricator~1job~1{jobId}~1toolpath"
    /admin/fabricator/jobs/checklist:
        $ref: "./modules/fabricator-jobs.yaml#/~1admin~1fabricator~1jobs~1checklist"
    /admin/fabricator/jobs/report:
        $ref: "./modules/fabricator-jobs.yaml#/~1admin~1fabricator~1jobs~1report"
    /admin/fabricator/jobs/report2:
        $ref: "./modules/fabricator-jobs.yaml#/~1admin~1fabricator~1jobs~1report2"
    /admin/fabricator/product/{id}:
        $ref: "./modules/fabricator-jobs.yaml#/~1admin~1fabricator~1product~1{id}"
    /admin/fabricator/variant/{id}:
        $ref: "./modules/fabricator-jobs.yaml#/~1admin~1fabricator~1variant~1{id}"

    /admin/auth/schemas:
        $ref: "./modules/moderation.yaml#/~1admin~1auth~1schemas"
    /admin/profile:
        $ref: "./modules/moderation.yaml#/~1admin~1profile"
    /admin/account/query/{field}/{value}:
        $ref: "./modules/moderation.yaml#/~1admin~1account~1query~1{field}~1{value}"
    /admin/search/{field}/{value}:
        $ref: "./modules/moderation.yaml#/~1admin~1search~1{field}~1{value}"
    /admin/account/{bigscreenAccountId}:
        $ref: "./modules/moderation.yaml#/~1admin~1account~1{bigscreenAccountId}"
    /admin/account/{bigscreenAccountId}/ban:
        $ref: "./modules/moderation.yaml#/~1admin~1account~1{bigscreenAccountId}~1ban"
    /admin/account/{bigscreenAccountId}/unban:
        $ref: "./modules/moderation.yaml#/~1admin~1account~1{bigscreenAccountId}~1unban"
    /admin/account/{bigscreenAccountId}/disable:
        $ref: "./modules/moderation.yaml#/~1admin~1account~1{bigscreenAccountId}~1disable"
    /admin/account/{bigscreenAccountId}/note:
        $ref: "./modules/moderation.yaml#/~1admin~1account~1{bigscreenAccountId}~1note"
    /admin/account/{bigscreenAccountId}/email_update_ticket:
        $ref: "./modules/moderation.yaml#/~1admin~1account~1{bigscreenAccountId}~1email_update_ticket"
    /admin/account/{bigscreenAccountId}/token:
        $ref: "./modules/moderation.yaml#/~1admin~1account~1{bigscreenAccountId}~1token"
    /admin/account/{bigscreenAccountId}/token2:
        $ref: "./modules/moderation.yaml#/~1admin~1account~1{bigscreenAccountId}~1token2"
    /admin/account/{bigscreenAccountId}/device_history:
        $ref: "./modules/moderation.yaml#/~1admin~1account~1{bigscreenAccountId}~1device_history"
    /admin/device/{deviceUniqueIdentifier}:
        $ref: "./modules/moderation.yaml#/~1admin~1device~1{deviceUniqueIdentifier}"
    /admin/ip/{ip}:
        $ref: "./modules/moderation.yaml#/~1admin~1ip~1{ip}"
    /admin/account/{bigscreenAccountId}/reports:
        $ref: "./modules/moderation.yaml#/~1admin~1account~1{bigscreenAccountId}~1reports"
    /admin/account_reports:
        $ref: "./modules/moderation.yaml#/~1admin~1account_reports"
    /admin/room_reports:
        $ref: "./modules/moderation.yaml#/~1admin~1room_reports"
    /admin/account_report/{accountReportId}:
        $ref: "./modules/moderation.yaml#/~1admin~1account_report~1{accountReportId}"
    /admin/room_report/{roomReportId}:
        $ref: "./modules/moderation.yaml#/~1admin~1room_report~1{roomReportId}"
    /admin/account/{bigscreenAccountId}/history:
        $ref: "./modules/moderation.yaml#/~1admin~1account~1{bigscreenAccountId}~1history"
    /admin/account/{bigscreenAccountId}/event/{event}:
        $ref: "./modules/moderation.yaml#/~1admin~1account~1{bigscreenAccountId}~1event~1{event}"
    /admin/account/{bigscreenAccountId}/stats:
        $ref: "./modules/moderation.yaml#/~1admin~1account~1{bigscreenAccountId}~1stats"
    /admin/account/{bigscreenAccountId}/logs:
        $ref: "./modules/moderation.yaml#/~1admin~1account~1{bigscreenAccountId}~1logs"
    /admin/logs/{logType}:
        $ref: "./modules/moderation.yaml#/~1admin~1logs~1{logType}"
    /admin/alert:
        $ref: "./modules/moderation.yaml#/~1admin~1alert"

    /admin/shop/test_order:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1test_order"
    /admin/shop/shopify_order:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1shopify_order"
    /admin/shop/shopify_order_2:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1shopify_order_2"
    /admin/shop/shopify_orders:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1shopify_orders"
    /admin/shop/shopify_order/{shopifyOrderId}:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1shopify_order~1{shopifyOrderId}"
    /admin/shop/shopify_order_cache/{shopifyOrderId}:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1shopify_order_cache~1{shopifyOrderId}"
    /admin/shop/shopify_order/{shopifyOrderId}/fulfillments:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1shopify_order~1{shopifyOrderId}~1fulfillments"
    /admin/shop/shopify_order/{shopifyOrderId}/fulfillment_orders:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1shopify_order~1{shopifyOrderId}~1fulfillment_orders"
    /admin/shop/shopify_order/{shopifyOrderId}/line_item:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1shopify_order~1{shopifyOrderId}~1line_item"
    /admin/shop/shopify_order/{shopifyOrderId}/line_item/{shopifyLineItemId}:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1shopify_order~1{shopifyOrderId}~1line_item~1{shopifyLineItemId}"
    /admin/shop/shopify_order/{shopifyOrderId}/risks:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1shopify_order~1{shopifyOrderId}~1risks"
    /admin/shop/webhooks/install:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1webhooks~1install"
    /admin/shop/webhooks/uninstall:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1webhooks~1uninstall"
    /admin/shop/webhooks:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1webhooks"
    /admin/shop/shopify_orders/pair:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1shopify_orders~1pair"
    /admin/shop/shopify_orders/pairs:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1shopify_orders~1pairs"
    /admin/shop/shopify_orders/pair/{pairId}:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1shopify_orders~1pair~1{pairId}"
    /admin/shop/orders:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1orders"
    /admin/shop/order:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1order"
    /admin/shop/order/{bigOrderId}:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1order~1{bigOrderId}"
    /admin/shop/order/{bigOrderId}/scan_requests:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1order~1{bigOrderId}~1scan_requests"
    /admin/shop/order/{bigOrderId}/shipping_summary:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1order~1{bigOrderId}~1shipping_summary"
    /admin/shop/order/{bigOrderId}/shipments:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1order~1{bigOrderId}~1shipments"
    /admin/shop/account/{bigscreenAccountId}/orders:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1account~1{bigscreenAccountId}~1orders"
    /admin/shop/order/{bigOrderId}/checklist:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1order~1{bigOrderId}~1checklist"
    /admin/shop/order/{bigOrderId}/sync_line_items:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1order~1{bigOrderId}~1sync_line_items"
    /admin/shop/order/{bigOrderId}/sync:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1order~1{bigOrderId}~1sync"
    /admin/shop/orders/report:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1orders~1report"
    /admin/shop/orders/report2:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1orders~1report2"
    /admin/shop/orders/checklist:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1orders~1checklist"
    /admin/shop/orders/data:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1orders~1data"
    /admin/shop/orders/sync:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1orders~1sync"
    /admin/shop/orders/sync2:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1orders~1sync2"
    /admin/shop/orders/sync3:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1orders~1sync3"
    /admin/shop/orders/sync_all_big_orders:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1orders~1sync_all_big_orders"
    /admin/shop/sync/{shopifyOrderId}:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1sync~1{shopifyOrderId}"
    /admin/shop/products:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1products"
    /admin/shop/products_snapshot:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1products_snapshot"
    /admin/shop/test/getBeyondPackageInventoryCode:
        $ref: "./modules/fabricator-orders.yaml#/~1admin~1shop~1test~1getBeyondPackageInventoryCode"

components:
    securitySchemes:
        adminApiKey:
            type: http
            scheme: bearer
            bearerFormat: AdminApiKey-or-OAuthJWT
            description: |
                64-character app-key registered for the `admin-api` application, OR an OAuth 2.0
                bearer JWT minted by the Bigscreen OAuth provider. The bearer shape (`xxx.yyy.zzz`
                vs single 64-char string) determines which admission path runs.
        adminAccessToken:
            type: apiKey
            in: header
            name: x-access-token
            description: |
                JWT for the **end-user account** the request is acting on behalf of. Required
                in addition to `Authorization` for `/admin/*`. Contains the access policies
                (`Admin`, `Inventory`, etc.) that gate per-endpoint authorization.
        fusionApiKey:
            type: http
            scheme: bearer
            description: |
                Used by `/fusion/*` only — Fusion 360 factory workstations. No access token
                required (network-level gating via load balancer).
        cncMachineApiKey:
            type: http
            scheme: bearer
            description: Used by `/cnc/*` together with a `CncMachine` access token.
        cncAccessToken:
            type: apiKey
            in: header
            name: x-access-token
            description: Operator JWT for `/cnc/*`.
        poseApiKey:
            type: http
            scheme: bearer
            description: Used by `/pose/*` together with a `PoseAppUser` access token.
        poseAccessToken:
            type: apiKey
            in: header
            name: x-access-token
            description: Operator JWT for `/pose/*`.

    responses:
        Unauthorized:
            description: Missing or invalid `Authorization` / `x-access-token`.
            content:
                application/json:
                    schema: { $ref: "#/components/schemas/Error" }
        Forbidden:
            description: Authenticated but lacks the required access policy or scope.
            content:
                application/json:
                    schema: { $ref: "#/components/schemas/Error" }

    schemas:
        Error:
            type: object
            required: [error]
            properties:
                error:
                    type: string
                    description: Human-readable error message.
                details:
                    description: Optional structured details (validation errors, etc.).
            example:
                error: "Forbidden"
                details: { requiredPolicy: "Admin" }

        BigInventoryItemStatus:
            type: string
            description: |
                State-machine position of an inventory item. Drives shipping eligibility,
                report inclusion, and dashboard counts.
            enum:
                - Unknown
                - RequiresQA
                - InStock
                - InShippingQueue
                - WithShipment
                - Shipped
                - Damaged
                - Deleted
            x-enum-descriptions:
                Unknown: Default — should not appear on persisted rows.
                RequiresQA: Item needs a QA step before it can be stocked.
                InStock: Available in inventory; ready to assign to a shipment.
                InShippingQueue: Selected for shipment; not yet packed.
                WithShipment: Attached to a `BigShipment`; not yet shipped.
                Shipped: Handed off to the carrier.
                Damaged: Flagged as damaged; not eligible for shipping.
                Deleted: Soft-deleted; hidden from default queries.

        BigInventoryTrackingType:
            type: string
            description: |
                How quantity is tracked for this item. `Personalized` items always have
                `quantity = 1` and a unique `serialNumber` (one customer, one cushion).
                `QuantityTracked` items aggregate (e.g. a tray of 200 soft straps).
                `Untracked` items are not counted (cables, screws — anything where exact
                inventory count isn't worth maintaining).
            enum:
                - Unknown
                - Personalized
                - QuantityTracked
                - Untracked

        BigProductType:
            type: string
            description: |
                Product taxonomy. Maps to Shopify variants for sellable items and to internal
                fabricator data for manufactured cushions. Adding a value requires a
                corresponding metafield in Shopify (see internal docs).
            enum:
                - Unknown
                - BigscreenBeyondV1
                - BeyondCushionV1
                - AudioStrapV1
                - BeyondFibreOpticCableV1
                - BeyondLinkBoxV1
                - BeyondSoftStrapV1
                - ReplacementBigscreenBeyondV1
                - ReplacementBeyondCushionV1
                - ReplacementBeyondFibreOpticCableV1
                - ReplacementBeyondLinkBoxV1
                - ReplacementBeyondSoftStrapV1
                - BeyondCyberboxV1
                - IPDDiscoveryUnitV1
                - CustomCushion
                - PrescriptionLenses
                - PrescriptionLensInserts
                - AudioStrap
                - Beyond2
                - Beyond2Upgrade
                - Beyond2Eye
                - Beyond2EyeUpgrade
                - Beyond2EyeVRChat
                - UniversalHalo
                - CoverShell
                - GenericCushion
                - Merchandise
                - Beyond2IPDTool
                - BigscreenRacingGloves
                - LinkBooster
                - Other

        BigInventoryItem:
            type: object
            description: |
                One physical (or virtual) inventory unit. Mirrors the `big_inventory_items`
                table; created by the manufacturing pipeline and consumed by the shipping
                pipeline.
            required: [id, type, status, trackingType]
            properties:
                id: { type: string }
                creatorBigscreenAccountId: { type: string }
                serialNumber:
                    type: string
                    description: Unique for `Personalized`; batch id or empty for the others.
                sku: { type: string }
                shopifySku: { type: string }
                type: { $ref: "#/components/schemas/BigProductType" }
                trackingType: { $ref: "#/components/schemas/BigInventoryTrackingType" }
                quantity:
                    type: integer
                    minimum: 0
                    default: 0
                status: { $ref: "#/components/schemas/BigInventoryItemStatus" }
                history:
                    type: array
                    items: { type: object, additionalProperties: true }
                bigShipmentId:
                    type: string
                    description: Set when `status` becomes `WithShipment`.
                pickingHint:
                    description: Free-form payload set by the picking station.
                jobId:
                    type: string
                    description: Manufacturing job that produced this item, if any.
                forecastBigOrderId:
                    type: string
                    description: For pre-allocated items reserved against a future order.
                createdAt: { type: string, format: date-time }
                updatedAt: { type: string, format: date-time }

        BigInventoryItemCreationParams:
            type: object
            properties:
                serialNumber: { type: string }
                sku: { type: string }
                productType: { $ref: "#/components/schemas/BigProductType" }
                trackingType: { $ref: "#/components/schemas/BigInventoryTrackingType" }
                quantity: { type: integer, minimum: 0 }
                jobId: { type: string }
                metadata:
                    type: object
                    additionalProperties: true

        InventoryReport:
            type: object
            required: [timestamp, summary, byProductType]
            properties:
                timestamp: { type: string, format: date-time }
                summary:
                    type: object
                    description: Top-level counts across all product types.
                    properties:
                        totalItems: { type: integer }
                        inStock: { type: integer }
                        inShippingQueue: { type: integer }
                        shipped: { type: integer }
                        damaged: { type: integer }
                        deleted: { type: integer }
                byProductType:
                    type: object
                    description: |
                        Same shape as `summary`, keyed by `BigProductType` value. Only product
                        types with at least one item are present.
                    additionalProperties:
                        type: object
                        properties:
                            total: { type: integer }
                            inStock: { type: integer }
                            inShippingQueue: { type: integer }
                            shipped: { type: integer }
                            damaged: { type: integer }
                recentActivity:
                    type: object
                    properties:
                        itemsCreatedToday: { type: integer }
                        itemsShippedToday: { type: integer }
                        itemsReturnedToday: { type: integer }
                lowStockWarnings:
                    type: array
                    items:
                        type: object
                        properties:
                            productType: { $ref: "#/components/schemas/BigProductType" }
                            currentStock: { type: integer }
                            threshold: { type: integer }
