URA is a clean-sheet addressing model with four strict separations:
- Addressing: where/what is addressed (
resource_uri). - Identity: who is invoking (
subject_id). - Tenant context: in which trust scope invocation is authorized (
tenant_id). - Runtime policy: what a verifier/runtime accepts or rejects.
resource_uri is no longer forced to carry all execution semantics.
resource_uri MUST be an absolute URI (RFC 3986).
Every conforming implementation MUST support:
httpshttpwsswseasynet
Implementations MAY support extra schemes by explicit runtime policy.
For http/https/ws/wss, parsing and serialization MUST use WHATWG URL algorithm outcomes as the primary source of truth for:
- Host parsing and normalization.
- Port handling.
- Path/query/fragment component split.
For network schemes, implementations MUST NOT substitute an RFC 3986-only parser as canonicalization authority.
For each runtime release, canonicalization behavior MUST bind to a fixed reference implementation/version (for example specific Node/Go/Rust/Java runtime versions) to avoid signing-byte drift from upstream parser changes.
- Verifier
MUSTcanonicalizeresource_uribefore signature verification. - Signed bytes
MUSTuse UTF-8 bytes of the canonical URI string. - Canonical re-serialization byte mismatch
MUSTfail closed asINVALID_RESOURCE_URI. - URI fragment (
#...)MUSTbe absent in signed invocation addresses. - URI userinfo (
user:pass@)MUSTbe rejected for network schemes. - Canonical URI string bytes
MUSTbe the only bytes used for routing, authorization, and policy lookup. - Runtime components
MUST NOTapply additional decode/normalize passes after canonicalization.
Invocation envelopes using URA v2 MUST carry an explicit uri_profile field:
- Allowed values:
web-safe-v2,easynet-strict-v2,easynet-v1-compat. uri_profileMUSTbe included in signature input.- Verifier
MUSTselect canonicalization behavior strictly from signeduri_profile. - Implicit profile inference is forbidden except explicitly configured migration mode.
- Runtime
MUSTenforce a per-endpoint allowed-profile whitelist before canonicalization. - Allowed-profile whitelist
MUSTcome from static runtime configuration andMUST NOTbe derived from request content.
Verifier order for URI handling is:
- Parse envelope structure and read unsigned field shapes, including
uri_profile. - Validate
uri_profileagainst runtime allowed-profile whitelist; on mismatch, reject immediately before any URI parsing/canonicalization. - Canonicalize
resource_uriusing the extracteduri_profile. - Verify signature over signed fields, including
uri_profile, and require signedresource_uribytes to equal canonical URI bytes. - Reject request if any canonicalization or byte-equality check fails.
Reading uri_profile before signature verification is an intentional bootstrap dependency. Trust is established only after signature verification succeeds.
Before signature verification completes, uri_profile is untrusted selector input and MUST be used only for parser/canonicalization path selection, not for authorization or policy grants.
Tenant authorization semantics are outside URI canonicalization and are defined in section 7.
Given (raw_resource_uri, uri_profile):
- Precondition:
uri_profilewhitelist validation from section 3.2 has already succeeded. - Parse as absolute URI.
- Require signed
uri_profile(section 3.1). - Branch by scheme class and profile:
- Network schemes (
http/https/ws/wss):- Canonicalization
MUSTuse WHATWG URL parser + serializer output. - Host normalization follows WHATWG + UTS 46 processing.
- Default ports are removed by canonical serializer behavior.
- Empty path canonicalizes to
/. - Fragment presence is a hard reject.
- Userinfo presence is a hard reject.
- No extra RFC 3986 post-processing pass is allowed.
- Canonicalization
easynetscheme:- Parse and validate using section 6 grammar.
easynet-strict-v2andweb-safe-v2canonical outputMUSTuse empty authority form (easynet:///...).easynet-v1-compatcanonical outputMUSTuse legacy authority form from Core v1 (easynet://r/...).- Lowercase structural tokens (
namespace,scope,subject-type,resource-kind). - Normalize Unicode text components required by section 6.8 to NFC.
- Validate percent triplets; invalid triplets are rejected.
- Percent triplet hex digits canonicalize to uppercase.
- Percent triplets for unreserved chars (
A-Z a-z 0-9 - . _ ~) decode exactly once. - Reserved-character triplets are preserved encoded.
- Network schemes (
- Apply query policy from signed
uri_profile:web-safe-v2: preserve pair order and duplicates.easynet-strict-v2:tenant_idfirst when present, then stable-sort remaining pairs by(key_bytes, value_bytes).easynet-v1-compat: apply Core v1 query rules (tenant_idfirst, ext keys ascending, duplicate keys invalid).
- Serialize canonical URI string.
Implementations MUST expose canonicalization as a pure function.
URA v2 defines three canonical profiles:
Purpose: maximum interoperability with internet URL behavior.
- Query order preserved.
- Duplicate query keys preserved.
- Tenant is carried outside URI by default.
- For
easynetscheme, canonical authority/path shape matcheseasynet-strict-v2(easynet:///...); difference is query handling policy. - Producer is responsible for deterministic query construction when signature stability is required; verifier does not reorder query pairs for this profile.
Purpose: deterministic internal protocol addresses with stronger normalization.
tenant_idis first when present; remaining pairs are stable-sorted by(key_bytes, value_bytes).- Profile-specific URI constraints may require presence/absence of specific query keys.
- Suitable for protocol-native resource identifiers and conformance suites.
Profile selection is explicit and signed (section 3.1).
Purpose: deterministic bridge profile for existing Core v1 signed traffic.
- Only valid for scheme
easynet. - Canonicalization behavior follows Core v1 rules, including authority-host form and query constraints.
- Intended for migration windows, not new protocol-native authoring.
- Runtime policy
SHOULDdisable this profile by default and enable it only for explicitly migrated endpoints.
Cross-profile signature rule:
- Different
uri_profilevalues can produce different canonical URI bytes for the same logical target. - Signatures are intentionally non-interoperable across profiles.
easynet scheme canonicalization uses URA grammar and rules in this section, not WHATWG URL network-scheme parsing.
Implementations MUST NOT use WHATWG URL parser for easynet URIs at any stage, including pre-validation parsing.
easynet:///{namespace}/{scope}/{subject-type}/{subject-value}/{resource-kind}/{resource-path}[@version-ref][?query]
Canonical URA v2 native form uses empty authority (easynet:///), with namespace as path segment 1.
Canonical serializer MUST emit exactly easynet:/// prefix for URA v2 native easynet URIs and MUST NOT collapse to easynet:.
namespace defines addressing domain, not actor identity.
Core namespaces:
r(resource addressing)resolve(identity/key lookup endpoints)registry(catalog/index resources)invoke(invocation gateway resources)
Extension namespaces:
x.<namespace-token>wherenamespace-tokenmatches[A-Za-z][A-Za-z0-9-]{0,31}.
ridentifies protocol resource addresses (capabilities, invocation resources, manifests).resolveidentifies identity/key resolution endpoints and metadata resources.registryidentifies indexing/discovery resources.invokeidentifies invocation gateway/control-plane endpoints, not capability resource identities.- Capability resources that are executed by runtime policy
MUSTbe addressed underrunless an extension profile explicitly states otherwise. - In Core invocation envelopes,
resource_uriMUSTusernamespace;invokenamespace URIsMUST NOTbe used asresource_urivalues.
scope values:
puborgprv
Core subject types:
pkhregnode
Extension subject types:
x.<namespace>.<token>
Parser MUST accept valid extension forms.
Runtime MUST decide allow/deny via policy.
Core kinds:
abilitiesinvocationsmanifestspolicieskeys
Extension kinds:
x.<namespace>.<token>
Kind semantics are namespace-scoped: the same kind token can carry different domain meaning under different namespaces unless a profile explicitly states shared semantics.
subject-valueandresource-pathsegments are Unicode text.- Canonical form
MUSTserialize them using UTF-8 + percent-encoding normalization from section 4. - Raw
%that is not part of a valid percent triplet is invalid. - For URA v2 native
easynetprofiles (web-safe-v2,easynet-strict-v2), query keysMUSTmatch^[A-Za-z0-9._-]{1,64}$and are not Unicode-normalized.
Accepted forms:
<major>.<minor>.<patch><major>sha256:<64hex><semver>+sha256:<64hex><major>+sha256:<64hex>
Validation constraints:
<major>.<minor>form is invalid.- Numeric identifiers in semver fields
MUSTmatch0|[1-9][0-9]*(no leading zeros except literal0). - Invalid semver text is rejected; there is no pass-through mode for malformed version refs.
- URA version references are not semver ranges;
@1is a pinned shorthand, not1.x.x.
Canonicalization:
<major>-><major>.0.0- Digest hex -> lowercase
<semver>+sha256:<digest>applies semver validation plus digest lowercase normalization.- Signature domain uses expanded canonical bytes;
@1and@1.0.0intentionally collapse to the same canonical URI bytes.
- For
easynetscheme, canonicalizationMUSTnormalizesubject-value, eachresource-pathsegment, and query values to Unicode NFC before percent-encoding normalization. - Canonicalization
MUST NOTapply NFKC/NFKD compatibility folding. - Producers
SHOULDstill normalize at input boundary to reduce user-visible surprises before signing.
Tenant semantics are policy-layer constraints and MUST NOT be globally hardcoded into URI grammar.
Scope boundary:
- URA defines URI behavior only; invocation envelope schema is defined in
docs/00-foundation/core-spec-v1.mdsection8. - In Core envelope terms, tenant value is carried in
tenant_id; URA does not redefine envelope field naming. - Runtime tenant context binding interface is implementation-specific but enforcement outcomes are mandatory.
- URI does not need
tenant_id. - Tenant authorization is enforced via envelope and runtime context.
For ecosystems needing URI-level tenant binding:
org/prvURIsMUSTincludetenant_id.pubURIsMUST NOTincludetenant_id.- URI tenant and envelope tenant
MUSTmatch.
Bound mode is a profile choice, not a global protocol axiom.
Bound tenant profile identifier is easynet-bound-tenant-v2 (runtime policy profile; not a uri_profile value).
- Reject non-absolute URI.
- Reject URI with fragment.
- Reject URI with userinfo for network schemes.
- Reject invalid IDNA host normalization results.
- Reject invalid percent triplets.
- Reject invalid extension token grammar.
- Reject missing or unsigned
uri_profile. - Reject any execution path that performs post-canonicalization decode/normalize.
- Reject
uri_profile = easynet-v1-compatwhen scheme is noteasynet. - Reject
uri_profilevalues not allowed by endpoint/runtime policy whitelist. - For
easynetwithweb-safe-v2oreasynet-strict-v2, reject any non-empty authority component. - For
easynet-v1-compat, authorityMUSTbe exactlyr. - For URA v2 native
easynetprofiles, reject query keys not matching^[A-Za-z0-9._-]{1,64}$.
Existing v1 URIs like:
easynet://r/org/reg/agent.quote-bot/abilities/order.quote@1.0.0?tenant_id=acme
remain verifiable under easynet-v1-compat.
Strict v2 canonical form for equivalent addressing intent is:
easynet:///r/org/reg/agent.quote-bot/abilities/order.quote@1.0.0?tenant_id=acme
Migration to easynet-strict-v2 requires re-signing because canonical bytes can change.
- Canonical
easynetURI uses empty authority with namespace in path segment 1. - Subject/resource taxonomies are extensible by grammar and constrained by policy.
- Percent-encoding is normalized, not globally forbidden.
- Tenant-in-URI is profile-selectable.
- Query canonical bytes may differ from v1 outside
easynet-v1-compat. - Version shorthand (
@1) collapses into expanded canonical form (@1.0.0) for signatures. - For the same logical URI target, different signed
uri_profilevalues are intentionally signature-incompatible.
Each implementation MUST provide:
- At least 300 total canonicalization vectors across
http/https/ws/wss/easynet. - At least 40 network-scheme baseline vectors (
http/https/ws/wss) covering parse/serialize edge cases independent of IDN. - At least 60 IDN/host normalization vectors (including invalid IDNA cases).
- At least 50 percent-encoding and path normalization vectors, including at least 30 negative vectors.
- At least 50 query/profile vectors covering duplicate keys, ordering, and profile divergence behavior.
- At least 40
easynetgrammar/version/NFC vectors. - At least 30 migration vectors covering
easynet-v1-compatverification and strict-v2 re-signing. - Cross-runtime parity execution on Node/Go/Rust/Java proving identical canonical bytes for the full normative vector corpus.
Draft-phase delivery flexibility:
- During draft releases, provisional conformance
MAYbe declared with at least 60% of total vector targets implemented. - Provisional conformance still
MUSTinclude complete security-critical negatives: fragment rejection, userinfo rejection, invalid percent triplets, profile whitelist rejection, and signature/profile mismatch cases. - Final conformance requires 100% of category minimums above.
Normative vector registry location:
reports/ura-v2-conformance/
Ownership:
- Foundation protocol maintainers are responsible for accepting and versioning vector updates.
https://api.example.com/v1/tools/list?tag=alpha&tag=beta
https://xn--fsqu00a.xn--0zwm56d/path/%E6%B5%8B%E8%AF%95
wss://stream.example.com/events?cursor=42
easynet:///r/org/reg/agent.quote-bot/abilities/order.quote@1.0.0?tenant_id=acme
easynet:///registry/pub/reg/global.index/invocations/catalog@2
easynet:///x.lineage/prv/x.research.agent/lineage-root/x.lineage.snapshot/main@3+sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
URA v2 security review MUST include at least these attack classes:
- Signature confusion: attacker attempts to alter canonicalization path/profile without invalidating signature.
- Parser differential: different runtimes produce different canonical bytes from identical input.
- IDN spoofing: visually confusable hosts or invalid UTS 46 transitions.
- Query collision/reorder: duplicate keys or reordered pairs change semantic meaning.
- Normalization replay: equivalent-looking Unicode/percent forms are replayed to bypass policy.
- Downgrade to migration profile: endpoint inadvertently accepts
easynet-v1-compatoutside migration window.
Mitigation baseline:
- Signed
uri_profile. - Static profile whitelist.
- Fail-closed canonical byte equality checks.
- Cross-runtime vector parity gates.
URA-level failures map to deterministic error codes:
INVALID_RESOURCE_URI: parse/canonicalization failure or canonical-byte mismatch.URI_PROFILE_UNSUPPORTED: unknownuri_profilevalue.URI_PROFILE_NOT_ALLOWED: profile rejected by endpoint whitelist.URI_SCHEME_NOT_ALLOWED: scheme rejected by runtime policy.URI_AUTHORITY_NOT_ALLOWED: non-empty authority where forbidden by profile.URI_IDNA_INVALID: host normalization failure.URI_PERCENT_ENCODING_INVALID: invalid percent triplet or disallowed decode form.
If a runtime uses Core v1 error surfaces, implementations MAY map 2-7 to INVALID_RESOURCE_URI, but internal telemetry SHOULD retain precise sub-code.
Registry scope:
- Core namespaces (
r,resolve,registry,invoke) are reserved. - Extension namespaces use
x.<namespace-token>.
Conflict policy:
- Namespace allocation follows first-registered ownership in Foundation registry records.
- Ownership updates require signed proof from current owner key binding.
- Conflicting claims fail closed until governance review resolution.
Registration metadata minimum:
- Namespace token.
- Owner subject identifier.
- Contact/maintainer pointer.
- Semantics document URL/path.
- Security considerations section.