Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,14 @@ RUN --mount=type=secret,id=sentry_auth_token \
FROM caddy:2-alpine
COPY Caddyfile /etc/caddy/Caddyfile
COPY --from=builder /app/web/dist /srv
# Source maps must never ship (ADR 0014). When a Sentry token is present, Vite
# emits hidden maps and the plugin uploads then deletes them (see the builder
# note above) — but nothing verifies that delete succeeded. If it silently
# fails (or a toolchain change alters the behavior), maps would be served
# publicly. Unconditional: runs on every build of this image regardless of
# whether maps were emitted. `&&`/`||` routing makes a find error fail the
# build too, rather than pass it vacuously.
RUN maps="$(find -L /srv -name '*.map')" && [ -z "$maps" ] || \
{ echo 'ERROR: source maps leaked into served assets (Sentry upload/delete likely failed):'; \
printf '%s\n' "$maps"; exit 1; }
EXPOSE 8080
2 changes: 1 addition & 1 deletion docs/adr/0014-sentry-source-maps-and-release-commits.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ The release name matches `VITE_SENTRY_RELEASE` (the git tag) already set in `ins
## Consequences

- Production traces de-minify to real `*.tsx:line`; releases appear in Sentry with their commits, enabling suspect-commit blaming and regression detection.
- The token never touches an image layer and no `.map` is served — verified by building the image with no secret and confirming `find /srv -name '*.map'` is empty.
- The token never touches an image layer and no `.map` is served. The no-`.map` invariant is enforced by an unconditional guard in the Dockerfile's serve stage that fails any image build (PR, push-to-main, or release) if a `.map` file survives into the served assets — automating what was originally a one-off manual check, and covering the release path where the plugin's delete step actually runs.
- `@sentry/cli` (a plugin dependency) ships a native binary; its build script is allow-listed in `pnpm-workspace.yaml` (`onlyBuiltDependencies`) so the Alpine image build has it. The single static `linux-x64` binary runs on musl.
- **Dependency-footprint + licensing (per [ADR 0001](0001-standalone-public-repo.md)).** This adds `@sentry/vite-plugin` (MIT) and ~15 transitive packages, including **`@sentry/cli`, licensed FSL-1.1-MIT — source-available, *not* OSI-approved** (it converts to MIT two years after each release). The footprint grows but FreightDesk's *distributed* artifact stays MIT-clean: `@sentry/vite-plugin` is a **devDependency**, and the published image is `caddy:2-alpine` + the static `dist` only — the builder stage holding `@sentry/cli` and its binary is discarded, so no FSL code is ever redistributed. The FSL terms (no competing product for 2 years) don't bite either: FreightDesk merely invokes the tool at build time and isn't a Sentry competitor. There is no MIT-licensed equivalent for Sentry source-map upload, so this is the cost of de-minified traces. Recorded explicitly because ADR 0001 makes the dependency footprint and licensing a reviewable public-facing artifact, not a silent default.
- **Stays forker-generic / no admin-token dependency (per [ADR 0001](0001-standalone-public-repo.md)).** The build no-ops without `SENTRY_AUTH_TOKEN`: a forker clones and `pnpm build` / `docker build`s with zero Sentry config and gets a working app — no maps emitted, no upload attempted, no failure. The token is the canonical operator's convenience, a separable secret, never a build prerequisite.
Expand Down
Loading