Skip to content

Commit 8c01cf0

Browse files
committed
Merge remote-tracking branch 'origin/main' into mollifier-phase-3
# Conflicts: # apps/webapp/app/runEngine/services/triggerTask.server.ts # apps/webapp/app/v3/mollifier/mollifierDrainer.server.ts # apps/webapp/app/v3/mollifier/mollifierGate.server.ts # apps/webapp/app/v3/mollifier/readFallback.server.ts # apps/webapp/test/engine/triggerTask.test.ts # apps/webapp/test/mollifierGate.test.ts # packages/redis-worker/src/mollifier/buffer.test.ts # packages/redis-worker/src/mollifier/buffer.ts
2 parents 854bf38 + 6b46a34 commit 8c01cf0

92 files changed

Lines changed: 5331 additions & 1645 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.

.github/workflows/release.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,13 @@ jobs:
302302
- name: Generate Prisma Client
303303
run: pnpm run generate
304304

305+
- name: Exit changeset pre mode (if active)
306+
run: |
307+
if [ -f .changeset/pre.json ]; then
308+
echo "Repo is in changeset pre mode; exiting so snapshot release can run"
309+
pnpm exec changeset pre exit
310+
fi
311+
305312
- name: Snapshot version
306313
run: pnpm exec changeset version --snapshot "${GITHUB_EVENT_INPUTS_PRERELEASE_TAG}"
307314
env:
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
area: webapp
3+
type: fix
4+
---
5+
6+
Dashboard runs, sessions, batches, and schedule-detail loaders now return 404 (or redirect to the user's home with a toast for missing projects) instead of 500 when a slug doesn't resolve.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
area: webapp
3+
type: feature
4+
---
5+
6+
Expose `is_warm_start` in the TRQL `runs` schema so warm vs cold start data can be queried and visualized in Dashboards.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
area: webapp
3+
type: fix
4+
---
5+
6+
Validate email format on the magic link login form.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
area: webapp
3+
type: fix
4+
---
5+
6+
Recover from ClickHouse `JSONEachRow` parse failures caused by lone
7+
UTF-16 surrogates in OTel attribute strings (`Cannot parse JSON object
8+
here ... ParallelParsingBlockInputFormat`).
9+
10+
`ClickhouseEventRepository.#flushBatch` and `#flushLlmMetricsBatch` now
11+
retry once after sanitizing every row in the batch: any string value
12+
containing a lone surrogate is replaced with `"[invalid-utf16]"`. If
13+
the sanitizer touched no fields (the parse error isn't a surrogate
14+
issue) or the retry still fails, the batch is dropped without further
15+
ClickHouse round-trips, `permanentlyDroppedBatches` increments, and an
16+
error log with a 1KB sample row is emitted. Non-parse errors propagate
17+
unchanged.
18+
19+
Detection reuses `detectBadJsonStrings` via `JSON.stringify(value)`,
20+
with a latent regex bug fixed: the low-surrogate hex nibble matched
21+
`[cd]` instead of `[c-f]`, missing the U+DE00–U+DFFF half of the range
22+
and false-flagging common emoji pairs. Healthy batches pay zero scan
23+
cost — the check only runs when ClickHouse has already rejected.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
area: webapp
3+
type: fix
4+
---
5+
6+
Include the S2 access-token scope fingerprint in its cache key so a scope change in code (e.g. adding a new op) auto-invalidates pre-deploy cached tokens instead of returning stale ones for up to 24h.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
area: webapp
3+
type: fix
4+
---
5+
6+
Expand API error response sanitization to additional loaders and actions so internal exception messages (Prisma errors, etc.) no longer leak to callers via 5xx response bodies.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
area: webapp
3+
type: feature
4+
---
5+
6+
Show the currently pinned `TRIGGER_VERSION` under the Atomic deployments toggle on the Vercel
7+
integration settings, and prompt the user to clear it from Vercel production when they disable
8+
atomic deployments. Also mark `TRIGGER_SECRET_KEY` writes to Vercel as `sensitive` so the value
9+
cannot be read back from the Vercel dashboard or API once written.

apps/webapp/app/components/integrations/VercelBuildSettings.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ type BuildSettingsFieldsProps = {
2323
disabledEnvSlugs?: Partial<Record<EnvSlug, string>>;
2424
autoPromote?: boolean;
2525
onAutoPromoteChange?: (value: boolean) => void;
26+
/** The currently pinned TRIGGER_VERSION on Vercel production, if any. Shown under the
27+
* Atomic deployments toggle so the user knows what version is set on Vercel right now. */
28+
currentTriggerVersion?: string | null;
29+
/** True when the Vercel lookup for TRIGGER_VERSION failed. We show this so the user knows
30+
* the pin status is unknown — distinct from "not set". */
31+
currentTriggerVersionFetchFailed?: boolean;
2632
/** Hide the section-level master toggles for "Pull env vars" and "Discover new env vars". */
2733
hideSectionToggles?: boolean;
2834
};
@@ -39,6 +45,8 @@ export function BuildSettingsFields({
3945
disabledEnvSlugs,
4046
autoPromote,
4147
onAutoPromoteChange,
48+
currentTriggerVersion,
49+
currentTriggerVersionFetchFailed,
4250
hideSectionToggles,
4351
}: BuildSettingsFieldsProps) {
4452
const isSlugDisabled = (slug: EnvSlug) => !!disabledEnvSlugs?.[slug];
@@ -208,6 +216,20 @@ export function BuildSettingsFields({
208216
</TextLink>
209217
.
210218
</Hint>
219+
{currentTriggerVersion && (
220+
<Hint className="pr-6">
221+
Currently pinned to{" "}
222+
<span className="font-mono text-text-bright">{currentTriggerVersion}</span> in Vercel
223+
production.
224+
</Hint>
225+
)}
226+
{!currentTriggerVersion && currentTriggerVersionFetchFailed && (
227+
<Hint className="pr-6 text-warning">
228+
Couldn't read{" "}
229+
<span className="font-mono text-text-bright">TRIGGER_VERSION</span> from Vercel —
230+
check the Vercel dashboard to confirm the production pin.
231+
</Hint>
232+
)}
211233
</div>
212234

213235
{/* Auto promotion — only visible when atomic deployments are on */}

apps/webapp/app/models/vercelIntegration.server.ts

Lines changed: 33 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -960,7 +960,7 @@ export class VercelIntegrationRepository {
960960
key: "TRIGGER_SECRET_KEY",
961961
value: runtimeEnv.apiKey,
962962
target: vercelTarget,
963-
type: "encrypted",
963+
type: "sensitive",
964964
environmentType: runtimeEnv.type,
965965
});
966966
}
@@ -1061,7 +1061,7 @@ export class VercelIntegrationRepository {
10611061
key: "TRIGGER_SECRET_KEY",
10621062
value: params.apiKey,
10631063
target: vercelTarget,
1064-
type: "encrypted",
1064+
type: "sensitive",
10651065
});
10661066

10671067
logger.info("Synced regenerated API key to Vercel", {
@@ -1115,28 +1115,26 @@ export class VercelIntegrationRepository {
11151115
return (env as any).customEnvironmentIds?.includes(customEnvironmentId);
11161116
});
11171117

1118+
// Always delete-then-create rather than editProjectEnv, because Vercel rejects
1119+
// in-place type changes (e.g. encrypted -> sensitive).
11181120
if (existingEnv && existingEnv.id) {
1119-
await client.projects.editProjectEnv({
1120-
idOrName: vercelProjectId,
1121-
id: existingEnv.id,
1122-
...(teamId && { teamId }),
1123-
requestBody: {
1124-
value,
1125-
type,
1126-
},
1127-
});
1128-
} else {
1129-
await client.projects.createProjectEnv({
1121+
await client.projects.batchRemoveProjectEnv({
11301122
idOrName: vercelProjectId,
11311123
...(teamId && { teamId }),
1132-
requestBody: {
1133-
key,
1134-
value,
1135-
type,
1136-
customEnvironmentIds: [customEnvironmentId],
1137-
} as any,
1124+
requestBody: { ids: [existingEnv.id] },
11381125
});
11391126
}
1127+
1128+
await client.projects.createProjectEnv({
1129+
idOrName: vercelProjectId,
1130+
...(teamId && { teamId }),
1131+
requestBody: {
1132+
key,
1133+
value,
1134+
type,
1135+
customEnvironmentIds: [customEnvironmentId],
1136+
} as any,
1137+
});
11401138
})(),
11411139
(error) => toVercelApiError(error)
11421140
)
@@ -1709,29 +1707,27 @@ export class VercelIntegrationRepository {
17091707
return target.length === envTargets.length && target.every((t) => envTargets.includes(t));
17101708
});
17111709

1710+
// Always delete-then-create rather than editProjectEnv, because Vercel rejects
1711+
// in-place type changes (e.g. encrypted -> sensitive). Same approach used by
1712+
// syncApiKeysToVercel via removeAllVercelEnvVarsByKey.
17121713
if (existingEnv && existingEnv.id) {
1713-
await client.projects.editProjectEnv({
1714-
idOrName: vercelProjectId,
1715-
id: existingEnv.id,
1716-
...(teamId && { teamId }),
1717-
requestBody: {
1718-
value,
1719-
target: target as any,
1720-
type,
1721-
},
1722-
});
1723-
} else {
1724-
await client.projects.createProjectEnv({
1714+
await client.projects.batchRemoveProjectEnv({
17251715
idOrName: vercelProjectId,
17261716
...(teamId && { teamId }),
1727-
requestBody: {
1728-
key,
1729-
value,
1730-
target: target as any,
1731-
type,
1732-
},
1717+
requestBody: { ids: [existingEnv.id] },
17331718
});
17341719
}
1720+
1721+
await client.projects.createProjectEnv({
1722+
idOrName: vercelProjectId,
1723+
...(teamId && { teamId }),
1724+
requestBody: {
1725+
key,
1726+
value,
1727+
target: target as any,
1728+
type,
1729+
},
1730+
});
17351731
}
17361732

17371733
static getAutoAssignCustomDomains(

0 commit comments

Comments
 (0)