Aromba — Website and Dashboard (aro.mba)
One domain, two halves. The website is public and static. The dashboard opens after Telegram login and shows one server. Phone first: people arrive from a Telegram link and want an answer in three seconds. Desktop is a bonus.
1. Website (phase 1)
Pages: home, docs, changelog, security.
Home is one screen: one sentence, the install command in a copy box, a 20-second recording of install → first report, three lines (what it touches, what it never touches, how to stop it), one line on what the AI costs — open models, a few dollars a busy month, paid per question and not by plan, beside what a subscription agent costs (PLAN D236, D282) — and links to GitHub, docs, security.
Docs are the docs/ folder rendered as pages plus a “Write a chore” guide. Changelog is one entry per release, written for users.
2. Login (phase 4)
Through the bot (PLAN D154). The page asks the relay for a code and shows four characters; the person opens t.me/<bot>?start=in_<id>, and the chat asks whether it is them — showing the same four characters. One tap, and the page has a session. No passwords, no email, no phone number, and no script on the page but ours.
The four characters are the security of it, not decoration: anybody can send anybody a t.me link, so a confirmation with nothing to compare would hand a stranger the session for one tap. The chat says what to do when the codes differ.
The Telegram user ID is matched to the chat_id the relay holds for the paired server. No paired server → the install page. Sessions: cookie, 30 days, revoked by /panic and aromba pair, and bound to one page — a dashboard session is not a session on the payment page, in the relay and not only in the browser.
3. The one question
Every page, above the fold, answers “is my server fine?” — one word and one color: Fine / Watch / Trouble, with the reason in one line. Everything else is below.
4. Pages
Space (home)
The server as a place Aromba lives in. After the first scan the daemon classifies the server and the page picks a scene:
| Type | Detected by |
|---|---|
| Empty | nothing running but ssh |
| One app | one web app, one domain |
| Multi-project | several repos / compose files / ports |
| Container farm | many containers, little else |
| Database | a database is the main process |
| Bot host | long-running scripts, no web |
Each scene lays out what was actually found as objects: containers, services, databases, domains, projects, cron jobs. Junk shows as dust on them, alerts as a red glow, fenced folders as locked boxes, quarantine as a bin. Tap an object → its card (status, size, last change, related chores). Scenes ship as SVG first; richer art later.
Empty server is not “coming soon” — it’s the sales moment: “Nothing here yet. Want me to prepare it?” with buttons on the scene: Next.js + Postgres · Telegram bot · Database · Docker host. Each opens the assistant with that request. The scene fills in as things get installed.
Share. One button: a snapshot of the scene with names, paths and domains replaced by generic labels, at aro.mba/s/<id> (opt-in, revocable), with an image card on the same address. This is what people post. Two things make it safe to leave up (PLAN D152, D153): what is published is built from counts and our own labels — an app is app 2, and the types have no field a name could sit in — and it is frozen, drawn once when it is made and never read from the server again. One share of each kind per server; sharing again mints a new address and the old one stops working. A week’s card is the same thing over seven days.
Map
The server as a graph, the thing Telegram can’t show: nodes are services, containers, databases, domains, projects, cron jobs, external APIs the server talks to; edges are who talks to whom, built from ports, compose files, nginx configs, and observed connections. Node size = resources, color = health. Tap a node → its card and its last 24 h. Useful for “what breaks if I stop this” and for showing a teammate how the server is wired.
Built so far (PLAN D155): the doors, not the graph. Every listening TCP port and the program behind it, split into what answers from off the machine and what answers only on loopback — measured with one ss, inferred from nothing. The edges are not drawn and the page says why: this server reads sockets and watches no connections, so a line between two of these would come out of nothing. The rest of this section — edges from compose files and nginx configs, node size, node colour, a node’s last 24 hours — needs the scan to read things it does not read yet, and each of those is a feature of its own.
Health
The lightweight collector (section 6) feeds this. Disk, memory, CPU, load, I/O, network, uptime, failed logins, pending updates, certificate days left — each over 24 h / 7 / 30 / 90 days.
Every chore run, deploy event, alert, ladder step, and update is a mark on the same timeline, so patterns are visible without analysis: the CPU spike at 03:10 sits on top of the “Database dump” mark. The assistant reads the same aggregates and says it in words: “CPU spikes daily at 03:10 — that’s your backup. Memory hasn’t come down since the 14:20 deploy.”
Aromba’s own footprint is a line here too: CPU, memory, disk and network used by Aromba itself this week, against its budget (50 MB idle RAM, 30 MB disk core; skills counted separately). We show it because nobody else does.
Trust
Everything a scared user would want to check, on one screen, without knowing what to ask:
- What Aromba can do on this server: the Warden’s
policy.toml, verbatim, in plain words next to it. - Where it can’t look: the fence list (auto and manual), with “add a folder”.
- Current mode: prod / normal, probation days left, ladder level right now.
- Isolation: caged, or none — on a host without namespaces the Warden runs only green system chores.
- What left the server this week: bytes to the relay, bytes to the AI provider, number of secrets redacted, number of cage violations (should be zero; if not, which chore).
- Last integrity check, Aromba version, signature status.
- Honeypot status: “12 decoys planted, 0 touched”.
- Buttons: Freeze now · Prod mode on/off (PIN) · Export audit.
Jobs
Every chore: color, on/off, trigger, params, last run and result, next run, cage status. Filters by verb, color, source (core / skill / community / mine). Tap → run history, touches, the file, last dry-run output. Toggles and params editable here from the first release, with the same approval and PIN rules as Telegram; red actions still confirm in Telegram.
Receipts
Calendar of days, each day’s receipt in full, search.
Quarantine
Files and folders, size, days to deletion, restore button. In prod mode: “never deleted” badge.
Activity
The journal, live: actor, command or tool, result, redaction count, cage events. Filter by actor: chore / assistant / user / warden.
Skills
Installed skills with weight and permissions; the catalog with search; enable with the same confirmation as Telegram (permissions listed, PIN for root commands); total skills footprint against the user’s skills budget.
Models
Three recommended models balanced for price and quality, refreshed each release, with live price per million tokens and a one-tap “use this”; the user’s own provider list below it; this month’s spend from the daemon’s counter.
Settings
/settings mirrored, editable, same rules as Telegram.
5. Data the relay stores for the dashboard
Sent by the daemon after each run or on change, per server:
Retention is the server’s history window — 30 days on Free, a year on Pro and Teams (11-money.md §5, PLAN D150) — and “current” below means a latest snapshot with no age. Nothing on the server is shortened by it: the journal, the receipts and 90 days of health stay there whatever the tier, and the chat gets all of it.
| Data | Retention |
|---|---|
| Health aggregates: 1-minute points for 24 h, 5-minute for 7 days, hourly beyond | the window |
| Installed skills and their declared weights | current |
| Receipt lines | the window |
| Chore states, params, last results | current |
| Alerts, open and closed | the window |
| Journal lines (redacted on the server) | the window, and never more than 30 days |
| Quarantine index (paths and sizes, not contents) | current |
| Scene and map: object names, types, sizes, edges — no file contents | current |
| Trust page numbers: bytes out, redactions, cage events, ladder level, fence list (paths only) | the window |
Never sent: file contents, logs beyond redacted journal lines, AI prompts and answers, keys, the notebook, honeypot locations, calendar addresses, what is kept from a connected calendar, and the user’s own calendar items. Sync can be turned off in /settings; the dashboard then shows only what the relay already had. Shared snapshots contain generic labels only.
Apart from sync, and only after a yes to the one-time question at the first receipt (03-bot.md settings): one number a night, bytes freed, with a random install id. It feeds the public counter and nothing else.
6. Lightweight collector
The health data must cost nothing noticeable:
- Reads
/proconce a minute (whattopdoes), no agents, no exec of external tools. - ~1 KB per minute written to the local SQLite ring buffer. Down-sampled to 5-minute points after 24 h, hourly after 7 days; each down-sampled point keeps the mean and the maximum — disk and memory are drawn by their maximum, CPU and load by their mean. A year of history is a few megabytes.
- Sends aggregates to the relay once every 5 minutes in one small request, batched with anything else pending.
- Budget for the whole daemon at idle: under 1% of one CPU core, under 50 MB RAM. Chores run at low CPU and I/O priority and pause when the server is busy. The Trust and Health pages show whether we keep this promise.
7. Later
- Several servers per account: Space becomes a street of servers; every page gets a switcher.
- Team access, tied to the sharing design.
- Public “wall of freed space” on the website, opt-in.
- Richer scene art; a scene marketplace alongside the skill catalog.