feat(telemetry): add observability release wiring#175
Conversation
|
Warning Review limit reached
Next review available in: 7 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (45)
📝 WalkthroughWalkthroughThis PR implements an end-to-end anonymous telemetry observability loop. It adds a new Changes
Runtime telemetry: attribution and exception sanitization
Sentry source-map build wiring
Web surface observability scripts
CI/workflow environment gates and release wiring
Documentation, plans, and tooling updates
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub. |
|
Warning Review the following alerts detected in dependencies. According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.
|
Preview DeployedLanding: https://pr-175.preview.caplets.dev Built from commit 6ef4a65 |
|
| Filename | Overview |
|---|---|
| packages/web-observability/src/privacy.ts | New browser-side Sentry/PostHog filter; sanitizes filenames, function names, and exception types — but sanitizeBrowserException is missing the empty-frames guard present in the server-side equivalent. |
| packages/core/src/cli.ts | Adds attribution claim/acknowledge lifecycle around the product telemetry event and wires error objects into reliability events; duplicates TELEMETRY_ARCHITECTURES/architectureForTelemetry from runtime.ts. |
| packages/core/src/telemetry/state.ts | Adds file-backed and env-var-backed attribution mechanism with claim/acknowledge/release lifecycle; logic looks correct and file is properly deleted after first successful acknowledgement. |
| packages/core/src/telemetry/privacy.ts | Adds sanitizeRuntimeException and sanitizeSentryException with proper empty-frames guard, stack line parser, and filename/function-name allowlists; server-side implementation is complete and consistent. |
| packages/web-observability/src/attribution.ts | New file implementing attributedInstallCommand — prepends the telemetry attribution sub-command before the install command; idempotency guard and runner detection look correct. |
| packages/web-observability/src/events.ts | New file defining typed web event schema, required/optional property sets, and bucket helpers; property validation and allowlist checks are thorough. |
| apps/catalog/src/scripts/observability.ts | New browser-side PostHog + Sentry init for the catalog surface; all persistence/recording features disabled, no PII in captured events. |
| apps/catalog/src/lib/server-observability.ts | New Cloudflare Worker Sentry reporting via manual envelope construction; only reports error type with no message or stack, no PII exposure. |
| packages/core/src/code-mode/static-analysis.ts | Adds ImportExpression to the executable import node check (Babel 8 dynamic import node type) and removes topLevelAwait/importAttributes plugins in favour of allowAwaitOutsideFunction; straightforward Babel 8 compatibility fix. |
| .github/workflows/deploy.yml | Maps consolidated secrets to PUBLIC_* variables for both the observability env check step and the deploy step; env block is consistent across both steps. |
| .github/workflows/release.yml | Renames CAPLETS_SENTRY_DSN to CAPLETS_RUNTIME_SENTRY_DSN and adds Sentry auth/org/project/release/environment secrets for source-map upload during runtime package releases. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[User visits landing / docs / catalog] -->|copy install command| B[attributedInstallCommand\nweb-observability]
B -->|prepends telemetry attribution marker cmd| C[Install command shown to user]
C -->|user pastes & runs| D[caplets telemetry attribution marker]
D -->|writeTelemetryAttribution| E[attribution.json on disk]
D -->|or CAPLETS_INSTALL_ATTRIBUTION env var| E
C --> F[caplets add / run ...]
F -->|captureCliTelemetry| G{telemetry enabled?}
G -- yes --> H[claimTelemetryAttribution\nread attribution.json or env var]
H --> I[buildProductTelemetryEvent\nwith attribution_source + first_activation]
I --> J[PostHog dispatch]
J --> K[acknowledgeTelemetryAttributionClaim\ndelete file + env var]
subgraph Browser Observability
L[Page load] -->|filterSentryBrowserEvent\nsanitizeBrowserException| M[Sentry]
L -->|buildWebEvent\nassertWebEventSafeProperties| N[PostHog]
end
subgraph Server Observability
O[Catalog worker error] -->|captureCatalogServerError\nexceptionFor - type only| P[Sentry envelope API]
end
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A[User visits landing / docs / catalog] -->|copy install command| B[attributedInstallCommand\nweb-observability]
B -->|prepends telemetry attribution marker cmd| C[Install command shown to user]
C -->|user pastes & runs| D[caplets telemetry attribution marker]
D -->|writeTelemetryAttribution| E[attribution.json on disk]
D -->|or CAPLETS_INSTALL_ATTRIBUTION env var| E
C --> F[caplets add / run ...]
F -->|captureCliTelemetry| G{telemetry enabled?}
G -- yes --> H[claimTelemetryAttribution\nread attribution.json or env var]
H --> I[buildProductTelemetryEvent\nwith attribution_source + first_activation]
I --> J[PostHog dispatch]
J --> K[acknowledgeTelemetryAttributionClaim\ndelete file + env var]
subgraph Browser Observability
L[Page load] -->|filterSentryBrowserEvent\nsanitizeBrowserException| M[Sentry]
L -->|buildWebEvent\nassertWebEventSafeProperties| N[PostHog]
end
subgraph Server Observability
O[Catalog worker error] -->|captureCatalogServerError\nexceptionFor - type only| P[Sentry envelope API]
end
Reviews (3): Last reviewed commit: "fix(telemetry): address observability re..." | Re-trigger Greptile
| return "external"; | ||
| } | ||
|
|
||
| function filterCategory( | ||
| changed: "trust" | "setup" | "tag" | "reset" | undefined, | ||
| ): NonNullable<WebEventProperties["filter_category"]> { | ||
| if (changed === "reset") return "clear"; | ||
| if (changed === "tag") return "tag"; |
There was a problem hiding this comment.
Search telemetry fires on every keystroke without debouncing
captureCatalogSearch is called from the input event listener on the search box (via applySearch), so every single keystroke generates a PostHog event. Typing a 10-character query produces 10 separate caplets_catalog_search events. A debounce of 400–500 ms on the search input handler would make the analytics data more useful and reduce event volume substantially.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
There was a problem hiding this comment.
Actionable comments posted: 15
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/core/src/telemetry/runtime.ts (1)
71-86: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy liftAttribution is consumed before you know the event was actually delivered.
consumeTelemetryAttribution()either deletes the stored marker immediately or replaysCAPLETS_INSTALL_ATTRIBUTIONon every call (packages/core/src/telemetry/state.ts, Lines 117-131). Doing that beforedispatcher.capture()means dropped sends can lose persisted first-activation data, and long-lived runtimes can stamp multiple successful events withfirst_activation: truewhile the env var is still present. This needs a read/delete-on-ack flow or an in-process latch, and the same eager-consume pattern is duplicated inpackages/core/src/cli.ts.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/core/src/telemetry/runtime.ts` around lines 71 - 86, The attribution is being consumed too early in runtime telemetry, before `dispatcher.capture()` confirms the event was delivered. Update `trackTelemetryEvent` in `runtime.ts` to only call `consumeTelemetryAttribution()` after a successful send, or gate it with an in-process latch so the same marker is not reused across multiple successes; make the flow acknowledge delivery before deleting or replaying attribution. Apply the same fix to the duplicated eager-consume logic in `cli.ts`, and keep the attribution handling aligned with `consumeTelemetryAttribution` and `attributionTelemetryProperties`.
🧹 Nitpick comments (2)
packages/core/test/telemetry-source-maps.test.ts (1)
31-39: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAssert the
sourcemapwiring explicitly.This loop only checks for helper names, so it still passes if a config imports
sentryConfiguredbut accidentally setsoutput.sourcemapback tofalse. Adding an assertion forsourcemap: sentryConfigured()would make the test cover the actual release contract.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/core/test/telemetry-source-maps.test.ts` around lines 31 - 39, The telemetry source maps test only verifies helper imports and can miss a broken sourcemap wiring; update the assertions in telemetry-source-maps.test to explicitly check that each config uses output.sourcemap: sentryConfigured() in addition to the existing runtimeSentryPlugins checks. Use the config variables coreConfig, cliConfig, opencodeConfig, and piConfig to locate the relevant expectations and ensure the release contract is covered directly.packages/core/test/telemetry-state.test.ts (1)
207-225: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd a second consume against the same env object.
This case stops after the first env-backed read, so it won't catch duplicate
first_activationtagging from repeated successful events in one process. Reusing the sameenvobject for a secondconsumeTelemetryAttribution()call would lock in the one-shot contract.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/core/test/telemetry-state.test.ts` around lines 207 - 225, The telemetry attribution test currently only exercises a single env-backed consume, so it misses repeated successful reads in one process. Update the test around consumeTelemetryAttribution and telemetryAttributionPath to call consumeTelemetryAttribution twice with the same env object for the safe marker case, and assert the second call is also undefined/no persistence so the one-shot behavior is locked in.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/catalog/src/lib/server-observability.ts`:
- Around line 16-20: The sentryEnvelopeUrl helper is stripping any DSN path
prefix and only using the host plus project id, which can send envelopes to the
wrong endpoint for proxied or self-hosted Sentry DSNs. Update sentryEnvelopeUrl
to preserve the full pathname prefix from the parsed URL while still extracting
the project id from the last path segment, and build the envelope URL using that
prefix before /api/{projectId}/envelope/. Keep the existing validation in
sentryEnvelopeUrl and ensure the new URL is derived from the same URL object.
In `@apps/catalog/src/pages/api/v1/catalog/install-signals.ts`:
- Around line 44-45: The 500 error path in the install-signals handler is being
blocked by awaiting best-effort telemetry. Update the catch block in the API
handler so `captureCatalogServerError(...)` is not awaited; instead, schedule it
via `waitUntil(...)` when available or invoke it fire-and-forget, while still
returning the failure response immediately.
In `@apps/catalog/src/scripts/virtual-results.ts`:
- Around line 134-138: The `captureCatalogSearch` call inside `applySearch()` is
now being triggered too often because the same filter controls are wired to both
`input` and `change`, causing one user interaction to emit
`caplets_catalog_search` twice. Update the event wiring in `virtual-results.ts`
so `applySearch()`/`captureCatalogSearch` is invoked only once per interaction,
and use the existing `filterChanged` path to preserve the intended telemetry in
`applySearch`, `captureCatalogSearch`, and the control listeners around the
`input`/`change` bindings.
In `@apps/docs/src/scripts/observability.ts`:
- Around line 106-115: The linkCategory helper is classifying root-relative
catalog URLs as docs because the href.startsWith("/") check runs before the
catalog match. Update linkCategory in observability.ts so catalog paths like
/caplets and /caplets/... are detected and returned as "catalog" before the
generic root-relative docs rule, while keeping the existing github, npm,
docs.caplets, and unknown handling intact.
In `@apps/docs/test/observability.test.ts`:
- Around line 6-12: The test currently only checks that
document.addEventListener is not mocked, which does not verify that
../src/scripts/observability actually registers the click handler. Update
observability.test.ts to spy on document.addEventListener before importing
observability, or assert the expected mocked analytics/navigation callback after
dispatching the click, so the test covers the listener registration path in
observability rather than the native API shape.
In `@apps/landing/src/scripts/observability.ts`:
- Around line 116-123: The shared link classifier in linkCategory is missing
/caplets routes, so those outbound clicks are falling through to unknown. Update
linkCategory in observability.ts to treat href values starting with /caplets
(including nested paths) as catalog, alongside the existing /catalog and
catalog.caplets checks, so telemetry matches the behavior in the shared
classifier from packages/web-observability/src/events.ts.
In `@packages/core/package.json`:
- Around line 126-131: The dependency bump to `@types/node` in the workspace
manifests should stay aligned with the current Node 22 runtime target. Update
the package.json entries that were changed so the type version matches Node 22
rather than exposing Node 26-only APIs, or make the runtime target move in
lockstep if that is the intended change. Check the shared workspace manifests,
including packages/core/package.json, for the same version to keep them
consistent.
In `@packages/core/rolldown.config.ts`:
- Line 19: The core build is currently disabling Sentry upload via
runtimeSentryPlugins("core", { disable: "disable-upload" }), which leaves the
Node-targeted `@caplets/core` artifacts unuploaded and un-symbolicated. Update the
core rolldown config so the Node outputs are uploaded as well, either by
removing the upload disable flag or by configuring runtimeSentryPlugins("core")
to include the Node-targeted build artifacts alongside the browser ones. Verify
the change in the core config and any related upload setup so stack frames from
the externalized `@caplets/core` output can resolve correctly.
In `@packages/core/src/telemetry/privacy.ts`:
- Around line 241-247: The `relativeSafePath()` path-collapsing logic is
accepting unsafe `packages/...` and `apps/...` suffixes even when they contain
`.` or `..` traversal segments, which lets hostile path structure survive
sanitization. Update the workspace match handling in `privacy.ts` so it only
returns a workspace path when every segment after `packages/` or `apps/` is a
valid non-traversal segment, and fall back to the existing basename/redaction
logic otherwise. Keep the fix localized to `relativeSafePath()` and its
workspace suffix check so the redaction boundary remains strict.
In `@packages/core/src/telemetry/state.ts`:
- Around line 120-125: Consume CAPLETS_INSTALL_ATTRIBUTION only once in
telemetry/state.ts by updating the helper that reads env attribution in state.ts
so a valid value is treated as one-time input: after
attributionFromMarker(envMarker) succeeds, clear or ignore the env marker for
subsequent calls and ensure any stored attribution file is removed or marked
consumed before returning. Update the shared attribution path used by the
CLI/runtime product-event flows so repeated calls to the same helper cannot
re-emit first_activation from the same process or from a leftover file on the
next success.
In `@packages/web-observability/src/attribution.ts`:
- Around line 11-15: The shared attributedInstallCommand helper is emitting a
POSIX-style environment prefix that breaks Windows shells. Update
attributedInstallCommand to avoid hardcoding CAPLETS_INSTALL_ATTRIBUTION=...
before the command, and instead generate shell-specific attribution syntax or
move the attribution payload into a cross-shell format that the CLI can read.
Use the existing attributedInstallCommand and attributionMarkerForSurface
symbols to locate the change.
In `@packages/web-observability/src/events.ts`:
- Around line 15-32: Model the telemetry payload as a discriminated union
instead of a single shared Partial: update WebEventProperties in events.ts and
the buildWebEvent() contract so each event name maps to its own required/allowed
properties. Use the event name as the discriminator and split the current
generic fields into per-event shapes so invalid mixes like
caplets_catalog_search with CTA-only fields or missing search buckets are
rejected at compile time. Keep the shared event symbols (WebEventProperties and
buildWebEvent) as the entry points, but make their typing enforce the correct
property set for each event.
In `@packages/web-observability/src/privacy.ts`:
- Around line 83-92: The filter in filterSentryBrowserEvent is forwarding
event.exception unchanged, so the browser-side privacy scrub is incomplete.
Update this function to sanitize the exception payload before assigning
filtered.exception, ideally by adding a browser-specific exception sanitizer
that strips raw message text and frame filenames/URLs, or omit exception
entirely when it cannot be proven safe. Make sure the beforeSend path that uses
filterSentryBrowserEvent continues to receive only sanitized exception data.
In `@scripts/check-web-observability-env.ts`:
- Around line 47-50: The URL validation in isHttpUrl currently allows both http
and https, which lets browser telemetry endpoints slip through with insecure
schemes. Tighten the checks in isHttpUrl and the related PostHog/Sentry
validation paths so only https: endpoints are accepted for browser-side
observability, and ensure any callers that rely on this helper reject http:
values during the environment check.
- Around line 43-44: The placeholder check in isNonPlaceholder is missing values
that are already rejected by the release gate, so align both validators. Update
the placeholder list used by isNonPlaceholder in check-web-observability-env to
also treat change-me and todo before release as invalid, matching the behavior
of checkTelemetryReleaseEnv. Keep the normalization logic the same so all
comparisons still use trimmed, lowercase values.
---
Outside diff comments:
In `@packages/core/src/telemetry/runtime.ts`:
- Around line 71-86: The attribution is being consumed too early in runtime
telemetry, before `dispatcher.capture()` confirms the event was delivered.
Update `trackTelemetryEvent` in `runtime.ts` to only call
`consumeTelemetryAttribution()` after a successful send, or gate it with an
in-process latch so the same marker is not reused across multiple successes;
make the flow acknowledge delivery before deleting or replaying attribution.
Apply the same fix to the duplicated eager-consume logic in `cli.ts`, and keep
the attribution handling aligned with `consumeTelemetryAttribution` and
`attributionTelemetryProperties`.
---
Nitpick comments:
In `@packages/core/test/telemetry-source-maps.test.ts`:
- Around line 31-39: The telemetry source maps test only verifies helper imports
and can miss a broken sourcemap wiring; update the assertions in
telemetry-source-maps.test to explicitly check that each config uses
output.sourcemap: sentryConfigured() in addition to the existing
runtimeSentryPlugins checks. Use the config variables coreConfig, cliConfig,
opencodeConfig, and piConfig to locate the relevant expectations and ensure the
release contract is covered directly.
In `@packages/core/test/telemetry-state.test.ts`:
- Around line 207-225: The telemetry attribution test currently only exercises a
single env-backed consume, so it misses repeated successful reads in one
process. Update the test around consumeTelemetryAttribution and
telemetryAttributionPath to call consumeTelemetryAttribution twice with the same
env object for the safe marker case, and assert the second call is also
undefined/no persistence so the one-shot behavior is locked in.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 408cf369-f5b6-4a54-87b9-99d7821521e9
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (79)
.changeset/tidy-observability-traces.md.github/workflows/deploy.yml.github/workflows/pr-preview-deploy.yml.github/workflows/release.ymlCONCEPTS.mdalchemy.run.tsapps/catalog/astro.config.mjsapps/catalog/package.jsonapps/catalog/src/lib/catalog-env.tsapps/catalog/src/lib/server-observability.tsapps/catalog/src/pages/api/v1/catalog/install-signals.tsapps/catalog/src/pages/caplets/[entryKey].astroapps/catalog/src/pages/index.astroapps/catalog/src/scripts/copy.tsapps/catalog/src/scripts/observability.tsapps/catalog/src/scripts/virtual-results.tsapps/catalog/test/observability.test.tsapps/catalog/test/virtual-results.test.tsapps/docs/astro.config.mjsapps/docs/package.jsonapps/docs/src/components/CapletsObservability.astroapps/docs/src/components/CapletsThemeProvider.astroapps/docs/src/content/docs/privacy/indexing.mdxapps/docs/src/content/docs/troubleshooting.mdxapps/docs/src/scripts/observability.tsapps/docs/test/observability.test.tsapps/docs/vitest.config.tsapps/landing/astro.config.mjsapps/landing/package.jsonapps/landing/src/pages/index.astroapps/landing/src/scripts/copy.tsapps/landing/src/scripts/observability.tsapps/landing/test/observability.test.tsapps/landing/vitest.config.tsdocs/plans/2026-06-28-002-feat-telemetry-observability-loop-plan.mddocs/product/anonymous-telemetry.mddocs/product/telemetry-provider-readiness.mddocs/product/telemetry-readout.mdmise.tomlpackage.jsonpackages/benchmarks/package.jsonpackages/cli/package.jsonpackages/cli/rolldown.config.tspackages/core/package.jsonpackages/core/rolldown.config.tspackages/core/src/cli.tspackages/core/src/code-mode/platform-runtime.generated.tspackages/core/src/code-mode/static-analysis.tspackages/core/src/telemetry/events.tspackages/core/src/telemetry/index.tspackages/core/src/telemetry/privacy.tspackages/core/src/telemetry/providers.tspackages/core/src/telemetry/runtime.tspackages/core/src/telemetry/state.tspackages/core/test/telemetry-docs.test.tspackages/core/test/telemetry-events.test.tspackages/core/test/telemetry-providers.test.tspackages/core/test/telemetry-redaction.test.tspackages/core/test/telemetry-release.test.tspackages/core/test/telemetry-runtime.test.tspackages/core/test/telemetry-source-maps.test.tspackages/core/test/telemetry-state.test.tspackages/opencode/package.jsonpackages/opencode/rolldown.config.tspackages/pi/package.jsonpackages/pi/rolldown.config.tspackages/web-observability/package.jsonpackages/web-observability/src/attribution.tspackages/web-observability/src/events.tspackages/web-observability/src/index.tspackages/web-observability/src/privacy.tspackages/web-observability/test/web-observability.test.tspackages/web-observability/tsconfig.jsonpackages/web-observability/vitest.config.tspnpm-workspace.yamlscripts/check-sentry-source-maps.tsscripts/check-telemetry-release-env.tsscripts/check-web-observability-env.tsscripts/runtime-sentry-rolldown.ts
Summary
Runtime and web telemetry now produce useful anonymous usage and error signals across the CLI, landing page, docs, and catalog without exposing user content. Sentry source maps are uploaded from all runtime package builds and the web deploy/release workflows now map consolidated GitHub secrets into the public/runtime environment variables each target needs.
This also refreshes the workspace dependency/toolchain set, including Astro 7, Vite 8, pnpm 11.9 via
mise.toml, and Babel 8. Code Mode static analysis now recognizes Babel 8ImportExpressionnodes so dynamic imports still produce the intendedIMPORT_UNAVAILABLEdiagnostic instead of falling through to cryptic TypeScript errors.Notes
PUBLIC_*only at build/deploy time.caplets,@caplets/opencode,@caplets/pi, and@caplets/coreall use the Sentry Rollup plugin for source map upload.Validation
pnpm verifypnpm verifysuccessfully before pushingSummary by CodeRabbit
New Features
Bug Fixes
Documentation