Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 23 additions & 20 deletions .agents/skills/add-integration/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,20 +131,24 @@ service's official documentation or an unambiguous local execution path proves t
field is consumed by an AI model. If that cannot be established, preserve existing tool behavior
and leave the field unannotated.

- **Ordinary provider/API input:** leave it unchanged. Do not add blanket result sanitization.
- **Ordinary provider/API input:** leave it unchanged. Explicit `{{...}}` references resolve and are
sent with their normal request semantics. A URL, domain, resource ID, control field, or opaque
payload is not model-visible merely because the provider is AI-backed or may process the
referenced resource later.
- **Text or structured content consumed by an AI model:** declare `request.modelInput` with
`mode: 'project'` and select only the exact model-visible fields. The shared executor replaces
activated Sim secrets with canonical `{{NAME}}` labels before request formatting. For nested or
JSON-string fields, use a small shared selector plus `applyProjected`; verify that selecting the
rebuilt params reproduces the projected selection.
- **Opaque model input sent directly to an external provider** such as a model-read URL or image
payload: declare `request.opaqueModelInput` with `mode: 'reject-resolved-secrets'` and select only
the exact effective value. The shared `executeTool` preflight rejects incomplete or secret-bearing
committed provenance before URL/body formatting or network I/O, preserves safe request bytes,
and sends no provenance metadata to the provider.
- **Opaque model input owned by an authenticated internal route** such as uploaded audio, image,
video, file bytes, or signed URLs: add `privateProvenance` to a projected request, or use
`mode: 'private-provenance'` when there is no textual projection. The route must call
- **Serialized model content sent directly to an external provider:** include the serialized
top-level param in `request.modelInput`. Project the private copy before the existing request
formatter parses it; keep formatter behavior deterministic when a whole-value placeholder is not
valid in the serialized grammar. Do not introduce a second hard-rejection path.
- **Opaque model input owned by an authenticated internal route** such as inline audio, image,
video, or document bytes: add `privateProvenance` to a projected request, or use
`mode: 'private-provenance'` when there is no textual projection. Do not select storage keys,
paths, signed URLs, or ordinary remote URLs as byte provenance; the owning route must authorize
stored bytes independently at model egress. The route must call
`validateOpaqueModelInputProvenance` before downloading or sending content to the model and must
apply the workspace-file provenance guard before reading a persisted workspace file.
- **Sim-owned durable storage or internal execution handoff** that can later enter a workflow/model
Expand All @@ -160,9 +164,9 @@ Hard rules:
- Never substitute secret plaintext into source or serialize plaintext provenance.
- Never hand-roll private provenance headers/envelopes; the shared `executeTool` boundary owns
transport and strips private metadata from functional results.
- Never attach private provenance to an external URL or to `directExecution`. Use the centralized
`opaqueModelInput` rejection mode for external/direct opaque model inputs, or an authenticated
internal route when encrypted provenance must cross the boundary.
- Never attach private provenance to an external URL or to `directExecution`. Project proven
model-visible external fields with `request.modelInput`; otherwise preserve ordinary request
semantics. Use an authenticated internal route when encrypted provenance must cross the boundary.
- Never sanitize arbitrary third-party tool results. Projection applies only to secrets activated
by Sim's resolved-secret provenance for that execution/tool call.
- Do not add provenance merely because a value is persisted, returned by a tool, or appears in a
Expand All @@ -173,12 +177,11 @@ Hard rules:
provider responses, filenames, URLs, and errors remain unchanged when Sim did not resolve a
secret into them.

Add focused tests covering named projection, ordinary identical text without provenance, nested
shape preservation, malformed/incomplete private metadata failing closed, centralized external
opaque rejection before formatting/I/O without byte changes or metadata transport, headerless
legacy requests, and absence of private metadata in the public tool result. For durable sinks, also
cover legacy `NULL` markers, exact-empty new writes, tracked secret writes, stale/missing sidecars,
and scope isolation.
Add focused tests covering named projection, ordinary identical text without provenance, nested and
serialized shape handling, unchanged ordinary external inputs, malformed/incomplete private metadata
failing closed, headerless legacy requests, and absence of private metadata in the public tool result.
For durable sinks, also cover legacy `NULL` markers, exact-empty new writes, tracked secret writes,
stale/missing sidecars, and scope isolation.

## Step 3: Create Block

Expand Down Expand Up @@ -594,8 +597,8 @@ If creating V2 versions (API-aligned outputs):
- [ ] Registered all tools in `tools/registry.ts`
- [ ] Ran `bun run tool-metadata:generate` and committed the regenerated artifacts
- [ ] Classified every model-visible, opaque, Sim-durable, and internal-execution request field
- [ ] Added shared model-input projection, centralized opaque rejection, or private provenance only
where required
- [ ] Added shared model-input projection or private provenance only where required; ordinary
external resource locators and control inputs retain their request semantics
- [ ] Confirmed ordinary third-party tool results are not generically sanitized
- [ ] Added provenance compatibility and fail-closed boundary tests where applicable

Expand Down
16 changes: 10 additions & 6 deletions .agents/skills/add-tools/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,16 @@ export const {serviceName}{Action}Tool: ToolConfig<
- Leave ordinary external API inputs and third-party results unchanged. Add provenance handling only
when an exact field is proven to cross a Sim model, durable-storage, or internal-execution boundary.
- Project AI-consumed text/structured fields with the smallest exact `request.modelInput` selector.
- Reject resolved secrets in opaque model input sent directly to an external provider with
`request.opaqueModelInput`; never attach private metadata to an external URL or `directExecution`.
- For authenticated internal routes, use `privateProvenance` for opaque model input or
`request.secretProvenance` for durable writes and execution handoffs. Authenticate first, validate
the exact selection and scope, strip the private envelope, then import or propagate provenance at
the receiving boundary. Preserve documented headerless legacy behavior.
- Treat URLs, domains, resource IDs, and control fields as ordinary request values unless the exact
field is proven model-visible. For serialized external model content, project the serialized
top-level param through `request.modelInput` before the existing formatter parses it; do not add a
separate hard-rejection mechanism.
- For authenticated internal routes, use `privateProvenance` for actual inline/raw model bytes or
`request.secretProvenance` for durable writes and execution handoffs. Do not treat a storage key,
path, signed URL, or remote URL as provenance for fetched bytes; authorize tracked stored bytes at
the owning model-egress boundary. Authenticate first, validate the exact selection and scope,
strip the private envelope, then import or propagate provenance at the receiving boundary.
Preserve documented headerless legacy behavior.
- Never substitute secret plaintext into source, serialize plaintext provenance, hand-roll private
headers, or blanket-sanitize tool results.
- Add focused tests for named projection, identical unproven public text, malformed/incomplete
Expand Down
30 changes: 16 additions & 14 deletions .agents/skills/validate-integration/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,21 +141,25 @@ search, extraction, or "AI-powered" marketing terminology.

- [ ] AI-consumed text/structured fields use `request.modelInput` with `mode: 'project'` and a
minimal exact selector; nested/JSON-string adapters preserve shape through `applyProjected`
- [ ] Opaque AI-consumed values sent directly to an external provider or `directExecution` use
`request.opaqueModelInput` with `mode: 'reject-resolved-secrets'` and an exact effective-value
selector; the central executor rejects incomplete/secret-bearing committed provenance before
formatting or I/O, leaves safe bytes unchanged, and sends no provenance metadata externally
- [ ] Opaque AI-consumed files/bytes/URLs owned by an authenticated internal route use
- [ ] Ordinary external URLs, domains, resource IDs, and control fields retain normal request
semantics unless the exact field is proven model-visible; an AI-backed provider or later model
processing of the referenced resource is not sufficient evidence
- [ ] Serialized content proven to be sent directly to an external model is selected by
`request.modelInput`, projected before the existing formatter parses it, and has deterministic
formatter behavior when a whole-value placeholder is invalid for the serialized grammar
- [ ] Actual inline/raw AI-consumed bytes owned by an authenticated internal route use
`privateProvenance` (or `mode: 'private-provenance'`), and the route validates
`validateOpaqueModelInputProvenance` before any download or model call
`validateOpaqueModelInputProvenance` before model egress; storage keys, paths, signed URLs,
and ordinary remote URLs are not treated as byte provenance, while tracked stored bytes are
authorized independently at the owning model-egress boundary
- [ ] Persisted workspace-file contents are checked with the shared provenance guard only when
their bytes or decoded content cross into a model/tool-result boundary; ordinary file APIs
remain unchanged. Unsupported secret-bearing file paths are rejected at `file_write`
- [ ] Sim-owned durable writes and internal execution handoffs that can enter workflows/models use
field-scoped `request.secretProvenance`; authenticated receivers validate the exact selection
and scope, strip private metadata, and persist, import, or propagate it at the owning boundary
- [ ] Private provenance is never attached to external URLs or `directExecution`; those paths use
centralized `opaqueModelInput` rejection when their opaque values are model-bound
- [ ] Private provenance is never attached to external URLs or `directExecution`; proven
model-visible external fields use projection, while other external inputs remain unchanged
- [ ] No tool performs raw secret plaintext/source substitution or serializes plaintext provenance
- [ ] No `transformResponse` or tool-local helper blanket-sanitizes ordinary third-party results;
only execution-scoped, activated Sim provenance is projected at shared model/log boundaries
Expand All @@ -166,10 +170,9 @@ search, extraction, or "AI-powered" marketing terminology.
metadata, provider results, or API payloads
- [ ] Diagnostic projection is applied only to values carrying execution-scoped provenance;
ordinary provider responses, filenames, URLs, and errors are unchanged
- [ ] Tests cover named `{{NAME}}` projection, unproven identical public text, nested shape
preservation, malformed/incomplete metadata, centralized opaque rejection before formatting
or I/O with safe-byte preservation, headerless legacy requests, metadata stripping, and
durable legacy/stale/scope cases when applicable
- [ ] Tests cover named `{{NAME}}` projection, unproven identical public text, nested and serialized
shape handling, unchanged ordinary external inputs, malformed/incomplete metadata, headerless
legacy requests, metadata stripping, and durable legacy/stale/scope cases when applicable

Treat a missing or bypassed model, durable, or internal-execution provenance boundary as
**critical**. Do not fix it with a tool-specific string replacer or by sanitizing every provider
Expand Down Expand Up @@ -348,8 +351,7 @@ Group findings by severity:
- Service-account metadata disagrees with the canonical OAuth service configuration
- `tools.config.tool` returning wrong tool ID for an operation
- Type coercions in `tools.config.tool` instead of `tools.config.params`
- AI-consumed request fields bypass the shared projection, centralized opaque rejection, or
private-provenance boundary
- Proven model-visible request fields bypass the shared projection or private-provenance boundary
- Opaque model input is downloaded or sent before provenance and workspace-file checks
- A Sim-owned durable sink or internal execution handoff drops encrypted provenance or breaks
legacy headerless/`NULL` data
Expand Down
43 changes: 23 additions & 20 deletions .claude/commands/add-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,20 +130,24 @@ service's official documentation or an unambiguous local execution path proves t
field is consumed by an AI model. If that cannot be established, preserve existing tool behavior
and leave the field unannotated.

- **Ordinary provider/API input:** leave it unchanged. Do not add blanket result sanitization.
- **Ordinary provider/API input:** leave it unchanged. Explicit `{{...}}` references resolve and are
sent with their normal request semantics. A URL, domain, resource ID, control field, or opaque
payload is not model-visible merely because the provider is AI-backed or may process the
referenced resource later.
- **Text or structured content consumed by an AI model:** declare `request.modelInput` with
`mode: 'project'` and select only the exact model-visible fields. The shared executor replaces
activated Sim secrets with canonical `{{NAME}}` labels before request formatting. For nested or
JSON-string fields, use a small shared selector plus `applyProjected`; verify that selecting the
rebuilt params reproduces the projected selection.
- **Opaque model input sent directly to an external provider** such as a model-read URL or image
payload: declare `request.opaqueModelInput` with `mode: 'reject-resolved-secrets'` and select only
the exact effective value. The shared `executeTool` preflight rejects incomplete or secret-bearing
committed provenance before URL/body formatting or network I/O, preserves safe request bytes,
and sends no provenance metadata to the provider.
- **Opaque model input owned by an authenticated internal route** such as uploaded audio, image,
video, file bytes, or signed URLs: add `privateProvenance` to a projected request, or use
`mode: 'private-provenance'` when there is no textual projection. The route must call
- **Serialized model content sent directly to an external provider:** include the serialized
top-level param in `request.modelInput`. Project the private copy before the existing request
formatter parses it; keep formatter behavior deterministic when a whole-value placeholder is not
valid in the serialized grammar. Do not introduce a second hard-rejection path.
- **Opaque model input owned by an authenticated internal route** such as inline audio, image,
video, or document bytes: add `privateProvenance` to a projected request, or use
`mode: 'private-provenance'` when there is no textual projection. Do not select storage keys,
paths, signed URLs, or ordinary remote URLs as byte provenance; the owning route must authorize
stored bytes independently at model egress. The route must call
`validateOpaqueModelInputProvenance` before downloading or sending content to the model and must
apply the workspace-file provenance guard before reading a persisted workspace file.
- **Sim-owned durable storage or internal execution handoff** that can later enter a workflow/model
Expand All @@ -159,9 +163,9 @@ Hard rules:
- Never substitute secret plaintext into source or serialize plaintext provenance.
- Never hand-roll private provenance headers/envelopes; the shared `executeTool` boundary owns
transport and strips private metadata from functional results.
- Never attach private provenance to an external URL or to `directExecution`. Use the centralized
`opaqueModelInput` rejection mode for external/direct opaque model inputs, or an authenticated
internal route when encrypted provenance must cross the boundary.
- Never attach private provenance to an external URL or to `directExecution`. Project proven
model-visible external fields with `request.modelInput`; otherwise preserve ordinary request
semantics. Use an authenticated internal route when encrypted provenance must cross the boundary.
- Never sanitize arbitrary third-party tool results. Projection applies only to secrets activated
by Sim's resolved-secret provenance for that execution/tool call.
- Do not add provenance merely because a value is persisted, returned by a tool, or appears in a
Expand All @@ -172,12 +176,11 @@ Hard rules:
provider responses, filenames, URLs, and errors remain unchanged when Sim did not resolve a
secret into them.

Add focused tests covering named projection, ordinary identical text without provenance, nested
shape preservation, malformed/incomplete private metadata failing closed, centralized external
opaque rejection before formatting/I/O without byte changes or metadata transport, headerless
legacy requests, and absence of private metadata in the public tool result. For durable sinks, also
cover legacy `NULL` markers, exact-empty new writes, tracked secret writes, stale/missing sidecars,
and scope isolation.
Add focused tests covering named projection, ordinary identical text without provenance, nested and
serialized shape handling, unchanged ordinary external inputs, malformed/incomplete private metadata
failing closed, headerless legacy requests, and absence of private metadata in the public tool result.
For durable sinks, also cover legacy `NULL` markers, exact-empty new writes, tracked secret writes,
stale/missing sidecars, and scope isolation.

## Step 3: Create Block

Expand Down Expand Up @@ -593,8 +596,8 @@ If creating V2 versions (API-aligned outputs):
- [ ] Registered all tools in `tools/registry.ts`
- [ ] Ran `bun run tool-metadata:generate` and committed the regenerated artifacts
- [ ] Classified every model-visible, opaque, Sim-durable, and internal-execution request field
- [ ] Added shared model-input projection, centralized opaque rejection, or private provenance only
where required
- [ ] Added shared model-input projection or private provenance only where required; ordinary
external resource locators and control inputs retain their request semantics
- [ ] Confirmed ordinary third-party tool results are not generically sanitized
- [ ] Added provenance compatibility and fail-closed boundary tests where applicable

Expand Down
Loading
Loading