Learning outcome
Treat model output as untrusted structure before it reaches native rendering.
protocol.mjs applies an allowlist, bounds text and graph size, checks unique component IDs, validates child references and rejects cycles or unreachable nodes. Actions must use known event IDs and recognized names. CheckBox paths are limited to ready0 through ready99. Only the bundled community image URL is accepted. These checks reduce the accepted language; they do not make every accepted output safe or useful in every context.
Selected constraints from the pinned validator
const allowed = new Set([
'Text', 'Column', 'Row', 'Card', 'Button', 'CheckBox', 'Divider', 'Image'
]);
const actions = new Set(['venue', 'prepare', 'website', 'directions', 'save', 'refine']);
// Component IDs are unique and restricted to this shape:
/^[a-zA-Z0-9_-]{1,60}$/
// Checkbox binding paths are restricted to this shape:
/^\/ready[0-9]{1,2}$/
The server validates composition before wrapping it. The Android client additionally checks message count, message kind and the expected surface ID, then delegates schema parsing to AndroidX. This is layered defense, not a full protocol implementation written from scratch. A graph rejection becomes a visible error; the app does not generate a replacement template.
Different guarantees
| Check | Catches | Does not establish |
|---|---|---|
| Unique component IDs | Ambiguous graph identity | Unique checkbox data paths |
| Published event ID | Action on a fabricated identifier | Truth of descriptive prose |
| HTTPS event link | Unexpected model URL path | Safety of every published destination |
| Response size/depth | Oversized or cyclic trees | Ideal mobile layout or token cost |
| Catalog allowlist | Unsupported component names | Complete production authorization |
The baseline validator permits two CheckBox components to share one ready path. That is valid binding syntax but a poor fit for independent preparation tasks: toggling one task can toggle another. The next lesson makes this application policy explicit with a failing regression test. Do not claim the published baseline already enforces that policy.
Practice and checkpoint
Read the 10 server tests and classify each as structural, action or state validation. Construct a missing-child example and a fabricated-event action; both should throw. Then create two different checkbox IDs bound to /ready0 and explain why the baseline currently accepts them.
Source and next steps
- Pinned implementation — The exact app and server revision used by this lesson.
Back to roadmap · Practice this unit in the codelab