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
19low
0info
Verdict
Ship readiness
64/ 100 ready
Releasable, but open findings should be triaged before a wide rollout.
Dimensions evaluated8 / 10
Total findings46
Breakdown
Category scores
Readiness by dimension
score · findingsBacklog
Consolidated findings46
worst severity first · deep-linked to the owning surface
| Severity | Category | Finding | Remediation | Refs | |
|---|---|---|---|---|---|
| high | Contract | 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, #9 | Fix |
| high | Contract | 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, #17 | Fix |
| high | Contract | 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, #17 | Fix |
| high | Security | 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. | #24 | Fix |
| high | Security | 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. | #24 | Fix |
| high | Security | 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. | #24 | Fix |
| high | Trace | 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, #49 | Fix |
| high | Trace | 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, #49 | Fix |
| high | Trace | 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, #49 | Fix |
| high | Trace | 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, #49 | Fix |
| high | Resilience | 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, #32 | Fix |
| high | Resilience | 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, #32 | Fix |
| high | Drift | 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, #11 | Fix |
| high | Drift | 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, #11 | Fix |
| medium | Contract | 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, #8 | Fix |
| medium | Contract | 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, #18 | Fix |
| medium | Contract | 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, #8 | Fix |
| medium | Governance | 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, #8 | Fix |
| medium | Security | 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. | #25 | Fix |
| medium | Resilience | 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. | #33 | Fix |
| medium | Resilience | 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. | #33 | Fix |
| medium | Resilience | 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, #32 | Fix |
| medium | Resilience | 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, #30 | Fix |
| medium | Resilience | 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. | #33 | Fix |
| medium | Agent | 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, #46 | Fix |
| medium | Agent | 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, #46 | Fix |
| medium | Agent | 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, #46 | Fix |
| low | Governance | 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, #39 | Fix |
| low | Governance | 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). | #17 | Fix |
| low | Governance | 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). | #17 | Fix |
| low | Governance | 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). | #17 | Fix |
| low | Governance | 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). | #17 | Fix |
| low | Security | 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. | #26 | Fix |
| low | Security | 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. | #41 | Fix |
| low | Security | 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. | #26 | Fix |
| low | Security | 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. | #41 | Fix |
| low | Security | 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. | #26 | Fix |
| low | Security | 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. | #41 | Fix |
| low | Security | 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. | #26 | Fix |
| low | Security | 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. | #41 | Fix |
| low | Trace | 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. | #37 | Fix |
| low | Drift | 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, #11 | Fix |
| low | Inventory | Stale endpoint — not exercised recently POST /orders has not been run for 20618 days. Stale endpoints drift from their implementation undetected. inventory.stalePOST /orders | Run a scenario against this endpoint, or confirm it should be deprecated. | #43, #45 | Fix |
| low | Inventory | Stale endpoint — not exercised recently GET /orders/{id} has not been run for 20618 days. Stale endpoints drift from their implementation undetected. inventory.staleGET /orders/{id} | Run a scenario against this endpoint, or confirm it should be deprecated. | #43, #45 | Fix |
| low | Inventory | Stale endpoint — not exercised recently PATCH /orders/{id} has not been run for 20618 days. Stale endpoints drift from their implementation undetected. inventory.stalePATCH /orders/{id} | Run a scenario against this endpoint, or confirm it should be deprecated. | #43, #45 | Fix |
| low | Inventory | Stale endpoint — not exercised recently POST /orders/{id}/fulfill has not been run for 20618 days. Stale endpoints drift from their implementation undetected. inventory.stalePOST /orders/{id}/fulfill | Run a scenario against this endpoint, or confirm it should be deprecated. | #43, #45 | Fix |
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.