Internet-Draft J.J. Brucker draft-foopgp-uetree-00 foopgp Intended status: Informational Mnème Expires: 2026-11-27 foopgp 27 May 2026 uetree — Universal Entities Tree, a Filesystem-Native Format for Decentralised Entity Registries draft-foopgp-uetree-00 Abstract This document specifies "uetree" (Universal Entities Tree), a filesystem-native format for organising registries of entities — humans, organisations, software agents, services — across multiple identifier types (cryptographic identifiers, e-mail addresses, telephone numbers, names) in a way that scales to billions of entries while remaining navigable with plain POSIX tools. A uetree instance is a directory tree with mirror multi-rooted branches (one per identifier type), each indexing the same universe of entities under a different naming convention. Each level of the tree carries a self-describing ".FORMAT" file pointing back to the instance root, so any subtree extracted in isolation remains intelligible. Cross-branch references and inter-instance redirections are expressed as plain-text files using a common typed, versioned pointer format. The format is deliberately conservative. It does not require any database, daemon, or special filesystem feature: a uetree instance is just files and directories that can live in a git repository, on a USB stick, or behind a static web server. Decentralisation is achieved by having many independent uetree instances that may publish, share, or refer to each other. This document defines uetree version 1.1. Version 1.0 was posted in May 2026. Version 1.1 adds a normative recommendation on leaf-file naming to ease merge operations during entity promotion. Status of This Memo This is an Internet-Draft submitted in full conformance with the provisions of BCP 78 and BCP 79. Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). They are subject to change and may be replaced or obsoleted at any time. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/. This Internet-Draft will expire on 27 November 2026. Copyright Notice Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved. This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info). Table of Contents 1. Introduction 1.1. Motivation 1.2. Relationship to Other Work 2. Conventions and Terminology 3. Format vs Instance 4. Typed Versioned Pointer 4.1. Syntax 4.2. Parsing 4.3. Reserved Conventional Files 5. Tree Structure 5.1. Multi-Root Layout 5.2. Auto-Localisation: .FORMAT 5.3. Canonical Branch: by-id/ 5.4. Visibility: Public-by-Nature vs Private-by-Nature 6. Branches and Fan-Out 6.1. by-id/u4/<2c>/<4c>// 6.2. by-id/u5//// 6.3. by-email//// 6.4. by-tel/<+cc>//<+E164>/ 6.5. by-name//<1>/<2>// 6.6. Reserved Roots for Future Versions 7. Entry Files 7.1. README.md 7.2. .ALIASES — Intra-Structure Pointers 7.3. .HOMONYMS — Disambiguation 7.4. .LINKS — Extra-Structure Pointers 7.5. Mutual Exclusivity of Entry Anchor Files 7.6. Leaf File Naming (1.1) 8. Canonical Operations 8.1. Promotion 8.2. Disambiguation 8.3. Alias-Chain Resolution 9. Deployment Modes 9.1. Private Monolithic Instance 9.2. Public Split Instances 9.3. Mixed Instance with Filtered Mirrors 10. Versioning and Graceful Degradation 11. Interaction with Access-Control Layers 12. URI Scheme (Non-Normative) 13. Internationalisation 14. IANA Considerations 15. Privacy Considerations 16. Security Considerations 17. References 17.1. Normative References 17.2. Informative References Authors' Addresses 1. Introduction 1.1. Motivation Decentralised systems that aim to recognise individuals, organisations and software agents — webs of trust, cooperative governance platforms, digital commons, mutual-aid currencies — need to maintain registries of entities. Such registries must typically be reached through multiple identifiers: a cryptographic key fingerprint, an e-mail address, a phone number, a legal name. None of these is universal: keys may not yet exist, e-mail addresses change, names collide, phone numbers leak privacy. A pragmatic registry therefore needs several indexes pointing to a single canonical record, and a clear discipline for promoting provisional entries to canonical ones as cryptographic identifiers become trusted. This document specifies such a discipline as a filesystem layout, suitable for storage in a git repository or on any POSIX filesystem. The format trades the conveniences of a relational database for the durability and portability of plain files, and for the trustworthiness of cryptographic signatures over content. 1.2. Relationship to Other Work uetree builds on long-standing prior art for hierarchical naming and federated directory services: o the Domain Name System [RFC1034] and its hierarchical labelled tree; o X.500 directories [X500] and LDAP [RFC4511], with attribute-based entry lookup; o Decentralised Identifiers (DIDs) [W3C-DID], which formalise identifier resolution against multiple methods; o petname systems and Zooko's triangle [ZOOKO], which capture the tension between secure, memorable and decentralised naming; o content-addressable storage approaches (Plan 9 Venti, git [GIT], IPFS [IPFS]), from which uetree borrows the idea of a directory tree as a self-describing data structure. uetree differs from these in that it is not a name resolution protocol or a database, but a filesystem layout convention. It describes how to lay out files on disk so that any consumer that understands the convention can read them with no additional software. uetree has a sibling format, "uftree" (Universal Files Tree, [I-D.foopgp-uftree]), which applies the same conventions to immutable file contents identified by their cryptographic hash. Where uetree indexes mutable entities, uftree indexes immutable contents. Both share the typed versioned pointer format (Section 4) and the reserved conventional files. 2. Conventions and Terminology The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here. The following terms are used throughout this document: entity A real-world or digital actor whose existence the registry is intended to record: a human, an organisation, a software agent, a service, a device. An entity may be known under several identifiers. identifier A string that designates an entity. Identifiers fall into types: cryptographic identifiers (such as the eid family defined in [I-D.foopgp-openpgp-id]), e-mail addresses, telephone numbers in E.164 form, human-readable names. eid OpenPGP Entity Identifier, as defined in [I-D.foopgp-openpgp-id]. Two variants are in use: u4 (humans, derived from civil registry) and u5 (any other entity, derived from a timestamp and geographic origin). This document treats eids as a particular kind of cryptographic identifier; the format does not depend on their internal structure. instance A specific deployment of a uetree: a directory hierarchy that follows this specification, optionally hosted in a git repository. branch A first-level subdirectory of a uetree instance, named "by-/" and indexing entries by a particular identifier type. leaf The deepest directory of a branch, named after a single identifier value, holding the files that describe one entity under that identifier. canonical When an entity has a leaf under "by-id/", that leaf is its canonical record. Other leaves for the same entity, under "by-email/" or "by-tel/" for example, are non-canonical and SHOULD link back to the canonical leaf via the ".ALIASES" file (Section 7.2). 3. Format vs Instance The format "uetree" is the convention described in this document. It is versioned. Tools may state that they implement "uetree 1.1" the way they state that they implement HTTP/1.1 or TLS 1.3. An instance of uetree is a particular directory tree that follows the convention. Instances are independent: different organisations, communities or individuals may run their own instances, with different visibility, different access control, and different sets of entities. The format does not prescribe how instances communicate with each other. Cross-instance references can be expressed as ".LINKS" entries (Section 7.4) carrying URIs; further integration is left to the deploying parties. 4. Typed Versioned Pointer 4.1. Syntax Many uetree files carry, on a single line, a pointer composed of three whitespace-separated fields: o : the family of the pointer. Defined types in this document: "uetree" (intra- or inter-instance pointer to a uetree node), "uftree" (pointer to a uftree node), "uri" (general URI [RFC3986]), and "file" (absolute POSIX path). Future versions or sibling specifications MAY register more types. o : the syntactic version of the family, e.g. "1.0", "1.1", "2.0". Consumers that do not recognise a version SHOULD emit a warning and continue if the surrounding context permits, rather than refuse the file. o : a family-specific value. It MUST NOT contain whitespace. If a value needs to encode whitespace or structural characters, it MUST be transport-encoded (percent-encoding when the family is URI-like, otherwise a family-defined escape). The line terminator MAY be LF or CRLF. A leading or trailing space on a pointer line MUST be ignored. 4.2. Parsing A reference parser, in POSIX shell, is one line: read type version value This is the recommended idiom for any tool that reads ".FORMAT", ".ALIASES", ".HOMONYMS" or ".LINKS". Consumers MUST treat lines whose first non-whitespace character is "#" as comments and skip them. Empty lines MUST be ignored. 4.3. Reserved Conventional Files Four conventional file names use the typed versioned pointer syntax inside a uetree instance: o ".FORMAT" — exactly one pointer line. Auto-localises the directory in which it sits (Section 5.2). Required at every level of an instance. o ".ALIASES" — zero or more pointer lines. Intra-structure references — typically uetree pointers to canonical leaves elsewhere in the same instance, or in another instance (Section 7.2). o ".HOMONYMS" — zero or more pointer lines. References to sibling leaves that share a derived identifier without sharing semantic identity, used for disambiguation of names and of weak hashes (Section 7.3). o ".LINKS" — zero or more pointer lines. Extra-structure references: URIs, filesystem paths, anything outside the uetree's own namespace (Section 7.4). No other file names are reserved by this specification. Tools MUST ignore files they do not recognise. 5. Tree Structure 5.1. Multi-Root Layout A uetree instance has the following top-level layout: / ├── .FORMAT ├── README.md (instance-level human description) ├── by-id/ │ ├── .FORMAT │ ├── u4/... │ └── u5/... ├── by-email/ │ ├── .FORMAT │ └── ... ├── by-tel/ │ ├── .FORMAT │ └── ... ├── by-name/ │ ├── .FORMAT │ └── ... └── REMOTE/ (optional, when hosted in a git repository under the access-control layer described in Section 11) Each branch is an independent index of the entity universe. A given entity MAY appear in zero, one, or several branches. When an entity has a canonical record under "by-id/", any non-canonical leaf for that entity SHOULD become an alias pointing to the canonical leaf, rather than holding a duplicate record. 5.2. Auto-Localisation: .FORMAT Every directory inside a uetree instance MUST carry a ".FORMAT" file whose single pointer line has the form: uetree The third field starts with "/" and refers to the root of the uetree instance, not to any POSIX filesystem root. Examples: cat /protagonists/.FORMAT uetree 1.1 / cat /protagonists/by-id/.FORMAT uetree 1.1 /by-id/ cat /protagonists/by-id/u4/.FORMAT uetree 1.1 /by-id/u4/ cat /protagonists/by-id/u4/sR/sRyU/sR…_42.17-002.76/.FORMAT uetree 1.1 /by-id/u4/sR/sRyU/sR…_42.17-002.76/ This auto-localisation has three consequences: o Any subtree extracted in isolation — "tar -czf"-ed, copied, mounted, served over HTTP — remains self-describing. o A tool that walks an arbitrary directory can identify whether it is inside a uetree instance and, if so, where in the instance it is. o A future schema check (".reject" hook in the access-control layer of Section 11) can verify that the directory contents match the schema implied by the ".FORMAT" path. 5.3. Canonical Branch: by-id/ The "by-id/" branch holds the canonical record of each entity it indexes. Sub-branches under "by-id/" are named after the identifier variant they use: o "by-id/u4/" for the u4 variant of OpenPGP entity identifier; o "by-id/u5/" for the u5 variant; o any future identifier variant designed to be unambiguous, forgery-resistant, and publishable. "by-id/" sub-branches are public-by-nature (Section 5.4): their identifiers are themselves designed to be publishable. 5.4. Visibility: Public-by-Nature vs Private-by-Nature Two orthogonal dimensions govern visibility: Dimension A — the branch. The mere existence of a leaf under a given branch may leak information. Branches divide into two classes: public-by-nature: "by-id/u4/", "by-id/u5/". The identifier is itself public, by construction; mapping it to a record adds no privacy leakage beyond what the identifier already entails. private-by-nature: "by-tel/", "by-name/", future "by-civil-status/". The identifier is personal data not protected by an OpenPGP-style design. Mapping it to an entity record is a privacy leak unless the consumer is authorised. "by-email/" is intermediate: an e-mail address may be public if the holder uses OpenPGP openly, or sensitive if not. Dimension B — the content. The "README.md" and other files of a leaf may be public or encrypted, independently of the branch. A leaf under "by-id/u5/" may carry a clear-text README; a leaf under the same branch may carry an encrypted README intended only for a circle. The operational rule is therefore: o Public deployments SHOULD only expose public-by-nature branches. o Within an exposed branch, individual leaves MAY remain encrypted at the discretion of their subject. o Private-by-nature branches MUST NOT appear in a public deployment. 6. Branches and Fan-Out Every branch uses a fan-out to limit the number of direct children of any single directory, typically below 10^4 entries per bucket, which is well within the limits of modern POSIX filesystems (ext4, btrfs, xfs, zfs). 6.1. by-id/u4/<2c>/<4c>// A u4 identifier [I-D.foopgp-openpgp-id] is 38 characters in the form "<22-base64url>_±". Fan-out: level 1: first 2 characters of the u4 level 2: first 4 characters of the u4 level 3: full u4 At about 16.7 million terminal buckets, a population of one billion humans would average about sixty records per bucket, well within filesystem comfort. If density rises further, a future "uetree 1.x" MAY introduce an additional intermediate level (<2>/<4>/<6>//) without breaking readers that only know the 1.0 fan-out. 6.2. by-id/u5//// A u5 identifier [I-D.foopgp-openpgp-id] is 30 characters in the form "e_", where "ts16" is a sixteen- character Unix timestamp and "_" is the coord14 geographic suffix. Fan-out: level 1: "e_" level 2: "e__" level 3: full u5 The leading "e" (for "earth") serves two purposes: it is a shared semantic anchor — every u5 originates on Earth, by design of the format — and it shields directory names from being parsed as command-line options when they begin with a minus sign (e.g. a negative longitude). This is a deterministic fan-out, not a geohash: two entities at very close longitudes that straddle a partition boundary (for example "005.38" and "005.40") will fall in different buckets. Scaling, not spatial indexing, is the primary goal. 6.3. by-email//// E-mail addresses are split as follows: level 1: last segment of the domain (TLD-as-is, not PSL) level 2: full domain (lowercase) level 3: full address, as supplied by the holder For example, the address user@bbc.co.uk falls under "by-email/uk/bbc.co.uk/user@bbc.co.uk/". Rare true ".uk" addresses (for instance under "nominet.uk") fall into the same level-1 bucket as ".co.uk" addresses; this is accepted as a trade-off. A future "uetree 2.0" MAY adopt the Public Suffix List [PSL] if operational experience demands it. Normalisation: o Domain: MUST be lowercase. o Local part: stored as the holder declares it; comparisons MUST be case-insensitive on the domain part and SHOULD be case-insensitive on the local part (as in many real deployments today), but the stored case is preserved for display. 6.4. by-tel/<+cc>//<+E164>/ This branch is private-by-nature. Telephone numbers are personal data not bound to a cryptographic key; mapping them to entities is a privacy leak. Numbers are stored exclusively in strict E.164 form [E.164], for example "+33612345678". Numbers that cannot be normalised to E.164 do not enter the branch in 1.x; a "by-tel/_unknown/" bucket MAY be defined in a future version if operational need arises. The stored leaf name MUST be the bare E.164 string (with the leading "+"). When the value is displayed to a human or embedded in a URI (links, RDF, vCard TEL property, etc.), it SHOULD be rendered as a "tel:" URI per [RFC3966], e.g. "tel:+33612345678". The "tel:" prefix is a presentation convention only; it is never part of the path on disk. Fan-out: level 1: "+" level 2: first digit of the local subscriber number (i.e. the digit immediately after the country code) level 3: full E.164 number, including the "+" Examples: by-tel/+33/1/+33123456789/ (a Paris landline) by-tel/+33/6/+33612345678/ (a French mobile) by-tel/+1/2/+12025551234/ (Washington DC landline) Level 2 gives a uniform fan-out of ten buckets per country code, regardless of how the local numbering plan is organised. If a country code grows very densely (for example "+86" or "+91"), a future "uetree 1.x" MAY selectively introduce a second local digit for that code. 6.5. by-name//<1>/<2>// This branch is private-by-nature. It is the fallback when no stronger identifier is available, and it is non-canonical: names collide. Slugs are kebab-case lowercase strings in Unicode Normalization Form C [UAX15] (NFC). The fan-out is by language tag and by the first one and two characters of the slug: level 1: BCP 47 language tag [RFC5646]. If the language of the name is unknown, the tag "und" (RFC 5646) MUST be used. POSIX "C" is NOT a valid tag. level 2: first Unicode character of the slug (NFC). level 3: first two Unicode characters of the slug (NFC). level 4: full slug. Examples: by-name/fr/s/sy/sylvie-renaud/ by-name/ja/山/山田/山田太郎/ by-name/ru/с/ст/стив-возняк/ Conventions: o Encoding: MUST be UTF-8. o Normalisation: NFC, to avoid the same name being represented by two different code-point sequences and landing in two separate paths. o Slug length: greater than one Unicode character; a name reduced to a single character is not indexable under "by-name/" and must be completed before insertion. When two distinct entities legitimately share a slug, the collision is resolved using ".HOMONYMS" (Section 7.3) and disambiguating suffixes such as "sylvie-renaud-1/" or "sylvie-renaud-marseille/". 6.6. Reserved Roots for Future Versions The following branch names are reserved by this specification for future use, to prevent ad-hoc adoption: o "by-civil-status/" — civil-registry-based identifiers (full surname, given names, date and place of birth). Many edge cases need to be settled (diacritics, partial dates, historical places, normalisation, applicable privacy law). Not specified in 1.x. 7. Entry Files 7.1. README.md A leaf directory MUST contain exactly one of "README.md", ".ALIASES", or ".HOMONYMS" (Section 7.5). When a leaf is the canonical record of an entity, it carries "README.md". The content of "README.md" is free-form Markdown in uetree 1.0 and 1.1. Implementations SHOULD nonetheless follow these conventions: o An optional YAML frontmatter block at the very start, used for structured metadata. Recommended keys include "email", "eid-claimed", "first-source-csv" (for treasury workflows), and so on. Keys with unknown semantics MUST be preserved by readers and round-tripped by writers (Postel's Law). o A first-level heading providing a short human title. o Free narrative body, possibly including links to other leaves expressed as uetree URIs (Section 12). Future versions may make some YAML keys mandatory. Until then, readers SHOULD tolerate variation. 7.2. .ALIASES — Intra-Structure Pointers A non-canonical leaf — typically under "by-email/", "by-tel/" or "by-name/", once promoted to "by-id/" — MUST replace its "README.md" with a ".ALIASES" file pointing to the canonical leaf, while preserving its ".FORMAT" file. The content of ".ALIASES" is a sequence of typed versioned pointers (Section 4) referring to other directories within any uetree instance. Example: cat by-email/com/yahoo.com/jdupont@yahoo.com/.ALIASES uetree 1.1 /by-id/u4/aB/aBcd/aBcdEf…_44.83_001.55/ uetree 1.1 /by-id/u4/xY/xYzw/xYzwAb…_48.50_007.74/ Multiple targets are allowed. This typically indicates an e-mail address that is genuinely shared by several entities, each with its own canonical leaf under "by-id/". The target path starts with "/" and refers to the root of the pointed instance. A pointer to another uetree instance (not the current one) MAY include an instance identifier in the value; the exact convention is left to deployers in 1.x and will be normalised in a future version. 7.3. .HOMONYMS — Disambiguation When a derived identifier — typically a slug under "by-name/", or a weak hash in [I-D.foopgp-uftree] — covers several distinct entities without semantic link, the slug directory contains neither "README.md" nor ".ALIASES" but a ".HOMONYMS" file listing the disambiguating leaves. Example: cat by-name/sylvie-renaud/.HOMONYMS uetree 1.1 /by-name/sylvie-renaud-1/ uetree 1.1 /by-name/sylvie-renaud-marseille/ Implementations SHOULD present the homonyms to the user and let the user choose, or surface them as a disambiguation list to upstream consumers. 7.4. .LINKS — Extra-Structure Pointers A ".LINKS" file in a leaf directory references resources outside the uetree instance: arbitrary URIs, POSIX paths, IPFS CIDs, git blob hashes, and so on. It is the counterpart of ".ALIASES" for references that leave the structured namespace. Example: cat by-id/u4/.../...//.LINKS uri 1.0 https://example.org/about/ uri 1.0 keys.foopgp.org/pks/lookup?op=index&search=0x file 1.0 /var/lib/foopgp/photos/.jpg The exact set of accepted types is open and may expand: new types are registered by sibling specifications without requiring a new uetree version. 7.5. Mutual Exclusivity of Entry Anchor Files A well-formed entry directory contains exactly one of the following three anchor files, in addition to its ".FORMAT": README.md ← the directory describes one canonical entity. .ALIASES ← the directory points to another canonical location (entity has moved or been promoted). .HOMONYMS ← the directory bears an ambiguous derived identifier (slug or weak hash) covering several unrelated entities. ".LINKS" is orthogonal: it MAY co-exist with "README.md", or stand alone in a uftree entry where no human description is appropriate. 7.6. Leaf File Naming (1.1) Operational experience with entity promotion (Section 8.1) showed that leaf merges across two instances — for example, moving from "by-email//" to "by-id/u4//" upon certification — must be safe under arbitrary file conflicts. Files with generic names such as a single date, a single label or a single counter are at risk of silent overwrites. uetree 1.1 therefore adds a SHOULD-level rule: Any file in a leaf directory, other than the reserved conventional files (".FORMAT", "README.md", ".ALIASES", ".HOMONYMS", ".LINKS"), SHOULD bear an intrinsically unique file name — sufficiently specific that no collision arises when the contents of one leaf are merged into another. The recommended pattern is to prefix the file name with an ISO 8601 timestamp at second granularity, followed by a source label. For example, a receipt produced by a treasury workflow: receipt/2026-05-12T14:32:08+00:00_HelloAsso_foopgp.asc The exception is "README.md", which is by design singular and whose merge is always an explicit editorial act. Some files have a structured, line-based content that admits automatic merge by content concatenation and sorting; such files MAY share a generic name across leaves, provided the tool that performs the merge knows how to combine them. uetree 1.1 leaves the catalogue of mergeable file names to the implementation; future versions MAY normalise it via a "/.MERGE-RULES" file at the instance root. Backward compatibility: o A "uetree 1.0" instance does not bear this obligation; a 1.1 tool encountering colliding names in a 1.0 instance issues a warning and falls back to manual resolution. o A "uetree 1.1" instance that nevertheless contains colliding generic names is in a non-compliant state and should be repaired by renaming the offending files. 8. Canonical Operations 8.1. Promotion Promotion moves an entity record from a non-canonical leaf (under "by-email/", "by-tel/", or "by-name/") to its canonical position under "by-id/". The triggering event is the certification, in an external trust system, of a strong identifier (eid) that the entity is known to hold. The canonical procedure is: 1. Verify, in the relevant trust system (for example, the foopgp web of trust [I-D.foopgp-openpgp-id]), that the claimed eid is bound to a verified credential. 2. Compute the target path under "by-id///" by applying the fan-out rules of Section 6. 3. Move ("git mv" or filesystem move) the "README.md" of the source leaf to the target. Move any leaf-specific files (subject to Section 7.6 uniqueness) likewise. When a file exists at both source and target and the tool knows a content-merge rule for it, merge it in place at the target; otherwise, abort the promotion and require manual resolution. 4. At the source leaf, replace the moved "README.md" with a ".ALIASES" file pointing to the new canonical position. Preserve the source's ".FORMAT". 5. Update the chain of ".FORMAT" files along the target path so each intermediate directory is correctly auto-localised. This procedure leaves the source path resolvable: users or tools that know the entity only by its non-canonical identifier (an old e-mail address, a phone number, a slug) can still traverse the alias chain to reach the canonical leaf. 8.2. Disambiguation When a second entity legitimately shares a "by-name/" slug, the canonical procedure (Section 6.5) is: 1. Move the first entity's "README.md" to a disambiguated slug directory, e.g. "sylvie-renaud-1/". 2. Create a new slug directory for the second entity, e.g. "sylvie-renaud-2/" or "sylvie-renaud-naturopathe/", with its own "README.md" and ".FORMAT" chain. 3. Replace the original slug directory's "README.md" with a ".HOMONYMS" file listing both new locations. 8.3. Alias-Chain Resolution A resolver that follows ".ALIASES" pointers MUST detect and abort on cycles. Recommended implementation: o Maintain a set of already-visited canonical paths. o Refuse to recurse if a path is encountered for the second time. o Limit the recursion depth to a small constant (for example sixteen) and abort with an error if the limit is reached. 9. Deployment Modes 9.1. Private Monolithic Instance A single git repository holds the entire tree, all branches confounded. Access is restricted to one or several owners identified by their OpenPGP fingerprints. This mode is appropriate when: o The set of authorised users is small and well-known. o Private-by-nature branches ("by-tel/", "by-name/") are used and MUST NOT leak. o Atomic transactional updates across branches are valued. 9.2. Public Split Instances Each publishable branch — typically "by-id/u4/" and "by-id/u5/" — lives in its own independent git repository ("uetree-by-id-u4.git", "uetree-by-id-u5.git", and so on). Each repository has its own ".FORMAT" rooted at the corresponding subtree, its own access-control configuration (Section 11), and its own publication channel. Private-by-nature branches do not appear in this mode. Visibility is enforced by absence of the repository, not by filtering. 9.3. Mixed Instance with Filtered Mirrors A private monolithic instance can publish its publishable branches to public split repositories using a post-receive filter (for example a "git filter-repo" subtree split or a periodic incremental mirror script). This mode combines operational convenience (single source of truth, atomic updates) with publication safety (only publishable branches reach the world), at the cost of divergence risk if the mirror process silently fails. Operators SHOULD monitor mirror lag. 10. Versioning and Graceful Degradation "uetree 1.0" is the initial published version. "uetree 1.1" is the version described by this document; it adds the leaf file-naming rule of Section 7.6 and is otherwise backward compatible. Future "1.x" versions will only add new features in a backward-compatible way: deeper fan-out, richer ".ALIASES" syntax, new branches, additional conventional files at the leaf. A tool that knows version 1.x of the format MUST tolerate reading instances of version 1.y where y > x: unknown conventional files SHOULD be ignored with a warning, unknown pointer types in ".LINKS" SHOULD be skipped, deeper fan-outs SHOULD be traversed. "uetree 2.0" is reserved for breaking changes — adoption of the Public Suffix List for "by-email/", hash-based fan-out for "by-id/u4/", or any other transformation that an 1.x tool cannot accommodate. Implementations MUST refuse to process a 2.0 instance with 1.x-only logic. 11. Interaction with Access-Control Layers A uetree instance hosted in a git repository typically uses an external access-control layer to enforce who may push which commits. The format itself does not specify access control; the recommended pattern, used by reference implementations, is to store access policies under a reserved top-level "REMOTE/" subdirectory whose contents are read by a "pre-receive" hook on the bare repository. The "REMOTE/" path is reserved by convention: tools MUST ignore it when computing the entity universe, and access- control policies SHOULD restrict who may modify it. The split between ".FORMAT" (what is here) and access-control files (who may modify what) is intentional: it lets either layer evolve independently. 12. URI Scheme (Non-Normative) The typed versioned pointer format is compatible with a URI reading: a pointer "uetree 1.1 /by-id/u4/sR/sRyU//" maps naturally to a URI of the form "uetree:/by-id/u4/sR/sRyU//". Within a single host instance, such URIs identify a node unambiguously. Cross-instance references would extend the syntax with an authority component, for example "uetree:///by-id/u4//". This document does not formally register the "uetree" URI scheme. Registration may follow once one or more implementations rely on cross-instance URI resolution. The present text records the open direction. 13. Internationalisation "by-name/" is the only branch with intrinsic language dependence; it carries a BCP 47 [RFC5646] language tag at level 1 and uses NFC normalisation (Section 6.5). "README.md" files are language-agnostic by default; the author SHOULD declare the language with a "lang:" YAML frontmatter key set to a BCP 47 tag. Translations live in companion files named "README.md.", e.g. "README.md.en" or "README.md.zh-Hant". Tools that only know "README.md" silently ignore translation companions, preserving compatibility with the wider Markdown ecosystem. 14. IANA Considerations This document requests no immediate IANA action. Should the "uetree" URI scheme be formalised in a later revision, registration under the "Provisional URI Scheme" registry would be requested following RFC 7595. Should pointer types in ".LINKS" be moved to a centrally maintained registry, registration under "Specification Required" policy [RFC8126] would be requested. 15. Privacy Considerations uetree is a layout convention. It does not by itself reveal private information; the choice of branches deployed, instance visibility, and per-leaf encryption all determine the effective privacy posture. Operators publishing a uetree instance SHOULD: o Restrict public deployment to public-by-nature branches (Section 5.4). o Avoid mixing public and private branches in a single public repository, even temporarily, since git history makes accidental publication irreversible. o Consider leaf-level encryption for entries whose content is sensitive even when their identifier is public. o When using "by-email/" publicly, document the implicit assumption that listed addresses participate in an identifiable trust system and accept the consequent visibility. Operators of private instances SHOULD use the access-control layer of Section 11 to ensure that read access matches the intent of the entities recorded. The fan-out structure may itself leak information: knowing that "by-id/u4/sR/" contains many leaves reveals the prevalence of u4 identifiers starting with "sR" in the instance. This leak is intrinsic to any indexed registry. 16. Security Considerations The format relies on signatures over content for authenticity. When stored in a git repository, the recommended pattern is to require signed commits and to define, in an external policy file ("REMOTE/pre-receive.acl" in the reference implementation), the set of authorised signers and the depth of writes they may perform. uetree itself defines no cryptographic primitives. All identifiers are taken as opaque strings; their unforgeability is the responsibility of the schemes that produce them ([I-D.foopgp-openpgp-id] for eids, [RFC5321] for e-mail addresses, [E.164] for telephone numbers). Tools that follow ".ALIASES" or ".LINKS" MUST sanitise the pointer values they read — never execute them, never assume they refer to safe locations — and MUST detect cycles (Section 8.3). When ".LINKS" pointers reference external resources, fetching those resources may leak the fact that the consumer was reading a particular leaf. Tools SHOULD allow operators to opt out of automatic ".LINKS" resolution. 17. References 17.1. Normative References [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997. [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, May 2017. [RFC3966] Schulzrinne, H., "The tel URI for Telephone Numbers", RFC 3966, December 2004. [RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform Resource Identifier (URI): Generic Syntax", STD 66, RFC 3986, January 2005. [RFC5321] Klensin, J., "Simple Mail Transfer Protocol", RFC 5321, October 2008. [RFC5646] Phillips, A. and M. Davis, "Tags for Identifying Languages", BCP 47, RFC 5646, September 2009. [E.164] ITU-T, "The international public telecommunication numbering plan", Recommendation E.164, 2010. [UAX15] Davis, M. and K. Whistler, "Unicode Normalization Forms", Unicode Standard Annex #15, 2024. [I-D.foopgp-openpgp-id] Brucker, J.J. and Mnème, "OpenPGP ID — Universal Digital Identity", draft-foopgp-openpgp-id-00, April 2026. 17.2. Informative References [RFC1034] Mockapetris, P., "Domain Names — Concepts and Facilities", STD 13, RFC 1034, November 1987. [RFC4511] Sermersheim, J., Ed., "Lightweight Directory Access Protocol (LDAP): The Protocol", RFC 4511, June 2006. [RFC7595] Thaler, D., Hansen, T., and T. Hardie, "Guidelines and Registration Procedures for URI Schemes", BCP 35, RFC 7595, June 2015. [RFC8126] Cotton, M., Leiba, B., and T. Narten, "Guidelines for Writing an IANA Considerations Section in RFCs", BCP 26, RFC 8126, June 2017. [X500] ITU-T, "Information technology — Open Systems Interconnection — The Directory: Overview of concepts, models and services", Recommendation X.500, 2019. [W3C-DID] Sporny, M., Longley, D., Sabadello, M., Reed, D., and O. Steele, "Decentralized Identifiers (DIDs) v1.0", W3C Recommendation, July 2022, . [ZOOKO] Wilcox-O'Hearn, B., "Names: Decentralized, Secure, Human-Meaningful: Choose Two", 2003. [GIT] Hamano, J.C. et al., "Git Distributed Version-Control System", git-scm.com, since 2005. [IPFS] Benet, J., "IPFS — Content Addressed, Versioned, P2P File System", arXiv:1407.3561, 2014. [PSL] Mozilla Foundation, "Public Suffix List", . [I-D.foopgp-uftree] Brucker, J.J. and Mnème, "uftree — Universal Files Tree, an Early Sketch", draft-foopgp-uftree-00, May 2026. Authors' Addresses Jean-Jacques Brucker foopgp u4=sRyUhEbNU5OwyLEjfSwaXAe_42.17-002.76 Mnème foopgp u5=001777236237.945e_43.30_005.38