Feature: ASGI application protocol handling As a server deployment operator I want the ASGI app to handle each protocol correctly So that HTTP, lifespan, and websocket scopes behave per ASGI contract Scenario: HTTP health endpoint returns success JSON Given the ASGI app module is loaded When I send an HTTP GET request to "/health" through the ASGI app Then the HTTP response status should be 200 And the HTTP response body should be "{\"status\":\"ok\"}" Scenario: HTTP liveness endpoint returns alive JSON Given the ASGI app module is loaded When I send an HTTP GET request to "/live" through the ASGI app Then the HTTP response status should be 200 And the HTTP response body should be "{\"status\":\"alive\"}" Scenario: HTTP readiness endpoint returns ready JSON Given the ASGI app module is loaded When I send an HTTP GET request to "/ready" through the ASGI app Then the HTTP response status should be 200 And the HTTP response body should be "{\"status\":\"ready\"}" Scenario: HTTP root endpoint returns service metadata Given the ASGI app module is loaded When I send an HTTP GET request to "/" through the ASGI app Then the HTTP response status should be 200 And the HTTP response body should be "{\"service\":\"cleveragents\"}" Scenario: Unknown HTTP endpoint returns not found Given the ASGI app module is loaded When I send an HTTP GET request to "/missing" through the ASGI app Then the HTTP response status should be 404 And the HTTP response body should be "{\"error\":\"not found\"}" Scenario: POST to known path returns method not allowed Given the ASGI app module is loaded When I send an HTTP POST request to "/health" through the ASGI app Then the HTTP response status should be 405 And the HTTP response body should be "{\"error\":\"method not allowed\"}" And the HTTP response should include an Allow header with value "GET" Scenario: POST to another known path returns method not allowed Given the ASGI app module is loaded When I send an HTTP POST request to "/live" through the ASGI app Then the HTTP response status should be 405 And the HTTP response body should be "{\"error\":\"method not allowed\"}" And the HTTP response should include an Allow header with value "GET" Scenario: HTTP responses include security-hardening headers Given the ASGI app module is loaded When I send an HTTP GET request to "/health" through the ASGI app Then the HTTP response status should be 200 And the HTTP response should include a content-length header And the HTTP response should include header "x-content-type-options" with value "nosniff" And the HTTP response should include header "cache-control" with value "no-store" Scenario: Lifespan startup and shutdown complete cleanly Given the ASGI app module is loaded When I run ASGI lifespan startup then shutdown Then the ASGI app should emit lifespan completion messages And no HTTP response frames should be emitted Scenario: Unrecognised lifespan message type logs warning and continues Given the ASGI app module is loaded When I run ASGI lifespan with an unrecognised message type Then the ASGI app should emit lifespan completion messages And a warning should be logged for the unrecognised lifespan message type Scenario: Websocket scopes close with protocol-correct frame Given the ASGI app module is loaded When I invoke the ASGI app with a websocket scope Then the ASGI app should emit a websocket close frame Scenario: Unsupported ASGI scope raises runtime error Given the ASGI app module is loaded When I invoke the ASGI app with an unsupported scope type Then the ASGI invocation should raise an unsupported scope runtime error