openapi: 3.1.0
info:
  title: Jasper Report Services
  version: 1.0.0
  description: |
    Source-derived integration and JSON action contract. Authentication uses only
    the Central acugis_session cookie. When no Central DSN resolves, application
    auth checks are disabled. Runtime report endpoints permit anonymous callers
    when the report grants Public view; this is represented by optional security.
servers:
  - url: https://reports.example.test/jasper-report-services
    description: Replace with the deployment origin
tags:
  - name: Registry
  - name: Discovery
  - name: Reports
  - name: Administration
  - name: UI actions
  - name: Debug
paths:
  /api/reports:
    get:
      tags: [Registry]
      summary: List the unfiltered report registry
      description: No method or authentication gate is implemented.
      security: []
      responses:
        "200":
          description: Published report registry
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/ReportRegistryItem"
  /api/reports/index.php:
    $ref: "#/paths/~1api~1reports"
  /api/datasources:
    get:
      tags: [Registry]
      summary: List enabled datasource names
      description: No method or authentication gate is implemented. Database failure is represented as an empty array.
      security: []
      responses:
        "200":
          description: Datasource registry
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/DatasourceItem"
  /api/datasources/index.php:
    $ref: "#/paths/~1api~1datasources"
  /api/discovery:
    get:
      tags: [Discovery]
      summary: Discover reports visible to the session user
      security:
        - cookieAuth: []
      responses:
        "200":
          description: Permission-filtered discovery document
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Discovery"
        "401":
          $ref: "#/components/responses/AuthenticationRequired"
        "503":
          $ref: "#/components/responses/CentralUnavailable"
  /api/discovery/index.php:
    $ref: "#/paths/~1api~1discovery"
  /api/resource-sync:
    get:
      tags: [Administration]
      summary: Inspect resource-sync capability
      security:
        - cookieAuth: []
      responses:
        "200":
          description: Sync capability
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SyncCapability"
        "401":
          $ref: "#/components/responses/AuthenticationRequired"
        "403":
          $ref: "#/components/responses/AdministratorRequired"
        "503":
          $ref: "#/components/responses/CentralUnavailable"
    post:
      tags: [Administration]
      summary: Synchronize report resources into Central
      security:
        - cookieAuth: []
      responses:
        "200":
          description: Sync statistics
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SyncResult"
        "401":
          $ref: "#/components/responses/AuthenticationRequired"
        "403":
          $ref: "#/components/responses/AdministratorRequired"
        "503":
          description: Central database is unavailable for sync
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/Error"
                  - type: object
                    properties:
                      ok:
                        const: false
                      service:
                        type: string
  /api/resource-sync/index.php:
    $ref: "#/paths/~1api~1resource-sync"
  /reports/get_report_config.php:
    get:
      tags: [Reports]
      summary: Get expanded report configuration
      description: SQL-backed select options are expanded. Anonymous access succeeds only when Public has report view.
      security:
        - cookieAuth: []
        - {}
      parameters:
        - $ref: "#/components/parameters/Report"
      responses:
        "200":
          description: Expanded report definition
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ReportDefinition"
        "400":
          $ref: "#/components/responses/InvalidReportJson"
        "403":
          $ref: "#/components/responses/PermissionDenied"
        "404":
          $ref: "#/components/responses/ReportNotFoundJson"
        "503":
          $ref: "#/components/responses/CentralUnavailable"
  /reports/serve_report_definition.php:
    get:
      tags: [Reports]
      summary: Get the raw report definition
      description: Anonymous access succeeds only when Public has report view.
      security:
        - cookieAuth: []
        - {}
      parameters:
        - $ref: "#/components/parameters/Report"
      responses:
        "200":
          description: Unexpanded on-disk report definition
          headers:
            X-Content-Type-Options:
              schema:
                type: string
                const: nosniff
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ReportDefinition"
        "400":
          description: Invalid report
          content:
            text/plain:
              schema:
                type: string
                const: Invalid report.
        "403":
          $ref: "#/components/responses/PermissionDenied"
        "404":
          description: Definition file not found
        "503":
          $ref: "#/components/responses/CentralUnavailable"
  /reports/report_thumbnail.php:
    get:
      tags: [Reports]
      summary: Get a report thumbnail
      description: Anonymous access succeeds only when Public has report view.
      security:
        - cookieAuth: []
        - {}
      parameters:
        - $ref: "#/components/parameters/Report"
      responses:
        "200":
          description: Stored thumbnail
          headers:
            Cache-Control:
              schema:
                type: string
                example: private, max-age=3600
          content:
            image/png:
              schema:
                type: string
                contentEncoding: binary
        "403":
          $ref: "#/components/responses/PermissionDenied"
        "404":
          description: Invalid report or asset not found
        "503":
          $ref: "#/components/responses/CentralUnavailable"
  /reports/execute_report.php:
    get:
      tags: [Reports]
      summary: Execute and export a report
      description: |
        Anonymous access succeeds only when Public has report view. Any additional
        non-underscore query parameter is forwarded to Jasper; repeat a key for
        multi-value input. POST body parameters are not forwarded and are unsupported.
      security:
        - cookieAuth: []
        - {}
      parameters:
        - name: _repName
          in: query
          required: true
          schema:
            $ref: "#/components/schemas/ReportKey"
        - name: _dataSource
          in: query
          required: true
          schema:
            type: string
            minLength: 1
        - name: _repFormat
          in: query
          required: false
          schema:
            $ref: "#/components/schemas/ExportFormat"
        - name: _outFilename
          in: query
          required: false
          schema:
            type: string
      responses:
        "200":
          description: Report output; exact media type and disposition depend on format
          headers:
            Content-Disposition:
              schema:
                type: string
          content:
            text/html:
              schema:
                type: string
            application/pdf:
              schema:
                type: string
                contentEncoding: binary
            application/octet-stream:
              schema:
                type: string
                contentEncoding: binary
            text/csv:
              schema:
                type: string
            application/xml:
              schema:
                type: string
        "400":
          description: Invalid report, unsupported format, or engine validation error
          content:
            text/plain:
              schema:
                type: string
            application/json:
              schema:
                $ref: "#/components/schemas/EngineError"
        "403":
          $ref: "#/components/responses/PermissionDenied"
        "404":
          description: Report not found
          content:
            text/plain:
              schema:
                type: string
                const: Report not found.
            application/json:
              schema:
                $ref: "#/components/schemas/EngineError"
        "500":
          description: Jasper engine execution error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/EngineError"
        "502":
          description: Jasper proxy error
          content:
            text/plain:
              schema:
                type: string
        "503":
          description: Central store or Jasper engine URL unavailable
          content:
            text/plain:
              schema:
                type: string
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /report_image.php:
    get:
      tags: [Reports]
      summary: Proxy an image generated by an HTML report
      security:
        - cookieAuth: []
      parameters:
        - name: _repName
          in: query
          required: true
          description: The report alias `report` is also accepted.
          schema:
            $ref: "#/components/schemas/ReportKey"
        - name: image
          in: query
          required: true
          schema:
            type: string
        - name: uuid
          in: query
          required: true
          schema:
            type: string
      responses:
        "200":
          description: Engine-provided image
          content:
            image/*:
              schema:
                type: string
                contentEncoding: binary
        "303":
          description: HTML-classified unauthenticated requests may redirect to Central login
        "403":
          description: Invalid report or permission denied
        "502":
          description: Image proxy failure
        "503":
          description: Central store or image engine URL unavailable
  /debug/session.php:
    get:
      tags: [Debug]
      summary: Probe the current Central session
      description: Available only when JRS_AUTH_DEBUG or JRS_AUTH_LOGIN_TRACE is enabled. Cookie is optional.
      security:
        - cookieAuth: []
        - {}
      responses:
        "200":
          description: Session diagnostics
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SessionDebug"
        "404":
          description: Debugging disabled
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /debug/param_pipeline_php.php:
    get:
      tags: [Debug]
      summary: Echo PHP query parsing diagnostics
      description: Unauthenticated development-only endpoint; do not expose publicly.
      security: []
      responses:
        "200":
          description: Query parsing diagnostics
          content:
            application/json:
              schema:
                type: object
                required: [raw_query_string, "$_GET", "$_REQUEST", "parse_str($rawQs)"]
                properties:
                  raw_query_string:
                    type: string
                  "$_GET":
                    type: object
                    additionalProperties: true
                  "$_REQUEST":
                    type: object
                    additionalProperties: true
                  "parse_str($rawQs)":
                    type: object
                    additionalProperties: true
  /action/schedule.php:
    post:
      tags: [UI actions]
      summary: Create, update, delete, or immediately run a schedule
      description: Platform-admin UI contract. Logical failures usually retain HTTP 200.
      security:
        - cookieAuth: []
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              $ref: "#/components/schemas/ScheduleAction"
          multipart/form-data:
            schema:
              $ref: "#/components/schemas/ScheduleAction"
      responses:
        "200":
          description: Action result
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ActionResult"
        "401":
          $ref: "#/components/responses/AuthenticationRequired"
        "403":
          $ref: "#/components/responses/AdministratorRequired"
        "500":
          description: Uncaught server error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ActionResult"
        "503":
          description: Application or Central database unavailable
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ActionResult"
  /action/recipient.php:
    post:
      tags: [UI actions]
      summary: Save or delete a schedule recipient
      description: Platform-admin UI contract. Logical failures usually retain HTTP 200.
      security:
        - cookieAuth: []
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              $ref: "#/components/schemas/RecipientAction"
          multipart/form-data:
            schema:
              $ref: "#/components/schemas/RecipientAction"
      responses:
        "200":
          description: Action result
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ActionResult"
        "401":
          $ref: "#/components/responses/AuthenticationRequired"
        "403":
          $ref: "#/components/responses/AdministratorRequired"
        "503":
          description: Application or Central database unavailable
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ActionResult"
  /action/email_template.php:
    post:
      tags: [UI actions]
      summary: Intended to save or delete an email template
      description: |
        Platform-admin UI contract. The current handler calls undefined repository
        functions (jrs_email_template_* rather than implemented jrs_email_tmpl_*)
        and appears nonfunctional.
      deprecated: true
      security:
        - cookieAuth: []
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              $ref: "#/components/schemas/EmailTemplateAction"
          multipart/form-data:
            schema:
              $ref: "#/components/schemas/EmailTemplateAction"
      responses:
        "200":
          description: Intended action result if repository functions are supplied
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ActionResult"
        "401":
          $ref: "#/components/responses/AuthenticationRequired"
        "403":
          $ref: "#/components/responses/AdministratorRequired"
        "500":
          description: Current likely undefined-function failure
components:
  securitySchemes:
    cookieAuth:
      type: apiKey
      in: cookie
      name: acugis_session
      description: Raw opaque Central session token; the service hashes it before lookup.
  parameters:
    Report:
      name: report
      in: query
      required: true
      schema:
        $ref: "#/components/schemas/ReportKey"
  responses:
    AuthenticationRequired:
      description: Valid Central session required
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          examples:
            default:
              value:
                error: authentication required
    PermissionDenied:
      description: Report or service permission denied
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          examples:
            default:
              value:
                error: Permission denied
    AdministratorRequired:
      description: Platform administrator required
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          examples:
            default:
              value:
                error: platform administrator required
    CentralUnavailable:
      description: Configured Central authentication store is unreachable
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          examples:
            default:
              value:
                error: central authentication store unavailable
    InvalidReportJson:
      description: Invalid report key
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          examples:
            default:
              value:
                error: invalid report
    ReportNotFoundJson:
      description: Report definition not found
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/Error"
          examples:
            default:
              value:
                error: report not found
  schemas:
    ReportKey:
      type: string
      pattern: "^[a-z0-9_-]+$"
    ExportFormat:
      type: string
      default: html
      enum: [html, pdf, xlsx, xls, csv, docx, rtf, odt, ods, pptx, xml]
    Error:
      type: object
      required: [error]
      properties:
        error:
          type: string
      additionalProperties: true
    EngineError:
      type: object
      properties:
        error:
          type: string
        exceptionClass:
          type: string
        exceptionMessage:
          type: string
      additionalProperties: false
    ReportRegistryItem:
      type: object
      required: [name, title, datasource]
      properties:
        name:
          $ref: "#/components/schemas/ReportKey"
        title:
          type: string
        datasource:
          type: string
      additionalProperties: false
    DatasourceItem:
      type: object
      required: [name]
      properties:
        name:
          type: string
      additionalProperties: false
    Discovery:
      type: object
      required: [service, resource_type, items]
      properties:
        service:
          type: string
          const: jasper-report-service
        resource_type:
          type: string
          const: jasper_report
        items:
          type: array
          items:
            $ref: "#/components/schemas/DiscoveryItem"
      additionalProperties: false
    DiscoveryItem:
      type: object
      required: [id, resource_type, resource_key, title, description, url, category, service]
      properties:
        id:
          $ref: "#/components/schemas/ReportKey"
        resource_type:
          type: string
          const: jasper_report
        resource_key:
          $ref: "#/components/schemas/ReportKey"
        title:
          type: string
        description:
          type: string
        url:
          type: string
        category:
          type: string
          const: Reports
        service:
          type: string
          const: jasper-report-service
        thumbnail:
          type: string
      additionalProperties: false
    SyncCapability:
      type: object
      required: [ok, service, hint]
      properties:
        ok:
          const: true
        service:
          type: string
          const: jasper-report-service
        hint:
          type: string
      additionalProperties: false
    SyncResult:
      type: object
      required: [service, ok, registered, already_exists, errors, skipped]
      properties:
        service:
          type: string
          const: jasper-report-service
        ok:
          type: boolean
        registered:
          type: integer
          minimum: 0
        already_exists:
          type: integer
          minimum: 0
        errors:
          type: integer
          minimum: 0
        skipped:
          type: boolean
        reason:
          type: string
      additionalProperties: false
    ReportDefinition:
      type: object
      required: [name, report]
      properties:
        name:
          type: string
        report:
          $ref: "#/components/schemas/ReportKey"
        datasource:
          type: string
        dataSource:
          type: string
        datasourceName:
          type: string
        format:
          type: string
        outputFormat:
          type: string
        description:
          type: string
        access_groups:
          type: string
        parameters:
          type: array
          items:
            $ref: "#/components/schemas/ReportParameter"
        params:
          type: array
          items:
            $ref: "#/components/schemas/ReportParameter"
      additionalProperties: true
    ReportParameter:
      type: object
      required: [name]
      properties:
        name:
          type: string
        type:
          type: string
        label:
          type: string
        required:
          type: boolean
        hidden:
          type: boolean
        multiple:
          type: boolean
        default: {}
        source:
          type: string
        options:
          type: array
          items:
            oneOf:
              - type: string
              - type: object
                properties:
                  label: {}
                  value: {}
                additionalProperties: true
      additionalProperties: true
    SessionDebug:
      type: object
      required:
        - service
        - auth_enabled
        - cookie_name
        - cookie_present
        - token_len
        - central_db
        - search_path
        - session_lookup_ok
        - authenticated
        - user
        - groups
      properties:
        service:
          type: string
          const: jasper-report-service
        auth_enabled:
          type: boolean
        cookie_name:
          type: string
          const: acugis_session
        cookie_present:
          type: boolean
        token_len:
          type: integer
          minimum: 0
        central_db:
          type: string
          enum: [skipped, auth_disabled, unreachable, disabled, ok]
        search_path:
          type: array
          items:
            type: string
        session_lookup_ok:
          type: boolean
        authenticated:
          type: boolean
        user:
          oneOf:
            - type: "null"
            - type: object
              required: [id, username, email, is_admin]
              properties:
                id:
                  type: integer
                username:
                  type: string
                email:
                  type: string
                is_admin:
                  type: boolean
              additionalProperties: false
        groups:
          type: array
          items:
            type: string
      additionalProperties: false
    ActionResult:
      type: object
      required: [success, message]
      properties:
        success:
          type: boolean
        message:
          type: string
        id:
          type: integer
        execution_id:
          type: integer
        output_file:
          type: string
        email_status:
          type: string
      additionalProperties: false
    ScheduleAction:
      type: object
      properties:
        create:
          type: string
        update:
          type: string
        delete:
          type: string
        run_now:
          type: string
        id:
          type: integer
        schedule_mode:
          type: string
          enum: [once, repeat_minutes, hourly, daily, weekly, monthly, custom]
        repeat_minutes:
          type: integer
          minimum: 1
          maximum: 1440
        hourly_minute:
          type: integer
          minimum: 0
          maximum: 59
        daily_time:
          type: string
          pattern: "^\\d{1,2}:\\d{2}$"
        weekly_day:
          type: string
          enum: [Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday]
        weekly_time:
          type: string
          pattern: "^\\d{1,2}:\\d{2}$"
        monthly_day:
          type: integer
          minimum: 1
          maximum: 31
        monthly_time:
          type: string
          pattern: "^\\d{1,2}:\\d{2}$"
        once_datetime:
          type: string
        cron_custom:
          type: string
        report_name:
          $ref: "#/components/schemas/ReportKey"
        datasource_name:
          type: string
        format:
          type: string
          enum: [pdf, xlsx, csv, html, xls, docx]
        filename:
          type: string
        email:
          type: string
        email_subject:
          type: string
        email_body:
          type: string
        email_template:
          type: string
        noemail:
          type: string
        url_opt_params:
          type: string
        enabled:
          type: string
      additionalProperties: true
    RecipientAction:
      type: object
      properties:
        delete:
          type: string
        id:
          type: integer
        name:
          type: string
        email:
          type: string
          format: email
        notes:
          type: string
      additionalProperties: false
    EmailTemplateAction:
      type: object
      properties:
        delete:
          type: string
        id:
          type: integer
        name:
          type: string
        subject:
          type: string
        body:
          type: string
      additionalProperties: false
