# Design: Add /hello Endpoint to API Service ## Architecture Approach This is a minimal addition that follows existing patterns exactly. No new architectural components are introduced. **Layers changed:** - `services/api/internal/api/handlers/` - New `hello.go` handler file - `services/api/internal/api/routes.go` - Route registration - `services/api/internal/api/spec.go` - OpenAPI documentation **Approach:** Create a standalone handler struct with a single `Say` method that returns a greeting. The handler follows the error-returning pattern used by `Example` handler (not the direct `http.HandlerFunc` pattern used by `Health`), allowing for consistent error handling if we add complexity later. ## Data Model Changes **No database or schema changes required.** Response structure (uses existing envelope): ```go // HelloResponse is the data returned by GET /api/v1/hello type HelloResponse struct { Message string `json:"message"` } ``` Envelope output: ```json { "data": { "message": "Hello, World!" }, "meta": { "request_id": "abc123", "timestamp": "2026-02-03T12:00:00Z" } } ``` ## API Changes ### New Endpoint | Method | Path | Auth | Description | |--------|------|------|-------------| | GET | `/api/v1/hello` | None | Returns greeting message | ### Request No request body or parameters. ### Response **Success (200 OK):** ```json { "data": { "message": "Hello, World!" }, "meta": { "request_id": "...", "timestamp": "..." } } ``` ## Component Diagram ``` ┌──────────────────────────────────────────────────────────────┐ │ HTTP Request │ │ GET /api/v1/hello │ └──────────────────────────────────────────────────────────────┘ │ ▼ ┌──────────────────────────────────────────────────────────────┐ │ Chi Router (routes.go) │ │ │ │ r.Get("/hello", app.Wrap(helloHandler.Say)) │ └──────────────────────────────────────────────────────────────┘ │ ▼ ┌──────────────────────────────────────────────────────────────┐ │ Middleware Stack │ │ [RequestID] → [CORS] → [Recovery] → [Logger] │ │ (Already configured in app.App) │ └──────────────────────────────────────────────────────────────┘ │ ▼ ┌──────────────────────────────────────────────────────────────┐ │ app.Wrap() │ │ Converts error-returning handler to http.HandlerFunc │ │ Maps HTTPError → status code, other errors → 500 │ └──────────────────────────────────────────────────────────────┘ │ ▼ ┌──────────────────────────────────────────────────────────────┐ │ handlers/hello.go │ │ │ │ func (h *Hello) Say(w, r) error { │ │ httpresponse.OK(w, r, HelloResponse{ │ │ Message: "Hello, World!", │ │ }) │ │ return nil │ │ } │ └──────────────────────────────────────────────────────────────┘ │ ▼ ┌──────────────────────────────────────────────────────────────┐ │ httpresponse.OK() │ │ Wraps data in {data, meta} envelope │ │ Adds request_id and timestamp to meta │ │ Sets Content-Type: application/json │ └──────────────────────────────────────────────────────────────┘ │ ▼ ┌──────────────────────────────────────────────────────────────┐ │ HTTP Response │ │ 200 OK │ │ {"data": {"message": "Hello, World!"}, "meta": ...} │ └──────────────────────────────────────────────────────────────┘ ``` ## Error Handling Strategy This endpoint has minimal failure modes: | Scenario | Handling | Response | |----------|----------|----------| | Normal request | Return greeting | 200 with `{data, meta}` | | Middleware panic | Recovery middleware catches | 500 with generic error | | JSON encoding failure | Caught by `httpresponse.OK` | 500 internal error | Since this handler: - Takes no input (no validation errors possible) - Makes no external calls (no timeout/network errors) - Has no authorization (no auth errors possible) The only realistic failure mode is a panic in the middleware stack, which is already handled by the Recovery middleware. **Decision:** Use error-returning handler pattern (`app.Wrap`) for consistency with other handlers, even though this specific handler always returns `nil`. This makes future extension easier if we add features like parameterized greetings. ## Security Considerations | Concern | Mitigation | |---------|------------| | **Authentication** | Endpoint is intentionally public (no auth required) | | **Authorization** | No protected resources accessed | | **Input validation** | No input accepted (GET with no params/body) | | **Data exposure** | Only static string returned, no sensitive data | | **Rate limiting** | Uses global rate limiting if configured (out of scope for this feature) | | **CORS** | Uses existing CORS middleware configuration | **Risk assessment:** Low risk. This is a read-only endpoint returning static content with no user input and no sensitive data. ## Performance Considerations | Aspect | Analysis | |--------|----------| | **Expected load** | Low - primarily used for connectivity checks | | **Response time** | Sub-millisecond (no I/O, no computation) | | **Memory** | Negligible - single small response struct | | **Caching** | Not needed - response is static and fast to generate | | **Connection pooling** | N/A - no database or external calls | **Optimization:** None required. The endpoint is already optimal by design. ## Migration / Rollout Plan **Zero-downtime deployment:** This is a purely additive change. 1. **No migration needed** - No database changes 2. **No feature flags needed** - Endpoint is stateless and low-risk 3. **No backwards compatibility concerns** - New endpoint, no existing consumers **Rollout steps:** 1. Deploy code changes (handler, routes, spec) 2. Verify endpoint responds at `/api/v1/hello` 3. Verify OpenAPI spec includes new endpoint at `/docs` **Rollback:** Standard deployment rollback if issues arise (no data cleanup needed). ## File Changes Summary | File | Change Type | Description | |------|-------------|-------------| | `services/api/internal/api/handlers/hello.go` | New | Handler struct and Say method | | `services/api/internal/api/handlers/hello_test.go` | New | Unit tests for handler | | `services/api/internal/api/routes.go` | Modify | Register GET /api/v1/hello route | | `services/api/internal/api/spec.go` | Modify | Add Hello tag and /hello path | ## Implementation Notes 1. **Handler location:** Create `handlers/hello.go` alongside existing handlers rather than adding to `health.go` - the spec recommends a dedicated "Hello" tag to distinguish from infrastructure health checks. 2. **Response type:** Define `HelloResponse` in the handler file (not a separate types file) since it's only used by this handler. 3. **Route registration:** Add `helloHandler` initialization in `RegisterRoutes` and register route in the public routes section (outside the auth group). 4. **OpenAPI tag:** Add `"Hello"` tag with description `"Simple greeting endpoint"` to differentiate from Health endpoints. 5. **Test pattern:** Follow `example_test.go` pattern with table-driven tests, though a single happy-path test is sufficient for this simple endpoint.