Tags: browser, urc, dx, interface
Applications need one stable lace: address syntax that
does not make an HTTP host part of a document’s identity. This
specification defines canonical Lace browser addresses, relative
resolution, reserved address attributes, and the JavaScript
address-class behavior used by address consumers and HTTP-compatible
hosts.
This is an address profile over the coordinates defined by 010. It
does not select a stored record, assign browser authority, or change the
meaning of a bare coordinate in Interlang or Lace porcelain. A future
native browser resolution design is preserved separately under
docs/experimental/browser/.
The absolute address form is:
lace://<group>//<app>//<name>[<jsonqa>]
Examples:
lace://u//jukebox//index.html
lace://u//jukebox//join.html{jukebox:abc,via:"wss:waypoint.example/interlace"}
lace://u//whatsup//index.html{community:c-123,room:general,#:thread}
After decoding, <group>, <app>,
and <name> are exactly 010 Group,
App, and Name values. JSONqa is defined by
310. It is address state and is not part of the coordinate or record
identity.
The profile does not accept:
lace:////<record-hash>;{*}, {_}, prefixes, or
other patterns;An application may put an exact application-record hash in app-defined JSONqa. The address still names the interface coordinate that interprets that state:
lace://u//whatsup//index.html{message:S.EXAMPLE_MESSAGE.H3}
A frontend bundle is an executable interface resource tree with a designated entry document. It is distinct from the application records and address state that the loaded code reads or writes.
A frontend bundle identified by <app-name> MUST
publish its base entry document at:
lace://u//<app-name>//index.html
If it has an HTTP-browser-compatibility variant, that variant MUST publish its entry document at:
lace://u//<app-name>/http//index.html
u is the exact Group. <app-name> is
an application-chosen valid 010 App value; the compatibility variant
appends the http App segment. Supporting resources for each
variant MUST use that variant’s Group and App and ordinary Name paths
relative to index.html. Hosts still resolve exact Names and
MUST NOT infer index.html from an incomplete
coordinate.
The base and HTTP-compatible variants are distinct App scopes.
Address parsing, HTTP projection, and hosts MUST NOT erase
/http, translate between the scopes, or treat one entry as
an alias for the other.
These are standard bundle publication and bootstrap coordinates, not
a restriction on application records or links interpreted by the loaded
code. A frontend MAY additionally define an application-specific
interface under a different Group or App, but that does not change its
well-known publication coordinates. The convention does not grant
authority, select records, or make u special for
non-frontend records.
lace: is not parsed as an HTTP-style authority URL. In
lace://u//jukebox//index.html, u is the Group;
it is not a DNS host.
The lexical form is:
browser-address = "lace:" encoded-coordinate [jsonqa]
encoded-coordinate = "//" encoded-group "//" encoded-app "//" encoded-name
The parser MUST isolate a terminal JSONqa object before applying
generic URL query or fragment processing. Raw ? and
# have no query or fragment meaning in a Lace browser
address. The # fragment attribute lives inside JSONqa. A
canonical address uses the canonical 310 serialization of its
JSONqa.
The two // field separators are found before
percent-decoding. Valid 010 path values contain no empty segment, so raw
// cannot occur inside Group, App, or Name.
Each decoded field is first validated under 010 and encoded as NFC UTF-8. The canonical browser spelling leaves these ASCII bytes unescaped:
A-Z a-z 0-9 - . _ ~ /
Every other UTF-8 byte is written as %HH with uppercase
hexadecimal digits. In particular, %, ?,
#, quotes, spaces, and non-ASCII bytes are percent-encoded
when they are coordinate field data.
A parser MUST reject:
A percent-encoded / is non-canonical and invalid. A
backslash is never normalized to /. Coordinate equality
compares decoded 010 values, not percent-encoding spelling.
This profile reserves these top-level 310 attributes:
| Attribute | Required value | Address meaning |
|---|---|---|
# |
string | application fragment or view target |
via |
string | syntactically valid 060 ILTP endpoint hint |
by |
canonical 009 verification-key text | interface by constraint |
Other attributes are app-defined. Reserved attributes remain visible as address state but do not become record fields, record identity, browser authority, peer identity, exposure, or permission. Duplicate attributes first undergo 310’s last-wins reduction and are then validated.
Reusable private capabilities and By-secret values MUST NOT appear in a browser address.
via tells a consuming application or browser where it
may try an acquisition. It does not establish trust in that endpoint or
grant transport permission. A canonical wss: value lets a
connected runtime select the default confidential peer-proof mode, but
only a successful live proof derives PeerConfidential;
parsing the address derives no authority. by constrains a
consumer that already has an interface key configuration. It does not
create or replace that configuration. A Mark is record-version-specific
and is not a valid by value. The V prefix in a
by value is 009’s verification-key type tag.
The address parser validates only the value shape and retains the attributes. A consuming profile owns their operational behavior.
Given:
lace://u//jukebox//pages/join.html{room:abc}
relative resolution is:
style.css -> lace://u//jukebox//pages/style.css
./style.css -> lace://u//jukebox//pages/style.css
../main.mjs -> lace://u//jukebox//main.mjs
/admin.html -> lace://u//jukebox//admin.html
//u//other//index.html -> lace://u//other//index.html
lace://u//other//index.html -> lace://u//other//index.html
The resolver first isolates a terminal JSONqa object, then interprets the raw path relative to Name. Rules:
./ path replaces the final Name segment
relative to its parent;../ removes one Name segment and MUST fail rather than
ascend above the Name root;/ starts at the current Group/App Name
root;// is a complete encoded Lace
coordinate;lace: address replaces the whole
address;Literal . and .. are navigation syntax only
and never become stored Name segments. Generic WHATWG authority/path
normalization is not authoritative for these rules.
The JavaScript surface uses classes rather than plain object snapshots:
new URC("//g//a//name{...}") creates a detached parsed
coordinate value. It exposes canonical href, Group, App,
Name, JSONqa, fragment, and relative resolution.new Address("lace://g//a//name{...}") creates a
detached absolute address. Changing its href reparses the
value but does not itself navigate a window. Its urc
property is a stable URC object.WindowAddress is the host-owned live-address base
class.LaceWindowAddress is its Lace subtype.A host profile may install one stable LaceWindowAddress
as window.address. Assigning window.address
forwards to its href. Host-driven updates mutate the live
object and its stable urc object rather than replacing
either one. Lace-320 defines this behavior for HTTP compatibility
mode.
qa exposes strings, arrays, and null-prototype objects
while retaining 310 object order for canonical serialization.
Two browser addresses are semantically equal when their decoded Group, App, and Name values and reduced ordered JSONqa values are equal. Canonical serialization is the stable byte key for history and address storage.
Malformed coordinates, invalid percent encoding, invalid JSONqa, malformed reserved attributes, and relative references that escape the Name root are errors. Parsing an address has no record-loading, network, trust, or navigation side effect.