Files
VerseVDI-Protocol/openspec/changes/phase-3d-client-display-input/design.md
T
sechmachine 408d4f9cc3
Verify Protocol / module (push) Successful in 1m17s
Verify Protocol / verify (push) Successful in 55s
feat(protocol): negotiate display and native input
2026-08-10 23:07:04 +07:00

55 lines
2.3 KiB
Markdown

## Context
The JSON control schema is the generated-binding authority for broker requests
and manifests, while VGI1 is the provider-neutral input payload. Both contracts
are strict: old decoders reject unknown response fields and old gateways reject
unknown VGI kinds. Phase 3D therefore needs optional fields plus explicit
feature negotiation rather than a wire-version or protobuf change.
## Goals / Non-Goals
**Goals:**
- Preserve legacy JSON shapes when display negotiation is absent.
- Generate optional referenced objects correctly in Go, Rust, and Swift.
- Define exact, bounded, cross-language absolute-pointer and scroll bytes.
**Non-Goals:**
- Server clamp policy, database persistence, or provider translation.
- Live display renegotiation, provider packet exposure, or protobuf changes.
## Decisions
- Keep control wire version 1 and gate additions with exact feature IDs. This
avoids changing every legacy request while allowing strict clients to demand
the accepted display field.
- Use one reusable `DisplayMode` with the existing provider-policy dimension
bounds. Optional referenced objects become Go pointers so `omitempty` is real;
Rust and Swift retain their existing optional generation.
- Encode absolute pointer as four big-endian u16 values and scroll as two
big-endian i16 values in VGI1. Viewport coordinates are self-contained and
provider-neutral; provider scaling stays outside Protocol.
- Leave protobuf unchanged because the observed broker and VGI consumers use
JSON and fixed byte frames, not generated protobuf messages.
## Risks / Trade-offs
- [Old strict consumers reject new response fields] → emit them only after
`display.request.v1` negotiation.
- [New VGI kinds reach an old or unadvertised gateway] → reject before provider
translation unless the matching input feature is active.
- [Generated Go optional values serialize as zero objects] → require pointers,
omission tests, and clean second generation.
## Migration Plan
Freeze a new never-reused Protocol RC after full verification. Server and Data
Plane then pin that exact tag together. Legacy sessions omit all new fields and
continue using existing input kinds.
## Open Questions
None at the Protocol boundary; policy clamp and Apollo translation remain
consumer-owned work.