Document: RFC-BETTY-001
Category: Experimental
Status: Draft
Date: November 2025
Authors: The BeTTY Project Contributors
This document specifies an experimental protocol for the Internet community and requests discussion and suggestions for improvements. Distribution of this memo is unlimited.
This is a pre-IETF draft, subject to change and reformatting.
BeTTY ("Better TeleType") is a federated, topic-based knowledge graph protocol that provides an alternative to the World Wide Web. BeTTY combines semantic web concepts, keyed-encryption based access control (KEBAC), and local-first architecture to create a secure, distributed information system. This document describes the BeTTY protocol, including its data model, network communication, and security mechanisms.
BeTTY (or simply "betty") is a topic-based local-first knowledge graph protocol that combines the most useful aspects of Project Xanadu, Plan 9 From Bell Labs, Gopher, IPFS, Wikis, and NoSQL into a human- and machine-readable alternative to the World Wide Web.
The BeTTY Protocol is a federated system of information exchange colloquially known as Bettyland. BettyDocs, JSON-LD files with extensible schemae and cryptographic permission structures, are exchanged among local-first nodes asynchronously.
After the FTP search engine (archie) and the gopher search engines (jughead, veronica), we will finally name a protocol after the only intelligent public-domain Archie comics main character: Betty Cooper.
The BeTTY protocol provides a method for distributed, encrypted information storage and retrieval across a federated network. BeTTY organizes information by topic using content-addressed storage and cryptographic permissions, with a many-to-many tag system to organize documents, rather than strict hierarchies.
BeTTY aims to avoid a lot of the cruft accumulated during the past 30 years of experimentation with the World Wide Web, a useful but ultimately troubled protocol. In bettyland, we ask: what if we took a different path? What if we could retake a crucial fork in the road to what we used to call the Information SuperHighway?
For BeTTY, that moment was represented by Gopher, a text-based competitor to the WWW. Gopherspace's "index server" search engines (WAIS, Veronica and Jughead) were based on the first Internet indexing search engine, Archie (which crawled FTP servers).
Gopher was built at the University of Minnesota to resemble a worldwide, interconnected hierarchical filesystem; everything served was either a resource or a menu of resources and/or inline text. Betty, on the other hand, is built to resemble gopher.
What if, after all these Archie Comics references, they finally got around to naming something after the only intelligent Riverdale character, Betty Cooper? The rest of them are all chuckleheads anyway.
BeTTY began as a simple proposition: what if we implemented gopher, but using flexible, machine- and human-readable JSON instead of the clunky old spreadsheet-style gophermap? What if instead of a "semantic web" we built a semantic gopher, based on the structured but extensible JSON-LD standard?
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
Node
A BeTTY server instance running the bettyd daemon
Topic
A content-addressed identifier for a document
Revision
A specific version of a topic identified by content hash
BettyDoc
A JSON-LD document conforming to the BeTTY specification
BettyMsg
A network transmission format for BeTTY documents
Bettyland
The UNIX-style ecosystem which delivers BeTTY's functionality (the servers and utilities which comprise the system)
KEBAC
Keyed Encryption-Based Access Control
LUMA
List, Upsert, Message, Append - BeTTY's API core verbs
PRPH
Poor Richard's Pseudo-Homomorphism - operations on encrypted data
BeTTY follows a client-server model where:
btty, httbd) construct BettyMsg requestsbettyd) process requests and return responsesBeTTY organizes information as documents with three types:
All document types can be extended via JSON-LD inheritance.
BeTTY operates as a federated network:
BeTTY uses a simple request/response protocol:
BeTTY replaces traditional CRUD (Create, Read, Update, Delete) with four core operations:
List: Query for documents, return single document or queue of links
Upsert: Create or replace entire document
Message: Append message to queue (blind append capable)
Append: Append data to document (copy-on-write)
The List operation has two distinct return behaviors based on query specificity:
Single Document Return - When the query uniquely identifies one document (e.g., by topic hash):
{
"meta": {
"result_count": 1
},
"payload": {
"topic": "abc123",
"title": "The Actual Document",
"content": "Full document content..."
}
}Queue Return - When the query matches multiple documents (e.g., by tag, criteria, or pattern):
{
"meta": {
"result_count": 2
},
"payload": {
"results": [
{
"topic": "abc123",
"title": "Getting Started with BeTTY",
"url": "betty://betty.directory/abc123"
},
{
"topic": "def456",
"title": "Advanced BeTTY Patterns",
"url": "betty://betty.directory/def456"
}
]
}
}This mirrors Gopher's behavior: a menu item either leads to a resource (single document) or another menu (queue of links).
Components MAY extend LUMA with additional verbs that provide specialized operations. These extensions MUST be clearly documented as non-core operations.
Example Extension - Fetch:
The Fetch operation is a convenience operation provided by a post-processing plugin like molloy that:
// Fetch response (always single document)
{
"routing": {
"to":"<IDENTITY>",
"topic": "abc123"
},
"meta": {
"title": "Single Document",
"docType":"content"
},
"payload": "Wfg6jlkfgFGHy5r3429dfd..." // an encrypted string
}Default port: 770 (seventy times ten, a nod to Gopher's port 70)
Alternative port: 70 (OPTIONAL, for compatibility)
Transport: HTTP/1.1
Encryption: Application-level (not TLS/SSL)
BeTTY uses port 770 by default to honor Gopher's legacy (70 × 11) while avoiding conflicts with any remaining legacy gopherspace servers. Port 770 was previously assigned to CadLock license management software, which has been discontinued following Autodesk's acquisition of CadLock, Inc.
Implementations MAY use port 70 for compatibility with existing Gopher infrastructure, but SHOULD default to port 770 unless explicitly configured otherwise.
betty://<node>[:<port>]/<path>
Components:
betty:// - Protocol scheme<node> - Node identifier (FQDN, domain, IP, or special name)<port> - Port number (OPTIONAL, defaults to 770)<path> - Topic path or querybetty.directory is a fully-qualified domain name, pointing to 127.0.0.1 (local-loopback). It is the default server location for all nodes.
betty://betty.directory/welcome
betty://betty.directory:770/users/alice
betty://node.example.com/articles/123
betty://node.example.com:70/topics/abc123
betty://remote-node/topics/abc123
URLs MAY include query parameters:
betty://betty.directory/list?tags=tutorial
betty://betty.directory/list?created_after=2025-01-01
BeTTY uses HTTP/1.1 over port 770 (or optionally port 70) as its transport protocol. Nodes MUST support HTTP/1.1 and MAY support HTTP/2. TLS/SSL is not required for transmission, as BettyMsg uses its own encryption-in-flight.
All BeTTY operations are accessed via REST API endpoints:
POST /api/v1/list
POST /api/v1/upsert
POST /api/v1/message
POST /api/v1/append
GET /api/v1/version
GET /api/v1/stats
HTTP Method: POST (for LUMA operations)
Content-Type: application/json
Body: BettyMsg (JSON document)
Example Request:
POST /api/v1/list HTTP/1.1
Host: betty.directory:770
Content-Type: application/json
Content-Length: 234
{
"routing": {
"from": "alice@example",
"to": "alice@betty.directory",
"signatures": [...]
},
"meta": {
"tags": ["article"]
},
"payload": "Wfg6jlkfgFGHy5r3429dfd..." // an encrypted string
}
Note: The @context is NOT included in wire messages. It is automatically prepended by one of the following bettyland components:
meta.tagsHTTP Status: 200 OK (for successful operations)
Content-Type: application/json
Body: BettyMsg response
Example Response:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 1234
{
"routing": {
"from": "betty.directory",
"to": "alice@example",
"signatures": [...]
},
"meta": {
"result_count": 2
},
"payload": {
"results": [
{
"topic": "abc123",
"title": "Getting Started",
"created": "2025-11-07T10:00:00Z"
},
{
"topic": "def456",
"title": "Advanced Topics",
"created": "2025-11-07T11:00:00Z"
}
]
}
}
Note: Response messages also omit @context. Clients apply context based on API version and document tags.
Nodes SHOULD support gzip compression:
Content-Encoding: gzipAccept-Encoding: gzipNodes MAY use HTTP keep-alive for multiple requests over a single connection.
The BettyDoc standard described below had two parts: the wire protocol (BettyMsg) and the storage format (BettyDoc).
Network messages exchanged via the Betty API MUST use this structure:
{
"routing": {
"from": "<sender-identity>",
"to": "<recipient-identity>",
"signatures": [...],
"content_hash": "<hash>"
},
"meta": {
"tags": [...],
"timestamp": "<ISO-8601-timestamp>"
},
"payload": {
...data...
}
}The BettyMsg should be encrypted to the node key of the server to which it is being sent, which obviates the routing.to key if the node's identity is the intended recipient.
Context Resolution: The @context key is NOT transmitted in wire messages. Instead:
/api/v1/ implies context version 1.0);meta.tags;When submitted to a node, the BettyMsg MUST be encrypted to the public node key of the server, which MUST be made available at betty://<SERVERNAME>/node.key.
All stored documents MUST conform to this structure:
{
"betty": {
"topic": "<content-hash>",
"rev": "<revision-hash>",
"owner": "<identity>",
"created": "<ISO-8601-timestamp>",
"modified": "<ISO-8601-timestamp>",
"permissions": {
"<identity>": <octal>
}
},
"meta": {
"tags": ["<tag1>", "<tag2>"],
"indices": {
"<field>": "<value>"
}
},
"<doctype>": {
...content...
}
}Required Keys:
betty - Local context metadatameta - Document metadata (i.e., information about the payload)content, queue, or directory, or a registered extension.When a BettyMsg is converted to BettyDoc, the routing key of the message is processed into the betty key, which holds information about the document which is relevant to the local server context.
This includes local permissions, cryptographic data, creation and revision dates, and anything about the file which is specific to the local node.
The meta key, on the other hand, SHOULD remain portable between wire and storage as-is. Local tagging and reindexing may change the contents of these keys in practice.
Topic Hash: SHA-256 of document content or meta.criteria
Revision Hash: SHA-256 of entire document including metadata
First revision: topic == rev
Subsequent revisions: topic unchanged, rev updated
The corpus to be hashed depends on the document type. For content style documents, the payload (e.g., the content key) is hashed to create the topic.
For queues and directories, which MAY operate as endpoints for collecting mutable lists or maps of data, the value of the meta.criteria key is hashed to create the topic.
The payload key (i.e., the third key in the BettyDoc) is hashed to create the rev of the document.
Documents MAY include an optional meta.salt key whose value is a string appended to either the content or meta.criteria before hashing. This allows:
Salt Application:
topic_hash = SHA-256(content + meta.salt)
rev_hash = SHA-256(entire_document + meta.salt)
Example with Salt:
{
"betty": {
"topic": "xyz789",
"rev": "xyz789"
},
"meta": {
"salt": "random-string-12345",
"tags": ["article"]
},
"content": {
"title": "Article",
"body": "Content..."
}
}Without the salt, this document would have topic hash abc123. With salt: "random-string-12345", it has topic hash xyz789.
The salt value MUST be preserved across all revisions of a topic to maintain topic identity. Changing the salt creates a new topic, not a new revision.
BettyMsg documents do NOT include explicit @context keys in wire transmission. Instead, context is applied through a layered system:
Layer 1 - API Context (applied by lakehouse):
/api/v1/ → context v1.0)betty://betty.land/contexts/api/<version>Layer 2 - Tag Contexts (applied by taghead):
meta.tags may reference a JSON-LD contextExample Context Resolution:
{
"meta": {
"tags": ["article", "tutorial"]
}
}Results in composed context: 1. betty://betty.land/contexts/api/1.0 (from API version) 2. betty://betty.land/contexts/tags/article (from "article" tag) 3. betty://betty.land/contexts/tags/tutorial (from "tutorial" tag)
Nodes MUST cache context documents locally. Clients and servers MUST apply the same context resolution rules to ensure semantic interoperability. Clients and servers MAY compose all applicable JSON-LD schemas into a single prepended schema document, or simply use the API schema as a base and then progressively apply any schema requirements imposed by each tag's JSON-LD schema progressively.
Content (type: content):
{
"betty": {...},
"meta": {...},
"content": {
"title": "Document Title",
"body": "Document content..."
}
}Queue (type: queue):
{
"betty": {...},
"meta": {...},
"queue": [
{
"from": "alice@example",
"timestamp": "2025-11-07T10:00:00Z",
"message": "Queue entry 1"
},
{
"from": "bob@example",
"timestamp": "2025-11-07T10:01:00Z",
"message": "Queue entry 2"
}
]
}Directory (type: directory):
{
"betty": {...},
"meta": {...},
"directory": {
"file1.txt": {
"topic": "abc123",
"size": 1024,
"modified": "2025-11-07T10:00:00Z"
},
"file2.txt": {
"topic": "def456",
"size": 2048,
"modified": "2025-11-07T11:00:00Z"
}
}
}The three basic DocTypes are extensions of each other:
BettyMsg → Content → Queue → Directory
Likewise, these DocTypes may be extended using JSON-LD schemas. For storage purposes, the directory is extended into volume, and volume is extended into various storage formats:
Directory → Volume → TarballVol → FileDirVol
TarballVol → RSSVol → XMLVol
The volume type extends the directory type by requiring a meta.manifest key that contains a comprehensive listing of all files in the volume. The manifest structure is:
{
"meta": {
"manifest": {
"filename1.txt": {
"topic": "abc123",
"size": 1024,
"modified": "2025-11-14T10:00:00Z",
"permissions": "644",
"checksum": "sha256:..."
},
"subdir/filename2.json": {
"topic": "def456",
"size": 2048,
"modified": "2025-11-14T11:00:00Z",
"permissions": "755",
"checksum": "sha256:..."
}
}
}
}Manifest Requirements:
topic - Content hash of the file (REQUIRED)size - File size in bytes (REQUIRED)modified - Last modification timestamp (REQUIRED)permissions - Unix-style permissions (OPTIONAL)checksum - Verification hash (OPTIONAL)The manifest provides a complete inventory of volume contents, enabling verification, synchronization, and integrity checking without accessing individual files.
Volume vs Directory:
Each node's server process must be started using the node key, which provides the node with a cryptographic identity on the federated network. This means all system configuration files and storage must be encrypted using this same key. Multiple nodes and node processes MAY use the same node key, but MUST have unique FQDNs or domain names on their local network.
BeTTY uses encryption-based access control:
Authorization: Granted by encrypting to recipient's public key
Authentication: Proven by successful decryption
No passwords, no session tokens, no role lookups.
Content hashing uses SHA-256, without making assumptions about the forward secrecy of these content hashes in the face of quantum decryption. However, for signing and encryption of data, BeTTY merely requires that the encryption be declared and that decryption binaries be available for free. This should allow quantum-proof encryption to remain compatible with Bettyland.
BeTTY additionally uses UNIX-style octals with BeTTY semantics to allow more complex access control, with full Access Control List capability.
Permissions denoted by octals resemble UNIX permissions, but are BeTTY-specific for the purposes of preserving meaning in a federated system where "read" permissions imply "copy":
| Octal | Binary | Permissions | Meaning |
|---|---|---|---|
| 0 | 000 | --- |
No access |
| 1 | 001 | --x |
Indexable (searchable) |
| 2 | 010 | -w- |
Write-only (blind append) |
| 3 | 011 | -wx |
Write and index |
| 4 | 100 | r-- |
Read-only |
| 5 | 101 | r-x |
Read and index |
| 6 | 110 | rw- |
Read and write |
| 7 | 111 | rwx |
Full access |
In this context, "write" (octal 2) means the ability to update the topic (i.e., modify the document at the content hash which identifies this stream of revisions within the node).
Server configuration MAY allow forked writes when a user has read permission (4) but not write permission (2) for a document. In this case:
abc123r-- but not rw-)def456abc123 remains unchangedThis allows users to create derivative works from read-only documents without modifying the original. The forked document maintains a reference to its source in the meta section. Since the new topic hash is computed from the modified content, the fork is naturally content-addressed.
Example Forked Write:
{
"betty": {
"topic": "def456",
"rev": "def456",
"owner": "alice@example",
"permissions": {
"alice@example": 7
}
},
"meta": {
"forked_from": "abc123",
"forked_by": "alice@example",
"fork_date": "2025-11-14T10:00:00Z"
},
"content": {
"title": "Modified Version",
"body": "Alice's changes..."
}
}Note that topic equals rev for the first revision of a forked document, maintaining BeTTY's content-addressing principle.
Forked writes are controlled by the server configuration parameter lakehouse.forked_write (boolean). When disabled, write attempts to read-only documents return an Unauthorized error.
Documents stored in NBSON format: - Line 0: Index (key→line mapping) - Line 1+: Encrypted values - Each line independently encrypted - EOF automatically closes structures
The key→line mapping MAY nominate dot-notated key values.
All BettyMsgs MUST be signed:
{
"routing": {
"signatures": [
{
"identity": "alice@example",
"algorithm": "ed25519",
"signature": "<base64-signature>",
"timestamp": "2025-11-07T10:00:00Z"
},
"<base64-signature>"
]
}
}The signature object MUST be JSON-compliant. Nodes MUST verify signatures before processing requests.
Public keys distributed via: - /api/v1/keys/<identity> endpoint - Out-of-band exchange
Nodes MUST cache public keys with configurable TTL.
Each node identified by:
In the case of a local node (i.e., whose domain name is betty.directory and IP address is 127.0.0.1), the node key MUST be unique. You MAY run multiple nodes on the same IP address, but they MUST have separate hostnames and/or port numbers.
Nodes communicate using the LUMA API:
Node A → POST /api/v1/list → Node B
Node B → Response → Node A
Transclusion: Reference remote content without copying
Caching: Cache remote content locally with TTL
Pinning: Agreement to host content for another node
Replication: Full replication of topics across nodes
Nodes MAY implement:
Nodes can host encrypted content without reading it:
betty file data which MUST be encrypted to the node keymeta encrypted to node (for indexing)content/queue/directory encrypted to ownerNode can route/index but not read user content.
BeTTY uses standard HTTP status codes:
200 OK: Successful operation
400 Bad Request: Invalid BettyMsg format
401 Unauthorized: Missing or invalid signature
403 Forbidden: Insufficient permissions
404 Not Found: Topic does not exist
429 Too Many Requests: Rate limit exceeded
500 Internal Server Error: Node malfunction
503 Service Unavailable: Node temporarily unavailable
{
"routing": {
"from": "node@example",
"to": "requesting-identity"
},
"meta": {
"tags": ["error"]
},
"payload": {
"error": "ErrorName",
"message": "Human-readable description",
"details": {
"field": "Additional context"
}
}
}Unauthorized: Insufficient permissions for operation
Unauthenticated: Cannot decrypt document
NotFound: Topic does not exist
InvalidFormat: Document does not conform to schema
SignatureInvalid: Signature verification failed
RateLimitExceeded: Too many requests
Clients SHOULD:
bettyd nodes without having to read or write raw BettyMsg requestsServers SHOULD:
The reference implementation uses NBSON ("NBSON is Betty's Standard Object Notation"). Storage backends seeking to replace NBSON MUST support its guarantees:
Nodes SHOULD support:
BeTTY protects against:
BeTTY does NOT protect against:
Users MUST:
BeTTY's authentication model requires:
Data Privacy: Encryption protects content from node operators
Metadata Privacy: Document structure visible in index line
Network Privacy: Use Tor or VPNs to hide node access patterns
Social Graph Privacy: Endorsements and relationships are public
Nodes SHOULD implement:
Key Strength: Minimum 256-bit security level
Random Number Generation: Use cryptographically secure RNG
Constant-Time Operations: Prevent timing attacks in crypto operations
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997.
[RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform Resource Identifier (URI): Generic Syntax", STD 66, RFC 3986, January 2005.
[RFC7231] Fielding, R. and J. Reschke, "Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content", RFC 7231, June 2014.
[RFC8032] Josefsson, S. and I. Liusvaara, "Edwards-Curve Digital Signature Algorithm (EdDSA)", RFC 8032, January 2017.
[JSON-LD] "JSON-LD 1.1: A JSON-based Serialization for Linked Data", W3C Recommendation, 16 July 2020.
[RFC1436] Anklesaria, F., et al., "The Internet Gopher Protocol (a distributed document search and retrieval protocol)", RFC 1436, March 1993.
[Xanadu] Nelson, T., "Project Xanadu", http://xanadu.com/
This section provides guidance for the Internet Assigned Numbers Authority (IANA) regarding registrations required for the BeTTY protocol.
Scheme Name: betty
Status: Provisional (pending IETF review)
Scheme Syntax:
betty-URI = "betty://" authority path-abempty [ "?" query ]
authority = host [ ":" port ]
host = IP-literal / IPv4address / reg-name
port = *DIGIT
Scheme Semantics: The betty URI scheme identifies resources in the BeTTY federated knowledge graph protocol. Resources are content-addressed documents served over HTTP/1 on port 770 (or optionally port 70).
Encoding Considerations: betty URIs are encoded as per RFC 3986. Topic and revision identifiers use base64url encoding (RFC 4648).
Applications/Protocols: BeTTY protocol (this specification)
Interoperability: betty:// URIs are not directly compatible with http:// or https:// but can be accessed via httbd gateway.
Security Considerations: See Section 11 of this document.
Contact: betty-protocol@betty.land
References: This document, BeTTY Protocol Specification
Service Name: betty
Port Number: 770
Transport Protocol: TCP
Description: BeTTY Protocol - Federated knowledge graph protocol using HTTP/1 over port 770
Assignee: BeTTY Protocol Working Group
Contact: betty-protocol@betty.land
Reference: This document, BeTTY Protocol Specification
Note: Port 770 was previously assigned to CadLock (license management, now defunct after Autodesk acquisition). BeTTY repurposes this port as 70×11, preserving the reference to Gopher (port 70) while avoiding conflicts with legacy gopherspace that may still operate on the original port.
Service Name: betty-alt
Port Number: 70
Transport Protocol: TCP
Description: BeTTY Protocol - Alternative port for compatibility with Gopher infrastructure
Assignee: BeTTY Protocol Working Group
Contact: betty-protocol@betty.land
Reference: This document, BeTTY Protocol Specification
Status: OPTIONAL - For use in environments where port 770 is unavailable or when operating alongside Gopher services
Note: Port 70 was historically assigned to Gopher protocol (RFC 1436). BeTTY can optionally use this port as a semantic successor to Gopher, serving structured JSON-LD documents instead of plaintext menus. Implementations SHOULD default to port 770 unless explicitly configured otherwise.
Type name: application
Subtype name: vnd.betty.doc+json
Required parameters: None
Optional parameters: - charset: Must be "utf-8" if specified - doctype: One of "content", "queue", "directory"
Encoding considerations: 8bit (UTF-8)
Security considerations: See Section 11 of this document. Documents may contain encrypted content requiring private keys for decryption.
Interoperability considerations: BettyDoc format is a strict superset of JSON-LD. Standard JSON-LD processors can parse BettyDoc but may not understand BeTTY-specific semantics.
Published specification: This document, BeTTY Protocol Specification
Applications: BeTTY protocol implementations, bettyd servers, btty clients
Additional information:
Contact: betty-protocol@betty.land
Intended usage: COMMON
Restrictions on usage: None
Author: BeTTY Protocol Working Group
Change controller: BeTTY Protocol Working Group
Type name: application
Subtype name: vnd.betty.msg+json
Required parameters: None
Optional parameters:
charset: Must be "utf-8" if specifiedencrypted: "true" if content is encryptedEncoding considerations: 8bit (UTF-8) or binary if encrypted
Security considerations: See Section 11 of this document. Messages contain routing information and may be encrypted end-to-end.
Interoperability considerations: BettyMsg format extends JSON-LD with routing semantics. Compatible with JSON-LD processors for @context and payload sections.
Published specification: This document, BeTTY Protocol Specification
Applications: BeTTY protocol implementations, network communication
Additional information: - Magic number(s): None - File extension(s): .bettymsg, .json - Macintosh file type code(s): TEXT
Contact: betty-protocol@betty.land
Intended usage: COMMON
Restrictions on usage: None
Author: BeTTY Protocol Working Group
Change controller: BeTTY Protocol Working Group
Type name: application
Subtype name: vnd.betty.nbson
Required parameters: None
Optional parameters:
compression: Compression algorithm ("gzip", "zstd", "none")encrypted: "true" if content is encryptedEncoding considerations: Binary
Security considerations: See Section 11 of this document. NBSON files contain encrypted data with line-delimited structure enabling PRPH operations.
Interoperability considerations: NBSON is a binary format specific to BeTTY. Requires NBSON-compatible parser. Not compatible with standard JSON parsers without conversion.
Published specification: This document, NBSON Specification
Applications: BeTTY storage engines, nbson implementations
Additional information:
Contact: betty-protocol@betty.land
Intended usage: COMMON
Restrictions on usage: None
Author: BeTTY Protocol Working Group
Change controller: BeTTY Protocol Working Group
BeTTY defines several JSON-LD contexts that should be registered with schema.org or an equivalent vocabulary registry:
Base Context: betty://betty.land/contexts/api/0.9
DocType Contexts:
betty://schema/content/v1 - Content document typebetty://schema/queue/v1 - Queue document typebetty://schema/directory/v1 - Directory document typeExtension Contexts:
betty://schema/volume/v1 - Volume extensions (lakehouse)betty://schema/identity/v1 - Identity documents (janek)betty://schema/tag/v1 - Tag definitions (taghead)Namespace: https://betty.land/vocab#
Prefix: betty:
Contact: betty-protocol@betty.land
URI suffix: betty
Change controller: BeTTY Protocol Working Group
Specification document: This document
Related information: Returns JSON document describing BeTTY node capabilities:
{
"node": "node.example.com",
"port": 770,
"version": "0.9",
"public_key": "age1abc123...",
"capabilities": ["list", "upsert", "message", "append"],
"plugins": ["lakehouse", "taghead", "callme"],
"api_endpoint": "betty://node.example.com:770/api/v1"
}Header field name: X-Betty-Topic
Applicable protocol: HTTP
Status: Provisional
Author/Change controller: BeTTY Protocol Working Group
Specification document: This document
Related information: Contains the topic identifier (content hash) of the requested or returned BeTTY document.
Example: X-Betty-Topic: abc123def456...
Header field name: X-Betty-Rev
Applicable protocol: HTTP
Status: Provisional
Author/Change controller: BeTTY Protocol Working Group
Specification document: This document
Related information: Contains the revision identifier (version hash) of the requested or returned BeTTY document.
Example: X-Betty-Rev: abc123def456-rev5
Header field name: X-Betty-Signature
Applicable protocol: HTTP
Status: Provisional
Author/Change controller: BeTTY Protocol Working Group
Specification document: This document
Related information: Contains cryptographic signature of the document content. May appear multiple times for multiple signatures.
Example: X-Betty-Signature: ed25519:abc123...
Name: BeTTY Document Format
+suffix: +bettydoc
References: This document
Encoding considerations: Same as application/json (RFC 8259)
Interoperability considerations: BettyDoc-structured data follows JSON-LD conventions with additional BeTTY-specific semantics.
Fragment identifier considerations: Fragment identifiers follow JSON Pointer (RFC 6901) syntax for referencing parts of BeTTY documents.
Security considerations: See Section 11 of this document.
Contact: betty-protocol@betty.land
All registrations requested in this section relate to a protocol that:
IANA should note that:
BeTTY inherits from Gopher but differs significantly:
| Aspect | Gopher | BeTTY |
|---|---|---|
| Data Format | Text menus | JSON-LD |
| Structure | Hierarchical | Topic-based graph |
| Security | None | Encryption-first |
| Access Control | Server-based | Cryptographic (KEBAC) |
| Semantics | None | JSON-LD contexts |
| Distribution | Centralized | Federated |
| Port | 70 | 770 (primary), 70 (optional) |
| Transport | Raw TCP | HTTP/1.1 |
| Content Addressing | Path-based | Hash-based |
Client Request (List):
POST /api/v1/list HTTP/1.1
Host: betty.directory:770
Content-Type: application/json
{
"routing": {
"from": "alice@example",
"signatures": [{
"identity": "alice@example",
"algorithm": "ed25519",
"signature": "base64-encoded-signature"
}]
},
"meta": {
"tags": ["tutorial"]
},
"payload": {
"query": {
"tags": ["tutorial"]
}
}
}
Note: No @context in wire message. Server applies: 1. API context (v1.0 from /api/v1/) 2. Tag context (tutorial)
Server Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"routing": {
"from": "betty.directory",
"to": "alice@example",
"signatures": [...]
},
"meta": {
"result_count": 2,
"tags": ["tutorial", "beginner", "advanced"]
},
"payload": {
"results": [
{
"topic": "abc123",
"title": "Getting Started with BeTTY",
"tags": ["tutorial", "beginner"],
"created": "2025-11-07T10:00:00Z",
"owner": "bob@example"
},
{
"topic": "def456",
"title": "Advanced BeTTY Patterns",
"tags": ["tutorial", "advanced"],
"created": "2025-11-08T14:30:00Z",
"owner": "carol@example"
}
]
}
}
Note: Client applies same context resolution as server to interpret response.
BeTTY uses port 770 as its primary port for several reasons:
BeTTY implementations MAY use port 70 for:
However, implementations SHOULD:
Clients discovering BeTTY nodes SHOULD:
/.well-known/betty for explicit port configurationType name: application
Subtype name: vnd.betty+json
Required parameters: None
Optional parameters: version, doctype
Encoding considerations: UTF-8
Security considerations: See Section 11
Interoperability considerations: Requires JSON-LD support
Published specification: This document
Applications that use this media type: BeTTY clients and servers
Fragment identifier considerations: JSON Pointer (RFC 6901)
Additional information: None
Person & email address to contact: betty-protocol@betty.land
Intended usage: COMMON
Restrictions on usage: None
Author: The BeTTY Project
Change controller: The BeTTY Project
Network Layer: - HTTP/1.1 over TCP (well-understood protocol) - No TLS required (encryption at application layer) - DDoS mitigation via rate limiting
Application Layer: - JSON parsing (use hardened parsers) - Signature verification (constant-time operations) - Encryption/decryption (use audited libraries)
Storage Layer: - File system access (standard OS permissions) - Content-addressed storage (immutable hashes) - NBSON format (line-delimited structure)
BeTTY is designed for cryptographic agility:
The BeTTY Project
https://betty.land
Email: betty-protocol@betty.land
Copyright (C) The BeTTY Project (2025). All Rights Reserved.
This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works.
This document itself may not be modified in any way, such as by removing the copyright notice or references to the BeTTY Project, except as needed for the purpose of developing BeTTY standards in which case the procedures for copyrights defined in the BeTTY Process must be followed, or as required to translate it into languages other than English.
The limited permissions granted above are perpetual and will not be revoked by the BeTTY Project or its successors or assigns.
This document and the information contained herein is provided on an "AS IS" basis and THE BETTY PROJECT DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
BeTTY builds upon ideas from:
Special thanks to:
End of RFC
Comments and feedback welcome at: betty-protocol@betty.land