You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(supply-chain): scan the plain manifest so the SBOM step can run at all
The SBOM step could not have succeeded. Half the per-arch subjects are
single-entry indexes — `imagetools create` writes an index even from one
manifest — and Syft resolves an index against the runner's platform, so an
arm64-only index fails outright on an amd64 runner with "no child with platform
linux/arm64". That is 5 of 25 legs failing on every push to main, taking
attest-images red and, through its gate, preventing any release from being
created.
Scanning by the `<sha>-<arch>` tag fixes it: that is the plain manifest the
alias index wraps, so no platform resolution happens. It also halves the pulls,
since both subjects for an architecture now share one scan of identical content.
An empty subject list would also have opened the release gate — a matrix built
from an empty include produces no legs and still reports success — so the gate
now checks a published count rather than trusting a sibling job's guard.
Two smaller corrections: `digest_of` no longer sleeps after its final attempt,
which was costing 18 seconds per legitimately absent tag, and the alias
comment now says what the code proves (content identity with this run's index)
rather than implying provenance.
The release gate's comment also now says what it gates. CodePipeline fires from
the ECR tags that promote-images moves, upstream of attestation, and only the
GHCR mirrors are signed — so this gates the GitHub release, not the deploy.
Docs, each verified against source:
- Restricted MCP, custom-tool and skill types fail the block; they are not
silently skipped, and the same page already said so 180 lines later.
- NO_PROXY needs every internal destination, not just model endpoints — the app
calls realtime, Presidio, and itself over the same default fetch.
- The proxy table omitted Google/Gemini and every other OpenAI-compatible
provider, and omitted Azure Communication Services from the email row.
- activeDeadlineSeconds caps a failing CronJob at five minutes, so it gets about
one attempt rather than six retries.
- Docker Compose does not schedule the retention endpoints either; the callout
blamed Helm alone while the table beside it was already right.
- Import-free JavaScript does leave the local VM when a block selects a sandbox
or references a file path.
- The GCS CORS list named headers that do not exist; the real key is sent
server-side and never by the browser.
- CRON_SECRET is optional, and nothing enforces the 32-character floor at
runtime because env validation is skipped.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015BwsJTEQRzWJaY4BRCkPZt
Copy file name to clipboardExpand all lines: apps/docs/content/docs/platform/enterprise/access-control.mdx
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -27,7 +27,7 @@ Assignment-time checks keep this unambiguous: a workspace has at most one all-me
27
27
When a user runs a workflow or uses Chat, Sim reads the resolved group's configuration and applies it:
28
28
29
29
-**In the executor:** If a workflow uses a disallowed block type or model provider, execution halts immediately with an error. This applies to both manual runs and scheduled or API-triggered deployments.
30
-
-**In Chat:** Disallowed blocks are filtered out of the block list so they cannot be added to a workflow. Disallowed tool types (MCP, custom tools, skills) are skipped if Sim attempts to use them.
30
+
-**In Chat:** Disallowed blocks are filtered out of the block list so they cannot be added to a workflow. Disallowed tool types (MCP, custom tools, skills) make the block fail with an error if Sim attempts to use them — they are refused, not silently dropped.
31
31
32
32
---
33
33
@@ -209,7 +209,7 @@ This applies regardless of how the workflow is triggered — manually, via API,
209
209
When a user opens Chat, their permission group is read before any block or tool suggestions are made:
210
210
211
211
- Blocks not in the allowed list are filtered out of the block picker entirely — they do not appear as options.
212
-
- If Sim generates a workflow step that would use a disallowed tool (MCP, custom, or skills), that step is skipped and the reason is noted.
212
+
- If Sim generates a workflow step that would use a disallowed tool (MCP, custom, or skills), the run fails with an error naming the restriction.
Copy file name to clipboardExpand all lines: apps/docs/content/docs/platform/enterprise/data-retention.mdx
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -195,7 +195,7 @@ Once enabled, retention settings are configurable through **Settings → Organiz
195
195
| Chats and Chat runs |`GET /api/cron/cleanup-tasks`|
196
196
197
197
<Callouttype="warn">
198
-
The Helm chart does **not** schedule these three endpoints. An operator who sets `DATA_RETENTION_ENABLED=true` on the chart alone still deletes nothing. Add them to `cronjobs.jobs`, or call them daily from an external scheduler.
198
+
Neither shipped deployment schedules these three endpoints — not the Helm chart, not Docker Compose's `cron` service. An operator who sets `DATA_RETENTION_ENABLED=true` alone still deletes nothing. Add them to `cronjobs.jobs`, or call them daily from an external scheduler.
The Helm chart schedules the data-drain dispatcher but **not** the three retention cleanup endpoints. Setting `DATA_RETENTION_ENABLED=true` on the chart alone deletes nothing — the windows are evaluated only when one of those endpoints is called. Add them to `cronjobs.jobs` yourself, or drive them from an external scheduler.
88
+
Both shipped deployments schedule the data-drain dispatcher but **not** the three retention cleanup endpoints — neither the Helm chart nor Docker Compose's `cron` service. Setting `DATA_RETENTION_ENABLED=true` alone deletes nothing — the windows are evaluated only when one of those endpoints is called. Add them to `cronjobs.jobs` yourself, or drive them from an external scheduler.
Copy file name to clipboardExpand all lines: apps/docs/content/docs/platform/self-hosting/background-jobs.mdx
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -71,7 +71,7 @@ cronjobs:
71
71
enabled: true
72
72
```
73
73
74
-
Each job runs a small `curlimages/curl` pod that calls the app's **in-cluster Service** (not the ingress), with `concurrencyPolicy: Forbid` so a slow run never overlaps itself. The Service load-balances that single call to one replica, so a job never fans out across pods. The chart keeps three completed and one failed Job per CronJob, but `ttlSecondsAfterFinished` defaults to 600, so a finished Job is deleted ten minutes after it ends — inspect a failure promptly or collect the logs. It sets no `backoffLimit`, so a failing job retries up to the Kubernetes default of six times before it is marked failed.
74
+
Each job runs a small `curlimages/curl` pod that calls the app's **in-cluster Service** (not the ingress), with `concurrencyPolicy: Forbid` so a slow run never overlaps itself. The Service load-balances that single call to one replica, so a job never fans out across pods. The chart keeps three completed and one failed Job per CronJob, but `ttlSecondsAfterFinished` defaults to 600, so a finished Job is deleted ten minutes after it ends — inspect a failure promptly or collect the logs. It sets no `backoffLimit`, but `cronjobs.activeDeadlineSeconds` (default `300`) terminates the whole Job after five minutes, and the pod's own script already retries three times inside that window — so a failing job gets roughly one pod attempt and is then marked `DeadlineExceeded`, not six retries.
75
75
76
76
Disable individual jobs you do not need — billing reconciliation is the obvious one on a self-hosted install:
|`INTERNAL_API_SECRET`| Internal API secret, at least 32 characters: `openssl rand -hex 32`|
17
17
|`NEXT_PUBLIC_APP_URL`| Public app URL |
18
-
|`CRON_SECRET`| Bearer token for the background job endpoints: `openssl rand -hex 32`. **Required whenever background jobs are enabled** — the Helm chart's default, and the chart will not render without it. See [Background Jobs](/platform/self-hosting/background-jobs)|
19
18
20
-
`openssl rand -hex 32` prints 64 hex characters. `ENCRYPTION_KEY` and `API_ENCRYPTION_KEY` must be exactly that — a value of any other shape throws the first time Sim encrypts or decrypts, not at startup. The rest are secrets of no fixed shape and only need 32 characters or more.
19
+
`openssl rand -hex 32` prints 64 hex characters. `ENCRYPTION_KEY` and `API_ENCRYPTION_KEY` must be exactly that — a value of any other shape throws the first time Sim encrypts or decrypts, not at startup. The rest are secrets of no fixed shape and only need 32 characters or more — a floor nothing enforces at runtime, so meeting it is on you.
21
20
22
21
<Callouttype="error">
23
22
`ENCRYPTION_KEY` and `API_ENCRYPTION_KEY` cannot be rotated or recovered. Losing either makes the data it protects permanently unreadable — workspace and personal environment variables, stored provider API keys, MCP OAuth credentials, and deployment/chat secrets in the first case, user-generated Sim API keys in the second. Back them up separately from the database.
@@ -28,6 +27,7 @@ import { Callout } from 'fumadocs-ui/components/callout'
28
27
| Variable | Description |
29
28
|----------|-------------|
30
29
|`API_ENCRYPTION_KEY`| Encrypts user-generated Sim API keys at rest, exactly 64 hex characters (32 bytes): `openssl rand -hex 32`. **When unset, API keys are stored in plain text** — the app logs one warning and keeps working |
30
+
|`CRON_SECRET`| Bearer token for the background job endpoints: `openssl rand -hex 32`. **Required whenever background jobs are enabled** — the Helm chart's default, and the chart will not render without it. See [Background Jobs](/platform/self-hosting/background-jobs)|
31
31
|`REDIS_URL`| Redis connection string. Optional on a single replica; **required** past one app or realtime replica — see [Redis](/platform/self-hosting/redis)|
32
32
|`REDIS_TLS_SERVERNAME`| TLS SNI override. Required when `REDIS_URL` uses `rediss://` with a bare IP, or the app throws the first time it opens a Redis connection |
33
33
|`NEXT_PUBLIC_SOCKET_URL`| WebSocket URL — defaults to the page origin; set only if realtime is on a separate host |
Copy file name to clipboardExpand all lines: apps/docs/content/docs/platform/self-hosting/index.mdx
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -113,4 +113,4 @@ Sim is self-contained for the core editor and execution engine. A few features r
113
113
|**Agent blocks**| An API key for at least one model provider | Or a self-hosted OpenAI-compatible endpoint: Ollama, vLLM, LM Studio, or LiteLLM. |
114
114
|**Chat module**|`COPILOT_API_KEY` from sim.ai | Set `NEXT_PUBLIC_CHAT_DISABLED=true` to hide the module instead. |
115
115
|**Integrations**| Your own OAuth app per service | See [Integrations & OAuth](/platform/self-hosting/integrations-oauth). |
116
-
|**Remote Function / Pi execution**| Optional E2B or Daytona key, plus a Function base image | Without one, JavaScript Function code that has no `import` or `require` still runs in the in-process isolated VM. Python, Shell, JavaScript with external imports, and custom Function Sandboxes require a configured remote provider **and** an immutable Function base image — the key alone is not enough. Pi uses a separate image, pinned with `E2B_PI_TEMPLATE_ID` or `DAYTONA_PI_SNAPSHOT_ID`. See [Sandboxes](/platform/self-hosting/sandboxes). |
116
+
|**Remote Function / Pi execution**| Optional E2B or Daytona key, plus a Function base image | Without one, JavaScript Function code that has no `import` or `require` still runs in the in-process isolated VM — unless it selects a sandbox or references a file path, which need a sandbox filesystem and are refused with a 422. Python, Shell, JavaScript with external imports, and custom Function Sandboxes require a configured remote provider **and** an immutable Function base image — the key alone is not enough. Pi uses a separate image, pinned with `E2B_PI_TEMPLATE_ID` or `DAYTONA_PI_SNAPSHOT_ID`. See [Sandboxes](/platform/self-hosting/sandboxes). |
| Model providers reached over the default `fetch` — Anthropic, OpenAI, Groq, Cerebras, xAI, Vertex, Ollama, LiteLLM | Yes |
311
-
| Email via Resend, and Gmail sending | Yes |
310
+
| Model providers reached over the default `fetch` — every provider except the three below: Anthropic, OpenAI, Google/Gemini, Vertex, Groq, Cerebras, xAI, Mistral, DeepSeek, OpenRouter, Together, Fireworks, Ollama, LiteLLM, and the other OpenAI-compatible providers | Yes |
311
+
| Email via Resend, Azure Communication Services, and Gmail sending | Yes |
312
312
| The desktop update feed's calls to GitHub | Yes |
313
313
| Object storage — Azure Blob and GCS | Yes — their SDK pipelines read the proxy variables |
314
314
| Everything through the SSRF guard — the HTTP block, tools, connectors, outbound webhooks, content fetches, MCP servers | No |
@@ -322,7 +322,14 @@ The server runs on Bun, and Bun's native `fetch` honors `$HTTP_PROXY`, `$HTTPS_P
322
322
The practical consequence: a mandatory-egress-proxy environment can route most LLM traffic, Resend mail, and Azure/GCS storage through the proxy, but guarded integration calls, S3, Bedrock, SMTP, telemetry, and datastore traffic still need a transparent proxy or NAT-based egress.
323
323
324
324
<Callout type="info">
325
-
Set `NO_PROXY` for any on-premises model endpoint. Self-hosted Ollama, LiteLLM, and vLLM are dialed over the default `fetch`, so a proxy that cannot reach your internal network will otherwise break them.
325
+
Set `NO_PROXY` for every destination that is not on the public internet, not just model endpoints. The app reaches the realtime server (`SOCKET_SERVER_URL`), the Presidio PII service (`PII_URL`), and itself (`INTERNAL_API_BASE_URL`) over the same default `fetch`, alongside self-hosted Ollama, LiteLLM, and vLLM — so a proxy that cannot reach your internal network breaks live updates and PII redaction, not only inference.
Copy file name to clipboardExpand all lines: apps/docs/content/docs/platform/self-hosting/object-storage.mdx
+2-3Lines changed: 2 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -311,8 +311,7 @@ cat > /tmp/cors.json <<'EOF'
311
311
"x-goog-meta-knowledgebaseid",
312
312
"x-goog-meta-folderid",
313
313
"x-goog-meta-workflowid",
314
-
"x-goog-meta-executionid",
315
-
"x-goog-meta-simuploadid"
314
+
"x-goog-meta-executionid"
316
315
],
317
316
"maxAgeSeconds": 3600
318
317
}
@@ -325,7 +324,7 @@ done
325
324
```
326
325
327
326
<Callouttype="info">
328
-
Header names must be listed individually — GCS CORS matches `responseHeader` entries exactly and does not support wildcards like `x-goog-meta-*`. `ETag` is required because large-file multipart uploads read each part's `ETag` from the browser, and CORS hides the header otherwise. `x-goog-if-generation-match` is required by Sim's create-only signed uploads, which prevent a reused upload URL from replacing existing bytes.`x-goog-meta-simuploadid` carries the opaque receipt used to verify an upload after an ambiguous network response.
327
+
Header names must be listed individually — GCS CORS matches `responseHeader` entries exactly and does not support wildcards like `x-goog-meta-*`. `ETag` is required because large-file multipart uploads read each part's `ETag` from the browser, and CORS hides the header otherwise. `x-goog-if-generation-match` is required by Sim's create-only signed uploads, which prevent a reused upload URL from replacing existing bytes.
Function blocks run in one of two places. JavaScript with no `import` or `require` runs in a local isolated VM and needs nothing configured. Python, Shell, JavaScript that imports, and custom workspace sandboxes run on a remote provider, and that provider needs both credentials and a dedicated Function base image.
9
+
Function blocks run in one of two places. JavaScript with no `import` or `require` runs in a local isolated VM and needs nothing configured — unless the block selects a sandbox or references a file path from another block or a sandbox output path. Those need the sandbox filesystem and are refused with a 422 when no provider is configured. Python, Shell, JavaScript that imports, and custom workspace sandboxes run on a remote provider, and that provider needs both credentials and a dedicated Function base image.
10
10
11
11
Until the base image is configured, those languages fail with an explicit configuration error rather than falling back. A saved Python block is never silently serialized or executed as JavaScript.
0 commit comments