Documentation
¶
Overview ¶
Package erasure is the one place a Contact's personal data is erased (GDPR Art. 17, ADR 0021). Deleting a Contact is Erasure: there is no softer variant. Every surface (the /site SPA API, the external /api and so MCP) hands it a Workspace-scoped client and an Identifier and gets back nil or a domain error; none re-implements what is removed, anonymized or kept.
The whole erasure is one transaction, opened through events.Bus.WithinScopedPurgeTx so the Contact change and the domain-event outbox commit together. Inside it the work is an ordered list of steps (see Module.steps), each a small function over the resolved Target; extending Erasure (another identifier kind, another dependent table, another signal published in the same transaction) means resolving the new identifier into a Target or adding one step, not a second code path.
Index ¶
Constants ¶
const ( RequesterUser = "user" RequesterAPIToken = "api_token" )
Requester kinds, as recorded on the contact.erased Event.
Variables ¶
var ErrInvalidEmail = errors.New("erasure: invalid email address")
ErrInvalidEmail means the address of a Privacy request is not a plain email address.
var ErrNotFound = errors.New("erasure: not found")
ErrNotFound means the identifier resolves to nothing in the Workspace.
Functions ¶
func Hash ¶
Hash is how Erasure names an address or a phone number to a consumer of the Erasures Export stream (ADR 0045): the lowercase hex SHA-256 of the value, and empty for an empty value. Erasure hashes before it publishes, so no address or phone reaches the outbox; a consumer hashes its own copy of a value the same way to find the rows to delete.
func NormalizeEmail ¶
NormalizeEmail returns the canonical form of an address and rejects anything that is not a single plain address (no display name, no list). Callers hand the raw input to Lookup and ByEmail, which normalize themselves; a handler calls this only to answer 400 for an invalid address before it acts.
Types ¶
type Holdings ¶
type Holdings struct {
ContactHeld bool
Events int
DeliveryRecords int
Unsubscribes int
Suppressions int
}
Holdings is what a Workspace holds for one email address, as counts (a Privacy request lookup). Nothing held is the zero value.
func Lookup ¶
Lookup counts what the Workspace of s holds for the address: the Contact with it, that Contact's Events and the Events carrying it, the delivery records to it, and the Unsubscribes and Suppressions on it. It reads only through s, so another Workspace's rows never match, and changes nothing.
type Identifier ¶
type Identifier struct {
// contains filtered or unexported fields
}
Identifier names the data subject to erase. Build one with ByContactID, ByEmail or ByVisitorID.
func ByContactID ¶
func ByContactID(id int64) Identifier
ByContactID identifies a Contact by its id.
func ByEmail ¶
func ByEmail(email string) Identifier
ByEmail identifies a Contact by its email address; with no such Contact it identifies the address itself, so delivery records to it are anonymized.
func ByVisitorID ¶
func ByVisitorID(visitorID string) Identifier
ByVisitorID identifies the Contact the visitor is bound to, or, for an anonymous Visitor with no Contact, the Visitor and its Events.
type Module ¶
type Module struct {
// contains filtered or unexported fields
}
Module erases data subjects.
type Requester ¶
Requester is who asked for the Erasure: a User (Site) or an API token (External, MCP).
type Target ¶
type Target struct {
// ContactID is the Contact being erased; zero for an address or an anonymous
// Visitor that has no Contact.
ContactID int64
// VisitorIDs are the anonymous devices bound to the Contact; their Events are
// erased with it.
VisitorIDs []string
// Destinations are the Contact's addresses.
Destinations []string
// Phone is the Contact's phone number; empty when it has none or there is no Contact.
Phone string
// SubjectID is the customer's own id for the person (the Contact's subject_id, or
// its sphericon id when it has none); only the contact.erased delivery carries it.
// Empty for an address alone: the address is never echoed into the message.
SubjectID string
// IdentifierKind is what the Identifier was.
IdentifierKind string
// Requester is who asked.
Requester Requester
}
Target is a resolved data subject: what every step erases. Resolving an Identifier into a Target is the only place the identifier kind matters.