manifest:
  id: free3d-worker-api-manifest
  updated_at: 2026-03-13
  mode: strict
  owner: free3d.online
  purpose:
    - source of truth for worker sync and direct static file publishing
    - define the product payload that main-site, plugins, and automation consume
    - forbid prepare-style extraction, temporary URLs, and fallback download paths

sources_of_truth:
  api_manifest_url: https://free3d.online/api/manifest.yaml
  api_docs_url: https://free3d.online/api-docs
  worker_manifest_url: https://free3d.online/assets/manifests/worker-manifest.yaml
  worker_guide_url: https://free3d.online/assets/manifests/worker-guide.md

global_rules:
  https_only: true
  direct_pipeline_only: true
  fallbacks: forbidden
  prepare_stage: forbidden
  temporary_extracted_urls: forbidden
  static_files_are_source_of_truth: true
  direct_file_access_must_be_public_https: true
  render_posters_must_not_use_texture_substitution: true

sync_routes:
  - path: /api-sync/status
    method: GET
    auth: public
  - path: /api-sync/status.json
    method: GET
    auth: public
  - path: /api-sync/changes
    method: GET
    auth: required
    query:
      since: integer
      limit: integer
  - path: /api-sync/product/{guid}
    method: GET
    auth: required

status_contract:
  required_fields:
    - ok
    - version
    - latestWorkerVersion
    - staticFilesEnabled
    - productsCount
    - posterCoverage
    - previewCoverage
  recommended_fields:
    - daemon
    - currentVersionLabel
    - syncWatermark
    - lastSuccessfulSyncAt

product_contract:
  envelope:
    accepted:
      - raw product object
      - object with product field containing the product object
  required_fields:
    - guid
    - version
    - type
    - title
    - description
    - keywords
    - updatedAt
    - deleted
    - hash
    - assets
    - files
  type_enum:
    - 0
    - 1
    - 2
  assets_required_fields:
    - previewSmallUrl
    - previewMediumUrl
    - previewLargeUrl
    - metaUrl
  assets_optional_fields:
    - glbUrl
    - glb1kUrl
    - glb10kUrl
    - glb100kUrl
    - animationsUrl
    - animations1kUrl
    - animations10kUrl
    - animations100kUrl
    - inventoryUrl
  poster_rules:
    previewSmallUrl: must point to rendered poster
    previewMediumUrl: must point to rendered poster
    previewLargeUrl: must point to rendered poster
    legacy_texture_jpg_as_poster: forbidden
  file_inventory_rules:
    source_of_truth_for_browser_api_plugin_downloads: true
    required_fields_per_entry:
      - relativePath
      - ext
      - directUrl
    optional_fields_per_entry:
      - lod
      - variant
      - kind
      - contentType
      - sizeBytes
      - browserDefault
      - supportFiles
    ext_lowercase_only: true
    relative_path_must_be_stable: true
    direct_url_must_be_https: true
    direct_url_must_not_expire: true
    topology_folder_rules:
      - per-lod exports should stay grouped under stable folder prefixes such as *_1k, *_10k, *_100k
      - if the same extension exists in multiple topology folders, each file must keep a unique relativePath
      - topology naming must remain deterministic so the main-site can group formats by 1k, 10k, and 100k
    browser_default_selection:
      - worker should mark exactly one browserDefault entry per extension when multiple scene files exist
      - if browserDefault is omitted, main-site may only use deterministic same-extension selection rules
    support_file_rules:
      - supportFiles must preserve product-relative paths
      - supportFiles entries must also expose directUrl equivalents
      - supportFiles should stay inside the same topology folder tree as the owning scene file when possible

direct_download_contract:
  browser_main_site_behavior:
    - main-site authorizes the user
    - main-site resolves the exact direct file from files inventory
    - main-site records download event
    - main-site redirects to directUrl
    - main-site may build short-lived generated archives for textures and all-files using inventory directUrls
  api_plugin_behavior:
    - public API and plugin surfaces must resolve directUrl without worker prepare
    - worker never generates temporary prepared files
    - directUrl is the final file location
  forbidden:
    - POST /api-download/prepare
    - prepared cache keys
    - extraction jobs
    - archive-member lookup as runtime download prerequisite
    - zip-first browser workflow as the primary download contract

change_tracking_rules:
  version_bump_required_when:
    - any metadata field changes
    - any assets URL changes
    - any file inventory entry changes
    - any poster or preview changes
    - any directUrl mapping changes
    - any deleted state changes
  hash_scope:
    - metadata
    - assets
    - files inventory
    - rendered posters

validation_examples:
  product_minimal_shape:
    guid: 11111111-2222-3333-4444-555555555555
    version: 81234
    type: 0
    title: Example static model
    description: Example product used to illustrate the direct static file contract.
    keywords:
      - example
      - static
    updatedAt: 2026-03-07T12:00:00+00:00
    deleted: false
    hash: sha256:example
    assets:
      previewSmallUrl: https://worker-0001.free3d.online/data/example/poster-small.jpg
      previewMediumUrl: https://worker-0001.free3d.online/data/example/poster-medium.jpg
      previewLargeUrl: https://worker-0001.free3d.online/data/example/poster-large.jpg
      metaUrl: https://worker-0001.free3d.online/data/example/example_metadata.json
      inventoryUrl: https://worker-0001.free3d.online/data/example/paths.json
      glb100kUrl: https://worker-0001.free3d.online/data/example/example_100k.glb
    files:
      - relativePath: uploads_files_example_100k/example_100k.glb
        ext: glb
        lod: 100k
        kind: scene
        browserDefault: true
        contentType: model/gltf-binary
        directUrl: https://worker-0001.free3d.online/data/example/uploads_files_example_100k/example_100k.glb
      - relativePath: uploads_files_example_100k/example_static.fbx
        ext: fbx
        lod: 100k
        variant: static
        kind: scene
        directUrl: https://worker-0001.free3d.online/data/example/uploads_files_example_100k/example_static.fbx
        supportFiles:
          - relativePath: uploads_files_example_100k/textures/example_basecolor.png
            ext: png
            kind: texture
            directUrl: https://worker-0001.free3d.online/data/example/uploads_files_example_100k/textures/example_basecolor.png
