openapi: 3.1.0
info:
  title: Geobuild API
  version: 1.0.0-draft
  description: Draft contract converted from Geobuild_API_Spec_v1.0.md
servers:
  - url: https://api.geobuild.cn/v1
    description: User API
  - url: https://ops-api.geobuild.cn/v1
    description: Ops API
tags:
  - name: Auth
  - name: Onboarding
  - name: Projects
  - name: AI
  - name: Subscription
  - name: Templates
  - name: Admin
  - name: Notifications
paths:
  /auth/register:
    post:
      tags: [Auth]
      summary: Register user
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [email, password]
              properties:
                email: { type: string, format: email }
                password: { type: string }
                phone: { type: string }
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Envelope"
  /auth/login:
    post:
      tags: [Auth]
      summary: Login
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [email, password]
              properties:
                email: { type: string, format: email }
                password: { type: string }
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Envelope"
  /users/me:
    get:
      tags: [Auth]
      summary: Current user profile
      security:
        - BearerAuth: []
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Envelope"
  /onboarding/save:
    post:
      tags: [Onboarding]
      summary: Save onboarding step data
      security:
        - BearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [step, data]
              properties:
                step: { type: integer, enum: [1, 2] }
                data: { type: object, additionalProperties: true }
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Envelope"
  /projects:
    post:
      tags: [Projects]
      summary: Create project
      security:
        - BearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [name]
              properties:
                name: { type: string }
      responses:
        "201":
          description: Created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Envelope"
    get:
      tags: [Projects]
      summary: List projects
      security:
        - BearerAuth: []
      parameters:
        - name: stage
          in: query
          schema: { type: string }
        - name: limit
          in: query
          schema: { type: integer, default: 20 }
        - name: offset
          in: query
          schema: { type: integer, default: 0 }
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Envelope"
  /projects/{id}/brief:
    patch:
      tags: [Projects]
      summary: Update structured brief
      security:
        - BearerAuth: []
      parameters:
        - $ref: "#/components/parameters/ProjectId"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                brief:
                  $ref: "#/components/schemas/ProjectBrief"
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Envelope"
  /ai/feasibility-check:
    post:
      tags: [AI]
      summary: Run S-07 feasibility decision
      security:
        - BearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [project_id, brief]
              properties:
                project_id: { type: string }
                brief:
                  $ref: "#/components/schemas/ProjectBrief"
      responses:
        "200":
          description: Decision result
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Envelope"
  /ai/template-match:
    post:
      tags: [AI]
      summary: Run S-08 template match
      security:
        - BearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [project_id]
              properties:
                project_id: { type: string }
                exclude_ids:
                  type: array
                  items: { type: string }
      responses:
        "200":
          description: Candidate templates
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Envelope"
  /subscription/upgrade-from-pack:
    post:
      tags: [Subscription]
      summary: Upgrade from 9.9 pack to monthly
      security:
        - BearerAuth: []
      responses:
        "200":
          description: Upgrade result
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Envelope"
  /templates:
    get:
      tags: [Templates]
      summary: List published templates
      parameters:
        - name: material
          in: query
          schema: { type: string }
        - name: subcategory
          in: query
          schema: { type: string }
        - name: limit
          in: query
          schema: { type: integer, default: 20 }
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Envelope"
  /admin/dashboard/users:
    get:
      tags: [Admin]
      summary: User dashboard metrics
      security:
        - BearerAuth: []
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Envelope"
  /admin/dashboard/sales:
    get:
      tags: [Admin]
      summary: Sales and PR funnel metrics
      security:
        - BearerAuth: []
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Envelope"
  /notifications:
    get:
      tags: [Notifications]
      summary: Notification center list
      security:
        - BearerAuth: []
      parameters:
        - name: unread_only
          in: query
          schema: { type: boolean }
      responses:
        "200":
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Envelope"
components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
  parameters:
    ProjectId:
      name: id
      in: path
      required: true
      schema:
        type: string
  schemas:
    Envelope:
      type: object
      required: [code, data, request_id]
      properties:
        code:
          type: integer
          example: 0
        data:
          type: object
          additionalProperties: true
        request_id:
          type: string
          example: req_abc123
    ProjectBrief:
      type: object
      properties:
        product_type: { type: string }
        scene: { type: string }
        material_hint: { type: string }
        size:
          type: object
          properties:
            h_mm: { type: integer }
            w_mm: { type: integer }
            d_mm: { type: integer }
        qty: { type: integer }
        color: { type: string }
        style: { type: string }
        surface: { type: string }
        site: { type: string }
        load: { type: string }
