credboundtest

package
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Aug 24, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

Documentation

Overview

Package credboundtest provides deterministic test doubles and constructors for host services that integrate github.com/deepteams/credbound.

NewManager builds a fully wired *credbound.Manager backed by the in-memory store, a fast fake password hasher, a deterministic clock and random source, and TOTP/passkey fakes whose enrollment and verification flows succeed with fixed inputs. Use it in host-service tests to exercise real Credbound flows — bootstrap, sign-in, second factors, step-up, PATs — without Argon2 latency, real WebAuthn ceremonies, or wall-clock coupling.

Nothing in this package is safe for production use. Passwords stores a recoverable marker instead of a real hash, TOTP accepts the fixed code ValidTOTPCode, AAL2 mints an assurance level that only a real second factor may produce in production, and the deterministic random source is predictable by design. Import it from _test files only.

Index

Constants

View Source
const (
	// BootstrapEmail is the primary address of the bootstrapped root user.
	BootstrapEmail = "root@example.com"
	// BootstrapPassword is the password of the bootstrapped root user.
	BootstrapPassword = "correct horse battery staple"
	// BootstrapDisplayName is the display name of the bootstrapped root user.
	BootstrapDisplayName = "Root"
	// BootstrapWorkspaceName is the name of the bootstrapped workspace.
	BootstrapWorkspaceName = "Main"
)

Fixed identity used by Bootstrap. The password satisfies the default minimum length of twelve characters.

View Source
const ValidPasskeyResponse = "valid"

ValidPasskeyResponse is the only client response the Passkeys fake accepts; pass []byte(ValidPasskeyResponse) to FinishPasskeyRegistration and FinishPasskeyAuthentication. Any other response fails the ceremony.

View Source
const ValidTOTPCode = "123456"

ValidTOTPCode is the only code the TOTP fake accepts. Any other input is rejected, so tests can exercise both success and failure paths.

Variables

View Source
var DefaultStartTime = time.Date(2026, 1, 1, 12, 0, 0, 0, time.UTC)

DefaultStartTime is the initial instant of the deterministic clock used by NewManager when no WithClock option is given. Tests can rely on it when asserting timestamps or constructing an AAL2 step-up for a manager whose clock was never advanced.

Functions

func AAL2

AAL2 fabricates an interactive AAL2 authentication for userID as of at, as if the user had just verified a TOTP code. Use it to satisfy step-up checks (for example before CreatePAT) without running a second-factor ceremony in every test.

This helper is test-only by definition: production code must never construct an AAL2 authentication itself — only VerifyTOTP, a passkey, or SSO reauthentication may produce one.

func Bootstrap

Bootstrap creates the first user and workspace of the instance with the fixed Bootstrap* identity and returns the resulting authentication and workspace. It fails the test on error, including the credbound.ErrConflict returned by a second call on the same manager.

func NewDeterministicRandom

func NewDeterministicRandom() io.Reader

NewDeterministicRandom returns an io.Reader emitting a fixed byte sequence, so identifiers and tokens are reproducible across runs. It is the default random source of NewManager and is, by design, not cryptographically secure; never use it outside tests.

func NewManager

func NewManager(t testing.TB, opts ...Option) *credbound.Manager

NewManager builds a *credbound.Manager wired for tests: memory.New() store, the fast Passwords hasher, the TOTP and Passkeys fakes, fixed secret key and peppers, a Clock frozen at DefaultStartTime, and a deterministic random source. Options override individual parts. Construction failures fail the test immediately.

The resulting manager must never back a production service: every secret it derives is fixed and every credential it accepts is predictable.

Types

type Clock

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

Clock is a manually driven time source for deterministic tests. It only moves when Advance or Set is called, so freshness windows such as Config.StepUpMaxAge and TOTP steps are fully under test control. It is safe for concurrent use.

func NewClock

func NewClock(start time.Time) *Clock

NewClock returns a Clock frozen at start.

func (*Clock) Advance

func (c *Clock) Advance(d time.Duration)

Advance moves the clock forward by d. Use it to cross freshness boundaries, for example Advance(30*time.Second) between two TOTP verifications so the second code lands on a new step, or Advance past Config.StepUpMaxAge to expire a step-up.

func (*Clock) Now

func (c *Clock) Now() time.Time

Now returns the current instant of the clock. Pass the method value (clock.Now) as credbound.Config.Clock.

func (*Clock) Set

func (c *Clock) Set(at time.Time)

Set moves the clock to the absolute instant at.

type DiscoverablePasskeys

type DiscoverablePasskeys struct{ Passkeys }

DiscoverablePasskeys extends the Passkeys fake with usernameless sign-in over discoverable credentials. Install it explicitly when a test exercises BeginDiscoverablePasskeyAuthentication, since the plain Passkeys fake — like a provider that does not implement the optional port — makes those flows return credbound.ErrNotSupported:

manager := credboundtest.NewManager(t, credboundtest.WithConfig(func(cfg *credbound.Config) {
	cfg.Passkeys = credboundtest.DiscoverablePasskeys{}
}))

FinishDiscoverableAuthentication resolves the fixed credential through the lookup, so the manager's account resolution and its user-handle check are exercised rather than bypassed.

func (DiscoverablePasskeys) BeginDiscoverableAuthentication

func (DiscoverablePasskeys) BeginDiscoverableAuthentication(context.Context) (json.RawMessage, []byte, error)

BeginDiscoverableAuthentication returns fixed request options and the session that FinishDiscoverableAuthentication expects back.

func (DiscoverablePasskeys) FinishDiscoverableAuthentication

func (DiscoverablePasskeys) FinishDiscoverableAuthentication(ctx context.Context, session, response []byte, lookup credbound.PasskeyUserLookup) (credentialID, credentialJSON []byte, err error)

FinishDiscoverableAuthentication validates the session issued by BeginDiscoverableAuthentication, accepts exactly []byte(ValidPasskeyResponse), and resolves the fixed credential through lookup, surfacing the ErrNotFound of an unknown credential.

type Option

type Option func(*settings)

Option customizes the manager built by NewManager.

func WithClock

func WithClock(clock *Clock) Option

WithClock replaces the manager's time source. Keep a reference to the clock to advance time from the test.

func WithConfig

func WithConfig(mutate func(*credbound.Config)) Option

WithConfig applies an arbitrary mutation to the assembled credbound.Config just before New runs, covering everything without a dedicated option — Config.SignUp, Config.OAuth, Config.SessionTTL, TTLs, and so on:

manager := credboundtest.NewManager(t, credboundtest.WithConfig(func(cfg *credbound.Config) {
	cfg.SignUp = &credbound.SignUpConfig{}
}))

Mutators run in registration order, after the other options are applied.

func WithEventListeners

func WithEventListeners(listeners ...credbound.EventListener) Option

WithEventListeners registers post-commit event listeners, mirroring credbound.Config.EventListeners.

func WithPasswordPolicy

func WithPasswordPolicy(policy credbound.PasswordPolicy) Option

WithPasswordPolicy installs an additional password vetting policy, mirroring credbound.Config.PasswordPolicy.

func WithRandom

func WithRandom(random io.Reader) Option

WithRandom replaces the deterministic random source, for example with crypto/rand.Reader when a test needs unpredictable tokens.

func WithSSOProviders

func WithSSOProviders(providers ...credbound.SSOProvider) Option

WithSSOProviders registers SSO providers, mirroring credbound.Config.SSOProviders.

func WithStore

func WithStore(store credbound.Store) Option

WithStore replaces the default in-memory store, for example with a migration-applied PostgreSQL store to test against real persistence.

func WithTransactionHooks

func WithTransactionHooks(hooks ...credbound.TransactionHook) Option

WithTransactionHooks registers transaction hooks, mirroring credbound.Config.TransactionHooks.

type Passkeys

type Passkeys struct{}

Passkeys is a fake credbound.PasskeyProvider for tests. Both ceremonies return fixed JSON options and an opaque session, and both Finish methods accept exactly []byte(ValidPasskeyResponse) as the client response. The registered credential is a fixed JSON document whose authenticator counter increments on authentication, mirroring a real WebAuthn provider closely enough for the manager's encrypt-at-rest and ceremony plumbing to be exercised end to end.

func (Passkeys) BeginAuthentication

func (Passkeys) BeginAuthentication(_ context.Context, user credbound.PasskeyUser) (json.RawMessage, []byte, error)

BeginAuthentication drains the user's stored credentials — surfacing any decryption error the manager reports — and returns fixed request options with the session that FinishAuthentication expects back.

func (Passkeys) BeginDecoyAuthentication

func (Passkeys) BeginDecoyAuthentication(_ context.Context, _ []byte) (json.RawMessage, []byte, error)

BeginDecoyAuthentication returns a fixed challenge for an address with no passkey, so the manager's answer never reveals whether an account has one.

func (Passkeys) BeginRegistration

BeginRegistration returns fixed creation options and the registration session that FinishRegistration expects back.

func (Passkeys) FinishAuthentication

func (Passkeys) FinishAuthentication(_ context.Context, _ credbound.PasskeyUser, session, response []byte) (credentialID, credentialJSON []byte, err error)

FinishAuthentication validates the session issued by BeginAuthentication and accepts exactly []byte(ValidPasskeyResponse), returning the fixed credential with its counter advanced.

func (Passkeys) FinishRegistration

func (Passkeys) FinishRegistration(_ context.Context, _ credbound.PasskeyUser, session, response []byte) (credentialID, credentialJSON []byte, err error)

FinishRegistration validates the session issued by BeginRegistration and accepts exactly []byte(ValidPasskeyResponse), returning a fixed credential.

type Passwords

type Passwords struct{}

Passwords is a fast fake credbound.PasswordHasher for tests. Hash returns a recoverable marker ("credboundtest$" plus the password) instead of a real key derivation, so building a manager and authenticating cost nothing.

It must never be used in production: it performs no salting, no stretching, and stores the password in clear inside the "hash".

func (Passwords) Hash

func (Passwords) Hash(password string) (string, error)

Hash returns a deterministic marker embedding the password.

func (Passwords) Verify

func (Passwords) Verify(password, encoded string) (match bool, rehash bool, err error)

Verify reports whether encoded is the marker produced by Hash for password. It never requests a rehash.

type TOTP

type TOTP struct{}

TOTP is a fake credbound.TOTPProvider for tests. Generate returns a fixed secret and otpauth URI, and Validate accepts exactly ValidTOTPCode ("123456" is always valid; everything else never is).

Validate reports the real 30-second step for the given instant, so the manager's replay protection behaves as in production: verifying ValidTOTPCode twice without advancing the Clock by at least 30 seconds fails the second attempt with credbound.ErrInvalidCredentials.

func (TOTP) Generate

func (TOTP) Generate(accountName string) (secret string, uri string, err error)

Generate returns a fixed secret and a syntactically valid otpauth URI for the account.

func (TOTP) Validate

func (TOTP) Validate(code, _ string, at time.Time) (step int64, valid bool)

Validate accepts exactly ValidTOTPCode and reports the 30-second step of at.

Jump to

Keyboard shortcuts

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