386 lines
26 KiB
Markdown
386 lines
26 KiB
Markdown
# Who Need Help — implementation verification
|
|
|
|
Observed through 2026-07-19 in the local workspace. This report separates observed
|
|
results from product limits and unknown production properties.
|
|
|
|
## Verified MVP capabilities
|
|
|
|
| Requirement | Status | Observed evidence | Limit |
|
|
| --- | --- | --- | --- |
|
|
| Urgent medicine-help flow | Implemented and tested | Request creation, discovery, matching, start, handover, two-party completion, and review rules are covered by the Phoenix test suite and exercised in the local UI. | The product coordinates pickup of an already purchased or reserved legal item; it is not a pharmacy, medical, or emergency service. |
|
|
| Urgent roadside help | Implemented and tested | Fuel, car wheel, bicycle, motorcycle, vehicle-breakdown, and secured-incident categories are seeded as a translated hierarchy. Server and LiveView tests exercise category paths, required fields, allowed values, boolean normalization, unknown-field rejection, and request creation. | Roadside requests require no immediate danger; this is not emergency response or professional recovery. |
|
|
| Extensible categories | Implemented and tested | Categories and validated text/select/boolean fields are stored in PostgreSQL. Proposal, vote, approve, reject, and merge paths have automated tests. | Coffee, cinema, hiking, and other social activities remain separate from urgent-help safety and ranking rules. |
|
|
| Separate Activity mode | Implemented and tested | Coffee, cinema, walk, and hiking categories use a separate activity lifecycle. Domain and two-client LiveView tests cover creation, join request, organizer approval, capacity enforcement, public/pending/chat privacy, exact-location disclosure to approved users, group chat, blocking, completion, and zero impact on helper reputation. Activity and message reports expose only the linked group conversation to an audited moderator; moderators can hide and restore reported activities. | This does not guarantee participant identity or physical safety. |
|
|
| Map and discovery | Implemented and browser-verified | The committed isolated Chromium suite rendered request and Activity maps, waited for MapLibre `idle`, and completed with no console, page, or request failures against a local PNG raster fixture. An earlier headed session rendered the configured OpenStreetMap tiles. | A production operator must configure a tile provider appropriate for its policy and traffic. |
|
|
| Private matched chat | Implemented and cross-client verified | A message sent from the helper browser appeared in the requester's browser without reload. An earlier Android emulator run also sent a message that appeared in the requester browser in real time. | There is no unsolicited general-purpose inbox. |
|
|
| Consent-driven live tracking | Implemented and cross-client verified | On API 37, Android started `TrackingService` as a location foreground service with a persistent Stop notification. After Home minimized the Activity, an emulator coordinate change reached PostGIS. Notification Stop removed the service, notification, active session, and raw position. | Browsers stop with the page. Android has no `ACCESS_BACKGROUND_LOCATION`, unattended start, or route history. |
|
|
| Privacy settings | Implemented and browser-verified | The profile exposed hidden, approximate public, exact for active match, and explicit exact-public options. Blocking and current-position cleanup have automated tests. | Exact public location remains a user opt-in; legal privacy and retention text still requires jurisdiction-specific review before launch. |
|
|
| Reputation and anti-abuse | Implemented at MVP level | Handover codes, two-party completion, double-blind reviews, unique-counterpart ranking, optional movement/proximity evidence, reports, blocks, abuse signals, and moderator audit paths have automated tests. | The system is not bot-proof and does not claim identity verification. No punitive numeric policy is enabled without measured and approved thresholds. |
|
|
| Social profiles | Manual links implemented; GitHub verification implemented and automated-tested | Manual links cannot set verification fields. The optional GitHub flow uses state, PKCE, a user-bound one-time session, unique provider ownership, and an audit record; 163 tests pass, including callback replay/state checks. No access-token field exists and the controller receives only normalized identity attributes. | The staging operator has not supplied GitHub OAuth credentials, so the real external provider redirect/callback remains disabled and has not been browser-verified. Other providers remain manual/unverified. |
|
|
| Voluntary thanks | Implemented as an external optional link | A helper can expose an optional link after completion; the UI states that the platform does not process the payment. | The platform does not provide payments, escrow, refunds, tax reporting, or payment guarantees. |
|
|
| Android client | Local and public-staging clients implemented and emulator-verified | The native packages `org.whoneedhelp.mobile.debug` and `org.whoneedhelp.mobile.staging` launch the same authenticated LiveView app. Public HTTPS login, map, two-way chat, permission prompts, minimized foreground-service location updates, notification Stop, deep-link routing, and server cleanup were exercised on API 37. | Production signing, Play Store publication, verified Android App Links, unattended/background-permission tracking, and iOS are not implemented. |
|
|
| Multiple web/worker instances | Implemented and locally failure/rollout-verified | The isolated Compose profile passed BEAM crashes and sequential replacement with 3 web/2 worker replicas, all five nodes joined, PubSub passed, and 743/743 readiness requests succeeded. The project-owned kind cluster replaced all 2 web/2 worker pod UIDs under `maxUnavailable=0`; all four replacement pods joined and PubSub passed. | Local PostGIS is a single instance. Production database HA, backups, and recovery are operator work and are not claimed complete. |
|
|
|
|
## Reproducible checks
|
|
|
|
- The isolated Phoenix suite completed on 2026-07-19 with 163
|
|
tests and 0 failures after cursor pagination, database aggregation, and the
|
|
full localization changes
|
|
on Elixir 1.20.2 and Erlang/OTP 29.0.3.
|
|
- `mix compile --force --warnings-as-errors` and
|
|
`mix format --check-formatted`: passed against the same final source.
|
|
- `./scripts/quality.sh` passed ShellCheck 0.11.0, Hadolint 2.14.0 at warning
|
|
threshold, actionlint 1.7.12, all four Compose renders, Helm lint, Trivy
|
|
source/rendered-manifest scanning, xref, Credo high-priority checks, Sobelow
|
|
strict/private checks, Hex audit, 163 Phoenix tests, both npm audits, and the
|
|
production-image vulnerability scan. The rendered Helm manifest and Debian
|
|
13.6 release image each reported zero HIGH/CRITICAL findings under the
|
|
configured gates.
|
|
- Dialyzer passed with three path- and warning-specific documented filters and
|
|
zero unused filters. Two findings are opaque-type warnings at Ecto
|
|
`Multi`/`MapSet` call sites; the third is the generated Gettext backend's
|
|
three-form plural-rule opaque-value warning;
|
|
the filters are visible in `.dialyzer_ignore.exs` rather than hidden by a
|
|
broad pattern. This is not a claim that third-party dependency compilation is
|
|
warning-free.
|
|
- The generated Activity migration was rolled back by exactly one step and
|
|
migrated forward again against `who_need_help_test`; both directions passed.
|
|
- The Activity-report migration was also rolled back and migrated forward. The
|
|
observed database constraint changed from exactly one of 3 urgent-help
|
|
targets to exactly one of 5 urgent-help/Activity targets.
|
|
- `mix format --check-formatted`: passed in the final run.
|
|
- Android local Docker build target: `testDebugUnitTest`, `lintDebug`,
|
|
`assembleDebug`, and `assembleDebugAndroidTest` passed. The isolated API 37
|
|
runner then passed 5/5 instrumentation tests for denied/granted location
|
|
permission, deep-link lifecycle, foreground location upload, notification
|
|
Stop, and disconnected-Stop retry state. The public-staging target ran the
|
|
unit tests plus `lintStaging` and `assembleStaging`; both previously recorded
|
|
lint reports contain no errors or warnings.
|
|
- Release Android guard: a release build without `WNH_BASE_URL` failed as
|
|
intended; release configuration accepts only an explicit HTTPS origin.
|
|
- Helm lint, template rendering, server-side dry-run, rollout waits, readiness
|
|
checks, and cross-node PubSub verification passed in the local kind cluster.
|
|
- The hardened kind rollout then ran PostGIS as UID/GID 70 and Mailpit as
|
|
UID/GID 10001. Both used read-only root filesystems, dropped all Linux
|
|
capabilities, disabled privilege escalation, and used RuntimeDefault seccomp.
|
|
Both web and both worker replicas were Ready; their migration-wait init
|
|
containers also used read-only root filesystems and dropped capabilities.
|
|
The cross-node probe observed all four BEAM nodes, and live/readiness returned
|
|
`ok`/`ready`. Database counts remained `0 users / 0 help requests`.
|
|
- The isolated Compose resilience drill observed a restart count increase for
|
|
one crashed web and worker BEAM process, replaced every replica sequentially,
|
|
observed all 5 cluster nodes, passed PubSub, and completed a real Oban retry
|
|
on attempt 2 after one recorded error. Its exact job row and all fixture
|
|
domain rows were absent afterward; 743 readiness samples had no final
|
|
failure.
|
|
- The reproducible kind rolling drill advanced both Deployments from revision
|
|
17 to 18, replaced all four pod UIDs, observed all 4 BEAM nodes, passed
|
|
PubSub, and left the database-count diff empty. All 305 readiness samples
|
|
ultimately returned 200; two samples needed three total reconnect attempts
|
|
during local single-node NodePort endpoint replacement.
|
|
- The committed browser suite passed its 1/1 bootstrap and all 8/8 Chromium
|
|
specs against a fresh PostGIS volume with two web and two worker replicas on
|
|
2026-07-19. The retained successful-run artifact directory is
|
|
`output/e2e/20260719012404-847451`.
|
|
It covered axe checks across four pages and two themes, keyboard navigation,
|
|
three responsive widths, Activity/moderation/privacy, the two-user medicine
|
|
handover and blind reviews, public boundaries, local raster maps, and an
|
|
offline LiveSocket transport failure/reconnect. It also verified persistent
|
|
Russian/Ukrainian public language selection and the selected Ukrainian
|
|
locale inside an authenticated LiveView. The uniquely named Compose volume
|
|
and networks were removed.
|
|
- The default localization domain contains 508 current messages and the errors
|
|
domain contains 40. Russian and Ukrainian catalogs have no empty or fuzzy
|
|
current entries. Category names, descriptions, structured-field labels and
|
|
select/boolean values use locale maps with an English fallback; the
|
|
compatibility `description` column remains as a fallback for pre-existing
|
|
categories.
|
|
- The isolated database-scale harness migrated an empty PostgreSQL 18.4
|
|
database to the exact pre-index version, seeded the configured canonical
|
|
sample, captured JSON `EXPLAIN (ANALYZE, BUFFERS)` plans before and after the
|
|
generated cursor-index migration, and removed its project and volume. The
|
|
final 50,000-row-per-large-table run selected every asserted cursor index;
|
|
two consecutive request pages matched the first 50 ordered rows with no gap
|
|
or duplicate. Exact observations and their non-SLO limitations are recorded
|
|
in `docs/performance.md`.
|
|
- Browser verification used headed Chrome. The authenticated matched-request
|
|
page rendered its chat, MapLibre marker, and live-location controls with no
|
|
console errors or warnings after the foreground-service rollout.
|
|
|
|
Local generated evidence (ignored by Git):
|
|
|
|
- `output/playwright/final-request-map-chat.png`
|
|
- `output/playwright/final-privacy-profile.png`
|
|
- `output/android/final-image-smoke.png`
|
|
- `output/android/foreground-notification.png`
|
|
- `output/android/staging-deep-link-safety.png`
|
|
- `output/android-instrumentation/20260718225400-2694340/results.txt`
|
|
|
|
Android artifact:
|
|
|
|
- `android/dist/who-need-help-debug.apk`
|
|
- SHA-256:
|
|
`4520aa0b50eaf53bb7052e7f4c096a73d456f45781380187586c79d7267c21c5`
|
|
- `android/dist-staging/who-need-help-staging.apk`
|
|
- SHA-256:
|
|
`08d990a9268a382052be5f2d3ba5afba2aa65a9ad5f9ae1ad4bff720f8999a6e`
|
|
- Observed staging manifest values: package
|
|
`org.whoneedhelp.mobile.staging`, version `0.1.0-staging`, minimum SDK 24,
|
|
target and compile SDK 37, cleartext traffic disabled, `singleTop`
|
|
`MainActivity`, and an exact HTTPS host of `whoneedhelp.imalto.site`.
|
|
- `apksigner verify` accepted the staging artifact's v2 generic debug
|
|
signature. That signing identity is only for installable staging verification
|
|
and is not a production release identity.
|
|
|
|
## Configuration finding
|
|
|
|
`WNH_DEBUG_BASE_URL` is a required Android build input, because the trusted
|
|
same-origin value is compiled into the debug APK. Its concrete local value is
|
|
read from the repository's ignored `.env` by `scripts/android-build.sh` and is
|
|
passed to Docker with `--build-arg`. `android/Dockerfile` only declares
|
|
`ARG WNH_DEBUG_BASE_URL`; it contains no URL default.
|
|
|
|
The example `http://10.0.2.2:4010` remains only as unit-test data for origin
|
|
matching. It is not a runtime or build default. The ignored `.env` is also
|
|
excluded from the root Docker build context.
|
|
|
|
## Database observations
|
|
|
|
The post-roadside local Compose observation found 2 users, 1 help request, 7
|
|
messages, and 1 assignment before and after deployment. Category seeding
|
|
changed only the category count from 1 to 9: 7 selectable categories and 2
|
|
inactive grouping nodes. These are local scenario data; the database is not
|
|
assumed empty.
|
|
|
|
The Activity migration then preserved those same user/help/message/assignment
|
|
counts, added empty `activities`, `activity_participants`, and
|
|
`activity_messages` tables, and expanded the category tree to 14 rows: 9 help
|
|
rows and 5 Activity rows. A validated custom-format dump was created immediately
|
|
before that migration at
|
|
`output/backups/compose-before-activity-20260718-203930.dump`; this ignored local
|
|
artifact is not a substitute for the still-required isolated restore drill.
|
|
|
|
The final kind observation found 0 users, 0 help requests, and 0 messages. That
|
|
state was queried before changing the database workload. The migration from the
|
|
old `emptyDir` Deployment created a custom-format dump, validated it with
|
|
`pg_restore --list`, changed PostGIS to a persistent StatefulSet, and restored
|
|
the dump before the Helm upgrade. The final kind database reported PostgreSQL
|
|
18.4 and PostGIS 3.6.4.
|
|
|
|
The local kind Secret contains independently generated values. Only their
|
|
decoded lengths were inspected: the PostgreSQL password is 64 characters and
|
|
each application secret is 128 characters. Secret values were not printed or
|
|
written to tracked files.
|
|
|
|
## Dependency-upgrade observations
|
|
|
|
- The running Compose and kind releases reported Elixir 1.20.2 and Erlang/OTP
|
|
29.
|
|
- Compose reported Traefik 3.7.8 and Mailpit 1.30.4; Compose and kind both
|
|
reported PostgreSQL 18.4 and PostGIS 3.6.4.
|
|
- The production asset build reported Tailwind CSS 4.3.3 and daisyUI 5.6.18;
|
|
esbuild is configured at 0.28.1.
|
|
- The isolated Node build stage reported Node.js 24.18.0, npm 12.0.1,
|
|
`npm outdated --json` returned `{}`, and `npm ci` reported zero known
|
|
vulnerabilities.
|
|
- The Android build used Android Gradle Plugin 9.3.0, Gradle 9.6.1, Command-line
|
|
Tools 22.0, and its embedded Android CLI 1.0.15857036. Unit tests, lint, and
|
|
debug assembly passed; the lint report says “No errors or warnings.” The
|
|
rebuilt emulator image contains the API 37 ps16k AVD and APK, and its emulator
|
|
36.6.11.0 binary returned its version successfully at runtime.
|
|
- The final complete `scripts/kind-up.sh` run was idempotent and finished with
|
|
both 2-replica Deployments Ready and a successful cross-replica PubSub probe.
|
|
|
|
The migration `20260718114233` and reverse block lookup index
|
|
`blocks_blocked_id_blocker_id_index` were present. An actual `EXPLAIN ANALYZE`
|
|
for that reverse lookup selected the index. The table contained no block rows,
|
|
so this confirms query shape, not production performance.
|
|
|
|
Exact production capacity, minimum CPU/RAM, and scaling thresholds are unknown:
|
|
there is no representative production dataset, traffic model, or
|
|
target-environment measurement. The isolated measurements in
|
|
`docs/performance.md` include the earlier paced public/readiness/heartbeat
|
|
comparison and a later 3-web/2-worker run with real authentication, LiveView,
|
|
chat writes, tracking writes, and explicit position deletion. The latter
|
|
completed 1,880 authenticated chains and 240 heartbeat sockets without a
|
|
functional failure and restored every tracked application table count after
|
|
fixture cleanup. Neither short run found a saturation point or represents
|
|
production traffic, so the Helm chart does not invent resource limits or an HPA
|
|
policy.
|
|
|
|
## Public staging observation
|
|
|
|
On 2026-07-18, `whoneedhelp.imalto.site` was published through the existing
|
|
Ubuntu Nginx gateway and its OpenVPN path to the local Compose proxy. HTTP
|
|
redirected to HTTPS; the homepage, fingerprinted assets, and both health
|
|
endpoints returned HTTP 200. A headed Chrome session rendered the public page
|
|
with zero console errors or warnings. A complete WebSocket Upgrade request to
|
|
`/live/websocket` returned `101 Switching Protocols`.
|
|
|
|
The observed Let's Encrypt certificate had the correct
|
|
`DNS:whoneedhelp.imalto.site` SAN and an expiry of 2026-10-16. Nginx and the
|
|
Certbot renewal timer were active. This verifies the current staging path; it
|
|
does not make the workstation or gateway a production availability
|
|
environment.
|
|
|
|
After the Activity rollout, headed Chrome rendered the updated public
|
|
navigation, followed the Activity link to the authenticated route, and received
|
|
the expected login redirect and flash with zero console errors or warnings.
|
|
|
|
After commit `307794c`, staging was rebuilt with the optional GitHub OAuth
|
|
boundary. Both web and both worker replicas started, the cross-node PubSub probe
|
|
passed, public home/readiness returned HTTP 200, and the before/after database
|
|
counts remained `2 users / 1 request / 7 messages / 14 categories / 1
|
|
assignment / 0 activities / 0 reports / 0 social identities`.
|
|
|
|
A headed Chrome E2E run then registered a uniquely named `example.invalid`
|
|
account, consumed its confirmation link from local Mailpit, authenticated,
|
|
opened `/profile`, and observed:
|
|
|
|
- the GitHub network option and the explicit provider-disabled explanation;
|
|
- no Verify button while both OAuth environment variables were absent;
|
|
- a manually added Telegram link labelled `unverified`;
|
|
- removal of that owner-controlled manual link;
|
|
- a direct `/auth/social/github` request returning to the profile with the
|
|
controlled `provider is not configured` flash;
|
|
- zero browser console errors or warnings.
|
|
|
|
The exact E2E user was checked for every foreign-key relationship to `users`.
|
|
It had only its one authentication token and no domain records after the manual
|
|
link was removed. That exact user was then deleted through Ecto, its browser
|
|
session became invalid, the generated Mailpit message was deleted individually,
|
|
and the original database counts were observed again. The browser windows were
|
|
left open.
|
|
|
|
Local ignored browser evidence:
|
|
|
|
- `.playwright-cli/page-2026-07-18T18-09-44-303Z.png`
|
|
|
|
## Public Android and cross-client observation
|
|
|
|
The public-staging APK was built with the explicit ignored `.env`
|
|
`WNH_BASE_URL`, installed on the API 37 emulator, and connected to
|
|
`https://whoneedhelp.imalto.site`. Android package inspection found exactly one
|
|
matching Activity for the configured HTTPS host and no matching Activity for
|
|
`attacker.example`. A standard implicit `ACTION_VIEW` launch of `/safety`
|
|
opened the native `MainActivity` and displayed the public Safety rules.
|
|
|
|
The manifest intentionally sets `android:autoVerify="false"`: this is a
|
|
same-origin HTTPS deep link, not a claimed verified Android App Link. Enabling
|
|
verification requires the final production application ID and signing
|
|
certificate fingerprint to be published in the deployment's
|
|
`/.well-known/assetlinks.json`.
|
|
|
|
A cross-client scenario then used headed Chrome as the requester and the
|
|
public-staging Android app as the helper. The observed behavior was:
|
|
|
|
- the Android app authenticated against the public HTTPS origin and rendered
|
|
the MapLibre request;
|
|
- chat messages travelled in both directions, including an Android-bound
|
|
browser message appearing without reload;
|
|
- Android granted foreground location permissions, started
|
|
`TrackingService`, and showed its persistent Stop notification;
|
|
- after Home minimized the Activity, an emulator location change from
|
|
`50.46009833, 30.5334` to `50.4611, 30.5344` reached PostGIS and produced
|
|
`121.97` metres of observed movement;
|
|
- the headed browser received the helper marker in real time and removed it
|
|
when tracking stopped;
|
|
- notification Stop removed the Android service and notification, ended the
|
|
exact tracking session, left zero active sessions, and deleted its raw current
|
|
position.
|
|
|
|
The browser scenario exposed one UI defect: movement evidence was persisted and
|
|
the marker updated, but the evidence badge remained stale until reload. The
|
|
tracking PubSub event now carries the already-derived movement/proximity
|
|
timestamps, and the LiveView updates its in-memory assignment from that same
|
|
event without an extra query. Domain and two-client LiveView regression tests
|
|
assert the event and badge change.
|
|
|
|
That fix was deployed with image digest
|
|
`sha256:1b991c1e07d98babb5151c010250cd0b9458195cf3de5a91972456ee72d75673`.
|
|
Both web and both worker containers used the digest, the cross-node PubSub probe
|
|
passed, local and public readiness returned HTTP 200, and no application
|
|
error/warning was found in the checked post-rollout logs. The before/after
|
|
database counts remained `2 users / 1 matched request / 7 messages / 14
|
|
categories / 1 assignment / 4 ended tracking sessions / 0 active tracking
|
|
sessions / 0 activities / 0 reports / 0 social identities`.
|
|
|
|
The exact temporary E2E users, tokens, request, assignment, messages, tracking
|
|
session, and audit records were removed in one scoped transaction. Queries by
|
|
their exact identifiers found no remaining rows and the original database
|
|
counts were restored. The headed browser windows and emulator were left open.
|
|
|
|
## Operations and metrics verification
|
|
|
|
On 2026-07-18, the Compose database was archived with PostgreSQL 18
|
|
custom-format `pg_dump`. The published archive and SHA-256 sidecar were
|
|
validated before an isolated restore. The restore drill created a database from
|
|
`template0`, restored with `pg_restore --exit-on-error`, read 23 public
|
|
application tables and 1106 restored rows, reported PostGIS 3.6.4, observed all
|
|
8 current migrations, and removed the exact temporary database. A follow-up
|
|
catalog query returned zero remaining restore-drill databases. Source counts
|
|
before and after remained `2 users / 1 help request / 7 messages / 14 categories
|
|
/ 1 assignment / 0 activities / 0 reports / 0 social identities`.
|
|
|
|
The same rollout started 2 healthy web replicas and 2 worker replicas. Local
|
|
live/readiness, public HTTPS readiness, and the public root returned HTTP 200.
|
|
The cross-node PubSub probe passed across all four connected BEAM nodes. The
|
|
protected metrics route returned HTTP 401 both locally and through public HTTPS
|
|
without credentials, returned valid Prometheus text with the generated ignored
|
|
local token, and was scraped directly from each web container. Helm 4.2.3 lint
|
|
and template rendering passed.
|
|
|
|
Before the runtime image change, every BEAM container logged that
|
|
`libsctp.so.1` was unavailable. The rebuilt Debian trixie release contains the
|
|
`libsctp1` package and the exact shared library; no SCTP, application error, or
|
|
application warning appeared in the post-rollout web/worker logs checked during
|
|
this verification window.
|
|
|
|
## Final full-stack regression
|
|
|
|
After isolating the load-test Compose project from staging, the complete
|
|
regression was repeated against the final source on 2026-07-18:
|
|
|
|
- `./scripts/test.sh` rebuilt the test image and passed all 150 Phoenix tests;
|
|
`mix format --check-formatted` and `mix compile --warnings-as-errors` also
|
|
passed.
|
|
- The staging and load-test Compose configurations both rendered successfully.
|
|
Helm 4.2.3 lint and template rendering passed with the checked-in kind values.
|
|
- The public root, `/healthz/live`, and `/healthz/ready` returned HTTP 200.
|
|
The two health responses were served by different web nodes during the
|
|
observation. The four-node web/worker cluster also passed the cross-node
|
|
Phoenix PubSub probe.
|
|
- Headed Chrome loaded the public home and Safety pages, including all
|
|
fingerprinted assets, and redirected an anonymous `/requests` visit to login
|
|
with the expected flash. The browser reported zero console errors and zero
|
|
warnings. Existing browser windows were left open.
|
|
- Both Android Docker builds repeated their unit-test, lint, and APK assembly
|
|
stages. The debug and staging artifacts retained the documented SHA-256
|
|
hashes, and both lint reports had no nonzero error or warning summary.
|
|
`apksigner` verified the staging APK's v2 generic debug signature; `aapt`
|
|
confirmed package `org.whoneedhelp.mobile.staging`, SDK 24 through 37,
|
|
disabled cleartext, and the exact HTTPS staging host.
|
|
- The protected metrics endpoint returned HTTP 401 without a token and valid
|
|
Prometheus text with the generated ignored token. The checked 15-minute
|
|
web/worker/proxy log window contained no application error, warning, or SCTP
|
|
finding.
|
|
- The staging database remained at 2 users, 1 help request, 1 assignment, 7
|
|
messages, 14 categories, 4 ended tracking sessions, 0 active tracking
|
|
sessions, 0 activities, 0 reports, and 0 social identities.
|
|
|
|
## Known work before a public production launch
|
|
|
|
- Replace the temporary staging origin with the production-owned domain and
|
|
production-sign the Android app.
|
|
- Operate PostgreSQL/PostGIS with backups, recovery testing, and the required
|
|
availability model.
|
|
- Load-test representative data and traffic, then set measured pool, resource,
|
|
autoscaling, and action-limit policies.
|
|
- Repeat representative authenticated write, chat, tracking, and reconnect
|
|
load scenarios before deriving production capacity or autoscaling policy.
|
|
- Publish jurisdiction-specific emergency contacts, privacy, retention,
|
|
prohibited-items, and voluntary-payment guidance after legal review.
|
|
- Create and configure a GitHub OAuth App, then exercise the real external
|
|
provider redirect/callback in a headed browser. Until then staging keeps the
|
|
provider disabled and manual links remain unverified.
|