mirror of
https://github.com/CyberMind-FR/secubox-deb.git
synced 2026-07-28 15:28:24 +00:00
Permanent documentation for the 8-verb / 8-layer modular tools box that emerged across #173, #176, #180-#184, #190, #212. Three new docs + one README section, all bearing the 1991 attribution. docs/grammar.md Canonical conceptual frame: layered map, 8 verbs in a table, composing-the-grammar worked examples, naming conventions, philosophical roots. HOWTO-grammar.md Concrete 6-step walkthrough for adding a 9th verb (~1h budget): issue framing, worktree, CTL skeleton (Bash + Python), FastAPI mirror, Debian packaging, nginx route under secubox-routes.d/, live test on the board, commit/PR conventions, common pitfalls drawn from real incidents (#163 secubox.d vs secubox-routes.d, #173 LXC default path, #176 hook trigger, #194 CAP_NET_ADMIN, #180 naming). wiki/CTL-Grammar.md Public-facing wiki page mirrored to the GitHub wiki repo (per the wiki-sync pattern established for Acknowledgments). Embeds Punk Exposure (Peek/Poke/Emancipate) as the seed concept with 1991 attribution. README.md New section under Features summarising the grammar with the 9-row layer table and a pointer to docs/grammar.md + HOWTO-grammar.md. Attribution recorded on all three documents: copyright spiritual concept Gerald Kerma (GK2), 1991, Notre-Dame-du-Cruet, Savoie. The CTL is the user's voice. The modular tools box is their organ. The language is the way they say *this is mine, this is mine, this is mine*. Co-authored-by: CyberMind-FR <gandalf@Gk2.net>
This commit is contained in:
parent
b5c8262c17
commit
53a630e9f8
326
HOWTO-grammar.md
Normal file
326
HOWTO-grammar.md
Normal file
|
|
@ -0,0 +1,326 @@
|
|||
# HOWTO — forge a new CTL verb
|
||||
|
||||
> *Copyright spiritual concept · Gérald Kerma · 1991*
|
||||
>
|
||||
> This is the concrete walkthrough. See `docs/grammar.md` for the
|
||||
> conceptual frame and the 8 canonical verbs already in place.
|
||||
|
||||
You want to add `xctl widget add/remove/list` (or any 9th verb). Follow
|
||||
these steps in order. Time budget: ~1 hour for a Bash-style verb,
|
||||
~2 hours for a Python+FastAPI one.
|
||||
|
||||
---
|
||||
|
||||
## 1. Frame the gap
|
||||
|
||||
Write the issue body following this template (adapt verbs/nouns):
|
||||
|
||||
```markdown
|
||||
## Context
|
||||
|
||||
The X module already exposes <capability> via the web UI and FastAPI, but
|
||||
operators have no CLI grammar for it. Closing the gap parallel to:
|
||||
|
||||
- `mitmproxyctl route add` (#173) — INTERCEPTION
|
||||
- `giteactl repo mirror add` (#176) — REPLICATION
|
||||
|
||||
## Gap
|
||||
|
||||
Forge `xctl widget` with subcommands:
|
||||
|
||||
xctl widget add NAME [--option ...]
|
||||
xctl widget remove NAME
|
||||
xctl widget list
|
||||
xctl widget status NAME
|
||||
|
||||
## Out of scope
|
||||
|
||||
(Anything you defer to a followup ticket.)
|
||||
```
|
||||
|
||||
Submit, capture the issue number. Reference it as `#<N>` in everything
|
||||
that follows.
|
||||
|
||||
---
|
||||
|
||||
## 2. Worktree
|
||||
|
||||
```bash
|
||||
scripts/agent-worktree.sh start --issue <N>
|
||||
cd ~/CyberMindStudio/secubox-deb-worktrees/<N>-<slug>
|
||||
```
|
||||
|
||||
You're now on a branch named `feature/<N>-<slug>` (or `fix/...` if the
|
||||
issue is labeled `bug`). Every commit message ends with `(ref #<N>)` or
|
||||
`(closes #<N>)` on the final commit.
|
||||
|
||||
---
|
||||
|
||||
## 3. Pick the language
|
||||
|
||||
| When | Use |
|
||||
|---|---|
|
||||
| The verb is mostly shell-orchestration (lxc-attach, systemctl, file ops) | Bash |
|
||||
| The verb needs rich subparsers, JSON I/O, or a registry pattern | Python |
|
||||
|
||||
Both styles exist in-tree. Reference implementations:
|
||||
|
||||
- **Bash** — `packages/secubox-gitea/sbin/giteactl`, `packages/secubox-metablogizer/sbin/metablogizerctl`
|
||||
- **Python** — `packages/secubox-mitmproxy/bin/mitmproxyctl`, `packages/secubox-health-doctor/sbin/healthctl`
|
||||
|
||||
---
|
||||
|
||||
## 4. Skeleton
|
||||
|
||||
### Bash skeleton
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: LicenseRef-CMSD-1.0
|
||||
# Copyright (c) 2026 CyberMind — Gérald Kerma <devel@cybermind.fr>
|
||||
#
|
||||
# xctl — SecuBox X control (issue #<N>).
|
||||
|
||||
set -euo pipefail
|
||||
VERSION="0.1.0"
|
||||
CONFIG_FILE="/etc/secubox/x.toml"
|
||||
|
||||
GREEN='\033[0;32m'; YELLOW='\033[1;33m'; RED='\033[0;31m'; NC='\033[0m'
|
||||
log() { printf "${GREEN}[X]${NC} %s\n" "$*"; }
|
||||
warn() { printf "${YELLOW}[WARN]${NC} %s\n" "$*"; }
|
||||
error() { printf "${RED}[ERROR]${NC} %s\n" "$*" >&2; }
|
||||
|
||||
# Lifecycle
|
||||
cmd_start() { systemctl start secubox-x.service && log started; }
|
||||
cmd_stop() { systemctl stop secubox-x.service && log stopped; }
|
||||
cmd_restart() { systemctl restart secubox-x.service && log restarted; }
|
||||
cmd_status() { systemctl is-active secubox-x.service; }
|
||||
cmd_logs() { journalctl -u secubox-x.service -n "${1:-50}" --no-pager; }
|
||||
|
||||
# Three-fold (JSON discovery)
|
||||
cmd_components() {
|
||||
cat <<EOF
|
||||
{"service":"secubox-x.service","api_base":"/api/v1/x","ctl_version":"$VERSION"}
|
||||
EOF
|
||||
}
|
||||
cmd_access() {
|
||||
cat <<EOF
|
||||
{"api":{"list":"GET /widgets","add":"POST /widget","remove":"DELETE /widget/{name}"}}
|
||||
EOF
|
||||
}
|
||||
|
||||
# Widget noun
|
||||
cmd_widget() {
|
||||
local act="${1:-}"; shift || true
|
||||
case "$act" in
|
||||
add) widget_add "$@" ;;
|
||||
remove|rm|delete) widget_remove "$@" ;;
|
||||
list|ls) widget_list "$@" ;;
|
||||
status) widget_status "$@" ;;
|
||||
*) echo "Usage: xctl widget {add|remove|list|status} [args]" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
widget_add() { :; } # implement: name validation, side effect, idempotent
|
||||
widget_remove() { :; }
|
||||
widget_list() { :; }
|
||||
widget_status() { :; }
|
||||
|
||||
case "${1:-}" in
|
||||
start|stop|restart|status) c="$1"; shift; cmd_$c "$@" ;;
|
||||
logs) shift; cmd_logs "$@" ;;
|
||||
components) cmd_components ;;
|
||||
access) cmd_access ;;
|
||||
widget) shift; cmd_widget "$@" ;;
|
||||
*) echo "Usage: xctl <command>"; exit 1 ;;
|
||||
esac
|
||||
```
|
||||
|
||||
### Python skeleton
|
||||
|
||||
```python
|
||||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: LicenseRef-CMSD-1.0
|
||||
# Copyright (c) 2026 CyberMind — Gérald Kerma <devel@cybermind.fr>
|
||||
"""xctl — SecuBox X control (#<N>)."""
|
||||
from __future__ import annotations
|
||||
import argparse, json, sys
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, "/usr/lib/secubox/x")
|
||||
from api import engine # canonical writer used by FastAPI too
|
||||
|
||||
def cmd_widget_add(args): engine.widget_add(args.name); return 0
|
||||
def cmd_widget_remove(args): engine.widget_remove(args.name); return 0
|
||||
def cmd_widget_list(args): print(json.dumps(engine.widget_list(), indent=2)); return 0
|
||||
|
||||
def build_parser():
|
||||
p = argparse.ArgumentParser(prog="xctl")
|
||||
sub = p.add_subparsers(dest="cmd", required=True)
|
||||
for n in ("start", "stop", "restart", "status", "components", "access", "logs"):
|
||||
sub.add_parser(n)
|
||||
w = sub.add_parser("widget"); ws = w.add_subparsers(dest="wc", required=True)
|
||||
add = ws.add_parser("add"); add.add_argument("name"); add.set_defaults(func=cmd_widget_add)
|
||||
rm = ws.add_parser("remove"); rm.add_argument("name"); rm.set_defaults(func=cmd_widget_remove)
|
||||
ls = ws.add_parser("list"); ls.set_defaults(func=cmd_widget_list)
|
||||
return p
|
||||
|
||||
def main():
|
||||
args = build_parser().parse_args()
|
||||
return args.func(args) if hasattr(args, "func") else 0
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. FastAPI mirror
|
||||
|
||||
Every verb has a route. Same engine, two callers (CTL and API).
|
||||
|
||||
```python
|
||||
# packages/secubox-x/api/main.py
|
||||
from fastapi import FastAPI
|
||||
from . import engine
|
||||
|
||||
app = FastAPI(root_path="/api/v1/x")
|
||||
|
||||
@app.get("/widgets")
|
||||
def widget_list(): return engine.widget_list()
|
||||
|
||||
@app.post("/widget")
|
||||
def widget_add(name: str): return engine.widget_add(name)
|
||||
|
||||
@app.delete("/widget/{name}")
|
||||
def widget_remove(name: str): return engine.widget_remove(name)
|
||||
```
|
||||
|
||||
The CTL and the web UI both call into `engine.widget_*`. **Don't
|
||||
duplicate business logic** between CTL and API — they're two surfaces
|
||||
on the same engine.
|
||||
|
||||
---
|
||||
|
||||
## 6. Debian packaging
|
||||
|
||||
`packages/secubox-x/debian/`:
|
||||
|
||||
- `control` — Depends on `secubox-core`, `python3-uvicorn`, etc.
|
||||
- `changelog` — bump version, include `Closes: #<N>`.
|
||||
- `rules` — install the CTL to `/usr/sbin/xctl`, the API to
|
||||
`/usr/lib/secubox/x/`, the systemd unit to `/lib/systemd/system/`.
|
||||
- `postinst` — `systemctl enable --now secubox-x.service` (idempotent).
|
||||
- `prerm` — `systemctl disable --now secubox-x.service`.
|
||||
|
||||
systemd unit boilerplate:
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=SecuBox X
|
||||
After=network.target secubox-core.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=secubox
|
||||
Group=secubox
|
||||
WorkingDirectory=/usr/lib/secubox/x
|
||||
ExecStart=/usr/bin/python3 -m uvicorn api.main:app \
|
||||
--uds /run/secubox/x.sock --log-level warning
|
||||
Restart=on-failure
|
||||
ReadWritePaths=/run/secubox /var/cache/secubox
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
If your CTL needs to read nft sets, add
|
||||
`AmbientCapabilities=CAP_NET_ADMIN` (see #194 — without it,
|
||||
`subprocess.run(["nft", ...])` silently returns empty).
|
||||
|
||||
---
|
||||
|
||||
## 7. Nginx route (so the API is reachable via admin.gk2)
|
||||
|
||||
Add `/etc/nginx/secubox-routes.d/x.conf`:
|
||||
|
||||
```nginx
|
||||
location /api/v1/x/ {
|
||||
proxy_pass http://unix:/run/secubox/x.sock:/api/v1/x/;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_read_timeout 60s;
|
||||
}
|
||||
```
|
||||
|
||||
This goes in `secubox-routes.d/`, **not** `secubox.d/` — the admin.gk2
|
||||
server block includes the former (lesson learned from #163).
|
||||
|
||||
---
|
||||
|
||||
## 8. Live test on the board
|
||||
|
||||
The verb is only forged when it survives prod. From your worktree:
|
||||
|
||||
```bash
|
||||
# Copy the CTL onto the board first
|
||||
scp packages/secubox-x/sbin/xctl root@192.168.1.200:/usr/sbin/
|
||||
|
||||
ssh root@192.168.1.200 'xctl access | jq .' # discovery
|
||||
ssh root@192.168.1.200 'xctl widget add demo' # the new verb
|
||||
ssh root@192.168.1.200 'xctl widget list' # observe side-effect
|
||||
```
|
||||
|
||||
If anything is wrong, the operator's CLI tells them so. That's the
|
||||
whole point of the grammar.
|
||||
|
||||
---
|
||||
|
||||
## 9. Commit + PR
|
||||
|
||||
Commit messages stay terse. Don't include AI attribution footers — the
|
||||
project's global reference is enough. Example:
|
||||
|
||||
```text
|
||||
feat(xctl): forge widget noun verbs (closes #<N>)
|
||||
|
||||
Ninth verb of the SecuBox grammar, layer = <layer>. Parallel to
|
||||
mitmproxyctl route (#173), giteactl repo mirror (#176).
|
||||
|
||||
Subcommands:
|
||||
xctl widget add NAME [--option ...]
|
||||
xctl widget remove NAME
|
||||
xctl widget list
|
||||
xctl widget status NAME
|
||||
|
||||
Live-tested on gk2 board: <one-line observation>.
|
||||
```
|
||||
|
||||
Push the branch, open the PR with a one-paragraph summary + a test plan
|
||||
checklist. Don't add `🤖 Generated with Claude Code` style footers.
|
||||
|
||||
---
|
||||
|
||||
## 10. Update grammar.md
|
||||
|
||||
After merge, add a row to the canonical table in `docs/grammar.md` and
|
||||
the wiki version. The grammar is a living document; new verbs extend it.
|
||||
|
||||
---
|
||||
|
||||
## Common pitfalls
|
||||
|
||||
- **Naming**: it's `<module>ctl`, not `<module>-ctl` or `<module>_ctl`.
|
||||
Renaming after the fact (e.g. `metactl` → `publishctl` in #180) is
|
||||
user-hostile; pick right from the start.
|
||||
- **Nounlessness**: don't ship a flat verb set without a noun. `xctl
|
||||
upload` invites future verb collisions; `xctl widget upload` does not.
|
||||
- **AmbientCapabilities** vs `NoNewPrivileges`: they coexist when caps
|
||||
are set in the unit (#194).
|
||||
- **Filesystem fetches don't trigger Gitea hooks** (#176): for verbs
|
||||
that pull data into Gitea-managed repos, use Gitea's API, not
|
||||
`git fetch` on the bare repo from the host.
|
||||
- **Default LXC paths**: board reality is `/data/lxc/`, not
|
||||
`/var/lib/lxc/` (#173). Auto-detect or read from config.
|
||||
- **The grammar surfaces real bugs**: when `healthctl check` flags 4/11
|
||||
failing on first run, those are real anomalies, not check bugs.
|
||||
32
README.md
32
README.md
|
|
@ -168,6 +168,38 @@ Automatic threat detection and IP blocking with community threat intelligence.
|
|||
|
||||
---
|
||||
|
||||
## CTL Grammar — modular tools box
|
||||
|
||||
> *Copyright spiritual concept · Gérald Kerma · 1991*
|
||||
|
||||
Each SecuBox module exposes its capability through three surfaces — a
|
||||
web UI, a FastAPI API, and a CTL command (`/usr/sbin/<module>ctl`). The
|
||||
CTL is the **grammar** of the system: each verb is a sentence addressed
|
||||
to a specific layer of the operator's expressive control over their own
|
||||
infrastructure.
|
||||
|
||||
| Layer | Verb |
|
||||
|----------------------|---------------------------------------------------|
|
||||
| ROUTING | `haproxyctl vhost add/remove` |
|
||||
| INTERCEPTION | `mitmproxyctl route add/remove/list` |
|
||||
| REPLICATION | `giteactl repo mirror add/remove` |
|
||||
| IDENTITY | `giteactl user add/remove` |
|
||||
| CI EXECUTION | `giteactl runner add/remove/list` |
|
||||
| PUBLISHING | `publishctl post` / `dropletctl publish` / `metablogizerctl site` |
|
||||
| EMANCIPATE | `metablogizerctl tor expose/revoke` |
|
||||
| HOSTING | `streamlitctl app deploy/.../info` |
|
||||
| DEV WORKBENCH | `streamforgectl project create/.../templates` |
|
||||
| OPS MONITORING | `healthctl check/list/status/alert` |
|
||||
|
||||
Composing the verbs expresses end-to-end workflows in three lines of
|
||||
shell. See [`docs/grammar.md`](docs/grammar.md) for the conceptual
|
||||
frame and the layered architecture map.
|
||||
|
||||
To **add a 9th verb**, follow [`HOWTO-grammar.md`](HOWTO-grammar.md) —
|
||||
the six-step recipe takes about an hour for a Bash CTL.
|
||||
|
||||
---
|
||||
|
||||
## Eye Remote — External Dashboard
|
||||
|
||||
<p align="center">
|
||||
|
|
|
|||
213
docs/grammar.md
Normal file
213
docs/grammar.md
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
# SecuBox CTL Grammar
|
||||
|
||||
> *Copyright spiritual concept · Gérald Kerma · 1991 ·
|
||||
> Notre-Dame-du-Cruet, Savoie · https://cybermind.fr*
|
||||
>
|
||||
> SecuBox is a **modular tools box** — a security-affected modular language
|
||||
> system that acts as an interface between users and the world of data
|
||||
> publishing of each user around the connected humanities. The 1991 concept
|
||||
> matured through SecuBox-OpenWrt and incarnates here as SecuBox-Deb on
|
||||
> Debian bookworm arm64/amd64. This document codifies the CLI grammar that
|
||||
> makes the modular concept expressible from the shell.
|
||||
|
||||
---
|
||||
|
||||
## The frame
|
||||
|
||||
Each SecuBox module exposes its capability through three surfaces:
|
||||
|
||||
1. **A web UI** (under `/<module>/` on the admin vhost)
|
||||
2. **A FastAPI API** (`/api/v1/<module>/*` over a Unix socket)
|
||||
3. **A CTL command** (`/usr/sbin/<module>ctl`)
|
||||
|
||||
The CTL is the **grammar** of the system: each verb is a sentence in the
|
||||
modular language, addressed to a specific layer of the operator's
|
||||
expressive control over their own infrastructure.
|
||||
|
||||
Without the CTL the organ exists but cannot be commanded —
|
||||
**instrumentation without préhension**. The CTL gives the operator
|
||||
*préhension* (grasping power) over what the module already instruments.
|
||||
|
||||
---
|
||||
|
||||
## The 8 layers / 8 canonical verbs
|
||||
|
||||
| Layer | Verb | Forged in |
|
||||
|----------------------|---------------------------------------------------|-----------|
|
||||
| ROUTING | `haproxyctl vhost add/remove` | pre-2026 |
|
||||
| INTERCEPTION | `mitmproxyctl route add/remove/list` | #173 |
|
||||
| REPLICATION | `giteactl repo mirror add/remove/sync/list` | #176 |
|
||||
| IDENTITY | `giteactl user add/remove/passwd/list` | pre-2026 |
|
||||
| CI EXECUTION | `giteactl runner add/remove/list/token` | #190 |
|
||||
| PUBLISHING (bundle) | `publishctl post upload/publish/...` | #180 |
|
||||
| PUBLISHING (file) | `dropletctl publish/list/remove/rename` | #181, #196 |
|
||||
| PUBLISHING (static) | `metablogizerctl site create/publish/...` | pre-2026 |
|
||||
| EMANCIPATE | `metablogizerctl tor expose/revoke/list/status` | #184 |
|
||||
| HOSTING | `streamlitctl app deploy/start/.../info/restart` | #182 |
|
||||
| DEV WORKBENCH | `streamforgectl project create/.../templates` | #183 |
|
||||
| OPS MONITORING | `healthctl check/list/status/alert` | #212 |
|
||||
|
||||
Each verb closes a previously implicit operation. Composing them
|
||||
expresses end-to-end workflows in three lines of shell:
|
||||
|
||||
```bash
|
||||
# WAF un-bypass for a vhost (the cookie-audit cascade fix, today's grammar):
|
||||
haproxyctl vhost add gitea.gk2.secubox.in mitmproxy_inspector ssl
|
||||
mitmproxyctl route add gitea.gk2.secubox.in 192.168.1.200 9080
|
||||
giteactl repo mirror add secubox/secubox-deb \
|
||||
https://github.com/CyberMind-FR/secubox-deb.git \
|
||||
--interval 10m --force
|
||||
```
|
||||
|
||||
```bash
|
||||
# Forge → host → expose pipeline (apps + static):
|
||||
streamforgectl project create dashboard --template basic
|
||||
streamlitctl app deploy dashboard gitea://secubox/dashboard.git
|
||||
metablogizerctl site publish dashboard
|
||||
metablogizerctl tor expose dashboard # Punk Exposure
|
||||
```
|
||||
|
||||
```bash
|
||||
# Daily ops dance:
|
||||
healthctl check # 60s pulse on vital services
|
||||
healthctl alert --since 1h # what failed or recovered
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Pattern recipe — adding the 9th verb
|
||||
|
||||
A new `<module>ctl <noun> <verb>` follows the same six-step recipe every
|
||||
time:
|
||||
|
||||
### 1. Open an issue framing the gap
|
||||
|
||||
State the **layer**, the **noun**, and the **operator workflow** that
|
||||
currently has no expressible form. Quote any sibling-grammar tickets (e.g.
|
||||
"parallel to #173 on the interception layer"). The issue is the design
|
||||
document; subsequent PRs reference it.
|
||||
|
||||
### 2. Worktree per issue
|
||||
|
||||
```bash
|
||||
scripts/agent-worktree.sh start --issue <N>
|
||||
```
|
||||
|
||||
This enforces the multi-agent worktree workflow (`.claude/CLAUDE.md`):
|
||||
the primary checkout stays on master, every non-trivial feature lives in
|
||||
its own worktree, each commit references `(ref #N)` or `(closes #N)`.
|
||||
|
||||
### 3. CTL skeleton
|
||||
|
||||
Bash for shell-shaped tools (giteactl, metablogizerctl), Python with
|
||||
`argparse` for tools with rich subcommands and JSON I/O (mitmproxyctl,
|
||||
healthctl). Both styles co-exist; pick the one closest to the existing
|
||||
ctls in the same package.
|
||||
|
||||
Three subsections in every CTL:
|
||||
|
||||
```text
|
||||
Lifecycle (top-level) install start stop restart status logs
|
||||
Three-fold (JSON) components access
|
||||
<noun> <verb>(s) the new grammar
|
||||
```
|
||||
|
||||
The Three-fold pair (`components` and `access`) is the discovery contract
|
||||
— operators run `<x>ctl access` to learn what the module exposes without
|
||||
reading source. See `giteactl` and `healthctl` for the canonical shape.
|
||||
|
||||
### 4. FastAPI mirror
|
||||
|
||||
Every verb is a function. Every function gets a route under
|
||||
`/api/v1/<module>/*`. The CTL becomes a thin wrapper over the API when
|
||||
running on the box, and the same routes are consumed by the web UI from
|
||||
the browser. CTL ↔ API parity is mechanical (one engine, two call sites).
|
||||
|
||||
See `packages/secubox-users/api/engine.py` ↔ `sbin/usersctl` for the
|
||||
reference pattern.
|
||||
|
||||
### 5. systemd integration
|
||||
|
||||
If the verb daemonizes anything, ship the unit:
|
||||
|
||||
```text
|
||||
debian/<service>.service Type=simple, User=secubox, ExecStart=python3 -m uvicorn ...
|
||||
debian/<service>-runner.timer for periodic actions (health-doctor, geoipupdate)
|
||||
```
|
||||
|
||||
The Debian `postinst` enables units; the `prerm` disables them. Both are
|
||||
idempotent. Use `AmbientCapabilities=` rather than running as root — we
|
||||
discovered (#194) that missing CAP_NET_ADMIN silently breaks aggregators
|
||||
that need to read `nft` sets.
|
||||
|
||||
### 6. Live test on the prod board
|
||||
|
||||
The grammar is empirical — a verb is only forged when it survives a live
|
||||
deploy on `gk2` (192.168.1.200). The PR body documents the verification:
|
||||
the exact command, the observable side-effect, the API endpoint check.
|
||||
|
||||
---
|
||||
|
||||
## Naming conventions
|
||||
|
||||
- `<module>ctl` (single binary name, no separator). `metactl` was renamed
|
||||
`publishctl` in #180 to align.
|
||||
- Verbs are imperative present tense: `add` / `remove` / `list` / `status`,
|
||||
not `creating` / `deletion` / `listed`.
|
||||
- Nouns are singular: `route`, `repo`, `app`, `project`, `vhost`, `user`.
|
||||
- Aliases are accepted but not advertised in `--help`: `rm`/`del` for
|
||||
`remove`, `ls` for `list`.
|
||||
- Three-fold output is always JSON (machine-readable). Other commands
|
||||
human-friendly by default; `--json` flag opt-in.
|
||||
|
||||
---
|
||||
|
||||
## Layered architecture map
|
||||
|
||||
```text
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ EMANCIPATE metablogizerctl tor (#184) Punk Exposure │
|
||||
├─────────────────────────────────────────────────────────────────────┤
|
||||
│ PUBLISHING metablogizerctl site, publishctl post (#180), │
|
||||
│ dropletctl publish (#181/#196) │
|
||||
│ HOSTING streamlitctl app (#182), streamforgectl project (#183)│
|
||||
├─────────────────────────────────────────────────────────────────────┤
|
||||
│ IDENTITY giteactl user │
|
||||
│ REPLICATION giteactl repo mirror (#176) │
|
||||
│ CI EXECUTION giteactl runner (#190) │
|
||||
├─────────────────────────────────────────────────────────────────────┤
|
||||
│ INTERCEPTION mitmproxyctl route (#173) │
|
||||
│ ROUTING haproxyctl vhost │
|
||||
├─────────────────────────────────────────────────────────────────────┤
|
||||
│ OPS MONITORING healthctl (#212) │
|
||||
│ surveille les 9 couches ci-dessus │
|
||||
└─────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
The monitoring layer at the bottom is meta — `healthctl` watches the
|
||||
state of the other nine and surfaces transitions via journal events.
|
||||
|
||||
---
|
||||
|
||||
## Philosophical roots
|
||||
|
||||
The SecuBox concept was conceived by **Gérald Kerma (GK²)** in **1991**
|
||||
as a modular tools box for user-controlled digital sovereignty over
|
||||
personal data publishing. The Punk Exposure verbs (`Peek`/`Poke`/
|
||||
`Emancipate`) trace back to that origin: three modes of expression
|
||||
through which the user occupies their own infrastructure rather than
|
||||
delegate it. The 8-verb CLI grammar is the operational incarnation of
|
||||
that frame on Debian, 35 years later.
|
||||
|
||||
The CTL is the user's voice. The modular tools box is their organ. The
|
||||
language is the way they say *this is mine, this is mine, this is mine*.
|
||||
|
||||
---
|
||||
|
||||
## See also
|
||||
|
||||
- `HOWTO-grammar.md` — concrete walkthrough for adding a 9th verb
|
||||
- `wiki/CTL-Grammar.md` — public-facing summary on the GitHub wiki
|
||||
- `.claude/CLAUDE.md` — operational rules for agents (worktree workflow,
|
||||
per-package conventions, hard rules)
|
||||
- Issues #173, #176, #180-#184, #190, #212 — the forging history
|
||||
118
wiki/CTL-Grammar.md
Normal file
118
wiki/CTL-Grammar.md
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
# SecuBox CTL Grammar
|
||||
|
||||
> *Copyright spiritual concept · Gérald Kerma · 1991 ·
|
||||
> Notre-Dame-du-Cruet, Savoie · https://cybermind.fr*
|
||||
>
|
||||
> SecuBox is a **modular tools box** — a security-affected modular
|
||||
> language system that acts as an interface between users and the world
|
||||
> of data publishing of each user around the connected humanities. The
|
||||
> 1991 concept matured through SecuBox-OpenWrt and now incarnates as
|
||||
> SecuBox-Deb on Debian bookworm.
|
||||
|
||||
## The frame
|
||||
|
||||
Each SecuBox module exposes its capability through three surfaces:
|
||||
|
||||
1. A **web UI** under `/<module>/` on the admin vhost
|
||||
2. A **FastAPI API** at `/api/v1/<module>/*` over a Unix socket
|
||||
3. A **CTL command** at `/usr/sbin/<module>ctl`
|
||||
|
||||
The CTL is the **grammar** of the system: each verb is a sentence
|
||||
addressed to a specific layer of the operator's expressive control over
|
||||
their own infrastructure. Without the CTL the organ exists but cannot
|
||||
be commanded — instrumentation without préhension.
|
||||
|
||||
## The 8 layers / 8 canonical verbs
|
||||
|
||||
| Layer | Verb |
|
||||
|----------------------|---------------------------------------------------|
|
||||
| ROUTING | `haproxyctl vhost add/remove` |
|
||||
| INTERCEPTION | `mitmproxyctl route add/remove/list` |
|
||||
| REPLICATION | `giteactl repo mirror add/remove/sync` |
|
||||
| IDENTITY | `giteactl user add/remove/passwd` |
|
||||
| CI EXECUTION | `giteactl runner add/remove/list` |
|
||||
| PUBLISHING (bundle) | `publishctl post upload/publish/list` |
|
||||
| PUBLISHING (file) | `dropletctl publish/list/remove/rename` |
|
||||
| PUBLISHING (static) | `metablogizerctl site create/publish/...` |
|
||||
| EMANCIPATE | `metablogizerctl tor expose/revoke/list` |
|
||||
| HOSTING | `streamlitctl app deploy/start/.../info` |
|
||||
| DEV WORKBENCH | `streamforgectl project create/.../templates` |
|
||||
| OPS MONITORING | `healthctl check/list/status/alert` |
|
||||
|
||||
## Composing the grammar
|
||||
|
||||
```bash
|
||||
# WAF un-bypass for a vhost (three layers, three verbs, one operation):
|
||||
haproxyctl vhost add gitea.gk2.secubox.in mitmproxy_inspector ssl
|
||||
mitmproxyctl route add gitea.gk2.secubox.in 192.168.1.200 9080
|
||||
giteactl repo mirror add secubox/secubox-deb \
|
||||
https://github.com/CyberMind-FR/secubox-deb.git \
|
||||
--interval 10m --force
|
||||
```
|
||||
|
||||
```bash
|
||||
# Forge → host → expose pipeline:
|
||||
streamforgectl project create dashboard --template basic
|
||||
streamlitctl app deploy dashboard gitea://secubox/dashboard.git
|
||||
metablogizerctl site publish dashboard
|
||||
metablogizerctl tor expose dashboard # Punk Exposure / Emancipate
|
||||
```
|
||||
|
||||
```bash
|
||||
# Daily ops:
|
||||
healthctl check # 60s pulse on vital services
|
||||
healthctl alert --since 1h
|
||||
```
|
||||
|
||||
## Three-fold pair on every CTL
|
||||
|
||||
Every CTL ships two JSON discovery subcommands:
|
||||
|
||||
- `<x>ctl components` — what processes/sockets/configs back this module
|
||||
- `<x>ctl access` — the API endpoints + CLI subcommands exposed
|
||||
|
||||
Operators learn the grammar by running `<x>ctl access | jq .`.
|
||||
|
||||
## Punk Exposure roots
|
||||
|
||||
The three-verb Punk Exposure pattern (`Peek` / `Poke` / `Emancipate`)
|
||||
predates the CLI grammar — it is the **conceptual seed** that the
|
||||
modular tools box is built around:
|
||||
|
||||
- **Peek** — read state without mutation (the discovery surface)
|
||||
- **Poke** — local mutation under operator control
|
||||
- **Emancipate** — multi-channel exposure (Tor / DNS+SSL / Mesh) that
|
||||
takes the user's data and publishes it on the user's terms
|
||||
|
||||
`metablogizerctl tor expose` is the canonical Emancipate verb at the
|
||||
publishing layer (issue #184).
|
||||
|
||||
## Want to add a 9th verb?
|
||||
|
||||
See `HOWTO-grammar.md` in the repo for the concrete walkthrough (~1h for
|
||||
a Bash CTL, ~2h for Python+FastAPI). The recipe is six steps: frame the
|
||||
gap as an issue, worktree, CTL skeleton, FastAPI mirror, Debian
|
||||
packaging, live test on the board.
|
||||
|
||||
## Attribution
|
||||
|
||||
The SecuBox concept was conceived by **Gérald Kerma (GK²)** in **1991**
|
||||
as a modular tools box for user-controlled digital sovereignty over
|
||||
personal data publishing. The Punk Exposure verbs (Peek / Poke /
|
||||
Emancipate) trace back to that origin. The 8-verb CLI grammar
|
||||
incarnates the same frame on Debian, 35 years later.
|
||||
|
||||
> The CTL is the user's voice.
|
||||
> The modular tools box is their organ.
|
||||
> The language is the way they say *this is mine, this is mine, this is mine*.
|
||||
|
||||
---
|
||||
|
||||
## See also
|
||||
|
||||
- [Acknowledgments](Acknowledgments) — partners and contributors
|
||||
- [[Multi-Agent-Worktree]] — operational workflow for agents adding new
|
||||
verbs without colliding
|
||||
- [Hardware-Matrix](Hardware-Matrix) — boards on which the grammar runs
|
||||
- In-repo: [`docs/grammar.md`](https://github.com/CyberMind-FR/secubox-deb/blob/master/docs/grammar.md),
|
||||
[`HOWTO-grammar.md`](https://github.com/CyberMind-FR/secubox-deb/blob/master/HOWTO-grammar.md)
|
||||
Loading…
Reference in New Issue
Block a user