openapi: 3.1.0
info:
  title: VASYOK Game API
  version: 0.4.0
  description: Phase 04 Rides + Contracts + Events API
servers:
  - url: http://localhost:3000
tags:
  - name: Auth
  - name: Gameplay
  - name: Content
paths:
  /v1/auth/telegram:
    post:
      tags: [Auth]
      summary: Validate Telegram initData and issue access token
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AuthTelegramRequest'
      responses:
        '200':
          description: Authenticated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AuthTelegramResponse'
  /v1/me:
    get:
      tags: [Gameplay]
      summary: Get full gameplay snapshot for current player
      security:
        - bearerAuth: []
      responses:
        '200':
          description: Current player state
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MeResponse'
  /v1/content/bundles:
    get:
      tags: [Content]
      summary: Get validated route/contract/event bundle summaries
      security:
        - bearerAuth: []
      responses:
        '200':
          description: Content bundle
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContentBundlesResponse'
  /v1/actions/claim:
    post:
      tags: [Gameplay]
      summary: Claim all finished shift timers
      security:
        - bearerAuth: []
      responses:
        '200':
          description: Claim processed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ActionEnvelope'
  /v1/actions/shift/start:
    post:
      tags: [Gameplay]
      summary: Start factory shift timer
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ShiftStartRequest'
      responses:
        '200':
          description: Shift started
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ActionEnvelope'
  /v1/actions/shift/finish:
    post:
      tags: [Gameplay]
      summary: Finish shift timer
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TimerFinishRequest'
      responses:
        '200':
          description: Shift settled
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ActionEnvelope'
  /v1/actions/ride/start:
    post:
      tags: [Gameplay]
      summary: Start ride timer for route
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RideStartRequest'
      responses:
        '200':
          description: Ride started
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ActionEnvelope'
  /v1/actions/ride/finish:
    post:
      tags: [Gameplay]
      summary: Finish ride timer and roll pending event
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TimerFinishRequest'
      responses:
        '200':
          description: Ride settled
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ActionEnvelope'
  /v1/actions/contract/accept:
    post:
      tags: [Gameplay]
      summary: Accept one contract template
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ContractAcceptRequest'
      responses:
        '200':
          description: Contract accepted
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ActionEnvelope'
  /v1/actions/contract/resolve:
    post:
      tags: [Gameplay]
      summary: Resolve completed contract reward
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ContractResolveRequest'
      responses:
        '200':
          description: Contract resolved
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ActionEnvelope'
  /v1/actions/event/resolve:
    post:
      tags: [Gameplay]
      summary: Resolve pending event choice
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/EventResolveRequest'
      responses:
        '200':
          description: Event resolved
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ActionEnvelope'
  /v1/actions/repair:
    post:
      tags: [Gameplay]
      summary: Repair one car system
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RepairRequest'
      responses:
        '200':
          description: Repair applied
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ActionEnvelope'
  /v1/actions/upgrade:
    post:
      tags: [Gameplay]
      summary: Buy garage or trunk upgrade
      security:
        - bearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpgradeRequest'
      responses:
        '200':
          description: Upgrade applied
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ActionEnvelope'
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
  schemas:
    AuthTelegramRequest:
      type: object
      required: [initData]
      properties:
        initData:
          type: string
    AuthTelegramResponse:
      type: object
      required: [accessToken, expiresInSec, profile]
      properties:
        accessToken:
          type: string
        expiresInSec:
          type: integer
        profile:
          $ref: '#/components/schemas/PlayerProfile'
    PlayerProfile:
      type: object
      required:
        [id, telegramUserId, firstName, isPremium, allowsWriteToPm, role, createdAt, lastSeenAt]
      properties:
        id: { type: string, format: uuid }
        telegramUserId: { type: integer }
        username: { type: string, nullable: true }
        firstName: { type: string }
        lastName: { type: string, nullable: true }
        languageCode: { type: string, nullable: true }
        isPremium: { type: boolean }
        allowsWriteToPm: { type: boolean }
        photoUrl: { type: string, format: uri, nullable: true }
        role:
          type: string
          enum: [player, owner]
        createdAt: { type: string, format: date-time }
        lastSeenAt: { type: string, format: date-time }
    MeResponse:
      type: object
      required: [profile, game]
      properties:
        profile:
          $ref: '#/components/schemas/PlayerProfile'
        game:
          $ref: '#/components/schemas/GameState'
    GameState:
      type: object
      description: Player-specific gameplay snapshot. Concrete fields are defined in packages/shared.
      additionalProperties: true
    ActionEnvelope:
      type: object
      required: [message, state]
      properties:
        message:
          type: string
        state:
          $ref: '#/components/schemas/GameState'
    ContentBundlesResponse:
      type: object
      description: Validated summaries of locations, routes, contracts and event catalog.
      additionalProperties: true
    ShiftStartRequest:
      type: object
      required: [durationCode, mode]
      properties:
        durationCode:
          type: string
          enum: [shift_5m, shift_30m, shift_2h, shift_8h]
        mode:
          type: string
          enum: [safety, normal, overdrive]
    TimerFinishRequest:
      type: object
      required: [timerId]
      properties:
        timerId:
          type: string
          format: uuid
    RideStartRequest:
      type: object
      required: [routeId]
      properties:
        routeId:
          type: string
        contractId:
          type: string
          format: uuid
          nullable: true
    ContractAcceptRequest:
      type: object
      required: [templateId]
      properties:
        templateId:
          type: string
    ContractResolveRequest:
      type: object
      required: [contractId]
      properties:
        contractId:
          type: string
          format: uuid
    EventResolveRequest:
      type: object
      required: [eventId, choiceId]
      properties:
        eventId:
          type: string
          format: uuid
        choiceId:
          type: string
    RepairRequest:
      type: object
      required: [system]
      properties:
        system:
          type: string
          enum: [engine, electric]
    UpgradeRequest:
      type: object
      required: [target]
      properties:
        target:
          type: string
          enum: [garage, trunk]
