Skip to content

CONTRACT.yaml Reference

Overview

CONTRACT.yaml is the central artifact in Prathya. It defines the behavioral contract for a module — what the software is supposed to do, expressed as versioned requirements with corner cases.

The file lives at the module root (next to pom.xml) and is version-controlled alongside the code.

Full Example

module:
  id: AUTH
  name: Authentication Module
  description: Handles user authentication, token issuance, and session management
  owner: team@example.com
  created: 2026-03-06
  version: 1.2.0

requirements:

  - id: AUTH-001
    version: 1.1.0
    status: approved
    title: User login with email and password
    description: >
      The system must authenticate a user given a valid email and password
      combination, issuing a signed JWT access token and a refresh token
      upon success.
    acceptance_criteria:
      - Valid credentials return a signed JWT access token and refresh token
      - Access token expiry is set to 15 minutes
      - Refresh token expiry is set to 7 days
    corner_cases:
      - id: AUTH-001-CC-001
        description: Email is valid but password is incorrect — must return 401, not 404
      - id: AUTH-001-CC-002
        description: Email does not exist — response must be identical to wrong password to prevent enumeration
      - id: AUTH-001-CC-003
        description: Email is provided in mixed case — must be normalized before lookup
    changelog:
      - version: 1.0.0
        date: 2026-01-10
        note: Initial definition
      - version: 1.1.0
        date: 2026-02-18
        note: Added enumeration prevention requirement to CC-002

  - id: AUTH-002
    version: 1.0.0
    status: approved
    title: JWT refresh
    description: >
      The system must issue a new access token when presented with a valid,
      non-expired refresh token.
    acceptance_criteria:
      - Valid refresh token returns a new access token
      - Original refresh token is rotated (invalidated and replaced)
      - Expired refresh token returns 401
    corner_cases:
      - id: AUTH-002-CC-001
        description: Refresh token is used twice — second use must fail (rotation enforcement)
      - id: AUTH-002-CC-002
        description: Refresh token from a revoked session must be rejected even if not expired
    changelog:
      - version: 1.0.0
        date: 2026-01-10
        note: Initial definition

  - id: AUTH-003
    version: 1.0.0
    status: superseded
    superseded_by: AUTH-005
    title: Single-factor password reset (superseded)
    description: >
      The system must allow password reset via email link only.
    acceptance_criteria:
      - Reset link is valid for 30 minutes
    corner_cases: []
    changelog:
      - version: 1.0.0
        date: 2026-01-10
        note: Initial definition
      - version: 1.0.0
        date: 2026-02-01
        note: Superseded by AUTH-005 (MFA-aware reset)

  - id: AUTH-005
    version: 1.0.0
    status: approved
    supersedes: AUTH-003
    title: MFA-aware password reset
    description: >
      The system must allow password reset via email link, with optional MFA
      verification step before the reset is permitted.
    acceptance_criteria:
      - Reset link is valid for 15 minutes
      - If MFA is enabled on the account, OTP verification is required before reset
      - Reset invalidates all existing sessions
    corner_cases:
      - id: AUTH-005-CC-001
        description: Reset link is used after expiry — must return 410 Gone, not 401
      - id: AUTH-005-CC-002
        description: User attempts reset while already logged in — session must still be invalidated
    changelog:
      - version: 1.0.0
        date: 2026-02-01
        note: Supersedes AUTH-003. Adds MFA step and session invalidation.

Schema Reference

module (required)

Field Type Required Description
id string Yes Short uppercase identifier (e.g., AUTH)
name string Yes Human-readable module name
description string No Module description
owner string No Contact for the module owner
created date No Creation date
version string No Module contract version (semver)

requirements[] (required)

Field Type Required Description
id string Yes Unique requirement ID (format: {MODULE}-{NNN})
version string Yes Requirement version (semver)
status string Yes One of: draft, approved, deprecated, superseded
title string Yes Short requirement title
description string Yes Full requirement description
acceptance_criteria string[] No List of acceptance criteria
corner_cases object[] No List of corner cases
changelog object[] No Version history
supersedes string No ID of the requirement this one replaces
superseded_by string No ID of the requirement that replaces this one

corner_cases[]

Field Type Required Description
id string Yes Corner case ID (format: {MODULE}-{NNN}-CC-{NNN})
description string Yes What the corner case tests

changelog[]

Field Type Required Description
version string Yes Version at which this change occurred
date date Yes Date of the change
note string Yes Description of the change

ID Format Rules

Pattern Example Meaning
{MODULE}-{NNN} AUTH-001 Requirement
{MODULE}-{NNN}-CC-{NNN} AUTH-001-CC-001 Corner case
  • IDs are append-only — never reused
  • Requirements are never deleted — use deprecated or superseded
  • Corner case IDs are scoped to their parent requirement

Annotation Usage

import com.intrigsoft.prathya.annotations.Requirement;

// Single requirement
@Test
@Requirement("AUTH-001")
void loginWithValidCredentials_returnsTokens() { /* ... */ }

// Multiple requirements or corner cases
@Test
@Requirement({"AUTH-001-CC-001", "AUTH-001-CC-002"})
void loginWithInvalidCredentials_returns401() { /* ... */ }

// Corner case
@Test
@Requirement("AUTH-002-CC-001")
void refreshTokenUsedTwice_secondCallFails() { /* ... */ }

@Requirement accepts a single ID or an array of IDs. Place it on test methods, not classes.