who_need_help/docs/local-hardening-plan.md

5.8 KiB

Who Need Help — local hardening completion plan

This plan deliberately excludes buying a domain, renting another server, and real third-party credentials. The existing local Docker/kind environments and the temporary whoneedhelp.imalto.site staging origin are sufficient for every item below unless the evidence column explicitly describes a local mock.

Area Observed baseline Local completion evidence
Browser E2E Manual headed-Chrome scenarios exist; no committed browser suite A fresh uniquely named Compose project runs two-user urgent help, Activity, moderation, privacy, and error paths; traces are retained on failure; its exact volume is removed
Android UI Two JVM unit-test files; no androidTest source set Emulator instrumentation covers deep links, permissions, foreground tracking, notification Stop, lifecycle, and network failure
CI and quality No tracked CI workflow or static/security analysis dependencies The same containerized gates pass locally and are represented in a validated CI workflow
Localization and accessibility Accessibility/keyboard/responsive/contrast browser gates pass; most product copy remains hard-coded English EN/UK/RU catalogs cover product UI; extraction is current; the existing browser gates remain green
Database scale Core discovery/chat/moderation lists call unbounded Repo.all() Cursor-bounded queries pass behavior tests and measured EXPLAIN ANALYZE checks on an isolated generated dataset
Load and resilience Public/readiness/heartbeat k6 profile exists Authenticated writes, chat, tracking, reconnect, rolling replacement, and worker retry profiles pass without touching staging data
Observability Protected Prometheus text endpoint exists Local Prometheus/Grafana/Alertmanager profile scrapes every replica and an induced isolated failure exercises alert delivery
Backup Validated local custom-format dump and restore drill exist An encrypted artifact is uploaded to local S3-compatible MinIO and restored into a fresh database; corruption and interrupted-upload checks fail closed
External boundaries Mailpit and a fake GitHub strategy cover parts of SMTP/OAuth Local protocol-level SMTP/OAuth mocks and the applicable push adapter boundary cover success, rejection, retry, replay, and timeout
Final regression 150 Phoenix tests and manual cross-client evidence Browser, Android, API, DB, WebSocket, backup, monitoring, failure, cleanup, docs, and clean Git are verified from the final commits

The goal remains open while any row lacks reproducible local evidence.

Verified progress

  • The isolated browser harness now generates independent local secrets, starts two web and two worker replicas behind Traefik, and removes only its uniquely named Compose project and PostGIS volume.
  • The browser suite passes public/authentication boundaries and the complete two-user medicine flow: Mailpit confirmation, category-driven request, matching, bidirectional realtime chat, handover verification, bilateral completion, and double-blind review reveal.
  • A separate browser scenario passes Activity creation, participant approval, bidirectional private group chat, a report scoped to the selected message, block/unblock, inherited location privacy, manual social-link removal, category-proposal rejection, report resolution, account restriction, and enforcement of that restriction. Its administrator is created in the isolated database through the existing audited one-time bootstrap command.
  • Browser console errors, page errors, and unexpected failed requests are test failures. Playwright traces, screenshots, video, JSON/HTML reports, and Compose logs are retained in ignored output on failure.
  • The browser gate also passes axe checks on the home, safety, login, and registration pages in both light and dark themes, keyboard skip navigation, and 360/768/1440-pixel overflow checks. Its local raster-tile endpoint exists only in the E2E-compiled image, and map scenarios wait for MapLibre idle before navigation.
  • A forced LiveSocket transport loss while Chromium is offline exposes the reconnect alert, and restoring the network clears it and reconnects the authenticated LiveView.
  • The isolated API 37 Android suite passes five device tests: missing and granted location permission, same-origin deep-link routing across Activity recreation, native foreground location upload, notification Stop with remote cleanup, and a disconnected Stop request with visible retry state. It uses an in-process loopback fixture, runs its emulator without external networking, retains diagnostics on failure, and removes its exact container and image.
  • The containerized scripts/quality.sh gate passes ShellCheck, Hadolint, actionlint, all Compose renders, Helm lint, a Trivy scan of tracked source and the rendered Kubernetes manifest, compiler/xref/Credo/Sobelow/Dialyzer/Hex checks, 150 Phoenix tests, both npm audits, and a Trivy scan of the production release image. It creates random one-run database credentials and removes its exact volume, networks, images, and source snapshot.
  • The checked-in GitHub Actions workflow runs the same isolated backend/security gate, browser E2E suite, and Android unit/lint/APK build. The workflow itself passes actionlint and uses a commit-pinned checkout action without persisted credentials.
  • The hardened local kind manifests also passed a runtime rollout: PostGIS, Mailpit, both web replicas, and both worker replicas became Ready as non-root containers with read-only root filesystems, dropped capabilities, and RuntimeDefault seccomp where configured. The cross-node PubSub probe passed.
  • The remaining rows above are still pending. In particular, complete EN/UK/RU extraction and catalogs are not implied by the completed accessibility checks; this document is not a completion claim.