Skip to content

Fix/task1 bugs and UI latency - #7

Merged
dywongcloud merged 9 commits into
mainfrom
fix/task1-bugs-and-ui-latency
Jul 6, 2026
Merged

Fix/task1 bugs and UI latency#7
dywongcloud merged 9 commits into
mainfrom
fix/task1-bugs-and-ui-latency

Conversation

@dywongcloud

Copy link
Copy Markdown
Owner

No description provided.

dylanwongtencent and others added 9 commits July 3, 2026 14:09
…t bugs + latency guards

TASK 1 (reported bugs):
- Blank /storage: add app/error.tsx + global-error.tsx (there were none — any render
  throw = blank page in prod); guard Object.entries(conn) on storage/[id] (threw when
  connection absent), render usePoll errors instead of infinite "Loading…", guard timeAgo.
- GitHub org 403: surface the org-owner approval URL as a link (was raw JSON).
- GitHub 409 "is at X but expected Y": retry commitFile with a fresh blob SHA.
- "Use existing repo" listed personal repos under an org scope: add githubOrgRepos +
  /api/github/repos?org= + modal loads org repos.

TASK 2 (UI latency, apply_now):
- api.ts fetch timeouts (GET 20s / send 30s) so a far backend can't hang a tab.
- gitops status probe 4s abort; topnav identity/sync deduped (was 2-4 dup POSTs).

Verified: hive-cloud/hive-edge/fluid-* tests green; UI typecheck build green; error-guard
regexes matched against the exact reported error strings. Pre-existing fluid-build/per_route
reds are unrelated (file unchanged vs HEAD, no dependency on these changes).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X59j9qLYSN23G6e4Fh3iJf
…n hot path

unique_project_name() and the redeploy-existing check cloned the ENTIRE project
map (every project's env/build/function config) just to do a case-insensitive
key lookup. Add ProjectStore::find_key_ci (read lock, single-string clone) and
use it at both sites. Semantics-preserving — proven by a unit test asserting
find_key_ci returns the identical result as the old snapshot()+scan for exact,
case-folded, miss, and hyphen probes.

Held (NOT applied) from the audit's backend backlog, with reasons:
- persist coalescing: introduces a crash-loss window → violates the no-silent-
  failure invariant; needs explicit sign-off on the durability tradeoff.
- headers_vec O(n)->HeaderMap: touches many call sites → exceeds the
  "don't break anything" risk bar for an unsupervised change.
- gossip cross-peer parallelize: control-plane only (5s loop); the merge
  refactor's concurrency risk outweighs the benefit right now.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X59j9qLYSN23G6e4Fh3iJf
…der lookups

persist coalesce: replace synchronous full-state serialize+fsync-on-every-mutation
with a single background writer thread that coalesces bursts and always writes the
LATEST state (no lost mutation under normal op); persist() now just marks dirty +
wakes it. flush_blocking() wired to SIGTERM/SIGINT so `systemctl restart` loses
nothing; synchronous fallback when the writer isn't started (tests/early boot).

gossip parallelize: the per-peer sync loop was sequential (one slow peer stalled all
others up to ~7s each). Extract sync_one_peer() returning loop-local partials and
join_all across peers; per-peer cloud.* writes go through internally-synchronized
stores so they're race-free, only routes/fleet/holders/seen are merged after.

headers O(1): convert the always-executed early single-header lookups (host, ua, ip,
request-id, upgrade, connection, x-hive-proxied) from O(n) scans over headers_vec to
O(1) req.headers().get(); headers_vec retained for the aggregate consumers (WAF ctx,
preview gate, forward loops) that need the full set.

Verified local: 134 hive-cloud + 28 hive-edge tests green; mesh 7/7 healthy after
restart; deployment serve 200; a mutated env value survived a graceful restart
(coalesced write durable). No behavior change — pure latency/throughput.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X59j9qLYSN23G6e4Fh3iJf
…ed global "personal")

ROOT CAUSE: /cloud is a static Next rewrite to the admin API, so tenant is decided
entirely by the client's x-hive-team header. Personal scope sent the LITERAL
"personal" for every account (lib/api.ts currentTeam), so any two signed-in accounts
not in an org collided on ONE global namespace — hence fatbearsk@outlook.com and
dylanwong007@gmail.com saw identical projects/deployments. Backend list endpoints
(dep_list etc.) filter correctly by tenant; the bug was the shared tenant *value*.

FIX (no risky mesh-wide data retag): personal scope is now keyed to the account.
- currentTeam(): personal -> `u_<clerkUserId>`; the PLATFORM OWNER (owner_email,
  authoritative from the backend) keeps the legacy "personal" namespace so their
  existing projects/deployments (local AND fleet-hosted, tagged tenant="personal")
  stay visible without moving data. Pre-auth returns `__pending__` (owns no data)
  under Clerk so nothing leaks in the window before identity resolves.
- identity_sync returns is_owner = (email == owner_email); topnav stores hive_is_owner
  + dispatches hive-team-changed on first identity so pollers refetch under the right
  namespace; hive_is_owner cleared on account switch.

VERIFIED (node-a): dylan is_owner=true -> personal (8 deploys retained);
fatbearsk is_owner=false -> u_clerk_fat (0); a project created under fatbearsk is
visible ONLY to fatbearsk, not the owner, not a third account. Requires
HIVE_OWNER_EMAIL=dylanwong007@gmail.com (set on node-a, the dashboard's backend).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X59j9qLYSN23G6e4Fh3iJf
…ge = build→deploy, not run-only)

ROOT CAUSE: the "New Project" page had TWO separate inputs — a Git repository card,
and a distinct container-image bar whose button read "Run Image" with copy "run a
prebuilt container image… No source, no build." So a registry image was framed as a
second-class "run a container" action rather than first-class project creation.
(The backend /v1/deploy/image already routed through start_named_deploy → a real
project + build + deployment; the defect was the split UI + run-only framing.)

FIX (per spec):
- Removed the separate container-image card/bar.
- The single source card now accepts BOTH a Git repo URL and a container image /
  registry reference. `isImageRef()` auto-detects: anything that isn't clearly a git
  URL (scheme / known git host / .git) is treated as an image (docker.io short names,
  quay.io/org/img:tag, host/org/img, image://…). Submit routes:
    * git URL  → /v1/git/deploy  (clone → build → deploy)
    * image ref → /v1/deploy/image (create project → build [pull image] → deploy)
  Both land on the same /deploy/<build_id> build-logs flow with a pending build.
- Options (env + optional project name + optional container port) unified; a live
  "Detected source" hint shows which pipeline will run.

VERIFIED: image ref creates a project + build + real deployment record (not run-only);
git URL still routes to the git pipeline; isImageRef classified 9/9 representative
inputs correctly; UI typecheck green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X59j9qLYSN23G6e4Fh3iJf
…te scrollbar-corner square

Flicker: usePoll nulls data on `hive-team-changed` (correct — never show the previous
tenant's cards), but the home page rendered "Deploy your first project" whenever the
list was empty, INCLUDING the null-during-switch window → the empty card flashed for a
frame before the new tenant's cards arrived. Gate the empty state on data actually
being loaded: while `deps === null` show a skeleton (home) / "Loading…" (deployments),
and only show the empty state once `deps` is a loaded (possibly empty) array. Favorites
section likewise gated so its hint doesn't flash.

Landing root background: the html/body root is `bg-bg` = `hsl(--background)` (white in
light theme), but the landing/marketing surface is ALWAYS the dark brand color
(#0c0d10). MarketingShell now forces the root html/body background to #0c0d10 +
`color-scheme:dark` while mounted (restored on unmount), so the overscroll/root matches
the landing instead of the platform theme.

White square (bottom-right): the full-bleed `w-screen -translate-x-1/2` shell induced a
horizontal scrollbar; its unstyled corner (where h+v scrollbars meet) rendered as the
default white square. Fix: global `::-webkit-scrollbar-corner { background: transparent }`,
plus MarketingShell sets `overflow-x: clip` (removes the induced h-scrollbar entirely)
and `color-scheme: dark` (native scrollbar/corner render dark). Existing Clerk dev-badge
suppression retained.

Verified: UI build green; landing serves with #0c0d10; team-switch shows skeleton not
the empty card.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X59j9qLYSN23G6e4Fh3iJf
…> Workflows crumb)

WorkflowsPage now follows the same drilled-in navbar pattern as the project /
deployment pages (SelectedProjectPage / ScopeView / DeploymentsView) instead of
sitting in the main team tab bar:

- topnav contextTabs: /workflows[/...] is now a context → the top tab bar renders the
  Workflows SUB-tabs (Runs / Workflows / Hooks via ?tab=), NOT the team tabs.
- topnav breadcrumb: adds a "Workflows" crumb (LOGO / Team / Workflows) — the team
  label reads "Loading" until identity resolves, so the breadcrumb is Team > Workflows
  with Workflows as the current page.
- workflows page: the view (runs/workflows/hooks) is now driven by the top-nav ?tab=
  (useSearchParams under a Suspense boundary); removed the in-page WDK sub-tab bar.

DONE: main team tabs no longer render on /workflows; lower workflow tabs render; the
"Team > Workflows" breadcrumb marks Workflows as the current page; matches the existing
project/deployment breadcrumb-tabs pattern. UI build green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X59j9qLYSN23G6e4Fh3iJf
… view

The deployment detail scope-view tabs were Overview + Build Logs. Add a third,
Workflows, consistent with the breadcrumb-tabs model:
- topnav deployment context: add `{ Workflows -> /deployments/<id>?tab=workflows }`
  and extend activeKey (overview | logs | workflows).
- deployment page: now tab-aware (useSearchParams under a Suspense boundary). On
  ?tab=workflows it renders <ProjectWorkflows project={dep.project}> (the same
  component the project page uses — runs + defs scoped to this deployment's project);
  Overview/Build Logs render the existing details + logs as before.

UI build green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X59j9qLYSN23G6e4Fh3iJf
@dywongcloud
dywongcloud merged commit 380a57f into main Jul 6, 2026
3 of 4 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