@@ -40,6 +40,11 @@ export type ContainerDriverConfig = {
4040 * `product` string `TenantProvisioningRequest` carries; an unconfigured product is a real
4141 * misconfiguration, not a silent no-op (see `bindingFor`). */
4242 bindings : Record < Product , ContainerNamespaceLike > ;
43+ /** The hosted fleet's central Sentry DSN (#7876), injected into every tenant container at cold boot as
44+ * {@link SENTRY_DSN_ENV_VAR} so its self-host process reports to it. Omitted/blank ⇒ containers start with
45+ * no injected DSN, byte-identical to the pre-#7876 call — the platform simply isn't reporting yet (e.g.
46+ * before #7875 provisions the secret). Sourced from the control-plane's own env in driver-factory.ts. */
47+ centralSentryDsn ?: string ;
4348} ;
4449
4550export type ContainerDriver = {
@@ -75,21 +80,34 @@ export const PINNED_VERSION_ENV_VAR = "LOOPOVER_PINNED_VERSION";
7580 * actually has custodied -- this driver never sees or needs to know what that is. */
7681export const TENANT_SECRET_ENV_VAR = "LOOPOVER_TENANT_SECRET_TOKEN" ;
7782
83+ /** The env var a tenant's container reads its Sentry DSN from at cold boot (#7876, implements #4934). A tenant
84+ * container runs an unmodified self-host image (root Dockerfile for ORB; packages/loopover-miner/Dockerfile
85+ * for AMS), whose process already inits error reporting from this exact var via the opt-in `initSentry`
86+ * pattern (`src/selfhost/sentry.ts`: a complete no-op when unset) — so pointing the hosted fleet at the
87+ * central DSN is purely INJECTING that value here, never a second Sentry-wiring mechanism. Deliberately the
88+ * self-host name `SENTRY_DSN` (not a hosted-only alias): the image's own init reads this and only this, and a
89+ * self-hoster who sets their own `SENTRY_DSN` is completely unaffected — this only supplies a value the
90+ * hosted platform would otherwise leave unset. The value is a control-plane secret (provisioned by #7875),
91+ * never hardcoded or committed. */
92+ export const SENTRY_DSN_ENV_VAR = "SENTRY_DSN" ;
93+
7894/** Idempotent: an already-provisioned tenant's container is left running as-is, never restarted -- a repeat
7995 * create must not interrupt a container mid-work. This is also the ONLY point in a tenant's lifecycle where
8096 * `envVars` actually reach the container (confirmed against the real `@cloudflare/containers` SDK: a `start()`
8197 * call against an already-running/starting instance is a no-op or throws, never re-applies `envVars`) -- so
82- * both of the values below must already be known by the time this runs, not supplied later. A tenant with a
83- * `pinnedVersion` (#4898) starts with that version in {@link PINNED_VERSION_ENV_VAR}; one with a
98+ * all three of the values below must already be known by the time this runs, not supplied later. A tenant with
99+ * a `pinnedVersion` (#4898) starts with that version in {@link PINNED_VERSION_ENV_VAR}; one with a
84100 * `bootstrapSecret` (#8202, set on `request` by `provisionTenant` from `injectSecrets`' result) starts with it
85- * in {@link TENANT_SECRET_ENV_VAR}; a tenant with neither gets the exact pre-#4898 `start()` call, so every
86- * existing tenant's behavior is byte-identical until either rollout applies. */
101+ * in {@link TENANT_SECRET_ENV_VAR}; and when the config carries a central Sentry DSN (#7876) every container
102+ * starts with it in {@link SENTRY_DSN_ENV_VAR}. A tenant with none of them gets the exact pre-#4898 `start()`
103+ * call, so every existing tenant's behavior is byte-identical until a rollout applies. */
87104export async function createTenantContainer ( config : ContainerDriverConfig , request : TenantProvisioningRequest ) : Promise < void > {
88105 const stub = bindingFor ( config , request . product ) . getByName ( instanceNameFor ( request ) ) ;
89106 if ( await stub . isProvisioned ( ) ) return ;
90107 const envVars : Record < string , string > = { } ;
91108 if ( request . tenant . pinnedVersion ) envVars [ PINNED_VERSION_ENV_VAR ] = request . tenant . pinnedVersion ;
92109 if ( request . bootstrapSecret ) envVars [ TENANT_SECRET_ENV_VAR ] = request . bootstrapSecret ;
110+ if ( config . centralSentryDsn ) envVars [ SENTRY_DSN_ENV_VAR ] = config . centralSentryDsn ;
93111 if ( Object . keys ( envVars ) . length > 0 ) {
94112 await stub . start ( { envVars } ) ;
95113 } else {
0 commit comments