domain

package
v1.0.0-alpha.21 Latest Latest
Warning

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

Go to latest
Published: Sep 3, 2026 License: AGPL-3.0 Imports: 43 Imported by: 0

Documentation

Index

Constants

View Source
const (
	SystemCatalogID      = "cat_sys_1"
	SystemCatalogOwnerID = "system"
)

System catalog identity (must match Goose seed).

View Source
const (
	BrandingLayoutCentered = "centered"
	BrandingLayoutSplit    = "split"
)

Branding layout presets understood by the bundled login template. The wire enum is defined in api/openapi/components/flows/branding.yaml; richer designs are delivered as Liquid templates, not new enum values (ADR 040).

View Source
const (
	EnvironmentNameMaxLength = 63
	EnvironmentNamePattern   = `^[a-z0-9]([a-z0-9-]*[a-z0-9])?$`
)
View Source
const (
	// FlowStepErrorInvalidCredentials reports a rejected password
	// proof. The client routes it inline to the password field
	// (fieldErrorKeys in liquid.ts).
	FlowStepErrorInvalidCredentials = "error.invalid_credentials"
	// FlowStepErrorPasskeyInvalid reports a rejected passkey assertion.
	FlowStepErrorPasskeyInvalid = "error.passkey_invalid"
	// FlowStepErrorPasskeyRegistrationInvalid reports a rejected
	// passkey registration attestation.
	FlowStepErrorPasskeyRegistrationInvalid = "error.passkey_registration_invalid"
)

Step error text keys the state machine emits when an auth-attempt proof is rejected. Every engine-emitted step error must be a localizable `error.*` catalog key or a reserved outcome token: /login localizes only `error.*`-prefixed step errors and treats outcome tokens as routing, so anything else renders verbatim (see `localiseFlowErrorKeys` in packages/components/src/orchestrator/liquid.ts). New emission sites add a const here; FlowStepErrorAllowed and its contract test keep the set honest.

View Source
const (
	DefaultMaxJSONSchemaResolveDepth = 10
	DefaultMaxJSONSchemaSize         = 1 << 20 // 1 MB

)
View Source
const (
	// SchemaAnnotationIdentifier designates the leaf property whose value
	// identifies a user (ADR 058 §1). Schema-root, dot-joined path.
	SchemaAnnotationIdentifier = "x-identifier"
	// SchemaAnnotationDisplay lists the leaf property paths rendering the
	// user's display name (ADR 058 §2). Schema-root.
	SchemaAnnotationDisplay = "x-display"
	// SchemaAnnotationUnique carries a property's uniqueness scope.
	SchemaAnnotationUnique = "x-unique"
	// SchemaAnnotationAuthMethods configures the schema's auth methods.
	SchemaAnnotationAuthMethods = "x-auth-methods"
)

Platform annotations read from tenant schema documents. One spelling each — a mistyped annotation does not fail loudly, it reads as absent.

View Source
const (
	SchemaUniqueScopeProject = "project"
	SchemaUniqueScopeTeam    = "team"
)

Values of the SchemaAnnotationUnique annotation.

View Source
const (
	PasskeyNameSecurityKey = "Security key"
	PasskeyNameSynced      = "Synced passkey"
	PasskeyNameDeviceBound = "Device-bound passkey"
)

Fallback passkey names, used when registration carries no caller-supplied name. WebAuthn reports no human-readable label for the authenticator, so the fallback describes the credential itself.

View Source
const AuthAttemptTTL = 15 * time.Minute
View Source
const ClaimChallengeTTL = 10 * time.Minute

ClaimChallengeTTL is the challenge lifetime (ADR 046 §3).

View Source
const FlowActionPasskey = "passkey"

FlowActionPasskey is the action a step declares to offer passkey authentication. Selecting it issues a WebAuthn challenge; the matching transition fires once the returned assertion verifies.

View Source
const FlowActionPasskeyRegister = "passkey_register"

FlowActionPasskeyRegister is the action a step declares to offer passkey enrollment. Selecting it issues a registration challenge; the matching transition fires once the returned attestation verifies.

View Source
const FlowActionSubmit = "submit"

FlowActionSubmit is the conventional outcome name for the primary "advance forward" action on a step.

View Source
const FlowChallengeMethodPasskey = "passkey"

FlowChallengeMethodPasskey is the FlowStepChallenge.Method / FlowPendingChallenge.Method value for the WebAuthn passkey ceremony.

View Source
const FlowChallengeMethodPasskeyRegister = "passkey_register"

FlowChallengeMethodPasskeyRegister is the FlowStepChallenge.Method / FlowPendingChallenge.Method value for the WebAuthn registration ceremony.

View Source
const FlowImplicitOutcomeUserAlreadyExists = "user_already_exists"

FlowImplicitOutcomeUserAlreadyExists drives the register → login flip.

View Source
const FlowImplicitOutcomeUserNotFound = "user_not_found"

FlowImplicitOutcomeUserNotFound drives the login → register flip.

View Source
const MaxBrandingTemplateBytes = 131072 // 128 KiB

MaxBrandingTemplateBytes caps the stored template size. Matches the maxLength on branding.liquid_template in the OpenAPI contract (which ogen enforces in characters; this gate re-checks in bytes).

View Source
const PasskeyRegistrationChallengeTTL = 5 * time.Minute

PasskeyRegistrationChallengeTTL bounds the registration ceremony: the attestation must come back within this window even though the attempt itself lives longer.

View Source
const SchemaDocumentKindUser = "user-schema"

SchemaDocumentKindUser is the `kind` discriminator of a user schema document (distinct from SchemaKindUser, the meta-schema filename stem).

View Source
const TeamNameMaxLength = 200

TeamNameMaxLength bounds the name in characters.

Variables

View Source
var (
	ErrMissingBuiltinPublicBase    = errors.New("missing builtinPublicBase")
	ErrInvalidBuiltinPublicBase    = errors.New("invalid builtinPublicBase")
	ErrBuiltinTemplateRenderFailed = errors.New("failed to render builtin template")
	ErrMetaSchemaCompileFailed     = errors.New("failed to compile meta-schema")
	ErrMissingBuiltinMetaSchema    = errors.New("missing built-in meta-schema")
	ErrMetaSchemaRefNotFound       = errors.New("meta-schema $ref not found in builtins")
	ErrMaxResolveDepthReached      = errors.New("max resolve depth reached")
	ErrSchemaValidationFailed      = errors.New("schema validation failed")
	ErrSchemaParseFailed           = errors.New("schema parse failed")
	ErrMissingSchemaID             = errors.New("missing schema ID")
	ErrUnknownSchemaURI            = errors.New("unknown built-in schema URI")
	ErrUnknownSchemaKind           = errors.New("unknown schema kind")
)

Errors

View Source
var DefaultEnvironmentNames = []string{"dev", "staging", "prod"}
View Source
var ErrEmptyRecoveryCodes = errors.New("recovery codes must contain at least one code")
View Source
var ErrFlowFieldNotScalar = errors.New("flow field: not a scalar property, name a nested leaf instead")

ErrFlowFieldNotScalar is returned by FlowFieldResolver.Resolve when a field names an object- or array-typed property. An object is collected one leaf at a time through its dotted path (`address.street`); an array has no field-shaped input.

View Source
var ErrFlowFieldUnknown = errors.New("flow field: not a property in the user schema")

ErrFlowFieldUnknown is returned by FlowFieldResolver.Resolve when a requested field name is not a property in the user schema. The offending field name is appended via `fmt.Errorf("%w: %q", ...)`.

View Source
var ErrFlowFieldUnsupportedType = errors.New("flow field: unsupported JSON type")

ErrFlowFieldUnsupportedType is returned by FlowFieldResolver.Resolve when a property declares a JSON `type` set the resolver cannot reduce to a single input kind. The nullable idiom `["null", X]` is reduced to X and does not trigger this error; any other multi-entry union does.

View Source
var ErrInvalidTokenType = errors.New("token type is not persistable")

ErrInvalidTokenType is returned when a token type cannot be stored (see TokenType.Persistable).

View Source
var ErrSchemaDesignationInvalid = errors.New("schema designation invalid")

ErrSchemaDesignationInvalid reports an x-identifier / x-display designation the user meta-schema cannot check itself (ADR 058 §1–§2): the named property must exist, be a leaf, and — for x-identifier — carry project-scoped uniqueness; a schema that enables an auth method needing identifier-first dispatch must designate an identifier.

View Source
var PlatformProjectID = PrefixProject.IDPrefix("platform") // "proj_platform"

PlatformProjectID is the well-known id of the deployment's platform project. The server owns it: bootstrap (platform.bootstrap_project) creates this row and default-project resolution pins to it. Readable body per ADR 047 §3.3; operators never author it.

RosterMembershipStatuses are the participation states that keep a user on a team's roster. MembershipStatusRemoved is deliberately absent: a removed membership is history, not roster, and roster reads must not serve it.

Functions

func AuthCheckTypeStrings

func AuthCheckTypeStrings() []string

AuthCheckTypeStrings returns a slice of all String values of the enum

func BuildPasskeyCreationOptions

func BuildPasskeyCreationOptions(c *AuthChallengePasskeyRegistration) ([]byte, error)

BuildPasskeyCreationOptions renders the stored registration challenge as the WebAuthn PublicKeyCredentialCreationOptions JSON the browser passes to navigator.credentials.create(). Mirrors BuildPasskeyRequestOptions for the registration ceremony.

func BuildPasskeyRequestOptions

func BuildPasskeyRequestOptions(c *AuthChallengePasskey) ([]byte, error)

BuildPasskeyRequestOptions renders the stored passkey challenge as the WebAuthn PublicKeyCredentialRequestOptions JSON (wrapped in the standard `{"publicKey": ...}` envelope) that the browser passes to navigator.credentials.get(). It reconstructs the options from the persisted challenge fields rather than the discarded ceremony output (see CreatePasskeyChallenge), so the flow engine and the auth-attempt REST API can share one mapping.

func CheckAs

func CheckAs[T AuthFactor](attempt *AuthAttempt, typ AuthCheckType) (T, bool)

CheckAs retrieves a check of the given type from the attempt and casts it to a specific AuthFactor type, returning the typed factor and true if it exists and matches the type.

func DecodePasskeyCredentialID

func DecodePasskeyCredentialID(s string) []byte

DecodePasskeyCredentialID reverses EncodePasskeyCredentialID.

func DesignatedAttributeKeys

func DesignatedAttributeKeys(schemaDocument []byte) []string

DesignatedAttributeKeys returns the attribute keys a schema document's designations read — the hydration set a batch ref resolution needs (ADR 058 §3a: rows hydrate only the designated attribute keys).

func DesignatedDisplay

func DesignatedDisplay(document []byte) []string

DesignatedDisplay reads the root x-display designation from a raw schema document: the ordered property paths whose values render the user's display name (ADR 058 §2). Same reader contract as DesignatedIdentifier — anything unreadable, including non-string entries, reads as undesignated.

func DesignatedIdentifier

func DesignatedIdentifier(document []byte) string

DesignatedIdentifier reads the root x-identifier designation from a raw schema document. It returns "" for a document that designates nothing — including one that is not a JSON object, since designation validity is enforced when the schema is created ([validateUserSchemaDesignations]) and readers treat anything unreadable as undesignated.

func EncodePasskeyCredentialID

func EncodePasskeyCredentialID(id []byte) string

EncodePasskeyCredentialID returns the storage form for WebAuthn credential IDs. Credential IDs are arbitrary bytes, so TEXT database columns must store an ASCII-safe representation.

func FieldsToStrings

func FieldsToStrings(f []Field) []string

FieldsToStrings lowers typed Field values back to wire-format strings at the API/repository boundary.

func FlattenValidationErrors

func FlattenValidationErrors(err error) map[string]string

FlattenValidationErrors collects meta-schema validation errors into a loc → msg map. loc segments are joined with "/" (e.g. "/required/x-auth-methods").

func FlowActionKindStrings

func FlowActionKindStrings() []string

FlowActionKindStrings returns a slice of all String values of the enum

func FlowDefinitionPurposeStrings

func FlowDefinitionPurposeStrings() []string

FlowDefinitionPurposeStrings returns a slice of all String values of the enum

func FlowDefinitionStatusStrings

func FlowDefinitionStatusStrings() []string

FlowDefinitionStatusStrings returns a slice of all String values of the enum

func FlowDefinitionTransitionActionStrings

func FlowDefinitionTransitionActionStrings() []string

FlowDefinitionTransitionActionStrings returns a slice of all String values of the enum

func FlowGateKindStrings

func FlowGateKindStrings() []string

FlowGateKindStrings returns a slice of all String values of the enum

func FlowOnSuccessStrings

func FlowOnSuccessStrings() []string

FlowOnSuccessStrings returns a slice of all String values of the enum

func FlowStepCompleteStrings

func FlowStepCompleteStrings() []string

FlowStepCompleteStrings returns a slice of all String values of the enum

func FlowStepErrorAllowed

func FlowStepErrorAllowed(key string) bool

FlowStepErrorAllowed reports whether a step error value honors the client contract: a localizable `error.*` text key or a reserved outcome token (reservedOutcomes in flow_definition_validator.go).

func GeneratePasskeyCredentialName

func GeneratePasskeyCredentialName(transports []string, backupEligible bool) string

PasskeyCredentialName returns the name stored for a registered credential. A caller-supplied name always wins; otherwise the name is derived from the credential's transports and backup eligibility. It never returns an empty string: the passkey list is a user-facing management surface, so every credential needs something displayable — the user's display name is not a candidate, since it is identical for every credential they register.

func HashClaimChallengeToken

func HashClaimChallengeToken(plain string) string

HashClaimChallengeToken derives the stored challenge id from a presented plaintext token. The claim_challenges.id column is TEXT, so unlike the handoff token's raw []byte hash this one is hex-encoded.

func HashPassword

func HashPassword(password string, hasher crypto.Hasher) (string, error)

func HashSecret

func HashSecret(plain string) string

HashSecret is the proof-of-possession hash of a presented bearer string (ADR 029): hex-encoded SHA-256. HandleOAuth2 stores it on claim init and the claim service compares it on claim/status with a constant-time compare, so the handler, domain, and tests must all derive it from this one definition.

func ImplicitOutcomesForChallenge

func ImplicitOutcomesForChallenge(c FlowFieldChallenge) []string

ImplicitOutcomesForChallenge returns the transition outcomes a field contributes by virtue of its challenge. Returns nil when the challenge implies no outcomes. Resolvers call it to populate FlowResolvedFields.ImplicitOutcomes; the state machine calls it to validate flow definitions against schema-implied outcomes.

func JSONSchemaKindStrings

func JSONSchemaKindStrings() []string

JSONSchemaKindStrings returns a slice of all String values of the enum

func NewClaimChallengeToken

func NewClaimChallengeToken() (plain, id string, err error)

NewClaimChallengeToken mints the plaintext challenge token and the stored challenge id (handoff-token pattern, ADR 046 §3): 128 bits of crypto/rand, prefixed and base64url-encoded. Only the id — the SHA-256 of the plaintext — is ever persisted; the plaintext travels in the claim_url and the CLI poll.

The plaintext uses the wire prefix "ch_" (challenge-id.yaml pins ^ch_[a-zA-Z0-9_-]+$, shared with the api-mock and CLI, and ogen validates it on input and output). PrefixClaimChallenge stays for error codes only; the stored id is an unprefixed hex digest either way.

func PasskeysToCredentials

func PasskeysToCredentials(passkeys []*UserPasskey) []webauthn.Credential

func RequireNonEmptyRecoveryCodes

func RequireNonEmptyRecoveryCodes(codes []string) error

func ResolveSessionTTL

func ResolveSessionTTL(requested *time.Duration, defaultTTL, maxTTL time.Duration) (time.Duration, error)

ResolveSessionTTL picks the effective session TTL for exchange. When requested is nil, defaultTTL is used. Otherwise requested must be positive and <= maxTTL.

func TeamBoundObjectType

func TeamBoundObjectType(objectType string) bool

TeamBoundObjectType reports whether objectType is always team-scoped for sk_team_ principals (user, team, team_membership, event). Mint-time validation and the sk_team allowlist share this set so a new allowlist entry cannot silently allow project-scoped minting.

func TokenTypeStrings

func TokenTypeStrings() []string

TokenTypeStrings returns a slice of all String values of the enum

func UniqueValueHash

func UniqueValueHash(value any) ([sha256.Size]byte, error)

UniqueValueHash is the one comparison function behind attribute uniqueness: the unique-attributes registry stores it and identifier resolution looks it up, so both always agree on what counts as the same value (ADR 058 §4a). String values are Unicode case-folded before hashing — Alice@Example.com and alice@example.com are one unique value — while the attribute itself keeps its original casing. Non-string values hash as encoded.

func ValidateBranding

func ValidateBranding(b *Branding) error

ValidateBranding is the lexical save gate for branding revisions.

func ValidateEnvironmentName

func ValidateEnvironmentName(name string) (string, error)

ValidateEnvironmentName returns the trimmed name, or ErrEnvironmentNameInvalid.

func ValidateSessionToken

func ValidateSessionToken(token *Token) error

func ValidateTeamName

func ValidateTeamName(name string) (string, error)

ValidateTeamName returns the trimmed name, or ErrTeamNameInvalid when it is empty or longer than TeamNameMaxLength.

func WriteBuiltinJSONSchema

func WriteBuiltinJSONSchema(w io.Writer, schemaPath string, canonicalDocumentURL string) error

WriteBuiltinJSONSchema renders a built-in JSON schema to w. schemaPath is the URL path after the configured public base, including the .json filename (for example user/v1/user.schema.json for URL https://iam.example.com/schema/user/v1/user.schema.json when the public base is https://iam.example.com/schema). canonicalDocumentURL must be the absolute schema URL used as JSON Schema $id and for resolution (typically the request URL used to serve this document).

Types

type Attribute

type Attribute struct {
	Key   AttributeKey `json:"key"`
	Value any          `json:"value"`
}

type AttributeKey

type AttributeKey string

func (AttributeKey) AppendNode

func (k AttributeKey) AppendNode(node string) AttributeKey

func (AttributeKey) Nodes

func (k AttributeKey) Nodes() []string

type AttributeUniqueness

type AttributeUniqueness int
const (
	AttributeUniquenessUnspecified AttributeUniqueness = iota
	AttributeUniquenessTeam
	AttributeUniquenessProject
)

type Attributes

type Attributes []Attribute

func AttributesFromMap

func AttributesFromMap(m map[string]any) Attributes

func (Attributes) Get

func (attrs Attributes) Get(key AttributeKey) (value any, ok bool)

Get returns the value for the given key.

TODO(go v27): make this method generic

func (Attributes) MarshalJSON

func (attrs Attributes) MarshalJSON() ([]byte, error)

func (Attributes) ToMap

func (attrs Attributes) ToMap() (map[string]any, error)

func (*Attributes) UnmarshalJSON

func (attrs *Attributes) UnmarshalJSON(data []byte) error

type AuthAttempt

type AuthAttempt struct {
	// ProjectID links to [Project].
	ProjectID string
	// ID is the unique identifier for the auth attempt within the project.
	// The storage layer assigns this value on Create (dialect-minted prefixed opaque string).
	ID string

	// HandoffToken is the single-use token minted explicitly with the handoff call after all required factors are verified, used by the client to exchange for a session.
	HandoffToken *HandoffToken
	// HandedOffAt is the timestamp when the handoff token was generated after the attempt was completed.
	HandedOffAt *time.Time

	// Used to link an auth attempt to a session. Use case is step up auth.
	// In this case we need to copy the factors from the session back to the auth attempt.
	SessionID *string

	// Links to the [AuthCheck]s that belong to the auth attempt.
	// An auth attempt can have multiple checks (e.g. for multi-factor authentication), but a check can only belong to one auth attempt.
	Checks         []AuthCheck
	RequiredChecks []AuthCheckType

	// The time when the auth attempt was created, it must be set by the storage and is read-only.
	CreatedAt time.Time

	// TTL describes how long an auth attempt is valid, it should be set to a reasonable value (e.g. 5 minutes) to prevent abuse and to ensure that old auth attempts are cleaned up.
	// An auth attempt gets garbage collected after CreatedAt + TimeToLive, so it is important to set it to a reasonable value to prevent abuse and to ensure that old auth attempts are cleaned up.
	TimeToLive *time.Duration

	// Internal marks a server-orchestrated ceremony (e.g. management-plane
	// passkey enrollment, ADR 056) whose attempt row is only a state carrier:
	// it must never be handed off, exchanged, or read through the attempt API.
	Internal bool
}

AuthAttempt represents the object defined [here](https://github.com/zitadel/nextgen/blob/15bd7f438d709fcd5205a163e24374f6f667b68f/docs/design/api/resource-map.md#auth-flows) It is short-lived and should therefore be stored near the client, do not store PII data in it.

func NewAuthAttempt

func NewAuthAttempt(projectID string, requiredChecks []AuthCheckType, opts ...AuthAttemptOption) (*AuthAttempt, error)

func (*AuthAttempt) ChallengeByID

func (a *AuthAttempt) ChallengeByID(id string) (AuthChallenge, bool)

ChallengeByID returns the check with the given challenge ID. Used to validate that a client's challenge ID is current before accepting a proof.

func (*AuthAttempt) ChallengeByType

func (a *AuthAttempt) ChallengeByType(typ AuthCheckType) (AuthChallenge, bool)

ChallengeByType returns the challenge of the given type, if it exists on the attempt.

func (*AuthAttempt) ExpiresAt

func (a *AuthAttempt) ExpiresAt() time.Time

ExpiresAt returns the timestamp when the attempt expires.

func (*AuthAttempt) FactorByClass

func (a *AuthAttempt) FactorByClass(typ AuthCheckType) (AuthFactor, bool)

FactorByClass returns a verified factor whose type competes in typ's class (see AuthCheckType.Class), if one exists on the attempt.

func (*AuthAttempt) FactorByType

func (a *AuthAttempt) FactorByType(typ AuthCheckType) (AuthFactor, bool)

FactorByType returns the verified factor of the given type, if it exists on the attempt.

func (*AuthAttempt) HasProvisionalRegistrationHandle

func (a *AuthAttempt) HasProvisionalRegistrationHandle(userID string) bool

HasProvisionalRegistrationHandle reports whether the attempt's current registration challenge is provisional and carries the given user handle. This is the only situation in which a caller-supplied handle is known to be server-minted, so a re-issued challenge may keep it; any other unknown handle must be replaced by a fresh mint, never adopted.

func (*AuthAttempt) IsCompleted

func (a *AuthAttempt) IsCompleted() bool

IsCompleted returns true if all required checks are verified successfully. Matching is by factor class, so a completed passkey enrollment satisfies a required passkey check.

func (*AuthAttempt) IsExpired

func (a *AuthAttempt) IsExpired() bool

IsExpired returns true if the attempt's TTL has elapsed. Returns false if the attempt is not yet initialized (zero CreatedAt) or TTL is nil.

func (*AuthAttempt) IsHandedOff

func (a *AuthAttempt) IsHandedOff() bool

IsHandedOff returns true if a handoff token has been generated.

func (*AuthAttempt) PrepareChallenge

func (a *AuthAttempt) PrepareChallenge(typ AuthCheckType) error

PrepareChallenge validates that a challenge can be issued for the given check type.

func (*AuthAttempt) PrepareHandoff

func (a *AuthAttempt) PrepareHandoff() error

PrepareHandoff validates that a handoff can be issued. And will generate and store the handoff token. Note: The HandoffToken is generated using a crypto/rand token and stored in a hashed way for security reasons.

func (*AuthAttempt) PreparePasskeyChallenge

func (a *AuthAttempt) PreparePasskeyChallenge() (string, error)

PreparePasskeyChallenge validates that a passkey challenge can be issued and returns the user ID if the user was already identified.

func (*AuthAttempt) PreparePasskeyRegistrationChallenge

func (a *AuthAttempt) PreparePasskeyRegistrationChallenge(requestedUserID string) (userID string, provisional bool, err error)

PreparePasskeyRegistrationChallenge validates that a passkey registration challenge can be issued and resolves the user handle for the ceremony. Unlike password, no prior user factor is required: registration is how a user comes to exist in the first place.

With a pinned user factor the enrollment targets that user (requestedUserID must match when set) and the ceremony is not provisional. Without one the ceremony is provisional: every authenticated path persists a user factor — including discoverable passkey login — so an unpinned attempt has no user. A non-empty requestedUserID is kept by the caller only when AuthAttempt.HasProvisionalRegistrationHandle confirms it is the handle of the attempt's own in-flight ceremony (a re-issued challenge); any other handle must be replaced by a fresh mint, so a caller-chosen id never becomes a user id. An empty handle signals the caller to mint a fresh one.

func (*AuthAttempt) PreparePasskeyRegistrationVerification

func (a *AuthAttempt) PreparePasskeyRegistrationVerification(challengeID string) (*AuthChallengePasskeyRegistration, error)

PreparePasskeyRegistrationVerification validates that a registration proof can be submitted. Beyond the generic checks it enforces the ceremony's own window (PasskeyRegistrationChallengeTTL), which is tighter than the attempt TTL, and that the attempt's user state still matches what the challenge was issued for: an authentication that happened after the issue supersedes the ceremony. Without this, a provisional attestation could create a second user on an attempt that meanwhile authenticated user A — overwriting the user check A→H while A's other factors survive, so the handoff would mint a session for H carrying factors verified against A.

func (*AuthAttempt) PreparePasskeyVerification

func (a *AuthAttempt) PreparePasskeyVerification(challengeID string) (AuthChallenge, *AuthFactorUser, error)

PreparePasskeyVerification validates that a passkey proof can be submitted. It returns the already-identified user when one is pinned (identified login), or a nil user factor for a discoverable/usernameless login where the user is resolved cryptographically from the assertion's user handle.

Allowing a nil user factor is safe because subject-switching is structurally prevented: when a user is already pinned, verification runs the identified path constrained to that user's credentials, so an assertion from any other credential simply fails. A nil user factor only occurs on a clean attempt (a password factor cannot exist without a user factor), so discoverable login cannot override an authenticated subject.

func (*AuthAttempt) PreparePasswordChallenge

func (a *AuthAttempt) PreparePasswordChallenge() error

PreparePasswordChallenge validates that a password challenge can be issued, which requires that a user was already identified to prevent issuing password challenges without a known user.

func (*AuthAttempt) PreparePasswordVerification

func (a *AuthAttempt) PreparePasswordVerification(challengeID string) (AuthChallenge, *AuthFactorUser, error)

PreparePasswordVerification validates that a password proof can be submitted and returns the user ID to verify against.

func (*AuthAttempt) PrepareUserChallenge

func (a *AuthAttempt) PrepareUserChallenge() error

PrepareUserChallenge validates that a user challenge can be issued. It's prohibited if the auth attempt is linked to a session with a verified user as this could lead to security issues. Also, as soon as there are more factors verified than the user (e.g. password) we'll not allow to change the user anymore. We'll probably change the latter in the future and reset all factors as soon as the new user challenge succeeded.

func (*AuthAttempt) PrepareUserVerification

func (a *AuthAttempt) PrepareUserVerification(challengeID string) (AuthChallenge, error)

PrepareUserVerification validates that the attempt is in a state where a user (identifier) proof can be submitted.

func (*AuthAttempt) PrepareVerification

func (a *AuthAttempt) PrepareVerification(challengeID string, checkType AuthCheckType) (AuthChallenge, error)

PrepareVerification verifies that the attempt is not expired or handed off, that the given challenge ID exists (preventing stale proofs), and that the proof type matches the challenge's type.

func (*AuthAttempt) SetCheck

func (a *AuthAttempt) SetCheck(check AuthCheck)

SetCheck sets a check to the given check. In the case of an AuthChallenge, it will overwrite an existing challenge of the same type but keep factors of the same type. In the case of an AuthFactor, it will overwrite an existing factor of the same type and remove challenges of the same type.

func (*AuthAttempt) SetPasskeyChallenge

func (a *AuthAttempt) SetPasskeyChallenge(passkeyChallenge *PasskeyChallenge) *AuthChallengePasskey

func (*AuthAttempt) SetPasskeyFactor

func (a *AuthAttempt) SetPasskeyFactor(passkeyVerification *PasskeyVerification) *AuthFactorPasskey

func (*AuthAttempt) SetPasskeyRegistrationChallenge

func (a *AuthAttempt) SetPasskeyRegistrationChallenge(registrationChallenge *PasskeyRegistrationChallenge, provisional bool) *AuthChallengePasskeyRegistration

SetPasskeyRegistrationChallenge registers a new passkey registration challenge on the attempt, replacing any existing challenge of the same type.

func (*AuthAttempt) SetPasskeyRegistrationFactor

func (a *AuthAttempt) SetPasskeyRegistrationFactor(passkey *CreateUserPasskey) *AuthFactorPasskeyRegistration

SetPasskeyRegistrationFactor records a completed passkey enrollment as a verified factor on the attempt, replacing the registration challenge.

func (*AuthAttempt) SetPasswordChallenge

func (a *AuthAttempt) SetPasswordChallenge() *AuthChallengePassword

SetPasswordChallenge registers a new password challenge on the attempt, replacing any existing challenge of the same type.

func (*AuthAttempt) SetPasswordFactor

func (a *AuthAttempt) SetPasswordFactor() *AuthFactorPassword

SetPasswordFactor registers a verified password factor on the attempt, overwriting existing factors of the same type and clearing any associated challenges.

func (*AuthAttempt) SetUserChallenge

func (a *AuthAttempt) SetUserChallenge() *AuthChallengeUser

SetUserChallenge registers a new user challenge on the attempt, replacing any existing challenge of the same type.

func (*AuthAttempt) SetUserFactor

func (a *AuthAttempt) SetUserFactor(user *User) *AuthFactorUser

SetUserFactor registers a verified user factor on the attempt, overwriting existing factors of the same type and clearing any associated challenges.

type AuthAttemptCreatedPayload

type AuthAttemptCreatedPayload struct{}

AuthAttemptCreatedPayload is empty; flow_id/session_id live on event columns.

type AuthAttemptHandedOffPayload

type AuthAttemptHandedOffPayload struct{}

AuthAttemptHandedOffPayload is empty; session_id lives on the event column.

type AuthAttemptOption

type AuthAttemptOption func(*AuthAttempt)

func WithSession

func WithSession(sessionID *string, authFactors ...AuthFactor) AuthAttemptOption

WithSession sets the session ID and copies existing factors from the session to the attempt.

type AuthChallenge

type AuthChallenge interface {
	AuthCheck
	SetID(id string)
	GetID() string
	GetLastChallengedAt() time.Time
	SetLastChallengedAt(lastChallengedAt time.Time)
	GetLastFailedAt() time.Time
	SetLastFailedAt(lastFailedAt time.Time)
	GetFailureCount() uint16
	SetFailureCount(failureCount uint16)
}

type AuthChallengePasskey

type AuthChallengePasskey struct {
	*PasskeyChallenge
	// contains filtered or unexported fields
}

func SetAuthChallengePasskey

func SetAuthChallengePasskey(id string, lastChallengedAt, lastFailedAt time.Time, failureCount uint16) *AuthChallengePasskey

func (*AuthChallengePasskey) GetFailureCount

func (a *AuthChallengePasskey) GetFailureCount() uint16

func (*AuthChallengePasskey) GetID

func (a *AuthChallengePasskey) GetID() string

func (*AuthChallengePasskey) GetLastChallengedAt

func (a *AuthChallengePasskey) GetLastChallengedAt() time.Time

func (*AuthChallengePasskey) GetLastFailedAt

func (a *AuthChallengePasskey) GetLastFailedAt() time.Time

func (*AuthChallengePasskey) Payload

func (a *AuthChallengePasskey) Payload() any

func (*AuthChallengePasskey) SetFailureCount

func (a *AuthChallengePasskey) SetFailureCount(failureCount uint16)

func (*AuthChallengePasskey) SetID

func (a *AuthChallengePasskey) SetID(id string)

func (*AuthChallengePasskey) SetLastChallengedAt

func (a *AuthChallengePasskey) SetLastChallengedAt(lastChallengedAt time.Time)

func (*AuthChallengePasskey) SetLastFailedAt

func (a *AuthChallengePasskey) SetLastFailedAt(lastFailedAt time.Time)

func (*AuthChallengePasskey) Type

type AuthChallengePasskeyRegistration

type AuthChallengePasskeyRegistration struct {
	*PasskeyRegistrationChallenge
	// Provisional is true when the challenge minted the user handle itself:
	// the user row does not exist yet and is created when the attestation is
	// verified.
	Provisional bool
	// contains filtered or unexported fields
}

func SetAuthChallengePasskeyRegistration

func SetAuthChallengePasskeyRegistration(id string, lastChallengedAt, lastFailedAt time.Time, failureCount uint16) *AuthChallengePasskeyRegistration

func (*AuthChallengePasskeyRegistration) GetFailureCount

func (a *AuthChallengePasskeyRegistration) GetFailureCount() uint16

func (*AuthChallengePasskeyRegistration) GetID

func (a *AuthChallengePasskeyRegistration) GetID() string

func (*AuthChallengePasskeyRegistration) GetLastChallengedAt

func (a *AuthChallengePasskeyRegistration) GetLastChallengedAt() time.Time

func (*AuthChallengePasskeyRegistration) GetLastFailedAt

func (a *AuthChallengePasskeyRegistration) GetLastFailedAt() time.Time

func (*AuthChallengePasskeyRegistration) Payload

func (*AuthChallengePasskeyRegistration) SetFailureCount

func (a *AuthChallengePasskeyRegistration) SetFailureCount(failureCount uint16)

func (*AuthChallengePasskeyRegistration) SetID

func (a *AuthChallengePasskeyRegistration) SetID(id string)

func (*AuthChallengePasskeyRegistration) SetLastChallengedAt

func (a *AuthChallengePasskeyRegistration) SetLastChallengedAt(lastChallengedAt time.Time)

func (*AuthChallengePasskeyRegistration) SetLastFailedAt

func (a *AuthChallengePasskeyRegistration) SetLastFailedAt(lastFailedAt time.Time)

func (*AuthChallengePasskeyRegistration) Type

type AuthChallengePassword

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

func SetAuthChallengePassword

func SetAuthChallengePassword(id string, lastChallengedAt, lastFailedAt time.Time, failureCount uint16) *AuthChallengePassword

func (*AuthChallengePassword) GetFailureCount

func (a *AuthChallengePassword) GetFailureCount() uint16

func (*AuthChallengePassword) GetID

func (a *AuthChallengePassword) GetID() string

func (*AuthChallengePassword) GetLastChallengedAt

func (a *AuthChallengePassword) GetLastChallengedAt() time.Time

func (*AuthChallengePassword) GetLastFailedAt

func (a *AuthChallengePassword) GetLastFailedAt() time.Time

func (*AuthChallengePassword) Payload

func (a *AuthChallengePassword) Payload() any

func (*AuthChallengePassword) SetFailureCount

func (a *AuthChallengePassword) SetFailureCount(failureCount uint16)

func (*AuthChallengePassword) SetID

func (a *AuthChallengePassword) SetID(id string)

func (*AuthChallengePassword) SetLastChallengedAt

func (a *AuthChallengePassword) SetLastChallengedAt(lastChallengedAt time.Time)

func (*AuthChallengePassword) SetLastFailedAt

func (a *AuthChallengePassword) SetLastFailedAt(lastFailedAt time.Time)

func (*AuthChallengePassword) Type

type AuthChallengeUser

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

func SetAuthChallengeUser

func SetAuthChallengeUser(id string, lastChallengedAt, lastFailedAt time.Time, failureCount uint16) *AuthChallengeUser

func (*AuthChallengeUser) GetFailureCount

func (a *AuthChallengeUser) GetFailureCount() uint16

func (*AuthChallengeUser) GetID

func (a *AuthChallengeUser) GetID() string

func (*AuthChallengeUser) GetLastChallengedAt

func (a *AuthChallengeUser) GetLastChallengedAt() time.Time

func (*AuthChallengeUser) GetLastFailedAt

func (a *AuthChallengeUser) GetLastFailedAt() time.Time

func (*AuthChallengeUser) Payload

func (a *AuthChallengeUser) Payload() any

func (*AuthChallengeUser) SetFailureCount

func (a *AuthChallengeUser) SetFailureCount(failureCount uint16)

func (*AuthChallengeUser) SetID

func (a *AuthChallengeUser) SetID(id string)

func (*AuthChallengeUser) SetLastChallengedAt

func (a *AuthChallengeUser) SetLastChallengedAt(lastChallengedAt time.Time)

func (*AuthChallengeUser) SetLastFailedAt

func (a *AuthChallengeUser) SetLastFailedAt(lastFailedAt time.Time)

func (*AuthChallengeUser) Type

func (a *AuthChallengeUser) Type() AuthCheckType

type AuthCheck

type AuthCheck interface {
	Type() AuthCheckType
	Payload() any
}

type AuthCheckPayload

type AuthCheckPayload struct {
	CheckID       string `json:"check_id"`
	CheckType     string `json:"check_type,omitempty"`
	AuthAttemptID string `json:"auth_attempt_id,omitempty"`
}

type AuthCheckType

type AuthCheckType uint8
const (
	AuthCheckTypeUnspecified AuthCheckType = iota
	AuthCheckTypeUser
	AuthCheckTypePassword
	AuthCheckTypePasskey
	AuthCheckTypePasskeyRegistration
)

func AuthCheckTypeString

func AuthCheckTypeString(s string) (AuthCheckType, error)

AuthCheckTypeString retrieves an enum value from the enum constants string name. Throws an error if the param is not part of the enum.

func AuthCheckTypeValues

func AuthCheckTypeValues() []AuthCheckType

AuthCheckTypeValues returns all values of the enum

func (AuthCheckType) Class

func (t AuthCheckType) Class() AuthCheckType

Class returns the factor class a check type competes in. Passkey enrollment proves the same thing an assertion does for that credential (ADR 056), so AuthCheckTypePasskeyRegistration shares the passkey class; every other type is its own class. Anything comparing "which kind of factor is this" — required-check matching, session merging, wire rendering — compares classes, not raw types.

func (AuthCheckType) IsAAuthCheckType

func (i AuthCheckType) IsAAuthCheckType() bool

IsAAuthCheckType returns "true" if the value is listed in the enum definition. "false" otherwise

func (AuthCheckType) MarshalText

func (i AuthCheckType) MarshalText() ([]byte, error)

MarshalText implements the encoding.TextMarshaler interface for AuthCheckType

func (AuthCheckType) String

func (i AuthCheckType) String() string

func (*AuthCheckType) UnmarshalText

func (i *AuthCheckType) UnmarshalText(text []byte) error

UnmarshalText implements the encoding.TextUnmarshaler interface for AuthCheckType

type AuthFactor

type AuthFactor interface {
	AuthCheck
	GetLastVerifiedAt() time.Time
	SetLastVerifiedAt(lastVerifiedAt time.Time)
}

type AuthFactorPasskey

type AuthFactorPasskey struct {
	UserVerified   bool
	UserID         string
	CredentialID   []byte
	BackupEligible bool
	BackupState    bool
	// contains filtered or unexported fields
}

func SetAuthFactorPasskey

func SetAuthFactorPasskey(lastVerifiedAt time.Time) *AuthFactorPasskey

func (*AuthFactorPasskey) GetLastVerifiedAt

func (a *AuthFactorPasskey) GetLastVerifiedAt() time.Time

func (*AuthFactorPasskey) Payload

func (a *AuthFactorPasskey) Payload() any

func (*AuthFactorPasskey) SetLastVerifiedAt

func (a *AuthFactorPasskey) SetLastVerifiedAt(lastVerifiedAt time.Time)

func (*AuthFactorPasskey) Type

func (a *AuthFactorPasskey) Type() AuthCheckType

type AuthFactorPasskeyRegistration

type AuthFactorPasskeyRegistration struct {
	UserVerified bool
	UserID       string
	// CredentialID is base64url-encoded ([EncodePasskeyCredentialID]).
	CredentialID   string
	BackupEligible bool
	BackupState    bool
	// PasskeyID and Name identify the persisted credential row, so callers of
	// the verify transaction can answer with the created passkey without a
	// read-back that could fail after the ceremony is already consumed.
	PasskeyID string
	Name      string
	// contains filtered or unexported fields
}

AuthFactorPasskeyRegistration records a completed passkey enrollment on the attempt. It merges into the session as a passkey-class factor: creating the credential with user verification proves possession and presence just like an assertion does for that credential.

func SetAuthFactorPasskeyRegistration

func SetAuthFactorPasskeyRegistration(lastVerifiedAt time.Time) *AuthFactorPasskeyRegistration

func (*AuthFactorPasskeyRegistration) GetLastVerifiedAt

func (a *AuthFactorPasskeyRegistration) GetLastVerifiedAt() time.Time

func (*AuthFactorPasskeyRegistration) Payload

func (a *AuthFactorPasskeyRegistration) Payload() any

func (*AuthFactorPasskeyRegistration) SetLastVerifiedAt

func (a *AuthFactorPasskeyRegistration) SetLastVerifiedAt(lastVerifiedAt time.Time)

func (*AuthFactorPasskeyRegistration) Type

type AuthFactorPassword

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

func SetAuthFactorPassword

func SetAuthFactorPassword(lastVerifiedAt time.Time) *AuthFactorPassword

func (*AuthFactorPassword) GetLastVerifiedAt

func (a *AuthFactorPassword) GetLastVerifiedAt() time.Time

func (*AuthFactorPassword) Payload

func (a *AuthFactorPassword) Payload() any

func (*AuthFactorPassword) SetLastVerifiedAt

func (a *AuthFactorPassword) SetLastVerifiedAt(lastVerifiedAt time.Time)

func (*AuthFactorPassword) Type

type AuthFactorPayload

type AuthFactorPayload struct {
	UserID   string `json:"user_id"`
	FactorID string `json:"factor_id,omitempty"`
}

type AuthFactorUser

type AuthFactorUser struct {
	UserID string
	// contains filtered or unexported fields
}

func SetAuthFactorUser

func SetAuthFactorUser(lastVerifiedAt time.Time) *AuthFactorUser

func (*AuthFactorUser) GetLastVerifiedAt

func (a *AuthFactorUser) GetLastVerifiedAt() time.Time

func (*AuthFactorUser) Payload

func (a *AuthFactorUser) Payload() any

func (*AuthFactorUser) SetLastVerifiedAt

func (a *AuthFactorUser) SetLastVerifiedAt(lastVerifiedAt time.Time)

func (*AuthFactorUser) Type

func (a *AuthFactorUser) Type() AuthCheckType

type AuthTokenIssuedPayload

type AuthTokenIssuedPayload struct {
	Scopes []string `json:"scopes,omitempty"`
}

type AuthTokenRevokedPayload

type AuthTokenRevokedPayload struct{}

type AuthzAssignment

type AuthzAssignment struct {
	ID              string
	ProjectID       string
	CatalogID       string
	PrincipalType   AuthzPrincipalType
	PrincipalID     string
	ObjectType      string
	Relation        string
	ScopeKind       AuthzScopeKind
	ScopeTeamID     *string
	ScopeResourceID *string
	GrantorType     *string
	GrantorID       *string
	DelegationID    *string
	ExpiresAt       *time.Time
	RevokedAt       *time.Time
	CreatedAt       time.Time
	UpdatedAt       time.Time
}

AuthzAssignment binds a principal to a catalog relation at an explicit scope. This is a grant row for the grants API / resolver — not dual-written from ordinary CreateUser/CreateTeam.

Relation identity is (ObjectType, Relation), matching authz_relations.

func NewClaimTeamAssignment

func NewClaimTeamAssignment(projectID, teamID string) *AuthzAssignment

NewClaimTeamAssignment is the grant claim/complete writes (ADR 046 §1): the team principal on the seeded project.team relation at project scope, making the project owned by the claiming user's personal team. Grantor columns stay unset — the schema CHECK ties grantor_id to delegation_id, so claimed-by provenance is carried by the authz.granted audit event's actor instead.

func NewSKProjProjectSetupAssignment

func NewSKProjProjectSetupAssignment(projectID string) *AuthzAssignment

NewSKProjProjectSetupAssignment is the grant seeded at CreateProject so the returned full project secret can set up the project via resolver.Check.

Relation is project.viewer (not admin): the seeded system catalog closure treats viewer as the assigned relation that satisfies viewer/editor/admin checks (placeholders pending #420). PrincipalID equals the project id so the grant survives secret rotate/claim.

func (*AuthzAssignment) ApplyScope

func (a *AuthzAssignment) ApplyScope(scope AuthzAssignmentScope)

ApplyScope sets the scope columns from a constructor-built scope value.

type AuthzAssignmentScope

type AuthzAssignmentScope struct {
	Kind       AuthzScopeKind
	TeamID     *string
	ResourceID *string
}

AuthzAssignmentScope encodes the CHECK-constrained scope columns.

func NewProjectAssignmentScope

func NewProjectAssignmentScope() AuthzAssignmentScope

func NewResourceAssignmentScope

func NewResourceAssignmentScope(resourceID string) AuthzAssignmentScope

func NewTeamAssignmentScope

func NewTeamAssignmentScope(teamID string) AuthzAssignmentScope

type AuthzCatalog

type AuthzCatalog struct {
	ID          string
	CatalogKind AuthzCatalogKind
	OwnerID     string
	Version     int
	Status      AuthzCatalogStatus
	SourceHash  *string
	Relations   []AuthzRelation
	References  []AuthzRelationReference
	Edges       []AuthzExpressionEdge
	Closure     []AuthzRelationClosure
}

AuthzCatalog is one persisted catalog version plus its projected relation rows (authz_relations / references / expression_edges / relation_closure).

type AuthzCatalogKind

type AuthzCatalogKind string

AuthzCatalogKind is authz_catalogs.catalog_kind.

const (
	AuthzCatalogKindSystem   AuthzCatalogKind = "system"
	AuthzCatalogKindAppGroup AuthzCatalogKind = "app_group"
)

func (AuthzCatalogKind) String

func (k AuthzCatalogKind) String() string

type AuthzCatalogStatus

type AuthzCatalogStatus string

AuthzCatalogStatus is authz_catalogs.status.

const (
	AuthzCatalogStatusDraft   AuthzCatalogStatus = "draft"
	AuthzCatalogStatusActive  AuthzCatalogStatus = "active"
	AuthzCatalogStatusRetired AuthzCatalogStatus = "retired"
)

func (AuthzCatalogStatus) String

func (s AuthzCatalogStatus) String() string

type AuthzCatalogVersion

type AuthzCatalogVersion struct {
	ID          string
	CatalogKind AuthzCatalogKind
	OwnerID     string
	Version     int
	SourceHash  *string
}

AuthzCatalogVersion is the catalog row metadata written with a compiled CatalogMutations payload (see PersistCatalogVersion).

type AuthzCheckParams

type AuthzCheckParams struct {
	CatalogID              string
	ProjectID              string
	PrincipalHomeProjectID string
	PrincipalType          AuthzPrincipalType
	PrincipalID            string
	ObjectType             string
	Relation               string
	ConstraintTeamID       string
	ResourceID             string
	// ResourceTeamID is RSI.team_id for by-id Check (team-scoped grant arm).
	ResourceTeamID string
}

AuthzCheckParams is the storage-level input for a single-resource permission check. PrincipalHomeProjectID is the project used for membership-edge lookup (defaults to ProjectID).

ConstraintTeamID, when set (sk_team_ tokens), requires the checked or listed object to belong to that team: users via authz_membership_edges, teams by id, other kinds via resource_scope_index.team_id (Check binds ResourceTeamID). ResourceID is the object being checked (empty for permission-level Check / list materialization). ResourceTeamID is RSI.team_id for by-id Check.

func (AuthzCheckParams) HomeProjectID

func (p AuthzCheckParams) HomeProjectID() string

HomeProjectID returns PrincipalHomeProjectID, or ProjectID when unset.

type AuthzExpressionEdge

type AuthzExpressionEdge struct {
	ObjectType         string
	Relation           string
	Kind               string
	SourceObjectType   *string
	SourceRelation     *string
	TuplesetObjectType *string
	TuplesetRelation   *string
	Position           int
}

AuthzExpressionEdge is one authz_expression_edges row. Kind is the CHECK value: direct | computed_userset | tuple_to_userset.

type AuthzGrantedPayload

type AuthzGrantedPayload struct {
	PrincipalType string `json:"principal_type,omitempty"`
	PrincipalID   string `json:"principal_id,omitempty"`
	Relation      string `json:"relation,omitempty"`
}

type AuthzListObjectsParams

type AuthzListObjectsParams struct {
	AuthzCheckParams
	ResourceKind ResourceKind
}

AuthzListObjectsParams lists resource_scope_index ids the principal may see for one resource kind under a required catalog relation (L4 / oracle helper). Endpoint wiring injects an authz predicate into the resource query (ADR 033).

type AuthzMemberType

type AuthzMemberType string

AuthzMemberType is authz_membership_edges.member_type.

const (
	AuthzMemberTypeUser AuthzMemberType = "user"
)

func (AuthzMemberType) String

func (t AuthzMemberType) String() string

type AuthzMembershipEdge

type AuthzMembershipEdge struct {
	ProjectID  string
	MemberType AuthzMemberType
	MemberID   string
	SetType    AuthzSetType
	SetID      string
	CreatedAt  time.Time
}

AuthzMembershipEdge is the authz projection of set membership (not lifecycle). The resolver expands team grants through these edges; team_memberships remains the roster table and is not read at check time.

func NewUserTeamMembershipEdge

func NewUserTeamMembershipEdge(projectID, teamID, userID string) *AuthzMembershipEdge

type AuthzMembershipEdgeField

type AuthzMembershipEdgeField uint8

AuthzMembershipEdgeField enumerates AuthzMembershipEdge columns for filter deletes.

const (
	AuthzMembershipEdgeFieldUnspecified AuthzMembershipEdgeField = iota
	AuthzMembershipEdgeFieldProjectID
	AuthzMembershipEdgeFieldMemberType
	AuthzMembershipEdgeFieldMemberID
	AuthzMembershipEdgeFieldSetType
	AuthzMembershipEdgeFieldSetID
	AuthzMembershipEdgeFieldCreatedAt
)

type AuthzMembershipEdgeKey

type AuthzMembershipEdgeKey struct {
	ProjectID  string
	SetType    AuthzSetType
	SetID      string
	MemberType AuthzMemberType
	MemberID   string
}

AuthzMembershipEdgeKey identifies one authz_membership_edges row.

func NewUserTeamMembershipEdgeKey

func NewUserTeamMembershipEdgeKey(projectID, teamID, userID string) AuthzMembershipEdgeKey

type AuthzPrincipalType

type AuthzPrincipalType string

AuthzPrincipalType is authz_assignments.principal_type (no project principals; see D13).

const (
	AuthzPrincipalTypeUser   AuthzPrincipalType = "user"
	AuthzPrincipalTypeTeam   AuthzPrincipalType = "team"
	AuthzPrincipalTypeAgent  AuthzPrincipalType = "agent"
	AuthzPrincipalTypeSKProj AuthzPrincipalType = "sk_proj"
	AuthzPrincipalTypeSKTeam AuthzPrincipalType = "sk_team"
)

func (AuthzPrincipalType) String

func (t AuthzPrincipalType) String() string

type AuthzRelation

type AuthzRelation struct {
	ObjectType string
	Relation   string
	Kind       AuthzRelationKind
}

AuthzRelation is one authz_relations row.

type AuthzRelationClosure

type AuthzRelationClosure struct {
	FromObjectType string
	FromRelation   string
	ToObjectType   string
	ToRelation     string
	Depth          int
}

AuthzRelationClosure is one authz_relation_closure row.

type AuthzRelationKind

type AuthzRelationKind string

AuthzRelationKind is authz_relations.kind.

const (
	AuthzRelationKindRelation   AuthzRelationKind = "relation"
	AuthzRelationKindPermission AuthzRelationKind = "permission"
)

func (AuthzRelationKind) String

func (k AuthzRelationKind) String() string

type AuthzRelationReference

type AuthzRelationReference struct {
	ObjectType  string
	Relation    string
	RefType     string
	RefRelation string
	Wildcard    bool
	Condition   string
	Position    int
}

AuthzRelationReference is one authz_relation_references row.

type AuthzRevokedPayload

type AuthzRevokedPayload struct {
	PrincipalType string `json:"principal_type,omitempty"`
	PrincipalID   string `json:"principal_id,omitempty"`
	Relation      string `json:"relation,omitempty"`
}

type AuthzScopeKind

type AuthzScopeKind string

AuthzScopeKind is authz_assignments.scope_kind.

const (
	AuthzScopeKindProject  AuthzScopeKind = "project"
	AuthzScopeKindTeam     AuthzScopeKind = "team"
	AuthzScopeKindResource AuthzScopeKind = "resource"
)

func (AuthzScopeKind) String

func (k AuthzScopeKind) String() string

type AuthzSetType

type AuthzSetType string

AuthzSetType is authz_membership_edges.set_type.

const (
	AuthzSetTypeTeam AuthzSetType = "team"
)

func (AuthzSetType) String

func (t AuthzSetType) String() string

type Branding

type Branding struct {
	ProjectID      string
	ID             string
	Layout         string
	LiquidTemplate string
	LogoURL        string
	FontURL        string
	HeroURL        string
	CreatedAt      time.Time
}

Branding is one immutable branding revision for a project. Revisions are never updated or deleted; every edit publishes a new revision and flow responses resolve the newest one per project (ADR 040).

func NewBranding

func NewBranding(projectID string, layout, liquidTemplate, logoURL, fontURL, heroURL string) (*Branding, error)

NewBranding builds a new revision, defaulting the layout, and validates it with the lexical gate in branding_validator.go.

type BrandingCreatedPayload

type BrandingCreatedPayload = BrandingPayload

BrandingCreatedPayload is an alias for branding.created.

type BrandingField

type BrandingField uint8

BrandingField enumerates the fields of Branding which can be used for filtering and ordering in list operations.

const (
	BrandingFieldUnspecified BrandingField = iota
	BrandingFieldProjectID
	BrandingFieldID
	BrandingFieldCreatedAt
)

type BrandingPayload

type BrandingPayload struct {
	Layout  string `json:"layout,omitempty"`
	LogoURL string `json:"logo_url,omitempty"`
	FontURL string `json:"font_url,omitempty"`
	HeroURL string `json:"hero_url,omitempty"`
}

type ClaimChallenge

type ClaimChallenge struct {
	// ID is the SHA-256 hash of the challenge token. It is the primary key and
	// is supplied by the caller, not minted here.
	ID string
	// ProjectID links to [Project].
	ProjectID string
	// InitiatingSecretHash is the SHA-256 of the project secret that initiated
	// the claim; it proves possession on claim/status (see Claim E1).
	InitiatingSecretHash string
	Status               ClaimChallengeStatus
	ExpiresAt            time.Time
	CreatedAt            time.Time
}

ClaimChallenge is the ephemeral proof-of-possession record for a project claim (ADR 046). Its ID is the SHA-256 hash of a handoff-token-style challenge token minted by the caller: the plaintext travels outside the system, only the hash is stored.

func NewClaimChallenge

func NewClaimChallenge(id, projectID, initiatingSecretHash string, expiresAt time.Time) (*ClaimChallenge, error)

NewClaimChallenge builds a pending claim challenge. Unlike managed resources the ID is not minted here: it is the externally computed SHA-256 hash of the challenge token (handoff-token pattern, ADR 046 §3).

type ClaimChallengeCreatedPayload

type ClaimChallengeCreatedPayload struct{}

type ClaimChallengeStatus

type ClaimChallengeStatus string

ClaimChallengeStatus is the lifecycle state of a claim challenge. It mirrors the DB CHECK on claim_challenges.status.

const (
	ClaimChallengeStatusPending   ClaimChallengeStatus = "pending"
	ClaimChallengeStatusCompleted ClaimChallengeStatus = "completed"
)

func (ClaimChallengeStatus) String

func (s ClaimChallengeStatus) String() string

type ClaimCompletedPayload

type ClaimCompletedPayload struct {
	TeamID string `json:"team_id,omitempty"`
}

type ClaimConflictDetails

type ClaimConflictDetails struct {
	TeamID       string `json:"team_id"`
	DashboardURL string `json:"dashboard_url"`
}

ClaimConflictDetails is the client-facing details body of the 409 already_claimed response: the owning team and where to manage the project.

type CollectedAuthMethodData

type CollectedAuthMethodData struct {
	Password string
}

type CollectedFlowData

type CollectedFlowData struct {
	UserData    map[string]any
	UserID      string
	AuthMethods CollectedAuthMethodData
}

type CreateAttribute

type CreateAttribute struct {
	Key         AttributeKey        `json:"key"`
	Value       any                 `json:"value"`
	UniqueScope AttributeUniqueness `json:"unique_scope"`
	ValueHash   [sha256.Size]byte   `json:"value_hash"`
}

func NewCreateAttribute

func NewCreateAttribute(key AttributeKey, value any, unique AttributeUniqueness) (*CreateAttribute, error)

type CreateAttributes

type CreateAttributes []CreateAttribute

func CreateAttributesFromMap

func CreateAttributesFromMap(m map[string]any, schema map[string]any) (CreateAttributes, error)

func (CreateAttributes) Get

func (attrs CreateAttributes) Get(key AttributeKey) (value *CreateAttribute, ok bool)

Get returns the value for the given key.

TODO(go v27): make this method generic

type CreateRecoveryCodes

type CreateRecoveryCodes struct {
	ID            string
	ProjectID     string
	UserID        string
	RecoveryCodes []string
}

type CreateUser

type CreateUser struct {
	ProjectID string
	SchemaURL string
	ID        string
	// LifecycleOwnerTeamID decides who manages this user's identity lifecycle (ADR 024).
	// nil => self-owned: the user survives team deletion and owns their own deprovisioning.
	// set => team-owned: deleting/deactivating that team can deactivate this user per policy.
	LifecycleOwnerTeamID *string
	// InitialMembershipTeamID is optional membership context at create time — not lifecycle ownership.
	// When set, Create also inserts an active team_memberships row for this team and uses it as the
	// team-scoped EAV uniqueness scope for attributes. A self-owned signup user can still set this
	// to their default workspace team; an enterprise provisioned user may set both fields to the
	// same tenant team, but lifecycle ownership and team membership remain separate concerns.
	InitialMembershipTeamID *string
	Attributes              CreateAttributes
}

func NewCreateUser

func NewCreateUser(params CreateUserParams) (*CreateUser, error)

NewCreateUser builds a CreateUser from the schema-defined attributes.

func (*CreateUser) AttributeTeamScope

func (c *CreateUser) AttributeTeamScope() string

AttributeTeamScope returns the team id used for team-scoped unique attributes on create.

type CreateUserParams

type CreateUserParams struct {
	ProjectID string
	// TeamID is optional membership context, not lifecycle ownership — it
	// becomes [CreateUser.InitialMembershipTeamID].
	TeamID *string
	// ID is empty for a server-minted id; non-empty is for ceremony only.
	ID string
	// SchemaURL names the schema, and Schema is that schema's document.
	SchemaURL string
	Schema    []byte
	// Attributes is the instance the schema validates: envelope fields (id,
	// schema, metadata) are not part of it, so a schema may declare properties
	// of those names and closed-world keywords such as additionalProperties:
	// false hold.
	Attributes map[string]any
}

CreateUserParams are the inputs to NewCreateUser. A struct rather than positional arguments because ID and SchemaURL are both strings: transposing them would type-check and write a schema url as the row's primary key.

type CreateUserPasskey

type CreateUserPasskey struct {
	ID              string
	ProjectID       string
	UserID          string
	CredentialID    string
	PublicKey       []byte
	AAGUID          []byte
	AttestationType *string
	Transports      []string
	SignCount       int64
	UserVerified    bool
	BackupEligible  bool
	BackupState     bool
	Name            string
	VerifiedAt      *time.Time
}

func VerifyPasskeyRegistration

func VerifyPasskeyRegistration(challenge *PasskeyRegistrationChallenge, attestation []byte, name string) (*CreateUserPasskey, error)

VerifyPasskeyRegistration parses the attestation response and calls webauthn.CreateCredential. Returns a CreateUserPasskey ready for storage. CredentialID is base64url-encoded to ensure valid UTF-8 in the TEXT column (valid for both Postgres and Spanner).

name labels the new credential in passkey management surfaces. It is the caller's if supplied, otherwise derived from the credential — see [PasskeyCredentialName].

type CreateUserTOTP

type CreateUserTOTP struct {
	ID        string
	ProjectID string
	UserID    string
	Secret    []byte
}

type CreatedUserDetails

type CreatedUserDetails struct {
	UserID string `json:"user_id"`
}

CreatedUserDetails names a user the server created, for the answer that cannot carry its representation.

type EncryptionKey

type EncryptionKey struct {
	ID          string
	ProjectID   string
	Purpose     EncryptionKeyPurpose
	Key         string
	Algorithm   jose.ContentEncryption
	State       KeyState
	CreatedAt   time.Time
	ActivatedAt *time.Time
	RetiredAt   *time.Time
}

func NewEncryptionKey

func NewEncryptionKey(
	projectID string,
	purpose EncryptionKeyPurpose,
	algorithm jose.ContentEncryption,
	kek crypto.Crypter,
) (*EncryptionKey, error)

func (*EncryptionKey) Activate

func (k *EncryptionKey) Activate(currentKey *EncryptionKey)

func (*EncryptionKey) Crypter

func (k *EncryptionKey) Crypter(kek crypto.Crypter) (crypto.Crypter, error)

func (*EncryptionKey) DecryptedKey

func (k *EncryptionKey) DecryptedKey(kek crypto.Decrypter) ([32]byte, error)

func (*EncryptionKey) IsActive

func (k *EncryptionKey) IsActive() bool

func (*EncryptionKey) IsRemoved

func (k *EncryptionKey) IsRemoved() bool

func (*EncryptionKey) MigrateToNewMasterKey

func (k *EncryptionKey) MigrateToNewMasterKey(oldMasterKey crypto.Crypter, newMasterKey crypto.Crypter) error

MigrateToNewMasterKey re-wraps the key material under newMasterKey without changing the key itself, so nothing encrypted by this key has to be touched.

type EncryptionKeyField

type EncryptionKeyField uint8
const (
	EncryptionKeyFieldUnspecified EncryptionKeyField = iota
	EncryptionKeyFieldID
	EncryptionKeyFieldProjectID
	EncryptionKeyFieldKey
	EncryptionKeyFieldAlgorithm
	EncryptionKeyFieldState
	EncryptionKeyFieldCreatedAt
	EncryptionKeyFieldActivatedAt
	EncryptionKeyFieldRetiredAt
	EncryptionKeyFieldPurpose
)

type EncryptionKeyPurpose

type EncryptionKeyPurpose string
const (
	// EncryptionKeyPurposeKEK indicates the key is the project's key encryption
	// key which is used to encrypt the purpose-scoped keys of the project. It is
	// itself encrypted by the master key.
	EncryptionKeyPurposeKEK EncryptionKeyPurpose = "kek"
	// EncryptionKeyPurposeToken indicates the key is used to encrypt tokens
	EncryptionKeyPurposeToken EncryptionKeyPurpose = "token"
	// EncryptionKeyPurposeSecret indicates the key is used to encrypt
	// third-party secrets like client-secrets, passwords,... for third party
	// applications
	EncryptionKeyPurposeSecret EncryptionKeyPurpose = "secret"
	// EncryptionKeyPurposeCookie indicates the key is used to encrypt cookies
	EncryptionKeyPurposeCookie EncryptionKeyPurpose = "cookie"
)

type Environment

type Environment struct {
	ProjectID string
	ID        string
	Name      string
	CreatedAt time.Time
}

func NewEnvironment

func NewEnvironment(projectID, name string) (*Environment, error)

type EnvironmentCreatedPayload

type EnvironmentCreatedPayload = EnvironmentPayload

type EnvironmentField

type EnvironmentField uint8
const (
	EnvironmentFieldUnspecified EnvironmentField = iota
	EnvironmentFieldProjectID
	EnvironmentFieldID
	EnvironmentFieldName
	EnvironmentFieldCreatedAt
)

type EnvironmentPayload

type EnvironmentPayload struct {
	Name string `json:"name,omitempty"`
}

type Error

type Error struct {
	Code    string `json:"code"`
	Message string `json:"message"`
	Details any    `json:"details,omitempty"`
	Parent  error  `json:"-"`
	errreport.Origin
}

func ErrAuthAttemptAlreadyCompleted

func ErrAuthAttemptAlreadyCompleted() Error

ErrAuthAttemptAlreadyCompleted returns an error indicating that the attempt is already completed.

func ErrAuthAttemptAlreadyHandedOff

func ErrAuthAttemptAlreadyHandedOff() Error

ErrAuthAttemptAlreadyHandedOff returns an error indicating that the attempt is already handed off.

func ErrAuthAttemptInvalidProof

func ErrAuthAttemptInvalidProof() Error

ErrAuthAttemptInvalidProof returns an error indicating that the proof is invalid.

func ErrAuthAttemptInvalidRequest

func ErrAuthAttemptInvalidRequest() Error

ErrAuthAttemptInvalidRequest returns an error indicating that the request is invalid.

func ErrAuthAttemptInvalidState

func ErrAuthAttemptInvalidState() Error

ErrAuthAttemptInvalidState returns an error indicating that the attempt is in an invalid state (e.g. expired).

func ErrAuthAttemptNotCompleted

func ErrAuthAttemptNotCompleted() Error

ErrAuthAttemptNotCompleted returns an error indicating that the attempt is not completed.

func ErrAuthAttemptNotFound

func ErrAuthAttemptNotFound() Error

ErrAuthAttemptNotFound returns an error indicating that the requested auth attempt was not found.

func ErrAuthAttemptProofRejected

func ErrAuthAttemptProofRejected(err error) Error

ErrAuthAttemptProofRejected returns an error indicating that the proof was rejected.

func ErrAuthAttemptStaleChallenge

func ErrAuthAttemptStaleChallenge() Error

ErrAuthAttemptStaleChallenge returns an error indicating that the challenge is stale or has been re-issued.

func ErrAuthUnauthorized

func ErrAuthUnauthorized(err error) Error

ErrAuthUnauthorized is returned when a request lacks valid credentials (e.g. missing session cookie, unsatisfied security requirement, expired nonce).

func ErrBrandingInvalid

func ErrBrandingInvalid(details any, parent error) Error

func ErrBrandingMissingProjectID

func ErrBrandingMissingProjectID() Error

func ErrBrandingNotFound

func ErrBrandingNotFound() Error

func ErrBrandingPermissionDenied

func ErrBrandingPermissionDenied() Error

func ErrClaimChallengeInvalid

func ErrClaimChallengeInvalid() Error

func ErrClaimChallengeNotFound

func ErrClaimChallengeNotFound() Error

func ErrClaimNoPersonalTeam

func ErrClaimNoPersonalTeam() Error

ErrClaimNoPersonalTeam covers a claim/complete session user without an active personal team. Impossible once #527's registration auto-creates it; until then it guards manually seeded platform projects.

func ErrClaimSessionExpired

func ErrClaimSessionExpired() Error

func ErrClaimSessionNotActive

func ErrClaimSessionNotActive() Error

func ErrClaimSessionWrongProject

func ErrClaimSessionWrongProject() Error

func ErrDecryptionFailed

func ErrDecryptionFailed(parent error) Error

func ErrEncryptionFailed

func ErrEncryptionFailed(parent error) Error

func ErrEncryptionKeyNotFound

func ErrEncryptionKeyNotFound() Error

func ErrEnvironmentNameInvalid

func ErrEnvironmentNameInvalid() Error

func ErrEnvironmentNotFound

func ErrEnvironmentNotFound() Error

func ErrEnvironmentPermissionDenied

func ErrEnvironmentPermissionDenied() Error

func ErrEnvironmentProjectNotFound

func ErrEnvironmentProjectNotFound() Error

func ErrEventInvalid

func ErrEventInvalid(details any, parent error) Error

func ErrEventNotFound

func ErrEventNotFound() Error

func ErrEventPermissionDenied

func ErrEventPermissionDenied() Error

func ErrFlowCompleted

func ErrFlowCompleted() Error

func ErrFlowCookieExpired

func ErrFlowCookieExpired() Error

func ErrFlowCookieInvalid

func ErrFlowCookieInvalid() Error

func ErrFlowDefinitionAlreadyExists

func ErrFlowDefinitionAlreadyExists() Error

func ErrFlowDefinitionInvalid

func ErrFlowDefinitionInvalid(details any, parent error) Error

func ErrFlowDefinitionNotFound

func ErrFlowDefinitionNotFound() Error

ErrFlowDefinitionNotFound is returned when a direct lookup by name does not match any definition for the project.

func ErrFlowDefinitionPermissionDenied

func ErrFlowDefinitionPermissionDenied() Error

func ErrFlowDefinitionPurposeMismatch

func ErrFlowDefinitionPurposeMismatch() Error

ErrFlowDefinitionPurposeMismatch is returned when a direct lookup matches a definition that does not serve the requested purpose.

func ErrFlowDefinitionUpdateConflict

func ErrFlowDefinitionUpdateConflict(details any) Error

func ErrFlowIntegrity

func ErrFlowIntegrity() Error

func ErrFlowInvalidAction

func ErrFlowInvalidAction() Error

func ErrFlowInvalidPurpose

func ErrFlowInvalidPurpose() Error

func ErrFlowNotFound

func ErrFlowNotFound() Error

func ErrFlowSessionConflict

func ErrFlowSessionConflict() Error

func ErrFlowUnsupported

func ErrFlowUnsupported() Error

func ErrGrantAlreadyExists

func ErrGrantAlreadyExists() Error

func ErrGrantInvalid

func ErrGrantInvalid() Error

func ErrGrantNotFound

func ErrGrantNotFound() Error

func ErrGrantPermissionDenied

func ErrGrantPermissionDenied() Error

func ErrGrantPrincipalNotFound

func ErrGrantPrincipalNotFound() Error

func ErrInternal

func ErrInternal(err error) Error

ErrInternal is the catch-all for unexpected errors that have no specific domain code.

func ErrInvalidToken

func ErrInvalidToken() Error

func ErrInvalidTokenIdentifiers

func ErrInvalidTokenIdentifiers() Error

ErrInvalidTokenIdentifiers is returned when session identifier fields do not match Token.Type.

func ErrJSONSchemaAlreadyExists

func ErrJSONSchemaAlreadyExists() Error

func ErrJSONSchemaInvalid

func ErrJSONSchemaInvalid() Error

func ErrJSONSchemaNotFound

func ErrJSONSchemaNotFound() Error

func ErrJSONSchemaPermissionDenied

func ErrJSONSchemaPermissionDenied() Error

func ErrJSONSchemaRevisionConflict

func ErrJSONSchemaRevisionConflict() Error

ErrJSONSchemaRevisionConflict reports that another revision of the same object type already holds this creation timestamp. Which of the two is the latest would be undecidable, so the loser is rejected and the caller can simply retry.

func ErrMissingFlowDefinitionID

func ErrMissingFlowDefinitionID() Error

func ErrMissingProjectID

func ErrMissingProjectID() Error

func ErrNoReplacementKey

func ErrNoReplacementKey() Error

func ErrNotImplemented

func ErrNotImplemented() Error

func ErrPersonalTeamNotActive

func ErrPersonalTeamNotActive(status string) Error

ErrPersonalTeamNotActive covers a platform user whose personal team exists but is not active: the membership was flipped, or the team was deactivated and cascaded the membership to removed.

Deliberately distinct from ErrClaimNoPersonalTeam. "You hold no membership" is provisioned automatically on the next sign-in, while a membership that is not active will not be provisioned around, so a UI has to say different things about them.

What clears it depends on the status, which is why Details carries it rather than the message summarising one cause: `removed` follows a team or user deactivation and needs an administrator, while `pending` is an invitation the user can still accept.

func ErrProjectAlreadyClaimed

func ErrProjectAlreadyClaimed() Error

func ErrProjectClaimExpired

func ErrProjectClaimExpired() Error

func ErrProjectMissingID

func ErrProjectMissingID() Error

func ErrProjectNameInvalid

func ErrProjectNameInvalid() Error

func ErrProjectNotFound

func ErrProjectNotFound() Error

func ErrProjectPermissionDenied

func ErrProjectPermissionDenied() Error

func ErrRequestInvalid

func ErrRequestInvalid() Error

ErrRequestInvalid is returned when an incoming HTTP request fails structural validation (missing required fields, wrong types, failed regex, etc.) before it reaches domain logic.

func ErrSchemaFetchFailed

func ErrSchemaFetchFailed(details any, parent error) Error

func ErrSessionExchangeConflict

func ErrSessionExchangeConflict() Error

func ErrSessionInvalidHandoffToken

func ErrSessionInvalidHandoffToken() Error

func ErrSessionInvalidTTL

func ErrSessionInvalidTTL() Error

func ErrSessionNotFound

func ErrSessionNotFound() Error

func ErrSessionPermissionDenied

func ErrSessionPermissionDenied() Error

func ErrSessionTokenCreationFailed

func ErrSessionTokenCreationFailed() Error

func ErrSessionTokenInvalid

func ErrSessionTokenInvalid() Error

func ErrSigningKeyNotFound

func ErrSigningKeyNotFound() Error

func ErrSupportedEncryptionAlgorithm

func ErrSupportedEncryptionAlgorithm(alg jose.ContentEncryption) Error

func ErrTeamAlreadyExists

func ErrTeamAlreadyExists() Error

func ErrTeamNameInvalid

func ErrTeamNameInvalid() Error

func ErrTeamNotFound

func ErrTeamNotFound() Error

func ErrTeamPermissionDenied

func ErrTeamPermissionDenied() Error

func ErrTeamProjectNotFound

func ErrTeamProjectNotFound() Error

func ErrTokenRevoked

func ErrTokenRevoked() Error

ErrTokenRevoked is returned when a token decrypts and is well-formed but its record no longer grants anything — gone from storage or expired. It is deliberately indistinguishable from ErrInvalidToken to a caller: a bearer learns only that the credential does not work.

func ErrUnavailable

func ErrUnavailable() Error

ErrUnavailable is returned when a request failed for a transient reason and retrying it may succeed, typically a database transaction that exhausted its abort retries under contention. Separate from ErrInternal because the caller's correct response differs: retry, rather than report a bug.

func ErrUserAlreadyExists

func ErrUserAlreadyExists() Error

func ErrUserInvalid

func ErrUserInvalid() Error

func ErrUserNotFound

func ErrUserNotFound() Error

func ErrUserPasswordInvalid

func ErrUserPasswordInvalid() Error

func ErrUserPermissionDenied

func ErrUserPermissionDenied() Error

func TokenNotFound

func TokenNotFound() Error

func (Error) As

func (e Error) As(target any) bool

func (Error) Error

func (e Error) Error() string

func (Error) Is

func (e Error) Is(target error) bool

func (Error) LogValue

func (e Error) LogValue() slog.Value

LogValue implements slog.LogValuer. Details are client-facing and omitted from logs by default (ADR 030).

func (Error) Unwrap

func (e Error) Unwrap() error

func (Error) WithDetails

func (e Error) WithDetails(details any) Error

WithDetails returns a copy with additional context attached. Code is unchanged so errors.Is still matches the original sentinel.

func (Error) WithMessage

func (e Error) WithMessage(msg string) Error

WithMessage returns a copy with the message overridden. Code is unchanged so errors.Is still matches the original sentinel.

func (Error) WithParent

func (e Error) WithParent(parent error) Error

WithParent returns a copy wrapping a lower-level cause. Code is unchanged so errors.Is still matches the original sentinel.

type Event

type Event struct {
	ProjectID  string
	ID         string
	EventType  EventType
	Category   EventCategory
	OccurredAt time.Time
	CreatedAt  time.Time

	TeamID *string

	ActorID   *string
	ActorType *EventActorType

	EntityType *string
	EntityID   *string

	ClientID       string
	TokenID        string
	DelegationType string
	DelegationID   string
	Grantor        string
	Fingerprint    string

	RequestID *string
	SessionID *string
	FlowID    *string

	Payload  json.RawMessage
	Metadata json.RawMessage

	// OccurredAtWait is an insert-only hint for Path A batching: dialects set
	// occurred_at = created_at - wait (DB clock or equivalent). Path A wait is
	// time since HTTP request start so request.api sorts first on request_id.
	// Zero means Path B (occurred_at = created_at). Not a persisted column.
	OccurredAtWait time.Duration
}

Event is one append-only wide-event row (ADR 048).

type EventActorType

type EventActorType string

EventActorType is who triggered the event.

const (
	EventActorTypeHuman   EventActorType = "human"
	EventActorTypeService EventActorType = "service"
	EventActorTypeSystem  EventActorType = "system"
	EventActorTypeAgent   EventActorType = "agent"
)

type EventCategory

type EventCategory string

EventCategory is the ADR 048 wide-event category.

const (
	EventCategoryRequest EventCategory = "request"
	EventCategoryAuth    EventCategory = "auth"
	EventCategorySession EventCategory = "session"
	EventCategoryAdmin   EventCategory = "admin"
	EventCategoryEntity  EventCategory = "entity"
	EventCategorySignal  EventCategory = "signal"
)

type EventClientMetadata

type EventClientMetadata struct {
	IP        string `json:"ip,omitempty"`
	UserAgent string `json:"user_agent,omitempty"`
	Origin    string `json:"origin,omitempty"`
}

EventClientMetadata is Path A requestor context on events.metadata.client.

type EventField

type EventField uint8

EventField enumerates filterable/sortable Event columns.

const (
	EventFieldUnspecified EventField = iota
	EventFieldProjectID
	EventFieldID
	EventFieldEventType
	EventFieldCategory
	EventFieldOccurredAt
	EventFieldCreatedAt
	EventFieldTeamID
	EventFieldActorID
	EventFieldActorType
	EventFieldEntityType
	EventFieldEntityID
	EventFieldClientID
	EventFieldTokenID
	EventFieldFingerprint
	EventFieldRequestID
	EventFieldSessionID
	EventFieldFlowID
)

type EventMetadata

type EventMetadata struct {
	Client *EventClientMetadata `json:"client,omitempty"`
}

EventMetadata is the events.metadata JSON object.

type EventSink

type EventSink struct {
	ID        string
	Type      EventSinkType
	Scope     EventSinkScope
	ProjectID *string
	URL       string
	Enabled   bool
}

EventSink is a first-class export destination (ADR 049).

type EventSinkCursor

type EventSinkCursor struct {
	SinkID        string
	ProjectID     string
	LastCreatedAt time.Time
	LastEventID   string
}

EventSinkCursor is a per-(sink, project) watermark for export (ADR 049). Progress is keyset-ordered on (last_created_at, last_event_id).

type EventSinkScope

type EventSinkScope string
const (
	EventSinkScopeDeployment EventSinkScope = "deployment"
	EventSinkScopeProject    EventSinkScope = "project"
)

type EventSinkType

type EventSinkType string
const (
	EventSinkTypeStdout  EventSinkType = "stdout"
	EventSinkTypeWebhook EventSinkType = "webhook"
)

type EventType

type EventType string

EventType is a semantic event name (dot-separated), e.g. user.created.

const (
	EventTypeRequestAPI EventType = "request.api"

	EventTypeProjectCreated EventType = "project.created"
	EventTypeProjectUpdated EventType = "project.updated"
	EventTypeProjectDeleted EventType = "project.deleted"

	EventTypeUserCreated      EventType = "user.created"
	EventTypeUserCreateFailed EventType = "user.create.failed"
	EventTypeUserDeleted      EventType = "user.deleted"

	EventTypeTeamCreated     EventType = "team.created"
	EventTypeTeamUpdated     EventType = "team.updated"
	EventTypeTeamDeactivated EventType = "team.deactivated"

	EventTypeAuthTokenIssued  EventType = "auth.token.issued"
	EventTypeAuthTokenRevoked EventType = "auth.token.revoked"

	EventTypeSessionEstablished EventType = "session.established"
	EventTypeSessionDeleted     EventType = "session.deleted"

	EventTypeAuthAttemptCreated   EventType = "auth.attempt.created"
	EventTypeAuthAttemptHandedOff EventType = "auth.attempt.handed_off"
	EventTypeAuthCheckFailed      EventType = "auth.check.failed"
	EventTypeAuthCheckSucceeded   EventType = "auth.check.succeeded"

	EventTypeFlowdefCreated EventType = "flowdef.created"
	EventTypeFlowdefUpdated EventType = "flowdef.updated"
	EventTypeFlowdefDeleted EventType = "flowdef.deleted"

	EventTypeSchemaCreated EventType = "schema.created"

	EventTypeBrandingCreated EventType = "branding.created"

	EventTypeEnvironmentCreated EventType = "environment.created"

	EventTypeAuthzGranted EventType = "authz.granted"
	EventTypeAuthzRevoked EventType = "authz.revoked"

	EventTypeAuthFactorPasswordSet     EventType = "auth.factor.password.set"
	EventTypeAuthFactorPasskeyEnrolled EventType = "auth.factor.passkey.enrolled"
)

Path A / Path B event types with live producers (see docs/design/api/events-catalog.md). Deferred types live only in the catalog Deferred section until follow-up issues land.

type Field

type Field string

Field carries the raw field name from a flow-definition step.

func FieldsFromStrings

func FieldsFromStrings(s []string) []Field

FieldsFromStrings lifts wire-format string field names into typed Field values at the API/repository boundary.

func (Field) AuthMethod

func (f Field) AuthMethod() string

AuthMethod returns the method name after the `x-auth-methods#` prefix (e.g. "password").

func (Field) IsAuthMethod

func (f Field) IsAuthMethod() bool

IsAuthMethod reports whether the field references an `x-auth-methods` entry.

func (Field) IsUserProperty

func (f Field) IsUserProperty() bool

IsUserProperty reports whether the field names a user-schema property.

func (Field) String

func (f Field) String() string

String returns the raw wire-format name.

type FlowAction

type FlowAction struct {
	Name    string
	Kind    FlowActionKind
	TextKey string
	Primary bool
}

FlowAction is a single user action surfaced on FlowStep.Actions.

type FlowActionKind

type FlowActionKind uint8

FlowActionKind classifies what the engine should do when a user invokes an action. Submit-style kinds run the input pipeline (field validation, challenge dispatch, on_success); Navigate skips the pipeline and just follows the matching transition.

const (
	// FlowActionKindUnset is the zero value. stepActionKind returns it
	// when the submitted name isn't declared on the step.
	FlowActionKindUnset FlowActionKind = iota
	// FlowActionKindSubmit advances by collecting the step's fields and
	// running the standard validate/dispatch/on_success pipeline.
	FlowActionKindSubmit
	// FlowActionKindPasskey issues a WebAuthn assertion challenge and
	// resolves the matching transition once the assertion verifies.
	FlowActionKindPasskey
	// FlowActionKindPasskeyRegister issues a WebAuthn registration
	// challenge and resolves the matching transition once the attestation
	// verifies.
	FlowActionKindPasskeyRegister
	// FlowActionKindNavigate routes through the transition without running
	// the input pipeline. Used for pure-routing actions declared in the flow
	// definition where the submitted fields are irrelevant.
	FlowActionKindNavigate
	// FlowActionKindBack pops the previous step from runtime history and
	// re-renders it. Injected by the engine on rendered step responses when
	// history is non-empty and the current step is non-terminal; rejected by
	// the validator on inbound flow definitions — flow authors never declare it.
	FlowActionKindBack
)

func FlowActionKindString

func FlowActionKindString(s string) (FlowActionKind, error)

FlowActionKindString retrieves an enum value from the enum constants string name. Throws an error if the param is not part of the enum.

func FlowActionKindValues

func FlowActionKindValues() []FlowActionKind

FlowActionKindValues returns all values of the enum

func (FlowActionKind) IsAFlowActionKind

func (i FlowActionKind) IsAFlowActionKind() bool

IsAFlowActionKind returns "true" if the value is listed in the enum definition. "false" otherwise

func (*FlowActionKind) Scan

func (i *FlowActionKind) Scan(value interface{}) error

func (FlowActionKind) String

func (i FlowActionKind) String() string

func (FlowActionKind) Value

func (i FlowActionKind) Value() (driver.Value, error)

type FlowAuthAttemptService

type FlowAuthAttemptService interface {
	Start(ctx context.Context, in FlowCreateAttemptInput) (attemptID string, err error)
	SubmitIdentifier(ctx context.Context, in FlowSubmitIdentifierInput) (userID string, err error)
	SubmitPassword(ctx context.Context, in FlowSubmitPasswordInput) error
	// IssuePasskeyChallenge mints a WebAuthn assertion challenge and
	// returns its id plus the PublicKeyCredentialRequestOptions the
	// browser passes to navigator.credentials.get().
	IssuePasskeyChallenge(ctx context.Context, in FlowIssuePasskeyChallengeInput) (FlowPasskeyChallengeOutput, error)
	// SubmitPasskey verifies the assertion against the issued challenge
	// and returns the authenticated user id. For a discoverable login the
	// user is resolved from the assertion; for an identified login it is
	// the already-pinned user. Rejection surfaces as
	// [ErrAuthAttemptProofRejected].
	SubmitPasskey(ctx context.Context, in FlowSubmitPasskeyInput) (userID string, err error)
	// IssuePasskeyRegistrationChallenge mints a WebAuthn registration
	// challenge on the attempt and returns its id plus the
	// PublicKeyCredentialCreationOptions the browser passes to
	// navigator.credentials.create(). Enrollment rides the same two-phase
	// ceremony shape as [IssuePasskeyChallenge]/[SubmitPasskey].
	IssuePasskeyRegistrationChallenge(ctx context.Context, in FlowIssuePasskeyRegistrationChallengeInput) (FlowPasskeyRegistrationChallengeOutput, error)
	// SubmitPasskeyRegistration verifies the attestation against the issued
	// challenge and persists the new credential; for a provisional ceremony
	// the user row is created in the same transaction. Rejection surfaces as
	// [ErrAuthAttemptProofRejected]; a conflicting user as
	// [ErrUserAlreadyExists].
	SubmitPasskeyRegistration(ctx context.Context, in FlowSubmitPasskeyRegistrationInput) error
	// Handoff mints the single-use token the client exchanges for a
	// session. Called by the state machine on the terminal step.
	Handoff(ctx context.Context, in FlowHandoffInput) (FlowHandoffOutput, error)
}

FlowAuthAttemptService is the FlowStateMachine's narrow view of the auth-attempt domain. Submit* calls collapse the underlying issue-then-verify cycle so the state machine never sees challenge IDs. Identifier no-match and password failure surface as ErrAuthAttemptProofRejected (use errors.Is).

Passkey is the exception: it is a two-phase WebAuthn ceremony, so it cannot collapse issue+verify into one call. [IssuePasskeyChallenge] mints the options the browser signs; [SubmitPasskey] verifies the returned assertion. The state machine threads the challenge id between the two via FlowState.PendingChallenge.

type FlowAuthRequestRef

type FlowAuthRequestRef struct {
	ID           string
	RequestedACR *string
}

FlowAuthRequestRef ties a flow to the OIDC authorization request it is fulfilling.

type FlowBackEntry

type FlowBackEntry struct {
	StepName string
	// Purpose is kept in the history so the flow returns with the current purpose.
	Purpose FlowDefinitionPurpose
}

FlowBackEntry holds an entry to be pushed into BackStack.

type FlowChallengeResponse

type FlowChallengeResponse struct {
	ChallengeID string
	Method      string
	// Proof is the method-specific payload (for passkey, the WebAuthn
	// PublicKeyCredential assertion JSON).
	Proof []byte
}

FlowChallengeResponse is the client's answer to a FlowPendingChallenge.

type FlowCreateAttemptInput

type FlowCreateAttemptInput struct {
	ProjectID      string
	SessionID      *string
	RequiredChecks []AuthCheckType
}

FlowCreateAttemptInput is the bootstrap input to FlowAuthAttemptService.Start. SessionID is set only for step-up auth; RequiredChecks overrides the project default when pinned.

type FlowDefinition

type FlowDefinition struct {
	ProjectID     string
	ID            string
	Name          string
	SchemaVersion string
	Status        FlowDefinitionStatus
	CreatedAt     time.Time
	UpdatedAt     time.Time
	// UserSchema is the URL of the JSON schema this flow operates on.
	UserSchema string
	// Purposes maps each purpose this definition handles to the name of
	// its entry-point step. Every value must match a step in [Steps].
	Purposes map[FlowDefinitionPurpose]string
	Audience FlowDefinitionAudience
	Steps    []FlowDefinitionStep
}

FlowDefinition is a customer-configured directed graph of authentication steps. It is immutable: modifications produce a new revision with a new SchemaVersion.

func NewFlowDefinition

func NewFlowDefinition(
	flowDefID string,
	projectID string,
	name string,
	schemaVersion string,
	userSchema string,
	purposes map[FlowDefinitionPurpose]string,
	audience FlowDefinitionAudience,
	steps []FlowDefinitionStep,
	status FlowDefinitionStatus,
) (_ *FlowDefinition, err error)

func (*FlowDefinition) FindStep

func (d *FlowDefinition) FindStep(name string) (*FlowDefinitionStep, bool)

FindStep returns a pointer into d.Steps for the step named name, or false if no such step exists.

func (*FlowDefinition) InitialStepFor

func (d *FlowDefinition) InitialStepFor(purpose FlowDefinitionPurpose) (string, bool)

InitialStepFor returns the entry-point step name for purpose, or false if the definition does not serve it.

type FlowDefinitionAudience

type FlowDefinitionAudience struct {
	AppIDs  []string
	TeamIDs []string
}

FlowDefinitionAudience describes which requests this definition should be selected for. Empty slices (or nil) mean "no restriction". Specificity for resolution is app > team > project-wide (both empty).

type FlowDefinitionField

type FlowDefinitionField uint8

FlowDefinitionField enumerates the fields of FlowDefinition which can be used for ordering in list operations.

const (
	FlowDefinitionFieldUnspecified FlowDefinitionField = iota
	FlowDefinitionFieldProjectID
	FlowDefinitionFieldID
	FlowDefinitionFieldName
	FlowDefinitionFieldSchemaVersion
	FlowDefinitionFieldStatus
	FlowDefinitionFieldCreatedAt
	FlowDefinitionFieldUpdatedAt
	FlowDefinitionFieldUserSchema
	FlowDefinitionFieldPurposes
	FlowDefinitionFieldAudience
	FlowDefinitionFieldSteps
)

type FlowDefinitionPurpose

type FlowDefinitionPurpose uint8
const (
	FlowDefinitionPurposeLogin FlowDefinitionPurpose = iota
	FlowDefinitionPurposeRegister
	FlowDefinitionPurposeRecovery
	FlowDefinitionPurposeProfiling
	FlowDefinitionPurposeReauth
	FlowDefinitionPurposeLinkAccount
)

func FlowDefinitionPurposeString

func FlowDefinitionPurposeString(s string) (FlowDefinitionPurpose, error)

FlowDefinitionPurposeString retrieves an enum value from the enum constants string name. Throws an error if the param is not part of the enum.

func FlowDefinitionPurposeValues

func FlowDefinitionPurposeValues() []FlowDefinitionPurpose

FlowDefinitionPurposeValues returns all values of the enum

func (FlowDefinitionPurpose) IsAFlowDefinitionPurpose

func (i FlowDefinitionPurpose) IsAFlowDefinitionPurpose() bool

IsAFlowDefinitionPurpose returns "true" if the value is listed in the enum definition. "false" otherwise

func (*FlowDefinitionPurpose) Scan

func (i *FlowDefinitionPurpose) Scan(value interface{}) error

func (FlowDefinitionPurpose) String

func (i FlowDefinitionPurpose) String() string

func (FlowDefinitionPurpose) Value

func (i FlowDefinitionPurpose) Value() (driver.Value, error)

type FlowDefinitionStatus

type FlowDefinitionStatus uint8
const (
	FlowDefinitionStatusDraft FlowDefinitionStatus = iota
	FlowDefinitionStatusActive
	FlowDefinitionStatusDeprecated
	FlowDefinitionStatusArchived
)

func FlowDefinitionStatusString

func FlowDefinitionStatusString(s string) (FlowDefinitionStatus, error)

FlowDefinitionStatusString retrieves an enum value from the enum constants string name. Throws an error if the param is not part of the enum.

func FlowDefinitionStatusValues

func FlowDefinitionStatusValues() []FlowDefinitionStatus

FlowDefinitionStatusValues returns all values of the enum

func (FlowDefinitionStatus) IsAFlowDefinitionStatus

func (i FlowDefinitionStatus) IsAFlowDefinitionStatus() bool

IsAFlowDefinitionStatus returns "true" if the value is listed in the enum definition. "false" otherwise

func (*FlowDefinitionStatus) Scan

func (i *FlowDefinitionStatus) Scan(value interface{}) error

func (FlowDefinitionStatus) String

func (i FlowDefinitionStatus) String() string

func (FlowDefinitionStatus) Value

func (i FlowDefinitionStatus) Value() (driver.Value, error)

type FlowDefinitionStep

type FlowDefinitionStep struct {
	Name string
	// Fields lists the user-schema property names this step collects.
	// Resolved against [FlowDefinition.UserSchema] at runtime to derive
	// per-field type, validation, and implicit outcomes.
	Fields []Field
	// Actions are the user-selectable actions on this step, in display
	// order. Each action's Name is what the frontend echoes back in the
	// submit request.
	Actions []FlowStepAction
	// Gates are security challenges that must be satisfied before the
	// step's submission is accepted, keyed by gate name.
	Gates map[string]FlowStepGate
	// SSOProviders lists the identity providers available on this step.
	SSOProviders []FlowSSOProvider
	// OnSuccess names the server-side mutation to run after field
	// validation passes, before the transition fires. Nil means advance
	// directly with no side effect.
	OnSuccess *FlowOnSuccess
	// Complete, when non-nil, marks this step as terminal and dictates
	// how the frontend finishes (redirect vs. success screen). Nil for
	// regular interactive steps.
	Complete *FlowStepComplete
	// Transitions maps an action or engine-emitted outcome name to the
	// next state. The key is either an action declared in [Actions] or a
	// reserved outcome the engine produces (e.g. `user_not_found`,
	// `callback`).
	Transitions map[string]FlowStepTransition
}

FlowDefinitionStep is a single node in the step graph.

type FlowDefinitionTransitionAction

type FlowDefinitionTransitionAction uint8
const (
	// Switch means switching to a new flow. Redirect the user to a new flow
	Switch FlowDefinitionTransitionAction = iota
	// Pivot means switching temporarily to a new flow, then comes back to current flow once done
	Pivot
)

func FlowDefinitionTransitionActionString

func FlowDefinitionTransitionActionString(s string) (FlowDefinitionTransitionAction, error)

FlowDefinitionTransitionActionString retrieves an enum value from the enum constants string name. Throws an error if the param is not part of the enum.

func FlowDefinitionTransitionActionValues

func FlowDefinitionTransitionActionValues() []FlowDefinitionTransitionAction

FlowDefinitionTransitionActionValues returns all values of the enum

func (FlowDefinitionTransitionAction) IsAFlowDefinitionTransitionAction

func (i FlowDefinitionTransitionAction) IsAFlowDefinitionTransitionAction() bool

IsAFlowDefinitionTransitionAction returns "true" if the value is listed in the enum definition. "false" otherwise

func (*FlowDefinitionTransitionAction) Scan

func (i *FlowDefinitionTransitionAction) Scan(value interface{}) error

func (FlowDefinitionTransitionAction) String

func (FlowDefinitionTransitionAction) Value

type FlowField

type FlowField struct {
	// Name is the user-schema property this field collects, as a dotted
	// path for a nested property (`address.street`).
	Name string

	// Type is the UI input kind the client should render. It is
	// derived from the property's JSON `type` and `format` in the user
	// meta-schema. The reserved `x-auth-methods#<method>` field name
	// forces the input kind matching that credential method
	// (e.g. `x-auth-methods#password` → password).
	Type FlowFieldType

	// TextKey is a localization key for the field label (e.g.
	// `field.email`). Resolved client-side via the `| t` filter.
	TextKey string

	// Required reflects membership in the schema's `required` array at
	// every level of the field's path: a nested leaf is required only
	// when each of its ancestors is required too, matching what schema
	// validation accepts for the document as a whole.
	Required bool

	// Value is an optional pre-fill (e.g. an identifier carried over
	// from a pivot). Nil when no pre-fill applies.
	Value *string

	// Validation carries the schema-derived validation rules. Nil when
	// the property has no rules beyond its JSON type.
	Validation *FlowFieldValidation

	// Unique mirrors the property's `x-unique` annotation: the scope at
	// which the value must be unique, or [AttributeUniquenessUnspecified]
	// when absent. The user-creation path consults it to set the
	// per-attribute uniqueness scope on storage.
	Unique AttributeUniqueness

	// Challenge names the auth-attempt challenge the field maps to, or
	// [FlowFieldChallengeNone] when the field carries neither an
	// identifier nor a credential proof. Derivation paths: the field
	// naming the schema's designated identifier (the schema-root
	// `x-identifier` path, ADR 058) surfaces as
	// [FlowFieldChallengeIdentifier]; the reserved `x-auth-methods#password` field
	// name combined with `x-auth-methods.password.enabled = true` at
	// the schema root surfaces as [FlowFieldChallengePassword]. Other
	// credential kinds (passkey, magic_link, sso, otp) do not have
	// field-shaped proofs and are produced by the state machine as
	// challenge steps, not by the resolver. The state machine consults
	// Challenge on submit to route the value — identifier fields drive
	// identifier resolution (and the `user_not_found` implicit outcome),
	// password fields drive the password challenge.
	Challenge FlowFieldChallenge
}

FlowField is the resolved per-field metadata.

func FindCollectedFieldByChallenge

func FindCollectedFieldByChallenge(resolved []FlowField, collected map[string]any, target FlowFieldChallenge) (name string, field FlowField, value any, ok bool)

FindCollectedFieldByChallenge looks up a field whose resolved Challenge matches target and whose name is present in collected. Returns the field name, the matched FlowField, and its collected value. Callers that don't need the FlowField discard it.

type FlowFieldChallenge

type FlowFieldChallenge string

FlowFieldChallenge names the auth-attempt challenge a field maps to. Values mirror the keys of `x-auth-methods` in the user meta-schema (api/openapi/endpoints/schemas/user-schema.yaml). `identifier` is sourced from the schema-root `x-identifier` designation; `password` is sourced from the reserved `x-auth-methods#password` field name combined with `x-auth-methods.password.enabled` at the schema root. The remaining credential values (passkey, magic_link, sso, otp) have no field-shaped proof and are produced by the state machine as challenge steps rather than by the resolver. Empty means the field maps to no challenge.

const (
	FlowFieldChallengeNone       FlowFieldChallenge = ""
	FlowFieldChallengeIdentifier FlowFieldChallenge = "identifier"
	FlowFieldChallengePassword   FlowFieldChallenge = "password"
	FlowFieldChallengePasskey    FlowFieldChallenge = "passkey"
	FlowFieldChallengeMagicLink  FlowFieldChallenge = "magic_link"
	FlowFieldChallengeSSO        FlowFieldChallenge = "sso"
	FlowFieldChallengeOTP        FlowFieldChallenge = "otp"
)

func ManifestForOnSuccess

func ManifestForOnSuccess(o FlowOnSuccess) []FlowFieldChallenge

ManifestForOnSuccess returns the credential kinds a mutation establishes. Dispatch (verify-vs-skip) and the validator (upstream-collects check) both read this table.

type FlowFieldResolver

type FlowFieldResolver interface {
	// Resolve returns the per-field metadata for fields against the
	// provided user schema. stepName is the flow step the fields are
	// being resolved for; it prefixes each field's text_key
	// (`<stepName>.field.<name>`). Schema loading is the caller's
	// responsibility — see [SchemaResolver].
	Resolve(schema *jsonschema.Schema, stepName string, fields []Field) (FlowResolvedFields, error)

	// Validate checks submitted values against the rules carried by a
	// previously resolved field set.
	Validate(fields FlowResolvedFields, values map[string]any) error

	// MissingRequired reports the required fields absent from values.
	// Applied only on field-collecting actions (the submit action and the
	// passkey-register issue leg); other actions legitimately submit a
	// subset of fields or none.
	MissingRequired(fields FlowResolvedFields, values map[string]any) FlowFieldValidationErrors
}

FlowFieldResolver maps property names referenced by a flow step to fully-resolved FlowField payloads, surfaces the implicit transition outcomes the schema implies (the designated `x-identifier` property implies a `user_not_found` outcome), and validates submitted values against the schema-derived rules.

The contract is shaped to the user meta-schema at api/openapi/endpoints/schemas/user-schema.yaml.

type FlowFieldType

type FlowFieldType string

FlowFieldType names the input kind the client should render. Mirrors the `type` enum in the OpenAPI flow-field component.

const (
	// FlowFieldTypeUnknown is a reserved field type that is only used in case of errors
	FlowFieldTypeUnknown  FlowFieldType = "unknown"
	FlowFieldTypeText     FlowFieldType = "text"
	FlowFieldTypeEmail    FlowFieldType = "email"
	FlowFieldTypePassword FlowFieldType = "password"
	FlowFieldTypeTel      FlowFieldType = "tel"
	FlowFieldTypeNumber   FlowFieldType = "number"
	FlowFieldTypeURL      FlowFieldType = "url"
	FlowFieldTypeDate     FlowFieldType = "date"
	FlowFieldTypeHidden   FlowFieldType = "hidden"
	FlowFieldTypeCheckbox FlowFieldType = "checkbox"
	FlowFieldTypeSelect   FlowFieldType = "select"
)

type FlowFieldValidation

type FlowFieldValidation struct {
	Format    string
	MinLength int
	MaxLength int
	Enum      []string

	// Const, when non-nil, pins the property to a fixed value (JSON
	// Schema `const`) of any type — e.g. a must-accept checkbox uses
	// `const: true`. A differing submission is reported as
	// [FlowFieldValidationRuleFormat].
	Const any
}

FlowFieldValidation carries the validation rules the resolver surfaces to the client and enforces on submit. Each field maps to a user meta-schema keyword on [user-property.yaml]:

  • Format ↔ `format` (enum: email, date-time, uuid, uri)
  • MinLength ↔ `minLength`
  • MaxLength ↔ `maxLength`
  • Enum ↔ `enum` (closed set of allowed string values)
  • Const ↔ `const` (property pinned to a fixed value)

Zero values mean "no rule". JSON Schema's `pattern` keyword is not part of the user meta-schema and is intentionally not surfaced.

type FlowFieldValidationError

type FlowFieldValidationError struct {
	Field string
	Rule  FlowFieldValidationRule
}

FlowFieldValidationError is a single rule violation reported by FlowFieldResolver.Validate.

func (FlowFieldValidationError) Error

func (e FlowFieldValidationError) Error() string

func (FlowFieldValidationError) TextKey

func (e FlowFieldValidationError) TextKey() string

TextKey returns the client-facing localisation key for the violation: `error.<field>_<rule>`, with the format rule aliased to `_invalid` — the text catalog's existing spelling (`error.email_invalid`). Field names are used verbatim, credential shape included (`error.x-auth-methods#password_required`): tenant schemas keep field naming open, so clients resolve unknown keys through generic `error.field_<rule>` fallbacks instead of a closed catalog — see `localiseFlowErrorKeys` in packages/components/src/orchestrator/liquid.ts.

type FlowFieldValidationErrors

type FlowFieldValidationErrors []FlowFieldValidationError

FlowFieldValidationErrors collects rule violations. Returned as `error` by FlowFieldResolver.Validate.

func (FlowFieldValidationErrors) Error

func (FlowFieldValidationErrors) StepError

func (e FlowFieldValidationErrors) StepError() string

StepError renders the violations for the wire `step.error` field: one FlowFieldValidationError.TextKey per violation, joined with "; ". Clients split on the joiner and localise each key. Error() stays the Go-side diagnostic ("flow field email: required") for logs and wrapped errors.

type FlowFieldValidationRule

type FlowFieldValidationRule string

FlowFieldValidationRule names a schema-derived validation rule the resolver enforces. Each rule doubles as the key suffix of the wire dialect (see FlowFieldValidationError.TextKey), so a new rule also needs a generic `error.field_<rule>` catalog entry and a suffix mapping in the client's `localiseFlowErrorKeys` (packages/components/src/orchestrator/liquid.ts).

const (
	FlowFieldValidationRuleRequired  FlowFieldValidationRule = "required"
	FlowFieldValidationRuleFormat    FlowFieldValidationRule = "format"
	FlowFieldValidationRuleMinLength FlowFieldValidationRule = "min_length"
	FlowFieldValidationRuleMaxLength FlowFieldValidationRule = "max_length"
	FlowFieldValidationRuleUnknown   FlowFieldValidationRule = "unknown_field"
)

type FlowGateKind

type FlowGateKind uint8
const (
	// FlowGateKindCaptcha challenges the user with a bot-detection
	// provider (altcha, turnstile, hcaptcha, etc).
	FlowGateKindCaptcha FlowGateKind = iota
)

func FlowGateKindString

func FlowGateKindString(s string) (FlowGateKind, error)

FlowGateKindString retrieves an enum value from the enum constants string name. Throws an error if the param is not part of the enum.

func FlowGateKindValues

func FlowGateKindValues() []FlowGateKind

FlowGateKindValues returns all values of the enum

func (FlowGateKind) IsAFlowGateKind

func (i FlowGateKind) IsAFlowGateKind() bool

IsAFlowGateKind returns "true" if the value is listed in the enum definition. "false" otherwise

func (*FlowGateKind) Scan

func (i *FlowGateKind) Scan(value interface{}) error

func (FlowGateKind) String

func (i FlowGateKind) String() string

func (FlowGateKind) Value

func (i FlowGateKind) Value() (driver.Value, error)

type FlowHandoffInput

type FlowHandoffInput struct {
	ProjectID string
	AttemptID string
}

type FlowHandoffOutput

type FlowHandoffOutput struct {
	Token     string
	ExpiresAt time.Time
}

type FlowIssuePasskeyChallengeInput

type FlowIssuePasskeyChallengeInput struct {
	ProjectID        string
	AttemptID        string
	RPID             string
	RPOrigins        []string
	UserVerification string
}

FlowIssuePasskeyChallengeInput carries the WebAuthn relying-party parameters the engine derives from the request. RPOrigins are the allowed origins; UserVerification is the requirement (empty defaults to the library default). RP params are needed only at issue time — verification re-reads them from the persisted challenge.

type FlowIssuePasskeyRegistrationChallengeInput

type FlowIssuePasskeyRegistrationChallengeInput struct {
	ProjectID   string
	AttemptID   string
	UserID      string
	Username    string
	DisplayName string
	RPID        string
	RPOrigins   []string
}

FlowIssuePasskeyRegistrationChallengeInput carries the relying-party parameters and the user context needed to begin a registration ceremony. UserID is the stable WebAuthn user handle (empty on a fresh sign-up: the attempt service mints a provisional one); Username and DisplayName are browser-visible labels when the flow has a collected identifier.

type FlowOnSuccess

type FlowOnSuccess uint8

FlowOnSuccess names the server-side mutation that runs after a step's fields validate, before its transition fires. Nil on FlowDefinitionStep.OnSuccess means no side effect.

const (
	FlowOnSuccessCreateUser FlowOnSuccess = iota
)

func FlowOnSuccessString

func FlowOnSuccessString(s string) (FlowOnSuccess, error)

FlowOnSuccessString retrieves an enum value from the enum constants string name. Throws an error if the param is not part of the enum.

func FlowOnSuccessValues

func FlowOnSuccessValues() []FlowOnSuccess

FlowOnSuccessValues returns all values of the enum

func (FlowOnSuccess) IsAFlowOnSuccess

func (i FlowOnSuccess) IsAFlowOnSuccess() bool

IsAFlowOnSuccess returns "true" if the value is listed in the enum definition. "false" otherwise

func (*FlowOnSuccess) Scan

func (i *FlowOnSuccess) Scan(value interface{}) error

func (FlowOnSuccess) String

func (i FlowOnSuccess) String() string

func (FlowOnSuccess) Value

func (i FlowOnSuccess) Value() (driver.Value, error)

type FlowOnSuccessHandler

type FlowOnSuccessHandler interface {
	Handle(ctx context.Context, in FlowOnSuccessInput) (FlowOnSuccessResult, error)
}

FlowOnSuccessHandler is the contract every on_success mutation satisfies. The state machine calls Handle after a step's fields validate and before its transition fires.

Each FlowOnSuccess value maps to one handler. Implementations live in their own file (e.g. flow_on_success_create_user.go).

type FlowOnSuccessInput

type FlowOnSuccessInput struct {
	ProjectID     string
	UserSchemaURL string
	Fields        map[string]any
	Resolved      FlowResolvedFields
	State         *FlowState
	ResolvedFlow  *FlowDefinition
}

FlowOnSuccessInput is the per-call context the state machine threads into a handler.

type FlowOnSuccessResult

type FlowOnSuccessResult struct {
	StepError *string
	// UserID is set when a handler creates a new user. The state machine
	// only records it in flow state — a handler returning a UserID MUST
	// have persisted the user's verified factors on the auth attempt
	// inside its own transaction (see FlowCreateUserWithPasswordHandler's
	// recordAttemptFactorsAction), or the exchanged session will be bound
	// to a user with no factors.
	UserID string
	// Irreversible flags mutations the user cannot reverse (e.g. created a user).
	Irreversible bool
}

FlowOnSuccessResult is what a handler returns. StepError keeps the user on the current step.

type FlowPasskeyChallengeOutput

type FlowPasskeyChallengeOutput struct {
	ChallengeID string
	Options     []byte
}

FlowPasskeyChallengeOutput is the issued challenge. Options is the PublicKeyCredentialRequestOptions JSON the client hands to the authenticator; ChallengeID binds the later assertion to this issue.

type FlowPasskeyRP

type FlowPasskeyRP struct {
	RPID    string
	Origins []string
}

FlowPasskeyRP is the relying-party context for issuing a passkey challenge, derived from the HTTP request at the API edge.

type FlowPasskeyRegistrationChallengeOutput

type FlowPasskeyRegistrationChallengeOutput struct {
	ChallengeID string
	UserID      string
	Options     []byte
}

FlowPasskeyRegistrationChallengeOutput is the issued challenge. UserID is the WebAuthn user handle (minted by the attempt service when the issue input had none).

type FlowPendingChallenge

type FlowPendingChallenge struct {
	// ID is the challenge identifier returned by the auth-attempt
	// service at issue time. The client echoes it back in
	// ChallengeResponse.
	ID string

	// Method names the ceremony kind (e.g. "passkey"). The state
	// machine uses it to route verification to the right service.
	Method string

	// Options is the client-facing ceremony options JSON (for passkey,
	// the PublicKeyCredentialRequestOptions). Surfaced on the rendered
	// step's challenge so the browser can run the ceremony; persisted in
	// the cookie so a re-render re-emits it.
	Options []byte

	// IssuedAt is when the challenge was minted. The auth-attempt
	// service enforces its own freshness window; this field is kept for
	// diagnostics and for the state machine to short-circuit obviously
	// stale challenges before calling Verify.
	IssuedAt time.Time
}

FlowPendingChallenge records the server-issued challenge the next submit must satisfy. The binding (id + method) is threaded through the cookie so the verify step can locate it; Options carries the client-facing ceremony options so a GET /flow re-render can re-emit them without re-issuing.

type FlowProgress

type FlowProgress struct {
	// DefinitionID is the flow definition currently being executed. On
	// pivot it changes to the child definition; on pop it is restored
	// from the parent entry on PivotStack.
	DefinitionID string

	// Purpose is the kind of flow (login, signup, recovery, …). The
	// handler uses it to surface a coarse classification without parsing
	// the definition.
	Purpose FlowDefinitionPurpose

	// CurrentPurpose is the dynamic dispatch mode. Flips on identifier
	// outcomes; Purpose stays pinned for telemetry / ACR.
	CurrentPurpose FlowDefinitionPurpose

	// CurrentStep is the name of the step the user is currently on
	// within DefinitionID. The next submit is interpreted against this
	// step.
	CurrentStep string

	// History is the append-only audit trail of visited steps.
	History []string

	// BackStack maintains the history of visited steps, but gets
	// cleared after an irreversible action.
	// The engine also uses it to decide when an action.back should
	// be injected into the response.
	BackStack []FlowBackEntry

	// CollectedData accumulates submitted field values for this
	// progress entry, keyed by schema property name. A child flow's
	// CollectedData is discarded when its progress is popped.
	CollectedData CollectedFlowData
}

FlowProgress captures the user's position within a single flow definition: which definition is running, the current step, the history of steps visited so far, and the data submitted along the way. It is embedded in FlowState for the active flow and pushed onto FlowState.PivotStack for paused parents.

type FlowResolvedFields

type FlowResolvedFields struct {
	// Fields holds the resolved per-field metadata in the same order as
	// the property names passed to Resolve.
	Fields []FlowField

	// ImplicitOutcomes lists the reserved transition outcomes each
	// field contributes, keyed by field name. The state machine uses it
	// to validate flow definitions and route schema-derived transitions.
	ImplicitOutcomes map[string][]string
}

FlowResolvedFields is the output of FlowFieldResolver.Resolve.

type FlowSSOProvider

type FlowSSOProvider struct {
	ID       string
	Name     string
	Template string
}

FlowSSOProvider is an identity provider option offered on a step.

type FlowSSOProviderRef

type FlowSSOProviderRef struct {
	ID string
}

type FlowSessionRef

type FlowSessionRef struct {
	ID      string
	Version int64
}

FlowSessionRef pins the session row this flow runs on top of. A version mismatch surfaces as ErrFlowSessionConflict.

type FlowStartInput

type FlowStartInput struct {
	Definition    *FlowDefinition
	Purpose       FlowDefinitionPurpose
	Session       FlowSessionRef
	AuthRequest   *FlowAuthRequestRef
	RedirectURI   *string
	UserSchemaURL string
}

FlowStartInput carries everything the state machine needs to bootstrap a new flow.

type FlowState

type FlowState struct {
	// ID is the flow handle minted at Start. The handler verifies it
	// matches the path (`/flow/{id}/...`) to reject path/cookie mismatches.
	ID string

	// ProjectID scopes the flow to a single tenant.
	ProjectID string

	// UserSchemaURL is the user schema this flow validates against,
	// captured at Start time so a mid-flow default change doesn't
	// reshape in-flight data.
	UserSchemaURL string

	// FlowProgress is the user's current progress: which definition is
	// running, which step is being shown, and what's been collected so
	// far. Promoted to the top level so callers read e.g.
	// state.CurrentStep directly.
	FlowProgress

	// IssuedAt is when this state was last sealed into the cookie. The
	// handler refuses to open a state older than the configured max-age,
	// bounding how long a stolen cookie remains replayable. Refreshed on
	// every advance.
	IssuedAt time.Time

	// SessionID is the stable identifier of the user session backing this
	// flow. It survives pivots — child and parent flows share it.
	SessionID string

	// SessionVersion pins the session row version observed when this flow
	// was last advanced. The state machine refuses to process a submit
	// against a stale version (e.g. another tab logged out the session).
	SessionVersion int64

	// StepVersion pins the step revision observed when CurrentStep was
	// emitted. If the definition is republished mid-flow, the state
	// machine surfaces an integrity error rather than silently applying
	// the new step shape to in-flight data.
	StepVersion int64

	// PivotStack records parent-flow resume points. When a flow pivots
	// into another flow, the parent's FlowProgress is pushed; on the
	// child's completion the state machine pops and re-renders the
	// parent's next step. Empty for non-stacked flows.
	PivotStack []FlowProgress

	// AuthRequestID, when set, identifies the OIDC authorization request
	// this flow is fulfilling. Nil for flows started outside an OIDC
	// context (e.g. standalone registration or recovery).
	AuthRequestID *string

	// RedirectURI is the terminal redirect destination for `complete:
	// redirect` flows (typically the OIDC callback). Nil for `complete:
	// show` flows that end on a success screen.
	RedirectURI *string

	// RequestedACR is the Authentication Context Class Reference asked
	// for by the relying party. The implicit policy evaluator compares
	// it against the session's assurance levels to decide whether the
	// flow can complete.
	RequestedACR *string

	// PendingChallenge binds an outstanding ceremony (passkey today,
	// other methods later) to the current step. Set by the state
	// machine when entering a step that declares a challenge; cleared
	// once the matching ChallengeResponse verifies. Nil when no
	// ceremony is in flight.
	PendingChallenge *FlowPendingChallenge

	// AuthAttemptID names the auth_attempts row this flow is collecting
	// factors against. Created at Start; completed intrinsically by the
	// last successful Submit* call; handed off by the API handler at
	// the OIDC redirect boundary.
	AuthAttemptID string
}

FlowState is the runtime state of a single in-flight flow. The handler JSON-encodes it as the payload of the sealed `_zflow` cookie on every response and decodes it back on every incoming request.

FlowState embeds FlowProgress: the active progress (definition, step, history, collected data) sits at the root, and any paused parents live on PivotStack. The remaining fields are session/OIDC context that only makes sense at the top level.

func (*FlowState) ClearBackStack

func (s *FlowState) ClearBackStack()

ClearBackStack drops any accumulated back-navigation entries. Called past irreversible mutations and at flow termination.

func (*FlowState) ClearPendingChallenge

func (s *FlowState) ClearPendingChallenge()

ClearPendingChallenge drops any outstanding ceremony binding on the state. Called when the challenge is superseded (verify succeeded, or the user navigated away).

func (*FlowState) PeekBackStack

func (s *FlowState) PeekBackStack() (FlowBackEntry, bool)

PeekBackStack returns the top BackStack entry without mutating the state. Returns false when the stack is empty.

func (*FlowState) PopBackStack

func (s *FlowState) PopBackStack() (FlowBackEntry, bool)

PopBackStack removes and returns the top BackStack entry. Returns false when the stack is empty, leaving the state untouched.

type FlowStateMachine

type FlowStateMachine interface {
	Start(ctx context.Context, in FlowStartInput) (FlowStepResult, error)
	Process(ctx context.Context, def *FlowDefinition, state *FlowState, in FlowSubmitInput) (FlowStepResult, error)
	// Render re-emits the current step without advancing. Backs GET /flow/{id}.
	Render(ctx context.Context, def *FlowDefinition, state *FlowState) (FlowStepResult, error)
}

FlowStateMachine drives a flow definition forward in response to client submissions. The handler owns cookie I/O; the state machine never touches cookies.

MVP scope: single linear flow per `flow_id`, no pivot stack, no challenges, no gates. `Pop` on FlowStepResult stays reserved for the deferred pivot work.

type FlowStateMachineRuntime

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

FlowStateMachineRuntime is the production FlowStateMachine.

func NewFlowStateMachine

func NewFlowStateMachine(
	schemas SchemaResolver,
	schemaStore JSONSchemaStore,
	fields FlowFieldResolver,
	createUser FlowOnSuccessHandler,
	authAttempts FlowAuthAttemptService,
	now func() time.Time,
) *FlowStateMachineRuntime

NewFlowStateMachine wires the runtime. The now hook is injectable so tests can produce deterministic FlowState.IssuedAt values.

func (*FlowStateMachineRuntime) Process

Process advances the flow one step by dispatching the submission to the handler for its action kind.

func (*FlowStateMachineRuntime) Render

Render re-emits the current step without advancing. Refreshes IssuedAt so the cookie max-age window slides while the user is on the step.

func (*FlowStateMachineRuntime) Start

type FlowStep

type FlowStep struct {
	Name         string
	Texts        FlowStepTexts
	Error        *string
	Complete     *FlowStepComplete
	RedirectURL  *string
	Fields       []FlowField
	Actions      []FlowAction
	SSOProviders []FlowSSOProvider
	// Challenge is a pending authentication ceremony the client must
	// satisfy before re-submitting (e.g. a passkey assertion). Nil unless
	// the engine just issued one.
	Challenge *FlowStepChallenge
}

FlowStep is the capability payload the API surfaces to the client. It mirrors the OpenAPI `flow-step` component in domain terms.

type FlowStepAction

type FlowStepAction struct {
	Name string
	// Kind classifies how the engine handles this action. See
	// [FlowActionKind] for the available kinds.
	Kind    FlowActionKind
	TextKey string
	Primary bool
}

FlowStepAction is a user-selectable action declared on a step.

type FlowStepChallenge

type FlowStepChallenge struct {
	Method      string
	ChallengeID string
	// Options is the protocol-specific options JSON the client passes to
	// the ceremony API (for passkey, PublicKeyCredentialRequestOptions).
	Options []byte
}

FlowStepChallenge mirrors the OpenAPI `flow-step.challenge`: a pending ceremony the client runs (passkey today) before re-submitting the proof.

type FlowStepComplete

type FlowStepComplete uint8

FlowStepComplete classifies a terminal step. The frontend uses this to decide between navigating to a protocol redirect URI or rendering a success/info screen. Set on FlowDefinitionStep.Complete to mark the step as terminal; nil for regular interactive steps.

const (
	// FlowStepCompleteRedirect navigates the client to the protocol
	// redirect URI (typically the OIDC/SAML callback).
	FlowStepCompleteRedirect FlowStepComplete = iota
	// FlowStepCompleteShow renders the step as a success or info screen.
	FlowStepCompleteShow
)

func FlowStepCompleteString

func FlowStepCompleteString(s string) (FlowStepComplete, error)

FlowStepCompleteString retrieves an enum value from the enum constants string name. Throws an error if the param is not part of the enum.

func FlowStepCompleteValues

func FlowStepCompleteValues() []FlowStepComplete

FlowStepCompleteValues returns all values of the enum

func (FlowStepComplete) IsAFlowStepComplete

func (i FlowStepComplete) IsAFlowStepComplete() bool

IsAFlowStepComplete returns "true" if the value is listed in the enum definition. "false" otherwise

func (*FlowStepComplete) Scan

func (i *FlowStepComplete) Scan(value interface{}) error

func (FlowStepComplete) String

func (i FlowStepComplete) String() string

func (FlowStepComplete) Value

func (i FlowStepComplete) Value() (driver.Value, error)

type FlowStepGate

type FlowStepGate struct {
	Kind     FlowGateKind
	Provider string
	// Config is provider-specific challenge configuration, opaque to the engine.
	Config map[string]any
}

FlowStepGate is a security challenge attached to a step.

type FlowStepResult

type FlowStepResult struct {
	State                 *FlowState
	Step                  *FlowStep
	Pop                   bool
	HandoffToken          string
	HandoffTokenExpiresAt time.Time
}

FlowStepResult is what the state machine returns from [Start] and [Process]. Pop is reserved for the deferred pivot stack. HandoffToken + HandoffTokenExpiresAt are populated only on the terminal step.

type FlowStepTexts

type FlowStepTexts struct {
	TitleKey       string
	DescriptionKey string
}

FlowStepTexts holds the step-level localization keys (`<step>.title`, `<step>.description`) the template resolves via the `| t` filter.

type FlowStepTransition

type FlowStepTransition struct {
	Action *FlowDefinitionTransitionAction
	// Target is either a step in the current flow OR a new flow.
	// When Action == nil, Target refers to a step in the current flow
	// When Action != nil, Target refers to another flow.
	Target string
	// Purpose, when non-nil, re-purposes the flow locally: taking this
	// transition sets [FlowState.CurrentPurpose] to this purpose while the
	// pinned [FlowState.Purpose] stays untouched. The purpose must be one
	// the definition serves and Target must be that purpose's entry step
	// (validated). Mutually exclusive with Action — a transition either
	// pivots to another flow or re-purposes within this one, never both.
	Purpose *FlowDefinitionPurpose
}

FlowStepTransition maps an action name to either a target step (regular) or a pivot purpose.

func (FlowStepTransition) IsCurrentFlow

func (fst FlowStepTransition) IsCurrentFlow() bool

type FlowSubmitIdentifierInput

type FlowSubmitIdentifierInput struct {
	ProjectID     string
	AttemptID     string
	AttributeName string
	Value         string
}

FlowSubmitIdentifierInput names the submitted identifier field (AttributeName, e.g. "email") and the user-entered value the auth-attempt service resolves to a user.

type FlowSubmitInput

type FlowSubmitInput struct {
	Action      string
	Fields      map[string]any
	GateProofs  map[string]string
	SSOProvider *FlowSSOProviderRef
	// ChallengeResponse carries the client's answer to a pending ceremony
	// (e.g. a passkey assertion). Present on the verify leg of a two-phase
	// challenge; nil otherwise.
	ChallengeResponse *FlowChallengeResponse
	// PasskeyRP carries the WebAuthn relying-party parameters the API
	// derived from the request. Required on the passkey issue leg.
	PasskeyRP *FlowPasskeyRP
}

FlowSubmitInput carries a single client submission.

GateProofs and SSOProvider are reserved; the state machine returns ErrFlowUnsupported for any flow that exercises them today.

type FlowSubmitPasskeyInput

type FlowSubmitPasskeyInput struct {
	ProjectID   string
	AttemptID   string
	ChallengeID string
	Assertion   []byte
}

FlowSubmitPasskeyInput carries the signed assertion (Proof) plus the ChallengeID returned by FlowAuthAttemptService.IssuePasskeyChallenge.

type FlowSubmitPasskeyRegistrationInput

type FlowSubmitPasskeyRegistrationInput struct {
	ProjectID      string
	AttemptID      string
	UserID         string
	ChallengeID    string
	Attestation    []byte
	UserSchemaURL  string
	UserAttributes map[string]any
}

FlowSubmitPasskeyRegistrationInput carries the attestation plus the ChallengeID returned by IssuePasskeyRegistrationChallenge. UserSchemaURL and UserAttributes feed the user creation that runs inside the verify transaction when the ceremony is provisional.

type FlowSubmitPasswordInput

type FlowSubmitPasswordInput struct {
	ProjectID string
	AttemptID string
	Plain     string
}

type FlowdefAudiencePayload

type FlowdefAudiencePayload struct {
	AppIDs  []string `json:"app_ids,omitempty"`
	TeamIDs []string `json:"team_ids,omitempty"`
}

FlowdefAudiencePayload is the allowlisted audience snapshot for flowdef events.

type FlowdefPayload

type FlowdefPayload struct {
	Name       string                  `json:"name,omitempty"`
	Status     string                  `json:"status,omitempty"`
	UserSchema string                  `json:"user_schema,omitempty"`
	Purposes   map[string]string       `json:"purposes,omitempty"`
	Audience   *FlowdefAudiencePayload `json:"audience,omitempty"`
}

FlowdefPayload is shared by flowdef.created (snapshot) and flowdef.updated (delta). Steps are intentionally omitted (large graph).

func FlowdefPayloadDelta

func FlowdefPayloadDelta(before, after *FlowDefinition) FlowdefPayload

FlowdefPayloadDelta is the allowlisted update delta (new values only).

func FlowdefPayloadSnapshot

func FlowdefPayloadSnapshot(fd *FlowDefinition) FlowdefPayload

FlowdefPayloadSnapshot is the allowlisted create snapshot for flowdef events.

type HandoffToken

type HandoffToken struct {
	TokenHash []byte
	// contains filtered or unexported fields
}

func (*HandoffToken) ExpiresAt

func (t *HandoffToken) ExpiresAt(handedOffAt *time.Time) time.Time

func (*HandoffToken) Plain

func (t *HandoffToken) Plain() string

type JSONSchema

type JSONSchema struct {
	ProjectID  string
	URL        string
	ObjectType *string
	Kind       JSONSchemaKind
	CreatedAt  time.Time
	Schema     []byte
}

func NewJSONSchema

func NewJSONSchema(projectID string, schemabs []byte) (_ *JSONSchema, err error)

type JSONSchemaField

type JSONSchemaField uint8

JSONSchemaField enumerates the fields of JSONSchema which can be used for filtering and ordering in list operations.

const (
	JSONSchemaFieldUnspecified JSONSchemaField = iota
	JSONSchemaFieldProjectID
	JSONSchemaFieldURL
	JSONSchemaFieldObjectType
	JSONSchemaFieldCreatedAt
	JSONSchemaFieldKind
)

type JSONSchemaKind

type JSONSchemaKind uint8

JSONSchemaKind is the `kind` a stored schema document declares. It is the discriminator the meta-schemas are keyed on, not the `kind` of a create request — `schema-url` describes how a schema was supplied, and the document fetched from that URL declares its own kind like any other.

const (
	// JSONSchemaKindUnknown is recorded when a schema is persisted without its
	// document being parsed, so no declared kind was ever read. Filtering by
	// kind never matches it.
	JSONSchemaKindUnknown    JSONSchemaKind = iota // unknown
	JSONSchemaKindUserSchema                       // user-schema
)

func JSONSchemaKindString

func JSONSchemaKindString(s string) (JSONSchemaKind, error)

JSONSchemaKindString retrieves an enum value from the enum constants string name. Throws an error if the param is not part of the enum.

func JSONSchemaKindValues

func JSONSchemaKindValues() []JSONSchemaKind

JSONSchemaKindValues returns all values of the enum

func (JSONSchemaKind) IsAJSONSchemaKind

func (i JSONSchemaKind) IsAJSONSchemaKind() bool

IsAJSONSchemaKind returns "true" if the value is listed in the enum definition. "false" otherwise

func (*JSONSchemaKind) Scan

func (i *JSONSchemaKind) Scan(value interface{}) error

func (JSONSchemaKind) String

func (i JSONSchemaKind) String() string

func (JSONSchemaKind) Value

func (i JSONSchemaKind) Value() (driver.Value, error)

type JSONSchemaResolver

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

JSONSchemaResolver retrieves JSON schemas by their URL recursively, starting from the given schema URL and following all references in the schema. It caches resolved schemas in memory and uses a JSONSchemaStore to load and persist them for future use.

func NewJSONSchemaResolver

func NewJSONSchemaResolver(
	cache *lru.TwoQueueCache[string, *jsonschema.Schema],
	maxResolveDepth int,
	maxSize int,
	httpClient *http.Client,
	builtinPublicBase *url.URL,
) *JSONSchemaResolver

NewJSONSchemaResolver wires a resolver with an LRU cache, resolve limits, an optional HTTP client for ingestion, and an optional builtinPublicBase URL. When builtinPublicBase is non-nil, schema URLs under that prefix are loaded from embedded templates instead of the database; they are not persisted via JSONSchemaStore.CreateJSONSchema. Persistence is supplied per JSONSchemaResolver.Resolve call via JSONSchemaStore.

func (*JSONSchemaResolver) Resolve

func (r *JSONSchemaResolver) Resolve(
	ctx context.Context,
	store JSONSchemaStore,
	projectID string,
	schemaURL string,
	rootSchema []byte,
) (*jsonschema.Schema, error)

Resolve retrieves a JSON schema by its URL recursively, starting from the given schema URL and following all references in the schema. It first tries to find the fully resolved schema in the cache. If not found in the cache, it looks for the schema and all its references by URL from the store. When the resolver has an HTTP client, it can fetch a missing schema from its URL and persist it.

type JSONSchemaStore

type JSONSchemaStore interface {
	GetJSONSchemaByID(ctx context.Context, projectID, schemaID string) (*JSONSchema, error)
	CreateJSONSchema(ctx context.Context, schema *JSONSchema) error
}

JSONSchemaStore is the persistence port for JSON schemas used by JSONSchemaResolver and service callers that only need get/create. Because schema validation happens on data writes in domain logic, schemas are immutable. They can only be created and deleted (if no data references them). Schemas can use versioned URLs to support multiple versions of the same schema.

Method names match the v2 statement surface so pool/tx statements satisfy this interface without an adapter.

type JWEHeader

type JWEHeader struct {
	KeyID               string                 `json:"kid"`
	EncryptionAlgorithm jose.ContentEncryption `json:"enc"`
}

func DecodeJWEHeader

func DecodeJWEHeader(token string) (*JWEHeader, error)

type KeyState

type KeyState string
const (
	KeyStateNotActiveYet KeyState = "not_active_yet"
	KeyStateActive       KeyState = "active"
	KeyStateExpired      KeyState = "expired"
	KeyStateRemoved      KeyState = "removed"
)

type KnownSchemaKind

type KnownSchemaKind string
const (
	SchemaKindUser           KnownSchemaKind = "user"
	SchemaKindFlowDefinition KnownSchemaKind = "flow-definition"
)

type MasterKey

type MasterKey struct {
	ID string

	ShouldBeUsedForEncryption bool
	// contains filtered or unexported fields
}

func NewMasterKey

func NewMasterKey(
	id string,
	key rsa.PrivateKey,
	shouldBeUsedForEncryption bool,
) MasterKey

func (*MasterKey) Decrypt

func (k *MasterKey) Decrypt(encrypted string) (string, error)

func (*MasterKey) Encrypt

func (k *MasterKey) Encrypt(decrypted string) (string, error)

Encrypt wraps decrypted with the master key and returns a JWE compact serialization. The JWE protected header carries the master key's ID as "kid" so the key can later be resolved without trying every configured master key.

type MasterKeys

type MasterKeys struct {
	Keys          []MasterKey
	EncryptionKey MasterKey
}

func NewMasterKeys

func NewMasterKeys(keys []MasterKey) (*MasterKeys, error)

func (MasterKeys) Decrypt

func (ks MasterKeys) Decrypt(encrypted string) (string, error)

func (MasterKeys) Encrypt

func (ks MasterKeys) Encrypt(decrypted string) (string, error)

func (MasterKeys) GetByKeyID

func (ks MasterKeys) GetByKeyID(id string) *MasterKey

type MembershipStatus

type MembershipStatus string

MembershipStatus is the roster participation state for a user on a team.

const (
	MembershipStatusPending  MembershipStatus = "pending"
	MembershipStatusActive   MembershipStatus = "active"
	MembershipStatusInactive MembershipStatus = "inactive"
	MembershipStatusRemoved  MembershipStatus = "removed"
)

func (MembershipStatus) IsAuthzActive

func (s MembershipStatus) IsAuthzActive() bool

IsAuthzActive reports whether the roster status should project an authz membership edge.

func (MembershipStatus) String

func (s MembershipStatus) String() string

type PasskeyChallenge

type PasskeyChallenge struct {
	Challenge            string
	AllowedCredentialIDs [][]byte
	// UserVerification mirrors the WebAuthn UserVerificationRequirement enum:
	// "required", "preferred" or "discouraged" (or empty for unset).
	UserVerification string
	RPID             string
	// TODO: RPOrigins must be a subset of the project's allowed origins
	// once a unified project-level origin config (prod + preview) exists.
	RPOrigins []url.URL

	UserID  []byte    `json:"user_id,omitempty" msg:"u,omitempty"`
	Expires time.Time `json:"expires" msg:"exp"`

	Extensions map[string]any               `json:"extensions,omitempty" msg:"exts,omitempty"`
	CredParams []PasskeyCredentialParameter `json:"credParams,omitempty" msg:"params,omitempty"`
	// Mediation mirrors the WebAuthn CredentialMediationRequirement enum.
	Mediation string `json:"mediation,omitempty" msg:"cmr,omitempty"`
}

func CreatePasskeyChallenge

func CreatePasskeyChallenge(id string, keys []*UserPasskey, verification string, rpID string, origins []url.URL) (*PasskeyChallenge, error)

type PasskeyCredentialParameter

type PasskeyCredentialParameter struct {
	Type      string `json:"type"`
	Algorithm int    `json:"alg"`
}

PasskeyCredentialParameter mirrors a WebAuthn PublicKeyCredentialParameters entry as a plain-Go type so the persisted/transmitted domain model stays independent of go-webauthn. JSON shape matches the WebAuthn spec.

type PasskeyRegistrationChallenge

type PasskeyRegistrationChallenge struct {
	Challenge   string
	RPID        string
	RPOrigins   []url.URL
	UserID      string
	Username    string
	DisplayName string
	ExcludeIDs  [][]byte // existing credential IDs excluded from this registration
	Expires     time.Time
	CredParams  []protocol.CredentialParameter
	Extensions  protocol.AuthenticationExtensions
}

PasskeyRegistrationChallenge holds server-side state for a BeginRegistration call. It must be persisted between the issue and verify legs of the registration ceremony.

func CreatePasskeyRegistrationChallenge

func CreatePasskeyRegistrationChallenge(userID, username, displayName string, existing []*UserPasskey, rpID string, origins []url.URL) (*PasskeyRegistrationChallenge, error)

CreatePasskeyRegistrationChallenge calls webauthn.BeginRegistration and maps the returned SessionData to a PasskeyRegistrationChallenge.

type PasskeyVerification

type PasskeyVerification struct {
	CredentialID   []byte
	SignCount      uint32
	UserVerified   bool
	BackupEligible bool
	BackupState    bool
	UserID         string
}

func VerifyPasskeyChallenge

func VerifyPasskeyChallenge(challenge *PasskeyChallenge, response []byte, userID string, passkeys []*UserPasskey, passkey func(userID string) ([]*UserPasskey, error)) (*PasskeyVerification, error)

type PersonalTeamNotActiveDetails

type PersonalTeamNotActiveDetails struct {
	MembershipStatus string `json:"membership_status"`
}

PersonalTeamNotActiveDetails names the membership state that blocked the personal-team resolution.

type PivotingTarget

type PivotingTarget struct {
	Name       string
	Step       string
	Transition string
}

func ValidateFlowDefinition

func ValidateFlowDefinition(userSchema *jsonschema.Schema, flowDefinition FlowDefinition) ([]PivotingTarget, error)

ValidateFlowDefinition is ported (rules and message strings) to packages/config/src/validate.ts for CLI plan-time validation — keep rule changes in sync; a drift-audit test over this file guards the function names and shared literals. The sync burden is interim: the validate-only bundle endpoint (zitadel/nextgen#449) supersedes the port, and the TS side is deleted when it lands.

type Project

type Project struct {
	ID        string
	Name      string
	CreatedAt time.Time
	UpdatedAt time.Time
	// PreviewOrigins are the allowed origins for the preview secret.
	// Callers must set this field before the project is persisted.
	PreviewOrigins []string
}

Project is a minimal representation of the object defined [here](https://github.com/zitadel/nextgen/blob/main/docs/design/api/resource-map.md#projects) It is hardly ever modified but read a lot therefore it should be stored in global tables.

func NewProject

func NewProject(name string, previewOrigins []string) (*Project, error)

func (*Project) GenerateNewKeySet

func (p *Project) GenerateNewKeySet(masterKey crypto.Crypter, mintID func(ResourcePrefix) (string, error)) (*ProjectKeySet, error)

GenerateNewKeySet creates the project's key encryption key, wrapped by the deployment's master key, and the purpose-scoped keys wrapped by that KEK. mintID must mint the KEK ID before wrapping — that ID is the JWE "kid" for purpose keys. Other key IDs stay empty for Create* Ensure.

func (*Project) PreviewToken

func (p *Project) PreviewToken() *Token

func (*Project) Token

func (p *Project) Token() *Token

type ProjectCreatedPayload

type ProjectCreatedPayload = ProjectPayload

ProjectCreatedPayload is an alias kept for call-site clarity.

type ProjectDeletedPayload

type ProjectDeletedPayload struct{}

type ProjectField

type ProjectField uint8

ProjectField enumerates the fields of Project which can be used for ordering in list operations.

const (
	ProjectFieldUnspecified ProjectField = iota
	ProjectFieldID
	ProjectFieldName
	ProjectFieldCreatedAt
	ProjectFieldUpdatedAt
	ProjectFieldPreviewOrigins
)

type ProjectKeySet

type ProjectKeySet struct {
	KeyEncryptionKey    *EncryptionKey
	TokenEncryptionKey  *EncryptionKey
	SecretEncryptionKey *EncryptionKey
	CookieEncryptionKey *EncryptionKey
	TokenSigningKey     *SigningKey
}

func (*ProjectKeySet) Activate

func (s *ProjectKeySet) Activate(oldKeys *ProjectKeySet)

type ProjectPayload

type ProjectPayload struct {
	Name           string   `json:"name,omitempty"`
	PreviewOrigins []string `json:"preview_origins,omitempty"`
}

ProjectPayload is shared by project.created (full snapshot) and project.updated (delta: only changed fields set).

type ProjectUpdatedPayload

type ProjectUpdatedPayload = ProjectPayload

ProjectUpdatedPayload is an alias kept for call-site clarity.

type RequestAPIPayload

type RequestAPIPayload struct {
	OperationID   string `json:"operation_id"`
	Method        string `json:"method"`
	RouteTemplate string `json:"route_template"`
	Status        int    `json:"status"`
	DurationMs    int64  `json:"duration_ms"`
}

type RequestInvalidFieldDetails

type RequestInvalidFieldDetails struct {
	Field string `json:"field"`
}

RequestInvalidFieldDetails names a request field that failed validation. Producers must attach only the field path — never parser text or payload fragments (ADR 030 Decision 4 + 6).

type ResourceKind

type ResourceKind string

ResourceKind is the resource_scope_index.resource_kind discriminator.

const (
	ResourceKindProject        ResourceKind = "project"
	ResourceKindTeam           ResourceKind = "team"
	ResourceKindUser           ResourceKind = "user"
	ResourceKindSchema         ResourceKind = "schema"
	ResourceKindBranding       ResourceKind = "branding"
	ResourceKindFlowDefinition ResourceKind = "flow_definition"
	ResourceKindSession        ResourceKind = "session"
	ResourceKindEnvironment    ResourceKind = "environment"
)

func (ResourceKind) String

func (k ResourceKind) String() string

type ResourcePrefix

type ResourcePrefix string

ResourcePrefix is the ID namespace for each domain resource ("user_xxxx"). Error codes often reuse that token for the resource's public API ("user.not_found") but may use a parent or surface prefix instead. Permission scopes follow the catalog name, not necessarily the ID abbrev.

const (
	PrefixAuthAttempt      ResourcePrefix = "att"
	PrefixChallenge        ResourcePrefix = "ch"
	PrefixHandoffToken     ResourcePrefix = "handoff"
	HandoffTokenExpiration                = time.Minute
)
const (
	PrefixClaim          ResourcePrefix = "claim"
	PrefixClaimChallenge ResourcePrefix = "claim_challenge"
)
const (
	PrefixSession       ResourcePrefix = "sess"
	PrefixUserAgent     ResourcePrefix = "ua"
	SessionAnonymousTTL                = 10 * time.Minute
)
const (
	FlowDefinitionPrefix ResourcePrefix = "flowdef"
)
const PrefixAuthzAssignment ResourcePrefix = "asgn"

PrefixAuthzAssignment is the dialect-minted ID prefix for authz_assignments (asgn_<opaque>).

const PrefixBranding ResourcePrefix = "brnd"
const (
	PrefixEncryptionKey ResourcePrefix = "enc_key"
)
const (
	PrefixEnvironment ResourcePrefix = "env"
)
const PrefixEvent ResourcePrefix = "evt"
const PrefixEventSink ResourcePrefix = "sink"
const PrefixFlow ResourcePrefix = "flow"

PrefixFlow is the error-code namespace for flow *runtime* (cookie, state machine, submit/get step). Flow *definition* CRUD uses PrefixFlowDefinition.

const PrefixFlowDefinition ResourcePrefix = "flowdef"
const PrefixGrant ResourcePrefix = "grant"

PrefixGrant is the public error-code prefix for the grants HTTP API (grant.not_found). Assignment IDs stay PrefixAuthzAssignment (asgn_<opaque>).

const (
	PrefixJSONSchema ResourcePrefix = "sch"
)
const (
	PrefixProject ResourcePrefix = "proj"
)
const (
	PrefixSigningKey ResourcePrefix = "sig_key"
)
const (
	PrefixTeam ResourcePrefix = "team"
)
const (
	PrefixUser ResourcePrefix = "user"
)
const PrefixUserPasskey ResourcePrefix = "upk"
const PrefixUserPassword ResourcePrefix = "upw"
const PrefixUserRecoveryCodes ResourcePrefix = "urc"
const PrefixUserTOTP ResourcePrefix = "utotp"
var TokenPrefix ResourcePrefix = "tkn"

func (ResourcePrefix) ErrorCodePrefix

func (p ResourcePrefix) ErrorCodePrefix(code string) string

func (ResourcePrefix) IDPrefix

func (p ResourcePrefix) IDPrefix(id string) string

func (ResourcePrefix) Matches

func (p ResourcePrefix) Matches(id string) bool

Matches reports whether id is well-formed under this prefix: the registered prefix, then "_", then a non-empty body (e.g. "proj_01H..." / "proj_platform").

type ResourceScope

type ResourceScope struct {
	ResourceID   string
	ResourceKind ResourceKind
	ProjectID    string
	TeamID       *string
	CreatedAt    time.Time
	UpdatedAt    time.Time
}

ResourceScope maps a globally addressable resource id to project/team scope (resource_scope_index). Answers "where does this path.id live?" for middleware and the future resolver — not a permission grant.

func NewProjectResourceScope

func NewProjectResourceScope(projectID string) *ResourceScope

func NewResourceScope

func NewResourceScope(kind ResourceKind, projectID, resourceID string) *ResourceScope

NewResourceScope builds a project-scoped RSI row (no team).

func NewTeamResourceScope

func NewTeamResourceScope(projectID, teamID string) *ResourceScope

func NewUserResourceScope

func NewUserResourceScope(projectID, userID string) *ResourceScope

type SchemaCreatedPayload

type SchemaCreatedPayload struct {
	Kind       string `json:"kind,omitempty"`
	ObjectType string `json:"object_type,omitempty"`
}

SchemaCreatedPayload is the allowlisted snapshot for schema.created. The document itself is omitted — it is customer-authored and unbounded, and the event's entity_id already identifies which schema this was.

func SchemaCreatedPayloadSnapshot

func SchemaCreatedPayloadSnapshot(schema *JSONSchema) SchemaCreatedPayload

SchemaCreatedPayloadSnapshot builds the schema.created payload.

type SchemaFieldResolver

type SchemaFieldResolver struct{}

SchemaFieldResolver is the production FlowFieldResolver. It is a stateless translator from a loaded user schema to FlowField payloads — schema loading is the caller's responsibility (see SchemaResolver).

Translation map (user meta-schema → FlowField):

func NewSchemaFieldResolver

func NewSchemaFieldResolver() *SchemaFieldResolver

NewSchemaFieldResolver returns a stateless FlowFieldResolver.

func (*SchemaFieldResolver) MissingRequired

func (r *SchemaFieldResolver) MissingRequired(fields FlowResolvedFields, values map[string]any) FlowFieldValidationErrors

MissingRequired reports a required violation for every declared required field absent from values — the unset controls clients omit (e.g. an unselected select) that SchemaFieldResolver.Validate never sees. Apply on field-collecting actions (submit, passkey-register issue leg); skip it where actions send a subset or none. Returns nil when none are missing.

func (*SchemaFieldResolver) Resolve

func (r *SchemaFieldResolver) Resolve(schema *jsonschema.Schema, stepName string, fieldNames []Field) (FlowResolvedFields, error)

func (*SchemaFieldResolver) Validate

func (r *SchemaFieldResolver) Validate(fields FlowResolvedFields, values map[string]any) error

Validate applies the rules carried by a previously resolved field set to the submitted values. Pure: no I/O, no schema loading.

Per-value checks (in order):

Validate only visits submitted fields; an omitted required field is not its concern — the submit action pairs this with SchemaFieldResolver.MissingRequired to catch omissions.

Caller is responsible for resolving the field set first (via FlowFieldResolver.Resolve); that is where schema loading and the "unknown property in schema" check happen.

type SchemaResolver

type SchemaResolver interface {
	Resolve(ctx context.Context, store JSONSchemaStore, projectID, schemaURL string, rootSchema []byte) (*jsonschema.Schema, error)
}

SchemaResolver loads a compiled JSON schema by URL. It is the loader FlowStateMachineRuntime depends on for runtime schema access; SchemaFieldResolver is the translator that runs on top of the loaded schema.

type SchemaValidator

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

SchemaValidator validates a tenant schema document against the server-owned meta-schema for its declared kind.

func NewSchemaValidator

func NewSchemaValidator(builtinPublicBase string) (*SchemaValidator, error)

NewSchemaValidator compiles the meta-schemas for the tenant schema kinds into memory and returns a SchemaValidator instance. The builtinPublicBase is used to construct canonical URLs for the built-in meta-schemas. It must be an absolute URL with a host (e.g. "https://raw.githubusercontent.com/zitadel/nextgen/refs/tags/v1.2.3/api/openapi/endpoints/schemas").

func (*SchemaValidator) GetBuiltinSchema

func (v *SchemaValidator) GetBuiltinSchema(uri string) (*jsonschema.Schema, error)

GetBuiltinSchema returns a clone of the compiled meta-schema for the given kind. The returned schema has all $refs resolved.

Example usage:

flowDefSchema, err := validator.GetBuiltinSchema(SchemaKindFlowDefinition)
if err != nil {
	return err
}
if err := flowDefSchema.Validate(flowDefinition); err != nil {
	return fmt.Errorf("flow definition invalid: %w", err)
}

todo: support fetching compiled schema by version as well when multiple versions of the meta-schemas are available.

func (*SchemaValidator) LatestSchemaURI

func (v *SchemaValidator) LatestSchemaURI(kind KnownSchemaKind) (string, error)

LatestSchemaURI returns the canonical URI of the latest registered version for the given kind stem (e.g. "flow-definition", "user-schema"). This is useful for fetching the latest version of a schema when it's optional to provide a version.

func (*SchemaValidator) ValidateAgainstMetaSchema

func (v *SchemaValidator) ValidateAgainstMetaSchema(schemaBs []byte) error

ValidateAgainstMetaSchema validates the given tenant schema document against the appropriate meta-schema based on its declared "kind" property. At the moment, only "user-schema" and "flow-definition" are supported.

type Session

type Session struct {
	// ProjectID links to [Project].
	ProjectID string
	// ID is the unique identifier for the session within the project and user.
	ID string

	// CreatedAt is the time when the session was created, it must be set by the storage and is read only.
	CreatedAt time.Time
	// UpdatedAt is the time when the session was last updated, it must be set by the storage and is read only.
	UpdatedAt time.Time
	// ExpiresAt is the time when the session expires. Is used for garbage collection.
	ExpiresAt time.Time
	// TimeToLive is the duration after which the session expires.
	TimeToLive time.Duration

	// TokenID is the id of the token that was generated for the session. The token must be generated by the storage and its id must be set to the session.
	TokenID string

	// UserID links to the [User] the session belongs to once associated.
	// A user may have multiple sessions (e.g. from different devices or browsers), and UserID may be nil during some lifecycle stages.
	UserID *string

	// User is the linked user's resolved reference (ADR 058 §3), derived
	// from the schema's x-identifier/x-display designations. Only populated
	// on identity-hydrating reads; nil for anonymous sessions.
	User *UserRef

	// UserAgent contains information about the user's device and browser.
	UserAgent *UserAgent

	// AssuranceLevels are computed at runtime and therefore not stored in the database.
	AssuranceLevels []string
	// Factors contain the authentication factors that were used to verify the session.
	// There is one factor per [AuthCheckType].
	// The factors must be verified using [AuthAttempt]s before being added to the session, and the VerifiedAt field must be set to the time of verification.
	// The factors are stored in the database.
	Factors []AuthFactor
}

Session represents the object defined [here](https://github.com/zitadel/nextgen/blob/main/docs/design/api/resource-map.md#sessions-durable-post-auth-only)

func NewSession

func NewSession(projectID string, agent *UserAgent) (*Session, error)

func (*Session) State

func (s *Session) State() SessionState

func (*Session) Token

func (s *Session) Token(encrypter op.Encrypter) (string, error)

type SessionDeletedPayload

type SessionDeletedPayload struct {
	Reason string `json:"reason,omitempty"`
}

type SessionEstablishedPayload

type SessionEstablishedPayload struct {
	UserID string `json:"user_id,omitempty"`
}

type SessionExpiredPayload

type SessionExpiredPayload struct{}

type SessionField

type SessionField uint8

SessionField enumerates the fields of Session which can be used for filtering and ordering in list operations.

const (
	SessionFieldUnspecified SessionField = iota
	SessionFieldProjectID
	SessionFieldID
	SessionFieldCreatedAt
	SessionFieldUpdatedAt
	SessionFieldExpiresAt
	SessionFieldTimeToLive
	SessionFieldTokenID
	SessionFieldUserID
	// SessionFieldHasVerifiedFactors is computed, not stored: it reflects
	// whether the session has verified factors, the test State() uses to
	// separate building from active. Filter only; not sortable.
	SessionFieldHasVerifiedFactors
	// SessionFieldLifecycleOwnerTeamID is computed, not stored: a session
	// belongs to the team that owns its bound user's lifecycle (ADR 024,
	// ADR 060). A user has at most one lifecycle owner, so a session matches
	// at most one team; a self-owned user's session and a session with no user
	// match none. It is filter only; not sortable — a team matches many
	// sessions, and the value lives on another table.
	SessionFieldLifecycleOwnerTeamID
)

type SessionInvalidTTLDetails

type SessionInvalidTTLDetails struct {
	TTL    time.Duration `json:"ttl"`
	MaxTTL time.Duration `json:"max_ttl"`
}

type SessionState

type SessionState uint8
const (
	SessionStateUnspecified SessionState = iota
	SessionStateBuilding
	SessionStateActive
	SessionStateExpired
)

type SetUserPassword

type SetUserPassword struct {
	// ID is the password row id. Dialects mint on create and overwrite with the
	// persisted id on upsert (RETURNING / equivalent) so emitters can set
	// entity_id / factor_id.
	ID             string
	ProjectID      string
	UserID         string
	EncodedHash    string
	ChangeRequired bool
	VerificationID *string
}

type SigningKey

type SigningKey struct {
	ID          string
	ProjectID   string
	Purpose     SigningKeyPurpose
	Key         string
	Algorithm   jose.SignatureAlgorithm
	State       KeyState
	CreatedAt   time.Time
	ActivatedAt *time.Time
	RetiredAt   *time.Time
}

func NewSigningKey

func NewSigningKey(
	projectID string,
	purpose SigningKeyPurpose,
	algorithm jose.SignatureAlgorithm,
	kek crypto.Crypter,
) (*SigningKey, error)

func (*SigningKey) Activate

func (k *SigningKey) Activate(currentKey *SigningKey)

func (*SigningKey) IsActive

func (k *SigningKey) IsActive() bool

func (*SigningKey) IsRemoved

func (k *SigningKey) IsRemoved() bool

func (*SigningKey) Signer

func (k *SigningKey) Signer(kek crypto.Crypter) (jose.Signer, error)

type SigningKeyField

type SigningKeyField uint8
const (
	SigningKeyFieldUnspecified SigningKeyField = iota
	SigningKeyFieldID
	SigningKeyFieldProjectID
	SigningKeyFieldKey
	SigningKeyFieldAlgorithm
	SigningKeyFieldState
	SigningKeyFieldCreatedAt
	SigningKeyFieldActivatedAt
	SigningKeyFieldRetiredAt
	SigningKeyFieldPurpose
)

type SigningKeyPurpose

type SigningKeyPurpose string
const (
	SigningKeyPurposeToken SigningKeyPurpose = "token"
)

type Team

type Team struct {
	// ProjectID links to [Project].
	ProjectID string
	// ID is the unique identifier for the team within the project.
	ID        string
	Name      string
	Status    TeamStatus
	CreatedAt time.Time
	UpdatedAt time.Time
}

Team represents the object defined [here](https://github.com/zitadel/nextgen/blob/main/docs/design/api/resource-map.md#teams) It is hardly ever modified but read a lot therefore it should be stored in global tables.

func NewTeam

func NewTeam(projectID, name string) (*Team, error)

type TeamCreatedPayload

type TeamCreatedPayload = TeamPayload

type TeamDeactivatedPayload

type TeamDeactivatedPayload struct{}

type TeamField

type TeamField uint8

TeamField enumerates the fields of Team which can be used for filtering and ordering.

const (
	TeamFieldUnspecified TeamField = iota
	TeamFieldProjectID
	TeamFieldID
	TeamFieldName
	TeamFieldStatus
	TeamFieldCreatedAt
	TeamFieldUpdatedAt
)

type TeamMembership

type TeamMembership struct {
	ProjectID string
	TeamID    string
	UserID    string
	Status    MembershipStatus
	CreatedAt time.Time
	UpdatedAt time.Time
}

TeamMembership is the canonical N:N roster between users and teams.

type TeamMembershipField

type TeamMembershipField uint8

TeamMembershipField enumerates the fields of TeamMembership which can be used for filtering and ordering in list operations.

const (
	TeamMembershipFieldUnspecified TeamMembershipField = iota
	TeamMembershipFieldProjectID
	TeamMembershipFieldTeamID
	TeamMembershipFieldUserID
	TeamMembershipFieldStatus
	TeamMembershipFieldCreatedAt
	TeamMembershipFieldUpdatedAt
)

type TeamMembershipUpdatedPayload

type TeamMembershipUpdatedPayload struct {
	UserID string `json:"user_id"`
	TeamID string `json:"team_id"`
	Status string `json:"status"`
}

type TeamPayload

type TeamPayload struct {
	Name string `json:"name,omitempty"`
}

TeamPayload is shared by team.created and team.updated (delta on update).

type TeamStatus

type TeamStatus string

TeamStatus is the lifecycle state of a team within a project.

const (
	TeamStatusActive       TeamStatus = "active"
	TeamStatusDeactivated  TeamStatus = "deactivated"
	TeamStatusPendingPurge TeamStatus = "pending_purge"
)

func (TeamStatus) String

func (s TeamStatus) String() string

type TeamUpdatedPayload

type TeamUpdatedPayload = TeamPayload

type Token

type Token struct {
	ProjectID string
	TokenID   string
	UserID    string
	Type      TokenType
	// SessionID is set for [TokenTypeSessionToken] only.
	SessionID *string
	// OIDCSessionID is set for [TokenTypeOIDCAccessToken] only.
	OIDCSessionID *string
	// SAMLSessionID is set for [TokenTypeSAMLAssertion] only.
	SAMLSessionID *string
	Scope         []string
	CreatedAt     time.Time
	ExpiresAt     *time.Time
}

Token is a persisted token record (access, session, PAT, etc.).

A revocable token carries its record's id (`TokenID`, the `jti`). The token itself is never stored — only the id, which is not a secret (ADR 029) — and verification resolves that id against the record to decide whether the token is still active. Revocation deletes the record: a token whose record is gone is rejected, and the tokens table does not accumulate rows that grant nothing (ADR 037).

func ParseAndValidateToken

func ParseAndValidateToken(ctx context.Context, token string, decrypter crypto2.DecrypterFunc) (*Token, error)

func (*Token) Active

func (t *Token) Active(now time.Time) bool

Active reports whether the stored record still grants the token's authority at the given instant. A revoked record is deleted, so reaching this call at all means the token was not revoked; only expiry is left to check.

func (*Token) IsRevocable

func (t *Token) IsRevocable() bool

IsRevocable reports whether this token's authority is resolved against a stored record. A revocable token must carry a TokenID to be verifiable.

func (*Token) JWE

func (t *Token) JWE(encrypter op.Encrypter) (string, error)

func (*Token) ValidatePersisted

func (t *Token) ValidatePersisted() error

ValidatePersisted checks identifier fields before writing to the tokens table.

type TokenField

type TokenField uint8

TokenField enumerates the fields of Token which can be used for filtering and ordering in list operations.

const (
	TokenFieldUnspecified TokenField = iota
	TokenFieldProjectID
	TokenFieldTokenID
	TokenFieldUserID
	TokenFieldType
	TokenFieldSessionID
	TokenFieldOIDCSessionID
	TokenFieldSAMLSessionID
	TokenFieldScope
	TokenFieldExpiresAt
	TokenFieldCreatedAt
)

type TokenType

type TokenType uint8
const (
	TokenTypeUnspecified TokenType = iota
	TokenTypeSessionToken
	TokenTypeOIDCAccessToken
	TokenTypeSAMLAssertion
	TokenTypePersonalAccessToken
	// TokenTypeFlow is carried in a flow-engine cookie; it is not stored and must not be used as a bearer token.
	TokenTypeFlow
	// TokenTypeJWTProfile is a self-signed JWT verified with a stored public key; it is not stored but may be used as a bearer token.
	TokenTypeJWTProfile
	// TokenTypeProjectToken is the confidential-plane project secret (ADR 036)
	TokenTypeProjectToken
	// TokenTypeProjectPreview is the read-only preview credential issued
	// alongside the project secret.
	TokenTypeProjectPreview
)

func TokenTypeString

func TokenTypeString(s string) (TokenType, error)

TokenTypeString retrieves an enum value from the enum constants string name. Throws an error if the param is not part of the enum.

func TokenTypeValues

func TokenTypeValues() []TokenType

TokenTypeValues returns all values of the enum

func (TokenType) IsATokenType

func (i TokenType) IsATokenType() bool

IsATokenType returns "true" if the value is listed in the enum definition. "false" otherwise

func (TokenType) IsProjectSecret

func (t TokenType) IsProjectSecret() bool

IsProjectSecret reports whether t may mint an sk_proj ScopeContext. TokenTypeJWTProfile may be presented as a bearer (see its const comment) but is not a project secret and must not take that path.

func (TokenType) MarshalJSON

func (i TokenType) MarshalJSON() ([]byte, error)

MarshalJSON implements the json.Marshaler interface for TokenType

func (TokenType) Persistable

func (t TokenType) Persistable() bool

Persistable reports whether t may be written to the tokens table.

func (*TokenType) Scan

func (t *TokenType) Scan(value any) error

func (TokenType) String

func (i TokenType) String() string

func (*TokenType) UnmarshalJSON

func (i *TokenType) UnmarshalJSON(data []byte) error

UnmarshalJSON implements the json.Unmarshaler interface for TokenType

func (TokenType) Value

func (t TokenType) Value() (driver.Value, error)

type User

type User struct {
	ProjectID string
	SchemaURL string
	ID        string
	// LifecycleOwnerTeamID is set when a team owns this user's lifecycle; nil means self-owned.
	LifecycleOwnerTeamID *string
	Metadata             UserMetadata

	// Attributes are populated by user read statements.
	Attributes Attributes

	// Ref is the derived identity of ADR 058 §3a, resolved live from the
	// schema's x-identifier/x-display designations. Populated by service
	// reads that resolve it; nil on plain statement-level reads.
	Ref *UserRef

	// Teams is the user's team memberships, populated only when the read asked
	// for it. Nil means it was not asked for; empty means the user has none.
	Teams []UserTeam
	// TeamsTruncated reports that the user is on more teams than the read's
	// cap carries. The whole list is served by ListUserTeams.
	TeamsTruncated bool

	// LifecycleOwnerTeam is the team named by LifecycleOwnerTeamID, populated
	// only when the read asked for it. Nil alone is ambiguous — a self-owned
	// user has no owner to load — so LifecycleOwnerTeamLoaded is what says the
	// read looked.
	LifecycleOwnerTeam *Team
	// LifecycleOwnerTeamLoaded reports that the read resolved the owner team.
	// It is the to-one counterpart of Teams being non-nil: it separates "not
	// asked for" from "asked for, and the user is self-owned".
	LifecycleOwnerTeamLoaded bool
}

User is a hydrated user projection (header + optional EAV joins).

func (*User) IsSelfOwned

func (u *User) IsSelfOwned() bool

IsSelfOwned reports whether the user owns their own lifecycle.

func (*User) IsTeamOwned

func (u *User) IsTeamOwned() bool

IsTeamOwned reports whether a team owns this user's lifecycle.

func (*User) OwningTeamID

func (u *User) OwningTeamID() (string, bool)

OwningTeamID returns the lifecycle owner team id when team-owned.

func (*User) StringAttribute

func (u *User) StringAttribute(key AttributeKey) string

StringAttribute returns the value of the attribute with the given key when it is a non-empty string, and "" otherwise (absent key or non-string value).

type UserAgent

type UserAgent struct {
	ID   string
	IP   string
	Info map[string]any
}

UserAgent contains information about the user's device and browser.

func (*UserAgent) Clone

func (ua *UserAgent) Clone() *UserAgent

Clone returns a deep copy safe to mutate independently of the original.

type UserCreateFailedPayload

type UserCreateFailedPayload struct {
	KeyName string `json:"key_name,omitempty"`
}

type UserCreatedPayload

type UserCreatedPayload struct {
	SchemaID      string         `json:"schema_id,omitempty"`
	AttributeKeys []string       `json:"attribute_keys,omitempty"`
	Attributes    map[string]any `json:"attributes,omitempty"`
}

UserCreatedPayload omits user_id (envelope entity_id). Attribute values appear only for schema fields marked x-audit.

type UserDeactivatedPayload

type UserDeactivatedPayload struct {
	Reason string `json:"reason,omitempty"`
}

type UserDeletedPayload

type UserDeletedPayload struct{}

type UserField

type UserField uint8

UserField enumerates the fields of User which can be used for filtering and ordering in list operations.

const (
	UserFieldUnspecified UserField = iota
	UserFieldProjectID
	UserFieldID
	UserFieldSchemaURL
	UserFieldLifecycleOwnerTeamID
	UserFieldStatus
	UserFieldCreatedAt
	UserFieldUpdatedAt
)

type UserMetadata

type UserMetadata struct {
	Status    UserStatus
	CreatedAt time.Time
	UpdatedAt time.Time
}

type UserPasskey

type UserPasskey struct {
	ID              string
	ProjectID       string
	UserID          string
	CredentialID    string
	PublicKey       []byte
	AAGUID          []byte
	AttestationType *string
	Transports      []string
	SignCount       int64
	BackupEligible  bool
	BackupState     bool
	Name            string
	VerifiedAt      *time.Time
	LastUsedAt      *time.Time
	CreatedAt       time.Time
	UpdatedAt       time.Time
}

type UserPasskeyAttestationTypeUpdate

type UserPasskeyAttestationTypeUpdate struct {
	AttestationType string
}

type UserPasskeyBackupEligibleUpdate

type UserPasskeyBackupEligibleUpdate struct {
	BackupEligible bool
}

type UserPasskeyBackupStateUpdate

type UserPasskeyBackupStateUpdate struct {
	BackupState bool
}

type UserPasskeyField

type UserPasskeyField uint8

UserPasskeyField enumerates the fields of UserPasskey which can be used for filtering and ordering in list operations.

const (
	UserPasskeyFieldUnspecified UserPasskeyField = iota
	UserPasskeyFieldID
	UserPasskeyFieldProjectID
	UserPasskeyFieldUserID
	UserPasskeyFieldCredentialID
	UserPasskeyFieldSignCount
	UserPasskeyFieldBackupEligible
	UserPasskeyFieldBackupState
	UserPasskeyFieldName
	UserPasskeyFieldVerifiedAt
	UserPasskeyFieldLastUsedAt
	UserPasskeyFieldCreatedAt
	UserPasskeyFieldUpdatedAt
)

type UserPasskeyLastUsedAtUpdate

type UserPasskeyLastUsedAtUpdate struct {
	LastUsedAt time.Time
}

type UserPasskeySignCountUpdate

type UserPasskeySignCountUpdate struct {
	SignCount int64
}

type UserPasskeyTransportsUpdate

type UserPasskeyTransportsUpdate struct {
	Transports []string
}

type UserPasskeyUpdate

type UserPasskeyUpdate interface {
	// contains filtered or unexported methods
}

type UserPasskeyVerifiedAtUpdate

type UserPasskeyVerifiedAtUpdate struct {
	VerifiedAt time.Time
}

type UserPassword

type UserPassword struct {
	ID                  string
	ProjectID           string
	UserID              string
	EncodedHash         string
	ChangeRequired      bool
	ChangedAt           time.Time
	VerificationID      *string
	LastSuccessfulCheck *time.Time
	FailedAttempts      int16
	CreatedAt           time.Time
	UpdatedAt           time.Time
}

func (*UserPassword) Verify

func (u *UserPassword) Verify(password string, verifier crypto.HashVerifier) error

type UserPasswordChangeRequiredUpdate

type UserPasswordChangeRequiredUpdate struct {
	ChangeRequired bool
}

type UserPasswordChangedAtUpdate

type UserPasswordChangedAtUpdate struct {
	ChangedAt time.Time
}

type UserPasswordEncodedHashUpdate

type UserPasswordEncodedHashUpdate struct {
	EncodedHash string
}

type UserPasswordField

type UserPasswordField uint8

UserPasswordField enumerates the fields of UserPassword which can be used for filtering and ordering in storage statements.

const (
	UserPasswordFieldUnspecified UserPasswordField = iota
	UserPasswordFieldID
	UserPasswordFieldProjectID
	UserPasswordFieldUserID
	UserPasswordFieldEncodedHash
	UserPasswordFieldChangeRequired
	UserPasswordFieldChangedAt
	UserPasswordFieldVerificationID
	UserPasswordFieldLastSuccessfulCheck
	UserPasswordFieldFailedAttempts
	UserPasswordFieldCreatedAt
	UserPasswordFieldUpdatedAt
)

type UserPasswordIncrementFailedAttemptsUpdate

type UserPasswordIncrementFailedAttemptsUpdate struct {
	Delta uint8
}

type UserPasswordLastSuccessfulCheckUpdate

type UserPasswordLastSuccessfulCheckUpdate struct {
	LastSuccessfulCheck time.Time
}

type UserPasswordResetFailedAttemptsUpdate

type UserPasswordResetFailedAttemptsUpdate struct{}

type UserPasswordUpdate

type UserPasswordUpdate interface {
	// contains filtered or unexported methods
}

type UserPasswordVerificationIDUpdate

type UserPasswordVerificationIDUpdate struct {
	VerificationID string
}

type UserRecoveryCodes

type UserRecoveryCodes struct {
	ID                  string
	ProjectID           string
	UserID              string
	RecoveryCodes       []string
	LastSuccessfulCheck *time.Time
	FailedAttempts      int16
	CreatedAt           time.Time
	UpdatedAt           time.Time
}

type UserRecoveryCodesCodesUpdate

type UserRecoveryCodesCodesUpdate struct {
	Codes []string
}

type UserRecoveryCodesField

type UserRecoveryCodesField uint8

UserRecoveryCodesField enumerates the fields of UserRecoveryCodes which can be used for filtering and ordering in list operations.

const (
	UserRecoveryCodesFieldUnspecified UserRecoveryCodesField = iota
	UserRecoveryCodesFieldID
	UserRecoveryCodesFieldProjectID
	UserRecoveryCodesFieldUserID
	UserRecoveryCodesFieldRecoveryCodes
	UserRecoveryCodesFieldLastSuccessfulCheck
	UserRecoveryCodesFieldFailedAttempts
	UserRecoveryCodesFieldCreatedAt
	UserRecoveryCodesFieldUpdatedAt
)

type UserRecoveryCodesIncrementFailedAttemptsUpdate

type UserRecoveryCodesIncrementFailedAttemptsUpdate struct {
	Delta uint8
}

type UserRecoveryCodesLastSuccessfulCheckUpdate

type UserRecoveryCodesLastSuccessfulCheckUpdate struct {
	LastSuccessfulCheck *time.Time
}

type UserRecoveryCodesResetFailedAttemptsUpdate

type UserRecoveryCodesResetFailedAttemptsUpdate struct{}

type UserRecoveryCodesUpdate

type UserRecoveryCodesUpdate interface {
	// contains filtered or unexported methods
}

type UserRef

type UserRef struct {
	UserID string
	// Identifier is the current value of the schema's designated identifier
	// (x-identifier). Empty when the schema designates nothing or the user
	// lacks the value.
	Identifier string
	// IdentifierProperty names the schema property Identifier came from, so
	// clients can reach the property's schema for semantics instead of
	// guessing from the value. Set exactly when Identifier is.
	IdentifierProperty string
	// Display is the x-display rendering: the designated properties' values
	// joined in list order. Purely presentational — no source attribution.
	Display string
}

UserRef is the resolved reference to a user carried by user-linked resources (ADR 058 §3). Fields are role-named, not property-named, so responses can mix users from different schemas. An empty field means absent on the wire; Identifier and Display resolve independently of each other, and clients render Display → Identifier → UserID.

func ResolveUserRef

func ResolveUserRef(user *User, schemaDocument []byte) UserRef

ResolveUserRef derives the user's reference from their schema document's designations. Attribute values are read from the user's loaded attributes: designation paths are dot-joined leaf paths, matching the EAV flattening of AttributeKey, so entries address attribute keys verbatim. The user's attributes must be hydrated with at least the designated keys (see DesignatedAttributeKeys).

type UserSchemaUnknownDetails

type UserSchemaUnknownDetails struct {
	Schema string `json:"schema"`
}

UserSchemaUnknownDetails names the schema a create referenced that the project does not have.

type UserStatus

type UserStatus string

UserStatus is the lifecycle state of a user identity within a project.

const (
	UserStatusActive       UserStatus = "active"
	UserStatusSuspended    UserStatus = "suspended"
	UserStatusDeactivated  UserStatus = "deactivated"
	UserStatusPendingPurge UserStatus = "pending_purge"
)

func (UserStatus) String

func (s UserStatus) String() string

type UserTOTP

type UserTOTP struct {
	ID                  string
	ProjectID           string
	UserID              string
	Secret              []byte
	VerifiedAt          time.Time
	LastSuccessfulCheck *time.Time
	FailedAttempts      int16
	CreatedAt           time.Time
	UpdatedAt           time.Time
}

type UserTOTPField

type UserTOTPField uint8

UserTOTPField enumerates the fields of UserTOTP which can be used for filtering and ordering in list operations.

const (
	UserTOTPFieldUnspecified UserTOTPField = iota
	UserTOTPFieldID
	UserTOTPFieldProjectID
	UserTOTPFieldUserID
	UserTOTPFieldSecret
	UserTOTPFieldVerifiedAt
	UserTOTPFieldLastSuccessfulCheck
	UserTOTPFieldFailedAttempts
	UserTOTPFieldCreatedAt
	UserTOTPFieldUpdatedAt
)

type UserTOTPIncrementFailedAttemptsUpdate

type UserTOTPIncrementFailedAttemptsUpdate struct {
	Delta uint8
}

type UserTOTPLastSuccessfulCheckUpdate

type UserTOTPLastSuccessfulCheckUpdate struct {
	LastSuccessfulCheck time.Time
}

type UserTOTPResetFailedAttemptsUpdate

type UserTOTPResetFailedAttemptsUpdate struct{}

type UserTOTPSecretUpdate

type UserTOTPSecretUpdate struct {
	Secret []byte
}

type UserTOTPUpdate

type UserTOTPUpdate interface {
	// contains filtered or unexported methods
}

type UserTOTPVerifiedAtUpdate

type UserTOTPVerifiedAtUpdate struct {
	VerifiedAt time.Time
}

type UserTeam

type UserTeam struct {
	ProjectID string
	UserID    string
	TeamID    string
	TeamName  string
	// Status is the roster participation state, not the team's own status.
	Status    MembershipStatus
	CreatedAt time.Time
	UpdatedAt time.Time
}

UserTeam is one entry of a user's team roster: the membership joined to the team it points at, so a reader gets the team's name without a second lookup.

The roster is not lifecycle ownership. A user can sit on many team rosters while still owning their own lifecycle — see User.LifecycleOwnerTeamID and ADR 024.

type UserTeamField

type UserTeamField uint8

UserTeamField enumerates the fields of UserTeam which can be used for filtering and ordering in list operations.

const (
	UserTeamFieldUnspecified UserTeamField = iota
	UserTeamFieldProjectID
	UserTeamFieldUserID
	UserTeamFieldTeamID
	UserTeamFieldTeamName
	UserTeamFieldStatus
	UserTeamFieldCreatedAt
	UserTeamFieldUpdatedAt
)

type UserUpdatedPayload

type UserUpdatedPayload struct {
	AttributeKeys []string       `json:"attribute_keys,omitempty"`
	Attributes    map[string]any `json:"attributes,omitempty"`
}

UserUpdatedPayload lists keys touched; values only for x-audit fields.

Directories

Path Synopsis
Package domainmock is a generated GoMock package.
Package domainmock is a generated GoMock package.

Jump to

Keyboard shortcuts

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