93 lines
9.8 KiB
Markdown
93 lines
9.8 KiB
Markdown
# Website Firebase Admin runtime configuration investigation
|
|
|
|
Date: 2026-10-04. Latest result: **USER-CONFIRMED production authenticated community empty state after administrator configuration.** Populated production discovery remains untested. This documentation update did not rebuild, redeploy, restart, rerun configuration, or independently recheck production.
|
|
|
|
## User-confirmed production follow-up
|
|
|
|
Evidence source: the administrator's direct report in this conversation on 2026-10-04, not a new agent browser/SSH verification. The administrator reports applying the configuration from `docs/website-firebase-admin-administrator-commands-2026-10-04.md`.
|
|
|
|
| Check | Latest result and provenance |
|
|
|---|---|
|
|
| Credential probes | PASS — user-confirmed |
|
|
| Administrator configuration and website restart | Completed — user-confirmed; no agent configuration rerun |
|
|
| Deployed revision | Unchanged at `8b3a7aa` — user-confirmed; existing full revision is `8b3a7aa29290b58a9456a564785e9c73cd8e3093` |
|
|
| Guest discovery | 401 — user-confirmed |
|
|
| Post-restart credential/discovery failures | Zero — user-confirmed |
|
|
| Signed-in Group Ride Hub community empty state | PASS — user-confirmed: **No Community Rides Scheduled** appears |
|
|
| Populated production discovery | UNTESTED |
|
|
| Raw authenticated HTTP status/JSON | Not supplied or independently captured in this follow-up; no claim of inspected HTTP 200 or response payload |
|
|
|
|
This user-confirmed result supersedes the historical missing-credential blocker for the production empty-state workflow. It does not establish populated discovery, ordering, pagination, blocking/exclusions, or other production behaviors. Exact live identity, IAM grants, file contents, and rollback-backup presence were not independently inspected after application. The administrator runbook retains the configuration rollback procedure; it was not exercised here. Existing isolated/regression evidence remains separate from this production confirmation.
|
|
|
|
## Historical investigation scope
|
|
|
|
Initial result before administrator application: **BLOCKED on privileged execution and identity approval/permission verification.** During that agent investigation, no production configuration was changed and no rebuild, restart, key generation, credential copy/export, commit, push, fixture, IAM change, or rules change occurred. The sections below preserve the original pre-configuration observations and plan; they are not current post-configuration assertions.
|
|
|
|
## Initial confirmed cause and provisioning
|
|
|
|
- Deployed revision remains `8b3a7aa29290b58a9456a564785e9c73cd8e3093` (`GET /api/version`: 200).
|
|
- The deployed server loader supports explicit `FIREBASE_SERVICE_ACCOUNT` or Application Default Credentials, including `GOOGLE_APPLICATION_CREDENTIALS`. Its production project fallback is `motoapp-d22e0`.
|
|
- `motorsignal-website.service` runs as `motorsignal`. It has no EnvironmentFile, no drop-in, no credential environment variable, and no website `.env*` file. Its existing environment preserves port 3001 and production settings.
|
|
- `/etc/motorsignal/firebase-admin.json` exists, mode 0600, owner/group `motorsignal`. The service user can read it by ownership; the SSH inspector cannot.
|
|
- `/etc/motorsignal/routing.env`, root-owned 0640, references that credential and project `motoapp-d22e0`. Active `motorsignal-routing.service` loads this file. This establishes **routing provisioning**, not website reuse approval or adequate Firestore permissions.
|
|
- Backend `production.env` specifies the same Firebase project but no Admin credential reference. It contains unrelated database/mail/session secrets and was not copied.
|
|
- The existing SSH key cannot authenticate as root. `sudo -n true` and a read-only check as `motorsignal` both return `sudo: a password is required`. Passwordless commands include website restart/status, but not credential inspection, systemd configuration edits, or daemon-reload. An opaque legacy staging helper was not invoked.
|
|
|
|
The security review therefore kept the routing identity untouched. The exact service-account email, credential validity, approved website purpose, IAM grants, and Firestore effective read permissions remain unknown. A filename and matching project variable do not prove them.
|
|
|
|
## Initial production checks (before administrator application)
|
|
|
|
| Check | Result |
|
|
|---|---|
|
|
| Existing authorized authenticated session | Restored; no sign-in or token extraction |
|
|
| Community discovery | Reproduced error UI and `server_error` browser warning; website status logs at 06:59:45 UTC show ADC loading failure |
|
|
| Successful structured authenticated response | BLOCKED; no successful response observed |
|
|
| Legitimate empty result display | NOT VERIFIED; failed request is not an empty result |
|
|
| Unauthenticated `GET /api/group-rides` | PASS: 401, `{"error":"unauthorized"}` |
|
|
| Credential-loading failures cleared | FAIL: still present; no fix applied |
|
|
| Revision and website availability | PASS: version 200, exact deployed revision; website service active |
|
|
|
|
Commands: read-only SSH `systemctl show`, metadata listings, sanitized `inspect-runtime.py`, allowed `sudo -n /usr/bin/systemctl status motorsignal-website`; browser navigation and community tab; local `node output/deployment/20261004-firebase-admin/smoke.mjs`. No broad suites were rerun.
|
|
|
|
## Original privileged provisioning plan (administrator now reports applied)
|
|
|
|
An administrator must first inspect **only** credential type, `project_id`, and `client_email` under the service user, without outputting the remaining JSON. For example, this read-only command does not print keys or tokens:
|
|
|
|
```sh
|
|
sudo -u motorsignal /usr/bin/python3 -c 'import json; d=json.load(open("/etc/motorsignal/firebase-admin.json")); print(json.dumps({k:d.get(k) for k in ("type","project_id","client_email")}))'
|
|
```
|
|
|
|
The identity owner/project administrator must confirm its intended website use and effective Firestore read permissions for the production database: community `group_rides`, participant documents, and `users/*/blocks` reads. The current website Admin routes are read-only; no Firebase Auth administration grant is requested. The necessary document get/list permissions are `datastore.entities.get` and `datastore.entities.list`; the predefined `roles/datastore.viewer` includes these, but grants access to all Firestore resources and is **not** an instruction to broaden an existing identity. Verify current grants/conditions and least privilege with the project owner. [Google Firestore IAM documentation](https://docs.cloud.google.com/firestore/native/docs/security/iam)
|
|
|
|
If this routing identity is approved and adequate, **reference the existing file in place**, without copying or changing its permissions. Otherwise provision an already-approved website identity through the same secure `/etc/motorsignal` runtime mechanism, using an existing credential or approved keyless ADC configuration. Do not generate a new service-account key as a workaround. The exact account email cannot be specified until privileged metadata inspection succeeds.
|
|
|
|
After that validation, use a website-specific runtime environment file (proposed `/etc/motorsignal/website.env`, root-owned 0640, group `motorsignal`), containing only non-secret settings:
|
|
|
|
```text
|
|
FIREBASE_PROJECT_ID=motoapp-d22e0
|
|
GOOGLE_APPLICATION_CREDENTIALS=/etc/motorsignal/firebase-admin.json
|
|
```
|
|
|
|
The credential path above is conditional on approval; use the approved identity's path otherwise. Load it from proposed `/etc/systemd/system/motorsignal-website.service.d/10-firebase-admin.conf`:
|
|
|
|
```ini
|
|
[Service]
|
|
EnvironmentFile=/etc/motorsignal/website.env
|
|
```
|
|
|
|
Do not point the website at `routing.env` or `production.env`: they include unrelated settings/secrets and routing's port. Do not add credential JSON to Next.js configuration, `.next`, public assets, or any `NEXT_PUBLIC_*` variable. Preserve existing website port/backend settings; no emulator variables are permitted.
|
|
|
|
Back up the prior website unit, drop-ins, and any existing website-specific environment file into a root-only backup directory **before** edits. Record which files did not exist. Then privileged `systemctl daemon-reload`, followed by restarting **only** `motorsignal-website`, is required. No code rebuild is necessary. These steps were documented, not executed.
|
|
|
|
Verify after restart with the existing authorized session: actual authenticated response status/JSON, eligible rides or genuine empty UI, unauthenticated 401, post-restart logs free of credential failures, unchanged revision. Any index or IAM failure is a separate reported blocker, not grounds for rules changes or fixtures.
|
|
|
|
## Historical rollback and preservation notes
|
|
|
|
No rollback is currently necessary because configuration is unchanged. No new production configuration backup was created.
|
|
|
|
For a future application of the proposed change, restore the prior website unit/drop-ins/environment files from the protected backup, or move newly added website-only files back into that backup when their previous state was absent. Run privileged daemon-reload and restart only the website. **Do not remove or alter the shared routing credential.** Keep deployed code revision unchanged. The earlier code rollback archive is unrelated to this configuration rollback.
|
|
|
|
Only new local evidence files and this report were added. Hash verification confirms all 117 files from the existing pre-deployment dirty-file baseline remain unchanged. Existing main-workspace changes remain unstaged; deployment worktree remains clean. The temporary authenticated verification tab was closed without signing out. A non-secret read-only inspector was uploaded to `/home/motorsignal-admin/inspect-website-credentials-20261004.py` and retained for the administrator; it does not contain credentials.
|
|
|
|
Evidence: `output/deployment/20261004-firebase-admin/runtime-inventory.json`, `authenticated-check.json`, `http-smoke.json`, `git-final.json`, and the corresponding non-secret inspection/smoke/preservation scripts.
|