The l4-port-manager service had a Dockerfile but was missing from the
GitHub Actions build matrix, so it was never built or pushed to GHCR.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Switch package manager and runtime from Node.js/npm to Bun across
Docker, CI, and scripts. The SQLite driver remains better-sqlite3
due to Next.js Turbopack being unable to resolve bun:sqlite during
build-time page pre-rendering.
Also fix the world map not rendering in the analytics page — the
overflowX wrapper added for mobile broke the flex height chain,
collapsing the map to 0px.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- test.yml: add pull_request trigger (safe — permissions: {}, no secrets
referenced; pull_request event from forks gets no secrets and read-only token)
- stale.yml: add explicit permissions (issues: write, pull-requests: write)
instead of relying on potentially over-broad repo defaults
- docker-build-pr.yml: add actions: write permission required for GHA
cache writes (cache-to: type=gha)
Remaining known limitation: actions are pinned to tags (@v3/@v6) rather
than SHAs — moving a tag upstream would run arbitrary code. Low risk for
official Docker/GitHub actions but worth noting.
ci: remove cache-to from PR build, drop actions: write permission
PR builds read from the GHA cache (warmed by main branch pushes) but
don't write back. This avoids needing actions: write on a job that runs
untrusted PR code.
ci: restrict test job permissions to zero
Zero out GITHUB_TOKEN permissions and remove the non-existent
ACTIONS_RUNNER_NO_SECRETS variable. No repo secrets are referenced
in this workflow, so the test runner has no credentials available.
The workflow only triggers on push to protected branches (not PRs),
so code is reviewed before it runs.
ci: add test workflow to run unit/integration tests on push
Runs `npm test` (Vitest unit + integration tests) on every push to
main and develop. E2E tests are excluded as they require a full
Docker Compose stack.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fixed error: "docker exporter does not currently support exporting manifest lists"
The issue occurred because SBOM and provenance attestations create manifest
lists, which cannot be loaded to the local Docker daemon (required for PRs).
Changes:
- Made sbom conditional: only enabled for push events (not PRs)
- Made provenance conditional: only enabled for push events (not PRs)
- PRs now build without attestations (faster, avoids manifest list error)
- Production pushes still get full SBOM and provenance attestations
This allows:
- PR builds to complete successfully with load=true
- Production builds to maintain supply chain security features
Fixed critical workflow issues preventing builds:
1. Job Dependency Structure:
- build-and-push now properly depends on security-check with always()
- Allows push/tag events to run even when security-check is skipped
- Only pull_request events trigger security-check
- Conditional logic checks needs.security-check.result to handle skipped cases
2. Platform vs Load Conflict:
- Removed platform specification for PR builds (load=true)
- load: true only works with single platform matching host
- Multi-platform (linux/amd64,linux/arm64) only for push events
- Empty string for platforms when using load to avoid conflicts
3. Conditional Logic Improvements:
- push events: always run (security-check skipped)
- workflow_dispatch: always run (security-check skipped)
- pull_request: only run if security-check succeeded and not a fork
- pull_request_target: only run if has 'safe-to-build' label
This ensures:
- Branch pushes work correctly
- Tag builds work correctly
- PRs are security-checked before building
- Fork PRs require manual approval
Fixed two critical build failures:
1. Platform Selection Bug:
- Fixed operator precedence issue in platform conditional
- Was evaluating to boolean 'true' instead of platform string
- Changed: platforms: ${{ ... || ... && 'linux/amd64' || ... }}
- To: platforms: ${{ (... || ...) && 'linux/amd64' || ... }}
- Now correctly uses linux/amd64 for PRs, linux/amd64,linux/arm64 for releases
2. Trivy Multiple Tags Issue:
- Trivy was receiving multiple tags separated by newlines
- Added step to extract first tag from metadata output
- Trivy now scans using single tag reference
- Prevents "multiple targets cannot be specified" error
Both PRs and production builds should now complete successfully.
Changed from SHA-pinned actions to version tags (e.g., @v3, @v4, @v5)
for easier maintenance and automatic security updates via Dependabot.
While SHA pinning provides slightly better supply chain security, version
tags with Dependabot updates provide a better balance of security and
maintainability for most projects.
Updated actions:
- actions/checkout@v4
- docker/setup-buildx-action@v3
- docker/login-action@v3
- docker/metadata-action@v5
- docker/build-push-action@v5
- aquasecurity/trivy-action@0.24.0
- github/codeql-action/upload-sarif@v3
Dependabot will automatically create PRs for security updates.
Security Improvements:
- Fork PR Protection: Builds from forks require manual 'safe-to-build' label approval
- Trivy Vulnerability Scanning: Scan all images for CRITICAL/HIGH vulnerabilities
- SHA-Pinned Actions: All GitHub Actions pinned to specific commits for supply chain security
- SBOM Generation: Generate Software Bill of Materials for all builds
- Provenance Attestation: Record build provenance for supply chain verification
- Security Events Upload: Upload scan results to GitHub Security tab
- Platform Optimization: Single-platform builds for PRs for faster feedback
Additional Security:
- Created SECURITY.md with vulnerability reporting process and security practices
- Added Dependabot configuration for automated dependency updates
- Limited permissions model (contents:read, packages:write, security-events:write)
- No registry push from PR builds (load-only for security scanning)
This addresses concerns about malicious PR builds by:
1. Requiring manual approval for fork PRs
2. Scanning all images before they could be pushed
3. Preventing PR builds from pushing to registry
4. Using verified, SHA-pinned actions
Remove the prefix={{branch}}- from the sha tag type which was causing
invalid tag formats like ":-cbc2c2c" when building pull requests.
The {{branch}} placeholder becomes empty for PRs, leaving only the dash
prefix which creates an invalid Docker tag.
Changed from: type=sha,prefix={{branch}}-
Changed to: type=sha
This generates valid tags like "sha-cbc2c2c" for all events.
* Correcting X-XSS-Protection Header
X-XSS-Protection sets the configuration for the cross-site scripting filters built into most browsers. The best configuration is "X-XSS-Protection: 1; mode=block".
Was "0"
Now "1; mode=block"
* Update issue templates