docs: introduce project and keep local reports out of source delivery

This commit is contained in:
cieanyau committed 2026-11-06 00:29:13 +08:00
1 parent db5762abd4
commit d37ce57d09
45 files changed
+232 -14820

No files matched your search

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 153 KiB

File diff suppressed because it is too large. Load diff
-2057
View File
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
-147
View File
@@ -1,147 +0,0 @@
{
"schemaVersion": 1,
"checkedOn": "2026-11-05",
"scope": "Rebuilt frontend and its integration boundaries; not a complete audit of the deployment archive",
"fixed": [
{
"id": "REQUEST_DEADLINE",
"problem": "Requests could wait indefinitely, including while reading response bodies",
"resolution": "One request deadline covers preflight, fetch and body; 30s JSON / 120s transfer defaults",
"evidence": "acceptance.json: the default request deadline aborts an unfinished JSON body and allows retry"
},
{
"id": "LOGOUT_PENDING",
"problem": "A pending logout response delayed local session revocation",
"resolution": "Capture old identity, clear local state immediately, revoke with a bounded background request",
"evidence": "acceptance.json: logout clears local access while its API request remains pending"
},
{
"id": "PAYMENT_DEADLINE",
"problem": "A stalled status request could consume the payment session deadline",
"resolution": "One session owns polling, an independent 5 minute deadline and invalidation on close/order/identity changes",
"evidence": "acceptance.json: stalled status and top-level Paid scenarios"
},
{
"id": "SSH_PAGINATION",
"problem": "Complete search results and server-paged results were sliced inconsistently",
"resolution": "Separate applied query from draft input and slice only complete search results",
"evidence": "acceptance.json: SSH search paginates 25 matches without repeating all rows"
},
{
"id": "SESSION_TREE",
"problem": "Session changes could unmount a login in progress or keep expired protected components alive",
"resolution": "Stable public login entry identity; protected component tree belongs to one authenticated session",
"evidence": "acceptance.json: login, legacy login, payment logout and payment 401 scenarios"
},
{
"id": "LEGACY_URL",
"problem": "Legacy credentials reappeared when router fullPath restored a query removed only from history",
"resolution": "Canonicalize both browser history and router location before mounting the legacy entry",
"evidence": "acceptance.json: a rejected legacy credential stays out of the error URL and can be retried"
},
{
"id": "CROSS_TAB",
"problem": "Other tabs retained a stale visible authenticated session after logout",
"resolution": "Reconcile browser storage events into the same reactive identity used by requests and UI",
"evidence": "acceptance.json: logout in another tab revokes both visible sessions"
},
{
"id": "VENDOR_LICENSE",
"problem": "The initially restored component-library version displayed an invalid commercial-license warning",
"resolution": "Use MIT PrimeVue 4 and MIT theme package; do not bypass license checks",
"evidence": "All browser scenarios reject visible Invalid PrimeUI License warnings"
},
{
"id": "LOCAL_ASSETS_RUNTIME",
"problem": "Default icon lookup used the external Iconify provider; mismatched framework versions broke server startup",
"resolution": "Serve bundled Lucide icons locally and align Nuxt/Vue/Router versions",
"evidence": "Production build and all browser scenarios run without non-local requests"
},
{
"id": "STATIC_GATE_TEMPLATES",
"problem": "Path checks missed template literals",
"resolution": "Inspect both literal strings and template elements in the lint-stage AST gate",
"evidence": "Negative gate smoke rejected string and template machine paths; final check passes"
}
],
"boundedDebt": [
{
"id": "AUTH_THEME_CYCLE_LABEL",
"state": "retained-ux-debt",
"what": "Blank auth layout labels the light-state button as switch to dark, while the existing theme cycle is auto -> light -> dark -> auto; with an initially light system, the first click stays light",
"whyDeferred": "Confirmed on both baseline and rewritten layout; this batch preserves existing theme behavior rather than changing the shared three-mode contract",
"blocks": "Claiming the theme button label accurately describes every next mode",
"nextStep": "Align the label with the three-mode theme cycle when the shared theme controls are revised"
},
{
"id": "REAL_BACKEND_ACCEPTANCE",
"state": "unverified",
"what": "Real ordering, invoices, verification, CAPTCHA/OAuth, financial changes, payment and VNC",
"whyDeferred": "No production access or real financial operations authorized for this rebuild",
"blocks": "Production release approval",
"nextStep": "Run staging acceptance against the real backend and supplier adapters"
},
{
"id": "REMOTE_GATEWAY_QUOTA",
"state": "known-out-of-scope",
"what": "Existing services/remote-console/gateway.mjs checks session quota before an await and registers later; two concurrent requests can both create a session at a limit of one",
"whyDeferred": "Independent server service, not frontend source rebuilding",
"blocks": "Claiming the remote-console stack has been fixed or production-validated",
"nextStep": "Separately authorize an atomic quota reservation fix and concurrent HTTP regression test"
},
{
"id": "DEPENDENCY_AUDIT",
"state": "open",
"what": "12 propagated npm audit findings: 6 low / 6 moderate",
"whyDeferred": "Suggested automatic fix force-downgrades Nuxt; reachability and compatibility need review",
"blocks": "Zero-vulnerability or unrestricted production-readiness claims",
"nextStep": "Review dependency-audit.json and patched upstream versions before release"
},
{
"id": "AUTH_PROTOCOL",
"state": "retained-contract",
"what": "Persistent browser JWT and discontinued CryptoJS AES login protocol remain",
"whyDeferred": "Changing the wire protocol requires coordinated backend changes",
"blocks": "Claiming an authentication-protocol security redesign",
"nextStep": "Plan session storage and login protocol migration with backend ownership"
},
{
"id": "RECOVERED_READABILITY",
"state": "open",
"what": "Most business SFCs retain render functions and short local variable names",
"whyDeferred": "Original source, comments and templates were not present in supplied archives",
"blocks": "Claiming verbatim original source recovery or a full manual rewrite of every page",
"nextStep": "Login, legacy entry, SSH keys and the blank auth layout are now handwritten setup/templates; continue incrementally with the remaining business pages"
},
{
"id": "AUDIT_DEPTH",
"state": "partial",
"what": "All delivered files are inventoried and all Vue/JS app modules are mechanically checked; only recorded security/lifecycle/payment/pagination boundaries received in-depth human review",
"whyDeferred": "Rebuilt business surface is large; static coverage is not manual or end-to-end coverage",
"blocks": "A 100% whole-project line-review or all-feature acceptance claim",
"nextStep": "Use audit-coverage.json to prioritize unreviewed pages and execute each remaining business entry in staging"
},
{
"id": "REVERSE_PROXY",
"state": "deployment-required",
"what": "Same-origin /captcha/ and /remote-console/sessions including WebSockets need separate reverse proxies",
"whyDeferred": "Local code cannot configure the deployment's proxy or supplier gateway",
"blocks": "Image CAPTCHA and remote-console integration without proxy configuration",
"nextStep": "Configure and verify the documented routes in a test deployment"
},
{
"id": "TRUSTED_IMPORTER",
"state": "documented-boundary",
"what": "One-time reconstruction script executes trusted build metadata and assumes its source paths are trusted",
"whyDeferred": "Retained as reconstruction provenance, not a generic or runtime importer; refuses an existing app/pages",
"blocks": "Using third-party/untrusted metadata as input",
"nextStep": "Do not run for normal development or builds; use only trusted owned release inputs"
}
],
"latestBatchReview": {
"scope": "Only the four handwritten SFCs, their changed tests and documented integration seams",
"confirmedRegressions": 0,
"acceptance": "21/21 passed after serial integration; browserErrors=0; networkViolations=0",
"remainingDebt": "All boundedDebt entries remain; no real provider acceptance claimed"
}
}
-246
View File
@@ -1,246 +0,0 @@
{
"checkedOn": "2026-11-05",
"command": "npm audit --json",
"exitCode": 1,
"interpretation": "12 dependency findings: 6 low, 6 moderate; no high/critical. Primarily propagated through Nuxt/Nitro build tooling. Not a zero-vulnerability claim; production reachability has not been exhaustively determined.",
"decision": "Retain current pinned Nuxt and lockfile. Do not apply the suggested force downgrade to Nuxt 4.1.3 without compatibility and security review. Reassess before external release.",
"auditReportVersion": 2,
"vulnerabilities": {
"@nuxt/nitro-server": {
"name": "@nuxt/nitro-server",
"severity": "low",
"isDirect": false,
"via": ["nitropack", "nuxt"],
"effects": ["nuxt"],
"range": ">=3.20.0",
"nodes": ["node_modules/@nuxt/nitro-server"],
"fixAvailable": {
"name": "nuxt",
"version": "4.1.3",
"isSemVerMajor": true
}
},
"@nuxt/vite-builder": {
"name": "@nuxt/vite-builder",
"severity": "low",
"isDirect": false,
"via": ["nuxt"],
"effects": ["nuxt"],
"range": "3.20.0 - 3.21.11 || >=4.2.0",
"nodes": ["node_modules/@nuxt/vite-builder"],
"fixAvailable": {
"name": "nuxt",
"version": "4.1.3",
"isSemVerMajor": true
}
},
"@nuxt/vite-server": {
"name": "@nuxt/vite-server",
"severity": "low",
"isDirect": false,
"via": ["nuxt"],
"effects": ["nuxt"],
"range": ">=4.6.0",
"nodes": ["node_modules/@nuxt/vite-server"],
"fixAvailable": {
"name": "nuxt",
"version": "4.1.3",
"isSemVerMajor": true
}
},
"@rollup/plugin-node-resolve": {
"name": "@rollup/plugin-node-resolve",
"severity": "low",
"isDirect": false,
"via": ["deepmerge"],
"effects": ["nitropack"],
"range": ">=8.0.0",
"nodes": ["node_modules/@rollup/plugin-node-resolve"],
"fixAvailable": {
"name": "nuxt",
"version": "4.1.3",
"isSemVerMajor": true
}
},
"@vercel/nft": {
"name": "@vercel/nft",
"severity": "moderate",
"isDirect": false,
"via": ["glob"],
"effects": ["nitropack"],
"range": ">=0.29.2",
"nodes": ["node_modules/@vercel/nft"],
"fixAvailable": {
"name": "nuxt",
"version": "4.1.3",
"isSemVerMajor": true
}
},
"archiver": {
"name": "archiver",
"severity": "moderate",
"isDirect": false,
"via": ["readdir-glob"],
"effects": ["nitropack"],
"range": ">=8.0.0",
"nodes": ["node_modules/archiver"],
"fixAvailable": {
"name": "nuxt",
"version": "4.1.3",
"isSemVerMajor": true
}
},
"deepmerge": {
"name": "deepmerge",
"severity": "low",
"isDirect": false,
"via": [
{
"source": 1243505,
"name": "deepmerge",
"dependency": "deepmerge",
"title": "deepmerge mergeObject() allows prototype poisoning of returned objects",
"url": "https://github.com/advisories/GHSA-gcqx-w48m-w2h4",
"severity": "low",
"cwe": ["CWE-1321"],
"cvss": {
"score": 5.3,
"vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N"
},
"range": ">=4.2.0 <=4.3.1"
}
],
"effects": ["@rollup/plugin-node-resolve"],
"range": ">=4.2.0",
"nodes": ["node_modules/deepmerge"],
"fixAvailable": {
"name": "nuxt",
"version": "4.1.3",
"isSemVerMajor": true
}
},
"glob": {
"name": "glob",
"severity": "moderate",
"isDirect": false,
"via": [
{
"source": 1244013,
"name": "glob",
"dependency": "glob",
"title": "Glob: AbortSignal cancellation bypass allows post-timeout filesystem traversal",
"url": "https://github.com/advisories/GHSA-3g3m-2fjr-6pw4",
"severity": "moderate",
"cwe": ["CWE-400"],
"cvss": {
"score": 0,
"vectorString": null
},
"range": ">=9.0.0 <=14.0.1"
},
"minimatch"
],
"effects": ["@vercel/nft"],
"range": "9.0.0 - 14.0.1",
"nodes": ["node_modules/glob"],
"fixAvailable": {
"name": "nuxt",
"version": "4.1.3",
"isSemVerMajor": true
}
},
"minimatch": {
"name": "minimatch",
"severity": "moderate",
"isDirect": false,
"via": [
{
"source": 1244623,
"name": "minimatch",
"dependency": "minimatch",
"title": "minimatch has potential denial of service via globparts amplification",
"url": "https://github.com/advisories/GHSA-g3hv-75wg-m249",
"severity": "moderate",
"cwe": ["CWE-405"],
"cvss": {
"score": 0,
"vectorString": null
},
"range": ">=7.0.0 <11.0.1"
}
],
"effects": ["glob", "readdir-glob"],
"range": "7.0.0 - 11.0.0",
"nodes": ["node_modules/minimatch"],
"fixAvailable": {
"name": "nuxt",
"version": "4.1.3",
"isSemVerMajor": true
}
},
"nitropack": {
"name": "nitropack",
"severity": "moderate",
"isDirect": false,
"via": ["@rollup/plugin-node-resolve", "@vercel/nft", "archiver"],
"effects": ["@nuxt/nitro-server"],
"range": ">=0.1.0",
"nodes": ["node_modules/nitropack"],
"fixAvailable": {
"name": "nuxt",
"version": "4.1.3",
"isSemVerMajor": true
}
},
"nuxt": {
"name": "nuxt",
"severity": "low",
"isDirect": true,
"via": ["@nuxt/nitro-server", "@nuxt/vite-builder", "@nuxt/vite-server"],
"effects": [
"@nuxt/nitro-server",
"@nuxt/vite-builder",
"@nuxt/vite-server"
],
"range": "3.20.0 - 3.21.11 || >=4.2.0",
"nodes": ["node_modules/nuxt"],
"fixAvailable": {
"name": "nuxt",
"version": "4.1.3",
"isSemVerMajor": true
}
},
"readdir-glob": {
"name": "readdir-glob",
"severity": "moderate",
"isDirect": false,
"via": ["minimatch"],
"effects": ["archiver"],
"range": ">=2.0.0",
"nodes": ["node_modules/readdir-glob"],
"fixAvailable": {
"name": "nuxt",
"version": "4.1.3",
"isSemVerMajor": true
}
}
},
"metadata": {
"vulnerabilities": {
"info": 0,
"low": 6,
"moderate": 6,
"high": 0,
"critical": 0,
"total": 12
},
"dependencies": {
"prod": 571,
"dev": 3,
"optional": 79,
"peer": 0,
"peerOptional": 0,
"total": 652
}
}
}
-439
View File
@@ -1,439 +0,0 @@
{
"pages": [
"pages/account/api-keys.vue",
"pages/account/connections.vue",
"pages/account/index.vue",
"pages/account/realname/company.vue",
"pages/account/realname/index.vue",
"pages/account/realname/personal.vue",
"pages/bills/[id].vue",
"pages/bills/index.vue",
"pages/cart/index.vue",
"pages/cloud-servers/index.vue",
"pages/dedicated-servers/index.vue",
"pages/finance/index.vue",
"pages/forgot-password.vue",
"pages/help.vue",
"pages/home.htm.vue",
"pages/index.vue",
"pages/invoices/index.vue",
"pages/invoices/invoice.vue",
"pages/invoices/request.vue",
"pages/invoices/settings/index.vue",
"pages/logbook/index.vue",
"pages/login.vue",
"pages/messages/index.vue",
"pages/news.vue",
"pages/notices/index.vue",
"pages/oauth/bind.vue",
"pages/oauth/callback.vue",
"pages/official-site.vue",
"pages/orders/[id].vue",
"pages/orders/index.vue",
"pages/orders/order/index.vue",
"pages/orders/order/paid.vue",
"pages/orders/order/pay.vue",
"pages/products/[id].vue",
"pages/products/cloud-server.vue",
"pages/products/dedicated-server/customize.vue",
"pages/products/dedicated-server/index.vue",
"pages/products/index.vue",
"pages/recommend/index.vue",
"pages/register.vue",
"pages/remote-console.vue",
"pages/resources.vue",
"pages/security/domains/index.vue",
"pages/security/groups/index.vue",
"pages/security/ssh-keys/index.vue",
"pages/servers/server.vue",
"pages/tickets/[id].vue",
"pages/tickets/create.vue",
"pages/tickets/index.vue",
"pages/tickets/ticket.vue",
"pages/transfer/index.vue",
"pages/vouchers/index.vue"
],
"components": [
"components/AuthProviders.vue",
"components/BackendNavEntry.vue",
"components/BackendNavigation.vue",
"components/BuildUpdateNotice.vue",
"components/CaptchaField.vue",
"components/ChartBox.vue",
"components/ClientLevelDialog.vue",
"components/ConsoleLegalFooter.vue",
"components/GeetestField.vue",
"components/GenericOAuthProviders.vue",
"components/GlobalSearch.vue",
"components/HostList.vue",
"components/ListEmpty.vue",
"components/ListSegments.vue",
"components/MfCloudBackupPanel.vue",
"components/NotificationPreferences.vue",
"components/OperatePasswordGate.vue",
"components/OperationNotice.vue",
"components/OperationToasts.vue",
"components/OsIcon.vue",
"components/PageInfoNotice.vue",
"components/PageSteps.vue",
"components/PaymentDialog.vue",
"components/PhoneCodeField.vue",
"components/ProductCategoryNotice.vue",
"components/ProductConfigurationSummary.vue",
"components/ProductDescription.vue",
"components/ProductGroupLabel.vue",
"components/RechargeDialog.vue",
"components/RichTextEditor.vue",
"components/RingProgress.vue",
"components/SecurityVerificationDialog.vue",
"components/SensitiveValue.vue",
"components/TicketAttachments.vue",
"components/TicketNotice.vue",
"components/UploadField.vue",
"components/WechatConnection.vue",
"components/WithdrawDialog.vue",
"components/config/CloudProductPicker.vue",
"components/config/CommonConfig.vue",
"components/config/ConfigBandwidth.vue",
"components/config/ConfigCheckout.vue",
"components/config/ConfigChoiceGrid.vue",
"components/config/ConfigDiskAdd.vue",
"components/config/ConfigDiskCard.vue",
"components/config/ConfigLoadingShell.vue",
"components/config/ConfigResourceOption.vue",
"components/config/FinanceConfig.vue",
"components/config/JyCloudConfig.vue",
"components/config/KkyEcsConfig.vue",
"components/config/MfCloudConfig.vue",
"components/config/MfDcimConfig.vue",
"components/config/ProductCustomFields.vue",
"components/config/PromoCodeField.vue",
"components/home/HomeConsumeTrend.vue",
"components/home/HomeExpiringPanel.vue",
"components/home/HomeNoticePanel.vue",
"components/home/HomeReferralPanel.vue",
"components/home/HomeServerPanel.vue",
"components/home/HomeTicketPanel.vue",
"components/home/HomeTicketStat.vue",
"components/home/HomeWalletCard.vue",
"components/home/RoxyMascot.vue",
"components/instance/CloudAccessExtras.vue",
"components/instance/CommonManage.vue",
"components/instance/CommonUpgrade.vue",
"components/instance/DcimActions.vue",
"components/instance/DcimBilling.vue",
"components/instance/DcimDefence.vue",
"components/instance/DcimDomains.vue",
"components/instance/DcimManage.vue",
"components/instance/DcimMonitor.vue",
"components/instance/DcimReinstallStatus.vue",
"components/instance/DcimUpgrade.vue",
"components/instance/FlowPacketPanel.vue",
"components/instance/ImagePurchaseDialog.vue",
"components/instance/InstanceAccess.vue",
"components/instance/InstanceBilling.vue",
"components/instance/InstanceDisks.vue",
"components/instance/InstanceLoadingShell.vue",
"components/instance/InstanceManage.vue",
"components/instance/InstanceMonitor.vue",
"components/instance/InstanceMonitorSkeleton.vue",
"components/instance/InstanceNetwork.vue",
"components/instance/InstanceOnDemand.vue",
"components/instance/InstanceOverview.vue",
"components/instance/InstanceRenewDialog.vue",
"components/instance/InstanceServiceInfo.vue",
"components/instance/InstanceSmsCode.vue",
"components/instance/InstanceStatusTag.vue",
"components/instance/InstanceTraffic.vue",
"components/instance/LegacyDcimActions.vue",
"components/instance/LegacyDcimManage.vue",
"components/instance/LegacyProductUpgrade.vue",
"components/instance/RemfUpgrade.vue",
"components/instance/RemoteConsole.vue",
"components/kkyecs/KkyUpgrade.vue",
"components/mfcloud/MfCloudDefence.vue",
"components/mfcloud/MfCloudIps.vue",
"components/mfcloud/MfCloudLogs.vue",
"components/mfcloud/MfCloudNat.vue",
"components/mfcloud/MfCloudResourceUpgrade.vue",
"components/mfcloud/MfCloudUpgrade.vue",
"components/mfcloud/MfCloudVpc.vue"
],
"layouts": [
"layouts/blank.vue",
"layouts/default.vue",
"layouts/official-site.vue",
"layouts/public-order.vue"
],
"shared": [
"app/lib/_plugin-vue_export-helper.js",
"app/lib/auth-redirect.js",
"app/lib/auth.js",
"app/lib/backend-menu.js",
"app/lib/bandwidth-display.js",
"app/lib/cart-edit.js",
"app/lib/cloud-instance-management.js",
"app/lib/common-advanced-rules.js",
"app/lib/complete-list.js",
"app/lib/composables-2.js",
"app/lib/configuration-display.js",
"app/lib/content-route.js",
"app/lib/dict.js",
"app/lib/finance-resource-chart.js",
"app/lib/instance-data.js",
"app/lib/instance-status.js",
"app/lib/interval.js",
"app/lib/invoice.js",
"app/lib/modules.js",
"app/lib/navigation-state.js",
"app/lib/oauth.js",
"app/lib/order-image-continuation.js",
"app/lib/os-name.js",
"app/lib/password-2.js",
"app/lib/product-description-data.js",
"app/lib/product-fields.js",
"app/lib/product-name.js",
"app/lib/product-order-module.js",
"app/lib/purchase-limit-state.js",
"app/lib/remote-console.js",
"app/lib/renewal-quote.js",
"app/lib/rolldown-runtime.js",
"app/lib/sanitize.js",
"app/lib/server-page.js",
"app/lib/storage-capacity.js",
"app/lib/ticketAttachments.js",
"app/lib/useCaptcha.js",
"app/lib/useListPage.js",
"app/lib/useMailbox.js",
"app/lib/useOAuth.js",
"app/lib/useOfficialSiteContent.js",
"app/lib/useSiteConfig.js",
"app/lib/useTheme.js",
"app/lib/useVerifyCode.js",
"app/lib/useWithdrawAvailability.js",
"app/lib/wechat-binding.js"
],
"routes": [
{
"source": "pages/account/realname/company.vue",
"path": "/account/realname/company"
},
{
"source": "pages/account/realname/personal.vue",
"path": "/account/realname/personal"
},
{
"source": "pages/orders/order/paid.vue",
"path": "/orders/order/paid"
},
{
"source": "pages/orders/order/pay.vue",
"path": "/orders/order/pay"
},
{
"source": "pages/products/dedicated-server/customize.vue",
"path": "/products/dedicated-server/customize"
},
{
"source": "pages/account/api-keys.vue",
"path": "/account/api-keys"
},
{
"source": "pages/account/connections.vue",
"path": "/account/connections"
},
{
"source": "pages/account/realname/index.vue",
"path": "/account/realname"
},
{
"source": "pages/invoices/invoice.vue",
"path": "/invoices/invoice"
},
{
"source": "pages/invoices/request.vue",
"path": "/invoices/request"
},
{
"source": "pages/invoices/settings/index.vue",
"path": "/invoices/settings"
},
{
"source": "pages/oauth/bind.vue",
"path": "/oauth/bind"
},
{
"source": "pages/oauth/callback.vue",
"path": "/oauth/callback"
},
{
"source": "pages/orders/order/index.vue",
"path": "/orders/order"
},
{
"source": "pages/products/cloud-server.vue",
"path": "/products/cloud-server"
},
{
"source": "pages/products/dedicated-server/index.vue",
"path": "/products/dedicated-server"
},
{
"source": "pages/security/domains/index.vue",
"path": "/security/domains"
},
{
"source": "pages/security/groups/index.vue",
"path": "/security/groups"
},
{
"source": "pages/security/ssh-keys/index.vue",
"path": "/security/ssh-keys"
},
{
"source": "pages/servers/server.vue",
"path": "/servers/server"
},
{
"source": "pages/tickets/create.vue",
"path": "/tickets/create"
},
{
"source": "pages/tickets/ticket.vue",
"path": "/tickets/ticket"
},
{
"source": "pages/bills/[id].vue",
"path": "/bills/:id()"
},
{
"source": "pages/orders/[id].vue",
"path": "/orders/:id()"
},
{
"source": "pages/products/[id].vue",
"path": "/products/:id()"
},
{
"source": "pages/tickets/[id].vue",
"path": "/tickets/:id()"
},
{
"source": "pages/account/index.vue",
"path": "/account"
},
{
"source": "pages/bills/index.vue",
"path": "/bills"
},
{
"source": "pages/cart/index.vue",
"path": "/cart"
},
{
"source": "pages/cloud-servers/index.vue",
"path": "/cloud-servers"
},
{
"source": "pages/dedicated-servers/index.vue",
"path": "/dedicated-servers"
},
{
"source": "pages/finance/index.vue",
"path": "/finance"
},
{
"source": "pages/forgot-password.vue",
"path": "/forgot-password"
},
{
"source": "pages/help.vue",
"path": "/help"
},
{
"source": "pages/home.htm.vue",
"path": "/home.htm"
},
{
"source": "pages/invoices/index.vue",
"path": "/invoices"
},
{
"source": "pages/logbook/index.vue",
"path": "/logbook"
},
{
"source": "pages/login.vue",
"path": "/login"
},
{
"source": "pages/messages/index.vue",
"path": "/messages"
},
{
"source": "pages/news.vue",
"path": "/news"
},
{
"source": "pages/notices/index.vue",
"path": "/notices"
},
{
"source": "pages/official-site.vue",
"path": "/official-site"
},
{
"source": "pages/orders/index.vue",
"path": "/orders"
},
{
"source": "pages/products/index.vue",
"path": "/products"
},
{
"source": "pages/recommend/index.vue",
"path": "/recommend"
},
{
"source": "pages/register.vue",
"path": "/register"
},
{
"source": "pages/remote-console.vue",
"path": "/remote-console"
},
{
"source": "pages/resources.vue",
"path": "/resources"
},
{
"source": "pages/tickets/index.vue",
"path": "/tickets"
},
{
"source": "pages/transfer/index.vue",
"path": "/transfer"
},
{
"source": "pages/vouchers/index.vue",
"path": "/vouchers"
},
{
"source": "pages/index.vue",
"path": "/"
}
],
"handwrittenTemplateBatch": {
"baseline": "5cd7210a1df33c97cba4c863e9633ace58e1472f963105ae93af46c607ce4f50",
"sourceCommit": "7f612c7e682a48d5e4b775b2ecb91234562f2b2c0cb9e9d063811d7ee18fb929",
"files": [
"app/pages/login.vue",
"app/pages/home.htm.vue",
"app/pages/security/ssh-keys/index.vue",
"app/layouts/blank.vue"
],
"productNetLines": -863,
"scope": "This batch only; other recovered business modules still contain render functions",
"acceptance": "21/21 offline browser scenarios; see acceptance.json"
}
}
-70
View File
@@ -1,70 +0,0 @@
# 完整前端项目交接说明
核对日期:2026-11-05。
## 交付的是什么
交付的是整个会员中心的独立 Nuxt 前端工程,而不是仅含登录或 SSH 页面的小样例。
“四个文件已手写重建”指第二轮的维护进度,不是压缩包中只有四个文件。
| 内容 | 数量与说明 |
| -------------- | ------------------------------------------------------------------------- |
| 页面 | 52 个,路由清单见 `module-inventory.json` |
| 业务组件 | 104 个 |
| 布局 | 4 套 |
| Vue 文件 | 161 个,含应用入口 |
| JS/TS 应用模块 | 55 个,含接口、会话、插件、路由保护与配置 |
| 样式文件 | 137 个 |
| public 资源 | 285 个,含图片、字体和站点资源 |
| 工程文件 | npm 依赖与锁文件、Nuxt 配置、示例环境配置、检查脚本、浏览器测试和验收记录 |
完整性检查未发现丢失的本地依赖或资源:4,647 处应用模块导入、252 处 CSS 本地资源引用均可解析。
上述数目说明文件覆盖,不等于所有业务分支都已经真实后端验收。
## 与服务器当前版本的关系
经用户授权,只读检查 `/www/wwwroot/crashwork-console`,没有修改文件、重启服务或部署。
检查时 `.output` 指向 `releases/20261025-kky-traffic-display/.output`。
当前发布目录仅含 `.output` 与发布指向记录;检查了 130 个发布目录中构建目录之外、深度不超过五层的源码候选,
未找到原始 `.vue`/`.tsx`/`.jsx` 页面或 Nuxt/Vite 工程配置。没有读取根 `.env` 或导入数据库备份。
服务器与本地重建依据的校验结果:
- `server/chunks/virtual/precomputed.mjs` SHA-256 一致:`e9a8d0e2be5f7e2263961e9f128bb6e89955d42814e5a7a0c43ae85c5a6327e1`。
- 元数据列出的 735 个唯一模块资源均存在,按文件名及内容 SHA-256 聚合后的摘要一致:`08144c47f9dda33a859105d5a746898feb288dd5b0c4ffb7464cf65fd704ed29`。
- 这证明重建依据与检查时服务器的模块构建一致;不证明真实供应商接口、全部服务器文件或线上业务均已验收。
## 员工如何使用
在本工程根目录使用 Node.js 22.12+:
```sh
npm ci
cp .env.example .env
npm run dev
```
配置 `NUXT_PUBLIC_API_BASE` 为后端 origin,不附加 `/console/v1`。
留空时需要同源反向代理;`/captcha/`、`/remote-console/sessions` 及其 WebSocket 还需独立反代配置。
后端服务不会随此前端工程自动启动。不要把生产 root 密码或其他秘密填入前端公开配置。
```sh
npm run check
npm run build
npm test
```
产物在本工程 `.output/`;运行方式及 Chrome 路径配置见根 README 和 `tests/README.md`。
已有干净解压安装、构建及 21 项真实浏览器场景通过的记录,见 `validation.md` 和 `acceptance.json`。
本次服务器版本核对后再次执行源码检查、生产构建及 21 项浏览器场景,全部通过,浏览器运行错误和外网请求均为零。
## 不能混淆的边界
- 这是完整可编辑、可构建的重建工程,不是原始源码的逐字恢复。49 个页面、103 个组件和 3 个布局仍使用恢复的渲染函数,合计 155 个 Vue 文件;并非文件缺失,也不能称为全站手写模板完成。
- 原模板、完整变量名、注释和原始业务需求文档不在服务器发布包中;不承诺逆向恢复这些已丢失的信息。
- 不包含后端、数据库、远控网关服务或生产反向代理配置;验证码、OAuth、支付、财务、供应商和 VNC 仍需测试环境联调。
- 保留当前登录协议及已记录的技术债,包括依赖告警和认证页主题切换文案,见 `defect-ledger.json`。
- 不含生产环境文件、登录凭证、Git 历史、`node_modules` 和构建产物;不要把根服务器目录或历史 releases 打包发给员工。
最小交付原则:在已可构建工程上补充核对证据,不增加产品字段、依赖、配置或另一套前端实现;
路由、资源和依赖由现有清单确定,不要求员工在历史发布目录中手工挑选版本。
-21
View File
@@ -1,21 +0,0 @@
# 前端源码重建方案
范围:当前 20261025 发布包的 52 个页面、4 个布局、104 个业务组件及其共享业务逻辑。新工程自包含,不引用历史发布目录,不替换线上发布指向。
最小设计检查:
1. 结构:建立独立可构建源码工程,解决源码缺失,而非在压缩产物上继续打补丁。
2. 调用负担:保持现有后端路径、请求字段及页面 URL,不要求后端新增协议。
3. 可推导信息:路由和模块清单从当前有效构建清单提取,不让使用者手工选择旧版文件。
4. 复杂度:沿用 Nuxt、Vue、PrimeVue;框架和组件库使用正式依赖,只恢复业务逻辑和现有样式。
5. 适用范围:覆盖当前入口的完整模块图,不只复刻登录页或几个示例页面。
最小可行方案是保留已发布业务行为,将编译后的业务模块恢复为格式化、具有业务路径和显式依赖的 Vue 渲染函数源码,并重建应用入口、框架依赖、构建清单与测试。原始变量名、注释和模板排版已在构建中丢失,不能宣称逐字恢复原始工程。Vue 单文件组件允许使用 render/setup 返回的渲染函数;不把旧发布包作为运行时依赖。
缺陷类别:异步操作的等待没有统一的时间边界,界面生命周期被远端响应决定;通用规则是请求有明确截止时间,界面清理由本地状态所有者完成。另一类是完整搜索结果与当前页结果混用,规则是只由一处分页逻辑生成当前可见集合。
验证:构建新工程;使用本地 HTTP 后端替身验证登录、鉴权、SSH 搜索分页、注销、支付等待边界及页面路由加载。真实支付、供应商实例和生产反代不在离线替身中伪称验证通过。
第二轮按维护边界逐页改成手写 setup 与模板:登录、旧平台登录入口、SSH 密钥及公共认证布局。
保持原协议与样式,不运行一次性导入器、不覆盖历史发布产物。四个产品文件净减少 863 行;
新增/扩展真实页面回归后为 21 场景。其余恢复模块仍按需逐页改写,不将这一批等同于全站重写。
-96
View File
@@ -1,96 +0,0 @@
# 重建与验收记录
日期:2026-11-05。基准:当前 20261025 发布版本;没有读取 `.env`,没有连接生产服务器或使用生产凭证。
## 可确认的范围
清单包含 52 个页面、104 个组件、4 个布局;另重写应用入口。所有业务文件采用源码路径和显式模块依赖,
不从历史 `.output`、`releases` 或旧哈希 JS 加载代码。保留编译后的作用域样式,以维持现有视觉规则。
原注释、模板排版、完整局部变量名不能逆向恢复;多数页面仍使用渲染函数,应逐步按实际维护需求重构。
源文件的解析/依赖门禁与生产构建覆盖全部 Vue 文件,但不等于所有业务交互都已验收。
逐文件覆盖台账另见 `audit-coverage.json`;未逐行人工审查的业务文件明确标记为未审查。
## 修复记录
| 问题 | 原因和处理 | 验证方式 |
| ------------------------ | ------------------------------------------------------------------------ | ------------------------------------- |
| 请求永久等待 | JSON 默认 30 秒、上传/下载 120 秒;截止时间覆盖响应正文和购买前置校验 | 真实页面的挂起请求与超时场景 |
| 注销被网络拖住 | 先捕获旧 Bearer,立即清理本地会话,后台有限时撤销 | `/logout` 不返回时仍退出 |
| 支付截止被挂起轮询吞掉 | 一个轮询会话拥有独立五分钟截止与单请求超时,关闭/换单/换身份使旧响应失效 | 浏览器外部时钟推进、无重复支付 |
| SSH 搜索翻页重复 | 区分服务端分页和完整搜索集合,仅由可见行计算切片 | 普通分页、搜索 10/10/5、查询切换/清空 |
| 重建入口改变登录生命周期 | 登录及旧平台入口在认证过程中保持组件身份;保护页面随会话失效卸载 | 登录和旧入口场景 |
| 会话失效后重复初始化 | 菜单、支付初始化由当前登录身份控制 | 401 与退出场景 |
| 图标依赖外网 | 本地打包 Lucide,禁用外部回退 | 所有场景禁止访问外网 |
| 组件库许可提示 | 换用 MIT 版本,不修改许可校验;主题也引用 MIT 包 | 可见 UI 许可检查 |
| 框架运行时混用 | Vue、共享函数、Router 版本统一;替换旧私有注入标识 | 实际启动构建服务及浏览器验收 |
| 跨标签页会话不一致 | 请求与界面使用同一个响应式身份;监听存储变动使其他标签页同步退出 | 第二标签页退出后第一个标签页被保护 |
| 旧入口凭证回到地址栏 | 同时清理 history 与路由的规范地址,失败页面也不恢复敏感查询 | 旧凭证被拒绝后检查 URL 与 Referrer |
首轮已在真实构建上重现 SSH、注销和支付三个缺陷;修复后基础 11 场景通过。
第二轮最终生产构建通过,扩展 21 个浏览器场景全部通过,无浏览器运行错误和外网请求。
结果见随本次交付保留的 `acceptance.json`、`acceptance-assets/` 截图和 `acceptance-requests.json` 脱敏请求顺序。
已修复问题与剩余债务另见 `defect-ledger.json`;这不是整站逐行审查或生产业务验收完成的声明。
首轮源码包曾在仓库之外的全新临时目录重新执行 `npm ci`、检查、构建与当时的 18 个浏览器场景,全部通过;
本轮 v2 包的独立验证记录见下文,不把首轮结果当作本轮验收。
## 第二轮:手写模板重建
本轮仅改写 `app/pages/login.vue`、`app/pages/home.htm.vue`、`app/pages/security/ssh-keys/index.vue`
和 `app/layouts/blank.vue`,从恢复的渲染函数改成可维护的 setup 与模板;不是在旧 render 外再包一层模板。
登录保留密码/短信配置、60 秒验证码倒计时、CAPTCHA/安全验证续登、OAuth 组件和安全跳转;
旧入口保留凭证验证、地址脱敏、重试与卸载取消;SSH 保留服务端分页、完整集合搜索及增改删,清理卸载后的计时器和迟到结果。
认证布局保留主题、站点配置、logo、redirect 和 slot。原样式的作用域接缝已逐项核对。
最小设计复核:以逐页等价替换解决可读性问题;不新增调用方字段或配置;路由与派生状态沿用已有来源;
不另建渲染/请求抽象或第二条实现路径;重写覆盖每个选定页面的完整模板,不为测试添加产品开关。
净行数:产品 -863(登录 -390、旧入口 -80、SSH -293、布局 -100),测试 +348,增长用于三个真实页面行为场景及旧场景扩展;依赖/锁文件零变动。
合并后执行 `npm run check`、`npm run build`、`npm test`,161 个 Vue 文件和 55 个模块门禁通过,21/21 浏览器场景通过。
新增覆盖:短信独占配置及倒计时、禁用短信时的默认登录方式、SSH 创建/编辑/删除末页恢复;
原旧入口失败场景扩展为真实点击重试,并检查不恢复 URL 凭证、不重新密码登录及无 Referrer。
测试仍通过真实生产构建和独立 HTTP 假后端,不替换内部模块、不预置 JWT、不访问生产服务。
本轮交叉复核完整读取四个新文件及相关样式;登录组件、安全验证、会话和路由接缝按台账记录读取范围。
最新质量复核未发现新增确认回退;详细原始业务规范并不存在,不能宣称全部原规范逐条一致。
本轮已验证的公开入口为 `/login`、`/home.htm` 与 `/security/ssh-keys`,未因此提升其他页面的人工审查/功能覆盖状态。
窄屏补查确认认证页和 SMS 表单在 320/390px 下不横向溢出,SSH 编辑弹窗在 390px 下宽 366px;
核对预填、取消、密码显示切换、注册/重置提示及 redirect 链接。截图证据随 `acceptance.json` 归档。
另确认一个既有主题文案问题:浅色系统下默认 auto 首次循环到 light,按钮虽写“切换深色模式”却仍浅色;
基准版本行为相同,作为 `AUTH_THEME_CYCLE_LABEL` 有界债务保留,不把首次点击截图当作深色验收。
门禁盲区:配置加载失败后重载、CAPTCHA/安全挑战/实名认证续登、真实 OAuth、SSH 剪贴板/失败响应/并发操作、
旧入口卸载时取消等分支尚未被这 21 个场景完整覆盖;代码复核不代替这些分支的真实交互验证,也无证据将其判定为已坏。
v2 源码候选包已通过独立干净目录验收:从提交 `6c73598` 仅导出 `frontend/`,解压到仓库外,
重新执行 `npm ci`、源码检查、生产构建和 21 个浏览器场景,全部通过;稳定的场景结果与主工作树一致。
导出包含 686 个文件,无符号链接,不含 `.env`、Git 历史、依赖目录、生成构建和数据库备份。
此后仅补充文档与台账,没有改变已验收产品、依赖或测试。12 项低/中危传递依赖告警仍在债务清单中。
结构性修复扫描:
```sh
rg -n 'fetch\(|AbortController|timeoutMs|logout|legacyLogin|useApi\(' app --glob '*.js' --glob '*.vue'
rg -n '/pay/.*status|setInterval\(|complete_list_n' app --glob '*.js' --glob '*.vue'
```
接口核心 JSON、上传、下载、旧平台身份验证共四个传输入口统一有限时;验证码刷新和 VNC 会话使用各自
既有的交互生命周期,不宣称已完成全局网络子系统重写。支付状态只有一个共享轮询所有者,已修复。
其余服务器刷新、验证码倒计时和实例查询不是同一个“支付绝对期限被吞掉”的缺陷,不在此改动中混改。
## 仍需联调 / 有界技术债
规模说明:原仓库没有 `frontend/`,新增的是已有业务的独立源码表达,不是同等数量的新功能。
相对重建前基准,应用源码约 +123,394 行、现有样式展开后 +19,836 行、测试约 +1,250 行;
构建/锁文件/工具约 +9,964 行,静态资产文本约 +2,605 行,另保留二进制图片和字体。
文档、截图与逐文件台账单独计量,不作为产品逻辑。较大体量主要来自恢复全部业务渲染函数和将压缩样式格式化;
没有为每个页面另造一套框架、请求系统或测试专用产品开关。不能因编译全绿就省略后续按业务逐页维护与联调。
- 真实下单、续费/升级、发票、财务、安全验证、短信/邮件、第三方 CAPTCHA/OAuth、真实支付、VNC 握手及生产反代:未使用生产环境验证。
- `/captcha/` 及 `/remote-console/sessions` 为同源接口,必须在开发/测试部署另行配置反代,不能仅依赖 API origin。
- 原远程控制网关属于独立服务。本工程保留客户端协议,但没有重写或部署该服务;此前审查发现的网关配额并发竞争仍需单独修复。
- 浏览器回归采用外部 HTTP 假后端,不能代替供应商接口兼容性验收;52 个页面可构建不代表所有分支、每种响应字段都已人工核对。
- 默认保留 JWT 持久化方式与登录 AES 协议,未进行会影响后端契约的身份协议升级;CryptoJS 已停止维护,应在前后端协同变更时迁移。
- `npm audit` 的传递依赖低/中危告警仍保留,具体结果见 `dependency-audit.json`;没有盲目使用 `--force` 降级框架。对外上线前应复核受影响路径与补丁版本。
- 大部分恢复页面仍含短局部变量和较长渲染函数,非逐字原始开发源码,也非每个页面都已重新手写模板。人工深度审查集中在入口、会话、支付、分页和远控边界。
旧服务器及数据库备份未导入新前端,没有覆盖原发布目录。新工程的所有变更仅限 `frontend/`。