
# DTS Functions
- [DTS Functions](#dts-functions)
- [DTS Functions Overview](#dts-functions-overview)
  - [DTS Implementation Options](#dts-implementation-options)
    - [Declarative - DTS Expression Language](#declarative---dts-expression-language)
    - [Imperative - Go Functions](#imperative---go-functions)
    - [Workflows - Serverless Workflow Spec](#workflows---serverless-workflow-spec)
- [DTS Function Syntax: Detailed Explanation](#dts-function-syntax-detailed-explanation)
  - [General Structure](#general-structure)
  - [Field Descriptions](#field-descriptions)
    - [`type`](#type)
    - [`(cti.cti)`](#cticti)
      - [Declarative Function CTI Example](#declarative-function-cti-example)
      - [Imperative Function (Go) CTI Example](#imperative-function-go-cti-example)
    - [`description`](#description)
    - [`additionalProperties`](#additionalproperties)
  - [Properties Section](#properties-section)
    - [`params`](#params)
    - [`returns`](#returns)
  - [`cti-traits` Section](#cti-traits-section)
    - [Key Fields in `cti-traits`](#key-fields-in-cti-traits)
      - [Fields Used for Declarative for Imperative Implementations](#fields-used-for-declarative-for-imperative-implementations)
  - [| auth\_scopes | all | all |](#-auth_scopes--all--all-)
      - [`entrypoint`](#entrypoint)
      - [`deterministic_behavior`](#deterministic_behavior)
      - [`language`](#language)
      - [`module`](#module)
      - [`ref_name`](#ref_name)
      - [`context`](#context)
      - [`return`](#return)
  - [Advanced Features](#advanced-features)
    - [`timeout`](#timeout)
    - [`tags`](#tags)
    - [`auth_scopes`](#auth_scopes)
  - [Complete Example: Hello Friend](#complete-example-hello-friend)

# DTS Functions Overview

DTS functions are a mechanism to provide logic in a CyberApp. The metadata layer is similar to protobuf service definintions used for gRPC - it provides an abstracted mechanism to group and define functions with strict arguments and return types that is agnostic about implementation.

DTS functions provide a "lowest common denominator" mechanism for defining the interface contract for a function, and provides multiple languages for the actual implementation. This allows functions to be implemented in various ways—including declaratively with [DTS Expression Language (DEL)](/dts/docs/DEL.md), using Go, or using [Serverless Workflow specifications (SWF 0.8)](https://github.com/serverlessworkflow/specification/tree/0.8.x), in a single process, cooperative environment.

## DTS Implementation Options

### Declarative - DTS Expression Language

Declarative DTS functions are best used to create objects, particularly when compositing between different APIs or with user-specific presentation logic such as localization or item visibility.

### Imperative - Go Functions

Currently, Go functions may only be contributed by Acronis directly because they may provide direct access to the available system. There are various limitations, but generally DTS Go functions are self-contained serverless functions that may be used either directly as entrypoints or as libraries by other Go functions or invoked using `$func` in DEL.

### Workflows - Serverless Workflow Spec

DTS functions can also be implemented using the [Serverless Workflow Specification (SWF 0.8)](https://github.com/serverlessworkflow/specification/tree/0.8.x). This approach allows you to define complex workflows using YAML or JSON, orchestrating multiple steps, conditions, and integrations in a declarative manner.

To use a Serverless Workflow as a DTS function, set the `language` field to `SERVERLESS_WORKFLOW` and provide the workflow definition in the `source` field within the `cti-traits` section. Support for generation/updating via CyberApp tool is planned. The workflow can invoke other DTS functions, perform data transformations, and handle branching logic, using most features available in the Serverless Workflow 0.8 Spec (TODO: Add page w/ differences to spec in acronis-platform).

# DTS Function Syntax: Detailed Explanation

This document provides a guide to using DTS Functions, particularly focusing on the declarative implementation approach. The declarative implementations are done with [DTS Expression Language (DEL)](/dts/docs/DEL.md).

---

## General Structure

A DTS function is defined in RAMLx as a CTI type that inherits from the `dts.DTSFunction` base type. It includes metadata annotations, properties, and traits that describe the function's behavior, interface, inputs, outputs, and execution context. The interface also declares the function's inputs and possible outcomes (success or error).

DTS Functions may be of two primary types: declarative and imperative. Declarative functions are written in [DTS Expression Language (DEL)](/dts/docs/DEL.md) and the CTI RAMLx itself is the source code.  For imperative code, we support Go and Serverless Workflows. In all cases, regardless of implementation type, DTS Functions are interchangeable and reusable regardless of the implementation type (Caveat - complete unification of workflows as DTS Functions is planned but not yet available in production).

Below is a simple example of a typical Declarative DTS Function:

```yaml
#%RAML 1.0 Library

uses:
  cti: ../../.platform/common/cti.raml
  dts: ../../.platform/dts/types.raml

types:
  FunctionName:
    type: dts.DTSFunction
    (cti.cti): <CTI Identifier>
    description: <Description of the function>
    additionalProperties: <true|false>
    properties:
      params:
        additionalProperties: <true|false>
        properties:
          <param_name>: <param_type>
      returns:
        type: <return_type>
    cti-traits:
      entrypoint: <true|false>
      deterministic_behavior: <PURE|QUERY|MUTATION|SIDE-EFFECT>
      
      # `return`, `error` and `error_stack` fields are used for declarative implementations
      return: <DEL Expression Object>
      error:
        - when: <DEL Expression>
          error: <DEL Expression Object>
      error_stack: <true|false>
      
      # these fields are used for imperative implementations
      # return is mutually exclusive with language/module/ref_name
      language: GO
      module: <CTI of Go Module containing the function>
      ref_name: <Go identifier of the function name on the module struct>

      # this field is used if it is a serverless workflow
      source: <Source YAML/JSON of SWF 0.7>
      
      # advanced (optional) fields
      timeout: 77
      tags:
      - cti.a.p.dts.ui.item.v1.0~a.p.main_menu.v1.0
      - cti.a.p.dts.tag.v1.0~a.p.left_menu_header.v1.0
      auth_scopes:
      - "urn:acronis.com:generative_ai::admin"
      - "urn:acronis.com:generative_ai::user"
```

---

## Field Descriptions

The behavior and contract for a given DTS function is defined in metadata with certain standardized fields.

### `type`
- Basic RAMLx field: indicates that the object represents a DTS function.

**Example:**
```yaml
type: dts.DTSFunction
```

### `(cti.cti)`
- A custom annotation that specifies the CTI (Cross-domain Type Identifier) for the function.
- The CTI uniquely identifies the function as a CTI entity, following the CTI format.
- [CTI format is described in our developers guide](https://developer.acronis.com/doc/cyberapps/reference/cti.html)


#### Declarative Function CTI Example
**Format:** `cti.<namespace>.p.dts.func.<version>~<project>.<identifier>.<version>`

**Example:** `cti.a.p.dts.func.v1.0~a.test_project.echo.v1.0`

#### Imperative Function (Go) CTI Example
**Format:** `cti.<namespace>.p.dts.func.<version>~<project>.<module>.<function>.<version>`

**Example:** `cti.a.p.dts.func.v1.0~a.test_project.echo.echo.v1.0`

### `description`
- A human-readable description of the function's purpose or behavior.
- Provides context for developers and users of the DTS function, as well as AI.
- Used to produce DTS Function documentation for end developers.

### `additionalProperties`
- Specifies whether additional properties are allowed in the object.
- Typically set to `false` to enforce strict validation and prevent unexpected fields.

---

## Properties Section

```yaml
properties:
  params:
    additionalProperties: <true|false>
    properties:
      <param_name>: <param_type>
  returns:
    type: <return_type>
```

### `params`
- Describes the input parameters required by the function.
- Includes:
  - `additionalProperties`: Specifies whether additional parameters are allowed (recommend `false` for strict validation).
  - `properties`: A map of parameter names to their types.

**Example:**
```yaml
params:
  additionalProperties: false
  properties:
    echo:
      type: string
```

### `returns`
- Describes the return type of the function.

**Example:**
```yaml
returns:
  type: string
```

---

## `cti-traits` Section

The `cti-traits` section defines additional metadata and traits for the DTS function. These traits provide information about the function's behavior, execution context, and implementation.

```yaml
cti-traits:
  entrypoint: <true|false>
  deterministic_behavior: <PURE|QUERY|MUTATION|SIDE-EFFECT>
  
  # `return`, `error` and `error_stack` fields are used for declarative implementations
  return: <DEL Expression Object>
  error:
    - when: <DEL Expression>
      error: <DEL Expression Object>
  error_stack: <true|false>
  
  # these fields are used for imperative implementations
  # return is mutually exclusive with language/module/ref_name
  language: GO
  module: <CTI of Go Module containing the function>
  ref_name: <Go identifier of the function name on the module struct>

  # this field is used if it is a serverless workflow
  source: <Source YAML/JSON of SWF 0.7>
  
  # advanced (optional) fields
  timeout: 77
  tags:
  - cti.a.p.dts.ui.item.v1.0~a.p.main_menu.v1.0
  - cti.a.p.dts.tag.v1.0~a.p.left_menu_header.v1.0
  auth_scopes:
  - "urn:acronis.com:generative_ai::admin"
  - "urn:acronis.com:generative_ai::user"
```

### Key Fields in `cti-traits`

#### Fields Used for Declarative for Imperative Implementations

|  Field | Implementation Type | Implementation Language |
|--------|---------------------|-------------------------|
| entrypoint | all | all |
| deterministic_behavior | all | all |
| return | declarative | [DTS Expression Language (DEL)](/dts/docs/DEL.md) |
| error | declarative | [DTS Expression Language (DEL)](/dts/docs/DEL.md) |
| error_stack | declarative | [DTS Expression Language (DEL)](/dts/docs/DEL.md) |
| language | imperative | Go or Serverless Workflows |
| source | imperative | Serverless Workflows |
| module | imperative | Go |
| ref_name | imperative | Go |
| timeout | all | all |
| tags | all | all |
| auth_scopes | all | all |
---

#### `entrypoint`
- Indicates whether the function is an entry point (i.e., callable via resolve endpoint).
- **Value:** `true` or `false`.

#### `deterministic_behavior`
- Describes the deterministic nature of the function.
- Not currently enforced, but is planned at the runtime layer.
- Useful to identify functions that are safe for offline uses, e.g. Continuous Integration.
- Used to determine which functions are cacheable, and according to what policy.
- Allowed values:
  - `PURE`: The function is pure and produces the same output for the same input.
  - `QUERY`: The function interacts with the environment in a read-only manner.
  - `MUTATION`: The function modifies the environment.
  - `SIDE_EFFECT`: The function causes external actions, such as sending an email.

**Example:**
```yaml
deterministic_behavior: PURE
```

#### `language`
- Only used with imperative or workflow implementations, mutually exclusive with declarative function fields such as `return`, `error`.
- Specifies the implementation language of the function.
- **Example values:** `GO`, `SERVERLESS_WORKFLOW`.

#### `module`
- Only used with imperative Go implementations, mutually exclusive with declarative function fields such as `return`, `error`.
- Links the function to its parent module.
- Uses the CTI identifier of the module.

**Example:**
```yaml
module: cti.a.p.dts.module.v0.1~vendor.app.echo.v1.0
```

#### `ref_name`
- Only used with imperative Go implementations, mutually exclusive with declarative function fields such as `return`, `error`.
- Provides the function's name in the Go module.

**Example:**
```yaml
ref_name: Echo
```

#### `context`
- Only used for declarative functions, it is mutually exclusive with fields such as `source`, `module`, `ref_name`, `language`, etc...
- Similar to function-level variables, can be declared and referenced later
- Intelligent dependency tree analysis evalutes context as-needed
- Reference later, from return or other context fields as `$.context.<field-name>`

**Example**
```yaml
context:
  full_name: $cel(.params.first_name + ' ' + .params.last_name)
```

#### `return`
- Only used for declarative functions, it is mutually exclusive with fields such as `source`, `module`, `ref_name`, `language`, etc...
- Specifies the declarative implementation of the function.
- Used when the function is defined without imperative code.

**Example:**
```yaml
return:
  id: $uuid()
  message: "Hello, World!"
```

---

## Advanced Features

### `timeout`
- Specifies the maximum execution time for the function in seconds.
- Default is 30 seconds.

**Example:**
```yaml
timeout: 60
```

### `tags`
- A list of tags that can be used to group or categorize the function, used for example by loops to dynamically search for matching functions.

**Example:**
```yaml
tags:
  - cti.a.p.dts.ui.item.v1.0~a.p.main_menu.v1.0
  - cti.a.p.dts.tag.v1.0~a.p.left_menu_header.v1.0
```

### `auth_scopes`
- Specifies the authorization scopes required to execute the function.
- Specified in URN format, full info in [access check documentation](https://developer.acronis.com/doc/introduction/access-model.html).
- Only used when running asynchronously, the function will be executed with a scope-limited token reduced to only those explicitly listed.
- Optional to specify
- Currently **IS NOT USED** for any form of access control checks on a function, it is only specifying the token scope for async execution.
- Not intended for 3rd party use.

**Example:**
```yaml
auth_scopes:
  - "urn:acronis.com:generative_ai::admin"
  - "urn:acronis.com:generative_ai::user"
```

---

## Complete Example: Hello Friend

Below is a complete example of a DTS function definition, demonstrating [DTS Expression Language (DEL)](/dts/docs/DEL.md) and DTS Function metadata:

```yaml
#%RAML 1.0 Library

uses:
  cti: ../../.platform/common/cti.raml
  dts: ../../.platform/dts/types.raml

types:
  GreetingFunction:
    type: dts.DTSFunction
    (cti.cti): cti.a.p.dts.func.v1.0~a.example_project.greeting.v1.0
    description: "A declarative DTS function that generates a personalized greeting message."
    additionalProperties: false
    properties:
      params:
        additionalProperties: false
        properties:
          first_name:
            type: string
            description: "The first name of the person to greet."
          last_name:
            type: string
            description: "The last name of the person to greet."
      returns:
        type: object
        properties:
          message:
            type: string
            description: "The personalized greeting message."
    cti-traits:
      entrypoint: true
      deterministic_behavior: PURE
      context:
        full_name: $cel(.params.first_name + ' ' +.params.last_name)
      return:
        message: $cel('Hello, ' + .context.full_name + '!')
```

```yaml
#%RAML 1.0 Library

uses:
  cti: ../../.platform/common/cti.raml
  dts: ../../.platform/dts/types.raml

types:
  PalindromeChecker:
    type: dts.DTSFunction
    (cti.cti): cti.a.p.dts.func.v1.0~a.example_project.palindrome_checker.v1.0
    description: "A declarative DTS function that checks if a given string is a palindrome."
    additionalProperties: false
    properties:
      params:
        additionalProperties: false
        properties:
          input_string:
            type: string
            description: "The string to check for palindrome."
      returns:
        type: object
        properties:
          is_palindrome:
            type: boolean
            description: "True if the input string is a palindrome, false otherwise."
    cti-traits:
      entrypoint: true
      deterministic_behavior: PURE
      return:
        is_palindrome: $cel(.params.input_string == .params.input_string.reverse())
```

```yaml
#%RAML 1.0 Library

uses:
  cti: ../../.platform/common/cti.raml
  dts: ../../.platform/dts/types.raml

types:
  FetchPostsFunction:
    type: dts.DTSFunction
    (cti.cti): cti.a.p.dts.func.v1.0~a.example_project.fetch_posts.v1.0
    description: "A declarative DTS function that fetches posts from the JSONPlaceholder API."
    additionalProperties: false
    properties:
      params:
        additionalProperties: false
        properties:
          user_id:
            type: integer
            description: "The ID of the user whose posts should be fetched."
      returns:
        type: object
        properties:
          posts:
            type: array
            items:
              type: object
              properties:
                userId:
                  type: integer
                id:
                  type: integer
                title:
                  type: string
                body:
                  type: string
    cti-traits:
      entrypoint: true
      deterministic_behavior: QUERY
      context:
        posts: $http[cti.a.p.oagw.route.v1.0~example.jsonplaceholder.common.v1.0](
          method="GET",
          path=$cel('/posts?userId=' + string(.params.user_id)),
          header=[
            {"name": "Accept", "value": "application/json"}
          ],
          options={
            "timeout": "PT10S",
            "allowed_status_codes": [200]
          }
        )
      return:
        posts: $.context.body
```