Skip to content

fix: make the panel usable on a phone, and show every page in the docs - #40

Merged
JarbasAl merged 3 commits into
devfrom
fix/mobile-navigation
Aug 12, 2026
Merged

fix: make the panel usable on a phone, and show every page in the docs#40
JarbasAl merged 3 commits into
devfrom
fix/mobile-navigation

Conversation

@JarbasAl

@JarbasAl JarbasAl commented Aug 12, 2026

Copy link
Copy Markdown
Member

🤖 Auto-generated by Claude Opus 5 (claude-opus-5) via Claude Code — NOT human-reviewed. Verify before acting. Found by driving the real deployment at hivemind.openvoiceos.pt with a phone viewport; every screenshot here is that deployment, not a mock.

The panel did not work on a phone

Not "looked cramped" — did not work. The stylesheet had a 768px breakpoint that slid the sidebar off-screen and waited for a .sidebar.open class:

.sidebar { transform: translateX(-100%); }
.sidebar.open { transform: translateX(0); }

Nothing ever added that class. grep -rn "sidebar.open\|hamburger\|toggleSidebar" across the markup and both JS files returned nothing. So on a phone you signed in, landed on the dashboard, and could not reach a single other page — Playwright's diagnosis was blunt: element is outside of the viewport.

Fixed with the control the stylesheet was already written for: a ☰ in the topbar under 768px, a backdrop, an Escape binding, and auto-close when a destination is picked (a drawer that covers the page you just asked for is its own bug).

Two layout bugs behind it

Wide content dragged the page sideways. Measured: clients overflowed by 398px, monitor by 2838px, so the layout slid out from under the sticky topbar. The fix that matters is min-width: 0 on the layout chain — a grid child defaults to min-width: auto, so a wide table widens its ancestors rather than letting the scroll container do its job. Tables now scroll inside their own box; logs and key material wrap.

The topbar had a fixed height: 64px. Once its controls wrapped to a second row, the sticky bar kept that height and painted its overflow straight over the first card — the status pill landed on top of the security banner. Visible in the before/after captures.

before after
page overflow, clients 398px 0
page overflow, monitor 2838px 0
pages reachable on a phone 1 of 16 16 of 16

Docs

Every page now shows the screen it describes, at widescreen and on a phone — 35 screenshots from the live deployment. Downscaled and palette-reduced to 2.2MB total rather than the 8MB they came out at.

Troubleshooting gains the five failures I actually hit running this thing today, which is the useful kind:

  • a reinstalled satellite that can never reconnect → hivemind-core reset-noise-pin
  • Address already in use on 5678 → the panel owns the hub in-process; a second hivemind-core service cannot also have it
  • an upgrade that leaves the hub on an old version → in-process mode runs the hub from the panel's venv, and the panel's own pins constrained it
  • a crash loop naming a missing plugin → optional STT/TTS/VAD plugins are not dependencies of what you upgraded, and the binary protocol raises KeyError: 'vad' rather than falling back
  • this mobile bug

Verification

  • panel suite: 243 passed
  • a Playwright regression check against the live panel: desktop hides the hamburger and has zero overflow; on a phone the drawer opens, navigates, and closes on eight different pages with worst-case overflow 0px
  • all internal links and all 49 image references resolve; every page carries a nav footer except the index, which is the map

Summary by CodeRabbit

  • Documentation

    • Added widescreen and mobile screenshots, diagrams, and interface previews throughout the documentation.
    • Expanded troubleshooting guidance for installation, networking, plugin, and mobile navigation issues.
  • Enhancements

    • Improved mobile responsiveness across the admin interface.
    • Added an accessible collapsible mobile sidebar with backdrop support, Escape-key closing, and automatic navigation closing.
    • Improved narrow-screen layouts, tables, long text, modals, and wrapped controls.
  • Changes

    • Removed the websocket TLS status self-check from the security checks.

Mobile navigation was broken outright. The stylesheet had a 768px breakpoint
that slid the sidebar off-screen and waited for a .sidebar.open class, but
nothing in the markup or the JS ever added it and there was no control to
trigger it. On a phone you signed in, landed on the dashboard, and could not
reach a single other page — the nav buttons were laid out beyond the viewport.

- add a hamburger in the topbar, shown only under 768px, with a backdrop, an
  Escape binding, and auto-close when a destination is picked
- stop wide content dragging the page sideways. The clients page overflowed by
  398px and the monitor by 2838px, so the layout slid out from under the
  sticky topbar. min-width:0 on the layout chain is the load-bearing part: a
  grid child defaults to min-width:auto, so a wide table widens its ancestors
  instead of letting the scroll container work
- the topbar had a fixed 64px height. Once its controls wrapped to a second
  row the sticky bar painted its overflow over the first card

Docs: every page now shows the screen it describes, at widescreen and on a
phone, captured from a real deployment rather than mocked. Troubleshooting
gains the five failures actually hit while running this: a reinstalled
satellite that cannot reconnect (reset-noise-pin), two services fighting over
5678, an upgrade that leaves the hub on an old version because the panel's own
pins hold it back, a crash loop after optional plugins go missing, and this
mobile bug.

Screenshots are downscaled and palette-reduced: 35 images, 2.2MB.
@github-actions github-actions Bot added the fix label Aug 12, 2026
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The panel adds mobile sidebar controls and broader responsive layout rules. The security checks no longer report websocket TLS status. Documentation pages add widescreen and mobile interface previews and troubleshooting guidance.

Changes

Responsive panel and documentation

Layer / File(s) Summary
Mobile sidebar controls and responsive layout
hivemind_admin_panel/static/index.html, hivemind_admin_panel/static/css/style.css, hivemind_admin_panel/static/js/app.js
The panel adds a mobile sidebar toggle, backdrop, ARIA state updates, Escape handling, navigation closing, and responsive layout rules for tables, text, grids, and modals.
Websocket TLS self-check removal
hivemind_admin_panel/api.py
The security checks stop calculating and reporting websocket TLS status. Comments state that HiveMind payloads use protocol-level encryption.
Widescreen and mobile documentation previews
docs/*.md
Documentation pages add “What it looks like” sections with widescreen and mobile screenshots, diagrams, and interface previews.
Troubleshooting guidance
docs/index.md, docs/troubleshooting.md
The documentation adds guidance for satellite reconnection, port conflicts, stale versions, plugin failures, binary-protocol configuration, and mobile navigation limits.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant AdminPanelUser
  participant NavigationToggle
  participant SidebarController
  participant Sidebar
  participant Backdrop
  AdminPanelUser->>NavigationToggle: Click menu button
  NavigationToggle->>SidebarController: Call toggleSidebar()
  SidebarController->>Sidebar: Toggle open state
  SidebarController->>Backdrop: Toggle visibility
  SidebarController->>NavigationToggle: Update aria-expanded
  AdminPanelUser->>Backdrop: Click backdrop
  Backdrop->>SidebarController: Call closeSidebar()
  SidebarController->>Sidebar: Remove open state
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes both main changes: mobile panel usability and expanded documentation coverage.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/mobile-navigation

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Aug 12, 2026

Copy link
Copy Markdown

Beep boop! Here's the latest status of your PR checks. 🤖

I've aggregated the results of the automated checks for this PR below.

🔍 Lint

A quick update on the progress of your PR checks. 📈

ruff: issues found — see job log

📋 Repo Health

The repo's annual physical is complete! 🩺

✅ All required files present.

Latest Version: 0.1.10a1

hivemind_admin_panel/version.py — Version file
README.md — README
LICENSE — License file
pyproject.toml — pyproject.toml
⚠️ setup.py — setup.py
🗑️ requirements.txt — legacy: pyproject.toml is present; this file is no longer needed
CHANGELOG.md — Changelog
hivemind_admin_panel/version.py has valid version block markers

🏷️ Release Preview

Predicting the ripple effect of this release. 🌊

Current: 0.1.10a1Next: 0.1.11a1

Signal Value
Label fix
PR title fix: make the panel usable on a phone, and show every page in the docs
Bump build

✅ PR title follows conventional commit format.


🚀 Release Channel Compatibility

Predicted next version: 0.1.11a1

Channel Status Note Current Constraint
Stable Not in channel -
Testing Not in channel -
Alpha Not in channel -

📊 Coverage

Ensuring our code is as robust as it looks. 💎

⚠️ 76.7% total coverage

Per-file coverage (8 files)
File Coverage Missing lines
hivemind_admin_panel/__init__.py 40.0% 12
hivemind_admin_panel/_chat.py 46.3% 51
hivemind_admin_panel/_persona_chat.py 48.1% 42
hivemind_admin_panel/__main__.py 78.1% 28
hivemind_admin_panel/api.py 78.5% 522
hivemind_admin_panel/_auth.py 82.6% 21
hivemind_admin_panel/_metrics.py 86.0% 7
hivemind_admin_panel/version.py 100.0% 0

Full report: download the coverage-report artifact.

🔨 Build Tests

Checking if the gears are still turning smoothly... ⚙️

✅ All versions pass

Python Build Install Tests
3.10
3.11
3.12
3.13

⚖️ License Check

Keeping the lawyers happy, one file at a time. 👔

✅ No license violations found.

Policy: Apache 2.0 (universal donor). StrongCopyleft / NetworkCopyleft / WeakCopyleft / Other / Error categories fail. MPL allowed.

🔒 Security (pip-audit)

I've checked for any insecure file permissions. 📂

✅ No known vulnerabilities found (99 packages scanned).


Your automated guardian for repository health 🛡️

@github-actions github-actions Bot added fix and removed fix labels Aug 12, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (1)
docs/troubleshooting.md (1)

159-162: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add language identifiers to diagnostic output fences.

markdownlint reports MD040 for both fences. Add text to each opening fence.

  • docs/troubleshooting.md#L159-L162: change the opening fence to ````text`.
  • docs/troubleshooting.md#L229-L233: change the opening fence to ````text`.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/troubleshooting.md` around lines 159 - 162, Update the opening
diagnostic-output fences in docs/troubleshooting.md at lines 159-162 and 229-233
to specify the text language identifier, changing each plain fence to a text
fence.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/api-reference.md`:
- Around line 69-75: Replace the promotional or purpose-based screenshot alt
text with concise visual descriptions: in docs/api-reference.md lines 69-75,
describe the dashboard elements visible in both widescreen and mobile images; in
docs/cli.md lines 95-101, describe the Clients page, its list, and visible
controls; and in docs/glossary.md lines 139-145, describe the visible dashboard
content rather than mentioning glossary terms.

In `@docs/bridges.md`:
- Around line 79-87: Update the “What it looks like” preview in docs/bridges.md
to use bridge-specific widescreen and mobile image assets with captions
describing the bridge UI, or remove the preview section until those assets are
available; do not retain the Agent Protocol images or captions.

In `@docs/index.md`:
- Line 14: Change the “What it looks like” heading from H3 to H2 so the document
heading hierarchy follows the existing H1 without skipping a level.

In `@hivemind_admin_panel/static/css/style.css`:
- Around line 884-902: Update the mobile overlay stacking in .sidebar-backdrop
and the responsive .sidebar rules: assign the backdrop a z-index above the
.topbar’s 100 level, then assign the sidebar a still higher z-index so it
renders above the backdrop and prevents topbar interaction while the drawer is
open.
- Around line 966-974: Replace the deprecated word-break declaration in the
pre/code/.log-entry/.monitor-log rule with overflow-wrap: anywhere, preserving
the existing max-width, horizontal overflow, and whitespace behavior.

In `@hivemind_admin_panel/static/js/app.js`:
- Around line 4618-4654: Update openSidebar() to focus the first .nav-item after
opening and set `#navToggle`’s accessible label to “Close navigation”; update
closeSidebar() to restore focus to `#navToggle` when the active element is inside
`#sidebar` and reset the label to its closed-state value, preserving the existing
drawer class and aria-expanded behavior.

---

Nitpick comments:
In `@docs/troubleshooting.md`:
- Around line 159-162: Update the opening diagnostic-output fences in
docs/troubleshooting.md at lines 159-162 and 229-233 to specify the text
language identifier, changing each plain fence to a text fence.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2ed7f656-63af-4327-95bf-bd550e758456

📥 Commits

Reviewing files that changed from the base of the PR and between df1911c and 9789b1c.

⛔ Files ignored due to path filters (35)
  • docs/img/acl-mobile.png is excluded by !**/*.png
  • docs/img/acl.png is excluded by !**/*.png
  • docs/img/agents-mobile.png is excluded by !**/*.png
  • docs/img/agents.png is excluded by !**/*.png
  • docs/img/binary-mobile.png is excluded by !**/*.png
  • docs/img/binary.png is excluded by !**/*.png
  • docs/img/chat-mobile.png is excluded by !**/*.png
  • docs/img/chat.png is excluded by !**/*.png
  • docs/img/clients-mobile.png is excluded by !**/*.png
  • docs/img/clients.png is excluded by !**/*.png
  • docs/img/dashboard-mobile.png is excluded by !**/*.png
  • docs/img/dashboard.png is excluded by !**/*.png
  • docs/img/database-mobile.png is excluded by !**/*.png
  • docs/img/database.png is excluded by !**/*.png
  • docs/img/encodings-mobile.png is excluded by !**/*.png
  • docs/img/encodings.png is excluded by !**/*.png
  • docs/img/login-mobile.png is excluded by !**/*.png
  • docs/img/login.png is excluded by !**/*.png
  • docs/img/monitor-mobile.png is excluded by !**/*.png
  • docs/img/monitor.png is excluded by !**/*.png
  • docs/img/nav-drawer-mobile.png is excluded by !**/*.png
  • docs/img/network-mobile.png is excluded by !**/*.png
  • docs/img/network.png is excluded by !**/*.png
  • docs/img/ops-mobile.png is excluded by !**/*.png
  • docs/img/ops.png is excluded by !**/*.png
  • docs/img/personas-mobile.png is excluded by !**/*.png
  • docs/img/personas.png is excluded by !**/*.png
  • docs/img/presets-mobile.png is excluded by !**/*.png
  • docs/img/presets.png is excluded by !**/*.png
  • docs/img/servers-mobile.png is excluded by !**/*.png
  • docs/img/servers.png is excluded by !**/*.png
  • docs/img/topology-mobile.png is excluded by !**/*.png
  • docs/img/topology.png is excluded by !**/*.png
  • docs/img/voice-plugins-mobile.png is excluded by !**/*.png
  • docs/img/voice-plugins.png is excluded by !**/*.png
📒 Files selected for processing (24)
  • docs/api-reference.md
  • docs/architecture.md
  • docs/bridges.md
  • docs/cli.md
  • docs/concepts.md
  • docs/configuration.md
  • docs/deployment.md
  • docs/development.md
  • docs/extending.md
  • docs/getting-started.md
  • docs/glossary.md
  • docs/index.md
  • docs/operations.md
  • docs/ovos-servers.md
  • docs/presets.md
  • docs/roadmap.md
  • docs/running.md
  • docs/security.md
  • docs/test-chat.md
  • docs/troubleshooting.md
  • docs/tutorial.md
  • hivemind_admin_panel/static/css/style.css
  • hivemind_admin_panel/static/index.html
  • hivemind_admin_panel/static/js/app.js

Comment thread docs/api-reference.md
Comment on lines +69 to +75
**Widescreen**

![Every panel screen is this API with a face on it (widescreen)](img/dashboard.png)

**Mobile**

![Every panel screen is this API with a face on it (mobile)](img/dashboard-mobile.png)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use visual descriptions for screenshot alt text.

The new alt text describes page purpose or uses promotional wording instead of describing the visible interface.

  • docs/api-reference.md#L69-L75: describe the dashboard elements visible in both screenshots.
  • docs/cli.md#L95-L101: describe the Clients page, its list, and visible controls.
  • docs/glossary.md#L139-L145: describe the dashboard content instead of stating that glossary terms appear there.
📍 Affects 3 files
  • docs/api-reference.md#L69-L75 (this comment)
  • docs/cli.md#L95-L101
  • docs/glossary.md#L139-L145
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/api-reference.md` around lines 69 - 75, Replace the promotional or
purpose-based screenshot alt text with concise visual descriptions: in
docs/api-reference.md lines 69-75, describe the dashboard elements visible in
both widescreen and mobile images; in docs/cli.md lines 95-101, describe the
Clients page, its list, and visible controls; and in docs/glossary.md lines
139-145, describe the visible dashboard content rather than mentioning glossary
terms.

Comment thread docs/bridges.md Outdated
Comment on lines +79 to +87
### What it looks like

**Widescreen**

![Agent Protocol: the AI backend answering for the hive (widescreen)](img/agents.png)

**Mobile**

![Agent Protocol: the AI backend answering for the hive (mobile)](img/agents-mobile.png)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use bridge screenshots on the Chat bridges page.

The new preview links agents.png and agents-mobile.png, and both captions identify the Agent Protocol UI. Use bridge-specific widescreen and mobile images, or remove this preview until those assets exist.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/bridges.md` around lines 79 - 87, Update the “What it looks like”
preview in docs/bridges.md to use bridge-specific widescreen and mobile image
assets with captions describing the bridge UI, or remove the preview section
until those assets are available; do not retain the Agent Protocol images or
captions.

Comment thread docs/index.md
![Dashboard](img/dashboard.png)


### What it looks like

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fix the heading level for What it looks like.

The page starts with an H1 and has no H2 before Line 14, so ### skips a heading level. Change it to ##, or add an H2 parent.

Suggested fix
-### What it looks like
+## What it looks like
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
### What it looks like
## What it looks like
🧰 Tools
🪛 markdownlint-cli2 (0.23.2)

[warning] 14-14: Heading levels should only increment by one level at a time
Expected: h2; Actual: h3

(MD001, heading-increment)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/index.md` at line 14, Change the “What it looks like” heading from H3 to
H2 so the document heading hierarchy follows the existing H1 without skipping a
level.

Source: Linters/SAST tools

Comment thread hivemind_admin_panel/static/css/style.css Outdated
Comment on lines +966 to +974
pre,
code,
.log-entry,
.monitor-log {
max-width: 100%;
overflow-x: auto;
white-space: pre-wrap;
word-break: break-word;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

npx --no-install stylelint hivemind_admin_panel/static/css/style.css
rg -n 'word-break:\s*break-word' hivemind_admin_panel/static/css/style.css

Repository: JarbasHiveMind/hivemind-admin-panel

Length of output: 1113


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- matching declarations ---'
rg -n -C 3 'word-break\s*:\s*break-word|overflow-wrap\s*:\s*anywhere' hivemind_admin_panel/static/css/style.css || true

printf '%s\n' '--- stylelint configuration files ---'
git ls-files | rg '(^|/)(stylelint|\.stylelintrc)([^/]*|/.*)$|package\.json$' || true

printf '%s\n' '--- repository references to the rule or value ---'
rg -n 'declaration-property-value-disallowed-list|word-break|break-word|overflow-wrap' --glob '!hivemind_admin_panel/static/css/style.css' . || true

Repository: JarbasHiveMind/hivemind-admin-panel

Length of output: 1213


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- package.json ---'
cat package.json

printf '%s\n' '--- tracked Stylelint-related files ---'
git ls-files | rg -i 'stylelint|\.stylelintrc|package-lock|npm-shrinkwrap|yarn\.lock|pnpm-lock' || true

Repository: JarbasHiveMind/hivemind-admin-panel

Length of output: 697


🌐 Web query:

MDN CSS word-break break-word deprecated value overflow-wrap anywhere

💡 Result:

The CSS value word-break: break-word is deprecated [1][2][3]. It is maintained in specifications primarily for legacy compatibility [2][4]. Modern CSS development should avoid using word-break: break-word [5]. Instead, authors should use the overflow-wrap property [3], specifically: 1. overflow-wrap: anywhere: This is the modern, recommended way to ensure long words or strings do not overflow their container [6]. It allows the browser to break lines at any point if no other break opportunities exist [6]. Unlike overflow-wrap: break-word, it considers these breaks when calculating the min-content intrinsic size of the element, which often leads to more predictable layouts in modern layout systems like Flexbox or Grid [6][7]. 2. overflow-wrap: break-word: This remains a valid option if you want the browser to prevent overflow while keeping the soft wrap opportunities from being considered in min-content size calculations [6]. The deprecated word-break: break-word behaves identically to overflow-wrap: anywhere (combined with word-break: normal) [1][8][9]. Because overflow-wrap: anywhere provides the same behavior with standard, non-deprecated syntax, it is the preferred replacement [3].

Citations:


Replace the deprecated word-break value.

Use overflow-wrap: anywhere for equivalent long-token wrapping.

🧰 Tools
🪛 Stylelint (17.14.0)

[error] 973-973: Deprecated keyword "break-word" for property "word-break" (declaration-property-value-keyword-no-deprecated)

(declaration-property-value-keyword-no-deprecated)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@hivemind_admin_panel/static/css/style.css` around lines 966 - 974, Replace
the deprecated word-break declaration in the pre/code/.log-entry/.monitor-log
rule with overflow-wrap: anywhere, preserving the existing max-width, horizontal
overflow, and whitespace behavior.

Source: Linters/SAST tools

Comment thread hivemind_admin_panel/static/js/app.js
An adversarial review drove the live panel across 8 viewports and refuted the
previous claim: on a 360x640 phone six of sixteen destinations were still
unreachable, because the drawer itself never scrolled.

Blockers fixed:
- the drawer scrolls (100dvh + overflow-y). 16 nav items and a footer are
  taller than a short phone; nothing clipped or scrolled them, so Presets
  through Operations and the theme/logout footer were simply off the bottom
- the drawer sits above the topbar (z-index 200 vs 100). Equal z-index with
  the topbar later in the DOM meant a tap in the top 17px of the first nav
  item silently hit the header instead
- opening the drawer moves focus into it. Tabbing from the toggle walked past
  the drawer entirely — it is earlier in the DOM — and landed on the
  destructive Restart button behind an opaque backdrop
- a closed drawer leaves the tab order (inert + aria-hidden). Six invisible
  controls came before any page content
- the toggle relabels itself Open/Close instead of always saying Open
- the page no longer scrolls underneath the backdrop
- landscape phones get the drawer: the query is now max-width 768px OR a short
  landscape viewport. At 844x390 none of the mobile CSS applied and the
  monitor overflowed by 2676px
- modals are a flex column, so the body scrolls and the footer stays put. In
  landscape the footer sat below the modal and Save could not be reached
- the min-width:0 containment and the topbar wrap moved OUT of the phone
  query. Scoped to <=768 they left 769px and every tablet overflowing, and
  the monitor still slid 960px sideways at 2560

Also: the dashboard no longer nags about websocket TLS. HiveMind encrypts its
payloads end to end — AES session key on v1/v2, Noise on v3 — so ws:// is not
cleartext. Flagging it taught operators to add TLS for a problem they did not
have.

Docs: duplicate screenshots removed, the bridges page no longer illustrated
with an unrelated screen, the drawer screenshot now documents the drawer, and
the five orphan images are placed. No orphans, no duplicates, no broken refs.
The committed images still showed the TLS banner that was removed, and the
pre-fix topbar. Recaptured from the live deployment with the final CSS.
@github-actions github-actions Bot added fix and removed fix labels Aug 12, 2026
@JarbasAl
JarbasAl merged commit 1f567d2 into dev Aug 12, 2026
13 checks passed
@JarbasAl
JarbasAl deleted the fix/mobile-navigation branch August 12, 2026 20:14

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/getting-started.md (1)

68-74: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Complete the widescreen preview section.

The visible Widescreen label is followed by no image or explanation. If img/login.png is the intended widescreen preview, state that it appears above or move the image into this subsection.

Proposed fix
 **Widescreen**
 
-<!-- duplicate screenshot removed -->
+The widescreen sign-in screen is shown above.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/getting-started.md` around lines 68 - 74, Complete the Widescreen
section in the getting-started documentation by restoring or adding the intended
img/login.png preview, or explicitly explaining where it appears. Keep the
existing Mobile subsection and its img/login-mobile.png image unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@hivemind_admin_panel/api.py`:
- Around line 5037-5041: Revise the websocket security handling around the
protocol-version transport check: retain core_tls or an equivalent
transport-security validation instead of claiming ws:// is always safe. Update
docs/security.md to accurately describe handshake metadata and
endpoint-authentication risks across v0–v3, and add regression tests enforcing
the minimum supported protocol security behavior.

In `@hivemind_admin_panel/static/js/app.js`:
- Around line 4628-4648: Update openSidebar() to keep keyboard focus within
`#sidebar` while it is open by making outside content inert or implementing a
focus trap, including wrapping Tab navigation from the last control to the
first. Update the Escape-key listener near the related sidebar handlers so it
dismisses the drawer only when focus is within the drawer context, and restore
outside interactivity when closing.
- Around line 4674-4684: The _syncSidebarInertness function must fully close and
reset the drawer when transitioning from mobile to desktop, clearing the
sidebar’s open/visible state, aria-expanded value, backdrop, and document.body
scroll lock while retaining the existing inert and aria-hidden synchronization.

---

Outside diff comments:
In `@docs/getting-started.md`:
- Around line 68-74: Complete the Widescreen section in the getting-started
documentation by restoring or adding the intended img/login.png preview, or
explicitly explaining where it appears. Keep the existing Mobile subsection and
its img/login-mobile.png image unchanged.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: bfaeb3ba-967b-4a59-9a73-8cfcbc9fdae5

📥 Commits

Reviewing files that changed from the base of the PR and between 9789b1c and db3da9e.

⛔ Files ignored due to path filters (32)
  • docs/img/acl-mobile.png is excluded by !**/*.png
  • docs/img/agents-mobile.png is excluded by !**/*.png
  • docs/img/agents.png is excluded by !**/*.png
  • docs/img/binary-mobile.png is excluded by !**/*.png
  • docs/img/binary.png is excluded by !**/*.png
  • docs/img/chat-mobile.png is excluded by !**/*.png
  • docs/img/clients-mobile.png is excluded by !**/*.png
  • docs/img/clients.png is excluded by !**/*.png
  • docs/img/dashboard-mobile.png is excluded by !**/*.png
  • docs/img/dashboard.png is excluded by !**/*.png
  • docs/img/database-mobile.png is excluded by !**/*.png
  • docs/img/database.png is excluded by !**/*.png
  • docs/img/encodings-mobile.png is excluded by !**/*.png
  • docs/img/encodings.png is excluded by !**/*.png
  • docs/img/login-mobile.png is excluded by !**/*.png
  • docs/img/login.png is excluded by !**/*.png
  • docs/img/monitor-mobile.png is excluded by !**/*.png
  • docs/img/monitor.png is excluded by !**/*.png
  • docs/img/nav-drawer-mobile.png is excluded by !**/*.png
  • docs/img/network-mobile.png is excluded by !**/*.png
  • docs/img/network.png is excluded by !**/*.png
  • docs/img/ops-mobile.png is excluded by !**/*.png
  • docs/img/ops.png is excluded by !**/*.png
  • docs/img/personas-mobile.png is excluded by !**/*.png
  • docs/img/presets-mobile.png is excluded by !**/*.png
  • docs/img/presets.png is excluded by !**/*.png
  • docs/img/servers-mobile.png is excluded by !**/*.png
  • docs/img/servers.png is excluded by !**/*.png
  • docs/img/topology-mobile.png is excluded by !**/*.png
  • docs/img/topology.png is excluded by !**/*.png
  • docs/img/voice-plugins-mobile.png is excluded by !**/*.png
  • docs/img/voice-plugins.png is excluded by !**/*.png
📒 Files selected for processing (14)
  • docs/bridges.md
  • docs/concepts.md
  • docs/configuration.md
  • docs/deployment.md
  • docs/getting-started.md
  • docs/index.md
  • docs/operations.md
  • docs/presets.md
  • docs/running.md
  • docs/troubleshooting.md
  • docs/tutorial.md
  • hivemind_admin_panel/api.py
  • hivemind_admin_panel/static/css/style.css
  • hivemind_admin_panel/static/js/app.js
🚧 Files skipped from review as they are similar to previous changes (10)
  • docs/configuration.md
  • docs/bridges.md
  • docs/index.md
  • docs/deployment.md
  • docs/running.md
  • docs/concepts.md
  • docs/tutorial.md
  • docs/troubleshooting.md
  • docs/presets.md
  • hivemind_admin_panel/static/css/style.css

Comment on lines +5037 to +5041
# There is deliberately no check for websocket TLS. HiveMind encrypts its
# own payloads end to end — an AES session key on protocol v1/v2 and the
# Noise transport on v3 — so ws:// is not cleartext and a satellite on a
# plain socket is not exposed. Flagging it taught operators to add TLS for
# a problem they did not have, and trained them to ignore this panel.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

rg -n -C 6 '\bcore_tls\b|setup/status|setup_acked|\bchecks\b' \
  --glob '*.py' --glob '*.js' --glob '*.html' --glob '*.md' . || true

rg -n -C 8 'hivemind-core|Noise|AES|session key|ws://|wss://|websocket|tls|SSL' \
  --glob '*.py' --glob '*.toml' --glob '*.yaml' --glob '*.yml' .

Repository: JarbasHiveMind/hivemind-admin-panel

Length of output: 50394


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- package declarations ---'
rg -n -C 3 'hivemind-core|hivemind_core' pyproject.toml setup.py setup.cfg requirements\* *.toml 2>/dev/null || true

printf '%s\n' '--- security-check implementation and consumers ---'
sed -n '4980,5110p' hivemind_admin_panel/api.py
rg -n -C 4 'admin_password|bind_host|core_tls|checks\.|checks\]|secure|clean|warnings' \
  hivemind_admin_panel tests docs --glob '*.py' --glob '*.js' --glob '*.html' --glob '*.md'

printf '%s\n' '--- protocol and connection configuration references ---'
rg -n -C 5 'protocol_version|protocol|session_key|AES|Noise|websocket|ws://|wss://|tls|ssl|cert' \
  hivemind_admin_panel tests docs pyproject.toml setup.py setup.cfg requirements\* 2>/dev/null \
  --glob '*.py' --glob '*.js' --glob '*.md' --glob '*.toml' --glob '*.yaml' --glob '*.yml' | head -n 1000

printf '%s\n' '--- tracked files that may contain vendored core code ---'
git ls-files | rg '(^|/)(hivemind_core|hivemind-core|protocol|transport|websocket|crypto|security)(/|\.|$)' | head -n 300

Repository: JarbasHiveMind/hivemind-admin-panel

Length of output: 50394


🌐 Web query:

hivemind-core protocol v1 v2 AES session key v3 Noise websocket TLS encryption authentication

💡 Result:

The HiveMind-core protocol architecture manages communication security through versioned handshake and encryption standards [1][2]. Protocol versions are negotiated at connection time [1]: Protocol Versions and Encryption: - v0: Legacy/Deprecated. Uses JSON-only encoding and a pre-shared AES key without a handshake, providing no forward secrecy [1][2][3]. - v1/v2: Handshake-based. v1 uses JSON-based communication (with binary framing optional in v2), authenticated via PBKDF2-SHA256 password hashes or RSA handshakes to derive session keys [1][4][5]. After the handshake, payload encryption is performed using negotiated ciphers [4]. - v3: Modern/Recommended. Employs a Noise-based handshake (typically Noise_XXpsk2_25519_ChaChaPoly_SHA256) [1]. It is always encrypted, utilizes binary framing, and requires a shared password for the PSK [1][2]. Authentication and Key Exchange: - Authentication is handled via API keys paired with either passwords or pre-shared keys [3]. - In v1/v2, the password itself is never transmitted; instead, both sides derive a shared session key through a handshake [4][3]. - For v3, the Noise protocol provides the cryptographic handshake to establish an encrypted session [1][5]. Transport and Security: - WebSocket/TLS: The reference transport is the hivemind-websocket-plugin [6]. While the protocol supports standard ws:// connections, TLS encryption (wss://) can be enabled in server.json by setting ssl to true and configuring the certificate directory [6]. - Cipher Negotiation: For v1/v2, the server and client negotiate an encryption cipher from an allowed list, defaulting to ["CHACHA20-POLY1305", "AES-GCM"] [4][7][8]. v3 natively handles the cipher suite via the Noise handshake [1]. Operators can enforce minimum security standards by setting the min_protocol_version in the server configuration [4][8]. Setting this to 3 forces all clients to use the modern, Noise-encrypted v3 protocol [4].

Citations:


🌐 Web query:

site:github.com/JarbasHiveMind hivemind-core Noise protocol AES websocket

💡 Result:

In hivemind-core, the integration of the Noise protocol, AES, and WebSockets forms the foundation of its secure communication architecture, primarily implemented in protocol version 3 [1]. WebSockets act as the transport layer, with the hivemind-websocket-protocol serving as the reference implementation for persistent connections between satellites and the hub [2][3]. The Noise protocol is used for an authenticated key exchange during the handshake process, which enables the establishment of an always-encrypted session [1][4]. Specifically, it utilizes the poorman_handshake library, which wraps the vetted noiseprotocol library (leveraging pyca/cryptography) to support patterns like KK_PSK0 and XX_PSK2 [4]. This v3 protocol handshake handles the security negotiation, binding, and session key derivation [1]. Once the Noise handshake is complete, the session transitions to using AES (specifically AES-GCM) for transport encryption [1][5]. In v3 connections, this Noise-based transport layer provides replay-resistant, sequential encryption for all subsequent communication, replacing the legacy AEAD-based crypto methods used in earlier protocol versions [1][5].

Citations:


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- local manifests ---'
fd -a -t f '^(pyproject\.toml|setup\.py|setup\.cfg|requirements.*|Pipfile|poetry\.lock)$' . \
  -x sh -c 'echo "--- $1"; rg -n -C 3 "hivemind.?core|hivemind.?websocket|hivemind" "$1"' sh {}

printf '%s\n' '--- exact local core_tls references ---'
rg -n -C 3 '\bcore_tls\b' . || true

printf '%s\n' '--- stale transport-TLS documentation ---'
rg -n -C 4 'websocket has TLS|websocket TLS|wss://|server\.json.*ssl|TLS configured' \
  docs hivemind_admin_panel tests --glob '*.md' --glob '*.py' --glob '*.js' --glob '*.html' || true

printf '%s\n' '--- upstream protocol source ---'
curl -fsSL https://raw.githubusercontent.com/JarbasHiveMind/HiveMind-core/dev/hivemind_core/protocol.py \
  | rg -n -C 5 'class .*Protocol|protocol_version|min_protocol|Noise|handshake|encrypt|decrypt|password|api_key' \
  | head -n 1200

printf '%s\n' '--- upstream configuration and websocket TLS source ---'
curl -fsSL https://raw.githubusercontent.com/JarbasHiveMind/HiveMind-core/dev/hivemind_core/config.py \
  | rg -n -C 5 'ssl|tls|websocket|protocol|cipher|allowed' \
  | head -n 800
curl -fsSL https://raw.githubusercontent.com/JarbasHiveMind/hivemind-websocket-protocol/dev/hivemind_websocket_protocol/__init__.py \
  | rg -n -C 5 'ssl|tls|websocket|protocol|handshake|encrypt|decrypt' \
  | head -n 800

Repository: JarbasHiveMind/hivemind-admin-panel

Length of output: 50391


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- websocket repository branches ---'
git ls-remote --heads https://github.com/JarbasHiveMind/hivemind-websocket-protocol.git \
  | head -n 30

printf '%s\n' '--- websocket repository tree ---'
curl -fsSL https://api.github.com/repos/JarbasHiveMind/hivemind-websocket-protocol/git/trees/HEAD?recursive=1 \
  | jq -r '.tree[]?.path' | head -n 300

printf '%s\n' '--- core protocol version and handshake ranges ---'
curl -fsSL https://raw.githubusercontent.com/JarbasHiveMind/HiveMind-core/dev/hivemind_core/protocol.py \
  | nl -ba | sed -n '100,165p;840,930p;1420,1535p'

printf '%s\n' '--- websocket TLS references from repository contents ---'
for path in \
  hivemind_websocket_protocol/__init__.py \
  hivemind_websocket_protocol/server.py \
  hivemind_websocket_protocol/client.py \
  README.md \
  setup.py \
  pyproject.toml
do
  url="https://raw.githubusercontent.com/JarbasHiveMind/hivemind-websocket-protocol/HEAD/$path"
  body="$(curl -fsSL "$url" 2>/dev/null || true)"
  if [ -n "$body" ]; then
    printf '%s\n' "--- $path"
    printf '%s\n' "$body" | rg -n -C 5 'ssl|tls|cert|websocket|WebSocket|create_connection|server' || true
  fi
done

Repository: JarbasHiveMind/hivemind-admin-panel

Length of output: 2430


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- websocket repository branches ---'
git ls-remote --heads https://github.com/JarbasHiveMind/hivemind-websocket-protocol.git \
  | head -n 30

printf '%s\n' '--- websocket repository tree ---'
curl -fsSL 'https://api.github.com/repos/JarbasHiveMind/hivemind-websocket-protocol/git/trees/HEAD?recursive=1' \
  | jq -r '.tree[]?.path' | head -n 300

printf '%s\n' '--- core protocol version and handshake ranges ---'
curl -fsSL https://raw.githubusercontent.com/JarbasHiveMind/HiveMind-core/dev/hivemind_core/protocol.py \
  | nl -ba | sed -n '100,165p;840,930p;1420,1535p'

printf '%s\n' '--- websocket TLS references from repository contents ---'
for path in \
  hivemind_websocket_protocol/__init__.py \
  hivemind_websocket_protocol/server.py \
  hivemind_websocket_protocol/client.py \
  README.md \
  setup.py \
  pyproject.toml
do
  url="https://raw.githubusercontent.com/JarbasHiveMind/hivemind-websocket-protocol/HEAD/$path"
  body="$(curl -fsSL "$url" 2>/dev/null || true)"
  if [ -n "$body" ]; then
    printf '%s\n' "--- $path"
    printf '%s\n' "$body" | rg -n -C 5 'ssl|tls|cert|websocket|WebSocket|create_connection|server' || true
  fi
done

Repository: JarbasHiveMind/hivemind-admin-panel

Length of output: 2430


Retain a transport-security check or narrow the replacement claim.

hivemind-core does not provide this guarantee for every supported version. v0 has no handshake, v1/v2 expose the initial handshake before session-key establishment, and v3 establishes Noise after initial negotiation. Payload encryption does not replace TLS for protecting handshake metadata or authenticating the endpoint. Retain core_tls or an equivalent transport check, update docs/security.md, and add protocol-floor regression tests.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@hivemind_admin_panel/api.py` around lines 5037 - 5041, Revise the websocket
security handling around the protocol-version transport check: retain core_tls
or an equivalent transport-security validation instead of claiming ws:// is
always safe. Update docs/security.md to accurately describe handshake metadata
and endpoint-authentication risks across v0–v3, and add regression tests
enforcing the minimum supported protocol security behavior.

Comment on lines +4628 to +4648
function openSidebar() {
const bar = document.getElementById('sidebar');
const backdrop = document.getElementById('sidebarBackdrop');
const toggle = document.getElementById('navToggle');
if (bar) {
bar.classList.add('open');
bar.removeAttribute('inert');
bar.removeAttribute('aria-hidden');
}
if (backdrop) backdrop.classList.add('visible');
if (toggle) {
toggle.setAttribute('aria-expanded', 'true');
toggle.setAttribute('aria-label', 'Close navigation');
}
// Move focus into the drawer. Without this, tabbing from the toggle walked
// straight past it — the drawer is earlier in the DOM — and landed on
// "Restart HiveMind" with an opaque backdrop over the page.
const target = bar && (bar.querySelector('.nav-item.active') || bar.querySelector('.nav-item'));
if (target) target.focus();
// Stop the page scrolling underneath the backdrop.
document.body.style.overflow = 'hidden';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Keep keyboard focus within the open drawer.

openSidebar() moves initial focus into #sidebar, but it does not trap focus or make the rest of the page inert. After the last drawer control, Tab can move to controls behind the visible backdrop. The Escape listener can also close the drawer from any focused element.

Make content outside #sidebar inert while the drawer is open, or add a focus trap. Limit Escape dismissal to the drawer context.

Also applies to: 4701-4707

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@hivemind_admin_panel/static/js/app.js` around lines 4628 - 4648, Update
openSidebar() to keep keyboard focus within `#sidebar` while it is open by making
outside content inert or implementing a focus trap, including wrapping Tab
navigation from the last control to the first. Update the Escape-key listener
near the related sidebar handlers so it dismisses the drawer only when focus is
within the drawer context, and restore outside interactivity when closing.

Comment on lines +4674 to +4684
function _syncSidebarInertness() {
const bar = document.getElementById('sidebar');
if (!bar) return;
if (_mobileLayout() && !bar.classList.contains('open')) {
bar.setAttribute('inert', '');
bar.setAttribute('aria-hidden', 'true');
} else {
bar.removeAttribute('inert');
bar.removeAttribute('aria-hidden');
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Synchronize drawer state when leaving the mobile layout.

If _mobileLayout() changes from true to false while the drawer is open, _syncSidebarInertness() only removes inert and aria-hidden. It leaves .open, .visible, aria-expanded="true", and document.body.style.overflow = "hidden" set. The desktop page then keeps the backdrop and scroll lock until the user clicks the backdrop.

Close the drawer and clear all related state during this breakpoint transition.

Also applies to: 4699-4699

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@hivemind_admin_panel/static/js/app.js` around lines 4674 - 4684, The
_syncSidebarInertness function must fully close and reset the drawer when
transitioning from mobile to desktop, clearing the sidebar’s open/visible state,
aria-expanded value, backdrop, and document.body scroll lock while retaining the
existing inert and aria-hidden synchronization.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant