Narrow host edge
The runtime reaches the operating system through a small host table.
- Trident app no OS calls
- Runtime request typed host verb
- Host table approved mechanism
- OS resource file • socket • process
2027 · MerTek technology
Core system / System overview
The host boundary, from crew laptop to fleet
Fathom is the host side of MTK: the tri process that runs Trident runtimes and joins them into one deployment. The host opens files, starts programs and talks to network peers; a Trident program only names what it was lent. Network input is checked for size, sender and shape before any handler sees it.
Worked example
Crew 14 at a water utility inspects about 600 meters a shift. All day, their truck laptop reads meter photos from one folder and runs a vendor converter on each, with no network. At 4 p.m. the truck returns to the yard and the laptop syncs with the regional office server. The utility's security lead wants a written list of everything this application can touch.
The operator lends one file anchor. An anchor is a named directory the host opens and pins before the program starts. The program says photos; the lend's io binding decides that photos is a read-only folder under the application's own data root.
chest io = {
u16 schemaVersion = 1
chest[] anchors = [{
u16 schemaVersion = 1
text name = "photos"
text? leaf = null
text access = "read"
text root = "data"
text directory = "photos"
}]
}The operator admits one program with one argument prefix. meterconv --to png may run; any other argument list or any other binary is refused before the filesystem is touched. The converter comes from a pinned tools directory that no writable anchor reaches, so the application cannot replace the binary it runs.
chest proc = {
u16 schemaVersion = 2
text? directory = "tools"
text root = "cwd"
u32 maxChildren = 2
chest[] allowedPrograms = [
{ u16 schemaVersion = 1, text name = "meterconv",
chest[] arguments = [ { text[] prefix = ["--to", "png"] } ] }
]
}The application calls those services by name. t.io.list reads the anchor and t.proc.spawn starts the converter. The child comes back as an opaque handle, never a process id. The program can only poll, read or stop a child it started.
text main(text[] argv) {
text[] photos = t.io.list("photos", "route-14")
resource<t.proc.child> child = t.proc.spawn(["meterconv", "--to", "png", photos[0]],
{ text stdout = "capture", text stderr = "inherit" })
chest status = t.proc.poll(child, 5000000000)
return t.proc.stdout.readText(child, 4096)
}At the yard the laptop connects to the regional server. The host does the network work: framing, size limits, a signed handshake against the server's pinned key, and decoding. Only then does on message run, with the host's facts in context and the server's document in payload.
chest main() {
chest target = { ip address = 10.40.2.7, u16 port = 9443 }
chest options = {}
chest answered = t.net.peer.connect("regional", target, options)
chest state = {}
return state
}
on message("regional", "workOrder", const context, const payload) {
text meter = payload.meter
t.log.info("work order for meter " + meter)
}On the regional server, a connection offer reaches the program only after the handshake proved the truck's key. The endpoint admits unknown keys so new laptops can enroll. The program decides: it accepts a pinned truck and rejects anything else with a reason.
chest main() {
chest state = {}
return state
}
on event("peerOffered", const chest offer) {
guid connection = offer.connection
bool? pinned = offer.pinned
if (pinned != null && pinned) {
t.net.peer.accept(connection)
} else {
t.net.peer.reject(connection, "unknown truck")
}
}
on message("trucks", "inspection", const context, const payload) {
text meter = payload.meter
t.log.info("inspection received for meter " + meter)
}Crew 14 converted 612 photos with no network and synced 31 work orders in under a minute at the yard. A test laptop with an unknown key was offered, rejected, and never reached on message. A script edit that tried meterconv --delete was refused with denied at the spawn, before the converter or any photo was opened.
System diagram
Host adapters provide mechanisms. Trident configuration selects the approved transport and offline policy.
Inside the system
Follow the data, decisions, and access boundaries. Each diagram explains a concept used by applications.
The runtime reaches the operating system through a small host table.
Mechanism, tenant, and application scope form separate names.
Network input is not application data until every check passes.
The node map declares where an application may run.
Old and new fleets overlap, so the wire contract must hold.
Key parts
These are the main boundaries, inputs, outputs, and failure rules. The examples show a specific use of each part.
The runtime reaches the outside only through typed services the host lends at launch: t.io, t.proc and t.net.peer. Each executable compiles in its own closed set, with no plug-in registry to widen. A library the lend does not cover is absent, and the launch stops by name.
A program that calls t.net.peer.connect under a lend with no t.net.peer row stops at launch with notLent: t.net.peer.
Bytes from the network are not application data. The host checks framing and size, authenticates the sender against its pin table, and decodes the document before a handler runs. A send that breaks a limit answers tooLarge or backpressure at the sender instead of failing at the receiver.
A 3 MB photo sent as one message on a 1 MiB lane answers tooLarge on the laptop. The server's handler never sees a partial document.
Where runtimes run is a host fact: the placement map in the host folder names pools and counts, and no program reads it. During a rollout, old and new runtimes share one wire. The handshake compares protocol identity, and each side advertises its receive limits, so two versions talk at the smaller ceiling.
The regional office grows its sync service from two machines to four by editing _host/fleet.draft and raising its generation. The program's digest does not change.
Code
Each example is short and complete enough to read on its own. Hover a dotted word for its definition.
The program sees only the name photos, and these figures bound every read, listing and tree walk under it. A name with no anchor row reaches no path at all.
{
u16 schemaVersion = 1
text id = "t.io"
chest? config = {
u16 schemaVersion = 1
chest[] anchors = [{
u16 schemaVersion = 1
text name = "photos"
text? leaf = null
text access = "read"
}]
u64 maxReadBytes = 8388608
u64 maxRangeSessionBytes = 67108864
u64 maxWriteBytes = 4194304
u64 maxListEntries = 4096
u64 maxListBytes = 4194304
u32 maxTreeDepth = 64
}
chest[] storeSlots = []
}
.. is not a legal path component, so ../payroll/rates.csv is not a path at all. No spelling reaches a file outside the folder the operator lent.
text main(text[] argv) {
bool inside = t.io.path.isValid("route-14/M-88213.jpg")
bool escape = t.io.path.isValid("../payroll/rates.csv")
if (inside && !escape) {
text[] photos = t.io.list("photos", "route-14")
return text(photos.count()) + " photos on route 14"
}
return "refused"
}
A program row names the binary, the argument prefixes it admits, and the child's whole environment. The child receives exactly these rows; the application cannot add PATH or anything else.
chest? config = {
u16 schemaVersion = 2
chest[] allowedPrograms = [
{ u16 schemaVersion = 1, text name = "meterconv",
chest[] arguments = [ { text[] prefix = ["--to", "png"] } ],
chest[] environment = [ { text key = "LANG", text value = "en_US.UTF-8" },
{ text key = "TMPDIR", text value = "/var/lib/meterinspect/tmp" } ] }
]
u32 maxChildren = 2
u32 maxArgs = 8
u32 maxArgBytes = 1024
}
The lend says which endpoints this program may name and in which role. Addresses, pinned keys and lane tables live in the host's plan, so an operator changes one without touching the other.
{
u16 schemaVersion = 1
text id = "t.net.peer"
chest? config = {
u16 schemaVersion = 1
chest[] endpoints = [{ text name = "regional", text role = "connector" }]
u32 maxLanes = 4
u64 maxMessageBytes = 1048576
u64 maxNameBytes = 64
u64 maxKeyBytes = 64
u32 maxInterestNames = 16
u32 maxPage = 32
}
chest[] storeSlots = []
}
--reach compiles the application and checks its lend without running it. The refusal names the library, the call that reached it, and the launch stage that stopped.
$ tricli --reach meter-sync
tricli: lend: notLent: t.net.peer
tricli: a/ reaches t.net.peer.connect, and this launch lends no t.net.peer
tricli: falseStart: grant
Uses
Review questions
Which directories, programs and peers each deployment should lend
Which device keys are pinned, and how a new device enrolls
How long two runtime versions must share the wire