# URL Schema

## Purpose

This document defines the `rho://` URL scheme for identifying Rho objects and externally resolved resources.

The goal is to keep identifiers:

- short
- unambiguous
- URI-valid
- extensible across many object types and providers

## Core Shape

The recommended shape is:

```text
rho://<kind>/<provider>/<provider-specific-path...>
```

Where:

- `<kind>` identifies the class of object
- `<provider>` identifies how it should be resolved
- `<provider-specific-path...>` is the remaining provider-defined path

## Why `kind` Comes First

The first path segment should be the object kind, not the provider.

Good:

```text
rho://id/github/madhavajay
rho://repo/github/openmined/rho
```

Bad:

```text
rho://github/madhavajay
```

The second form is ambiguous because GitHub offers many object types:

- users
- orgs
- repos
- issues
- releases
- gists

By putting `kind` first, the URL remains easy to parse and easy to extend.

## Recommended V1 Kinds

- `id`
- `key`
- `repo`
- `tool`
- `message`
- `request`
- `approval`
- `run`
- `dataset`
- `artifact`
- `model`

These should be treated as the Rho-level namespace.

## Examples

### Identity

```text
rho://id/github/madhavajay
rho://id/email/madhava@openmined.org
```

### Key

```text
rho://key/github/madhavajay/ed25519-1
rho://key/email/madhava@openmined.org/rsa-1
```

### Repo

```text
rho://repo/github/openmined/rho
rho://repo/gitlab/example/project
```

### Model

```text
rho://model/huggingface/Qwen/Qwen3-Coder-480B-A35B-Instruct
rho://model/openai/gpt-5.4
```

### Dataset

```text
rho://dataset/huggingface/owner/name
rho://dataset/rho/prices-demo
```

### Rho-local objects

```text
rho://tool/rho/sum-prices
rho://message/rho/msg-001
rho://request/rho/req-001
rho://run/rho/run-001
```

## Identity And TOFU

The base identity URL should identify the actor, not a specific key.

Preferred:

```text
rho://id/github/madhavajay
```

Specific keys should be separate objects:

```text
rho://key/github/madhavajay/ed25519-1
```

This allows:

- short human-facing identifiers
- multiple keys per identity
- future key rollover
- local TOFU trust records that pin a concrete key fingerprint without changing the actor id

## Resolution Model

Resolution should happen in layers:

1. Parse the `rho://` URL.
2. Dispatch by `kind`.
3. Dispatch by `provider`.
4. Resolve the provider-specific path.
5. Return a typed object or manifest.

Example:

```text
rho://id/github/madhavajay
```

may resolve to:

- a public identity bundle
- one or more public keys
- proofs linking the identity to GitHub

while:

```text
rho://repo/github/openmined/rho
```

may resolve to:

- a Git repository URL
- a repo manifest
- repo metadata needed by `rho repo`

## Extensibility Rules

To keep the namespace coherent:

### Rule 1: Add new providers without changing kinds

Examples:

- `rho://id/github/...`
- `rho://id/email/...`
- `rho://id/nostr/...`

### Rule 2: Add new kinds without changing provider syntax

Examples:

- `rho://model/huggingface/...`
- `rho://dataset/huggingface/...`

### Rule 3: Keep provider-specific path semantics inside the provider

Rho should not force every provider into identical path depth.

These are both acceptable:

```text
rho://repo/github/openmined/rho
rho://model/openai/gpt-5.4
```

### Rule 4: Do not overload one URL to mean multiple object classes

Avoid:

```text
rho://github/madhavajay
```

because it leaves object type implicit.

### Rule 5: Keep fragments and queries optional and secondary

The core object identity should live in the authority plus path shape above.

If fragments or queries are used later, they should refer to:

- subresources
- versions
- views

not the primary object type.

## Suggested Grammar

Conceptually:

```text
rho://<kind>/<provider>/<path...>
```

More explicitly:

```text
scheme     = "rho"
kind       = 1*(ALPHA / DIGIT / "-" )
provider   = 1*(ALPHA / DIGIT / "-" )
path-part  = 1*( unreserved / pct-encoded / "@" / "." / ":" )
rho-url    = "rho://" kind "/" provider *( "/" path-part )
```

Exact parsing rules can be tightened in implementation.

## Open Questions

- Should `kind` be a fixed enum in v1 or partly extensible through plugins?
- Should local repo objects always use provider `rho`, or should there be repo-scoped providers later?
- How should versioned subresources be represented: path segment, query, or manifest field only?

## Recommended V1 Stance

- Keep `kind` as a fixed enum in v1.
- Allow providers to vary by kind.
- Use `rho` as the provider for Rho-native local objects.
- Keep trust pinned to concrete keys in manifests, not embedded into the base identity URL.
