@superglue/cli 1.1.18 → 1.1.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/dist/cli.js +832 -23922
- package/dist/skills/superglue/SKILL.md +240 -27
- package/dist/skills/superglue/references/access-rules.md +137 -0
- package/dist/skills/superglue/references/data-handling.md +303 -0
- package/dist/skills/superglue/references/databases.md +7 -3
- package/dist/skills/superglue/references/file-handling.md +160 -0
- package/dist/skills/superglue/references/file-servers.md +13 -37
- package/dist/skills/superglue/references/http-apis.md +248 -0
- package/dist/skills/superglue/references/redis.md +4 -5
- package/package.json +2 -1
- package/skills/superglue/SKILL.md +240 -27
- package/skills/superglue/references/access-rules.md +137 -0
- package/skills/superglue/references/data-handling.md +303 -0
- package/skills/superglue/references/databases.md +7 -3
- package/skills/superglue/references/file-handling.md +160 -0
- package/skills/superglue/references/file-servers.md +13 -37
- package/skills/superglue/references/http-apis.md +248 -0
- package/skills/superglue/references/redis.md +4 -5
- package/dist/dist/cli.js +0 -24370
- package/dist/dist/skills/superglue/SKILL.md +0 -678
- package/dist/dist/skills/superglue/agents/openai.yaml +0 -7
- package/dist/dist/skills/superglue/assets/superglue.png +0 -0
- package/dist/dist/skills/superglue/references/databases.md +0 -249
- package/dist/dist/skills/superglue/references/file-servers.md +0 -136
- package/dist/dist/skills/superglue/references/integration.md +0 -279
- package/dist/dist/skills/superglue/references/redis.md +0 -190
- package/dist/dist/skills/superglue/references/transforms-and-output.md +0 -92
- package/dist/skills/superglue/references/transforms-and-output.md +0 -92
- package/skills/superglue/references/transforms-and-output.md +0 -92
|
@@ -19,8 +19,9 @@ description: "Build, test, deploy and integrate superglue tools via the sg CLI a
|
|
|
19
19
|
|
|
20
20
|
**Authentication & Credentials:**
|
|
21
21
|
|
|
22
|
-
- **
|
|
23
|
-
-
|
|
22
|
+
- **Authentication must always be explicitly configured** — nothing is injected automatically in any protocol
|
|
23
|
+
- For HTTP: include auth headers using `<<systemId_credentialKey>>` syntax (e.g., `"Authorization": "Bearer <<systemId_access_token>>"`)
|
|
24
|
+
- For databases/Redis/file servers: embed credential placeholders in the connection URL (e.g., `postgres://<<sys_user>>:<<sys_pass>>@host/db`)
|
|
24
25
|
- OAuth systems also require explicit headers — only token refresh is automatic
|
|
25
26
|
|
|
26
27
|
**Saving Tools:**
|
|
@@ -31,7 +32,7 @@ description: "Build, test, deploy and integrate superglue tools via the sg CLI a
|
|
|
31
32
|
|
|
32
33
|
**Credentials in Non-Interactive Environments (AI Agents, CI):**
|
|
33
34
|
|
|
34
|
-
- **Pass ALL credentials (including secrets) directly via `--credentials` JSON**
|
|
35
|
+
- **Pass ALL credentials (including secrets) directly via `--credentials` JSON**
|
|
35
36
|
- Ask the user to provide secret values, then pass them in `--credentials '{"api_key":"sk-xxx"}'`
|
|
36
37
|
|
|
37
38
|
---
|
|
@@ -121,15 +122,67 @@ sg tool save --draft <draftId>
|
|
|
121
122
|
|
|
122
123
|
| Flag | Description |
|
|
123
124
|
| ------------------ | ------------------------------------------- |
|
|
124
|
-
| `--
|
|
125
|
+
| `--table` | Human-readable table output (default: JSON) |
|
|
126
|
+
| `--full` | Disable truncation of large fields |
|
|
125
127
|
| `--api-key <key>` | Override API key |
|
|
126
128
|
| `--endpoint <url>` | Override API endpoint |
|
|
127
129
|
|
|
130
|
+
## Capability Presets
|
|
131
|
+
|
|
132
|
+
The CLI supports three capability presets that control which commands are available. Set during `sg init` or via `SUPERGLUE_CLI_PRESET` env var. Stored in `config.json` as `"preset"`.
|
|
133
|
+
|
|
134
|
+
| Preset | Description |
|
|
135
|
+
| --------- | ------------------------------------------------------------------ |
|
|
136
|
+
| `runner` | Run saved tools by ID only. Read-only lookups. No building/editing |
|
|
137
|
+
| `builder` | Runner + build/edit/save tools, call systems. No system CRUD |
|
|
138
|
+
| `admin` | Full access (default) |
|
|
139
|
+
|
|
140
|
+
### Preset-to-Command Matrix
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
Command runner builder admin
|
|
144
|
+
─────────────────────────────────────────────────
|
|
145
|
+
sg init x x x
|
|
146
|
+
sg update x x x
|
|
147
|
+
sg skill x x x
|
|
148
|
+
sg tool build - x x
|
|
149
|
+
sg tool run --tool x x x
|
|
150
|
+
sg tool run --config/etc - x x
|
|
151
|
+
sg tool edit - x x
|
|
152
|
+
sg tool save - x x
|
|
153
|
+
sg tool find / list x x x
|
|
154
|
+
sg system create - - x
|
|
155
|
+
sg system edit - - x
|
|
156
|
+
sg system oauth - - x
|
|
157
|
+
sg system call - x x
|
|
158
|
+
sg system search-docs - x x
|
|
159
|
+
sg system find / list x x x
|
|
160
|
+
sg run list x x x
|
|
161
|
+
sg run get x x x
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Setting the Preset
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
# During init (interactive or non-interactive)
|
|
168
|
+
sg init --preset runner --api-key "..." --global
|
|
169
|
+
|
|
170
|
+
# Via environment variable (overrides config.json)
|
|
171
|
+
export SUPERGLUE_CLI_PRESET=builder
|
|
172
|
+
|
|
173
|
+
# Manually edit .superglue/config.json
|
|
174
|
+
{ "preset": "runner", "apiKey": "...", ... }
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Blocked commands print a clear error with the current preset name and how to change it.
|
|
178
|
+
|
|
128
179
|
## Command Reference
|
|
129
180
|
|
|
130
181
|
### `sg init`
|
|
131
182
|
|
|
132
|
-
Interactive setup — API key, endpoint, output mode. Creates `.superglue/`.
|
|
183
|
+
Interactive setup — API key, endpoint, output mode, capability preset. Creates `.superglue/`.
|
|
184
|
+
|
|
185
|
+
Non-interactive: `sg init --api-key "..." --preset runner --global`
|
|
133
186
|
|
|
134
187
|
### Tool Commands
|
|
135
188
|
|
|
@@ -212,17 +265,16 @@ sg system create --name "Slack" --template slack
|
|
|
212
265
|
|
|
213
266
|
**Full flag reference:**
|
|
214
267
|
|
|
215
|
-
| Flag
|
|
216
|
-
|
|
|
217
|
-
| `--name <name>`
|
|
218
|
-
| `--id <id>`
|
|
219
|
-
| `--url <url>`
|
|
220
|
-
| `--template <id>`
|
|
221
|
-
| `--credentials <json>`
|
|
222
|
-
| `--
|
|
223
|
-
| `--
|
|
224
|
-
| `--
|
|
225
|
-
| `--env <environment>` | Environment: `dev` or `prod` (default: prod) |
|
|
268
|
+
| Flag | Description |
|
|
269
|
+
| ---------------------- | ---------------------------------------------------------------------- |
|
|
270
|
+
| `--name <name>` | Human-readable name — **REQUIRED** |
|
|
271
|
+
| `--id <id>` | System ID (lowercase, underscores only) — derived from name if omitted |
|
|
272
|
+
| `--url <url>` | API base URL — **REQUIRED** (auto-filled by `--template`) |
|
|
273
|
+
| `--template <id>` | Template ID (stripe, shopify, slack, etc.) |
|
|
274
|
+
| `--credentials <json>` | Credentials JSON (all fields including secrets) |
|
|
275
|
+
| `--docs-url <url>` | Documentation URL to scrape |
|
|
276
|
+
| `--openapi-url <url>` | OpenAPI spec URL |
|
|
277
|
+
| `--env <environment>` | Environment: `dev` or `prod` (default: prod) |
|
|
226
278
|
|
|
227
279
|
**`sg system edit`** — Update system config or credentials. Supports `--env dev|prod`.
|
|
228
280
|
**`sg system list` / `sg system find`** — List or search systems. `find` supports `--env dev|prod`.
|
|
@@ -367,7 +419,7 @@ Basic auth is auto-encoded: if the value after `Basic ` isn't already base64, th
|
|
|
367
419
|
### Credential Lifecycle
|
|
368
420
|
|
|
369
421
|
- Non-sensitive creds (`client_id`, `auth_url`, etc.) are stored via `--credentials`
|
|
370
|
-
- Sensitive creds (`api_key`, `client_secret`) —
|
|
422
|
+
- Sensitive creds (`api_key`, `client_secret`) — pass via `--credentials` JSON: `--credentials '{"client_secret":"..."}'`
|
|
371
423
|
- OAuth tokens (`access_token`, `refresh_token`) are auto-refreshed before each step execution
|
|
372
424
|
|
|
373
425
|
---
|
|
@@ -549,9 +601,8 @@ All types stop when `stopCondition` returns true, response is empty, or max page
|
|
|
549
601
|
### Credential Model
|
|
550
602
|
|
|
551
603
|
- `credentials` — all credentials passed as JSON via `--credentials`
|
|
552
|
-
-
|
|
553
|
-
-
|
|
554
|
-
- **For human interactive use:** use `--sensitive-credentials` for masked input of secrets
|
|
604
|
+
- **Pass ALL credentials** (including secrets like api_key, client_secret) directly via `--credentials '{"api_key":"..."}'`. Ask the user to provide the secret values, then include them in the JSON.
|
|
605
|
+
- OAuth tokens (`access_token`, `refresh_token`) are auto-refreshed before each step execution
|
|
555
606
|
|
|
556
607
|
### Templates
|
|
557
608
|
|
|
@@ -594,6 +645,165 @@ sg system oauth --system-id gmail --scopes "https://www.googleapis.com/auth/gmai
|
|
|
594
645
|
|
|
595
646
|
---
|
|
596
647
|
|
|
648
|
+
## Tool Building Guide
|
|
649
|
+
|
|
650
|
+
### Build Recipe
|
|
651
|
+
|
|
652
|
+
Before producing a tool config:
|
|
653
|
+
|
|
654
|
+
1. Load relevant skills: data-handling and protocol skill(s) for the involved systems
|
|
655
|
+
2. Use `sg system find` for every involved system — note `storedCredentials` and URL
|
|
656
|
+
3. Use `sg system search-docs` for each system — look up endpoints, auth patterns, pagination, response structure
|
|
657
|
+
4. Use `sg system call` to test 1-2 primary endpoints — verify response structure and field names before building
|
|
658
|
+
5. Only then call `sg tool build --config '...'` with the full tool config
|
|
659
|
+
|
|
660
|
+
### Planning Steps
|
|
661
|
+
|
|
662
|
+
- Fetch prerequisites: available projects, entity types, categories, etc.
|
|
663
|
+
- Each step = one API call, one DB query, one file operation, or a transform step (no compound ops)
|
|
664
|
+
- Final aggregation/filtering/sorting should happen in the `outputTransform`, not in a step
|
|
665
|
+
- Step instructions: 2-3 sentences describing the goal and expected data
|
|
666
|
+
- `instruction`: Write a 1-2 sentence summary of the tool's purpose. Never leave empty.
|
|
667
|
+
|
|
668
|
+
### Step Result Envelopes
|
|
669
|
+
|
|
670
|
+
Every step result is wrapped — you MUST account for this in dataSelectors and outputTransform.
|
|
671
|
+
|
|
672
|
+
- **Object selector (or none)** — access via `sourceData.stepId.data`
|
|
673
|
+
- **Array selector** — access via `sourceData.stepId.map(i => i.data)`
|
|
674
|
+
- **Paginated step** — access via `sourceData.stepId.data` (pages are merged server-side into a single envelope — do NOT `.map()` over it)
|
|
675
|
+
|
|
676
|
+
NEVER access step results without `.data` — `sourceData.stepId.results` will fail because you're hitting the envelope, not the API response.
|
|
677
|
+
|
|
678
|
+
### modify Flag
|
|
679
|
+
|
|
680
|
+
Set `modify: true` only when the step writes, updates, or deletes live data. Don't rely on HTTP method alone — a POST that only reads (e.g., GraphQL query) should be `modify: false`. Default is false.
|
|
681
|
+
|
|
682
|
+
### Validation Rules
|
|
683
|
+
|
|
684
|
+
- Tool must have a valid `id` string
|
|
685
|
+
- Tool must have a `steps` array
|
|
686
|
+
- `systemId` is optional on request steps. Setting it makes that system's credentials available as `<<systemId_credKey>>` template variables, and enables `<<systemId_url>>` for the base URL. Omit for public APIs.
|
|
687
|
+
- Every request step must have a non-empty `url`
|
|
688
|
+
- Transform steps must have `transformCode`
|
|
689
|
+
|
|
690
|
+
### Key Pitfalls
|
|
691
|
+
|
|
692
|
+
- NEVER guess API endpoints — always verify with `sg system search-docs` or `sg system call` first
|
|
693
|
+
- NEVER put `systemId` on the step object — it belongs inside `step.config.systemId`
|
|
694
|
+
- NEVER use `<<(sourceData) => sourceData.payload.X>>` — payload fields are at root level of sourceData
|
|
695
|
+
- NEVER use `<<currentItem.id>>` — use arrow function syntax: `<<(sourceData) => sourceData.currentItem.id>>`
|
|
696
|
+
- NEVER hardcode pagination params — use `<<page>>`, `<<offset>>`, `<<cursor>>`, `<<limit>>`
|
|
697
|
+
- NEVER add an `outputSchema` unless the user explicitly requested a specific response structure
|
|
698
|
+
- NEVER leave instructions empty
|
|
699
|
+
- ALWAYS explicitly configure authentication in every step — credentials are never automatically included in any protocol
|
|
700
|
+
- PREFER system URL variables (`<<systemId_url>>`) over hardcoded base URLs
|
|
701
|
+
- Check `sg system find` output for `storedCredentials` to know the exact variable names available
|
|
702
|
+
- `outputTransform` must be a single-line JS string (no literal newlines or tabs)
|
|
703
|
+
- NEVER use regex literals with `/` or complex escapes in transforms — they corrupt during serialization. Use `new URL()`, `.split()`, or `new RegExp()` instead. See data-handling reference "Serialization Safety".
|
|
704
|
+
- For complex request bodies, use a preceding transform step — don't put multi-statement logic inside `<<>>` expressions
|
|
705
|
+
- When the body contains nested/stringified JSON (e.g. LLM APIs): have `<<>>` expressions return a string via `JSON.stringify(...)`, and use a single expression for the whole body rather than mixing `<<>>` expressions with static JSON
|
|
706
|
+
|
|
707
|
+
### Complex Body Construction
|
|
708
|
+
|
|
709
|
+
When a request body needs data from multiple steps or requires aggregation, use a preceding transform step:
|
|
710
|
+
|
|
711
|
+
```javascript
|
|
712
|
+
// Step: prepareBody (transform)
|
|
713
|
+
transformCode: "(sourceData) => { var items = sourceData.step1.data.results; return { data: items.filter(function(i) { return i.active; }), count: items.length }; }";
|
|
714
|
+
|
|
715
|
+
// Step: submitData (request)
|
|
716
|
+
body: "<<(sourceData) => JSON.stringify(sourceData.prepareBody.data)>>";
|
|
717
|
+
```
|
|
718
|
+
|
|
719
|
+
---
|
|
720
|
+
|
|
721
|
+
## Tool Editing Guide
|
|
722
|
+
|
|
723
|
+
Edit tools using RFC 6902 JSON Patch operations via `sg tool edit`.
|
|
724
|
+
|
|
725
|
+
### Patch Format
|
|
726
|
+
|
|
727
|
+
Each operation:
|
|
728
|
+
|
|
729
|
+
```typescript
|
|
730
|
+
{
|
|
731
|
+
op: "add" | "remove" | "replace" | "move" | "copy" | "test",
|
|
732
|
+
path: string, // JSON Pointer (e.g., "/steps/0/config/url")
|
|
733
|
+
value?: any, // required for add, replace, test
|
|
734
|
+
from?: string // required for move, copy
|
|
735
|
+
}
|
|
736
|
+
```
|
|
737
|
+
|
|
738
|
+
### Key Paths
|
|
739
|
+
|
|
740
|
+
- `/instruction` — tool description
|
|
741
|
+
- `/steps/N` — step at index N
|
|
742
|
+
- `/steps/N/config/url`, `/steps/N/config/method`, `/steps/N/config/headers`, etc.
|
|
743
|
+
- `/steps/N/dataSelector` — JS function controlling input + loop mode
|
|
744
|
+
- `/outputTransform` — final output shaping function
|
|
745
|
+
- `/outputSchema` — optional JSON schema for output
|
|
746
|
+
|
|
747
|
+
### Operations
|
|
748
|
+
|
|
749
|
+
- **`replace`** — Change an existing value. **Path must exist** — if the field is `null` or absent, `replace` fails. Use `add` instead for optional fields.
|
|
750
|
+
- **`add`** — Creates the field if missing, overwrites if it exists. **Prefer `add` over `replace`** when the field might be null or absent. Append to array with `/steps/-`.
|
|
751
|
+
- **`remove`** — Delete field or array element.
|
|
752
|
+
- **`move`** — Reorder or relocate.
|
|
753
|
+
|
|
754
|
+
### Validation Rules
|
|
755
|
+
|
|
756
|
+
- Never patch `id` — tool IDs and draft IDs are immutable when editing
|
|
757
|
+
- `op` and `path` are required on every patch; `path` must start with `/`
|
|
758
|
+
- Patches are applied **sequentially** — later patches see effects of earlier ones
|
|
759
|
+
- After patches, same validation rules as building apply (valid id, steps array, URLs present)
|
|
760
|
+
|
|
761
|
+
### Principles
|
|
762
|
+
|
|
763
|
+
- **Check result wrapping** — before writing any dataSelector or outputTransform patch, determine whether the upstream step used an object or array selector, and access `.data` accordingly
|
|
764
|
+
- **Don't forget downstream** — if you change a step's output shape, check if later dataSelectors and outputTransform need updating
|
|
765
|
+
- **Index shifts** — when removing array elements, subsequent indices shift down. Account for this in multi-patch operations.
|
|
766
|
+
|
|
767
|
+
---
|
|
768
|
+
|
|
769
|
+
## Systems Handling Guide
|
|
770
|
+
|
|
771
|
+
Systems are reusable building blocks that store configuration details and credentials.
|
|
772
|
+
|
|
773
|
+
### Credential Use in Tool Configurations
|
|
774
|
+
|
|
775
|
+
For every `systemId` referenced in a tool, credentials are namespaced as `<<systemId_credentialKey>>` and must be explicitly placed in the step config. For HTTP: in headers. For databases/Redis/file servers: in the connection URL. Nothing is injected automatically.
|
|
776
|
+
|
|
777
|
+
```
|
|
778
|
+
System id="stripe", storedCredentials: api_key → "sk_proj****"
|
|
779
|
+
→ Available as: <<stripe_api_key>>
|
|
780
|
+
```
|
|
781
|
+
|
|
782
|
+
OAuth tokens (`access_token`, `refresh_token`) are auto-refreshed before each step execution. Access tokens must also be explicitly referenced in step headers.
|
|
783
|
+
|
|
784
|
+
### System URL Variables
|
|
785
|
+
|
|
786
|
+
System URLs are available as `<<systemId_url>>` and should be used instead of hardcoding base URLs:
|
|
787
|
+
|
|
788
|
+
```
|
|
789
|
+
System id="salesforce", url="https://mycompany.salesforce.com"
|
|
790
|
+
→ Available as: <<salesforce_url>>
|
|
791
|
+
|
|
792
|
+
Step config: { "url": "<<salesforce_url>>/services/data/v58.0/sobjects/Account" }
|
|
793
|
+
```
|
|
794
|
+
|
|
795
|
+
### Dev/Prod Environments
|
|
796
|
+
|
|
797
|
+
`environment` is `"dev"` or `"prod"` (or unset for legacy systems). Set at creation only — immutable afterward. Two systems with the same ID but different environments are automatically linked. Dev systems inherit documentation from their linked prod system. When creating a dev system, always ask for new credentials — never copy from prod.
|
|
798
|
+
|
|
799
|
+
Tools reference systems by ID only. Execution mode determines which environment is used (dev mode falls back to prod if no dev system exists).
|
|
800
|
+
|
|
801
|
+
### System-Specific Instructions
|
|
802
|
+
|
|
803
|
+
Systems may include `specificInstructions` from the user (visible in `sg system find` output). Follow them when present. These capture API constraints, rate limits, special endpoints, auth requirements, or usage patterns.
|
|
804
|
+
|
|
805
|
+
---
|
|
806
|
+
|
|
597
807
|
## Debugging Failed Tools
|
|
598
808
|
|
|
599
809
|
### Debug Workflow
|
|
@@ -653,13 +863,16 @@ with client as c:
|
|
|
653
863
|
|
|
654
864
|
For detailed documentation on specific topics, read these files in the `references/` directory:
|
|
655
865
|
|
|
656
|
-
| File
|
|
657
|
-
|
|
|
658
|
-
| `references/integration.md`
|
|
659
|
-
| `references/databases.md`
|
|
660
|
-
| `references/redis.md`
|
|
661
|
-
| `references/file-servers.md`
|
|
662
|
-
| `references/
|
|
866
|
+
| File | When to read |
|
|
867
|
+
| ----------------------------- | ------------------------------------------------------------------------------------------------ |
|
|
868
|
+
| `references/integration.md` | **READ THIS** when deploying tools to production - SDK usage, REST API, webhooks, error handling |
|
|
869
|
+
| `references/databases.md` | Building tools that query PostgreSQL or Microsoft SQL Server (Azure SQL) databases |
|
|
870
|
+
| `references/redis.md` | Building tools that interact with Redis (commands, pipelines, data types) |
|
|
871
|
+
| `references/file-servers.md` | Building tools that interact with FTP/SFTP/SMB file servers |
|
|
872
|
+
| `references/data-handling.md` | Variables, selectors, result envelopes, transforms, JS sandbox constraints |
|
|
873
|
+
| `references/file-handling.md` | File detection, parsing, producedFiles, file references, aliasing rules |
|
|
874
|
+
| `references/http-apis.md` | HTTP step config — auth patterns, pagination, retries, error detection |
|
|
875
|
+
| `references/access-rules.md` | RBAC roles, tool/system permissions, custom rules, mutation detection (enterprise only) |
|
|
663
876
|
|
|
664
877
|
**Important:** When the user asks about integrating superglue into their codebase, deploying tools, using the SDK, or calling tools from code, you MUST read `references/integration.md` for complete examples.
|
|
665
878
|
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# Access Rules (RBAC)
|
|
2
|
+
|
|
3
|
+
On superglue, roles define tool-level and system-level allowlists. Users can have multiple roles. Roles and access rules are only available on enterprise organizations. Non-enterprise orgs do not have RBAC — all users have admin access on personal organizations.
|
|
4
|
+
|
|
5
|
+
## Data Model
|
|
6
|
+
|
|
7
|
+
### Role
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
interface Role {
|
|
11
|
+
id: string;
|
|
12
|
+
name: string;
|
|
13
|
+
description?: string;
|
|
14
|
+
tools: "ALL" | string[]; // tool allowlist
|
|
15
|
+
systems: "ALL" | Record<string, SystemPermission>; // system allowlist
|
|
16
|
+
isBaseRole?: boolean; // true for admin, member, enduser
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### SystemPermission
|
|
21
|
+
|
|
22
|
+
Each system entry is either a predefined access level or a custom rule:
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
type SystemPermission = SystemAccessLevel | { rules: CustomRule[] };
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
| Type | Meaning |
|
|
29
|
+
| ------------------ | ------------------------------------------------ |
|
|
30
|
+
| `"read-write"` | All HTTP methods allowed |
|
|
31
|
+
| `"read-only"` | Only GET and HEAD; POST/PUT/PATCH/DELETE blocked |
|
|
32
|
+
| `{ rules: [...] }` | Custom JS expressions that gate access |
|
|
33
|
+
|
|
34
|
+
Systems not listed in the role's `systems` map are DENIED, unless the system access is set to `"ALL"`.
|
|
35
|
+
|
|
36
|
+
### CustomRule
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
interface CustomRule {
|
|
40
|
+
id: string;
|
|
41
|
+
name: string;
|
|
42
|
+
expression?: string; // JS expression, receives stepConfig
|
|
43
|
+
isActive: boolean;
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Custom rules are inline in the systems map. A system either has a standard access level OR a custom rule, never both. Custom rules must return truthy to **allow** the request. If it returns falsy, throws, or has no expression, the request is blocked (fail-closed).
|
|
48
|
+
|
|
49
|
+
## Tool Permissions
|
|
50
|
+
|
|
51
|
+
- `tools: "ALL"` — every tool is allowed, including tools created in the future
|
|
52
|
+
- `tools: ["tool-id-1", "tool-id-2"]` — only these specific tools are allowed; new tools are NOT auto-included (but see Auto-Append below)
|
|
53
|
+
|
|
54
|
+
## System Permissions
|
|
55
|
+
|
|
56
|
+
- `systems: "ALL"` — every system allowed at READ_WRITE level, including future systems. Custom rules are not possible in this mode.
|
|
57
|
+
- `systems: { "gmail": "read-write", "stripe": "read-only" }` — SPECIFIC mode: per-system access levels; unlisted systems are denied.
|
|
58
|
+
- `systems: { "gmail": { rules: [{ name: "block-deletes", expression: "stepConfig.method !== 'DELETE'", isActive: true }] } }` — custom rule on a specific system
|
|
59
|
+
|
|
60
|
+
## Mutation Detection by Protocol
|
|
61
|
+
|
|
62
|
+
Read-only mode blocks mutating requests. How "mutating" is determined per protocol:
|
|
63
|
+
|
|
64
|
+
- **HTTP** — POST, PUT, PATCH, DELETE are mutating; GET and HEAD are read-only
|
|
65
|
+
- **Postgres** — SQL statements starting with or containing INSERT, UPDATE, DELETE, DROP, ALTER, CREATE, TRUNCATE, etc. are mutating; everything else (SELECT) is read-only
|
|
66
|
+
- **FTP / SMB** — operations other than `list`, `get`, `exists`, `stat` are mutating
|
|
67
|
+
- **Redis** — commands not in the read-only set (GET, MGET, EXISTS, KEYS, SCAN, TTL, TYPE, HGET, HGETALL, LRANGE, SMEMBERS, SCARD, etc.) are mutating
|
|
68
|
+
- **Transform** — never mutating (pure data transformation, no external system)
|
|
69
|
+
|
|
70
|
+
On parse failure, all protocols default to **mutating** (fail-closed).
|
|
71
|
+
|
|
72
|
+
## Custom Rule Expressions
|
|
73
|
+
|
|
74
|
+
Custom rules only apply in SPECIFIC mode. If systems is `"ALL"`, no custom rules exist.
|
|
75
|
+
|
|
76
|
+
Expressions receive a **resolved** `stepConfig` object — all template variables (`<<variable>>` and `<<(sourceData) => ...>>` expressions) are substituted with their actual runtime values before the rule evaluates. This means rules see the real URL, headers, body, and query params, not raw templates.
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
interface StepConfig {
|
|
80
|
+
url: string;
|
|
81
|
+
method: string;
|
|
82
|
+
headers: Record<string, string>;
|
|
83
|
+
queryParams: Record<string, string>;
|
|
84
|
+
body: unknown;
|
|
85
|
+
systemId: string;
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Example expressions:
|
|
90
|
+
|
|
91
|
+
```javascript
|
|
92
|
+
// Block all POST requests to a specific endpoint
|
|
93
|
+
stepConfig.method !== "POST" || !stepConfig.url.includes("/admin");
|
|
94
|
+
|
|
95
|
+
// Only allow GET requests to /api/v1/read endpoints
|
|
96
|
+
stepConfig.method === "GET" && stepConfig.url.includes("/api/v1/read");
|
|
97
|
+
|
|
98
|
+
// Block requests with certain headers
|
|
99
|
+
!stepConfig.headers["x-dangerous-header"];
|
|
100
|
+
|
|
101
|
+
// Block a specific datasource ID in the resolved body
|
|
102
|
+
!(typeof stepConfig.body === "object" && stepConfig.body?.datasource?.id === "blocked-id");
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Multi-Role Semantics
|
|
106
|
+
|
|
107
|
+
Users can have multiple roles. Resolution is **union (most permissive wins) everywhere**:
|
|
108
|
+
|
|
109
|
+
| Layer | Semantics | Example |
|
|
110
|
+
| ------------ | ------------------------------ | --------------------------------------------------------------------------- |
|
|
111
|
+
| Tools | Union (most permissive wins) | If role A allows tool X and role B doesn't, tool X is allowed |
|
|
112
|
+
| Systems | Union (most permissive wins) | If role A gives READ_ONLY and role B gives READ_WRITE, result is READ_WRITE |
|
|
113
|
+
| Custom rules | Per-role union (any role wins) | If any role's complete rule set allows the request, it goes through |
|
|
114
|
+
|
|
115
|
+
Custom rule detail:
|
|
116
|
+
|
|
117
|
+
- **Within a single role**, all custom rules for that system must pass (AND logic)
|
|
118
|
+
- **Across roles**, evaluation is per-role: if any role fully allows the request (all its rules pass, or it has no custom rule for that system), the request is allowed (OR logic)
|
|
119
|
+
|
|
120
|
+
## Base Roles
|
|
121
|
+
|
|
122
|
+
Every user has exactly **one** base role. There are three:
|
|
123
|
+
|
|
124
|
+
- **`admin`** — Full access to everything. Bypasses all RBAC checks. The admin role is **immutable** — it cannot be edited at all, nor can it be re-assigned.
|
|
125
|
+
- **`member`** — Default for org team members. Starts with `tools: "ALL"`, `systems: "ALL"`. Tool and system allowlists can be narrowed to restrict access. Name and description cannot be changed. Cannot be deleted.
|
|
126
|
+
- **`enduser`** — Default for end users / portal consumers. Starts with `tools: []`, `systems: {}` (no access). Tool and system allowlists must be explicitly populated to grant access. Name and description cannot be changed. Cannot be deleted.
|
|
127
|
+
|
|
128
|
+
Base roles define the starting permissions that custom roles can extend or build on top of. Users can also have additional **custom roles** on top of their base role. Custom roles are fully editable (name, description, tools, systems) and can be created and deleted.
|
|
129
|
+
|
|
130
|
+
### Auto-append on resource creation
|
|
131
|
+
|
|
132
|
+
When a user creates a new tool or system, the backend automatically adds it to the **creator's base role** — but only if that base role uses SPECIFIC mode (not `"ALL"`) for the relevant field:
|
|
133
|
+
|
|
134
|
+
- New tool created → appended to the creator's base role's `tools` list (skipped if `tools: "ALL"`)
|
|
135
|
+
- New system created → appended to the creator's base role's `systems` map with `read-write` access (skipped if `systems: "ALL"`)
|
|
136
|
+
|
|
137
|
+
This only affects the base role, not additional custom roles. It ensures that a user on a restricted allowlist automatically gets access to resources they create.
|