This is a very informal RFC draft
tl;dr I'm trying to write a protocol and URL scheme, one that uses existing protocols to make it easier to find web resources. This is not intended as a replacement for any existing protocols
What problem are you trying to address?
Being able to access a web resource by its intended name.
I'll use Datadog (no affiliation) as an example.
Their domain is https://www.datadoghq.com/ while the intended name is Datadog.
How do you find their site today?
If I wanted to go to Datadog's website today I would enter datadog, the name I'm familiar with, into a search engine.
How would you like to find their site?
- What if I could just type
@datadoginto my client, be it a Browser, CLI, etc. and have it resolve to their website? - What if I could write an email to
@datadog@supportor even enter@datadog@support@emailand have it open my email client with their email address? - What if I could make requests to their API by addressing
@datadog@apiwithout having to worry about 301's, or API version upgrades?
How would you do that?
An optionally stateless, decentralized protocol that can be implemented by agents with the purpose of resolving web resources by their intended names. A protocol that works with existing IP's, maximizing interoperability.
How is this different then...
DNS lookups?
...
Editing your host file?
...
Gnunet's GNS or (insert name system here)?
...
The Spec
Handle Syntax
The handle establishes a new URI scheme. It is a sequence of components, each defined as any number of characters, preceded by the @ character.
@[schemaurl]@[schemahash]@[schemaencoded]@[name]
While each component is optional at least one handle must follow the
@character.
schemaurl
This is a URL that returns a schema file. e.g. https://www.datadoghq.com/schema.json
schemahash
This is a short or long SHA256 hash of a Base64-encoded ASCII string of the target schema file. It is for clients to resolve cached versions if they exist.
schemaencoded
This is a Base64-encoded ASCII string of the target schema file.
name
The handle name is any additional handle segment to be resolved using the template syntax.
Every handle segment is optional. It would be possible to access
@https://www.datadoghq.com/schema.json@s9fa9da9@datadag,@s9fa9da9@datadag, or@datadog, they would all resolve to the same output.
Template Syntax
-
A scopes template can be a literal string value.
-
It also supports interpolated values from previously resolved scopes or dynamic values e.g.
#{[handle]}.
It cannot reference a parent or child scope handle in its template.
- It can also extend another scope by setting the value to another scopes handle and optionally replacing the extended scopes template e.g.
[handle]:[template].
It cannot extend a child scope
Examples
Given the schema:
{
"version": "1.0.0",
"scopes": {
"@datadog": "datadoghq.com",
"@datadog@eu": "@datadog:datadoghq.eu",
"@datadog@api": "api.#{@datadog}/api/#{@datadog@api}",
"@datadog@https": "https://#{@datadog}/#{@datadog@https}"
}
}
The following would resolve to
@datadog@eu@api -> api.datadoghq.eu/api/
Dynamic values
@datadog@https@about -> https://datadoghq.com/about
Agent Resolve
Below defines the protocol for resolving a handles component parts
Schema
The following is a pseudo code example of how an agent resolves a handles schema file
segments = handle.split('@')
if isCached(segments, cache)
return getCache(segments, cache)
else if isEncoded(segments[0])
schema = decode(segments[0])
else if isUrl(segments[0])
schema = fetch(segments[0])
if schema
hash = hashSchema(schema)
cacheSchema(segments[0], hash, schema, cache)
return getCache(segments, cache)
else
return :(
Scope
Given a handle and its associated schema file, the following is pseudo code of how a agent resolves a handles scope
segments = handle.split('@')
...
Output
Given a handle and its associated scope, the following is pseudo code of how a agent resolves a handles output
segments = handle.split('@')
...
Schema Format
{
version: 1,
scopes: {
handle: template
}
}
Scope Format
This is the same as the full schema but only the scopes included in a particular handle
{
version: 1,
scopes: {
handle: template
}
}
Output Format
The output format is defined by the target scopes template. The output does not have to be an absolute URI.
TODO
- come up with a name for the protocol
- write a rest service that implements the protocol
- write a web client that optionally assigns itself as a protocol handler
- write a CLI client that optionally assigns itself as a protocol handler
- write a redirect service that provides automatic URL redirection
Example REST API
The rest api will be responsible for proxying schema files, resolving a scope, and parsing and formatting a handle to a URL. It will act as an agent implementing the protocol.
GET /api/v1/resolve/${handle}
This endpoint will return a response payload with the following format
{
ok: true,
schema: {
version,
scopes
},
scope: {
handle: template
},
output: string
}
If there is an error the response format is
{
ok: false,
error: message
}
FAQ
How are scopes with the same name resolved?
The unique identifier will be the first component i.e. the schema file URL. Once the address is cached by either the client or the service it will no longer need to be included in the full handle. If there are multiple scopes with the same name cached, the agent will proceed with a search and return a list of matching handles and their associated scopes.
How does this protocol interoperate with existing protocols like DNS?
This protocol is not meant to be a replacement for DNS. The protocol would not override any DNS records. A handle lookup may or may not return a URI.
What is the security model?
Similar to a site owner validation process where the vetting agent validates that the response body of an HTTP request to the domain matches some criteria e.g. Google Analytics site validation.