OTA Update Notifications on Slow Links: Bound Metadata Before Downloading an Artifact
Bound update notifications before allocating their full representation or following their artifact links. A small firmware downloader can still exhaust memory, stack or connection time while parsing a large or deeply nested campaign message. Authentication does not remove the need to bound the work needed to reach an authentication decision.
This guide uses an application-defined JSON notification as the concrete format, following RFC 8259. It is not a RAUC manifest format or a complete signed-update protocol. The limits below are hypothetical product choices, not Internet-standard maxima. No parser, network or device tests were executed.
1. Identify every representation that consumes resources
Draw the path from transport bytes to decoded body, parser tokens, strings, candidate records and any fetched manifest. Record which stage owns each buffer and when it is released. A 16 KiB message can require more than 16 KiB of heap after tokenization and object construction.
RFC 9124’s simple-parsing requirement and pre-download evaluation discussion motivate keeping update processing manageable on constrained devices. Its information model does not prescribe the JSON schema or numerical budgets in this example.
Separate notification limits from later manifest and artifact limits. An accepted notification grants permission to evaluate its contents under policy; it does not authorize an unbounded download or make a referenced payload trustworthy.

2. Set independent budgets before receiving input
The following fixture profile accepts an uncompressed UTF-8 JSON body. A product supporting compression needs additional encoded-size, decoded-size and decompression-work limits; it must not silently inherit this simpler profile.
| Dimension | Hypothetical fixture limit | Enforcement point |
|---|---|---|
| Received JSON body | 16 KiB | Count actual bytes before appending to the body buffer |
| Nesting depth | 8 containers | Parser enters each array or object |
| Total object members | 128 across the complete document | Before allocating another member |
| Artifact candidates | 4 | Before constructing another candidate record |
| Decoded locator | 512 UTF-8 bytes | During bounded string decoding and schema validation |
| Parser allocation | Separate qualified implementation budget | Allocator or bounded arena, including error paths |
RFC 8259 section 9 permits implementation limits on text size, nesting, number range/precision and strings. It supplies no universal safe values for an embedded updater. Derive production limits from required messages and measured implementation costs, then version the profile with the server and device.
Count bytes even when the transport supplies an advertised length. Reject oversized declarations early, but do not trust them to replace actual counting. Include a bounded receive lifetime so a slow sender cannot retain resources indefinitely while remaining below the byte cap.
3. Enforce structure while parsing, not afterward
A check applied after building a complete object tree is too late to bound that tree’s allocation. Require parser support for the selected depth, token/member and string limits, or use a qualified bounded representation that rejects before exceeding them.
Do not count opening braces with a text search: quoted and escaped characters are not container boundaries. Depth belongs to the parser’s grammar state. Define whether the outermost object counts as depth one so boundary tests match implementation and documentation.
Apply limits to decoded strings as well as source text. Validate encoding and escape handling without truncating identifiers to fit. An overlong artifact reference should fail clearly, not become a shortened reference to different content.
4. Remove ambiguous schema interpretations
RFC 8259 says object names should be unique and describes different receiver behavior when they are repeated. For this notification contract, reject duplicate names within an object, including names that become equal after JSON escape decoding. This is a stricter application rule, not a claim that the RFC universally mandates duplicate rejection.
Require exact types and allowed fields for the chosen schema version. Distinguish an absent required field from null, an empty string or zero. Reject unsupported versions explicitly instead of treating them as malformed older messages.
Choose a precise representation for sizes and campaign generations. RFC 8259 notes numeric interoperability limits among common implementations. Do not pass a large integer through a floating-point representation and then assume exact identity survived. Use a schema-defined exact integer range or another explicitly specified encoding, with checked conversion on both ends.
5. Keep pre-authentication work bounded and inert
Some parsing is necessary to locate authentication material or the protected object. Treat that initial parse as untrusted: bounded memory and work, no installation side effects, and no automatic fetching of arbitrary embedded URLs.
After the format’s required authenticity checks, evaluate target applicability, current campaign authority and retrieval policy. Only then admit the next bounded acquisition. Preserve the exact authenticated representation required by the chosen signature scheme; do not invent a JSON reserialization rule and assume signatures remain valid.
If a notification contains an embedded manifest, count that data against the relevant enclosing and nested budgets. If it references another object, give that retrieval its own size, redirect, timeout and trust limits. A short first message must not open an unlimited chain of metadata downloads.
6. Build rejection fixtures around each boundary
- Body exactly at the permitted size and one byte over it.
- Depth eight and depth nine under the declared counting convention.
- Maximum total members spread across many small objects.
- Five candidates when the contract allows four.
- Locator whose decoded UTF-8 length exceeds the bound.
- Duplicate security-relevant field, including escaped-name equivalence.
- Oversized or fractional number where an exact bounded integer is required.
- A slowly delivered body that exceeds the receive lifetime.
Require stable error classes, bounded memory, no artifact fetch and no retained partial campaign on rejection. Exercise allocation failure and repeated rejected requests as well. A single clean rejection is insufficient if every failure leaks memory or leaves a connection slot occupied.
Hypothetical harmless-looking metadata flood
A notification stays below 16 KiB but contains many nested containers and thousands of tiny values. A byte-only gate admits it, while an unconstrained object-tree parser allocates far beyond the expected budget.
The corrected design rejects at the structural boundary before those allocations occur. The server’s legitimate fixtures still pass, and resource measurements cover both accepted and rejected cases. Publish the actual tested profile and implementation version; do not present the illustrative limits above as evidence of device capacity.