openapi: 3.1.0
info:
  title: AI Context Public Read API
  version: 1.2.0
  description: |
    Read-only public API contract for AI Context.

    The canonical source of truth is always the published AI Context JSON document
    (`context.json` or equivalent). Optional HTTP resource views described here are
    projections of that same document. They must not introduce a second datastore or
    divergent business logic.

    Future protocol adapters (for example MCP tools) should map one-to-one to these
    read operations, or fetch the canonical document and select resources locally.

    This contract does not define authentication, mutation, or MCP-specific transport.
  license:
    name: AI Context Specification
    url: https://aicontext.gr/specification/
  contact:
    name: AIContext.gr
    url: https://aicontext.gr/

servers:
  - url: '{contextOrigin}{contextBasePath}'
    description: Publisher context base (same origin as the canonical AI Context document)
    variables:
      contextOrigin:
        default: https://example.gov
        description: Scheme and host of the published context
      contextBasePath:
        default: /ai-context
        description: Path prefix shared by the context document and optional v1 views

tags:
  - name: Context
    description: Canonical document and organisation identity
  - name: Services
    description: Public services and procedures
  - name: Sources
    description: Official citation records

paths:
  /context.json:
    get:
      operationId: getContext
      tags: [Context]
      summary: Get full AI Context document
      description: |
        Returns the complete canonical AI Context JSON document. This is the authoritative
        representation. All other operations in this contract are optional views over the
        same content.
      responses:
        '200':
          description: Full AI Context document
          headers:
            ETag:
              description: Optional entity tag for cache revalidation
              schema:
                type: string
            Last-Modified:
              description: Optional last modification time of the published document
              schema:
                type: string
                format: date-time
          content:
            application/json:
              schema:
                $ref: './context.schema.json'
        '404':
          $ref: '#/components/responses/NotFound'
        '410':
          $ref: '#/components/responses/Gone'
        '503':
          $ref: '#/components/responses/Unavailable'

  /.well-known/ai-context:
    get:
      operationId: getDiscovery
      tags: [Context]
      summary: Get AI Context Discovery document
      description: |
        Returns the discovery document pointing at the canonical context URL,
        specification version, and optional public API metadata.
      responses:
        '200':
          description: AI Context Discovery document
          content:
            application/json:
              schema:
                $ref: './discovery.schema.json'
        '404':
          $ref: '#/components/responses/NotFound'

  /v1/context:
    get:
      operationId: getContextView
      tags: [Context]
      summary: Get full context (optional alias)
      description: |
        Optional alias for the canonical document. When implemented, the response body
        MUST be byte-identical to `GET /context.json`, or a strict subset that includes
        a `_meta` block with `canonical_url` pointing at the full document.
      responses:
        '200':
          description: Canonical AI Context document or equivalent view
          content:
            application/json:
              schema:
                $ref: './context.schema.json'
        '404':
          $ref: '#/components/responses/NotFound'

  /v1/organisation:
    get:
      operationId: getOrganisation
      tags: [Context]
      summary: Get organisation identity
      description: |
        Returns the organisation identity block (for example `municipality` or `organisation`)
        from the canonical document, plus `_meta` linking back to the full context.
      responses:
        '200':
          description: Organisation identity view
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrganisationView'
        '404':
          $ref: '#/components/responses/NotFound'

  /v1/services:
    get:
      operationId: listServices
      tags: [Services]
      summary: List services
      description: |
        Returns the `services` array from the canonical document. Supports optional
        read-only filtering for adapter use cases such as MCP `searchServices`.
      parameters:
        - name: q
          in: query
          required: false
          description: Case-insensitive search across service `id`, `name`, `name_en`, and `description`
          schema:
            type: string
        - name: department_id
          in: query
          required: false
          description: Filter by stable department identifier
          schema:
            type: string
      responses:
        '200':
          description: Service list view
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceListView'
        '404':
          $ref: '#/components/responses/NotFound'

  /v1/services/{service_id}:
    get:
      operationId: getService
      tags: [Services]
      summary: Get one service
      parameters:
        - $ref: '#/components/parameters/ServiceId'
      responses:
        '200':
          description: Single service view
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceView'
        '404':
          $ref: '#/components/responses/NotFound'

  /v1/sources/{source_id}:
    get:
      operationId: getSource
      tags: [Sources]
      summary: Get source citation record
      description: |
        Returns a machine-readable citation record for an official source referenced
        by a service, event, or other resource in the canonical document.
      parameters:
        - $ref: '#/components/parameters/SourceId'
      responses:
        '200':
          description: Source citation view
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SourceView'
        '404':
          $ref: '#/components/responses/NotFound'

components:
  parameters:
    ServiceId:
      name: service_id
      in: path
      required: true
      description: Stable service identifier (`services[].id`)
      schema:
        type: string
        pattern: '^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$'
    SourceId:
      name: source_id
      in: path
      required: true
      description: Stable source identifier (`source.id` on the owning resource)
      schema:
        type: string
        pattern: '^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$'

  schemas:
    MetaBlock:
      type: object
      required: [resource_type, canonical_url, specification_version]
      properties:
        resource_type:
          type: string
          enum: [context, organisation, service, service_list, source, discovery]
        resource_id:
          type: string
          description: Present when the view represents a single addressable resource
        self:
          type: string
          format: uri
          description: URL of this view, when served over HTTP
        canonical_url:
          type: string
          format: uri
          description: URL of the authoritative full AI Context document
        specification_version:
          type: string
          example: '1.2'
        context_version:
          type: string
          description: Publisher content version from the canonical document (`version` field)

    ErrorBody:
      type: object
      required: [error]
      properties:
        error:
          type: object
          required: [code, message]
          properties:
            code:
              type: string
              enum:
                - not_found
                - gone
                - invalid_request
                - specification_unsupported
                - unavailable
            message:
              type: string
            resource_type:
              type: string
            resource_id:
              type: string
            specification_version:
              type: string
            canonical_url:
              type: string
              format: uri

    OrganisationView:
      type: object
      required: [_meta]
      properties:
        _meta:
          $ref: '#/components/schemas/MetaBlock'
        id:
          type: string
        name:
          type: string
        name_en:
          type: string
        url:
          type: string
          format: uri
        scope:
          type: string

    ServiceListView:
      type: object
      required: [_meta, services]
      properties:
        _meta:
          $ref: '#/components/schemas/MetaBlock'
        services:
          type: array
          items:
            type: object
            additionalProperties: true

    ServiceView:
      type: object
      required: [_meta]
      properties:
        _meta:
          $ref: '#/components/schemas/MetaBlock'
      additionalProperties: true

    SourceView:
      type: object
      required: [_meta, source]
      properties:
        _meta:
          $ref: '#/components/schemas/MetaBlock'
        source:
          type: object
          required: [id, url]
          properties:
            id:
              type: string
            url:
              type: string
              format: uri
            type:
              type: string
              enum: [official_page, official_form, official_announcement, official_portal, other]
            title:
              type: string
            last_checked:
              type: string
              format: date

  responses:
    NotFound:
      description: Resource not found in the canonical AI Context document
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorBody'
          example:
            error:
              code: not_found
              message: Service not found
              resource_type: service
              resource_id: unknown-service
              specification_version: '1.2'
              canonical_url: https://example.gov/ai-context/context.json
    Gone:
      description: Context or resource permanently withdrawn
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorBody'
    Unavailable:
      description: Temporary publisher outage
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorBody'
