From a1a20264e076dfa278d60c28e01454ba43b2fe4c Mon Sep 17 00:00:00 2001 From: Gunnar Beck Nelson <52630999+GChief117@users.noreply.github.com> Date: Sun, 6 Sep 2026 22:47:50 -0700 Subject: [PATCH] Publish reconciled connector contract --- .github/workflows/ci.yml | 79 ++ README.md | 13 +- openapi.json | 1045 ++++++++++++++++- packages/python/release.sha256 | 4 +- .../src/integration_recovery/__init__.py | 22 +- packages/typescript/release.sha256 | 2 +- packages/typescript/src/index.cts | 71 +- packages/typescript/src/index.ts | 71 +- sdk/python/integration_recovery.py | 22 +- sdk/typescript/index.ts | 71 +- 10 files changed, 1342 insertions(+), 58 deletions(-) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..d0a6512 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,79 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + +permissions: + contents: read + +jobs: + contract: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 + with: + persist-credentials: false + - name: Verify public contract and SDK copies + run: | + set -euo pipefail + jq empty openapi.json + cmp sdk/typescript/index.ts packages/typescript/src/index.ts + cmp sdk/typescript/index.ts packages/typescript/src/index.cts + cmp sdk/python/integration_recovery.py packages/python/src/integration_recovery/__init__.py + grep -F 'requiredBodyFieldAlternatives: [["check"], ["checks"]]' sdk/typescript/index.ts + grep -F '"413"' openapi.json + + npm-package: + runs-on: ubuntu-latest + defaults: + run: + working-directory: packages/typescript + steps: + - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 + with: + persist-credentials: false + - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 + with: + node-version: '24.20.0' + registry-url: 'https://registry.npmjs.org' + package-manager-cache: false + - name: Build, test, and reproduce the npm archive + env: + SOURCE_DATE_EPOCH: '1788572555' + run: | + set -euo pipefail + test "$(npm --version)" = '11.19.0' + npm ci --ignore-scripts --no-audit --no-fund + npm run build + npm test + mkdir -p release-dist + npm pack --ignore-scripts --pack-destination release-dist + (cd release-dist && sha256sum -c ../release.sha256) + + pypi-package: + runs-on: ubuntu-latest + defaults: + run: + working-directory: packages/python + steps: + - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 + with: + persist-credentials: false + - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 + with: + python-version: '3.12.14' + cache: '' + - name: Build, inspect, and reproduce the Python archives + env: + SOURCE_DATE_EPOCH: '1788572555' + PYTHONNOUSERSITE: '1' + run: | + set -euo pipefail + python -m pip install --disable-pip-version-check -r requirements-release.txt + python -c "compile(open('src/integration_recovery/__init__.py', encoding='utf-8').read(), '', 'exec')" + python -m build --no-isolation --sdist --wheel + python -m twine check dist/* + PYTHONPATH=src python test/smoke.py + (cd dist && sha256sum -c ../release.sha256) diff --git a/README.md b/README.md index ac8c59a..7038304 100644 --- a/README.md +++ b/README.md @@ -81,13 +81,12 @@ curl -sS -X POST https://integrationrecovery-api.com/v1/checks \ - [TypeScript SDK](./sdk/typescript/index.ts) The request shown here is a supported runtime example and has been checked -against the deployed comparison engine. The current OpenAPI document describes -the routes and documented request shapes, but it is not authoritative for the -still-unreconciled nullable or opaque response fields. Generated/certified -connector use remains held until Development reconciles the deployed runtime, -OpenAPI, and SDK request exclusivity, required fields, response shapes, -nullability, `evaluatedAt`, and `rateLimit` behavior. This hold does not prevent -the exact direct-HTTP example above from being used. +against the deployed comparison engine. The OpenAPI document, generated SDKs, +and production runtime now agree on the exactly-one-of `check`/`checks` input, +closed repair parameters, response fields and nullability, `evaluatedAt`, +`rateLimit`, and the `413 payload_too_large` error envelope. Connector builders +can use the published contract directly; the examples above remain the fastest +way to confirm the first useful result. ## Collection scope diff --git a/openapi.json b/openapi.json index 7ef724e..c7ed42e 100644 --- a/openapi.json +++ b/openapi.json @@ -78,18 +78,44 @@ "application/json": { "schema": { "type": "object", + "required": [ + "count", + "breaking", + "checks", + "requestId" + ], + "additionalProperties": false, "properties": { "count": { - "type": "integer" + "type": "integer", + "minimum": 1, + "maximum": 50 }, "breaking": { "type": "integer", + "minimum": 0, + "maximum": 50, "description": "How many of the checks came back with verdict \"broken\"." }, "checks": { "type": "array", + "minItems": 1, + "maxItems": 50, "items": { "type": "object", + "required": [ + "integrationId", + "provider", + "verdict", + "summary", + "changes", + "repairPlan", + "rateLimit", + "sunsets", + "evaluatedAt", + "warnings" + ], + "additionalProperties": false, "properties": { "integrationId": { "type": "string" @@ -107,12 +133,67 @@ }, "summary": { "type": "object", - "description": "Totals by severity, plus counts by code and by surface." + "required": [ + "total", + "breaking", + "degraded", + "safe", + "byCode", + "bySurface" + ], + "additionalProperties": false, + "properties": { + "total": { + "type": "integer", + "minimum": 0 + }, + "breaking": { + "type": "integer", + "minimum": 0 + }, + "degraded": { + "type": "integer", + "minimum": 0 + }, + "safe": { + "type": "integer", + "minimum": 0 + }, + "byCode": { + "type": "object", + "additionalProperties": { + "type": "integer", + "minimum": 0 + }, + "description": "A map whose keys are emitted drift codes or surfaces and whose values are occurrence counts." + }, + "bySurface": { + "type": "object", + "additionalProperties": { + "type": "integer", + "minimum": 0 + }, + "description": "A map whose keys are emitted drift codes or surfaces and whose values are occurrence counts." + } + } }, "changes": { "type": "array", "items": { "type": "object", + "required": [ + "code", + "surface", + "direction", + "target", + "container", + "breaking", + "severity", + "from", + "to", + "detail" + ], + "additionalProperties": false, "properties": { "code": { "type": "string", @@ -143,7 +224,10 @@ "description": "The field path, scope, event name or endpoint the change lands on." }, "container": { - "type": "string", + "type": [ + "string", + "null" + ], "description": "An endpoint label like \"POST /v2/orders\", a webhook event name, or null for auth and rate limits." }, "breaking": { @@ -159,10 +243,16 @@ ] }, "from": { - "type": "string" + "type": [ + "string", + "null" + ] }, "to": { - "type": "string" + "type": [ + "string", + "null" + ] }, "detail": { "type": "string", @@ -174,15 +264,38 @@ }, "repairPlan": { "type": "object", + "required": [ + "steps", + "autoApplicable", + "requiresHuman", + "fullyAutomatic", + "minConfidence" + ], + "additionalProperties": false, "description": "The ordered remediation. One step per breaking or degraded change; safe changes get none.", "properties": { "steps": { "type": "array", "items": { "type": "object", + "required": [ + "change", + "action", + "phase", + "order", + "target", + "container", + "confidence", + "autoApplicable", + "requiresHuman", + "parameters", + "detail" + ], + "additionalProperties": false, "properties": { "change": { "type": "integer", + "minimum": 0, "description": "Index into `changes` of the drift this repairs." }, "action": { @@ -202,13 +315,17 @@ }, "order": { "type": "integer", + "minimum": 1, "description": "1-based. Apply in ascending order: auth before routing before schemas before throughput." }, "target": { "type": "string" }, "container": { - "type": "string" + "type": [ + "string", + "null" + ] }, "confidence": { "type": "integer", @@ -221,12 +338,207 @@ "description": "True only when applying it mechanically cannot lose information, change what you store, or weaken a security check. A repair can be high-confidence and still false here." }, "requiresHuman": { - "type": "string", + "type": [ + "string", + "null" + ], "description": "Why a human is needed. Null when autoApplicable is true." }, "parameters": { "type": "object", - "description": "Machine-readable arguments for the action." + "additionalProperties": false, + "properties": { + "from": { + "type": [ + "string", + "null" + ] + }, + "to": { + "type": [ + "string", + "null" + ] + }, + "direction": { + "type": "string", + "enum": [ + "outbound", + "inbound" + ] + }, + "path": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "string", + "integer", + "number", + "boolean", + "object", + "array", + "any" + ] + }, + "hasSuggestion": { + "type": "boolean" + }, + "suggested": { + "type": [ + "string", + "boolean", + "null" + ] + }, + "event": { + "type": [ + "string", + "null" + ] + }, + "at": { + "type": "string", + "enum": [ + "before_send", + "after_receive" + ] + }, + "removed": { + "type": "array", + "items": { + "type": "string" + } + }, + "permitted": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + } + }, + "added": { + "type": "array", + "items": { + "type": "string" + } + }, + "candidates": { + "type": "array", + "items": { + "type": "string" + } + }, + "endpoint": { + "type": [ + "string", + "null" + ] + }, + "sunsetOn": { + "type": [ + "string", + "null" + ], + "format": "date-time" + }, + "daysRemaining": { + "type": [ + "integer", + "null" + ] + }, + "field": { + "type": "string" + }, + "maxPageSize": { + "type": [ + "integer", + "null" + ], + "minimum": 1 + }, + "scope": { + "type": "string" + }, + "previousSeconds": { + "type": [ + "integer", + "null" + ], + "minimum": 1 + }, + "currentSeconds": { + "type": "integer", + "minimum": 1 + }, + "suggestedRefreshSeconds": { + "type": "integer", + "minimum": 1 + }, + "minIntervalMs": { + "type": [ + "integer", + "null" + ], + "minimum": 1 + }, + "backoff": { + "type": [ + "object", + "null" + ], + "required": [ + "initialDelayMs", + "multiplier", + "maxDelayMs", + "maxAttempts" + ], + "additionalProperties": false, + "properties": { + "initialDelayMs": { + "type": "integer", + "minimum": 1 + }, + "multiplier": { + "type": "integer", + "minimum": 1 + }, + "maxDelayMs": { + "type": "integer", + "minimum": 1 + }, + "maxAttempts": { + "type": "integer", + "minimum": 1 + } + } + }, + "permittedInObservedWindow": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "excessRequests": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "code": { + "type": "string" + }, + "target": { + "type": "string" + } + }, + "description": "Action-specific machine-readable arguments. Branch on action before reading the corresponding subset." }, "detail": { "type": "string" @@ -237,32 +549,209 @@ }, "autoApplicable": { "type": "integer", + "minimum": 0, "description": "Steps that can run without a human." }, "requiresHuman": { - "type": "integer" + "type": "integer", + "minimum": 0 }, "fullyAutomatic": { "type": "boolean", "description": "True only when every step is auto-applicable." }, "minConfidence": { - "type": "integer", + "type": [ + "integer", + "null" + ], + "minimum": 0, + "maximum": 100, "description": "The weakest step in the plan. Null when there are no steps." } } }, "rateLimit": { - "type": "object", - "description": "Exact integer analysis of the limit change against your observed volume, with the minimum interval and a backoff schedule. Null when neither snapshot declares a limit." + "type": [ + "object", + "null" + ], + "required": [ + "previous", + "current", + "direction", + "observedVolume", + "permittedInObservedWindow", + "excessRequests", + "headroomPct", + "willExceed", + "minIntervalMs", + "backoff" + ], + "additionalProperties": false, + "properties": { + "previous": { + "type": "object", + "required": [ + "limit", + "windowSeconds" + ], + "additionalProperties": false, + "properties": { + "limit": { + "type": "integer", + "minimum": 1 + }, + "windowSeconds": { + "type": "integer", + "minimum": 1 + } + } + }, + "current": { + "type": "object", + "required": [ + "limit", + "windowSeconds" + ], + "additionalProperties": false, + "properties": { + "limit": { + "type": "integer", + "minimum": 1 + }, + "windowSeconds": { + "type": "integer", + "minimum": 1 + } + } + }, + "direction": { + "type": "string", + "enum": [ + "reduced", + "increased", + "unchanged" + ] + }, + "observedVolume": { + "type": [ + "object", + "null" + ], + "required": [ + "requests", + "windowSeconds" + ], + "additionalProperties": false, + "properties": { + "requests": { + "type": "integer", + "minimum": 0 + }, + "windowSeconds": { + "type": "integer", + "minimum": 1 + } + } + }, + "permittedInObservedWindow": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "excessRequests": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "headroomPct": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "maximum": 100 + }, + "willExceed": { + "type": [ + "boolean", + "null" + ] + }, + "minIntervalMs": { + "type": "integer", + "minimum": 1 + }, + "backoff": { + "type": "object", + "required": [ + "initialDelayMs", + "multiplier", + "maxDelayMs", + "maxAttempts" + ], + "additionalProperties": false, + "properties": { + "initialDelayMs": { + "type": "integer", + "minimum": 1 + }, + "multiplier": { + "type": "integer", + "minimum": 1 + }, + "maxDelayMs": { + "type": "integer", + "minimum": 1 + }, + "maxAttempts": { + "type": "integer", + "minimum": 1 + } + } + } + }, + "description": "Exact integer analysis of the limit change against observed volume. Null when both snapshots do not declare a comparable limit." }, "sunsets": { "type": "array", "items": { - "type": "object" + "type": "object", + "required": [ + "endpoint", + "sunsetOn", + "daysRemaining", + "passed" + ], + "additionalProperties": false, + "properties": { + "endpoint": { + "type": "string" + }, + "sunsetOn": { + "type": "string", + "format": "date-time" + }, + "daysRemaining": { + "type": "integer" + }, + "passed": { + "type": "boolean" + } + } }, "description": "Every current endpoint with a sunset date, soonest first, in whole UTC days." }, + "evaluatedAt": { + "type": "string", + "format": "date-time", + "description": "The exact instant used for deterministic sunset evaluation." + }, "warnings": { "type": "array", "items": { @@ -272,6 +761,10 @@ } } } + }, + "requestId": { + "type": "string", + "format": "uuid" } } } @@ -284,6 +777,9 @@ "401": { "$ref": "#/components/responses/Error" }, + "413": { + "$ref": "#/components/responses/Error" + }, "429": { "$ref": "#/components/responses/Error" }, @@ -297,6 +793,18 @@ "application/json": { "schema": { "type": "object", + "oneOf": [ + { + "required": [ + "check" + ] + }, + { + "required": [ + "checks" + ] + } + ], "properties": { "check": { "type": "object", @@ -1890,9 +2398,27 @@ "application/json": { "schema": { "type": "object", + "required": [ + "check", + "requestId" + ], + "additionalProperties": false, "properties": { "check": { "type": "object", + "required": [ + "integrationId", + "provider", + "verdict", + "summary", + "changes", + "repairPlan", + "rateLimit", + "sunsets", + "evaluatedAt", + "warnings" + ], + "additionalProperties": false, "properties": { "integrationId": { "type": "string" @@ -1910,12 +2436,67 @@ }, "summary": { "type": "object", - "description": "Totals by severity, plus counts by code and by surface." + "required": [ + "total", + "breaking", + "degraded", + "safe", + "byCode", + "bySurface" + ], + "additionalProperties": false, + "properties": { + "total": { + "type": "integer", + "minimum": 0 + }, + "breaking": { + "type": "integer", + "minimum": 0 + }, + "degraded": { + "type": "integer", + "minimum": 0 + }, + "safe": { + "type": "integer", + "minimum": 0 + }, + "byCode": { + "type": "object", + "additionalProperties": { + "type": "integer", + "minimum": 0 + }, + "description": "A map whose keys are emitted drift codes or surfaces and whose values are occurrence counts." + }, + "bySurface": { + "type": "object", + "additionalProperties": { + "type": "integer", + "minimum": 0 + }, + "description": "A map whose keys are emitted drift codes or surfaces and whose values are occurrence counts." + } + } }, "changes": { "type": "array", "items": { "type": "object", + "required": [ + "code", + "surface", + "direction", + "target", + "container", + "breaking", + "severity", + "from", + "to", + "detail" + ], + "additionalProperties": false, "properties": { "code": { "type": "string", @@ -1946,7 +2527,10 @@ "description": "The field path, scope, event name or endpoint the change lands on." }, "container": { - "type": "string", + "type": [ + "string", + "null" + ], "description": "An endpoint label like \"POST /v2/orders\", a webhook event name, or null for auth and rate limits." }, "breaking": { @@ -1962,10 +2546,16 @@ ] }, "from": { - "type": "string" + "type": [ + "string", + "null" + ] }, "to": { - "type": "string" + "type": [ + "string", + "null" + ] }, "detail": { "type": "string", @@ -1977,15 +2567,38 @@ }, "repairPlan": { "type": "object", + "required": [ + "steps", + "autoApplicable", + "requiresHuman", + "fullyAutomatic", + "minConfidence" + ], + "additionalProperties": false, "description": "The ordered remediation. One step per breaking or degraded change; safe changes get none.", "properties": { "steps": { "type": "array", "items": { "type": "object", + "required": [ + "change", + "action", + "phase", + "order", + "target", + "container", + "confidence", + "autoApplicable", + "requiresHuman", + "parameters", + "detail" + ], + "additionalProperties": false, "properties": { "change": { "type": "integer", + "minimum": 0, "description": "Index into `changes` of the drift this repairs." }, "action": { @@ -2005,13 +2618,17 @@ }, "order": { "type": "integer", + "minimum": 1, "description": "1-based. Apply in ascending order: auth before routing before schemas before throughput." }, "target": { "type": "string" }, "container": { - "type": "string" + "type": [ + "string", + "null" + ] }, "confidence": { "type": "integer", @@ -2024,12 +2641,207 @@ "description": "True only when applying it mechanically cannot lose information, change what you store, or weaken a security check. A repair can be high-confidence and still false here." }, "requiresHuman": { - "type": "string", + "type": [ + "string", + "null" + ], "description": "Why a human is needed. Null when autoApplicable is true." }, "parameters": { "type": "object", - "description": "Machine-readable arguments for the action." + "additionalProperties": false, + "properties": { + "from": { + "type": [ + "string", + "null" + ] + }, + "to": { + "type": [ + "string", + "null" + ] + }, + "direction": { + "type": "string", + "enum": [ + "outbound", + "inbound" + ] + }, + "path": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "string", + "integer", + "number", + "boolean", + "object", + "array", + "any" + ] + }, + "hasSuggestion": { + "type": "boolean" + }, + "suggested": { + "type": [ + "string", + "boolean", + "null" + ] + }, + "event": { + "type": [ + "string", + "null" + ] + }, + "at": { + "type": "string", + "enum": [ + "before_send", + "after_receive" + ] + }, + "removed": { + "type": "array", + "items": { + "type": "string" + } + }, + "permitted": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + } + }, + "added": { + "type": "array", + "items": { + "type": "string" + } + }, + "candidates": { + "type": "array", + "items": { + "type": "string" + } + }, + "endpoint": { + "type": [ + "string", + "null" + ] + }, + "sunsetOn": { + "type": [ + "string", + "null" + ], + "format": "date-time" + }, + "daysRemaining": { + "type": [ + "integer", + "null" + ] + }, + "field": { + "type": "string" + }, + "maxPageSize": { + "type": [ + "integer", + "null" + ], + "minimum": 1 + }, + "scope": { + "type": "string" + }, + "previousSeconds": { + "type": [ + "integer", + "null" + ], + "minimum": 1 + }, + "currentSeconds": { + "type": "integer", + "minimum": 1 + }, + "suggestedRefreshSeconds": { + "type": "integer", + "minimum": 1 + }, + "minIntervalMs": { + "type": [ + "integer", + "null" + ], + "minimum": 1 + }, + "backoff": { + "type": [ + "object", + "null" + ], + "required": [ + "initialDelayMs", + "multiplier", + "maxDelayMs", + "maxAttempts" + ], + "additionalProperties": false, + "properties": { + "initialDelayMs": { + "type": "integer", + "minimum": 1 + }, + "multiplier": { + "type": "integer", + "minimum": 1 + }, + "maxDelayMs": { + "type": "integer", + "minimum": 1 + }, + "maxAttempts": { + "type": "integer", + "minimum": 1 + } + } + }, + "permittedInObservedWindow": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "excessRequests": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "code": { + "type": "string" + }, + "target": { + "type": "string" + } + }, + "description": "Action-specific machine-readable arguments. Branch on action before reading the corresponding subset." }, "detail": { "type": "string" @@ -2040,32 +2852,209 @@ }, "autoApplicable": { "type": "integer", + "minimum": 0, "description": "Steps that can run without a human." }, "requiresHuman": { - "type": "integer" + "type": "integer", + "minimum": 0 }, "fullyAutomatic": { "type": "boolean", "description": "True only when every step is auto-applicable." }, "minConfidence": { - "type": "integer", + "type": [ + "integer", + "null" + ], + "minimum": 0, + "maximum": 100, "description": "The weakest step in the plan. Null when there are no steps." } } }, "rateLimit": { - "type": "object", - "description": "Exact integer analysis of the limit change against your observed volume, with the minimum interval and a backoff schedule. Null when neither snapshot declares a limit." + "type": [ + "object", + "null" + ], + "required": [ + "previous", + "current", + "direction", + "observedVolume", + "permittedInObservedWindow", + "excessRequests", + "headroomPct", + "willExceed", + "minIntervalMs", + "backoff" + ], + "additionalProperties": false, + "properties": { + "previous": { + "type": "object", + "required": [ + "limit", + "windowSeconds" + ], + "additionalProperties": false, + "properties": { + "limit": { + "type": "integer", + "minimum": 1 + }, + "windowSeconds": { + "type": "integer", + "minimum": 1 + } + } + }, + "current": { + "type": "object", + "required": [ + "limit", + "windowSeconds" + ], + "additionalProperties": false, + "properties": { + "limit": { + "type": "integer", + "minimum": 1 + }, + "windowSeconds": { + "type": "integer", + "minimum": 1 + } + } + }, + "direction": { + "type": "string", + "enum": [ + "reduced", + "increased", + "unchanged" + ] + }, + "observedVolume": { + "type": [ + "object", + "null" + ], + "required": [ + "requests", + "windowSeconds" + ], + "additionalProperties": false, + "properties": { + "requests": { + "type": "integer", + "minimum": 0 + }, + "windowSeconds": { + "type": "integer", + "minimum": 1 + } + } + }, + "permittedInObservedWindow": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "excessRequests": { + "type": [ + "integer", + "null" + ], + "minimum": 0 + }, + "headroomPct": { + "type": [ + "integer", + "null" + ], + "minimum": 0, + "maximum": 100 + }, + "willExceed": { + "type": [ + "boolean", + "null" + ] + }, + "minIntervalMs": { + "type": "integer", + "minimum": 1 + }, + "backoff": { + "type": "object", + "required": [ + "initialDelayMs", + "multiplier", + "maxDelayMs", + "maxAttempts" + ], + "additionalProperties": false, + "properties": { + "initialDelayMs": { + "type": "integer", + "minimum": 1 + }, + "multiplier": { + "type": "integer", + "minimum": 1 + }, + "maxDelayMs": { + "type": "integer", + "minimum": 1 + }, + "maxAttempts": { + "type": "integer", + "minimum": 1 + } + } + } + }, + "description": "Exact integer analysis of the limit change against observed volume. Null when both snapshots do not declare a comparable limit." }, "sunsets": { "type": "array", "items": { - "type": "object" + "type": "object", + "required": [ + "endpoint", + "sunsetOn", + "daysRemaining", + "passed" + ], + "additionalProperties": false, + "properties": { + "endpoint": { + "type": "string" + }, + "sunsetOn": { + "type": "string", + "format": "date-time" + }, + "daysRemaining": { + "type": "integer" + }, + "passed": { + "type": "boolean" + } + } }, "description": "Every current endpoint with a sunset date, soonest first, in whole UTC days." }, + "evaluatedAt": { + "type": "string", + "format": "date-time", + "description": "The exact instant used for deterministic sunset evaluation." + }, "warnings": { "type": "array", "items": { @@ -2074,6 +3063,10 @@ "description": "Usually a piece of usage data that was not supplied, and the severity we refused to lower because of it." } } + }, + "requestId": { + "type": "string", + "format": "uuid" } } } @@ -3425,7 +4418,7 @@ } }, "example": { - "token": "EXAMPLE_CLAIM_TOKEN_NOT_A_SECRET" + "token": "eyJ2IjoxLCJlIjoieW91QGV4YW1wbGUuY29tIn0.ZXhhbXBsZQ" } } } diff --git a/packages/python/release.sha256 b/packages/python/release.sha256 index e3ec24f..963594e 100644 --- a/packages/python/release.sha256 +++ b/packages/python/release.sha256 @@ -1,2 +1,2 @@ -dbbcdfbba6dff548096559aa97d2563c18c4574532efce71b2927c31e82f6fe0 integration_recovery-1.0.0-py3-none-any.whl -bca8e3f735bcc7a7e45cb6f7d9cc9a42b85cb7a2e462f8d47da25bc4572267e0 integration_recovery-1.0.0.tar.gz +6a4f65a94b506ff49dca29b375ae2a36f9ce9ec15df191fbab8c7f7ea2ba94ec integration_recovery-1.0.0-py3-none-any.whl +cf5352e07c7d426364497de608cdbda55090b67918d56925c999cf6ebe446912 integration_recovery-1.0.0.tar.gz diff --git a/packages/python/src/integration_recovery/__init__.py b/packages/python/src/integration_recovery/__init__.py index de3d3fc..14dc66a 100644 --- a/packages/python/src/integration_recovery/__init__.py +++ b/packages/python/src/integration_recovery/__init__.py @@ -254,6 +254,7 @@ def create_key( "path_params": (), "query_params": (), "required_body_fields": (), + "required_body_field_alternatives": (), "success_status": 200, "response_fields": (), }, @@ -267,6 +268,7 @@ def create_key( "path_params": (), "query_params": (), "required_body_fields": (), + "required_body_field_alternatives": (), "success_status": 200, "response_fields": (), }, @@ -280,6 +282,7 @@ def create_key( "path_params": (), "query_params": (), "required_body_fields": (), + "required_body_field_alternatives": (), "success_status": 200, "response_fields": (), }, @@ -293,6 +296,7 @@ def create_key( "path_params": (), "query_params": (), "required_body_fields": ("tier",), + "required_body_field_alternatives": (), "success_status": 200, "response_fields": ("checkoutUrl", "tier", "sku", "requestId"), }, @@ -306,8 +310,9 @@ def create_key( "path_params": (), "query_params": (), "required_body_fields": (), + "required_body_field_alternatives": (("check",), ("checks",)), "success_status": 200, - "response_fields": ("count", "breaking", "checks"), + "response_fields": ("count", "breaking", "checks", "requestId"), }, { "operation_id": "postV1DemoCheck", @@ -319,8 +324,9 @@ def create_key( "path_params": (), "query_params": (), "required_body_fields": ("check",), + "required_body_field_alternatives": (), "success_status": 200, - "response_fields": ("check",), + "response_fields": ("check", "requestId"), }, { "operation_id": "getV1DriftTypes", @@ -332,6 +338,7 @@ def create_key( "path_params": (), "query_params": (), "required_body_fields": (), + "required_body_field_alternatives": (), "success_status": 200, "response_fields": ("directions", "severities", "verdicts", "driftCodes", "repairPhases", "repairActions", "rules", "limits"), }, @@ -345,6 +352,7 @@ def create_key( "path_params": (), "query_params": (), "required_body_fields": (), + "required_body_field_alternatives": (), "success_status": 200, "response_fields": ("product", "count", "note", "invoices", "requestId"), }, @@ -358,6 +366,7 @@ def create_key( "path_params": (), "query_params": (), "required_body_fields": (), + "required_body_field_alternatives": (), "success_status": 200, "response_fields": ("product", "accountId", "keys", "requestId"), }, @@ -371,6 +380,7 @@ def create_key( "path_params": (), "query_params": (), "required_body_fields": ("email",), + "required_body_field_alternatives": (), "success_status": 202, "response_fields": ("status", "email", "expiresAt", "next", "message", "requestId"), }, @@ -384,6 +394,7 @@ def create_key( "path_params": ("id",), "query_params": (), "required_body_fields": (), + "required_body_field_alternatives": (), "success_status": 200, "response_fields": ("id", "status", "message", "requestId"), }, @@ -397,6 +408,7 @@ def create_key( "path_params": ("id",), "query_params": (), "required_body_fields": (), + "required_body_field_alternatives": (), "success_status": 201, "response_fields": ("apiKey", "keyId", "replaced", "product", "quotaPerPeriod", "plan", "warning", "requestId"), }, @@ -410,6 +422,7 @@ def create_key( "path_params": (), "query_params": (), "required_body_fields": ("token",), + "required_body_field_alternatives": (), "success_status": 201, "response_fields": ("apiKey", "keyId", "product", "quotaPerPeriod", "plan", "warning", "usage", "requestId"), }, @@ -423,6 +436,7 @@ def create_key( "path_params": (), "query_params": (), "required_body_fields": (), + "required_body_field_alternatives": (), "success_status": 200, "response_fields": ("product", "count", "note", "payments", "requestId"), }, @@ -436,6 +450,7 @@ def create_key( "path_params": (), "query_params": (), "required_body_fields": (), + "required_body_field_alternatives": (), "success_status": 200, "response_fields": ("product", "subscribed", "status", "plan", "pendingPlan", "planChangesGoThrough", "baseFeeOwner", "cancellation", "tiers", "requestId"), }, @@ -449,6 +464,7 @@ def create_key( "path_params": (), "query_params": (), "required_body_fields": (), + "required_body_field_alternatives": (), "success_status": 200, "response_fields": ("canceled", "canceledAt", "entitlement", "money", "finalInvoice", "requestId"), }, @@ -462,6 +478,7 @@ def create_key( "path_params": (), "query_params": (), "required_body_fields": ("planId",), + "required_body_field_alternatives": (), "success_status": 200, "response_fields": ("changed", "direction", "from", "to", "entitlement", "billing", "requestId"), }, @@ -475,6 +492,7 @@ def create_key( "path_params": (), "query_params": (), "required_body_fields": (), + "required_body_field_alternatives": (), "success_status": 200, "response_fields": ("product", "tier", "status", "unit", "period", "included", "used", "ceiling", "remaining", "overageSoFarMinor", "spendCapMinor", "requestId"), }, diff --git a/packages/typescript/release.sha256 b/packages/typescript/release.sha256 index ffe6bcc..cfd9586 100644 --- a/packages/typescript/release.sha256 +++ b/packages/typescript/release.sha256 @@ -1 +1 @@ -ace6fd213550c56526cd77c88439eba6d6d01b9e7cac091633252fda2b7576f9 integration-recovery-1.0.0.tgz +f90e04ad2697870921f8f1329661b21043e17e376555e0338d3ddfc426bcea7b integration-recovery-1.0.0.tgz diff --git a/packages/typescript/src/index.cts b/packages/typescript/src/index.cts index d617aed..2d75995 100644 --- a/packages/typescript/src/index.cts +++ b/packages/typescript/src/index.cts @@ -173,7 +173,8 @@ export interface Repair { */ autoApplicable: boolean requiresHuman: string | null - parameters: Record + /** Closed, contract-generated set of action-specific arguments. */ + parameters: RepairParameters detail: string } @@ -246,8 +247,8 @@ export class ApiError extends Error { this.name = 'ApiError' this.status = status this.code = code - this.requestId = requestId - this.details = details + if (requestId !== undefined) this.requestId = requestId + if (details !== undefined) this.details = details } } @@ -338,7 +339,7 @@ export class IntegrationRecovery { } /** The real engine with no key: one check, at most 5 endpoints and 60 fields. */ - async demoCheck(check: IntegrationCheckInput): Promise<{ check: IntegrationDrift }> { + async demoCheck(check: IntegrationCheckInput): Promise<{ check: IntegrationDrift; requestId: string }> { return this.request('POST', '/v1/demo/check', { check }, false) } @@ -412,6 +413,8 @@ export interface OperationDescriptor { readonly pathParams: readonly string[] readonly queryParams: readonly string[] readonly requiredBodyFields: readonly string[] + /** Alternative required-field sets from a root `oneOf`; exactly one set must be satisfied. */ + readonly requiredBodyFieldAlternatives: readonly (readonly string[])[] readonly successStatus: number | null /** Property names of the documented 2xx body. A field absent here is a field the service does not promise. */ readonly responseFields: readonly string[] @@ -432,6 +435,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: [], }, @@ -445,6 +449,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: [], }, @@ -458,6 +463,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: [], }, @@ -471,6 +477,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: ["tier"], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: ["checkoutUrl", "tier", "sku", "requestId"], }, @@ -484,8 +491,9 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [["check"], ["checks"]], successStatus: 200, - responseFields: ["count", "breaking", "checks"], + responseFields: ["count", "breaking", "checks", "requestId"], }, { operationId: "postV1DemoCheck", @@ -497,8 +505,9 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: ["check"], + requiredBodyFieldAlternatives: [], successStatus: 200, - responseFields: ["check"], + responseFields: ["check", "requestId"], }, { operationId: "getV1DriftTypes", @@ -510,6 +519,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: ["directions", "severities", "verdicts", "driftCodes", "repairPhases", "repairActions", "rules", "limits"], }, @@ -523,6 +533,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: ["product", "count", "note", "invoices", "requestId"], }, @@ -536,6 +547,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: ["product", "accountId", "keys", "requestId"], }, @@ -549,6 +561,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: ["email"], + requiredBodyFieldAlternatives: [], successStatus: 202, responseFields: ["status", "email", "expiresAt", "next", "message", "requestId"], }, @@ -562,6 +575,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: ["id"], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: ["id", "status", "message", "requestId"], }, @@ -575,6 +589,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: ["id"], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 201, responseFields: ["apiKey", "keyId", "replaced", "product", "quotaPerPeriod", "plan", "warning", "requestId"], }, @@ -588,6 +603,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: ["token"], + requiredBodyFieldAlternatives: [], successStatus: 201, responseFields: ["apiKey", "keyId", "product", "quotaPerPeriod", "plan", "warning", "usage", "requestId"], }, @@ -601,6 +617,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: ["product", "count", "note", "payments", "requestId"], }, @@ -614,6 +631,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: ["product", "subscribed", "status", "plan", "pendingPlan", "planChangesGoThrough", "baseFeeOwner", "cancellation", "tiers", "requestId"], }, @@ -627,6 +645,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: ["canceled", "canceledAt", "entitlement", "money", "finalInvoice", "requestId"], }, @@ -640,6 +659,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: ["planId"], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: ["changed", "direction", "from", "to", "entitlement", "billing", "requestId"], }, @@ -653,8 +673,47 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: ["product", "tier", "status", "unit", "period", "included", "used", "ceiling", "remaining", "overageSoFarMinor", "spendCapMinor", "requestId"], }, ] + +/** `RepairParameters` — generated from POST /v1/checks (properties/checks/items/properties/repairPlan/properties/steps/items/properties/parameters). */ +export interface RepairParameters { + from?: string | null + to?: string | null + direction?: "outbound" | "inbound" + path?: string + type?: "string" | "integer" | "number" | "boolean" | "object" | "array" | "any" + hasSuggestion?: boolean + suggested?: string | boolean | null + event?: string | null + at?: "before_send" | "after_receive" + removed?: string[] + permitted?: string[] | null + added?: string[] + candidates?: string[] + endpoint?: string | null + sunsetOn?: string | null + daysRemaining?: number | null + field?: string + maxPageSize?: number | null + scope?: string + previousSeconds?: number | null + currentSeconds?: number + suggestedRefreshSeconds?: number + minIntervalMs?: number | null + backoff?: { + initialDelayMs: number + multiplier: number + maxDelayMs: number + maxAttempts: number + } | null + permittedInObservedWindow?: number | null + excessRequests?: number | null + code?: string + target?: string +} + // ---8<--- END GENERATED BY tools/gen-sdk.mjs ---8<--- diff --git a/packages/typescript/src/index.ts b/packages/typescript/src/index.ts index d617aed..2d75995 100644 --- a/packages/typescript/src/index.ts +++ b/packages/typescript/src/index.ts @@ -173,7 +173,8 @@ export interface Repair { */ autoApplicable: boolean requiresHuman: string | null - parameters: Record + /** Closed, contract-generated set of action-specific arguments. */ + parameters: RepairParameters detail: string } @@ -246,8 +247,8 @@ export class ApiError extends Error { this.name = 'ApiError' this.status = status this.code = code - this.requestId = requestId - this.details = details + if (requestId !== undefined) this.requestId = requestId + if (details !== undefined) this.details = details } } @@ -338,7 +339,7 @@ export class IntegrationRecovery { } /** The real engine with no key: one check, at most 5 endpoints and 60 fields. */ - async demoCheck(check: IntegrationCheckInput): Promise<{ check: IntegrationDrift }> { + async demoCheck(check: IntegrationCheckInput): Promise<{ check: IntegrationDrift; requestId: string }> { return this.request('POST', '/v1/demo/check', { check }, false) } @@ -412,6 +413,8 @@ export interface OperationDescriptor { readonly pathParams: readonly string[] readonly queryParams: readonly string[] readonly requiredBodyFields: readonly string[] + /** Alternative required-field sets from a root `oneOf`; exactly one set must be satisfied. */ + readonly requiredBodyFieldAlternatives: readonly (readonly string[])[] readonly successStatus: number | null /** Property names of the documented 2xx body. A field absent here is a field the service does not promise. */ readonly responseFields: readonly string[] @@ -432,6 +435,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: [], }, @@ -445,6 +449,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: [], }, @@ -458,6 +463,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: [], }, @@ -471,6 +477,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: ["tier"], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: ["checkoutUrl", "tier", "sku", "requestId"], }, @@ -484,8 +491,9 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [["check"], ["checks"]], successStatus: 200, - responseFields: ["count", "breaking", "checks"], + responseFields: ["count", "breaking", "checks", "requestId"], }, { operationId: "postV1DemoCheck", @@ -497,8 +505,9 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: ["check"], + requiredBodyFieldAlternatives: [], successStatus: 200, - responseFields: ["check"], + responseFields: ["check", "requestId"], }, { operationId: "getV1DriftTypes", @@ -510,6 +519,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: ["directions", "severities", "verdicts", "driftCodes", "repairPhases", "repairActions", "rules", "limits"], }, @@ -523,6 +533,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: ["product", "count", "note", "invoices", "requestId"], }, @@ -536,6 +547,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: ["product", "accountId", "keys", "requestId"], }, @@ -549,6 +561,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: ["email"], + requiredBodyFieldAlternatives: [], successStatus: 202, responseFields: ["status", "email", "expiresAt", "next", "message", "requestId"], }, @@ -562,6 +575,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: ["id"], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: ["id", "status", "message", "requestId"], }, @@ -575,6 +589,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: ["id"], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 201, responseFields: ["apiKey", "keyId", "replaced", "product", "quotaPerPeriod", "plan", "warning", "requestId"], }, @@ -588,6 +603,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: ["token"], + requiredBodyFieldAlternatives: [], successStatus: 201, responseFields: ["apiKey", "keyId", "product", "quotaPerPeriod", "plan", "warning", "usage", "requestId"], }, @@ -601,6 +617,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: ["product", "count", "note", "payments", "requestId"], }, @@ -614,6 +631,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: ["product", "subscribed", "status", "plan", "pendingPlan", "planChangesGoThrough", "baseFeeOwner", "cancellation", "tiers", "requestId"], }, @@ -627,6 +645,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: ["canceled", "canceledAt", "entitlement", "money", "finalInvoice", "requestId"], }, @@ -640,6 +659,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: ["planId"], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: ["changed", "direction", "from", "to", "entitlement", "billing", "requestId"], }, @@ -653,8 +673,47 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: ["product", "tier", "status", "unit", "period", "included", "used", "ceiling", "remaining", "overageSoFarMinor", "spendCapMinor", "requestId"], }, ] + +/** `RepairParameters` — generated from POST /v1/checks (properties/checks/items/properties/repairPlan/properties/steps/items/properties/parameters). */ +export interface RepairParameters { + from?: string | null + to?: string | null + direction?: "outbound" | "inbound" + path?: string + type?: "string" | "integer" | "number" | "boolean" | "object" | "array" | "any" + hasSuggestion?: boolean + suggested?: string | boolean | null + event?: string | null + at?: "before_send" | "after_receive" + removed?: string[] + permitted?: string[] | null + added?: string[] + candidates?: string[] + endpoint?: string | null + sunsetOn?: string | null + daysRemaining?: number | null + field?: string + maxPageSize?: number | null + scope?: string + previousSeconds?: number | null + currentSeconds?: number + suggestedRefreshSeconds?: number + minIntervalMs?: number | null + backoff?: { + initialDelayMs: number + multiplier: number + maxDelayMs: number + maxAttempts: number + } | null + permittedInObservedWindow?: number | null + excessRequests?: number | null + code?: string + target?: string +} + // ---8<--- END GENERATED BY tools/gen-sdk.mjs ---8<--- diff --git a/sdk/python/integration_recovery.py b/sdk/python/integration_recovery.py index de3d3fc..14dc66a 100644 --- a/sdk/python/integration_recovery.py +++ b/sdk/python/integration_recovery.py @@ -254,6 +254,7 @@ def create_key( "path_params": (), "query_params": (), "required_body_fields": (), + "required_body_field_alternatives": (), "success_status": 200, "response_fields": (), }, @@ -267,6 +268,7 @@ def create_key( "path_params": (), "query_params": (), "required_body_fields": (), + "required_body_field_alternatives": (), "success_status": 200, "response_fields": (), }, @@ -280,6 +282,7 @@ def create_key( "path_params": (), "query_params": (), "required_body_fields": (), + "required_body_field_alternatives": (), "success_status": 200, "response_fields": (), }, @@ -293,6 +296,7 @@ def create_key( "path_params": (), "query_params": (), "required_body_fields": ("tier",), + "required_body_field_alternatives": (), "success_status": 200, "response_fields": ("checkoutUrl", "tier", "sku", "requestId"), }, @@ -306,8 +310,9 @@ def create_key( "path_params": (), "query_params": (), "required_body_fields": (), + "required_body_field_alternatives": (("check",), ("checks",)), "success_status": 200, - "response_fields": ("count", "breaking", "checks"), + "response_fields": ("count", "breaking", "checks", "requestId"), }, { "operation_id": "postV1DemoCheck", @@ -319,8 +324,9 @@ def create_key( "path_params": (), "query_params": (), "required_body_fields": ("check",), + "required_body_field_alternatives": (), "success_status": 200, - "response_fields": ("check",), + "response_fields": ("check", "requestId"), }, { "operation_id": "getV1DriftTypes", @@ -332,6 +338,7 @@ def create_key( "path_params": (), "query_params": (), "required_body_fields": (), + "required_body_field_alternatives": (), "success_status": 200, "response_fields": ("directions", "severities", "verdicts", "driftCodes", "repairPhases", "repairActions", "rules", "limits"), }, @@ -345,6 +352,7 @@ def create_key( "path_params": (), "query_params": (), "required_body_fields": (), + "required_body_field_alternatives": (), "success_status": 200, "response_fields": ("product", "count", "note", "invoices", "requestId"), }, @@ -358,6 +366,7 @@ def create_key( "path_params": (), "query_params": (), "required_body_fields": (), + "required_body_field_alternatives": (), "success_status": 200, "response_fields": ("product", "accountId", "keys", "requestId"), }, @@ -371,6 +380,7 @@ def create_key( "path_params": (), "query_params": (), "required_body_fields": ("email",), + "required_body_field_alternatives": (), "success_status": 202, "response_fields": ("status", "email", "expiresAt", "next", "message", "requestId"), }, @@ -384,6 +394,7 @@ def create_key( "path_params": ("id",), "query_params": (), "required_body_fields": (), + "required_body_field_alternatives": (), "success_status": 200, "response_fields": ("id", "status", "message", "requestId"), }, @@ -397,6 +408,7 @@ def create_key( "path_params": ("id",), "query_params": (), "required_body_fields": (), + "required_body_field_alternatives": (), "success_status": 201, "response_fields": ("apiKey", "keyId", "replaced", "product", "quotaPerPeriod", "plan", "warning", "requestId"), }, @@ -410,6 +422,7 @@ def create_key( "path_params": (), "query_params": (), "required_body_fields": ("token",), + "required_body_field_alternatives": (), "success_status": 201, "response_fields": ("apiKey", "keyId", "product", "quotaPerPeriod", "plan", "warning", "usage", "requestId"), }, @@ -423,6 +436,7 @@ def create_key( "path_params": (), "query_params": (), "required_body_fields": (), + "required_body_field_alternatives": (), "success_status": 200, "response_fields": ("product", "count", "note", "payments", "requestId"), }, @@ -436,6 +450,7 @@ def create_key( "path_params": (), "query_params": (), "required_body_fields": (), + "required_body_field_alternatives": (), "success_status": 200, "response_fields": ("product", "subscribed", "status", "plan", "pendingPlan", "planChangesGoThrough", "baseFeeOwner", "cancellation", "tiers", "requestId"), }, @@ -449,6 +464,7 @@ def create_key( "path_params": (), "query_params": (), "required_body_fields": (), + "required_body_field_alternatives": (), "success_status": 200, "response_fields": ("canceled", "canceledAt", "entitlement", "money", "finalInvoice", "requestId"), }, @@ -462,6 +478,7 @@ def create_key( "path_params": (), "query_params": (), "required_body_fields": ("planId",), + "required_body_field_alternatives": (), "success_status": 200, "response_fields": ("changed", "direction", "from", "to", "entitlement", "billing", "requestId"), }, @@ -475,6 +492,7 @@ def create_key( "path_params": (), "query_params": (), "required_body_fields": (), + "required_body_field_alternatives": (), "success_status": 200, "response_fields": ("product", "tier", "status", "unit", "period", "included", "used", "ceiling", "remaining", "overageSoFarMinor", "spendCapMinor", "requestId"), }, diff --git a/sdk/typescript/index.ts b/sdk/typescript/index.ts index d617aed..2d75995 100644 --- a/sdk/typescript/index.ts +++ b/sdk/typescript/index.ts @@ -173,7 +173,8 @@ export interface Repair { */ autoApplicable: boolean requiresHuman: string | null - parameters: Record + /** Closed, contract-generated set of action-specific arguments. */ + parameters: RepairParameters detail: string } @@ -246,8 +247,8 @@ export class ApiError extends Error { this.name = 'ApiError' this.status = status this.code = code - this.requestId = requestId - this.details = details + if (requestId !== undefined) this.requestId = requestId + if (details !== undefined) this.details = details } } @@ -338,7 +339,7 @@ export class IntegrationRecovery { } /** The real engine with no key: one check, at most 5 endpoints and 60 fields. */ - async demoCheck(check: IntegrationCheckInput): Promise<{ check: IntegrationDrift }> { + async demoCheck(check: IntegrationCheckInput): Promise<{ check: IntegrationDrift; requestId: string }> { return this.request('POST', '/v1/demo/check', { check }, false) } @@ -412,6 +413,8 @@ export interface OperationDescriptor { readonly pathParams: readonly string[] readonly queryParams: readonly string[] readonly requiredBodyFields: readonly string[] + /** Alternative required-field sets from a root `oneOf`; exactly one set must be satisfied. */ + readonly requiredBodyFieldAlternatives: readonly (readonly string[])[] readonly successStatus: number | null /** Property names of the documented 2xx body. A field absent here is a field the service does not promise. */ readonly responseFields: readonly string[] @@ -432,6 +435,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: [], }, @@ -445,6 +449,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: [], }, @@ -458,6 +463,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: [], }, @@ -471,6 +477,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: ["tier"], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: ["checkoutUrl", "tier", "sku", "requestId"], }, @@ -484,8 +491,9 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [["check"], ["checks"]], successStatus: 200, - responseFields: ["count", "breaking", "checks"], + responseFields: ["count", "breaking", "checks", "requestId"], }, { operationId: "postV1DemoCheck", @@ -497,8 +505,9 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: ["check"], + requiredBodyFieldAlternatives: [], successStatus: 200, - responseFields: ["check"], + responseFields: ["check", "requestId"], }, { operationId: "getV1DriftTypes", @@ -510,6 +519,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: ["directions", "severities", "verdicts", "driftCodes", "repairPhases", "repairActions", "rules", "limits"], }, @@ -523,6 +533,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: ["product", "count", "note", "invoices", "requestId"], }, @@ -536,6 +547,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: ["product", "accountId", "keys", "requestId"], }, @@ -549,6 +561,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: ["email"], + requiredBodyFieldAlternatives: [], successStatus: 202, responseFields: ["status", "email", "expiresAt", "next", "message", "requestId"], }, @@ -562,6 +575,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: ["id"], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: ["id", "status", "message", "requestId"], }, @@ -575,6 +589,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: ["id"], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 201, responseFields: ["apiKey", "keyId", "replaced", "product", "quotaPerPeriod", "plan", "warning", "requestId"], }, @@ -588,6 +603,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: ["token"], + requiredBodyFieldAlternatives: [], successStatus: 201, responseFields: ["apiKey", "keyId", "product", "quotaPerPeriod", "plan", "warning", "usage", "requestId"], }, @@ -601,6 +617,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: ["product", "count", "note", "payments", "requestId"], }, @@ -614,6 +631,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: ["product", "subscribed", "status", "plan", "pendingPlan", "planChangesGoThrough", "baseFeeOwner", "cancellation", "tiers", "requestId"], }, @@ -627,6 +645,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: ["canceled", "canceledAt", "entitlement", "money", "finalInvoice", "requestId"], }, @@ -640,6 +659,7 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: ["planId"], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: ["changed", "direction", "from", "to", "entitlement", "billing", "requestId"], }, @@ -653,8 +673,47 @@ export const OPERATIONS: readonly OperationDescriptor[] = [ pathParams: [], queryParams: [], requiredBodyFields: [], + requiredBodyFieldAlternatives: [], successStatus: 200, responseFields: ["product", "tier", "status", "unit", "period", "included", "used", "ceiling", "remaining", "overageSoFarMinor", "spendCapMinor", "requestId"], }, ] + +/** `RepairParameters` — generated from POST /v1/checks (properties/checks/items/properties/repairPlan/properties/steps/items/properties/parameters). */ +export interface RepairParameters { + from?: string | null + to?: string | null + direction?: "outbound" | "inbound" + path?: string + type?: "string" | "integer" | "number" | "boolean" | "object" | "array" | "any" + hasSuggestion?: boolean + suggested?: string | boolean | null + event?: string | null + at?: "before_send" | "after_receive" + removed?: string[] + permitted?: string[] | null + added?: string[] + candidates?: string[] + endpoint?: string | null + sunsetOn?: string | null + daysRemaining?: number | null + field?: string + maxPageSize?: number | null + scope?: string + previousSeconds?: number | null + currentSeconds?: number + suggestedRefreshSeconds?: number + minIntervalMs?: number | null + backoff?: { + initialDelayMs: number + multiplier: number + maxDelayMs: number + maxAttempts: number + } | null + permittedInObservedWindow?: number | null + excessRequests?: number | null + code?: string + target?: string +} + // ---8<--- END GENERATED BY tools/gen-sdk.mjs ---8<---