contract-first-design

Contract-First Design Skill

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "contract-first-design" with this command: npx skills add melodic-software/claude-code-plugins/melodic-software-claude-code-plugins-contract-first-design

Contract-First Design Skill

When to Use This Skill

Use this skill when:

  • Contract First Design tasks - Working on design and manage api contracts before implementation using openapi and asyncapi specifications for contract-first development

  • Planning or design - Need guidance on Contract First Design approaches

  • Best practices - Want to follow established patterns and standards

Overview

Apply contract-first development methodology for APIs, ensuring specifications drive implementation.

Contract-First Methodology

Core Principles

contract_first_principles: design_before_code: description: "API specification comes before implementation" benefits: - "Early feedback from consumers" - "Parallel development enabled" - "Clear contract for testing" - "Documentation from day one"

specification_as_source_of_truth: description: "Spec is authoritative, code conforms to it" enforcement: - "Generate code from spec" - "Validate implementation against spec" - "CI/CD gates on spec compliance"

consumer_centric: description: "Design for consumer needs, not provider convenience" practices: - "Involve consumers in design reviews" - "Consumer-driven contract testing" - "Gather real-world usage patterns"

evolution_over_revolution: description: "Evolve contracts without breaking consumers" practices: - "Semantic versioning" - "Backward compatibility by default" - "Deprecation before removal"

Development Workflow

contract_first_workflow: phases: 1_design: activities: - "Identify API consumers and use cases" - "Define resources and operations" - "Draft specification (OpenAPI/AsyncAPI)" - "Review with stakeholders" artifacts: - "Draft API specification" - "Use case documentation" gate: "Specification approved by consumers"

2_validate:
  activities:
    - "Lint specification for style/standards"
    - "Check backward compatibility"
    - "Generate mock server"
    - "Consumer acceptance testing with mocks"
  artifacts:
    - "Lint report"
    - "Compatibility report"
    - "Mock server configuration"
  gate: "Consumers validated against mocks"

3_implement:
  activities:
    - "Generate server stubs"
    - "Implement business logic"
    - "Contract testing against spec"
    - "Integration testing"
  artifacts:
    - "Generated code"
    - "Contract test results"
  gate: "Implementation passes contract tests"

4_publish:
  activities:
    - "Publish specification to catalog"
    - "Generate documentation"
    - "Update changelog"
    - "Notify consumers"
  artifacts:
    - "Published specification"
    - "API documentation portal"
    - "Changelog entry"
  gate: "Documentation live, consumers notified"

5_operate:
  activities:
    - "Monitor API usage"
    - "Collect consumer feedback"
    - "Track breaking change requests"
    - "Plan next version"
  artifacts:
    - "Usage metrics"
    - "Feedback log"
    - "Deprecation schedule"

Contract Management

Specification Organization

specification_organization: directory_structure: recommended: specs/ openapi/ order-service.yaml customer-service.yaml inventory-service.yaml asyncapi/ order-events.yaml inventory-events.yaml shared/ schemas/ common-types.yaml error-responses.yaml parameters/ pagination.yaml security/ auth-schemes.yaml

file_naming: pattern: "{service-name}.yaml" versioned: "{service-name}-v{major}.yaml"

modular_specs: description: "Split large specs into components" approach: main_file: "Defines paths, references components" components_dir: "Reusable schemas, parameters, responses" shared_dir: "Cross-API shared definitions"

example_main:
  openapi: "3.1.0"
  info:
    title: "Order Service API"
    version: "1.0.0"
  paths:
    $ref: "./paths/orders.yaml"
  components:
    schemas:
      $ref: "./schemas/_index.yaml"

Version Management

version_management: semantic_versioning: major: "Breaking changes" minor: "Backward-compatible additions" patch: "Backward-compatible fixes"

version_in_spec: location: "info.version" format: "MAJOR.MINOR.PATCH"

api_versioning_strategies: url_path: spec_example: servers: - url: "https://api.example.com/v1" change_approach: "New spec file for major versions"

header:
  spec_example:
    parameters:
      API-Version:
        in: header
        required: false
        schema:
          type: string
          default: "2025-01-01"

changelog_requirements: location: "CHANGELOG.md alongside spec" format: "Keep a Changelog" content: - "Version number and date" - "Added: new endpoints/fields" - "Changed: modified behavior" - "Deprecated: marked for removal" - "Removed: breaking deletions" - "Fixed: bug fixes" - "Security: vulnerability patches"

Breaking Change Detection

breaking_changes: definition: "Changes that can break existing consumers"

openapi_breaking: removals: - "Remove endpoint" - "Remove required response field" - "Remove enum value" - "Remove supported content type"

modifications:
  - "Change field type"
  - "Add required request field"
  - "Narrow validation (smaller max, larger min)"
  - "Change authentication requirements"

renames:
  - "Rename field (equivalent to remove + add)"
  - "Change endpoint path"

asyncapi_breaking: removals: - "Remove channel" - "Remove message type" - "Remove required payload field"

modifications:
  - "Change payload schema incompatibly"
  - "Change channel address format"
  - "Modify required headers"

detection_tools: openapi: - "openapi-diff" - "oasdiff" - "speccy" asyncapi: - "asyncapi/diff"

ci_integration: script: | # Compare current spec against main branch oasdiff breaking main.yaml current.yaml if [ $? -ne 0 ]; then echo "Breaking changes detected!" exit 1 fi

C# Models for Contract Management

namespace SpecDrivenDevelopment.ContractFirst;

/// <summary> /// Represents an API contract lifecycle state /// </summary> public enum ContractStatus { Draft, InReview, Approved, Implementing, Published, Deprecated, Retired }

/// <summary> /// API contract metadata /// </summary> public record ApiContract { public required string Id { get; init; } public required string Name { get; init; } public required string Version { get; init; } public required ContractType Type { get; init; } public required ContractStatus Status { get; init; } public required string SpecificationPath { get; init; } public string? Description { get; init; } public List<string> Owners { get; init; } = []; public List<string> Consumers { get; init; } = []; public DateTimeOffset CreatedAt { get; init; } public DateTimeOffset? PublishedAt { get; init; } public DateTimeOffset? DeprecatedAt { get; init; } public DateTimeOffset? SunsetAt { get; init; } }

public enum ContractType { OpenApi, AsyncApi, GraphQL, gRPC }

/// <summary> /// Tracks changes between contract versions /// </summary> public record ContractChange { public required string ContractId { get; init; } public required string FromVersion { get; init; } public required string ToVersion { get; init; } public required ChangeType Type { get; init; } public required BreakingLevel Breaking { get; init; } public required string Path { get; init; } public required string Description { get; init; } public string? MigrationGuide { get; init; } }

public enum ChangeType { Added, Modified, Deprecated, Removed }

public enum BreakingLevel { None, Minor, // Backward compatible Major // Breaking change }

/// <summary> /// Contract validation result /// </summary> public record ContractValidationResult { public required bool IsValid { get; init; } public List<ValidationIssue> Issues { get; init; } = []; public List<ContractChange> Changes { get; init; } = []; public bool HasBreakingChanges => Changes.Any(c => c.Breaking == BreakingLevel.Major); }

public record ValidationIssue { public required ValidationSeverity Severity { get; init; } public required string Code { get; init; } public required string Message { get; init; } public required string Path { get; init; } public string? Suggestion { get; init; } }

public enum ValidationSeverity { Error, Warning, Info }

/// <summary> /// Consumer contract registration /// </summary> public record ConsumerContract { public required string ConsumerId { get; init; } public required string ConsumerName { get; init; } public required string ProviderId { get; init; } public required string ProviderVersion { get; init; } public List<string> UsedEndpoints { get; init; } = []; public List<string> UsedSchemas { get; init; } = []; public DateTimeOffset RegisteredAt { get; init; } public DateTimeOffset? LastVerifiedAt { get; init; } }

/// <summary> /// Service for contract management /// </summary> public interface IContractService { Task<ApiContract> CreateContractAsync(CreateContractRequest request); Task<ApiContract> GetContractAsync(string id); Task<IReadOnlyList<ApiContract>> ListContractsAsync(ContractFilter? filter = null); Task<ContractValidationResult> ValidateContractAsync(string id); Task<ContractValidationResult> CompareVersionsAsync(string id, string fromVersion, string toVersion); Task PublishContractAsync(string id); Task DeprecateContractAsync(string id, DateTimeOffset sunsetDate); Task RegisterConsumerAsync(string contractId, ConsumerContract consumer); Task<IReadOnlyList<ConsumerContract>> GetConsumersAsync(string contractId); }

public record CreateContractRequest { public required string Name { get; init; } public required ContractType Type { get; init; } public required string SpecificationContent { get; init; } public string? Description { get; init; } public List<string> Owners { get; init; } = []; }

public record ContractFilter { public ContractType? Type { get; init; } public ContractStatus? Status { get; init; } public string? Owner { get; init; } public string? Consumer { get; init; } }

Contract Testing

Provider Verification

provider_verification: description: "Verify implementation matches specification"

approaches: schema_validation: description: "Validate request/response against spec" tools: - "express-openapi-validator" - "NSwag middleware" - "Spectral"

contract_tests:
  description: "Test endpoints match spec exactly"
  tools:
    - "Dredd"
    - "Schemathesis"
    - "Prism"

dotnet_example: integration_test: | [Fact] public async Task GetOrder_ReturnsValidResponse() { // Arrange var spec = await OpenApiDocument.FromFileAsync("specs/order-service.yaml"); var validator = new OpenApiValidator(spec);

      // Act
      var response = await _client.GetAsync("/orders/123");
      var body = await response.Content.ReadAsStringAsync();

      // Assert
      var result = validator.ValidateResponse(
          "/orders/{orderId}",
          "get",
          (int)response.StatusCode,
          body);

      Assert.True(result.IsValid, result.ErrorMessage);
  }

ci_pipeline: steps: - "Load OpenAPI/AsyncAPI spec" - "Start application under test" - "Run contract tests against all endpoints" - "Fail build if any contract violation"

Consumer-Driven Contracts

consumer_driven_contracts: description: "Consumers define expected provider behavior"

workflow: 1_consumer_defines: action: "Consumer creates contract with expected interactions" artifact: "Pact file or similar contract"

2_provider_verifies:
  action: "Provider runs consumer contracts"
  validation: "Provider can satisfy all consumer expectations"

3_publish:
  action: "Publish verified contracts to broker"
  enables: "Can-I-Deploy checks"

pact_example: consumer_test: | [Fact] public async Task GetOrder_ExpectedBehavior() { var pact = Pact.V3("OrderConsumer", "OrderProvider");

      pact.Given("Order 123 exists")
          .UponReceiving("A request for order 123")
          .WithRequest(HttpMethod.Get, "/orders/123")
          .WillRespond()
          .WithStatus(200)
          .WithJsonBody(new
          {
              id = "123",
              status = Match.Type("pending"),
              totalAmount = Match.Decimal(99.99m)
          });

      await pact.VerifyAsync(async ctx =>
      {
          var client = new OrderClient(ctx.MockServerUri);
          var order = await client.GetOrderAsync("123");
          Assert.NotNull(order);
      });
  }

asyncapi_contracts: approach: "Message schema contracts" verification: - "Producer publishes valid messages" - "Consumer can deserialize all message versions" - "Schema registry enforces compatibility"

API Governance

Style Guidelines

api_style_guidelines: naming: resources: - "Use plural nouns (users, orders, products)" - "Use kebab-case for multi-word (order-items)" - "Avoid verbs in resource names"

operations:
  - "operationId: camelCase (getUser, createOrder)"
  - "Consistent verb usage across APIs"

fields:
  - "camelCase for JSON properties"
  - "Consistent date format (ISO 8601)"
  - "Use standard field names (id, createdAt, updatedAt)"

structure: versioning: "URL path versioning (/v1/)" pagination: "Cursor-based or offset, consistent approach" errors: "RFC 7807 Problem Details" filtering: "Query parameters with consistent naming"

security: authentication: "OAuth 2.0 / API Key as standard" authorization: "Scopes documented in spec" sensitive_data: "Never in URL parameters"

documentation: required: - "Summary for every operation" - "Description for complex operations" - "Examples for request/response bodies" - "Error response documentation"

Automated Enforcement

automated_enforcement: linting: tools: - "Spectral (OpenAPI)" - "AsyncAPI Studio" - "Redocly CLI"

spectral_rules: |
  extends: ["spectral:oas", "spectral:asyncapi"]

  rules:
    operation-operationId:
      severity: error
    operation-summary:
      severity: error
    operation-tags:
      severity: warn
    info-contact:
      severity: error
    response-error-format:
      description: "Errors must use RFC 7807"
      severity: error
      given: "$.paths.*.*.responses[?(@property >= '400')]"
      then:
        field: content.application/problem+json
        function: truthy

breaking_change_detection: ci_step: | - name: Check Breaking Changes run: | oasdiff breaking
--base main:specs/api.yaml
--revision HEAD:specs/api.yaml
--fail-on ERR

pre_commit_hooks: config: | repos: - repo: local hooks: - id: lint-openapi name: Lint OpenAPI entry: spectral lint specs/**/*.yaml language: node types: [yaml]

API Catalog

api_catalog: purpose: "Central registry of all API contracts"

features: discovery: "Find APIs by name, domain, capability" documentation: "Auto-generated from specs" versioning: "Track all versions and changes" dependencies: "Consumer/provider relationships" metrics: "Usage, errors, latency"

metadata_per_api: identity: - "Name and description" - "Owner team" - "Domain/capability" lifecycle: - "Current version" - "Status (draft/published/deprecated)" - "Sunset date if deprecated" consumers: - "Registered consumers" - "Usage statistics" quality: - "Documentation score" - "Test coverage" - "Breaking change history"

integration: specification_source: "Git repository" ci_cd: "Publish on merge to main" portal: "Developer portal generation"

Validation Checklist

contract_first_checklist: pre_design: - "Consumer use cases documented" - "Resource model defined" - "Authentication/authorization strategy chosen" - "Versioning strategy agreed"

specification: - "Valid OpenAPI/AsyncAPI syntax" - "Passes linting rules" - "All operations have operationId" - "Examples provided for complex types" - "Error responses documented" - "Security schemes defined"

review: - "Consumer representatives reviewed" - "No unnecessary breaking changes" - "Backward compatibility verified" - "Documentation complete"

implementation: - "Generated stubs used" - "Contract tests passing" - "Response validation enabled" - "Schema changes go through spec first"

publication: - "Changelog updated" - "Catalog entry created" - "Consumers notified" - "Deprecation warnings if applicable"

References

  • Related skill: openapi-authoring

  • OpenAPI specification authoring

  • Related skill: asyncapi-authoring

  • AsyncAPI specification authoring

  • Related skill: gherkin-authoring

  • Acceptance criteria in Gherkin format

Last Updated: 2025-12-26

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

design-thinking

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

plantuml-syntax

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

system-prompt-engineering

No summary provided by upstream source.

Repository SourceNeeds Review