health-api Specification

Purpose

Provide a runnable HTTP foundation for the MLOps course with a health check, an inspectable API description, and independent application instances.

Requirements

Requirement: Provide an operational health endpoint

The service SHALL respond to GET /health with HTTP 200 and the JSON object {“status”: “ok”}. The response SHALL indicate that the HTTP application is running without invoking recommendation computation or external services.

Scenario: Check a running application

  • WHEN a client sends GET /health to a running service
  • THEN it receives HTTP 200 with application/json content and {“status”: “ok”}

Requirement: Publish the generated API description and documentation

The service SHALL provide a valid OpenAPI document at GET /openapi.json, including the health endpoint and its successful response contract. It SHALL provide the default documentation pages at /docs and /redoc, configured to use that schema URL.

Scenario: Inspect the API contract

  • WHEN a client requests GET /openapi.json
  • THEN it receives HTTP 200 with a valid OpenAPI JSON document describing GET /health and its successful JSON response

Scenario: Open API documentation

  • WHEN a client requests GET /docs or GET /redoc
  • THEN it receives HTTP 200 with an HTML documentation page referring to /openapi.json

Requirement: Preserve a versioned application API boundary

Future application endpoints SHALL use /api/v1 as their initial routing prefix. Recommendations SHALL be exposed under that prefix; health and default API documentation SHALL retain their agreed root paths.

Scenario: Request an unimplemented application endpoint

  • WHEN a client requests GET /api/v1/predict
  • THEN the service responds with HTTP 404 rather than exposing prediction or placeholder business behavior

Requirement: Keep application instances independent

Constructing an application SHALL create fresh application and routing state. Importing application modules SHALL NOT start a server, create shared mutable application instances, or allocate external service resources. Changes to one application’s routing SHALL NOT affect another application’s routing.

Scenario: Construct multiple applications

  • WHEN two applications are constructed in one process and routing is subsequently added to one of them
  • THEN the other application’s routes remain unchanged

Requirement: Provide a configurable local server entry point

The service SHALL be runnable through a repository Bazel target with configurable host and port. It SHALL bind to 127.0.0.1:8000 by default, accept an explicitly selected loopback address and available port, and shut down cleanly on termination.

Scenario: Use an explicitly selected port

  • WHEN the server target starts with a loopback host and an available port
  • THEN the health and OpenAPI endpoints are served on that address
  • AND terminating the server releases its resources and listening socket

Requirement: Serve model recommendations

GET /api/v1/recommend SHALL accept a required track_name query and an integer n query defaulting to 5, constrained to 1 through 20. It SHALL return a RecommenderRecommendationResponse with requested_track and recommendations of RecommenderSong (track_name, artists, album_name). It SHALL use the upstream load_model function to load the declared model.pkl during application lifespan, with per-application state and no global model object.

Scenario: Recommend a known track

  • WHEN a client requests a track in the trained model with n=3
  • THEN it receives HTTP 200 and three typed song recommendations
  • AND requested_track matches the query

Scenario: Reject an invalid recommendation count

  • WHEN n is 0, 21, or nonnumeric, or track_name is absent
  • THEN the response is HTTP 422

Scenario: Request an unknown track

  • WHEN track_name does not exist in the model
  • THEN requested_track is preserved and recommendations is empty