Skip to content

Stage D part 3: dismantle General and Security - #1311

Merged
Paul Lizer (paullizer) merged 1 commit into
feature/admin-settings-iafrom
admin-ia-stage-d3
Aug 19, 2026
Merged

Paul Lizer (paullizer) merged 1 commit into
feature/admin-settings-iafrom
admin-ia-stage-d3

Conversation

@paullizer

Copy link
Copy Markdown
Contributor

Third batch of Stage D. Breaks up the two worst catch-all tabs: General and Security.

Base: feature/admin-settings-ia.

Why

General had grown into eleven unrelated cards — branding sat next to health checks, API documentation, terms of use and system settings. It was the tab you landed on, and it told you nothing about where anything lived.

Security held a single Key Vault card, while a separate Safety tab mixed content filtering with role permissions. Deciding who may log in and deciding what may be said are different jobs with different owners.

Appearance

Tab Cards
Branding branding, home page text, appearance
Notices & Agreements classification banner, chat AI notice, terms of use, user agreement (from Workspaces)
Pages & Links static pages, external links (from General)

Security

Tab Card Job
Access & Roles permissions-section who gets in, and as what
Secrets keyvault-section was the security tab
Content Safety content-safety-section what may be said once you are in
Session system-settings-section interim, see below
Network front-door-section unchanged

Elsewhere

  • Operations → Logging becomes Logging & Health, gaining health check and API documentation from General. Both report on how the app is running rather than how it looks.
  • Help → gains Support Menu from General, next to Send Feedback.

Navigation is now 13 groups / 31 tabs / 88 sections.

One deliberate compromise

system-settings-section is a genuinely mixed card: max file size, conversation history limit, four idle-timeout fields, default system prompt and access-denied message. Idle timeout is the plurality, so Session is its interim home. Splitting the card into its real destinations is a separate change, because that is markup surgery inside a card rather than a whole-card move.

Two hardcoded-id traps closed

Both were latent breakage that only surfaced because a tab id changed. Worth calling out because they are the class of bug this whole rework exists to prevent.

openKeyVaultSettings in admin_data_management.js switched tabs by the literal id security-tab and set location.hash = "security". The "Open Key Vault settings" link from Data Management would have silently stopped working. The function was dead weight — the link now carries data-admin-link and admin_card_links.js resolves the owning tab from the DOM.

The landing pane was hardcoded in two places: show active in one pane's markup, and showAdminTab('general') in the sidebar script. Splitting that pane left Admin Settings with no active pane at all. Every pane now renders:

<div class="tab-pane fade{% if admin_landing_tab == 'branding' %} show active{% endif %}" ...>

fed by get_landing_tab_id(), which returns the first tab of the first group. The sidebar reads the first rendered tab instead of a fixed id. The landing tab now follows the settings, and can never be Latest Features.

Tests: assert durable properties, not current ids

Four test files hardcoded general or security and broke. Rather than update the literals, they now assert what actually matters:

  • Latest Features is the last tab and never the landing tab
  • Every tab in the map renders exactly one pane (stronger than naming one tab)
  • Exactly one pane resolves to active, and it is the first tab of the first group
  • No pane hardcodes show active

No settings changed

Not one name= attribute was touched.

Check Result
Field contract 462 names / 110 card ids, byte-identical
Regression set (75 files) 32 failures, identical set to baseline
Jinja compile 33/33 admin templates
XSS sinks 41 changed files pass
Render check exactly one pane resolves active, and it is the landing tab

Next

Remaining Stage D groups: AI Models, Agents & Actions, Workspaces, Workflow, Knowledge. Backup & Recovery goes last because its ~985-line migration workflow has to split as one unit. Then Stage E splits system-settings-section and mirrors the role toggles.

General had grown into a catch-all of eleven unrelated cards. Security
held one card while a separate Safety tab mixed content filtering with
role permissions. Both are broken up here.

Appearance
  Branding             branding, home page text, appearance
  Notices & Agreements classification banner, chat AI notice, terms of
                       use, user agreement (from workspaces)
  Pages & Links        static pages, external links (from general)

Security
  Access & Roles   permissions-section        who gets in, and as what
  Secrets          keyvault-section           was the "security" tab
  Content Safety   content-safety-section     what may be said once in
  Session          system-settings-section    interim home, see below
  Network          front-door-section

Operations   Logging becomes Logging & Health, gaining health check and
             API documentation from General.
Help         Gains Support Menu from General.

system-settings-section is a mixed card: four of its eight fields are
idle timeout, so Session is the plurality home. The remaining fields
are split out to their real homes in a later change.

Two hardcoded-id traps closed
  openKeyVaultSettings switched tabs by the literal id "security-tab",
  so the Data Management link to Key Vault broke the moment that tab
  was renamed. The function was dead weight: the link now carries
  data-admin-link and the tab is resolved from the DOM.

  The landing pane was hardcoded twice, as "show active" in one pane
  and showAdminTab('general') in the sidebar. Splitting that pane left
  Admin Settings with no active pane at all. Every pane now renders
  {% if admin_landing_tab == '<id>' %} show active{% endif %}, fed by
  get_landing_tab_id(), and the sidebar reads the first rendered tab.

Four test files hardcoded 'general' or 'security'. They now assert the
durable properties instead: Latest Features is last, exactly one pane
resolves active, every tab renders exactly one pane.

Navigation is now 13 groups / 31 tabs / 88 sections.

Verified
  field contract   462 names / 110 card ids, unchanged
  regression set   32 failures, identical to baseline
  jinja compile    33/33 admin templates
  xss sinks        41 changed files pass
  render check     exactly one pane resolves active, and it is the
                   first tab of the first group

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@paullizer
Paul Lizer (paullizer) merged commit ee569c9 into feature/admin-settings-ia Aug 19, 2026
11 checks passed
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