# API Contract Template A contract is the **frozen, reviewed interface** between two or more components. When task A produces a shared model, DTO, schema, event payload, or public API, and task B consumes it, they must not reverse-engineer each other's implementation — they must read the contract. Save the filled contract at `_docs/02_document/contracts//.md`. Reference it from the producing task's `## Contract` section and from every consuming task's `## Dependencies` section. --- ```markdown # Contract: [contract-name] **Component**: [component-name] **Producer task**: [TRACKER-ID] — [task filename] **Consumer tasks**: [list of TRACKER-IDs or "TBD at decompose time"] **Version**: 1.0.0 **Status**: [draft | frozen | deprecated] **Last Updated**: [YYYY-MM-DD] ## Purpose Short statement of what this contract represents and why it is shared (1–3 sentences). ## Shape Choose ONE of the following shape forms per the contract type: ### For data models (DTO / schema / event) ```[language] // language-native type definitions — e.g., Python dataclass, C# record, TypeScript interface, Rust struct, JSON Schema ``` For each field: | Field | Type | Required | Description | Constraints | |-------|------|----------|-------------|-------------| | `id` | `string` (UUID) | yes | Unique identifier | RFC 4122 v4 | | `created_at` | `datetime` (ISO 8601 UTC) | yes | Creation timestamp | | | `...` | ... | ... | ... | ... | ### For function / method APIs | Name | Signature | Throws / Errors | Blocking? | |------|-----------|-----------------|-----------| | `do_x` | `(input: InputDto) -> Result` | `XError::NotFound`, `XError::Invalid` | sync | | ... | ... | ... | ... | ### For HTTP / RPC endpoints | Method | Path | Request body | Response | Status codes | |--------|------|--------------|----------|--------------| | `POST` | `/api/v1/resource` | `CreateResource` | `Resource` | 201, 400, 409 | | ... | ... | ... | ... | ... | ## Invariants Properties that MUST hold for every valid instance or every allowed interaction. These survive refactors. - Invariant 1: [statement] - Invariant 2: [statement] ## Non-Goals Things this contract intentionally does NOT cover. Helps prevent scope creep. - Not covered: [statement] ## Versioning Rules - **Breaking changes** (field renamed/removed, type changed, required→optional flipped) require a new major version and a deprecation path for consumers. - **Non-breaking additions** (new optional field, new error variant consumers already tolerate) require a minor version bump. ## Test Cases Representative cases that both producer and consumer tests must cover. Keep short — this is the contract test surface, not an exhaustive suite. | Case | Input | Expected | Notes | |------|-------|----------|-------| | valid-minimal | minimal valid instance | accepted | | | invalid-missing-required | missing `id` | rejected with specific error | | | edge-case-x | ... | ... | | ## Change Log | Version | Date | Change | Author | |---------|------|--------|--------| | 1.0.0 | YYYY-MM-DD | Initial contract | [agent/user] | ``` --- ## Decompose-skill rules for emitting contracts A task is a **shared-models / shared-API task** when ANY of the following is true: - The component spec lists it as a shared component (under `shared/*` in `module-layout.md`). - The task's **Scope.Included** mentions any of: "public interface", "DTO", "schema", "event", "contract", "API endpoint", "shared model". - The task is parented to a cross-cutting epic (`epic_type: cross-cutting`). - The task is depended on by ≥2 other tasks across different components. For every shared-models / shared-API task: 1. Create a contract file at `_docs/02_document/contracts//.md` using this template. 2. Fill in Shape, Invariants, Non-Goals, Versioning Rules, and at least 3 Test Cases. 3. Add a mandatory `## Contract` section to the task spec that links to the contract file: ```markdown ## Contract This task produces/implements the contract at `_docs/02_document/contracts//.md`. Consumers MUST read that file — not this task spec — to discover the interface. ``` 4. For every consuming task, add the contract path to its `## Dependencies` section as a document dependency (not a task dependency): ```markdown ### Document Dependencies - `_docs/02_document/contracts//.md` — API contract produced by [TRACKER-ID]. ``` 5. If the contract changes after it was frozen, the producer task must bump the `Version` and note the change in `Change Log`. Consumers referenced in the contract header must be notified (surface to user via Choose format). ## Code-review-skill rules for verifying contracts Phase 2 (Spec Compliance) adds a check: - For every task with a `## Contract` section: - Verify the referenced contract file exists at the stated path. - Verify the implementation's public signatures (types, method shapes, endpoint paths) match the contract's Shape section. - If they diverge, emit a `Spec-Gap` finding with High severity. - For every consuming task's Document Dependencies that reference a contract: - Verify the consumer's imports / calls match the contract's Shape. - If they diverge, emit a `Spec-Gap` finding with High severity and a hint that either the contract or the consumer is drifting.