Files
meshcore-analyzer/.gitattributes
TeTeHackoandClaude Opus 5.5 684f89f200 feat(frontend): serve Leaflet, leaflet.heat and Chart.js from vendor/, not unpkg.com (#2299)
Refs #1554.

`index.html`, `area-map.html` and `geofilter-builder.html` load Leaflet,
leaflet.heat and Chart.js from **unpkg.com** on every page view. That
causes three problems:

- **Privacy:** every visitor sends a request to a third party.
- **Availability:** where unpkg is blocked (script blockers, filtered
networks) or down, the map and every chart are gone. The observer page
then fails with `Error: Chart is not defined`.
- **#1554:** the CSP target there, `script-src 'self'`, blocks these
scripts just like the inline handlers the issue lists, but they are
missing from its inventory.

## Change

- **Vendored libraries:** `public/vendor/leaflet-1.9.4/` (with
`images/`), `vendor/leaflet-heat-0.2.0.js` and
`vendor/chart-4.5.1.umd.min.js`.
- They are the unpkg dist files byte for byte, verified against the SRI
hashes `index.html` already pins.
- The two standalone pages loaded Leaflet without SRI; they now carry
it.
  - This is the same pattern as `vendor/leaflet.markercluster.js`.
- **`.gitattributes`:** `public/vendor/** -text`. Otherwise `* text=auto
eol=lf` rewrites `leaflet.css`, which ships with CRLF, and the browser
refuses it for the integrity mismatch. I hit exactly that while
preparing this.
- **`scripts/instrument-frontend.sh`:** now copies `vendor/`
recursively. The flat `cp public/vendor/*` left the E2E server without
`vendor/leaflet-1.9.4/`, which showed up as `L is not defined`.
- **New test `tests/unit/test-vendored-libs.js`:**
  - no off-site `<script src>` or stylesheet in the served pages
  - every `integrity` attribute matches its vendored file
  - the images Leaflet's stylesheet references exist

  I checked that it fails against the old `index.html`.

## Checks

- `sh test-all.sh` passes.
- These E2E suites pass against the fixture: `test-e2e-playwright.js`,
`test-analytics-fluid-charts.js`, `test-issue-1236-map-mobile-e2e.js`
and `test-issue-1329-map-controls-accordion-e2e.js`.
- On a live instance, a headless browser with `unpkg.com`, `jsdelivr`
and `cdnjs` blocked:
  - the observer page renders all four charts
  - the map loads tiles and markers
  - `typeof L` and `typeof Chart` are defined
  - no CDN request is made and no page error occurs

## Not in this PR

Swagger UI on `/api/docs` (`cmd/server/openapi.go`) still loads
`swagger-ui-dist` from unpkg. I can vendor it in a follow-up if wanted.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 15:43:16 +01:00

23 lines
623 B
Plaintext

# Force LF line endings for all text files (prevents CRLF churn from Windows agents)
* text=auto eol=lf
# Vendored third-party files stay byte-identical to upstream: index.html
# pins their SRI hashes, and an EOL rewrite (leaflet.css ships with CRLF)
# makes the browser refuse them.
public/vendor/** -text
# Explicitly mark binary files
*.png binary
*.jpg binary
*.ico binary
*.db binary
# Squad: union merge for append-only team state files
.squad/decisions.md merge=union
.squad/agents/*/history.md merge=union
.squad/log/** merge=union
.squad/orchestration-log/** merge=union
manage.sh text eol=lf
*.sh text eol=lf