Parking a design direction so it isn't lost. Nothing here is built, and this is deliberately not scoped as a task yet.
The observation
Ghost Keys are a one-time purchase. At roughly $3 average, "a major funding source" means order 100k purchases a year, which needs distribution the project doesn't have.
Recurring changes the unit from transactions to people. At $3/month, a ~$240k annual run rate needs about 6,700 active members. Same money, and instead of persuading 100,000 people a year you persuade about seven thousand once and keep them. That is a plausible community size for a project with Freenet's profile; 100k annual buyers is not.
Why it's compatible with the anonymity model
The obvious objection is that a subscription needs a standing customer record with an email and a card, which sounds like it wrecks the privacy story. It doesn't, and the distinction is worth stating precisely:
Donor anonymity was never the promise. Key unlinkability was.
Blind signing does not hide that you donated. It makes it impossible to connect your donation to the key you walk away with. Someone can be a fully identified monthly member, on a receipt and a tax letter, and still hold a Ghost Key nobody can tie to them.
What the code says today
- No expiry mechanism exists.
NotaryPayload (rust/gklib/src/notary_certificate.rs) carries a verifying key and a free-form info string; GhostkeyCertificateV1 carries the notary cert, a verifying key, and a signature. Nothing temporal anywhere.
- Period cohorts would need no wire change. Notary keys are already per-amount. Making them per-(amount, period) and putting the period in
info gives apps a freshness signal for free, with old notary keys staying published so old certificates keep verifying.
- Anything stronger is a V2. The CBOR field names are frozen for backward compatibility (see the
#[serde(rename = "delegate")] comments), so a real expiry field means a new certificate version and a verifier migration.
The tradeoff to decide deliberately
Period cohorts shrink the anonymity set. Today it is everyone who ever bought at that tier; with monthly cohorts it is everyone who bought at that tier that month, which early on could be very few people. Quarterly or annual cohorts are a middle ground if a freshness signal is wanted without slicing the set too thin. This is the same volume-is-a-security-property point that the tier ladder (#100) already had to reckon with.
Suggested shape, if pursued
Don't expire keys. Sell a membership that recurs; keys already minted stay valid forever. Continued membership buys the right to keep minting (where bundled issuance, freenet/ghostkeys#2, earns its keep) plus the ordinary reasons people sustain a nonprofit. Expiring keys would rent people their identity, which undercuts the thing the project trades on, and would drag offline verification toward the call-home the design deliberately avoids. If an app wants recency it can apply its own policy against the cohort in info.
Cost, stated honestly
Not a tweak. Stripe Subscriptions is a different integration from the PaymentIntent flow the whole API is built on, and recurring billing brings a permanent operational tail for a small team: failed cards and dunning, cancellation, proration, receipts, tax letters.
Cheaper experiment first
Make River require a Ghost Key to post. It is the project's own app, it has the spam problem, and it is the only way to learn whether the flow survives contact with real users at a price above zero. It creates baseline demand and dogfoods bundled issuance, at a fraction of the cost of a go-to-market.
Related: freenet/ghostkeys#2 (bundled issuance), #25 (unlinkable presentation via ZK).
[AI-assisted - Claude]
Parking a design direction so it isn't lost. Nothing here is built, and this is deliberately not scoped as a task yet.
The observation
Ghost Keys are a one-time purchase. At roughly $3 average, "a major funding source" means order 100k purchases a year, which needs distribution the project doesn't have.
Recurring changes the unit from transactions to people. At $3/month, a ~$240k annual run rate needs about 6,700 active members. Same money, and instead of persuading 100,000 people a year you persuade about seven thousand once and keep them. That is a plausible community size for a project with Freenet's profile; 100k annual buyers is not.
Why it's compatible with the anonymity model
The obvious objection is that a subscription needs a standing customer record with an email and a card, which sounds like it wrecks the privacy story. It doesn't, and the distinction is worth stating precisely:
Donor anonymity was never the promise. Key unlinkability was.
Blind signing does not hide that you donated. It makes it impossible to connect your donation to the key you walk away with. Someone can be a fully identified monthly member, on a receipt and a tax letter, and still hold a Ghost Key nobody can tie to them.
What the code says today
NotaryPayload(rust/gklib/src/notary_certificate.rs) carries a verifying key and a free-forminfostring;GhostkeyCertificateV1carries the notary cert, a verifying key, and a signature. Nothing temporal anywhere.infogives apps a freshness signal for free, with old notary keys staying published so old certificates keep verifying.#[serde(rename = "delegate")]comments), so a real expiry field means a new certificate version and a verifier migration.The tradeoff to decide deliberately
Period cohorts shrink the anonymity set. Today it is everyone who ever bought at that tier; with monthly cohorts it is everyone who bought at that tier that month, which early on could be very few people. Quarterly or annual cohorts are a middle ground if a freshness signal is wanted without slicing the set too thin. This is the same volume-is-a-security-property point that the tier ladder (#100) already had to reckon with.
Suggested shape, if pursued
Don't expire keys. Sell a membership that recurs; keys already minted stay valid forever. Continued membership buys the right to keep minting (where bundled issuance, freenet/ghostkeys#2, earns its keep) plus the ordinary reasons people sustain a nonprofit. Expiring keys would rent people their identity, which undercuts the thing the project trades on, and would drag offline verification toward the call-home the design deliberately avoids. If an app wants recency it can apply its own policy against the cohort in
info.Cost, stated honestly
Not a tweak. Stripe Subscriptions is a different integration from the PaymentIntent flow the whole API is built on, and recurring billing brings a permanent operational tail for a small team: failed cards and dunning, cancellation, proration, receipts, tax letters.
Cheaper experiment first
Make River require a Ghost Key to post. It is the project's own app, it has the spam problem, and it is the only way to learn whether the flow survives contact with real users at a price above zero. It creates baseline demand and dogfoods bundled issuance, at a fraction of the cost of a go-to-market.
Related: freenet/ghostkeys#2 (bundled issuance), #25 (unlinkable presentation via ZK).
[AI-assisted - Claude]