Marsad — a desktop client built on "found none" and "nobody looked" being different answers

I’ve been building a desktop Kubernetes client for about a year and released the first version
this week. Rather than list what it does, I’d rather put the one design decision everything else
follows from in front of people who will tell me where it’s wrong.

**

The rule: if a number is on screen, something measured it.**

The failure I kept hitting with every tool I used is that “zero” and “the read failed” render
identically. You look at a panel at 3am, see 0 restarts, and move on — when nobody counted
anything. Same for a clean scan that never ran, and an empty list that was actually a 403.

So in Marsad:

  • A count that could not be read renders as a dash, never 0.

  • A check that could not run is reported separately from a check that ran and found nothing, and
    a report refuses to call itself clean while any check is in the first group.

  • A namespace whose workloads could not be listed is drawn struck through with the reason on it,
    rather than as empty space.

It costs features. There is no cost estimate without configured rates — the sheet says rates are
not set instead of reaching for a typical cloud price. Where other tools show a confident chart,
this sometimes says it does not know.

Deterministic first, model second

There is an AI copilot, and the part I’d defend is what it is not allowed to do.

Diagnosis is a rules engine over objects, not a prompt. “Why is this pod not running” is answered
by comparing requirements against every node and citing the fields it read — including what was
ruled out: “12 nodes checked: 9 lack memory, 2 tainted dedicated=voice:NoSchedule with no
toleration, 1 matches but its PVC is bound in another zone.” The model’s job is to explain that
verdict, never to produce it. Same for the linter, the RBAC answers and the rollback checks: all
deterministic, all working with no provider configured at all.

The copilot also cannot write. Not “is instructed not to” — it holds read capabilities and there
is no write among them. It can propose a change, which becomes a row behind a server-side dry run
and a blast-radius sheet you confirm. The autonomy gate runs as the first statement of the apply
path, before a request is built.

Some of it, concretely

  • Impossible situations — deterministic checks for things that cannot work, split into
    broken-now and breaks-when-something-moves. A PDB whose arithmetic makes eviction impossible
    works perfectly until someone drains a node. Every finding cites the field and the two numbers
    compared; no severity scores.

  • Who can? — RBAC answered as a question, every answer carrying its chain (subject ← binding
    ← role ← the rule verbatim), aggregated ClusterRoles resolved through their selectors, and
    groups reported as opaque because your IdP decides membership, not the cluster.

  • Rollback rehearsal — dry-runs an old ReplicaSet’s pod template against today’s cluster:
    image still in the registry, Secrets and ConfigMaps still present, PSA labels, node fit. Where
    it cannot check (a registry with no credentials) it says so specifically.

  • Flight recorder — a bounded local ring buffer of what its watches saw, so a cluster with no
    observability stack still has thirty minutes of history to scrub back through.

  • Expiry radar — certificates and tokens by horizon, including webhook CA bundles, whose
    expiry takes down every write to the cluster and which almost nothing watches.

Nothing is installed in your cluster. No agent, no operator, no CRD, no webhook. It reads with
your kubeconfig and keeps what it learns in a local SQLite file. That constraint shaped several
features — the recorder exists because the alternative was requiring Prometheus.

Licensing, stated plainly

Marsad is source-available, not open source. The licence (PolyForm Noncommercial 1.0.0) is free
for personal, academic and charitable use, and commercial use needs a separate licence. An
OSI-approved licence cannot forbid commercial use — that’s clause 6 of the OSD — so calling it
open source would be false. I’d rather say that here than have it discovered.

Practical consequence: don’t vendor it into an open source project.

What I’d like

Argument, mostly. The honesty rule is expensive and I’ve had to defend it to myself repeatedly:
it produces screens that say “3 of 8 checks could not run” where a competitor says “all clear”,
and I’m aware that reads as a worse product to someone who hasn’t been burned.

If you run clusters: does the dash-instead-of-zero distinction actually matter to you in practice,
or is it a thing I’ve talked myself into? And is there a category of “cannot work” check you’d
want that isn’t in the list above?

Repo and releases (macOS, Windows, Linux): GitHub - rowbench/marsad · GitHub