Repository navigation
feat(vercel): Vercel and AI Gateway integration - #1583
JeremyFunk wants to merge 17 commits into
Conversation
Maple review🔴 Confidence 1/10 · do not merge Adds a Vercel/AI Gateway integration end to end: encrypted token store, drain reconciliation in a new alerting lane, a
Before merge
Findings🟠 Warning · F1 · Drain logs carry
|
| Issue | Service | Occurrences | File |
|---|---|---|---|
| @maple/http/errors/WarehouseUpstreamError | alerting | 80k | apps/alerting/src/scheduled.ts |
| @maple/http/errors/WarehouseUpstreamError | alerting | 20k | apps/alerting/src/scheduled.ts |
| @maple/http/errors/ErrorPersistenceError | alerting | 2.6k | apps/alerting/src/scheduled.ts |
| @maple/backend/services/pr-review/PrReviewTelemetryReadError | alerting | 2.0k | apps/alerting/src/scheduled.ts |
| @maple/backend/integrations/PlanetScaleForbiddenError | alerting | 1.6k | apps/alerting/src/scheduled.ts |
| @maple/backend/integrations/PlanetScaleForbiddenError | alerting | 1.6k | apps/alerting/src/scheduled.ts |
| @maple/backend/integrations/PlanetScaleForbiddenError | alerting | 1.6k | apps/alerting/src/scheduled.ts |
| @maple/backend/integrations/PlanetScaleForbiddenError | alerting | 1.6k | apps/alerting/src/scheduled.ts |
| @maple/backend/integrations/PlanetScaleForbiddenError | alerting | 1.6k | apps/alerting/src/scheduled.ts |
| @maple/http/errors/ErrorPersistenceError | alerting | 1.2k | apps/alerting/src/scheduled.ts |
After this merges, Maple checks whether they stop.
Production traffic of the changed files (last 7 days)
| File | Calls/day | Busiest operations |
|---|---|---|
apps/ingest/src/vercel_logs.rs |
955 | GET 819/day, 2.9% errGET 136/day, 0.1% err |
packages/query-engine-integrations/src/benchmark/index.ts |
955 | GET 819/day, 2.9% errGET 136/day, 0.1% err |
packages/domain/src/http/integrations.ts |
277 | GET /v2/integrations/gcp 277/day, 0.0% err |
apps/api/src/routes/internal/query-engine.http.ts |
10 | gcpInfraPresence 10/day, 0.0% err |
apps/api/src/routes/queries.ts |
10 | gcpInfraPresence 10/day, 0.0% err |
packages/domain/src/http/query-engine.ts |
10 | gcpInfraPresence 10/day, 0.0% err |
Telemetry this change adds and removes (30)
- ➕ span name
McpTool.syncVercel·apps/ai/src/mcp/tools/integration-writes.ts:157 - ➕ span name
QueryEngine.getVercelProjects·apps/web/src/api/warehouse/vercel-infra.ts:38 - ➕ span name
QueryEngine.getVercelRequestTimeseries·apps/web/src/api/warehouse/vercel-infra.ts:62 - ➕ span name
QueryEngine.getVercelProjectDetail·apps/web/src/api/warehouse/vercel-infra.ts:77 - ➕ span name
QueryEngine.getVercelAiGateway·apps/web/src/api/warehouse/vercel-infra.ts:94 - ➕ span name
VercelIntegrationService.reconcileDrain·packages/backend/src/services/integrations/VercelIntegrationService.ts:443 - ➕ attribute
maple.vercel.drain_kind·packages/backend/src/services/integrations/VercelIntegrationService.ts:455 - ➕ attribute
maple.vercel.drains_found·packages/backend/src/services/integrations/VercelIntegrationService.ts:456 - ➕ span name
VercelIntegrationService.reconcileDrains·packages/backend/src/services/integrations/VercelIntegrationService.ts:528 - ➕ span name
VercelIntegrationService.removeDrains·packages/backend/src/services/integrations/VercelIntegrationService.ts:543 - ➕ attribute
maple.vercel.drains_removed·packages/backend/src/services/integrations/VercelIntegrationService.ts:564 - ➕ span name
VercelIntegrationService.storeProjects·packages/backend/src/services/integrations/VercelIntegrationService.ts:588 - ➕ attribute
maple.vercel.projects·packages/backend/src/services/integrations/VercelIntegrationService.ts:595 - ➕ span name
VercelIntegrationService.storeDeployments·packages/backend/src/services/integrations/VercelIntegrationService.ts:645 - ➕ span name
VercelIntegrationService.getStatus·packages/backend/src/services/integrations/VercelIntegrationService.ts:720 - ➕ span name
VercelIntegrationService.discover·packages/backend/src/services/integrations/VercelIntegrationService.ts:821 - ➕ span name
VercelIntegrationService.connect·packages/backend/src/services/integrations/VercelIntegrationService.ts:900 - ➕ attribute
maple.vercel.team_id·packages/backend/src/services/integrations/VercelIntegrationService.ts:905 - ➕ span name
VercelIntegrationService.updateSettings·packages/backend/src/services/integrations/VercelIntegrationService.ts:1010 - ➕ span name
VercelIntegrationService.disconnect·packages/backend/src/services/integrations/VercelIntegrationService.ts:1041 - ➕ span name
VercelIntegrationService.deployments·packages/backend/src/services/integrations/VercelIntegrationService.ts:1057 - ➕ span name
VercelIntegrationService.pollOrg·packages/backend/src/services/integrations/VercelIntegrationService.ts:1074 - ➕ attribute
maple.vercel.deployments_upserted·packages/backend/src/services/integrations/VercelIntegrationService.ts:1212 - ➕ attribute
maple.vercel.drains_repaired·packages/backend/src/services/integrations/VercelIntegrationService.ts:1213 - ➕ attribute
maple.vercel.failures·packages/backend/src/services/integrations/VercelIntegrationService.ts:1214 - ➕ span name
VercelIntegrationService.pollAllOrgs·packages/backend/src/services/integrations/VercelIntegrationService.ts:1242 - ➕ span name
VercelIntegrationService.sync·packages/backend/src/services/integrations/VercelIntegrationService.ts:1297 - ➕ span name
VercelApi.listTeams·packages/backend/src/services/integrations/vercel/api.ts:110 - ➕ span name
VercelApi.listProjects·packages/backend/src/services/integrations/vercel/api.ts:171 - ➕ attribute
maple.vercel.projects_complete·packages/backend/src/services/integrations/vercel/api.ts:198
What was checked
- Every new Vercel query filters
OrgId(vercel-infra.ts:31,vercel-ai-gateway.ts:34) - New query payloads use
TinybirdDateTime/BucketSecondsat the HTTP boundary (http/query-engine.ts:501-536) - Token never appears in a status response schema;
VercelIntegrationStatuscarries only team, scope and drain state
Observability coverage: 1 of 3 changes observable
| Change | Kind | Observable | Evidence |
|---|---|---|---|
| POST /v1/logpush/vercel (log drain ingest) | HTTP route | no | not read in this pass; only grepped for the ingest-source attribute |
| vercel lane in the alerting cron (drain reconcile + discovery) | cron | yes | reconcile annotates the span with maple.vercel.team_id (VercelIntegrationService.ts:1090) |
| Vercel REST calls (projects, deployments, drains) | outbound HTTP | no | vercel/api.ts not read in this pass |
Files not reviewed (32)
The review ended before it read these diffs, so nothing above vouches for them.
apps/ai/src/mcp/__evals__/provider-world.tsapps/alerting/src/scheduled.test.tsapps/local-ui/src/hooks/use-local-service-map.test.tsapps/web/src/components/dashboard/nav-items.test.tsapps/web/src/components/infra/overview/summaries.test.tsapps/web/src/components/infra/vercel/list-model.test.tsapps/web/src/components/integrations/vercel-model.test.tsapps/web/src/lab/bench/service-map-bench.tsxapps/web/src/lab/infra-lab.tsxapps/web/src/lab/registry.tsapps/web/src/lab/vercel-infra-fixtures.tsapps/web/src/lab/vercel-integration-lab.tsxapps/web/src/lib/agent-sessions/vendor-color.test.tsapps/web/src/lib/agent-sessions/vendor-icon.tsapps/web/src/lib/agent-sessions/vendor-label.tsapps/web/src/lib/docs.tsapps/web/src/routes/lab/vercel.tsxpackages/backend/src/dashboard-templates/index.tspackages/backend/src/dashboard-templates/infrastructure/vercel.test.tspackages/backend/src/dashboard-templates/infrastructure/vercel.tspackages/backend/src/services/integrations/IntegrationInventoryService.test.tspackages/backend/src/services/integrations/VercelIntegrationService.test.tspackages/domain/src/gen-ai.tspackages/query-engine-integrations/src/vercel/vercel.test.tspackages/ui/src/components/icons/index.tspackages/ui/src/components/icons/vercel.tsxpackages/ui/src/components/service-map/service-map-canvas.tsxpackages/ui/src/components/service-map/service-map-node.tsxpackages/ui/src/components/service-map/service-map-types.tspackages/ui/src/components/service-map/service-map-utils.ts- and 2 more
dd8bf24 · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one. Check ids refer to Maple's instrumentation audit.
🍁 Maple PR previewThe preview is ready:
Smoke test: passed Sign in with the PR preview form on the sign-in page and the preview access key ( Deployed from |
Maple review🟡 Confidence 5/10 · needs attention The only change since the previous review raises the web startup JS budget from 707.5 to 710 KB; the seven open findings are untouched. The alerting warehouse, persistence and PlanetScale errors in Before merge
Still open from earlier reviews
Production impactOpen errors in the changed files
After this merges, Maple checks whether they stop. Production traffic of the changed files (last 7 days)
Telemetry this change adds and removes (30)
What was checked
|
… visible read and save failures
…ain pending, tiny USD
Maple review🟢 Confidence 10/10 · safe to merge The follow-up commits fix every open finding: drain reconciliation by org marker, pruning when every project is deleted, indexed resource grouping, the
Before merge
Fixed since the last review
Production impactOpen errors in the changed files
After this merges, Maple checks whether they stop. Production traffic of the changed files (last 7 days)
Telemetry this change adds and removes (30)
What was checked
Observability coverage: 3 of 3 changes observable
|
# Conflicts: # apps/ai/src/mcp/resources/instructions.ts # apps/ingest/src/main.rs # apps/web/perf/check-bundle-budget.ts
Maple review🟢 Confidence 9/10 · safe to merge Adds Vercel and AI Gateway as a managed integration: encrypted token storage, a drain-reconciling poller lane, a
Before merge
Production impactOpen errors in the changed files
After this merges, Maple checks whether they stop. Production traffic of the changed files (last 7 days)
Telemetry this change adds and removes (30)
What was checked
Observability coverage: 2 of 2 changes observable
|
…e error-log table
Maple review🟢 Confidence 8/10 · likely safe to merge Reviewed the seven files changed since the last pass: the Vercel dashboard template, the Vercel source listing, and platform/docs copy. The template is sound; the new Vercel source row has no telemetry attribution, so its usage always reads zero. The open alerting errors (
Before merge
Findings🟠 Warning · F8 · Vercel source is listed but its telemetry never carries
|
| Issue | Service | Occurrences | File |
|---|---|---|---|
| @maple/http/errors/WarehouseUpstreamError | alerting | 80k | apps/alerting/src/scheduled.ts |
| @maple/http/errors/WarehouseUpstreamError | alerting | 20k | apps/alerting/src/scheduled.ts |
| @maple/http/errors/ErrorPersistenceError | alerting | 2.6k | apps/alerting/src/scheduled.ts |
| @maple/backend/services/pr-review/PrReviewTelemetryReadError | alerting | 2.0k | apps/alerting/src/scheduled.ts |
| @maple/backend/integrations/PlanetScaleForbiddenError | alerting | 1.6k | apps/alerting/src/scheduled.ts |
| @maple/backend/integrations/PlanetScaleForbiddenError | alerting | 1.6k | apps/alerting/src/scheduled.ts |
| @maple/backend/integrations/PlanetScaleForbiddenError | alerting | 1.6k | apps/alerting/src/scheduled.ts |
| @maple/backend/integrations/PlanetScaleForbiddenError | alerting | 1.6k | apps/alerting/src/scheduled.ts |
| @maple/backend/integrations/PlanetScaleForbiddenError | alerting | 1.6k | apps/alerting/src/scheduled.ts |
| @maple/http/errors/ErrorPersistenceError | alerting | 1.2k | apps/alerting/src/scheduled.ts |
After this merges, Maple checks whether they stop.
Production traffic of the changed files (last 7 days)
| File | Calls/day | Busiest operations |
|---|---|---|
apps/ingest/src/vercel_logs.rs |
977 | GET 841/day, 2.8% errGET 136/day, 0.1% err |
packages/query-engine-integrations/src/benchmark/index.ts |
977 | GET 841/day, 2.8% errGET 136/day, 0.1% err |
packages/domain/src/http/integrations.ts |
330 | GET /v2/integrations/gcp 330/day, 0.0% err |
apps/api/src/routes/internal/query-engine.http.ts |
10 | gcpInfraPresence 10/day, 0.0% err |
apps/api/src/routes/queries.ts |
10 | gcpInfraPresence 10/day, 0.0% err |
packages/domain/src/http/query-engine.ts |
10 | gcpInfraPresence 10/day, 0.0% err |
packages/backend/src/services/integrations/VercelIntegrationService.ts |
6 | VercelIntegrationService.getStatus 6/day, 0.0% err |
Telemetry this change adds and removes (30)
- ➕ span name
McpTool.syncVercel·apps/ai/src/mcp/tools/integration-writes.ts:157 - ➕ span name
QueryEngine.getVercelProjects·apps/web/src/api/warehouse/vercel-infra.ts:38 - ➕ span name
QueryEngine.getVercelRequestTimeseries·apps/web/src/api/warehouse/vercel-infra.ts:62 - ➕ span name
QueryEngine.getVercelProjectDetail·apps/web/src/api/warehouse/vercel-infra.ts:77 - ➕ span name
QueryEngine.getVercelAiGateway·apps/web/src/api/warehouse/vercel-infra.ts:94 - ➕ span name
VercelIntegrationService.reconcileDrain·packages/backend/src/services/integrations/VercelIntegrationService.ts:443 - ➕ attribute
maple.vercel.drain_kind·packages/backend/src/services/integrations/VercelIntegrationService.ts:455 - ➕ attribute
maple.vercel.drains_found·packages/backend/src/services/integrations/VercelIntegrationService.ts:456 - ➕ span name
VercelIntegrationService.reconcileDrains·packages/backend/src/services/integrations/VercelIntegrationService.ts:531 - ➕ span name
VercelIntegrationService.removeDrains·packages/backend/src/services/integrations/VercelIntegrationService.ts:546 - ➕ attribute
maple.vercel.drains_removed·packages/backend/src/services/integrations/VercelIntegrationService.ts:567 - ➕ span name
VercelIntegrationService.storeProjects·packages/backend/src/services/integrations/VercelIntegrationService.ts:591 - ➕ attribute
maple.vercel.projects·packages/backend/src/services/integrations/VercelIntegrationService.ts:598 - ➕ span name
VercelIntegrationService.storeDeployments·packages/backend/src/services/integrations/VercelIntegrationService.ts:648 - ➕ span name
VercelIntegrationService.discover·packages/backend/src/services/integrations/VercelIntegrationService.ts:824 - ➕ span name
VercelIntegrationService.connect·packages/backend/src/services/integrations/VercelIntegrationService.ts:903 - ➕ attribute
maple.vercel.team_id·packages/backend/src/services/integrations/VercelIntegrationService.ts:908 - ➕ span name
VercelIntegrationService.updateSettings·packages/backend/src/services/integrations/VercelIntegrationService.ts:1013 - ➕ span name
VercelIntegrationService.disconnect·packages/backend/src/services/integrations/VercelIntegrationService.ts:1044 - ➕ span name
VercelIntegrationService.deployments·packages/backend/src/services/integrations/VercelIntegrationService.ts:1060 - ➕ span name
VercelIntegrationService.pollOrg·packages/backend/src/services/integrations/VercelIntegrationService.ts:1077 - ➕ attribute
maple.vercel.deployments_upserted·packages/backend/src/services/integrations/VercelIntegrationService.ts:1214 - ➕ attribute
maple.vercel.drains_repaired·packages/backend/src/services/integrations/VercelIntegrationService.ts:1215 - ➕ attribute
maple.vercel.failures·packages/backend/src/services/integrations/VercelIntegrationService.ts:1216 - ➕ span name
VercelIntegrationService.pollAllOrgs·packages/backend/src/services/integrations/VercelIntegrationService.ts:1244 - ➕ span name
VercelIntegrationService.sync·packages/backend/src/services/integrations/VercelIntegrationService.ts:1299 - ➕ span name
VercelApi.listTeams·packages/backend/src/services/integrations/vercel/api.ts:110 - ➕ span name
VercelApi.listProjects·packages/backend/src/services/integrations/vercel/api.ts:171 - ➕ attribute
maple.vercel.projects_complete·packages/backend/src/services/integrations/vercel/api.ts:198 - ➕ span name
VercelApi.listDeployments·packages/backend/src/services/integrations/vercel/api.ts:253
What was checked
- Every Vercel template SQL widget passes
prepareRawSql:$__orgFilter,$__timeGroup,$__startTime/$__interval_sall expand (vercel.test.ts:25) attr.http.request.method existsmatches only request logs: the mapper omits the attribute on non-request entries (vercel_logs.rs:432)- The new vercel read filters
orgId(integration-sources.ts:152) andteamNameis non-null inpackages/db/src/tables/vercel.ts:16
2ee28cd · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.
Preview test (pr-1583, synthetic Vercel data)A separate agent tested the preview with drain-format logs and AI Gateway/deployment traces sent straight to Ingest
Log mapping
AI Gateway
Connect flow: a fake token gives an inline "Vercel rejected this token" error, no crash. Dashboard template: the preview run found that its raw-SQL time series drew nothing for a single burst. Fixed in 2ee28cd (
Traces (Maple self-telemetry,
|
| Span | n | p50 | p95 | errors |
|---|---|---|---|---|
VercelIntegrationService.getStatus (one SELECT) |
35 | 21 ms | 66 ms | 0 |
alerting.vercel_tick → pollAllOrgs |
3 | 55 ms | 62 ms | 0 |
VercelIntegrationService.discover → VercelApi.listTeams |
1 | 308 ms | – | 1 (expected: fake token) |
RawSql.execute (dashboard widgets) |
23 | 58 ms | 212 ms | 0 |
- No N+1 queries or waterfalls
- The preview ingest gateway sends no traces of its own, so route timing for
/v1/logpush/vercelcomes from the Rust tests, not traces
Not yet verified
- Real Vercel drains and real payloads (connect, drain creation, the poller against a Pro team, real AI Gateway and
@vercel/oteltraces). Pending a test token.
…el drains send theirs
Maple review🟢 Confidence 8/10 · likely safe to merge Adds
Before merge
Findings🟠 Warning · F9 ·
|
| Issue | Service | Occurrences | File |
|---|---|---|---|
| @maple/http/errors/WarehouseUpstreamError | alerting | 80k | apps/alerting/src/scheduled.ts |
| @maple/http/errors/WarehouseUpstreamError | alerting | 20k | apps/alerting/src/scheduled.ts |
| @maple/http/errors/ErrorPersistenceError | alerting | 2.6k | apps/alerting/src/scheduled.ts |
| @maple/backend/services/pr-review/PrReviewTelemetryReadError | alerting | 2.0k | apps/alerting/src/scheduled.ts |
| @maple/backend/integrations/PlanetScaleForbiddenError | alerting | 1.6k | apps/alerting/src/scheduled.ts |
| @maple/backend/integrations/PlanetScaleForbiddenError | alerting | 1.6k | apps/alerting/src/scheduled.ts |
| @maple/backend/integrations/PlanetScaleForbiddenError | alerting | 1.6k | apps/alerting/src/scheduled.ts |
| @maple/backend/integrations/PlanetScaleForbiddenError | alerting | 1.6k | apps/alerting/src/scheduled.ts |
| @maple/backend/integrations/PlanetScaleForbiddenError | alerting | 1.6k | apps/alerting/src/scheduled.ts |
| @maple/http/errors/ErrorPersistenceError | alerting | 1.2k | apps/alerting/src/scheduled.ts |
After this merges, Maple checks whether they stop.
Production traffic of the changed files (last 7 days)
| File | Calls/day | Busiest operations |
|---|---|---|
apps/ingest/src/vercel_logs.rs |
974 | GET 840/day, 2.8% errGET 134/day, 0.1% err |
packages/query-engine-integrations/src/benchmark/index.ts |
974 | GET 840/day, 2.8% errGET 134/day, 0.1% err |
packages/domain/src/http/integrations.ts |
337 | GET /v2/integrations/gcp 337/day, 0.0% err |
apps/api/src/routes/internal/query-engine.http.ts |
11 | gcpInfraPresence 11/day, 0.0% err |
apps/api/src/routes/queries.ts |
11 | gcpInfraPresence 11/day, 0.0% err |
packages/domain/src/http/query-engine.ts |
11 | gcpInfraPresence 11/day, 0.0% err |
packages/backend/src/services/integrations/VercelIntegrationService.ts |
7 | VercelIntegrationService.getStatus 7/day, 0.0% err |
Telemetry this change adds and removes (30)
- ➕ span name
McpTool.syncVercel·apps/ai/src/mcp/tools/integration-writes.ts:157 - ➕ span name
QueryEngine.getVercelProjects·apps/web/src/api/warehouse/vercel-infra.ts:38 - ➕ span name
QueryEngine.getVercelRequestTimeseries·apps/web/src/api/warehouse/vercel-infra.ts:62 - ➕ span name
QueryEngine.getVercelProjectDetail·apps/web/src/api/warehouse/vercel-infra.ts:77 - ➕ span name
QueryEngine.getVercelAiGateway·apps/web/src/api/warehouse/vercel-infra.ts:94 - ➕ span name
VercelIntegrationService.reconcileDrain·packages/backend/src/services/integrations/VercelIntegrationService.ts:487 - ➕ attribute
maple.vercel.drain_kind·packages/backend/src/services/integrations/VercelIntegrationService.ts:499 - ➕ attribute
maple.vercel.drains_found·packages/backend/src/services/integrations/VercelIntegrationService.ts:500 - ➕ span name
VercelIntegrationService.reconcileDrains·packages/backend/src/services/integrations/VercelIntegrationService.ts:575 - ➕ span name
VercelIntegrationService.removeDrains·packages/backend/src/services/integrations/VercelIntegrationService.ts:590 - ➕ attribute
maple.vercel.drains_removed·packages/backend/src/services/integrations/VercelIntegrationService.ts:611 - ➕ span name
VercelIntegrationService.storeProjects·packages/backend/src/services/integrations/VercelIntegrationService.ts:635 - ➕ attribute
maple.vercel.projects·packages/backend/src/services/integrations/VercelIntegrationService.ts:642 - ➕ span name
VercelIntegrationService.storeDeployments·packages/backend/src/services/integrations/VercelIntegrationService.ts:692 - ➕ span name
VercelIntegrationService.discover·packages/backend/src/services/integrations/VercelIntegrationService.ts:868 - ➕ span name
VercelIntegrationService.connect·packages/backend/src/services/integrations/VercelIntegrationService.ts:947 - ➕ attribute
maple.vercel.team_id·packages/backend/src/services/integrations/VercelIntegrationService.ts:952 - ➕ span name
VercelIntegrationService.updateSettings·packages/backend/src/services/integrations/VercelIntegrationService.ts:1057 - ➕ span name
VercelIntegrationService.disconnect·packages/backend/src/services/integrations/VercelIntegrationService.ts:1088 - ➕ span name
VercelIntegrationService.deployments·packages/backend/src/services/integrations/VercelIntegrationService.ts:1104 - ➕ span name
VercelIntegrationService.pollOrg·packages/backend/src/services/integrations/VercelIntegrationService.ts:1121 - ➕ attribute
maple.vercel.deployments_upserted·packages/backend/src/services/integrations/VercelIntegrationService.ts:1258 - ➕ attribute
maple.vercel.drains_repaired·packages/backend/src/services/integrations/VercelIntegrationService.ts:1259 - ➕ attribute
maple.vercel.failures·packages/backend/src/services/integrations/VercelIntegrationService.ts:1260 - ➕ span name
VercelIntegrationService.pollAllOrgs·packages/backend/src/services/integrations/VercelIntegrationService.ts:1288 - ➕ span name
VercelIntegrationService.sync·packages/backend/src/services/integrations/VercelIntegrationService.ts:1343 - ➕ span name
VercelApi.listTeams·packages/backend/src/services/integrations/vercel/api.ts:110 - ➕ span name
VercelApi.listProjects·packages/backend/src/services/integrations/vercel/api.ts:171 - ➕ attribute
maple.vercel.projects_complete·packages/backend/src/services/integrations/vercel/api.ts:198 - ➕ span name
VercelApi.listDeployments·packages/backend/src/services/integrations/vercel/api.ts:253
What was checked
- Drain claims are verified against the org: a foreign
x-maple-source-idfalls back to the default source (main.rs:13700-13731) accepts_source_claimsadmits private keys only, so the drains can claim while a source token cannot (main.rs:1395)pollOrg's lease, budget and disconnected paths still release the lease and remove the drains it created (:1235-1285)
Observability coverage: 1 of 1 changes observable
| Change | Kind | Observable | Evidence |
|---|---|---|---|
| POST /v1/logpush/vercel | inbound HTTP route | yes | handle_signal opens the ingest span named POST /v1/logpush/vercel and records item counts (main.rs:4668-4699) |
c45d3d3 · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.
…disconnected meanwhile
Maple review🟢 Confidence 10/10 · safe to merge The delta since the last review is ten lines:
Before merge
Fixed since the last review
Production impactOpen errors in the changed files
After this merges, Maple checks whether they stop. Production traffic of the changed files (last 7 days)
Telemetry this change adds and removes (30)
What was checked
|
# Conflicts: # apps/local-ui/src/hooks/use-local-service-map.test.ts # apps/local-ui/src/hooks/use-local-service-map.ts # apps/web/perf/check-bundle-budget.ts # apps/web/src/components/dashboard-builder/templates/template-icons.ts # apps/web/src/components/dashboard/app-sidebar.tsx # apps/web/src/components/dashboard/nav-items.test.ts # apps/web/src/components/dashboard/nav-items.ts # apps/web/src/components/infra/overview/infra-overview.tsx # apps/web/src/components/infra/overview/summaries.test.ts # apps/web/src/components/infra/overview/summaries.ts # apps/web/src/components/infra/platform-label.tsx # apps/web/src/components/integrations/integration-catalog.tsx # apps/web/src/hooks/use-infra-surfaces.ts # apps/web/src/lab/bench/service-map-bench.tsx # apps/web/src/lab/infra-lab.tsx # apps/web/src/lib/agent-sessions/vendor-icon.ts # apps/web/src/lib/services/atoms/warehouse-query-atoms.ts # apps/web/src/page/sources/kit/platforms.ts # apps/web/src/routeTree.gen.ts # apps/web/src/routes/integrations.tsx # packages/web-data/src/warehouse/vercel-infra.ts
… labs in the Foldkit app
Maple review🔴 Confidence 1/10 · do not merge Adds Vercel and AI Gateway as an integration: new tables, a poller lane, the
Before merge
Findings🔴 Critical · F18 · Credential
|
| Issue | Service | Occurrences | File |
|---|---|---|---|
| @maple/http/errors/WarehouseUpstreamError | alerting | 80k | apps/alerting/src/scheduled.ts |
| @maple/http/errors/WarehouseUpstreamError | alerting | 20k | apps/alerting/src/scheduled.ts |
| @maple/http/errors/ErrorPersistenceError | alerting | 2.6k | apps/alerting/src/scheduled.ts |
| @maple/backend/services/pr-review/PrReviewTelemetryReadError | alerting | 2.0k | apps/alerting/src/scheduled.ts |
| @maple/backend/integrations/PlanetScaleForbiddenError | alerting | 1.6k | apps/alerting/src/scheduled.ts |
| @maple/backend/integrations/PlanetScaleForbiddenError | alerting | 1.6k | apps/alerting/src/scheduled.ts |
| @maple/backend/integrations/PlanetScaleForbiddenError | alerting | 1.6k | apps/alerting/src/scheduled.ts |
| @maple/backend/integrations/PlanetScaleForbiddenError | alerting | 1.6k | apps/alerting/src/scheduled.ts |
| @maple/backend/integrations/PlanetScaleForbiddenError | alerting | 1.6k | apps/alerting/src/scheduled.ts |
| @maple/http/errors/ErrorPersistenceError | alerting | 1.2k | apps/alerting/src/scheduled.ts |
After this merges, Maple checks whether they stop.
Production traffic of the changed files (last 7 days)
| File | Calls/day | Busiest operations |
|---|---|---|
apps/ingest/src/vercel_logs.rs |
1.0k | GET 902/day, 2.6% errGET 132/day, 0.1% err |
packages/query-engine-integrations/src/benchmark/index.ts |
1.0k | GET 902/day, 2.6% errGET 132/day, 0.1% err |
packages/domain/src/http/integrations.ts |
360 | GET /v2/integrations/gcp 360/day, 0.0% err |
packages/backend/src/services/integrations/VercelIntegrationService.ts |
43 | VercelIntegrationService.pollAllOrgs 35/day, 0.0% errVercelIntegrationService.getStatus 8/day, 0.0% err |
apps/web/src/shell/data.ts |
20 | LoadCloudflareStatus 10/day, 0.0% errLoadPlanetscaleStatus 10/day, 0.0% err |
apps/api/src/routes/internal/query-engine.http.ts |
11 | gcpInfraPresence 11/day, 0.0% err |
apps/api/src/routes/queries.ts |
11 | gcpInfraPresence 11/day, 0.0% err |
packages/domain/src/http/query-engine.ts |
11 | gcpInfraPresence 11/day, 0.0% err |
Telemetry this change adds and removes (30)
- ➕ span name
McpTool.syncVercel·apps/ai/src/mcp/tools/integration-writes.ts:157 - ➕ span name
VercelIntegrationService.reconcileDrain·packages/backend/src/services/integrations/VercelIntegrationService.ts:487 - ➕ attribute
maple.vercel.drain_kind·packages/backend/src/services/integrations/VercelIntegrationService.ts:499 - ➕ attribute
maple.vercel.drains_found·packages/backend/src/services/integrations/VercelIntegrationService.ts:500 - ➕ span name
VercelIntegrationService.reconcileDrains·packages/backend/src/services/integrations/VercelIntegrationService.ts:575 - ➕ span name
VercelIntegrationService.removeDrains·packages/backend/src/services/integrations/VercelIntegrationService.ts:590 - ➕ attribute
maple.vercel.drains_removed·packages/backend/src/services/integrations/VercelIntegrationService.ts:611 - ➕ span name
VercelIntegrationService.storeProjects·packages/backend/src/services/integrations/VercelIntegrationService.ts:635 - ➕ attribute
maple.vercel.projects·packages/backend/src/services/integrations/VercelIntegrationService.ts:642 - ➕ span name
VercelIntegrationService.storeDeployments·packages/backend/src/services/integrations/VercelIntegrationService.ts:692 - ➕ span name
VercelIntegrationService.discover·packages/backend/src/services/integrations/VercelIntegrationService.ts:868 - ➕ span name
VercelIntegrationService.connect·packages/backend/src/services/integrations/VercelIntegrationService.ts:947 - ➕ attribute
maple.vercel.team_id·packages/backend/src/services/integrations/VercelIntegrationService.ts:952 - ➕ span name
VercelIntegrationService.updateSettings·packages/backend/src/services/integrations/VercelIntegrationService.ts:1060 - ➕ span name
VercelIntegrationService.disconnect·packages/backend/src/services/integrations/VercelIntegrationService.ts:1094 - ➕ span name
VercelIntegrationService.deployments·packages/backend/src/services/integrations/VercelIntegrationService.ts:1110 - ➕ span name
VercelIntegrationService.pollOrg·packages/backend/src/services/integrations/VercelIntegrationService.ts:1127 - ➕ attribute
maple.vercel.deployments_upserted·packages/backend/src/services/integrations/VercelIntegrationService.ts:1264 - ➕ attribute
maple.vercel.drains_repaired·packages/backend/src/services/integrations/VercelIntegrationService.ts:1265 - ➕ attribute
maple.vercel.failures·packages/backend/src/services/integrations/VercelIntegrationService.ts:1266 - ➕ span name
VercelIntegrationService.sync·packages/backend/src/services/integrations/VercelIntegrationService.ts:1349 - ➕ span name
VercelApi.listTeams·packages/backend/src/services/integrations/vercel/api.ts:110 - ➕ span name
VercelApi.listProjects·packages/backend/src/services/integrations/vercel/api.ts:171 - ➕ attribute
maple.vercel.projects_complete·packages/backend/src/services/integrations/vercel/api.ts:198 - ➕ span name
VercelApi.listDeployments·packages/backend/src/services/integrations/vercel/api.ts:253 - ➕ attribute
maple.vercel.deployments·packages/backend/src/services/integrations/vercel/api.ts:293 - ➕ span name
VercelApi.createDrain·packages/backend/src/services/integrations/vercel/api.ts:333 - ➕ span name
VercelApi.updateDrain·packages/backend/src/services/integrations/vercel/api.ts:348 - ➕ span name
VercelApi.listDrains·packages/backend/src/services/integrations/vercel/api.ts:416 - ➕ attribute
maple.vercel.drains·packages/backend/src/services/integrations/vercel/api.ts:422
What was checked
- Migration adds three tables;
OrgScopedTablepurge covers all three, including the encrypted token - New ClickHouse queries filter
OrgIdand bound time;sql_baselineregenerated integration-inventory.ts:417maps an unknown drain status topending, notfailing
Files not reviewed (40)
The review ended before it read these diffs, so nothing above vouches for them.
apps/ai/src/mcp/__evals__/provider-world.tsapps/ai/src/mcp/tools/__tests__/integration-tools.test.tsapps/ai/src/mcp/tools/__tests__/provider-infra-tools.test.tsapps/alerting/src/scheduled.test.tsapps/local-ui/src/page/service-map/data.tsapps/local-ui/src/page/service-map/rows.tsapps/web/src/components/infra/vercel/list-model.test.tsapps/web/src/components/integrations/vercel-model.test.tsapps/web/src/components/mcp/mcp-tool-groups.tsapps/web/src/lab/vercel-lab.test.tsapps/web/src/lab/vercel-lab.tsapps/web/src/lib/agent-sessions/vendor-color.test.tsapps/web/src/lib/agent-sessions/vendor-color.tsapps/web/src/lib/agent-sessions/vendor-label.tsapps/web/src/lib/docs.tsapps/web/src/page/agent-sessions/kit/vendor.tsapps/web/src/page/dashboards/templates/derive.tsapps/web/src/page/infra-integrations/vercel/list/vercel.scene.test.tsapps/web/src/page/infra-integrations/vercel/project/project.scene.test.tsapps/web/src/page/infra/kubernetes/workloads/workloads.scene.test.tsapps/web/src/page/integrations/vercel.scene.test.tsapps/web/src/page/settings/setup-health/derive.tsapps/web/src/page/sources/kit/platforms.tsapps/web/src/page/sources/kit/shared.tsapps/web/src/service-map/map/node-card.tspackages/backend/src/dashboard-templates/infrastructure/vercel.test.tspackages/backend/src/services/integrations/IntegrationInventoryService.test.tspackages/backend/src/services/integrations/VercelIntegrationService.test.tspackages/backend/src/services/integrations/VercelIntegrationService.tspackages/domain/src/integration-inventory.test.ts- and 10 more
9d247e5 · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one. Check ids refer to Maple's instrumentation audit.
There was a problem hiding this comment.
Devin Review found 3 potential issues.
1 flag not posted on this PR by your GitHub settings — view it in Devin Review. (Configure)
| const newest = Math.max( | ||
| claimed.deploymentsWatermarkAt ?? 0, | ||
| ...listed.success.map((d) => d.createdAt), | ||
| ) | ||
| if (newest > 0) yield* write({ deploymentsWatermarkAt: newest }) |
There was a problem hiding this comment.
🔴 Deployment history loses older pages
When more than 500 deployments need backfilling, pollOrg advances the watermark from the first five pages. Subsequent polls start near that watermark, permanently omitting older deployments.
Learn more
The deployment API lists newest entries first, and listDeployments stops after the supplied page cap without returning a continuation cursor. A newly connected team with more than five pages of recent deployments only stores those first pages. Advancing deploymentsWatermarkAt to their newest timestamp makes the next poll start an hour before that timestamp, so older pages never enter its query window.
Example: A team created 600 deployments this week. The first poll stores the newest 500 and sets its watermark to the newest deployment. The next poll begins an hour before that deployment, so the remaining 100 older deployments stay absent.
Recommended fix: Persist pagination progress or a separate backfill frontier, continue paging on later ticks until the initial lookback is fully covered, and only then use the newest-created watermark for incremental polling. Include a test with more than DEPLOYMENT_PAGES_PER_TICK * PAGE_SIZE deployments.
Was this helpful? React with 👍 or 👎 to provide feedback.
| const reconciled = yield* Effect.result( | ||
| reconcileDrains(claimed, token, forwarding, ingestKey.success, false), |
There was a problem hiding this comment.
🔴 Concurrent poll restores old drain settings
If settings change during pollOrg, its stale claimed snapshot can overwrite the new drain configuration. The saved settings then disagree with Vercel until another poll repairs them.
Learn more
A poll claims a lease and holds a snapshot of the forwarding settings. updateSettings does not wait for that lease: it saves and reconciles new settings concurrently. When the older poll later calls reconcileDrains using claimed, it patches the drains back to the old settings, and saveOutcomes records the old outcome. The next successful poll can eventually restore the saved configuration, but telemetry in the interval uses the wrong settings.
Example: The poll reads logsEnabled=true; an admin disables logs and the save deletes the log drain. The poll then creates that log drain again from its old snapshot, although the status says logsEnabled=false.
Recommended fix: Serialize settings changes with polling on the same connection, or reload forwarding settings and validate their revision before reconciling and saving outcomes. Test a poll paused before listing drains while a settings save completes.
Was this helpful? React with 👍 or 👎 to provide feedback.
| // Every picked project was deleted on Vercel: there is nothing to forward, and no valid body. | ||
| const nothingPicked = forwarding.projectScope === "some" && forwarding.projectIds.length === 0 | ||
| const write = nothingPicked | ||
| ? undefined | ||
| : kept === undefined |
There was a problem hiding this comment.
🟡 Empty project selection leaves idle drains
When discovery removes every selected project, nothingPicked skips reconciliation but retains enabled drains. The integration reports healthy drains although they no longer forward any projects.
Learn more
The discovery pass prunes deleted project IDs, so a some scope can become empty. reconcileDrain then leaves existing drains in place and reports their old status rather than deleting or marking them as unable to forward. The health display treats these enabled drains as healthy, even though no project remains selected.
Example: An admin selects only prj_old; Vercel deletes that project. On the next hourly discovery the saved IDs become [], while both drains remain enabled and the card shows healthy.
Recommended fix: Represent an empty selection as an explicit attention state or disable/delete the drains when no projects remain, and expose a recoverable state in the status and UI.
Was this helpful? React with 👍 or 👎 to provide feedback.
| if span.attributes.iter().any(|attr| attr.key == COST) { | ||
| return; | ||
| } | ||
| let cost = span.attributes.iter().find_map(|attr| { |
There was a problem hiding this comment.
Warning
normalize stamps a non-USD gateway cost as gen_ai.usage.cost
F10 · Warning · correctness
vercel.ai_gateway.cost.total is copied into gen_ai.usage.cost without reading vercel.ai_gateway.cost.currency, so a request billed in any other currency is restated as USD and summed into maple_ai.usage.cost and the session/model cost totals. This PR's own vercelAiGatewaySummarySQL guards the same field with sumIf(..., inList(currency, ["", "USD"])), so the session cost and Infrastructure → Vercel disagree for the same request.
Read `vercel.ai_gateway.cost.currency` and only emit `gen_ai.usage.cost` when it is absent or `USD`; add a test with `cost.currency: "EUR"` asserting no cost attribute.
🤖 Prompt to fix with an AI agent
In `apps/ingest/src/ai_session/vercel_ai_gateway.rs:38`: `normalize` stamps a non-USD gateway cost as `gen_ai.usage.cost`.
`vercel.ai_gateway.cost.total` is copied into `gen_ai.usage.cost` without reading `vercel.ai_gateway.cost.currency`, so a request billed in any other currency is restated as USD and summed into `maple_ai.usage.cost` and the session/model cost totals. This PR's own `vercelAiGatewaySummarySQL` guards the same field with `sumIf(..., inList(currency, ["", "USD"]))`, so the session cost and Infrastructure → Vercel disagree for the same request.
Suggested fix: Read `vercel.ai_gateway.cost.currency` and only emit `gen_ai.usage.cost` when it is absent or `USD`; add a test with `cost.currency: "EUR"` asserting no cost attribute.
Verify the problem exists at that location before changing it, and keep the fix to those lines.
| claimed.deploymentsWatermarkAt ?? 0, | ||
| ...listed.success.map((d) => d.createdAt), | ||
| ) | ||
| if (newest > 0) yield* write({ deploymentsWatermarkAt: newest }) |
There was a problem hiding this comment.
Warning
Deployment watermark advances past the page cap, dropping unread deployments
F11 · Warning · correctness
The poll writes the newest listed deployment as deploymentsWatermarkAt even when listDeployments stopped at its page cap, so on the first pass (since 7 days back, newest-first listing) a team with more deployments than the cap only ever sees the newest pages and every older deployment is skipped for good. Those projects keep an empty deployment list on the Infrastructure → Vercel pages.
Have `listDeployments` report whether the last page was reached, and only advance the watermark when the listing was complete (or advance it to the oldest fetched page so the next tick resumes).
🤖 Prompt to fix with an AI agent
In `packages/backend/src/services/integrations/VercelIntegrationService.ts:1218`: Deployment watermark advances past the page cap, dropping unread deployments.
The poll writes the newest listed deployment as `deploymentsWatermarkAt` even when `listDeployments` stopped at its page cap, so on the first pass (`since` 7 days back, newest-first listing) a team with more deployments than the cap only ever sees the newest pages and every older deployment is skipped for good. Those projects keep an empty deployment list on the Infrastructure → Vercel pages.
Suggested fix: Have `listDeployments` report whether the last page was reached, and only advance the watermark when the listing was complete (or advance it to the oldest fetched page so the next tick resumes).
Verify the problem exists at that location before changing it, and keep the fix to those lines.
| onIdle: () => null, | ||
| onLoading: () => null, | ||
| onFailure: () => "failed" as const, | ||
| onStale: () => "failed" as const, |
There was a problem hiding this comment.
Warning
A failed revalidation leaves the Vercel card's quick metrics as permanent skeletons
F12 · Warning · correctness
When a read that previously succeeded fails, Keyed.accept leaves AsyncData.Stale({ data, error }); readOf maps that to "failed" and discards the data, while failureOf/usageFailure only match AsyncData.isFailure, so quickMetrics renders statRailLoading forever with no error text and no retry. The admin sees a card that never finishes loading instead of the retained numbers plus an error.
Treat `onStale` as stale-with-data: pass the retained `data` to the value function and surface `error` through `usageFailure`/`errorState`.
🤖 Prompt to fix with an AI agent
In `apps/web/src/page/integrations/view-vercel.ts:257`: A failed revalidation leaves the Vercel card's quick metrics as permanent skeletons.
When a read that previously succeeded fails, `Keyed.accept` leaves `AsyncData.Stale({ data, error })`; `readOf` maps that to `"failed"` and discards the data, while `failureOf`/`usageFailure` only match `AsyncData.isFailure`, so `quickMetrics` renders `statRailLoading` forever with no error text and no retry. The admin sees a card that never finishes loading instead of the retained numbers plus an error.
Suggested fix: Treat `onStale` as stale-with-data: pass the retained `data` to the value function and surface `error` through `usageFailure`/`errorState`.
Verify the problem exists at that location before changing it, and keep the fix to those lines.
|
|
||
| export function vercelHealth(status: VercelIntegrationStatus): VercelHealth { | ||
| if (vercelIssues(status).length > 0) return "attention" | ||
| return status.lastSuccessAt === null ? "pending" : "healthy" |
There was a problem hiding this comment.
Warning
vercelHealth ignores status.lastError, so a failed first sync reads as "First sync pending"
F13 · Warning · correctness
The backend records lastError on a failed pass without advancing lastSuccessAt, but the derivation keys only on lastSuccessAt, and isVercelSettling stops the 15 s re-reads once connectedAt is ten minutes old — so an org whose token is rejected or whose poll keeps timing out shows "First sync pending", no issue row and no retry, forever. apps/web/src/page/integrations/derive.ts:295 derives the same wrong state for the hub row.
Return `"attention"` plus an issue when `status.lastError !== null` (or when `lastSuccessAt === null` and `connectedAt` is older than the settling window), and apply the same rule in `derive.ts`'s `vercelHealth`.
🤖 Prompt to fix with an AI agent
In `apps/web/src/components/integrations/vercel-model.ts:181`: `vercelHealth` ignores `status.lastError`, so a failed first sync reads as "First sync pending".
The backend records `lastError` on a failed pass without advancing `lastSuccessAt`, but the derivation keys only on `lastSuccessAt`, and `isVercelSettling` stops the 15 s re-reads once `connectedAt` is ten minutes old — so an org whose token is rejected or whose poll keeps timing out shows "First sync pending", no issue row and no retry, forever. `apps/web/src/page/integrations/derive.ts:295` derives the same wrong state for the hub row.
Suggested fix: Return `"attention"` plus an issue when `status.lastError !== null` (or when `lastSuccessAt === null` and `connectedAt` is older than the settling window), and apply the same rule in `derive.ts`'s `vercelHealth`.
Verify the problem exists at that location before changing it, and keep the fix to those lines.
| project?.framework === null || project === null ? undefined : heroChip(h, project.framework), | ||
| meta: | ||
| production === null | ||
| ? [h.span([h.Class("text-2xs text-muted-foreground")], ["No production deployment recorded"])] |
There was a problem hiding this comment.
Warning
A failed vercelStatus read renders as "No production deployment recorded"
F14 · Warning · correctness
projectStatusOf returns null for both "loading" and "the read failed", so a failed LoadVercelProjectStatus makes the header claim the project has no production deployment, drops the framework chip and leaves the raw prj_… id as the page title. The model's Message union has no retry for this slot, so the read can never be re-issued without reloading the page; the list page shows an errorState with a retry for the same data.
Give the status slot a failure branch like the list page's plus a `ClickedRetryStatus` message, and keep the "No production deployment recorded" line for loaded data only.
🤖 Prompt to fix with an AI agent
In `apps/web/src/page/infra-integrations/vercel/project/view.ts:640`: A failed `vercelStatus` read renders as "No production deployment recorded".
`projectStatusOf` returns `null` for both "loading" and "the read failed", so a failed `LoadVercelProjectStatus` makes the header claim the project has no production deployment, drops the framework chip and leaves the raw `prj_…` id as the page title. The model's `Message` union has no retry for this slot, so the read can never be re-issued without reloading the page; the list page shows an `errorState` with a retry for the same data.
Suggested fix: Give the status slot a failure branch like the list page's plus a `ClickedRetryStatus` message, and keep the "No production deployment recorded" line for loaded data only.
Verify the problem exists at that location before changing it, and keep the fix to those lines.
| h, | ||
| { | ||
| className: "w-44", | ||
| defaultValue: String(draft.samplingRate), |
There was a problem hiding this comment.
Warning
The sampling select shows 100% for a connection saved at any rate outside VERCEL_SAMPLING_RATES
F15 · Warning · correctness
Vercel accepts any rate in 0.01–1 and the settings PATCH stores what it is sent, so a connection saved at e.g. samplingRate: 0.3 produces defaultValue: "0.3", which matches no nativeOption; the browser selects the first entry ("Everything") while the drains panel prints "30% of events" for the same connection. changedSampling (update-vercel.ts:304) also drops any value outside the list, so the admin cannot re-pick the stored rate.
Append the saved rate as an option when it is not in `VERCEL_SAMPLING_RATES` so the control always reflects `draft.samplingRate`.
🤖 Prompt to fix with an AI agent
In `apps/web/src/page/integrations/view-vercel-configure.ts:416`: The sampling select shows 100% for a connection saved at any rate outside `VERCEL_SAMPLING_RATES`.
Vercel accepts any rate in 0.01–1 and the settings PATCH stores what it is sent, so a connection saved at e.g. `samplingRate: 0.3` produces `defaultValue: "0.3"`, which matches no `nativeOption`; the browser selects the first entry ("Everything") while the drains panel prints "30% of events" for the same connection. `changedSampling` (`update-vercel.ts:304`) also drops any value outside the list, so the admin cannot re-pick the stored rate.
Suggested fix: Append the saved rate as an option when it is not in `VERCEL_SAMPLING_RATES` so the control always reflects `draft.samplingRate`.
Verify the problem exists at that location before changing it, and keep the fix to those lines.
| h.Autocomplete("off"), | ||
| h.Spellcheck(false), | ||
| h.Placeholder("Paste a token"), | ||
| ...Field.controlAttributes(h, configure.token, (message) => |
There was a problem hiding this comment.
Caution
Credential configure.token written to a span attribute
F18 · Critical · security · PII-01
Anyone who can read the organization's telemetry can read it, for the whole retention window. Drop it, or record only whether it is set, and rotate any value already sent.
🤖 Prompt to fix with an AI agent
In `apps/web/src/page/integrations/view-vercel-configure.ts:116`: Credential `configure.token` written to a span attribute.
Anyone who can read the organization's telemetry can read it, for the whole retention window. Drop it, or record only whether it is set, and rotate any value already sent.
Verify the problem exists at that location before changing it, and keep the fix to those lines.
|
Removed the |







Adds Vercel and Vercel AI Gateway as an infrastructure integration.
An admin pastes a Vercel access token on Integrations → Vercel, picks a team, projects, a sampling rate, and logs and/or traces. Maple then creates two drains on that team:
POST /v1/logpush/vercel(Bearer org ingest key, same auth, billing and limits as/v1/logs), mapped to OTel logs withvercel.*,http.*andurl.*attributes/v1/traces, which also carries AI Gateway traces (service.name=ai-gateway)What's in it
vercel_connections,vercel_projects,vercel_deployments(one migration); the token is AES-GCM encrypted/internal/integrations/vercel(status, discover, connect, settings, sync, disconnect, deployments)vercelon cron2-59/5 * * * *?maple_org=marker on the endpoint. It deletes duplicates, patches drift and ingest-key rotations, and recreates missing drains, so concurrent connects or interrupted runs settle within one tickvercel_logs.rsmapper: JSON array or NDJSON, gzip; bad lines are skippedvercel_ai_gateway: cost fromvercel.ai_gateway.cost.total, only server spans count, one session per request/lab/verceland/lab/infraintegrations/vercel.mddocsCFG-INTEG-07list_infra/inspect_infrakinds andsync_vercelvercelservice-map platformOut of V1: Observability Plus metrics API, a Vercel OAuth/Marketplace app, the AI Gateway reporting API.
Verification
tsrs --noEmitpasses in web, api, ai, alerting, backend, domain, db, query-engine-integrations, ui and local-uicargo testpasses for the vercel and ai_session suites (112) and the route test (NDJSON, gzip,[]→ 200, malformed → 400, no key → 401)CLICKHOUSE_E2E=1catalog e2e) passes 482/482, including all 11 new Vercel queriesScreenshots (lab fixtures)
Need help on this PR? Tag
@codesmith-botwith what you need.Summary by CodeRabbit