openapi: 3.0.3
info:
  title: Builder API
  description: |
    <a href="/openapi/ui/builder-openapi.yaml" target="_blank" download="builder-openapi.yaml"><button>Download OpenAPI Specification</button></a>

    APIs for registering Technology Adapters, generating descriptors from uploaded archives, and starting and monitoring template instantiations.
  version: '1.0.0'
tags:
  - name: Builder
servers:
  - url: /api/builder
paths:
  /register:
    post:
      tags:
        - Builder
      summary: Register a Tech Adapter
      description: |
        This endpoint is used to register the Technology Adapter's URL and link it to the `infrastructureTemplateId`.

        After deploying a new Technology Adapter into the infrastructure, all the components with a your chosen `infrastructureTemplateId` should invoke said microservice. 

        To do so, we need to link the `infrastructureTemplateId` with the Technology Adapter's URL where the microservice is located. Make sure the URL is reachable by the Witboost platform.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - id
                - name
                - description
                - version
                - url
                - environment
              properties:
                id:
                  type: string
                  description: Unique identifier of the Technology Adapter, in the form of a Witboost's URN, like "urn:dmb:itm:snowflake-outputport-provisioner:0"
                name:
                  type: string
                  description: Name of the Technology Adapter, like "Snowflake Output Port"
                description:
                  type: string
                  description: A description that explains the purpose of the Technology Adapter
                version:
                  type: string
                  description: The Technology Adapter's version, like "0". This version must be ALWAYS equal to the version defined in the URN identifier (the last section of the URN identifier after the last ":")
                url:
                  type: string
                  description: The URL of the Technology Adapter, like "http://my-tech-adapter:8093/snowflake-outputport-provisioner". This URL must be reachable from the provisioning coordinator (from a pod in the Kubernetes cluster where the provisioning coordinator is running)
                environment:
                  type: string
                  description: The environment where the Technology Adapter is running, like "production". The environment here must be one of the environments configured for the Builder module of Witboost.
                properties:
                  $ref: '#/components/schemas/InfraTemplateProperties'
            examples:
              snowflakeOutputPort:
                summary: Snowflake Output Port
                value:
                  id: 'urn:dmb:itm:snowflake-outputport-provisioner:0'
                  name: 'Snowflake Output Port'
                  description: 'Provisions a Snowflake Output Port'
                  version: '0'
                  url: 'http://my-tech-adapter:8093/snowflake-outputport-provisioner'
                  environment: 'production'
              guardianTemplate:
                summary: Data Contract Guardian
                value:
                  id: 'urn:dmb:itm:guardian-template:0'
                  name: 'Guardian Template'
                  description: 'Provisions a data contract guardian'
                  version: '0'
                  url: 'http://my-tech-adapter:8093/guardian-provisioner'
                  environment: 'production'
                  properties:
                    dataContractGuardian:
                      policies:
                        - resourceType: dataproduct
                          spec:
                            id: my-guardian-policy-id
                        - resourceType: biproject
                          spec:
                            name: My Guardian Policy
                            description: Policy to collect data contract monitoring results
      responses:
        200:
          description: The Technology Adapter has been registered correctly
          content:
            application/json:
              schema:
                type: string
                description: Contains the result, if no problems are detected, the result will be "OK"
                example: OK
        500:
          description: An error occurred while registering the Technology Adapter
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                error:
                  value:
                    error:
                      message: 'An error occurred while registering the Technology Adapter'

  /v1/entities/descriptor/from-files/info:
    get:
      tags:
        - Builder
      summary: Get descriptor files info
      description: |
        Returns the list of files/folders expected by the descriptor generation flow.
      operationId: getDescriptorFilesInfo
      responses:
        200:
          description: Descriptor files info retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetDescriptorInfoFromFilesResponse'
              examples:
                success:
                  value:
                    files:
                      - catalog-info.yaml
                      - environments
                      - parameters.yaml
        500:
          description: An error occurred while getting info from descriptor files
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                error:
                  value:
                    error:
                      message: 'Error while getting info from descriptor files.'

  /v1/entities/descriptor/from-files:
    post:
      tags:
        - Builder
      summary: Build descriptor from files archive
      description: |
        Builds a single descriptor by processing an uploaded archive containing one or more entity directories.

        The archive must be in `.tar.gz` or `.tgz` format. Each top-level directory in the archive represents one entity and must include a `catalog-info.yaml` file. It can also optionally include:
        - `parameters.yaml`
        - `environments/<environment>/configurations.yaml`

        The processing flow unpacks all directories, resolves each entity's descriptor from its `catalog-info.yaml`, distinguishes between system and component descriptors, then merges all component descriptors into the system descriptor, which acts as the root.

        **Note:** The archive is expected to contain exactly one system directory. If multiple system directories are present, only the first one will be used and the others will be ignored.
      operationId: buildDescriptorFromFiles
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/BuildDescriptorFromFilesRequest'
            encoding:
              archive:
                contentType: application/gzip
            examples:
              minimal:
                value:
                  environment: development
      responses:
        200:
          description: Descriptor built successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BuildDescriptorFromFilesResponse'
              examples:
                success:
                  value:
                    descriptor:
                      projectKind: system
                      dataProductOwner: group:default/data-team
                      domain: finance
                      kind: System
                      metadata:
                        name: my-data-product
        400:
          description: Invalid form data
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationError'
              examples:
                invalidBody:
                  value:
                    errors:
                      - Invalid form data: missing archive or environment
                    moreInfo:
                      problems:
                        - '{"code":"invalid_type","path":["archive"],"message":"Required"}'
                      solutions: []
        500:
          description: An error occurred while building descriptor from files
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                error:
                  value:
                    error:
                      message: 'Error while building descriptor from files.'

  /v1/templates/instantiation:
    post:
      tags:
        - Builder
      summary: Instantiate a template
      description: |
        Starts a new template instantiation asynchronously. The endpoint returns the created task identifier. 

        See the [Template page](/docs/data-teams/p6_advanced/p6_1_templates#how-to-instantiate-a-template-programmatically) for a step-by-step guide.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/InstantiateTemplateRequest'
            examples:
              minimal:
                value:
                  templateRef: 'template:default/my-data-product-template'
                  values:
                    name: 'my-data-product'
                    owner: 'group:default/data-team'
              withEnvironmentParameters:
                value:
                  templateRef: 'template:default/my-template'
                  values:
                    name: 'my-data-product'
                  environmentParameters:
                    development:
                      region: 'eu-west-1'
                    production:
                      region: 'eu-central-1'
      responses:
        200:
          description: Template instantiation started successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InstantiateTemplateResponse'
              examples:
                success:
                  value:
                    id: '2f4b7a6f-6d2e-4a22-a912-cce8f90b3843'
        400:
          description: Invalid request body
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                invalidBody:
                  value:
                    error:
                      message: 'Invalid request body: missing template reference or values'
        500:
          description: An error occurred while instantiating the template
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                error:
                  value:
                    error:
                      message: 'Error while instantiating template.'

  /v1/templates/instantiation/{taskId}/stream:
    get:
      tags:
        - Builder
      summary: Stream template instatiation events
      description: |
        Opens a Server-Sent Events (SSE) stream for a template instantiation task.

        Events are emitted as `event: <type>` and `data: <json>` records. Supported event types include
        `log`, `recovered`, `cancelled`, and `completion`.

        See the [Template page](/docs/data-teams/p6_advanced/p6_1_templates#how-to-instantiate-a-template-programmatically) for a step-by-step guide.
      parameters:
        - in: path
          name: taskId
          required: true
          description: The template instantiation task identifier
          schema:
            type: string
      responses:
        200:
          description: SSE stream opened successfully
          content:
            text/event-stream:
              schema:
                type: string
                description: Server-Sent Events stream payload
              examples:
                logEvent:
                  value: |
                    event: log
                    data: {"message":"Starting template execution","createdAt":"2026-01-01T10:00:00.000Z"}

                    event: completion
                    data: {"message":"Task completed","createdAt":"2026-01-01T10:00:10.000Z"}
        500:
          description: An error occurred while streaming template instantiation logs
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                error:
                  value:
                    error:
                      message: 'An error occurred while streaming template instantiation logs.'

  /v1/templates/instantiation/{taskId}/status:
    get:
      tags:
        - Builder
      summary: Get template instantiation status
      description: |
        Returns the latest status for a template instantiation task.

        See the [Template page](/docs/data-teams/p6_advanced/p6_1_templates#how-to-instantiate-a-template-programmatically) for a step-by-step guide.
      parameters:
        - in: path
          name: taskId
          required: true
          description: The template instantiation task identifier
          schema:
            type: string
      responses:
        200:
          description: Task status retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetTemplateInstantiationStatusResponse'
              examples:
                open:
                  value:
                    status: 'open'
                completed:
                  value:
                    status: 'completed'
        500:
          description: An error occurred while getting template instantiation status
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                error:
                  value:
                    error:
                      message: 'Error while getting template instantiation status.'

  /api/actionHandler/hooks/{id}:
    servers:
      - url: /
    patch:
      tags:
        - Builder
      summary: Update the status of a hook
      description: |
        Witboost Hooks model third-party approval workflows. 

        Hooks are used, for instance, to model the Access Control workflow, where an Data Consumer asks access to a Data Owner.
        In case an Access Control request is forwarded to third-party ticketing systems, this endpoint helps Witboost understand whether the request is still pending, completed or rejected/failed.  

        In general, outside of the Access Control workflow, this endpoint is used to update the status of a hook, so that the Witboost platform knows how to proceed with a pending request.
      parameters:
        - in: path
          name: id
          schema:
            type: string
          required: true
          description: |
            Request ID as provided by the Witboost platform in the respondToUrl field.
      requestBody:
        description: A resource to be evaluated
        content:
          application/json:
            schema:
              oneOf:
                - $ref: '#/components/schemas/UpdateHookRequest'
                - $ref: '#/components/schemas/TraceableUpdateHookRequest'
            examples:
              accept:
                value:
                  status: OK
                  hookInfo:
                    message: 'The request has been accepted on the external system'
              reject:
                value:
                  status: KO
                  hookInfo:
                    message: 'The request has been rejected on the external system'
              acceptWithTracking:
                value:
                  status: OK
                  hookInfo:
                    message: 'The request has been accepted on the external system'
                    tracking:
                      id: '123456'
                      url: 'https://external-system.com/requests/123456'

        required: true
      responses:
        200:
          description: The hook has been updated correctly
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UpdateHookResponse'
              examples:
                accepted:
                  value:
                    hookId: '34797dd1-1f25-48b0-89c7-14d2ce04a78b'
                    hookName: 'RemoteRequestHook'
                    actionId: '0298b78f-4d77-45f7-a7a4-f16278144141'
                    actionName: 'AccessControlAction'
                    creationAt: '2021-09-01T12:00:00Z'
                    updateAt: '2021-09-01T12:00:00Z'
                    status: OK
                rejected:
                  value:
                    hookId: '34797dd1-1f25-48b0-89c7-14d2ce04a78b'
                    hookName: 'RemoteRequestHook'
                    actionId: '0298b78f-4d77-45f7-a7a4-f16278144141'
                    actionName: 'AccessControlAction'
                    creationAt: '2021-09-01T12:00:00Z'
                    updateAt: '2021-09-01T12:00:00Z'
                    status: KO
        404:
          description: There is no hook handler or no action handler for the specified hook. This can happen when a action or a hook gets removed from witboost after a deprecation period.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                notFound:
                  value:
                    error:
                      message: 'The hook handler or action handler was not found'
        409:
          description: Hook is in an immutable state. A hook can be updated only if its status is WAITING
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                immutable:
                  value:
                    error:
                      message: 'The hook is in an immutable state'
        500:
          description: System problem
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                error:
                  value:
                    error:
                      message: 'An error occurred while updating the hook'

components:
  schemas:
    InfraTemplateProperties:
      type: object
      description: Additional infrastructure template properties
      properties:
        dataContractGuardian:
          $ref: '#/components/schemas/InfraTemplateGuardianProperties'

    InfraTemplateGuardianProperties:
      type: object
      description: When specified during the registration of an infrastructure template, the template will be designated as a data contract guardian template
      required:
        - policies
      properties:
        policies:
          description: >
            List of policies in the Witboost Computational Governance to be associated to the guardian template.
            This list should include **at most one** policy per resource type.
            If the provided list contains fewer policies than those currently associated with the template, 
            the additional policies that are not included in the list will be unlinked from the template. 
            This means that the list you provide represents the target set of policies for the template
          type: array
          items:
            type: object
            required:
              - resourceType
              - spec
            properties:
              resourceType:
                description: >
                  During the provisioning of a data contract guardian linked to this infrastructure template, 
                  the Coordinator will identify the resource type of the deployment unit containing the data contract guardian (as a component),
                  and use it to retrieve the corresponding passive policy that will be provided to the guardian's tech adapter.
                  <br /><br />**Note:** The referenced resource type is that of the deployment unit containing the data contract guardian, 
                  and not the resource type of the guardian itself
                type: string
                example: dataproduct
              spec:
                type: object
                description: >
                  Policy specification. You must provide either:
                    - the `id` of an existing passive policy that is already registered in the Witboost Computational Governance.
                      **Note:** If a policy for the same resource type is already associated with this template, it will be replaced by the provided policy.
                      The previous policy will NOT be removed from the Witboost Computational Governance
                    - OR, `name` and (optionally) `description` for a new passive policy that will be automatically registered in the Witboost Computational Governance.
                      **Note:** If a policy for the same resource type is already associated with this template, this spec will have no effect
                properties:
                  id:
                    description: Id of an existing passive policy (**required** when `name` is not specified)
                    type: string
                    example: 9f86d081-8143-4196-8536-41c91f876f7c
                  name:
                    description: Name of the passive policy (**required** when `id` is not specified)
                    type: string
                    example: Data Contract Guardian Policy
                  description:
                    description: Description of the passive policy
                    type: string
                    example: Passive policy for data contract monitoring results

    GetDescriptorInfoFromFilesResponse:
      type: object
      description: Response containing expected files/folders for descriptor generation
      required:
        - files
      properties:
        files:
          type: array
          items:
            type: string
          description: List of required or supported files/folders

    BuildDescriptorFromFilesRequest:
      type: object
      description: Multipart payload used to generate a descriptor from an archive
      required:
        - archive
        - environment
      properties:
        archive:
          type: string
          format: binary
          description: Archive file containing descriptor source files (`.tar.gz` or `.tgz`)
        environment:
          type: string
          description: Target environment used to resolve environment-specific configurations
          example: development

    BuildDescriptorFromFilesResponse:
      type: object
      description: Resulting descriptor built from uploaded files
      required:
        - descriptor
      properties:
        descriptor:
          type: object
          description: Generated descriptor object
          additionalProperties: true

    ValidationError:
      type: object
      required:
        - errors
      properties:
        errors:
          type: array
          items:
            type: string
          description: User-friendly validation errors
        moreInfo:
          type: object
          additionalProperties: true
          description: Additional diagnostics for troubleshooting input issues

    InstantiateTemplateRequest:
      type: object
      description: Request payload to start a template instantiation task
      required:
        - templateRef
        - values
      properties:
        templateRef:
          type: string
          description: Entity reference of the template to instantiate
          example: template:default/my-template
        values:
          type: object
          description: Input values for template parameters
          additionalProperties: true
        environmentParameters:
          type: object
          description: Optional environment-scoped parameter overrides
          additionalProperties:
            type: object
            additionalProperties: true

    InstantiateTemplateResponse:
      type: object
      description: Response returned after template task creation
      required:
        - id
      properties:
        id:
          type: string
          description: Identifier of the created task
          example: 2f4b7a6f-6d2e-4a22-a912-cce8f90b3843

    GetTemplateInstantiationStatusResponse:
      type: object
      description: Current status of a template instantiation task
      required:
        - status
      properties:
        status:
          type: string
          description: Current task status
          enum:
            - open
            - processing
            - completed
            - failed
            - skipped
          example: processing

    UpdateHookRequest:
      type: object
      description: An update hook request
      required:
        - status
      properties:
        status:
          $ref: '#/components/schemas/RequestedHookState'
        hookInfo:
          type: object
          description: A free-form object that will be stored as the hook's response data

    TraceableUpdateHookRequest:
      type: object
      description: An update hook request with embedded traceable information
      required:
        - status
      properties:
        status:
          $ref: '#/components/schemas/RequestedHookState'
        hookInfo:
          type: object
          description: A free-form object that will be stored as the hook's response data with an optional reserved field name for tracking information
          properties:
            tracking:
              type: object
              description: A reserved field for any available tracking information for the users to check the status of their request in the external system
              properties:
                id:
                  type: string
                  description: An optional id of the request on the external system, this is helpful if the external system is known to witboost and can reconstruct the URL that a user should visit. Or when it's not possible to provide a viewable URL for the user to check the status of the request.
                url:
                  type: string
                  description: An optional URL of the request on the external system, it should link to an external system that can show to the users the status of their requests
          additionalProperties: true

    UpdateHookResponse:
      type: object
      description: Represents the response structure for updating a hook.
      required:
        - hookId
        - hookName
        - creationAt
        - updateAt
        - status
      properties:
        hookId:
          type: string
          description: The unique identifier of the hook.
        hookName:
          type: string
          description: The name of the hook.
        actionId:
          type: string
          description: The unique identifier of the action associated with the hook, if any.
        actionName:
          type: string
          description: The name of the action associated with the hook, if any.
        creationAt:
          type: string
          format: date-time
          description: The timestamp indicating when the hook was created.
        updateAt:
          type: string
          format: date-time
          description: The timestamp indicating the last update time of the hook.
        status:
          $ref: '#/components/schemas/HookState'

    RequestedHookState:
      type: string
      description: Represents the desired state of the hook. OK means the third-party interaction has been completed with a positive result, KO on the other hand can be used to represent a negative result. If the hook is attached to an action, signaling KO could prevent the action's callback to be invoked
      enum:
        - KO
        - OK

    HookState:
      type: string
      description: The current state of the hook, referencing the HookState schema.
      enum:
        - WAITING
        - KO
        - OK

    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - message
          properties:
            message:
              type: string
              description: An informative user-friendly message that informs about occurred errors
          additionalProperties: true
