Three settings rows are hidden via `if (false)` — all code is fully preserved
and can be restored by removing the condition:
- 对话引擎: 引擎切换属平台级配置,普通用户无需感知
- 检查更新: 启动时已静默后台检查,无需额外入口
- 语音 I/O 测试: 仅供开发调试,正式版不对用户展示
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The it0hub org doesn't exist on Docker Hub. Switch to hailin168/openclaw-bridge:latest
which was built and pushed from openclaw source + IT0 bridge.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- agent-instance.controller: POST :id/heartbeat — bridge calls this every 60s;
auto-transitions status from deploying→running when gateway is confirmed connected
- system-prompt-builder: teach iAgent about OpenClaw deployment capability:
create/list/stop/remove instance API endpoints, when to trigger deployment,
and what to tell users about channel connectivity (Telegram/WhatsApp etc.)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add animated robot avatar widget (CustomPainter, 5 states: idle/thinking/executing/speaking/alert)
- Add FloatingRobotFab that mirrors chatProvider AgentStatus as robot animation state
- Replace 5-tab nav (dashboard/chat/tasks/alerts/settings) with 4-tab (home/my-agents/billing/profile)
- Chat is now pushed full-screen from the robot FAB with slide-up transition
- HomePage: active agent status card + official agent horizontal scroll + quick tips
- MyAgentsPage: empty state with 3-step guide + template grid; shows list when agents exist
- ProfilePage: merged settings + prominent billing entry (replaces old SettingsPage as tab)
- ChatPage AppBar: robot avatar replaces plain text title, reflects real-time agent state
- Add agentConfigs endpoint to ApiEndpoints
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Backend: GET /api/v1/auth/my-org returns tenant info + member list
- Backend: GET /api/v1/auth/my-org/invites lists pending invites
- Backend: POST /api/v1/auth/my-org/invite creates invite link
- Frontend: /my-org page with member list and invite creation
- Frontend: add '用户管理' to tenant sidebar
- Frontend: add '套餐' (plans) to tenant billing section
- Frontend: admin layout initializes tenant store (fixes '租户:未选择')
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- auth-service: add SmsService (Aliyun SMS) + RedisProvider for OTP storage
- POST /api/v1/auth/sms/send — send OTP (rate limited 1/min per phone)
- POST /api/v1/auth/sms/verify — verify OTP only
- POST /api/v1/auth/login/otp — passwordless login with phone + OTP
- register endpoint now requires smsCode when registering with phone
- Web Admin register page: add OTP input + 60s countdown button for phone mode
- Flutter login page: add 验证码登录 tab with phone + OTP flow
- SMS enabled via ALIYUN_ACCESS_KEY_ID/SECRET + SMS_ENABLED=true env vars
- Falls back to mock mode (logs code) when env vars not set
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously GET /api/v1/billing/subscription threw 404 for tenants with no
subscription, causing React Query error state on the Plans and Overview pages.
Now returns a graceful default response so the UI renders without errors.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Systematically add platform_admin and platform_super_admin to all
controllers that were restricted to 'admin' only:
- audit-service: queryLogs, exportLogs
- inventory-service: decryptCredential
- auth-service: RoleController, PermissionController
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
SettingsController was restricted to 'admin' only, blocking platform_admin
from the dashboard settings page (403 on general/api-keys/theme/account).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Member/invite endpoints were restricted to 'admin' role only, blocking
platform_admin from accessing them on the tenant detail page (403).
Added platform_admin and platform_super_admin to all six endpoints.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- listMembers was returning { data, total } but frontend expects TenantMember[]
directly, causing members.map is not a function crash on the detail page.
- updateMember now also syncs role changes to public.users so the new role
takes effect the next time the user logs in (JWT is generated from public.users).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
After a platform admin sends an invite, the generated invite URL is
displayed inline with a one-click copy button so it can be shared via
any channel (email, WeChat, etc.). Link auto-dismisses when the invite
form is reopened.
Also adds i18n keys for invite link UI in en/zh.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- TenantController invite endpoints (list/create/revoke) were passing the
tenant UUID from the URL param directly to AuthService methods that
expect a slug, causing 404 on every invite operation. Now resolves
tenant via findTenantOrFail() first and passes slug.
- removeMember now also deletes from public.users so removed members
can no longer log in.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously, acceptInvite only wrote to the tenant schema, causing invited
users to be invisible to the login() flow which queries public.users for
cross-tenant email/phone lookup. Now inserts into both public.users and
the tenant schema within the same transaction, matching registerWithNewTenant behavior.
Also tightens duplicate check to cross-tenant uniqueness (public.users)
instead of per-tenant.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Each tenant row now has a Delete button with confirmation dialog.
Previously delete was only accessible from the detail page which
had no navigation link from the list.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- DELETE /api/v1/admin/tenants/:id now accepts platform_admin role
- Fix cascade cleanup to use tenant slug (not UUID) for users/invites/api_keys
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- createInvite: findOneBy({ slug }) instead of { id } since JWT tenantId is slug
- getMemberCount: use SET LOCAL + transaction to prevent pool search_path leak
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Users list: use ADMIN_TOKEN (platform_admin role required)
- Billing subscription: accept 200 or 404 (new tenants have no subscription)
- Invite flow: use TOKEN (tenant admin 'admin' role) not ADMIN_TOKEN
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Change SET search_path to SET LOCAL in tenant schema template (002)
so it reverts on COMMIT and doesn't contaminate the connection pool
- Add RESET search_path before queryRunner.release() as defensive measure
- Add ALTER TABLE public.tenants admin_email DROP NOT NULL to migration 007
to sync the direct server change back to source
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The backend returns { data: User[], total: number } but the frontend
was treating usersData directly as User[], causing filteredUsers.map
to throw 'not a function' when the page loaded.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
billing/page.tsx, billing/plans/page.tsx, billing/invoices/page.tsx
were hardcoded in English. Added zh/billing.json and en/billing.json
covering overview, plans, and invoices sections. Registered billing
namespace in i18n config.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Platform admins operate across all tenants and don't belong to any
specific tenant — showing 'Tenant: Not selected' was misleading.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>