Commit Graph

232 Commits

Author SHA1 Message Date
nyk 2111f03542
fix: prevent Docker build failure when pnpm lockfile is missing (#130)
* fix: make docker build resilient when lockfile is absent

* test: update e2e credentials for secure admin seed policy
2026-03-04 08:33:09 +07:00
Bhavik Patel 90b712ea29
feat(#115): virtual office visualization for agents (#127)
- Create OfficePanel with Office floor plan and Org Chart view modes
- Desk-style cards with status glow, emoji indicators, pulse animation for busy agents
- Agent detail modal with task stats, activity, session info
- Auto-refresh every 10 seconds for real-time updates
- Status summary in header (working/idle/error/away counts)
- Add OfficeIcon and office nav item in CORE group
- Register office route in page.tsx

Closes #115

Co-authored-by: bhavikprit <petrobhakti@gmail.com>
2026-03-04 08:03:24 +07:00
Mark Liu 720872a391
security: reject known-insecure default passwords during admin seeding (#123)
The admin seeding function previously fell back to password 'admin' when
AUTH_PASS was unset, and accepted any value from .env.example including
the documented default 'change-me-on-first-login'. This meant a user who
copied .env.example without changing the password (or forgot to set
AUTH_PASS entirely) would have an instance running with publicly known
credentials.

The seeding function now:
- Skips seeding entirely if AUTH_PASS is not set (instead of defaulting
  to 'admin')
- Checks AUTH_PASS against a blocklist of known insecure values
  (admin, password, change-me-on-first-login, changeme, testpass123)
- Logs a clear warning explaining what to do in both cases

Existing instances that already have users in the database are not
affected — the seeding function only runs when the users table is empty.

Signed-off-by: Mark Liu <mark@prove.com.au>
2026-03-04 08:03:11 +07:00
nyk 498cb2f8d5
feat: phase 1 workspace isolation across auth and core APIs (#112)
* feat: add workspace-scoped auth sessions and core API filtering

* feat: extend workspace scoping to search status standup and messaging

* feat: scope agent connect github and alert workflows by workspace

* fix: scope status sync and session alerts by workspace

* feat: add phase2 workspace migration and scope chat pipeline alerts

* feat: add model selection for agents and cron jobs

* feat: add deterministic agent avatars to task and squad views

* feat: add read-only cron calendar and agenda views

* feat: render task descriptions with markdown
2026-03-04 00:27:47 +07:00
nyk d682395266
feat: improve agent config tab model editing and display 2026-03-03 21:07:12 +07:00
nyk 6cd5e3e534
feat: enrich agent config with workspace identity and tools 2026-03-03 21:07:02 +07:00
nyk e4594c7854
feat: aggregate token usage from db with stable agent grouping 2026-03-03 21:06:54 +07:00
Othavio Quiliao 33f28d6877
fix: align Mission Control device auth handshake with OpenClaw protocol 2026-03-03 20:51:22 +07:00
nyk 5f7a2b5029
Docs/flight deck teaser (#100)
* docs: add Flight Deck teaser to roadmap

* docs: add Flight Deck teaser to roadmap
2026-03-03 19:16:15 +07:00
nyk f23c78f43a
fix: resolve WebSocket disconnect bugs and add SSE reconnect backoff (#97)
- Fix stale closure: onclose now calls connectRef.current instead of
  capturing connect by value, so reconnect always uses the latest version
- Fix disconnect-reconnect race: manualDisconnectRef prevents onclose
  from scheduling a new reconnect after explicit disconnect()
- Fix double-connect guard: check both OPEN and CONNECTING states
- Add SSE exponential backoff with 20-attempt cap (was flat 3s infinite)
- Add SSE error logging (was silently swallowed)
- Update README: fix stale counts (28 panels, 66 routes, 21 migrations,
  148 E2E tests), add missing features (SOUL system, Ed25519, agent
  messaging, update checker), document NEXT_PUBLIC_GATEWAY_TOKEN
2026-03-03 17:53:02 +07:00
nyk e6bae7ad88
fix: sync agent SOUL content with workspace files (#91) (#95)
Workspace file is now the primary source for soul.md with DB as
fallback. Reads prefer workspace → DB. Writes go to both. Config sync
imports soul.md from each agent's workspace using double resolveWithin
guard to prevent path traversal.
2026-03-03 17:36:14 +07:00
nyk 274b726df4
feat: add Update Available banner with GitHub release check (#94)
* fix: migrate middleware.ts to proxy.ts for Next.js 16 (#88)

Next.js 16 deprecated the `middleware` file convention in favor of
`proxy`. The proxy runs on the Node.js runtime instead of Edge, so
safeCompare now uses crypto.timingSafeEqual instead of manual XOR.

All auth logic, CSRF validation, host matching, and security headers
are preserved unchanged.

* feat: add "Update Available" banner with GitHub release check

Add a dismissible emerald banner that appears when a newer GitHub release
exists, so self-hosting users know an update is available. The banner
dismisses per-version (reappears for new releases).

- Create src/lib/version.ts as single source of truth from package.json
- Add /api/releases/check route with 1hr caching and graceful fallback
- Add UpdateBanner component mirroring LocalModeBanner pattern
- Add update state to Zustand store with localStorage persistence
- Fix hardcoded v2.0 in header-bar.tsx and 2.0.0 in websocket.ts
2026-03-03 17:17:15 +07:00
nyk 71f2627138
fix: task board SSE wiring, priority enum, webhook event, auto-advance, parallel broadcast (#73) (#89)
- Wire task board panel into Zustand store for real-time SSE updates
  instead of local useState; add useSmartPoll fallback when SSE disconnects
- Fix priority enum mismatch: UI now uses 'critical' matching the Zod
  validation schema instead of 'urgent'
- Add 'task.status_changed' to webhook EVENT_MAP so external consumers
  receive status transition events
- Auto-advance task to 'done' column when aegis quality review approves,
  broadcasting task.status_changed for real-time UI update
- Parallelize broadcast loop with Promise.allSettled so N agents execute
  concurrently (~10s) instead of serially (N×10s)

Closes #73
2026-03-03 16:20:53 +07:00
nyk 6ce38b13dc
feat: sync side panel navigation with URL routes (#76) (#87)
Move page.tsx to [[...panel]] optional catch-all route so each panel
gets its own URL (e.g. /tasks, /agents, /settings). URL is the source
of truth — synced into Zustand via usePathname on every navigation.
Enables bookmarking, refresh persistence, deep-linking, and browser
back/forward.
2026-03-03 15:08:59 +07:00
nyk a6fb27392b
fix: deduplicate sessions by sessionId and add task edit modal (#86)
Deduplicate gateway sessions server-side using sessionId as primary key,
falling back to agent:key composite for sessions without sessionId. This
prevents duplicate React keys when OpenClaw tracks cron runs under the
same session ID as the parent session.

Also adds EditTaskModal to the task board panel with inline edit button
in the task detail modal, and improves CreateTaskModal error handling.

Cherry-picked and adapted from PR #77 by @arana198.

Closes #80
2026-03-03 14:38:09 +07:00
nyk a4a606d5ac
feat: Ed25519 device identity for WebSocket challenge-response handshake (#85)
Add client-side Ed25519 key pair generation and nonce signing for
OpenClaw gateway protocol v3 connect.challenge flow. Keys persist in
localStorage and are reused across sessions. The handshake falls back
gracefully to auth-token-only mode when Ed25519 is unavailable.

Closes #74, closes #79, closes #81
2026-03-03 14:30:25 +07:00
nyk f0f22129be
fix: healthcheck auth, secure cookie auto-detect, model object crash (#84)
Bug 1 (#78): Dockerfile HEALTHCHECK curled authenticated /api/status,
always got 401 in production. Changed to /login which is public.

Bug 2 (#78): Login hangs on HTTP deployments because secure=true cookie
is silently rejected. Now auto-detects protocol from x-forwarded-proto
header, only sets secure when request actually came over HTTPS.

Bug 3 (#78): Agent model field from OpenClaw 2026.3.x is {primary: "name"}
object instead of string, causing React error #31. Added normalizeModel()
helper and applied it in all WebSocket/session mapping code paths.
2026-03-03 14:19:34 +07:00
nyk d826435401
feat: add local mode auto-detection for no-gateway users (#83)
When no OpenClaw gateway is detected, Mission Control now automatically
switches to Local Mode — showing a clear info banner, greying out
gateway-dependent panels, and surfacing Claude Code session stats,
GitHub profile data, and subscription-aware cost display.

Changes:
- Add capabilities endpoint to detect gateway, Claude home, subscription
- Add dashboardMode/gatewayAvailable/subscription state to Zustand store
- Add dismissible LocalModeBanner component
- Grey out Agents/Spawn/Config nav items when no gateway
- Show blue "Local Mode" indicator instead of red "Disconnected"
- Dashboard shows local metric cards (sessions, projects, tokens, cost)
- Claude Code Stats panel with session/token/cost breakdown
- GitHub panel with repo stats, languages, star/fork counts
- Subscription detection from ~/.claude/.credentials.json
- Show "Included (Max plan)" instead of dollar cost for subscribers
- Fix token cost estimation (cache reads at 10%, not 100%)
- Sessions API falls back to local Claude session scanner
- Live feed injects session items in local mode
- Memory browser auto-creates data dir with fallback path
2026-03-03 13:41:55 +07:00
nyk 8cb3a11baa
chore: bump version to 1.3.0 and update changelog/readme for release (#72) 2026-03-02 23:58:49 +07:00
nyk 304a9b3194
fix: cherry-pick improvements from PR #57 (#71)
Cherry-picks three valuable fixes from @doanbactam's WebSocket refactor PR:

1. Feed item ID collision fix — prefix log IDs with 'log-' to avoid
   React key collisions with activity IDs in the combined feed

2. Jittered reconnect backoff — add random jitter (0-50% of base) to
   WebSocket exponential backoff to prevent thundering-herd reconnects
   when multiple tabs reconnect after a server restart

3. Cron job deduplication + async I/O — deduplicate jobs.json entries
   by name (keeps latest), prevent duplicates on add, and convert
   sync file reads/writes to async to avoid blocking the event loop

Co-authored-by: Doan Bac Tam <24356000+doanbactam@users.noreply.github.com>
2026-03-02 23:54:20 +07:00
nyk 55fdb45e53
docs: update API route count in architecture section (#70)
Co-authored-by: 唐国梁Tommy <26358638+TGLTommy@users.noreply.github.com>
2026-03-02 23:25:36 +07:00
nyk ff5ee73dec
fix: correct model display logic in session details panel (#69)
getModelInfo() always returned the first model (haiku) for unrecognized
model names because providerAliases was a truthy string used directly
as a .find() predicate. Fix by comparing m.alias === matchedAlias.

Credit: @TGLTommy (PR #67)
2026-03-02 23:20:45 +07:00
nyk 96168fe2f4
feat: audit hardening, webhook retry, and local Claude session tracking (#68)
Security hardening:
- Fix timing-safe comparison bugs in webhooks.ts and auth.ts (was comparing buffer with itself)
- Harden rate limiter IP extraction — use rightmost untrusted IP from XFF chain with MC_TRUSTED_PROXIES support
- Add 12-char minimum password validation in Zod schema and runtime check
- Add Zod validation on PUT /api/tasks bulk status update

Webhook retry system (completing in-progress feature):
- Exponential backoff with circuit breaker in webhooks.ts
- POST /api/webhooks/retry endpoint for manual retry
- GET /api/webhooks/verify-docs endpoint for signature verification docs
- Scheduler integration for automatic retry processing
- Unit tests for signature verification and backoff logic

Local Claude Code session tracking:
- New claude-sessions.ts scanner parses JSONL transcripts from ~/.claude/projects/
- Extracts model, tokens, messages, cost estimates, active status per session
- Migration 020 adds claude_sessions table
- GET/POST /api/claude/sessions endpoint with filtering and aggregate stats
- Scheduler runs scan every 60s with MC_CLAUDE_HOME config

Quality improvements:
- Replace all console.error/warn with structured logger across 31 API routes
- Add Docker HEALTHCHECK directive
- Add vitest coverage config with v8 provider (60% threshold)
- Update README with new features, API docs, env vars, and roadmap items
- Fix E2E tests for password length and rate limiter IP changes
2026-03-02 22:17:35 +07:00
nyk b2703b37d5
fix: resolve all 44 failing CI E2E tests (#64)
* fix: resolve all 44 failing CI E2E tests

- Bypass non-critical rate limiters in test env (MC_DISABLE_RATE_LIMIT=1)
  to prevent 429s when 165 tests share the same IP bucket
- Make admin seed idempotent (INSERT OR IGNORE) to fix UNIQUE constraint
  race when multiple Next.js workers initialize concurrently
- Add distinct x-forwarded-for headers to login-flow tests so they never
  share the critical login rate-limit bucket with other test suites
- Add missing 018_token_usage migration that the heartbeat POST handler
  depends on, fixing the 500 on inline token reporting

* docs: update README with latest features and test count

- Update migration count from 15 to 18
- Update E2E test count from 146 to 165
- Move Direct CLI, OpenAPI docs, and GitHub sync to completed roadmap
- Add Direct CLI and GitHub sync feature descriptions
- Add /api/connect and /api/github to API reference
- Remove resolved known limitation (vitest stubs)
- Update repo description

* fix: prevent build-time admin seed with wrong credentials in CI

Move `cp .env.test .env` before `pnpm build` in CI workflow so env vars
are present during build. Add NEXT_PHASE guard to skip seed during build
as belt-and-suspenders — env vars may not be available at build time.

Root cause: `next build` imports db.ts, triggering seedAdminUserFromEnv()
with undefined AUTH_USER/AUTH_PASS, seeding user `admin` instead of
`testadmin`. Runtime seed then sees count > 0 and skips. Tests login
as `testadmin` which doesn't exist → 401.
2026-03-02 13:53:00 +07:00
nyk d6879c66c1
Merge pull request #63 from builderz-labs/feat/github-issues-sync
feat: GitHub Issues Sync (Phase 1)
2026-03-02 13:02:22 +07:00
Nyk 60197ab21f feat: add GitHub Issues sync (Phase 1, Issue #58)
Import GitHub issues as Mission Control tasks with duplicate detection,
priority mapping from labels, and bidirectional actions (comment/close).

- Migration 017: github_syncs table for sync history tracking
- GitHub API client (src/lib/github.ts) with fetch, comment, close ops
- POST/GET /api/github route with sync, comment, close, status actions
- GitHubSyncPanel UI: import form, issue preview, sync history, linked tasks
- Nav rail + page router wiring
- 6 E2E tests (all passing)
- Validation schema + github.synced event type
2026-03-02 12:45:39 +07:00
nyk 7eff5e8efe
Merge pull request #62 from builderz-labs/fix/ubuntu-launch-and-reconnect
fix: resolve reconnect storm and improve Ubuntu deployment
2026-03-02 12:15:50 +07:00
Nyk ebdc8de8b9 fix: resolve reconnect storm and improve Ubuntu deployment
Fix WebSocket reconnect storm (issue #53) caused by stale closure
reading connection.reconnectAttempts from Zustand state. Use a ref
to track attempts, avoiding the closure capture problem entirely.

Improve Dockerfile: create .data directory with correct ownership for
SQLite, set PORT/HOSTNAME env vars explicitly.

Add deployment guide documenting Ubuntu prerequisites (python3, make,
g++ for better-sqlite3 native compilation) and platform-specific
build constraints.
2026-03-02 12:15:19 +07:00
nyk 8510ee5f2c
Merge pull request #55 from rezero-household/docs/openclaw-memory-dir-env
docs: clarify OPENCLAW_MEMORY_DIR — memory browser shows only .sqlite without it
2026-03-02 11:51:29 +07:00
nyk f3e6c896a5
Merge pull request #54 from rezero-household/fix/websocket-auth-token-field
fix: use correct auth field in gateway WebSocket handshake
2026-03-02 11:51:19 +07:00
nyk 5c65db713c
Merge pull request #61 from builderz-labs/feat/direct-cli
feat: direct CLI integration for gateway-free connections
2026-03-02 11:45:41 +07:00
Nyk f7aa1db27e feat: add direct CLI integration for gateway-free tool connections
- Add migration 016 for direct_connections table
- Add POST/GET/DELETE /api/connect for CLI tool registration
- Enhance heartbeat POST to accept connection_id and inline token_usage
- Add connectSchema to validation
- Add connection.created/disconnected event types to event bus
- Show direct CLI connections in gateway manager panel
- Add 5 E2E tests for connection lifecycle
- Add CLI integration documentation (docs/cli-integration.md)
- Fix openapi.json brace mismatch on line 642 (Phase 2 bug)
- Add /api/connect endpoints to OpenAPI spec
2026-03-02 11:45:12 +07:00
nyk e88942e8f8
Merge pull request #60 from builderz-labs/feat/openapi-docs
feat: OpenAPI 3.1 documentation with Scalar UI
2026-03-02 11:04:11 +07:00
Nyk 4c7b3257d6 feat: add OpenAPI 3.1 documentation with Scalar UI
- Add openapi.json spec covering all 59 API routes (~95 operations)
- Serve spec at GET /api/docs (no auth required, cached)
- Add interactive Scalar API reference UI at /docs
- Allow unauthenticated access to /api/docs and /docs in middleware
- Add @scalar/api-reference-react dependency
- Add 3 E2E tests for spec validation and auth bypass
2026-03-02 11:03:16 +07:00
nyk 4489a5f715
Merge pull request #59 from builderz-labs/feat/agent-cost-panel
feat: per-agent cost breakdown panel
2026-03-02 10:47:44 +07:00
Nyk 98da58a8ba feat: add per-agent cost breakdown panel
- Add `agents` field to tokens action=stats response (groups by agent
  extracted from sessionId split on ':')
- Add new action=agent-costs returning per-agent stats, model breakdown,
  session list, and daily cost/token timeline
- New AgentCostPanel with summary cards, pie chart, trend lines,
  efficiency bars, and expandable ranking table
- Add nav-rail entry in OBSERVE group after Tokens
- Add ContentRouter case for agent-costs tab
- Add 5 E2E tests for the new API endpoints
2026-03-02 10:46:13 +07:00
rezero-household 55487bc7c9 docs: clarify OPENCLAW_MEMORY_DIR for memory browser
OpenClaw does not create a memory/ subdirectory under OPENCLAW_HOME.
Agent memory markdown files (daily logs, MEMORY.md, etc.) live in each
agent's workspace directory, not in ~/.openclaw/memory/.

Without OPENCLAW_MEMORY_DIR set, the memory browser falls back to
OPENCLAW_HOME, which only contains .sqlite session indices — not the
human-readable markdown files users expect to see.

Document the correct value and add an inline note to .env.example.
2026-03-01 14:46:54 -08:00
rezero-household 2eec86cc87 fix: use correct auth field in gateway WebSocket handshake
OpenClaw gateway configured with auth.mode='token' expects
{ token: '...' } in the connect handshake params, not { password: '...' }.
Sending 'password' causes the gateway to reject the handshake, resulting
in a disconnect→reconnect loop that floods the error log.

Tested against OpenClaw gateway v2026.2.25 with auth.mode='token'.
2026-03-01 14:46:04 -08:00
nyk e77ec4cf2d
Merge pull request #52 from builderz-labs/fix/cron-trigger-params
fix: cron job manual trigger sending wrong params
2026-03-02 02:48:09 +07:00
Nyk b6c6bb955d fix: send jobId/jobName instead of command when triggering cron jobs
The triggerJob function was sending { command: job.command } to the API,
but the backend expects jobId or jobName to identify the job. This caused
all manual cron triggers to fail with "Job ID required" (400 error).

Also adds the missing `id` field to the CronJob store interface so
TypeScript recognizes the field already returned by the API.
2026-03-02 02:44:20 +07:00
nyk 1544d9f725
Merge pull request #51 from builderz-labs/feat/e2e-test-expansion
E2E test expansion + middleware fix + roadmap updates
2026-03-02 02:26:11 +07:00
Nyk a2846357ac docs: add per-agent cost breakdowns to roadmap
User feedback: per-agent cost visibility is a top priority for
operators running their own agent orchestration setups. Currently
derivable from per-session data but not yet a dedicated panel.
2026-03-02 02:21:45 +07:00
Nyk 45ad4a488b test: add 94 E2E tests covering all CRUD routes + fix middleware location
Add comprehensive Playwright E2E test coverage for all major API routes:
- tasks-crud (18 tests): full lifecycle, filters, Aegis approval gate
- agents-crud (15 tests): CRUD, lookup by name/id, admin-only delete
- task-comments (7 tests): threaded comments, validation
- workflows-crud (8 tests): workflow template lifecycle
- webhooks-crud (9 tests): secret masking, regeneration
- alerts-crud (8 tests): alert rule lifecycle
- notifications (7 tests): delivery tracking, read status
- quality-review (6 tests): reviews with batch lookup
- search-and-export (7 tests): global search, export, activities
- user-management (8 tests): user admin CRUD
- helpers.ts: shared factory functions and cleanup utilities

Infrastructure fixes:
- Move middleware.ts to src/middleware.ts (Next.js 16 Turbopack
  requires middleware in src/ when using src/app/ directory — the
  root-level file was silently ignored, breaking CSRF protection)
- Add MC_DISABLE_RATE_LIMIT env var to bypass non-critical rate
  limiters during E2E runs (login limiter stays active via critical flag)
- Fix limit-caps test: /api/activities caps at 500, not 200
- Set playwright workers=1, fullyParallel=false for serial execution
- Add CSRF origin fallback to request.nextUrl.host

Roadmap additions from user feedback:
- Agent-agnostic gateway support (not just OpenClaw)
- Direct CLI integration (Codex, Claude Code, etc.)
- Native macOS app (Electron or Tauri)

146/146 E2E tests passing (up from 51).
2026-03-02 02:21:10 +07:00
nyk 31520fe85d
Merge pull request #50 from builderz-labs/feat/v1.2-release
feat: v1.2.0 — validation hardening, unit tests, quality improvements
2026-03-02 00:26:13 +07:00
Nyk df06c3a2ad feat: v1.2.0 — validation hardening, unit tests, quality improvements
- Fix task status enum mismatch (blocked → quality_review)
- Add 12 Zod schemas for all unvalidated mutation routes
- Apply validateBody() across 11 API route handlers
- Add readLimiter (120/min) for GET-heavy endpoints
- Extend heavyLimiter to search, backup, cleanup routes
- Add security headers (X-Content-Type-Options, X-Frame-Options, Referrer-Policy)
- Fill auth test stubs with real assertions (safeCompare, requireRole)
- Add validation, rate-limit, and db-helpers unit test suites (60 tests total)
- Replace as-any casts with typed interfaces (SessionQueryRow, UserQueryRow, CountRow)
- Bump version to 1.2.0, add CHANGELOG.md, update README roadmap
2026-03-02 00:22:59 +07:00
nyk 281315c685
Merge pull request #49 from builderz-labs/fix/scrub-sensitive-data
fix: scrub deployment-specific data from public repo
2026-03-01 15:40:16 +07:00
Nyk ef872652e9 fix: replace screenshot with redacted version
Blur Sessions, Recent Logs, and Live Feed panels to remove
production filesystem paths and agent session names.
2026-03-01 15:39:49 +07:00
Nyk 8dd6e7ef17 fix: scrub deployment-specific data from public repo
- Replace hardcoded Telegram bot integrations (Jarv/Forge/Nefes/Ops)
  with a single generic Telegram entry
- Remove 'forge' agent from hardcoded UI color themes
- Replace /home/openclaw/ paths in .env.example with /path/to/
- Fix default port in scripts: 3005 → 3000 (matches docs)
- Replace 'Jarvis' placeholder with generic 'my-agent'
- Rename 'Forge' → 'Builder' in agent identity registry
2026-03-01 15:37:55 +07:00
nyk 55b2544aab
Merge pull request #47 from builderz-labs/fix/v1.1-security-bugs
fix: patch security and build bugs in v1.1
2026-03-01 15:35:00 +07:00
nyk 9c95933521
Merge pull request #48 from builderz-labs/docs/add-screenshot
docs: add dashboard screenshot and fix E2E test count
2026-03-01 15:27:48 +07:00