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).
35 lines
1.3 KiB
Gherkin
35 lines
1.3 KiB
Gherkin
@magic-link
|
|
Feature: Passwordless magic-link sign-in
|
|
As a user without a password
|
|
I want to sign in by clicking a link sent to my email
|
|
So I can access the system without typing a password
|
|
|
|
Scenario: Happy path - request, receive, consume
|
|
Given the server is running
|
|
And I have an email address for this scenario
|
|
When I request a magic link for my email
|
|
Then I should receive an email with subject "Your sign-in link"
|
|
And the email contains a magic link token
|
|
When I consume the magic link token
|
|
Then the consume should succeed and return a JWT
|
|
|
|
Scenario: Token cannot be consumed twice
|
|
Given the server is running
|
|
And I have an email address for this scenario
|
|
When I request a magic link for my email
|
|
And the email contains a magic link token
|
|
When I consume the magic link token
|
|
Then the consume should succeed and return a JWT
|
|
When I consume the magic link token
|
|
Then the consume should fail with 401
|
|
|
|
Scenario: Missing token returns 400
|
|
Given the server is running
|
|
When I consume an empty magic link token
|
|
Then the response should have status 400
|
|
|
|
Scenario: Unknown token returns 401
|
|
Given the server is running
|
|
When I consume an unknown magic link token
|
|
Then the consume should fail with 401
|