openapi: 3.0.3
info:
  title: Shoehorn Organization API
  description: |
    Org-chart endpoints. The read endpoint is available to all authenticated
    users; the write endpoint is admin-only.
  version: 1.0.0

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

paths:
  /organization/org-chart:
    get:
      summary: Get the org chart
      description: |
        Returns every active team plus its parent relationship, member count,
        and the team's primary manager (the highest-ranking member matching
        owner / manager / lead / team_lead). `total_member_count` includes
        descendants. Sub-team links are computed server-side.
      tags: [OrgChart]
      responses:
        '200':
          description: Org chart
          content:
            application/json:
              schema:
                type: object
                properties:
                  teams:
                    type: array
                    items:
                      $ref: '#/components/schemas/OrgChartTeam'

  /admin/org-chart:
    put:
      summary: Bulk-update team parent relationships
      description: |
        Admin-only. Each update sets a team's `parent_team_id`; pass `null`
        (or omit) to make the team a root team. Updates run inside one
        transaction. The server walks ancestry to reject cycles before
        applying — if any update would create a cycle, the entire request
        fails with `CIRCULAR_REFERENCE`.
      tags: [OrgChart]
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [updates]
              properties:
                updates:
                  type: array
                  minItems: 1
                  items:
                    type: object
                    required: [team_id]
                    properties:
                      team_id:
                        type: string
                        format: uuid
                      parent_team_id:
                        type: string
                        format: uuid
                        nullable: true
                        description: "Set null to make the team a root team."
      responses:
        '200':
          description: Updates applied
          content:
            application/json:
              schema:
                type: object
                properties:
                  success: { type: boolean }
                  updated: { type: integer, description: "Number of updates applied." }
        '400':
          description: |
            Returned for an empty `updates` array, an invalid UUID, or a
            cycle. Cycles use the error code `CIRCULAR_REFERENCE`.
        '403':
          description: Caller lacks admin permission

components:
  schemas:
    OrgChartTeam:
      type: object
      properties:
        id: { type: string, format: uuid }
        name: { type: string }
        slug: { type: string }
        display_name: { type: string, nullable: true }
        description: { type: string, nullable: true }
        parent_team_id: { type: string, format: uuid, nullable: true }
        sub_team_ids:
          type: array
          items: { type: string, format: uuid }
        member_count:
          type: integer
          description: Direct members.
        total_member_count:
          type: integer
          description: Direct members plus all descendants.
        manager_user_id:
          type: string
          nullable: true
          description: Highest-ranking team member (owner > manager > lead > team_lead).
        manager_role:
          type: string
          nullable: true
        metadata:
          type: object
          additionalProperties: true
