# /system/configuration/protocol.csv — who may claim, and who may reach, a name
# under /protocol (docs/os-development/protocol-namespace.md).
#
# init is the registrar: it serves /protocol, and every bind AND every open is
# checked against this file. It is AUTHORITATIVE — a name no row grants cannot be
# bound or reached, and a missing file means nothing may be bound or reached at
# all.
#
# A refused open is answered exactly as a name nobody bound is: -ENOENT, and no
# capability. That is not politeness, it is the model — the namespace IS the
# restriction, so what a process may not open simply does not exist for it, and
# there is no "permission denied" for it to tell apart from "no such contract".
# Which is why a missing row here shows up as a client retrying forever rather
# than as an error: check this file first, and `readdir /protocol` second.
#
# '#' starts a comment (whole-line or trailing); blank lines are ignored.
# Whitespace around a field is trimmed, so columns may be padded. Four
# comma-separated fields per row:
#
#   binary      the claimant's binary path, exactly as the kernel stamped it at
#               spawn (argv[0]) — unforgeable, read from the process records
#   supervisor  the authorized supervising TASK, written as the binary it runs —
#               the path init was started as for its own services, the device
#               manager's path for the drivers it starts. The one word that is not
#               a path is 'kernel', because a kernel task has no binary; that is
#               what the test harness's direct spawns look like.
#               Matched by IDENTITY, not by spelling. Name alone is not identity —
#               spawn is ungated, so a hostile process can start a granted binary
#               itself and inherit its grants; and it can equally start its own
#               instance of the *supervisor's* binary and have that spawn the
#               granted one, at which point both names read correctly (the
#               laundering deputy). So init also asks which task the supervisor
#               is: 'kernel' means supervisor id 0, which only the kernel can
#               confer; init's own path means this init; any other path means a
#               task init spawned itself or one the kernel spawned. Task ids are
#               monotonic and never reused, so an id cannot be borrowed.
#   permission  bind (provide this contract) | open (speak to it) |
#               supervise (stand in someone else's chain — see below)
#   name        the contract, relative to /protocol
#
# A trailing '*' on any field matches any tail — how a subtree is granted whole.
#
# 'supervise' exists because attestation is one hop deep and the driver tree is
# three: the device manager starts the PS/2 bus, and the bus starts the keyboard
# and mouse drivers. Init never met the bus, so it cannot vouch for it by
# acquaintance — and it must not vouch for it by name, or the laundering deputy
# walks straight in. A 'supervise' row is the manifest saying it: a task running
# this binary, under this supervisor, may be the supervising task an 'open' row
# names, for this contract and no other. It grants the delegate nothing itself,
# and it is deliberately open-only — a delegate may vouch for what its children
# REACH, never for what they CLAIM, so every bind refusal is untouched by it.
#
# binary                                     supervisor                       permission  name

# --- the services init spawns from init.csv ---------------------------------
/system/services/input,                      /system/services/init,           bind,       input
/system/services/device-manager,             /system/services/init,           bind,       device-manager
/system/services/fat,                        /system/services/init,           bind,       vfs
/system/services/display,                    /system/services/init,           bind,       display

# The discovery service ships under one neutral name per firmware (docs/discovery.md);
# on x86 it is the acpi service, and what it provides is the power contract.
/system/services/discovery,                  /system/services/device-manager, bind,       power

# --- the drivers, which the device manager spawns ---------------------------
/system/drivers/ps2-bus,                     /system/services/device-manager, bind,       ps2-bus
/system/drivers/usb-xhci-bus,                /system/services/device-manager, bind,       usb-transfer
/system/drivers/usb-storage,                 /system/services/device-manager, bind,       block
/system/drivers/virtio-gpu,                  /system/services/device-manager, bind,       scanout

# --- the same providers when the kernel test harness starts them directly ---
# A scenario boot spawns its own providers instead of letting init do it
# (docs/security-track-plan.md, decision 9), so the same binaries appear with
# 'kernel' as the supervisor. Nothing else changes: the binary must still match.
/system/services/input,                      kernel,                          bind,       input
/system/services/device-manager,             kernel,                          bind,       device-manager
/system/services/fat,                        kernel,                          bind,       vfs
/system/services/display,                    kernel,                          bind,       display
/system/services/discovery,                  kernel,                          bind,       power

# --- test fixtures ----------------------------------------------------------
# The subtree rule, dogfooded: anything installed under /test may claim anything
# under /protocol/test, and nothing above it — whether the harness spawned it or
# another fixture did.
/test/*,                                     kernel,                          bind,       test/*
/test/*,                                     /test/*,                         bind,       test/*


# ============================================================================
# open — who may REACH each contract. One row per client per contract; a client
# with no row here simply finds the name absent, forever.
# ============================================================================

# --- init's own services ----------------------------------------------------
# fat reaches the block device behind the volume it mounts; the compositor
# reaches the scanout its driver announced, its own endpoint (the mouse-listener
# thread opens /protocol/display like any other client — threads share no
# handles), and the input stream that moves the cursor.
/system/services/fat,                        /system/services/init,           open,       block
/system/services/display,                    /system/services/init,           open,       scanout
/system/services/display,                    /system/services/init,           open,       display
/system/services/display,                    /system/services/init,           open,       input
/system/services/display-demo,               /system/services/init,           open,       display

# --- the same two when the kernel test harness starts them directly ---------
/system/services/display,                    kernel,                          open,       scanout
/system/services/display,                    kernel,                          open,       display
/system/services/display,                    kernel,                          open,       input
/system/services/display-demo,               kernel,                          open,       display

# --- the drivers, and the discovery service ---------------------------------
# Every driver says hello to the manager that started it — one row for the whole
# subtree, because that handshake is what being a driver means. The rest are per
# driver: the storage and HID class drivers talk to their controller, the HID
# drivers publish into the input stream, and the GPU driver announces its scanout
# to the compositor.
/system/drivers/*,                           /system/services/device-manager, open,       device-manager
/system/services/discovery,                  /system/services/device-manager, open,       device-manager
/system/drivers/usb-storage,                 /system/services/device-manager, open,       usb-transfer
/system/drivers/usb-hid-keyboard,            /system/services/device-manager, open,       usb-transfer
/system/drivers/usb-hid-keyboard,            /system/services/device-manager, open,       input
/system/drivers/usb-hid-mouse,               /system/services/device-manager, open,       usb-transfer
/system/drivers/usb-hid-mouse,               /system/services/device-manager, open,       input
/system/drivers/virtio-gpu,                  /system/services/device-manager, open,       display

# --- the PS/2 child drivers, one hop further down ---------------------------
# The keyboard and mouse drivers are started by the BUS driver, not by the
# device manager — the one three-deep chain in the tree. Init cannot vouch for
# the bus by acquaintance (it never started it), so the manifest authorizes it
# explicitly, and only for the two contracts its children need.
/system/drivers/ps2-bus,                     /system/services/device-manager, supervise,  ps2-bus
/system/drivers/ps2-bus,                     /system/services/device-manager, supervise,  input
/system/drivers/ps2-keyboard,                /system/drivers/ps2-bus,         open,       ps2-bus
/system/drivers/ps2-keyboard,                /system/drivers/ps2-bus,         open,       input
/system/drivers/ps2-mouse,                   /system/drivers/ps2-bus,         open,       ps2-bus
/system/drivers/ps2-mouse,                   /system/drivers/ps2-bus,         open,       input

# --- test fixtures ----------------------------------------------------------
# The /protocol/test subtree is theirs whole, the way the bind rows give it to
# them. Everything ABOVE that subtree is named one fixture at a time, so a
# fixture reaches a system contract only where a scenario needs it — which is
# what leaves the rest genuinely absent for the rest of them (the protocol-denied
# case asks for one it was not given, and is told there is no such thing).
/test/*,                                     kernel,                          open,       test/*
/test/*,                                     /test/*,                         open,       test/*
/test/*,                                     kernel,                          open,       device-manager
/test/*,                                     /system/services/device-manager, open,       device-manager
/test/system/services/input-source,          kernel,                          open,       input
/test/system/services/input-test,            kernel,                          open,       input

# The laundering-deputy probe (test/system/services/protocol-registry-test) runs
# a grandchild whose supervisor is a fixture nobody authorized — that is the
# point of it, and its bind must stay refused. It still has to report the verdict
# it got, so its reporting channel, and nothing else, is delegated.
/test/*,                                     /test/*,                         supervise,  test/verdict
