# Namespace Resolution Protocol v0.1
**neurons.me  /  suiGn **
**Status:** Draft — Working Document
**License:** CC0 1.0 Universal — Public Domain

---

## Preamble
This document specifies the **Namespace Resolution Protocol (NRP)** for the `me://` URI scheme.

The **NRP** defines how a `me://` URI is resolved *from a symbolic address into a concrete semantic value*, across a **distributed mesh** of surfaces — without a central registry, without a central server, and without requiring persistent connectivity.

It is the *protocol* that closes the gap between:

- **Semantic resolution** — already implemented in `this.me`: local, mathematical, derivation-based. The kernel resolves `me.get("wallet.balance")` entirely offline.

- **Topological resolution** — the new work: how a requesting surface finds and reaches the surface that holds the target namespace, path, and key material.

  These two layers are separate concerns, implemented separately, but always composed in that order:

```
me://jabellae.cleaker.me[surface:iphone]/wallet.balance
         │                    │                 │
    topological           topological        semantic
    (find the             (find which        (resolve the
     namespace)            surface)           path locally)
```

The **NRP** specifies the topological layer. The semantic layer is already specified by `this.me`.

---

## 1. Definitions

**Namespace** — A named semantic domain. Represented as a human-readable label (e.g., `jabellae.cleaker.me`). A namespace is owned by whoever holds its root key material. There is no central authority that grants or revokes a namespace.

**Surface** — A physical or logical runtime context that can hold a `.me` kernel instance and participate in the mesh. Examples: an iPhone app, a MacBook daemon, a server process, a browser tab. A surface has a name within a namespace.

**Surface identity** — The cryptographic identifier of a surface within a namespace:

```
surface_id = hash(namespace_key, surface_name)
```

This is never the cleartext `surface_name`. Only holders of `namespace_key` can derive or verify a `surface_id`.

**Namespace key** — The root secret from which all key material in a namespace is derived. Equivalent to the seed in the derivation-based identity model. Never transmitted; always local.

**Endpoint descriptor** — A transport-layer locator for a surface (IP:port, relay address, onion address, etc.). Stored encrypted inside the surface index. Not the surface's identity — just how to reach it right now.

**Surface index** — A `.me` secret space, scoped under the namespace key, that maps surface identities to their current endpoint descriptors. It is the mesh's contact book. Every surface that holds the namespace key can read and write it.

**Claim token** — A one-time, time-limited token that authorizes a new surface to join a namespace. Generated by an existing surface. Expires. Consumed on first use.

**Stealth root** — A secret scope root that returns `undefined` on resolution. This is an honest absence, not an error. The NRP must preserve this distinction at the network level.

**Semantic island** — A self-contained `.me` kernel instance holding a fragment of a namespace. Islands do not need to be constantly connected. They interact by exchanging mathematical hashes, not cleartext data.

---

## 2. The Two-Layer Model

Resolution of a `me://` URI proceeds in two phases, always in this order.

### Phase 1 — Topological resolution

**Input:** `namespace` + `selector`
**Output:** a reachable surface endpoint

The requesting surface must find the surface that can serve the requested path. This involves:

1. Deriving the target `surface_id` from the local namespace key and the selector's surface name.

2. Looking up the endpoint descriptor for that `surface_id` in the local surface index.

3. Establishing a connection to that endpoint.

   If the surface index does not contain the target `surface_id`, or if the target surface is unreachable, topological resolution fails. The request does not proceed to Phase 2.

### Phase 2 — Semantic resolution

**Input:** `path` + key material (if the path is within a secret scope)
**Output:** the resolved value, or `undefined`, or a closed failure

Once the requesting surface has a connection to the target surface, it sends a read request for the path. The target surface resolves the path locally using its `.me` kernel, and returns a **disclosure envelope** (see Section 6).

Semantic resolution is entirely local to the target surface. The requesting surface never sees the target's kernel state directly — only the disclosure envelope for the specific path requested.

---

## 3. Surface Identity and the Surface Index

### 3.1 Surface identity derivation

A surface's identity within a namespace is:

```
surface_id = HMAC-SHA256(namespace_key, "surface:" + surface_name)
```

This produces a 32-byte opaque identifier. It is the surface's public identity on the mesh. Parties without the `namespace_key` cannot derive it, verify it, or enumerate surfaces in the namespace.

The `surface_name` is a human-readable label chosen by the surface operator (e.g., `"iphone"`, `"macbook"`, `"daemon-home"`). It is meaningful only to namespace holders.

### 3.2 Surface index structure

The surface index is a `.me` secret space:

```ts
me.surfaces["_"]("namespace_key");

// For each known surface:
me.surfaces[surface_id].name("iphone");
me.surfaces[surface_id].endpoint("encrypted_endpoint_descriptor");
me.surfaces[surface_id].last_seen(timestamp);
me.surfaces[surface_id].public_key("surface_ephemeral_pubkey");
```

The index is stored locally on every surface that holds the namespace key. There is no canonical remote copy. Surfaces sync the index through the mesh on reconnection (see Section 7).

The `endpoint_descriptor` field is doubly encrypted: first under the namespace key (so only namespace members can read it), and second it may use an ephemeral surface key for transport security. The endpoint is volatile and may change. The `surface_id` is stable.

### 3.3 Reading from the surface index

A surface resolves `me://[surface:iphone]/some.path` as follows:

```
1. Compute: target_id = HMAC-SHA256(namespace_key, "surface:iphone")
2. Read: endpoint = me("surfaces." + target_id + ".endpoint")
3. If endpoint is undefined → surface not found → fail with NRP_ERROR_SURFACE_NOT_FOUND
4. Decrypt endpoint descriptor → get transport address
5. Proceed to Phase 2 (semantic resolution)
```

---

## 4. The Claim Ceremony

The claim ceremony is how a new surface joins a namespace. It replaces the need for a central authority to "add" a surface.

The current implementation has a claim token as a temporary in-memory value. This section formalizes and hardens it.

### 4.1 Token generation

An existing surface in the namespace (the **inviting surface**) generates a claim token:

```
nonce         = random_bytes(16)
expiry        = now() + TTL            // recommended TTL: 300 seconds
claim_token   = HMAC-SHA256(namespace_key, nonce + expiry)
claim_payload = base64url(nonce + expiry + claim_token)
```

The claim payload is encoded into the URI:

```
me://jabellae.cleaker.me[claim:CLAIM_PAYLOAD]/new-surface
```

And optionally rendered as a QR code for physical proximity pairing (already implemented in Cleaker).

### 4.2 Token verification

The **new surface** presents the claim payload. The inviting surface (or any namespace surface that receives the pairing request) verifies:

```
1. Decode claim_payload → extract nonce, expiry, presented_token
2. Check: now() < expiry → if expired, reject with NRP_ERROR_CLAIM_EXPIRED
3. Recompute: expected_token = HMAC-SHA256(namespace_key, nonce + expiry)
4. Check: presented_token == expected_token → if not, reject with NRP_ERROR_CLAIM_INVALID
5. Check: token has not been used before (nonce registry, local) → if used, reject with NRP_ERROR_CLAIM_CONSUMED
```

### 4.3 Key handshake

After verification, the inviting surface and new surface perform a key handshake:

```
1. New surface generates an ephemeral keypair: (eph_pub, eph_priv)
2. New surface sends eph_pub to inviting surface
3. Inviting surface encrypts namespace_key with eph_pub:
     encrypted_namespace_key = ECIES(eph_pub, namespace_key)
4. Inviting surface sends encrypted_namespace_key + its own surface_id + current surface index snapshot
5. New surface decrypts with eph_priv → receives namespace_key and surface index
6. New surface registers itself in the surface index:
     surface_id_new = HMAC-SHA256(namespace_key, "surface:" + new_surface_name)
     me.surfaces[surface_id_new].endpoint(...)
     me.surfaces[surface_id_new].public_key(eph_pub)
7. New surface broadcasts its registration to all online surfaces (see Section 5.3)
```

### 4.4 Token consumption

The nonce is added to a local consumed-nonce registry after a successful claim. The registry is pruned of entries older than the maximum TTL. This prevents replay attacks.

```ts
me.system.consumed_nonces[nonce].at(timestamp);
```

---

## 5. Selector Resolution Rules

The `me://` URI selector determines how topological resolution proceeds.

### 5.1 `[current]` — current surface

```
me://jabellae.cleaker.me[current]/profile.name
// or equivalently:
me://profile.name
```

Resolves entirely locally on the surface receiving the request. No topological resolution needed. Phase 1 is a no-op.

### 5.2 `[surface:name]` — specific surface

```
me://jabellae.cleaker.me[surface:iphone]/runtime.battery
```

1. Derive `target_id = HMAC-SHA256(namespace_key, "surface:iphone")`
2. Look up endpoint in surface index
3. If not found: `NRP_ERROR_SURFACE_NOT_FOUND`
4. If found but unreachable: `NRP_ERROR_SURFACE_UNREACHABLE`
5. If found and reachable: proceed to semantic resolution

### 5.3 `[]` — broadcast to all surfaces

```
me://jabellae.cleaker.me[]/chat
```

1. Read the full surface index

2. Iterate all known `surface_id` entries

3. For each entry, attempt to reach the endpoint

4. Send the request to all reachable surfaces

5. Collect responses (or timeout)

6. Offline surfaces are skipped — broadcast is best-effort

7. The requesting surface may optionally queue undelivered messages for retry (implementation-defined)

   Broadcast does **not** wait for all surfaces to respond. It fires and collects what it can within a configurable timeout window.

### 5.4 `[claim:token]` — pairing handshake

```
me://jabellae.cleaker.me[claim:CLAIM_PAYLOAD]/new-surface
```

Triggers the claim ceremony (Section 4). Does not proceed to semantic resolution — the claim selector is a control-plane operation, not a data-plane operation.

---

## 6. The Disclosure Model

This is what a target surface returns for each category of path request. This model must be implemented consistently across all surfaces. A surface that leaks structural information in error responses breaks the security model.

### 6.1 Public path

The path exists and is not within any secret scope.

**Returns:** the resolved value.

```json
{
  "status": "ok",
  "path": "profile.name",
  "value": "José Abella",
  "origin": "public"
}
```

### 6.2 Stealth root

The path points to the root of a secret scope (e.g., `wallet` when `wallet` is declared with `["_"]`).

**Returns:** `undefined`. Explicitly. Not a 404, not an error, not a "path not found." The absence is honest and intentional.

```json
{
  "status": "ok",
  "path": "wallet",
  "value": null,
  "origin": "stealth"
}
```

The distinction between `null` (stealth root) and `NRP_ERROR_PATH_NOT_FOUND` (path does not exist at all) is architectural. Callers must not be able to distinguish "this path is secret" from "this path does not exist" — both return a form of `undefined`. The implementation choice of `null` vs. omitting the field is left to the transport binding, but the semantics must be indistinguishable to an observer without the secret key.

### 6.3 Secret leaf — correct key

The path is within a secret scope, and the requesting surface presents the correct key (via the `secret:key@` prefix in the URI, or through a pre-established shared secret).

**Returns:** the resolved value.

```json
{
  "status": "ok",
  "path": "wallet.balance",
  "value": 12480,
  "origin": "stealth"
}
```

### 6.4 Secret leaf — wrong or absent key

The path is within a secret scope, and the requesting surface does not present the correct key, or presents no key.

**Returns:** same envelope as stealth root. The response must be indistinguishable from case 6.2. A wrong key must not produce a different error than no key.

```json
{
  "status": "ok",
  "path": "wallet.balance",
  "value": null,
  "origin": "stealth"
}
```

This is the "fail closed, leak nothing" invariant. It directly mirrors the `["_"]` axiom in the `.me` kernel (A0 + A2).

### 6.5 Path does not exist

The path is not declared in the kernel and is not within any secret scope.

**Returns:**

```json
{
  "status": "not_found",
  "path": "does.not.exist"
}
```

This is the only case where a `not_found` status is returned. It must only be returned for genuinely absent paths that are not near any secret scope. If there is any ambiguity about whether a path might be secret, return the stealth envelope (6.2) instead.

---

## 7. Surface Index Synchronization

The surface index is local on each surface. When surfaces reconnect after being offline, they may have divergent views of the index. The protocol uses a simple Last-Write-Wins (LWW) strategy, consistent with the `.me` kernel's A9 axiom (deterministic conflict resolution).

### 7.1 Sync on reconnect

When surface A reconnects to surface B:

1. A sends its surface index version vector (a map of `surface_id → last_seen_timestamp`)
2. B compares against its own version vector
3. Each sends the other the entries that are newer on its side
4. Both apply the updates using LWW on `last_seen` timestamp

### 7.2 Surface expiry

A surface entry that has not updated its `last_seen` timestamp within a configurable window (e.g., 30 days) may be marked stale. Stale surfaces are kept in the index but deprioritized in routing. They are not deleted automatically — deletion requires an explicit `["-"]` operation by a namespace holder.

### 7.3 Endpoint volatility

Endpoint descriptors are volatile. A surface's IP address or relay address may change frequently. Each surface is responsible for updating its own endpoint descriptor in the index whenever its transport address changes, and broadcasting the update to all online surfaces.

---

## 8. Error Reference

| Code                            | Meaning                                                   |
| ------------------------------- | --------------------------------------------------------- |
| `NRP_ERROR_SURFACE_NOT_FOUND`   | `surface_id` not in local index                           |
| `NRP_ERROR_SURFACE_UNREACHABLE` | surface_id found but endpoint not reachable               |
| `NRP_ERROR_CLAIM_EXPIRED`       | claim token TTL exceeded                                  |
| `NRP_ERROR_CLAIM_INVALID`       | HMAC verification failed                                  |
| `NRP_ERROR_CLAIM_CONSUMED`      | nonce already used                                        |
| `NRP_ERROR_NAMESPACE_UNKNOWN`   | no namespace key available for this namespace             |
| `NRP_ERROR_PATH_NOT_FOUND`      | path does not exist and is not near any secret scope      |
| `NRP_ERROR_TRANSPORT`           | network-level failure (connection refused, timeout, etc.) |

---

## 9. What Is Not Specified Here (v0.1 scope)

The following are intentionally deferred to later versions:

**Transport binding** — This document specifies the protocol semantics, not the wire format. A v0.2 transport binding document will specify the exact message encoding (JSON-over-WebSocket, protobuf, etc.) and the TLS/noise handshake for the surface-to-surface connection.

**Relay infrastructure** — When two surfaces cannot reach each other directly (NAT, firewall, different networks), a relay is needed. The relay protocol is not specified here. The relay must not be able to read message content — it is a blind forwarder. Relay discovery and selection are deferred.

**Namespace key distribution across surfaces** — This document assumes the namespace key is already present on the requesting surface. The initial key bootstrap (how the first surface gets the namespace key from the derivation seed) is specified by the `.me` kernel, not the NRP. Subsequent key sharing is handled by the claim ceremony (Section 4).

**Multi-namespace resolution** — A surface may hold keys for multiple namespaces. How a surface selects the correct namespace key when a URI omits the namespace qualifier is implementation-defined in v0.1.

**Revocation** — How to revoke a surface from a namespace (e.g., a lost device) without a central authority is an open problem. A candidate mechanism is a signed revocation entry in the surface index, broadcast to all surfaces. Deferred to v0.2.

---

## 10. Design Principles

These are the invariants that any implementation must preserve. They are not implementation details — they are the protocol's soul.

**1. No central registry.** The surface index is local to each namespace holder. Discovery requires holding the namespace key. There is nothing to hack that reveals a complete list of surfaces or identities.

**2. Identity is computation, not storage.** A surface's identity is derived from a key and a name. It is not assigned by an authority and not stored in a global directory.

**3. Honest absence.** A stealth root returns `undefined`, not an error. The protocol does not reveal the existence of secret scopes to parties without the key. Absence and secrecy are indistinguishable from the outside.

**4. Fail closed.** Wrong keys produce the same response as absent keys. The protocol leaks no information about why a resolution returned `undefined`.

**5. Minimum surface area.** Surfaces exchange only what is necessary. A broadcast sends a path read request — not the full kernel state, not the surface index, not any metadata beyond what the request requires.

**6. Mathematical fragmentation.** No single surface holds a complete picture of any namespace. The identity is distributed across surfaces by design. Stealing one surface does not compromise the namespace.

**7. Offline-capable.** Local resolution (`[current]` or no selector) works with no network access. The protocol degrades gracefully: offline surfaces are skipped in broadcast, missing surfaces return `NRP_ERROR_SURFACE_UNREACHABLE`. The local kernel is never blocked by network state.

---

## Appendix A — Formal Grammar (ABNF, from URI scheme v1)

```txt
me-uri       = "me://" [ namespace ] [ selector ] [ "/" path ]

namespace    = 1*( ALPHA / DIGIT / "." / "_" / "-" )
selector     = "[" ( "current" / "" / "surface:" surface-name / "claim:" token ) "]"
surface-name = 1*( ALPHA / DIGIT / "-" / "_" )
token        = 1*( ALPHA / DIGIT / "-" / "_" )
path         = *( VCHAR / "/" )
```

The `secret:key@namespace` prefix for authenticated access is parsed as:

```txt
me-uri-auth  = "me://" "secret:" secret-key "@" namespace [ selector ] [ "/" path ]
secret-key   = 1*( ALPHA / DIGIT / "-" / "_" )
```

---

## Appendix B — Open Questions for v0.2

These are the questions this document intentionally leaves open, in priority order:

1. **Relay protocol** — How do two surfaces on different networks find a common relay, and how does the relay stay blind?

2. **Surface revocation** — How does a namespace holder revoke a lost or compromised surface without a central authority?

3. **Namespace discovery** — Can a surface discover other namespaces it does not already hold keys for? (Current answer: no. Is this the right answer forever?)

4. **Index consistency under partition** — If the mesh is partitioned for a long time and surfaces update their own entries, what is the merge strategy beyond LWW?

5. **Derivation-based namespace bootstrap** — Should the namespace key be derivable from a BIP-39 mnemonic or similar standard seed phrase, so it can be reconstructed without any network access?

6. **Cross-namespace pointers** — The `["->"]` operator in `.me` can create semantic links between namespaces. How does the NRP resolve a path that crosses namespace boundaries?

---

**∴ Witness our seal**
**suiGn / neurons.me**
**v0.1 — Draft**