Skip to content

Ownership and validation

Result values sit between application handlers and protocol adapters. They need to remain stable after an application returns, even when the application reuses an input buffer or another reader changes a returned copy. Constructors therefore copy slices, raw JSON and annotation pointers; accessors detach mutable storage again. Immutable owned metadata and references can safely share their private backing storage.

Completed values support concurrent reads. Callers must avoid changing input storage while its constructor is copying it, as with other Go APIs. Separate goroutines can mutate their own accessor copies without changing the result.

Raw JSON is validated without converting numbers to float64. The validator rejects duplicate decoded member names at every nesting level, including an escaped spelling of the same key. It preserves the original raw representation in structured output and metadata accessors. JSONResult cannot recover precision already lost before the caller passed it a Go value. Presentation serialization may compact whitespace while retaining numbers.

Leaf content constructors stay simple. NewResult checks recognized concrete variants and rejects nil values, unconstructed content, typed nil pointers and external wrappers that embed the content interface. Nil options and duplicate singleton options also fail. Independent metadata keys may merge; duplicates fail.

Structural checks cover JSON, UTF-8, MIME declarations, reference identity and annotation shapes. They do not validate an operation's output schema, apply per-location byte limits, authorize a read or approve an Apps view. Registry.Invoke now enforces the operation's input/output schemas and core budgets, while New checks definitions and configured limit relationships. Resources enforce plan identity, current visibility/read policy and resource budgets. Adapter-specific wire checks remain integration work.

Invocation arguments are normalized to sorted-key JSON with exact decimal number semantics. Original and normalized bytes each have to fit the argument budget. Schema defaults never change those arguments. Policy and handler access receive detached copies, preventing a callback from changing a value after validation or authorization. See the registry reference for the bounded numeric compiler profile.

Failure messages are explicit caller-safe host input. Invalid codes, empty messages, malformed UTF-8 or messages over 1 KiB normalize to internal with a safe generic message. Private causes stay in the toolkit error chain. Wire serialization must use the safe accessors, never serialize an arbitrary cause or error chain.