- Date Created: 2025-12-06
- Last Modified: 2025-12-06
Progress Log: Response Schema Design for Serial Protocol¶
Task Description¶
Investigate the value and feasibility of introducing a formal response schema for the kurikintons serial protocol. Current context:
- Firmware sends JSONL responses with
"type":"response"and"status":"ok"|"error"headers - Data fields currently placed directly in response object (no wrapper)
- Complex responses like GET_STATUS use nested JSON objects
- No formal schema definition exists - documentation is text-based
Proposal: Introduce 3-layer response structure:
{
"type": "response",
"status": "ok"|"error",
"payload": { /* command-specific data */ }
}
Key question: Is a formal schema (JSON Schema, TypeScript types, or documented) worth implementing?
Outcome¶
Analysis Results¶
- Current Response Architecture
- Type-safe response layer exists (
response.h/cpp) using C++ union types - Handles simple responses well: error, ok, single/multiple key-value pairs
- Does NOT handle nested structures - GET_STATUS uses raw JsonDocument
-
Inconsistency: Some handlers use type-safe builders, others raw JSON
-
Payload Wrapper Benefits (3-layer structure)
- ✓ Consistent structure across all responses
- ✓ Separates envelope (type/status) from content (payload)
- ✓ Flexible: payload can be nested or flat
- ✓ Client-side decision: flatten or preserve structure
-
✓ Future-proof: easier to add metadata to envelope
-
Schema Definition Value
- ✓ Clarifies command response contracts
- ✓ Enables client-side type safety (TypeScript, JSON Schema validation)
- ✓ Single source of truth for API documentation
- ✓ Supports auto-generation of client stubs
-
⚠ Adds maintenance burden (schema must track implementation)
-
Type Safety Analysis
- Current union-based approach: Compile-time checks via
pair_count - Proposed payload wrapper: Can maintain same safety with union variants
- Schema definition: Does NOT reduce type safety if done correctly
- Trade-off: Slightly increased JSON size (~40 bytes) for clarity
Design Decisions¶
Recommended approach: Phase-based adoption
Phase 1 (NOW): Document existing responses in CLAUDE.md¶
- Add "Response Schema" section listing all GET_ and SET_ commands
- Show example JSON for each command
- No code changes required
- Immediate value for client developers
Phase 2 (Recommended): Implement payload wrapper¶
- Refactor response.h to support payload-based structure
- All responses get
"payload"wrapper - Maintains type safety via union variants
- Backward compatible if done correctly (documentation bump to v2.0)
Phase 3 (Optional): Formal schema definition¶
- JSON Schema (standards-based) OR TypeScript types (developer-friendly)
- Place in
/schemas/response-schema.jsonor/types/responses.ts - Optional client-side validation
- Can be deferred to v2.0+ cycle
Current Response Examples¶
Simple response (GET_VERSION):
{"type":"response","status":"ok","version":"1.10.6"}
Complex response (GET_STATUS):
{
"type":"response","status":"ok",
"system":{"version":"1.10.6","uptime_ms":12345,"adc_channel":32},
"detection":{"poll_count":100,"deadtime_ms":0,"threshold1":1234},
"features":{"bme280":1,"rtc":1,"timestamp":1,"wifi":0}
}
Error response:
{"type":"response","status":"error","error_code":1}
Learnings¶
- Schema is valuable, not just academic
- Current state: Developers must read source code or docs to understand response format
- With schema: Machine-readable contract between firmware and client
-
ESP32 environment: No excuse for poor API contracts (unlike resource-constrained IoT)
-
Payload wrapper aligns with REST conventions
- Separates metadata (type/status) from data (payload)
- Similar to HTTP: status code + response body structure
-
Makes error handling uniform across clients
-
Type safety maintained through careful design
- Union-based variant dispatch still works with payload wrapper
pair_countdiscriminator can be extended to handle nested variants-
No requirement to sacrifice type checking for clarity
-
Implementation debt already exists
- GET_STATUS is inconsistent (raw JsonDocument vs type-safe builders)
- TEST_LED handler uses raw JSON when it could use builders
- Inconsistency makes maintaining the protocol harder over time
Next Steps¶
Immediate (this session)¶
- Add "Response Schema" section to CLAUDE.md
- Document all command responses with examples
- Update README or getting-started guide with schema reference
Short-term (v1.11.x cycle)¶
- Evaluate payload wrapper feasibility
- Create migration plan for existing handlers
- Decide on schema format (JSON Schema vs TypeScript)
Medium-term (v2.0 cycle)¶
- Implement payload wrapper if Phase 1 is successful
- Refactor response.h to support nested variants
- Deploy formal schema (JSON Schema or TS types)
- Generate client stub code from schema (optional)