For the complete documentation index, see llms.txt. This page is also available as Markdown.

Structures

Parse lists and dictionaries, read the path a violation was found at, and cap what a hostile payload can cost you.

A list or a dictionary is parsed with a schema per part. The item schema can be any schema — including one you wrote.

Lists

// At least one objective, at most ten, and each one trimmed and bounded.
public static readonly Schema<IReadOnlyList<string>, IReadOnlyList<string>>
    Objectives = Schema.List(Schema.Text.Trim().NotEmpty().MaxLength(120))
                       .MinCount(1)
                       .MaxCount(10);

Every item is parsed, so a bad item at index 3 does not hide a bad one at index 7. Both are reported.

MaxCount is the exception. It counts before parsing anything, which is what makes it a guard on untrusted input rather than a report afterwards. An eleventh objective is rejected on its own, with nothing said about the ten.

The item schema is just a schema, so nothing stops it being one of yours.

public static readonly Schema<IReadOnlyList<LeaderDto>, IReadOnlyList<Leader>>
    Leaders = Schema.List(LeaderSchema.Instance).MinCount(1);

Dictionaries

// A schema for the keys and a schema for the values.
public static readonly
    Schema<IReadOnlyDictionary<string, int>, IReadOnlyDictionary<string, int>>
    Bounties = Schema.Dictionary(
                          Schema.Text.Trim().Matches(BountyName),
                          Schema.Number.Int32.Positive())
                     .MaxCount(50);

Keys are parsed too, so a malformed key is a violation rather than a silent entry nobody ever looks up. MaxCount counts first here as well — a fifty-first entry is rejected before any key is read.

Paths

A violation inside a structure carries where it was found. The path reads [1] for a list position and leader.email through a nested schema; in a field set both are prefixed by the field, giving objectives[1].

Reading a path in code

The rendered path is written for a human. Branch on the segments instead.

A list position, a dictionary key and a failed Schema.Any branch all render inside brackets. Only the segment's Kind tells you which one you are looking at.

The report is capped

One list or dictionary reports at most 64 problems and then stops.

That cap is a guard, not a limitation of the design. Without it, a payload of ten thousand blank strings costs ten thousand rendered messages to reject — and whoever sent it chose the number.

When the cap is reached, the report says so with a Truncated violation rather than trailing off. Check for that code before you tell a caller the list they sent has exactly 64 problems.

Last updated

Was this helpful?