A Channel is a small program with one job and a numbered place in a fixed table. Sixteen core channels make up the machine. The first, Channel 0, is NetXecChannel: it is the System. As the conductor it starts all sixteen cores (itself included), gives each its own thread and its own slice of a shared bus, and tells them when to wake. Everything else plugs in beside them as sidecars and sub-channels.
The idea that goes with it is older than the code: the person who owns the data owns the machine that holds it. The source tree says it in one line in channels6-review/channel_data.h:4: “> Web 4 < Channel Paradigm is controlled by your Solid Pod.” Your solid pod holds your identity, your records and your choices. You can carry it, bind it to a server or a device when you need one, and unbind it again. Nothing is taken from the pod without your say.
Your data, your choice. Consent starts off. People-recognition starts off. Raw camera frames stay in your pod. Section 6 lists every default and where it comes from.
512 slots × 16 KiB = 8,388,608 bytes; 36-byte slot header, 16,348 bytes of payload. These are NetXecChannel’s block today; GPUChannel is not connected to it yet planned
64-bit, 0 is invalid; records are big-endian and mostly fixed size
NODE-RECORD.md
Capability bits
IPV6 1, RELAY 2, DHT 4, AI 8, ALL 15
meshrec.h:27
This page replaces the older “Channels · ContainerDisplayChannel roster & joins” page. The interactive join chart is still at /dev/channels/joins/.
How to read this manual
Every statement about the code is taken from the source files and carries a file:line reference. Where the sources do not say something, this page says planned or leaves it out. Each channel and each sub-channel wears one of these labels:
builtReal behaviour exists in the source (it may still be small).stubThe channel opens and holds state or settings, but there is no real device, codec or network behind it.name onlyThe name is reserved in the sub-channel table. No code is behind it.stagedWritten and tested offline, but not wired into the running system.plannedA design or a roadmap item. Nothing runs today.
“Opened at boot” is a separate question from “built”. Several sidecars have working code that nothing in NetXecChannel.c opens automatically; those are marked not opened at boot.
All numbers use decimal unless written 0x…. Offsets count from byte 0. “BE” means big-endian, the wire order of every pod record.
Part 1
NetXecChannel: the System, core Channel 0
builtNetXecChannel.c (1,608 lines) is the “Web4 microkernel bootstrap and main loop” (NetXecChannel.c:1-15). It is the program that builds as solidpod.exe. NetXecChannel is the System: core Channel 0, one of the sixteen cores. In the current source, core 0 is named “System” in the name tables and there is no separate SystemChannel.c; this file holds its code. As core 0 it creates the sixteen cores (itself included), executes them and routes between them. Its job in four parts:
Create the 16 core channels (its own System slot, channel 0, among them), each with a name, a lock, a run-state record and a thread (BootstrapChannels, NetXecChannel.c:466-556).
Allocate the crossbar, the shared 8 MiB block that is meant to carry data between cores (NetXecChannel.c:481).
Route wake-ups: when one channel has something for another, it sets a bit; the per-core threads (one per core, core 0 included) see it and run the matching handler from a 512-entry dispatch table (NetXecChannel.c:600-756).
Run the main loop: poll the window system, tick STDIO and Container, run a watchdog, and shut everything down in a safe order (NetXecChannel.c:1301-1565).
The structures it owns
Structure
Bytes
What it is
NetXecChannel
336
The record that holds core 0’s tables and the other cores: channel_base[16] (core 0 itself is channel_base[0], a Channel), buffer_block (the crossbar), threads[16], thread parameters, the event channel, the container, bridge and STDIO pointers, flags.
Channel
488
One channel: id, name, ch_input / ch_output crossbar slots, ch_event_flags, an I/O request queue of 16, a lock, runtime, run-info, thread, ch_listeners[16], ch_sub_channel[16], listener mask, QoS class (channels.h:277-297).
Runtime
920
The function table of a channel: init, start, run, paint, expunge, join, merge, leave, read, write, halt, pause, quit, open, close, plus 16 × 2 tables of lock, unlock and callback pointers.
RunInfo
160
Run state (RT_* 0–27), wait time, iteration count, timestamps.
HyperLock
32
A mutex plus a condition variable and a name, one per channel.
Sizes are compile-time asserts at channels.h:456-498. Also asserted there: IORequest 64, NetXecThread 64, ThreadParams 32, SPSCRing 32, Field 112, Object 312, MemoryHandle 64, ArbitrationChannel 2,128.
Boot sequence
OpenNetXecChannel (NetXecChannel.c:152-460) opens things in this order. Memory comes first because everyone allocates through it; it is closed last.
Step
What happens
Line
1
Open Memory. Every other channel allocates from it, so it comes first and closes last.
158
2
Open Thread (the thread pool).
166
3
Allocate the NetXecChannel struct.
174
4
BootstrapChannels: allocate the crossbar and the 16 channel structs with their runtimes and run-infos.
184
5
Create a HyperLock for each channel.
191
6
Fill the thread parameters.
220
7
InitDispatchTable: 512 entries, all harmless defaults except one real handler.
234
8
GetChannelThreads: one thread per core.
239
9
Open Event (the OS-event ring).
242
10
Open Container (windows and display).
251
11
Open STDIO; join it to Event and to the Signal core (270-283).
262
11b
Open MainChannel early (the session owner). Its joins wait until step 17.
294
12 / 12b / 12c
Open URL, then Image, then Code (the Code Share front).
308, 312, 316
13
Open Server.
320
14
Open Font.
324
15
Open Media.
328
16
Open Clock and seat it in its core slot (ClockJoinCore: it sets the id, name and NetXec pointer and stores Clock in channel_base[6]; it makes no ChannelJoin call).
341
17
MainJoinHub joins MainChannel to every live core; the optional stubs that CHANNELS7_OPEN_* variables ask for are opened.
365
The environment variables are read at NetXecChannel.c:289, 370-380, 398-454:
Variable
Default
Effect
CHANNELS7_OPEN_MAIN
on
=0 skips MainChannel. The older name CHANNELS7_OPEN_USER=1 still forces it on.
CHANNELS7_OPEN_CONTAINER_DISPLAY
off
=1 opens ContainerDisplayChannel (sidecar 111).
CHANNELS7_OPEN_SQL
off
=1 opens SQLChannel (sidecar 112, a stub).
CHANNELS7_OPEN_NIMOSINI
off
=1 opens the Nimosini placeholder (NetXecChannel.c:433). See channel 15.
Threads, wake-up flags and the dispatch table
Every core channel has its own thread (CoreChannelThread, NetXecChannel.c:600-695). The thread sleeps on the channel’s HyperLock condition, waking at least every 16 ms (ri_wait_time), or earlier when another channel pokes it.
The poke is one bit. Each channel owns a 64-bit ch_event_flags word. It is cut into 16 nibbles, one per possible sender (defines.h:34-44):
bit 0READbit 1WRITEbit 2JOINbit 3reserved
The woken thread reads and clears the word (NetXecChannel.c:662), then for each non-zero nibble n it looks up dispatch_table[IO_PERMUTATION_INDEX(n, self, dir)] and calls the handler (NetXecChannel.c:675-686). The index is (src<<5) | (tgt<<1) | dir with DIR_READ 0 and DIR_WRITE 1 (defines.h:55-62). Sixteen sources × sixteen targets × two directions = 512 entries.
Honest status. All 512 table entries are no-op defaults except one: SystemReadFromSignal (Signal → System), installed at NetXecChannel.c:755. The fabric is complete; the handlers for the other 511 cells are not written yet. planned
Known issue in the wake bits. The READ and WRITE macros build their mask by shifting a plain 32-bit int by ch × 4 (defines.h:41-44; the JOIN and RESERVED macros on lines 43-44 shift the same way). For senders 8–15 that shift reaches past bit 31, so those wakes are unreliable (the MASK macro already uses a 64-bit constant). The Signal sender, nibble 4, which the one live handler uses, is not affected. A fix that widens the constants to 64 bits has been proposed and is not applied. planned
Example flow: a key press reaches System
The main loop polls the window system and turns each event into a 64-bit code with EncodeEvent (NetXecChannel.c:797-822). Key down is 0x05010000 | scancode<<8, key up 0x05020000…, mouse button down, button up and motion use 0x0601…, 0x0602… and 0x0603…. Motion packs x and y; button down and up pack the button number and x only (NetXecChannel.c:805-816). Quit is 0xFF010000.
HandEventToEventChannel pushes the code on the EventChannel ring (NetXecChannel.c:1175-1216).
WakeSystemForSignal sets the READ bit in System’s nibble 4 (NetXecChannel.c:853-863).
System’s thread wakes and runs SystemReadFromSignal, which pops 8-byte codes from the ring into the crossbar slot [System][Signal][READ] (NetXecChannel.c:713-744).
STDIO, joined to Event and Signal at boot, reads the same events from the Event ring through its own cursor (EventChannelPopSTDIO, STDIOChannel.c:525-540), not from the crossbar slot, for the command line (channel 12).
The sub-channel table
SubChannelAllocatedNames[256] (NetXecChannel.c:82-115) is the master list of names. A flat id is core × 16 + sub, so Memory’s “registry” (core 2, sub 4) is flat id 36. Unused cells hold the string “null”. Names are not code: the right-hand column of each channel card below says what, if anything, stands behind each name. The table below is generated straight from the source by a small C program, so it cannot drift.
Process1 “code” (flat id 188) is present in the source but was missing from the earlier version of this page. It is the Code Share front (docs/CODECHANNEL.md). Container’s header also defines a fifth sub, CC_SUB_CONFIG 4 (ContainerChannel.h:42), that the name table does not list.
The CoreChannelNames table (NetXecChannel.c:66-71) gives the display names; CoreChannelClearNames (:74-79) gives the STDIO prefixes such as SystemChannel (core 0, NetXecChannel) or ContainerChannel.
Main loop, watchdog and shutdown
Main loop (RunMainLoop, NetXecChannel.c:1301-1350): poll events; tick STDIO; run the watchdog; tick Container every 16 ms. The window is 1280×960, twice HyperView’s 640×480 (NetXecChannel.c:1226).
Watchdog (NetXecChannel.c:828-847): for each core that is sleeping on its wait condition (RT_WAITCOND) and has waited longer than its wait time plus 10 ms (100 ms if none is set), sets bit 0x1 and signals it, so an idle waiter always wakes.
Diagnostic menu: Esc opens a menu of keys r (print channel diagnostics), e, x, c, u, s, t; q quits (NetXecChannel.c:1059-1173).
Shutdown (NetXecChannel.c:1373-1565) follows the HyperView rule: mark every runtime RT_STOPPING then RT_SHUTDOWN, wake all threads, join every thread, wait up to 1 s for each runtime to reach RT_ZOMBIE or RT_STOPPED (then force RT_STOPPED), and only then close Server, Clock, Container, Image, Code, URL, Bridge, STDIO, Font, Media and Event, free the channels and the crossbar, and close Memory last.
main prints “NetXec: 16 core channels online” once boot completes (NetXecChannel.c:1571-1608).
Part 2
The sixteen core channels
Ids are CHANNEL_SYSTEM 0 to CHANNEL_NIMOSINI 15 (defines.h:73-88). Channel 0, System, is NetXecChannel (part 1); the other fifteen follow it. Each card gives: the id and status, what the channel is for, what reading and writing mean for it, its sub-channels, what it may be joined to, and an example flow. “Links” come from the draft join chart (docs/channel-joins.md); the binary does not enforce that chart yet (see Joins and the policy chart).
Reading a card: “read” and “write” are the two directions of the crossbar pair. A channel reads from the slot [self][peer][READ] and writes to [self][peer][WRITE] (channel_io.c:112-140). Core slot versus core id: bootstrap makes a plain Channel in every channel_base[n] (NetXecChannel.c:507-547). Only Clock replaces its slot (ClockJoinCore, ClockChannel.c:137). Container, URL, Media, Server and STDIO open their own channel object that carries the core id but leave the slot as bootstrap made it (ContainerChannel.c:4, 214, URLChannel.c:883, MediaChannel.c:41, ServerChannel.c:40, STDIOChannel.c:167). (Some source comments call these objects “sidecar”; this manual keeps “sidecar” for channels that are not the core’s own object.)
0 System (NetXecChannel) builtcode in NetXecChannel.c
Purpose
System is NetXecChannel, core Channel 0 (part 1). The root of the machine: standard streams, OS events, and the authority to start, stop and pause other channels. In the source it is the channel_base[0] slot with its own thread; there is no separate SystemChannel.c: its code is NetXecChannel.c. The EventChannel (the OS-event ring) reports itself as System’s sink: ch_id = CHANNEL_SYSTEM, name “Event” (EventChannel.c, “event sink rides on System”).
Read / write
Read from Signal: the one real dispatch handler in the whole table pops 8-byte event codes from the EventChannel ring into the crossbar (NetXecChannel.c:713-744, 755). Write: no handler yet. Design intent for the kill switch: System sets RT_STOPPING or RT_PAUSED on channel 15 and that always wins (Nimosini spec §2, planned).
Sub-channels
0 stdin (0)1 stdout (1)2 stderr (2)3 event (3)name only except event, which is the EventChannel ring: 64 KiB of 8-byte codes (8,192 events), single producer, lock-free flags, plus a second read cursor for STDIO (EventChannel.c).
Links
Chart allows Device, Memory, Thread, Signal, Media, Clock, Container, URL, Server, STDIO, Compiler, Debug, Nimosini. It denies Process0 and Process1.
Example
Key press → EncodeEvent → Event ring → SystemReadFromSignal → crossbar slot (no code consumes that slot yet, only debug prints peek at it: NetXecChannel.c:1003-1011, 1087-1093). STDIO reads the Event ring itself, through its own cursor, for the command line (see the walk-through).
1 Device stub
Purpose
Hardware: graphics, USB, serial. The planned home for cameras and microphones and for seeing a pod drive when it is plugged in.
Read / write
None yet. Nothing in the source opens these three channels at boot.
Sub-channels
0 gpu (16)stub GPUChannel, the Blitter Bus (crossbar), is the crossbar of the Web 4 Channel Paradigm (see part 3). Source channels7/GPUChannel.c (153 lines): a query-name call only, no device; never opened at boot and called by no other file. There is no CHANNEL_GPU: gpu is Device sub-channel 0 (flat id 16), and the stub sets its channel id to Device (GPUChannel.c:90), so it has no slot in the crossbar. The separate channels7-read/GPUChannel.c (1,838 lines) is a different file, described in part 3. 1 usb (17)stubDeviceUSBChannel.c: a vendor/product filter; enumerate returns 0 and open returns −2 (no libusb). 2 rs232 (18)stubDeviceRS232Channel.c: configure only; open-port returns −2.
Also homed here
GPSChannel.c and GPRSChannel.c set ch_id = CHANNEL_DEVICE (GPSChannel.c:90), although the name table lists “gps” and “gprs” under Process1. See Process1.
Links
Chart allows only System, Memory, Thread, Signal; every other pair is denied. Devices hand data to Memory, they do not talk to the network.
Planned
Camera and microphone frames delivered into Memory rings for channel 15 (Nimosini spec §2). USB volume detection for the portable pod (see bind on demand). planned
2 Memory built
Purpose
Every allocation in the system goes through Memory. It is opened first and closed last. The 8 MiB crossbar itself is allocated here as shared (IPC) memory (NetXecChannel.c:481).
Read / write
AllocMem / FreeMem take a request: size, name, RAM type, data type, dimension, flags (memory.h). A header (MemoryHandle, 64 bytes) and an IPC prefix sit in front of the memory you receive. Memory types (defines.h:376-383): HEAP 0, STACK 1, IPC 2, GPU 3, CLOUD 4, REGISTRY 5, PAGE 6.
What is real
IPC (POSIX shm / Win32 mapping, MemoryChannel.c:179, 219-232) and PAGE (mmap / VirtualAlloc, MemoryChannel.c:297-303) are real. HEAP and STACK are plain calloc (MemoryChannel.c:114-133). GPU, CLOUD and REGISTRY currently fall back to plain calloc. In the source: // TODO: SDL_GPUBuffer path and // TODO: remote pod-backed storage (MemoryChannel.c:262, 275). That second TODO is the hook where the pod will plug in; see Take your pod with you. planned
Sub-channels
0 heap (32)1 stack (33)2 shared (34)3 cloud (35)4 registry (36)5 device (37)6 page (38)7 buffer (39) Code behind them: shared = SharedMemoryChannel.c, a named mapping built; buffer = BufferChannel.c over MemoryBuffers.h, a Java-NIO-style Buffer (position, limit, capacity, mark; flags READONLY, DIRECT, BIG_ENDIAN, MAPPED) built; registry = RegistryChannel.c, a thin preferences get/put front built; heap, stack, cloud, device, page = allocator types or names with no separate channel file.
Typed data
Memory also carries ChannelData (an 80-byte typed header: 32 data types in 4 dimensions) and Objects made of named Fields, saved as NAME.chd (defines.h:410-452, channel_data.h). Flags are tabled in ChannelData flags.
Links
Chart allows Memory to join all fifteen other cores; it is the shared floor.
3 Thread built
Purpose
The thread pool and the thread records. GetNetXecThread hands out threads (up to MAX_CPU_THREADS 64), each pointing at its owner channel’s RunInfo and HyperLock (ThreadChannel.c:186-187, defines.h:19-32).
Portable threads
PodThread (256 bytes, thread.h:53-66) is a thread you can sign and send: name[80], id u64, owner WebID[64], signature[64], entry hash u64, data bytes u64, memory type, flags, priority, stack size. PodThreadFromLocal, PodThreadSign (Ed25519) and PodThreadVerify work. PodThreadToLocal — turning a received pod thread back into a running one — is a TODO that returns −1 (ThreadChannel.c:359-366). planned
Sub-channels
0 arbitration (48)not opened at bootArbitrationChannel.c is a sidecar lock-request queue (256 requests, 4 workers, channels.h:370-387). Nothing in the NetXec bootstrap opens it, and the arbitration pointer in NetXecChannel is never set.
Every core channel’s own thread is started at boot by GetChannelThreads (step 8).
4 Signal builtsmall
Purpose
Soft signals and the path events take into the system. SignalChannel is a software latch: SignalArm, SignalDisarm, SignalRaise, SignalPoll, SignalClear, a queue of 16 (SignalChannel.h). It installs no OS signal handlers.
Read / write
As a core slot, Signal is the source side of the one real handler: System reads “from Signal”. STDIO is joined to the Signal core at boot (NetXecChannel.c:277-283). The sidecar OpenSignalChannel is not called by the bootstrap. not opened at boot
Sub-channels
None — all sixteen cells (flat 64–79) are “null”.
Links
Chart allows Signal with every core except Compiler.
Planned
Nimosini spec: Signal carries mail, news and peer-up / peer-down events to channel 15. planned
5 Media builtmostly stubs
Purpose
Pictures, sound and video. A MediaChannel is opened at boot step 15, carries core id 5, and groups three sub-slots: VIDEO 0, AUDIO 1, TELECONFER 2 (MediaChannel.h:17-19). It does not replace the core slot channel_base[5].
Sub-channels
1 image (81)builtImageChannel.c: URL-driven, non-blocking (rides the curl pool), interlaced fill so a picture appears progressively, observers are notified; opened at boot step 12b. 0 audio (80)stubAudioChannel.c: a PCM queue with play/stop flags; no audio device. 5 audiowav (85)stubAudioWavChannel.c: parses WAV into a buffer; play is a stub. 2 video (82)stubVideoChannel.c: stubs, no ffmpeg; aware of the video pod flags. 3 vlc (83)stubVLCChannel.c: reads a path from preferences only. 6 player (86)stubPlayerChannel.c: path and transport state only. 4 tv (84)name only.
Calls
The phone records (see Phone records) say who rings whom; the sound and picture of a call belong to Media. Constants for audio and video rings, codecs (OPUS 1, AV1 2, H264 3, VP9 4) and media states are in defines.h:581-604. Nimosini never touches call media (spec §2). The real media engine is planned.
Time and ticks for everyone else. ClockChannel.c is described in its own source comment as a “thin compile-clean skeleton” (ClockChannel.c:3): it opens, counts iterations and stamps the time; its status string reads “Clock open stub”. It is opened at boot (step 16) and seated in its core slot by ClockJoinCore (ClockChannel.c:131-138): the call sets its id, name and NetXec pointer and stores it in channel_base[6]. It makes no ChannelJoin call, so at boot nothing joins Clock to a peer except the one join MainJoinHub adds; the draft join chart below says which links are meant. Its wait time is 40 ms.
Rate-limit windows and the scheduler tick for Nimosini (spec §2). The draft join chart, however, denies Clock↔Nimosini, so this needs reconciling (see the open questions). planned
7 Container built
Purpose
The screen: windows, gadgets, graphic objects (gobs), menus. ContainerChannel is the HyperView-parity UI catalog. Limits: 64 containers, 16 windows, 256 members, 64 gobs; the view is 640×480 (ContainerChannel.h). It is ticked every 16 ms by the main loop and is closed before Image at shutdown.
Read / write
Anything that can be seen is a Container “kind” (CC_KIND_* 0–18: file, archive, window, container, channel, solid, gob, gadget, animated gob, text pane, super-bitmap, file pop-up, prefs pane, title bar, memory window, server config, pup catalog, scroll bar). Each frame is drawn in the HyperView order: animate → composite → status → present (ContainerChannel.h, display tick).
Sub-channels
0 menu (112)1 screen (113)2 twitter (114)3 solid (115) — ids 0–3 are CC_SUB_MENU/SCREEN/TWITTER/SOLID. screen is backed by ScreenChannel.c (display query) built; solid by SolidChannel (see Process1); menu and twitter are names.
Sidecars
BridgeChannel gives Container a main()-like entry (argc/argv) and a console sink. FontChannel (SDL3_ttf optional). ContainerDisplayChannel (id 111) is a display-name layer over Container; the core id stays 7 (opened only when CHANNELS7_OPEN_CONTAINER_DISPLAY=1). ChannelConfig is the Container “config board” with 16 user-defined channel slots and LINK / SET_RT operations (ChannelConfig.h:20-35).
The owner’s setup and consent screen for Nimosini is drawn by Container (spec §2). planned
8 URL built
Purpose
Fetching things by address. URLChannel is a singleton (ch_id 8, URLChannel.c:883) with a libcurl multi pool. A fetch is only queued (URLFetch, URLFetchStart); progress happens on every channel tick (URLChannelTick), so Container never blocks on the network. URLCancel sets a cancel flag and the next tick removes the transfer (URLChannel-CURL.md).
Schemes
http://, https:// and file:// go through libcurl. tachyon://host:port/path does not: it uses the TachyonDB page wire (PAGE_GET, tachyon_page.c) on a small helper thread (URLChannel.c:12). The contract says URLChannel tries Tachyon first and falls back to the Blitz docroot when a page is not found or Tachyon is down (WEB4-CONTRACT.md, “Storage”).
Sub-channels
3 file (131)builtFileChannel.c: local file I/O through stdio (ch_id 8, FileChannel.c:148). 0 ftp (128)1 telnet (129)2 gopher (130)4 chat (132)5 irc (133)name only
Links
Chart allows System, Memory, Signal, Container, Server, STDIO. It denies Device, Thread, Media, Clock, Process0, Process1, Compiler, Debug, Nimosini. The Nimosini spec lists URL as never used by the AI (tier 3).
Example
A page asks for a picture: Image calls URLFetchStart; curl runs on the tick; the done-ring hands bytes back; Image paints them in interlaced passes.
9 Server config only
Purpose
Where this machine listens and answers. In the desktop runtime, ServerChannel only holds a listen port and a bind address. Its header says it plainly: “Does NOT bind a socket yet” (ServerChannel.h:4); the LISTENING flag is reserved and never set, and ServerChannel.c contains no bind, listen or accept calls. A future listener is to run on its own thread so the main loop never blocks.
Sub-channels
8 portserver (152)stubPortServerChannel.c hands off to ServerChannel. 5 bql (149)builtBQLChannel.c keeps a query string and the TachyonDB connection settings and speaks PAGE_GET / PAGE_PUT. (Its ch_id in code is Process1, BQLChannel.c:105.) 4 bml (148)built, smallBMLChannel.c is a buffer bridge whose stream starts with the magic bytes ‘B’, ‘M’, ‘L’, 0x02. The full walk is done by the bml/ library and BlitzBrowse. (Its ch_id in code is Process0, BMLChannel.c:90.) 0 socket (144)1 ftp (145)2 apache (146)3 mysql (147)6 blockc (150)7 debug (151)name only
Beyond the desktop
The site side is separate code: a headless daemon with the Blitz protocol on TCP 23232 (see Blit path and Blitz), and the mesh endpoint /cgi-bin/mesh.cgi that mesh/MESH-SPEC.md specifies for the mesh handshake. The sources do not show the mesh endpoint as live. In the Nimosini design, Server holds the pod’s signing key and signs the three whitelisted AI mesh messages (spec §8).
Links
Chart allows System, Memory, Signal, URL, Process0, Process1, STDIO. It denies Nimosini — see the conflict in open questions.
10 Process0 some built
Purpose
The first group of workers: crypto, counting, compression, colour, and a long reserve list of language and finance names.
Sub-channels
0 encryption (160)builtEncryptionChannel.c: AES-256-GCM compiled in, no libsodium. Wire format nonce(12) | ciphertext | tag(16), so output is input + 28 bytes; an AAD variant binds CodeVault blobs (repo_id||"BLOB") and manifests (repo_id||"MANI") (EncryptionChannel.h:2-8, 49). 13 compression (173)partialCompressionChannel.c: STORE (raw) and a simple RLE of (count, value) pairs. DEFLATE is a TODO: “no zlib/miniz in tree” (CompressionChannel.c:2, 217-219). planned 1 statistics (161)stub a tick counter. 8 color (168)stub RGBA packing and a 256-entry palette. 2 transform (162)3 smc (163)4 js0 (164)5 js1 (165)6 c (166)7 fortran (167)9 antlr (169)10 bitcoin (170)11 wallet (171)12 piet (172)name only
Also homed here
JavaChannel.c (:90) and BMLChannel.c (:90) set ch_id = CHANNEL_PROCESS0; the name table lists java under Compiler and bml under Server and Process1.
Code Share uploads a project: the Code front asks Encryption for AES-256-GCM with the repository id as AAD, then Server carries the sealed blob. The key stays with the owner’s Ed25519 identity (SolidChannel.h:1-9).
11 Process1 some built
Purpose
The second group of workers: data, code, markets and location.
Sub-channels
12 code (188)builtcodechannel/CodeChannel.h: the Cont front for Code Share. One dispatcher with drivers for CodeVault (CODEVAULT 1, speaking PCL opcodes), git (2) and svn (3), with room for more; opened at boot step 12c and closed before URL (docs/CODECHANNEL.md). The core name table is untouched. 11 stock (187)builtStockChannel.c: a quote sidecar around SP_StockConfig, a 48-byte record (symbol[16], exchange[8], last price × 10,000, bid, ask, flags, volume) (StockChannel.h:2-5). 3 bql (179)built the same BQLChannel listed under Server; its code is homed on Process1. 5 sql (181)stubSQLChannel.c is a sidecar with id 112; its driver kinds are NONE, STUB and SQLITE (reserved); there is no SQLite in the tree (SQLChannel.h:23). Opened only by CHANNELS7_OPEN_SQL=1. 9 state (185)stubStateMachineChannel.c: a state id. 0 gps (176)1 gprs (177)stub last-fix store and APN store; no NMEA parser, no modem. Homed on Device in code (see Device). 2 bml (178)4 html (180)6 emscripten (182)7 solid (183)8 xml (184)10 shopping (186)name only in this core.
SolidChannel
builtSolidChannel.c is the SolidPod object sidecar. It is homed on Container (SolidChannel.c:93) and surfaced as Container’s solid sub-channel. It carries the CodeVault client hooks: client-side AES-256-GCM through Encryption, Ed25519 ownership signatures (ed25519_pod / cv_sign, secret key = seed‖public key, 64 bytes), and the signed request headers Code Share sends to the server (SOLID-AUTH-HEADERS.md): X-Solid-WebID, X-Solid-Ts, X-Solid-Pk (64 hex), X-Solid-Sig (128 hex) over the text CV-SOLID|v1|<webid>|<ts>|<METHOD>|<path>. SolidChannel never invents keys; they come from the caller’s buffers (SolidChannel.h:78, 110).
The cooked text hub: the command line, logging and key input. STDIOChannel (616-byte struct) has an input and an output ring. Writes go to the output ring and wake joined peers; STDIOTick drains it to a sink and reads events via EventChannelPopSTDIO. Printable keys arrive through STDIOFeedKey only (STDIOChannel.h:7).
Marshal prefixes
Lines are tagged with the sender’s clear name (CoreChannelClearNames, NetXecChannel.c:74-79), for example ContainerChannel:.
Sub-channels
0 cli (192)builtCLIChannel.c (832-byte struct: line[256], prompt[32]). Commands: abort (leave a stuck display frame) and help or ? (CLIChannel.c:37, 48). STDIO is the only channel that fills ch_sub_channel[16].
Links
Chart allows every core except Device. At boot it is joined to Event and to Signal.
13 Compiler stub
Purpose
Turning source into programs. Today CompilerChannel.c stores a source path and nothing else (no code generation). stub
Sub-channels
4 java (212)stubJavaChannel.c records java_home from preferences; no JVM is started. 0 x64 (208)1 arm8 (209)2 c (210)3 fortran (211)5 emscripten (213)6 js (214)7 julia (215)name only
Links
Chart allows System, Memory, Process0, Process1, STDIO, Debug. Everything else is denied, including Signal and Nimosini. The Nimosini spec lists Compiler as never used by the AI (tier 3).
14 Debug slot only
Purpose
Reserved for debugging. There is no Debug source file; the core exists only as its slot, thread and lock. The Esc diagnostic menu in NetXec is a separate facility, not this channel (NetXecChannel.c:1059-1173).
Sub-channels
0 gdb (224)1 vc (225)name only
Links
Chart allows System, Memory, Signal, Process0, Process1, STDIO, Compiler. It also denies Nimosini; the Nimosini design would have Debug show counters, which the draft chart does not allow (see open questions).
15 Nimosini design / planned
Status, plainly
Core id 15 is reserved for Nimosini (defines.h:88), and the name table gives it twelve sub-channel names. There is no working Nimosini code in the running system.NimosiniChannel.c and NeuralNetChannel.c in channels7 are placeholders, they open only when CHANNELS7_OPEN_NIMOSINI=1, and nothing in this manual treats them as design sources. Everything below comes from the draft specification NIMOSINI-CHANNEL-SPEC.md (draft 2, 2026-10-02, “design only”). planned
Role
One Nimosini per pod. It is the AI aggregator and controller for that pod. On the mesh it appears as “Nimosini @ node id”: the same name and avatar everywhere, with the pod’s 64-bit node id as its instance id. A pod that has not granted anything stays dormant: it announces presence and does nothing else.
Sub-channels
Flat ids 240–255, all name only, no code behind them:
0–7 neural0…neural7 (240–247)8 grok (248)9 bert (249)10 chatgpt (250)11 neuralnet (251) and cells 252–255 are “null”. Design roles: nets 0–5 = cameras (vision and depth), net 6 = audio input, net 7 spare; grok is reserved and not wired; bert is the encoder slot and chatgpt the text slot (the spec calls them the “Burt” and “GPT” slots). Sub-channels have no crossbar slot of their own (channel_io.c:136-139). The staged prototype uses different names for 248–250; see open questions.
Nets
Each net is independent: its own ring, weights, thresholds and failure state. Frames are 8-bit ARGB words, big-endian, default 1080×720 = 3,110,400 bytes. Audio is signed 16-bit big-endian, mono, 16 kHz. Weight files are “NMW1”: a 64-byte header plus 32 bytes per layer, up to 64 layers.
How it is controlled
A one-time grant by the owner, scoped by a 15-bit mask (see AI records). Four tiers: 0 observe; 1 reversible and local; 2 outward or exposure-increasing — allowed only if the scope is granted and the action is untainted and rate limits allow; 3 never (grants, keys, weights, compiler or URL use, audit edits, avatar generation, peer commands). Anything built from text or audio the owner did not provide is tainted and capped at tier 1. Hard limits: a hash-chained audit log (32-byte records, 32,768 of them = 1 MiB), a kill switch that always wins (System channel, RT_STOPPING / RT_PAUSED), per-verb rate limits (tier 1 up to 20 per minute; tier 2 up to 12 per hour and 4 per hour per verb; mail up to 5 per hour), and a breaker that trips on 5 failures in 1 minute or 3 undo taps in 10 minutes.
Keys
Nimosini never holds the signing key. Server (channel 9) holds it and signs only three message types. Nimosini cannot sign anything else or impersonate the pod.
Resources
The owner sets RAM and disk for it: RAM 256–8,192 MiB (default 1,024), disk 2,048–65,536 MiB (default 8,192), never more than 50 % of physical RAM or 25 % of free disk (airec.h:38-63). Running a language model in the pod needs at least 2,048 MiB of RAM. The language-model engine itself is planned to be a separate OS process.
Lifecycle
INIT (read config; no grant = DORMANT) → PROBE → JOIN → RUN, with DEGRADED, PAUSED and BREAKER side states → STOPPING → STOPPED. Tick 16 ms, 12 ms AI budget per tick.
Links
Chart allows System, Memory, Thread, Signal, Container, Process0, Process1, STDIO. It denies Device (cameras reach it through Memory rings), Media (it never touches call media), Clock, URL, Server, Compiler and Debug. In the design: Memory holds the read-only frame and audio rings; Signal brings events; Container draws the owner’s setup and consent screen. The design also wants a tick from Clock, key custody and signing from Server, and counters on Debug, all three of which the draft chart denies (see open questions).
Not built
The Nexus pyramid share formula (60 % RAM / 40 % disk, weighted by 30-day uptime) is a proposal only. planned
Part 3
Sidecars, the Blitter Bus (crossbar) and the blit path
Sixteen cores are not enough for a whole system, so Channels has three more ideas that sit beside them. Sidecars are extra channels with ids of 100 and above. The join fabric says who is connected to whom. GPUChannel, the Blitter Bus (crossbar), is meant by design to carry the data between the cores: the Blitter Bus is the crossbar of the Web 4 Channel Paradigm. planned What exists today: NetXecChannel allocates the 8 MiB block Crossbar8MB (512 slots × 16 KiB, NetXecChannel.c:481); only SystemReadFromSignal writes to it; ChannelWriteSlot and ChannelReadSlot have no callers; and GPUChannel is not connected to it yet. Together these are the “bus” of this manual.
About the Blitter Bus. GPUChannel, the Blitter Bus (crossbar), is the crossbar of the Web 4 Channel Paradigm. Today that crossbar is the 8 MiB block that NetXecChannel allocates (NetXecChannel.c:481; see The crossbar below). Which file is meant matters. channels7/GPUChannel.c (153 lines) is a query-name stub with no device: nothing opens it at boot and no other file calls it (see Device). A separate file, channels7-read/GPUChannel.c (1,838 lines), is an offscreen renderer that uses CPU loops and does not use the crossbar; it does not build against channels7, because commands.h, BitPack.h and ThreadChannelGPUDrawLines are missing. There is no CHANNEL_GPU: “gpu” is Device sub-channel 0 (flat id 16), and the stub sets its channel id to Device (GPUChannel.c:90), so as a sidecar it has no slot in the crossbar. Do not confuse the Blitter Bus with two other things that carry similar names, both described in Blit path and Blitz: the Container’s dirty-rectangle blit that puts pixels on screen, and Blitz, the network protocol on TCP 23232. (Lineage only: the name echoes the blitterList / blitterLock graphics-update queue of the older Java HyperView.)
Sidecars
A sidecar is a channel that is not one of the sixteen. It has the same parts as a core (buffer, Runtime, RunInfo, lock) and can be joined to cores, but it lives outside the 16×16 matrix. Two kinds exist:
Own-id sidecars (id ≥ 100): they have an id of their own.
Homed sidecars: most of the code files (Image, URL helpers, Encryption, Stock, …) are sidecars that claim a core id as their home. They do not add a sixteenth-and-first core.
Id
Sidecar
What it is
Status
110
MainChannel
The session hub; formerly UserChannel (the old name remains as an alias). Holds a direct peers[16] table; MainJoinHub joins it to every live core; MainWriteTo is its direct write helper. Flags OPEN / READY / JOINED. STDIO prefix “MainChannel” (MainChannel.h:11, 28).
built default on
111
ContainerDisplayChannel
A display-name layer around Container. Its core id stays 7 (CONTDISP_CORE_ID) (ContainerDisplayChannel.h:29).
built default off
112
SQLChannel
Database front. Driver kinds NONE / STUB / SQLITE (reserved); no SQLite in the tree (SQLChannel.h:23). SQLJoinCore joins Server, Process1 and Memory.
Names used by the Container “config board” (ChannelConfig.h:25-29) so a link between two sidecars can be drawn. In memory only; 16 user-defined channels; operations LINK and SET_RT.
How a sidecar is joined.ChannelJoin stores a core peer at the index equal to the peer’s id; a sidecar takes the first free of the 16 listener slots, and the listener mask bit is the slot index (channel_io.c:50-64). Sidecars have no crossbar slot: ChannelBindIO leaves their input and output pointers NULL (channel_io.c:136-139). They use their own buffers and wake bits. A wake sent by any id of 16 or more is recorded as coming from Signal, nibble 4 (channel_io.c:158-160). The join policy for sidecars is kept apart from the core chart (docs/channel-joins.md, “policy by sidecar id ≥ 100”).
The crossbar (the Blitter Bus)
One contiguous block, allocated by Memory as shared memory at boot (NetXecChannel.c:481):
512 slots = 16 channels × 16 peers × 2 directions, each 16 KiB, 8,388,608 bytes in all (defines.h:50-59).
Each core gets ch_input = [self][peer][READ] and ch_output = [self][peer][WRITE] for a joined core peer (channel_io.c:112-140). Before binding, ch_output = ch_input (NetXecChannel.c:545).
Data moves in 8-byte words. The writer advances the interrupt cursor; the reader advances the user cursor (channel_io.c:184-230).
Slot header (36 bytes) · channels.h:160-177
Offset
Size
Field
Meaning
0
8
ptr
Pointer to external payload (if any)
8
8
ext_size
Size of the external payload
16
4
interrupt
Producer write cursor (byte offset into data)
20
4
user
Consumer read cursor
24
4
size
Usable data size
28
4
seq / reserved32
Sequence counter if CROSSBAR_SEQ_ENABLED; that switch defaults to 0 (defines.h:64-67)
32
1
type
Payload type
33
1
flags
Slot flags
34
2
reserved16
Reserved
36
16,348
data[]
The payload (16,384 − 36)
The crossbar does not enforce per-writer permissions. It is one block in one process with no memory protection between slots. ChannelWriteSlot and ChannelReadSlot contain no permission test; the join mask is never consulted on a write (channel_io.c:184-230); ChannelWakePeer trusts the sender id the caller passes (channel_io.c:151-170). Any code running in the process can write any slot. Rules such as “this ring is written only by its producer” hold by convention, not by enforcement. This is the reason the AI design keeps keys out of the AI channel and routes signing through Server, and why the join chart (below) is still only a policy.
Two more facts a reader of the code will notice. ChannelWriteSlot(A,B) fills [A][B][WRITE] while ChannelReadSlot(B,A) reads [B][A][READ], which is a different address. The one handler written so far, SystemReadFromSignal, writes straight into the reader’s own READ slot (NetXecChannel.c:727-744). And a slot is a plain wrapping buffer of 8-byte words with no lock and no “full” check. A set of proposed fixes (per-pair lock, range checks, a status return from the wake call) exists as an unapplied patch.
Joins and the policy chart
ChannelJoin(a, b) is symmetric. It fails on self or NULL, and for a sidecar peer when the listener slots are all in use (core peers are stored at index = their channel id, so a core-to-core join cannot run out of slots, channel_io.c:50-55), and it rolls back if only one side succeeds (channel_io.c:85-100). ChannelLeave undoes it (:102-110); ChannelIsJoined asks (:172-182).
Joins made at boot: STDIO ↔ Event and Signal; MainChannel ↔ every live core (MainJoinHub). ClockJoinCore is not a join: it only seats Clock in channel_base[6] (ClockChannel.c:131-138, no ChannelJoin call). NimosiniJoinCore would seat channel_base[15] and join Signal and Memory when the optional stub is enabled; SQLJoinCore joins Server, Process1 and Memory (docs/channel-joins.md).
The draft join chart below is the policy the designers want: of the 256 ordered core pairs, 144 ALLOW, 96 DENY, 16 SELF. As undirected pairs that is 72 allowed links. Memory is allowed with all; the “dense core” is System, Memory, Thread, Signal, Clock, Container, STDIO; the rest are spokes. It is generated from docs/channel-joins-corexcore.csv.
Not enforced yet. The document itself says “No hard allow-table in binary yet.” A later step is a join_policy[16][16] table consulted inside ChannelJoin, and showing it in the Container config board. planned
Counting the name cells instead: 256 cells make 65,536 ordered pairs (about 255²). That figure shows why the design does not mesh everything.
src ↓ / tgt →
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
0 System
·
✓
✓
✓
✓
✓
✓
✓
✓
✓
×
×
✓
✓
✓
✓
1 Device
✓
·
✓
✓
✓
×
×
×
×
×
×
×
×
×
×
×
2 Memory
✓
✓
·
✓
✓
✓
✓
✓
✓
✓
✓
✓
✓
✓
✓
✓
3 Thread
✓
✓
✓
·
✓
×
✓
✓
×
×
✓
✓
✓
×
×
✓
4 Signal
✓
✓
✓
✓
·
✓
✓
✓
✓
✓
✓
✓
✓
×
✓
✓
5 Media
✓
×
✓
×
✓
·
✓
✓
×
×
×
×
✓
×
×
×
6 Clock
✓
×
✓
✓
✓
✓
·
✓
×
×
×
×
✓
×
×
×
7 Container
✓
×
✓
✓
✓
✓
✓
·
✓
×
×
×
✓
×
×
✓
8 URL
✓
×
✓
×
✓
×
×
✓
·
✓
×
×
✓
×
×
×
9 Server
✓
×
✓
×
✓
×
×
×
✓
·
✓
✓
✓
×
×
×
10 Process0
×
×
✓
✓
✓
×
×
×
×
✓
·
✓
✓
✓
✓
✓
11 Process1
×
×
✓
✓
✓
×
×
×
×
✓
✓
·
✓
✓
✓
✓
12 STDIO
✓
×
✓
✓
✓
✓
✓
✓
✓
✓
✓
✓
·
✓
✓
✓
13 Compiler
✓
×
✓
×
×
×
×
×
×
×
✓
✓
✓
·
✓
×
14 Debug
✓
×
✓
×
✓
×
×
×
×
×
✓
✓
✓
✓
·
×
15 Nimosini
✓
×
✓
✓
✓
×
×
✓
×
×
✓
✓
✓
×
×
·
✓ ALLOW× DENY· SELF Row = source channel, column = target channel; the column numbers are channel ids. For the interactive chart see /dev/channels/joins/.
Blit path and Blitz
The display blit (inside one machine)
Container draws every frame in the HyperView order animate → composite → status → present. To avoid redrawing the whole 640×480 view each time, it keeps a list of dirty rectangles: ContDirtyAddRect(x, y, w, h) adds one, ContDirtyClear empties the list, ContDirtyCount returns how many there are, and ContDirtySetFullBlit(on) says “redraw everything” (the count then reads −1) (ContainerChannel.h:727-730, cont_wave.c:734-745). Title bars and the wave code call the full-blit switch whenever something large changes (Titlebar.c:222, cont_wave.c:102).
Blitz (between machines)
Blitz is the binary request/response protocol the headless server speaks on TCP 23232, with BML pages as its content (WEB4-CONTRACT.md, “Blitz protocol”). All Blitz numbers are little-endian — unlike pod records, which are big-endian. A frame is [opcode u8][flags u8][reserved u16][length u32] then the payload. Flags: MORE 1, ERR 2. The tables below follow WEB4-CONTRACT.md and the channels7 copy blitzbrowse/blitz_proto.h; the newer master channels-server/blitz_proto.h adds opcode NOP 0x00, method PUT 0x04, two more header ids and the statuses 201, 401 and 409.
Opcode
Name
Direction
Payload
0x01
HELLO
client
magic “BLZ1”, version 1, caps u32, client name
0x02
HELLO_ACK
server
same shape
0x10
REQUEST
client
method (GET 1, HEAD 2, POST 3), URL
0x11 / 0x12
HEADER / END_HEADERS
client
field id + value; ids 1 content-type, 2 content-length, 3 user-agent, 4 host, 5 connection, 6 accept
0x20
RESPONSE
server
status u16 (200, 400, 404, 408, 413, 500), then headers
0x21 / 0x22
BODY / END
server
16 KiB chunks, then end
0x30 / 0x31 / 0x32 / 0x7F
CLOSE / PING / PONG / ERROR
either
control
Capability bits: BML 1, CHDD 2, KEEPALIVE 4 (keep-alive is not implemented; one request per connection). Limits: payload 1 MiB, 64 headers, URL 1,024, header value 4,096, 30 s I/O timeout. The page store behind it is TachyonDB (PAGE_PUT / PAGE_GET, local port only). By contract (WEB4-CONTRACT.md, “Storage”), inline Blitz sends are capped at the crossbar slot payload, 16,348 bytes, while larger pages use references; no Blitz code uses crossbar slots today. The data object on the Blitz wire is CHDD. The blob starts with the u32 magic 0x43444844 (CHD_SER_MAGIC_CD, chd_serialize.h:20), written little-endian, so the first four bytes on the wire are 44 48 44 43; then version u32 = 1; then the 80-byte ChannelData body, 88 bytes in all (CHD_CD_WIRE_SIZE, chd_serialize.c:49). An object uses 0x4348444F (CHD_SER_MAGIC_OB). The comments in the source and WEB4-CONTRACT.md call the magic “CHDD”, but 0x43444844 does not spell that in either byte order; the name is a label, not the bytes. BML v2 pages start with ‘B’ ‘M’ ‘L’ 0x02 and are little-endian too.
Part 4
Take your pod with you, bind on demand
A solid pod is a person’s own store: identity, records, files and settings, owned by them and signed by their key. The Web 4 idea is that the pod does not live in a server. The pod is the thing, and a server or a device is somewhere it binds when it needs CPU and a network connection, and leaves when it does not.
Status. The pieces below are real; the whole journey is mostly a design (GALAXYGATE.md, “design lock” 2026-09-26). Each step is marked. Nothing in this section runs end to end today.
What makes a pod portable
Everything is a record, mostly fixed size, and most carry a version byte. Big-endian, one write per record, 64-bit node ids (records). A record can be copied to a drive, a phone or another server and still means the same thing.
Records are signed. Ed25519, compiled into the source (TweetNaCl-style), no external library. Each family has its own signing tag so a signature from one family can never pass as another’s: W4MESHv1 (mesh), W4NMv1 (Nimosini), W4PHv1 (phone).
Identity is a WebID, the standard Solid way. The pod’s node card lives in its Solid pod and is linked from the WebID profile (MESH-SPEC.md).
Threads are portable too. A PodThread is 256 bytes, signable with the pod key (Thread). Restoring one on the receiving side is a TODO. planned
Memory has a pod hook. The CLOUD allocator is marked TODO: remote pod-backed storage (MemoryChannel.c:275). planned
Data can carry a “belongs to the pod” tag. Three ChannelData flags are defined for this: HOME_BOUND (bit 19), TRANSPORT_HOME (20) and POD_AUTHORITATIVE (21) (defines.h:676-712). They are defined only; no behaviour is documented yet.
Bind on demand: the thumb-drive story
The design rule is one sentence: “The thumbdrive is the node. Host supplies CPU and network; drive supplies identity and data.” The drive holds a sealed pod package: WebID, sealed key store, friend (FOAF) list, phone number, a pointer to the DHT root, and a pod marker. It is not an operating-system image.
Plug in. The host sees a removable volume. Device’s USB channel is to be the sensor, and today it is still a stub. planned
Detect and bind. Container recognises the pod marker and binds: it opens the pod, loads the WebID and phone number, and starts a local front door (an Apache with the BML module, or a Solid endpoint) on a local address. planned
Open the door, if allowed. If GalaxyGate is on, the host is on DHCP and the owner allows it, UPnP may open ports 80 and 443. planned
Say where you are. The pod registers a signed record in the IP registry: “phone / WebID → current IP:port, with a time-to-live and the public key”. The signature is made with the pod’s Ed25519 key, so a random host cannot steal a number. planned
Unplug. The pod unregisters, or its record simply expires. planned
Many pods, one machine. Plug several drives into a USB hub and many pods bind on one compute brick, each keeping its own WebID, phone number and port. planned
Trust rules locked in the design
Binding or publishing is never silent on an unknown host such as a café PC. It needs local consent, an unlock PIN or key, and/or a host allow-list.
The first mount on a host needs a confirmed phone number and an unlock.
A stolen drive must not advertise itself without being unlocked.
The registry says where, never what. Content stays in the pod or the DHT, so the registry is not a chokepoint for content. Where the registry runs is an open question.
A call needs mutual enable: A may ring B only if B is on A’s list and B has enabled A. The phone number is the human dial id; the friend graph is FOAF; Solid WebID stays the identity on the wire.
Not Kubernetes ingress, and not GalaxyCore (a thin Docker / kubectl relay). Content is never published automatically from a sealed pod on an unknown host.
Phase sketch (design)
#
Phase
Status
1
Design document
done
2
ApacheChannel stub: open, start, stop, status, generate config with a sample BML location
planned
3
GalaxyGate flag: DHCP detection; call the existing UPnP helper only when the flag is on; no port mapping without consent
planned
4
IP registry v0: signed register, lookup and TTL; dialling uses the lookup
planned
5
Portable bind: volume marker, USB or volume watch, bind, register
planned
6
FOAF and mutual enable enforced on the call path; Solid WebID on the wire
planned
The flag name SP_FLAG_GALAXY_GATE is only proposed in the design note. It does not exist in defines.h. Pod cloud (a 4 KB resident file system per user) is likewise intent only.
The mesh: WebID, Ed25519 handshake, DHT
Pods find and trust each other without a central switchboard. The flow in mesh/MESH-SPEC.md (draft) is:
Discovery. B fetches A’s WebID profile. The profile links to the pod’s node card: node id, public key, mesh endpoint.
Challenge. A sends B a random one-time nonce with a short expiry.
Proof. B signs with Ed25519; A checks the signature against the key in B’s profile. HELLO and CHALLENGE are unsigned, so nothing is trusted until the PROOF verifies.
Admission. A adds B to its peer table with “WebID-verified” and “key-pinned” set; state goes handshake → online. B joins the DHT.
Ongoing. Every message is signed. A key rotation must be signed by the old key.
The endpoint is /cgi-bin/mesh.cgi, and the message types are HELLO 1, CHALLENGE 2, PROOF 3, ACCEPT 4, PEERS 5, LEAVE 6. Safety rules: rate limits per address and per WebID, a banned state, never fetch private or loopback addresses when resolving a WebID, constant-time comparisons, no secrets in logs. The records are specified in meshrec.h and tested in C (node-records/test_*); a live mesh endpoint is not shown in the sources. records built · endpoint planned
What is signed. The signature is Ed25519 over the 8-byte tag W4MESHv1 followed by every byte of the message before the signature; the signature is always the last 64 bytes. The verifier rejects non-canonical S values and zero, identity or small-order keys (meshsig.h).
The DHT (planned)
Pod content is meant to be found by key through a Kademlia-style table with 64-bit routing keys and XOR distance: 64 buckets × 16 entries × 16 bytes = 16,384 bytes of routing table. Message types: PING 0x10 … STORED 0x18, and a HEAD record 0x40 of 174 bytes (dhtrec.h, draft 1; design in dht-fs/DESIGN.md). There is no live DHT. planned
One Nimosini per pod
The AI controller (channel 15) travels with the pod and is exactly one per pod. Every pod announces a presence record, even a dormant one (NM_PRESENCE, AI records), so peers see a single “Nimosini @ node” per pod. A pod advertises the AI capability bit (CAP_AI = 8) only while a valid, granted AI configuration exists; otherwise the bit is stripped before the hello or node card is built (airec.h:125-138). Peers may serve each other language-model requests only when the owner has switched that scope on.
Part 5
Solid pod structure: bits, sizes, capabilities
The pod has three layers, and this part of the manual covers all three. Read them from the inside out:
The pod struct (struct SolidPod): a lean index of identity, settings and pointers. Big data stays as files in the encrypted pod archive (SOLID-POD-INTENT.md).
Flag words: 64-bit words that switch features on and off, and pack small settings. Two sets exist in the sources: set A (defines.h, canonical) and set B (solid_pod.h, being conformed to A); both are shown.
Wire records: big-endian, mostly fixed-size records that travel between pods. These are the pod’s public language.
Two flag sets.Set A is channels7/defines.h: SP_FLAG_* (64 bits) and SP_FLAG2_* (packed fields plus flag bits). Set A is canonical. Set B is the older pod header solid_pod.h v6.1 with SP_FEATURE_*, SP_USER_*, SP_SOCIAL_* and SP_STORE_*; it is being conformed to set A (a pending change, not done yet). The two sets describe the same fields with different names and bit numbers, and both headers define the five names SP_MAX_BLOG_POSTS, SP_GET_THEME, SP_SET_THEME, SP_GET_INTEREST_COUNT and SP_SET_INTEREST_COUNT with different definitions. This page prints both exactly as written and labels the file.
The SolidPod struct (v6.1)
From solid/solid_pod.h (660 lines): magic SP_POD_MAGIC0x504F4453, version SP_POD_VERSION0x00060001, config version SP_CONFIG_VERSION 2. In the pod file the first fields are the header, then identity, profile, bit words, times, quotas, home page and the collections. The offsets below were computed by compiling a small C program against that header with 64-bit gcc; the total is 78,416 bytes. Fields after sp_video_url contain pointers or nested structs whose sizes depend on the 64-bit build.
Note: the header comment says “HEADER – 16 bytes” but its fields (magic, version, size, checksum, config version) occupy 24 bytes. Offsets here follow the fields.
Struct fields with offsets and sizes (53 fields)
Offset
Size
Field
Group
Meaning
0
4
sp_magic
header
magic number
4
4
sp_version
header
pod format version
8
8
sp_size
header
total size
16
4
sp_checksum
header
checksum
20
4
sp_config_version
header
config version
24
32
sp_username
identity
user name
56
64
sp_email
identity
email
120
128
sp_webid
identity
WebID URL
248
32
sp_pod_id
identity
pod id
280
64
sp_display_name
profile
display name
344
512
sp_bio
profile
bio text
856
64
sp_location
profile
location text
920
32
sp_avatar_hash
profile
avatar hash
952
512
sp_pod_url
pod
pod URL
1464
8
sp_flags
bit words
feature bits (set B: SP_FEATURE_*; set A: SP_FLAG_* and SP_FLAG2_*)
1472
8
sp_user_flags
bit words
user bits (set B: SP_USER_*; set A: SP_FLAG_* in sp_flags)
1480
8
sp_social_flags
bit words
social link bits (set B: SP_SOCIAL_*; set A: SP_FLAG_SHOW_* for 8 of the 12)
1488
8
sp_storage_flags
bit words
storage mode bits (SP_STORE_*)
1496
8
sp_ui_prefs
bit words
packed UI preferences
1504
8
sp_interests
bit words
packed interests and position
1512
8
sp_crc64
bit words
CRC-64
1520
8
sp_session_bits
bit words
session bits
1528
4
sp_created_at
time
created
1532
4
sp_last_modified
time
last modified
1536
4
sp_last_login
time
last login
1540
4
sp_last_backup
time
last backup
1544
4
sp_session_expiry
session
session expiry
1548
4
sp_session_id
session
session id
1552
4
sp_session_timeout
session
session timeout
1556
4
sp_session_last_act
session
last activity
1560
4
sp_storage_quota_mb
quota
storage quota MB
1564
4
sp_storage_used_mb
quota
storage used MB
1568
4
sp_bandwidth_quota_mb
quota
bandwidth quota MB
1572
4
sp_bandwidth_used_mb
quota
bandwidth used MB
1576
64
sp_cloud_key
storage
cloud key
1640
256
sp_local_path
storage
local path
1896
128
sp_home_title
home page
home title
2024
8192
sp_home_content
home page
home content
10216
512
sp_video_url
home page
video URL
10728
47304
sp_wallet
collections
wallet block
58032
128
sp_calendar
collections
calendar index
58160
48
sp_notes
collections
notes index
58208
48
sp_bookmarks
collections
bookmarks index
58256
48
sp_tasks
collections
tasks index
58304
48
sp_contacts
collections
contacts index
58352
56
sp_messages
collections
messages index
58408
1480
sp_blog
collections
blog index
59888
424
sp_podfs
collections
pod file-system index
60312
480
sp_dht
mesh
DHT block
60792
12616
sp_ai
mesh
AI block
73408
776
sp_nexus
mesh
Nexus 8-layer pyramid
74184
3976
sp_social
social
social links
78160
256
sp_reserved
tail
reserved
Collection limits (SP_MAX_*)
Collection
Maximum
Blog posts
512
Notes
2,048
Messages
2,048
Tasks
2,048
Contacts
1,024
Bookmarks
4,096
Events, groups, pages, podcasts, badges
256 each
Wiki, news, goals, achievements
512 each
Reviews
1,024
Leaderboards, tournaments
128 each
Source: solid_pod.h (collection limits block). Only the blog-posts limit exists in both headers: 512 here in set B, 256 in set A (defines.h:352); the conform will take 256. The other limits in defines.h:349-353 exist only in set A and have no counterpart here: social links 32, cron jobs 16, webhooks 8, named flags 64.
Flag words and bit defines
Set A (canonical) · channels7/defines.h: SP_FLAG_ and SP_FLAG2_
Set A is the canonical flag set. These two tables list the defines.h names and bit numbers exactly as written (checked row by row against defines.h:157-276).
sp_flags · SP_FLAG_* (all 64 bits)
Several names overlap in meaning (for example UPNP_ENABLED 19 and ENABLE_UPNP 39; FEDERATION_ENABLED 17 and ENABLE_FEDERATION 41). They are printed as written. defines.h:157-220.
Bit
Name
Mask
Source
0
SP_FLAG_EMAIL_CONFIRMED
0x0000000000000001
defines.h:157
1
SP_FLAG_PHONE_CONFIRMED
0x0000000000000002
defines.h:158
2
SP_FLAG_MEMBER
0x0000000000000004
defines.h:159
3
SP_FLAG_DEVELOPER
0x0000000000000008
defines.h:160
4
SP_FLAG_ADMIN
0x0000000000000010
defines.h:161
5
SP_FLAG_ANIMATIONS
0x0000000000000020
defines.h:162
6
SP_FLAG_COMPACT_MODE
0x0000000000000040
defines.h:163
7
SP_FLAG_TWO_FACTOR_ENABLED
0x0000000000000080
defines.h:164
8
SP_FLAG_CLOUD_BACKUP_ENABLED
0x0000000000000100
defines.h:165
9
SP_FLAG_ENCRYPTION_ENABLED
0x0000000000000200
defines.h:166
10
SP_FLAG_STREAMING_ENABLED
0x0000000000000400
defines.h:167
11
SP_FLAG_RECORDING_ENABLED
0x0000000000000800
defines.h:168
12
SP_FLAG_VIDEO_AUTO_ANSWER
0x0000000000001000
defines.h:169
13
SP_FLAG_PAINT_AUTO_BACKUP
0x0000000000002000
defines.h:170
14
SP_FLAG_AI_MODEL_ENABLED
0x0000000000004000
defines.h:171
15
SP_FLAG_AI_SHARE_USAGE
0x0000000000008000
defines.h:172
16
SP_FLAG_RECOVERY_ENABLED
0x0000000000010000
defines.h:173
17
SP_FLAG_FEDERATION_ENABLED
0x0000000000020000
defines.h:174
18
SP_FLAG_MESH_DISCOVERY_ENABLED
0x0000000000040000
defines.h:175
19
SP_FLAG_UPNP_ENABLED
0x0000000000080000
defines.h:176
20
SP_FLAG_UPNP_AUTO_REGISTER
0x0000000000100000
defines.h:177
21
SP_FLAG_WEB4_ENABLED
0x0000000000200000
defines.h:178
22
SP_FLAG_LOGGING_ENABLED
0x0000000000400000
defines.h:179
23
SP_FLAG_METRICS_ENABLED
0x0000000000800000
defines.h:180
24
SP_FLAG_METRICS_SHARE_NETWORK
0x0000000001000000
defines.h:181
25
SP_FLAG_DEVELOPER_MODE
0x0000000002000000
defines.h:182
26
SP_FLAG_TERMINAL_ENABLED
0x0000000004000000
defines.h:183
27
SP_FLAG_API_ENABLED
0x0000000008000000
defines.h:184
28
SP_FLAG_MEDIA_AUTOPLAY
0x0000000010000000
defines.h:185
29
SP_FLAG_USE_EMBEDDED_HTML
0x0000000020000000
defines.h:186
30
SP_FLAG_USE_BACKGROUND_IMAGE
0x0000000040000000
defines.h:187
31
SP_FLAG_USE_BANNER
0x0000000080000000
defines.h:188
32
SP_FLAG_USE_FAVICON
0x0000000100000000
defines.h:189
33
SP_FLAG_USE_LOGO
0x0000000200000000
defines.h:190
34
SP_FLAG_ENABLE_VIDEO_NETWORK
0x0000000400000000
defines.h:191
35
SP_FLAG_ENABLE_DHT
0x0000000800000000
defines.h:192
36
SP_FLAG_ENABLE_WEBSOCKET
0x0000001000000000
defines.h:193
37
SP_FLAG_ENABLE_WEB4
0x0000002000000000
defines.h:194
38
SP_FLAG_ENABLE_PARALLEL_JOBS
0x0000004000000000
defines.h:195
39
SP_FLAG_ENABLE_UPNP
0x0000008000000000
defines.h:196
40
SP_FLAG_ENABLE_CLOUDRAM
0x0000010000000000
defines.h:197
41
SP_FLAG_ENABLE_FEDERATION
0x0000020000000000
defines.h:198
42
SP_FLAG_SHOW_FACEBOOK
0x0000040000000000
defines.h:199
43
SP_FLAG_SHOW_TIKTOK
0x0000080000000000
defines.h:200
44
SP_FLAG_SHOW_INSTAGRAM
0x0000100000000000
defines.h:201
45
SP_FLAG_SHOW_YOUTUBE
0x0000200000000000
defines.h:202
46
SP_FLAG_SHOW_MASTODON
0x0000400000000000
defines.h:203
47
SP_FLAG_SHOW_BLUESKY
0x0000800000000000
defines.h:204
48
SP_FLAG_SHOW_TWITTER
0x0001000000000000
defines.h:205
49
SP_FLAG_SHOW_TELEGRAM
0x0002000000000000
defines.h:206
50
SP_FLAG_BLOG_ENABLED
0x0004000000000000
defines.h:207
51
SP_FLAG_BLOG_COMMENTS_ENABLED
0x0008000000000000
defines.h:208
52
SP_FLAG_BLOG_MODERATION_ENABLED
0x0010000000000000
defines.h:209
53
SP_FLAG_BLOG_RSS_ENABLED
0x0020000000000000
defines.h:210
54
SP_FLAG_BML_ENABLE_EDITOR
0x0040000000000000
defines.h:211
55
SP_FLAG_BML_ENABLE_PREVIEW
0x0080000000000000
defines.h:212
56
SP_FLAG_BML_ENABLE_DEBUG
0x0100000000000000
defines.h:213
57
SP_FLAG_BQL_ENABLE_CACHE
0x0200000000000000
defines.h:214
58
SP_FLAG_BQL_ENABLE_INDEXING
0x0400000000000000
defines.h:215
59
SP_FLAG_BQL_ENABLE_LOGGING
0x0800000000000000
defines.h:216
60
SP_FLAG_PHONE_ENABLED
0x1000000000000000
defines.h:217
61
SP_FLAG_VIDEO_WAN_ENABLED
0x2000000000000000
defines.h:218
62
SP_FLAG_SFU_ENABLED
0x4000000000000000
defines.h:219
63
SP_FLAG_FLAGS_INITIALIZED
0x8000000000000000
defines.h:220
sp_flags2 · packed fields (bits 0–29)
defines.h:226-247; accessors SP_GET_* / SP_SET_* at :279-337.
Field
Shift
Mask
Bits
interest_count
0
0x3F
6
nexus_level
6
0x07
3
theme (LIGHT 0, DARK 1, AUTO 2)
9
0x03
2
log_level (OFF 0 … DEBUG 4; DEBUG does not fit the 2-bit field, so setting it stores 0)
Set B (being conformed to set A) · solid_pod.h v6.1: feature, user, social, storage bits
Set B is the older pod-header naming. It is being conformed to set A (a pending change, not done yet): names that exist in both sets will take the defines.h name and bit number, and the rest stay pod-only. Until that lands, these tables print the header as it stands, so the bit numbers below do not match set A.
Each is a 64-bit word in the struct (sp_flags, sp_user_flags, sp_social_flags, sp_storage_flags). The mask is 1<<bit.
Source: solid_pod.h, UI-prefs and interest packing macros.
Sticky pod words (PodStickyStore, 128 named bits)
Separate from the struct, each pod keeps two 64-bit sticky words = 128 bits that the owner can name and toggle from the web (pod_sticky.h, found in publish-vaultmagic/src, not in channels6-review/solid). The store has the magic 0x4B545350 (“PSTK” little-endian), version 1, the two words, a colour mode (blue 0 / green 1), an external-BQL switch and URL (256 bytes), a 32-byte name per bit and a 96-byte handler per bit. Neighbouring named bits form one multi-bit field. It is kept at /pod/<user>/sticky in TachyonMem, with a Redis mirror for the web side. The names and the blue / green grouping are still to be settled. planned
Wire records: the pod’s public language
Every record below is big-endian and written in one write; most are fixed size (a few carry a count byte, and PROFILE and the pod image entry have a length), and all use 64-bit node ids (id 0 is invalid). The mesh, AI, phone and DHT records start with a two-byte header: ver u8 (=1) then type u8; the node, edge, peer, workload, replica, avatar, news and theme records have no such header. Reserved bits must be 0, and readers reject any record with a reserved bit set, so a bit can only be given a meaning by raising the version. The local TacyonMem copy uses native byte order with the same bit layout (NODE-RECORD.md). In a browser, 64-bit ids need BigInt or hex strings (RECORDS-FOR-UI.md).
Size codes: value = ((8 + mantissa) << exponent) >> 3, where the code byte is exponent<<3 | mantissa (noderec.h, size_enc / size_dec). RAM is in KiB, storage in MiB.
Byte 9: high nibble = hops, low nibble = load in sixteenths. A peers body is ver 1 | count N | N × 16. The WebID side table is keyed by FNV-1a 64 of the WebID bytes, with the full WebID compared on lookup (peerrec.h:15).
Mesh messages
Type
Message
Bytes
Layout
Signed
1
HELLO
32
hdr 2 · from u64 @2 · to u64 @10 (0 = any) · WebID hash u64 @18 · time u32 @26 · caps u16 @30
no
2
CHALLENGE
54
hdr · from A · to B · nonce[32] · expires u32
no
3
PROOF
114
hdr · from B · to A · nonce[32] · sig[64]
Ed25519
4
ACCEPT
99
hdr · from A · to B · status u8 · peer[16] (A’s view of B) · sig[64]; on refusal peer and sig are zero
Ed25519
5
PEERS
75 + 16N
hdr · from u64 · count u8 (0–16) · N × peer[16] · sig[64]
Ed25519
6
LEAVE
87
hdr · from · to · reason u8 · time u32 · sig[64]
Ed25519
—
NODE CARD
122
ver @0 · flags @1 (b0 accepts mesh, b1 relay ok, b2 IPv6, b3–7 = 0) · node u64 @2 · WebID hash u64 @10 · public key[32] @18 · key time u32 @50 · port u16 @54 (0 = web port) · caps u16 @56 · sig[64] @58 over tag + bytes 0..57
self-signed
Accept status: OK, RATE, BADPROOF, EXPIRED, BANNED, UNKNOWN, BADMSG (0–6). Leave reasons: NORMAL, SHUTDOWN, REKEY, MOVED (0–3). The node card is published in the pod and linked from the WebID profile; a key rotation is a new card also signed by the old key (MESH-SPEC.md; meshrec.h:1-27). Signing tag for every mesh message: W4MESHv1.
Capability bits
The 16-bit caps field of HELLO (offset 30) and of the node card (offset 56) (meshrec.h:27).
Bit
Name
Value
Meaning
0
CAP_IPV6
1
Node is reachable over IPv6
1
CAP_RELAY
2
Node will relay for others
2
CAP_DHT
4
Node takes part in the DHT
3
CAP_AI
8
The pod has a granted Nimosini (set only while a valid AI configuration with a grant time exists)
4–15
reserved
0
Readers reject any record with these set
—
CAP_ALL
15
Mask of all defined bits (was 7 before CAP_AI). An older peer that still has CAP_ALL = 7 rejects bit 3 until it is updated.
meshrec.h:46, 85 (hello_get and card_get reject bits 4–15); airec.h:125-138 (ai_hello_caps).
AI records (Nimosini) staged
Defined in airec.h with passing C tests; staged, not live. Signing tag W4NMv1 (6 bytes), different from the mesh tag at byte 2, so one family’s signature can never pass as the other’s. Every Nimosini (NM_*) message carries to inside the signed bytes, and a reader rejects to ≠ its own node id, so a captured message cannot be replayed to another pod.
Record
Type
Bytes
Layout (offsets)
AICFG (local, unsigned, written once by owner setup, never on the mesh)
Presence state: 0 dormant, 1 starting, 2 running, 3 degraded, 4 paused, 5 breaker, 6 leaving (sent once on a clean shutdown; the receiver treats the sender as gone at once instead of waiting for the record to go stale); 7 is rejected (airec.h:75-76, airec.h:200). Backend: 0 none, 1 CPU, 2 GPU. Receivers keep a seen-ring of 1,024 entries × 24 bytes (up to 128 per sender, 300 s windows) so a repeated request is refused; the deadline window is at most 300 s; a grant time may be at most 300 s in the future (AI_GRANT_SKEW_S, airec.h:36). A receiver verifies the signature before changing any state and admits only known peers (airec.h:236-250). A server may first run the read-only nm_lm_precheck_sender to drop a sender that already holds its 128 live entries without paying for the Ed25519 verify (airec.h:309-315).
AICFG grant mask (grant_mask, 15 bits, GS_ALL = 0x7FFF)
Bit
Scope
Pre-ticked at setup (0x0205)
Irreversible?
0
LOCAL_TUNE
ticked
no
1
CAMERA_USE
off
no
2
CALL_BASIC
ticked
no
3
CALL_VIDEO_DIAL
off
yes
4
MAIL_SEND
off
yes
5
NEWS_PUBLISH
off
yes
6
PEER_ADMIT
off
yes
7
WORKLOAD
off
no
8
DATA_DELETE
off
yes
9
LM_POD
ticked
no
10
LM_PEER_USE
off
no
11
LM_PEER_SERVE
off
no
12
AUDIO_IN
off
no
13
SPEECH
off
no
14
TRANSLATE
off
no
15
reserved
must be 0
—
Bits and names: airec.h:65-69 (bit 15 must be 0, comment at line 65). Pre-ticked default NM_GRANT_DEFAULT = 0x0205: airec.h:70-71. The “irreversible” column follows the spec’s list of mail, publish, dial, delete and peer admit.
Pre-ticked defaults. At setup only three scopes are pre-ticked: local tuning (bit 0), basic call handling (bit 2: decline) and the pod’s own language model (bit 9), which is 0x0205 (airec.h:70-71). Everything else is opt-in. An earlier draft pre-ticked camera, audio and peer scopes (0x1E87); that value is gone from the header. In every version, nothing is granted until the owner completes setup: grant_time = 0 means dormant, and the irreversible scopes (mail, publish, video dial, delete, admit) are off.
LM order values: 0 pod, 1 peer, 2 pod then peer, 3 peer then pod. Both b7 and b6 default to 0. Bit 6 is named “frames off pod” and means that when it is set, camera frames are allowed to leave the pod; unset, they never do (airec.h:72-73; the later draft renames it FRAMES_MAY_LEAVE).
Resource limits: RAM 256–8,192 MiB (default 1,024); disk 2,048–65,536 MiB (default 8,192); RAM at most 50 % of physical, disk at most 25 % of free; a pod language model needs at least 2,048 MiB (airec.h:38-63).
Phone, pod files, ChannelData and the roadmap
Phone records staged
phonerec.h (v1) defines a video-phone built on the pod. Staged, not live. A pod has one pod number: 12 decimal digits, the first 1–9, the last a Luhn check digit, stored in 5 bytes and shown as 4444-4444-4444. Phone messages are signed with the pod server’s key; devices never sign. Signing tag W4PHv1. As with the AI records, to is inside the signed bytes and a reader rejects any message whose to is not the local node. A message older than 300 s (PH_FRESH_S) is stale; a seen-cache holds 128 call ids for 600 s.
Call reasons: 0 none, 1 do-not-disturb, 2 no such number, 3 friends only, 4 blocked, 5 no video, 6 offline, 7 error, 8 not allowed, 9 answered elsewhere, 10 media failed. Participant state byte: b0 audio muted · b1 video off · b2 hand raised · b3 screen sharing · b4 host · b5 moderator · b6 spectator · b7 force-muted. A conference holds at most 24 people (CONF_MAXP).
How a call works. A call rings every ringable device the callee has. The first to answer wins; the others get a CANCEL with reason 9, “answered elsewhere”. The call state machine is DIALING, RINGING, CONNECTED, ENDED. The page never signs anything; the server does. A caller who is blocked is shown “no answer” (RECORDS-FOR-UI.md). The sound and picture travel through Media, encrypted with DTLS-SRTP; Nimosini may decline within its grant but never touches call media.
At most 1,024 px a side. Nothing is ever generated: all zero means no picture and the page shows initials.
POD IMAGE ENTRY
20 + name + data
header 20: ver @0 · kind @1 (1 = PNG) · flags @2 (b0 re-encoded by server, b1 brand sign, b2 public-readable) · name length @3 (1–32) · data length u32 @4 · CRC-32 @8 · width @12 · height @14 · modified u32 @16; then name, then PNG bytes
Name: 1–32 characters from a-z 0-9 _ -, first character a-z or 0-9 (lowercase only), so a name cannot escape the pod. Proposed limits: 1 MiB and 4,096 px.
NEWS
13
subscribed mask u64 @0 (bit n = newspaper n, 0–63) · last seen u32 @8 · flags @12 (b0 member has chosen, b1 mail digest)
All zero = never chosen; the site default applies.
ChannelData is the 80-byte typed header that wraps any value that moves between channels. It carries a 64-bit flag word (defines.h:676-712). Types: 32 values = 8 base types (byte, short, char, int, long, float, double, object) × 4 shapes (single, array, 2-D, 3-D) (defines.h:410-452). Content classes (:718-727): DATA 0, CONTROL 1, SIGNAL 2, STREAM_FRAG 3, FRAG_END 4, HEARTBEAT 5, ERROR 6, RETRY 7, OBJECT 8, REGISTRY 9. The flags marked pod are the hooks for “your data lives in your pod”.
All 33 flag bits
Bit
Name
Mask
Source
0
CD_FLAG_OWNED
0x0000000000000001
defines.h:676
1
CD_FLAG_READONLY
0x0000000000000002
defines.h:677
2
CD_FLAG_DESTROY_ON_CONSUME
0x0000000000000004
defines.h:678
3
CD_FLAG_CACHED
0x0000000000000008
defines.h:679
4
CD_FLAG_PINNED
0x0000000000000010
defines.h:680
5
CD_FLAG_ENCRYPTED
0x0000000000000020
defines.h:681
6
CD_FLAG_INLINE
0x0000000000000040
defines.h:683
7
CD_FLAG_EXTERNAL
0x0000000000000080
defines.h:684
8
CD_FLAG_COMPRESSED
0x0000000000000100
defines.h:685
9
CD_FLAG_SPARSE
0x0000000000000200
defines.h:686
10
CD_FLAG_SIGNED
0x0000000000000400
defines.h:687
11
CD_FLAG_PACKED
0x0000000000000800
defines.h:688
12
CD_FLAG_REMOTE
0x0000000000001000
defines.h:690
13
CD_FLAG_FETCHED
0x0000000000002000
defines.h:691
14
CD_FLAG_FETCH_PENDING
0x0000000000004000
defines.h:692
15
CD_FLAG_DOWNLOAD
0x0000000000008000
defines.h:693
16
CD_FLAG_UPLOAD
0x0000000000010000
defines.h:694
17
CD_FLAG_SYNC_REQUIRED
0x0000000000020000
defines.h:695
18
CD_FLAG_SMART_BUFFER
0x0000000000040000
defines.h:697
19
CD_FLAG_HOME_BOUND
0x0000000000080000
defines.h:698
20
CD_FLAG_TRANSPORT_HOME
0x0000000000100000
defines.h:699
21
CD_FLAG_POD_AUTHORITATIVE
0x0000000000200000
defines.h:700
22
CD_FLAG_FEDERATED
0x0000000000400000
defines.h:701
23
CD_FLAG_DHT_PINNED
0x0000000000800000
defines.h:702
24
CD_FLAG_EPHEMERAL
0x0000000001000000
defines.h:704
25
CD_FLAG_MONETIZED
0x0000000002000000
defines.h:705
26
CD_FLAG_AI_LABELED
0x0000000004000000
defines.h:706
27
CD_FLAG_MODERATION_PENDING
0x0000000008000000
defines.h:707
28
CD_FLAG_SENSITIVE
0x0000000010000000
defines.h:708
29
CD_FLAG_STREAM
0x0000000020000000
defines.h:709
30
CD_FLAG_GAME_WINDOW
0x0000000040000000
defines.h:710
31
CD_FLAG_OBJECT
0x0000000080000000
defines.h:711
32
CD_FLAG_REGISTRY
0x0000000100000000
defines.h:712
Pod flags: HOME_BOUND 19, TRANSPORT_HOME 20, POD_AUTHORITATIVE 21. Also relevant to ownership: ENCRYPTED 5, SIGNED 10, FEDERATED 22, DHT_PINNED 23, SENSITIVE 28, AI_LABELED 26. Defined only; the sources do not describe their run-time behaviour.
Future plans
Everything on this list is planned. Each item says where the source marks it as not done.
Area
Plan
Where the source says so
Dispatch
Handlers for the other 511 cells of the dispatch table
NetXecChannel.c:701-756
Join policy
A real join_policy[16][16] table inside ChannelJoin, shown on the config board
docs/channel-joins.md
Crossbar
Per-pair lock, range checks, sender-identity check on wake; 64-bit wake-bit macros for senders 8–15 (defines.h:41-44)
proposed patch, not applied
Server
A real listening socket on its own thread
ServerChannel.h:4, 6-9
Device
libusb and serial I/O; camera and microphone into Memory rings; pod-drive detection
stubs; GALAXYGATE.md
Memory
Pod-backed CLOUD memory and a GPU buffer path
MemoryChannel.c:262, 275
Thread
Restore a signed pod thread (PodThreadToLocal); wire the arbitration queue
ThreadChannel.c:359-366
Process0
DEFLATE compression
CompressionChannel.c:2, 217
Process1
SQLite driver, GPS and modem parsers
SQLChannel.h; stubs
Media
Real audio device, video decode and player
stubs
Compiler, Debug
Code generation; a Debug channel
stub; no source
Nimosini
Phases M1–M6 from an observe-only skeleton to real nets, language-model use and peer serving; nothing goes live without a backup and the owner’s go-ahead
NIMOSINI-CHANNEL-SPEC.md §13
Nexus pyramid
Eight-layer resource sharing; the 60 / 40 RAM-disk share formula is a proposal
Export .chd objects as a Java class, JavaScript object, JSON, TypeScript and Python (.py)
channels6-review/channel_data.h:21-26
Part 6
Privacy and ownership: your data, your choice
Web 4 is solid. The pod is yours, the keys are yours, and every switch that matters is a switch you flip. This is how the design above turns that sentence into rules. Each rule points at the place in the sources where it is written.
Rule
What it means
Where
Consent starts off
A pod with no grant is dormant: grant_time = 0 means “not granted”. Nimosini then announces its presence and does nothing else. The irreversible scopes — send mail, publish news, start video calls, delete data, admit peers — are off in every draft.
airec.h:65-71; spec §5, §9
People-recognition is off by default
Policy bit POL_PEOPLE_ID (b7) is 0. Names and identities stay in the pod’s own Memory and never go on the wire.
airec.h:72-73; spec §5
Frames stay in the pod
Policy bit POL_FRAMES_OFF_POD (b6) is 0, which means raw camera frames never leave the pod. Embeddings stay in Memory too.
airec.h:72-73
One grant, scoped, revocable
The owner grants specific scopes once, on a setup screen, and can pause or stop Nimosini at any time. The System channel’s stop and pause always win.
spec §2, §5
The AI never holds the key
The pod’s server signs; Nimosini cannot sign anything else, impersonate the pod, change grants, touch keys or weights, or use the compiler or URL channels.
spec §5, §8
Outside words are not commands
Text or audio the owner did not provide is tainted and can never trigger an outward action.
spec §5
Indicators stay visible
Camera and microphone indicators are always on screen while in use.
spec §5
Records are signed and addressed
Each Nimosini (NM_*) and phone message names its receiver inside the signed bytes, so a captured message cannot be replayed to another pod. Receivers verify the signature before changing any state and admit only known peers.
airec.h:15-17, 236-250
Nothing is generated for you
If you have no avatar, the page shows initials. A picture is never invented. Nimosini may not generate avatars (tier 3).
avatarrec.h:1-14
Visibility is yours to set
Profile visibility (public, friends, private), online status (hide or show) and last-seen visibility are fields in your own flag word.
defines.h:226-247
Calls need mutual consent
You can ring someone only if they are on your list and have enabled you. A blocked caller sees “no answer”. Do-not-disturb, friends-only and listed-in-directory are your own phone flags.
GALAXYGATE.md; phonerec.h
Binding is never silent
A portable pod asks for your consent, an unlock key and/or a trusted host before it binds or advertises itself. A stolen drive stays quiet.
GALAXYGATE.md (design)
Your resources are yours
You choose how much RAM and disk the AI may use, and the system caps it at half of physical RAM and a quarter of free disk.
airec.h:38-63
Analytics on this page
This manual’s text, style and script come from this site. The only outside party is Google: the page loads gtag.js and sends page-view data to Google Analytics, which may set cookies (see the privacy page). The page has no ads and loads nothing else from any other site.
this page
Only a few of these are running code today. The record formats, the policy bits and the grant checks are built and tested in C; the Nimosini channel and the portable-pod bind are designs. Privacy statements about Nimosini describe the design, not a deployed service.
The project’s name for a web built on solid pods: the owner holds the data and the keys, and servers are places a pod visits.
Solid pod
A person’s own data store: identity, profile, records, files and settings. Described in part 5. “Solid” also names the open standard for WebIDs and pods that the wire format follows.
WebID
A web address that names a person or pod and links to a profile document with its public key and node card.
FOAF
“Friend of a friend”: the friend graph. A call needs both sides to have enabled each other.
Channel
A small program with one job, a numbered place in the table, its own lock and run-state record.
Core channel
One of the sixteen channels with ids 0–15: System (NetXecChannel, Channel 0), Device, Memory, Thread, Signal, Media, Clock, Container, URL, Server, Process0, Process1, STDIO, Compiler, Debug, Nimosini.
Sub-channel
One of sixteen named cells under a core. The flat id is core × 16 + sub, 0–255.
Sidecar
A channel that is not itself one of the sixteen cores: it has an id of 100 or more, or is a code file homed on a core’s id (Image, Font, Video, CLI, BQL, GPU). A core’s own channel object (Container, URL, Media, Server, STDIO) is not called a sidecar here. Has no crossbar slot.
NetXecChannel
The System, core Channel 0, one of the sixteen cores. As the conductor it creates the cores (itself included), owns the crossbar (the Blitter Bus) and dispatch table, and runs the main loop.
Crossbar
See GPUChannel, the Blitter Bus (crossbar). A block of 512 slots (16 KiB each, 8 MiB in all), addressed [channel][peer][direction], that is meant by design to carry data between cores. Today NetXecChannel allocates it and only System←Signal writes to it.
Slot
One 16 KiB cell of the crossbar: a 36-byte header and 16,348 bytes of data.
Dispatch table
512 handlers indexed by source, target and direction.
Join
A symmetric link between two channels, held in each one’s listener table (16 slots).
HyperLock
A mutex plus condition variable, one per channel, that its thread sleeps on.
Event ring
The 64 KiB single-producer ring of 8-byte OS-event codes in the EventChannel.
Cont
The sources’ shorthand for the Container layer and its API and coding style (“Cont style”: no typedef, no enum, no union).
HyperView
The Java UI framework whose structure Container mirrors (gobs, gadgets, panes). The view is 640×480.
Blit
Copying finished pixels to the screen. Container tracks dirty rectangles or forces a full blit.
Blitz
The binary protocol on TCP 23232 that carries BML pages (little-endian).
BML
The binary page format. A v2 stream begins with the bytes B, M, L, 0x02.
BQL
The query side of page storage. BQLChannel holds a query string and the connection settings for TachyonDB.
TachyonDB / TacyonMem
The page store (PAGE_GET / PAGE_PUT, local port) and its in-memory copy of pod records (native byte order).
Code Share / CodeVault / PCL
Code hosting. CodeChannel is its front; PCL is its control language of one-byte opcodes.
ChannelData / CHDD / .chd
The 80-byte typed header for moving data; its 88-byte wire form starts with the u32 0x43444844 (bytes 44 48 44 43 on the wire; see Blit path and Blitz); saved objects are NAME.chd.
Node id
A 64-bit number naming a pod or device on the mesh. 0 is invalid.
Node card
The 122-byte self-signed record that tells peers a node’s id, key, port and capabilities.
Ed25519
The signature scheme used for every signed record. The code is compiled in (TweetNaCl-style); no library is needed.
Signing tag
A fixed prefix signed with the message so one record family cannot pass as another: W4MESHv1, W4NMv1, W4PHv1.
DHT
Distributed hash table; a Kademlia-style table of 64-bit keys for finding pod content. Planned.
GalaxyGate
The planned reachability mode: optional UPnP port mapping on a DHCP host and a signed IP-registry entry. Not Kubernetes ingress.
GalaxyCore
A thin Docker / kubectl relay. Different from GalaxyGate.
IP registry
A planned signed “number or WebID → where to reach it” directory with a time-to-live.
Pod number
The 12-digit phone number of a pod, last digit a Luhn check.
Nimosini
The planned AI controller, channel 15; one per pod.
Net
One of eight independent neural-network slots (neural0–7) in the Nimosini design.
Grant, scope, tier, taint
The owner’s one-time permission (grant) is split into scopes; actions have tiers 0–3; input the owner did not provide is tainted and capped at tier 1.
AICFG
The 26-byte local record that holds the owner’s grant, resource limits and policy byte.
Nexus
The eight-layer resource-sharing pyramid held in the pod struct. Not built.
Big-endian
Most-significant byte first. The byte order of every pod record. Blitz and BML are little-endian.
Where the sources disagree or are silent, this manual says so rather than guessing:
Two flag sets. Set A, SP_FLAG_* / SP_FLAG2_* (channels7 defines.h), is canonical. Set B, SP_FEATURE_* (pod header solid_pod.h v6.1), describes the same pod differently and is being conformed to A (pending, not done yet); both are printed in part 5.
The join chart is a draft. It is not enforced in the binary. It denies Nimosini↔Server, Nimosini↔Clock and Nimosini↔Debug (as well as Device, Media, URL and Compiler), while the Nimosini design relies on Server to hold the key and sign, on Clock for the tick and on Debug for counters; the chart and the design need reconciling.
Home core vs name table. GPS and GPRS are homed on Device in code but named under Process1; BML is homed on Process0 but named under Server and Process1; Java is homed on Process0 but named under Compiler.
Nimosini sub-channel names. The master table says grok / bert / chatgpt / neuralnet at 248–251. The staged prototype uses other names for 248–250 (aichannel, speech, translate). No code in the running system uses either.
Record sizes. An older Nimosini draft lists AICFG 32, NM_PRESENCE 81, NM_AICFG 86 and NM_LM 1,088 bytes. The record headers, which this page follows, say 26, 89, 94 and 1,096.
Handshake signing. The mesh note mentions libsodium and signing the nonce; the record header and the node-record note specify the compiled-in Ed25519 and the W4MESHv1 tag over every preceding byte. This page follows the record header.
Type bytes. DHT messages 0x10–0x12 reuse the numbers of the Nimosini mesh types 16–18; the signing tag and the channel keep them apart.
Pre-ticked AI scopes. The record header now holds the safe default 0x0205 (local tune, basic call, pod language model); an earlier draft's 0x1E87 is gone. See AI records.
Blitter Bus. GPUChannel, the Blitter Bus (crossbar), is the crossbar of the Web 4 Channel Paradigm. By design it carries data between the cores; today the crossbar is the block NetXecChannel allocates, only System←Signal writes to it, and channels7/GPUChannel.c (153 lines) is a query-name stub that is not connected to it. The 1,838-line channels7-read/GPUChannel.c is a different file and does not use the crossbar. The draft join chart gives Device (where GPUChannel is homed) only four partners (System, Memory, Thread, Signal), and the 512-entry dispatch table has one real handler (the other 511 are no-op defaults, NetXecChannel.c:746-755); both need work before the Blitter Bus carries data between all cores. See The crossbar.
Not documented in the sources: run-time behaviour of the three pod ChannelData flags; the Debug channel; handlers for 511 of 512 dispatch cells; a live mesh endpoint; a live DHT.
Source files this manual draws on
channels7: NetXecChannel.c, defines.h, channels.h, channel_io.c, ChannelConfig.h, MainChannel.h, ServerChannel.h, ThreadChannel.c, MemoryChannel.c, EventChannel.c, SignalChannel.h, ClockChannel.c, ContainerChannel.h, URLChannel.c, EncryptionChannel.h, CompressionChannel.c, SolidChannel.h, StockChannel.h, STDIOChannel.h, CLIChannel.c, GALAXYGATE.md, docs/channel-joins.md, docs/channel-joins-corexcore.csv, docs/CODECHANNEL.md, URLChannel-CURL.md, SOLID-AUTH-HEADERS.md. Pod: channels6-review/solid/solid_pod.h, pod_sticky.h (not in channels6-review/solid; it is in publish-vaultmagic/src), channel_data.h, handoff-solid-pod/SOLID-POD-INTENT.md. Records: node-records/*.h and NODE-RECORD.md, mesh/MESH-SPEC.md, WEB4-CONTRACT.md. Design: nimosini-channel/NIMOSINI-CHANNEL-SPEC.md.