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.

Implementation in progress. The design below is settled and the verbs are specified. The network layer is being built against it.

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.

Nothing here is a blocklist. Filtering is how these systems usually fail: someone eventually finds an address, an alias, or a redirect that was not on the list. Your namespace is not filtered — it is separate. Another namespace is not blocked from yours; it is not attached to yours at any point, so there is no route to block. 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.1Your loopback. Yours alone — a server you start inside the sandbox binds here and only you can reach it
10.0.0.1Your gateway. The route to the public internet
10.0.0.210.0.0.254Yours to assign. Every name you map gets one
anything elseNowhere. There is no route, so there is nothing to refuse
Every namespace uses these same addresses. Two namespaces both using 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.

Naming a Site, a Database and a Machine
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.

A Fixed Address
NETWORK MAP "pi.internal" TO MACHINE "workshop-pi" AT "10.0.0.50" SET ?r
AFTER EMIT ?r("address")
(* 10.0.0.50 *)
An address outside 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.

Repointing a Name
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 files80, 443
TO DATABASE "name"One of your databases, speaking the real wire protocol3306
TO MACHINE "name"A machine running your clientas forwarded
TO FOLDER "/path"A folder in your namespace, served as static files80

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.

A WebAssembly Block Reaching Your Own Database
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
Fetching Your Own Site From Inside a Sandbox
NETWORK MAP "shop.internal" TO SITE "myshop"
AFTER WEBASSEMBLY TYPE "bash" ENTER `curl -s http://shop.internal/health` SET ?health
The public internet still works. Your gateway NATs outbound traffic, so 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

Every Mapping You Have
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.

Removing a Mapping
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 ?rName one of your subdomains. Returns name, address, target
NETWORK MAP "name" TO DATABASE "d" SET ?rName a database, reachable on its real port
NETWORK MAP "name" TO MACHINE "m" SET ?rName a machine running your client
NETWORK MAP "name" TO FOLDER "/p" SET ?rServe a folder as static files
... AT "10.0.0.50"Pin the address instead of being allocated one
NETWORK LIST SET ?routesEvery mapping, with its address and target
NETWORK DELETE "name" SET ?okRemove one mapping
NETWORK DELETE ALL SET ?nRemove every mapping, returning how many