Skip to content

Latest commit

 

History

305 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🌐 Network Pro™ — Web Presence

Locking Down Networks, Unlocking Confidence™
Security, Networking, Privacy — Network Pro™

 

Vercel NPM Version Build and Publish to Registries
Code Style: Prettier stylelint Contributor Covenant

🚀 Project Overview

This GitHub repository powers the official web presence of Network Pro Strategies — a research- and infrastructure-focused technology initiative working across cybersecurity, digital systems, and privacy. Our work spans applied research and development, experimental infrastructure, educational tools and publications, and public advocacy for security- and privacy-respecting technology.

Technology Stack

Built with Svelte 5 and SvelteKit, deployed primarily on Vercel, with a separate hardened audit environment on Netlify.

Blog and documentation subsites built with Material for MkDocs and deployed via Vercel.

Infrastructure and data flows are designed with transparency, privacy, and self-hosting where practical as core considerations.

Table of Contents


📦 Template & Distribution Intent

This repository serves multiple purposes:

  • It powers the official Network Pro™ web presence
  • It is distributed via npm and GitHub Package Registry
  • It is intentionally designed to function as a reference implementation and starter template for SvelteKit projects that emphasize security, documentation, and maintainability

As a result, this codebase is treated as a continuously maintained software project, rather than a static website snapshot.

Copyright & Header Conventions

Source code and configuration files in this repository use copyright year ranges (e.g. © 2025–2026) to reflect ongoing development over time. This approach aligns with common practice in actively maintained software projects and templates.

User-facing content (such as pages, documentation, and rendered site output) may derive effective copyright years dynamically at runtime to more accurately reflect publication and revision timelines.

These conventions are intentional and aim to balance legal clarity, maintainability, and practical reuse for downstream consumers of this project.


📝 Changelog

For a history of changes to the Network Pro™ Web Presence, see the CHANGELOG. All notable updates are documented there.

This project follows Keep a Changelog. Version numbers use a SemVer-inspired MAJOR.MINOR.PATCH format, with version increments reflecting both user-visible and operational impact.

Back to top


📁 Repository Structure

  .
  ├── .github/
  │   └── workflows/                # CI workflows (e.g. test, deploy)
  ├── .vscode/
  │   ├── customData.json           # Custom CSS IntelliSense (e.g. FontAwesome)
  │   ├── extensions.json           # Recommended VS Code / VSCodium extensions
  │   ├── extensions.jsonc          # Commented version of extensions.json
  │   └── settings.json             # Workspace settings
  ├── scripts/                      # General-purpose utility scripts
  ├── src/
  │   ├── lib/                      # Components, utilities, types, styles
  │   │   ├── components/           # Svelte components
  │   │   ├── data/                 # Custom data (e.g. JSON, metadata, constants)
  │   │   └── utils/                # Helper utilities
  │   ├── routes/                   # SvelteKit pages (+page.svelte, +server.js)
  │   ├── app.html                  # Entry HTML template and bootstrapping
  │   ├── hooks.client.ts           # Client-side error handling
  │   ├── hooks.server.js           # Request-time security headers and diagnostics
  │   └── service-worker.js         # Custom PWA service worker
  ├── static/                       # Public assets served at site root
  │   ├── pgp/                      # PGP keys
  │   ├── disableSw.js              # Service worker bypass (via ?nosw param)
  │   ├── manifest.json             # PWA metadata
  │   ├── robots.txt                # SEO: allow/disallow crawlers
  │   └── sitemap.xml               # SEO: full site map
  ├── tests/
  │   ├── e2e/                        # Playwright end-to-end tests
  │   ├── meta/                       # Metadata end-to-end CI tests
  │   └── unit/                       # Vitest unit tests
  │       ├── client/                 # Client-side (jsdom) unit tests
  │       └── server/                 # Server-side (node) unit tests
  │           └── internal/           # Internal audit/test helpers
  │               └── auditCoverage.test.js  # Warns about untested source modules
  ├── AGENTS.md                     # Tool-neutral automated-agent guidance
  ├── CHANGELOG.md                  # Chronological record of notable project changes
  ├── CLAUDE.md                     # Claude Code project/tool guidance
  ├── vercel.json                   # Vercel configuration
  ├── package.json                  # Project manifest (scripts, deps, etc.)
  └── ...

 

🔐 static/pgp/ Directory Structure

This directory contains public PGP key files. Their corresponding QR code images are now loaded dynamically from src/lib/img/qr. A dynamic QR code import utility in src/lib/images.js allows these files to be imported directly from $lib.

static/
├── pgp/
│   ├── contact@s.neteng.pro.asc       # Public key for secure email
│   ├── security@s.neteng.pro.asc      # Public key for security contact
│   ├── support@netwk.pro.asc          # Public key for general support
└── ...
  • .asc files are excluded from service worker precaching but served directly via the /pgp/[key] route.
  • QR code images—including WebP and PNG versions—are served dynamically from src/lib/img/qr using <picture> elements.
  • This route does not use fallback rendering; only explicitly defined files are available and expected to resolve.
  • A dynamic [key]/+server.js handler under src/routes/pgp/ serves the .asc files with appropriate Content-Type and download headers.

 

E2E Test Structure

End-to-end tests are located in tests/e2e/ and organized by feature or route:

Note: WebKit/Safari E2E coverage is currently not part of the default Playwright matrix. Previous attempts to enable it produced unstable failures; revisit with a dedicated macOS/WebKit stabilization pass if Safari coverage becomes a release requirement.

tests/
├── e2e/
│   ├── app.spec.js       # Desktop and mobile route tests
│   ├── mobile.spec.js    # Mobile-specific assertions
│   └── shared/
│       └── helpers.js    # Shared test utilities (e.g., getFooter, setDesktopView, setMobileView)
└── ...

Back to top


🛠 Getting Started

For full setup guidance, including environment setup, version enforcement, and local tooling, refer to the 📚 Environment Requirements Wiki.

The project requires Node.js >=24.15.0 <25 and npm >=10.0.0 <13. The repository pins Node.js 24.18.1 in .nvmrc and .node-version; CI currently uses npm 12.0.2.

git clone https://github.com/netwk-pro/netwk-pro.github.io.git
cd netwk-pro.github.io
cp .env.template .env
npm ci
npx playwright install

Back to top


🛡️ Configuration

This project includes custom runtime configuration files for enhancing security, error handling, and PWA functionality. These modules are used by the framework during server- and client-side lifecycle hooks.

🔐 Security Headers and CSP

Security headers are split between SvelteKit configuration and request-time server hooks:

  • svelte.config.js defines kit.csp with environment-based directives:
    • Production/Audit: Enforced, hardened CSP
    • Test/Dev: Uses Content-Security-Policy-Report-Only for safe diagnostics
  • src/hooks.server.js adds request-time headers and diagnostics:
    • Report-To metadata for production CSP reporting
    • Probely scanner diagnostics in audit mode
    • Audit-hostname mismatch warnings when PUBLIC_ENV_MODE is not audit
  • Standard HTTP security headers are also set in src/hooks.server.js:
    • Permissions-Policy
    • X-Content-Type-Options
    • X-Frame-Options
    • Referrer-Policy
    • Strict-Transport-Security (in non-test environments)

⚙️ CSP Behavior by Environment

Environment Header Analytics Enabled CSP Reporting
production Content-Security-Policy ✅ Yes ✅ Yes
audit Content-Security-Policy ❌ No ❌ No
dev Content-Security-Policy-Report-Only ❌ No ✅ Yes (mock)
test Content-Security-Policy-Report-Only ❌ No ✅ Yes (mock)

🧪 Reporting & Debugging

  • In dev/test environments, CSP headers are set to report-only mode.
  • Violations are POSTed to /api/mock-csp, which logs reports to the console.
  • In production, violations are sent to a real CSP collection endpoint (https://csp.netwk.pro/.netlify/functions/csp-report).
  • CSP selection is made at build/config time from PUBLIC_ENV_MODE, Vite mode, and local command fallbacks.
  • Requests for audit.netwk.pro are logged as diagnostics if the build was not produced with PUBLIC_ENV_MODE=audit.

⚠️ Current Trade-Off

SvelteKit manages CSP hashes/nonces for framework-generated inline scripts. The production policy keeps scripts restricted to 'self' plus the Matomo origin, while style-src 'unsafe-inline' remains because Svelte transitions can generate inline styles at runtime. The Keep Android Open banner is implemented first-party as a Svelte component to avoid third-party inline script injection.


📈 Future Improvements (Strict CSP Plan)

To move toward a strict, nonce-based CSP:

  1. Keep CSP policy construction in svelte.config.js so SvelteKit can manage framework hashes/nonces.
  2. Keep third-party scripts out of app.html unless they work with the current CSP without inline script injection.
  3. Add a CSP-compatible analytics stack only after consent, audit-mode, and deployment behavior are reviewed.
  4. Review and refactor any components that rely on dynamic style= or <style> blocks without support for CSP nonces.
  5. Move third-party scripts out of inline <script> tags where possible

ℹ️ Nonce-based CSP remains a long-term goal for dynamic pages, but prerendered pages use hashes. A fully strict policy still requires cooperation from third-party scripts and style-generating runtime behavior.

 

🧭 hooks.client.ts

Located at src/hooks.client.ts, this file is currently limited to handling uncaught client-side errors via the handleError() lifecycle hook.

Client-side PWA logic (such as handling the beforeinstallprompt event, checking browser compatibility, and manually registering the service worker) lives in src/lib/registerServiceWorker.js. The root layout's beforeNavigate hook coordinates activation of an installed update with eligible internal navigation. SvelteKit's automatic service-worker registration is disabled so diagnostic bypass logic runs before registration.

💡 This separation ensures that error handling is isolated from PWA lifecycle logic, making both concerns easier to maintain.

Back to top


🧩 Continuous Security & Dependency Checks

Network Pro™ automatically performs dependency and vulnerability checks as part of its CI/CD pipeline:

  • Gitleaks Secret Scanning — detects potential secrets and credentials in commits, pull requests, and full-history scans.
  • CodeQL Analysis — runs static code scanning to detect code-level vulnerabilities.
  • Probely DAST Scans — executes weekly external scans on the audit deployment (audit.netwk.pro) to identify web application vulnerabilities.
  • npm Audit — runs during the build phase to detect known vulnerabilities in installed dependencies (npm audit --audit-level=moderate).
  • Dependabot — automatically monitors and updates outdated dependencies via pull requests.
  • ESLint, Prettier, etc. (Local) — enforces code quality and consistency during local development before commits.

Security and dependency checks are designed to avoid requiring production credentials or production-side execution. External DAST scanning targets the dedicated audit deployment rather than the production site.

Back to top


⚙️ Service Worker Architecture

The project uses a custom service worker for bounded offline support and PWA assets. SvelteKit bundles src/service-worker.js, but automatic registration is disabled in svelte.config.js; src/lib/registerServiceWorker.js owns registration and update behavior instead.

🗄️ service-worker.js

Precache and cache ownership

  • Every versioned file generated by SvelteKit's $service-worker.build list is a required precache asset.
  • /disableSw.js, /offline.html, and /offline.min.css are also required. If any required asset cannot be cached, installation fails and the incomplete asset cache is removed.
  • PWA icons, the web manifest, and the two Font Awesome WOFF2 files are optional precache assets. They are cached independently so one unavailable optional file does not invalidate an otherwise complete worker.
  • Other files in static/ are not automatically precached. This keeps screenshots, PGP files, large images, crawler metadata, and unrelated downloads out of Cache Storage unless they become explicit offline requirements.
  • Assets and route documents use separate, versioned cache-networkpro-assets-* and cache-networkpro-pages-* caches. Activation removes only obsolete caches owned by the cache-networkpro- prefix and leaves unrelated origin caches alone.

Request handling and offline behavior

  • Same-origin document navigations use a network-first strategy with navigation preload when supported.
  • Only successful, same-origin HTML responses for /, /about, and /pgp can enter the page cache. Redirected, opaque, private, no-store, non-HTML, and URL-mismatched responses are rejected.
  • When navigation fails, an approved cached route is returned when available; otherwise the worker serves /offline.html and finally a minimal 503 response if that file is unavailable.
  • Explicitly precached assets use a cache-first strategy.
  • Non-GET, cross-origin, /api, /api/*, /relay-*, and non-precached same-origin asset requests are not intercepted. This keeps analytics, third-party traffic, APIs, relays, and ordinary runtime requests out of service-worker caches.

🔄 Update lifecycle

Once the browser discovers a new worker, it must complete the entire required precache before installation succeeds. It then remains waiting instead of immediately replacing the worker controlling an open page.

The root layout uses beforeNavigate to coordinate activation:

  1. If registration returns an already-waiting worker, the client immediately asks it to call skipWaiting().
  2. Workers that begin waiting later can also activate on the next eligible SvelteKit-owned link or goto navigation. Forms, browser history traversal, external or unloading navigations, and hash-only changes proceed normally.
  3. For navigation-triggered activation, the page cancels the eligible client-side navigation and records its destination before requesting activation regardless of other open tabs.
  4. The activated worker deletes obsolete worker-owned caches, enables navigation preload, and calls clients.claim() so every controlled tab receives controllerchange.
  5. A navigation-triggering tab performs a full navigation to its recorded destination. Every other controlled tab, including the tab that requested page-load activation, independently reloads its current URL under the new worker.

A five-second fallback completes the requested navigation if activation stalls. First-time installation claims the page without forcing a reload, and a per-tab reload guard prevents repeated controllerchange reloads.

registerServiceWorker.js

Located at src/lib/registerServiceWorker.js, this module:

  • Registers /service-worker.js once, after the document is loaded, using module format in development and classic format in production.
  • Tracks installing and waiting workers and coordinates controllerchange behavior.
  • Dispatches pwa-install-available for the custom install UI when the browser emits beforeinstallprompt.
  • Skips registration and unregisters existing workers when ?nosw or window.__DISABLE_SW__ is present.
  • Unregisters workers instead of registering during Firefox development.

initAnalytics() invokes registration during the root layout's client initialization. Despite that utility's historical name, service-worker registration is not conditional on analytics consent.

🧹 unregisterServiceWorker.js

Located at src/lib/unregisterServiceWorker.js, this utility unregisters all service-worker registrations for the origin. It does not delete Cache Storage; the worker normally manages its own versioned caches during activation.

🚫 disableSw.js and ?nosw

static/disableSw.js is loaded from app.html before the application starts. When the URL contains ?nosw, it sets window.__DISABLE_SW__, unregisters all service workers, and deletes all Cache Storage entries for the origin. The registration module checks the same diagnostic state and does not register another worker.

https://netwk.pro/?nosw

This bypass is intended for debugging and clean first-load testing. It does not persist: visiting the site again without ?nosw allows normal registration. Because it clears all origin caches, it should not be treated as a user preference or routine offline toggle.

Back to top


?debug=true Query Parameter

Appending ?debug=true to the URL enables environment diagnostics in the browser console during initial client setup, even in production builds. The current logs confirm:

  • The current Vite mode
  • Whether the client considers the build a development build
  • Whether the debug query parameter was parsed as true
https://netwk.pro/?debug=true

💡 The setting is not stored outside the URL. Reloading the same URL retains the query parameter and repeats the logs; removing it disables the extra production logs on the next full client initialization. Ordinary SvelteKit client-side navigation does not reinitialize the flag.


📣 CSP Report Handler

This project integrates with a dedicated CSP reporting endpoint, implemented as a Netlify Edge Function and hosted separately at:

The endpoint receives Content Security Policy (CSP) violation reports and logs details for inspection. High-risk violations (e.g., script-src, form-action) also trigger real-time alerts via ntfy. You can extend this further by integrating with SIEM platforms, logging tools, or notification systems.

Usage

To enable reporting, make sure your CSP policy includes both the legacy report-uri and the modern report-to directives.
This project configures those directives in svelte.config.js for production CSP, while src/hooks.server.js adds the required Report-To response header:

# Example response headers
Content-Security-Policy: ...; report-uri https://csp.netwk.pro/.netlify/functions/csp-report; report-to csp-endpoint;

Report-To: {
  "group": "csp-endpoint",
  "max_age": 10886400,
  "endpoints": [
    { "url": "https://csp.netwk.pro/.netlify/functions/csp-report" }
  ],
  "include_subdomains": true
}

Back to top


🧪 Testing

This project uses a mix of automated performance, accessibility, and end-to-end testing tools to maintain quality across environments and deployments.

Tool Purpose Usage Context
@playwright/test End-to-end testing framework with browser automation Local + CI
@lhci/cli Lighthouse CI — automated performance audits CI (optional local)
lighthouse Manual/scripted Lighthouse runs via CLI Local (global)

Note: The repository's supported Lighthouse command is npm run lhci:run, backed by the local @lhci/cli dev dependency. Standalone Lighthouse can be installed globally or run through Chrome DevTools, but there is no separate lighthouse npm script.

CI uses Chrome for Lighthouse audits. For local experimentation, you may run Lighthouse manually using Brave, which can reveal differences related to privacy features or tracking protection.

 

Testing Configuration Files

File Description Usage Context
playwright.config.js Configures Playwright test environment (browsers, timeouts, base URL) Local + CI
.lighthouserc.cjs Lighthouse CI config for defining audit targets, budgets, and assertions CI

 

E2E Setup

Playwright is included in devDependencies and installed as part of the locked dependency tree with:

npm ci

To install browser dependencies (required once):

npx playwright install

This downloads the browser binaries (Chromium, Firefox, WebKit) used for testing. You only need to run this once per machine or after a fresh clone.

 

Running Tests

Local testing via Vitest and Playwright:

npm run test:client     # Run client-side unit tests with Vitest
npm run test:server     # Run server-side unit tests with Vitest
npm run test:all        # Run full test suite
npm run test:watch      # Watch mode for client tests
npm run test:coverage   # Collect code coverage reports
npm run test:e2e        # Runs Playwright E2E tests (with one retry on failure)

The unit test suite includes a coverage audit (auditCoverage.test.js) that warns when source files in src/ or scripts/ do not have corresponding unit tests. This helps track test completeness without failing CI.

Playwright will retry failed tests once (--retries=1) to reduce false negatives from transient flakiness (network, render delay, etc.).

Audit your app using Lighthouse:

# Run Lighthouse CI (via @lhci/cli) using the current build
npm run lhci:run

Manual auditing with Lighthouse (e.g., via Brave or Chrome):

# Install globally (if not already installed)
npm install -g lighthouse

# Run Lighthouse manually against a deployed site
lighthouse https://netwk.pro --view

You can also audit locally using Chrome DevTools → Lighthouse tab for on-the-fly testing and preview reports.

The repo uses @lhci/cli for CI-based audits. It is installed as a dev dependency and does not require a global install.

To trace the exact Chrome version and audit timestamp used in CI:

cat .lighthouseci/chrome-version.txt

Back to top


🧰 Development Reference

Tooling setup, configuration files, and CLI scripts have been moved to the project Wiki for easier maintenance and discoverability.

Refer to the Wiki for:

  • Recommended toolchain
  • Configuration file overview
  • CLI script usage and automation

AI-Assisted Development

The repository includes guidance for AI-assisted development:

  • AGENTS.md — tool-neutral operational guidance for automated agents
  • CLAUDE.md — Claude Code-specific project context and tool guidance

Agent-assisted changes are expected to follow the same security, privacy, testing, and deployment constraints as human-authored changes.

Back to top


🧾 License

This project is licensed under:

Source code, branding, and visual assets are subject to reuse and distribution terms specified on our Legal, Copyright, and Licensing page.

Back to top


🙋‍♂️Questions?

Reach out via our Contact Form, open an issue on this repo, or email us directly at support (at) netwk.pro.

Back to top

 

Designed for professionals. Hardened for privacy. Built with intent.
Network Pro Strategies


Copyright © 2025, 2026
Network Pro Strategies, LLC (Network Pro™)

Network Pro™, the shield logo, and the "Locking Down Networks...™" slogan are trademarks of Network Pro Strategies.

Licensed under CC BY 4.0 and the GNU GPL, as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.