✨ feat(bdd): magic-link BDD scenarios + bcrypt overflow fix (ADR-0028 Phase A.5)
Adds 4 BDD scenarios covering the passwordless magic-link flow: - Happy path (request -> email arrives -> consume -> JWT) - Token cannot be consumed twice (single-use guarantee) - Missing token returns 400 - Unknown token returns 401 Implementation: - features/auth/magic_link.feature with the gherkin spec - pkg/bdd/steps/magic_link_steps.go: per-scenario unique recipient (`<scenario-key>-<8hex>@bdd.local`, ADR-0030), Mailpit-driven token extraction, regex parse of the consume URL - pkg/bdd/steps/scenario_state.go: 2 fields added (MagicLinkEmail, MagicLinkToken) - pkg/bdd/steps/steps.go: register 5 new step regexes Bug fix exposed by the BDD run: - pkg/user/api/magic_link_handler.go: passwordless-signup random password was 96 hex chars (48 bytes) which overflowed bcrypt's 72-byte input limit, breaking first-link signup. Reduced to 64 hex chars (32 bytes, 256 bits entropy). Test infra fix: - pkg/bdd/testserver/server.go: createTestConfig() builds the Config literal directly (no Viper defaults), so add explicit Email + MagicLink config so the From address is set when the handler sends via local Mailpit. Mistral wrote the feature file, magic_link_steps.go, scenario_state.go edit, and steps.go edit autonomously in a worktree workspace. Claude fixed the bcrypt overflow + the test-config gap exposed during verification. Most authoring by Mistral Vibe (mistral-vibe-cli-latest).
This commit is contained in:
@@ -815,6 +815,20 @@ func createTestConfig(port int, v2Enabled bool) *config.Config {
|
||||
JWT: config.JWTConfig{
|
||||
TTL: 24 * time.Hour,
|
||||
},
|
||||
// Email + MagicLink defaults so the magic-link BDD scenarios
|
||||
// (ADR-0028 Phase A.5) can send to local Mailpit. Without these
|
||||
// the literal Config skips Viper's SetDefault and From stays
|
||||
// empty — pkg/email then rejects the message.
|
||||
Email: config.EmailConfig{
|
||||
From: "noreply@bdd.local",
|
||||
SMTPHost: "localhost",
|
||||
SMTPPort: 1025,
|
||||
Timeout: 5 * time.Second,
|
||||
},
|
||||
MagicLink: config.MagicLinkConfig{
|
||||
TTL: 15 * time.Minute,
|
||||
BaseURL: "http://localhost:8080",
|
||||
},
|
||||
},
|
||||
API: config.APIConfig{
|
||||
V2Enabled: v2Enabled,
|
||||
|
||||
Reference in New Issue
Block a user