project-standalo-note-to-app/skills/guardrail-orchestrator/schemas/api_contract.yml

348 lines
11 KiB
YAML

# API Contract Schema
# The binding agreement between frontend and backend implementations
# Generated during design phase, validated during review phase
#
# This contract ensures:
# 1. Backend implements exactly the endpoints frontend expects
# 2. Frontend calls endpoints with correct methods/bodies
# 3. Both use the same TypeScript types from shared file
# ============================================================================
# CONTRACT METADATA
# ============================================================================
api_contract:
# Links to workflow
workflow_version: string # e.g., v001
design_document_revision: integer
# Timestamps
generated_at: timestamp
validated_at: timestamp | null
# Contract status
status: draft | active | violated
# ============================================================================
# SHARED TYPES (Source of truth for both agents)
# ============================================================================
# These types are generated into app/types/api.ts
# Both frontend and backend MUST import from this file
types:
description: "TypeScript interfaces shared between frontend and backend"
type_schema:
# Identity
id: string # type_<Name> (e.g., type_User, type_CreateUserRequest)
name: string # PascalCase type name (exported interface name)
# Type definition
definition:
type: object | array | enum | union
# For object types
properties:
- name: string # Property name (camelCase)
type: string # TypeScript type (string, number, boolean, other type name)
required: boolean
description: string
validation: string # Optional validation rule
# For enum types
enum_values: [string]
# For union types
union_members: [string] # Array of type names or literal types
# For array types
array_item_type: string # Type of array items
# Usage tracking
used_by:
requests: [string] # endpoint_ids that use this as request body
responses: [string] # endpoint_ids that use this as response
models: [string] # model_ids this type represents
# Example
example_type:
id: type_User
name: User
definition:
type: object
properties:
- name: id
type: string
required: true
description: "Unique user identifier"
- name: email
type: string
required: true
description: "User email address"
validation: email
- name: name
type: string
required: true
description: "Display name"
- name: createdAt
type: Date
required: true
description: "Account creation timestamp"
used_by:
responses: [api_get_user, api_create_user, api_list_users]
models: [model_user]
# ============================================================================
# ENDPOINT CONTRACTS (Binding specifications)
# ============================================================================
endpoints:
description: "API endpoint contracts with strict request/response typing"
endpoint_schema:
# Identity
id: string # api_<verb>_<resource> from design_document
# HTTP Specification
method: GET | POST | PUT | PATCH | DELETE
path: string # Exact path with params (e.g., /api/users/:id)
# Path parameters (extracted from path)
path_params:
- name: string
type: string # TypeScript type
description: string
# Query parameters (for GET requests)
query_params:
- name: string
type: string
required: boolean
default: any
description: string
# Request body (for POST/PUT/PATCH)
request_body:
type_id: string # Reference to types section (e.g., type_CreateUserRequest)
content_type: application/json
# Response specification
response:
# Success response
success:
status: integer # 200, 201, 204
type_id: string # Reference to types section
is_array: boolean # If response is array of type
# Error responses
errors:
- status: integer # 400, 401, 403, 404, 500
type_id: string # Error response type (usually type_ApiError)
description: string
# Authentication
auth:
required: boolean
roles: [string] # Required roles (empty = any authenticated)
# Contract version for compatibility
version: string # Semantic version of this endpoint spec
# Example
example_endpoint:
id: api_create_user
method: POST
path: /api/users
path_params: []
query_params: []
request_body:
type_id: type_CreateUserRequest
content_type: application/json
response:
success:
status: 201
type_id: type_User
is_array: false
errors:
- status: 400
type_id: type_ValidationError
description: "Invalid request body"
- status: 409
type_id: type_ApiError
description: "Email already exists"
auth:
required: false
roles: []
version: "1.0.0"
# ============================================================================
# FRONTEND USAGE CONTRACTS (What frontend expects to call)
# ============================================================================
frontend_calls:
description: "Expected API calls from frontend components/pages"
call_schema:
# Identity
id: string # call_<component>_<action>
# Source
source:
entity_id: string # page_xxx or component_xxx
file_path: string # Expected file location
# Target endpoint
endpoint_id: string # Reference to endpoints section
# Call context
purpose: string # Why this call is made
trigger: string # What triggers this call (onLoad, onClick, onSubmit)
# Data mapping
request_mapping:
# How component data maps to request
from_props: [string] # Props used in request
from_state: [string] # State used in request
from_form: [string] # Form fields used in request
response_handling:
# How response is handled
success_action: string # What happens on success
error_action: string # What happens on error
# Example
example_call:
id: call_signup_form_submit
source:
entity_id: component_signup_form
file_path: app/components/SignupForm.tsx
endpoint_id: api_create_user
purpose: "Submit registration form"
trigger: onSubmit
request_mapping:
from_form: [email, name, password]
response_handling:
success_action: "Redirect to dashboard"
error_action: "Display error message"
# ============================================================================
# BACKEND IMPLEMENTATION CONTRACTS (What backend must provide)
# ============================================================================
backend_routes:
description: "Required backend route implementations"
route_schema:
# Identity
id: string # route_<verb>_<path>
# Target endpoint
endpoint_id: string # Reference to endpoints section
# Implementation location
file_path: string # Expected file (e.g., app/api/users/route.ts)
export_name: string # Exported function name (GET, POST, etc.)
# Dependencies
uses_models: [string] # model_ids this route uses
uses_services: [string] # Service files this route depends on
# Implementation requirements
must_validate:
- field: string
rule: string
must_authenticate: boolean
must_authorize: [string] # Role checks required
# Example
example_route:
id: route_post_users
endpoint_id: api_create_user
file_path: app/api/users/route.ts
export_name: POST
uses_models: [model_user]
uses_services: [lib/auth.ts, lib/db.ts]
must_validate:
- field: email
rule: email
- field: password
rule: min:8
must_authenticate: false
must_authorize: []
# ============================================================================
# VALIDATION RULES
# ============================================================================
validation_rules:
contracts:
- "Every frontend_call must reference existing endpoint_id"
- "Every backend_route must reference existing endpoint_id"
- "Request body type_id must exist in types section"
- "Response type_id must exist in types section"
- "Path params in endpoint must match :param patterns in path"
types:
- "Every type must have unique id"
- "Type references (nested types) must exist"
- "Required properties cannot have default values"
implementation:
- "Frontend must import types from shared types file"
- "Backend must import types from shared types file"
- "HTTP methods must match contract specification"
- "Response shapes must conform to type definitions"
# ============================================================================
# GENERATED FILES
# ============================================================================
generated_files:
shared_types:
path: app/types/api.ts
description: "TypeScript interfaces for all API types"
template: |
// AUTO-GENERATED - DO NOT EDIT
// Source: .workflow/versions/vXXX/contracts/api_contract.yml
// Generated: {timestamp}
// === Types ===
{type_definitions}
// === API Paths (for type-safe fetch calls) ===
export const API_PATHS = {
{path_constants}
} as const;
// === API Response Types ===
{response_type_helpers}
api_client:
path: app/lib/api-client.ts
description: "Type-safe API client (optional)"
template: |
// AUTO-GENERATED - DO NOT EDIT
// Type-safe API client generated from contract
import type { * } from '@/types/api';
{api_client_methods}
# ============================================================================
# CONTRACT VIOLATION HANDLING
# ============================================================================
violations:
severity_levels:
critical:
- "Endpoint exists in frontend but not backend"
- "Method mismatch (frontend calls POST, backend has GET)"
- "Required field missing in implementation"
high:
- "Response type mismatch"
- "Missing error handling for documented errors"
medium:
- "Extra undocumented endpoint in backend"
- "Type property order differs"
low:
- "Description mismatch"
- "Optional field handling differs"
on_violation:
critical: "Block deployment, require immediate fix"
high: "Warn in review, require acknowledgment"
medium: "Report in review, fix recommended"
low: "Log for tracking"