Files
dance-lessons-coach/.vibe/skills/product-owner-assistant/wiki/user-story-workflow.md
Gabriel Radureau 52065c9cf3
Some checks failed
CI/CD Pipeline / Build Docker Cache (push) Successful in 10s
CI/CD Pipeline / CI Pipeline (push) Failing after 13s
refactor: convert all DanceLessonsCoach mentions to kebab-case
2026-04-07 19:11:39 +02:00

12 KiB

User Story Implementation Workflow

🎯 Overview

This document describes the standardized workflow for implementing user stories in the dance-lessons-coach project. The workflow follows a test-driven development approach with clear phases and deliverables.

🔄 Workflow Diagram

graph TD
    A[Product Owner Creates User Story] --> B[Create BDD Test Scenario]
    B --> C[BDD Test Fails (Red Phase)]
    C --> D[Implement Service with Mocks]
    D --> E[Write Unit Tests]
    E --> F[Add Real Persistence Layer]
    F --> G[BDD Test Passes (Green Phase)]
    G --> H[Update OpenAPI Documentation]
    H --> I[CI/CD Pipeline Validation]
    I --> J[Product Owner Review]
    J --> K[Ready for Deployment]

📋 Detailed Workflow Steps

Step 1: User Story Creation (Product Owner)

Responsibility: Product Owner Output: Gitea issue with clear acceptance criteria

## User Story: [Title]

**As a** [role]
**I want to** [feature]
**So that** [benefit]

### Acceptance Criteria
- [ ] Criteria 1
- [ ] Criteria 2
- [ ] Criteria 3

### Technical Notes
- API endpoint: `POST /api/v1/[resource]`
- Database: Requires `users` table
- Security: JWT authentication required

### Priority
- High/Medium/Low

### Estimated Effort
- Story Points: [1-8]
- Complexity: [Low/Medium/High]

Step 2: Create BDD Test Scenario

Responsibility: Developer Output: Failing BDD test in .feature file

# features/[feature].feature
Feature: [Feature Name]
  [Feature description]

  @wip @user-management
  Scenario: [Scenario Name]
    Given [precondition]
    When [action]
    Then [expected result]
    And [additional verification]

Example:

# features/user-persistence.feature
Feature: User Persistence
  Users should be able to register and persist their data

  @wip @user-management
  Scenario: User registration with persistence
    Given the server is running with database
    When I register a new user with username "testuser" and password "secure123"
    Then the response should contain a user ID
    And the user should be persisted in the database
    And I should be able to login with the same credentials

Step 3: BDD Test Fails (Red Phase)

Responsibility: Developer Output: Failing test execution

# Run BDD tests
cd /Users/gabrielradureau/Work/Vibe/dance-lessons-coach
godog features/user-persistence.feature

# Expected: Test fails with "pending" or "undefined" steps

Step 4: Implement Service with Mocks

Responsibility: Developer Output: Service implementation with mock persistence

// pkg/user/service.go
package user

type UserService struct {
    repo UserRepository
}

func NewUserService(repo UserRepository) *UserService {
    return &UserService{repo: repo}
}

func (s *UserService) Register(ctx context.Context, username, password string) (*User, error) {
    // Validate input
    if err := validateUsername(username); err != nil {
        return nil, err
    }
    
    // Hash password
    hashedPassword, err := hashPassword(password)
    if err != nil {
        return nil, err
    }
    
    // Create user
    user := &User{
        Username:     username,
        PasswordHash: hashedPassword,
    }
    
    // Persist user (using interface - mockable)
    if err := s.repo.CreateUser(user); err != nil {
        return nil, err
    }
    
    return user, nil
}

Step 5: Write Unit Tests

Responsibility: Developer Output: Passing unit tests with mock repository

// pkg/user/service_test.go
package user

import (
    "context"
    "testing"
    "github.com/stretchr/testify/assert"
    "github.com/stretchr/testify/mock"
)

type MockUserRepository struct {
    mock.Mock
}

func (m *MockUserRepository) CreateUser(user *User) error {
    args := m.Called(user)
    return args.Error(0)
}

func TestUserService_Register(t *testing.T) {
    // Setup
    mockRepo := new(MockUserRepository)
    service := NewUserService(mockRepo)
    
    // Expectations
    mockRepo.On("CreateUser", mock.AnythingOfType("*user.User")).Return(nil)
    
    // Test
    user, err := service.Register(context.Background(), "testuser", "secure123")
    
    // Assertions
    assert.NoError(t, err)
    assert.NotNil(t, user)
    assert.Equal(t, "testuser", user.Username)
    mockRepo.AssertExpectations(t)
}

Step 6: Add Real Persistence Layer

Responsibility: Developer Output: Database implementation and passing BDD test

// pkg/user/repository.go
package user

import "gorm.io/gorm"

type GormUserRepository struct {
    db *gorm.DB
}

func NewGormUserRepository(db *gorm.DB) *GormUserRepository {
    return &GormUserRepository{db: db}
}

func (r *GormUserRepository) CreateUser(user *User) error {
    return r.db.Create(user).Error
}

func (r *GormUserRepository) GetUserByUsername(username string) (*User, error) {
    var user User
    err := r.db.Where("username = ?", username).First(&user).Error
    return &user, err
}

Database Setup:

# docker-compose.yml
services:
  postgres:
    image: postgres:15-alpine
    environment:
      POSTGRES_USER: dancecoach
      POSTGRES_PASSWORD: secure-password
      POSTGRES_DB: dance_lessons_coach
    ports:
      - "5432:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data

Step 7: BDD Test Passes (Green Phase)

Responsibility: Developer Output: Passing BDD test

# Run BDD tests with real database
export DLC_DB_HOST=localhost
export DLC_DB_PORT=5432
export DLC_DB_USER=dancecoach
export DLC_DB_PASSWORD=secure-password
export DLC_DB_NAME=dance_lessons_coach

godog features/user-persistence.feature

# Expected: All tests pass

Step 8: Update OpenAPI Documentation

Responsibility: Developer Output: Updated Swagger documentation

// pkg/user/api_handlers.go

// Register godoc
// @Summary Register a new user
// @Description Create a new user account
// @Tags API/v1/User
// @Accept json
// @Produce json
// @Param request body RegisterRequest true "User registration data"
// @Success 201 {object} RegisterResponse
// @Failure 400 {object} ErrorResponse
// @Failure 409 {object} ErrorResponse
// @Router /auth/register [post]
func (h *AuthHandler) handleRegister(w http.ResponseWriter, r *http.Request) {
    // Implementation
}

// Generate documentation
go generate ./pkg/server/

Step 9: CI/CD Pipeline Validation

Responsibility: DevOps/Developer Output: Passing CI/CD pipeline

# .gitea/workflows/ci-cd.yaml
jobs:
  test:
    steps:
      - name: Run BDD tests
        run: godog features/
      
      - name: Run unit tests
        run: go test ./... -cover
      
      - name: Check OpenAPI docs
        run: test -f pkg/server/docs/swagger.json

Step 10: Product Owner Review

Responsibility: Product Owner Output: Approval or feedback

Review Checklist:

  • Acceptance criteria met
  • BDD tests pass
  • Unit tests pass
  • API documentation updated
  • CI/CD pipeline passes
  • Code follows project conventions
  • Security considerations addressed

📁 File Structure Example

dance-lessons-coach/
├── features/
│   └── user-persistence.feature      # BDD tests
├── pkg/
│   └── user/
│       ├── models.go                 # Data models
│       ├── repository.go            # Repository interface
│       ├── gorm_repository.go       # GORM implementation
│       ├── service.go               # Business logic
│       ├── service_test.go          # Unit tests
│       ├── api_handlers.go           # HTTP handlers
│       └── context.go               # Context utilities
└── docker-compose.yml              # Database setup

🎯 User Story Implementation Example

User Story: User Registration

Gitea Issue:

## User Story: User Registration

**As a** new user
**I want to** create an account
**So that** I can access personalized features

### Acceptance Criteria
- ✅ User can register with username and password
- ✅ Username must be unique and 3-50 alphanumeric characters
- ✅ Password must be at least 8 characters
- ✅ User data is persisted in database
- ✅ Successful registration returns user ID and JWT token
- ✅ Duplicate username returns appropriate error

### Technical Implementation
1. Create `features/user-registration.feature` with BDD scenarios
2. Implement `UserService.Register()` method
3. Create `GormUserRepository` for database persistence
4. Add `POST /api/v1/auth/register` endpoint
5. Update OpenAPI documentation
6. Ensure CI/CD tests pass

BDD Test:

Feature: User Registration
  Users should be able to create accounts

  @user-registration
  Scenario: Successful user registration
    Given the server is running with database
    When I register with username "newuser" and password "securePassword123"
    Then the response status should be 201
    And the response should contain "user_id"
    And the response should contain "token"
    And I should be able to login with username "newuser" and password "securePassword123"

  @user-registration
  Scenario: Duplicate username registration
    Given a user "existinguser" already exists
    When I register with username "existinguser" and password "anotherPassword456"
    Then the response status should be 409
    And the response should contain error "user_exists"

Implementation Steps:

  1. Create BDD test (failing)
  2. Implement service with mock repository
  3. Write unit tests
  4. Add GORM repository implementation
  5. Update database schema
  6. BDD test passes
  7. Add OpenAPI documentation
  8. CI/CD validation
  9. Product Owner review

🔧 Tools and Technologies

  • BDD Testing: Godog (Cucumber for Go)
  • Mocking: testify/mock
  • ORM: GORM with PostgreSQL
  • API Docs: Swaggo (OpenAPI)
  • CI/CD: Gitea Actions
  • Testing: Standard Go testing

📈 Metrics and Success Criteria

User Story Completion:

  • BDD tests: 100% passing
  • Unit tests: ≥80% coverage
  • Integration tests: All critical paths covered
  • Documentation: Complete and accurate
  • CI/CD: All checks passing

Quality Gates:

  • No critical vulnerabilities
  • Code review approved
  • Performance acceptable
  • Error handling comprehensive
  • Logging appropriate

🎓 Best Practices

BDD Test Writing

  1. Focus on behavior, not implementation
  2. One scenario per test case
  3. Use clear, descriptive language
  4. Include both happy and error paths
  5. Keep scenarios independent

Service Implementation

  1. Interface-based design for testability
  2. Context-aware methods
  3. Proper error handling and logging
  4. Input validation at service level
  5. Separation of concerns between layers

Repository Pattern

  1. Interface first, implementation second
  2. Database-agnostic design
  3. Transaction support where needed
  4. Efficient queries
  5. Proper error mapping

API Design

  1. RESTful endpoints
  2. Consistent response formats
  3. Proper HTTP status codes
  4. Comprehensive OpenAPI documentation
  5. Rate limiting for public endpoints

🔄 Feedback Loop

graph LR
    PO[Product Owner] -->|Creates User Story| Dev[Developer]
    Dev -->|Implements & Tests| CI[CI/CD Pipeline]
    CI -->|Pass/Fail| Dev
    Dev -->|Ready for Review| PO
    PO -->|Approves/Feedback| Dev
    Dev -->|Deployed| Prod[Production]
    Prod -->|Monitor| PO

📚 References

This workflow ensures consistent, high-quality implementation of user stories while maintaining test coverage and documentation standards throughout the development process.