Specification Writing Guide
Learn how to write clear, effective specifications using SDD Tool.
Overview
Writing effective specifications is core to Spec-Driven Development. This guide covers best practices, formats, and conventions.
Key Principles
- Clarity - Specifications must be unambiguous
- Completeness - Cover all scenarios and edge cases
- Consistency - Follow conventions throughout
- Testability - Specifications should be verifiable
- Maintainability - Specs should be easy to update
Specification Structure
Every specification file has three main parts:
1. Metadata (YAML Front Matter)
---
id: user-authentication
title: "User Authentication"
status: draft
created: 2025-01-30
updated: 2025-01-31
version: 1.0.0
constitution_version: 1.0.0
domain: auth
---Required Fields:
id- Unique identifier (kebab-case)title- Human-readable titlestatus- One of: draft, active, deprecatedcreated- Creation date (YYYY-MM-DD)constitution_version- Project constitution version
Optional Fields:
updated- Last update dateversion- Specification versiondomain- Domain this spec belongs torelated- Related specification IDstags- Category tags
2. Overview Section
# User Authentication
> A concise description of what this spec covers
## Purpose
Explain why this feature is needed and its importance.
## Scope
Define what is and isn't covered by this spec.
### What's Included
- Email/password authentication
- Session management
- Token-based API access
### What's Excluded
- Social login (see social-auth spec)
- Multi-factor authentication3. Requirements Section
Define specific requirements using RFC 2119 keywords.
## Requirements
### REQ-001: Email/Password Login
The system SHALL support user login using email and password.
- Email SHALL be validated as RFC 5322 compliant
- Password SHALL be at least 8 characters
- Failed login attempts SHOULD be rate-limitedRFC 2119 Keywords
Use standardized keywords to specify requirement levels:
SHALL / MUST (Absolute Requirement)
Use for critical requirements that are non-negotiable.
- The system SHALL authenticate users via email/password
- The API SHALL return HTTP 401 for invalid credentials
- All data SHALL be encrypted in transitImplications:
- Implementation MUST satisfy this requirement
- Tests MUST verify compliance
- Violations are bugs
SHOULD (Recommended)
Use for important but flexible requirements.
- The system SHOULD provide password recovery
- The response SHOULD include helpful error messages
- The system SHOULD log failed authentication attemptsImplications:
- Implementation SHOULD satisfy this requirement
- May be skipped with documented justification
- Consider requirements carefully before skipping
MAY (Optional)
Use for features that are truly optional.
- The system MAY support single sign-on (SSO)
- The UI MAY include biometric authentication
- The API MAY cache user profile dataImplications:
- Implementation may choose to include or exclude
- No requirement to test for compliance
SHALL NOT (Forbidden)
Use to explicitly forbid certain behaviors.
- The system SHALL NOT store passwords in plaintext
- The API SHALL NOT expose user IDs in error messages
- The client SHALL NOT store sensitive data locallyImplications:
- Implementation MUST NOT do this
- Tests MUST verify non-compliance
- Violations are security issues
Writing Scenarios (GIVEN-WHEN-THEN)
Scenarios provide concrete examples of how features work:
Basic Structure
### Scenario 1: Successful Login
- **GIVEN** a user with email "alice@example.com" exists in the system
- **WHEN** they submit a login form with correct password
- **THEN** they receive a valid JWT token
- **AND** their last login time is updatedAnatomy of a Scenario
GIVEN - Initial context and preconditions
- What state must exist before the action
- What data or configuration is in place
WHEN - The action or trigger
- What the user or system does
- What event occurs
THEN - Expected outcomes
- What should happen as a result
- What state or data changes
AND/OR - Additional outcomes or conditions
- Multiple conditions in one step
- Related outcomes
Good Scenario Examples
Login Success:
### Scenario: Valid Credentials
- **GIVEN** a registered user with email "user@example.com"
- **AND** they know their correct password
- **WHEN** they submit the login form
- **THEN** they receive an authentication token
- **AND** they are redirected to the dashboardLogin Failure:
### Scenario: Invalid Password
- **GIVEN** a registered user with email "user@example.com"
- **WHEN** they submit the login form with wrong password
- **THEN** they see an error message "Invalid credentials"
- **AND** the login attempt is logged
- **AND** their account is not affectedEdge Cases:
### Scenario: Non-existent User
- **GIVEN** no user exists with email "unknown@example.com"
- **WHEN** someone attempts to log in with that email
- **THEN** they see a generic error message
- **AND** no information about user existence is revealedBest Practices for Scenarios
Be Specific - Use concrete values, not abstractions
- Good: "email: alice@example.com"
- Bad: "a valid email"
One Outcome Per THEN - Keep scenarios focused
- Good: One scenario per success/failure path
- Bad: Multiple different outcomes in one scenario
Cover Happy and Sad Paths
- Happy path: Normal successful flow
- Sad paths: All failure modes
- Edge cases: Boundary conditions
Make Scenarios Testable
- Each scenario should have a corresponding test
- Use clear, verifiable assertions
Use Consistent Language
- Same terminology throughout
- Define terms in glossary if needed
Complete Specification Example
---
id: user-authentication
title: "User Authentication System"
status: active
created: 2025-01-30
version: 1.0.0
constitution_version: 1.0.0
domain: auth
tags:
- security
- core
---
# User Authentication System
> Provides secure user authentication using email/password and JWT tokens
## Purpose
Enable secure user identification and session management while protecting user credentials.
## Scope
### What's Included
- Email/password authentication
- JWT token generation and validation
- Session management
- Password reset functionality
### What's Excluded
- Multi-factor authentication
- Social login (future feature)
- Account recovery procedures
## Core Requirements
### REQ-001: Email/Password Authentication
The system SHALL support secure authentication using email and password.
#### Functional Requirements
- User SHALL provide email and password
- System SHALL validate email format (RFC 5322)
- System SHALL validate password meets minimum requirements:
- Minimum 8 characters
- At least one uppercase letter
- At least one number
- At least one special character
#### Security Requirements
- Passwords SHALL be hashed using bcrypt (minimum 10 rounds)
- Passwords SHALL NOT be stored in plaintext
- Passwords SHALL NOT be returned in any API response
- Failed attempts SHALL be logged for security audit
#### Performance Requirements
- Login response time SHOULD be under 500ms
- The system SHOULD rate-limit failed attempts (5 attempts per 15 minutes)
### REQ-002: JWT Token Management
The system SHALL use JWT (JSON Web Tokens) for API authentication.
- Token SHALL expire after 24 hours
- Token MAY be refreshed using a refresh token
- Refresh token SHALL have 30-day expiration
- Expired tokens SHALL be rejected with HTTP 401
### REQ-003: Password Reset
The system SHOULD provide password reset capability.
- User SHALL request password reset via email
- System SHOULD send reset link (valid for 1 hour)
- User SHALL be able to set new password via link
- Old password SHALL NOT be required for reset
## Scenarios
### Successful Login Flow
#### Scenario 1: User Logs In with Valid Credentials
- **GIVEN** a user "alice@example.com" is registered with password "SecurePass123!"
- **WHEN** alice submits login form with email and correct password
- **THEN** the system validates the credentials
- **AND** the system generates a JWT token
- **AND** alice receives the token with 24-hour expiration
- **AND** alice can use the token for API requests
#### Scenario 2: Login Redirects to Dashboard
- **GIVEN** alice has successfully logged in
- **WHEN** the login form processes the response
- **THEN** alice is redirected to the dashboard
- **AND** the token is stored securely in the client
### Login Failure Scenarios
#### Scenario 3: Invalid Password
- **GIVEN** a user "bob@example.com" is registered
- **WHEN** bob submits login form with wrong password
- **THEN** the system returns error "Invalid credentials"
- **AND** the login attempt is logged
- **AND** bob is NOT logged in
#### Scenario 4: Account Lockout After Failed Attempts
- **GIVEN** a user has failed login 5 times in 15 minutes
- **WHEN** they attempt to log in again
- **THEN** the system returns error "Account temporarily locked"
- **AND** the account is locked for 15 minutes
- **AND** an alert email is sent to the user
#### Scenario 5: Non-existent User
- **GIVEN** no user exists with email "unknown@example.com"
- **WHEN** someone attempts login with that email
- **THEN** the system returns generic error "Invalid credentials"
- **AND** no information is leaked about user existence
### Token Management
#### Scenario 6: Token Expiration
- **GIVEN** a user has a token that expired 1 hour ago
- **WHEN** they attempt to make an API request
- **THEN** the API returns HTTP 401 Unauthorized
- **AND** the client should redirect to login
#### Scenario 7: Token Refresh
- **GIVEN** a user has a valid refresh token
- **WHEN** their access token expires
- **THEN** they can use refresh token to get new access token
- **AND** the new token is valid for another 24 hours
### Password Reset
#### Scenario 8: Successful Password Reset
- **GIVEN** charlie has forgotten their password
- **WHEN** charlie requests password reset for "charlie@example.com"
- **THEN** charlie receives an email with reset link
- **AND** the link is valid for 1 hour
- **WHEN** charlie opens the link and sets new password "NewPass456!"
- **THEN** the password is updated in the system
- **AND** charlie can log in with new password
## Glossary
| Term | Definition |
|------|-----------|
| JWT | JSON Web Token - stateless authentication token |
| Bearer Token | Authorization header containing JWT |
| Refresh Token | Long-lived token used to obtain new access tokens |
| bcrypt | Cryptographic algorithm for password hashing |
## Related Specifications
- social-auth - Social login implementation
- mfa - Multi-factor authentication
- password-policy - Organization password requirements
## Notes
- Security review scheduled for Q2 2025
- Consider bcrypt performance on large-scale deployments
- Plan for token revocation mechanism in future versionWriting Tips
1. Use Clear, Precise Language
Good:
- "The system SHALL validate email format according to RFC 5322"
Avoid:
- "The system should check if the email looks okay"
- "The email must be valid or something"
2. Be Specific About Constraints
Good:
- Password SHALL be 8-64 characters
- Password SHALL contain at least one uppercase letter
- Password SHALL contain at least one numberAvoid:
- Password must be strong
- Password should be secure3. Separate Concerns into Different Requirements
Good:
### REQ-001: Email Validation
- Emails SHALL be RFC 5322 compliant
### REQ-002: Password Validation
- Passwords SHALL be minimum 8 charactersAvoid:
### REQ-001: User Credentials
- Emails should be valid and passwords should be strong4. Include Negative Tests
Good:
### Scenario: Rejected Invalid Password
- **GIVEN** a user with valid email
- **WHEN** they submit invalid password
- **THEN** login is rejected5. Make Scenarios Independent
Each scenario should be runnable independently without depending on other scenarios.
Good: Each scenario fully describes its preconditions Avoid: "After scenario 1, the user should..."
Common Pitfalls
Pitfall 1: Using Ambiguous Terms
Problem: "The system SHOULD be fast" Solution: "Response time SHOULD be under 500ms"
Pitfall 2: Mixing Levels of Abstraction
Problem: "The system SHALL authenticate users and show a nice UI" Solution: Separate into authentication and UI specs
Pitfall 3: Over-Specifying Implementation
Problem: "The system SHALL use bcrypt with 10 rounds" Better: "Passwords SHALL be securely hashed using industry-standard algorithms"
Pitfall 4: Neglecting Edge Cases
Problem: Only happy path scenarios Solution: Include edge cases, error conditions, boundary values
Pitfall 5: Outdated Specifications
Problem: Specs not updated when requirements change Solution: Update specs before implementation changes, not after
Reviewing Specifications
Before implementing, review specs for:
- Clarity - Can team members understand requirements?
- Completeness - Are all scenarios covered?
- Consistency - Is terminology consistent?
- Feasibility - Can requirements be implemented?
- Testability - Can requirements be verified?
- Alignment - Do specs match constitution?
Specification Lifecycle
draft
↓
(review & feedback)
↓
active (being implemented)
↓
(updates during development)
↓
completed (implementation done)
↓
(later changes)
↓
deprecated (replaced by newer version)Next Steps
Ready to write specifications? Start with the Getting Started Guide.