-
Notifications
You must be signed in to change notification settings - Fork 0
ci: add contract lint and example gate #11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
f58893b
24b24a5
790a214
e38c941
2c01992
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| # Changelog | ||
|
|
||
| All notable contract releases are recorded here. Contract tags are immutable; | ||
| corrections require a new patch tag and must not be moved in place. | ||
|
|
||
| ## [1.0.0-draft] - 2026-07-25 | ||
|
|
||
| Initial reviewed draft for the proven Device and Command public slice. | ||
|
|
||
| ### Added | ||
|
|
||
| - canonical public device and command identifiers; | ||
| - tenant-scoped device listing, lookup, creation and command operations; | ||
| - `application/problem+json` error responses with correlation IDs; | ||
| - canonical event envelope and device lifecycle event definitions; | ||
| - compatibility policy and public OpenAPI compatibility gate. | ||
|
|
||
| ### Explicitly not released | ||
|
|
||
| Tenant provisioning, partner credentials, webhooks, telemetry, billing and | ||
| privileged administration remain outside this draft until their contracts and | ||
| runtime parity evidence are reviewed. | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| # Contract compatibility matrix | ||
|
|
||
| This matrix records the contract version and verification boundary for each | ||
| consumer. A draft tag is immutable, but it is not a production support claim. | ||
|
|
||
| | Surface | Contract source | Version | Compatibility gate | Current status | | ||
| | --- | --- | --- | --- | --- | | ||
| | Public HTTP API | `openapi/corelink-public-v1.yaml` | `1.0.0-draft` | OpenAPI syntax + public diff checker | Draft reviewed; runtime parity is a separate gate | | ||
| | Admin HTTP API | `openapi/corelink-admin-v1.yaml` | `1.0.0-draft` | OpenAPI syntax + authorization review | Internal draft; not a public release | | ||
| | Internal HTTP API | `openapi/corelink-internal-v1.yaml` | `1.0.0-draft` | OpenAPI syntax + service ownership review | Internal draft; not a public release | | ||
|
Comment on lines
+9
to
+10
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
These rows state that the admin and internal contracts have OpenAPI syntax gates, but the pull-request path filters in Useful? React with 👍 / 👎. |
||
| | Events | `asyncapi/corelink-events-v1.yaml` | `1.0.0-draft` | AsyncAPI validation + event envelope review | Draft; delivery/replay evidence remains platform-owned | | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The checked workflow only calls Useful? React with 👍 / 👎. |
||
| | Python/TypeScript/Java SDKs | Generated or hand-written consumers | N/A | Contract version pinned per release | No stable SDK release claim for this draft | | ||
| | CLI, mock server and MCP server | Consumer repositories | N/A | Runtime parity and examples | Must consume a reviewed tag before beta | | ||
|
|
||
| ## Release rules | ||
|
|
||
| 1. Each released row must point to an immutable Git tag. | ||
| 2. Additive changes within the same major version require a new minor or patch | ||
| tag and a changelog entry. | ||
| 3. Breaking changes require a new major contract document and migration notes. | ||
| 4. A contract tag is not a runtime release until the corresponding consumer | ||
| parity checks and operational evidence are attached to the release record. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| #!/usr/bin/env ruby | ||
| # frozen_string_literal: true | ||
|
|
||
| # Small dependency-free contract lint. It catches incomplete operations before | ||
| # a full OpenAPI/AsyncAPI validator is introduced in the contract toolchain. | ||
|
|
||
| require "json" | ||
| require "yaml" | ||
|
|
||
| PUBLIC_SPEC = "openapi/corelink-public-v1.yaml" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When a breaking change is correctly introduced in a new document such as Useful? React with 👍 / 👎. |
||
| OPERATIONS = %w[get put post patch delete head options].freeze | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
OpenAPI 3.1.1 permits Useful? React with 👍 / 👎. |
||
|
|
||
| spec = YAML.safe_load(File.read(PUBLIC_SPEC), permitted_classes: [], aliases: false) | ||
| errors = [] | ||
| paths = spec.fetch("paths", {}) | ||
| errors << "public contract must declare paths" if paths.empty? | ||
|
|
||
| paths.each do |path, path_item| | ||
| OPERATIONS.each do |method| | ||
| operation = path_item[method] | ||
|
Comment on lines
+18
to
+20
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
OpenAPI 3.1 permits a path entry to reference a reusable Path Item, but this loop only inspects HTTP-method keys directly present on the entry. If an operation is moved under a Useful? React with 👍 / 👎. |
||
| next unless operation | ||
|
|
||
| location = "#{method.upcase} #{path}" | ||
| errors << "#{location}: missing operationId" if operation["operationId"].to_s.empty? | ||
| errors << "#{location}: missing x-corelink-stability" if operation["x-corelink-stability"].to_s.empty? | ||
| errors << "#{location}: missing responses" if operation.fetch("responses", {}).empty? | ||
| end | ||
| end | ||
|
|
||
| %w[ | ||
| postman/corelink-public-v1.postman_collection.json | ||
| postman/corelink-public-v1.postman_environment.json | ||
| ].each do |path| | ||
| JSON.parse(File.read(path)) | ||
| rescue JSON::ParserError => error | ||
| errors << "#{path}: invalid JSON (#{error.message})" | ||
| end | ||
|
|
||
| if errors.empty? | ||
| puts "Contract lint passed." | ||
| else | ||
| warn errors.join("\n") | ||
| exit 1 | ||
| end | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reviewed repository has no
refs/tags/v1.0.0-draft, and the target commit is not pointed to by such a tag. SDK, CLI, and mock-server consumers directed here to pin the immutable baseline therefore cannot resolve it; publish the tag as part of this release or describe the draft by an existing commit until the tag is available.Useful? React with 👍 / 👎.