mmurl://

Specification

The mURL specification.

Version 0.2, an experimental draft. It is the normative reference for the format and for resolution behavior, as implemented by the reference implementation in this repository.

  • experimental draft
  • format v0.2
  • reference v0.5.0
  • unregistered scheme

murl://authority/name[@version][?query][#selector]

the shape of every mURL, from §3 of the grammar

Read SPECIFICATION.md on GitHub

Not a standard, and not on a track to becoming one yet. Nothing in this document is an internet standard and it must not be presented as one. The murl scheme and the application/murl+json media type are both unregistered; the intended path is provisional registration per RFC 7595 §5.2 once the format stabilizes, which has not happened. Until then the specification claims only the conventional murl:// string.

What it covers

SectionContents
§3 Syntax The ABNF grammar for murl://authority/name[@version][?query][#selector], the constraints every parser must enforce, and the canonical form that defines identity.
§4 Authorities The reserved local namespace and DNS-named authorities — who is allowed to define a name.
§5 Manifest The envelope, top-level members, resource members, and relations between resources (dependsOn, ordering).
§6 Resolution The pipeline, where manifests live (the well-known path), caching, identity binding, recursion, the normative limits, and selector failure semantics.
§7 Canonical form MCF-1, the byte form a signature covers, and the ed25519 signature block.
§8 Security Principles, the three tiers — safe sensitive dangerous — and the baseline policy. Summarized here, detailed in the security model.
§9 Versioning murlVersion, pinned versus @latest name versions, and the rollback window that @latest implies.
§10–11 Registration, extensions Registration status and the extension points: custom:* kinds, unknown-member handling, the reserved query component.

Changes from 0.1

0.2 is additive over 0.1, and consumers must still accept manifests declaring "murlVersion": "0.1". Duplicate JSON members are now explicitly invalid (§5.1); the optional notBefore member bounds a manifest's validity window; selectors gained multiple items and the role= / tag= forms; and the mutability contract for @latest is spelled out rather than implied.

The conformance suite

A specification with one implementation is a description of that implementation. The vector suite exists to make a second implementation cheap to build and cheap to check: run the vectors, and you know whether you agree with the reference implementation on the cases that actually matter.

153
conformance vectors
6
rules to satisfy, the sixth optional
2
implementations: Rust reference, Python
222
tests in the reference
tree
spec/conformance/
  manifests/valid/*.murl.json     must parse AND validate with zero errors
  manifests/invalid/*.murl.json   must fail parsing, OR produce ≥1 error
  murls/valid.txt                 one mURL per line; each must parse
  murls/invalid.txt               one mURL per line; each must be rejected
  canonical/*.input.json          exact bytes of *.canonical.json, or fail
  signatures/{valid,invalid}/     must verify / fail — optional

Six rules an implementation has to satisfy — the sixth only if it verifies signatures:

  1. Valid manifests parse and produce no validation errors. Warnings are allowed — several valid vectors deliberately carry unknown members, which must warn and never fail.

  2. Invalid manifests are rejected, either at parse time or by validation with at least one error. Which of the two is implementation-defined; failing to reject at all is a conformance failure.

  3. Valid mURLs parse and round-trip — re-parsing the canonical form yields an equal value. Some vectors are deliberately non-canonical on input and must normalize.

  4. Invalid mURLs are rejected. No repair, no guessing.

  5. Canonical form — each input document must canonicalize to the exact bytes of its .canonical.json twin. This rule exists because a second implementation passed the first four while producing different bytes, which would have made every signature it checked or produced incompatible.

  6. Signatures (optional) — vectors under signatures/valid must verify and those under signatures/invalid must fail, for the stated reason. One is deliberately hostile to the obvious shortcut: an implementation that re-serializes its typed view before verifying drops an unknown member and fails.

Validation is a static check: it never consults the clock or the network. A vector whose expires is in the past is still valid if its format and ordering are correct — time-of-use policy is a resolution concern, tested separately.

bash
# against the reference implementation
cargo test -p murl-core --test conformance

Against your own implementation, point a harness at the four locations above and apply the four rules. The reference harness is about a hundred lines and is a fine template. Vectors are versioned with the specification: new ones are added freely, existing ones change only when the spec does.

What is stable, and what is not

Nothing here is stable yet, and the project says so in the same place it says everything else. The grammar, the manifest format, MCF-1 and the signature block, and the well-known resolution path are all experimental, intended to freeze at 1.0 — the format's grammar specifically once a second implementation passes the conformance suite. The canonical form freezes with the format for a mechanical reason: changing it invalidates every signature already issued.

After 1.0, patch releases are editorial, minor releases are strictly additive, and anything that would make an older consumer unsafe rather than merely less capable is a major change. One exception is stated up front: a change required to fix a vulnerability may break compatibility in any release, because the alternative is a format whose defects are permanent.

After 1.0May contain
patchEditorial changes only.
minorStrictly additive changes; older consumers stay safe, merely less capable.
majorAnything that would make an older consumer unsafe.
anyA change required to fix a vulnerability may break compatibility.

Full stability and compatibility policy

Registration considerations

  • The murl scheme is unregistered. Provisional registration per RFC 7595 §5.2 is the intended path once the format stabilizes; the template is drafted in the repository but has not been submitted.
  • application/murl+json is likewise unregistered; the +json structured syntax suffix follows RFC 6839.
  • Unrelated single-URL libraries named "murl" exist on PyPI and crates.io. The name collides; the scheme string itself has no known conflicting deployment. Both are documented in prior art.

The drafted registration templates