Documentation
¶
Overview ¶
Package plugin: authz.go — shared route-group guards for plugins.
Plugins register their own routes (see RouteProvider), which means each plugin is responsible for gating its own admin and account surfaces. The helpers here package the same chain the core API uses for /v1/admin so a plugin group can't accidentally ship unauthenticated.
Package plugin: contract.go — optional interface a plugin implements when it ships a forge-dashboard contract surface (manifest + handlers).
Plugins that adopt this interface participate in authsome's RegisterContractContributor lifecycle: the extension iterates every plugin after the auth contributor itself registers, invoking RegisterContract on each implementer in the order they were registered with the plugin registry. Order matters when a plugin extends another plugin's pages — register host-owning plugins first.
This is the only way a plugin contributes to the dashboard; its UI ships as a React plugin that calls these intents. Non-implementers are skipped.
Package plugin defines the plugin system for AuthSome v0.5.0. Plugins implement the base Plugin interface and optionally implement any combination of lifecycle and event hook interfaces.
The registry type-caches plugins at registration time so emit calls iterate only over plugins implementing the relevant hook.
Package plugin: tenant_scope.go — the app tenancy boundary, shared between the core API and plugin route groups.
AdminGuard answers "may this caller manage clients?". It cannot answer "is this client one of theirs?", because that is a property of the caller AND a row the handler has not loaded yet. No middleware can see that row, so the second check necessarily lives in handlers. These helpers are what keeps every handler answering it the same way.
Index ¶
- func AdminGuard(engine Engine, action, resource string) []forge.Middleware
- func AssertAppScope(ctx forge.Context, resourceAppID id.AppID) error
- func CallerAppID(ctx forge.Context) (id.AppID, bool)
- func PermissionGuard(engine Engine, action, resource string) []forge.Middleware
- func PermissionRouteOptions(engine Engine, action, resource string) []forge.RouteOption
- func ScopedAppID(ctx forge.Context, requested string) (id.AppID, error)
- func SessionGuard(engine Engine) []forge.Middleware
- type AfterMemberAdd
- type AfterMemberRemove
- type AfterMemberRoleChange
- type AfterOrgCreate
- type AfterOrgDelete
- type AfterOrgUpdate
- type AfterPrincipalAuth
- type AfterSessionCreate
- type AfterSessionRefresh
- type AfterSessionRevoke
- type AfterSignIn
- type AfterSignOut
- type AfterSignUp
- type AfterUserCreate
- type AfterUserDelete
- type AfterUserUpdate
- type AuthMethod
- type AuthMethodContributor
- type AuthMethodUnlinker
- type BeforeMemberRemove
- type BeforePrincipalAuth
- type BeforeSessionCreate
- type BeforeSignIn
- type BeforeSignOut
- type BeforeSignUp
- type BeforeUserCreate
- type BeforeUserDelete
- type BeforeUserUpdate
- type ContractContributor
- type DataExportContributor
- type DispatcherProvider
- type Engine
- type Extensible
- type LedgerEngineProvider
- type LedgerStoreProvider
- type MigrationProvider
- type NotificationMapping
- type NotificationMappingContributor
- type OnInit
- type OnShutdown
- type PermissionChecker
- type Plugin
- type PrincipalAuthGateProvider
- type Registry
- func (r *Registry) CollectExportData(ctx context.Context, userID id.UserID) map[string]any
- func (r *Registry) CollectMigrationGroups(driverName string) []*migrate.Group
- func (r *Registry) EmitAfterMemberAdd(ctx context.Context, m *organization.Member)
- func (r *Registry) EmitAfterMemberRemove(ctx context.Context, memberID id.MemberID)
- func (r *Registry) EmitAfterMemberRoleChange(ctx context.Context, m *organization.Member)
- func (r *Registry) EmitAfterOrgCreate(ctx context.Context, o *organization.Organization)
- func (r *Registry) EmitAfterOrgDelete(ctx context.Context, orgID id.OrgID)
- func (r *Registry) EmitAfterOrgUpdate(ctx context.Context, o *organization.Organization)
- func (r *Registry) EmitAfterPrincipalAuth(ctx context.Context, a *principal.AuthAttempt, s *session.Session)
- func (r *Registry) EmitAfterSessionCreate(ctx context.Context, s *session.Session)
- func (r *Registry) EmitAfterSessionRefresh(ctx context.Context, s *session.Session)
- func (r *Registry) EmitAfterSessionRevoke(ctx context.Context, sessionID id.SessionID)
- func (r *Registry) EmitAfterSignIn(ctx context.Context, u *user.User, s *session.Session)
- func (r *Registry) EmitAfterSignOut(ctx context.Context, sessionID id.SessionID)
- func (r *Registry) EmitAfterSignUp(ctx context.Context, u *user.User, s *session.Session)
- func (r *Registry) EmitAfterUserCreate(ctx context.Context, u *user.User)
- func (r *Registry) EmitAfterUserDelete(ctx context.Context, userID id.UserID)
- func (r *Registry) EmitAfterUserUpdate(ctx context.Context, u *user.User)
- func (r *Registry) EmitBeforeMemberRemove(ctx context.Context, m *organization.Member) error
- func (r *Registry) EmitBeforePrincipalAuth(ctx context.Context, a *principal.AuthAttempt) error
- func (r *Registry) EmitBeforeSessionCreate(ctx context.Context, s *session.Session) error
- func (r *Registry) EmitBeforeSignIn(ctx context.Context, req *account.SignInRequest) error
- func (r *Registry) EmitBeforeSignOut(ctx context.Context, sessionID id.SessionID) error
- func (r *Registry) EmitBeforeSignUp(ctx context.Context, req *account.SignUpRequest) error
- func (r *Registry) EmitBeforeUserCreate(ctx context.Context, u *user.User) error
- func (r *Registry) EmitBeforeUserDelete(ctx context.Context, userID id.UserID) error
- func (r *Registry) EmitBeforeUserUpdate(ctx context.Context, u *user.User) error
- func (r *Registry) EmitOnInit(ctx context.Context, engine Engine) error
- func (r *Registry) EmitOnShutdown(ctx context.Context)
- func (r *Registry) Plugin(name string) Plugin
- func (r *Registry) Plugins() []Plugin
- func (r *Registry) Register(p Plugin)
- func (r *Registry) RootRouteProviders() []RootRouteProvider
- func (r *Registry) RouteProviders() []RouteProvider
- type RetentionSweeper
- type RootRouteProvider
- type RouteProvider
- type SessionRevoker
- type SettingsProvider
- type StrategyProvider
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AdminGuard ¶
func AdminGuard(engine Engine, action, resource string) []forge.Middleware
AdminGuard returns SessionGuard plus an RBAC permission check, mirroring the core API's /v1/admin chain (middleware.RequireAuth + RequirePermission). Use it for plugin admin groups that manage tenant-wide configuration — OAuth2 clients, SSO connections, provider credentials, billing plans.
The permission check is appended only when the engine implements PermissionChecker. An engine without RBAC still gets session enforcement, which is the property that matters most: the group is never anonymous.
func AssertAppScope ¶
AssertAppScope verifies that a loaded resource belongs to the caller's tenant app. It returns a 404 (not 403) on mismatch so the endpoint never discloses the existence of another app's resource. A missing caller app yields 401.
func CallerAppID ¶
CallerAppID returns the app the authenticated caller is bound to. This is the tenant boundary used to scope app-owned admin resources (webhooks, environments, OAuth2 clients, per-app config) to the caller.
The credential decides: the session's app first, then a machine principal's app. The context app id set by the publishable-key middleware is consulted only when no credential is present (public routes), because a publishable key is public by design and must never move an authenticated caller into another tenant.
func PermissionGuard ¶
func PermissionGuard(engine Engine, action, resource string) []forge.Middleware
PermissionGuard returns just the RBAC permission check, without the session middleware. Use it on individual routes inside a group that already carries SessionGuard — typically to hold mutating routes to a higher bar than the reads they sit beside.
Returns nil when the engine doesn't implement PermissionChecker, so an engine without RBAC falls back to the group's session requirement rather than failing closed on every request.
func PermissionRouteOptions ¶
func PermissionRouteOptions(engine Engine, action, resource string) []forge.RouteOption
PermissionRouteOptions is PermissionGuard adapted to per-route options, for use alongside forge.WithSummary and friends in a route registration.
func ScopedAppID ¶
ScopedAppID resolves the caller's tenant app for create/list operations, rejecting any request that explicitly targets a different app than the caller is bound to. A caller may therefore only ever create or enumerate resources within their own app, never one supplied in the request body/query.
func SessionGuard ¶
func SessionGuard(engine Engine) []forge.Middleware
SessionGuard returns the middleware chain that requires a resolved session on every route in a group. Use it for plugin surfaces that act on behalf of the calling user (creating a key for yourself, reading your own billing).
Pair it with forge.WithGroupAuth("session") so the OpenAPI document advertises the requirement alongside the enforcement:
g := router.Group("/v1/things",
forge.WithGroupAuth("session"),
forge.WithGroupMiddleware(plugin.SessionGuard(engine)...),
)
Returns nil when engine is nil or exposes no auth registry (minimal test wiring), so tests that construct a bare plugin still register routes.
Types ¶
type AfterMemberAdd ¶
type AfterMemberAdd interface {
OnAfterMemberAdd(ctx context.Context, m *organization.Member) error
}
AfterMemberAdd is called after a member is added to an organization.
type AfterMemberRemove ¶
type AfterMemberRemove interface {
OnAfterMemberRemove(ctx context.Context, memberID id.MemberID) error
}
AfterMemberRemove is called after a member is removed from an organization.
type AfterMemberRoleChange ¶
type AfterMemberRoleChange interface {
OnAfterMemberRoleChange(ctx context.Context, m *organization.Member) error
}
AfterMemberRoleChange is called after a member's role is changed.
type AfterOrgCreate ¶
type AfterOrgCreate interface {
OnAfterOrgCreate(ctx context.Context, o *organization.Organization) error
}
AfterOrgCreate is called after an organization is created.
type AfterOrgDelete ¶
AfterOrgDelete is called after an organization is deleted.
type AfterOrgUpdate ¶
type AfterOrgUpdate interface {
OnAfterOrgUpdate(ctx context.Context, o *organization.Organization) error
}
AfterOrgUpdate is called after an organization is updated.
type AfterPrincipalAuth ¶
type AfterPrincipalAuth interface {
OnAfterPrincipalAuth(ctx context.Context, a *principal.AuthAttempt, s *session.Session) error
}
AfterPrincipalAuth is called once a non-human caller has a session. Errors are logged and do not fail the request, matching the other After hooks.
type AfterSessionCreate ¶
type AfterSessionCreate interface {
OnAfterSessionCreate(ctx context.Context, s *session.Session) error
}
AfterSessionCreate is called after a session is created.
type AfterSessionRefresh ¶
type AfterSessionRefresh interface {
OnAfterSessionRefresh(ctx context.Context, s *session.Session) error
}
AfterSessionRefresh is called after a session token is refreshed.
type AfterSessionRevoke ¶
type AfterSessionRevoke interface {
OnAfterSessionRevoke(ctx context.Context, sessionID id.SessionID) error
}
AfterSessionRevoke is called after a session is revoked.
type AfterSignIn ¶
type AfterSignIn interface {
OnAfterSignIn(ctx context.Context, u *user.User, s *session.Session) error
}
AfterSignIn is called after successful authentication.
type AfterSignOut ¶
AfterSignOut is called after session termination.
type AfterSignUp ¶
type AfterSignUp interface {
OnAfterSignUp(ctx context.Context, u *user.User, s *session.Session) error
}
AfterSignUp is called after a new account is created.
type AfterUserCreate ¶
AfterUserCreate is called after a user is created.
type AfterUserDelete ¶
AfterUserDelete is called after a user is deleted.
type AfterUserUpdate ¶
AfterUserUpdate is called after a user is updated.
type AuthMethod ¶
type AuthMethod struct {
Type string `json:"type"` // e.g. "password", "social:google", "passkey", "phone"
Provider string `json:"provider"` // e.g. "google", "github", "password", "phone"
Label string `json:"label"` // Human-readable label, e.g. "Google (user@gmail.com)"
LinkedAt string `json:"linked_at,omitempty"`
}
AuthMethod describes a single authentication method linked to a user account.
type AuthMethodContributor ¶
type AuthMethodContributor interface {
Plugin
ListUserAuthMethods(ctx context.Context, userID id.UserID) ([]*AuthMethod, error)
}
AuthMethodContributor is implemented by plugins that can report which authentication methods are linked to a user. The engine aggregates these to provide a unified "list auth methods" API.
type AuthMethodUnlinker ¶
type AuthMethodUnlinker interface {
Plugin
UnlinkAuthMethod(ctx context.Context, userID id.UserID, provider string) error
CanUnlink(ctx context.Context, userID id.UserID, provider string) bool
}
AuthMethodUnlinker is optionally implemented by plugins that support unlinking an auth method from a user account.
type BeforeMemberRemove ¶
type BeforeMemberRemove interface {
OnBeforeMemberRemove(ctx context.Context, m *organization.Member) error
}
BeforeMemberRemove is called before a member is removed from an organization, while the member record can still be read. AfterMemberRemove carries only the id and fires after deletion, so a plugin that needs to know which user left which org has to use this hook.
type BeforePrincipalAuth ¶
type BeforePrincipalAuth interface {
OnBeforePrincipalAuth(ctx context.Context, a *principal.AuthAttempt) error
}
BeforePrincipalAuth is called before a credential becomes a session for a caller that did not go through sign-in: an API key, a token exchange, a workload JWT.
Returning an error denies the authentication. This is the machine-side counterpart to BeforeSignIn, and it exists because static API key traffic reaches strategy.Authenticate and never fires the sign-in hooks, so every risk plugin was blind to it.
type BeforeSessionCreate ¶
type BeforeSessionCreate interface {
OnBeforeSessionCreate(ctx context.Context, s *session.Session) error
}
BeforeSessionCreate is called before a session is created.
type BeforeSignIn ¶
type BeforeSignIn interface {
OnBeforeSignIn(ctx context.Context, req *account.SignInRequest) error
}
BeforeSignIn is called before authentication.
type BeforeSignOut ¶
BeforeSignOut is called before session termination.
type BeforeSignUp ¶
type BeforeSignUp interface {
OnBeforeSignUp(ctx context.Context, req *account.SignUpRequest) error
}
BeforeSignUp is called before a new account is created.
type BeforeUserCreate ¶
BeforeUserCreate is called before a user is created.
type BeforeUserDelete ¶
BeforeUserDelete is called before a user is deleted.
type BeforeUserUpdate ¶
BeforeUserUpdate is called before a user is updated.
type ContractContributor ¶
type ContractContributor interface {
// RegisterContract is called once during engine bootstrap, after the
// auth contributor's own Register has succeeded. Implementations
// should:
// 1. Load and validate their embedded manifest YAML.
// 2. Register the manifest with reg (which applies any `extends`
// blocks against previously-registered contributors).
// 3. Register every intent handler with d under the manifest's
// contributor name.
//
// Returning a non-nil error aborts the plugin loop — keep error
// messages prefixed with the plugin name so the failing plugin is
// identifiable in startup logs.
RegisterContract(d *dispatcher.Dispatcher, reg contract.Registry, wreg contract.WardenRegistry, engine Engine) error
}
ContractContributor is implemented by plugins that ship a contract manifest + handler bundle. The signature mirrors authsome's own contract.Register, with the addition of the typed Engine handle so plugins don't have to capture it during OnInit just to wire a contract. The Engine parameter is a plugin.Engine interface; plugins that need the concrete *authsome.Engine for app-resolution helpers can type-assert internally.
type DataExportContributor ¶
type DataExportContributor interface {
ExportUserData(ctx context.Context, userID id.UserID) (key string, data any, err error)
}
DataExportContributor allows a plugin to contribute data to the GDPR user export. The returned key names the data section (e.g. "organizations") and data is the payload that will be included in the export.
type DispatcherProvider ¶
type DispatcherProvider interface {
Dispatcher() bridge.Dispatcher
}
DispatcherProvider is optionally implemented by engines that expose a background job queue. A plugin that needs deferred work should fall back to its own goroutine when the host returns nil. *authsome.Engine already satisfies it.
type Engine ¶
type Engine interface {
// Store returns the aggregate persistence store.
Store() store.Store
// DB returns the raw database handle. Returns nil if not set.
DB() *grove.DB
// Plugins returns the plugin registry.
Plugins() *Registry
// Plugin returns a registered plugin by name, or nil if not found.
Plugin(name string) Plugin
// Hooks returns the hook event bus.
Hooks() *hook.Bus
// Logger returns the engine's logger.
Logger() log.Logger
// Settings returns the dynamic settings manager.
Settings() *settings.Manager
// The audit trail is not exposed here on purpose: plugins record through
// bridge.NewBusChronicle(engine.Hooks()) so every event takes the one
// enriched path into Chronicle.
Relay() bridge.EventRelay
Herald() bridge.Herald
Mailer() bridge.Mailer
SMSSender() bridge.SMSSender
Ledger() bridge.Ledger
// TokenEncryptor returns the at-rest Encryptor used for sensitive
// opaque payloads such as third-party OAuth access/refresh tokens.
// Always non-nil — falls back to bridge.NoopEncryptor when no key
// is configured (with a startup warning).
TokenEncryptor() bridge.Encryptor
// SessionConfigForApp resolves per-app (and optional per-environment)
// session configuration.
SessionConfigForApp(ctx context.Context, appID id.AppID, envIDs ...id.EnvironmentID) account.SessionConfig
// TokenFormatForApp returns the token format configured for an app.
TokenFormatForApp(appID string) tokenformat.Format
// CeremonyStore returns the store for short-lived ceremony state.
CeremonyStore() ceremony.Store
// APIKeyStore returns the API key store.
APIKeyStore() apikey.Store
// DPoPValidator returns the RFC 9449 proof validator. Never nil.
DPoPValidator() *dpop.Validator
// DPoPNonceSigner returns the DPoP nonce signer, or nil when no signing
// secret could be derived.
DPoPNonceSigner() *dpop.NonceSigner
// DPoPModeForApp resolves an app's DPoP mode. Fold a per-client value in
// with dpop.MaxMode; a client value must never lower the app's.
DPoPModeForApp(ctx context.Context, appID id.AppID) dpop.Mode
// DPoPNonceRequiredForApp reports whether an app demands a nonce.
DPoPNonceRequiredForApp(ctx context.Context, appID id.AppID) bool
// ResolveSessionByToken resolves a session from its opaque token.
ResolveSessionByToken(ctx context.Context, token string) (*session.Session, error)
// ResolveUser resolves a user by ID string.
ResolveUser(ctx context.Context, userID string) (*user.User, error)
// GetUser fetches a user by typed ID.
GetUser(ctx context.Context, userID id.UserID) (*user.User, error)
// RevokeOtherUserSessions ends every session of the user except keep.
// Plugins call it after a credential change (second factor, passkey) so
// a session an attacker already holds does not survive the change.
RevokeOtherUserSessions(ctx context.Context, userID id.UserID, keep id.SessionID) error
// EnsureDefaultRole assigns the default role to a user if none is set.
EnsureDefaultRole(ctx context.Context, appID id.AppID, userID id.UserID)
// ResolvePrincipal resolves any caller, human or otherwise, by ref.
// Use this rather than ResolveUser when a plugin must work for agents and
// workloads as well as people.
ResolvePrincipal(ctx context.Context, ref principal.Ref) (*principal.Principal, error)
// PrincipalStore returns the principal and delegation store.
PrincipalStore() principal.Store
// Can is the chain-aware authorization check. Pass an empty chain for an
// ordinary single-subject check.
Can(ctx context.Context, subject principal.Ref, actors principal.Chain,
action, resource string) (bool, error)
// AuthMiddleware returns the engine's non-blocking authentication
// middleware (cookie bridge + session resolver + JWT + strategies).
// Populates user context when a valid token is present but passes
// through unauthenticated requests. Applied globally by the extension.
AuthMiddleware() forge.Middleware
// AuthRegistry returns the forge auth provider registry. Plugins can:
// - Register custom auth providers (API keys, SSO, etc.) via Register()
// - Create blocking middleware via Middleware("session", "api-key")
// - Use forge.WithGroupAuth("session") for OpenAPI + enforcement
AuthRegistry() auth.Registry
// RateLimiter returns the engine's rate limiter. May be nil.
RateLimiter() ratelimit.Limiter
// PlatformAppID returns the platform/bootstrap app ID.
PlatformAppID() id.AppID
// DefaultAppID returns the configured app ID string.
DefaultAppID() string
// BasePath returns the URL prefix for auth routes.
BasePath() string
}
Engine is the typed interface that plugins receive during OnInit. It exposes the engine's capabilities without importing the concrete authsome.Engine type (which would create an import cycle).
All commonly-used methods are included here so plugins can call them directly instead of ad-hoc type assertions. For specialised capabilities that would cause import cycles (e.g. warden, keysmith, ledger engines), use the optional interfaces below.
type Extensible ¶
Extensible allows a plugin to accept sub-plugins.
type LedgerEngineProvider ¶
type LedgerEngineProvider interface {
LedgerEngine() any
}
LedgerEngineProvider is optionally implemented by engines with a first-class billing/ledger engine.
type LedgerStoreProvider ¶
type LedgerStoreProvider interface {
LedgerStore() any
}
LedgerStoreProvider is optionally implemented by engines with a ledger store for direct query access.
type MigrationProvider ¶
MigrationProvider allows a plugin to register its own grove migration groups. The engine collects these groups and passes them to Store.Migrate() so plugin tables are created alongside the core schema. The driverName parameter ("pg", "sqlite", "mongo") lets the plugin return driver-specific migration groups.
type NotificationMapping ¶
type NotificationMapping struct {
// Template is the Herald template slug (e.g. "billing.payment-failed").
Template string
// Channels lists the channels to send on (e.g. ["email", "inapp"]).
Channels []string
// Enabled controls whether this mapping is active.
Enabled bool
}
NotificationMapping describes a hook-to-notification template mapping contributed by an external plugin.
type NotificationMappingContributor ¶
type NotificationMappingContributor interface {
Plugin
NotificationMappings() map[string]*NotificationMapping
}
NotificationMappingContributor is implemented by plugins that want to contribute notification template mappings. The notification plugin collects these during initialization to extend its default mappings. Plugin-contributed mappings do not override user-provided config mappings.
type OnInit ¶
OnInit is called during engine initialization. The engine parameter provides typed access to all engine capabilities.
type OnShutdown ¶
OnShutdown is called during engine shutdown.
type PermissionChecker ¶
type PermissionChecker interface {
HasPermission(ctx context.Context, userID id.UserID, action, resource string) (bool, error)
}
PermissionChecker is optionally implemented by engines that support RBAC permission checking. Mirrors middleware.PermissionChecker to avoid importing the middleware package from the plugin package.
type Plugin ¶
type Plugin interface {
Name() string
}
Plugin is the base interface that all plugins must implement.
type PrincipalAuthGateProvider ¶
type PrincipalAuthGateProvider interface {
PrincipalAuthGate() any
}
PrincipalAuthGateProvider is optionally implemented by engines that score machine callers (API keys, and anything else authenticating without a human sign-in) through the principal-auth hooks before minting a session. Returns any, not a named gate type, so this package does not have to import a specific plugin's interface (which would create an import cycle with a plugin that itself needs the concrete authsome.Engine type, as the apikey plugin does). The consuming plugin type-asserts the result against its own narrow gate interface. *authsome.Engine satisfies it.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry holds registered plugins and dispatches lifecycle events. It type-caches plugins at registration time so emit calls iterate only over plugins implementing the relevant hook.
func NewRegistry ¶
NewRegistry creates a plugin registry with the given logger.
func (*Registry) CollectExportData ¶
CollectExportData gathers data from all plugins that implement DataExportContributor. The returned map is keyed by each plugin's export key (e.g. "organizations") and contains the exported data.
func (*Registry) CollectMigrationGroups ¶
CollectMigrationGroups gathers migration groups from all plugins that implement MigrationProvider for the given driver name.
func (*Registry) EmitAfterMemberAdd ¶
func (r *Registry) EmitAfterMemberAdd(ctx context.Context, m *organization.Member)
EmitAfterMemberAdd notifies all plugins that implement AfterMemberAdd.
func (*Registry) EmitAfterMemberRemove ¶
EmitAfterMemberRemove notifies all plugins that implement AfterMemberRemove.
func (*Registry) EmitAfterMemberRoleChange ¶
func (r *Registry) EmitAfterMemberRoleChange(ctx context.Context, m *organization.Member)
EmitAfterMemberRoleChange notifies all plugins that implement AfterMemberRoleChange.
func (*Registry) EmitAfterOrgCreate ¶
func (r *Registry) EmitAfterOrgCreate(ctx context.Context, o *organization.Organization)
EmitAfterOrgCreate notifies all plugins that implement AfterOrgCreate.
func (*Registry) EmitAfterOrgDelete ¶
EmitAfterOrgDelete notifies all plugins that implement AfterOrgDelete.
func (*Registry) EmitAfterOrgUpdate ¶
func (r *Registry) EmitAfterOrgUpdate(ctx context.Context, o *organization.Organization)
EmitAfterOrgUpdate notifies all plugins that implement AfterOrgUpdate.
func (*Registry) EmitAfterPrincipalAuth ¶
func (r *Registry) EmitAfterPrincipalAuth(ctx context.Context, a *principal.AuthAttempt, s *session.Session)
EmitAfterPrincipalAuth notifies all plugins that implement AfterPrincipalAuth. Errors are logged, never propagated.
func (*Registry) EmitAfterSessionCreate ¶
EmitAfterSessionCreate notifies all plugins that implement AfterSessionCreate.
func (*Registry) EmitAfterSessionRefresh ¶
EmitAfterSessionRefresh notifies all plugins that implement AfterSessionRefresh.
func (*Registry) EmitAfterSessionRevoke ¶
EmitAfterSessionRevoke notifies all plugins that implement AfterSessionRevoke.
func (*Registry) EmitAfterSignIn ¶
EmitAfterSignIn notifies all plugins that implement AfterSignIn.
func (*Registry) EmitAfterSignOut ¶
EmitAfterSignOut notifies all plugins that implement AfterSignOut.
func (*Registry) EmitAfterSignUp ¶
EmitAfterSignUp notifies all plugins that implement AfterSignUp.
func (*Registry) EmitAfterUserCreate ¶
EmitAfterUserCreate notifies all plugins that implement AfterUserCreate.
func (*Registry) EmitAfterUserDelete ¶
EmitAfterUserDelete notifies all plugins that implement AfterUserDelete.
func (*Registry) EmitAfterUserUpdate ¶
EmitAfterUserUpdate notifies all plugins that implement AfterUserUpdate.
func (*Registry) EmitBeforeMemberRemove ¶
EmitBeforeMemberRemove notifies all plugins that implement BeforeMemberRemove. Unlike EmitAfterMemberRemove, which fires after deletion and only logs a hook's error, this fires before deletion and returns the first error so the caller can abort the removal, matching EmitBeforeUserDelete.
func (*Registry) EmitBeforePrincipalAuth ¶
EmitBeforePrincipalAuth notifies all plugins that implement BeforePrincipalAuth, stopping at the first error.
func (*Registry) EmitBeforeSessionCreate ¶
EmitBeforeSessionCreate notifies all plugins that implement BeforeSessionCreate.
func (*Registry) EmitBeforeSignIn ¶
EmitBeforeSignIn notifies all plugins that implement BeforeSignIn.
func (*Registry) EmitBeforeSignOut ¶
EmitBeforeSignOut notifies all plugins that implement BeforeSignOut.
func (*Registry) EmitBeforeSignUp ¶
EmitBeforeSignUp notifies all plugins that implement BeforeSignUp.
func (*Registry) EmitBeforeUserCreate ¶
EmitBeforeUserCreate notifies all plugins that implement BeforeUserCreate.
func (*Registry) EmitBeforeUserDelete ¶
EmitBeforeUserDelete notifies all plugins that implement BeforeUserDelete.
func (*Registry) EmitBeforeUserUpdate ¶
EmitBeforeUserUpdate notifies all plugins that implement BeforeUserUpdate.
func (*Registry) EmitOnInit ¶
EmitOnInit notifies all plugins that implement OnInit, stopping at the first failure and returning it.
Unlike the after-hooks, an OnInit error is fatal rather than logged. OnInit is where a plugin resolves its store, keys, and bridges; a plugin that fails here is not "degraded", it is absent. Continuing would leave the engine serving traffic with a security control silently missing — an MFA plugin that never wired its store enforces nothing — and a warning in the startup log is not a reliable way to notice. Startup is the one point where failing loudly costs nothing.
func (*Registry) EmitOnShutdown ¶
EmitOnShutdown notifies all plugins that implement OnShutdown.
func (*Registry) Register ¶
Register adds a plugin and type-asserts it into all applicable hook caches. Plugins are notified in registration order. Duplicate plugins (same Name()) are silently skipped.
func (*Registry) RootRouteProviders ¶
func (r *Registry) RootRouteProviders() []RootRouteProvider
RootRouteProviders returns all plugins that provide origin-root routes.
func (*Registry) RouteProviders ¶
func (r *Registry) RouteProviders() []RouteProvider
RouteProviders returns all plugins that provide routes.
type RetentionSweeper ¶
type RetentionSweeper interface {
SweepRetention(ctx context.Context, cutoff func(kind string) time.Time, batch int) (int64, error)
}
RetentionSweeper is implemented by a plugin that keeps rows with a lifetime of their own. The engine's retention sweeper calls it on every run: cutoff returns the instant before which rows of a kind (a store.Retention* name, or the plugin's own) may go, or the zero time when that kind is kept forever; batch is how many rows one delete may remove. The plugin loops until a batch comes back short and reports the total.
type RootRouteProvider ¶
RootRouteProvider is implemented by plugins that must serve routes at the origin root rather than under the extension's mount prefix. Well-known discovery documents are the only legitimate use: RFC 8414 and RFC 9728 define their locations relative to the origin, so a prefixed copy is invisible to a client that only knows the host.
type RouteProvider ¶
RouteProvider allows a plugin to register additional HTTP routes.
type SessionRevoker ¶
SessionRevoker is optionally implemented by engines that can revoke a single session by ID. Revoking through this rather than deleting rows directly keeps the AfterSessionRevoke hooks, the hook bus and the outbound relay firing. *authsome.Engine already satisfies it.
type SettingsProvider ¶
SettingsProvider is implemented by plugins that declare configurable settings via the dynamic settings system. The engine calls DeclareSettings during initialization so the settings are registered before use.
type StrategyProvider ¶
StrategyProvider is implemented by plugins that contribute an authentication strategy to the strategy registry. The engine auto-registers these strategies during Start() so they participate in layered auth middleware evaluation.