mirror of
https://seed.radicle.dev/rad:z3trNYnLWS11cJWC6BbxDs5niGo82.git
synced 2026-10-18 19:10:39 +08:00
It was written as a string shorthand, but that's not valid ABNF for its purpose.
215 lines
9.3 KiB
ABNF
215 lines
9.3 KiB
ABNF
; This grammar is written using ABNF, as defined in RFC 5234
|
|
; (https://datatracker.ietf.org/doc/html/rfc5234), from which ALPHA, DIGIT
|
|
; and HEXDIG are borrowed
|
|
;
|
|
; Furthermore, this grammar is based on and specialises the generic URI
|
|
; specification (https://datatracker.ietf.org/doc/html/rfc3986) for Radicle,
|
|
; from which 'query', 'fragment', 'host', 'port', 'unreserved', 'pchar', ...
|
|
; are borrowed
|
|
|
|
; tag::overview[]
|
|
; RFC 3986 defines the syntax for 'query' and 'fragment'
|
|
rad = rad-scheme ":" rad-auth-and-resource rad-resource-type-and-identity [ "?" query ] [ "#" fragment ]
|
|
/ rad-scheme ":" rad-legacy
|
|
|
|
rad-scheme = "rad"
|
|
|
|
; RFC 3986 allows an absolute resource path without authority, i.e. a URI
|
|
; that looks like this: rad:/{RID}/{NID}
|
|
; We don't include that sort of URI in this scheme, because it's, strictly
|
|
; speaking, unnecessary in this context, and may seem confusing.
|
|
rad-auth-and-resource = "//" [ rad-auth ] "/" rad-resource ; abs. resource "path" with authority
|
|
/ rad-resource ; rel. resource "path"
|
|
|
|
; rad-legacy are URLs defined by RIP #3. That URL doesn't quite hold up
|
|
; against the general URI syntax defined in RFC3986, in so far that a node
|
|
; (identified with NID or NID@host) is the conceptual authority, not
|
|
; a repository.
|
|
; To be noted is that RIDs and NIDs are distinct enough that there should not
|
|
; be any ambiguity between rad-auth-and-resource and rad-legacy.
|
|
; Of all current implementations, this mostly impacts the git remote helper
|
|
; git-remote-rad.
|
|
rad-legacy = "//" rad-resource
|
|
; end::overview[]
|
|
|
|
; The NID is conceptually ambiguous from an RFC 3986 syntax perspective:
|
|
;
|
|
; authority = [ userinfo "@" ] host [ ":" port ]
|
|
;
|
|
; Is the NID 'userinfo' or 'host'? In a sense, it currently is a little bit
|
|
; of both. Furthermore, Radicle requires that if a hostname (+ port) is
|
|
; given, the NID must be given too. Therefore, instead of using 'authority'
|
|
; strictly as given by RFC 3986, we allow ourselves a slightly different
|
|
; syntax, which is fine. Do note also, that a 'host' can still be made to
|
|
; look like an NID, so programs dealing directly with the Radicle network
|
|
; will have to be prepared to handle that ambiguity appropriately.
|
|
; tag::authority[]
|
|
;
|
|
; TODO: There already are ways to resolve its NID from a hostname.
|
|
; For example, if `radicle-httpd` runs next to the node, then it can be
|
|
; queried for its NID via HTTPS. Also, there are ways to use DNS TXT records,
|
|
; which is also done for DNS-SD.
|
|
; We would therefore likely make the `rad-node` optional, or even omit it.
|
|
; If `rad-node` is sufficiently different from a DNS name (it probably is
|
|
; not), then we can even omit "@".
|
|
rad-auth = rad-node [ "@" rad-host-and-port ]
|
|
|
|
; TODO: Port might be optional in the future, once we have convinced IANA
|
|
; to assign one to us. There currently is no default port.
|
|
rad-host-and-port = host ":" port
|
|
|
|
; rad-node is a semantic symbol, to signify intent
|
|
rad-node = rad-nid
|
|
|
|
; An NID is an ID that is ultimately a public key in the Radicle network.
|
|
; This is used to uniquely represent a node, or a user (also a node), or a
|
|
; namespace within a repository.
|
|
; It is a [multibase] and [multicodec] encoded string, using [base58btc] as the multibase
|
|
; and the codec for the underlying Ed25519 public key.
|
|
;
|
|
; It is always 48 characters long, including the initial "z6Mk",
|
|
; the `z` corresponding to the base, and `6Mk` corresponding to the codec.
|
|
;
|
|
; [base58btc]: https://digitalbazaar.github.io/base58-spec/
|
|
; [multibase]: https://www.ietf.org/archive/id/draft-multiformats-multibase-07.html
|
|
; [multicodec]: https://github.com/multiformats/multicodec/
|
|
;
|
|
; TODO: New NIDs in the future? Even this might change, as we allow rotating
|
|
; keys for nodes. But this is even further out than stable IDs for users.
|
|
rad-nid = "z6Mk" 44( base58btc )
|
|
; end::authority[]
|
|
|
|
; tag::resource[]
|
|
rad-resource = rad-repository [ "/" rad-namespace ]
|
|
|
|
; rad-repository is a semantic symbol, to signify intent
|
|
rad-repository = rad-rid
|
|
|
|
; rad-namespace is a semantic symbol, to signify intent
|
|
rad-namespace = rad-nid
|
|
|
|
; An RID uniquely represents a git repository in the Radicle network.
|
|
; It is a [multibase] encoded string of a Git OID, using [base58btc] as the multibase.
|
|
;
|
|
; It is 28 or 29 characters long, including the initial multibase identifier "z".
|
|
;
|
|
; [base58btc]: https://digitalbazaar.github.io/base58-spec/
|
|
; [multibase]: https://www.ietf.org/archive/id/draft-multiformats-multibase-07.html
|
|
;
|
|
; TODO: In the near future (as soon as Git repositories with SHA-256 object
|
|
; format become popular, which will be in late 2026), we will have to extend
|
|
; the syntax of RIDs. Leave a note here so that implementors know this and
|
|
; make design decisions accordingly.
|
|
rad-rid = "z" 27*28( base58btc )
|
|
; end::resource[]
|
|
|
|
; tag::resource-type-and-identity[]
|
|
; 'rad-resource-type-and-identity' is empty by default, and more resource
|
|
; types and identities will be added further on, using the ABNF =/ operator,
|
|
; see RFC 5234 "3.3. Incremental Alternatives: Rule1 =/ Rule2"
|
|
rad-resource-type-and-identity = ""
|
|
|
|
; tag::git-type-and-identity[]
|
|
; For git specific resource types
|
|
rad-resource-type-and-identity =/ git-commit / git-tree / git-blob / git-tag
|
|
|
|
git-commit = "/" "commit" "/" git-obj-or-ref
|
|
git-tree = "/" "tree" "/" git-obj
|
|
git-blob = "/" "blob" "/" git-obj
|
|
git-tag = "/" "tag" "/" git-obj-or-ref
|
|
|
|
; Note: this rule will always be ambiguous, as something that looks like a
|
|
; git object ID could very well be a branch or a tag.
|
|
; Some git commands will warn when such refs are used, but not all.
|
|
git-obj-or-ref = git-obj / git-ref
|
|
; Currently, only sha1 identities are supported.
|
|
git-obj = git-sha1
|
|
; HEXDIG is defined in RFC 5234
|
|
git-sha1 = 40HEXDIG
|
|
|
|
; unreserved is defined in RFC 3986. Not that this syntax allows much
|
|
; more than what can be specified for a git reference. It's left to
|
|
; the implementation to parse and apply semantics properly.
|
|
; Our best reference for how to interpret and parse git references is
|
|
; https://git-scm.com/docs/protocol-common.html
|
|
git-ref = 1*unreserved *( "/" 1*unreserved )
|
|
; end::git-type-and-identity[]
|
|
|
|
; tag::rad-cob-type-and-identity[]
|
|
; For Radicle collaborative object resource types
|
|
rad-resource-type-and-identity =/ rad-cob / rad-cobs
|
|
|
|
rad-cob = "/" "cob" "/" rad-cob-type "/" rad-cob-obj
|
|
rad-cobs = "/" "cob" "/" rad-cob-type
|
|
|
|
; The COB type is like a reversed FQDN. The syntax spec is derived from
|
|
; https://datatracker.ietf.org/doc/html/rfc1034#section-3.5
|
|
rad-cob-type = rad-cob-label 1*( "." rad-cob-label )
|
|
rad-cob-label = 1*( ALPHA / DIGIT ) *( "-" 1*( ALPHA / DIGIT ) )
|
|
|
|
; syntactically, radicle COB objects and object revisions are git objects
|
|
; semantically, they are as well, at least for now
|
|
rad-cob-obj = git-obj
|
|
; end::rad-cob-type-and-identity[]
|
|
; end::resource-type-and-identity[]
|
|
|
|
; tag::rfc5234[]
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; Copied from RFC 5234
|
|
|
|
ALPHA = %x41-5A / %x61-7A ; A-Z / a-z
|
|
DIGIT = %x30-39 ; 0-9
|
|
HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
|
|
|
|
; Copied from RFC 3986
|
|
host = IP-literal / IPv4address / reg-name
|
|
port = *DIGIT
|
|
|
|
IP-literal = "[" ( IPv6address / IPvFuture ) "]"
|
|
|
|
IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
|
|
|
|
IPv6address = 6( h16 ":" ) ls32
|
|
/ "::" 5( h16 ":" ) ls32
|
|
/ [ h16 ] "::" 4( h16 ":" ) ls32
|
|
/ [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
|
|
/ [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
|
|
/ [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
|
|
/ [ *4( h16 ":" ) h16 ] "::" ls32
|
|
/ [ *5( h16 ":" ) h16 ] "::" h16
|
|
/ [ *6( h16 ":" ) h16 ] "::"
|
|
|
|
h16 = 1*4HEXDIG
|
|
ls32 = ( h16 ":" h16 ) / IPv4address
|
|
IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
|
|
dec-octet = DIGIT ; 0-9
|
|
/ %x31-39 DIGIT ; 10-99
|
|
/ "1" 2DIGIT ; 100-199
|
|
/ "2" %x30-34 DIGIT ; 200-249
|
|
/ "25" %x30-35 ; 250-255
|
|
|
|
reg-name = *( unreserved / pct-encoded / sub-delims )
|
|
|
|
pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
|
|
|
|
query = *( pchar / "/" / "?" )
|
|
|
|
fragment = *( pchar / "/" / "?" )
|
|
|
|
pct-encoded = "%" HEXDIG HEXDIG
|
|
|
|
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
|
|
sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
|
|
/ "*" / "+" / "," / ";" / "="
|
|
; end::rfc5234[]
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; Base58 Bitcoin Alphabet
|
|
base58btc = "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9"
|
|
/ "A" / "B" / "C" / "D" / "E" / "F" / "G" / "H" / "J"
|
|
/ "K" / "L" / "M" / "N" / "P" / "Q" / "R" / "S" / "T"
|
|
/ "U" / "V" / "W" / "X" / "Y" / "Z"
|
|
/ "a" / "b" / "c" / "d" / "e" / "f" / "g" / "h" / "i"
|
|
/ "j" / "k" / "m" / "n" / "o" / "p" / "q" / "r" / "s"
|
|
/ "t" / "u" / "v" / "w" / "x" / "y" / "z"
|