pub struct Waitlist { /* private fields */ }Expand description
A per-product waitlist.
Implementations§
Source§impl Waitlist
impl Waitlist
Sourcepub fn new() -> Self
pub fn new() -> Self
No products allowed until Waitlist::products or
Waitlist::any_product says otherwise; 7-day confirm TTL;
referrals on.
Sourcepub fn products(
self,
products: impl IntoIterator<Item = impl Into<String>>,
) -> Self
pub fn products( self, products: impl IntoIterator<Item = impl Into<String>>, ) -> Self
Exactly these product slugs may be joined.
Sourcepub fn any_product(self) -> Self
pub fn any_product(self) -> Self
Accept any product slug (single-product ventures that do not want an allowlist).
Sourcepub fn confirm_ttl_days(self, days: u32) -> Self
pub fn confirm_ttl_days(self, days: u32) -> Self
How long a confirmation link stays valid (default 7 days).
Sourcepub fn retention_days_pending(self, days: u32) -> Self
pub fn retention_days_pending(self, days: u32) -> Self
Purge pending entries untouched for this many days from the
scheduled handler (default 30; issue #13 retention rule).
Sourcepub fn status_redirect(self, url: impl Into<String>) -> Self
pub fn status_redirect(self, url: impl Into<String>) -> Self
Where confirmation redirects to, as
<url>?token=<status token> (default
<public_url>/waitlist/status).
Trait Implementations§
Source§impl Module for Waitlist
impl Module for Waitlist
Source§fn personal_data(&self) -> &'static [PersonalDataSet]
fn personal_data(&self) -> &'static [PersonalDataSet]
The entry is anonymised, not deleted; the other two tables have no subject column at all (issue #265).
Why Anonymise and not Erase. A confirmed entry carries two
numbers that belong to other people as much as to its owner:
position is a dense per-product join order that is deliberately
never recomputed, and referrals is a credit already granted. Delete
the row and the queue acquires a hole nobody can explain and every
referred_by pointing at its code orphans; keep it and null the
person out of it, and the request is answered without rewriting
anybody else’s place in the line. Migration 0005 exists for exactly
this: email and email_normalized were NOT NULL, so the SET … = NULL this declaration promises could not have run.
referral_code is deliberately kept. It is a random 8-character
string that names nobody once the address is gone, and it is what the
referrals other people were credited for still resolve against.
Why id and not the address. GET /v1/privacy/export?subject=…
puts the subject value in a URL, and URLs outlive their request in
access logs, proxies and browser history — which is why this module’s
own links carry the opaque row id and never the address (issue #135).
Declaring email_normalized as the subject would have made a subject
access request the one operation that writes an address into those
logs.
Why the other two are none. waitlist_position_lock is one row
per product and genuinely names nobody. waitlist_send_cooldown is
the harder case and its reason says so plainly: its primary key is the
address and product the mail throttle counts against, so the address
is inside a key rather than in a column of its own, and
… WHERE <column> = ? cannot reach it. That is the same shape issue
#266 describes for Outbox, and the table is core’s
SendCooldown shape rather than this
module’s, so giving it a column of its own is a change to every module
that has one. Saying so is the honest answer available here; inventing
a subject column that matched nothing would not be.
Source§fn requires(&self) -> &'static [Port]
fn requires(&self) -> &'static [Port]
Source§fn tables(&self) -> &'static [&'static str]
fn tables(&self) -> &'static [&'static str]
Source§fn emits(&self) -> &'static [&'static str]
fn emits(&self) -> &'static [&'static str]
"<module>.<event>"), listed by
/__health.Source§fn public_writes(&self) -> bool
fn public_writes(&self) -> bool
Source§fn migrations(&self) -> Migrations
fn migrations(&self) -> Migrations
Source§fn validate_config(&self, cfg: &dyn Config) -> Result<(), ConfigError>
fn validate_config(&self, cfg: &dyn Config) -> Result<(), ConfigError>
Source§fn router(&self, ctx: ModuleContext) -> Router
fn router(&self, ctx: ModuleContext) -> Router
/v1/<name>.Source§fn surface(&self) -> Surface
fn surface(&self) -> Surface
Action::input::<Body>()), so the
declaration cannot drift from the route. Harness::build
validates it; GET /__surface serves the composition. Default:
nothing, and a module that declares nothing renders nothing.Source§fn scheduled<'a>(
&'a self,
ctx: &'a ModuleContext,
cron: &'a str,
) -> BoxFuture<'a, Result<(), AnyError>>
fn scheduled<'a>( &'a self, ctx: &'a ModuleContext, cron: &'a str, ) -> BoxFuture<'a, Result<(), AnyError>>
cron is the trigger expression). Default: none.Source§fn harness_api(&self) -> u32
fn harness_api(&self) -> u32
Harness::build.Source§fn depends_on(&self) -> &'static [&'static str]
fn depends_on(&self) -> &'static [&'static str]
Source§fn public_write_policy(&self) -> RoutePolicy
fn public_write_policy(&self) -> RoutePolicy
RoutePolicy on
(issue #143). Read moreSource§fn self_check(&self) -> Vec<String>
fn self_check(&self) -> Vec<String>
Source§fn well_known(&self) -> Option<Router>
fn well_known(&self) -> Option<Router>
/.well-known, for
spec-mandated discovery documents (OIDC openid-configuration,
jwks.json) that must live outside /v1 (issue #46). Paths are
relative to the prefix: register /jwks.json, not
/.well-known/jwks.json. Read more