openapi: 3.0.3
info:
  title: Shoehorn Marketplace API
  description: |
    Addon marketplace browsing, installation, configuration, and runtime management.
    Addons extend Shoehorn with custom integrations, widgets, and backend logic.
  version: 1.0.0

servers:
  - url: https://shoehorn.example.com/api/v1
    description: Production

paths:
  /marketplace:
    get:
      summary: List marketplace catalog
      description: Returns available addons in the marketplace, optionally filtered by kind.
      tags: [Marketplace]
      parameters:
        - name: kind
          in: query
          description: Filter by addon kind
          schema: { type: string, enum: [addon, widget, integration] }
        - name: category
          in: query
          schema: { type: string }
        - name: search
          in: query
          schema: { type: string }
      responses:
        '200':
          description: Marketplace catalog
          content:
            application/json:
              schema:
                type: object
                properties:
                  items:
                    type: array
                    items: { $ref: '#/components/schemas/MarketplaceItem' }

  /marketplace/installed:
    get:
      summary: List installed addons
      description: Returns all addons currently installed in this tenant.
      tags: [Marketplace]
      responses:
        '200':
          description: Installed addons
          content:
            application/json:
              schema:
                type: object
                properties:
                  addons:
                    type: array
                    items: { $ref: '#/components/schemas/InstalledAddon' }

  /marketplace/install:
    post:
      summary: Install addon
      description: Installs an addon from the marketplace by slug.
      tags: [Marketplace]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [slug]
              properties:
                slug: { type: string, description: Addon slug from marketplace }
      responses:
        '201':
          description: Addon installed
        '409':
          description: Addon already installed

  /marketplace/{slug}/uninstall:
    delete:
      summary: Uninstall addon
      description: Removes an installed addon and its configuration.
      tags: [Marketplace]
      parameters:
        - name: slug
          in: path
          required: true
          schema: { type: string }
      responses:
        '204':
          description: Addon uninstalled
        '404':
          description: Addon not found

  /marketplace/{slug}/enable:
    post:
      summary: Enable addon
      description: Re-enables a previously disabled addon.
      tags: [Marketplace]
      parameters:
        - name: slug
          in: path
          required: true
          schema: { type: string }
      responses:
        '200':
          description: Addon enabled

  /marketplace/{slug}/disable:
    post:
      summary: Disable addon
      description: Disables an addon without uninstalling it. Configuration is preserved.
      tags: [Marketplace]
      parameters:
        - name: slug
          in: path
          required: true
          schema: { type: string }
      responses:
        '200':
          description: Addon disabled

  /marketplace/import-manifest:
    post:
      summary: Import addon manifest
      description: Publishes an addon manifest to the marketplace. Used by addon developers.
      tags: [Marketplace]
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/AddonManifest' }
      responses:
        '201':
          description: Manifest imported
        '422':
          description: Manifest validation failed

  /marketplace/{slug}/bundle:
    post:
      summary: Upload addon bundle
      description: |
        Uploads backend and/or frontend bundles for a published addon.
        Uses multipart form upload with `backend` and `frontend` file fields.
      tags: [Marketplace]
      parameters:
        - name: slug
          in: path
          required: true
          schema: { type: string }
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                backend:
                  type: string
                  format: binary
                  description: Backend JS bundle (QuickJS IIFE)
                frontend:
                  type: string
                  format: binary
                  description: Frontend JS bundle (ESM)
      responses:
        '200':
          description: Bundle uploaded

  # --- Addon Runtime ---
  /addons/{slug}/status:
    get:
      summary: Get addon runtime status
      description: Returns the runtime status of an installed addon.
      tags: [Addon Runtime]
      parameters:
        - name: slug
          in: path
          required: true
          schema: { type: string }
      responses:
        '200':
          description: Addon status
          content:
            application/json:
              schema: { $ref: '#/components/schemas/AddonStatus' }

  /addons/{slug}/logs:
    get:
      summary: Get addon logs
      description: Returns recent log entries from the addon runtime.
      tags: [Addon Runtime]
      parameters:
        - name: slug
          in: path
          required: true
          schema: { type: string }
        - name: limit
          in: query
          schema: { type: integer, default: 50, maximum: 500 }
      responses:
        '200':
          description: Addon logs
          content:
            application/json:
              schema:
                type: object
                properties:
                  logs:
                    type: array
                    items: { $ref: '#/components/schemas/LogEntry' }

  /addons/{slug}/{path}:
    get:
      summary: Call addon route (GET)
      description: Proxies a GET request to the addon's handleRoute() function.
      tags: [Addon Runtime]
      parameters:
        - name: slug
          in: path
          required: true
          schema: { type: string }
        - name: path
          in: path
          required: true
          schema: { type: string }
      responses:
        '200':
          description: Addon response

    post:
      summary: Call addon route (POST)
      description: Proxies a POST request to the addon's handleRoute() function.
      tags: [Addon Runtime]
      parameters:
        - name: slug
          in: path
          required: true
          schema: { type: string }
        - name: path
          in: path
          required: true
          schema: { type: string }
      requestBody:
        content:
          application/json:
            schema: { type: object }
      responses:
        '200':
          description: Addon response

components:
  schemas:
    MarketplaceItem:
      type: object
      properties:
        slug: { type: string }
        name: { type: string }
        description: { type: string }
        version: { type: string }
        author: { type: string }
        category: { type: string }
        tier: { type: string, enum: [free, pro, enterprise] }
        icon: { type: string }
        installed: { type: boolean }

    InstalledAddon:
      type: object
      properties:
        slug: { type: string }
        name: { type: string }
        version: { type: string }
        enabled: { type: boolean }
        status: { type: string, enum: [running, stopped, error] }
        installed_at: { type: string, format: date-time }
        config: { type: object }

    AddonManifest:
      type: object
      required: [schemaVersion, kind, metadata, addon]
      properties:
        schemaVersion: { type: integer, enum: [1] }
        kind: { type: string, enum: [addon] }
        metadata:
          type: object
          required: [slug, name, version, description, author, category, tier]
          properties:
            slug: { type: string }
            name: { type: string }
            version: { type: string }
            description: { type: string }
            author: { type: object }
            category: { type: string }
            tier: { type: string }
        addon:
          type: object
          required: [tier, runtime, permissions]
          properties:
            tier: { type: string, enum: [declarative, scripted, full] }
            runtime: { type: string, enum: [quickjs] }
            permissions: { type: object }
            sync: { type: object }
            config: { type: object }
            frontend: { type: object }

    AddonStatus:
      type: object
      properties:
        slug: { type: string }
        enabled: { type: boolean }
        status: { type: string, enum: [running, stopped, error] }
        last_sync: { type: string, format: date-time }
        last_error: { type: string }
        items_synced: { type: integer }
        uptime_seconds: { type: integer }

    LogEntry:
      type: object
      properties:
        timestamp: { type: string, format: date-time }
        level: { type: string, enum: [debug, info, warn, error] }
        message: { type: string }
        fields: { type: object }
