Weighted draws eventually produce a very reasonable question: can somebody outside CrowdRelay verify that the result was not quietly changed afterwards?

My first implementation path pointed toward a smart contract. It would have produced an impressive diagram and several dependencies that had nothing to do with selecting a fair winner: wallets, gas, RPC providers, chain configuration, contract upgrades and operational keys.

The requirement was smaller than a blockchain

The draw did not need a blockchain. It needed a durable local proof and an independent public timestamp.

Two proofs, two responsibilities

CrowdRelay now separates those jobs.

PostgreSQL stores the complete deterministic proof: the eligible candidate snapshot, winner snapshot, revealed seed, algorithm version, receipt hash and Merkle inclusion data. That is the source of truth. The result can be reproduced and checked offline without contacting a public service.

A separate worker builds a metadata-only commitment for a proof batch, signs it and publishes it to the Sigstore Rekor transparency log. Rekor adds an append-only public record, integrated time, log index, Signed Entry Timestamp and Merkle inclusion proof.

Publish the commitment, not the people

The public payload is intentionally boring:

proof batch UUIDproof kind and schema versionSHA-256 rootleaf counthash and tree algorithms

Fan records, winners, email addresses, ticket data, consent and event payloads remain inside CrowdRelay. Publishing evidence should not become publishing the people the evidence is about.

Public proof cannot block the draw

Rekor is also outside the critical path. A draw completes when the local transaction and deterministic proof complete. If the transparency log is unavailable, the draw does not wait, roll back or pretend that no winner exists. The external proof batch remains pending and a bounded worker retries it later.

A lost response must not duplicate proof

That worker needed careful failure semantics. A successful upload followed by a lost response must not create a second public entry on the next attempt. The submission is deterministic, the worker keeps a crash-safe pending-confirmation journal and a Rekor conflict can be resolved through the existing entry location instead of logging another copy.

Local truth and public existence

The distinction between the two layers is important:

local proof: explains and reproduces the draw
public proof: shows that one exact commitment existed by a public time

Rekor does not decide the winner. It does not know the candidate list and it cannot prove that an application rule was ethically perfect. It proves that the signed commitment returned during verification is bound to an append-only public log entry.

Verify offline, confirm online

Verification follows the same split. A local receipt can be checked offline. The Rekor binding, signature and Merkle path can also be checked from the stored public proof, while an optional online check confirms that the same body is currently present in the public log.

Use the property, skip the platform

This architecture is less theatrical than placing every draw on-chain. It is also cheaper, easier to operate and better aligned with the actual threat model. PostgreSQL remains authoritative, CrowdRelay keeps private data private and the external system contributes one property we cannot create alone: independent public evidence of existence.

No wallet appears in the fan journey. Ticketing, admission, mail delivery and consent do not depend on Rekor. The feature can be disabled without changing any business flow.

Fairness still comes from explicit rules, frozen inputs and deterministic receipts. The transparency log makes later rewriting harder to hide.

That was the useful part I wanted from a public ledger. I did not need to turn the rest of the product into one.