service

package
v0.1.0-alpha.13 Latest Latest
Warning

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

Go to latest
Published: Jun 26, 2026 License: AGPL-3.0 Imports: 17 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AuthAttemptService

type AuthAttemptService interface {
	// Create and store a new auth attempt.
	//
	// If input.SessionID is set, the existing session's verified checks are copied
	// into the attempt for step-up authentication against an existing session.
	//
	// If input.RequiredChecks are nil, the project's default required checks are used.
	//
	// errors: domain.ErrAuthAttemptInvalidRequest, domain.ErrInternal
	Create(ctx context.Context, input CreateAuthAttemptInput) (*domain.AuthAttempt, error)

	// GetByID retrieves an auth attempt including all factors and challenges by its ID.
	//
	// errors: domain.ErrAuthAttemptNotFound, domain.ErrInternal
	GetByID(ctx context.Context, projectID, attemptID string) (*domain.AuthAttempt, error)

	// IssueChallenge creates and returns a new challenge for the given check type.
	// An existing challenge of the same type will be overwritten.
	//
	// For passkey challenges, the user check must already be verified, so the user ID is known
	// for retrieving registered credentials.
	//
	// errors: domain.ErrAuthAttemptNotFound, domain.ErrAuthAttemptInvalidRequest, domain.ErrAuthAttemptInvalidState, domain.ErrAuthAttemptAlreadyCompleted, domain.ErrInternal
	IssueChallenge(ctx context.Context, input IssueChallengeInput) (*domain.AuthAttempt, error)

	// VerifyProof verifies the submitted proof against the challenge identified by ChallengeID.
	//
	// On success, it persists the verification and marks the attempt complete if all
	// required checks are now satisfied.
	//
	// On failure, it records the failed attempt for rate-limiting purposes.
	//
	// The ChallengeID must match the ID returned by IssueChallenge to prevent use of
	// stale proofs after a challenge is re-issued.
	//
	// errors: domain.ErrAuthAttemptNotFound, domain.ErrAuthAttemptStaleChallenge, domain.ErrAuthAttemptInvalidRequest, domain.ErrAuthAttemptProofRejected, domain.ErrAuthAttemptInvalidState, domain.ErrAuthAttemptAlreadyCompleted, domain.ErrInternal
	VerifyProof(ctx context.Context, input VerifyProofInput) (*domain.AuthAttempt, error)

	// Handoff mints a single-use handoff token for a completed attempt.
	//
	// The client exchanges the token at POST /sessions/exchange to create
	// a new session or add factors to an existing session.
	//
	// The attempt must be in a completed state and not expired.
	//
	// errors: domain.ErrAuthAttemptNotFound, domain.ErrAuthAttemptInvalidState, domain.ErrAuthAttemptNotCompleted, domain.ErrInternal
	Handoff(ctx context.Context, input HandoffInput) (*domain.AuthAttempt, error)

	// RegisterCreatedUser registers a newly-created user's ID as a verified user
	// factor directly on the auth attempt, bypassing the challenge/proof cycle.
	// Used after on_success: create_user and passkey registration so the session
	// receives user_id after exchange.
	RegisterCreatedUser(ctx context.Context, projectID, attemptID, userID string) error
}

AuthAttemptService is the primary port for auth attempt operations. REST handler, OIDC server, SAML server and the flow engine all depend on this interface.

func NewAuthAttemptService

func NewAuthAttemptService(
	pool database.Pool,
	attempts domain.AuthAttemptRepository,
	sessions SessionResolver,
	projects ProjectLoader,
	users UserLookup,
	userPasswords UserPasswords,
	userPasskeys UserPasskeys,
	passwordVerifier crypto.HashVerifier,
) AuthAttemptService

type BeginRegistrationInput

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

BeginRegistrationInput carries the parameters needed to start a passkey registration ceremony.

type BeginRegistrationOutput

type BeginRegistrationOutput struct {
	RegistrationID string
	Options        []byte // PublicKeyCredentialCreationOptions JSON
}

BeginRegistrationOutput is returned by PasskeyRegistrationService.Begin.

type BuiltinSchemaProvider

type BuiltinSchemaProvider interface {
	GetBuiltinSchema(uri string) (*jsonschema.Schema, error)
	LatestSchemaURI(kind domain.KnownSchemaKind) (string, error)
}

type Challenge

type Challenge interface {
	ChallengeCheckType() domain.AuthCheckType
}

Challenge is implemented by each check-type-specific challenge value.

type CreateAuthAttemptInput

type CreateAuthAttemptInput struct {
	ProjectID string
	// SessionID is set for step-up auth against an existing session.
	SessionID *string
	// RequiredChecks overrides the project's default policy.
	// Used by the OIDC adapter (acr_values) and flow engine.
	// If nil the project's DefaultRequiredChecks are used.
	RequiredChecks []domain.AuthCheckType
}

type CreateSchemaByURLInput

type CreateSchemaByURLInput struct {
	ProjectID string
	TeamID    string
	URL       url.URL
}

type CreateSchemaInput

type CreateSchemaInput struct {
	ProjectID string
	TeamID    string
	Schema    []byte
}

type CreateSessionInput

type CreateSessionInput struct {
	ProjectID string
	UserAgent *domain.UserAgent
}

type CreateTeamInput

type CreateTeamInput struct {
	ProjectID string
}

type CreateUserAction

type CreateUserAction struct {
	CreateUserInput

	CreateUser *domain.CreateUser
	// contains filtered or unexported fields
}

func NewCreateUserAction

func NewCreateUserAction(input CreateUserInput, userRepo domain.UserRepository, schemaRepo domain.JSONSchemaRepository) *CreateUserAction

func (*CreateUserAction) Apply

func (*CreateUserAction) Prepare

type CreateUserInput

type CreateUserInput struct {
	ProjectID string
	TeamID    *string
	User      map[string]any
}

type DeleteSessionInput

type DeleteSessionInput struct {
	ProjectID string
	SessionID string
}

type ExchangeInput

type ExchangeInput struct {
	ProjectID      string
	HandoffToken   string
	IdempotencyKey *string
	// TTL is optional; nil uses the configured default.
	TTL *time.Duration
}

type FinishRegistrationInput

type FinishRegistrationInput struct {
	ProjectID      string
	RegistrationID string
	Attestation    []byte
}

FinishRegistrationInput carries the parameters needed to complete a passkey registration.

type FlowAuthAttemptAdapter

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

FlowAuthAttemptAdapter adapts the broad AuthAttemptService surface to the narrow domain.FlowAuthAttemptService the flow state machine consumes. Each Submit* collapses the underlying issue-then-verify cycle so the state machine never deals with challenge IDs.

func NewFlowAuthAttemptAdapter

func NewFlowAuthAttemptAdapter(attempts AuthAttemptService) *FlowAuthAttemptAdapter

func (*FlowAuthAttemptAdapter) Handoff

func (*FlowAuthAttemptAdapter) IssuePasskeyChallenge

IssuePasskeyChallenge issues a WebAuthn assertion challenge and returns its id plus the PublicKeyCredentialRequestOptions the browser hands to navigator.credentials.get(). Unlike the other Submit* methods it does not verify — the assertion arrives on a later submit (see [SubmitPasskey]).

func (*FlowAuthAttemptAdapter) RegisterCreatedUser

RegisterCreatedUser registers a newly-created user's ID as a verified user factor on the auth attempt. Delegates to the service layer which issues a synthetic challenge and immediately marks it succeeded.

func (*FlowAuthAttemptAdapter) Start

func (*FlowAuthAttemptAdapter) SubmitIdentifier

func (*FlowAuthAttemptAdapter) SubmitPasskey

SubmitPasskey verifies the assertion against the challenge identified by ChallengeID and returns the authenticated user id (resolved from the assertion for a discoverable login, or the already-pinned user otherwise).

func (*FlowAuthAttemptAdapter) SubmitPassword

type FlowCreateUserForPasskeyHandler

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

func NewFlowCreateUserForPasskeyHandler

func NewFlowCreateUserForPasskeyHandler(
	users flowUserWriter,
) *FlowCreateUserForPasskeyHandler

func (*FlowCreateUserForPasskeyHandler) CreateProvisionalUser

func (h *FlowCreateUserForPasskeyHandler) CreateProvisionalUser(ctx context.Context, client database.QueryExecutor, userID string, state *domain.FlowState, resolved domain.FlowResolvedFields) error

CreateProvisionalUser creates a passwordless user with a pre-assigned ID from state.CollectedData. If the user already exists (UniqueError from a prior on_success handler), the call succeeds silently. Intended to be called within the passkey verify phase, sharing the same client transaction as the passkey save for atomicity.

type FlowCreateUserWithPasswordHandler

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

FlowCreateUserWithPasswordHandler implements the `create_user` on_success: persist a new user from validated identifier + password fields.

func NewFlowCreateUserHandler

func NewFlowCreateUserHandler(
	userRepo domain.UserRepository,
	passwordRepo domain.UserPasswordRepository,
	hasher crypto.Hasher,
	userService *UserService,
	schemaRepo domain.JSONSchemaRepository,
) *FlowCreateUserWithPasswordHandler

func (*FlowCreateUserWithPasswordHandler) Handle

type FlowDefinitionRequest

type FlowDefinitionRequest struct {
	FlowDefinitionID string
	ProjectID        string
	Name             string
	Status           string
	SchemaVersion    string // todo (grvijayan): currently empty as the request does not contain schema version
	FlowSchemaURI    string // todo (grvijayan): schema_version (semver) stored in the db vs schema_uri needed for validation
	UserSchema       string
	Purposes         map[string]string
	Audience         domain.FlowDefinitionAudience
	Steps            []domain.FlowDefinitionStep
}

type FlowDefinitionService

type FlowDefinitionService interface {
	Create(ctx context.Context, req FlowDefinitionRequest) (*domain.FlowDefinition, error)
	Update(ctx context.Context, req FlowDefinitionRequest) (*domain.FlowDefinition, error)
	Get(ctx context.Context, projectID, id string) (*domain.FlowDefinition, error)
	List(ctx context.Context, req ListFlowDefinitionsRequest) ([]*domain.FlowDefinition, error)
	Delete(ctx context.Context, projectID string, id string) error
}

func NewFlowDefinitionService

func NewFlowDefinitionService(
	db database.Pool,
	schemaGetter SchemaGetter,
	schemaProvider BuiltinSchemaProvider,
	flowDefinitionValidatorFn flowDefinitionValidatorFunc,
	flowDefinitionRepo domain.FlowDefinitionRepository,
) FlowDefinitionService

type FlowPasskeyRegistrationAdapter

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

FlowPasskeyRegistrationAdapter wraps *PasskeyRegistrationService and implements the narrow domain.FlowPasskeyRegistrationService interface consumed by the flow engine. It translates flow input/output types to the canonical service API.

func NewFlowPasskeyRegistrationAdapter

func NewFlowPasskeyRegistrationAdapter(svc *PasskeyRegistrationService) *FlowPasskeyRegistrationAdapter

NewFlowPasskeyRegistrationAdapter returns a new adapter wrapping svc.

func (*FlowPasskeyRegistrationAdapter) IssuePasskeyRegistrationChallenge

IssuePasskeyRegistrationChallenge implements domain.FlowPasskeyRegistrationService.

func (*FlowPasskeyRegistrationAdapter) SubmitPasskeyRegistration

SubmitPasskeyRegistration implements domain.FlowPasskeyRegistrationService. client is the flow engine's DB transaction; the passkey write shares that transaction so it is atomic with user creation.

type FlowService

type FlowService interface {
	// Resolve returns the [domain.FlowDefinition] to run. Direct lookup
	// when Name is set; audience match otherwise.
	Resolve(ctx context.Context, req ResolveFlowRequest) (*domain.FlowDefinition, error)
	// Start mints a fresh flow on the resolved definition.
	Start(ctx context.Context, req StartFlowRequest) (domain.FlowStepResult, error)
	// Submit advances the state machine. Re-fetches the definition
	// from FlowState.DefinitionID.
	Submit(ctx context.Context, req SubmitFlowRequest) (domain.FlowStepResult, error)
	// GetStep re-emits the current step without advancing.
	GetStep(ctx context.Context, req GetFlowStepRequest) (domain.FlowStepResult, error)
}

FlowService is the flow engine's use-case surface. The API handler depends only on this interface.

func NewFlowService

func NewFlowService(
	pool database.Pool,
	flowDefs domain.FlowDefinitionRepository,
	stateMachine domain.FlowStateMachine,
	ids idgen.Generator,
) FlowService

type GetFlowStepRequest

type GetFlowStepRequest struct {
	State *domain.FlowState
}

type GetMyUserInput

type GetMyUserInput struct {
	SessionToken string
}

type GetSessionInput

type GetSessionInput struct {
	ProjectID string
	SessionID string
}

type GetUserInput

type GetUserInput struct {
	ProjectID string
	TeamID    *string
	UserID    string
}

type HandoffInput

type HandoffInput struct {
	ProjectID      string
	AttemptID      string
	IdempotencyKey *string
}

type IssueChallengeInput

type IssueChallengeInput struct {
	ProjectID string
	AttemptID string
	// Challenge is a discriminated union — use one of the Challenge* types below.
	Challenge Challenge
}

type LazyUserAction

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

LazyUserAction allows for lazy initialization of a user-action. It forwards the `Prepare` and `Apply` methods to the generated action. The UserAction is only right before it is used in those functions.

This action can be wrapped around an action when the wrapped action requires an output of a previous action. It can then use a clojure to get the data from the other action.

func NewLazyUserAction

func NewLazyUserAction(factory UserActionFactory) *LazyUserAction

func (*LazyUserAction) Action

func (*LazyUserAction) Apply

func (*LazyUserAction) Prepare

func (o *LazyUserAction) Prepare(ctx context.Context, db database.QueryExecutor) (err error)

type ListFlowDefinitionsRequest

type ListFlowDefinitionsRequest struct {
	ProjectID string
	Purpose   string
	Limit     int
	PageToken string
}

type ListSessionInput

type ListSessionInput struct {
	ProjectID string
}

type PasskeyChallenge

type PasskeyChallenge struct {
	UserVerification string
	RPID             string
	RPOrigins        []url.URL
}

PasskeyChallenge carries the raw WebAuthn assertion response bytes.

func (PasskeyChallenge) ChallengeCheckType

func (PasskeyChallenge) ChallengeCheckType() domain.AuthCheckType

type PasskeyProof

type PasskeyProof struct {
	AssertionResponse []byte
}

PasskeyProof carries the raw WebAuthn assertion response bytes.

type PasskeyRegistrationService

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

PasskeyRegistrationService is the authoritative service for the passkey registration ceremony. It exposes [Begin] and [Finish] for direct callers and is wrapped by FlowPasskeyRegistrationAdapter for the flow engine.

func (*PasskeyRegistrationService) Begin

Begin starts a passkey registration ceremony for the given user and relying-party parameters. It mints a challenge, persists it, and returns the creation options for the browser's navigator.credentials.create() call.

func (*PasskeyRegistrationService) Finish

Finish verifies the attestation against the stored challenge and persists the new credential. The user identity is authoritative from the stored challenge record. Rejection surfaces as domain.ErrAuthAttemptProofRejected.

func (*PasskeyRegistrationService) FinishWith

FinishWith is like [Finish] but uses the given QueryExecutor instead of the pool. Used by FlowPasskeyRegistrationAdapter to run the credential write inside the flow engine's transaction so the passkey save is atomic with user creation.

type PasswordChallenge

type PasswordChallenge struct{}

PasswordChallenge carries the plaintext password for verification.

func (PasswordChallenge) ChallengeCheckType

func (PasswordChallenge) ChallengeCheckType() domain.AuthCheckType

type PasswordProof

type PasswordProof struct {
	Password string
}

PasswordProof carries the plaintext password for verification.

type ProjectLoader

type ProjectLoader interface {
	Get(ctx context.Context, client database.QueryExecutor, id string) (*domain.Project, error)
}

type ProjectService

type ProjectService interface {
	// Create generates a new project with server-minted secrets and persists it.
	// Returns the stored project including timestamps.
	Create(ctx context.Context, previewOrigins []string) (*domain.Project, error)

	// Get retrieves a project by ID.
	// Returns [database.NoRowFoundError] when no project with the given ID exists.
	Get(ctx context.Context, id string) (*domain.Project, error)
}

ProjectService is the project use-case surface.

func NewProjectService

func NewProjectService(
	pool database.Pool,
	repo domain.ProjectRepository,
	schemaRepo domain.JSONSchemaRepository,
	flowDefinitionRepo domain.FlowDefinitionRepository,
	tokenGenerator domain.TokenGenerator,
	serverURL string,
	schemaValidator *domain.SchemaValidator,
) ProjectService

NewProjectService returns a ProjectService backed by the given repository.

type Proof

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

Proof is implemented by each check-type-specific proof value.

type ResolveFlowHint

type ResolveFlowHint struct {
	AppID        *string
	TeamID       *string
	UserSchemaID *string
}

type ResolveFlowRequest

type ResolveFlowRequest struct {
	ProjectID     string
	Purpose       domain.FlowDefinitionPurpose
	Name          *string // direct-lookup slug
	SchemaVersion *string // nil = latest active
	AuthRequestID *string
	// Hint is plumbed through but not yet honored — see TODO on resolveByAudience.
	Hint ResolveFlowHint
}

type SchemaGetter

type SchemaGetter interface {
	GetSchema(ctx context.Context, projectID string, teamID string, schemaID string) (*domain.JSONSchema, error)
}

type SchemaService

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

func NewSchemaService

func NewSchemaService(
	pool database.Pool,
	schemaRepo domain.JSONSchemaRepository,
	schemaResolver *domain.JSONSchemaResolver,
	schemaValidator *domain.SchemaValidator,
) *SchemaService

func (*SchemaService) CreateSchema

func (s *SchemaService) CreateSchema(ctx context.Context, input CreateSchemaInput) (_ *domain.JSONSchema, err error)

func (*SchemaService) CreateSchemaByUrl

func (s *SchemaService) CreateSchemaByUrl(ctx context.Context, input CreateSchemaByURLInput) (*domain.JSONSchema, error)

func (*SchemaService) GetSchema

func (s *SchemaService) GetSchema(ctx context.Context, projectID string, teamID string, schemaID string) (*domain.JSONSchema, error)

type SessionConfig

type SessionConfig struct {
	DefaultTTL time.Duration `mapstructure:"default_ttl"`
	MaxTTL     time.Duration `mapstructure:"max_ttl"`
}

SessionConfig holds server-wide session TTL settings for exchange.

func (SessionConfig) Validate

func (c SessionConfig) Validate() error

Validate checks session TTL configuration at startup.

type SessionResolver

type SessionResolver interface {
	Get(ctx context.Context, q database.QueryExecutor, projectID, sessionID string) (*domain.Session, error)
}

type SessionService

type SessionService interface {
	Create(ctx context.Context, input CreateSessionInput) (*domain.Session, error)
	Exchange(ctx context.Context, input ExchangeInput) (*domain.Session, error)
	Get(ctx context.Context, input GetSessionInput) (*domain.Session, error)
	List(ctx context.Context, input ListSessionInput) ([]*domain.Session, error)
	Delete(ctx context.Context, input DeleteSessionInput) error
}

func NewSessionService

func NewSessionService(pool database.Pool, repo domain.SessionRepository, cfg SessionConfig) SessionService

type SetPasswordInput

type SetPasswordInput struct {
	ProjectID                string
	UserID                   string
	Password                 string
	IsPasswordChangeRequired bool
}

type SetPasswordUserAction

type SetPasswordUserAction struct {
	SetPasswordInput
	// contains filtered or unexported fields
}

func NewSetUserPasswordAction

func NewSetUserPasswordAction(input SetPasswordInput, hasher crypto.Hasher, passwordRepo domain.UserPasswordRepository) *SetPasswordUserAction

func (*SetPasswordUserAction) Apply

func (*SetPasswordUserAction) Prepare

type StartFlowRequest

type StartFlowRequest struct {
	Definition    *domain.FlowDefinition
	Purpose       domain.FlowDefinitionPurpose
	RedirectURI   *string
	AuthRequestID *string
	SessionID     *string
}

type SubmitFlowRequest

type SubmitFlowRequest struct {
	State         *domain.FlowState
	Action        string
	Fields        map[string]any
	GateProofs    map[string]string
	SSOProviderID *string
	// ChallengeResponse carries the client's answer to a pending ceremony
	// (e.g. a passkey assertion). Nil unless the step issued a challenge.
	ChallengeResponse *domain.FlowChallengeResponse
	// PasskeyRP carries the WebAuthn relying-party params derived from the
	// request, needed when issuing a passkey challenge.
	PasskeyRP *domain.FlowPasskeyRP
}

type TeamService

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

func NewTeamService

func NewTeamService(
	pool database.Pool,
	teamRepo domain.TeamRepository,
) *TeamService

func (*TeamService) CreateTeam

func (s *TeamService) CreateTeam(ctx context.Context, input CreateTeamInput) (team *domain.Team, err error)

func (*TeamService) GetTeam

func (s *TeamService) GetTeam(ctx context.Context, projectID string, teamID string) (*domain.Team, error)

type UserAction

type UserAction interface {
	Prepare(ctx context.Context, db database.QueryExecutor) error
	Apply(ctx context.Context, db database.QueryExecutor) error
}

type UserActionFactory

type UserActionFactory = func(ctx context.Context, db database.QueryExecutor) (UserAction, error)

type UserChallenge

type UserChallenge struct{}

UserChallenge identifies the user by login name (email, username, phone).

func (UserChallenge) ChallengeCheckType

func (UserChallenge) ChallengeCheckType() domain.AuthCheckType

type UserLookup

type UserLookup interface {
	Get(ctx context.Context, client database.QueryExecutor, opts ...database.QueryOption) (*domain.User, error)
	ProjectIDCondition(projectID string) database.Condition
	IDCondition(id string) database.Condition
	AttributesCondition(attributes []domain.Attribute) database.Condition
}

type UserPasskeys

type UserPasskeys interface {
	Get(ctx context.Context, client database.QueryExecutor, opts ...database.QueryOption) (*domain.UserPasskey, error)
	List(ctx context.Context, client database.QueryExecutor, opts ...database.QueryOption) ([]*domain.UserPasskey, error)
	Update(ctx context.Context, client database.QueryExecutor, condition database.Condition, changes ...database.Change) error
	// contains filtered or unexported methods
}

type UserPasswords

type UserPasswords interface {
	Get(ctx context.Context, client database.QueryExecutor, opts ...database.QueryOption) (*domain.UserPassword, error)
	UserIDCondition(userID string) database.Condition
	ProjectIDCondition(pid string) database.Condition
}

type UserProof

type UserProof struct {
	AttributeName string
	LoginName     string
}

UserProof identifies the user by login name (email, username, phone).

type UserService

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

func NewUserService

func NewUserService(
	pool database.Pool,
	userRepo domain.UserRepository,
	passwordRepo domain.UserPasswordRepository,
	schemaRepo domain.JSONSchemaRepository,
	hasher crypto.Hasher,
	tokenVerifier domain.TokenVerifier,
) *UserService

func (*UserService) ApplyActions

func (s *UserService) ApplyActions(ctx context.Context, actions ...UserAction) (err error)

func (*UserService) CreateUser

func (s *UserService) CreateUser(ctx context.Context, input CreateUserInput) (_ map[string]any, err error)

func (*UserService) GetMyUser

func (s *UserService) GetMyUser(ctx context.Context, input GetMyUserInput) ([]byte, error)

func (*UserService) GetUserByID

func (s *UserService) GetUserByID(ctx context.Context, input GetUserInput) (map[string]any, error)

func (*UserService) SetPassword

func (s *UserService) SetPassword(ctx context.Context, input SetPasswordInput) (err error)

type VerifyProofInput

type VerifyProofInput struct {
	ProjectID string
	AttemptID string
	// ChallengeID must match the ID returned by IssueChallenge.
	// Prevents use of stale proofs after a challenge is re-issued.
	ChallengeID string
	// Proof is a discriminated union — use one of the Proof* types below.
	Proof Proof
}

Directories

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

Jump to

Keyboard shortcuts

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