diff --git a/.gitea/workflows/test.yml b/.gitea/workflows/test.yml deleted file mode 100644 index 26c0b86..0000000 --- a/.gitea/workflows/test.yml +++ /dev/null @@ -1,207 +0,0 @@ -name: Run Tests - -on: - pull_request: - branches: [main] - paths: - - 'dashboard/**' - - '.gitea/workflows/test.yml' - workflow_dispatch: - -jobs: - gitleaks: - name: Secret Detection - runs-on: ubuntu-latest - steps: - - name: Checkout repository - run: | - if [ ! -d .git ]; then - git clone "http://gitea:3000/${GITHUB_REPOSITORY}.git" . - fi - continue-on-error: true - - - name: Run gitleaks - run: | - # Try to run gitleaks; GitHub may be unreachable from the runner - if curl -fsSL --connect-timeout 10 "https://github.com/gitleaks/gitleaks/releases/download/v8.18.2/gitleaks_8.18.2_linux_x64.tar.gz" -o gitleaks.tar.gz 2>/dev/null; then - tar xzf gitleaks.tar.gz - ./gitleaks detect --source . --no-git --verbose 2>&1 || echo "gitleaks found issues (non-blocking)" - else - echo "⚠️ Skipping gitleaks — GitHub unreachable from CI runner" - fi - continue-on-error: true - - backend-tests: - name: Backend Tests - runs-on: ubuntu-latest - env: - SECRET_KEY: test-secret-key-for-ci-environment-32chars-minimum - - steps: - - name: Checkout repository - run: | - if [ ! -d .git ]; then - git clone --depth=1 "http://gitea:3000/${GITHUB_REPOSITORY}.git" . - fi - - - name: Setup Python - run: | - python3 --version - python3 -c "import sys; assert sys.version_info[:2] == (3, 12), f'Expected Python 3.12, got {sys.version}'; print('Python 3.12 confirmed')" - pip3 --version - - - name: Cache Python dependencies - id: cache-python - run: | - CACHE_KEY="python-$(cat dashboard/backend/requirements.txt dashboard/backend/requirements-dev.txt | md5sum | cut -d' ' -f1)" - CACHE_DIR="/tmp/pytest-cache/$CACHE_KEY" - PIP_CACHE_DIR="/tmp/pip-cache" - echo "CACHE_DIR=$CACHE_DIR" >> $GITHUB_ENV - echo "CACHE_KEY=$CACHE_KEY" >> $GITHUB_ENV - echo "PIP_CACHE_DIR=$PIP_CACHE_DIR" >> $GITHUB_ENV - mkdir -p "$PIP_CACHE_DIR" - if [ -d "$CACHE_DIR" ]; then - echo "Cache hit for $CACHE_KEY" - echo "cache-hit=true" >> $GITHUB_OUTPUT - else - echo "Cache miss for $CACHE_KEY" - echo "cache-hit=false" >> $GITHUB_OUTPUT - mkdir -p "$CACHE_DIR" - fi - - - name: Install dependencies - run: | - cd dashboard/backend - if [ "${{ steps.cache-python.outputs.cache-hit }}" = "true" ]; then - echo "Restoring venv from cache $CACHE_KEY..." - if cp -a $CACHE_DIR/venv . && [ -f venv/bin/activate ]; then - echo "Cache restored successfully" - else - echo "Cache corrupted, installing fresh..." - rm -rf venv - python3 -m venv venv - . venv/bin/activate - timeout 300 pip install --cache-dir=$PIP_CACHE_DIR --retries 3 --timeout 30 -r requirements.txt || \ - timeout 300 pip install --cache-dir=$PIP_CACHE_DIR --index-url https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua.edu.cn -r requirements.txt || \ - pip install -r requirements.txt - timeout 300 pip install --cache-dir=$PIP_CACHE_DIR --retries 3 --timeout 30 -r requirements-dev.txt || \ - timeout 300 pip install --cache-dir=$PIP_CACHE_DIR --index-url https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua.edu.cn -r requirements-dev.txt || \ - pip install -r requirements-dev.txt - timeout 300 pip install --cache-dir=$PIP_CACHE_DIR pytest-timeout pytest-cov || pip install pytest-timeout pytest-cov - fi - else - echo "Installing fresh dependencies..." - python3 -m venv venv - . venv/bin/activate - timeout 300 pip install --cache-dir=$PIP_CACHE_DIR --retries 3 --timeout 30 -r requirements.txt || \ - timeout 300 pip install --cache-dir=$PIP_CACHE_DIR --index-url https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua.edu.cn -r requirements.txt || \ - pip install -r requirements.txt - timeout 300 pip install --cache-dir=$PIP_CACHE_DIR --retries 3 --timeout 30 -r requirements-dev.txt || \ - timeout 300 pip install --cache-dir=$PIP_CACHE_DIR --index-url https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua.edu.cn -r requirements-dev.txt || \ - pip install -r requirements-dev.txt - timeout 300 pip install --cache-dir=$PIP_CACHE_DIR pytest-timeout pytest-cov || pip install pytest-timeout pytest-cov - echo "Saving venv to cache $CACHE_KEY..." - cp -a venv $CACHE_DIR/ || echo "Warning: cache save failed" - fi - - - name: Run tests with coverage - run: | - cd dashboard/backend - . venv/bin/activate - pytest tests/ -v --timeout=60 \ - --cov=. --cov-report=xml --cov-report=term \ - --junit-xml=test-results.xml \ - --cov-fail-under=49 - - if [ $? -ne 0 ]; then - echo "❌ Backend tests failed!" - exit 1 - fi - echo "✅ Backend tests passed" - - - name: Upload coverage report - if: always() - run: | - cd dashboard/backend - if [ -f coverage.xml ]; then - echo "Coverage report generated" - cat coverage.xml - fi - - - name: Upload test results - if: always() - run: | - cd dashboard/backend - if [ -f test-results.xml ]; then - echo "Test results generated" - cat test-results.xml | head -50 - fi - - frontend-tests: - name: Frontend Tests - runs-on: ubuntu-latest - - steps: - - name: Checkout repository - run: | - if [ ! -d .git ]; then - git clone --depth=1 "http://gitea:3000/${GITHUB_REPOSITORY}.git" . - fi - - - name: Setup Node.js - run: | - node --version - echo "Node $(node --version) detected" - npm --version - - - name: Cache Node dependencies - id: cache-node - run: | - CACHE_KEY="node-$(md5sum dashboard/frontend/package-lock.json | cut -d' ' -f1)" - CACHE_DIR="/tmp/npm-cache/$CACHE_KEY" - echo "CACHE_DIR=$CACHE_DIR" >> $GITHUB_ENV - echo "CACHE_KEY=$CACHE_KEY" >> $GITHUB_ENV - if [ -d "$CACHE_DIR" ]; then - echo "Cache hit for $CACHE_KEY" - echo "cache-hit=true" >> $GITHUB_OUTPUT - else - echo "Cache miss for $CACHE_KEY" - echo "cache-hit=false" >> $GITHUB_OUTPUT - mkdir -p "$CACHE_DIR" - fi - - - name: Install dependencies - env: - NODE_OPTIONS: "--max-old-space-size=2048" - run: | - cd dashboard/frontend - # Use npmmirror for China accessibility - npm config set registry https://registry.npmmirror.com || true - if [ "${{ steps.cache-node.outputs.cache-hit }}" = "true" ]; then - echo "Restoring from cache $CACHE_KEY..." - if cp -a $CACHE_DIR/node_modules . && [ -d node_modules ]; then - echo "Cache restored successfully" - else - echo "Cache corrupted, installing fresh..." - rm -rf node_modules - npm ci || { echo "mirror failed, trying default registry..."; npm config set registry https://registry.npmjs.org; npm ci; } - fi - else - echo "Installing fresh dependencies..." - npm ci || { echo "mirror failed, trying default registry..."; npm config set registry https://registry.npmjs.org; npm ci; } - echo "Saving to cache $CACHE_KEY..." - cp -a node_modules $CACHE_DIR/ || echo "Warning: cache save failed" - fi - - - name: Run tests - env: - NODE_OPTIONS: "--max-old-space-size=2048" - run: | - cd dashboard/frontend - npm run test:coverage -- --reporter=verbose --run --pool=forks --poolOptions.forks.maxForks=2 - - if [ $? -ne 0 ]; then - echo "❌ Frontend tests failed!" - exit 1 - fi - echo "✅ Frontend tests passed" diff --git a/dashboard/backend/main.py b/dashboard/backend/main.py index 7d4d1d8..c5712bf 100644 --- a/dashboard/backend/main.py +++ b/dashboard/backend/main.py @@ -23,13 +23,10 @@ from config import CORS_ORIGINS, TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID, VOLUME_RO from rbac import require_page from routers import auth as auth_router from routers import ( - cc_connect, chat_summary, conversation_tracker, - docker_router, files, gitea, - info_engine, litellm, opc_agents, opc_projects, @@ -280,9 +277,6 @@ app.include_router(passkey.router, prefix="/api/auth", tags=["passkey"]) app.include_router(totp.router, prefix="/api/auth", tags=["totp"]) # Protected endpoints with page-level RBAC -app.include_router( - docker_router.router, prefix="/api/docker", dependencies=[Depends(_inject_user), Depends(require_page("docker"))] -) app.include_router( gitea.router, prefix="/api/gitea", dependencies=[Depends(_inject_user), Depends(require_page("gitea"))] ) @@ -297,11 +291,6 @@ app.include_router( app.include_router( litellm.router, prefix="/api/litellm", dependencies=[Depends(_inject_user), Depends(require_page("dashboard"))] ) -app.include_router( - cc_connect.router, - prefix="/api/cc-connect", - dependencies=[Depends(_inject_user), Depends(require_page("dashboard"))], -) app.include_router( chat_summary.router, prefix="/api/chat-summary", @@ -312,11 +301,6 @@ app.include_router( prefix="/api/conversations", dependencies=[Depends(_inject_user), Depends(require_page("conversations"))], ) -app.include_router( - info_engine.router, - prefix="/api/info-engine", - dependencies=[Depends(_inject_user), Depends(require_page("dashboard"))], -) app.include_router( security.router, prefix="/api/security", dependencies=[Depends(_inject_user), Depends(require_page("security"))] ) diff --git a/dashboard/frontend/src/routes/CcConnect.svelte b/dashboard/frontend/src/routes/CcConnect.svelte deleted file mode 100644 index 7d72a9e..0000000 --- a/dashboard/frontend/src/routes/CcConnect.svelte +++ /dev/null @@ -1,155 +0,0 @@ - - -
-
-
-

cc-connect

-

Mobile bridge operational status

-
- up - down -
-
-
- {#if health?.container_status === "running"} - - {:else} - - {/if} - -
-
- - {#if requestError} -
-

cc-connect action failed

-

{requestError}

-
- {/if} - -
- {#if loading && !health} -
-
-
- {#each Array(8) as _} -
- {/each} -
-
- {:else if health} -
-

Health Status

- {valueOrDash(health.status)} -
- -
-
-

OK

-

{String(Boolean(health.ok))}

-
- -
-

Source

-

{valueOrDash(health.source)}

-
- -
-

Container

-

{valueOrDash(health.container_name)}

-
- -
-

Container Status

-

{valueOrDash(health.container_status)}

-
- -
-

Endpoint

-

{valueOrDash(health.endpoint)}

-
- -
-

HTTP Status

-

{valueOrDash(health.http_status)}

-
- -
-

Latency

-

{health.latency_ms === null || health.latency_ms === undefined ? "—" : `${health.latency_ms} ms`}

-
- -
-

Error

-

{valueOrDash(health.error)}

-
-
- {:else} -

No health data available.

- {/if} -
-
diff --git a/dashboard/frontend/src/routes/Docker.svelte b/dashboard/frontend/src/routes/Docker.svelte deleted file mode 100644 index 0f7d578..0000000 --- a/dashboard/frontend/src/routes/Docker.svelte +++ /dev/null @@ -1,160 +0,0 @@ - - -
-
-
-

Docker

-

{containers.length} containers · {containers.filter(c => c.status === "running").length} running

-
- -
- - {#if loading} -
- {#each Array(5) as _} -
- {/each} -
- {:else if error} -
-
-
- -

{error}

-
- -
-
- {:else} -
- {#each containers as c} -
-
- - {#if c.status === "running"} - - - {:else} - - {/if} - -
-

{c.name}

-

{c.image}

-
-
-
- {#if c.status === "running"} - - - {:else} - - {/if} - -
-
- {/each} -
- {/if} - - - {#if logTarget} - - {/if} -
diff --git a/dashboard/frontend/src/routes/InfoEngine.svelte b/dashboard/frontend/src/routes/InfoEngine.svelte deleted file mode 100644 index 25d7433..0000000 --- a/dashboard/frontend/src/routes/InfoEngine.svelte +++ /dev/null @@ -1,139 +0,0 @@ - - -
-
-
-

Info Engine

-

Context-aware stream of curated signals

-
- -
- - {#if requestError} -
-

{requestError}

-
- {/if} - -
-
-
- Latest items ({total}) -
- {#if loading} -
- {#each Array(6) as _} -
- {/each} -
- {:else if items.length === 0} -
No items yet.
- {:else} -
- {#each items as item} - - {/each} -
- {/if} -
- -
- {#if loadingDetail} -
-
-
-
-
-
- {:else if selectedItem} -

{selectedItem.title}

-
-

Source: {selectedItem.source}

-

Published: {formatDate(selectedItem.published_at)}

-

Collected: {formatDate(selectedItem.collected_at)}

-
- - {#if selectedItem.tags?.length} -
- {#each selectedItem.tags as tag} - {tag} - {/each} -
- {/if} - -

{selectedItem.summary || selectedItem.content_text || "No summary available."}

- - - Open source - - {:else} -

Select an item to view details.

- {/if} -
-
-
diff --git a/dashboard/frontend/src/routes/OpenClaw.svelte b/dashboard/frontend/src/routes/OpenClaw.svelte deleted file mode 100644 index 25a8e6d..0000000 --- a/dashboard/frontend/src/routes/OpenClaw.svelte +++ /dev/null @@ -1,66 +0,0 @@ - - -
-
-

OpenClaw

-

AI Assistant

-
- - {#if canAccess} -
-
- - - -
-

OpenClaw Ready

-

- OpenClaw's security settings prevent it from being embedded inside the dashboard. Click below to launch the assistant securely in a new tab. -

- - Launch OpenClaw - - - - -
- {:else} -
- - - -

Tailscale Network Required

-

- For security reasons, OpenClaw is only accessible when connected directly to the NAS via the internal Tailscale network. -

-

- Connect to Tailscale and visit http://100.78.131.124:4000 to use the AI Assistant. -

-
- {/if} -