Skip to content

Replace the interim Git-backed Supporter register with database-backed publication #345

Description

@callumflack

Problem

The live Supporter-signing path uses Git as its durable datastore and publication queue:

  1. /api/sign stores an unconfirmed submission in KV and sends a confirmation email.
  2. Confirmation commits one PII-bearing JSON file to PDP-Connect/supporters-private#signatures.
  3. That push rebuilds apps/site/public/principles/supporters.json on publish/supporters and opens or updates a pull request.
  4. Production continues reading the old register from main until a maintainer merges that pull request.

This was explicitly shipped as an interim arrangement, but no tracked work owns its replacement.

The current boundary has concrete failures:

  • A confirmed supporter is not published until a maintainer merges the generated register PR.
  • Repeat submissions receive new IDs, so the same email can create duplicate public rows. Confirmation is idempotent only per token, not per signatory.
  • Correcting a duplicate or other record requires a private Git mutation and another publication cycle.
  • Deleting a signatory file does not remove its PII from reachable Git history, while the public privacy text says withdrawal deletes the record.
  • Repository workflows, tokens, branch policy and manual review are carrying ordinary datastore responsibilities.

Required outcome

Replace the interim private Git repository and PR publisher with a persistent database-backed signing and publication path. Record the storage, identity, correction, withdrawal, migration and failure semantics in an OpenSpec change before implementation.

The design must:

  • Keep unconfirmed submissions expiring without durable residue.
  • Define and enforce repeat-signing semantics using a private normalized identity key without exposing that key publicly. A retry must not create another public supporter accidentally.
  • Make confirmation idempotent and transactional across the confirmed record and its public visibility.
  • Expose only the existing five-field public projection: publicName, type, country, signedOn, and principlesVersion.
  • Publish confirmed, consented supporters without a Git commit, pull request, maintainer action, or deployment.
  • Make correction and withdrawal semantics explicit, including actual private-data deletion under the stated retention policy.
  • Migrate the live signatures records with a count and field reconciliation at migration time, while preserving each signatory's confirmed public name, date, version and consent.
  • Retire PDP-Connect/supporters-private, publish/supporters, the publisher workflows/scripts, and their credentials only after migration verification and rollback criteria are satisfied.
  • Update the register documentation and privacy page to describe the resulting system accurately.

Acceptance checks

  • A real production submission remains absent before email confirmation.
  • After confirmation, its public projection appears on /principles and /principles/supporters.json within a defined short latency, without a repository mutation or PR.
  • Repeating a submission for the same private identity follows the specified correction/rejection behaviour and cannot create duplicate public rows.
  • Withdrawal removes the public entry and deletes or irreversibly anonymizes the private record according to the documented retention contract.
  • Public responses, logs and repository artifacts contain none of the private fields.
  • Migration evidence reconciles every active private record to exactly one database record and every consented record to exactly one public projection.
  • The full submit → confirm → publish → withdraw journey is exercised against the production-shaped deployment before the Git-backed path is retired.

Assisted-by: AI

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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