Requirements
The requirements section is required and holds the core normative content.
Structure
reqPackage: Optional grouping container with@id,title, optionalownerRef, optionaldescription, and nestedreqitems.req: Individual requirement with attributes:@id(IdType, unique within document)@type(one ofFR,NFR,IR,DR,SR,CR,PR,UXR,OR)@title(human-readable)- Optional
status,priority,ownerRef,appliesTo - Children:
statement(required), optionalrationale,notes,acceptance.
acceptance: Contains one or morecriterionentries, each with optional@idandgiven/when/thentext blocks.
Requirement type meanings
- FR — Functional Requirement: What the system must do—features, behaviors, business functions.
- NFR — Non-Functional Requirement: Quality attributes and constraints on how well it works (performance, reliability, usability, etc.).
- IR — Interface Requirement: Contracts with other systems/components (APIs, endpoints, message formats, error semantics).
- DR — Data Requirement: Data models, fields, validation rules, retention, lineage, classification (e.g., PII).
- SR — Security Requirement: Security controls (authn/authz, encryption, secrets handling, auditing, threat mitigations).
- CR — Constraint Requirement: Hard constraints on solution space (mandated tech, platforms, standards, environments).
- PR — Policy/Compliance Requirement: Regulatory or internal policy obligations (GDPR, audit rules, retention policies, evidence needs).
- UXR — User Experience Requirement: UI/interaction expectations (flows, accessibility, i18n, content rules, user-facing behavior).
- OR — Operational Requirement: Run/operate/observe the system (monitoring, logging, alerting, backups, RPO/RTO, runbooks).
Authoring tips
- Keep
statementcrisp and testable; useacceptanceto express BDD-style criteria when needed. - Reuse
@idreferences from catalogs, domain entities, and goals via trace edges orappliesTo. - Use
priorityto distinguishmust/should/mayandstatusto track lifecycle (draft/review/approved/deprecated). - Group related requirements into
reqPackageto clarify ownership and scope.
Example
<requirements>
<reqPackage id="PKG-AUTH" title="Authorization" ownerRef="STK-RISK">
<description>Payment authorization flow</description>
<req id="REQ-AUTH-001" type="FR" title="Authorize payment" priority="must">
<statement>The system SHALL authorize card payments via the acquiring bank.</statement>
<rationale>Enable online checkout for merchants.</rationale>
<acceptance>
<criterion id="CRIT-1">
<given>An authenticated merchant requests authorization</given>
<when>The acquirer responds with approval</when>
<then>The payment is marked authorized with paymentId</then>
</criterion>
</acceptance>
</req>
</reqPackage>
</requirements>
Code generation examples
LLMs generate different code patterns based on requirement type:
Functional Requirements (FR) → Application logic:
// From REQ-AUTH-001: Authorize card payments
export class PaymentAuthService {
async authorizePayment(req: AuthRequest): Promise<Payment> {
// Implements REQ-AUTH-001
const authResult = await this.acquirer.authorize({
amount: req.amount,
currency: req.currency,
cardToken: req.cardToken,
});
return this.createPayment({
id: generateId(),
status: authResult.approved ? 'authorized' : 'declined',
...authResult,
});
}
}
Security Requirements (SR) → Security middleware:
// From SR requirement: Enforce TLS 1.2+
export function tlsEnforcementMiddleware(req: Request, res: Response, next: NextFunction) {
const tlsVersion = req.socket.getPeerCertificate()?.version;
if (!tlsVersion || tlsVersion < 'TLSv1.2') {
return res.status(426).json({ error: 'TLS 1.2+ required' });
}
next();
}
Data Requirements (DR) → Validation schemas:
// From DR requirement: Email validation per RFC 5322
import { z } from 'zod';
export const PaymentRequestSchema = z.object({
amount: z.number().positive(),
currency: z.string().length(3),
email: z.string().email(), // Implements DR-EMAIL-001
});
Operational Requirements (OR) → Observability:
// From OR requirement: Emit structured logs
export class PaymentLogger {
logAuthorization(payment: Payment): void {
logger.info('payment.authorized', {
paymentId: payment.id,
amount: payment.amount,
timestamp: new Date().toISOString(),
requirement: 'OR-LOGGING-001',
});
}
}
Test generation examples
Requirements drive test implementation through acceptance criteria:
- Given-When-Then tests: Direct translation from acceptance criteria to test cases
- Type-specific tests: FR → integration tests, SR → security tests, NFR → performance tests
- Priority-based suites: Critical path tests from "must" requirements first
- Coverage mapping: Each requirement gets at least one test
- Traceability: Test names reference requirement IDs for impact analysis
Example test from acceptance criterion:
describe('REQ-AUTH-001: Authorize payment', () => {
it('CRIT-1: authorized payment with valid merchant', async () => {
// Given: authenticated merchant requests authorization
const merchant = await createAuthenticatedMerchant();
// When: acquirer responds with approval
mockAcquirer.authorize.mockResolvedValue({ approved: true });
const result = await paymentService.authorize(merchant, validRequest);
// Then: payment marked authorized with paymentId
expect(result.status).toBe('authorized');
expect(result.paymentId).toBeDefined();
});
});
Theory
- Requirements should be necessary, verifiable, unambiguous, and feasible (IEEE 29148 qualities).
- Categorizing by type (FR/NFR/etc.) aligns with classic RE taxonomies; acceptance criteria make requirements testable (BDD/Gherkin influence).
- Packaging requirements aids scoping and ownership, echoing Volere and disciplined backlog management.
- Bibliography: IEEE 29148-2018, Specification by Example, Volere Template.