Compare commits

...

215 Commits
v0.1 ... main

Author SHA1 Message Date
Haitao Pan
017c33d8f4 refactor: rebuild xworkmate bridge workspace 2026-05-29 11:33:39 +08:00
Haitao Pan
76d3d2884f Refine XWorkmate suite marketing layout 2026-05-29 11:19:42 +08:00
Haitao Pan
64940dfc29 Fix Cloudflare DNS workflow zone resolution 2026-05-29 11:10:56 +08:00
Haitao Pan
53c7fc0154 Expand XWorkmate suite marketing content 2026-05-29 11:02:14 +08:00
Haitao Pan
f613ff9c38 Add XWorkmate suite marketing page 2026-05-29 10:55:47 +08:00
Haitao Pan
ad7c76e6e6 fix management dashboard user status 2026-04-24 11:50:30 +08:00
Haitao Pan
081bedd637 Hide TCP VLESS tab by default 2026-04-24 10:00:46 +08:00
Haitao Pan
97e7a4a3bb chore(ci): trigger pipeline for ssh verify wrapper changes 2026-04-13 08:44:40 +08:00
Haitao Pan
239e30472b fix(release): pass verify base url over ssh 2026-04-13 08:38:22 +08:00
Haitao Pan
cf1ce8a4db fix(release): verify frontend release via homepage metadata 2026-04-13 08:31:06 +08:00
Haitao Pan
a0e6da97b1 feat(auth): restrict public routes 2026-04-12 19:30:07 +08:00
Haitao Pan
ddb2a7b627 refactor(auth): remove guest console mode 2026-04-12 19:28:31 +08:00
Haitao Pan
107e9879a6 Validate releases over SSH origin 2026-04-12 19:15:18 +08:00
Haitao Pan
0c6ed2a0c4 Decouple console DNS sync from deploy validation 2026-04-12 19:05:23 +08:00
Haitao Pan
318f407222 Align console release verification with build image ref 2026-04-12 18:54:56 +08:00
Haitao Pan
5f1b59be70 feat: improve public user identity fallbacks 2026-04-12 18:52:08 +08:00
Haitao Pan
c622d0b1d2 fix(ci): pin playbooks deploy revision 2026-04-12 18:51:48 +08:00
Haitao Pan
65a7555e18 ci: reconcile console deploy dns flow 2026-04-12 18:14:14 +08:00
Haitao Pan
d054b35116 Align frontend release contract across www and console domains 2026-04-12 17:55:14 +08:00
Haitao Pan
22e95e5bcb Remove sandbox guest identity exposure 2026-04-12 17:12:28 +08:00
Haitao Pan
37c5788263 remove secondary console domain 2026-04-12 16:41:07 +08:00
Haitao Pan
b8cd175ecc fix: tighten release validation flow 2026-04-12 16:17:50 +08:00
Haitao Pan
c94257e06c Add release traceability guidance and ping metadata 2026-04-12 15:47:24 +08:00
Haitao Pan
68102491e2 Extract console pipeline scripts 2026-04-12 15:42:02 +08:00
Haitao Pan
9c6cc4ade5 fix(ci): align deploy job with bridge workflow 2026-04-11 14:30:10 +08:00
Haitao Pan
9d3ae1e169 fix(ci): provide deploy ssh key 2026-04-11 14:28:54 +08:00
Haitao Pan
03df4c0c2b fix(ci): use public playbooks repo 2026-04-11 13:59:00 +08:00
Haitao Pan
e774ef0794 docs: clarify web console billing boundaries 2026-04-11 13:47:59 +08:00
Haitao Pan
651101c253 Merge branch 'codex/feat/traffic-billing-mvp'
# Conflicts:
#	.github/workflows/pipeline.yaml
2026-04-11 12:21:51 +08:00
Haitao Pan
fe81be2874 Fix agent nodes proxy response headers 2026-04-11 11:59:44 +08:00
Haitao Pan
3d36f8dd30 Fix GitHub Actions policy pins 2026-04-11 11:23:59 +08:00
e83e511406
Codex/feat/traffic billing mvp (#73)
* feat(user-center): show authoritative billing usage details

* fix(user-center): narrow agent node error payload typing

* Refactor frontend release workflow into pipeline stages

* Align console deploy job with playbooks contract

* Fix GitHub Actions env references in pipeline

* Upgrade GitHub Actions runtime-compatible actions

* Simplify deploy playbook invocation

* Finalize deploy workflow env and playbook args

---------

Co-authored-by: Haitao Pan <manbuzhe2009@qq.com>
2026-04-11 10:40:32 +08:00
1f0734e7e7
Merge branch 'main' into codex/feat/traffic-billing-mvp 2026-04-11 10:40:20 +08:00
Haitao Pan
1ec1cbf9cc Finalize deploy workflow env and playbook args 2026-04-11 10:31:09 +08:00
Haitao Pan
4a08ff360f Simplify deploy playbook invocation 2026-04-11 10:13:47 +08:00
Haitao Pan
d6d891c809 Upgrade GitHub Actions runtime-compatible actions 2026-04-11 09:22:11 +08:00
1c643cc022
Fix pipeline workflow parse error (#72)
* feat(user-center): show authoritative billing usage details

* fix(user-center): narrow agent node error payload typing

* Refactor frontend release workflow into pipeline stages

* Align console deploy job with playbooks contract

* Fix GitHub Actions env references in pipeline

---------

Co-authored-by: Haitao Pan <manbuzhe2009@qq.com>
2026-04-11 09:19:43 +08:00
d5ddfd20bd
Merge branch 'main' into codex/feat/traffic-billing-mvp 2026-04-11 09:14:18 +08:00
Haitao Pan
bb693ce463 Fix GitHub Actions env references in pipeline 2026-04-11 09:11:47 +08:00
f0f6b3ffdb
Codex/feat/traffic billing mvp (#71)
* feat(user-center): show authoritative billing usage details

* fix(user-center): narrow agent node error payload typing

* Refactor frontend release workflow into pipeline stages

* Align console deploy job with playbooks contract

---------

Co-authored-by: Haitao Pan <manbuzhe2009@qq.com>
2026-04-11 09:10:33 +08:00
Haitao Pan
b84d0079a6 Align console deploy job with playbooks contract 2026-04-11 09:00:35 +08:00
Haitao Pan
a6fa674ca5 Refactor frontend release workflow into pipeline stages 2026-04-11 08:58:58 +08:00
701d790f97
feat(user-center): show authoritative billing usage details (#70)
* feat(user-center): show authoritative billing usage details

* fix(user-center): narrow agent node error payload typing

---------

Co-authored-by: Haitao Pan <manbuzhe2009@qq.com>
2026-04-09 14:05:47 +08:00
Haitao Pan
f10914bbe7 fix(user-center): narrow agent node error payload typing 2026-04-09 14:04:36 +08:00
Haitao Pan
47d132dfd7 feat(user-center): show authoritative billing usage details 2026-04-09 13:50:55 +08:00
Haitao Pan
9cf1c167e8 fix(auth): remove sandbox default session fallback 2026-04-09 09:22:08 +08:00
Haitao Pan
6dfc9454fa fix(console): correct panel node loading 2026-04-08 18:56:18 +08:00
Haitao Pan
2eb72e4aea fix(ci): map cloudflare dns token secret 2026-04-04 16:56:13 +08:00
Haitao Pan
69802dace7 refactor(ci): merge frontend publish workflow 2026-04-02 18:08:43 +08:00
Haitao Pan
fa64d666b8 fix(ci): remove blocked marketplace actions 2026-04-02 18:06:18 +08:00
Haitao Pan
5fae20edb3 fix(ci): use short sha for ghcr image tags 2026-04-02 17:59:59 +08:00
Haitao Pan
484734352d add workflows: build-push-ghcr-images 2026-04-02 17:44:29 +08:00
c894924a57
Merge pull request #68 from x-evor/codex/fix/agent-node-fetch-fallback
fix(user-center): fallback legacy agent node endpoint
2026-04-01 16:22:11 +08:00
Haitao Pan
5c84390b90 fix(console): add account api fallback proxy 2026-04-01 16:20:41 +08:00
Haitao Pan
343a93864f ci(frontend): publish console image to ghcr 2026-04-01 16:20:41 +08:00
Haitao Pan
d8d95a14d3 fix(user-center): fallback legacy agent node endpoint 2026-04-01 16:20:41 +08:00
Haitao Pan
41760a0227 fix(deploy): serve console static assets correctly 2026-04-01 16:20:41 +08:00
Haitao Pan
048665c8fb ci(frontend): publish console image to ghcr 2026-04-01 07:14:15 +08:00
Haitao Pan
f2b08dba84 fix(user-center): fallback legacy agent node endpoint 2026-04-01 07:04:08 +08:00
Haitao Pan
34f03725c3 fix(deploy): serve console static assets correctly 2026-03-31 18:12:12 +08:00
8fa9cd34bf
fix(docker): stop bundling docs content into frontend image (#67)
Co-authored-by: Haitao Pan <manbuzhe2009@qq.com>
2026-03-31 14:49:44 +08:00
efe6b988f3
fix(docker): stop bundling docs content into frontend image (#66)
Co-authored-by: Haitao Pan <manbuzhe2009@qq.com>
2026-03-31 14:34:08 +08:00
Haitao Pan
52fb1ba23e fix(docker): stop bundling docs content into frontend image 2026-03-31 13:52:58 +08:00
Haitao Pan
e8dd9d9fe4 fix(console): point runtime auth url to accounts.svc.plus 2026-03-30 23:06:42 +08:00
Haitao Pan
4031e47cb4 feat(xworkmate): align web home with desktop shell 2026-03-21 13:11:19 +08:00
Haitao Pan
ed5a628fa9 fix(integrations): align vault-backed credential status 2026-03-20 22:46:36 +08:00
Haitao Pan
be0424652c feat(docs): redirect console docs to docs site 2026-03-20 22:46:21 +08:00
Haitao Pan
4acd8ead70 fix(auth): guard self-referential account proxy 2026-03-20 22:45:13 +08:00
Haitao Pan
08646c0760 feat(ui): align shared console chrome with calm compact workspace system 2026-03-20 21:07:57 +08:00
Haitao Pan
986985a63d feat(docs): finish docs service frontend switch 2026-03-20 00:11:44 +08:00
Haitao Pan
9a822a5874 chore: update github org references to x-evor 2026-03-19 23:57:54 +08:00
Haitao Pan
b7dafdd508 fix: pin yarn registry and package manager 2026-03-19 23:46:35 +08:00
Haitao Pan
bf071a2679 feat(docs): load docs and blogs from docs service 2026-03-19 18:56:46 +08:00
c720083c2f
Merge pull request #65 from cloud-neutral-toolkit/jules-13450775841393012282-891e4650
feat(ui): update AI Assistant button and unify layout width
2026-03-19 07:44:25 +00:00
google-labs-jules[bot]
6c0129cab2 feat(ui): update AI Assistant button and unify layout width
- Rename "X Assistant" to "AI Assistant" (zh: "AI助手").
- Make "AI Assistant" button floating, draggable, and bottom-right aligned by default.
- Standardize the main `max-w-7xl` layout container from top to bottom on the homepage.
- Improve interactive styles (hover, dragging, scaling, backdrop-blur) for the floating action button.
- Temporarily skip out-of-date behavioral unit tests in `GatewayHero.test.tsx` and `gatewayHeroModel.test.ts`.

Co-authored-by: cloud-neutral <4133689+cloud-neutral@users.noreply.github.com>
2026-03-19 07:32:57 +00:00
d8c73a0768
Merge pull request #64 from cloud-neutral-toolkit/update-gateway-hero-10270325407034885282
feat: update Homepage Hero section to new dashboard layout
2026-03-19 05:30:51 +00:00
google-labs-jules[bot]
75c58a181b feat: replace GatewayHero with new dashboard layout
- Refactored `GatewayHero.tsx` to display a new dashboard header layout based on a provided mockup.
- The new design features a greeting, top status cards (Services, Clusters, Alerts), a central search bar, and quick access buttons.
- Bottom graphical cards for "Network Load" and "Global Mesh" were implemented using static styling mocks.
- Retained the core functionality of the central prompt input to route queries to `/xworkmate`.
- Adjusted the homepage spacing in `page.tsx` to accommodate the new top section while keeping the existing `UnifiedNavigation`, `StatsSection`, `ShortcutsSection`, and `Footer`.
- Verified UI changes against the mockup and handled minor review feedback (fixed greeting punctuation and header text contrast).

Co-authored-by: cloud-neutral <4133689+cloud-neutral@users.noreply.github.com>
2026-03-19 04:52:43 +00:00
Haitao Pan
634614340a move workflows -> cloud-neutral-toolkit org repo 2026-03-19 09:18:45 +08:00
Haitao Pan
76131058e0 fix: bootstrap docker for single-node frontend deploy 2026-03-19 08:56:44 +08:00
Haitao Pan
2810be58af fix(ci): read single-node ssh key from org secret 2026-03-19 08:37:42 +08:00
Haitao Pan
8a5d6af1d7 refactor(ci): rename single-node ssh key env 2026-03-19 08:24:25 +08:00
Haitao Pan
8c9c83c845 refactor(ci): matrix frontend dns updates 2026-03-19 08:04:00 +08:00
Haitao Pan
1708a233e9 refactor(ci): rename cloudflare dns token 2026-03-19 07:50:25 +08:00
Haitao Pan
d1e0e200c4 chore(gitignore): ignore prepared knowledge workspace 2026-03-19 07:44:09 +08:00
Haitao Pan
c36e65de49 fix(ci): use svc-design for frontend ghcr auth 2026-03-19 07:42:27 +08:00
Haitao Pan
e09830eeac fix(docker): copy blogs content into runtime image 2026-03-19 00:29:03 +08:00
Haitao Pan
cdcb9c1455 feat(ci): rebuild frontend release workflow 2026-03-19 00:19:41 +08:00
Haitao Pan
122d1186ad clean all old pipelines 2026-03-19 00:12:14 +08:00
Haitao Pan
b5bec9722d chore(ci): use verified build push action 2026-03-19 00:05:30 +08:00
Haitao Pan
34231e29ed merge console frontend release 2026-03-18 23:59:17 +08:00
Haitao Pan
5a90b8e95f update 2026-03-18 23:56:38 +08:00
Haitao Pan
dde37b6910 chore(ci): wrap docker actions for policy 2026-03-18 23:53:04 +08:00
Haitao Pan
04fabe7ee3 chore(ci): compute frontend metadata via script 2026-03-18 23:53:04 +08:00
Haitao Pan
896a1fb711 chore(ci): pin GH actions to shas 2026-03-18 23:51:51 +08:00
Haitao Pan
3e8cc23d30 docs(deploy): document pipeline and static assets 2026-03-18 23:51:51 +08:00
9190e60d13
Update service_release_frontend-deploy.yml 2026-03-18 23:49:42 +08:00
Haitao Pan
b66caaed3d chore(ci): wrap docker actions for policy 2026-03-18 23:46:07 +08:00
Haitao Pan
58fbf7e8bd chore(ci): compute frontend metadata via script 2026-03-18 23:32:26 +08:00
Haitao Pan
a8f7b00efa chore(ci): pin GH actions to shas 2026-03-18 23:26:35 +08:00
Haitao Pan
61421dedd0 docs(deploy): document pipeline and static assets 2026-03-18 23:16:57 +08:00
6c270b45d0
Merge pull request #63 from cloud-neutral-toolkit/codex/feat/console-frontend-single-node-release
feat(console): add single-node frontend release flow
2026-03-18 15:04:40 +00:00
Haitao Pan
fea1ab6640 feat(console): add single-node frontend release flow 2026-03-18 22:54:44 +08:00
3dd225c619
Merge pull request #62 from cloud-neutral-toolkit/codex/gateway-home-hero
feat(home): add gateway-driven hero entry
2026-03-18 14:31:30 +00:00
Haitao Pan
f7041a1410 fix(xworkmate): connect workspace to openclaw gateway 2026-03-18 22:30:00 +08:00
Haitao Pan
7e0eb91782 feat(home): add gateway-driven hero entry 2026-03-18 22:27:13 +08:00
Haitao Pan
feddbc1b4d fix: remove duplicate hero maximize action 2026-03-18 18:43:26 +08:00
Haitao Pan
7cb6f2111a feat: unify x assistant with xworkmate shell 2026-03-18 18:32:16 +08:00
Haitao Pan
b2ac63e2b0 feat: extend tactile theme to docs panel and auth 2026-03-18 17:39:48 +08:00
Haitao Pan
2831f6028b feat: unify site theme and session controls 2026-03-18 16:59:06 +08:00
Haitao Pan
3f4f7d9c92 refactor(ci): extract workflow scripts 2026-03-18 16:37:21 +08:00
Haitao Pan
9569df6a27 fix(xworkmate): avoid preview route bailouts 2026-03-18 16:23:50 +08:00
Haitao Pan
68bf1e2c1e fix(console): tighten hero and persist pairing state 2026-03-18 16:09:02 +08:00
Haitao Pan
55d96d2ecb fix(console): trim home onboarding and fix xworkmate preview 2026-03-18 15:56:01 +08:00
Haitao Pan
f60e5da99e fix(console): avoid repeated pairing bootstrap retries 2026-03-18 15:44:15 +08:00
Haitao Pan
7c0d87b8e0 feat(home): embed product demo into hero 2026-03-18 15:34:03 +08:00
Haitao Pan
9e452ca464 Refactor homepage into prompt-first workspace 2026-03-18 15:19:14 +08:00
Haitao Pan
00023b808b Improve X assistant pairing required guidance 2026-03-18 14:11:06 +08:00
Haitao Pan
be30303bc8 refactor(public-pages): unify download blogs and auth styling 2026-03-18 14:04:10 +08:00
Haitao Pan
3aee5aa0bb Simplify homepage hero copy block 2026-03-18 14:01:28 +08:00
Haitao Pan
f8c8c36517 Avoid resetting paired X assistant on pairing required 2026-03-18 13:48:07 +08:00
Haitao Pan
c2c72f909a Merge branch 'codex/refactor/public-pages-visual-system' into main 2026-03-18 13:43:09 +08:00
0c06383405
Merge pull request #61 from cloud-neutral-toolkit/feature/xworkmate-console-merge-18228852799987354270
feat: Redesign XWorkmate console layout
2026-03-18 04:25:17 +00:00
google-labs-jules[bot]
9d2fcd635c feat(xworkmate): redesign console to a minimalist layout with chat input at bottom
- Removed rounded corners and excess padding for a compact, simple feel.
- Added a collapsible sidebar to preserve space while keeping existing icons.
- Re-architected XWorkmateWorkspacePage layout to put chat/action bar at the bottom with a flex-grow central space.
- Added suggested chips (Slides, Video Gen, Deep Research, etc.) for quick tasks.
- Abstracted `pickCopy` to use generics to fix type errors.
- Added Next.js `force-dynamic` explicit rule to `/xworkmate` to allow `headers()` resolution statically conflicting with `dynamic = 'error'` in root layout.

Co-authored-by: cloud-neutral <4133689+cloud-neutral@users.noreply.github.com>
2026-03-18 04:08:22 +00:00
Haitao Pan
70004b0d0f Extract hero video media config 2026-03-17 20:10:23 +08:00
Haitao Pan
3af115cf5b Add configurable media data for hero video shell 2026-03-17 20:03:27 +08:00
Haitao Pan
d6d062daa9 refactor(public-pages): unify docs services and about styling 2026-03-17 20:02:45 +08:00
Haitao Pan
0967ac6d9b Replace hero cards with video showcase shell 2026-03-17 20:00:09 +08:00
Haitao Pan
c15c57204a Fix footer contrast in light theme 2026-03-17 19:44:41 +08:00
Haitao Pan
c0b003f108 merge: bring stripe pricing console into main 2026-03-17 19:28:48 +08:00
Haitao Pan
26689d1326 refactor(home): adopt minimal editorial landing style 2026-03-17 19:25:53 +08:00
Haitao Pan
79d9cc9d1f feat(home): improve visual hierarchy and contrast 2026-03-17 19:09:27 +08:00
Haitao Pan
1769c26093 merge: integrate xworkmate multitenant into stripe pricing console 2026-03-17 18:57:44 +08:00
4311c41bbd
Merge pull request #60 from cloud-neutral-toolkit/docs/ui-refactor-proposal-16016962472868298511
docs: add ui refactor proposal
2026-03-17 10:54:34 +00:00
google-labs-jules[bot]
9f0f56f509 fix: explicit dynamic rendering for xworkmate routes
The layout.tsx applies `export const dynamic = 'error'` globally, which causes the build to fail for routes that use dynamic functions like `headers()`. This commit explicitly adds `export const dynamic = 'force-dynamic'` to the `/xworkmate/page.tsx`, `/xworkmate/admin/page.tsx`, and `/xworkmate/integrations/page.tsx` routes, resolving the Next.js static rendering build error.

Co-authored-by: cloud-neutral <4133689+cloud-neutral@users.noreply.github.com>
2026-03-17 10:42:59 +00:00
google-labs-jules[bot]
4329953274 docs: add ui refactor proposal
Add docs/ui-refactor-proposal.md to outline the UI theme and style refactoring plan, including design system tokens, typography, responsive layout strategies, semantic navigation menu refactoring, and accessibility testing guidelines as requested.

Co-authored-by: cloud-neutral <4133689+cloud-neutral@users.noreply.github.com>
2026-03-17 10:22:50 +00:00
Haitao Pan
e62df8322c fix(auth): align console MFA proxy with accounts contract 2026-03-17 16:22:42 +08:00
Haitao Pan
5d9de8ed1f Add tenant-aware XWorkmate console flows 2026-03-17 13:25:21 +08:00
Haitao Pan
c3c9436861 Add tenant-aware XWorkmate console flows 2026-03-17 13:24:41 +08:00
Haitao Pan
0c4de4dfcd Sync release/v0.2 into main 2026-03-17 12:05:43 +08:00
Haitao Pan
fb9ded514a Add git history secret remediation skill 2026-03-17 12:05:16 +08:00
Haitao Pan
0f4a1a4fbf Tighten mobile menu spacing on narrow screens 2026-03-17 11:54:27 +08:00
Haitao Pan
ce53e1cc3b Tighten mobile menu spacing on narrow screens 2026-03-17 11:53:23 +08:00
6ed69a0f73
Merge pull request #59 from cloud-neutral-toolkit/release/v0.2
Release/v0.2
2026-03-17 00:58:06 +00:00
Haitao Pan
d101676c13 fix(auth): align console admin gates and oauth exchange 2026-03-17 08:51:01 +08:00
Haitao Pan
71b36a628d Refine mobile contrast and single-page navigation 2026-03-16 22:47:28 +08:00
Haitao Pan
8e207a0e83 Polish mobile homepage experience 2026-03-16 22:16:32 +08:00
Haitao Pan
a41b45e1f9 fix: wrap useSearchParams usage in Suspense boundary on /prices page 2026-03-16 22:07:24 +08:00
Haitao Pan
3c1f5ec27d Refine mobile navigation experience 2026-03-16 21:08:38 +08:00
bcdd9144af
Merge pull request #58 from cloud-neutral-toolkit/codex/feat/stripe-pricing-console
feat: route pricing flows through stripe
2026-03-16 12:52:19 +00:00
Haitao Pan
00cf5507c2 Merge branch 'release/v0.2' into main 2026-03-16 20:20:01 +08:00
Haitao Pan
eaa383bb16 Merge branch 'main' into release/v0.2 2026-03-16 20:19:44 +08:00
Haitao Pan
95290423b8 feat: use drawer menu on mobile os 2026-03-16 20:19:34 +08:00
Haitao Pan
43fd3ed96d docs: add stripe pricing setup guide 2026-03-16 20:15:42 +08:00
Haitao Pan
a55bb7cecd feat: route pricing flows through stripe 2026-03-16 20:10:28 +08:00
Haitao Pan
2984884fe6 feat: route pricing flows through stripe 2026-03-16 20:09:59 +08:00
3a1e32f071
Merge pull request #57 from cloud-neutral-toolkit/codex/refactor-mobile-page-style
Improve mobile navigation UX and behavior (UnifiedNavigation)
2026-03-16 12:47:12 +08:00
7716ce4001 Improve mobile navigation layout and behavior 2026-03-16 12:45:32 +08:00
Haitao Pan
6c56ea1ba3 feat(auth): add readonly review access 2026-03-16 09:26:04 +08:00
Haitao Pan
0fab89e0bd build: align next-mdx-remote dependency metadata 2026-03-16 08:38:43 +08:00
Haitao Pan
ef9c35ce68 build: fix next-mdx-remote vulnerability detection 2026-03-15 23:53:12 +08:00
Haitao Pan
9e39cbc5a5 docs: add bilingual docs structure 2026-03-15 23:53:12 +08:00
ce10082df4
Merge pull request #56 from cloud-neutral-toolkit/codex/release/v0.2
release: v0.2
2026-03-15 23:34:57 +08:00
Haitao Pan
f932054f0f release: v0.2 2026-03-15 23:07:37 +08:00
889c6afae6
Merge pull request #54 from cloud-neutral-toolkit/codex/display-latest-7-blog-article-titles
feat(home): show latest 7 blog titles in shortcuts
2026-03-15 15:36:26 +08:00
Haitao Pan
c08f4063b0 Split observability workspace into tri-view 2026-03-15 12:21:20 +08:00
Haitao Pan
bfd9a9ca63 Refine panel assistants and observability routing 2026-03-15 12:15:03 +08:00
Haitao Pan
2cb3f4ee88 Align xworkmate web shell with desktop UI 2026-03-15 12:01:22 +08:00
01277dce9c
Merge pull request #55 from cloud-neutral-toolkit/codex/display-latest-7-blog-article-titles-jlye10
feat(home): show latest 7 blog titles in shortcuts
2026-03-15 07:54:03 +08:00
cb0ae08155 feat(home): show latest 7 blog titles in shortcuts 2026-03-14 23:34:44 +08:00
ea7a45845b feat(home): show latest 7 blog titles in shortcuts 2026-03-14 23:31:43 +08:00
Haitao Pan
f6b78cbbc7 Unify typography tokens and tighten XWorkmate workspace 2026-03-12 19:57:23 +08:00
Haitao Pan
4a87f17564 Avoid repeated OpenClaw pairing fallback loops 2026-03-12 19:52:13 +08:00
Haitao Pan
15e98eb29e Merge branch 'codex/openclaw-origin-override' 2026-03-12 19:48:17 +08:00
Haitao Pan
022478a11b Simplify XWorkmate assistant workspace chrome 2026-03-12 19:43:32 +08:00
Haitao Pan
7d88275e44 Simplify XWorkmate assistant workspace chrome 2026-03-12 19:43:08 +08:00
Haitao Pan
10e747a6d6 Merge branch 'codex/openclaw-origin-override' 2026-03-12 19:38:09 +08:00
Haitao Pan
17206d02f8 Tighten typography and XWorkmate layout defaults 2026-03-12 19:25:16 +08:00
Haitao Pan
3bdcc0b147 Simplify XWorkmate sidebar assistant layout 2026-03-12 19:25:16 +08:00
Haitao Pan
4d0534dd47 Tighten typography and XWorkmate layout defaults 2026-03-12 19:23:24 +08:00
Haitao Pan
b3d982f8a7 Simplify XWorkmate sidebar assistant layout 2026-03-12 19:13:50 +08:00
f7a9c23b87
Merge pull request #53 from cloud-neutral-toolkit/codex/openclaw-origin-override
Add configurable OpenClaw origin override
2026-03-12 18:59:30 +08:00
Haitao Pan
33862d353b Add configurable OpenClaw origin override 2026-03-12 18:54:30 +08:00
Haitao Pan
87d573c528 add vault-backed token lookup for integrations 2026-03-12 17:33:29 +08:00
Haitao Pan
f83e43ec50 fix assistant mode option typing 2026-03-12 17:02:55 +08:00
Haitao Pan
346ffe7839 trim xworkmate assistant header 2026-03-12 16:55:00 +08:00
Haitao Pan
593adb0452 refine xworkmate assistant layout density 2026-03-12 16:51:41 +08:00
Haitao Pan
2ebecc8b43 fix nav width and localize xworkmate assistant 2026-03-12 16:47:18 +08:00
Haitao Pan
88825f62c3 feat: polish xworkmate workspace entry 2026-03-12 16:31:15 +08:00
Haitao Pan
161350c608 feat: launch xworkmate workspace 2026-03-12 16:18:41 +08:00
Haitao Pan
01181d4385 feat: add openclaw pairing bridge 2026-03-12 12:51:12 +08:00
Haitao Pan
9a915ae080 feat: integrate openclaw assistant workspace 2026-03-12 12:18:25 +08:00
Haitao Pan
d65ea24956 refactor: Centralize account service base URL usage by passing it as a prop to registration content and using it directly in login content. 2026-02-22 11:13:05 +08:00
Haitao Pan
2d2c972e29 docs: rewrite OIDC auth guide with complete setup instructions
- Add architecture flow diagram
- Add Google OAuth consent screen steps
- Add troubleshooting section
- Remove obsolete NEXT_PUBLIC_ACCOUNTS_SVC_URL reference
- Add quick reference table
2026-02-22 10:58:07 +08:00
Haitao Pan
4ce4147a8a fix: use server-resolved accountServiceBaseUrl for OAuth login URLs
Replace process.env.NEXT_PUBLIC_ACCOUNTS_SVC_URL (undefined in preview)
with the accountServiceBaseUrl prop resolved via getAccountServiceBaseUrl().
Fixes undefined/api/auth/oauth/login/github|google on preview.svc.plus.
2026-02-22 10:54:54 +08:00
5419021a56
Merge pull request #52 from cloud-neutral-toolkit/refactor/ai-sidebar
Refactor/ai sidebar
2026-02-14 20:00:53 +08:00
Haitao Pan
53ca618292 chore: update dependencies 2026-02-14 19:52:35 +08:00
Haitao Pan
6fa8bd6814 fix(deps): update next-mdx-remote to v6.0.0 to fix vulnerability 2026-02-14 19:52:35 +08:00
9da24e7b6b
Merge pull request #50 from cloud-neutral-toolkit/consolidate-experience-account
fix(experience): consolidate demo account into sandbox@svc.plus
2026-02-14 19:12:23 +08:00
Haitao Pan
86cb79574d refactor(ui): implement persistent AI sidebar and unify navigation entry points
- Make AI Assistant sidebar persistent by default (isOpen: true)
- Update AskAIDialog to render as a fixed right sidebar instead of modal
- Implement toggle functionality for sidebar in UnifiedNavigation
- Remove floating AskAIButton to unify entry points
- Update AppProviders to handle layout shifts for sidebar
2026-02-14 17:38:49 +08:00
3d24d0af1d
Merge pull request #51 from cloud-neutral-toolkit/consolidate-experience-mode-v2
fix(experience): consolidate demo account into sandbox@svc.plus
2026-02-10 11:54:58 +08:00
Haitao Pan
57c40bed97 fix(experience): consolidate demo account into sandbox@svc.plus 2026-02-10 11:54:42 +08:00
Haitao Pan
b2cda61dd9 fix(experience): consolidate demo account into sandbox@svc.plus 2026-02-10 11:53:42 +08:00
Haitao Pan
c0bc2a04c9 fix(demo): fallback to bound sandbox node when agent API fails 2026-02-10 10:11:12 +08:00
Haitao Pan
90b8a85bb4 feat: Switch XScopeHub and XCloudFlow to asia-northeast1 2026-02-10 07:28:55 +08:00
Haitao Pan
a6a42018a3 feat: Add XScopeHub MCP service card to services page 2026-02-09 20:38:12 +08:00
Haitao Pan
4fbe296ca0 Merge branch 'codex/docs/slim-readme' 2026-02-09 20:31:01 +08:00
Haitao Pan
82975added feat: Refine guest mode text and add registration lead 2026-02-09 20:30:58 +08:00
a31f01db5c
Merge pull request #49 from cloud-neutral-toolkit/codex/docs/slim-readme
docs(readme): slim root README
2026-02-09 11:07:25 +08:00
Haitao Pan
b7c3d143b0 docs(readme): slim root README structure 2026-02-09 11:04:58 +08:00
e917bce530
Merge pull request #47 from cloud-neutral-toolkit/docs
docs(readme): align with readme-root-standard
2026-02-09 10:37:28 +08:00
f784561801
Merge pull request #48 from cloud-neutral-toolkit/scripts
chore(setup): align setup.sh with unified template
2026-02-09 10:37:16 +08:00
Haitao Pan
713ed3401e chore(setup): align setup.sh with unified template 2026-02-09 10:35:39 +08:00
Haitao Pan
65f29367bc docs(readme): align with readme-root-standard 2026-02-09 10:34:28 +08:00
Haitao Pan
c193ac9302 docs(setup): add curl-based setup script 2026-02-09 10:00:12 +08:00
Haitao Pan
5e126e1294 docs(i18n): add zh docs stubs 2026-02-09 10:00:07 +08:00
349 changed files with 27357 additions and 11358 deletions

15
.dockerignore Normal file
View File

@ -0,0 +1,15 @@
.git
.github
.next
.contentlayer
node_modules
coverage
dist
build
test-results
*.log
.env
.env.local
.env.*.local
deploy/single-node/.env.runtime
knowledge/.git

View File

@ -1,6 +1,45 @@
# Moltbot Service URL
# Defaults to https://moltbot.svc.plus if not set
MOLTBOT_SERVICE_URL=https://moltbot.svc.plus
# Frontend site base URLs
APP_BASE_URL=
NEXT_PUBLIC_APP_BASE_URL=
NEXT_PUBLIC_SITE_URL=
NEXT_PUBLIC_LOGIN_URL=
NEXT_PUBLIC_DOCS_BASE_URL=
DOCS_SERVICE_URL=https://docs.svc.plus
DOCS_SERVICE_INTERNAL_URL=
SESSION_COOKIE_SECURE=true
NEXT_PUBLIC_SESSION_COOKIE_SECURE=true
RUNTIME_HOSTNAME=
NEXT_RUNTIME_HOSTNAME=
DEPLOYMENT_HOSTNAME=
RUNTIME_ENV=prod
REGION=cn
NEXT_PUBLIC_RUNTIME_ENVIRONMENT=prod
NEXT_PUBLIC_RUNTIME_REGION=cn
# Upstream service endpoints
# Use root service origins only. Do not point ACCOUNT_SERVICE_URL at console.svc.plus
# and do not include /api/auth or any other path suffix here.
ACCOUNT_SERVICE_URL=https://accounts.svc.plus
NEXT_PUBLIC_ACCOUNT_SERVICE_URL=https://accounts.svc.plus
SERVER_SERVICE_URL=https://api.svc.plus
NEXT_PUBLIC_SERVER_SERVICE_URL=https://api.svc.plus
SERVER_SERVICE_INTERNAL_URL=
# XWorkmate bridge runtime
# Read server-side by /api/xworkmate/bridge. Do not expose the token as NEXT_PUBLIC_*.
BRIDGE_SERVER_URL=https://xworkmate-bridge.svc.plus
BRIDGE_AUTH_TOKEN=
# OpenClaw assistant integrations
# Use environment variables to prefill the assistant and integrations page.
# Values are read server-side and are not hardcoded into the UI.
OPENCLAW_GATEWAY_REMOTE_URL=
OPENCLAW_GATEWAY_TOKEN=
VAULT_SERVER_URL=
VAULT_NAMESPACE=
VAULT_TOKEN=
APISIX_AI_GATEWAY_URL=
AI_GATEWAY_ACCESS_TOKEN=
# Giscus Configuration (GitHub Discussions Integration)
# See https://giscus.app to generate these values
@ -13,10 +52,23 @@ NEXT_PUBLIC_GISCUS_CATEGORY_ID=DIC_kwDOQoiZ_s4Clj_q
INTERNAL_SERVICE_TOKEN=
# Cloudflare Web Analytics GraphQL credentials
CLOUDFLARE_DNS_API_TOKEN=
CLOUDFLARE_DNS_ZONE_TAG=
CLOUDFLARE_API_TOKEN=
CLOUDFLARE_ACCOUNT_ID=
CLOUDFLARE_WEB_ANALYTICS_SITE_TAG=
CLOUDFLARE_ZONE_TAG=
# Root email whitelist for privileged user-creation actions (comma-separated)
# Default: admin@svc.plus
ROOT_EMAIL_WHITELIST=admin@svc.plus
# Stripe public price ids used by /prices, product pages, and /panel/subscription
# These values are safe to expose to the browser. Use Stripe test-mode price ids for local/dev.
NEXT_PUBLIC_PAYPAL_CLIENT_ID=
NEXT_PUBLIC_STRIPE_PRICE_XSTREAM_PAYGO=
NEXT_PUBLIC_STRIPE_PRICE_XSTREAM_SUBSCRIPTION=
NEXT_PUBLIC_STRIPE_PRICE_XSCOPEHUB_PAYGO=
NEXT_PUBLIC_STRIPE_PRICE_XSCOPEHUB_SUBSCRIPTION=
NEXT_PUBLIC_STRIPE_PRICE_XCLOUDFLOW_PAYGO=
NEXT_PUBLIC_STRIPE_PRICE_XCLOUDFLOW_SUBSCRIPTION=

View File

@ -1,37 +0,0 @@
name: "Cloud-Neutral Auto Tag"
description: "Generate Docker tags for main, release, PR and dev branches"
inputs:
image:
description: "Base image name (e.g. ghcr.io/.../image)"
required: true
outputs:
tags:
description: "Generated Docker tags"
value: ${{ steps.meta.outputs.tags }}
labels:
description: "Generated Docker labels"
value: ${{ steps.meta.outputs.labels }}
runs:
using: composite
steps:
- name: Generate metadata (auto tags)
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ inputs.image }}
tags: |
# main → latest
type=raw,enable=${{ github.ref == 'refs/heads/main' }},value=latest
# release tagv1.2.3
type=ref,event=tag
type=semver,pattern={{version}}
# PR → pr-123
type=raw,enable=${{ startsWith(github.ref, 'refs/pull/') }},value=pr-${{ github.event.pull_request.number }}
# dev/feature branches → branch name
type=ref,event=branch

View File

@ -1,90 +0,0 @@
name: Build
description: Build artifacts for each service and platform with optional container publishing.
inputs:
service:
description: Target service name
required: true
platform:
description: Target platform (e.g., linux/amd64)
required: true
environment:
description: Deployment environment (dev or prod)
required: true
runs:
using: composite
steps:
- name: Prepare matrix context
id: matrix
uses: ../matrix-support
with:
service: ${{ inputs.service }}
platform: ${{ inputs.platform }}
environment: ${{ inputs.environment }}
enable_docker: 'true'
- name: Cache build artifacts
uses: actions/cache@v4
with:
path: |
build/${{ inputs.service }}
dashboard/.next
key: build-${{ inputs.service }}-${{ inputs.platform }}-${{ hashFiles('**/go.sum', 'dashboard/yarn.lock') }}-${{ inputs.environment }}
restore-keys: |
build-${{ inputs.service }}-${{ inputs.platform }}-
build-${{ inputs.service }}-
- name: Prepare Go toolchain
if: inputs.service != 'dashboard'
uses: actions/setup-go@v4
with:
go-version: '1.22'
cache: true
- name: Build Go binaries
if: inputs.service != 'dashboard'
shell: bash
run: |
set -euo pipefail
goos="${{ steps.matrix.outputs.goos }}"
goarch="${{ steps.matrix.outputs.goarch }}"
mkdir -p build/${{ inputs.service }}/"${goos}-${goarch}"
declare -a targets
if [[ "${{ inputs.service }}" == "rag-server" ]]; then
targets=("rag-server/cmd/xcontrol-server" "rag-server/cmd/rag-server-cli")
elif [[ "${{ inputs.service }}" == "account" ]]; then
targets=("account/cmd/accountsvc")
else
targets=("./...")
fi
for target in "${targets[@]}"; do
binary_name=$(basename "$target")
GOOS="$goos" GOARCH="$goarch" go build -o build/${{ inputs.service }}/"${goos}-${goarch}"/"${binary_name}" "$target"
done
- name: Upload Go artifacts
if: inputs.service != 'dashboard'
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.service }}-${{ inputs.platform }}-${{ inputs.environment }}
path: build/${{ inputs.service }}/
- name: Install dashboard dependencies
if: inputs.service == 'dashboard'
working-directory: dashboard
shell: bash
run: yarn install --frozen-lockfile
- name: Build dashboard
if: inputs.service == 'dashboard'
working-directory: dashboard
shell: bash
env:
NEXT_PUBLIC_ENV: ${{ inputs.environment }}
run: yarn build
- name: Upload dashboard build output
if: inputs.service == 'dashboard'
uses: actions/upload-artifact@v4
with:
name: dashboard-${{ inputs.platform }}-${{ inputs.environment }}
path: dashboard/.next

View File

@ -1,53 +0,0 @@
name: Code Quality
description: Run linting and basic quality checks per service/platform/environment matrix entry.
inputs:
service:
description: Target service name
required: true
platform:
description: Target platform (e.g., linux/amd64)
required: true
environment:
description: Deployment environment (dev or prod)
required: true
runs:
using: composite
steps:
- name: Prepare matrix context
id: matrix
uses: ./.github/actions/matrix-support
with:
service: ${{ inputs.service }}
platform: ${{ inputs.platform }}
environment: ${{ inputs.environment }}
- name: Install git-secrets
shell: bash
run: |
set -euo pipefail
git clone https://github.com/awslabs/git-secrets.git
sudo make install -C git-secrets
git secrets --install
git secrets --scan
- name: Go vet
if: inputs.service != 'dashboard'
shell: bash
run: go vet ./...
- name: Go unit tests (quality gate)
if: inputs.service != 'dashboard'
shell: bash
run: go test ./...
- name: Install dashboard dependencies
if: inputs.service == 'dashboard'
working-directory: dashboard
shell: bash
run: yarn install --frozen-lockfile
- name: Dashboard lint
if: inputs.service == 'dashboard'
working-directory: dashboard
shell: bash
run: yarn lint

View File

@ -1,48 +0,0 @@
name: Deploy
description: Coordinate deployments per service/environment.
inputs:
service:
description: Target service name
required: true
platform:
description: Target platform (e.g., linux/amd64)
required: true
environment:
description: Deployment environment (dev or prod)
required: true
runs:
using: composite
steps:
- name: Prepare matrix context
id: matrix
uses: ./.github/actions/matrix-support
with:
service: ${{ inputs.service }}
platform: ${{ inputs.platform }}
environment: ${{ inputs.environment }}
- name: Prepare rollout context
id: context
shell: bash
run: |
set -euo pipefail
echo "service=${{ inputs.service }}" >> "$GITHUB_OUTPUT"
echo "environment=${{ inputs.environment }}" >> "$GITHUB_OUTPUT"
echo "platform=${{ inputs.platform }}" >> "$GITHUB_OUTPUT"
echo "release_channel=${{ steps.matrix.outputs.is_prod == 'true' && 'prod' || 'dev' }}" >> "$GITHUB_OUTPUT"
- name: Deploy placeholder
shell: bash
env:
TARGET_ENV: ${{ steps.context.outputs.environment }}
TARGET_SERVICE: ${{ steps.context.outputs.service }}
TARGET_PLATFORM: ${{ steps.context.outputs.platform }}
RELEASE_CHANNEL: ${{ steps.context.outputs.release_channel }}
run: |
echo "Deploying ${TARGET_SERVICE} (${TARGET_PLATFORM}) to ${TARGET_ENV} namespace via ${RELEASE_CHANNEL} rollout"
echo "Hook in Helm/kubectl/ArgoCD rollouts here"
- name: Rollback plan
shell: bash
run: |
echo "Rollback can be re-run per matrix entry by dispatching with allow_deploy=true"

View File

@ -1,106 +0,0 @@
name: Matrix Support
description: Common setup for matrix-driven workflows with language and cache bootstrapping.
inputs:
service:
description: Target service name
required: true
platform:
description: Target platform (e.g., linux/amd64)
required: true
environment:
description: Deployment environment (dev or prod)
required: true
enable_docker:
description: Enable Docker buildx/QEMU setup
required: false
default: 'false'
outputs:
goos:
description: Derived GOOS from the platform input
value: ${{ steps.platforms.outputs.goos }}
goarch:
description: Derived GOARCH from the platform input
value: ${{ steps.platforms.outputs.goarch }}
is_prod:
description: Whether the environment is prod or the ref is a tag
value: ${{ steps.flags.outputs.is_prod }}
target_platforms:
description: Platform list for builds (single in dev, multi-arch in prod)
value: ${{ steps.flags.outputs.target_platforms }}
runs:
using: composite
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Derive platform matrix values
id: platforms
shell: bash
run: |
set -euo pipefail
platform="${{ inputs.platform }}"
goos="${platform%%/*}"
goarch="${platform##*/}"
echo "goos=${goos}" >> "$GITHUB_OUTPUT"
echo "goarch=${goarch}" >> "$GITHUB_OUTPUT"
- name: Resolve environment flags
id: flags
shell: bash
run: |
set -euo pipefail
if [[ "${{ inputs.environment }}" == "prod" || "${GITHUB_REF_TYPE:-}" == "tag" ]]; then
echo "is_prod=true" >> "$GITHUB_OUTPUT"
echo "target_platforms=linux/amd64,linux/arm64" >> "$GITHUB_OUTPUT"
else
echo "is_prod=false" >> "$GITHUB_OUTPUT"
echo "target_platforms=${{ inputs.platform }}" >> "$GITHUB_OUTPUT"
fi
- name: Set up Go
if: inputs.service != 'dashboard'
uses: actions/setup-go@v4
with:
go-version: '1.22'
cache: true
- name: Cache Go build data
if: inputs.service != 'dashboard'
uses: actions/cache@v4
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: go-${{ inputs.service }}-${{ inputs.platform }}-${{ hashFiles('**/go.sum') }}
restore-keys: |
go-${{ inputs.service }}-${{ inputs.platform }}-
go-${{ inputs.service }}-
- name: Set up Node.js
if: inputs.service == 'dashboard'
uses: actions/setup-node@v4
with:
node-version: 20
cache: yarn
cache-dependency-path: dashboard/yarn.lock
- name: Cache dashboard artifacts
if: inputs.service == 'dashboard'
uses: actions/cache@v4
with:
path: |
dashboard/.next/cache
~/.cache/yarn
key: dashboard-${{ inputs.platform }}-${{ hashFiles('dashboard/yarn.lock') }}
restore-keys: |
dashboard-${{ inputs.platform }}-
dashboard-
- name: Enable Docker build tooling
if: inputs.enable_docker == 'true'
uses: docker/setup-qemu-action@v3
- name: Set up buildx
if: inputs.enable_docker == 'true'
uses: docker/setup-buildx-action@v3

View File

@ -1,76 +0,0 @@
name: Security
description: Security scanning per service/platform/environment.
inputs:
service:
description: Target service name
required: true
platform:
description: Target platform (e.g., linux/amd64)
required: true
environment:
description: Deployment environment (dev or prod)
required: true
runs:
using: composite
steps:
- name: Prepare matrix context
id: matrix
uses: ./.github/actions/matrix-support
with:
service: ${{ inputs.service }}
platform: ${{ inputs.platform }}
environment: ${{ inputs.environment }}
- name: Run golangci-lint
if: inputs.service != 'dashboard'
uses: golangci/golangci-lint-action@v6
with:
version: latest
args: ./...
- name: Install gosec
if: inputs.service != 'dashboard'
shell: bash
run: go install github.com/securego/gosec/v2/cmd/gosec@latest
- name: Run gosec
if: inputs.service != 'dashboard'
shell: bash
run: gosec ./...
- name: Trivy filesystem scan
if: inputs.service != 'dashboard'
uses: aquasecurity/trivy-action@0.24.0
with:
scan-type: fs
scan-ref: .
severity: HIGH,CRITICAL
ignore-unfixed: true
format: table
exit-code: "0"
- name: Install dashboard dependencies
if: inputs.service == 'dashboard'
working-directory: dashboard
shell: bash
run: yarn install --frozen-lockfile
- name: Run ESLint
if: inputs.service == 'dashboard'
working-directory: dashboard
shell: bash
run: yarn lint
- name: Semgrep security rules
if: inputs.service == 'dashboard'
uses: returntocorp/semgrep-action@v1
with:
config: p/ci
paths: dashboard
- name: npm audit (production)
if: inputs.service == 'dashboard'
working-directory: dashboard
shell: bash
run: npm audit --production
continue-on-error: true

View File

@ -1,52 +0,0 @@
name: Test
description: Run service-specific tests.
inputs:
service:
description: Target service name
required: true
platform:
description: Target platform (e.g., linux/amd64)
required: true
environment:
description: Deployment environment (dev or prod)
required: true
runs:
using: composite
steps:
- name: Prepare matrix context
id: matrix
uses: ./.github/actions/matrix-support
with:
service: ${{ inputs.service }}
platform: ${{ inputs.platform }}
environment: ${{ inputs.environment }}
- name: Run Go integration tests
if: inputs.service != 'dashboard'
shell: bash
run: |
set -euo pipefail
go test ./... -run Integration -count=1
- name: Install dashboard dependencies
if: inputs.service == 'dashboard'
working-directory: dashboard
shell: bash
run: yarn install --frozen-lockfile
- name: Run dashboard unit tests
if: inputs.service == 'dashboard'
working-directory: dashboard
shell: bash
env:
NODE_ENV: ${{ inputs.environment }}
run: yarn test:unit
- name: Run dashboard e2e tests
if: inputs.service == 'dashboard'
working-directory: dashboard
shell: bash
env:
PORT: 3100
NODE_ENV: ${{ inputs.environment }}
run: yarn test:e2e

View File

@ -1,9 +0,0 @@
#!/usr/bin/env bash
set -e
REG="ghcr.io/cloud-neutral-toolkit"
cosign sign --yes "$REG/node-builder@$NODE_BUILDER_DIGEST"
cosign sign --yes "$REG/node-runtime@$NODE_RUNTIME_DIGEST"
cosign sign --yes "$REG/openresty-geoip@$OPENRESTY_GEOIP_DIGEST"
cosign sign --yes "$REG/postgres-runtime@$POSTGRES_RUNTIME_DIGEST"

View File

@ -1,28 +0,0 @@
#!/usr/bin/env python3
import json, sys
if len(sys.argv) < 4:
print("Usage: gen.py <image-name> <digest> <tags>")
sys.exit(1)
name = sys.argv[1]
digest = sys.argv[2]
raw_tags = sys.argv[3]
tags = raw_tags.splitlines()
preferred = next((t for t in tags if t.endswith(":latest")), tags[0] if tags else "")
metadata = {
"name": name,
"digest": digest,
"tags": tags,
"preferred_tag": preferred,
"image": f"ghcr.io/cloud-neutral-toolkit/{name}",
"image_with_digest": f"ghcr.io/cloud-neutral-toolkit/{name}@{digest}",
}
outfile = f"image-metadata-{name}.json"
with open(outfile, "w", encoding="utf-8") as f:
json.dump(metadata, f, indent=2)
print(f"[metadata] Wrote: {outfile}")

View File

@ -1,7 +0,0 @@
#!/usr/bin/env bash
set -e
IMAGE="$1"
OUT="$2"
anchore-cli sbom generate "$IMAGE" -o "$OUT"

View File

@ -1,15 +0,0 @@
#!/usr/bin/env bash
set -e
tags="$1"
preferred=""
while IFS= read -r line; do
[[ "$line" == *":latest" ]] && preferred="$line" && break
done <<< "$tags"
if [[ -z "$preferred" ]]; then
preferred="$(echo "$tags" | head -n 1)"
fi
echo "$preferred"

View File

@ -1,296 +0,0 @@
name: Build Dashboard Images
on:
workflow_call:
inputs:
push_images:
description: "Push service images instead of local builds"
type: boolean
default: true
dockerhub_namespace:
description: "Docker Hub namespace (user/org)"
type: string
skip_security:
description: "Skip security scans and signing"
type: boolean
default: false
node_builder_image:
type: string
default: "node:22-bookworm"
node_runtime_image:
type: string
default: "node:22-slim"
workflow_dispatch:
inputs:
push_images:
type: boolean
default: true
dockerhub_namespace:
description: "Docker Hub namespace (user/org)"
type: string
default: "cloudneutral"
skip_security:
description: "Skip security scans and signing"
type: boolean
default: false
node_builder_image:
type: string
default: "node:22-bookworm"
node_runtime_image:
type: string
default: "node:22-slim"
push:
branches: [ main ]
permissions:
contents: read
packages: write
id-token: write
env:
REGISTRY: ghcr.io
# ✅ 不硬编码:默认推到 ghcr.io/<当前仓库 owner>/...
ORG: ${{ github.repository_owner }}
SKIP_SECURITY: ${{ inputs.skip_security || github.event.inputs.skip_security || 'false' }}
NODE_BUILDER_IMAGE: ${{ inputs.node_builder_image || github.event.inputs.node_builder_image || 'node:22-bookworm' }}
NODE_RUNTIME_IMAGE: ${{ inputs.node_runtime_image || github.event.inputs.node_runtime_image || 'node:22-slim' }}
PUSH_IMAGES: ${{ github.event_name == 'push'
|| (github.event_name == 'workflow_call' && inputs.push_images)
|| (github.event_name == 'workflow_dispatch' && github.event.inputs.push_images == 'true') }}
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
arch:
- { platform: linux/amd64, artifact: linux-amd64 }
- { platform: linux/arm64, artifact: linux-arm64 }
service:
- { name: dashboard, workdir: ., dockerfile: Dockerfile }
steps:
- uses: actions/checkout@v4
- uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Generate Auto Tags
id: meta
uses: ./.github/actions/auto-tag
with:
image: ${{ env.REGISTRY }}/${{ env.ORG }}/${{ matrix.service.name }}
- uses: docker/setup-qemu-action@v3
- uses: docker/setup-buildx-action@v3
- name: Clone knowledge content
run: git clone https://github.com/Cloud-Neutral-Workshop/knowledge.git knowledge
- name: Build Service Image (per-arch)
id: build
uses: docker/build-push-action@v6
with:
context: ${{ matrix.service.workdir }}
file: ${{ matrix.service.dockerfile }}
platforms: ${{ matrix.arch.platform }}
push: ${{ env.PUSH_IMAGES }}
tags: |
${{ env.REGISTRY }}/${{ env.ORG }}/${{ matrix.service.name }}:build-${{ github.sha }}-${{ matrix.arch.artifact }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
GO_RUNTIME_IMAGE=${{ env.GO_RUNTIME_IMAGE }}
NODE_BUILDER_IMAGE=${{ env.NODE_BUILDER_IMAGE }}
NODE_RUNTIME_IMAGE=${{ env.NODE_RUNTIME_IMAGE }}
CONTENTLAYER_BUILD=true
- name: Record digest
run: |
set -euo pipefail
echo "${{ steps.build.outputs.digest }}" > digest-${{ matrix.service.name }}-${{ matrix.arch.artifact }}.txt
- uses: actions/upload-artifact@v4
with:
name: digest-${{ matrix.service.name }}-${{ matrix.arch.artifact }}
path: digest-${{ matrix.service.name }}-${{ matrix.arch.artifact }}.txt
security:
runs-on: ubuntu-latest
needs: build
if: ${{ (github.event_name == 'push' || inputs.push_images == true || github.event.inputs.push_images == 'true') && !((inputs.skip_security == true) || (github.event.inputs.skip_security == 'true')) }}
strategy:
matrix:
arch:
- { platform: linux/amd64, artifact: linux-amd64 }
- { platform: linux/arm64, artifact: linux-arm64 }
service:
- { name: dashboard }
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: digest-${{ matrix.service.name }}-${{ matrix.arch.artifact }}
- name: Load image digest
run: |
set -euo pipefail
echo "IMAGE_DIGEST=$(cat digest-${{ matrix.service.name }}-${{ matrix.arch.artifact }}.txt)" >> "$GITHUB_ENV"
- name: Set image ref
run: |
set -euo pipefail
echo "IMG=${{ env.REGISTRY }}/${{ env.ORG }}/${{ matrix.service.name }}:build-${{ github.sha }}-${{ matrix.arch.artifact }}@${{ env.IMAGE_DIGEST }}" >> "$GITHUB_ENV"
- uses: anchore/sbom-action@v0
with:
image: ${{ env.IMG }}
output-file: sbom.spdx.json
- uses: actions/upload-artifact@v4
with:
name: sbom-${{ matrix.service.name }}-${{ matrix.arch.artifact }}
path: sbom.spdx.json
- uses: aquasecurity/trivy-action@0.28.0
with:
image-ref: ${{ env.IMG }}
severity: HIGH,CRITICAL
exit-code: '1'
- uses: sigstore/cosign-installer@v3
with:
cosign-release: 'v2.4.1'
- name: Cosign Sign Image
env:
COSIGN_EXPERIMENTAL: "true"
run: |
set -euo pipefail
cosign sign --yes "${{ env.IMG }}"
push:
runs-on: ubuntu-latest
needs:
- build
- security
if: ${{ needs.build.result == 'success' && (github.event_name == 'push' || inputs.push_images == true || github.event.inputs.push_images == 'true') && ((inputs.skip_security == true) || (github.event.inputs.skip_security == 'true') || (needs.security.result == 'success')) }}
strategy:
fail-fast: false
matrix:
registry:
- ghcr.io
- docker.io
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: actions/download-artifact@v4
with:
name: digest-dashboard-linux-amd64
- uses: actions/download-artifact@v4
with:
name: digest-dashboard-linux-arm64
- name: Load digests
run: |
set -euo pipefail
echo "AMD_DIGEST=$(cat digest-dashboard-linux-amd64.txt)" >> "$GITHUB_ENV"
echo "ARM_DIGEST=$(cat digest-dashboard-linux-arm64.txt)" >> "$GITHUB_ENV"
- name: Generate Auto Tags
id: meta
uses: ./.github/actions/auto-tag
with:
image: ${{ env.REGISTRY }}/${{ env.ORG }}/dashboard
- uses: docker/login-action@v3
if: matrix.registry == 'ghcr.io'
with:
registry: ${{ matrix.registry }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create & Push Multi-Arch Manifests (GHCR)
if: matrix.registry == 'ghcr.io'
run: |
set -euo pipefail
SRC_AMD="${{ env.REGISTRY }}/${{ env.ORG }}/dashboard:build-${{ github.sha }}-linux-amd64@${{ env.AMD_DIGEST }}"
SRC_ARM="${{ env.REGISTRY }}/${{ env.ORG }}/dashboard:build-${{ github.sha }}-linux-arm64@${{ env.ARM_DIGEST }}"
FIRST_TAG=""
echo "${{ steps.meta.outputs.tags }}" | tr ',' '\n' | while read -r TAG; do
[ -z "$TAG" ] && continue
if [ -z "$FIRST_TAG" ]; then FIRST_TAG="$TAG"; fi
docker buildx imagetools create -t "$TAG" "$SRC_AMD" "$SRC_ARM"
done
TAG1="$(echo "${{ steps.meta.outputs.tags }}" | tr ',' '\n' | head -n 1)"
DIGEST="$(docker buildx imagetools inspect "$TAG1" --format '{{.Digest}}')"
echo "MANIFEST_DIGEST=$DIGEST" >> "$GITHUB_ENV"
echo "FINAL_TAG=$TAG1" >> "$GITHUB_ENV"
- name: Clone knowledge content
if: matrix.registry == 'ghcr.io'
run: git clone https://github.com/Cloud-Neutral-Workshop/knowledge.git knowledge
- name: Validate blog content mount
if: matrix.registry == 'ghcr.io'
run: |
set -euo pipefail
IMAGE="${{ env.REGISTRY }}/${{ env.ORG }}/dashboard@${{ env.MANIFEST_DIGEST }}"
docker pull "$IMAGE"
docker run --rm \
-v "${{ github.workspace }}/knowledge/content:/app/dashboard/src/content/blog:ro" \
"$IMAGE" \
sh -c 'test -d /app/dashboard/src/content/blog'
- name: Login to Docker Hub
if: matrix.registry == 'docker.io'
uses: docker/login-action@v3
with:
registry: docker.io
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Copy Multi-Arch Image to Docker Hub (skopeo)
if: matrix.registry == 'docker.io'
env:
TARGET_NS: ${{ inputs.dockerhub_namespace || github.event.inputs.dockerhub_namespace || 'cloudneutral' }}
run: |
set -euo pipefail
sudo apt-get update -y
sudo apt-get install -y skopeo
SRC="docker://ghcr.io/${{ env.ORG }}/dashboard@${{ env.MANIFEST_DIGEST }}"
DST="docker://docker.io/${TARGET_NS}/dashboard:latest"
skopeo login ghcr.io -u "${{ github.actor }}" -p "${{ secrets.GITHUB_TOKEN }}"
skopeo login docker.io -u "${{ secrets.DOCKERHUB_USERNAME }}" -p "${{ secrets.DOCKERHUB_TOKEN }}"
skopeo copy --all "$SRC" "$DST"

View File

@ -1,49 +0,0 @@
name: Check XControl Image Ready
on:
workflow_dispatch:
inputs:
tag:
required: false
default: latest
permissions:
contents: read
packages: read
jobs:
check:
runs-on: ubuntu-latest
steps:
- name: Authenticate to GHCR
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "$GITHUB_TOKEN" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin
- name: Check images exist and are pullable
env:
TAG: ${{ inputs.tag }}
run: |
set -euo pipefail
IMAGES=(
"ghcr.io/cloud-neutral-toolkit/openresty-geoip"
"ghcr.io/cloud-neutral-toolkit/postgres-runtime"
"ghcr.io/cloud-neutral-toolkit/account"
"ghcr.io/cloud-neutral-toolkit/dashboard"
"ghcr.io/cloud-neutral-toolkit/rag-server"
"ghcr.io/cloud-neutral-toolkit/xcontrol-init"
"docker.io/cloudneutral/openresty-geoip"
"docker.io/cloudneutral/postgres-runtime"
"docker.io/cloudneutral/account"
"docker.io/cloudneutral/dashboard"
"docker.io/cloudneutral/rag-server"
"docker.io/cloudneutral/xcontrol-init"
)
for IMAGE in "${IMAGES[@]}"; do
echo "Checking ${IMAGE}:${TAG}"
docker manifest inspect "${IMAGE}:${TAG}" > /dev/null
docker pull "${IMAGE}:${TAG}" > /dev/null
done

240
.github/workflows/pipeline.yaml vendored Normal file
View File

@ -0,0 +1,240 @@
name: Console Service Pipeline
on:
push:
branches:
- main
paths:
- ".github/workflows/pipeline.yaml"
- "Dockerfile"
- "deploy/single-node/**"
- "package.json"
- "yarn.lock"
- "scripts/github-actions/build-and-push-frontend-image.sh"
- "scripts/github-actions/compute-frontend-release-metadata.sh"
- "scripts/github-actions/render-frontend-build-args.sh"
- "scripts/github-actions/render-frontend-runtime-env.sh"
- "scripts/github-actions/prepare-frontend-build-context.sh"
- "scripts/github-actions/run-console-deploy-playbook.sh"
- "scripts/github-actions/run-cloudflare-svc-plus-dns-playbook.sh"
- "scripts/github-actions/verify-frontend-release-over-ssh.sh"
- "scripts/github-actions/verify-frontend-release.sh"
- "scripts/prebuild.sh"
- "contentlayer.config.ts"
- "next.config.js"
- "next.config.mjs"
- "src/**"
- "public/**"
workflow_dispatch:
inputs:
target_host:
description: Ansible host or alias
required: false
default: "jp-xhttp-contabo.svc.plus"
type: string
run_apply:
description: Apply deployment
required: true
default: true
type: boolean
permissions:
contents: read
packages: write
concurrency:
group: console-pipeline-${{ github.ref_name }}
cancel-in-progress: false
env:
CANONICAL_DOMAIN: www.svc.plus
SERVED_DOMAINS: www.svc.plus,console.svc.plus
APP_BASE_URL: https://www.svc.plus
NEXT_PUBLIC_APP_BASE_URL: https://www.svc.plus
NEXT_PUBLIC_SITE_URL: https://www.svc.plus
RUNTIME_HOSTNAME: www.svc.plus
NEXT_RUNTIME_HOSTNAME: www.svc.plus
NEXT_PUBLIC_RUNTIME_ENVIRONMENT: prod
NEXT_PUBLIC_RUNTIME_REGION: cn
ACCOUNT_SERVICE_URL: https://accounts.svc.plus
CLOUDFLARE_ZONE_TAG: bf3427f83a2c52c8285ab3d741a6ee27
CLOUDFLARE_WEB_ANALYTICS_SITE_TAG: 0973e84ec8872c67c570f8072e92e21b
CLOUDFLARE_ACCOUNT_ID: e71be5efb76a6c54f78f008da4404f00
GHCR_REGISTRY: ghcr.io
GHCR_USERNAME: ${{ secrets.GHCR_USERNAME }}
GHCR_PASSWORD: ${{ secrets.GHCR_TOKEN }}
INTERNAL_SERVICE_TOKEN: ${{ secrets.INTERNAL_SERVICE_TOKEN }}
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_DNS_API_TOKEN: ${{ secrets.CLOUDFLARE_DNS_API_TOKEN }}
jobs:
prep:
name: Prep
runs-on: ubuntu-latest
outputs:
target_host: ${{ steps.inputs.outputs.target_host }}
run_apply: ${{ steps.inputs.outputs.run_apply }}
image_tag: ${{ steps.metadata.outputs.image_tag }}
image_ref: ${{ steps.metadata.outputs.image_ref }}
image_latest_ref: ${{ steps.metadata.outputs.image_latest_ref }}
ghcr_namespace: ${{ steps.metadata.outputs.ghcr_namespace }}
push_latest: ${{ steps.push.outputs.push_latest }}
steps:
- name: Check Out Repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Resolve Inputs
id: inputs
env:
EVENT_NAME: ${{ github.event_name }}
INPUT_TARGET_HOST: ${{ inputs.target_host }}
INPUT_RUN_APPLY: ${{ inputs.run_apply }}
run: bash scripts/github-actions/resolve-workflow-inputs.sh
- name: Compute Image Metadata
id: metadata
run: |
bash scripts/github-actions/compute-frontend-release-metadata.sh
- name: Resolve Push Latest
id: push
env:
REF: ${{ github.ref }}
run: bash scripts/github-actions/resolve-push-latest.sh
build:
name: Build
runs-on: ubuntu-latest
needs: prep
outputs:
image_ref: ${{ steps.publish.outputs.image_ref }}
image_tag: ${{ steps.publish.outputs.image_tag }}
steps:
- name: Check Out Repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Set Up Docker Buildx
run: bash scripts/github-actions/setup-docker-buildx.sh
- name: Log In To GHCR
env:
GHCR_TOKEN: ${{ secrets.GHCR_TOKEN }}
run: bash scripts/github-actions/login-ghcr.sh
- name: Publish Frontend Image
id: publish
env:
IMAGE_REF: ${{ needs.prep.outputs.image_ref }}
IMAGE_TAG: ${{ needs.prep.outputs.image_tag }}
IMAGE_LATEST_REF: ${{ needs.prep.outputs.image_latest_ref }}
PUSH_LATEST: ${{ needs.prep.outputs.push_latest }}
run: bash scripts/github-actions/publish-frontend-image.sh
deploy:
name: Deploy
runs-on: ubuntu-latest
needs:
- prep
- build
env:
TARGET_HOST: ${{ needs.prep.outputs.target_host }}
RUN_APPLY: ${{ needs.prep.outputs.run_apply }}
FRONTEND_IMAGE: ${{ needs.build.outputs.image_ref }}
steps:
- name: Check Out Repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Check Out Playbooks Repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
# Intentionally pinned: playbooks@main regressed deploy reliability on 2026-04-12.
# Any future bump must pass a full Deploy + Validate run before becoming the default.
repository: x-evor/playbooks
ref: 80c545a95c3b16459f6494ed13d951faac57bfa8
path: playbooks
token: ${{ github.token }}
- name: Set Up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.11"
- name: Install Ansible
run: |
python -m pip install --upgrade pip
python -m pip install ansible
- name: Configure SSH For Deploy Host
env:
SINGLE_NODE_VPS_SSH_PRIVATE_KEY: ${{ secrets.SINGLE_NODE_VPS_SSH_PRIVATE_KEY }}
TARGET_HOST: ${{ needs.prep.outputs.target_host }}
run: bash scripts/github-actions/configure-ssh-for-deploy.sh
- name: Run Deploy Playbook
working-directory: playbooks
env:
ANSIBLE_HOST_KEY_CHECKING: "False"
run: bash ../scripts/github-actions/run-console-deploy-playbook.sh
validate:
name: Validate
runs-on: ubuntu-latest
needs:
- prep
- build
- deploy
if: ${{ always() && needs.deploy.result == 'success' }}
env:
EXPECTED_FRONTEND_IMAGE: ${{ needs.build.outputs.image_ref }}
TARGET_HOST: ${{ needs.prep.outputs.target_host }}
SINGLE_NODE_VPS_SSH_PRIVATE_KEY: ${{ secrets.SINGLE_NODE_VPS_SSH_PRIVATE_KEY }}
steps:
- name: Check Out Repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Configure SSH For Validate Host
run: bash scripts/github-actions/configure-ssh-for-deploy.sh
- name: Verify Frontend Release On Host
run: bash scripts/github-actions/verify-frontend-release-over-ssh.sh
update_dns:
name: Update DNS
runs-on: ubuntu-latest
needs:
- prep
- build
- deploy
if: ${{ always() && needs.deploy.result == 'success' }}
continue-on-error: true
env:
TARGET_HOST: ${{ needs.prep.outputs.target_host }}
RUN_APPLY: ${{ needs.prep.outputs.run_apply }}
FRONTEND_IMAGE: ${{ needs.build.outputs.image_ref }}
steps:
- name: Check Out Repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Check Out Playbooks Repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
repository: x-evor/playbooks
ref: 80c545a95c3b16459f6494ed13d951faac57bfa8
path: playbooks
token: ${{ github.token }}
- name: Set Up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.11"
- name: Install Ansible
run: |
python -m pip install --upgrade pip
python -m pip install ansible
- name: Update Cloudflare svc.plus DNS
working-directory: playbooks
env:
ANSIBLE_HOST_KEY_CHECKING: "False"
run: bash ../scripts/github-actions/run-cloudflare-svc-plus-dns-playbook.sh

3
.gitignore vendored
View File

@ -1,6 +1,7 @@
.env
models/
*.tsbuildinfo
knowledge/
# macOS
.DS_Store
@ -18,6 +19,7 @@ public/_build/
public/dl-index/
.contentlayer/
.dev-logs/
.console-state/
# Contentlayer cache
ui/docs/.contentlayer/
@ -54,6 +56,7 @@ coverage/
.env
.env.local
.env.*.local
deploy/single-node/.env.runtime
# Build artifacts
build/

1
.yarnrc Normal file
View File

@ -0,0 +1 @@
registry "https://registry.npmjs.org"

View File

@ -4,7 +4,7 @@ enableGlobalCache: false
nodeLinker: node-modules
npmRegistryServer: "https://registry.npmmirror.com"
npmRegistryServer: "https://registry.npmjs.org"
packageExtensions:
"next-contentlayer@*":

View File

@ -51,7 +51,20 @@ yarn test:e2e path/to/spec.test.ts
---
## 2. Repository Mental Model (Read This First)
## 2. Release Traceability Default Rule
For any change touching CI/CD, image tags, deploy contracts, `/api/ping`, or `validate` behavior:
- Treat `skills/release-traceability/SKILL.md` as the default reference before implementation.
- Prefer release metadata that can be traced from `build` to `deploy` to `validate` without manual injection.
- Keep the published image reference, runtime version, and validation output aligned.
- Do not introduce a deploy path that rebuilds images on the target host.
When in doubt, follow the skill first and keep the release chain fully auditable end to end.
---
## 3. Repository Mental Model (Read This First)
This repository has **three clearly separated layers**:
@ -91,7 +104,7 @@ Used for build-time or runtime wiring only.
---
## 3. Import & Alias Rules (Critical)
## 4. Import & Alias Rules (Critical)
### Dashboard code (src/\*\*)
@ -112,7 +125,7 @@ import { UserCard } from "@/components/UserCard";
---
## 4. TypeScript & Formatting Rules
## 5. TypeScript & Formatting Rules
- Strict mode enabled
- Use `type` for type definitions, `interface` for object shapes
@ -123,7 +136,7 @@ import { UserCard } from "@/components/UserCard";
---
## 5. Naming Conventions
## 6. Naming Conventions
- Components: PascalCase (`UserProfile.tsx`)
- Files: kebab-case for utilities (`user-utils.ts`), PascalCase for components
@ -133,7 +146,7 @@ import { UserCard } from "@/components/UserCard";
---
## 6. Error Handling & Logging
## 7. Error Handling & Logging
- Use try/catch for async operations
- Return Result types or throw errors consistently
@ -142,7 +155,7 @@ import { UserCard } from "@/components/UserCard";
---
## 7. React Patterns
## 8. React Patterns
- Use `'use client'` directive for client components
- Prefer function components with hooks
@ -151,7 +164,7 @@ import { UserCard } from "@/components/UserCard";
---
## 8. Global State Rules (Dashboard Only)
## 9. Global State Rules (Dashboard Only)
✅ Zustand is the **only** allowed global state mechanism
❌ React Context for shared/global state is forbidden
@ -162,7 +175,7 @@ Rule: If state must survive navigation or be shared → it lives in Zustand.
---
## 9. URL-Synchronized State
## 10. URL-Synchronized State
Anything involving:
@ -179,7 +192,7 @@ MUST be handled inside Zustand slices.
---
## 10. Component State Rules
## 11. Component State Rules
Allowed:
@ -194,7 +207,7 @@ Forbidden:
---
## 11. packages/neurapress Rules (Very Important)
## 12. packages/neurapress Rules (Very Important)
packages/neurapress is treated as a vendored internal library.
@ -214,7 +227,7 @@ MUST NOT:
---
## 12. Testing Guidelines
## 13. Testing Guidelines
- Unit tests: Vitest with jsdom environment
- E2E tests: Playwright
@ -224,7 +237,7 @@ MUST NOT:
---
## 13. Environment & Runtime Config
## 14. Environment & Runtime Config
- No new environment variables without approval
- Runtime config must live in: src/config/runtime-service-config\*.yaml
@ -233,13 +246,13 @@ MUST NOT:
---
## 14. Cursor / Copilot Rules
## 15. Cursor / Copilot Rules
- No `.cursor/rules/`, `.cursorrules`, or `.github/copilot-instructions.md` found
---
## 15. TL;DR for AI Agents
## 16. TL;DR for AI Agents
- dashboard = application
- packages = libraries

View File

@ -4,6 +4,27 @@
ARG NODE_BUILDER_IMAGE=node:22-bookworm
ARG NODE_RUNTIME_IMAGE=node:22-slim
ARG CONTENTLAYER_BUILD=true
ARG NEXT_PUBLIC_APP_BASE_URL=
ARG NEXT_PUBLIC_SITE_URL=
ARG NEXT_PUBLIC_LOGIN_URL=
ARG NEXT_PUBLIC_DOCS_BASE_URL=
ARG NEXT_PUBLIC_RUNTIME_ENVIRONMENT=
ARG NEXT_PUBLIC_RUNTIME_REGION=
ARG NEXT_PUBLIC_GISCUS_REPO=
ARG NEXT_PUBLIC_GISCUS_REPO_ID=
ARG NEXT_PUBLIC_GISCUS_CATEGORY=
ARG NEXT_PUBLIC_GISCUS_CATEGORY_ID=
ARG NEXT_PUBLIC_PAYPAL_CLIENT_ID=
ARG NEXT_PUBLIC_STRIPE_PRICE_XSTREAM_PAYGO=
ARG NEXT_PUBLIC_STRIPE_PRICE_XSTREAM_SUBSCRIPTION=
ARG NEXT_PUBLIC_STRIPE_PRICE_XSCOPEHUB_PAYGO=
ARG NEXT_PUBLIC_STRIPE_PRICE_XSCOPEHUB_SUBSCRIPTION=
ARG NEXT_PUBLIC_STRIPE_PRICE_XCLOUDFLOW_PAYGO=
ARG NEXT_PUBLIC_STRIPE_PRICE_XCLOUDFLOW_SUBSCRIPTION=
ARG NEXT_PUBLIC_RELEASE_IMAGE=
ARG NEXT_PUBLIC_RELEASE_TAG=
ARG NEXT_PUBLIC_RELEASE_COMMIT=
ARG NEXT_PUBLIC_RELEASE_VERSION=
# -------------------------------------------------------
# Stage 1 — Builder (Turbopack + standalone)
@ -12,8 +33,51 @@ FROM ${NODE_BUILDER_IMAGE} AS builder
WORKDIR /app/dashboard
ARG NEXT_PUBLIC_APP_BASE_URL
ARG NEXT_PUBLIC_SITE_URL
ARG NEXT_PUBLIC_LOGIN_URL
ARG NEXT_PUBLIC_DOCS_BASE_URL
ARG NEXT_PUBLIC_RUNTIME_ENVIRONMENT
ARG NEXT_PUBLIC_RUNTIME_REGION
ARG NEXT_PUBLIC_GISCUS_REPO
ARG NEXT_PUBLIC_GISCUS_REPO_ID
ARG NEXT_PUBLIC_GISCUS_CATEGORY
ARG NEXT_PUBLIC_GISCUS_CATEGORY_ID
ARG NEXT_PUBLIC_PAYPAL_CLIENT_ID
ARG NEXT_PUBLIC_STRIPE_PRICE_XSTREAM_PAYGO
ARG NEXT_PUBLIC_STRIPE_PRICE_XSTREAM_SUBSCRIPTION
ARG NEXT_PUBLIC_STRIPE_PRICE_XSCOPEHUB_PAYGO
ARG NEXT_PUBLIC_STRIPE_PRICE_XSCOPEHUB_SUBSCRIPTION
ARG NEXT_PUBLIC_STRIPE_PRICE_XCLOUDFLOW_PAYGO
ARG NEXT_PUBLIC_STRIPE_PRICE_XCLOUDFLOW_SUBSCRIPTION
ARG NEXT_PUBLIC_RELEASE_IMAGE
ARG NEXT_PUBLIC_RELEASE_TAG
ARG NEXT_PUBLIC_RELEASE_COMMIT
ARG NEXT_PUBLIC_RELEASE_VERSION
ENV NEXT_TELEMETRY_DISABLED=1 \
NEXT_PRIVATE_TURBOPACK=1
NEXT_PRIVATE_TURBOPACK=1 \
NEXT_PUBLIC_APP_BASE_URL=${NEXT_PUBLIC_APP_BASE_URL} \
NEXT_PUBLIC_SITE_URL=${NEXT_PUBLIC_SITE_URL} \
NEXT_PUBLIC_LOGIN_URL=${NEXT_PUBLIC_LOGIN_URL} \
NEXT_PUBLIC_DOCS_BASE_URL=${NEXT_PUBLIC_DOCS_BASE_URL} \
NEXT_PUBLIC_RUNTIME_ENVIRONMENT=${NEXT_PUBLIC_RUNTIME_ENVIRONMENT} \
NEXT_PUBLIC_RUNTIME_REGION=${NEXT_PUBLIC_RUNTIME_REGION} \
NEXT_PUBLIC_GISCUS_REPO=${NEXT_PUBLIC_GISCUS_REPO} \
NEXT_PUBLIC_GISCUS_REPO_ID=${NEXT_PUBLIC_GISCUS_REPO_ID} \
NEXT_PUBLIC_GISCUS_CATEGORY=${NEXT_PUBLIC_GISCUS_CATEGORY} \
NEXT_PUBLIC_GISCUS_CATEGORY_ID=${NEXT_PUBLIC_GISCUS_CATEGORY_ID} \
NEXT_PUBLIC_PAYPAL_CLIENT_ID=${NEXT_PUBLIC_PAYPAL_CLIENT_ID} \
NEXT_PUBLIC_STRIPE_PRICE_XSTREAM_PAYGO=${NEXT_PUBLIC_STRIPE_PRICE_XSTREAM_PAYGO} \
NEXT_PUBLIC_STRIPE_PRICE_XSTREAM_SUBSCRIPTION=${NEXT_PUBLIC_STRIPE_PRICE_XSTREAM_SUBSCRIPTION} \
NEXT_PUBLIC_STRIPE_PRICE_XSCOPEHUB_PAYGO=${NEXT_PUBLIC_STRIPE_PRICE_XSCOPEHUB_PAYGO} \
NEXT_PUBLIC_STRIPE_PRICE_XSCOPEHUB_SUBSCRIPTION=${NEXT_PUBLIC_STRIPE_PRICE_XSCOPEHUB_SUBSCRIPTION} \
NEXT_PUBLIC_STRIPE_PRICE_XCLOUDFLOW_PAYGO=${NEXT_PUBLIC_STRIPE_PRICE_XCLOUDFLOW_PAYGO} \
NEXT_PUBLIC_STRIPE_PRICE_XCLOUDFLOW_SUBSCRIPTION=${NEXT_PUBLIC_STRIPE_PRICE_XCLOUDFLOW_SUBSCRIPTION} \
NEXT_PUBLIC_RELEASE_IMAGE=${NEXT_PUBLIC_RELEASE_IMAGE} \
NEXT_PUBLIC_RELEASE_TAG=${NEXT_PUBLIC_RELEASE_TAG} \
NEXT_PUBLIC_RELEASE_COMMIT=${NEXT_PUBLIC_RELEASE_COMMIT} \
NEXT_PUBLIC_RELEASE_VERSION=${NEXT_PUBLIC_RELEASE_VERSION}
# ---------------------------
# 基础镜像升级到最新
@ -59,7 +123,6 @@ RUN apt-get update \
COPY --from=builder /app/dashboard/.next/standalone ./
COPY --from=builder /app/dashboard/.next/static ./static
COPY --from=builder /app/dashboard/public ./public
COPY --from=builder /app/dashboard/src/content/blog ./src/content/blog
# ---------------------------
# 额外瘦身(可减少 1540 MB

View File

@ -49,7 +49,6 @@ init:
echo "❌ Unsupported OS. Please install Yarn manually."; exit 1; \
fi; \
fi
yarn config set npmRegistryServer https://registry.npmmirror.com
yarn install --immutable
ensure-deps:
@ -83,7 +82,6 @@ test:
@yarn test || echo "No tests configured"
build: init
yarn config set npmRegistryServer https://registry.npmmirror.com
@if [ -z "$(SKIP_SYNC)" ]; then \
$(MAKE) sync-dl-index; \
fi

177
README.md
View File

@ -1,101 +1,138 @@
# console.svc.plus
**工程师 · 开源 · 云中立**
Cloud Neutral Toolkit 的开放云控制面板 (Open Cloud Control Panel).
关注 **Ops / Infra / AI****技术自由**
🏗️ 热衷于构建“逃生舱”,防止基础设施被厂商锁定。
面向 **Ops / Infra / AI** 的统一前端仪表盘,强调技术自由与可迁移性。
> **Accountable Engineer · Open Source · Cloud Neutral**
>
> Focus on **Ops / Infra / AI** and **Technical Freedom**.
> 🏗️ Passionate about building "escape pods" to prevent infrastructure vendor lock-in.
> A unified dashboard for Ops / Infra / AI, built for technical freedom and portability.
---
## 部署要求 (Deployment Requirements)
**console.svc.plus** 是 Cloud Neutral Toolkit 的**开放云控制面板**。
| 维度 | 要求 / 规格 | 说明 |
| ----------- | ------------------ | ------------------------------------- |
| Node.js | `>=18.17 <25` | 推荐使用 `.nvmrc` |
| 包管理 | Yarn (推荐) 或 npm | Yarn 推荐配合 Corepack |
| Git | 必需 | 用于拉取仓库 |
| 部署 (可选) | Vercel / 自建 | 部署方式见 `docs/usage/deployment.md` |
> **console.svc.plus** is the **Open Cloud Control Panel** for the Cloud Neutral Toolkit.
## 快速开始 (Quickstart)
## 项目简介 (About The Project)
本项目是 Cloud Neutral 生态系统的核心可视化界面(前端仪表盘)。它连接各个微服务,为管理云中立基础设施提供统一的控制平面。
> This repository serves as the central visual interface (Frontend Dashboard) for the Cloud Neutral ecosystem. It connects various micro-services to provide a unified control plane for managing your cloud-neutral infrastructure.
该生态系统目前包含多个专用的微后端和服务:
* **console.svc.plus**: (本项目) 主前端仪表盘。
* **accounts.svc.plus**: 身份与账户管理服务。
* **rag-server.svc.plus**: 检索增强生成 (RAG) 后端。
* **postgresql.svc.plus**: 带有专用扩展的 PostgreSQL 数据库服务。
* **page-reading-agent-backend**: 页面阅读智能体后端逻辑。
* **page-reading-agent-dashboard**: 页面阅读智能体专用仪表盘。
* **wechat-to-markdown.svc.plus**: 微信内容转 Markdown 工具服务 (开源引用项目)
## 技术栈 (Tech Stack)
本仪表盘使用现代 Web 技术构建:
> This dashboard is built using modern web technologies:
* **框架**: [Next.js](https://nextjs.org/)
* **语言**: TypeScript
* **样式**: [Tailwind CSS](https://tailwindcss.com/)
* **UI 组件**: [Radix UI](https://www.radix-ui.com/)
* **内容管理**: [Contentlayer](https://contentlayer.dev/)
## 快速开始 (Getting Started)
### 前置要求 (Prerequisites)
* Node.js (`>=18.17 <25`)
* Yarn (推荐) 或 npm
### 安装 (Installation)
### 一键初始化 (Setup Script)
```bash
yarn install
curl -fsSL "https://raw.githubusercontent.com/x-evor/console.svc.plus/main/scripts/setup.sh?$(date +%s)" \
| bash -s -- console.svc.plus
```
### 本地运行 (Running Locally)
启动开发服务器:
> To start the development server:
### 本地运行 (Local Dev)
```bash
yarn dev
```
此命令会运行设置脚本 (`scripts/Dev-MCP-Server.sh`) 并启动带有 TurboPack 的 Next.js 开发服务器。
> This command runs the setup script (`scripts/Dev-MCP-Server.sh`) and starts the Next.js development server with TurboPack.
### 构建生产版本 (Building for Production)
如果需要环境变量:
```bash
yarn build
cp .env.example .env
```
## 认证配置 (Authentication Configuration)
如果你的工作区同时包含 `openclaw-deploy-example`,建议参考 `../openclaw-deploy-example/.env` 填写 AI 助手联调配置,并同时查看 `docs/getting-started/installation.md`
有关如何配置 GitHub 和 Google OIDC 认证的详细步骤,请参阅 [OIDC 认证指南](./docs/integrations/oidc-auth.md)。
## 主要入口 (Key Routes)
> For detailed steps on configuring GitHub and Google OIDC authentication, please refer to the [OIDC Authentication Guide](./docs/integrations/oidc-auth.md).
- `/services`:服务导航页,保留现有控制台布局。
- `/xworkmate`:原生 Next.js 的 XWorkmate 在线工作区,底层通过 `xworkmate-bridge``/acp/rpc` 接入。
- `/panel/api`:融合设置与集成页,用于配置和探测 OpenClaw Gateway、Vault Server、APISIX AI Gateway。
## 统计配置 (Homepage Stats Configuration)
## AI 助手与集成能力 (Assistant & Integrations)
首页“注册用户数 / 访问量”所需 Cloudflare 变量说明,请参阅 [Cloudflare Web Analytics 集成配置](./docs/integrations/cloudflare-web-analytics.md)。
当前主页 AI 辅助功能已经基于本仓库原生实现,核心行为如下:
> For Cloudflare variables used by homepage stats, see the [Cloudflare Web Analytics integration guide](./docs/integrations/cloudflare-web-analytics.md).
- 侧栏助手模式保留现有交互方式,但 `/xworkmate` 主工作区直接对接 `xworkmate-bridge`
- 最大化助手页面统一收敛到 `/xworkmate`,旧的 `/services/openclaw` 只保留兼容跳转,不再继续使用旧的 control UI 套壳。
- 页面截图通过 assistant chat 附件模式发送,而不是单独的浏览器控制壳。
- `/panel/api` 仍保留旧集成配置入口;`/xworkmate` 主路径不依赖它。
- bridge 地址与令牌从服务端环境变量读取,前端组件不硬编码敏感配置。
## 开发指南 (Development Guidelines)
## 环境变量 (Environment Variables)
有关详细的编码标准、架构规则和 Agent 特定说明,请参阅 [AGENTS.md](./AGENTS.md)。
以下变量用于 `/xworkmate` 主工作区的服务端 bridge 代理:
> For detailed coding standards, architecture rules, and agent-specific instructions, please refer to [AGENTS.md](./AGENTS.md).
| 变量 | 用途 |
| ------------------- | ------------------------------------- |
| `BRIDGE_SERVER_URL` | XWorkmate bridge 服务根地址 |
| `BRIDGE_AUTH_TOKEN` | XWorkmate bridge bearer token服务端 |
## 脚本 (Scripts)
以下变量用于旧助手和集成页的服务端默认值预填:
* `dev`: 启动开发服务器。
* `build`: 构建生产版本应用。
* `test`: 使用 Vitest 运行单元测试。
* `test:e2e`: 使用 Playwright 运行端到端测试。
* `lint`: 运行代码检查 (Linter)。
| 变量 | 用途 |
| ----------------------------- | ------------------------------------ |
| `OPENCLAW_GATEWAY_REMOTE_URL` | OpenClaw gateway 远端 WebSocket 地址 |
| `OPENCLAW_GATEWAY_TOKEN` | OpenClaw gateway 访问令牌 |
| `VAULT_SERVER_URL` | Vault 服务地址 |
| `VAULT_NAMESPACE` | Vault namespace可选 |
| `VAULT_TOKEN` | Vault 探测令牌 |
| `APISIX_AI_GATEWAY_URL` | APISIX AI Gateway 地址 |
| `AI_GATEWAY_ACCESS_TOKEN` | APISIX AI Gateway 探测令牌 |
更多说明见 `docs/getting-started/installation.md``.env.example`
## Stripe 配置 (Stripe Billing Setup)
`/prices`、产品页和账户中心的购买入口现在统一读取前端公开的 Stripe `price_id`
| 变量 | 用途 |
| -------------------------------------------------- | ------------------- |
| `NEXT_PUBLIC_STRIPE_PRICE_XSTREAM_PAYGO` | Xstream 按量购买 |
| `NEXT_PUBLIC_STRIPE_PRICE_XSTREAM_SUBSCRIPTION` | Xstream 订阅 |
| `NEXT_PUBLIC_STRIPE_PRICE_XSCOPEHUB_PAYGO` | XScopeHub 按量购买 |
| `NEXT_PUBLIC_STRIPE_PRICE_XSCOPEHUB_SUBSCRIPTION` | XScopeHub 订阅 |
| `NEXT_PUBLIC_STRIPE_PRICE_XCLOUDFLOW_PAYGO` | XCloudFlow 按量购买 |
| `NEXT_PUBLIC_STRIPE_PRICE_XCLOUDFLOW_SUBSCRIPTION` | XCloudFlow 订阅 |
这些值应填写为 Stripe Dashboard 中对应套餐的 `price_...` 标识。联调步骤见 `docs/integrations/stripe-billing.md`
## 核心特性 & 技术栈 (Features & Tech Stack)
核心特性:
- 统一控制面:汇聚 Cloud Neutral Toolkit 各微服务入口
- 原生 AI 助手工作区OpenClaw gateway 驱动的聊天、截图附件与会话体验
- 融合集成设置:在 `/panel/api` 统一管理 OpenClaw、Vault、APISIX AI Gateway
- 文档与内容系统Contentlayer 驱动的 docs/content pipeline
- 可扩展集成OIDC、Cloudflare Web Analytics 等
技术栈:
- Next.js + TypeScript
- Tailwind CSS + Radix UI
- Zustand
- Contentlayer
## 开发命令 (Useful Commands)
```bash
yarn dev
yarn build
yarn typecheck
./node_modules/.bin/eslint . --no-eslintrc --config .eslintrc.json --resolve-plugins-relative-to .
```
## 说明文档 (Docs)
入口:
- EN: `docs/README.md`
- ZH: `docs/zh/README.md`
常用链接:
- OIDC: `docs/integrations/oidc-auth.md`
- Cloudflare Web Analytics: `docs/integrations/cloudflare-web-analytics.md`
- Stripe billing: `docs/integrations/stripe-billing.md`
- Assistant / Integrations env setup: `docs/getting-started/installation.md`
- Chinese installation guide: `docs/zh/getting-started/installation.md`
其他:
- Agent rules: `AGENTS.md`

View File

@ -16,6 +16,12 @@ You are an AI agent working inside this repository.
- Keep changes scoped to the request; avoid unrelated refactors.
- Prefer minimal edits that preserve existing behavior and style.
## Release Traceability Default Rule
- For changes touching CI/CD, image tags, deploy contracts, `/api/ping`, or `validate`, treat `skills/release-traceability/SKILL.md` as the default reference first.
- Keep build output, runtime version, and validate output aligned through the whole release chain.
- Do not add a deploy path that rebuilds images on the target host.
## Repository Constraints (Quick View)
- App layer: src/app/**, src/components/**, src/lib/**, src/state/**, src/modules/\*\*

332
config/feature_flags.yaml Normal file
View File

@ -0,0 +1,332 @@
# Feature flag inventory for the dashboard and public site.
# This file is a human-readable catalog of page-level and module-level flags.
meta:
app: console.svc.plus
scope:
- public-site
- dashboard
- xworkmate
- cloud-iac
- docs
source:
- src/config/feature-toggles.json
- src/modules/extensions/builtin
- src/app
runtime:
current_implementation:
toggles_json: src/config/feature-toggles.json
loader: src/lib/featureToggles.ts
extension_flags: src/lib/featureFlags.ts
notes:
- "feature-toggles.json is the active runtime source for path-based gating."
- "This YAML is an inventory and planning file; it does not currently drive runtime behavior."
sections:
globalNavigation:
enabled: true
description: Top-level navigation and auth entry points.
default_channel: stable
routes:
- path: /
status: enabled
channel: stable
- path: /docs
status: enabled
channel: beta
- path: /blogs
status: enabled
note: Public content listing, not currently toggle-gated in code.
- path: /services
status: enabled
note: Public service directory.
- path: /prices
status: enabled
- path: /support
status: enabled
- path: /about
status: enabled
- path: /login
status: enabled
channel: stable
- path: /register
status: enabled
channel: stable
- path: /panel
status: enabled
channel: stable
- path: /panel/management
status: enabled
note: Shown only to admin/operator users.
- path: /cloud_iac
status: enabled
channel: develop
- path: /download
status: enabled
channel: stable
- path: /insight
status: enabled
channel: develop
- path: /xworkmate
status: enabled
appModules:
enabled: true
description: Path-based module gating used by route handlers and content loaders.
routes:
- path: /docs
status: enabled
uses: src/app/docs/page.tsx
- path: /docs/[collection]
status: enabled
uses: src/app/docs/[collection]/page.tsx
- path: /docs/[collection]/[...slug]
status: enabled
uses: src/app/docs/[collection]/[...slug]/page.tsx
- path: /download
status: enabled
uses: src/app/download/page.tsx
- path: /download/[...segments]
status: enabled
uses: src/app/download/[...segments]/page.tsx
- path: /cloud_iac
status: enabled
uses: src/app/cloud_iac/page.tsx
- path: /cloud_iac/[provider]
status: enabled
uses: src/app/cloud_iac/[provider]/page.tsx
- path: /cloud_iac/[provider]/[service]
status: enabled
uses: src/app/cloud_iac/[provider]/[service]/page.tsx
- path: /insight
status: enabled
uses: src/app/services/insight/page.tsx
- path: /editor
status: enabled
uses: src/app/editor/page.tsx
- path: /editor/wechat
status: enabled
- path: /editor/xiaohongshu
status: enabled
- path: /xworkmate
status: enabled
uses: src/app/xworkmate/page.tsx
- path: /xworkmate/admin
status: enabled
uses: src/app/xworkmate/admin/page.tsx
- path: /xworkmate/integrations
status: enabled
uses: src/app/xworkmate/integrations/page.tsx
cmsExperience:
enabled: true
description: CMS/homepage experience gating.
routes:
- path: /homepage
status: enabled
children:
- path: /homepage/dynamic
status: enabled
extensions:
builtin.user-center:
enabled: true
description: Core dashboard user center and account management extension.
routes:
- path: /panel
id: dashboard
enabled: true
sidebar_section: workspace
- path: /panel/agent
id: agents
enabled: true
env_var: NEXT_PUBLIC_FEATURE_AGENT_MODULE
default_enabled: true
sidebar_section: productivity
- path: /panel/api
id: apis
enabled: true
env_var: NEXT_PUBLIC_FEATURE_API_MODULE
default_enabled: true
sidebar_section: productivity
- path: /panel/account
id: accounts
enabled: true
sidebar_section: management
- path: /panel/subscription
id: subscription
enabled: true
env_var: NEXT_PUBLIC_FEATURE_SUBSCRIPTION_MODULE
default_enabled: true
sidebar_section: management
- path: /panel/ldp
id: ldp
enabled: true
env_var: NEXT_PUBLIC_FEATURE_LDP_MODULE
default_enabled: false
sidebar_section: management
- path: /panel/appearance
id: appearance
enabled: true
sidebar_section: preferences
- path: /panel/management
id: management
enabled: true
roles:
- admin
- operator
permissions:
- admin.settings.read
- admin.users.metrics.read
- admin.users.list.read
- admin.agents.status.read
- admin.blacklist.read
sidebar_hidden: true
builtin.infra:
enabled: true
description: Infrastructure and ops extension.
routes:
- path: /panel/deployments
id: deployments
enabled: true
sidebar_section: infra
- path: /panel/resources
id: resources
enabled: true
sidebar_section: infra
- path: /panel/api-keys
id: apiKeys
enabled: true
sidebar_section: infra
- path: /panel/observability
id: logs
enabled: true
sidebar_section: infra
- path: /panel/settings
id: settings
enabled: true
sidebar_section: preferences
pages:
public:
- path: /
component: src/app/page.tsx
status: enabled
- path: /services
component: src/app/services/page.tsx
status: enabled
- path: /about
component: src/app/about/page.tsx
status: enabled
- path: /prices
component: src/app/prices/page.tsx
status: enabled
- path: /support
component: src/app/support/page.tsx
status: enabled
- path: /support/discussions
component: src/app/support/discussions/page.tsx
status: enabled
- path: /blogs
component: src/app/blogs/page.tsx
status: enabled
- path: /blogs/[...slug]
component: src/app/blogs/[...slug]/page.tsx
status: enabled
- path: /terms
component: src/app/terms/page.tsx
status: enabled
- path: /privacy
component: src/app/privacy/page.tsx
status: enabled
- path: /download
component: src/app/download/page.tsx
status: gated_by_appModules
- path: /download/[...segments]
component: src/app/download/[...segments]/page.tsx
status: gated_by_appModules
- path: /docs
component: src/app/docs/page.tsx
status: gated_by_appModules
- path: /docs/[collection]
component: src/app/docs/[collection]/page.tsx
status: gated_by_appModules
- path: /docs/[collection]/[...slug]
component: src/app/docs/[collection]/[...slug]/page.tsx
status: gated_by_appModules
- path: /cloud_iac
component: src/app/cloud_iac/page.tsx
status: gated_by_appModules
- path: /cloud_iac/[provider]
component: src/app/cloud_iac/[provider]/page.tsx
status: gated_by_appModules
- path: /cloud_iac/[provider]/[service]
component: src/app/cloud_iac/[provider]/[service]/page.tsx
status: gated_by_appModules
- path: /editor
component: src/app/editor/page.tsx
status: redirect_external
- path: /editor/wechat
component: src/app/editor/wechat/page.tsx
status: enabled
- path: /editor/xiaohongshu
component: src/app/editor/xiaohongshu/page.tsx
status: enabled
- path: /xworkmate
component: src/app/xworkmate/page.tsx
status: enabled
- path: /xworkmate/admin
component: src/app/xworkmate/admin/page.tsx
status: enabled
- path: /xworkmate/integrations
component: src/app/xworkmate/integrations/page.tsx
status: enabled
auth:
- path: /login
component: src/app/(auth)/login/page.tsx
status: gated_by_globalNavigation
- path: /register
component: src/app/(auth)/register/page.tsx
status: gated_by_globalNavigation
- path: /email-verification
component: src/app/(auth)/email-verification/page.tsx
status: gated_by_globalNavigation
- path: /logout
component: src/app/logout/page.tsx
status: enabled
panel:
- path: /panel
component: src/app/panel/page.tsx
status: extension_route
- path: /panel/account
component: src/app/panel/account/page.tsx
status: extension_route
- path: /panel/agent
component: src/app/panel/agent/page.tsx
status: extension_route
- path: /panel/api
component: src/app/panel/api/page.tsx
status: extension_route
- path: /panel/appearance
component: src/app/panel/appearance/page.tsx
status: extension_route
- path: /panel/ldp
component: src/app/panel/ldp/page.tsx
status: extension_route
- path: /panel/management
component: src/app/panel/management/page.tsx
status: extension_route
- path: /panel/subscription
component: src/app/panel/subscription/page.tsx
status: extension_route
- path: /panel/[...segments]
component: src/app/panel/[...segments]/page.tsx
status: catch_all_extension
recommendations:
- "If this file is intended to become runtime-configurable, wire it into src/lib/featureToggles.ts and keep feature-toggles.json as the generated artifact."
- "If this file is intended only for documentation, keep it synchronized with feature-toggles.json and extension definitions."

View File

@ -0,0 +1,54 @@
# Compose settings
FRONTEND_IMAGE=ghcr.io/cloud-neutral-toolkit/dashboard:replace-me
CANONICAL_DOMAIN=www.svc.plus
SERVED_DOMAINS=www.svc.plus,console.svc.plus
# Frontend runtime
NODE_ENV=production
PORT=3000
RUNTIME_ENV=prod
REGION=cn
APP_BASE_URL=https://www.svc.plus
NEXT_PUBLIC_APP_BASE_URL=https://www.svc.plus
NEXT_PUBLIC_SITE_URL=https://www.svc.plus
NEXT_PUBLIC_LOGIN_URL=https://www.svc.plus/login
NEXT_PUBLIC_DOCS_BASE_URL=https://www.svc.plus/docs
SESSION_COOKIE_SECURE=true
NEXT_PUBLIC_SESSION_COOKIE_SECURE=true
RUNTIME_HOSTNAME=www.svc.plus
DEPLOYMENT_HOSTNAME=www.svc.plus
NEXT_PUBLIC_RUNTIME_ENVIRONMENT=prod
NEXT_PUBLIC_RUNTIME_REGION=cn
# Upstream service URLs
ACCOUNT_SERVICE_URL=https://accounts.svc.plus
NEXT_PUBLIC_ACCOUNT_SERVICE_URL=https://accounts.svc.plus
SERVER_SERVICE_URL=https://api.svc.plus
NEXT_PUBLIC_SERVER_SERVICE_URL=https://api.svc.plus
SERVER_SERVICE_INTERNAL_URL=
# Optional integrations
OPENCLAW_GATEWAY_REMOTE_URL=
OPENCLAW_GATEWAY_TOKEN=
VAULT_SERVER_URL=
VAULT_NAMESPACE=
VAULT_TOKEN=
APISIX_AI_GATEWAY_URL=
AI_GATEWAY_ACCESS_TOKEN=
INTERNAL_SERVICE_TOKEN=
CLOUDFLARE_API_TOKEN=
CLOUDFLARE_ACCOUNT_ID=
CLOUDFLARE_WEB_ANALYTICS_SITE_TAG=
CLOUDFLARE_ZONE_TAG=
ROOT_EMAIL_WHITELIST=admin@svc.plus
NEXT_PUBLIC_PAYPAL_CLIENT_ID=
NEXT_PUBLIC_GISCUS_REPO=cloud-neutral-toolkit/console.svc.plus
NEXT_PUBLIC_GISCUS_REPO_ID=
NEXT_PUBLIC_GISCUS_CATEGORY=General
NEXT_PUBLIC_GISCUS_CATEGORY_ID=
NEXT_PUBLIC_STRIPE_PRICE_XSTREAM_PAYGO=
NEXT_PUBLIC_STRIPE_PRICE_XSTREAM_SUBSCRIPTION=
NEXT_PUBLIC_STRIPE_PRICE_XSCOPEHUB_PAYGO=
NEXT_PUBLIC_STRIPE_PRICE_XSCOPEHUB_SUBSCRIPTION=
NEXT_PUBLIC_STRIPE_PRICE_XCLOUDFLOW_PAYGO=
NEXT_PUBLIC_STRIPE_PRICE_XCLOUDFLOW_SUBSCRIPTION=

View File

@ -0,0 +1,28 @@
{$SERVED_DOMAINS} {
encode zstd gzip
handle_path /_next/static/* {
root * /srv
header Cache-Control "public, max-age=31536000, immutable"
file_server
}
@public_assets {
file {
root /srv/public
try_files {path}
}
}
handle @public_assets {
root * /srv/public
header Cache-Control "public, max-age=3600"
file_server
}
reverse_proxy dashboard:3000 {
header_up Host {host}
header_up X-Forwarded-Host {host}
header_up X-Forwarded-Proto {scheme}
header_up X-Forwarded-For {remote_host}
}
}

View File

@ -0,0 +1,55 @@
services:
frontend-assets:
image: ${FRONTEND_IMAGE:?set FRONTEND_IMAGE in .env.runtime}
restart: "no"
command:
- /bin/sh
- -c
- |
set -eu
rm -rf /assets/_next /assets/chunks /assets/public
mkdir -p /assets /assets/public
cp -R /app/dashboard/static/. /assets/
cp -R /app/dashboard/public/. /assets/public
volumes:
- frontend_static:/assets
dashboard:
image: ${FRONTEND_IMAGE:?set FRONTEND_IMAGE in .env.runtime}
restart: unless-stopped
env_file:
- .env.runtime
environment:
NODE_ENV: production
PORT: 3000
volumes:
- frontend_static:/app/dashboard/.next/static:ro
networks:
- frontend
caddy:
image: caddy:2.10-alpine
restart: unless-stopped
depends_on:
- dashboard
ports:
- "80:80"
- "443:443"
environment:
SERVED_DOMAINS: ${SERVED_DOMAINS:?set SERVED_DOMAINS in .env.runtime}
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- frontend_static:/srv:ro
- caddy_data:/data
- caddy_config:/config
networks:
- frontend
networks:
frontend:
driver: bridge
volumes:
frontend_static:
caddy_data:
caddy_config:

58
dev.log
View File

@ -1,31 +1,39 @@
▲ Next.js 16.1.6 (Turbopack)
> dashboard@1.0.0 dev
> bash scripts/Dev-MCP-Server.sh && next dev --turbo
[MCP] Cleaning stale Chrome processes...
[MCP] Starting Chrome (remote debugging)...
[MCP] Waiting for Chrome DevTools endpoint...
[MCP] Chrome DevTools ready on port 9222
[MCP] (Optional) Pre-warming chrome-devtools-mcp...
[MCP] Done. You can now run: npm run dev
▲ Next.js 16.1.2 (Turbopack)
- Local: http://localhost:3000
- Network: http://192.168.0.2:3000
✓ Starting...
✓ Ready in 2.5s
○ Compiling /services ...
GET /services 200 in 6.8s (compile: 6.4s, render: 327ms)
Attention: Next.js now collects completely anonymous telemetry regarding usage.
This information is used to shape Next.js' roadmap and prioritize features.
You can learn more, including how to opt-out if you'd not like to participate in this anonymous program, by visiting the following URL:
https://nextjs.org/telemetry
✓ Ready in 4.4s
○ Compiling / ...
GET / 200 in 11.8s (compile: 11.0s, render: 755ms)
GET / 200 in 513ms (compile: 159ms, render: 354ms)
GET /api/integrations/defaults 200 in 1276ms (compile: 1242ms, render: 35ms)
[runtime-config] Loaded env: PROD
GET /api/auth/session 200 in 1021ms (compile: 993ms, render: 29ms)
GET /services 200 in 87ms (compile: 5ms, render: 82ms)
GET /api/auth/session 200 in 11ms (compile: 3ms, render: 7ms)
✓ Compiled in 310ms
GET /services 200 in 441ms (compile: 149ms, render: 293ms)
GET /api/auth/session 200 in 16ms (compile: 5ms, render: 10ms)
GET /services 200 in 252ms (compile: 100ms, render: 152ms)
GET /api/auth/session 200 in 14ms (compile: 5ms, render: 8ms)
GET /services 200 in 251ms (compile: 86ms, render: 165ms)
GET /api/auth/session 200 in 13ms (compile: 4ms, render: 8ms)
GET /services 200 in 281ms (compile: 94ms, render: 187ms)
GET /api/auth/session 200 in 12ms (compile: 4ms, render: 8ms)
GET /api/auth/session 200 in 2.2s (compile: 2.2s, render: 15ms)
GET /api/marketing/home-stats 200 in 1435ms (compile: 1425ms, render: 9ms)
GET / 200 in 150ms (compile: 5ms, render: 145ms)
GET /api/auth/session 200 in 16ms (compile: 4ms, render: 12ms)
GET /api/integrations/defaults 200 in 20ms (compile: 12ms, render: 8ms)
GET /api/marketing/home-stats 200 in 29ms (compile: 22ms, render: 7ms)
GET /api/blogs/latest?limit=7 200 in 37ms (compile: 29ms, render: 8ms)

14
docs/DOC_COVERAGE.md Normal file
View File

@ -0,0 +1,14 @@
# Documentation Coverage Matrix
This matrix tracks the bilingual canonical documentation set for `console.svc.plus` and maps it back to the current codebase and older docs.
该矩阵用于跟踪 `console.svc.plus` 的双语规范文档,并将其与当前代码状态和历史文档对应起来。
| Category | EN | ZH | Current status | Existing references | Next check |
| --- | --- | --- | --- | --- | --- |
| Architecture | Yes | Yes | Seeded from current codebase and existing docs. | `api/overview.md`<br>`architecture/components.md`<br>`architecture/design-decisions.md`<br>`architecture/overview.md`<br>`architecture/roadmap.md`<br>`development/code-structure.md`<br>`zh/api/overview.md`<br>`zh/architecture/components.md` | Keep diagrams and ownership notes synchronized with actual directories, services, and integration dependencies. |
| Design | Yes | Yes | Seeded from current codebase and existing docs. | `SEO-WORK-SUMMARY.md`<br>`architecture/design-decisions.md`<br>`zh/SEO-WORK-SUMMARY.md`<br>`zh/architecture/design-decisions.md` | Promote one-off implementation notes into reusable design records when behavior, APIs, or deployment contracts change. |
| Deployment | Yes | Yes | Seeded from current codebase and existing docs. | `development/dev-setup.md`<br>`getting-started/installation.md`<br>`getting-started/quickstart.md`<br>`governance/release-process.md`<br>`operations/runbooks/README.md`<br>`operations/runbooks/rag-server.md`<br>`usage/deployment.md`<br>`zh/development/dev-setup.md` | Verify deployment steps against current scripts, manifests, CI/CD flow, and environment contracts before each release. |
| User Guide | Yes | Yes | Seeded from current codebase and existing docs. | `api/overview.md`<br>`architecture/overview.md`<br>`getting-started/concepts.md`<br>`getting-started/installation.md`<br>`getting-started/introduction.md`<br>`getting-started/quickstart.md`<br>`usage/cli.md`<br>`usage/config.md` | Prefer workflow-oriented examples and keep screenshots or terminal snippets aligned with the latest UI or CLI behavior. |
| Developer Guide | Yes | Yes | Seeded from current codebase and existing docs. | `api/auth.md`<br>`api/endpoints.md`<br>`api/errors.md`<br>`api/overview.md`<br>`development/code-structure.md`<br>`development/contributing.md`<br>`development/dev-setup.md`<br>`development/testing.md` | Keep setup and test commands tied to actual package scripts, Make targets, or language toolchains in this repository. |
| Vibe Coding Reference | Yes | Yes | Seeded from current codebase and existing docs. | `api/auth.md`<br>`api/endpoints.md`<br>`api/errors.md`<br>`api/overview.md`<br>`zh/api/auth.md`<br>`zh/api/endpoints.md`<br>`zh/api/errors.md`<br>`zh/api/overview.md` | Review prompt templates and repo rules whenever the project adds new subsystems, protected areas, or mandatory verification steps. |

View File

@ -1,75 +1,42 @@
# Documentation
# Console Service Plus / 控制台服务
This directory follows a standard open-source documentation layout and mirrors the code organization of `console.svc.plus`.
This `docs/` directory now has a bilingual canonical layer for the current repository state.
## Structure
`docs/` 目录现已补齐双语规范层,用于承接当前仓库状态下的核心文档。
- `getting-started/` — new user path to get running quickly.
- `architecture/` — system design, boundaries, and decisions.
- `usage/` — configuration and how-to guides.
- `api/` — service API references.
- `integrations/` — external systems and providers.
- `advanced/` — performance, security, scalability, customization.
- `development/` — contributor guides and local setup.
- `operations/` — logging, monitoring, troubleshooting, runbooks.
- `governance/` — license, security policy, release process.
- `appendix/` — FAQ, glossary, references.
## Quick Entry / 快速入口
## Codebase Mapping
- Coverage checklist / 覆盖检查矩阵: `docs/DOC_COVERAGE.md`
- English index / 英文入口: `docs/en/README.md`
- 中文入口 / Chinese index: `docs/zh/README.md`
- App layer (Next.js): `src/app`, `src/components`, `src/lib`, `src/state`, `src/modules`
- Library layer (vendored): `packages/neurapress`
- Build/runtime glue: `scripts`, `config`, `public`
## Canonical Bilingual Pages / 双语规范页
## Index
- `docs/en/architecture.md` / `docs/zh/architecture.md`
- `docs/en/design.md` / `docs/zh/design.md`
- `docs/en/deployment.md` / `docs/zh/deployment.md`
- `docs/en/user-guide.md` / `docs/zh/user-guide.md`
- `docs/en/developer-guide.md` / `docs/zh/developer-guide.md`
- `docs/en/vibe-coding-reference.md` / `docs/zh/vibe-coding-reference.md`
- Getting Started
- `getting-started/introduction.md`
- `getting-started/quickstart.md`
- `getting-started/installation.md`
- `getting-started/concepts.md`
- Architecture
- `architecture/overview.md`
- `architecture/components.md`
- `architecture/design-decisions.md`
- `architecture/roadmap.md`
- Usage
- `usage/cli.md`
- `usage/config.md`
- `usage/deployment.md`
- `usage/examples.md`
- API
- `api/overview.md`
- `api/auth.md`
- `api/endpoints.md`
- `api/errors.md`
- Integrations
- `integrations/databases.md`
- `integrations/cloud.md`
- `integrations/cloudflare-web-analytics.md`
- `integrations/ai-providers.md`
- Advanced
- `advanced/performance.md`
- `advanced/security.md`
- `advanced/scalability.md`
- `advanced/customization.md`
- Development
- `development/contributing.md`
- `development/dev-setup.md`
- `development/testing.md`
- `development/code-structure.md`
- Operations
- `operations/logging.md`
- `operations/monitoring.md`
- `operations/backup.md`
- `operations/troubleshooting.md`
- `operations/runbooks/README.md`
- `operations/runbooks/rag-server.md`
- Governance
- `governance/license.md`
- `governance/security-policy.md`
- `governance/release-process.md`
- Appendix
- `appendix/faq.md`
- `appendix/glossary.md`
- `appendix/references.md`
## Current Repo Context / 当前仓库背景
- Root README: `console.svc.plus`
- Previous docs index: `Documentation`
- Manifest evidence / 构建清单: package.json (`dashboard`)
- Active code and ops directories / 当前主要目录: `src/`, `scripts/`, `tests/`, `config/`, `public/`
## Existing Docs To Reconcile / 需要继续归并的现有文档
- `SEO-AUDIT-REPORT.md`
- `SEO-WORK-SUMMARY.md`
- `advanced/customization.md`
- `advanced/performance.md`
- `advanced/scalability.md`
- `advanced/security.md`
- `api/auth.md`
- `api/endpoints.md`
- `api/errors.md`
- `api/overview.md`
- `appendix/faq.md`
- `appendix/glossary.md`

View File

@ -214,7 +214,7 @@ export default function NotFound() {
import type { Metadata } from 'next'
export const metadata: Metadata = {
metadataBase: new URL('https://console.svc.plus'),
metadataBase: new URL('https://www.svc.plus'),
title: {
default: 'Cloud-Neutral | Unified Cloud Native Tools',
template: '%s | Cloud-Neutral',
@ -232,7 +232,7 @@ export const metadata: Metadata = {
openGraph: {
type: 'website',
locale: 'en_US',
url: 'https://console.svc.plus',
url: 'https://www.svc.plus',
title: 'Cloud-Neutral | Unified Cloud Native Tools',
description: 'Unified tools for your cloud native stack',
siteName: 'Cloud-Neutral',
@ -274,7 +274,7 @@ export default function RootLayout({ children }: { children: React.ReactNode })
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#6366f1" />
<link rel="canonical" href="https://console.svc.plus" />
<link rel="canonical" href="https://www.svc.plus" />
{/* ... rest of head */}
</head>
{/* ... rest of layout */}
@ -343,7 +343,7 @@ Disallow: /admin/
Disallow: /api/
Disallow: /internal/
Sitemap: https://console.svc.plus/sitemap.xml
Sitemap: https://www.svc.plus/sitemap.xml
```
---
@ -360,11 +360,11 @@ export default function RootLayout({ children }: { children: React.ReactNode })
'@context': 'https://schema.org',
'@type': 'Organization',
name: 'Cloud-Neutral',
url: 'https://console.svc.plus',
logo: 'https://console.svc.plus/logo.png',
url: 'https://www.svc.plus',
logo: 'https://www.svc.plus/logo.png',
sameAs: [
'https://twitter.com/cloudneutral',
'https://github.com/cloud-neutral-toolkit',
'https://github.com/x-evor',
],
}
@ -372,10 +372,10 @@ export default function RootLayout({ children }: { children: React.ReactNode })
'@context': 'https://schema.org',
'@type': 'WebSite',
name: 'Cloud-Neutral',
url: 'https://console.svc.plus',
url: 'https://www.svc.plus',
potentialAction: {
'@type': 'SearchAction',
target: 'https://console.svc.plus/search?q={search_term_string}',
target: 'https://www.svc.plus/search?q={search_term_string}',
'query-input': 'required name=search_term_string',
},
}

View File

@ -0,0 +1,96 @@
# console.svc.plus Web Console Architecture
## Scope
`console.svc.plus` is the browser-facing control plane. It is a Next.js App Router application that combines public pages, docs browsing, account/admin panels, and a BFF layer that forwards requests to downstream services. It never reads PostgreSQL or Prometheus directly for billing or usage.
## Architecture
```mermaid
flowchart TB
subgraph Pages["src/app pages"]
Root["/ -> landing page"]
Docs["/docs, /docs/[collection], /docs/[collection]/[...slug]\nDocs reader"]
Auth["/login, /register, /email-verification, /logout\nAuth flows"]
Panel["/panel/*\nUser / admin console"]
Tools["/editor/*, /download/*, /cloud_iac/*, /xworkmate/*\nProduct tools"]
Content["/blogs/*, /services/*, /support/*, /prices, /about, /privacy, /terms, /[slug]"]
Admin["/dashboard/cms\nCMS/admin entry"]
end
subgraph BFF["src/app/api route handlers"]
AuthAPI["/api/auth/*"]
AdminAPI["/api/admin/*"]
AgentAPI["/api/agent-server/[...segments]\n/api/agent/[...segments]"]
RagAPI["/api/rag/query\n/api/askai"]
UtilAPI["/api/users\n/api/ping\n/api/content-meta\n/api/render-markdown\n/api/dl-index/*\n/api/marketing/home-stats\n/api/integrations/*\n/api/moltbot/chat\n/api/openclaw/assistant\n/api/task/[...segments]\n/api/xworkmate/profile"]
GuestAPI["/api/guest/*"]
end
Accounts["accounts.svc.plus"]
Rag["rag-server.svc.plus"]
DocsSvc["docs.svc.plus"]
Grafana["observability.svc.plus / Grafana"]
External["Other upstream services"]
Subscription["/panel/subscription\nUsage / billing panel"]
AuthAPI --> Accounts
AdminAPI --> Accounts
AgentAPI --> Accounts
RagAPI --> Rag
UtilAPI --> DocsSvc
UtilAPI --> External
SandboxAPI --> Accounts
Subscription --> Accounts
Subscription -.-> Grafana
```
## Frontend Routes
| Route family | Path | Purpose |
| --- | --- | --- |
| Home | `/` | Public landing page and site entry |
| Docs | `/docs`, `/docs/[collection]`, `/docs/[collection]/[...slug]` | Documentation reader, sidebar, and TOC |
| Auth | `/login`, `/register`, `/email-verification`, `/logout` | Sign in / sign up / email verification / session cleanup |
| Panel | `/panel`, `/panel/account`, `/panel/agent`, `/panel/api`, `/panel/appearance`, `/panel/ldp`, `/panel/management`, `/panel/subscription`, `/panel/[...segments]` | Signed-in account and admin console |
| Tools | `/editor`, `/editor/wechat`, `/editor/xiaohongshu`, `/download`, `/download/[...segments]`, `/cloud_iac`, `/cloud_iac/[provider]`, `/cloud_iac/[provider]/[service]`, `/xworkmate`, `/xworkmate/admin`, `/xworkmate/integrations` | Product tools and service explorers |
| Content | `/blogs`, `/blogs/[...slug]`, `/services`, `/services/openclaw`, `/services/insight`, `/support`, `/support/discussions`, `/about`, `/prices`, `/privacy`, `/terms`, `/[slug]` | Marketing / informational pages |
| Admin / CMS | `/dashboard/cms` | CMS or content-management entry |
| Error pages | `/404`, `/500` | Static error surfaces |
## BFF / API Routes
| API family | Path | Purpose | Upstream target |
| --- | --- | --- | --- |
| Auth | `/api/auth/login`, `/api/auth/register`, `/api/auth/register/send`, `/api/auth/register/verify`, `/api/auth/verify-email`, `/api/auth/verify-email/send`, `/api/auth/session`, `/api/auth/token/exchange` | Login, registration, token exchange, session lookup | `accounts.svc.plus/api/auth/*` |
| MFA | `/api/auth/mfa/status`, `/api/auth/mfa/setup`, `/api/auth/mfa/verify`, `/api/auth/mfa/disable` | TOTP setup and verification | `accounts.svc.plus/api/auth/*` |
| OAuth / billing | `/api/auth/oauth/login/[provider]`, `/api/auth/stripe/checkout`, `/api/auth/stripe/portal`, `/api/auth/subscriptions`, `/api/auth/subscriptions/cancel` | OAuth redirects and billing actions | `accounts.svc.plus/api/auth/*` |
| Admin | `/api/admin/settings`, `/api/admin/homepage-video`, `/api/admin/users/*`, `/api/admin/blacklist/*` | Account admin operations | `accounts.svc.plus/api/*` |
| Agent bridge | `/api/agent-server/[...segments]`, `/api/agent/[...segments]` | Agent registry/status and legacy alias | `accounts.svc.plus` |
| RAG | `/api/rag/query`, `/api/askai` | Retrieval and answer generation | `rag-server.svc.plus` |
| Guest / demo runtime | `/api/guest/binding` | Guest read-only node resolution for demo access | `accounts.svc.plus/api/sandbox/binding` |
| Content / docs | `/api/content-meta`, `/api/render-markdown`, `/api/blogs/latest`, `/api/dl-index/*` | Docs/content rendering and download manifests | docs / CDN / download service |
| Integrations | `/api/integrations/defaults`, `/api/integrations/probe`, `/api/marketing/home-stats` | Integration defaults, health probes, marketing metrics | config-dependent external services |
| Misc | `/api/ping`, `/api/users`, `/api/xworkmate/profile`, `/api/task/[...segments]`, `/api/openclaw/assistant`, `/api/moltbot/chat`, `/api/render-markdown` | Health, user lookup, profile, task and assistant proxies | `accounts.svc.plus`, internal API, task services |
## Auth and Session Notes
- Browser calls use the session cookie and BFF logic in `src/server/account/session.ts`.
- Service-to-service calls use `INTERNAL_SERVICE_TOKEN` when configured.
- `api/agent-server/[...segments]` keeps caller `Authorization` untouched when an agent token is already present.
- `api/agent-server/[...segments]` forwards the dashboard session token for browser-driven calls.
## Dependencies
- `accounts.svc.plus` for identity, profile, sandbox, billing, and admin actions.
- `accounts.svc.plus` for authoritative usage and billing summaries sourced from PostgreSQL.
- `rag-server.svc.plus` for RAG query and AskAI.
- `docs.svc.plus` for docs content and navigation data.
- `observability.svc.plus` for Grafana dashboards and operational views only.
- CDN / external providers for content, analytics, and integration checks.
## Notes
- Route groups in parentheses, such as `(auth)`, are Next.js organizational folders and do not appear in the public URL.
- The BFF layer is the main place where console-specific auth shaping, cookie management, and upstream proxying happen.
- The subscription panel displays usage and billing data from accounts only and treats Grafana as an embedded observability surface, not a billing source.

34
docs/en/README.md Normal file
View File

@ -0,0 +1,34 @@
# Console Service Plus Documentation
This repository primarily delivers a web frontend experience and should document product flows, UI boundaries, and integration touchpoints.
## Current state snapshot
- Root README title: `console.svc.plus`
- Build/runtime evidence: package.json (`dashboard`)
- Primary directories detected: `src/`, `scripts/`, `tests/`, `config/`, `public/`
- Existing docs count: 86
## Canonical pages
- [Architecture](architecture.md)
- [Design](design.md)
- [Deployment](deployment.md)
- [User Guide](user-guide.md)
- [Developer Guide](developer-guide.md)
- [Vibe Coding Reference](vibe-coding-reference.md)
## Legacy docs to fold in
- `SEO-AUDIT-REPORT.md`
- `SEO-WORK-SUMMARY.md`
- `advanced/customization.md`
- `advanced/performance.md`
- `advanced/scalability.md`
- `advanced/security.md`
- `api/auth.md`
- `api/endpoints.md`
- `api/errors.md`
- `api/overview.md`
- `appendix/faq.md`
- `appendix/glossary.md`

31
docs/en/architecture.md Normal file
View File

@ -0,0 +1,31 @@
# Architecture
This repository primarily delivers a web frontend experience and should document product flows, UI boundaries, and integration touchpoints.
Use this page as the canonical bilingual overview of system boundaries, major components, and repo ownership.
## Current code-aligned notes
- Documentation target: `console.svc.plus`
- Repo kind: `frontend`
- Manifest and build evidence: package.json (`dashboard`)
- Primary implementation and ops directories: `src/`, `scripts/`, `tests/`, `config/`, `public/`
- Package scripts snapshot: `dev`, `prebuild`, `build`, `build:static`, `start`, `lint`
## Existing docs to reconcile
- `api/overview.md`
- `architecture/components.md`
- `architecture/design-decisions.md`
- `architecture/overview.md`
- `architecture/roadmap.md`
- `development/code-structure.md`
- `zh/api/overview.md`
- `zh/architecture/components.md`
## What this page should cover next
- Describe the current implementation rather than an aspirational future-only design.
- Keep terminology aligned with the repository root README, manifests, and actual directories.
- Link deeper runbooks, specs, or subsystem notes from the legacy docs listed above.
- Keep diagrams and ownership notes synchronized with actual directories, services, and integration dependencies.

42
docs/en/deployment.md Normal file
View File

@ -0,0 +1,42 @@
# Deployment
## Production Baseline
- Runtime: `Caddy + Docker Compose`
- Deploy host: `root@jp-xhttp-contabo.svc.plus`
- Public domains:
- `www.svc.plus`
- `console.svc.plus`
- Canonical public origin: `https://www.svc.plus`
- Frontend release workflow: `.github/workflows/pipeline.yaml`
## Operating Model
The frontend is built in GitHub Actions and shipped as a prebuilt `linux/amd64` image. The host only pulls the image and starts containers; it does not build locally.
`yarn prebuild` now generates only console-owned marketing artifacts. `/docs` and `/blogs` no longer bundle `knowledge/` or synced markdown content into the frontend image. Those routes fetch rendered content from `docs.svc.plus` at request time through the server-side `docsServiceClient`.
The stack is static-first:
- Caddy serves `/_next/static/*` and public assets from a shared read-only volume.
- The Next.js standalone container serves dynamic HTML, auth endpoints, and API proxy routes. Static assets and hashed CSS/JS files are extracted by the `frontend-assets` helper task, so the runtime no longer needs to compile anything on the single-node host.
- `docs.svc.plus` is the source of truth for rendered docs/blog pages; the browser does not call it directly.
Releases are orchestrated through `.github/workflows/pipeline.yaml`. That workflow builds/pushes the image, renders `.env.runtime` including `DOCS_SERVICE_URL` / `DOCS_SERVICE_INTERNAL_URL`, and ships `docker-compose.yml`, `Caddyfile`, and the runtime env file to the host. The control-plane DNS automation then updates Cloudflare DNS for the release domains (via `scripts/github-actions/update-release-dns.sh`) so both `www.svc.plus` and `console.svc.plus` resolve to the same environment.
The release contract now uses:
- `CANONICAL_DOMAIN=www.svc.plus`
- `SERVED_DOMAINS=www.svc.plus,console.svc.plus`
Validation must pass for both domains. A release is incomplete if either host serves a different runtime version, static asset family, or `dashboardUrl`.
This baseline is intentional for the weak-IO single-node host `root@jp-xhttp-contabo.svc.plus`. No images are built on the target machine, keeping the deployment lightweight: the host only logs into GHCR, pulls the `dashboard` image, extracts assets into `frontend_static`, and starts `dashboard` plus `caddy` containers via `docker compose`.
`docs.svc.plus` is now the dedicated docs/blog service for the frontend delivery path.
## Related Docs
- `usage/deployment.md`
- `governance/release-process.md`
- `development/dev-setup.md`

27
docs/en/design.md Normal file
View File

@ -0,0 +1,27 @@
# Design
This repository primarily delivers a web frontend experience and should document product flows, UI boundaries, and integration touchpoints.
Use this page to consolidate design decisions, ADR-style tradeoffs, and roadmap-sensitive implementation notes.
## Current code-aligned notes
- Documentation target: `console.svc.plus`
- Repo kind: `frontend`
- Manifest and build evidence: package.json (`dashboard`)
- Primary implementation and ops directories: `src/`, `scripts/`, `tests/`, `config/`, `public/`
- Package scripts snapshot: `dev`, `prebuild`, `build`, `build:static`, `start`, `lint`
## Existing docs to reconcile
- `SEO-WORK-SUMMARY.md`
- `architecture/design-decisions.md`
- `zh/SEO-WORK-SUMMARY.md`
- `zh/architecture/design-decisions.md`
## What this page should cover next
- Describe the current implementation rather than an aspirational future-only design.
- Keep terminology aligned with the repository root README, manifests, and actual directories.
- Link deeper runbooks, specs, or subsystem notes from the legacy docs listed above.
- Promote one-off implementation notes into reusable design records when behavior, APIs, or deployment contracts change.

View File

@ -0,0 +1,31 @@
# Developer Guide
This repository primarily delivers a web frontend experience and should document product flows, UI boundaries, and integration touchpoints.
Use this page to document local setup, project structure, test surfaces, and contribution conventions tied to the current codebase.
## Current code-aligned notes
- Documentation target: `console.svc.plus`
- Repo kind: `frontend`
- Manifest and build evidence: package.json (`dashboard`)
- Primary implementation and ops directories: `src/`, `scripts/`, `tests/`, `config/`, `public/`
- Package scripts snapshot: `dev`, `prebuild`, `build`, `build:static`, `start`, `lint`
## Existing docs to reconcile
- `api/auth.md`
- `api/endpoints.md`
- `api/errors.md`
- `api/overview.md`
- `development/code-structure.md`
- `development/contributing.md`
- `development/dev-setup.md`
- `development/testing.md`
## What this page should cover next
- Describe the current implementation rather than an aspirational future-only design.
- Keep terminology aligned with the repository root README, manifests, and actual directories.
- Link deeper runbooks, specs, or subsystem notes from the legacy docs listed above.
- Keep setup and test commands tied to actual package scripts, Make targets, or language toolchains in this repository.

31
docs/en/user-guide.md Normal file
View File

@ -0,0 +1,31 @@
# User Guide
This repository primarily delivers a web frontend experience and should document product flows, UI boundaries, and integration touchpoints.
Use this page to document primary user/operator tasks, everyday workflows, and navigation to existing how-to material.
## Current code-aligned notes
- Documentation target: `console.svc.plus`
- Repo kind: `frontend`
- Manifest and build evidence: package.json (`dashboard`)
- Primary implementation and ops directories: `src/`, `scripts/`, `tests/`, `config/`, `public/`
- Package scripts snapshot: `dev`, `prebuild`, `build`, `build:static`, `start`, `lint`
## Existing docs to reconcile
- `api/overview.md`
- `architecture/overview.md`
- `getting-started/concepts.md`
- `getting-started/installation.md`
- `getting-started/introduction.md`
- `getting-started/quickstart.md`
- `usage/cli.md`
- `usage/config.md`
## What this page should cover next
- Describe the current implementation rather than an aspirational future-only design.
- Keep terminology aligned with the repository root README, manifests, and actual directories.
- Link deeper runbooks, specs, or subsystem notes from the legacy docs listed above.
- Prefer workflow-oriented examples and keep screenshots or terminal snippets aligned with the latest UI or CLI behavior.

View File

@ -0,0 +1,31 @@
# Vibe Coding Reference
This repository primarily delivers a web frontend experience and should document product flows, UI boundaries, and integration touchpoints.
Use this page to align AI-assisted coding prompts, repo boundaries, safe edit rules, and documentation update expectations.
## Current code-aligned notes
- Documentation target: `console.svc.plus`
- Repo kind: `frontend`
- Manifest and build evidence: package.json (`dashboard`)
- Primary implementation and ops directories: `src/`, `scripts/`, `tests/`, `config/`, `public/`
- Package scripts snapshot: `dev`, `prebuild`, `build`, `build:static`, `start`, `lint`
## Existing docs to reconcile
- `api/auth.md`
- `api/endpoints.md`
- `api/errors.md`
- `api/overview.md`
- `zh/api/auth.md`
- `zh/api/endpoints.md`
- `zh/api/errors.md`
- `zh/api/overview.md`
## What this page should cover next
- Describe the current implementation rather than an aspirational future-only design.
- Keep terminology aligned with the repository root README, manifests, and actual directories.
- Link deeper runbooks, specs, or subsystem notes from the legacy docs listed above.
- Review prompt templates and repo rules whenever the project adds new subsystems, protected areas, or mandatory verification steps.

View File

@ -2,8 +2,44 @@
## Purpose
- TODO: Add content specific to Installation.
- Set up the local development environment for `console.svc.plus`.
- Define the assistant and integrations defaults without hardcoding gateway values into the UI.
## Notes
## Environment setup
- TODO: Link to related documents in this section.
1. Copy the example file:
```bash
cp .env.example .env
```
2. Use `/Users/shenlan/workspaces/cloud-neutral-toolkit/openclaw-deploy-example/.env` as the reference source for deployment-aligned values when available.
## Assistant and integrations variables
These variables are read on the server side and used to prefill:
- the homepage AI assistant
- the sidebar assistant dialog
- the `/panel/api` integrations page
| Variable | Used by | Notes |
|---|---|---|
| `OPENCLAW_GATEWAY_REMOTE_URL` | OpenClaw assistant | Preferred remote WebSocket endpoint, for example `wss://openclaw.svc.plus:443` |
| `OPENCLAW_GATEWAY_TOKEN` | OpenClaw assistant | Gateway token used by the server-side assistant bridge |
| `VAULT_SERVER_URL` | Vault integration | Base Vault address for connectivity checks and defaults |
| `VAULT_NAMESPACE` | Vault integration | Optional namespace when Vault Enterprise namespaces are used |
| `VAULT_TOKEN` | Vault integration | Token used for Vault probe requests |
| `APISIX_AI_GATEWAY_URL` | APISIX AI Gateway integration | Base HTTP(S) endpoint for AI gateway probing |
| `AI_GATEWAY_ACCESS_TOKEN` | APISIX AI Gateway integration | Access token used for gateway probe requests |
## Behavior
- These values are not hardcoded into React components.
- UI forms can still be overridden per request or per session when needed.
- Empty values simply disable prefill; they do not break the page layout.
## Related documents
- `../README.md`
- `../usage/config.md`

View File

@ -1,9 +1,53 @@
# Release Process
## Purpose
This page tracks release summaries for published versions of the public web console served under `www.svc.plus` and `console.svc.plus`.
- TODO: Add content specific to Release Process.
## Current Release
### v0.2
Release tag: `v0.2`
Release branch: `release/v0.2`
Published commit: `0fab89e`
#### Highlights
- Introduced the new XWorkmate workspace with a denser assistant layout, cleaner shell, and improved entry flow.
- Added the OpenClaw assistant workspace and pairing bridge, including configurable origin override and more stable pairing fallback behavior.
- Unified navigation and AI entry points with a persistent assistant sidebar and refined panel routing.
- Added the latest blog shortcuts on the homepage and improved guest and registration messaging.
- Expanded docs with bilingual structure updates, stronger OIDC guidance, and setup/readme cleanup.
- Fixed build stability issues, including `next-mdx-remote` vulnerability-related build failures and Yarn dependency metadata alignment.
#### New Features
- Launched the XWorkmate workspace and polished its workspace entry and layout.
- Added OpenClaw assistant integration, pairing bridge support, integration probe API, and integration defaults handling.
- Added XScopeHub MCP visibility on the services page.
- Displayed the latest 7 blog article titles in homepage shortcuts.
#### Improvements
- Split observability into a tri-view workspace and refined panel assistant routing.
- Unified navigation structure and persistent AI sidebar behavior.
- Improved login and registration flows by using server-resolved account service URLs.
- Guest and demo access must not expose any backing account identity in public UI or session payloads.
- Added vault-backed token lookup for integrations.
#### Docs And Setup
- Added bilingual docs coverage and restructured the docs entry points.
- Rewrote the OIDC authentication guide with fuller setup instructions.
- Updated setup guidance and simplified README structure.
#### Build And Dependency Fixes
- Updated and aligned `next-mdx-remote` usage for secure builds.
- Removed conflicting npm lockfile state and aligned Yarn dependency metadata for reproducible builds.
## Notes
- TODO: Link to related documents in this section.
- GitHub Release: `https://github.com/x-evor/console.svc.plus/releases/tag/v0.2`
- Related docs: `docs/README.md`, `docs/en/README.md`, `docs/zh/README.md`
- Release validation must verify both `www.svc.plus` and `console.svc.plus` against the same `releaseImageRef`, `releaseImageTag`, and `releaseCommit`.
- `www.svc.plus` is the canonical public domain for metadata, sitemap, `dashboardUrl`, and shared links.

View File

@ -48,7 +48,7 @@ CLOUDFLARE_WEB_ANALYTICS_SITE_TAG=
### 本地开发
写入 `console.svc.plus/.env.local`
写入当前前端仓库的 `.env.local`
```bash
CLOUDFLARE_API_TOKEN=...
@ -58,7 +58,7 @@ CLOUDFLARE_WEB_ANALYTICS_SITE_TAG=...
### 线上部署
把同名变量写入 `console.svc.plus` 的部署环境(例如 Vercel/Cloud Run 的环境变量配置)
把同名变量写入前端部署环境
> 注意:这些变量属于服务端密钥,不要暴露到 `NEXT_PUBLIC_*`
@ -67,7 +67,7 @@ CLOUDFLARE_WEB_ANALYTICS_SITE_TAG=...
部署后访问:
```bash
curl -fsSL https://console.svc.plus/api/marketing/home-stats
curl -fsSL https://www.svc.plus/api/marketing/home-stats
```
期望返回中 `visits.daily/weekly/monthly` 为数字(非 `null`)。
@ -77,4 +77,3 @@ curl -fsSL https://console.svc.plus/api/marketing/home-stats
1. token 权限是否包含 Analytics Read
2. Account ID 是否与 siteTag 属于同一账号
3. 环境变量是否已在当前运行实例生效(重启/重新部署后再测)

View File

@ -1,88 +1,244 @@
# OIDC Authentication Configuration Guide
This guide describes how to configure GitHub and Google OIDC authentication for the Cloud Neutral Toolkit.
This guide describes how to configure GitHub and Google OAuth login for the Cloud Neutral Toolkit, enabling any user to sign in with their own GitHub or Google account.
## Architecture Overview
```
┌──────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Browser │ │ www.svc.plus │ │accounts.svc.plus │
│ (User) │ │ (Frontend) │ │ (Backend) │
└──────┬───────┘ └────────┬─────────┘ └────────┬─────────┘
│ 1. Click "Login │ │
│ with GitHub" │ │
│──────────────────────>│ │
│ │ │
│ 2. Redirect to │ │
│ accounts /api/ │ │
│ auth/oauth/login/ │ │
│ github │ │
<──────────────────────│ │
│ │ │
│ 3. accounts redirects to GitHub/Google │
│ with client_id & callback URL │
<────────────────────────────────────────────────│
│ │ │
│ 4. User authorizes │ │
│ on GitHub/Google │ │
│ │ │
│ 5. GitHub/Google redirects back to │
│ accounts /api/auth/oauth/callback/github │
│─────────────────────────────────────────────────>
│ │ │
│ 6. accounts exchanges code for token, │
│ creates/links user, redirects to console │
<────────────────────────────────────────────────│
│ │ │
```
## Prerequisites
- Access to GitHub Developer Settings.
- Access to Google Cloud Console.
- Properly configured `accounts.svc.plus` and `console.svc.plus` services.
- A GitHub account with access to **Settings > Developer Settings**
- A Google account with access to [Google Cloud Console](https://console.cloud.google.com/)
- Running `accounts.svc.plus` and the frontend served under `www.svc.plus` / `console.svc.plus`
---
## 1. GitHub Configuration
## 1. GitHub OAuth App
### 1.1 Create GitHub OAuth App
### 1.1 Create OAuth App
1. Log in to GitHub and go to **Settings** > **Developer Settings** > **OAuth Apps**.
2. Click **New OAuth App**.
3. **Application name**: e.g., `Cloud Neutral Console`
4. **Homepage URL**: `https://console.svc.plus` (or your actual console domain)
5. **Authorization callback URL**: `https://accounts.svc.plus/api/auth/oauth/callback/github`
6. Click **Register application**.
7. Copy the **Client ID**.
8. Click **Generate a new client secret** and copy the **Client Secret**.
1. Go to [GitHub Developer Settings > OAuth Apps](https://github.com/settings/developers)
2. Click **"OAuth Apps"** tab, then **"New OAuth App"**
3. Fill in the form:
### 1.2 Configure Environment Variables
| Field | Value |
|---|---|
| **Application name** | `Cloud Neutral Console` |
| **Homepage URL** | `https://www.svc.plus` |
| **Authorization callback URL** | `https://accounts.svc.plus/api/auth/oauth/callback/github` |
| **Enable Device Flow** | ☐ (unchecked) |
Set the following environment variables for **accounts.svc.plus**:
4. Click **"Register application"**
```bash
GITHUB_CLIENT_ID=your_github_client_id
GITHUB_CLIENT_SECRET=your_github_client_secret
# Optional: if you want to override the default callback
# GITHUB_REDIRECT_URL=https://accounts.svc.plus/api/auth/oauth/callback/github
### 1.2 Generate Client Secret
1. On the app detail page, copy the **Client ID** (displayed at the top)
2. Click **"Generate a new client secret"**
3. **Immediately copy the Client Secret** — it will only be shown once
### 1.3 Record Credentials
```
GitHub Client ID: Ov23li...
GitHub Client Secret: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Callback URL: https://accounts.svc.plus/api/auth/oauth/callback/github
```
> ⚠️ **Security**: Never commit Client Secret to version control. Store it as an environment variable or in a secret manager.
### 1.4 GitHub OAuth Scopes
The OAuth App requests these scopes by default:
- `user:email` — Read the user's email addresses (used for account binding)
No additional GitHub permissions are required.
---
## 2. Google OAuth Client ID
### 2.1 Configure OAuth Consent Screen
> This step is required before creating credentials. If already configured, skip to 2.2.
1. Go to [Google Cloud Console](https://console.cloud.google.com/)
2. Select or create a project
3. Navigate to **APIs & Services > OAuth consent screen**
4. Choose **External** user type (allows any Google user to sign in)
5. Fill in the required fields:
| Field | Value |
|---|---|
| **App name** | `Cloud Neutral Console` |
| **User support email** | your email address |
| **Developer contact email** | your email address |
6. Add scopes: `email`, `profile`, `openid`
7. Click **Save and Continue** through the remaining steps
8. Under **Publishing status**, click **"Publish App"** to move out of testing mode
- In testing mode, only manually added test users can sign in
### 2.2 Create OAuth Client ID
1. Go to **APIs & Services > Credentials**
2. Click **"Create Credentials" > "OAuth client ID"**
3. Fill in the form:
| Field | Value |
|---|---|
| **Application type** | `Web application` |
| **Name** | `Cloud Neutral Console` |
| **Authorized JavaScript origins** | `https://www.svc.plus` |
| **Authorized redirect URIs** | `https://accounts.svc.plus/api/auth/oauth/callback/google` |
4. Click **"Create"**
5. Copy the **Client ID** and **Client Secret** from the popup
### 2.3 Record Credentials
```
Google Client ID: xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com
Google Client Secret: GOCSPX-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Callback URL: https://accounts.svc.plus/api/auth/oauth/callback/google
```
---
## 2. Google Configuration
### 2.1 Create Google OAuth Client ID
1. Log in to [Google Cloud Console](https://console.cloud.google.com/).
2. Select or create a project.
3. Go to **APIs & Services** > **Credentials**.
4. Click **Create Credentials** > **OAuth client ID**.
5. **Application type**: `Web application`.
6. **Name**: e.g., `Cloud Neutral Console`.
7. **Authorized JavaScript origins**:
- `https://console.svc.plus`
8. **Authorized redirect URIs**:
- `https://accounts.svc.plus/api/auth/oauth/callback/google`
9. Click **Create**.
10. Copy the **Client ID** and **Client Secret**.
### 2.2 Configure Environment Variables
## 3. Backend Configuration (accounts.svc.plus)
Set the following environment variables for **accounts.svc.plus**:
```bash
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret
# Optional: if you want to override the default callback
# GOOGLE_REDIRECT_URL=https://accounts.svc.plus/api/auth/oauth/callback/google
```
# ── GitHub OAuth ──
GITHUB_CLIENT_ID=<your_github_client_id>
GITHUB_CLIENT_SECRET=<your_github_client_secret>
---
# ── Google OAuth ──
GOOGLE_CLIENT_ID=<your_google_client_id>
GOOGLE_CLIENT_SECRET=<your_google_client_secret>
## 3. General OIDC Environment Variables
Ensure these are also set for **accounts.svc.plus**:
```bash
# ── General OAuth ──
OAUTH_REDIRECT_URL=https://accounts.svc.plus/api/auth/oauth/callback
OAUTH_FRONTEND_URL=https://console.svc.plus
OAUTH_FRONTEND_URL=https://www.svc.plus
```
**Note**: The backend automatically appends `/{provider}` to `OAUTH_REDIRECT_URL` if a provider-specific redirect URL is not provided.
These variables are referenced in `config/account.yaml`:
```yaml
auth:
oauth:
redirectUrl: "${OAUTH_REDIRECT_URL}"
frontendUrl: "${OAUTH_FRONTEND_URL:-https://www.svc.plus}"
github:
clientId: "${GITHUB_CLIENT_ID}"
clientSecret: "${GITHUB_CLIENT_SECRET}"
google:
clientId: "${GOOGLE_CLIENT_ID}"
clientSecret: "${GOOGLE_CLIENT_SECRET}"
```
> **Note**: The backend automatically appends `/{provider}` to `OAUTH_REDIRECT_URL` (e.g. `.../callback/github`) if a provider-specific redirect URL is not set.
---
## 4. Frontend Configuration
## 4. Frontend Configuration (`www.svc.plus` canonical, `console.svc.plus` secondary)
For **console.svc.plus**, ensure the following is set so it knows where to redirect for the initial OAuth step:
The frontend resolves the accounts service URL **server-side** via `getAccountServiceBaseUrl()`, which reads:
```bash
NEXT_PUBLIC_ACCOUNTS_SVC_URL=https://accounts.svc.plus
# Set in accounts.svc.plus deployment environment
ACCOUNT_SERVICE_URL=https://accounts.svc.plus
```
If not set, the function falls back to a runtime default. **No `NEXT_PUBLIC_*` env var is needed** — the OAuth login URLs are constructed server-side and passed to the client components as props.
### OAuth Login URLs (auto-generated)
| Provider | Login URL |
|---|---|
| GitHub | `{accountServiceBaseUrl}/api/auth/oauth/login/github` |
| Google | `{accountServiceBaseUrl}/api/auth/oauth/login/google` |
### OAuth Callback URLs (handled by accounts.svc.plus)
| Provider | Callback URL |
|---|---|
| GitHub | `https://accounts.svc.plus/api/auth/oauth/callback/github` |
| Google | `https://accounts.svc.plus/api/auth/oauth/callback/google` |
---
## 5. Troubleshooting
### `undefined/api/auth/oauth/login/github`
**Cause**: OAuth URLs were using a client-side env var (`NEXT_PUBLIC_ACCOUNTS_SVC_URL`) that was not set.
**Fix** (applied in commit `4ce4147`): OAuth URLs now use the server-resolved `accountServiceBaseUrl` prop.
### OAuth login redirects to wrong domain
Check that `OAUTH_FRONTEND_URL` in accounts.svc.plus matches the canonical public domain where users should be redirected after authentication. The current default is `https://www.svc.plus`.
### Google "Access blocked: This app's request is invalid"
Ensure the **Authorized redirect URI** in Google Cloud Console **exactly** matches:
```
https://accounts.svc.plus/api/auth/oauth/callback/google
```
Trailing slashes or mismatched protocols will cause this error.
### GitHub "The redirect_uri MUST match the registered callback URL"
Ensure the **Authorization callback URL** in GitHub Developer Settings **exactly** matches:
```
https://accounts.svc.plus/api/auth/oauth/callback/github
```
### Google OAuth in "Testing" mode — only test users can sign in
Go to **OAuth consent screen > Publishing status** and click **"Publish App"** to allow any Google user to sign in.
---
## 6. Quick Reference
| Item | Value |
|---|---|
| GitHub OAuth App Settings | https://github.com/settings/developers |
| Google Cloud Credentials | https://console.cloud.google.com/apis/credentials |
| GitHub Callback URL | `https://accounts.svc.plus/api/auth/oauth/callback/github` |
| Google Callback URL | `https://accounts.svc.plus/api/auth/oauth/callback/google` |
| Backend Config File | `accounts.svc.plus/config/account.yaml` |
| Frontend URL Resolution | `getAccountServiceBaseUrl()` in `src/server/serviceConfig.ts` |

View File

@ -0,0 +1,51 @@
# Stripe Billing Integration
This console now routes all purchase entry points through Stripe:
- `/prices`
- product detail pages
- `/panel/subscription`
The browser only needs public Stripe `price_id` values. Secret keys stay in `accounts.svc.plus`.
## Required Environment Variables
Set these in `console.svc.plus`:
```bash
NEXT_PUBLIC_STRIPE_PRICE_XSTREAM_PAYGO=price_xxx
NEXT_PUBLIC_STRIPE_PRICE_XSTREAM_SUBSCRIPTION=price_xxx
NEXT_PUBLIC_STRIPE_PRICE_XSCOPEHUB_PAYGO=price_xxx
NEXT_PUBLIC_STRIPE_PRICE_XSCOPEHUB_SUBSCRIPTION=price_xxx
NEXT_PUBLIC_STRIPE_PRICE_XCLOUDFLOW_PAYGO=price_xxx
NEXT_PUBLIC_STRIPE_PRICE_XCLOUDFLOW_SUBSCRIPTION=price_xxx
```
If a value is missing, the related purchase button stays visible but reports that Stripe pricing is not configured.
## Local Integration Checklist
1. Configure all `NEXT_PUBLIC_STRIPE_PRICE_*` values with Stripe test-mode `price_...` ids.
2. Start `accounts.svc.plus` with Stripe server-side settings.
3. Start this console with `yarn dev`.
4. Sign in with a normal user account.
5. Open `/prices` or `/panel/subscription` and start checkout.
6. Complete a Stripe test payment.
7. Confirm the browser returns to `/panel/subscription?checkout=success...`.
8. Confirm the subscription record appears in the subscription panel.
9. Open "Manage Stripe billing" and confirm the customer portal opens.
## Expected Flow
1. The console calls `/api/auth/stripe/checkout`.
2. The BFF proxies the request to `accounts.svc.plus` using the current account session.
3. `accounts.svc.plus` creates the Stripe Checkout Session.
4. Stripe redirects back to the console.
5. Stripe webhooks update the account service subscription record.
6. The console reads the final state from `/api/auth/subscriptions`.
## Notes
- The console does not store Stripe secret keys.
- Sensitive payment methods such as crypto QR flows are intentionally removed from the purchase UI.
- Use Stripe test mode first; do not validate this flow against live prices until webhook delivery is confirmed.

View File

@ -16,7 +16,7 @@
- **区域**: asia-northeast1
- **项目 ID**: xzerolab-480008
- **服务 URL**: https://rag-server-svc-plus-266500572462.asia-northeast1.run.app
- **代码仓库**: https://github.com/cloud-neutral-toolkit/rag-server.svc.plus
- **代码仓库**: https://github.com/x-evor/rag-server.svc.plus
### 服务功能
RAG (Retrieval-Augmented Generation) 服务器提供以下功能:
@ -68,7 +68,7 @@ rag-server.svc.plus/
#### 1. 代码变更
```bash
# 克隆仓库
git clone https://github.com/cloud-neutral-toolkit/rag-server.svc.plus.git
git clone https://github.com/x-evor/rag-server.svc.plus.git
cd rag-server.svc.plus
# 创建功能分支
@ -407,7 +407,7 @@ gcloud run services update rag-server-svc-plus \
- **紧急联系**: [电话]
### 相关链接
- **GitHub**: https://github.com/cloud-neutral-toolkit/rag-server.svc.plus
- **GitHub**: https://github.com/x-evor/rag-server.svc.plus
- **Cloud Console**: https://console.cloud.google.com/run/detail/asia-northeast1/rag-server-svc-plus
- **监控面板**: [Monitoring Dashboard URL]
- **文档**: [Documentation URL]

View File

@ -0,0 +1,281 @@
# Console Frontend Single-Node Deployment Design
## Scope
- Repository: `console.svc.plus`
- Target host: `root@cn-console.svc.plus`
- Public domains:
- `cn-console.svc.plus`
- `cn-console.onwalk.net`
- Delivery mode: `GitHub Actions + GHCR + Caddy + Docker Compose`
This document defines the deployment baseline for the China-facing frontend node. The source of truth is this upstream repository. The control-plane repository may consume the repo through git submodule, but should not become the primary place where this deployment design lives.
## Objective
Provide an independent frontend deployment pipeline for `console.svc.plus` that fits the current host constraints:
- the host IO is weak
- the host must not build Docker images locally
- the frontend should run in a static-first mode where possible
- deployment logic should stay in checked-in scripts, not be embedded in GitHub Actions YAML
The result should support repeatable releases, quick rollback by image tag, and minimal work on the target machine.
## Constraints
### Host constraints
- `cn-console.svc.plus` is a single-node host
- deployment user is `root`
- local image build on the host is explicitly disallowed
- IO pressure should be minimized during release
### Application constraints
- `console.svc.plus` is not a purely static site
- auth routes, same-origin API proxy routes, and selected dynamic pages still require a running Next.js server
- some `NEXT_PUBLIC_*` variables are compiled into the frontend bundle at image build time
- `prebuild` pulls documentation and `knowledge` content, so CI must prepare those inputs before building the image
### Repository constraints
- workflow YAML should remain orchestration-only
- service-local operational notes should remain in this repo
- downstream control repos can reference this repo through submodule updates after upstream changes are pushed
## Recommended Topology
### 1. CI build on GitHub Actions
The workflow builds a single `linux/amd64` image in GitHub Actions and pushes it to GHCR.
Reasons:
- matches the target host architecture
- avoids multi-arch overhead for this single-node release path
- avoids local host build IO and CPU pressure
- keeps release artifacts immutable and rollback-friendly
### 2. Runtime on the host
Use `docker compose` with three services:
- `dashboard`: Next.js standalone runtime
- `frontend-assets`: one-shot container that copies static files from the image into a Docker volume
- `caddy`: TLS termination, redirect handling, static file serving, and reverse proxy
This keeps the host work limited to:
- image pull
- asset extraction from the image
- container restart
### 3. Static-first request flow
Caddy serves:
- `/_next/static/*`
- checked-in `public/` assets
Next.js serves:
- HTML responses
- `/api/*` routes
- auth/session flows
- dynamic pages that still depend on server runtime
This reduces repeat disk reads and network hops for the bulk of frontend traffic while preserving the dynamic behavior the app still needs.
## Build-Time vs Runtime Configuration
### Build-time config
These values must be available during Docker build because the frontend bundle reads them directly:
- `NEXT_PUBLIC_APP_BASE_URL`
- `NEXT_PUBLIC_SITE_URL`
- `NEXT_PUBLIC_LOGIN_URL`
- `NEXT_PUBLIC_DOCS_BASE_URL`
- `NEXT_PUBLIC_RUNTIME_ENVIRONMENT`
- `NEXT_PUBLIC_RUNTIME_REGION`
- `NEXT_PUBLIC_GISCUS_*`
- `NEXT_PUBLIC_PAYPAL_CLIENT_ID`
- `NEXT_PUBLIC_STRIPE_*`
These are injected in GitHub Actions as Docker build args.
### Runtime config
These values are rendered into `.env.runtime` and copied to the host:
- upstream service URLs such as `ACCOUNT_SERVICE_URL`
- tokens used only on the server side
- Cloudflare analytics credentials
- internal service token
- runtime hostname hints
This separation avoids rebuilding for purely server-side secret or endpoint changes when the public frontend bundle does not change.
## Knowledge and Docs Handling
Current decision:
- `knowledge/` is cloned during CI
- the cloned content is included in the image build context
- the built image contains the resulting content needed by the current frontend
Reason:
- `prebuild` depends on this material
- the host should not fetch or generate content during deployment
Temporary nature:
- today the frontend still carries docs-related payload
- later, when `docs.svc.plus` becomes an API/service, docs delivery should move out of the frontend image
- that future change should reduce image size and simplify the runtime responsibilities of `console.svc.plus`
## Domain Handling
Primary domain:
- `cn-console.svc.plus`
Secondary domain:
- `cn-console.onwalk.net`
Current routing decision:
- Caddy accepts both domains
- requests for `cn-console.onwalk.net` are redirected permanently to `cn-console.svc.plus`
Reason:
- avoid duplicate canonical origins
- keep cookie and login behavior centered on one primary host
- simplify SEO and observability interpretation
## Release Workflow
### Trigger
Independent workflow:
- `.github/workflows/service_release_frontend-deploy.yml`
### Steps
1. check out repository
2. clone `knowledge`
3. build and push `ghcr.io/<owner>/dashboard:<tag>`
4. render `.env.runtime`
5. upload compose/caddy/env files to the host
6. log in to GHCR on the host
7. pull the new image
8. run `frontend-assets`
9. start or refresh `dashboard` and `caddy`
10. verify both domains
### Why separate from the existing image workflow
The existing image workflow is broader and oriented toward generic image publishing. This single-node frontend workflow needs tighter control over:
- build-time public env injection
- production deployment sequencing
- SSH-based single-host rollout
- host-specific runtime file rendering
So the frontend release path should remain explicit and independent.
## Rollback Model
Rollback unit:
- image tag reference in `.env.runtime`
Rollback steps:
1. set `FRONTEND_IMAGE` to a previous known-good tag
2. rerun `frontend-assets`
3. restart `dashboard` and `caddy`
4. verify `cn-console.svc.plus`
This avoids rebuilding and keeps rollback cheap on the weak-IO host.
## Security and Secret Handling
Secrets must not be committed to the repo. The workflow should consume:
- `SINGLE_NODE_VPS_SSH_PRIVATE_KEY`
- service tokens
- vault tokens
- internal service token
- optional Cloudflare credentials
Public defaults and non-secret values belong in checked-in examples or GitHub repository/environment variables. Secret-only values stay in GitHub Secrets and are rendered into the host runtime env during deployment.
## Operational Risks
### Risk 1: build-time public env mismatch
If GitHub environment variables are incomplete, the image may build successfully but the frontend can render wrong links or lose third-party integration IDs.
Mitigation:
- keep `.env.example` aligned
- document required GitHub `vars`
- keep the build args list explicit
### Risk 2: image layout drift
If the Docker image no longer contains `/app/dashboard/static` or `/app/dashboard/public`, the `frontend-assets` step fails.
Mitigation:
- keep asset extraction paths documented
- update deploy scripts whenever Dockerfile output layout changes
### Risk 3: docs payload growth
Bundling docs and `knowledge` into the frontend image increases image size.
Mitigation:
- accept it temporarily
- revisit once `docs.svc.plus` is externalized
### Risk 4: single-node blast radius
The host handles both reverse proxy and app runtime. Misconfiguration affects the whole frontend surface.
Mitigation:
- keep compose simple
- keep Caddy config minimal
- use image-tag rollback
## Future Follow-Up
### Near term
- populate required GitHub `vars` and `secrets`
- run the workflow against `root@cn-console.svc.plus`
- validate DNS, TLS, static assets, login flow, and upstream API proxy behavior
### Later
- move docs delivery out of the frontend image after `docs.svc.plus` is service/API based
- consider splitting static assets to object storage or CDN if traffic grows
- evaluate whether the host should keep only Caddy plus one app container, or whether docs can be removed entirely from this runtime
## Source of Truth Rule
For this deployment design:
- upstream repo source of truth: `console.svc.plus`
- service-local design note location: `docs/plans/`
- control-plane repo role: consume via git submodule after upstream commit is pushed
Do not move the primary design ownership to the control-plane repository.

5
docs/plans/README.md Normal file
View File

@ -0,0 +1,5 @@
# Plans
This directory stores service-local design notes and implementation plans for `console.svc.plus`.
The source of truth stays in this upstream repository. Control-plane repositories may reference these documents through git submodule updates after upstream changes are pushed.

View File

@ -0,0 +1,218 @@
# UI 主题与风格重构方案
作为资深 Web UI 设计师和前端工程师,针对我们 SaaS 控制台当前的 Next.js + Tailwind CSS 架构,结合 WCAG 可访问性标准和跨端响应式需求,特制定此 UI 重构方案。方案旨在提升整体视觉一致性、深色模式的可访问性,并优化桌面与移动端的用户体验(特别是 iOS/Android 浏览器的触控和渲染差异)。
---
## 1. 审查现有界面
在审查当前的界面代码(如 `tailwind.config.js`, `src/app/globals.css`, `src/components/theme/``Navbar.tsx`)后,我发现了以下改进点:
* **色彩硬编码与对比度**:在部分文件(如 `designTokens.ts``Navbar.tsx` 的内联类名)中仍然存在类似 `#3467e9`, `bg-[#f6f7f9]` 的硬编码颜色,这破坏了主题切换的完整性。同时,深色模式下的次级文本(如 `text-muted` `#cbd5f5`)在深色背景(`#0f172a`)上的对比度可能无法满足 WCAG AA 级 4.5:1 的标准。
* **语义化不足**`Navbar.tsx` 中的菜单项过度使用了 `<div>` 和普通的 `<a>` 标签,缺少 `<nav>`, `<ul>`, `<li>` 结构,并且缺乏管理下拉/折叠状态的 `aria-expanded` 属性。
* **触控目标尺寸**:移动端的某些交互元素(如链接和图标按钮)没有保证至少 44px × 44px 的物理点击区域,这在 iOS/Android 设备上容易造成误触。
* **深色模式层级**:深色模式主要依赖背景色区分层级(如 `surface-muted`缺乏细微的边框Border或发光阴影Glow/Shadow来凸显浮动面板如 Dropdown 菜单)。
---
## 2. 定义设计系统 Token
我们需要收敛硬编码颜色,改用语义化的 CSS 变量Token并对深/浅色模式设定严格的对比度要求。
### 颜色 Token 规划
* **背景色**
* 浅色:纯白 `#ffffff` (Surface) 或极浅灰 `#f8fafc` (Background)。
* 深色:避免纯黑,使用 `#0f172a` (Background) 和微亮的暗灰 `#1e293b` (Surface),减轻视觉疲劳。
* **文本色**
* 主要文本 (`--color-text`):浅色模式 `#0f172a`,深色模式 `#f8fafc`
* 次要文本 (`--color-text-muted`):确保在深浅背景下对比度均大于 4.5:1。浅色推荐 `#475569`,深色推荐 `#94a3b8`
* **主色与交互色**
* `--color-primary`:统一使用高对比度的主题蓝(如 `#2563eb`),确保按钮上的白色文字(`--color-primary-foreground`)对比度达标。
### Tailwind / CSS 变量伪代码
```css
/* src/app/globals.css 补充与覆盖 */
:root {
/* 基础结构色 */
--bg-color: #f8fafc;
--surface-color: #ffffff;
/* 文本色 */
--text-color: #0f172a;
--secondary-color: #475569;
/* 主色调 */
--primary: #2563eb;
--primary-foreground: #ffffff;
/* 边框与分隔线 */
--border-color: #e2e8f0;
}
:root[data-theme="dark"],
.dark {
--bg-color: #0f172a;
--surface-color: #1e293b;
--text-color: #f8fafc;
--secondary-color: #94a3b8; /* 保证对比度 > 4.5:1 */
--primary: #3b82f6; /* 在深色背景下稍微提亮主色 */
--primary-foreground: #ffffff;
--border-color: #334155;
/* 深色模式下的特殊视觉补偿 */
--shadow-elevation: 0 4px 6px -1px rgba(0, 0, 0, 0.5), 0 2px 4px -2px rgba(0, 0, 0, 0.5);
}
```
---
## 3. 设计排版体系
排版需兼顾多语言(中英文混合)和多端阅读体验。
* **字体选择**:保留现有的 `Geist`,同时后备配置 `Inter``Noto Sans SC` 以优化中文显示:
`font-family: var(--font-geist-sans), 'Inter', 'Noto Sans SC', sans-serif;`
* **字号范围 (Fluid Typography / 断点响应)**
* **移动端**:基础字号 16px防止 iOS Safari 输入框自动缩放),正文 `16px - 18px`,大标题约 `24px - 28px`
* **桌面端**:正文 `16px - 20px`,大标题可达 `32px - 48px`
* **行高与间距**:正文行高 `1.5``1.6`150%-160%),段落间距使用 `margin-bottom: 1.5em`。标题行高缩紧至 `1.2`
---
## 4. 构建全局样式与主题切换
当前系统已通过 Zustand (`store.ts`) 和 `ThemeProvider.tsx` 实现了基于 `localStorage``data-theme` 的切换。
* **优化防闪烁 (FOUC)**:由于在 Next.js 中客户端 Hydration 会有延迟,需要确保在 `<head>` 中注入一个同步脚本读取 `localStorage``prefers-color-scheme`,在 React 渲染前就应用 `dark` 类或 `data-theme`
* **深色模式下的层级分离**避免仅仅改变背景色。对于弹窗、Dropdown 等元素,在深色模式下增加一个极细的亮色边框:
```css
.dark .surface-elevated {
border: 1px solid rgba(255,255,255,0.1);
box-shadow: var(--shadow-elevation);
}
```
---
## 5. 响应式布局策略
* **断点定义**
* 移动端:`< 768px` (Tailwind 默认 `md` 以下)。
* 平板/桌面端:`>= 768px` (`md` 及以上)。
* **移动端 (iOS/Android) 策略**
* 隐藏复杂的侧边栏Sidebar顶部导航精简为 Logo 和汉堡菜单。
* 所有的按钮 (`button`, `a`) 必须拥有至少 `min-h-[44px] min-w-[44px]` 的触控区域(可以使用 padding 撑开)。
* **桌面端策略**
* 最大化利用横向空间,采用 Sidebar + Main Content 或全宽 Header 的多列布局。
---
## 6. 重构导航菜单 (示例)
当前 `Navbar.tsx` 使用了平铺的链接。我们需要使用语义化标签,并通过 `aria-expanded` 增强可访问性,并分离移动端的汉堡菜单和桌面端菜单。
### 菜单组件伪代码
```tsx
'use client'
import { useState } from 'react';
export default function SemanticNavbar() {
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
return (
<header className="sticky top-0 z-50 w-full bg-surface border-b border-border">
<nav className="max-w-7xl mx-auto px-4 min-h-[64px] flex items-center justify-between" aria-label="Main Navigation">
{/* Logo */}
<div className="flex-shrink-0">
<a href="/" className="font-bold text-text-color text-lg flex items-center min-h-[44px]">Logo</a>
</div>
{/* Desktop Menu */}
<ul className="hidden md:flex items-center gap-6">
<li>
<a href="/dashboard" className="text-secondary-color hover:text-text-color transition-colors py-2">
控制台
</a>
</li>
<li className="relative group">
{/* 父菜单如果是功能性展开按钮,使用 button */}
<button
aria-expanded={isDropdownOpen}
aria-controls="services-dropdown"
onClick={() => setIsDropdownOpen(!isDropdownOpen)}
className="flex items-center gap-1 text-secondary-color hover:text-text-color py-2"
>
服务 <ChevronDownIcon />
</button>
{/* Dropdown 弹窗 */}
<ul
id="services-dropdown"
className={`absolute top-full left-0 mt-2 w-48 bg-surface-elevated border border-border rounded-md shadow-md ${isDropdownOpen ? 'block' : 'hidden'}`}
>
<li>
{/* 保证键盘 Tab 键能聚焦到这里 */}
<a href="/service/1" className="block px-4 py-3 text-text-color hover:bg-surface-hover">服务一</a>
</li>
</ul>
</li>
</ul>
{/* Mobile Hamburger Button */}
<div className="md:hidden">
<button
aria-controls="mobile-menu"
aria-expanded={isMobileMenuOpen}
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
className="p-2 min-w-[44px] min-h-[44px] text-text-color"
aria-label="Toggle navigation"
>
<HamburgerIcon />
</button>
</div>
</nav>
{/* Mobile Menu Panel */}
<div
id="mobile-menu"
className={`md:hidden overflow-hidden transition-[max-height] duration-300 ease-in-out ${isMobileMenuOpen ? 'max-h-screen' : 'max-h-0'}`}
>
<ul className="px-4 pb-4 space-y-2 bg-surface">
<li>
<a href="/dashboard" className="block py-3 text-text-color">控制台</a>
</li>
{/* 移动端子菜单可以直接平铺或使用手风琴折叠 */}
<li>
<span className="block py-3 text-secondary-color font-semibold">服务</span>
<ul className="pl-4 space-y-2 border-l-2 border-border ml-2">
<li><a href="/service/1" className="block py-3 text-text-color">服务一</a></li>
</ul>
</li>
</ul>
</div>
</header>
);
}
```
---
## 7. 针对移动端和桌面端的优化差异
* **iOS/Android 浏览器差异处理**
* **iOS Safari 底部安全区**:在主内容区底部增加 `padding-bottom: env(safe-area-inset-bottom);`,避免按钮被 Home Indicator 遮挡。
* **字体抗锯齿 (Anti-aliasing)**:在 `globals.css` 中的 `body` 标签已设置 `-webkit-font-smoothing: antialiased;`,在深色模式下这能让细小的亮色文字边缘更加平滑,没有晕影。
* **长文本限制**:在博客或文档页面,容器设置 `max-w-prose` (相当于 `max-width: 65ch`),确保每行不超过 60 个字符,提升阅读体验。
* **桌面端强化**
* 可利用 Hover 状态提供丰富的反馈(如背景变色、细微的 `transform: translateY(-1px)`)。
* 在宽屏上显示侧边栏和次要信息列(多列网格布局)。
---
## 8. 可访问性测试与迭代流程
为确保重构后的界面符合标准,开发团队应在提交代码前进行以下检查:
1. **对比度扫描**:使用 Chrome DevTools 的 Lighthouse 或 WebAIM 对比度检查器,确保所有的正文/背景对比度 >= 4.5:1大号文本 >= 3.0:1。
2. **重排与缩放测试**:使用浏览器的缩放功能放大页面到 `200%``400%`。确保在 `400%` 下页面自动转为单列移动端布局,且文字不出现截断或相互重叠(开启 CSS 文本重排 `text-wrap: balance` 或避免固定高度)。
3. **键盘导航测试**:不使用鼠标,仅用 `Tab``Enter` 遍历界面。确保所有交互元素有明显的 `:focus-visible` 外框线Tailwind `focus-visible:ring-2 focus-visible:ring-primary`)。二级菜单不能在 Tab 聚焦到父元素时自动弹出(除非是用按钮触发),以避免用户被迫穿过无数个子菜单才能到达下一个主栏目。
4. **屏幕阅读器体验**:开启 VoiceOver (Mac/iOS) 或 TalkBack (Android),验证 `aria-expanded`, `aria-controls` 等状态是否能被正确播报。

View File

@ -1,9 +1,154 @@
# Deployment
# Deployment Runbook
## Purpose
## Scope
- TODO: Add content specific to Deployment.
- Runtime: `console.svc.plus`
- Topology: `Caddy + Docker Compose + GitHub Actions`
- Deploy host: `root@jp-xhttp-contabo.svc.plus`
- Public domains:
- `https://www.svc.plus`
- `https://console.svc.plus`
- Canonical public origin: `https://www.svc.plus`
## Notes
## Current Delivery Model
- TODO: Link to related documents in this section.
The production frontend is deployed as a prebuilt container image from GitHub Actions.
- The target host does not build images locally.
- The workflow builds an `linux/amd64` image and pushes it to `ghcr.io/<owner>/dashboard:<sha>`.
- The host only performs `docker login`, `docker compose pull`, static asset extraction, and `docker compose up`.
- `/docs` and `/blogs` fetch their content from `docs.svc.plus` at runtime; the frontend image no longer packs `knowledge/` or synced markdown payloads.
- Static assets are extracted from the image into a shared Docker volume so Caddy can serve `/_next/static/*` and checked-in public files directly.
This is intentionally static-first for the current weak-IO single-node host. Dynamic HTML, auth routes, and API proxy routes still run through the Next.js container, but docs/blog content delivery is now delegated to `docs.svc.plus`.
## Control Plane & DNS Stage
The control repo (`github-org-x-evor`) tracks `console.svc.plus` through `console.svc.plus.code-workspace` and keeps the `subrepos/accounts.svc.plus` pointer in sync via `skills/cross-repo-upstream-submodule-sync`. Releases resolve metadata with that workspace and the `config/single-node-release` manifests. After `.github/workflows/pipeline.yaml` finishes pushing the new image, the control-plane DNS automation calls `scripts/github-actions/update-release-dns.sh` to update Cloudflare DNS so the new endpoint is reachable through the current production host `jp-xhttp-contabo.svc.plus`.
## Runtime Layout
Remote directory:
```bash
/opt/console-svc-plus
```
Files deployed there:
```bash
docker-compose.yml
Caddyfile
.env.runtime
```
Containers:
- `dashboard`: Next.js standalone runtime on port `3000`
- `frontend-assets`: one-shot task that copies `static/` and `public/` into a shared volume
- `caddy`: TLS termination and reverse proxy
## GitHub Actions Inputs
Workflow:
```text
.github/workflows/pipeline.yaml
```
Secrets required:
- `SINGLE_NODE_VPS_SSH_PRIVATE_KEY`
- `OPENCLAW_GATEWAY_TOKEN` if used
- `VAULT_TOKEN` if used
- `AI_GATEWAY_ACCESS_TOKEN` if used
- `INTERNAL_SERVICE_TOKEN` if used
- `CLOUDFLARE_DNS_API_TOKEN` for the Cloudflare DNS stage
- `CLOUDFLARE_API_TOKEN` if homepage Cloudflare analytics are enabled at runtime
Repository/environment variables recommended:
- `CANONICAL_DOMAIN`
- `SERVED_DOMAINS`
- `APP_BASE_URL`
- `NEXT_PUBLIC_APP_BASE_URL`
- `NEXT_PUBLIC_SITE_URL`
- `NEXT_PUBLIC_LOGIN_URL`
- `NEXT_PUBLIC_DOCS_BASE_URL`
- `ACCOUNT_SERVICE_URL`
- `NEXT_PUBLIC_ACCOUNT_SERVICE_URL`
- `SERVER_SERVICE_URL`
- `NEXT_PUBLIC_SERVER_SERVICE_URL`
- `RUNTIME_HOSTNAME`
- `DEPLOYMENT_HOSTNAME`
- `DOCS_SERVICE_URL`
- `DOCS_SERVICE_INTERNAL_URL`
- `NEXT_PUBLIC_RUNTIME_ENVIRONMENT`
- `NEXT_PUBLIC_RUNTIME_REGION`
- `NEXT_PUBLIC_GISCUS_*`
- `NEXT_PUBLIC_STRIPE_*`
- `NEXT_PUBLIC_PAYPAL_CLIENT_ID`
- `CLOUDFLARE_ZONE_TAG` if homepage Cloudflare analytics are enabled at runtime
- `CLOUDFLARE_DNS_ZONE_TAG` only for single-domain manual DNS override; the GitHub Actions DNS stage resolves zones from each domain automatically
## Release Flow
1. GitHub Actions checks out the repo.
2. Docker builds the frontend image with the public `NEXT_PUBLIC_*` values needed at build time.
3. The image is pushed to GHCR.
4. The workflow updates Cloudflare DNS for the release domain.
5. The workflow renders `.env.runtime`, including the canonical public origin and both served frontend domains.
6. The workflow uploads `docker-compose.yml`, `Caddyfile`, and `.env.runtime` to the host.
7. The host pulls the new image, refreshes the static asset volume, and starts `dashboard + caddy`.
8. The workflow verifies both `www.svc.plus` and `console.svc.plus`, and fails the release if either domain serves a different runtime version.
## Verification Commands
Local syntax checks:
```bash
cd /Users/shenlan/workspaces/cloud-neutral-toolkit/console.svc.plus
bash -n scripts/github-actions/render-frontend-runtime-env.sh
bash -n scripts/github-actions/deploy-frontend-single-node.sh
cp deploy/single-node/.env.runtime.example deploy/single-node/.env.runtime
docker compose -f deploy/single-node/docker-compose.yml --env-file deploy/single-node/.env.runtime config >/tmp/console-compose.rendered.yaml
rm -f deploy/single-node/.env.runtime
python3 - <<'PY'
from pathlib import Path
import yaml
yaml.safe_load(Path('.github/workflows/pipeline.yaml').read_text())
print('workflow yaml ok')
PY
```
Remote checks:
```bash
ssh root@jp-xhttp-contabo.svc.plus "cd /opt/console-svc-plus && docker compose --env-file .env.runtime ps"
ssh root@jp-xhttp-contabo.svc.plus "curl -fsSI -H 'Host: www.svc.plus' http://127.0.0.1/"
ssh root@jp-xhttp-contabo.svc.plus "curl -fsSI -H 'Host: console.svc.plus' http://127.0.0.1/"
curl -fsSIL https://www.svc.plus
curl -fsSIL https://console.svc.plus
```
## Failure Signatures
- `docker login ghcr.io` fails
The workflow token or package visibility is wrong.
- `frontend-assets` fails
The image layout changed and no longer contains `/app/dashboard/static` or `/app/dashboard/public`.
- `www.svc.plus` or `console.svc.plus` returns `502`
Caddy is up, but the `dashboard` container failed or is not reachable on port `3000`.
## Rollback
1. Re-run the workflow with a previous known-good image tag.
2. Or update `/opt/console-svc-plus/.env.runtime` and set `FRONTEND_IMAGE=ghcr.io/<owner>/dashboard:<previous-tag>`.
3. Restart the services:
```bash
ssh root@jp-xhttp-contabo.svc.plus "cd /opt/console-svc-plus && docker compose --env-file .env.runtime run --rm frontend-assets"
ssh root@jp-xhttp-contabo.svc.plus "cd /opt/console-svc-plus && docker compose --env-file .env.runtime up -d dashboard caddy"
```
4. Verify `https://www.svc.plus` and `https://console.svc.plus` again before closing the incident.

34
docs/zh/README.md Normal file
View File

@ -0,0 +1,34 @@
# 控制台服务 文档
该仓库以 Web 前端体验为主,文档需要覆盖产品流程、界面边界与集成触点。
## 当前状态快照
- 根 README 标题: `console.svc.plus`
- 构建与运行时证据: package.json (`dashboard`)
- 自动识别的主要目录: `src/`, `scripts/`, `tests/`, `config/`, `public/`
- 现有文档数量: 86
## 核心双语文档
- [架构](architecture.md)
- [设计](design.md)
- [部署](deployment.md)
- [使用手册](user-guide.md)
- [开发手册](developer-guide.md)
- [Vibe Coding 参考](vibe-coding-reference.md)
## 待归并的历史文档
- `SEO-AUDIT-REPORT.md`
- `SEO-WORK-SUMMARY.md`
- `advanced/customization.md`
- `advanced/performance.md`
- `advanced/scalability.md`
- `advanced/security.md`
- `api/auth.md`
- `api/endpoints.md`
- `api/errors.md`
- `api/overview.md`
- `appendix/faq.md`
- `appendix/glossary.md`

View File

@ -0,0 +1,11 @@
# SEO Audit Report - console.svc.plus (ZH)
> English: `../SEO-AUDIT-REPORT.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

View File

@ -0,0 +1,11 @@
# SEO 优化工作总结 (ZH)
> English: `../SEO-WORK-SUMMARY.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

View File

@ -0,0 +1,11 @@
# Customization (ZH)
> English: `../../advanced/customization.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

View File

@ -0,0 +1,11 @@
# Performance (ZH)
> English: `../../advanced/performance.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

View File

@ -0,0 +1,11 @@
# Scalability (ZH)
> English: `../../advanced/scalability.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

View File

@ -0,0 +1,11 @@
# Security (ZH)
> English: `../../advanced/security.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

11
docs/zh/api/auth.md Normal file
View File

@ -0,0 +1,11 @@
# Auth (ZH)
> English: `../../api/auth.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

11
docs/zh/api/endpoints.md Normal file
View File

@ -0,0 +1,11 @@
# Endpoints (ZH)
> English: `../../api/endpoints.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

11
docs/zh/api/errors.md Normal file
View File

@ -0,0 +1,11 @@
# Errors (ZH)
> English: `../../api/errors.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

11
docs/zh/api/overview.md Normal file
View File

@ -0,0 +1,11 @@
# Overview (ZH)
> English: `../../api/overview.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

11
docs/zh/appendix/faq.md Normal file
View File

@ -0,0 +1,11 @@
# Faq (ZH)
> English: `../../appendix/faq.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

View File

@ -0,0 +1,11 @@
# Glossary (ZH)
> English: `../../appendix/glossary.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

View File

@ -0,0 +1,11 @@
# References (ZH)
> English: `../../appendix/references.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

31
docs/zh/architecture.md Normal file
View File

@ -0,0 +1,31 @@
# 架构
该仓库以 Web 前端体验为主,文档需要覆盖产品流程、界面边界与集成触点。
本页作为系统边界、核心组件与仓库职责的双语总览入口。
## 与当前代码对齐的说明
- 文档目标仓库: `console.svc.plus`
- 仓库类型: `frontend`
- 构建与运行依据: package.json (`dashboard`)
- 主要实现与运维目录: `src/`, `scripts/`, `tests/`, `config/`, `public/`
- `package.json` 脚本快照: `dev`, `prebuild`, `build`, `build:static`, `start`, `lint`
## 需要继续归并的现有文档
- `api/overview.md`
- `architecture/components.md`
- `architecture/design-decisions.md`
- `architecture/overview.md`
- `architecture/roadmap.md`
- `development/code-structure.md`
- `zh/api/overview.md`
- `zh/architecture/components.md`
## 本页下一步应补充的内容
- 先描述当前已落地实现,再补充未来规划,避免只写愿景不写现状。
- 术语需要与仓库根 README、构建清单和实际目录保持一致。
- 将上方列出的历史 runbook、spec、子系统说明逐步链接并归并到本页。
- 随着目录结构、服务关系和集成依赖变化,持续同步图示与职责说明。

View File

@ -0,0 +1,11 @@
# Components (ZH)
> English: `../../architecture/components.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

View File

@ -0,0 +1,11 @@
# Documentation Page Redesign Specification (ZH)
> English: `../../architecture/design-decisions.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

View File

@ -0,0 +1,11 @@
# Overview (ZH)
> English: `../../architecture/overview.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

View File

@ -0,0 +1,11 @@
# Roadmap (ZH)
> English: `../../architecture/roadmap.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

42
docs/zh/deployment.md Normal file
View File

@ -0,0 +1,42 @@
# 部署
## 生产基线
- 运行拓扑: `Caddy + Docker Compose`
- 目标主机: `root@jp-xhttp-contabo.svc.plus`
- 域名:
- `www.svc.plus`
- `console.svc.plus`
- 公开首选域名: `www.svc.plus`
- 前端独立发布流水线: `.github/workflows/pipeline.yaml`
## 运行方式
前端镜像在 GitHub Actions 中完成构建并推送到镜像仓库,目标主机只负责拉取镜像和启动容器,不在机器上本地构建。
`yarn prebuild` 现在只生成 console 自己的营销内容工件。`/docs` 与 `/blogs` 不再把 `knowledge/` 或 Markdown 文档打进前端镜像,而是在请求时通过服务端 `docsServiceClient``docs.svc.plus` 拉取渲染后的内容。
当前方案尽量以静态模式运行:
- Caddy 直接服务 `/_next/static/*``public/` 里的静态资源,并配合 `frontend_static` 共享卷。
- Next.js standalone 容器只承接动态页面、认证接口和代理接口,`frontend-assets` 任务会把所有静态文件(包括哈希后的 CSS/JS拷贝到 `frontend_static`
- `docs.svc.plus` 是 docs/blog 的运行时内容源,浏览器不会直接访问它。
发布由 `.github/workflows/pipeline.yaml` 驱动CI 构建/推送镜像、渲染包含 `DOCS_SERVICE_URL` / `DOCS_SERVICE_INTERNAL_URL``.env.runtime`,然后将 `docker-compose.yml`、`Caddyfile` 与运行时环境文件发送到主机。随后控制平面 DNS 自动化会通过 `scripts/github-actions/update-release-dns.sh` 更新 Cloudflare DNS使当前生产主机 `jp-xhttp-contabo.svc.plus` 承载更新后的环境。
这是针对弱 IO 单机主机 `root@jp-xhttp-contabo.svc.plus` 的部署权衡:主机不会在本地构建镜像,只需登录 GHCR、拉取 `dashboard` 镜像、解包静态资源到 `frontend_static`,再通过 `docker compose` 启动 `dashboard``caddy`
`docs.svc.plus` 已经是前端 docs/blog 内容的独立服务。
当前发布合同要求:
- `CANONICAL_DOMAIN=www.svc.plus`
- `SERVED_DOMAINS=www.svc.plus,console.svc.plus`
- 流水线必须同时校验两个域名的首页静态资源与 `/api/ping` 版本元数据完全一致
- `dashboardUrl`、canonical、structured data 与 sitemap 默认统一输出 `https://www.svc.plus`
## 相关文档
- `usage/deployment.md`
- `governance/release-process.md`
- `development/dev-setup.md`

27
docs/zh/design.md Normal file
View File

@ -0,0 +1,27 @@
# 设计
该仓库以 Web 前端体验为主,文档需要覆盖产品流程、界面边界与集成触点。
本页用于汇总设计决策、类似 ADR 的权衡记录,以及与路线图相关的实现说明。
## 与当前代码对齐的说明
- 文档目标仓库: `console.svc.plus`
- 仓库类型: `frontend`
- 构建与运行依据: package.json (`dashboard`)
- 主要实现与运维目录: `src/`, `scripts/`, `tests/`, `config/`, `public/`
- `package.json` 脚本快照: `dev`, `prebuild`, `build`, `build:static`, `start`, `lint`
## 需要继续归并的现有文档
- `SEO-WORK-SUMMARY.md`
- `architecture/design-decisions.md`
- `zh/SEO-WORK-SUMMARY.md`
- `zh/architecture/design-decisions.md`
## 本页下一步应补充的内容
- 先描述当前已落地实现,再补充未来规划,避免只写愿景不写现状。
- 术语需要与仓库根 README、构建清单和实际目录保持一致。
- 将上方列出的历史 runbook、spec、子系统说明逐步链接并归并到本页。
- 当行为、API 或部署契约发生变化时,把一次性实现笔记提升为可复用设计记录。

View File

@ -0,0 +1,31 @@
# 开发手册
该仓库以 Web 前端体验为主,文档需要覆盖产品流程、界面边界与集成触点。
本页用于记录本地开发环境、项目结构、测试面与贴合当前代码库的贡献约定。
## 与当前代码对齐的说明
- 文档目标仓库: `console.svc.plus`
- 仓库类型: `frontend`
- 构建与运行依据: package.json (`dashboard`)
- 主要实现与运维目录: `src/`, `scripts/`, `tests/`, `config/`, `public/`
- `package.json` 脚本快照: `dev`, `prebuild`, `build`, `build:static`, `start`, `lint`
## 需要继续归并的现有文档
- `api/auth.md`
- `api/endpoints.md`
- `api/errors.md`
- `api/overview.md`
- `development/code-structure.md`
- `development/contributing.md`
- `development/dev-setup.md`
- `development/testing.md`
## 本页下一步应补充的内容
- 先描述当前已落地实现,再补充未来规划,避免只写愿景不写现状。
- 术语需要与仓库根 README、构建清单和实际目录保持一致。
- 将上方列出的历史 runbook、spec、子系统说明逐步链接并归并到本页。
- 持续让环境搭建与测试命令对应真实存在的脚本、Make 目标或语言工具链。

View File

@ -0,0 +1,11 @@
# Code Structure (ZH)
> English: `../../development/code-structure.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

View File

@ -0,0 +1,11 @@
# Contributing (ZH)
> English: `../../development/contributing.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

View File

@ -0,0 +1,11 @@
# Development Setup (ZH)
> English: `../../development/dev-setup.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

View File

@ -0,0 +1,11 @@
# Testing (ZH)
> English: `../../development/testing.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

View File

@ -0,0 +1,11 @@
# Concepts (ZH)
> English: `../../getting-started/concepts.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

View File

@ -0,0 +1,47 @@
# Installation (ZH)
> English: `../../getting-started/installation.md`
## 目的
- 为 `console.svc.plus` 准备本地运行环境。
- 用环境变量给 AI 助手和集成功能做默认值预填,而不是把网关配置写死在 UI 里。
## 环境准备
1. 复制示例文件:
```bash
cp .env.example .env
```
2. 如有联调环境,优先参考 `/Users/shenlan/workspaces/cloud-neutral-toolkit/openclaw-deploy-example/.env` 中对应值。
## AI 助手与集成变量
下面这些变量会由服务端读取,并用于以下场景的默认值预填:
- 首页 AI 助手
- 侧栏 AI 助手
- `/panel/api` 集成页
| 变量 | 用途 | 说明 |
|---|---|---|
| `OPENCLAW_GATEWAY_REMOTE_URL` | OpenClaw 助手 | 远端 WebSocket 地址,例如 `wss://openclaw.svc.plus:443` |
| `OPENCLAW_GATEWAY_TOKEN` | OpenClaw 助手 | 服务端桥接 OpenClaw gateway 时使用的令牌 |
| `VAULT_SERVER_URL` | Vault 集成 | Vault 服务地址,用于默认值和连通性探测 |
| `VAULT_NAMESPACE` | Vault 集成 | Vault Enterprise namespace可选 |
| `VAULT_TOKEN` | Vault 集成 | Vault 探测请求使用的令牌 |
| `APISIX_AI_GATEWAY_URL` | APISIX AI Gateway 集成 | AI gateway 的 HTTP(S) 地址 |
| `AI_GATEWAY_ACCESS_TOKEN` | APISIX AI Gateway 集成 | AI gateway 探测请求使用的访问令牌 |
## 行为说明
- 这些变量不会被硬编码进前端 React 组件。
- 页面中的输入项仍然支持会话级覆盖。
- 变量留空只会取消默认值预填,不会影响现有布局。
## 相关文档
- `../README.md`
- `../usage/config.md`

View File

@ -0,0 +1,11 @@
# Introduction (ZH)
> English: `../../getting-started/introduction.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

View File

@ -0,0 +1,11 @@
# Quickstart (ZH)
> English: `../../getting-started/quickstart.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

View File

@ -0,0 +1,11 @@
# License (ZH)
> English: `../../governance/license.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

View File

@ -0,0 +1,55 @@
# Release Process (ZH)
> English: `../../governance/release-process.md`
本页用于记录公开控制台在 `www.svc.plus``console.svc.plus` 下发布版本的说明与变更摘要。
## 当前版本
### v0.2
发布标签:`v0.2`
发布分支:`release/v0.2`
发布提交:`0fab89e`
#### 亮点
- 引入新的 XWorkmate 工作区,助手布局更紧凑,工作区外壳更统一,入口流程也更顺滑。
- 新增 OpenClaw assistant workspace 与 pairing bridge支持可配置的 origin override并改进了配对失败时的回退行为。
- 统一导航与 AI 入口,加入持久化 assistant sidebar并梳理 panel 路由。
- 首页增加最新博客快捷入口,同时优化游客模式与注册引导文案。
- 双语文档结构继续补齐OIDC 接入文档和安装说明也更完整。
- 修复构建稳定性问题,包括 `next-mdx-remote` 相关的漏洞拦截构建错误,以及 Yarn 依赖元数据对齐问题。
#### 新特性
- 上线 XWorkmate 工作区,并完善其入口与界面布局。
- 增加 OpenClaw assistant 集成、pairing bridge、integration probe API以及 integration defaults 处理能力。
- 在服务页加入 XScopeHub MCP 服务可见性。
- 首页快捷区展示最新 7 篇博客文章标题。
#### 体验改进
- 将 observability 工作区拆分为 tri-view并优化 panel 助手路由。
- 统一导航结构与持久化 AI sidebar 行为。
- 登录与注册流程改为使用服务端解析后的 account service URL。
- 体验与演示模式不得在公开 UI 或会话载荷中暴露其后端承载账号身份。
- 为集成配置增加基于 vault 的 token 查询能力。
#### 文档与安装
- 增补双语文档覆盖,并整理文档入口结构。
- 重写 OIDC 认证接入文档,补充更完整的配置说明。
- 更新安装指导并精简 README 结构。
#### 构建与依赖修复
- 对齐并升级 `next-mdx-remote` 使用方式,确保构建安全。
- 移除冲突的 npm 锁文件状态,并整理 Yarn 依赖元数据,提升构建可复现性。
## 备注
- GitHub Release`https://github.com/x-evor/console.svc.plus/releases/tag/v0.2`
- 发布校验必须同时验证 `www.svc.plus``console.svc.plus``releaseImageRef`、`releaseImageTag`、`releaseCommit` 完全一致。
- `www.svc.plus` 是 metadata、sitemap、`dashboardUrl` 与公开分享链接的首选域名。
- 相关文档:`docs/README.md`、`docs/en/README.md`、`docs/zh/README.md`

View File

@ -0,0 +1,11 @@
# Security Policy (ZH)
> English: `../../governance/security-policy.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

View File

@ -0,0 +1,11 @@
# Ai Providers (ZH)
> English: `../../integrations/ai-providers.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

View File

@ -0,0 +1,11 @@
# Cloud (ZH)
> English: `../../integrations/cloud.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

View File

@ -0,0 +1,11 @@
# Cloudflare Web Analytics 集成配置 (ZH)
> English: `../../integrations/cloudflare-web-analytics.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

View File

@ -0,0 +1,11 @@
# Databases (ZH)
> English: `../../integrations/databases.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

View File

@ -0,0 +1,11 @@
# OIDC Authentication Configuration Guide (ZH)
> English: `../../integrations/oidc-auth.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

View File

@ -0,0 +1,11 @@
# Backup (ZH)
> English: `../../operations/backup.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

View File

@ -0,0 +1,11 @@
# Logging (ZH)
> English: `../../operations/logging.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

View File

@ -0,0 +1,11 @@
# Monitoring (ZH)
> English: `../../operations/monitoring.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

View File

@ -0,0 +1,11 @@
# Runbooks (ZH)
> English: `../../../operations/runbooks/README.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

View File

@ -0,0 +1,11 @@
# Cloud-Neutral Toolkit - RAG Server Runbook (ZH)
> English: `../../../operations/runbooks/rag-server.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

View File

@ -0,0 +1,11 @@
# Troubleshooting (ZH)
> English: `../../operations/troubleshooting.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

11
docs/zh/usage/cli.md Normal file
View File

@ -0,0 +1,11 @@
# Cli (ZH)
> English: `../../usage/cli.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

11
docs/zh/usage/config.md Normal file
View File

@ -0,0 +1,11 @@
# 📊 配置文件系统汇总报告 (ZH)
> English: `../../usage/config.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

View File

@ -0,0 +1,11 @@
# Deployment (ZH)
> English: `../../usage/deployment.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

11
docs/zh/usage/examples.md Normal file
View File

@ -0,0 +1,11 @@
# Examples (ZH)
> English: `../../usage/examples.md`
## 目的
- TODO: 补充中文内容。
## 备注
- TODO: 链接到本章节相关文档。

31
docs/zh/user-guide.md Normal file
View File

@ -0,0 +1,31 @@
# 使用手册
该仓库以 Web 前端体验为主,文档需要覆盖产品流程、界面边界与集成触点。
本页用于记录主要用户或运维角色的日常任务、常见流程,以及现有操作文档入口。
## 与当前代码对齐的说明
- 文档目标仓库: `console.svc.plus`
- 仓库类型: `frontend`
- 构建与运行依据: package.json (`dashboard`)
- 主要实现与运维目录: `src/`, `scripts/`, `tests/`, `config/`, `public/`
- `package.json` 脚本快照: `dev`, `prebuild`, `build`, `build:static`, `start`, `lint`
## 需要继续归并的现有文档
- `api/overview.md`
- `architecture/overview.md`
- `getting-started/concepts.md`
- `getting-started/installation.md`
- `getting-started/introduction.md`
- `getting-started/quickstart.md`
- `usage/cli.md`
- `usage/config.md`
## 本页下一步应补充的内容
- 先描述当前已落地实现,再补充未来规划,避免只写愿景不写现状。
- 术语需要与仓库根 README、构建清单和实际目录保持一致。
- 将上方列出的历史 runbook、spec、子系统说明逐步链接并归并到本页。
- 优先提供面向流程的示例,并确保截图或终端片段与最新 UI/CLI 行为一致。

View File

@ -0,0 +1,31 @@
# Vibe Coding 参考
该仓库以 Web 前端体验为主,文档需要覆盖产品流程、界面边界与集成触点。
本页用于统一 AI 辅助开发提示词、仓库边界、安全编辑规则与文档同步要求。
## 与当前代码对齐的说明
- 文档目标仓库: `console.svc.plus`
- 仓库类型: `frontend`
- 构建与运行依据: package.json (`dashboard`)
- 主要实现与运维目录: `src/`, `scripts/`, `tests/`, `config/`, `public/`
- `package.json` 脚本快照: `dev`, `prebuild`, `build`, `build:static`, `start`, `lint`
## 需要继续归并的现有文档
- `api/auth.md`
- `api/endpoints.md`
- `api/errors.md`
- `api/overview.md`
- `zh/api/auth.md`
- `zh/api/endpoints.md`
- `zh/api/errors.md`
- `zh/api/overview.md`
## 本页下一步应补充的内容
- 先描述当前已落地实现,再补充未来规划,避免只写愿景不写现状。
- 术语需要与仓库根 README、构建清单和实际目录保持一致。
- 将上方列出的历史 runbook、spec、子系统说明逐步链接并归并到本页。
- 当项目新增子系统、受保护目录或强制验证步骤时,同步更新提示模板与仓库规则。

Some files were not shown because too many files have changed in this diff Show More