Pre-launch — Gluecron is in final validation. Public signups and git hosting for non-owner users open after launch review.
Commitae2a071

fix(nav): connect the orphaned repo-settings and account-settings tree

fix(nav): connect the orphaned repo-settings and account-settings tree

RepoNav had "settings" in its active-tab type union but rendered no
<a> for it — the entire repo-settings tree (mirrors, dep updater,
audit log, webhooks, environments, pages, workflow secrets, protected
tags, rulesets, automation, collaborators) was reachable only via the
Cmd-K palette, never from normal navigation. Two pages already rendered
RepoNav active="settings" correctly, confirming this was expected to
exist, not scope creep.

- components.tsx: add the missing Settings tab render; link the
  CommitList "Verified" badge to /settings/signing-keys (previously a
  dead-end badge with no path to manage your own signing key).
- environments.tsx, pages.tsx: fix active="code" -> active="settings".
- webhooks.tsx, mirrors.tsx, collaborators.tsx: add RepoNav
  (previously rendered no nav at all).
- dep-updater.tsx: was rendering the wrong nav entirely (IssueNav,
  active="code") -- replaced with RepoNav active="settings".
- repo-settings.tsx: the /settings index page itself was missing
  RepoNav too (found during verification, same bug, same root cause)
  -- fixed, and exported RepoSettingsSidebar for reuse.

Account settings had the identical shape: SettingsSubnav only listed
4 of 11 settings pages, and 2 of those 4 (agents, deploy-targets)
rendered no subnav themselves either. Extended SettingsSubnav with
2fa/passkeys/signing-keys/sessions/integrations and wired it into all
7 previously-orphaned pages (settings-agents, deploy-targets,
settings-2fa, passkeys, signing-keys, settings-sessions,
settings-integrations).

Verified: grep confirms all files reference the nav component; full
build-check on every touched file; existing route tests (green-
ecosystem, signatures, collaborators, dep-updater, mirrors) all green;
full suite 3073 pass / 4 pre-existing unrelated fails, no regressions.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
ccanty labs committed on July 16, 2026Parent: 2daad3c
16 files changed+5616ae2a0710134f4bcb371ea41275a92e9a6a2ab6b9
16 changed files+56−16
Modifiedsrc/routes/collaborators.tsx+2−1View fileUnifiedSplit
3030 repoCollaborators,
3131} from "../db/schema";
3232import { Layout } from "../views/layout";
33import { RepoHeader } from "../views/components";
33import { RepoHeader, RepoNav } from "../views/components";
3434import { softAuth, requireAuth } from "../middleware/auth";
3535import type { AuthEnv } from "../middleware/auth";
3636import { generateInviteToken, hashInviteToken } from "../lib/invite-tokens";
601601 return c.html(
602602 <Layout title={`Collaborators — ${ownerName}/${repoName}`} user={user}>
603603 <RepoHeader owner={ownerName} repo={repoName} />
604 <RepoNav owner={ownerName} repo={repoName} active="settings" />
604605 <div class="collab-wrap">
605606 <div class="collab-crumbs">
606607 <a href={`/${ownerName}/${repoName}/settings`}>
Modifiedsrc/routes/dep-updater.tsx+5−4View fileUnifiedSplit
99 * 2026 polish: scoped `.dep-*` class system mirrors the gradient hero and
1010 * card patterns from admin-integrations.tsx and admin-ops.tsx. Bump tables
1111 * use tabular-nums + mono for versions; PR refs + branch names are mono.
12 * RepoHeader + IssueNav above are untouched — only the content beneath
13 * the nav is restyled.
12 * RepoHeader + RepoNav above are untouched — only the content beneath
13 * the nav is restyled. (Was rendering the wrong nav component, IssueNav
14 * with active="code" — fixed to RepoNav active="settings".)
1415 */
1516
1617import { Hono } from "hono";
2021import { Layout } from "../views/layout";
2122import { RepoHeader } from "../views/components";
2223import { formatRelative } from "../views/ui";
23import { IssueNav } from "./issues";
24import { RepoNav } from "../views/components";
2425import { softAuth, requireAuth } from "../middleware/auth";
2526import type { AuthEnv } from "../middleware/auth";
2627import { runDepUpdateRun, type Bump } from "../lib/dep-updater";
629630 return c.html(
630631 <Layout title={`Dep Updater — ${ownerName}/${repoName}`} user={user}>
631632 <RepoHeader owner={ownerName} repo={repoName} />
632 <IssueNav owner={ownerName} repo={repoName} active="code" />
633 <RepoNav owner={ownerName} repo={repoName} active="settings" />
633634 <div class="dep-wrap">
634635 <section class="dep-hero">
635636 <div class="dep-hero-orb" aria-hidden="true" />
Modifiedsrc/routes/deploy-targets.tsx+2−0View fileUnifiedSplit
1616import { db } from "../db";
1717import { serverTargets } from "../db/schema";
1818import { Layout } from "../views/layout";
19import { SettingsSubnav } from "./settings";
1920import type { AuthEnv } from "../middleware/auth";
2021import { requireAuth } from "../middleware/auth";
2122import {
413414 return c.html(
414415 <Layout title="Deploy targets — settings" user={user}>
415416 <style dangerouslySetInnerHTML={{ __html: styles }} />
417 <SettingsSubnav active="deploy-targets" />
416418 <div class="dt-wrap">
417419 {/* ─── Hero ─── */}
418420 <div class="dt-hero">
Modifiedsrc/routes/environments.tsx+1−1View fileUnifiedSplit
574574 forkCount={repoRow.forkCount}
575575 currentUser={user.username}
576576 />
577 <RepoNav owner={owner} repo={repo} active="code" />
577 <RepoNav owner={owner} repo={repo} active="settings" />
578578
579579 <div class="envs-wrap">
580580 <section class="envs-head">
Modifiedsrc/routes/mirrors.tsx+2−1View fileUnifiedSplit
1919import { db } from "../db";
2020import { repositories, users } from "../db/schema";
2121import { Layout } from "../views/layout";
22import { RepoHeader } from "../views/components";
22import { RepoHeader, RepoNav } from "../views/components";
2323import { formatRelative } from "../views/ui";
2424import { softAuth, requireAuth } from "../middleware/auth";
2525import type { AuthEnv } from "../middleware/auth";
647647 return c.html(
648648 <Layout title={`Mirror — ${ownerName}/${repoName}`} user={user}>
649649 <RepoHeader owner={ownerName} repo={repoName} />
650 <RepoNav owner={ownerName} repo={repoName} active="settings" />
650651 <div class="mirror-wrap">
651652 <section class="mirror-hero">
652653 <div class="mirror-hero-orb" aria-hidden="true" />
Modifiedsrc/routes/pages.tsx+1−1View fileUnifiedSplit
658658 notificationCount={unread}
659659 >
660660 <RepoHeader owner={ownerName} repo={repoName} />
661 <RepoNav owner={ownerName} repo={repoName} active="code" />
661 <RepoNav owner={ownerName} repo={repoName} active="settings" />
662662 <div class="pages-wrap">
663663 <header class="pages-head">
664664 <div class="pages-head-text">
Modifiedsrc/routes/passkeys.tsx+2−0View fileUnifiedSplit
3030import type { AuthEnv } from "../middleware/auth";
3131import { requireAuth } from "../middleware/auth";
3232import { Layout } from "../views/layout";
33import { SettingsSubnav } from "./settings";
3334import {
3435 startRegistration,
3536 finishRegistration,
638639
639640 return c.html(
640641 <Layout title="Passkeys" user={user}>
642 <SettingsSubnav active="passkeys" />
641643 <div class="pk-wrap">
642644 <section class="pk-hero">
643645 <div class="pk-hero-orb" aria-hidden="true" />
Modifiedsrc/routes/repo-settings.tsx+3−2View fileUnifiedSplit
77import { db } from "../db";
88import { repositories, users, repoTransfers, branchProtection } from "../db/schema";
99import { Layout } from "../views/layout";
10import { RepoHeader } from "../views/components";
10import { RepoHeader, RepoNav } from "../views/components";
1111import { softAuth, requireAuth } from "../middleware/auth";
1212import type { AuthEnv } from "../middleware/auth";
1313import { requireRepoAccess } from "../middleware/repo-access";
619619}
620620
621621/** Left-hand settings navigation sidebar. */
622function RepoSettingsSidebar(props: { owner: string; repo: string; currentPath: string }) {
622export function RepoSettingsSidebar(props: { owner: string; repo: string; currentPath: string }) {
623623 const { owner, repo, currentPath } = props;
624624 const base = `/${owner}/${repo}`;
625625
722722 return c.html(
723723 <Layout title={`Settings — ${ownerName}/${repoName}`} user={user}>
724724 <RepoHeader owner={ownerName} repo={repoName} />
725 <RepoNav owner={ownerName} repo={repoName} active="settings" />
725726 <style dangerouslySetInnerHTML={{ __html: repoSettingsStyles }} />
726727 <div class="repo-settings-container">
727728 <RepoSettingsHero owner={ownerName} repo={repoName} />
Modifiedsrc/routes/settings-2fa.tsx+2−0View fileUnifiedSplit
2222import type { AuthEnv } from "../middleware/auth";
2323import { requireAuth } from "../middleware/auth";
2424import { Layout } from "../views/layout";
25import { SettingsSubnav } from "./settings";
2526import { verifyPassword } from "../lib/auth";
2627import {
2728 generateTotpSecret,
562563
563564 return c.html(
564565 <Layout title="Two-factor authentication" user={user}>
566 <SettingsSubnav active="2fa" />
565567 <div class="tfa-wrap">
566568 <section class="tfa-hero">
567569 <div class="tfa-hero-orb" aria-hidden="true" />
Modifiedsrc/routes/settings-agents.tsx+2−0View fileUnifiedSplit
1212import { db } from "../db";
1313import { agentLeases, agentSessions } from "../db/schema";
1414import { Layout } from "../views/layout";
15import { SettingsSubnav } from "./settings";
1516import type { AuthEnv } from "../middleware/auth";
1617import { requireAuth } from "../middleware/auth";
1718import {
362363
363364 return c.html(
364365 <Layout title="Agent sessions" user={user}>
366 <SettingsSubnav active="agents" />
365367 {raw(body)}
366368 </Layout>
367369 );
Modifiedsrc/routes/settings-integrations.tsx+2−0View fileUnifiedSplit
2121import { db } from "../db";
2222import { chatIntegrations, repositories } from "../db/schema";
2323import { Layout } from "../views/layout";
24import { SettingsSubnav } from "./settings";
2425import { softAuth, requireAuth } from "../middleware/auth";
2526import type { AuthEnv } from "../middleware/auth";
2627import { notifyChatChannels } from "../lib/chat-notifier";
380381 return c.html(
381382 <Layout title="Chat integrations" user={user}>
382383 <style dangerouslySetInnerHTML={{ __html: chatiStyles }} />
384 <SettingsSubnav active="integrations" />
383385 <div class="chati-wrap">
384386 <div class="chati-hero">
385387 <div class="chati-hero-orb" aria-hidden="true" />
Modifiedsrc/routes/settings-sessions.tsx+2−0View fileUnifiedSplit
1414import { requireAuth } from "../middleware/auth";
1515import type { AuthEnv } from "../middleware/auth";
1616import { Layout } from "../views/layout";
17import { SettingsSubnav } from "./settings";
1718
1819const settingsSessions = new Hono<AuthEnv>();
1920settingsSessions.use("/settings/sessions*", requireAuth);
117118 return c.html(
118119 <Layout title="Active sessions" user={user}>
119120 <style dangerouslySetInnerHTML={{ __html: sessionsStyles }} />
121 <SettingsSubnav active="sessions" />
120122 <div class="sessions-page">
121123 <div class="sessions-hero">
122124 <h1>Active sessions</h1>
Modifiedsrc/routes/settings.tsx+15−1View fileUnifiedSplit
599599}
600600
601601/** Pill-row sub-navigation, hand-built so we don't depend on shared components. */
602export type SettingsSubnavKey = "profile" | "keys" | "agents" | "deploy-targets";
602export type SettingsSubnavKey =
603 | "profile"
604 | "keys"
605 | "agents"
606 | "deploy-targets"
607 | "2fa"
608 | "passkeys"
609 | "signing-keys"
610 | "sessions"
611 | "integrations";
603612
604613export function SettingsSubnav(props: { active: SettingsSubnavKey }) {
605614 const items: Array<{ key: SettingsSubnavKey; href: string; label: string }> = [
606615 { key: "profile", href: "/settings", label: "Profile" },
607616 { key: "keys", href: "/settings/keys", label: "SSH keys" },
617 { key: "signing-keys", href: "/settings/signing-keys", label: "Signing keys" },
618 { key: "2fa", href: "/settings/2fa", label: "2FA" },
619 { key: "passkeys", href: "/settings/passkeys", label: "Passkeys" },
620 { key: "sessions", href: "/settings/sessions", label: "Sessions" },
621 { key: "integrations", href: "/settings/integrations", label: "Integrations" },
608622 { key: "agents", href: "/settings/agents", label: "Agents" },
609623 { key: "deploy-targets", href: "/settings/deploy-targets", label: "Deploy targets" },
610624 ];
Modifiedsrc/routes/signing-keys.tsx+2−0View fileUnifiedSplit
2323
2424import { Hono } from "hono";
2525import { Layout } from "../views/layout";
26import { SettingsSubnav } from "./settings";
2627import type { AuthEnv } from "../middleware/auth";
2728import { requireAuth } from "../middleware/auth";
2829import {
439440 const now = new Date();
440441 return c.html(
441442 <Layout title="Signing keys" user={user}>
443 <SettingsSubnav active="signing-keys" />
442444 <div class="sk-wrap">
443445 <header class="sk-head">
444446 <div class="sk-eyebrow">
Modifiedsrc/routes/webhooks.tsx+2−1View fileUnifiedSplit
2626 drainPendingDeliveries,
2727} from "../lib/webhook-delivery";
2828import { Layout } from "../views/layout";
29import { RepoHeader } from "../views/components";
29import { RepoHeader, RepoNav } from "../views/components";
3030import { softAuth, requireAuth } from "../middleware/auth";
3131import type { AuthEnv } from "../middleware/auth";
3232import { requireRepoAccess } from "../middleware/repo-access";
508508 return c.html(
509509 <Layout title={`Webhooks — ${ownerName}/${repoName}`} user={user}>
510510 <RepoHeader owner={ownerName} repo={repoName} />
511 <RepoNav owner={ownerName} repo={repoName} active="settings" />
511512 <div class="wh-wrap">
512513 <header class="wh-head">
513514 <div class="wh-eyebrow">
Modifiedsrc/views/components.tsx+11−4View fileUnifiedSplit
267267 >
268268 Security
269269 </a>
270 <a
271 href={`/${owner}/${repo}/settings`}
272 class={active === "settings" ? "active" : ""}
273 >
274 Settings
275 </a>
270276 <a
271277 href={`/${owner}/${repo}/cloud-deployments`}
272278 class={active === "deployments" ? "active" : ""}
516522 {commit.message}
517523 </a>
518524 {v?.verified && (
519 <span
520 title="Signed with a registered key"
521 style="margin-left:8px;font-size:10px;padding:1px 6px;border-radius:3px;background:var(--green,#2ea043);color:#fff;text-transform:uppercase;letter-spacing:.4px"
525 <a
526 href="/settings/signing-keys"
527 title="Signed with a registered key — manage your signing keys"
528 style="margin-left:8px;font-size:10px;padding:1px 6px;border-radius:3px;background:var(--green,#2ea043);color:#fff;text-transform:uppercase;letter-spacing:.4px;text-decoration:none"
522529 >
523530 Verified
524 </span>
531 </a>
525532 )}
526533 </div>
527534 <div class="commit-meta">
528535