Files
cameleer-server/.planning/phases/01-ingestion-pipeline-api-foundation/01-03-PLAN.md

189 lines
9.6 KiB
Markdown
Raw Normal View History

---
phase: 01-ingestion-pipeline-api-foundation
plan: 03
type: execute
wave: 2
depends_on: ["01-01"]
files_modified:
- cameleer3-server-app/src/main/java/com/cameleer3/server/app/interceptor/ProtocolVersionInterceptor.java
- cameleer3-server-app/src/main/java/com/cameleer3/server/app/config/WebConfig.java
- cameleer3-server-app/src/main/java/com/cameleer3/server/app/Cameleer3ServerApplication.java
- cameleer3-server-app/src/test/java/com/cameleer3/server/app/interceptor/ProtocolVersionIT.java
- cameleer3-server-app/src/test/java/com/cameleer3/server/app/controller/HealthControllerIT.java
- cameleer3-server-app/src/test/java/com/cameleer3/server/app/controller/OpenApiIT.java
- cameleer3-server-app/src/test/java/com/cameleer3/server/app/controller/ForwardCompatIT.java
autonomous: true
requirements:
- API-01
- API-02
- API-03
- API-04
- API-05
- INGST-06
must_haves:
truths:
- "GET /api/v1/health returns 200 with health status"
- "GET /api/v1/swagger-ui returns Swagger UI page"
- "GET /api/v1/api-docs returns OpenAPI JSON spec listing all endpoints"
- "Requests without X-Cameleer-Protocol-Version header to /api/v1/data/* return 400"
- "Requests with wrong protocol version return 400"
- "Health and swagger endpoints work without protocol version header"
- "Unknown JSON fields in request body do not cause deserialization errors"
- "ClickHouse tables have TTL clause for 30-day retention"
artifacts:
- path: "cameleer3-server-app/src/main/java/com/cameleer3/server/app/interceptor/ProtocolVersionInterceptor.java"
provides: "Validates X-Cameleer-Protocol-Version:1 header on data endpoints"
min_lines: 20
- path: "cameleer3-server-app/src/main/java/com/cameleer3/server/app/config/WebConfig.java"
provides: "Registers interceptor with path patterns"
min_lines: 10
key_links:
- from: "WebConfig.java"
to: "ProtocolVersionInterceptor.java"
via: "addInterceptors registration"
pattern: "addInterceptors.*ProtocolVersionInterceptor"
- from: "application.yml"
to: "Actuator health endpoint"
via: "management.endpoints config"
pattern: "management\\.endpoints"
- from: "application.yml"
to: "springdoc"
via: "springdoc.api-docs.path and swagger-ui.path"
pattern: "springdoc"
---
<objective>
Implement the API foundation: health endpoint, OpenAPI documentation, protocol version header validation, forward compatibility, and TTL verification.
Purpose: Completes the API scaffolding so all endpoints follow the protocol v1 contract. Health endpoint enables monitoring. OpenAPI enables discoverability. Protocol version interceptor enforces compatibility. TTL verification confirms data retention.
Output: Working health, Swagger UI, protocol header enforcement, and verified TTL retention.
</objective>
<execution_context>
@C:/Users/Hendrik/.claude/get-shit-done/workflows/execute-plan.md
@C:/Users/Hendrik/.claude/get-shit-done/templates/summary.md
</execution_context>
<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/01-ingestion-pipeline-api-foundation/01-RESEARCH.md
@.planning/phases/01-ingestion-pipeline-api-foundation/01-01-SUMMARY.md
</context>
<tasks>
<task type="auto" tdd="true">
<name>Task 1: Protocol version interceptor, WebConfig, and Spring Boot application class</name>
<files>
cameleer3-server-app/src/main/java/com/cameleer3/server/app/interceptor/ProtocolVersionInterceptor.java,
cameleer3-server-app/src/main/java/com/cameleer3/server/app/config/WebConfig.java,
cameleer3-server-app/src/main/java/com/cameleer3/server/app/Cameleer3ServerApplication.java
</files>
<behavior>
- Request to /api/v1/data/* without X-Cameleer-Protocol-Version header returns 400
- Request to /api/v1/data/* with X-Cameleer-Protocol-Version:2 returns 400
- Request to /api/v1/data/* with X-Cameleer-Protocol-Version:1 passes through
- Request to /api/v1/health without the header succeeds (excluded from interceptor)
- Request to /api/v1/swagger-ui without the header succeeds (excluded)
- Request to /api/v1/api-docs without the header succeeds (excluded)
</behavior>
<action>
1. Create ProtocolVersionInterceptor implementing HandlerInterceptor:
- preHandle: read X-Cameleer-Protocol-Version header
- If null or not "1": set response status 400, write JSON error body {"error": "Missing or unsupported X-Cameleer-Protocol-Version header"}, return false
- If "1": return true
2. Create WebConfig implementing WebMvcConfigurer:
- @Configuration
- Inject ProtocolVersionInterceptor (declare it as @Component or @Bean)
- Override addInterceptors: register interceptor with pathPatterns "/api/v1/data/**" and "/api/v1/agents/**"
- Explicitly EXCLUDE: "/api/v1/health", "/api/v1/api-docs/**", "/api/v1/swagger-ui/**", "/api/v1/swagger-ui.html"
3. Create or update Cameleer3ServerApplication:
- @SpringBootApplication in package com.cameleer3.server.app
- @EnableScheduling (needed for ClickHouseFlushScheduler from Plan 02)
- @EnableConfigurationProperties(IngestionConfig.class)
- Main method with SpringApplication.run()
- Ensure package scanning covers com.cameleer3.server.app and com.cameleer3.server.core
</action>
<verify>
<automated>mvn clean compile -pl cameleer3-server-app -q 2>&1 | tail -5</automated>
</verify>
<done>ProtocolVersionInterceptor validates header on data/agent paths. Health, swagger, and api-docs paths excluded. Application class enables scheduling and config properties.</done>
</task>
<task type="auto" tdd="true">
<name>Task 2: Health, OpenAPI, protocol version, forward compat, and TTL integration tests</name>
<files>
cameleer3-server-app/src/test/java/com/cameleer3/server/app/controller/HealthControllerIT.java,
cameleer3-server-app/src/test/java/com/cameleer3/server/app/controller/OpenApiIT.java,
cameleer3-server-app/src/test/java/com/cameleer3/server/app/interceptor/ProtocolVersionIT.java,
cameleer3-server-app/src/test/java/com/cameleer3/server/app/controller/ForwardCompatIT.java
</files>
<behavior>
- GET /api/v1/health returns 200 with JSON containing status field
- GET /api/v1/api-docs returns 200 with OpenAPI JSON containing paths
- GET /api/v1/swagger-ui/index.html returns 200 (Swagger UI page)
- POST /api/v1/data/executions without protocol header returns 400
- POST /api/v1/data/executions with X-Cameleer-Protocol-Version:1 does NOT return 400 (may return 202 or other based on body)
- POST /api/v1/data/executions with X-Cameleer-Protocol-Version:2 returns 400
- GET /api/v1/health without protocol header returns 200 (not intercepted)
- POST /api/v1/data/executions with extra unknown JSON fields returns 202 (not 400/422)
- ClickHouse route_executions table SHOW CREATE TABLE includes TTL
</behavior>
<action>
1. Create HealthControllerIT (extends AbstractClickHouseIT):
- Test: GET /api/v1/health -> 200 with body containing "status"
- Test: No X-Cameleer-Protocol-Version header required for health
2. Create OpenApiIT (extends AbstractClickHouseIT):
- Test: GET /api/v1/api-docs -> 200, body contains "openapi" and "paths"
- Test: GET /api/v1/swagger-ui/index.html -> 200 or 302 (redirect to UI)
- Test: api-docs lists /api/v1/data/executions path
3. Create ProtocolVersionIT (extends AbstractClickHouseIT):
- Test: POST /api/v1/data/executions without header -> 400 with error message
- Test: POST /api/v1/data/executions with header value "2" -> 400
- Test: POST /api/v1/data/executions with header value "1" and valid body -> 202 (not 400)
- Test: GET /api/v1/health without header -> 200 (excluded from interceptor)
- Test: GET /api/v1/api-docs without header -> 200 (excluded from interceptor)
4. Create ForwardCompatIT (extends AbstractClickHouseIT):
- Test: POST /api/v1/data/executions with valid RouteExecution JSON plus extra unknown fields (e.g., "futureField": "value") -> 202 (Jackson does not fail on unknown properties)
- This validates API-05 requirement explicitly.
5. TTL verification (add to HealthControllerIT or separate test):
- Query ClickHouse: SHOW CREATE TABLE route_executions
- Assert result contains "TTL start_time + toIntervalDay(30)"
- Query: SHOW CREATE TABLE agent_metrics
- Assert result contains TTL clause
Note: All tests that POST to data endpoints must include X-Cameleer-Protocol-Version:1 header.
</action>
<verify>
<automated>mvn test -pl cameleer3-server-app -Dtest="HealthControllerIT,OpenApiIT,ProtocolVersionIT,ForwardCompatIT" -q 2>&1 | tail -15</automated>
</verify>
<done>Health returns 200. OpenAPI docs are available and list endpoints. Protocol version header enforced on data paths, not on health/docs. Unknown JSON fields accepted. TTL confirmed in ClickHouse DDL.</done>
</task>
</tasks>
<verification>
- `mvn test -pl cameleer3-server-app -Dtest="HealthControllerIT,OpenApiIT,ProtocolVersionIT,ForwardCompatIT" -q` -- all tests pass
- GET /api/v1/health returns 200
- GET /api/v1/api-docs returns OpenAPI spec
- Missing protocol header returns 400 on data endpoints
- Health works without protocol header
</verification>
<success_criteria>
All four integration test classes green. Health endpoint accessible. OpenAPI docs list all ingestion endpoints. Protocol version header enforced on data/agent paths but not health/docs. Forward compatibility confirmed. TTL verified in ClickHouse schema.
</success_criteria>
<output>
After completion, create `.planning/phases/01-ingestion-pipeline-api-foundation/01-03-SUMMARY.md`
</output>