Skip to content

Replace Node UI token bootstrap with dashboard sessions#1428

Open
Jurij89 wants to merge 69 commits into
mainfrom
codex/node-ui-auth-bootstrap-session
Open

Replace Node UI token bootstrap with dashboard sessions#1428
Jurij89 wants to merge 69 commits into
mainfrom
codex/node-ui-auth-bootstrap-session

Conversation

@Jurij89

@Jurij89 Jurij89 commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Removes the browser-visible window.__DKG_TOKEN__ bootstrap from production /ui and Vite dev serving, so the static SPA no longer receives a reusable daemon bearer token.
  • Adds server-side dashboard sessions for browser access: opaque HttpOnly SameSite=Strict cookies, loopback bootstrap, token exchange, logout/status/CSRF endpoints, and CSRF checks for unsafe dashboard API requests.
  • Moves Node UI fetch/SSE/e2e helpers to same-origin session credentials, updates the devnet smoke and Playwright coverage, and adds a CI static bundle contract that fails if the built UI contains the legacy token global.

Related

  • None

Files changed

File What
packages/cli/src/daemon/dashboard-session.ts New dashboard session store, cookie helpers, loopback/exchange/logout/status/CSRF routes.
packages/cli/src/auth.ts Allows protected routes to authenticate with a valid dashboard session while preserving bearer-token precedence and explicit auth failures.
packages/cli/src/daemon/lifecycle.ts Wires dashboard session routes before the auth guard and stops passing daemon tokens to Node UI static serving.
packages/node-ui/src/api.ts, packages/node-ui/vite.config.ts Removes HTML token injection and serves secret-free static UI with security/cache headers.
packages/node-ui/src/ui/** Centralizes browser API calls through session-aware apiFetch, removes EventSource query tokens, and avoids sending dashboard credentials to external RPC URLs.
packages/node-ui/e2e/**, packages/node-ui/test/**, packages/cli/test/** Updates unit/e2e helpers and adds regression coverage for no browser bearer token, session-authenticated API access, CSRF, and SSE without query tokens.
scripts/devnet-test-node-ui-smoke.sh Upgrades the smoke from "HTML exists" to auth/session/security contract checks against a real devnet.
.github/workflows/ci.yml Adds a static build:ui contract check for no __DKG_TOKEN__ and valid referenced assets.
agent-docs/** Adds the requested upgrade plan, team prompt, execution todo, and durable memory notes.

Test plan

  • pnpm --filter @origintrail-official/dkg exec vitest run --config vitest.unit.config.ts test/auth.test.ts test/dashboard-session.test.ts passed: 44 tests.
  • pnpm --filter @origintrail-official/dkg-node-ui exec vitest run test/api-routes.test.ts test/ui-compat.test.ts test/ui-api-pure.test.ts test/pca-api.test.ts test/web3-clients.test.ts test/use-current-agent.test.ts test/openclaw-bridge.test.ts --no-file-parallelism passed: 296 passed, 38 skipped.
  • pnpm --filter @origintrail-official/dkg-node-ui exec tsc --noEmit passed.
  • pnpm --filter @origintrail-official/dkg exec tsc --noEmit passed.
  • pnpm --filter @origintrail-official/dkg-node-ui run build:ui passed; existing chunk-size / mock-subgraph export warnings only.
  • Static bundle contract against packages/node-ui/dist-ui/index.html passed: no __DKG_TOKEN__, referenced assets present.
  • pnpm --filter @origintrail-official/dkg run build passed.
  • scripts/devnet-test-node-ui-smoke.sh against a one-node WSL devnet passed: PASS=11 FAIL=0.
  • PLAYWRIGHT_DEVNET_TIMEOUT_MS=300000 PW_HEADLESS=1 pnpm exec playwright test e2e/specs/auth-session.spec.ts passed on the standard four-node real-node devnet: 1 passed.

Comment thread packages/node-ui/src/ui/api.ts Outdated
Comment thread packages/node-ui/src/ui/web3/clients.ts Outdated
Comment thread packages/cli/src/auth.ts Outdated
Comment thread packages/node-ui/src/ui/api.ts Outdated
Comment thread packages/cli/src/daemon/dashboard-session.ts
Comment thread packages/cli/src/daemon/dashboard-session.ts
Comment thread packages/node-ui/e2e/specs/auth-session.spec.ts
Comment thread packages/cli/src/daemon/dashboard-session.ts Outdated
Comment thread packages/node-ui/src/ui/dashboardSessionClient.ts Outdated
Comment thread packages/node-ui/src/ui/dashboardSessionClient.ts Outdated
Comment thread agent-docs/todo.md Outdated
Comment thread packages/cli/src/auth.ts Outdated
Comment thread packages/node-ui/src/api.ts
Comment thread packages/cli/src/daemon/dashboard-session.ts Outdated
Comment thread packages/cli/src/daemon/lifecycle.ts Outdated
Comment thread packages/cli/src/daemon/handle-request.ts Outdated
Comment thread packages/node-ui/src/ui/hooks/useNodeEvents.ts Outdated
Comment thread scripts/devnet-test-node-ui-smoke.sh Outdated
Comment thread packages/cli/src/daemon/routes/context.ts Outdated
Comment thread packages/cli/src/daemon/dashboard-session.ts Outdated
Comment thread packages/node-ui/src/ui/dashboardSessionClient.ts Outdated
Comment thread packages/cli/src/daemon/dashboard-session.ts
Comment thread packages/cli/src/daemon/dashboard-session.ts
Comment thread packages/cli/src/auth.ts
Comment thread packages/cli/src/daemon/lifecycle.ts Outdated
Comment thread packages/cli/src/daemon/lifecycle.ts Outdated
Comment thread packages/node-ui/src/ui/hooks/useNodeEvents.ts
Comment thread packages/cli/src/daemon/dashboard-session-cookie.ts
Comment thread packages/cli/src/daemon/dashboard-session.ts Outdated
Comment thread packages/node-ui/src/ui/hooks.ts
Comment thread packages/node-ui/src/ui/api.ts
@Jurij89 Jurij89 mentioned this pull request Jul 4, 2026
18 tasks
// widening the api.ts surface.
async function post<T = unknown>(path: string, body: unknown): Promise<T> {
const res = await fetch(path, {
const res = await apiFetch(path, {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 Bug: Ontology install helper breaks the new daemonFetch path contract

What's wrong
The PR introduces a typed same-origin fetch boundary for dashboard-session requests, but this changed call passes a plain string into that boundary. That weakens the contract and is likely to break TypeScript compilation for ontology install.

Example
post('/api/sub-graph/create', ...) is valid at runtime, but inside post the literal has been widened to string, so apiFetch(path, ...) no longer satisfies the new DaemonPath contract.

Suggested direction
Keep the typed same-origin boundary by using DaemonPath at the helper boundary or validating with daemonPath.

For Agents
In packages/node-ui/src/ui/lib/ontologyInstall.ts, change the helper to accept DaemonPath or wrap the argument with daemonPath(path) before calling apiFetch. Preserve the same-origin path guard and type-check this file.

try {
const { ensureDashboardCredentials } = await import('../daemon/dashboard-credentials.js');
return await ensureDashboardCredentials();
} catch (err: any) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Issue: Init dashboard credential failure path is untested

What's wrong
The new init flow intentionally catches dashboard credential creation failures so dkg init can continue, but the added init tests only cover success and auth-disabled paths. A regression that rethrows here would break first-run setup when a stale or corrupt credential file exists, and the current init test suite would not catch it.

Example
A focused regression test can create an invalid dashboard.credentials.json, call ensureDashboardCredentialsForInit(true), and assert it resolves null plus logs the reset-password guidance instead of throwing.

Suggested direction
Add an init-specific regression test for invalid or unreadable dashboard credentials so the best-effort contract is pinned.

For Agents
Add coverage in packages/cli/test/init-dashboard-credentials.test.ts for the catch path in ensureDashboardCredentialsForInit: seed an invalid credential file under DKG_HOME, call the helper with auth enabled, assert no throw, null result, and warning guidance. Preserve existing create/rerun/auth-disabled behavior.

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.

2 participants