SB Sommar – Project Documentation

SB Sommar – Requirements: Platform and Security

Cross-cutting platform concerns: reliability, accessibility, Swedish language, security hardening, analytics, feedback, PWA, admin token, rate limiting.

Part of the requirements index. Section IDs (02-§N.M) are stable and cited from code; they do not encode the file path.


12. Reliability

Participants must be able to trust that:

The schedule is a shared coordination tool during the camp week.



13. Accessibility

The site must meet WCAG AA as a baseline:



14. Language

The site is written entirely in Swedish.

This includes: all page content, navigation labels, form labels, error messages, confirmation messages, and accessibility text (alt, aria-label, etc.).



39. CodeQL Alert Remediation

GitHub CodeQL static analysis reports six alerts across workflows, server code, and test files. All must be resolved so the repository reaches zero open CodeQL alerts.

39.1 Workflow permissions (CI)

39.2 Workflow permissions (deploy)

39.3 ReDoS-safe slugify

39.4 Test assertion specificity

39.5 Verification



49. API-Layer Security Validation

The event security scan (injection patterns, link protocol, length limits) currently runs only in CI as a post-commit check. This means malicious payloads can reach the git repository before being caught. Moving these checks into the API request validation layer rejects dangerous input at submission time — before any data is written to git.

This change does not remove the existing CI security scan; it adds an earlier, identical check. The CI scan will be removed in a future pipeline optimisation.

49.1 Injection pattern scanning in the API

49.3 Parity between Node.js and PHP implementations



63. Site Analytics

The site needs usage analytics to answer questions about traffic, visitor behaviour, and content effectiveness. Analytics must respect the static-site, no-backend, minimal-JS constraints.

63.1 Tool choice

63.2 Environment scope

63.3 Script inclusion

63.4 Basic traffic (automatic)

GoatCounter provides these automatically — no custom code required:

63.5 Custom events (behaviour tracking)

The following interactions must be tracked as GoatCounter custom events:

63.6 QR code referrer tracking

63.7 Constraints



73. Feedback Button (GitHub Issues)

A discreet feedback button in the navigation bar lets any visitor submit feedback that is automatically created as a GitHub Issue. The feature uses the same API patterns as add-event (Node.js + PHP dual implementation) and the same GitHub API primitives.

73.1 User requirements

73.2 API requirements

73.3 Validation requirements

73.4 Accessibility requirements

73.5 Metadata collection

73.6 Implementation parity

73.7 Clarity requirements

73.8 Local environment warning


83. Progressive Web App (PWA) Support

The site must be installable as a Progressive Web App so participants can add it to their home screen and use it in a standalone app-like experience. A service worker provides offline caching so that core pages and recent event data remain accessible without network connectivity.

83.1 Web App Manifest (site requirements)

83.2 HTML head tags (site requirements)

83.3 Service worker (site requirements)

83.4 Icon assets (site requirements)

83.6 Offline fallback page (site requirements)

83.7 Implementation constraints



84. API Error Messages

When an API call fails, the user must receive an error message that helps them understand whether the problem is actionable or not.

84.1 User requirements

84.2 Site requirements


87. Manifest Metadata for Richer Install UI

Chrome requires additional manifest fields to show a richer install prompt. Missing fields degrade the install experience or block the install prompt on newer browser versions.

87.1 Manifest identity (site requirements)

87.2 Manifest screenshots (site requirements)

87.3 Constraints


88. PWA Install Guide

Many users — especially on iPhone — do not notice that the site can be installed as an app. A discreet install button in the top bar helps them discover this without being intrusive.

88.1 Install button in navigation (user requirements)

88.2 Platform-specific behaviour (site requirements)

88.3 Persistence (site requirements)

88.4 Constraints



91. Admin Token — Activation and Status Indicator

91.1 Context

The site uses a cookie-based ownership model where each participant can only edit events they created. During camp, one or two designated administrators need the ability to edit or delete any event — for example to correct mistakes, remove duplicates, or update events on behalf of participants who lost their cookie.

This requirement covers the token infrastructure: storage, activation, verification, and a visual status indicator. The edit/delete authorisation behaviour that uses this token is defined in §7, §18, and §89.

91.2 Admin tokens (site requirements)

91.3 Token verification endpoint (API requirements)

91.4 Admin activation page (user requirements)

91.5 Token expiry (site requirements)

91.7 Constraints



92. PWA Full Pre-Cache and Offline Guard

The PWA pre-caches every asset the build produces so the entire site works offline from the first launch after installation. Form pages and the feedback modal detect offline status and clearly communicate that submission requires an internet connection.

92.1 Build-time pre-cache manifest (site requirements)

92.2 Service worker (site requirements)

92.3 Offline guard — form pages (user requirements)

92.4 Offline guard — feedback modal (user requirements)

92.5 Constraints



93. Rate Limiting for Authorization Endpoints

93.1 Context

The API exposes four POST endpoints that either perform authorization (/verify-admin) or accept ownership-gated writes (/edit-event, /delete-event), plus the user-feedback channel (/feedback). CodeQL flagged three of these as missing rate limiting (alerts #40, #41, #42, rule js/missing-rate-limiting), which allows an attacker to brute-force admin tokens or hammer the GitHub write path. The feedback endpoint already enforces a per-IP rate limit through an in-memory / file-based counter; this requirement extends the same protection to the remaining authorization endpoints and consolidates the mechanism into a single reusable implementation per runtime.

93.2 Per-endpoint rate limits (API requirements)

93.3 Rate-limit implementation (site requirements)

93.4 Constraints



95. Security Hygiene: Regex Performance and Escaping

95.1 Context

CodeQL flagged four regex-related issues in the codebase:

Neither alert represents an active vulnerability — slug inputs come from authored camp data and the flagged test selectors are hardcoded — but both should be eliminated so the CodeQL queue stays actionable and future changes do not silently inherit the unsafe pattern.

95.2 Slugify performance (site requirements)

95.3 Regex escape helper (test infrastructure requirements)

95.4 Constraints



96. Self-Healing Service Worker Upgrade

96.1 Context

Clients that had visited the site before a deploy could end up serving a stale /style.css from the service worker’s Cache Storage even after a new service worker activated. Two factors combined to cause this:

  1. The pre-cache step used cache.addAll(PRE_CACHE_URLS) with default fetch semantics, which respects the browser’s HTTP cache. When the HTTP cache held a style.css copy from before the deploy (served with Cache-Control: max-age=604800), that stale copy was pulled directly into the new sb-sommar-v<N> cache.
  2. The service worker never called self.skipWaiting() or self.clients.claim(), so a freshly installed worker stayed in the waiting state until every existing client was closed. Users who kept the site open (especially as an installed PWA) never saw the new worker activate.

The result was that CSS changes landed on the server but did not reach existing clients — the banners added in §94 rendered as unstyled inline links on devices that had visited the site within the last week.

This section defines the service-worker upgrade behaviour that removes the need for any user action (no “clear cache and data”) to recover from a stale cache.

96.2 Service worker (site requirements)

96.3 Pre-cache URL list (site requirements)

96.4 Self-healing behaviour (user requirements)

96.5 Constraints