# Channel joins -- core fabric draft

Tree: `channels7`. Style note: Cont/channels ASCII; no typedef/enum/union in wire types.

Generated for Tony: full core×core allow/deny draft + MainChannel star hub story (Cont is adding MainChannel.c).
Artifact also: `channel-joins.mmd`, `channel-joins.html` (Permalink-ready).

## 255² story (why the matrix matters)

Crossbar + listener fabric is pairwise. Rough space:

- **Core×core**: 16×16 = 256 directed cells (120 undirected pairs + 16 self).
- **Sub×sub name slots**: `SubChannelAllocatedNames[256]` (16 cores × 16 subs).
- **Full directed pairwise** among 256 slots: 256×256 = **65536** (~255²).
- Most pairs are **nonsense** (Device↔Compiler, Clock↔URL, …). Policy must DENY by default
  and ALLOW a **dense core** plus a **MainChannel star** for session/main.

Join implementation today: `ChannelJoin` / `ChannelLeave` / `ChannelBindIO` in `channel_io.c`.
No hard allow-table in binary yet — this doc is the **policy draft** to encode later.

## Roles

| Face | Role | Core id | Open flag |
|------|------|---------|-----------|
| MainChannel | session/main join hub (sidecar) | sidecar 110 | `CHANNELS7_OPEN_USER=1` |
| ContainerDisplayChannel | display name over Cont | wraps **7** | `CHANNELS7_OPEN_CONTAINER_DISPLAY=1` |
| ContainerChannel | core Cont UI | **7** `CHANNEL_CONTAINER` | always (NetXec step 10) |
| SQLChannel | SQL driver stub (no SQLite yet) | sidecar 112 | `CHANNELS7_OPEN_SQL=1` |
| NimosiniChannel | bot Tick/Ping under Nimosini | **15** | `CHANNELS7_OPEN_NIMOSINI=1` |

**Mapping:** `ContainerDisplayChannel` is a source-visible display layer; core name stays
`"Container"` id 7 for now (`CONTDISP_CORE_ID`).

## Mermaid flowchart

```mermaid
flowchart TB
  %% channels7 core join draft -- MainChannel star + dense fabric
  %% ContainerDisplayChannel == Container core id 7 (display name layer)
  subgraph HUB["MainChannel (sidecar join hub)"]
    USER(["MainChannel\nsession/main"])
  end
  subgraph DENSE["Dense core fabric (ALLOW mesh)"]
    C0["0:System"]
    C2["2:Memory"]
    C3["3:Thread"]
    C4["4:Signal"]
    C6["6:Clock"]
    C7["7:Container"]
    C12["12:STDIO"]
  end
  subgraph SPOKE["Spoke cores"]
    C1["1:Device"]
    C5["5:Media"]
    C8["8:URL"]
    C9["9:Server"]
    C10["10:Process0"]
    C11["11:Process1"]
    C13["13:Compiler"]
    C14["14:Debug"]
    C15["15:Nimosini"]
  end
  subgraph SIDE["Sidecar faces (optional OPEN flags)"]
    CD["ContainerDisplayChannel\nwraps Cont id7"]
    SQL["SQLChannel\nProcess1/Server"]
    NIMO["NimosiniChannel\ncore15 bots"]
  end
  USER -.->|star join| C0
  USER -.->|star join| C1
  USER -.->|star join| C2
  USER -.->|star join| C3
  USER -.->|star join| C4
  USER -.->|star join| C5
  USER -.->|star join| C6
  USER -.->|star join| C7
  USER -.->|star join| C8
  USER -.->|star join| C9
  USER -.->|star join| C10
  USER -.->|star join| C11
  USER -.->|star join| C12
  USER -.->|star join| C13
  USER -.->|star join| C14
  USER -.->|star join| C15
  C0 --- C2
  C2 --- C3
  C3 --- C4
  C4 --- C6
  C6 --- C7
  C7 --- C12
  C12 --- C0
  C5 -->|ALLOW| C7
  C5 -->|ALLOW| C4
  C8 -->|ALLOW| C9
  C8 -->|ALLOW| C7
  C9 -->|ALLOW| C11
  C9 -->|ALLOW| C10
  C13 -->|ALLOW| C10
  C14 -->|ALLOW| C13
  C15 -->|ALLOW| C2
  C15 -->|ALLOW| C4
  C1 -->|ALLOW| C2
  C1 -->|ALLOW| C4
  C12 -->|ALLOW| C4
  C0 -->|ALLOW| C4
  CD --- C7
  SQL -->|ALLOW| C9
  SQL -->|ALLOW| C11
  NIMO --- C15
  %% DENY examples (dashed red conceptually)
  C1 -.->|DENY| C8
  C1 -.->|DENY| C13
  C5 -.->|DENY| C13
  C6 -.->|DENY| C8
  C6 -.->|DENY| C9
  C15 -.->|DENY| C1
```

## Legend

- **A** = ALLOW (draft): `ChannelJoin` should succeed / be encouraged.
- **D** = DENY (draft): nonsense or unsafe; reject or no-op in future policy table.
- **-** = SELF: never join self.

Counts (directed): ALLOW=144, DENY=96, SELF=16, total=256.

## Core×core allow/deny matrix (draft)

| src\\tgt | 0:Syst | 1:Devi | 2:Memo | 3:Thre | 4:Sign | 5:Medi | 6:Cloc | 7:Cont | 8:URL | 9:Serv | 10:Proc | 11:Proc | 12:STDI | 13:Comp | 14:Debu | 15:Nimo |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| **0:System** | - | A | A | A | A | A | A | A | A | A | D | D | A | A | A | A |
| **1:Device** | A | - | A | A | A | D | D | D | D | D | D | D | D | D | D | D |
| **2:Memory** | A | A | - | A | A | A | A | A | A | A | A | A | A | A | A | A |
| **3:Thread** | A | A | A | - | A | D | A | A | D | D | A | A | A | D | D | A |
| **4:Signal** | A | A | A | A | - | A | A | A | A | A | A | A | A | D | A | A |
| **5:Media** | A | D | A | D | A | - | A | A | D | D | D | D | A | D | D | D |
| **6:Clock** | A | D | A | A | A | A | - | A | D | D | D | D | A | D | D | D |
| **7:Container** | A | D | A | A | A | A | A | - | A | D | D | D | A | D | D | A |
| **8:URL** | A | D | A | D | A | D | D | A | - | A | D | D | A | D | D | D |
| **9:Server** | A | D | A | D | A | D | D | D | A | - | A | A | A | D | D | D |
| **10:Process0** | D | D | A | A | A | D | D | D | D | A | - | A | A | A | A | A |
| **11:Process1** | D | D | A | A | A | D | D | D | D | A | A | - | A | A | A | A |
| **12:STDIO** | A | D | A | A | A | A | A | A | A | A | A | A | - | A | A | A |
| **13:Compiler** | A | D | A | D | D | D | D | D | D | D | A | A | A | - | A | D |
| **14:Debug** | A | D | A | D | A | D | D | D | D | D | A | A | A | A | - | D |
| **15:Nimosini** | A | D | A | A | A | D | D | A | D | D | A | A | A | D | D | - |

### Undirected ALLOW pairs (canonical min,max)

| a | b | a name | b name |
|---|---|--------|--------|
| 0 | 1 | System | Device |
| 0 | 2 | System | Memory |
| 0 | 3 | System | Thread |
| 0 | 4 | System | Signal |
| 0 | 5 | System | Media |
| 0 | 6 | System | Clock |
| 0 | 7 | System | Container |
| 0 | 8 | System | URL |
| 0 | 9 | System | Server |
| 0 | 12 | System | STDIO |
| 0 | 13 | System | Compiler |
| 0 | 14 | System | Debug |
| 0 | 15 | System | Nimosini |
| 1 | 2 | Device | Memory |
| 1 | 3 | Device | Thread |
| 1 | 4 | Device | Signal |
| 2 | 3 | Memory | Thread |
| 2 | 4 | Memory | Signal |
| 2 | 5 | Memory | Media |
| 2 | 6 | Memory | Clock |
| 2 | 7 | Memory | Container |
| 2 | 8 | Memory | URL |
| 2 | 9 | Memory | Server |
| 2 | 10 | Memory | Process0 |
| 2 | 11 | Memory | Process1 |
| 2 | 12 | Memory | STDIO |
| 2 | 13 | Memory | Compiler |
| 2 | 14 | Memory | Debug |
| 2 | 15 | Memory | Nimosini |
| 3 | 4 | Thread | Signal |
| 3 | 6 | Thread | Clock |
| 3 | 7 | Thread | Container |
| 3 | 10 | Thread | Process0 |
| 3 | 11 | Thread | Process1 |
| 3 | 12 | Thread | STDIO |
| 3 | 15 | Thread | Nimosini |
| 4 | 5 | Signal | Media |
| 4 | 6 | Signal | Clock |
| 4 | 7 | Signal | Container |
| 4 | 8 | Signal | URL |
| 4 | 9 | Signal | Server |
| 4 | 10 | Signal | Process0 |
| 4 | 11 | Signal | Process1 |
| 4 | 12 | Signal | STDIO |
| 4 | 14 | Signal | Debug |
| 4 | 15 | Signal | Nimosini |
| 5 | 6 | Media | Clock |
| 5 | 7 | Media | Container |
| 5 | 12 | Media | STDIO |
| 6 | 7 | Clock | Container |
| 6 | 12 | Clock | STDIO |
| 7 | 8 | Container | URL |
| 7 | 12 | Container | STDIO |
| 7 | 15 | Container | Nimosini |
| 8 | 9 | URL | Server |
| 8 | 12 | URL | STDIO |
| 9 | 10 | Server | Process0 |
| 9 | 11 | Server | Process1 |
| 9 | 12 | Server | STDIO |
| 10 | 11 | Process0 | Process1 |
| 10 | 12 | Process0 | STDIO |
| 10 | 13 | Process0 | Compiler |
| 10 | 14 | Process0 | Debug |
| 10 | 15 | Process0 | Nimosini |
| 11 | 12 | Process1 | STDIO |
| 11 | 13 | Process1 | Compiler |
| 11 | 14 | Process1 | Debug |
| 11 | 15 | Process1 | Nimosini |
| 12 | 13 | STDIO | Compiler |
| 12 | 14 | STDIO | Debug |
| 12 | 15 | STDIO | Nimosini |
| 13 | 14 | Compiler | Debug |

Total undirected ALLOW pairs: **72**.

## Nonsense / DENY examples (sample of 255²)

| a | b | pair | reason (draft) |
|---|---|------|----------------|
| 1 | 8 | Device <-> URL | bot HTTP deferred [D] |
| 1 | 13 | Device <-> Compiler | hardware vs language toolchain [D] |
| 5 | 13 | Media <-> Compiler | media pipeline vs compile [D] |
| 6 | 8 | Clock <-> URL | timer sidecar vs net stack [D] |
| 6 | 9 | Clock <-> Server | timer sidecar vs net stack [D] |
| 15 | 1 | Nimosini <-> Device | bot agent vs raw device [D] |
| 14 | 5 | Debug <-> Media | debug vs media path [D] |
| 14 | 1 | Debug <-> Device | draft DENY [D] |
| 13 | 5 | Compiler <-> Media | media pipeline vs compile [D] |
| 13 | 1 | Compiler <-> Device | hardware vs language toolchain [D] |
| 7 | 1 | Container <-> Device (rare; prefer System) | prefer System mediation [D] |
| 11 | 5 | Process1 <-> Media | process vs media [D] |
| 10 | 5 | Process0 <-> Media | process vs media [D] |
| 15 | 8 | Nimosini <-> URL (bot HTTP later; draft DENY) | bot HTTP deferred [D] |
| 6 | 13 | Clock <-> Compiler | timer sidecar vs net stack [D] |

## Dense core (mesh)

Always-on fabric candidates (star neighbors for MainChannel too):

- `0` System
- `2` Memory
- `3` Thread
- `4` Signal
- `6` Clock
- `7` Container
- `12` STDIO

## MainChannel star

`UserJoinHub` walks `nx->channel_base[0..15]` and `ChannelJoin`s each live peer.
That is the session/main equivalent: one hub, many cores, without expanding CORE_CHANNEL_NUMBER.

## SQL / ContainerDisplayChannel / Nimosini joins

- **SQLJoinCore**: Server + Process1 + Memory (sql sub name under Process1).
- **ContainerDisplayChannel**: joins the Cont base; core id remains 7.
- **NimosiniJoinCore**: seats `channel_base[15]`, joins Signal + Memory.

## Encode later

1. Optional `join_policy[16][16]` uint8 table (A/D) consulted inside `ChannelJoin`.
2. Cont Config board already has `ChannelConfigLink` — surface this matrix there.
3. Keep sidecars out of core matrix; policy by sidecar id (>=100) separately.

## Test one-at-a-time

```bash
export CHANNELS7_OPEN_USER=1
# or: CHANNELS7_OPEN_CONTAINER_DISPLAY=1
# or: CHANNELS7_OPEN_SQL=1
# or: CHANNELS7_OPEN_NIMOSINI=1
./solidpod.exe
```

