Skip to content

Commit 546aac6

Browse files
waleedlatif1claude
andcommitted
fix: address the first review round on the combined PR
The mirror override in the inventory header double-prefixed. It told operators to override the device plugin with `<your-registry>/nvidia/k8s-device-plugin` while global rewriting stayed on, so `sim.image` prepended the registry a second time and the DaemonSet landed in ImagePullBackOff. Verified by rendering both forms; the override has to be the bare repository. The plugin's DaemonSet also now carries `global.imagePullSecrets`, which it was the only workload to omit — an authenticated mirror could not pull it. The resolver skipped `latest*` whenever the alias did not resolve to this run's index, which conflated "the guard withheld it" with "the read was stale". create-ghcr-manifests now publishes its guard decision and the resolver fails instead of skipping when the guard says latest was published this run. Docs corrections, each verified against source: - The loopback carve-out does lift plain HTTP and the private-address block; it leaves only the denied-port list in force. `egress.ts` skips the port check for allowlist vouching alone, which is what makes `http://localhost:5432` stay refused. - Not every guarded response is capped — the pinned fetch used by provider SDKs sets no limit. - A partially configured storage backend is skipped when a later one is complete; it fails only when none is. - GCE Ingress can serve a provisioned TLS Secret, so cert-manager is an alternative to a ManagedCertificate rather than requiring a different controller. - Workload Identity needs roles/iam.serviceAccountTokenCreator to sign GCS URLs. - NEXT_PUBLIC_BRAND_BACKGROUND_COLOR is a contrast flag, not a background. - NEXT_PUBLIC_SANDBOXES_ENABLED is a browser gate, not provider readiness. - An incomplete certificate chain is not fixed by NODE_EXTRA_CA_CERTS; the endpoint has to serve the intermediate. - Script migrations run once — the eight retries are for SQL lock timeouts. - NO_PROXY belongs in the application environment, not a shell assignment, and the GKE annotate command no longer hard-codes a release name and namespace. - Pi's own image, the Microsoft login callback, the custom-block identity split, the whitelabeling surfaces that ignore configured URLs, and sim-setup's Compose-only scope are all now stated. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015BwsJTEQRzWJaY4BRCkPZt
1 parent 01c4e12 commit 546aac6

22 files changed

Lines changed: 69 additions & 35 deletions

.github/workflows/ci.yml

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,11 @@ jobs:
554554
permissions:
555555
contents: read
556556
packages: write
557+
# Every matrix leg evaluates the same guard against the same commit, so the
558+
# value is identical whichever leg reports it last. attest-subjects needs it
559+
# to tell "the guard withheld latest" from "the registry read was stale".
560+
outputs:
561+
latest_fresh: ${{ steps.guard.outputs.fresh }}
557562
strategy:
558563
matrix:
559564
include:
@@ -661,6 +666,7 @@ jobs:
661666
IS_RELEASE: ${{ needs.detect-version.outputs.is_release }}
662667
VERSION: ${{ needs.detect-version.outputs.version }}
663668
SHA: ${{ github.sha }}
669+
LATEST_FRESH: ${{ needs.create-ghcr-manifests.outputs.latest_fresh }}
664670
run: |
665671
set -euo pipefail
666672
@@ -759,11 +765,16 @@ jobs:
759765
done
760766
761767
if [ "$alias_index" != "$sha_index" ]; then
762-
# `latest` is legitimately allowed to lag: the monotonic guard in
763-
# create-ghcr-manifests holds it back when the branch has moved
764-
# on, and it then belongs to an older run that attested it.
768+
# `latest` is allowed to lag, but only when the guard actually
769+
# withheld it. If the guard published latest this run, a mismatch
770+
# here is a stale read, not a deliberate skip — and silently
771+
# dropping it would leave a published tag unsigned.
765772
if [ "$alias" = "latest" ]; then
766-
echo "Skipping latest* for ${image}: it does not point at this run's index."
773+
if [ "${LATEST_FRESH}" = "true" ]; then
774+
echo "::error::${image}:latest was published by this run but resolves to ${alias_index:-nothing}"
775+
exit 1
776+
fi
777+
echo "Skipping latest* for ${image}: the monotonic guard withheld it this run."
767778
continue
768779
fi
769780
# A version tag has no such carve-out. This run published it, so

apps/docs/content/docs/platform/enterprise/custom-blocks.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ A custom block always runs the **latest deployed version** of its source workflo
1414

1515
## Common uses
1616

17-
The block's author keeps the credentials and the workflow logic; by default consumers see only the inputs and outputs, unless the author enables **Trace runs in consumer logs**. Common patterns:
17+
Consumers see only the inputs and outputs by default, unless the author enables **Trace runs in consumer logs**. Identity splits at execution: the source workflow's owner supplies personal variables and delegated calls, and the source workspace supplies workspace variables and carries the billing. Common patterns:
1818

1919
- **Internal API gateway.** Wrap an authenticated internal or partner endpoint — "Create Ticket", "Charge Account", "Provision User" — behind a block that takes only the business inputs. Teammates call it without the base URL, API key, or auth headers, and when the endpoint changes you update one workflow instead of every consumer's.
2020
- **Blessed knowledge lookup.** Package a vetted retrieval pipeline — chunking, filters, reranking — as "Search Company Docs" with a single query input, so teams reuse the approved retrieval instead of each rebuilding it.

apps/docs/content/docs/platform/enterprise/data-retention.mdx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,8 @@ PII redaction runs against a standalone [Presidio](https://microsoft.github.io/p
213213

214214
```bash
215215
# The Presidio service exposing /analyze and /anonymize
216-
# Helm — substitute your release name and namespace
216+
# Helm — setting pii.enabled wires this for you. Set it by hand only for an
217+
# external Presidio, substituting your release name and namespace.
217218
PII_URL=http://<release>-pii.<namespace>.svc.cluster.local:5001
218219
# Docker Compose — the PII service name on your network
219220
# PII_URL=http://pii:5001

apps/docs/content/docs/platform/enterprise/index.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ See the [SSO setup guide](/platform/enterprise/sso) for step-by-step instruction
4141

4242
## White-labeling
4343

44-
Replace Sim's default branding — logos, wordmark, product name, and theme colors — with your own. Instance-wide branding environment variables additionally cover the favicon, custom CSS, and the brand background colour. See the [white-labeling guide](/platform/enterprise/whitelabeling).
44+
Replace Sim's default branding — logos, wordmark, product name, and theme colors — with your own. Instance-wide branding environment variables additionally cover the favicon and custom CSS. `NEXT_PUBLIC_BRAND_BACKGROUND_COLOR` is not a background — it only tells Sim whether your brand ground is dark, which it uses to pick contrasting text. See the [white-labeling guide](/platform/enterprise/whitelabeling).
4545

4646
---
4747

apps/docs/content/docs/platform/enterprise/whitelabeling.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ Once enabled, configure branding through **Settings → Organization → White-l
106106

107107
## Instance-wide branding
108108

109-
Instance-wide branding is a separate mechanism from the organization settings above. It is read from environment variables at every render, needs **no organization** and **no** `WHITELABELING_ENABLED`, and applies to the whole deployment — including the surfaces organization white-labeling never reaches: the login modal, the PWA manifest, and public file-share pages.
109+
Instance-wide branding is a separate mechanism from the organization settings above. It is read from environment variables at every render, needs **no organization** and **no** `WHITELABELING_ENABLED`, and applies across the deployment, including surfaces organization settings never reach — though not uniformly: the PWA manifest ignores the configured logo and favicon URLs, and public file-share pages drop the Sim logo without substituting yours. It covers the surfaces organization white-labeling never reaches: the login modal, the PWA manifest, and public file-share pages.
110110

111111
Where both are set, an organization's saved settings take precedence for members of that organization; the instance-wide values are the deployment's baseline.
112112

apps/docs/content/docs/platform/self-hosting/authentication.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ DISABLE_MICROSOFT_AUTH=true
5656
```
5757

5858
<Callout type="info">
59-
`GOOGLE_CLIENT_ID` and `MICROSOFT_CLIENT_ID` are shared with the integration connectors. One app registration can serve both login and integrations — register the login callback (`/api/auth/callback/google`) alongside the connector callbacks (`/api/auth/oauth2/callback/google-email` and friends) on the same OAuth client. See [Integrations & OAuth](/platform/self-hosting/integrations-oauth).
59+
`GOOGLE_CLIENT_ID` and `MICROSOFT_CLIENT_ID` are shared with the integration connectors. One app registration can serve both login and integrations — register that provider's own login callback `/api/auth/callback/google` for Google, `/api/auth/callback/microsoft` for Microsoft — alongside the connector callbacks (`/api/auth/oauth2/callback/google-email` and friends) on the same OAuth client. See [Integrations & OAuth](/platform/self-hosting/integrations-oauth).
6060
</Callout>
6161

6262
## SSO (SAML and OIDC)

apps/docs/content/docs/platform/self-hosting/background-jobs.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ cronjobs:
7171
enabled: true
7272
```
7373
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 the Kubernetes default of six applies and the chart exposes no key to change it. `cronjobs.activeDeadlineSeconds` (default `300`) bounds the **whole Job** — retries and the controller's back-off included — so a persistently failing job is usually marked `DeadlineExceeded` after four or five attempts rather than six. The same deadline cuts off a single hung request. One attempt is already several HTTP calls: the container retries three times, ten seconds apart, with `curl --retry 2` inside each.
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 the Kubernetes default of six applies and the chart exposes no key to change it. `cronjobs.activeDeadlineSeconds` (default `300`) bounds the **whole Job** — retries and the controller's back-off included — so whichever limit is reached first ends the Job — six attempts, or five minutes of attempts plus back-off. The same deadline cuts off a single hung request. One attempt is already several HTTP calls: the container retries three times, ten seconds apart, with `curl --retry 2` inside each.
7575

7676
Disable individual jobs you do not need — billing reconciliation is the obvious one on a self-hosted install:
7777

apps/docs/content/docs/platform/self-hosting/desktop.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ SIM_DESKTOP_DEFAULT_ORIGIN=https://sim.example.com bun run package:mac
144144
This bakes your origin in as the default for fresh installs, so nobody has to set the server by hand (the picker stays available in the menu). The mac target builds a single universal binary, so artifacts land in `apps/desktop/release/` as `Sim-<version>-universal.dmg` and `Sim-<version>-universal.zip`. Add `-c.appId=com.example.sim` if you want your own bundle identifier rather than Sim's.
145145

146146
<Callout type="warn">
147-
The origin you bake in also decides the app's **identity**. A loopback origin, or a `dev.sim.ai` / `staging.sim.ai` hostname, produces a differently named app with its own bundle identifier, its own userData directory, and its own single-instance lock — deliberately, so those installs can sit alongside a production one. Any other origin, including your own domain, is treated as production and shares the plain `Sim` identity. Baking in `http://localhost:3000` to test therefore does not produce a build your users can later repoint; it produces a separate app.
147+
The origin you bake in also decides the app's **identity**. A loopback origin, or a `dev.sim.ai` / `staging.sim.ai` hostname, produces a differently named app with its own userData directory, and its own single-instance lock — deliberately, so those installs can sit alongside a production one. Any other origin, including your own domain, is treated as production and shares the plain `Sim` identity. Baking in `http://localhost:3000` to test therefore does not produce a build your users can later repoint; it produces a separate app.
148148
</Callout>
149149

150150
`package:share` overrides both the output directory and the artifact name — builds land in `apps/desktop/release/<channel-slug>/` as `<channel-slug>-<version>-<arch>.<ext>`, not the names above.

apps/docs/content/docs/platform/self-hosting/docker.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,15 +159,15 @@ docker compose -f docker-compose.prod.yml up -d --force-recreate simstudio
159159

160160
## The `sim-setup` CLI
161161

162-
`npx sim-setup` also manages an existing install. Run it from the directory holding your `.env` and Compose file.
162+
`npx sim-setup` also manages an existing install created from the production or local-development Compose files. It does not detect or manage an Ollama-stack install. Run it from the directory holding your `.env` and Compose file.
163163

164164
| Command | What it does |
165165
|---|---|
166166
| `sim-setup` | The setup wizard. `--quick` skips the prompts, `--dir <path>` picks the directory, `--mode compose\|dev\|k8s` picks the target (`dev` and `k8s` need a source checkout) |
167167
| `sim-setup status` | Show what is installed and healthy |
168168
| `sim-setup logs` | Follow logs |
169169
| `sim-setup start` / `stop` / `restart` | Bring the install up, down, or cycle it |
170-
| `sim-setup update` | Pull or rebuild images and apply them |
170+
| `sim-setup update` | Pull or rebuild images and apply them. Compose installs only — it refuses on source checkouts and Kubernetes, which update through git and `helm upgrade` |
171171
| `sim-setup down` | Remove containers, keep the data |
172172
| `sim-setup reset` | Archive `.env` and wipe managed data |
173173
| `sim-setup config` | Show configured capabilities and integrations |

apps/docs/content/docs/platform/self-hosting/environment-variables.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ Who may sign up and sign in — the allowlists, blocklists, `DISABLE_REGISTRATIO
143143
| `E2B_FUNCTION_TEMPLATE_ID` | Immutable `<template>:<build-id>` ref for the Function base image. Required for E2B; a mutable tag is refused |
144144
| `E2B_FUNCTION_TEMPLATE_GENERATION` | Monotonic release generation printed by the same build. Required for E2B |
145145
| `DAYTONA_FUNCTION_SNAPSHOT_ID` | Immutable snapshot **ID** (not a name) for the Function base image. Required for Daytona |
146+
| `E2B_PI_TEMPLATE_ID` / `DAYTONA_PI_SNAPSHOT_ID` | The image Pi runs on. Separate from the Function base — configuring the provider and Function image alone leaves Pi failing closed |
146147
| `SANDBOXES_ENABLED` / `NEXT_PUBLIC_SANDBOXES_ENABLED` | Enable custom sandboxes on a self-hosted deployment, bypassing the hosted-plan requirement. Neither is sufficient on its own — a provider key **and** an immutable Function base must also be configured. Set the `NEXT_PUBLIC_` twin only after the server side works; it asserts readiness to the browser rather than enabling anything |
147148
| `IVM_MAX_EXECUTIONS_PER_WORKER` | Executions before an isolated-vm worker is recycled |
148149
| `IVM_MAX_BROKERS_PER_EXECUTION` | Host-call brokers per execution |

0 commit comments

Comments
 (0)