Skip to content

Logs verify against a set the registry key is not in - #100

Merged
nicodes merged 1 commit into
mainfrom
feat/account-log-key
Aug 8, 2026
Merged

Logs verify against a set the registry key is not in#100
nicodes merged 1 commit into
mainfrom
feat/account-log-key

Conversation

@nicodes

@nicodes nicodes commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Implements nicodes/komizo-be#187 and nicodes/komizo-be#188 — the box half of the account-log-key epic (komizo-be#186).

The problem

komizo-be#180 put the registry key into the one set every route verified against. That is correct for commands — it is what lets any signed-in device work — and wrong for exactly one route.

Logs are the only bytes on a box that never leave it any other way. Reports, history and metrics are pushed to the service by the agent, so it holds them already and a signature changes nothing about who can see them. app-only.md §5 said what that makes logs:

putting the most sensitive bytes on the machine behind the same single env var, and then calling the protection structural, would be false.

Two sets

OperatorKeys carries the registry key. LogKeys is operator keys plus account log keys, and does not.

Built, not filtered. Deriving the log set by removing the registry key from the command set would be shorter and would fail open the day somebody refactors the derivation — and failing open here is silent, because a log that can be read looks exactly like a log that should be readable.

Passed, not defaulted. verifiedRead takes its key set as an argument, so every route names the one it uses and a new route cannot avoid the decision.

Why an account key works where a device key did not

It is portable. The private half comes from a passphrase, so it works on any device the person signs in from. Device keys being per-browser is what broke the product flow and why #180 removed them from the required path.

Planting one is a root action and there is no op that does it. If the service could push a log key it would push its own and read every log, and all of the above would be theatre. TestNoSignedCommandCanPlantALogKey holds the op set to that.

The central test asserts both halves

One key, one box, two routes, opposite answers:

  • the registry key reads the report — without this, everything below passes against a box that is simply broken
  • the registry key cannot read the log
  • the account key does the exact opposite

Asserting only the refusal is this codebases recurring failure: the passing result indistinguishable from the not-running result.

Mutation-tested

mutation result
logs verify against OperatorKeys again (the bug) central test fails
LogTrustedKeys also returns the registry key 2 tests fail
the log-keys-empty guard removed logs refusal test fails
ParseLogKey accepts any prefix prefix test fails
an unreadable log key is skipped all-or-nothing test fails

A box with no log key is normal, not broken

It is every box between #180 and an account setting a passphrase — including the users, the moment this ships. Both enrol and serve say so in their own words, because an empty log screen otherwise sends somebody to the machine to fix something working as designed.

🤖 Generated with Claude Code

komizo-be#180 put the registry key into the one set every route verified
against. Correct for commands -- it is what lets any signed-in device
work -- and wrong for exactly one route.

Logs are the only bytes on a box that never leave it any other way.
Reports, history and metrics are PUSHED to the service by the agent, so
it holds them already and a signature changes nothing about who can see
them. app-only.md §5 said what that makes logs:

  putting the most sensitive bytes on the machine behind the same single
  env var, and then calling the protection structural, would be false.

So there are two sets now. OperatorKeys carries the registry key;
LogKeys is operator keys plus ACCOUNT log keys and does not.

BUILT, NOT FILTERED. Deriving the log set by removing the registry key
from the command set would be shorter and would fail OPEN the day
somebody refactors the derivation -- and failing open here is silent,
because a log that can be read looks exactly like a log that should be
readable.

AND PASSED, NOT DEFAULTED. verifiedRead now takes its key set as an
argument, so every route names the one it uses and a new route cannot
avoid the decision. A default would mean whoever forgot got the wider
set, in the direction that does not announce itself.

An account key is portable where a device key is not: its private half
comes from a passphrase, so it works on any device the person signs in
from. That is the property that makes this possible at all -- it was
device keys being per-browser that broke the product flow in the first
place, and #180 removed them from the required path for that reason.

Planting one is a root action and there is no op that does it. If the
service could push a log key it would push its own, and all of the above
would be theatre. TestNoSignedCommandCanPlantALogKey holds the op set
to it.

The central test asserts BOTH halves on one box: the registry key reads
the report and cannot read the log, and the account key does the
opposite. Asserting only the refusal would pass against a box that
refuses everything, which is this codebase's recurring failure -- the
passing result indistinguishable from the not-running result.

A box that commands and serves no logs is NORMAL, not broken. It is
every box between #180 and an account setting a passphrase. Both enrol
and serve say so in their own words, because an empty log screen
otherwise sends somebody to the machine to fix something that is working
as designed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@nicodes
nicodes merged commit e40136e into main Aug 8, 2026
2 checks passed
@nicodes
nicodes deleted the feat/account-log-key branch August 8, 2026 19:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant