The short version: Fair Lawn Apps runs on Cloudflare's edge network with HTTPS everywhere, uses passkeys instead of passwords, stores minimal data with automatic expiration, and never handles sensitive personal information.

Overview

Fair Lawn Apps is a community project that makes public information from fairlawn.org and other sources more accessible. It handles gym schedules, library programs, pool hours, local alerts, Farmers Market status, and theater events.

The amount of data involved is deliberately small: push notification subscriptions, anonymous passkey credentials, and user preferences. There are no user accounts with names or emails, no payment processing, and no sensitive personal records. That limited scope is itself a security advantage โ€” there is very little to protect, and every layer described below exists to protect it.

Data in transit

All traffic between your browser and Fair Lawn Apps is encrypted with HTTPS (TLS 1.2+). There are no HTTP fallbacks.

Data at rest

Cloudflare Workers KV

Push subscriptions, notification preferences, occupancy reports, alert watches, and feedback are stored in Cloudflare Workers KV.

Cloudflare D1

The D1 SQLite database stores anonymous passkey accounts and sessions, managed through better-auth with the Drizzle ORM.

No PII beyond optional feedback email

The only personal information Fair Lawn Apps may hold is an email address if a user voluntarily provides one in the feedback form. That email is stored alongside the feedback message (with a 90-day TTL) and is used only if a follow-up is needed.

Authentication

Fair Lawn Apps uses passkeys (WebAuthn/FIDO2) for cross-device sync. This is entirely optional โ€” the apps work without any sign-in at all.

Secret management

All secrets are stored as Cloudflare Workers secrets (encrypted at rest, injected at runtime). None appear in source code or environment variables checked into the repository.

Bot protection

The feedback form is protected by Cloudflare Turnstile, a privacy-preserving CAPTCHA alternative. Turnstile verifies that submissions come from a real browser without fingerprinting users or showing image puzzles.

Push notifications

Push delivery follows the Web Push protocol with VAPID authentication (RFC 8292).

Rate limiting

Rate limits protect against abuse while preserving privacy.

OWASP Top 10 self-assessment

A brief status against the OWASP Top 10 (2021) categories.

A01 โ€” Broken Access Control

Admin endpoints (/notify, /stats) require an API key via the X-Api-Key header. CORS is configured per-endpoint: credentialed auth routes restrict the origin to the app domain; public data routes use Access-Control-Allow-Origin: * where appropriate (e.g., subscription PATCH uses endpoint-as-auth, no cookies needed).

A02 โ€” Cryptographic Failures

TLS everywhere. Session cookies signed with HMAC-SHA256. Push payloads encrypted per RFC 8291. Internal passwords are random UUIDs โ€” SHA-256 is appropriate for that entropy level.

A03 โ€” Injection

No raw SQL โ€” the D1 database is accessed exclusively through the Drizzle ORM with parameterized queries. User input (feedback messages, notification preferences) is validated and typed before use.

A04 โ€” Insecure Design

Minimal attack surface by design: anonymous accounts, no PII collection, automatic data expiration, and passkey-only authentication.

A05 โ€” Security Misconfiguration

TLS is managed by Cloudflare (automatic certificate renewal, modern cipher suites). The worker runs on Cloudflare's hardened V8 isolate runtime. No server configuration files to misconfigure.

A06 โ€” Vulnerable and Outdated Components

Dependencies are monitored via npm audit. Known CVEs in transitive dependencies (e.g., rollup, hono, lodash) are addressed via package.json overrides to force patched versions.

A07 โ€” Identification and Authentication Failures

Passkey-only authentication eliminates password reuse, credential stuffing, and phishing. No password reset flows. No security questions. Session tokens are HMAC-signed and transmitted over HTTPS only.

A08 โ€” Software and Data Integrity Failures

JSON.parse is used only on data from trusted sources (KV store, authenticated API responses). Svelte auto-escapes all rendered content โ€” no innerHTML or {@html} in user-facing components.

A09 โ€” Security Logging and Monitoring Failures

Worker errors and push delivery failures are logged via Cloudflare Workers analytics (console.error/console.warn). No sensitive data (tokens, keys, endpoints) appears in logs. Umami analytics tracks page views without cookies or personal data.

A10 โ€” Server-Side Request Forgery (SSRF)

The worker makes outbound requests only to fixed, hardcoded URLs: push endpoints (controlled by the browser, validated by the push service), the GitHub API, and Cloudflare's Turnstile verification endpoint. No user-controlled URLs are fetched server-side.

Incident response

In the event of a security incident:

New Jersey reporting requirements

Under New Jersey law (S297), entities holding personal data of NJ residents must report qualifying security incidents to the NJ Cybersecurity and Communications Integration Cell (NJCCIC) within 72 hours of discovery.

Because Fair Lawn Apps collects almost no personal data (no names, no payment information, and only optional email addresses in feedback), the scope of any reportable incident is inherently limited. That said, the 72-hour reporting obligation is taken seriously.

Contact

To report a security concern, use the feedback form. For anything urgent, include "SECURITY" in the message โ€” those are triaged immediately.

Third-party services

No data is shared with advertisers, data brokers, or other third parties. The services above are infrastructure providers, not data consumers.

Open source

Fair Lawn Apps is open source. The full codebase โ€” including the worker, scrapers, and all client apps โ€” is available on GitHub for anyone to inspect.

Last updated: March 16, 2026

See also: Privacy Policy ยท Terms of Service