Skip to content

Commit ada0334

Browse files
committed
integration projections
1 parent 27efa0f commit ada0334

383 files changed

Lines changed: 20819 additions & 2585 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.agents/skills/add-integration/SKILL.md

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
name: add-integration
3-
description: Add a complete Sim integration from API docs, covering tools, block, icon, optional triggers, registrations, and integration conventions. Use when introducing a new service under `apps/sim/tools`, `apps/sim/blocks`, and `apps/sim/triggers`.
3+
description: Add a complete Sim integration from API docs, covering tools, block, icon, optional triggers, registrations, resolved-secret/model-input safety, and integration conventions. Use when introducing a new service under `apps/sim/tools`, `apps/sim/blocks`, and `apps/sim/triggers`.
44
argument-hint: <service-name> [api-docs-url]
55
---
66

@@ -122,6 +122,63 @@ export const {service}{Action}Tool: ToolConfig<Params, Response> = {
122122
- When using `type: 'json'` and you know the object shape, define `properties` with the inner fields so downstream consumers know the structure. Only use bare `type: 'json'` when the shape is truly dynamic
123123
- If you do not know the response JSON shape from docs or verified examples, you MUST tell the user and stop. Never guess outputs or response mappings.
124124

125+
### Resolved Secrets at Model and Persistence Boundaries
126+
127+
Classify every request field before implementing the tool:
128+
129+
This is opt-in, not a blanket integration migration. Add a model-input declaration only when the
130+
service's official documentation or an unambiguous local execution path proves that the exact
131+
field is consumed by an AI model. If that cannot be established, preserve existing tool behavior
132+
and leave the field unannotated.
133+
134+
- **Ordinary provider/API input:** leave it unchanged. Do not add blanket result sanitization.
135+
- **Text or structured content consumed by an AI model:** declare `request.modelInput` with
136+
`mode: 'project'` and select only the exact model-visible fields. The shared executor replaces
137+
activated Sim secrets with canonical `{{NAME}}` labels before request formatting. For nested or
138+
JSON-string fields, use a small shared selector plus `applyProjected`; verify that selecting the
139+
rebuilt params reproduces the projected selection.
140+
- **Opaque model input sent directly to an external provider** such as a model-read URL or image
141+
payload: declare `request.opaqueModelInput` with `mode: 'reject-resolved-secrets'` and select only
142+
the exact effective value. The shared `executeTool` preflight rejects incomplete or secret-bearing
143+
committed provenance before URL/body formatting or network I/O, preserves safe request bytes,
144+
and sends no provenance metadata to the provider.
145+
- **Opaque model input owned by an authenticated internal route** such as uploaded audio, image,
146+
video, file bytes, or signed URLs: add `privateProvenance` to a projected request, or use
147+
`mode: 'private-provenance'` when there is no textual projection. The route must call
148+
`validateOpaqueModelInputProvenance` before downloading or sending content to the model and must
149+
apply the workspace-file provenance guard before reading a persisted workspace file.
150+
- **Sim-owned durable storage** that can later re-enter a workflow/model (table cells, Agent
151+
memory, knowledge documents/chunks, and workspace-file contents): transport encrypted
152+
field-scoped provenance with
153+
`request.secretProvenance`, persist it through the shared sidecar service, and load/import it at
154+
every re-entry boundary. Preserve shared legacy behavior for rows/files whose provenance marker
155+
is `NULL`; never invent a tool-local migration rule.
156+
157+
Hard rules:
158+
159+
- Never substitute secret plaintext into source or serialize plaintext provenance.
160+
- Never hand-roll private provenance headers/envelopes; the shared `executeTool` boundary owns
161+
transport and strips private metadata from functional results.
162+
- Never attach private provenance to an external URL or to `directExecution`. Use the centralized
163+
`opaqueModelInput` rejection mode for external/direct opaque model inputs, or an authenticated
164+
internal route when encrypted provenance must cross the boundary.
165+
- Never sanitize arbitrary third-party tool results. Projection applies only to secrets activated
166+
by Sim's resolved-secret provenance for that execution/tool call.
167+
- Do not add provenance merely because a value is persisted, returned by a tool, or appears in a
168+
filename. Require a concrete Sim `{{...}}` resolution path and a later model/log boundary. If an
169+
unsupported field can resolve a secret but does not justify durable tracking (for example a
170+
`file_write` path), reject it at that exact ingress.
171+
- At diagnostic boundaries, project only values carrying execution-scoped provenance. Ordinary
172+
provider responses, filenames, URLs, and errors remain unchanged when Sim did not resolve a
173+
secret into them.
174+
175+
Add focused tests covering named projection, ordinary identical text without provenance, nested
176+
shape preservation, malformed/incomplete private metadata failing closed, centralized external
177+
opaque rejection before formatting/I/O without byte changes or metadata transport, headerless
178+
legacy requests, and absence of private metadata in the public tool result. For durable sinks, also
179+
cover legacy `NULL` markers, exact-empty new writes, tracked secret writes, stale/missing sidecars,
180+
and scope isolation.
181+
125182
## Step 3: Create Block
126183

127184
### File Location
@@ -535,6 +592,11 @@ If creating V2 versions (API-aligned outputs):
535592
- [ ] Created `index.ts` barrel export
536593
- [ ] Registered all tools in `tools/registry.ts`
537594
- [ ] Ran `bun run tool-metadata:generate` and committed the regenerated artifacts
595+
- [ ] Classified every model-visible, opaque, and Sim-durable request field
596+
- [ ] Added shared model-input projection, centralized opaque rejection, or private provenance only
597+
where required
598+
- [ ] Confirmed ordinary third-party tool results are not generically sanitized
599+
- [ ] Added provenance compatibility and fail-closed boundary tests where applicable
538600

539601
### Block
540602
- [ ] Created `blocks/blocks/{service}.ts`

.agents/skills/validate-integration/SKILL.md

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
name: validate-integration
3-
description: Validate an existing Sim integration (tools, block, registry) against the service's API docs
3+
description: Validate an existing Sim integration (tools, block, registry, and resolved-secret/model-input boundaries) against the service's API docs and Sim execution conventions
44
argument-hint: <service-name> [api-docs-url]
55
---
66

@@ -129,6 +129,51 @@ For **every** tool file, check:
129129
- [ ] Registry keys use snake_case and match tool IDs exactly
130130
- [ ] Entries are in alphabetical order within the file
131131

132+
### Resolved-Secret Provenance and Model Input
133+
134+
For every request field, determine whether it is ordinary API input, model-visible text/structured
135+
content, opaque model input, or a value persisted into Sim-owned durable storage.
136+
137+
Treat model-input provenance as opt-in. Require official documentation or an unambiguous local
138+
execution path proving that the exact field reaches an AI model. If the evidence is ambiguous,
139+
leave the integration unchanged; do not infer a model boundary merely from natural-language,
140+
search, extraction, or "AI-powered" marketing terminology.
141+
142+
- [ ] AI-consumed text/structured fields use `request.modelInput` with `mode: 'project'` and a
143+
minimal exact selector; nested/JSON-string adapters preserve shape through `applyProjected`
144+
- [ ] Opaque AI-consumed values sent directly to an external provider or `directExecution` use
145+
`request.opaqueModelInput` with `mode: 'reject-resolved-secrets'` and an exact effective-value
146+
selector; the central executor rejects incomplete/secret-bearing committed provenance before
147+
formatting or I/O, leaves safe bytes unchanged, and sends no provenance metadata externally
148+
- [ ] Opaque AI-consumed files/bytes/URLs owned by an authenticated internal route use
149+
`privateProvenance` (or `mode: 'private-provenance'`), and the route validates
150+
`validateOpaqueModelInputProvenance` before any download or model call
151+
- [ ] Persisted workspace-file contents are checked with the shared provenance guard only when
152+
their bytes or decoded content cross into a model/tool-result boundary; ordinary file APIs
153+
remain unchanged. Unsupported secret-bearing file paths are rejected at `file_write`
154+
- [ ] Sim-owned durable writes that can re-enter workflows/models use field-scoped
155+
`request.secretProvenance` and the shared sidecar/load/import services
156+
- [ ] Private provenance is never attached to external URLs or `directExecution`; those paths use
157+
centralized `opaqueModelInput` rejection when their opaque values are model-bound
158+
- [ ] No tool performs raw secret plaintext/source substitution or serializes plaintext provenance
159+
- [ ] No `transformResponse` or tool-local helper blanket-sanitizes ordinary third-party results;
160+
only execution-scoped, activated Sim provenance is projected at shared model/log boundaries
161+
- [ ] Private headers/envelopes are produced and stripped by the shared tool executor, never
162+
hand-rolled or returned as functional output
163+
- [ ] Every added provenance hook has a concrete Sim `{{...}}` resolution path and a later
164+
persistence/model/log crossing; there is no generic handling for arbitrary filenames,
165+
metadata, provider results, or API payloads
166+
- [ ] Diagnostic projection is applied only to values carrying execution-scoped provenance;
167+
ordinary provider responses, filenames, URLs, and errors are unchanged
168+
- [ ] Tests cover named `{{NAME}}` projection, unproven identical public text, nested shape
169+
preservation, malformed/incomplete metadata, centralized opaque rejection before formatting
170+
or I/O with safe-byte preservation, headerless legacy requests, metadata stripping, and
171+
durable legacy/stale/scope cases when applicable
172+
173+
Treat a missing or bypassed model/durable provenance boundary as **critical**. Do not fix it with a
174+
tool-specific string replacer or by sanitizing every provider result; repair the shared request,
175+
authenticated internal-route, persistence, or re-entry boundary that owns the data.
176+
132177
## Step 4: Validate Block
133178

134179
### Block ↔ Tool Alignment (CRITICAL)
@@ -301,6 +346,12 @@ Group findings by severity:
301346
- Service-account metadata disagrees with the canonical OAuth service configuration
302347
- `tools.config.tool` returning wrong tool ID for an operation
303348
- Type coercions in `tools.config.tool` instead of `tools.config.params`
349+
- AI-consumed request fields bypass the shared projection, centralized opaque rejection, or
350+
private-provenance boundary
351+
- Opaque model input is downloaded or sent before provenance and workspace-file checks
352+
- A Sim-owned durable sink/re-entry path drops encrypted provenance or breaks legacy `NULL` data
353+
- A tool substitutes secret plaintext into source, leaks private metadata, or generically sanitizes
354+
unrelated third-party results
304355

305356
**Warning** (follows conventions incorrectly or has usability issues):
306357
- Optional field not set to `mode: 'advanced'`
@@ -375,6 +426,9 @@ After fixing, confirm:
375426
- [ ] Validated memory load safety using `.agents/skills/memory-load-check/SKILL.md` when tools list/search/download/import/export/batch data
376427
- [ ] Validated error handling (error checks, meaningful messages)
377428
- [ ] Validated registry entries (tools and block, alphabetical, correct imports)
429+
- [ ] Validated model-visible/opaque inputs and Sim-durable provenance at their owning boundaries
430+
- [ ] Confirmed legacy persisted data keeps working and tracked invalid provenance fails closed
431+
- [ ] Confirmed ordinary third-party results remain unchanged absent activated Sim provenance
378432
- [ ] Validated `{Service}BlockMeta` exported with at least 7 templates
379433
- [ ] Reported all issues grouped by severity
380434
- [ ] Fixed all critical and warning issues

.claude/commands/add-integration.md

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
description: Add a complete Sim integration from API docs, covering tools, block, icon, optional triggers, registrations, and integration conventions. Use when introducing a new service under `apps/sim/tools`, `apps/sim/blocks`, and `apps/sim/triggers`.
2+
description: Add a complete Sim integration from API docs, covering tools, block, icon, optional triggers, registrations, resolved-secret/model-input safety, and integration conventions. Use when introducing a new service under `apps/sim/tools`, `apps/sim/blocks`, and `apps/sim/triggers`.
33
argument-hint: <service-name> [api-docs-url]
44
---
55

@@ -121,6 +121,63 @@ export const {service}{Action}Tool: ToolConfig<Params, Response> = {
121121
- When using `type: 'json'` and you know the object shape, define `properties` with the inner fields so downstream consumers know the structure. Only use bare `type: 'json'` when the shape is truly dynamic
122122
- If you do not know the response JSON shape from docs or verified examples, you MUST tell the user and stop. Never guess outputs or response mappings.
123123

124+
### Resolved Secrets at Model and Persistence Boundaries
125+
126+
Classify every request field before implementing the tool:
127+
128+
This is opt-in, not a blanket integration migration. Add a model-input declaration only when the
129+
service's official documentation or an unambiguous local execution path proves that the exact
130+
field is consumed by an AI model. If that cannot be established, preserve existing tool behavior
131+
and leave the field unannotated.
132+
133+
- **Ordinary provider/API input:** leave it unchanged. Do not add blanket result sanitization.
134+
- **Text or structured content consumed by an AI model:** declare `request.modelInput` with
135+
`mode: 'project'` and select only the exact model-visible fields. The shared executor replaces
136+
activated Sim secrets with canonical `{{NAME}}` labels before request formatting. For nested or
137+
JSON-string fields, use a small shared selector plus `applyProjected`; verify that selecting the
138+
rebuilt params reproduces the projected selection.
139+
- **Opaque model input sent directly to an external provider** such as a model-read URL or image
140+
payload: declare `request.opaqueModelInput` with `mode: 'reject-resolved-secrets'` and select only
141+
the exact effective value. The shared `executeTool` preflight rejects incomplete or secret-bearing
142+
committed provenance before URL/body formatting or network I/O, preserves safe request bytes,
143+
and sends no provenance metadata to the provider.
144+
- **Opaque model input owned by an authenticated internal route** such as uploaded audio, image,
145+
video, file bytes, or signed URLs: add `privateProvenance` to a projected request, or use
146+
`mode: 'private-provenance'` when there is no textual projection. The route must call
147+
`validateOpaqueModelInputProvenance` before downloading or sending content to the model and must
148+
apply the workspace-file provenance guard before reading a persisted workspace file.
149+
- **Sim-owned durable storage** that can later re-enter a workflow/model (table cells, Agent
150+
memory, knowledge documents/chunks, and workspace-file contents): transport encrypted
151+
field-scoped provenance with
152+
`request.secretProvenance`, persist it through the shared sidecar service, and load/import it at
153+
every re-entry boundary. Preserve shared legacy behavior for rows/files whose provenance marker
154+
is `NULL`; never invent a tool-local migration rule.
155+
156+
Hard rules:
157+
158+
- Never substitute secret plaintext into source or serialize plaintext provenance.
159+
- Never hand-roll private provenance headers/envelopes; the shared `executeTool` boundary owns
160+
transport and strips private metadata from functional results.
161+
- Never attach private provenance to an external URL or to `directExecution`. Use the centralized
162+
`opaqueModelInput` rejection mode for external/direct opaque model inputs, or an authenticated
163+
internal route when encrypted provenance must cross the boundary.
164+
- Never sanitize arbitrary third-party tool results. Projection applies only to secrets activated
165+
by Sim's resolved-secret provenance for that execution/tool call.
166+
- Do not add provenance merely because a value is persisted, returned by a tool, or appears in a
167+
filename. Require a concrete Sim `{{...}}` resolution path and a later model/log boundary. If an
168+
unsupported field can resolve a secret but does not justify durable tracking (for example a
169+
`file_write` path), reject it at that exact ingress.
170+
- At diagnostic boundaries, project only values carrying execution-scoped provenance. Ordinary
171+
provider responses, filenames, URLs, and errors remain unchanged when Sim did not resolve a
172+
secret into them.
173+
174+
Add focused tests covering named projection, ordinary identical text without provenance, nested
175+
shape preservation, malformed/incomplete private metadata failing closed, centralized external
176+
opaque rejection before formatting/I/O without byte changes or metadata transport, headerless
177+
legacy requests, and absence of private metadata in the public tool result. For durable sinks, also
178+
cover legacy `NULL` markers, exact-empty new writes, tracked secret writes, stale/missing sidecars,
179+
and scope isolation.
180+
124181
## Step 3: Create Block
125182

126183
### File Location
@@ -534,6 +591,11 @@ If creating V2 versions (API-aligned outputs):
534591
- [ ] Created `index.ts` barrel export
535592
- [ ] Registered all tools in `tools/registry.ts`
536593
- [ ] Ran `bun run tool-metadata:generate` and committed the regenerated artifacts
594+
- [ ] Classified every model-visible, opaque, and Sim-durable request field
595+
- [ ] Added shared model-input projection, centralized opaque rejection, or private provenance only
596+
where required
597+
- [ ] Confirmed ordinary third-party tool results are not generically sanitized
598+
- [ ] Added provenance compatibility and fail-closed boundary tests where applicable
537599

538600
### Block
539601
- [ ] Created `blocks/blocks/{service}.ts`

0 commit comments

Comments
 (0)