!!id:"https://tson.io/2026/39/m/net.tn?sha256=371fc20c8628b5461b56a7a28f2559a1cfde4eda718f72d60ceb1b5a007bac06" !!import:"https://tson.io/2026/39/m/meta.tn?sha256=c9b069b606f7cc8a043ebabe3fe91e4aaa35a9ffd814b68be0ba4bbe6d02bfb5" @doc:""" TSON net — the network and identifier type library (2026 Revision 39 draft). Its root holds the network and identifier types a data schema writes: `email`, `ipv4`, `ipv6`, `cidr4`, `cidr6`, `mac`, `hostname`, `host`, `media_type`, `uri_reference`, `uri` and `uuid`. Their constructors are machinery, members of `net`, a schema map nested in its root, each named by its path: `net.ipv4_type`, `net.hostname_type`, `net.uri_type`, `net.uuid_type`. The kernel contributes to the same map: `net.iri_type`, the constructor of the kernel's `iri`, and its schemes, `net.scheme_set` and `net.scheme_name`. The instances are empty, but for `uri`, which refines `uri_reference` to require a scheme. The schemaless annotations of the same names ([TSON-DATA] §5.5) denote these types. It imports the kernel, meta.tn, alone: the kernel's constructors, `atom.specification`, `net.scheme_set` and classifying annotations are what it builds on, and it needs nothing of numeric.tn or temporal.tn. A schema importing it reserves its root names beside the kernel's, `net` among those ([TSON-SCHEMA] §2.2.3), so a schema imports it when it wants these names, and only then. core.tn imports it with numeric.tn and temporal.tn, for a schema that wants every bundled type. Hash pins here are real digests over the bytes of this copy; see meta.tn's note. References: RFC 1123 Host name syntax (§2.1) RFC 3492 Punycode RFC 3986 URI syntax, and the IPv4address grammar RFC 3987 Internationalized Resource Identifiers (ihost) RFC 4291 IPv6 addressing architecture RFC 4632 Classless Inter-domain Routing (CIDR) RFC 5321, RFC 5322 Email address format RFC 5890-5893 IDNA2008: definitions, protocol, code points, Bidi RFC 5952 IPv6 address text representation RFC 6838, RFC 6839 Media type specifications, structured suffixes RFC 9110 §8.3.1 Media type parameters RFC 9542 IEEE 802 parameters (EUI-48 format) RFC 9562 UUID format """ !schema { @doc:"The network constructors, each named by its path, `net.ipv4_type`." net => !schema { @doc:""" Email constraint vocabulary. Instance is `email`. An address is its text as written: a mailbox's local part is case-sensitive (RFC 5321 §2.4), so a form over the whole text could merge two mailboxes. """ email_type => unicode.text_type & atom.specification & { spec?: = "https://www.rfc-editor.org/rfc/rfc5322" normalization?: = NONE } @doc:""" IPv4 address constraint vocabulary. Instance is `ipv4`. The spec pin cites RFC 3986 for its `IPv4address` production — the normative dotted-quad grammar ([TSON-DATA] §5.5). `within` and `excluding` list IPv4 networks, each a `cidr4`: the address must lie inside at least one `within` network when the field is present, and inside no `excluding` network. `excluding` carves holes out of `within`. """ ipv4_type => meta.atom & atom.specification & { spec?: = "https://www.rfc-editor.org/rfc/rfc3986" within?: [cidr4] excluding?: [cidr4] } @doc:""" IPv6 address constraint vocabulary. Instance is `ipv6`. `within` and `excluding` list IPv6 networks, each a `cidr6`: the address must lie inside at least one `within` network when the field is present, and inside no `excluding` network. """ ipv6_type => meta.atom & atom.specification & { spec?: = "https://www.rfc-editor.org/rfc/rfc4291" within?: [cidr6] excluding?: [cidr6] } @doc:""" IPv4 network constraint vocabulary. Instance is `cidr4`. `min_prefix`/`max_prefix` narrow the prefix length within the family range 0-32; bounds outside that range are invalid at the schema level. `within` lists IPv4 networks, each a `cidr4`: the value must be a subnet of at least one. `excluding`: the value must not overlap any listed network — overlap, not containment. """ cidr4_type => meta.atom & atom.specification & { spec?: = "https://www.rfc-editor.org/rfc/rfc4632" min_prefix?: numeric.count max_prefix?: numeric.count within?: [cidr4] excluding?: [cidr4] } @doc:""" IPv6 network constraint vocabulary. Instance is `cidr6`. `min_prefix`/`max_prefix` narrow the prefix length within the family range 0-128. `within` and `excluding` list IPv6 networks, each a `cidr6`, with the semantics of `cidr4_type`: subnet-of for `within`, non-overlap for `excluding`. """ cidr6_type => meta.atom & atom.specification & { spec?: = "https://www.rfc-editor.org/rfc/rfc4291" min_prefix?: numeric.count max_prefix?: numeric.count within?: [cidr6] excluding?: [cidr6] } @doc:"MAC address (EUI-48) constraint vocabulary. Instance is `mac`." mac_type => meta.atom & atom.specification & { spec?: = "https://www.rfc-editor.org/rfc/rfc9542" } @doc:""" Host name constraint vocabulary. Instance is `hostname`. A domain name as a host names it: labels of ASCII letters, digits and hyphens (RFC 1123 §2.1), or internationalized labels judged by IDNA2008 (RFC 5890 to RFC 5893), written as U-labels or as their A-labels, in any mix. `A`-`Z` read as `a`-`z`; nothing else is mapped, so uppercase beyond ASCII, a U-label not in NFC and percent-encoding are not host names. A label is at most 63 octets and the name at most 253, counted in the A-label form; no label is empty, none begins or ends with `-`, and there is no trailing `.`. The last label does not begin with a digit, so a dotted-quad is never a host name. The value is the name: every spelling of one name is one value, and its canonical text has each internationalized label as its U-label. `allow_idn` false admits only names with no internationalized label, in either spelling. """ hostname_type => meta.atom & atom.specification & { spec?: = "https://www.rfc-editor.org/rfc/rfc5890" allow_idn?: boolean ~ true } @doc:""" Host constraint vocabulary. Instance is `host`. RFC 3987's `ihost` with a DNS name: a host name as `hostname_type` has it, an IPv4 address in dotted-quad, or an IPv6 address, written with or without the brackets a URI puts around one. No zone identifier. The value is the name or the address, never both; a name compares by name, an address by its octets, and an IPv4 address never equals an IPv6 one, IPv4-mapped included. The canonical text is the member's: the name's U-labels, the dotted-quad, or RFC 5952 text without brackets. """ host_type => meta.atom & atom.specification & { spec?: = "https://www.rfc-editor.org/rfc/rfc3987" } @doc:""" Media type constraint vocabulary. Instance is `media_type`. A media type (RFC 6838) and its parameters (RFC 9110 §8.3.1): the type and subtype are RFC 6838 §4.2's `restricted-name`, and each parameter is a token name, `=` and a token or quoted-string value, after a `;` with optional whitespace around it. Nothing beyond US-ASCII. A media range (`text/*`) is not a media type. The value is the type, the subtype and a map of parameters: the type, subtype and parameter names compare without ASCII case, a quoted value equals its token form, parameter order carries no meaning and a repeated name is a resolver error, and a parameter value keeps its case except `charset`'s, which folds. The canonical text is lowercase, with `charset` folded and parameters sorted by name, each value a token where it is one, joined by `;` without whitespace. `allow_parameters` admits parameters, false by default. `types` lists the top-level types admitted. `suffixes` lists RFC 6839 structured suffixes: a suffix admits a subtype ending `+` and the suffix, and the subtype that is the suffix itself. A refinement withdraws `allow_parameters` and shrinks `types` and `suffixes`; it never widens them. """ media_type_type => meta.atom & atom.specification & { spec?: = "https://www.rfc-editor.org/rfc/rfc6838" allow_parameters?: boolean ~ false types?: [text] suffixes?: [text] } @doc:""" URI constraint vocabulary per RFC 3986. Instances are `uri` and `uri_reference`. The facets are `net.iri_type`'s, over RFC 3986's grammar: `schemes` lists the admitted schemes as `net.scheme_name` values, which fold case; `allow_relative` admits a relative reference (§4.2) beside a URI (§3), so its default is a URI-reference (§4.1); `allow_fragment` admits a fragment (§3.5), and withdrawing it beside `allow_relative` leaves an absolute-URI (§4.3). A URI is US-ASCII (§2), and its text as written, as an IRI is. """ uri_type => unicode.text_type & atom.specification & { spec?: = "https://www.rfc-editor.org/rfc/rfc3986" schemes?: net.scheme_set allow_relative?: boolean ~ true allow_fragment?: boolean ~ true normalization?: = NONE } @doc:"UUID constraint vocabulary. Instance is `uuid`." uuid_type => meta.atom & atom.specification & { spec?: = "https://www.rfc-editor.org/rfc/rfc9562" version?: numeric.count } } @doc:"Email address per RFC 5322." @atom.ordering:NONE @atom.bounded:false email => !net.email_type {} @doc:""" IPv4 address, dotted-quad per the RFC 3986 IPv4address production. Totally ordered by numeric address value over a finite 32-bit space. """ @atom.ordering:TOTAL @atom.bounded:true ipv4 => !net.ipv4_type {} @doc:""" IPv6 address, RFC 4291 §2.2 text representation. Zone identifiers (RFC 4007, `fe80::1%eth0`) are host-local and excluded from the contract. Totally ordered by numeric address value over a finite 128-bit space. (TSON text: contains colons, so quote it.) """ @atom.ordering:TOTAL @atom.bounded:true ipv6 => !net.ipv6_type {} @doc:""" IPv4 network, address `/` prefix length 0-32 (RFC 4632). PARTIAL ordering is by containment: a network precedes another when its address range is a strict subset; CIDR blocks never partially overlap, so any two are nested or disjoint, and disjoint networks are incomparable. (TSON text: contains `/`, so quote it.) """ @atom.ordering:PARTIAL @atom.bounded:false cidr4 => !net.cidr4_type {} @doc:""" IPv6 network, address `/` prefix length 0-128 (RFC 4291 §2.3). PARTIAL ordering is by containment, as for cidr4. (TSON text: contains colons and `/`, so quote it.) """ @atom.ordering:PARTIAL @atom.bounded:false cidr6 => !net.cidr6_type {} @doc:""" MAC address, EUI-48: six hex octets, colon- or hyphen-separated (RFC 9542). An opaque hardware identifier — like uuid, ordering is not semantically meaningful. (TSON text: the colon form must be quoted; the hyphen form may go unquoted.) """ @atom.ordering:NONE @atom.bounded:false mac => !net.mac_type {} @doc:""" Internet host name, in either label form: `Example.COM` and `example.com` are one value, and so are `xn--bcher-kva.example` and `bücher.example`, whose canonical text is the second. See `net.hostname_type`. """ @atom.ordering:NONE @atom.bounded:false hostname => !net.hostname_type {} @doc:""" A host: a `hostname`, an IPv4 address or an IPv6 address, one string-class type, so `localhost`, `"127.0.0.1"`, `"::1"` and `"[::1]"` need no tag. See `net.host_type`. """ @atom.ordering:NONE @atom.bounded:false host => !net.host_type {} @doc:""" A media type without parameters: `text/html`, `application/ld+json`. See `net.media_type_type`. """ @atom.ordering:NONE @atom.bounded:false media_type => !net.media_type_type {} @doc:"A URI-reference (RFC 3986 §4.1): a URI or a relative reference." @atom.ordering:NONE @atom.bounded:false uri_reference => !net.uri_type {} @doc:"A URI (RFC 3986 §3): the scheme is required." @atom.ordering:NONE @atom.bounded:false uri => !uri_reference ^ { allow_relative: false } @doc:"128-bit identifier per RFC 9562." @atom.ordering:NONE @atom.bounded:false uuid => !net.uuid_type {} }