The Namespace Network
Your namespace has its own network. Not a filtered view of ours — its own loopback, its own address range, and its own name resolution. You give things names, and inside your namespace those names work like any other host on any other network.
Why this exists
Sandboxed code needs to reach things. A WebAssembly block wants to query your database; a script wants to fetch from your own site; a program you did not write expects to open a socket to localhost. Handing that code the real network would be the end of every guarantee this platform makes.
So it does not get the real network. It gets a network — a complete, ordinary one, that happens to contain only your things.
127.0.0.1 inside your namespace is your own loopback, and nothing of Ocalt’s is listening on it.What you get
| Address | What it is |
|---|---|
127.0.0.1 | Your loopback. Yours alone — a server you start inside the sandbox binds here and only you can reach it |
10.0.0.1 | Your gateway. The route to the public internet |
10.0.0.2 – 10.0.0.254 | Yours to assign. Every name you map gets one |
| anything else | Nowhere. There is no route, so there is nothing to refuse |
10.0.0.2 is not a collision, the same way two houses both having a room 1 is not a collision — they are different houses. This is why you never have to coordinate addresses with anyone, and why the address never contains your account id.NETWORK MAP — Giving Something a Name
A name and a target. The address is allocated for you unless you ask for a particular one.
NETWORK MAP "shop.internal" TO SITE "myshop" SET ?r
AFTER EMIT ?r("address")
(* 10.0.0.2 *)
AFTER NETWORK MAP "db.internal" TO DATABASE "shopdb" SET ?r2
AFTER EMIT ?r2("address")
(* 10.0.0.3 *)
AFTER NETWORK MAP "pi.internal" TO MACHINE "workshop-pi" SET ?r3
Pinning an address
Some software wants a fixed address — a config file that cannot take a hostname, a device that was set up years ago. AT pins one, the way a static lease does on any other network.
NETWORK MAP "pi.internal" TO MACHINE "workshop-pi" AT "10.0.0.50" SET ?r
AFTER EMIT ?r("address")
(* 10.0.0.50 *)
10.0.0.0/24 is refused — not because it is on a list, but because your network does not extend there. 10.0.0.1 is refused too: that is your gateway, and taking it would cut off your own route out.A name maps to one thing
Mapping a name that already exists replaces it. There is no such thing as two mappings competing for one name, and you never have to remove the old one first.
NETWORK MAP "db.internal" TO DATABASE "shopdb"
AFTER NETWORK MAP "db.internal" TO DATABASE "shopdb_v2"
(* db.internal now reaches shopdb_v2. There is one mapping, not two. *)
What You Can Map
| Target | Reaches | On port |
|---|---|---|
TO SITE "name" | One of your subdomains, served from your own files | 80, 443 |
TO DATABASE "name" | One of your databases, speaking the real wire protocol | 3306 |
TO MACHINE "name" | A machine running your client | as forwarded |
TO FOLDER "/path" | A folder in your namespace, served as static files | 80 |
Ports are real. A database on port 3306 speaks the database protocol; the same address on port 80 refuses the connection, because there is no web server there. That is deliberate — software you did not write expects a network to behave like a network, and one where every port answers the same way would break every client library you might want to use.
Using It
Nothing needs configuring. Inside a sandbox, the names resolve and the addresses answer.
NETWORK MAP "db.internal" TO DATABASE "shopdb"
AFTER WEBASSEMBLY TYPE "python" ENTER `
import mysql.connector
c = mysql.connector.connect(host="db.internal", user="ocalt", database="shopdb")
cur = c.cursor()
cur.execute("SELECT COUNT(*) FROM orders")
print(cur.fetchone()[0])
` SET ?count
AFTER EMIT ?count
NETWORK MAP "shop.internal" TO SITE "myshop"
AFTER WEBASSEMBLY TYPE "bash" ENTER `curl -s http://shop.internal/health` SET ?health
curl https://api.stripe.com from inside a sandbox reaches Stripe exactly as you would expect. What it cannot reach is anything of ours, or anyone else’s — there is no path from your network to theirs.NETWORK LIST
NETWORK LIST SET ?routes
AFTER FOREACH ?routes SET ?r
OPEN
EMIT ?r("name") & " → " & ?r("address") & " (" & ?r("target") & ")"
CLOSE
NETWORK DELETE
Removes a mapping by name. The address returns to the pool. Anything still trying to reach that name stops resolving — which is the point.
NETWORK DELETE "db.internal" SET ?ok
AFTER EMIT ?ok
AFTER NETWORK DELETE ALL SET ?n
AFTER EMIT "removed " & ?n & " mappings"
What This Is Not
This gives you a private network, not a public server. Nothing outside your namespace can open a connection into it — there is no inbound path, by design.
When you want the outside world to reach something, that is what TUNNEL and SERVE are for. They are deliberately separate verbs: exposing something publicly is a decision worth making explicitly, and it is metered and revocable in a way an address on a private network is not.
Full Verb Reference
| Verb | Description |
|---|---|
NETWORK MAP "name" TO SITE "s" SET ?r | Name one of your subdomains. Returns name, address, target |
NETWORK MAP "name" TO DATABASE "d" SET ?r | Name a database, reachable on its real port |
NETWORK MAP "name" TO MACHINE "m" SET ?r | Name a machine running your client |
NETWORK MAP "name" TO FOLDER "/p" SET ?r | Serve a folder as static files |
... AT "10.0.0.50" | Pin the address instead of being allocated one |
NETWORK LIST SET ?routes | Every mapping, with its address and target |
NETWORK DELETE "name" SET ?ok | Remove one mapping |
NETWORK DELETE ALL SET ?n | Remove every mapping, returning how many |