Skip to content

Run the signalsPosted backfill before the removal release (blocked on ADC) #74

Description

@BurningAXE

functions/scripts/backfill_signals_posted.js is written and committed but has never run. It must run before the app release that ships signal removal (#68).

Why it is needed

Contribution statistics (master spec §3.5.1: "these stats remain even when old cases are deleted or archived") used to be a live count() over signals filtered by reporter — so the number really measured signals still visible. handleSignalCreated now increments publicProfiles/{uid}.signalsPosted once at report time and nothing decrements it.

profile_page._loadSignalsPosted falls back to the old live count when the field is absent, so nothing is visibly broken today. What the backfill buys is that accounts which reported before the counter existed keep their number, and that the fallback can eventually be deleted (tracked in #73).

Why the ordering is strict

The script counts the live signals collection. Once users can remove signals, a removed signal is no longer there to count — so running it after the release writes numbers lower than the ones it exists to restore, for exactly the accounts the change was meant to protect.

Run it before the release, not after.

What is blocking it

It needs Application Default Credentials, which this machine does not have:

gcloud auth application-default login

This is the same gap that leaves functions/scripts/grant_moderator.js unverified (SPECIFICATION §14) — the 2026-08-17 moderator grants were made through the Firebase MCP instead, so that script's own code path has still never executed. Setting ADC up unblocks both.

Steps

  • gcloud auth application-default login
  • Dry run, eyeball the counts: cd functions && node scripts/backfill_signals_posted.js --project help-a-paw-dev
  • Apply: node scripts/backfill_signals_posted.js --project help-a-paw-dev --apply
  • Spot-check a profile in the app — the Signals stat should match, and should now come from the counter rather than the fallback

Safety notes

  • Dry-run by default; --apply is required to write.
  • Writes an absolute count via set(..., {merge: true}), not an increment, so re-running converges rather than doubling — safe to re-run after a partial failure.
  • Writes only signalsPosted. publicProfiles also holds the display name, and a full set() would erase it.
  • publicProfiles has no triggers, so this notifies nobody.
  • Production only. Test-mode signals are excluded by recordSignalPosted, and counting them here would write in a number the trigger would never produce.
  • help-a-paw-dev IS production despite the name.

Known limitation, worth recording rather than fixing

The backfill cannot recover credit for signals that were hard-deleted under the old behaviour — those documents are gone. Affected accounts will under-report permanently.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions