Skip to content

ledger rung 5 has no auth story: the shipped GUI installs no principal, and RemoteServer would clear one anyway #242

Description

@Yaraslaut

What I found

Rung 5 (examples/ledger) has no authentication or authorization story at all, and the consequence is that every mutating LedgerModel/BudgetModel/RuleModel action fails in the shipped desktop client, in both deployment modes.

Every mutating action in the rung opens with the same gate:

const auto* ctx = morph::session::current();
if (ctx == nullptr || ctx->principal.empty()) {
    throw EmptyPrincipalError{};
}

There are two independent ways rung 5 fails to supply that principal.

1. Local mode: nobody ever installs one

examples/ledger/gui/main.cpp builds an AppContext and four QML bridges, and never calls ctx.login(...). Nothing in examples/ledger/gui_lib/ calls Bridge::setDefaultSession either:

$ grep -rn "login\|setDefaultSession\|principal" examples/ledger/gui_lib/ examples/ledger/gui/main.cpp
examples/ledger/gui/main.cpp:65:        // Nothing is torn down and rebuilt around login: a login only installs

AppContext's default session is empty, so LocalBackend installs an empty session::Context and OpenAccount — the first thing a user does — throws EmptyPrincipalError.

Contrast bookmarks/kanban, whose gui/main.cpp files each mint a Local-mode token and log in explicitly.

2. Remote mode: RemoteServer clears the claim, and there is no server anyway

RemoteServer::dispatchExecute (include/morph/core/remote.hpp) does:

if (auto verified = _authorizer->authenticate(env.session)) {
    env.session.principal = std::move(*verified);
} else {
    env.session.principal.clear();
}

which is correct and deliberate (docs/spec/security.md: never pass an unverified claim through). But IAuthorizer::authenticate's default — and therefore AllowAllAuthorizer's — returns nullopt, so with the allow-all default any principal is cleared. Rung 5 ships no src/auth/, no AuthModel, no Login action and no token secret, so allow-all is the only authorizer it can install.

It also ships no src/server/, so there is no ladder_ledger_server for --server <url> to connect to.

Verification status

Inferred from reading the code, not reproduced by running the GUI. What I did measure, on fix/160-ledger-app-layer (branched from d6690c5): an App dispatching RunReportJob over a RemoteServer with the allow-all default failed with the model's own principal check, which is the same mechanism:

[ERROR] [ledger::App] RunReportJob dispatch failed for job 1: RunReportJob: only the report runner may run a report job

Switching that dispatch to a LocalBackend (which installs the session directly, with no authenticate step) made it pass. That is direct evidence for (2). For (1) I have only the greps above and the gate's source; I did not launch ladder_ledger_gui.

Note that examples/ledger/tests/test_multiclient.cpp uses BackendRig in Mode::Local, so rung 5's own suite has never exercised a RemoteServer carrying a principal — which is why this has stayed invisible.

What would change the verdict

Close this if either turns out to be wrong:

  • launching ladder_ledger_gui and successfully creating an account (would falsify (1));
  • a session path I missed that installs a principal for the rung's bridges.

Otherwise this closes when rung 5 gains a login + authorizer (and, if it is to have a Remote mode at all, a src/server/main.cpp), the way rungs 1-4 each did.

Not folded into #160

Found while implementing #160 (moving the report job out of LedgerModel into an App layer). Per AGENTS.md it is filed rather than fixed there: that PR works around (2) by dispatching over a LocalBackend and says so in examples/ledger/include/ledger/app/app.hpp, and does not touch (1) at all.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: ladderSubsystem: ladderbugSomething isn't workingtriage: validWell-framed; implement as written

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions