Add AGENTS.md or CLAUDE.md

# Yaak YAML Sync File Spec

## Files & Overview

* Each model corresponds to one file, named `yaak.<model-id>.yaml`, stored at the root of the sync folder.
* The YAML content is a `SyncModel` union. The top-level `type` field identifies the model kind and the corresponding model fields are embedded.
* The `model` field must match the `type` value (e.g., when `type: "workspace"`, `model` must be the string `workspace`).
* All `id` values use the `prefix_randomId` format (e.g., `wk_abcd1234EF`). Prefixes by model: `wk` = workspace, `ev` = environment, `fl` = folder, `rq` = HTTP request, `gr` = gRPC request, `wr` = WebSocket request.
* `createdAt` and `updatedAt` use the `chrono::NaiveDateTime` serialization format (`YYYY-MM-DDTHH:MM:SS[.microseconds]`, UTC timezone).
* All strings are stored as UTF-8. Unspecified fields fall back to application defaults.

## Shared Fields & Substructures

* **`authenticationType`**: Selects a pluggable auth flow. Default `null` means inherit from the parent. Built-in plugin names include `basic`, `bearer`, `apikey`, `jwt`, `oauth2`; additional plugins may add other string values.
* **`authentication`**: `Record<string, any>` holding fields for the chosen auth type.

  * Common key: `disabled` (boolean, default `false`; when `true`, the auth is disabled even if configured).
  * Other keys depend on the plugin. For example, Basic uses `username`, `password`; Bearer uses `token`, `prefix`, etc.
* **`headers`**: Array of `{ name: string, value: string, enabled?: boolean, id?: string }`.

  * `enabled` defaults to `true`. `id` is for UI tracking and can be omitted when adding manually.
* **`urlParameters`**: Same shape as headers (`{ name, value, enabled?, id? }`), used only for HTTP/WebSocket. Entries with `enabled: false` or an empty `name` are ignored.
* **`body.form` entries**: For form-type HTTP bodies.

  * URL-encoded: each entry `{ name, value, enabled?: boolean, id?: string }`.
  * Multipart: entries `{ name, enabled?: boolean, value?: string, file?: string, contentType?: string, id?: string }`. Use either `file` or `value`. `file` stores a local file path.
* **GraphQL Body**: The `body` object contains `{ query: string, variables?: string }`, where `variables` is a formatted JSON string.
* **Binary Body**: The `body` object contains `{ filePath: string }`, pointing to the full path of the file to upload.
* **Plain-text/JSON/XML Body**: The `body` object contains `{ text: string }`.

## Workspace (`type: "workspace"`)

* `id`: `wk_…`.
* `name`: Workspace name.
* `description`: Markdown string, freeform.
* `authenticationType` / `authentication`: When set, becomes the default auth for all descendants.
* `headers`: Defaults applied to all requests in the workspace.
* `encryptionKeyChallenge`: String or `null`, challenge code for protected workspaces.
* `settingValidateCertificates`: Boolean, default `true`, whether to validate TLS certificates.
* `settingFollowRedirects`: Boolean, default `true`.
* `settingRequestTimeout`: Integer, milliseconds; `0` means no request timeout.

### Workspace YAML Example

```yaml
type: workspace
model: workspace
id: wk_oTs8PQX12A
createdAt: 2024-04-24T08:17:52.123456
updatedAt: 2024-04-24T08:20:01.654321
name: Demo Workspace
description: |
  This workspace is used for sync testing.
authenticationType: bearer
authentication:
  disabled: false
  token: {{ secrets.token }}
  prefix: Bearer
headers:
  - name: User-Agent
    value: yaak
settingValidateCertificates: true
settingFollowRedirects: true
settingRequestTimeout: 0
```

## Environment (`type: "environment"`)

* `id`: `ev_…`; `workspaceId` points to the owning workspace.
* `name`: Environment name.
* `public`: Boolean; `true` means shareable across workspaces (operations restricted by UI).
* `variables`: Array; each `{ name, value, enabled?: boolean, id?: string }`.

  * `enabled` defaults to `true`.
* `color`: `null` or a CSS color (e.g., `#FFB300`).
* `parentModel`: String, one of `workspace` / `environment` / `folder`.
* `parentId`: `null` or the parent’s `id`; must be `null` when `parentModel` is `workspace`.

### Environment YAML Example

```yaml
type: environment
model: environment
id: ev_5nXPHK3m9J
workspaceId: wk_oTs8PQX12A
createdAt: 2024-04-24T08:19:05
updatedAt: 2024-05-02T01:12:44
name: Production
public: false
color: "#2E86AB"
parentModel: workspace
parentId: null
variables:
  - name: api_base
    value: https://api.example.com
  - name: auth_token
    value: {{ secrets.prod_token }}
    enabled: false
```

## Folder (`type: "folder"`)

* `id`: `fl_…`; `workspaceId` required; `folderId` points to the parent folder or `null`.
* `name`: Folder name.
* `description`: Markdown string.
* `sortPriority`: Float, used for UI ordering (smaller = earlier).
* `authenticationType` / `authentication`, `headers`: Override workspace settings and are inherited by descendants.

### Folder YAML Example

```yaml
type: folder
model: folder
id: fl_Sz1G4LTwQe
workspaceId: wk_oTs8PQX12A
createdAt: 2024-04-24T08:25:10
updatedAt: 2024-04-24T08:25:10
folderId: null
name: Billing APIs
description: A collection of customized billing service requests.
sortPriority: 0
authenticationType: basic
authentication:
  disabled: false
  username: {{ secrets.billing_user }}
  password: {{ secrets.billing_pass }}
headers:
  - name: X-App-Version
    value: 1.4.0
```

## HTTP Request (`type: "http_request"`)

* `id`: `rq_…`; `workspaceId` required; `folderId` may be `null`.
* `name`, `description`: Request name and description.
* `method`: HTTP verb, default `GET`.
* `url`: Full URL (may include path and query).
* `urlParameters`: See shared substructure.
* `headers`: See shared substructure.
* `authenticationType` / `authentication`: When `null`, inherit from the hierarchy.
* `bodyType`: `null` or a content type. Common values:

  * `application/json`
  * `text/xml`
  * `graphql`
  * `application/x-www-form-urlencoded`
  * `multipart/form-data`
  * `binary`
  * `other` (use with a custom `Content-Type` header)
* `body`: Structure varies by `bodyType` (see below).
* `sortPriority`: Float, for UI ordering.

### Body Types & Structures

| `bodyType`                              | `body` content                          | Notes                                            |
| --------------------------------------- | --------------------------------------- | ------------------------------------------------ |
| `null`                                  | `{}` or omitted                         | No request body                                  |
| `application/json` and other text types | `{ text: string }`                      | `text` may include template syntax               |
| `text/xml` / `other`                    | `{ text: string }`                      | For `other`, set `Content-Type` in `headers`     |
| `graphql`                               | `{ query: string, variables?: string }` | `variables` must be a JSON string; omit if unset |
| `application/x-www-form-urlencoded`     | `{ form: Array<FormEntry> }`            | `FormEntry` per shared substructure              |
| `multipart/form-data`                   | `{ form: Array<FormEntry> }`            | `FormEntry` may include `file` **or** `value`    |
| `binary`                                | `{ filePath: string }`                  | Local file path                                  |

### HTTP Request YAML Example

```yaml
type: http_request
model: http_request
id: rq_Az0rKwLh8U
workspaceId: wk_oTs8PQX12A
folderId: fl_Sz1G4LTwQe
createdAt: 2024-04-24T08:31:45
updatedAt: 2024-05-02T05:10:03
name: Create Invoice
method: POST
url: https://api.example.com/v1/invoices
urlParameters:
  - name: dry_run
    value: "true"
    enabled: false
headers:
  - name: Content-Type
    value: application/json
bodyType: application/json
body:
  text: |
    {
      "customerId": "{{ env.customer_id }}",
      "amount": {{ env.amount | number }},
      "currency": "USD"
    }
authenticationType: bearer
authentication:
  disabled: false
  token: {{ env.auth_token }}
sortPriority: 1
```

## gRPC Request (`type: "grpc_request"`)

* `id`: `gr_…`; `workspaceId` required; `folderId` may be `null`.
* `url`: Target gRPC server, e.g., `https://grpc.example.com`.
* `service`: Proto service name.
* `method`: Method name.
* `message`: String, typically JSON-formatted request data.
* `metadata`: Same shape as `headers`, used for gRPC metadata.
* `authenticationType` / `authentication`: Same behavior as HTTP.
* `sortPriority`: Float.

### gRPC Request YAML Example

```yaml
type: grpc_request
model: grpc_request
id: gr_k19fHQLX5c
workspaceId: wk_oTs8PQX12A
folderId: fl_Sz1G4LTwQe
createdAt: 2024-04-24T08:40:12
updatedAt: 2024-04-24T08:40:12
name: ChargeCustomer
service: billing.v1.InvoiceService
method: CreateInvoice
url: https://grpc.example.com
message: |
  {
    "customerId": "{{ env.customer_id }}",
    "amount": {{ env.amount }}
  }
metadata:
  - name: x-trace-id
    value: {{ uuid() }}
authenticationType: null
sortPriority: 0
```

## WebSocket Request (`type: "websocket_request"`)

* `id`: `wr_…`; `workspaceId` required; `folderId` may be `null`.
* `url`: WebSocket/Socket URL, e.g., `wss://ws.example.com/realtime`.
* `message`: Default message to send (plain text). Templating supported.
* `urlParameters`, `headers`: Same structures as HTTP.
* `authenticationType` / `authentication`: Same behavior as HTTP.
* `sortPriority`: Float.

### WebSocket Request YAML Example

```yaml
type: websocket_request
model: websocket_request
id: wr_v6QEz91Ppa
workspaceId: wk_oTs8PQX12A
folderId: null
createdAt: 2024-04-24T08:45:30
updatedAt: 2024-04-24T09:02:11
name: Subscribe Orders
url: wss://ws.example.com/realtime
urlParameters:
  - name: channel
    value: orders
headers:
  - name: X-Client-ID
    value: mobile-app
message: |
  {
    "type": "subscribe",
    "topics": ["orders"]
  }
authenticationType: apikey
authentication:
  disabled: false
  location: header
  key: X-Api-Key
  value: {{ env.ws_api_key }}
sortPriority: 0
```

## Common Notes

* If any `id` field is omitted, the app will auto-generate one. If you edit manually, ensure uniqueness and keep the prefix.
* To disable inheritance from Workspace/Folder auth or headers, override `authenticationType` at the Request level or remove specific headers from `headers`.
* `bodyType` and the `Content-Type` header are **not** automatically synchronized—if you change one, update the other as well (the UI behaves the same way).
* If a GraphQL request still uses the legacy `{ text: string }` body, update it to `{ query, variables }` to avoid another UI migration.
* `filePath` and `file` fields store local paths. When moving the sync folder to another machine, ensure paths remain valid or adopt a relative-path strategy.

Please authenticate to join the conversation.

Upvoters
Status

Needs Triage

Board

Feedback

Date

9 months ago

Author

Joseph Wang

Subscribe to post

Get notified by email when there are changes.