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.
Readiness truth · V2
Score, coverage, confidence, and verdict are separate
blocked
- Score
- 35/100
- Evaluation coverage
- 100%
- Evidence confidence
- Unknown
- State
- failed
Formula apimaster.readiness.formula.v2 · rule pack apimaster.legacy-readiness-adapter.v1. N/A rules are excluded; missing or insufficient evidence remains Unknown and never becomes a perfect score.
0critical
14high
18medium
15low
0info
Verdict
Ship readiness
64/ 100 ready
Releasable, but open findings should be triaged before a wide rollout.
Dimensions evaluated10 / 11
Total findings47
Breakdown
Category scores
Readiness by dimension
score · findings- 882 mediumSchema quality
- 466 highContract & scenario coverage
- 846 mediumGovernance & lint
- 4212 highSecurity posture
- 505 highTrace & observability
- 467 highResilience
- 743 highDrift & breaking change
- 100cleanInventory & ownership
- 543 mediumAgent readiness
- 100cleanVersion compatibilityn/a
- 823 mediumPlatform hand-off
Backlog
Consolidated findings47
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 | Schema | Order leaves enum-like fields unconstrained Enum-like string fields need an explicit allowed-value set. schema.enum-hygiene | Declare stable enum values and document their meaning; preserve compatibility when adding or removing members. | #15 | Fix |
| medium | Schema | OrderItem has no usable example Neither the schema, its properties, nor a linked response supplies an example payload, so documentation, mocks and contract tests must invent data. schema.example-coverage | Add a representative schema or response example with non-secret values. | #17 | 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 |
| medium | Platform | No health or readiness endpoint is declared Order Management API declares 4 endpoints and none of them is a probe (GET /healthz, /readyz, /livez, /health, /ready, /live, /status, or a `health` tag). A platform cannot know when this service may receive traffic or must be restarted; a generated workload manifest would carry no probe. platform.probe.missing | Declare GET /healthz (liveness) and GET /readyz (readiness) in the definition — unauthenticated, 200 on success, a small JSON or text body. Startup-heavy services add GET /startupz. | #33 | Fix |
| medium | Platform | Error responses declare no schema 8 error responses (4xx/5xx) are declared and not one carries a schema. Gateways, SDKs and on-call engineers then cannot rely on an error envelope — no stable code, no correlation id, no retryability signal. platform.error.no-schema | Declare one error schema and reference it from every 4xx/5xx response. RFC 9457 (application/problem+json: type, title, status, detail, instance) is the standard shape; add a stable `code` and a correlation id field. | #29, #30 | Fix |
| medium | Platform | 1 readable resource can be overwritten without noticing PATCH /orders/{id} replaces a resource the same path also exposes for reading, and declare no precondition — no If-Match, no If-Unmodified-Since, no version field in the body. Two clients that read, edit and write in that order both succeed, and the second silently discards the first one's change. platform.concurrency.no-precondition | Declare an If-Match header parameter (or a version property in the request body) and answer a mismatch with 412 or 409. Endpoints with no readable counterpart are not judged here. | #24 | 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 |
How it scores
The legacy score remains visible for compatibility. V2 reports score, evaluated coverage, evidence confidence, and verdict independently. N/A dimensions are excluded; unevaluated or insufficient evidence is Unknown, never an implicit 100. Computed entirely in this browser.