Skip to content

Audit fixes: server log, visible answers, wording, accessibility, rename/detach, key file and request boundary, result card - #74

Merged
hyperdrivebeep merged 9 commits into
mainfrom
public-20261112b
Nov 12, 2026
Merged

hyperdrivebeep merged 9 commits into
mainfrom
public-20261112b

Conversation

@hyperdrivebeep

@hyperdrivebeep hyperdrivebeep commented Nov 11, 2026 •

Copy link
Copy Markdown
Owner

First part of the post-beta audit fixes, made in seven batches.

Server log for unexpected failures

  • An unexpected command failure is now written to <workspace>/logs/thoth.log under its operation id. Request strings, token-shaped values and anything past 300 characters are left out of the log.
  • The screen shows the same operation id with the error.
  • A cancel request with a non-JSON body returns 400 instead of 500.

Answer stays visible without a model

  • The question area takes 19–24% of the window instead of 39–48%.
  • A conversation opens at the latest answer.
  • The "no model" notice appears once instead of twice.
  • The send button is named "Send" and says why it is disabled.

Wording

  • Translated the English labels that were hard-coded on screen.
  • Use one Korean word each for "workspace" and "evidence text".
  • Rewrote sentences that used internal terms.
  • Server failures are shown in the screen language.
  • A new test scans the translation tables for banned words and hard-coded labels.

Accessibility

  • Tabs point to their panels.
  • The faint text colour meets 4.5:1 contrast.
  • Elements with a label but no role now have a role.
  • Notices are announced to screen readers.
  • axe reports no violations on 13 screens.

Rename and detach

  • Projects and conversations can be renamed.
  • A source can be detached after a warning that every existing answer will need review.
  • Archive, stop and detach use one in-app confirmation dialog.

Key file and request boundary

  • The API key file is written atomically.
  • A key file that cannot be read is no longer overwritten.
  • On Windows, the key file's ACL is limited to the current user and drops broad groups.
  • Changing requests are accepted only from the server's own origin and the Vite dev origin on port 5173.
  • Local responses send anti-framing and nosniff headers.
  • The local-actor check uses the list of read queries.
  • Staging a file for an unknown project returns 404 once the workspace is open.

Result card

  • The conclusion status and the answer check count appear once.
  • The judgement's own unchecked conditions are named separately from the answer checks.
  • One "technical details" section per card.
  • Action labels say "low risk" and "can run without approval" instead of two near-identical phrases.

Validation: CI ran 7,163 tests with 0 failures. The web suite, axe and mutation checks ran for each batch.

THOTH added 9 commits November 12, 2026 08:00
When a command ended with an unexpected exception, the server returned
"internal command failure" and kept no record of it, so a beta report could
only be investigated by reproducing it. The bus now writes one record per
failure (method, operation id, project id, exception chain, short call path),
and serve/desktop write warnings to the console and to
<workspace>/logs/thoth.log (1 MB, 3 old files). Request string values, token
shaped strings and text past 300 characters are removed from the record.
The screen shows the operation id with an internal failure so a report can be
matched to the log line.

Background indexing and dense scoring failures still do not block requests but
are now recorded once per place. A cancel request with a non-JSON body returns
400 instead of 500.
With no model connected, the question area took 39-48% of the window and the
latest answer showed 22 px at 1440x900 and nothing at smaller sizes; the same
notice appeared twice in the page. The question area now folds the model and
effort choices when there is nothing to choose, keeps one notice, opens a
conversation at the start of the latest answer, names the send button "Send"
with the reason it is off (title and aria-describedby), and outlines the
question box on focus.
Four English labels that were not in the translation tables (Workspace,
PROJECTS, RESEARCH WORKSTATION, LOCAL) and two more found by a new scan are now
translated. One word is used for the workspace (작업 공간) and for evidence text
(근거 원문); fourteen sentences that used internal terms are rewritten; an
unexpected server failure is shown in the screen language with its operation
id; joined sentences, spaces between Japanese and Chinese sentences, and Korean
em dashes are fixed; long help text is split into sentences. A wording test
scans the translation tables for the banned words and the hard-coded labels.
Work tabs now point aria-controls at the panel they show (role=tabpanel with
the same id), the faint text colour rises from 4.28:1 to 5.8:1 contrast, five
elements that had an aria-label without a role get one, 21 failure and success
notices are announced as alert or status, progress bars have names and the
answer check table has proper rows. axe (WCAG 2.x A/AA) reports no violation on
13 screens, down from three kinds on all seven screens checked before.
Projects and conversations can be renamed from their menus, and a connected
source can be detached after a confirmation that says every existing answer in
the project will need review. Archiving, stopping a research run and detaching
use one in-app confirmation dialog instead of window.confirm. The screen shows
a conversation's display_name, counts only attached sources, and marks evidence
from a detached source as detached. No server change.
The API key file is written to a temporary file, flushed and swapped in, and a
key file that cannot be read is no longer overwritten: registering another key
is refused with a message instead of silently dropping the stored keys. On
Windows the key file gets a current-user-only ACL; the ACL code of the provider
profiles moves to one shared module unchanged.

Changing requests are accepted only from the server's own origin and the Vite
dev origins on port 5173 (more local origins through THOTH_ALLOWED_ORIGINS).
Local responses send frame-ancestors 'none', X-Frame-Options, nosniff and
no-referrer. The local-actor check uses the list of read queries instead of a
substring of the method name, and staging a file for a project that does not
exist returns 404 once the workspace is open.
The result card repeated its conclusion status up to four times and used the
word "check" for two different counts, so "needs check 0" sat above six
"still to check" lines. The card now states the conclusion status and the
answer check count once, names the judgement's own unchecked conditions
separately with one line of explanation, keeps one "technical details"
disclosure at the end of the review section, omits the next-action row when
the stored value is NONE, and labels action cards "low risk" and "can run
without approval" instead of two near-identical phrases. No unchecked or held
reason is removed; a test compares the reasons before and after.
… ACL shape

On the GitHub Windows runner the key-file ACL test saw four explicit entries
(the user, SYSTEM, Administrators, OWNER RIGHTS) that come from the DACL Python
3.13 gives a 0o700 pytest folder, where the test expected exactly one. The
test now checks the property that matters: protected, no inherited entry, full
control for the current user, and no other trustee except SYSTEM,
Administrators and OWNER RIGHTS. make_private also removes twelve broad groups
(Everyone, Users, Authenticated Users, ...) if they are set explicitly, in the
same icacls call; SYSTEM and Administrators are kept.
On the runner the current user is the built-in Administrator, which icacls
/save writes as the alias LA while the test named it by its full SID. The test
now turns SDDL aliases into SIDs before comparing, and the decision moves into
a pure function with OS-independent tests, including the runner's exact SDDL.
@hyperdrivebeep hyperdrivebeep changed the title Record unexpected command failures in a server log Audit fixes: server log, visible answers, wording, accessibility, rename/detach, key file and request boundary, result card Nov 12, 2026
@hyperdrivebeep
hyperdrivebeep merged commit a905789 into main Nov 12, 2026
22 checks passed
@hyperdrivebeep
hyperdrivebeep deleted the public-20261112b branch November 12, 2026 10:07
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