openapi: 3.0.3
info:
  title: Ignite Lean API
  version: "0.1.0"
  description: |
    Public REST + Edge Function API for Ignite Lean. Today this covers
    Personal Access Token-authenticated endpoints; the Supabase
    PostgREST surface (`/rest/v1/...`) is also available with the same
    PAT or with a Supabase JWT.

    Auth flow
    ---------
    1. Sign in to https://console.ignitelean.com
    2. Go to **Settings → Integrations** and click **New token**
    3. Copy the `il_pat_xxx…` value once — we only store the hash
    4. Send every request as `Authorization: Bearer il_pat_xxx…`

    The token inherits **your** role and org scope. RLS applies to every
    downstream query, so a PAT minted by a `viewer` cannot create
    work orders, and an admin's PAT cannot read another org.

    Token format
    ------------
    `il_pat_<32 hex chars>`. The first 8 characters after the underscore
    are the **prefix**, visible in the Settings → Integrations list so
    you can identify a token without revealing the secret half.
  contact:
    name: Ignite Lean Support
    url: https://www.ignitelean.com/contact
  license:
    name: Proprietary

servers:
  - url: https://tkxyvcsjvppdabokrbiv.functions.supabase.co
    description: Production Edge Functions
  - url: https://tkxyvcsjvppdabokrbiv.supabase.co/rest/v1
    description: Production PostgREST (raw table + view + RPC surface)

tags:
  - name: Auth
    description: Token validation + identity discovery
  - name: PostgREST
    description: Direct table / view / RPC access (RLS-gated by your PAT's profile)

security:
  - personalAccessToken: []

paths:
  /api-whoami:
    get:
      tags: [Auth]
      operationId: getWhoami
      summary: Validate a PAT and return the resolved identity
      description: |
        Smoke-test endpoint. Returns the `profile_id` + `org_id` the token
        resolves to, or 401 if the token is missing / malformed / revoked /
        expired. Side effect: bumps the token's `last_used_at` so the
        Settings → Integrations list shows when the token was last used.
      responses:
        "200":
          description: Token valid; identity resolved.
          content:
            application/json:
              schema:
                type: object
                required: [authenticated, profile_id, org_id, token_id]
                properties:
                  authenticated:
                    type: boolean
                    example: true
                  profile_id:
                    type: string
                    format: uuid
                  org_id:
                    type: string
                    format: uuid
                  token_id:
                    type: string
                    format: uuid
        "401":
          description: Missing / malformed token, or token revoked / expired.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "405":
          description: Method not allowed (use GET).
        "500":
          description: Internal error.

  /work_orders_v?select=*:
    get:
      tags: [PostgREST]
      operationId: listWorkOrders
      summary: List work orders (joined with asset + failure code labels)
      description: |
        Reads `public.work_orders_v` — the canonical work-order list view.
        Columns include the WO row, joined asset name + tag + criticality
        tier, and the three failure-code labels (defect / failure / intervention).
        Use PostgREST query syntax for filter / order / range. Example:

        ```
        GET /work_orders_v?status=eq.in_progress&order=created_at.desc&limit=50
        ```
      responses:
        "200":
          description: Array of WO rows in the caller's org (RLS-filtered).
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/WorkOrderRow"

  /quality_ncs?select=*:
    get:
      tags: [PostgREST]
      operationId: listNcs
      summary: List non-conformances
      description: |
        Reads `public.quality_ncs`. Filter by status / disposition /
        capa_status etc. via PostgREST syntax. Includes the Q3
        `production_impact` field.

components:
  securitySchemes:
    personalAccessToken:
      type: http
      scheme: bearer
      bearerFormat: il_pat_<32 hex>
      description: |
        Mint at Settings → Integrations. Format: `il_pat_xxx…`. The token
        inherits the issuing profile's role + org scope (RLS).

  schemas:
    Error:
      type: object
      properties:
        error:
          type: string
          example: invalid_or_revoked_token
        hint:
          type: string
          example: 'Send "Authorization: Bearer il_pat_<your token>".'
        detail:
          type: string

    WorkOrderRow:
      type: object
      properties:
        id: { type: string, format: uuid }
        org_id: { type: string, format: uuid }
        wo_number: { type: string, example: WO-2026-0184 }
        title: { type: string }
        status:
          type: string
          enum: [requested, approved, assigned, in_progress, on_hold, complete, verified, cancelled]
        priority:
          type: string
          enum: [low, medium, high, critical]
        work_type:
          type: string
          enum: [corrective, preventive, predictive, project, calibration]
        asset_id: { type: string, format: uuid, nullable: true }
        asset_name: { type: string, nullable: true }
        asset_tag:  { type: string, nullable: true }
        asset_criticality:
          type: integer
          nullable: true
          minimum: 1
          maximum: 5
        asset_criticality_tier:
          type: string
          nullable: true
          enum: [low, important, critical]
        failure_code_id: { type: string, format: uuid, nullable: true }
        failure_defect_label:       { type: string, nullable: true }
        failure_failure_label:      { type: string, nullable: true }
        failure_intervention_label: { type: string, nullable: true }
        due_date:     { type: string, format: date, nullable: true }
        completed_at: { type: string, format: date-time, nullable: true }
        total_cost:   { type: number }
        overdue:      { type: boolean }
