Help us shape the future of Go! Take the 2026 Go Developer Survey

consent

package
v1.9.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 2, 2026 License: MIT Imports: 31 Imported by: 0

README

Records who agreed to what, when, and against which version of your policy.

Under GDPR the burden is on you to show consent existed, which means keeping the record. This plugin stores a versioned record per purpose, marketing, analytics, whatever you define, keeps the full history including revocations, and contributes the lot to the user's data export.

Versioning against a policy version is the part people forget. When your privacy policy changes, consent gathered under the old one does not automatically carry over.

Use it when

  • You operate under GDPR, CCPA or anything with a similar burden of proof
  • Marketing wants to know who opted in and you need one answer everyone trusts
  • You need an audit trail showing consent existed at the moment you acted on it

Skip it when

  • You handle no personal data worth consenting to, which is rarer than it sounds
  • Your consent already lives in a dedicated CMP and duplicating it here creates two sources of truth
  • You have not defined your purposes yet. This plugin stores decisions, it does not design your policy

Wiring

authsome.WithPlugin(consent.New()),

No configuration. The purposes and policy versions are values you pass on the grant call.

Endpoints

Mounted under {basePath}/consent.

Method Path Purpose
POST /grant Record consent for a purpose at a policy version
POST /revoke Record a withdrawal
GET `` List the caller's consent records

Lifecycle hooks

None on the sign-in path. It registers a DataExportContributor, so consent history is included in the GDPR export, and a MigrationProvider for its tables.

organization contributes memberships to the same export. oauth2provider is where consent matters for third-party access grants.

Documentation

Overview

contract.go: Wires the consent plugin into the forge-dashboard contract surface via plugin.ContractContributor. The plugins/consent/contract subpackage declares its own ConsentStore interface (cycle avoidance); this file adapts the plugin's concrete consent.Store into that interface via a small shim.

Package consent provides GDPR-compliant consent tracking for AuthSome.

The consent plugin records when users grant or revoke consent for specific purposes (e.g., marketing, analytics, essential). Each consent record is versioned against a policy version, and the full history is queryable.

Usage:

eng, _ := authsome.NewEngine(
    authsome.WithStore(store),
    authsome.WithPlugin(consent.New()),
)

Index

Constants

This section is empty.

Variables

View Source
var ErrNotFound = errors.New("consent: not found")

ErrNotFound is returned when a consent record is not found.

View Source
var PostgresMigrations = migrate.NewGroup("authsome-consent", migrate.DependsOn("authsome"))

PostgresMigrations is the postgres migration group for the consent plugin.

View Source
var SqliteMigrations = migrate.NewGroup("authsome-consent", migrate.DependsOn("authsome"))

SqliteMigrations is the SQLite migration group for the consent plugin.

Functions

This section is empty.

Types

type Consent struct {
	ID        id.ConsentID `json:"id"`
	UserID    id.UserID    `json:"user_id"`
	AppID     id.AppID     `json:"app_id"`
	Purpose   string       `json:"purpose"`              // e.g. "marketing", "analytics", "essential"
	Granted   bool         `json:"granted"`              // true = granted, false = revoked
	Version   string       `json:"version"`              // policy version this consent applies to
	IPAddress string       `json:"ip_address"`           // IP at time of consent action
	GrantedAt time.Time    `json:"granted_at"`           // when consent was granted
	RevokedAt *time.Time   `json:"revoked_at,omitempty"` // when consent was revoked (nil if active)
	CreatedAt time.Time    `json:"created_at"`
	UpdatedAt time.Time    `json:"updated_at"`
}

Consent represents a user's consent record for a specific purpose.

type GrantConsentRequest

type GrantConsentRequest struct {
	AppID   string `json:"app_id,omitempty" description:"Application ID"`
	Purpose string `json:"purpose" description:"Consent purpose (e.g. marketing, analytics, essential)"`
	Version string `json:"version,omitempty" description:"Policy version this consent applies to"`
}

GrantConsentRequest binds the body for POST /consent/grant.

type ListConsentsRequest

type ListConsentsRequest struct {
	Purpose string `query:"purpose" description:"Filter by consent purpose"`
	Cursor  string `query:"cursor" description:"Pagination cursor"`
	Limit   int    `query:"limit" description:"Maximum number of results (default 50, max 200)"`
}

ListConsentsRequest binds query params for GET /consent.

type ListResponse

type ListResponse struct {
	Consents   []*Consent `json:"consents" description:"List of consent records"`
	NextCursor string     `json:"next_cursor,omitempty" description:"Pagination cursor for next page"`
}

ListResponse wraps a paginated list of consent records.

type MemoryStore

type MemoryStore struct {
	// contains filtered or unexported fields
}

MemoryStore is an in-memory consent store for development and testing.

func NewMemoryStore

func NewMemoryStore() *MemoryStore

NewMemoryStore creates an in-memory consent store.

func (*MemoryStore) AnonymizeUserConsents

func (s *MemoryStore) AnonymizeUserConsents(_ context.Context, userID id.UserID) (int64, error)

func (*MemoryStore) GetConsent

func (s *MemoryStore) GetConsent(_ context.Context, userID id.UserID, appID id.AppID, purpose string) (*Consent, error)

func (*MemoryStore) GrantConsent

func (s *MemoryStore) GrantConsent(_ context.Context, c *Consent) error

func (*MemoryStore) ListConsents

func (s *MemoryStore) ListConsents(_ context.Context, q *Query) ([]*Consent, string, error)

func (*MemoryStore) RevokeConsent

func (s *MemoryStore) RevokeConsent(_ context.Context, userID id.UserID, appID id.AppID, purpose string) error

type MongoStore

type MongoStore struct {
	// contains filtered or unexported fields
}

MongoStore implements consent.Store using the Grove MongoDB driver.

func NewMongoStore

func NewMongoStore(db *grove.DB) *MongoStore

NewMongoStore creates a new MongoDB-backed consent store.

func (*MongoStore) AnonymizeUserConsents

func (s *MongoStore) AnonymizeUserConsents(ctx context.Context, userID id.UserID) (int64, error)

func (*MongoStore) GetConsent

func (s *MongoStore) GetConsent(ctx context.Context, userID id.UserID, appID id.AppID, purpose string) (*Consent, error)

func (*MongoStore) GrantConsent

func (s *MongoStore) GrantConsent(ctx context.Context, c *Consent) error

func (*MongoStore) ListConsents

func (s *MongoStore) ListConsents(ctx context.Context, q *Query) ([]*Consent, string, error)

func (*MongoStore) RevokeConsent

func (s *MongoStore) RevokeConsent(ctx context.Context, userID id.UserID, appID id.AppID, purpose string) error

type Plugin

type Plugin struct {
	// contains filtered or unexported fields
}

Plugin is the consent tracking plugin.

func New

func New() *Plugin

New creates a new consent plugin. An in-memory consent store is used by default. Use SetConsentStore to inject a persistent store.

func (*Plugin) ExportUserData

func (p *Plugin) ExportUserData(ctx context.Context, userID id.UserID) (category string, data any, err error)

ExportUserData returns the user's consent records for GDPR data export.

func (*Plugin) HasConsent

func (p *Plugin) HasConsent(ctx context.Context, userID id.UserID,
	appID id.AppID, purpose string) (bool, error)

HasConsent reports whether the user currently has an active grant for purpose. A missing record, a revoked grant and an unconfigured store all report false, so a caller gating an outbound send never has to distinguish "no" from "do not know" before deciding not to send.

func (*Plugin) MigrationGroups

func (p *Plugin) MigrationGroups(driverName string) []*migrate.Group

MigrationGroups returns the consent migration groups for the given driver.

func (*Plugin) Name

func (p *Plugin) Name() string

Name returns the plugin name.

func (*Plugin) OnBeforeUserDelete

func (p *Plugin) OnBeforeUserDelete(ctx context.Context, userID id.UserID) error

OnBeforeUserDelete keeps the user's consent history as proof of what was granted and when, with every recorded address reduced to its network.

func (*Plugin) OnInit

func (p *Plugin) OnInit(_ context.Context, engine plugin.Engine) error

OnInit captures engine capabilities.

func (*Plugin) RegisterContract

func (p *Plugin) RegisterContract(
	d *dispatcher.Dispatcher,
	reg contract.Registry,
	wreg contract.WardenRegistry,
	engine plugin.Engine,
) error

func (*Plugin) RegisterRoutes

func (p *Plugin) RegisterRoutes(router forge.Router) error

RegisterRoutes registers consent HTTP routes.

func (*Plugin) SetConsentStore

func (p *Plugin) SetConsentStore(s Store)

SetConsentStore allows direct consent store injection.

type PostgresStore

type PostgresStore struct {
	// contains filtered or unexported fields
}

PostgresStore implements consent.Store using the Grove ORM with PostgreSQL.

func NewPostgresStore

func NewPostgresStore(db *grove.DB) *PostgresStore

NewPostgresStore creates a new PostgreSQL-backed consent store.

func (*PostgresStore) AnonymizeUserConsents

func (s *PostgresStore) AnonymizeUserConsents(ctx context.Context, userID id.UserID) (int64, error)

func (*PostgresStore) GetConsent

func (s *PostgresStore) GetConsent(ctx context.Context, userID id.UserID, appID id.AppID, purpose string) (*Consent, error)

func (*PostgresStore) GrantConsent

func (s *PostgresStore) GrantConsent(ctx context.Context, c *Consent) error

func (*PostgresStore) ListConsents

func (s *PostgresStore) ListConsents(ctx context.Context, q *Query) ([]*Consent, string, error)

func (*PostgresStore) RevokeConsent

func (s *PostgresStore) RevokeConsent(ctx context.Context, userID id.UserID, appID id.AppID, purpose string) error

type Query

type Query struct {
	UserID  id.UserID `json:"user_id"`
	AppID   id.AppID  `json:"app_id"`
	Purpose string    `json:"purpose,omitempty"`
	Cursor  string    `json:"cursor,omitempty"`
	Limit   int       `json:"limit,omitempty"`
}

Query holds filters for listing consent records.

type RevokeConsentRequest

type RevokeConsentRequest struct {
	AppID   string `json:"app_id,omitempty" description:"Application ID"`
	Purpose string `json:"purpose" description:"Consent purpose to revoke"`
}

RevokeConsentRequest binds the body for POST /consent/revoke.

type SqliteStore

type SqliteStore struct {
	// contains filtered or unexported fields
}

SqliteStore implements consent.Store using the Grove ORM with SQLite.

func NewSqliteStore

func NewSqliteStore(db *grove.DB) *SqliteStore

NewSqliteStore creates a new SQLite-backed consent store.

func (*SqliteStore) AnonymizeUserConsents

func (s *SqliteStore) AnonymizeUserConsents(ctx context.Context, userID id.UserID) (int64, error)

func (*SqliteStore) GetConsent

func (s *SqliteStore) GetConsent(ctx context.Context, userID id.UserID, appID id.AppID, purpose string) (*Consent, error)

func (*SqliteStore) GrantConsent

func (s *SqliteStore) GrantConsent(ctx context.Context, c *Consent) error

func (*SqliteStore) ListConsents

func (s *SqliteStore) ListConsents(ctx context.Context, q *Query) ([]*Consent, string, error)

func (*SqliteStore) RevokeConsent

func (s *SqliteStore) RevokeConsent(ctx context.Context, userID id.UserID, appID id.AppID, purpose string) error

type StatusResponse

type StatusResponse struct {
	Status string `json:"status" description:"Operation status"`
}

StatusResponse is a generic status response.

type Store

type Store interface {
	// GrantConsent records or updates a consent grant for a specific purpose.
	// If a consent record already exists for the user+app+purpose combination,
	// it is updated rather than duplicated.
	GrantConsent(ctx context.Context, c *Consent) error

	// RevokeConsent marks a consent as revoked by setting RevokedAt and Granted=false.
	RevokeConsent(ctx context.Context, userID id.UserID, appID id.AppID, purpose string) error

	// GetConsent returns a specific consent record by user, app, and purpose.
	GetConsent(ctx context.Context, userID id.UserID, appID id.AppID, purpose string) (*Consent, error)

	// ListConsents returns all consent records matching the query.
	ListConsents(ctx context.Context, q *Query) ([]*Consent, string, error)

	// AnonymizeUserConsents keeps a deleted user's consent rows as proof of
	// what was granted and when, but replaces each recorded address with
	// its network so the rows stop identifying a device. It reports how
	// many rows changed.
	AnonymizeUserConsents(ctx context.Context, userID id.UserID) (int64, error)
}

Store persists and queries consent records.

Directories

Path Synopsis
Package consenttest provides a backend-agnostic conformance suite for the consent.Store interface.
Package consenttest provides a backend-agnostic conformance suite for the consent.Store interface.
Package contract is the consent plugin's forge-dashboard contract surface.
Package contract is the consent plugin's forge-dashboard contract surface.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL