Private referral ledger

Schema between Buttondown exports and public standings.

Define the private referral ledger needed between Buttondown subscriber exports and any moderated public leaderboard.

Private schema only. Do not import real subscriber exports, publish standings, contact reward recipients or send email until Buttondown credentials exist, tests pass and the editor approves launch.

Storage rules

These rules keep raw subscriber data out of the repo and out of public HTML.

OpenStorage ruleStore hashed subscriber identifiers only; never commit raw emails, Buttondown subscriber IDs or private referral tokens.OpenStorage ruleKeep raw Buttondown exports outside the repo and delete or archive them according to the approved data-handling process after hashing.OpenStorage ruleTreat the public leaderboard as a derived view containing display name, area tag, verified referral count and tier only.OpenStorage ruleDocument every fraud-control override in moderation_note before a public refresh.OpenStorage ruleStop the refresh if consent, unsubscribe status, duplicate handling or local-intent evidence is unclear.

Private columns

Fields used for moderation and scoring before a public projection exists. Raw emails and Buttondown subscriber IDs are deliberately absent.

Private ledger field

subscriber_hash

Type: sha256_hex | Required: yes

Lower-cased subscriber email hashed outside the public website build.

Private ledger field

referrer_code

Type: string | Required: yes

Buttondown metadata captured from ?ref= or localStorage-backed subscribe form.

Private ledger field

verified_referral_count

Type: integer | Required: yes

Manual count after confirmed-subscriber, duplicate and fraud checks.

Public-safe source field

area_tag

Type: enum | Required: yes

Signup metadata or manual moderation.

Allowed: Brighton, Hove, Portslade, Rottingdean, Patcham, Other local

Private ledger field

first_seen_path

Type: path | Required: no

First landing or CTA path seen with the referral code.

Private ledger field

last_credited_at

Type: iso8601 | Required: no

Manual ledger refresh timestamp.

Private ledger field

reward_status

Type: enum | Required: yes

Manual moderation outcome.

Allowed: pending, verified, credited, withheld, sponsor-prize-ready

Private ledger field

moderation_note

Type: string | Required: yes

Reason for credit, hold, withholding or public-display decision.

Public projection

The only fields intended to appear on a published leaderboard after the editor approves a refresh.

Public projection

display_name

Source: Reader-provided or manually approved display name only.

Rule: Default to anonymous local reader if no display consent exists.

Public projection

area_tag

Source: Private ledger area_tag.

Rule: Use broad local tags only; never publish street, email domain or exact signup path.

Public projection

verified_referrals

Source: Private ledger verified_referral_count.

Rule: Publish moderated counts only after the editor approves a refresh.

Public projection

current_tier

Source: Reward tier derived from verified_referrals.

Rule: Do not imply prize fulfilment until sponsor terms and approval exist.

Redacted samples

Sample rows are fake and exist only to make the manual refresh path testable before credentials exist.

Redacted sample row

founding-reader-001

Area: Hove

Verified referrals: 5

Reward status: verified

Note: Sample row only; no real subscriber data.

Redacted sample row

brighton-parent-list

Area: Brighton

Verified referrals: 2

Reward status: pending

Note: Sample row below public threshold.

Manual refresh checklist

Run this after Buttondown credentials exist and before any public standings, reward email or prize fulfilment.

OpenRefresh step 1Export confirmed Buttondown subscribers to a private working file outside the repo.OpenRefresh step 2Hash emails before creating the ledger and discard raw identifiers from the publish path.OpenRefresh step 3Merge referrer metadata, first-seen path, signup region and confirmation status.OpenRefresh step 4Apply duplicate, self-referral, disposable-domain and local-intent checks.OpenRefresh step 5Generate a public projection that contains no raw private fields.OpenRefresh step 6Run npm run issue:build, npm run website:build and npm run website:check.OpenRefresh step 7Confirm internally before publishing standings, emailing reward recipients or fulfilling prizes.

Linear proof

Track this against MY-2577 and related issue MY-2571.

Boundary

No real export import, subscriber email, reward fulfilment or public leaderboard refresh is enabled by this static page.