Readiness

Readiness Scorecard

Can I ship this API safely? One weighted verdict across schema, contract, governance, security, trace, resilience and drift — with a consolidated, deep-linked findings backlog.

0critical
14high
13medium
15low
0info
Verdict
Ship readiness
65/ 100 ready
Ship with caution

Releasable, but open findings should be triaged before a wide rollout.

Dimensions evaluated8 / 10
Total findings42
Breakdown
Category scores
Backlog
Consolidated findings42
worst severity first · deep-linked to the owning surface
SeverityCategoryFindingRemediationRefs
highContract
POST /orders declares errors but tests none
The spec declares error responses (400, 401, 409) but no scenario exercises any error path — consumers cannot verify failure handling.
contract.error-path-uncoveredPOST /orders
Add a validation/auth/error scenario asserting one of 400, 401, 409.#8, #9Fix
highContract
No scenario covers GET /orders/{id}
This endpoint has zero scenarios, so no behaviour beyond the static schema is asserted. Schema validation alone cannot prove what each input does.
contract.endpoint-uncoveredGET /orders/{id}
Author at least a happy-path scenario for GET /orders/{id} (and a validation/error scenario for unsafe methods).#8, #9, #17Fix
highContract
No scenario covers POST /orders/{id}/fulfill
This endpoint has zero scenarios, so no behaviour beyond the static schema is asserted. Schema validation alone cannot prove what each input does.
contract.endpoint-uncoveredPOST /orders/{id}/fulfill
Author at least a happy-path scenario for POST /orders/{id}/fulfill (and a validation/error scenario for unsafe methods).#8, #9, #17Fix
highSecurity
BOLA risk is untested for GET /orders/{id}
GET /orders/{id} takes an object id {id} but has no auth_error scenario proving a forbidden id is rejected. Object-level authorization is asserted in code, never in a test.
sec.bola.no-forbidden-scenarioGET /orders/{id}
Add an auth_error / forbidden-object scenario (403/404) exercising another tenant's id to lock the BOLA boundary.#24Fix
highSecurity
BOLA risk is untested for PATCH /orders/{id}
PATCH /orders/{id} takes an object id {id} but has no auth_error scenario proving a forbidden id is rejected. Object-level authorization is asserted in code, never in a test.
sec.bola.no-forbidden-scenarioPATCH /orders/{id}
Add an auth_error / forbidden-object scenario (403/404) exercising another tenant's id to lock the BOLA boundary.#24Fix
highSecurity
BOLA risk is untested for POST /orders/{id}/fulfill
POST /orders/{id}/fulfill takes an object id {id} but has no auth_error scenario proving a forbidden id is rejected. Object-level authorization is asserted in code, never in a test.
sec.bola.no-forbidden-scenarioPOST /orders/{id}/fulfill
Add an auth_error / forbidden-object scenario (403/404) exercising another tenant's id to lock the BOLA boundary.#24Fix
highTrace
No trace-context header on request
POST /orders accepts neither a W3C `traceparent` nor a correlation/request-id header. Calls to this endpoint cannot be stitched into a distributed trace — events here are orphaned from the wider flow.
trace.context.missingPOST /orders
Declare a `traceparent` (W3C Trace Context) request header, or at minimum an `x-correlation-id`, as a required header on this endpoint. Use the one-click 'Add trace headers' helper on /trace-readiness.#34, #49Fix
highTrace
No trace-context header on request
GET /orders/{id} accepts neither a W3C `traceparent` nor a correlation/request-id header. Calls to this endpoint cannot be stitched into a distributed trace — events here are orphaned from the wider flow.
trace.context.missingGET /orders/{id}
Declare a `traceparent` (W3C Trace Context) request header, or at minimum an `x-correlation-id`, as a required header on this endpoint. Use the one-click 'Add trace headers' helper on /trace-readiness.#34, #49Fix
highTrace
No trace-context header on request
PATCH /orders/{id} accepts neither a W3C `traceparent` nor a correlation/request-id header. Calls to this endpoint cannot be stitched into a distributed trace — events here are orphaned from the wider flow.
trace.context.missingPATCH /orders/{id}
Declare a `traceparent` (W3C Trace Context) request header, or at minimum an `x-correlation-id`, as a required header on this endpoint. Use the one-click 'Add trace headers' helper on /trace-readiness.#34, #49Fix
highTrace
No trace-context header on request
POST /orders/{id}/fulfill accepts neither a W3C `traceparent` nor a correlation/request-id header. Calls to this endpoint cannot be stitched into a distributed trace — events here are orphaned from the wider flow.
trace.context.missingPOST /orders/{id}/fulfill
Declare a `traceparent` (W3C Trace Context) request header, or at minimum an `x-correlation-id`, as a required header on this endpoint. Use the one-click 'Add trace headers' helper on /trace-readiness.#34, #49Fix
highResilience
POST /orders has no Idempotency-Key support
Unsafe methods without an Idempotency-Key let a client/load-balancer retry duplicate the operation — duplicated orders, double charges, inconsistent state.
resilience.no-idempotency-keyPOST /orders
Accept an "Idempotency-Key" request header and de-duplicate by it; document the header as a parameter so clients and agents discover it.#29, #31, #32Fix
highResilience
POST /orders/{id}/fulfill has no Idempotency-Key support
Unsafe methods without an Idempotency-Key let a client/load-balancer retry duplicate the operation — duplicated orders, double charges, inconsistent state.
resilience.no-idempotency-keyPOST /orders/{id}/fulfill
Accept an "Idempotency-Key" request header and de-duplicate by it; document the header as a parameter so clients and agents discover it.#29, #31, #32Fix
highDrift
No scenario covers GET /orders/{id}
This endpoint declares 2 responses but has no scenario validating any of them — the contract is unverified, so a breaking change here would pass CI undetected.
drift.spec-contract.no-scenarioGET /orders/{id}
Author at least a happy-path scenario for GET /orders/{id} (Scenarios → New) so its contract is exercised.#2, #11Fix
highDrift
No scenario covers POST /orders/{id}/fulfill
This endpoint declares 3 responses but has no scenario validating any of them — the contract is unverified, so a breaking change here would pass CI undetected.
drift.spec-contract.no-scenarioPOST /orders/{id}/fulfill
Author at least a happy-path scenario for POST /orders/{id}/fulfill (Scenarios → New) so its contract is exercised.#2, #11Fix
mediumContract
POST /orders asserts no business-rule outcome
This write endpoint only has happy-path coverage. Business semantics — which inputs are rejected and why — are not asserted, the exact gap schema validation cannot close.
contract.business-semantics-gapPOST /orders
Add a validation_error (or partial_success) scenario that asserts the business outcome for an invalid/edge input, then encode it as a Validation Engine rule.#6, #8Fix
mediumContract
PATCH /orders/{id} has uncovered success responses (200)
The spec declares 1 success status code(s) with no scenario asserting that path, so response-path coverage is incomplete.
contract.response-path-uncoveredPATCH /orders/{id}
Add scenarios returning 200 so every declared success path is exercised.#9, #18Fix
mediumContract
PATCH /orders/{id} asserts no business-rule outcome
This write endpoint only has happy-path coverage. Business semantics — which inputs are rejected and why — are not asserted, the exact gap schema validation cannot close.
contract.business-semantics-gapPATCH /orders/{id}
Add a validation_error (or partial_success) scenario that asserts the business outcome for an invalid/edge input, then encode it as a Validation Engine rule.#6, #8Fix
mediumGovernance
3 mutating endpoint(s) have no behavioural scenario
Schema validation does not capture business rules — which input yields which status code or downstream effect. These mutating endpoints have no scenario: POST /orders, PATCH /orders/{id}, POST /orders/{id}/fulfill.
gov.business.mutation-no-scenario
Author at least one scenario (happy-path + a validation/error path) per mutating endpoint so business behaviour is governed, not just the schema shape.#6, #5, #8Fix
mediumSecurity
Bulk endpoint lacks authorization scenario
POST /orders returns or mutates a collection but has no auth_error scenario. Bulk endpoints leak or alter rows across tenants when scoping is wrong (OWASP API1/API3 at scale).
sec.bola.bulk-unguardedPOST /orders
Add a bulk-authorization scenario asserting results are tenant-scoped and forbidden filters return 403.#25Fix
mediumResilience
POST /orders has no timeout/downstream-failure scenario
Dependency timeouts and downstream failures are common in service meshes but routinely under-tested. Without a scenario the degradation path is unproven.
resilience.no-failure-scenarioPOST /orders
Use the Validation Engine failure-orchestration panel to add a timeout (504) and/or downstream_failure (503) scenario.#33Fix
mediumResilience
GET /orders/{id} has no timeout/downstream-failure scenario
Dependency timeouts and downstream failures are common in service meshes but routinely under-tested. Without a scenario the degradation path is unproven.
resilience.no-failure-scenarioGET /orders/{id}
Use the Validation Engine failure-orchestration panel to add a timeout (504) and/or downstream_failure (503) scenario.#33Fix
mediumResilience
PATCH /orders/{id} has no Idempotency-Key support
Unsafe methods without an Idempotency-Key let a client/load-balancer retry duplicate the operation — duplicated orders, double charges, inconsistent state.
resilience.no-idempotency-keyPATCH /orders/{id}
Accept an "Idempotency-Key" request header and de-duplicate by it; document the header as a parameter so clients and agents discover it.#29, #31, #32Fix
mediumResilience
POST /orders/{id}/fulfill throttles without a Retry-After signal
A 429/503 response with no Retry-After header forces clients and agents to guess back-off timing, amplifying load on an already-stressed service.
resilience.no-retry-afterPOST /orders/{id}/fulfill
Declare and emit a Retry-After header on 429/503 responses so back-off is deterministic.#27, #30Fix
mediumResilience
POST /orders/{id}/fulfill has no timeout/downstream-failure scenario
Dependency timeouts and downstream failures are common in service meshes but routinely under-tested. Without a scenario the degradation path is unproven.
resilience.no-failure-scenarioPOST /orders/{id}/fulfill
Use the Validation Engine failure-orchestration panel to add a timeout (504) and/or downstream_failure (503) scenario.#33Fix
mediumAgent
Examples coverage is weak for agents (0%)
0/4 return at least one response example. Agents stall where humans guess — this lowers automated-consumer readiness.
agent.examples
Add response examples so agents can infer payloads.#17, #46Fix
mediumAgent
Error-model clarity is weak for agents (25%)
1/4 declare both 4xx and 5xx classes. Agents stall where humans guess — this lowers automated-consumer readiness.
agent.errors
Declare 4xx and 5xx responses so agents handle failure deterministically.#8, #46Fix
mediumAgent
Idempotency hints is weak for agents (0%)
0/3 mutators declare Idempotency-Key. Agents stall where humans guess — this lowers automated-consumer readiness.
agent.idempotency
Accept an Idempotency-Key header on POST/PATCH so retries are safe.#29, #31, #46Fix
lowGovernance
Schema ships no example
Schema "OrderItem" (7 fields) has no example payload. Without examples, docs are harder to read and test-data generation is guesswork.
gov.examples.schema-no-example
Add a representative `example` to "OrderItem" — it doubles as documentation and a scenario / mock seed.#17, #39Fix
lowGovernance
Success response has no example
POST /orders returns 201 but ships no response example. Consumers cannot see the expected shape without calling the live API.
gov.examples.operation-no-examplePOST /orders
Attach at least one example to the success response of POST /orders (a Data Pack or generated mock can seed it).#17Fix
lowGovernance
Success response has no example
GET /orders/{id} returns 200 but ships no response example. Consumers cannot see the expected shape without calling the live API.
gov.examples.operation-no-exampleGET /orders/{id}
Attach at least one example to the success response of GET /orders/{id} (a Data Pack or generated mock can seed it).#17Fix
lowGovernance
Success response has no example
PATCH /orders/{id} returns 200 but ships no response example. Consumers cannot see the expected shape without calling the live API.
gov.examples.operation-no-examplePATCH /orders/{id}
Attach at least one example to the success response of PATCH /orders/{id} (a Data Pack or generated mock can seed it).#17Fix
lowGovernance
Success response has no example
POST /orders/{id}/fulfill returns 202 but ships no response example. Consumers cannot see the expected shape without calling the live API.
gov.examples.operation-no-examplePOST /orders/{id}/fulfill
Attach at least one example to the success response of POST /orders/{id}/fulfill (a Data Pack or generated mock can seed it).#17Fix
lowSecurity
No rate-limit signalling
POST /orders declares no 429 response, no per-status throttle behaviour and no rate_limit scenario. Without resource/rate limiting the endpoint is an abuse target (OWASP API4).
sec.ratelimit.no-signallingPOST /orders
Document a 429 response with Retry-After and add a rate_limit scenario so clients can be proven to back off.#26Fix
lowSecurity
No negative / fuzz scenario
POST /orders has no validation_error, auth_error or rate_limit scenario. Only happy-path behaviour is asserted, so malformed and hostile input is untested (dynamic security testing gap).
sec.fuzz.no-negative-scenarioPOST /orders
Add at least one negative scenario (malformed body → 400, missing auth → 401/403) to cover hostile input.#41Fix
lowSecurity
No rate-limit signalling
GET /orders/{id} declares no 429 response, no per-status throttle behaviour and no rate_limit scenario. Without resource/rate limiting the endpoint is an abuse target (OWASP API4).
sec.ratelimit.no-signallingGET /orders/{id}
Document a 429 response with Retry-After and add a rate_limit scenario so clients can be proven to back off.#26Fix
lowSecurity
No negative / fuzz scenario
GET /orders/{id} has no validation_error, auth_error or rate_limit scenario. Only happy-path behaviour is asserted, so malformed and hostile input is untested (dynamic security testing gap).
sec.fuzz.no-negative-scenarioGET /orders/{id}
Add at least one negative scenario (malformed body → 400, missing auth → 401/403) to cover hostile input.#41Fix
lowSecurity
No rate-limit signalling
PATCH /orders/{id} declares no 429 response, no per-status throttle behaviour and no rate_limit scenario. Without resource/rate limiting the endpoint is an abuse target (OWASP API4).
sec.ratelimit.no-signallingPATCH /orders/{id}
Document a 429 response with Retry-After and add a rate_limit scenario so clients can be proven to back off.#26Fix
lowSecurity
No negative / fuzz scenario
PATCH /orders/{id} has no validation_error, auth_error or rate_limit scenario. Only happy-path behaviour is asserted, so malformed and hostile input is untested (dynamic security testing gap).
sec.fuzz.no-negative-scenarioPATCH /orders/{id}
Add at least one negative scenario (malformed body → 400, missing auth → 401/403) to cover hostile input.#41Fix
lowSecurity
No rate-limit signalling
POST /orders/{id}/fulfill declares no 429 response, no per-status throttle behaviour and no rate_limit scenario. Without resource/rate limiting the endpoint is an abuse target (OWASP API4).
sec.ratelimit.no-signallingPOST /orders/{id}/fulfill
Document a 429 response with Retry-After and add a rate_limit scenario so clients can be proven to back off.#26Fix
lowSecurity
No negative / fuzz scenario
POST /orders/{id}/fulfill has no validation_error, auth_error or rate_limit scenario. Only happy-path behaviour is asserted, so malformed and hostile input is untested (dynamic security testing gap).
sec.fuzz.no-negative-scenarioPOST /orders/{id}/fulfill
Add at least one negative scenario (malformed body → 400, missing auth → 401/403) to cover hostile input.#41Fix
lowTrace
No scenario asserts trace headers
This API has 2 scenario(s), but none set or assert a trace/correlation header. Observability isn't wired into the validation pipeline, so trace regressions ship undetected.
trace.observability.no_scenario
Add a scenario that injects a `traceparent`/`x-correlation-id` header and asserts the id is echoed on the response, turning trace readiness into a pre-release gate.#37Fix
lowDrift
Success response uncovered on PATCH /orders/{id}
Declared success response 200 has no scenario — coverage drift the green pipeline does not reveal.
drift.spec-contract.partial-coveragePATCH /orders/{id}
Add a scenario asserting 200 on PATCH /orders/{id}.#2, #11Fix
How it scores
Overall is the weight-normalised average of all seven dimensions. Ship requires ≥80 and zero critical findings; ≥55 is caution; below that is blocked. Empty dimensions stay neutral and never drag the score down. Computed entirely in this browser.