mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-07-26 11:49:16 +00:00
chore: GitHub workflow revamp — GitHub Flow, community files, CI updates (#101)
* chore: add comprehensive .gitignore * ci: update CI workflow for GitHub Flow - Change triggers from develop to main (PRs to main + pushes to main) - Add concurrency controls to cancel stale runs - Update docker/build-push-action to v6 - Add descriptive job names for branch protection status checks - Update screenshot refresh and docs sync to trigger on main pushes * ci: update docker-publish for GitHub Flow - Remove develop branch trigger (no more dev tag) - Keep v* tag trigger for releases - Update docker/build-push-action to v6 * docs: add community and governance files - CONTRIBUTING.md with dev setup and PR guidelines - SECURITY.md with vulnerability reporting policy - CODE_OF_CONDUCT.md (Contributor Covenant v2.1 reference) - PR template with conventional commits checklist - Issue templates for bug reports and feature requests - CODEOWNERS defaulting to @AnsoCode - Dependabot config for npm (root, backend, frontend) and GitHub Actions * docs: add README with badges, quick start, and contributing section * chore: add LICENSE placeholder and open license decision issue (#100) * docs: update CLAUDE.md for GitHub Flow branching model - Replace develop-based Git Flow with GitHub Flow (main only) - All branches now created off main, PRs target main - Simplify release checklist (no develop-to-main merge step) - Update testing strategy to reference Vitest and Playwright - Fix docs.json reference (was mint.json) * chore: track CLAUDE.md in version control Remove CLAUDE.md from .gitignore so project workflow instructions are versioned alongside the code they govern. * docs: add MANUAL_STEPS.md for GitHub settings that require UI configuration
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
# Default owner for everything
|
||||||
|
* @AnsoCode
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
name: Bug Report
|
||||||
|
description: Report a bug in Sencho
|
||||||
|
labels: ["bug"]
|
||||||
|
body:
|
||||||
|
- type: textarea
|
||||||
|
id: description
|
||||||
|
attributes:
|
||||||
|
label: Describe the bug
|
||||||
|
placeholder: A clear description of the bug
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: reproduce
|
||||||
|
attributes:
|
||||||
|
label: Steps to reproduce
|
||||||
|
placeholder: |
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '...'
|
||||||
|
3. See error
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: expected
|
||||||
|
attributes:
|
||||||
|
label: Expected behavior
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: input
|
||||||
|
id: version
|
||||||
|
attributes:
|
||||||
|
label: Sencho version
|
||||||
|
placeholder: "0.2.2"
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: dropdown
|
||||||
|
id: deployment
|
||||||
|
attributes:
|
||||||
|
label: Deployment method
|
||||||
|
options:
|
||||||
|
- Docker Compose
|
||||||
|
- Docker run
|
||||||
|
- Development (npm run dev)
|
||||||
|
- Other
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: input
|
||||||
|
id: browser
|
||||||
|
attributes:
|
||||||
|
label: Browser (if UI issue)
|
||||||
|
placeholder: "Chrome 120, Firefox 121, etc."
|
||||||
|
- type: textarea
|
||||||
|
id: logs
|
||||||
|
attributes:
|
||||||
|
label: Relevant logs
|
||||||
|
description: Paste any relevant container or browser console logs
|
||||||
|
render: shell
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
name: Feature Request
|
||||||
|
description: Suggest a new feature for Sencho
|
||||||
|
labels: ["enhancement"]
|
||||||
|
body:
|
||||||
|
- type: textarea
|
||||||
|
id: problem
|
||||||
|
attributes:
|
||||||
|
label: Problem or motivation
|
||||||
|
description: What problem does this feature solve? Why do you need it?
|
||||||
|
placeholder: I'm always frustrated when...
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: solution
|
||||||
|
attributes:
|
||||||
|
label: Proposed solution
|
||||||
|
description: Describe the feature you'd like to see
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: alternatives
|
||||||
|
attributes:
|
||||||
|
label: Alternatives considered
|
||||||
|
description: Any workarounds or alternative approaches you've considered
|
||||||
|
- type: dropdown
|
||||||
|
id: scope
|
||||||
|
attributes:
|
||||||
|
label: Feature scope
|
||||||
|
options:
|
||||||
|
- Dashboard / UI
|
||||||
|
- Stack management
|
||||||
|
- Multi-node / remote nodes
|
||||||
|
- App Store
|
||||||
|
- Observability / Logs
|
||||||
|
- Settings / Configuration
|
||||||
|
- Docker / Infrastructure
|
||||||
|
- API
|
||||||
|
- Other
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
## What does this PR do?
|
||||||
|
|
||||||
|
<!-- Brief description of the change -->
|
||||||
|
|
||||||
|
## Related Issue
|
||||||
|
|
||||||
|
<!-- Link to issue: Closes #123 -->
|
||||||
|
|
||||||
|
## Checklist
|
||||||
|
|
||||||
|
- [ ] Tests added/updated (if applicable)
|
||||||
|
- [ ] Documentation updated (if applicable)
|
||||||
|
- [ ] ESLint passes (`npm run lint` in backend/ and frontend/)
|
||||||
|
- [ ] Commit messages follow Conventional Commits
|
||||||
|
- [ ] CHANGELOG.md updated under `## [Unreleased]` (for user-facing changes)
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: "npm"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
|
labels:
|
||||||
|
- "dependencies"
|
||||||
|
open-pull-requests-limit: 10
|
||||||
|
|
||||||
|
- package-ecosystem: "npm"
|
||||||
|
directory: "/backend"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
|
labels:
|
||||||
|
- "dependencies"
|
||||||
|
open-pull-requests-limit: 10
|
||||||
|
|
||||||
|
- package-ecosystem: "npm"
|
||||||
|
directory: "/frontend"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
|
labels:
|
||||||
|
- "dependencies"
|
||||||
|
open-pull-requests-limit: 10
|
||||||
|
|
||||||
|
- package-ecosystem: "github-actions"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
|
labels:
|
||||||
|
- "ci"
|
||||||
+19
-14
@@ -2,12 +2,18 @@ name: Sencho CI
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ main, develop ]
|
branches: [main]
|
||||||
push:
|
push:
|
||||||
branches: [ develop ]
|
branches: [main]
|
||||||
|
|
||||||
|
# Cancel previous runs on the same branch/PR
|
||||||
|
concurrency:
|
||||||
|
group: ci-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
backend:
|
backend:
|
||||||
|
name: Backend (Build, Test, Lint)
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Code
|
- name: Checkout Code
|
||||||
@@ -41,6 +47,7 @@ jobs:
|
|||||||
run: npm audit --audit-level=high
|
run: npm audit --audit-level=high
|
||||||
|
|
||||||
frontend:
|
frontend:
|
||||||
|
name: Frontend (Build, Lint)
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Code
|
- name: Checkout Code
|
||||||
@@ -70,6 +77,7 @@ jobs:
|
|||||||
run: npm audit --audit-level=high
|
run: npm audit --audit-level=high
|
||||||
|
|
||||||
docker-validate:
|
docker-validate:
|
||||||
|
name: Docker Build & Scan
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Code
|
- name: Checkout Code
|
||||||
@@ -79,7 +87,7 @@ jobs:
|
|||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
- name: Build Docker image (validation only)
|
- name: Build Docker image (validation only)
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
push: false
|
push: false
|
||||||
@@ -98,6 +106,7 @@ jobs:
|
|||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
|
|
||||||
e2e:
|
e2e:
|
||||||
|
name: E2E Tests (Playwright)
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [backend, frontend]
|
needs: [backend, frontend]
|
||||||
steps:
|
steps:
|
||||||
@@ -163,9 +172,10 @@ jobs:
|
|||||||
retention-days: 7
|
retention-days: 7
|
||||||
|
|
||||||
update-screenshots:
|
update-screenshots:
|
||||||
|
name: Refresh Doc Screenshots
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
# Only on develop pushes; skip bot commits to avoid an infinite loop
|
# Only on main pushes (merged PRs); skip bot commits to avoid infinite loop
|
||||||
if: "github.event_name == 'push' && github.ref == 'refs/heads/develop' && !contains(github.event.head_commit.message, 'docs: refresh screenshots')"
|
if: "github.event_name == 'push' && github.ref == 'refs/heads/main' && !contains(github.event.head_commit.message, 'docs: refresh screenshots')"
|
||||||
needs: [backend, frontend]
|
needs: [backend, frontend]
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
@@ -174,8 +184,6 @@ jobs:
|
|||||||
- name: Checkout Code
|
- name: Checkout Code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
# PAT required — GITHUB_TOKEN cannot create PRs against a protected
|
|
||||||
# branch. DOCS_REPO_TOKEN is a classic PAT with repo scope.
|
|
||||||
token: ${{ secrets.DOCS_REPO_TOKEN }}
|
token: ${{ secrets.DOCS_REPO_TOKEN }}
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
@@ -234,7 +242,7 @@ jobs:
|
|||||||
branch: chore/refresh-screenshots
|
branch: chore/refresh-screenshots
|
||||||
commit-message: "docs: refresh screenshots"
|
commit-message: "docs: refresh screenshots"
|
||||||
title: "docs: refresh screenshots"
|
title: "docs: refresh screenshots"
|
||||||
body: "Automated screenshot refresh — generated by the `update-screenshots` CI job on every push to `develop`."
|
body: "Automated screenshot refresh — generated by the `update-screenshots` CI job on push to `main`."
|
||||||
add-paths: docs/images/
|
add-paths: docs/images/
|
||||||
delete-branch: true
|
delete-branch: true
|
||||||
|
|
||||||
@@ -248,8 +256,9 @@ jobs:
|
|||||||
--repo ${{ github.repository }}
|
--repo ${{ github.repository }}
|
||||||
|
|
||||||
sync-docs:
|
sync-docs:
|
||||||
|
name: Sync Docs to sencho-docs
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: github.event_name == 'push' && github.ref == 'refs/heads/develop'
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Sencho repo
|
- name: Checkout Sencho repo
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@@ -260,8 +269,6 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
DOCS_TOKEN: ${{ secrets.DOCS_REPO_TOKEN }}
|
DOCS_TOKEN: ${{ secrets.DOCS_REPO_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
# Always start clean so a previous partial/broken checkout can't cause
|
|
||||||
# "not in a git directory" on subsequent steps.
|
|
||||||
rm -rf sencho-docs
|
rm -rf sencho-docs
|
||||||
|
|
||||||
REMOTE="https://x-access-token:${DOCS_TOKEN}@github.com/AnsoCode/sencho-docs.git"
|
REMOTE="https://x-access-token:${DOCS_TOKEN}@github.com/AnsoCode/sencho-docs.git"
|
||||||
@@ -278,8 +285,6 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Copy /docs into sencho-docs root
|
- name: Copy /docs into sencho-docs root
|
||||||
# --exclude='.git' prevents rsync --delete from wiping the .git
|
|
||||||
# directory that was just cloned/initialized in the previous step.
|
|
||||||
run: rsync -av --delete --exclude='.git' sencho/docs/ sencho-docs/
|
run: rsync -av --delete --exclude='.git' sencho/docs/ sencho-docs/
|
||||||
|
|
||||||
- name: Commit and push to sencho-docs
|
- name: Commit and push to sencho-docs
|
||||||
@@ -288,5 +293,5 @@ jobs:
|
|||||||
git config user.email "docs-bot@sencho.io"
|
git config user.email "docs-bot@sencho.io"
|
||||||
git config user.name "Sencho Docs Bot"
|
git config user.name "Sencho Docs Bot"
|
||||||
git add -A
|
git add -A
|
||||||
git commit -m "docs: sync from develop@${{ github.sha }}" || echo "No changes to commit"
|
git commit -m "docs: sync from main@${{ github.sha }}" || echo "No changes to commit"
|
||||||
git push origin HEAD:main
|
git push origin HEAD:main
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ name: Build and Publish Docker Image
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
|
||||||
- develop
|
|
||||||
tags:
|
tags:
|
||||||
- 'v*'
|
- 'v*'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
@@ -36,14 +34,11 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
images: saelix/sencho
|
images: saelix/sencho
|
||||||
tags: |
|
tags: |
|
||||||
# If pushing to develop, tag as 'dev'
|
|
||||||
type=raw,value=dev,enable=${{ github.ref == 'refs/heads/develop' }}
|
|
||||||
# If pushing a v* tag, tag as 'latest' and the specific semver version
|
|
||||||
type=raw,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/v') }}
|
type=raw,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/v') }}
|
||||||
type=semver,pattern={{version}},enable=${{ startsWith(github.ref, 'refs/tags/v') }}
|
type=semver,pattern={{version}},enable=${{ startsWith(github.ref, 'refs/tags/v') }}
|
||||||
|
|
||||||
- name: Build and push Docker image
|
- name: Build and push Docker image
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
push: true
|
push: true
|
||||||
|
|||||||
+21
-7
@@ -1,7 +1,5 @@
|
|||||||
# Dependencies
|
# Dependencies
|
||||||
node_modules/
|
node_modules/
|
||||||
frontend/node_modules/
|
|
||||||
backend/node_modules/
|
|
||||||
|
|
||||||
# Environment Variables (CRITICAL: Never commit secrets)
|
# Environment Variables (CRITICAL: Never commit secrets)
|
||||||
.env
|
.env
|
||||||
@@ -10,8 +8,6 @@ backend/node_modules/
|
|||||||
|
|
||||||
# Build Outputs
|
# Build Outputs
|
||||||
dist/
|
dist/
|
||||||
frontend/dist/
|
|
||||||
backend/dist/
|
|
||||||
|
|
||||||
# Sencho User Data & Mocks
|
# Sencho User Data & Mocks
|
||||||
data/
|
data/
|
||||||
@@ -22,13 +18,31 @@ sencho.json
|
|||||||
# OS Generated Files
|
# OS Generated Files
|
||||||
.DS_Store
|
.DS_Store
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
Desktop.ini
|
||||||
|
ehthumbs.db
|
||||||
|
|
||||||
#PRD
|
# IDE / Editors
|
||||||
Product Requirements Document
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
|
*.sublime-project
|
||||||
|
*.sublime-workspace
|
||||||
|
|
||||||
|
# Testing
|
||||||
|
test-results/
|
||||||
|
e2e/report/
|
||||||
|
html-report/
|
||||||
|
.coverage/
|
||||||
|
coverage/
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
|
||||||
# Claude Code
|
# Claude Code
|
||||||
.claude/
|
.claude/
|
||||||
CLAUDE.md
|
|
||||||
plans/
|
plans/
|
||||||
|
|
||||||
# Playwright MCP
|
# Playwright MCP
|
||||||
|
|||||||
@@ -0,0 +1,271 @@
|
|||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
> **Every session:** Read this file fully before starting any task.
|
||||||
|
> **Every commit:** Before committing, run through the checklist below.
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
|
||||||
|
Sencho is a self-hosted Docker Compose management dashboard - a React + Express full-stack app that provides a GUI for managing Docker Compose stacks.
|
||||||
|
**Architecture Model:** It uses a "Distributed API" model. It manages local stacks directly. To manage remote nodes, it acts as a transparent HTTP/WebSocket proxy, routing requests to other autonomous Sencho instances running on those remote servers via long-lived JWT Bearer tokens.
|
||||||
|
|
||||||
|
## Development Commands
|
||||||
|
|
||||||
|
### Backend
|
||||||
|
```bash
|
||||||
|
cd backend
|
||||||
|
npm install
|
||||||
|
npm run dev # nodemon + ts-node, watches src/
|
||||||
|
npm run build # tsc → dist/
|
||||||
|
npm start # node dist/index.js (production)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Frontend
|
||||||
|
```bash
|
||||||
|
cd frontend
|
||||||
|
npm install
|
||||||
|
npm run dev # Vite dev server (proxies /api → localhost:3000)
|
||||||
|
npm run build # tsc -b && vite build
|
||||||
|
npm run lint # ESLint 9 flat config
|
||||||
|
npm run preview # preview production build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Full Docker build
|
||||||
|
```bash
|
||||||
|
docker build -t sencho . # multi-stage: frontend build → backend build → runtime
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Versioning & Release Flow
|
||||||
|
|
||||||
|
Sencho uses **Semantic Versioning** (`MAJOR.MINOR.PATCH`) driven by **Conventional Commits** and automated by the `release-please` GitHub Action.
|
||||||
|
|
||||||
|
### How it works (GitHub Flow)
|
||||||
|
|
||||||
|
1. Create a short-lived feature branch off `main` (e.g., `feat/my-feature`, `fix/my-bug`).
|
||||||
|
2. Commit using conventional commit prefixes (see below).
|
||||||
|
3. Open a PR into `main`. CI runs automatically.
|
||||||
|
4. Once CI is green, merge the PR (squash-merge recommended for clean history).
|
||||||
|
5. On every push to `main`, the `release-please` workflow automatically opens or updates a **Release PR** titled `chore(main): release vX.Y.Z`. This PR contains:
|
||||||
|
- An updated `CHANGELOG.md` entry generated from commit messages.
|
||||||
|
- A `package.json` version bump.
|
||||||
|
6. When you're ready to publish, **merge the Release PR**. This triggers:
|
||||||
|
- A `vX.Y.Z` git tag created by release-please.
|
||||||
|
- The `docker-publish.yml` workflow fires on the tag → builds and pushes `latest` + `X.Y.Z` to Docker Hub.
|
||||||
|
|
||||||
|
> You never create tags manually. Merging the Release PR is the only release action required.
|
||||||
|
> There is no `develop` branch. `main` is the only long-lived branch.
|
||||||
|
|
||||||
|
### Conventional Commit format
|
||||||
|
|
||||||
|
```
|
||||||
|
<type>(optional scope): <short description>
|
||||||
|
|
||||||
|
# Examples
|
||||||
|
fix(auth): prevent login loop on remote node 401
|
||||||
|
feat(app-store): add category filter pill bar
|
||||||
|
feat!: replace SSH with Distributed API proxy ← BREAKING CHANGE
|
||||||
|
docs(quickstart): update Docker run command
|
||||||
|
chore(deps): bump express to 4.19.2
|
||||||
|
ci: add arm64 platform to docker-publish
|
||||||
|
```
|
||||||
|
|
||||||
|
### Version bump rules
|
||||||
|
|
||||||
|
| Commit type | Example | Version bump |
|
||||||
|
|---|---|---|
|
||||||
|
| `fix:` / `perf:` / `revert:` | Bug fixes, perf improvements | `PATCH` — 0.1.0 → 0.1.1 |
|
||||||
|
| `feat:` | New user-facing feature | `MINOR` — 0.1.x → 0.2.0 |
|
||||||
|
| `feat!:` / `BREAKING CHANGE:` footer | Breaking API or UX change | `MAJOR` — 0.x.y → 1.0.0 |
|
||||||
|
| `docs:` / `chore:` / `ci:` / `test:` / `refactor:` | Infrastructure, no user impact | No bump (hidden in CHANGELOG) |
|
||||||
|
|
||||||
|
> While the version is `0.x`, `feat:` bumps the **minor** digit (0.1 → 0.2), not the patch. `fix:` still bumps patch (0.1.0 → 0.1.1). A `feat!:` will bump to `1.0.0`.
|
||||||
|
|
||||||
|
### Enriching the auto-generated Release PR
|
||||||
|
|
||||||
|
release-please generates CHANGELOG entries from commit subject lines. If a change deserves more context (e.g. a security fix or complex feature), **edit the Release PR description and CHANGELOG entry directly** before merging — release-please preserves manual edits on subsequent updates.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Architecture & Request Flow
|
||||||
|
|
||||||
|
### The Distributed API Proxy Flow
|
||||||
|
1. **Frontend:** Makes API calls via `apiFetch` (`frontend/src/lib/api.ts`), which injects the `x-node-id` header (or `?nodeId=` query param for WebSockets) from `NodeContext`.
|
||||||
|
2. **Backend Gateway (`index.ts`):** The `nodeContextMiddleware` evaluates the node ID.
|
||||||
|
- **If Local:** The request passes through standard auth and hits the local Express route handlers.
|
||||||
|
- **If Remote:** The request hits `http-proxy-middleware`. The backend strips the `x-node-id` header, injects `Authorization: Bearer <api_token>`, and seamlessly proxies the entire HTTP or WebSocket request to the remote Sencho instance's `api_url`.
|
||||||
|
|
||||||
|
### Backend Services (`backend/src/services/`)
|
||||||
|
All core services execute **locally only**. (Remote execution is handled by proxying the request to the remote Sencho instance, which then executes locally on its own machine).
|
||||||
|
- **`DockerController`** - Dockerode wrapper for local containers, images, volumes, networks, stats, exec.
|
||||||
|
- **`ComposeService`** - Spawns `docker compose` CLI child processes locally.
|
||||||
|
- **`FileSystemService`** - Simple `fs.promises` wrapper. All reads/writes happen against the local `COMPOSE_DIR`.
|
||||||
|
- **`DatabaseService`** - SQLite via `better-sqlite3`. Stores alerts, settings, metrics, and node routing configs at `/app/data/sencho.db`.
|
||||||
|
- **`NodeRegistry`** - Manages node configurations. Returns the local Docker socket for local ops, and returns `{ api_url, api_token }` targets for remote proxies.
|
||||||
|
|
||||||
|
### Frontend Structure
|
||||||
|
- **`App.tsx`** - Root router: setup flow → login → `EditorLayout`.
|
||||||
|
- **`context/AuthContext.tsx`** - JWT auth state; handles first-boot setup detection.
|
||||||
|
- **`context/NodeContext.tsx`** - Active node selection state.
|
||||||
|
- **`components/NodeManager.tsx`** - UI for adding nodes (requires Name, Sencho API URL, and API Token).
|
||||||
|
- **`lib/api.ts`** - `apiFetch` wrapper that handles headers and 401 redirects.
|
||||||
|
|
||||||
|
### Authentication
|
||||||
|
- **Browser-to-Backend:** JWT stored in `httpOnly` cookies.
|
||||||
|
- **Node-to-Node (Proxy):** Long-lived JWT passed via `Authorization: Bearer <token>` header.
|
||||||
|
- **Middleware:** `authMiddleware` accepts *both* cookies and Bearer tokens seamlessly.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🛑 AGENT DIRECTIVES (CRITICAL INSTRUCTIONS)
|
||||||
|
|
||||||
|
To prevent hallucinations, regressions, and context loss, you MUST adhere to the following rules:
|
||||||
|
|
||||||
|
**1. Targeted Reading of index.ts (Avoid Full-File Context Waste)**
|
||||||
|
- Before modifying `index.ts`, do NOT read the entire ~1500-line file. Read only the relevant section: Lines 50-250 (Auth/Setup), Lines 300-500 (Stacks/Compose), Lines 550-750 (Docker Entities), Lines 800-1000 (System/Metrics), Lines 1050-1250 (Nodes/Proxy), Lines 1300+ (WebSockets/Errors).
|
||||||
|
- For middleware ordering, check lines 100-300.
|
||||||
|
- Confirm exact placement by searching for the prefix.
|
||||||
|
|
||||||
|
2. **Respect the Architecture:**
|
||||||
|
- We do NOT use SSH, SFTP, or remote Docker TCP sockets. For remote file reading, you must use the HTTP Proxy model.
|
||||||
|
- Ensure `http-proxy-middleware` catches remote requests before local route handlers.
|
||||||
|
|
||||||
|
3. **Limit Repetition & Be Concise:**
|
||||||
|
- Do not output massive blocks of unchanged code. Use precise edits, diffs, or surgical replacements.
|
||||||
|
- Do not over-explain your steps unless asked. State your intent, perform the file modifications, and report the result.
|
||||||
|
|
||||||
|
4. **Strict GitHub Flow & Conventional Commits:**
|
||||||
|
- All feature work and bug fixes must happen on a newly created branch off `main`.
|
||||||
|
- **Every commit MUST use a conventional commit prefix** (`fix:`, `feat:`, `docs:`, `chore:`, `ci:`, `refactor:`, `test:`, `perf:`). This is what drives automated versioning — no prefix means no version bump and no CHANGELOG entry.
|
||||||
|
- Update `CHANGELOG.md` under `## [Unreleased]` before committing (the auto-generated entry from release-please will be terse; add context here for significant changes).
|
||||||
|
- Stage, commit, push to `origin`, and **open a PR into `main`**. This is required to trigger automated CI/CD actions.
|
||||||
|
- **Do NOT manually create git tags or push version commits.** Versioning is fully automated by `release-please` — it fires on every push to `main` and creates the Release PR automatically.
|
||||||
|
|
||||||
|
5. **Strict Security & API Standards:**
|
||||||
|
- **Default Deny:** EVERY new endpoint in `index.ts` under `/api/` MUST be protected by `authMiddleware` unless explicitly designated as public.
|
||||||
|
- **SQL Injection Prevention:** ALWAYS use `better-sqlite3` parameterized statements. Do not manually sanitize or string-escape inputs.
|
||||||
|
- **No Secrets in Code:** Never hardcode secrets. Rely on `DatabaseService.getInstance().getGlobalSettings()`.
|
||||||
|
|
||||||
|
6. **UX & UI Engineering Constraints:**
|
||||||
|
- Use only Tailwind CSS and existing `shadcn/ui` components.
|
||||||
|
- Handle loading states. Every frontend API call must be wrapped in `try/catch`.
|
||||||
|
- When using `sonner` toast, use this exact defensive pattern: `toast.error(error?.message || error?.error || error?.data?.error || 'Something went wrong.');`
|
||||||
|
- Do not assume `error` is a standard Error instance.
|
||||||
|
|
||||||
|
7. **Backend Error Handling:**
|
||||||
|
- **Do Not Swallow Errors:** Do not write empty `catch` blocks.
|
||||||
|
- **Standardized Responses:** If a backend operation fails, log the actual error to the console for debugging, but return a clean, standard JSON error to the frontend: `res.status(500).json({ error: "Clear message" });`.
|
||||||
|
- **No Server Crashes:** Ensure all asynchronous proxy streams (WebSockets/SSE) have robust error handling and `.on('error')` listeners to prevent the Node event loop from crashing.
|
||||||
|
|
||||||
|
8. **WebSocket Nuances & Middleware Bypasses:**
|
||||||
|
- Express middlewares (`authMiddleware`, `nodeContextMiddleware`, `cookieParser`) **DO NOT RUN** on WebSocket (`server.on('upgrade')`) connections.
|
||||||
|
- You MUST manually parse cookies/headers and manually execute `jwt.verify()` inside the `upgrade` event handler.
|
||||||
|
- Extract `nodeId` from URL query parameters (`?nodeId=`) for WebSockets, NOT from the `x-node-id` header.
|
||||||
|
|
||||||
|
9. **Filesystem Security & Path Traversal:**
|
||||||
|
- Perform strict directory traversal validation at the Express route level before any `FileSystemService` call.
|
||||||
|
- Use this exact pattern: `const safePath = path.resolve(COMPOSE_DIR, stackName, filename);` `if (!safePath.startsWith(path.resolve(COMPOSE_DIR))) { return res.status(400).json({ error: 'Invalid path' }); }`
|
||||||
|
- Reject inputs with `..` or absolute paths.
|
||||||
|
|
||||||
|
10. **React Dependency Traps (Infinite Loops):**
|
||||||
|
- Be extremely cautious fixing `react-hooks/exhaustive-deps` warnings in global context files like `NodeContext.tsx`.
|
||||||
|
- We intentionally use `useRef` (e.g., `activeNodeRef`) to hold current state inside `useCallback` functions. **DO NOT blindly add state variables to dependency arrays** to satisfy ESLint, as it will trigger infinite API-fetching loops.
|
||||||
|
|
||||||
|
11. **The Monolithic index.ts Constraint:**
|
||||||
|
- The backend `index.ts` file is currently a monolith (~1500 lines).
|
||||||
|
- Continue appending new routes into their logical groups (e.g., Auth, Stacks, System, Nodes). **DO NOT** attempt to proactively split or refactor this file into a multi-router architecture unless explicitly instructed by the user.
|
||||||
|
|
||||||
|
12. **Environment & File System Context:**
|
||||||
|
- `FileSystemService` strictly operates against the `COMPOSE_DIR` environment variable.
|
||||||
|
- **DO NOT** hardcode `/app/compose` as an immutable path or implicitly assume it is the only path. It is merely the Docker default. Your code must dynamically read `process.env.COMPOSE_DIR` (or rely on `FileSystemService.getInstance(nodeId).getBaseDir()`) to respect each user's unique volume mounts or local OS paths.
|
||||||
|
|
||||||
|
13. **Mandatory Test Validation Before Completing Any Task:**
|
||||||
|
- Validate behavior before considering a task done.
|
||||||
|
- **Always kill existing services first** — do not assume a running process has the latest code (it may have been started with `npm start` or `node dist/index.js`, not nodemon):
|
||||||
|
```bash
|
||||||
|
kill $(lsof -ti:3000) 2>/dev/null; kill $(lsof -ti:5173) 2>/dev/null
|
||||||
|
```
|
||||||
|
- Then start fresh in the background using `npm run dev` (nodemon) only:
|
||||||
|
```bash
|
||||||
|
cd backend && npm run dev &
|
||||||
|
cd frontend && npm run dev &
|
||||||
|
```
|
||||||
|
- Wait for readiness before proceeding:
|
||||||
|
```bash
|
||||||
|
curl -s -o /dev/null -w "%{http_code}" http://localhost:3000/api/health # expect 200
|
||||||
|
curl -s -o /dev/null -w "%{http_code}" http://localhost:5173 # expect 200
|
||||||
|
```
|
||||||
|
- If Playwright MCP is available, use it to navigate and interact with the affected UI and confirm expected behavior.
|
||||||
|
- If Playwright is unavailable: explicitly state "Playwright validation unavailable; recommend manual testing: [describe exact steps]".
|
||||||
|
- **Always kill both services when done with validation** — never leave orphan processes:
|
||||||
|
```bash
|
||||||
|
kill $(lsof -ti:3000) 2>/dev/null; kill $(lsof -ti:5173) 2>/dev/null
|
||||||
|
```
|
||||||
|
- Explicitly confirm in your response that services have been stopped after validation.
|
||||||
|
- Never open a PR without documented validation.
|
||||||
|
|
||||||
|
14. **TypeScript Strictness Rules**
|
||||||
|
- `tsconfig.json` has `"strict": true`.
|
||||||
|
- Write code that compiles without `any` casts or `@ts-ignore`. Prefer proper types over `any`.
|
||||||
|
- If a library lacks types, import `@types/...` or use `unknown` + narrowing.
|
||||||
|
- Never add casts to silence errors.
|
||||||
|
|
||||||
|
15. **Testing Strategy Reference**
|
||||||
|
- **Backend unit tests:** Vitest (`cd backend && npm test`). Add tests for new backend logic.
|
||||||
|
- **E2E tests:** Playwright (`npm run test:e2e`). Covers auth, stack management, and node management flows.
|
||||||
|
- **Manual validation:** Use the Playwright MCP server for UI changes, or `curl` for backend-only changes.
|
||||||
|
- For UI changes: use the Playwright MCP server to navigate to `http://localhost:5173`, interact with the affected components, and confirm expected behavior.
|
||||||
|
- For backend-only changes: validate via `curl` against `localhost:3000/api/...` with a valid `Authorization: Bearer <token>` or session cookie.
|
||||||
|
|
||||||
|
16. **Environment Variables Reference**
|
||||||
|
- Read vars from `process.env` or `DatabaseService`.
|
||||||
|
- Never hardcode. Key vars: `COMPOSE_DIR` (base directory), `JWT_SECRET` (token signing), `PORT` (listen port), `NODE_ENV`. Check `.env.example` for the full list.
|
||||||
|
|
||||||
|
17. **Code Review Standards**
|
||||||
|
- After completing any implementation, review the code for:
|
||||||
|
- Functions longer than 30 lines (likely doing too much)
|
||||||
|
- Logic duplicated more than twice (extract to utility)
|
||||||
|
- Any `any` type usage in TypeScript (replace with real types)
|
||||||
|
- Components with more than 3 props that could be grouped into an object
|
||||||
|
- Missing error handling on async operations
|
||||||
|
- Run /simplify before presenting code to the user.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
Whenever you create, modify, or remove a user-facing feature, API endpoint, or configuration option, you MUST also update or create the relevant `.mdx` file inside the `/docs` folder.
|
||||||
|
- Follow the existing structure in `/docs/docs.json` navigation
|
||||||
|
- Write docs from the perspective of the end user, not internal implementation
|
||||||
|
- Use Mintlify MDX components where useful (e.g. `<Card>`, `<CodeGroup>`, `<Note>`)
|
||||||
|
- Add the new/updated doc page to the `navigation` array in `mint.json` if it's a new file
|
||||||
|
- Keep tone friendly and concise
|
||||||
|
|
||||||
|
### Screenshots
|
||||||
|
When adding or updating a doc page for a user-facing feature:
|
||||||
|
1. Follow the service lifecycle in Directive 13: kill any running processes on ports 3000/5173, restart with `npm run dev`, wait for readiness, and kill again when done
|
||||||
|
2. Use the Playwright MCP server to navigate to the relevant page/feature in the app
|
||||||
|
3. Take a screenshot and save it to `/docs/images/<feature-name>/<screenshot-name>.png`
|
||||||
|
4. Use descriptive filenames (e.g. `dashboard-overview.png`, `settings-dark-mode.png`)
|
||||||
|
5. For multi-step flows, highlight the relevant UI element by injecting a CSS border
|
||||||
|
before screenshotting: `element.style.border = '3px solid #0F172A'`
|
||||||
|
6. Reference screenshots in MDX files using:
|
||||||
|
`<img src="/images/<feature-name>/<screenshot-name>.png" alt="..." />`
|
||||||
|
or Mintlify's `<Frame>` component for a polished look:
|
||||||
|
`<Frame><img src="/images/..." alt="..." /></Frame>`
|
||||||
|
7. Always take screenshots at 1280x800 desktop resolution for consistency
|
||||||
|
|
||||||
|
## Pre-Commit Checklist
|
||||||
|
- [ ] Am I on a feature branch off `main`? (never commit to main directly)
|
||||||
|
- [ ] Does my commit message start with a conventional prefix? (`fix:`, `feat:`, `docs:`, `chore:`, `ci:`, `refactor:`, `test:`, `perf:`)
|
||||||
|
- [ ] Did I update CHANGELOG.md under `## [Unreleased]`? (add context beyond what the commit subject captures)
|
||||||
|
- [ ] Did I update or create the relevant `/docs/*.mdx` file?
|
||||||
|
- [ ] Did I take/update screenshots via Playwright MCP if UI changed?
|
||||||
|
- [ ] Did I validate behavior via Playwright MCP (UI) or `curl` (backend), and kill the dev servers afterwards? (Directive 13)
|
||||||
|
- [ ] Is the PR going into `main`?
|
||||||
|
|
||||||
|
## Release Checklist (when shipping to users)
|
||||||
|
- [ ] Is `main` stable and CI green?
|
||||||
|
- [ ] Wait for the `release-please` workflow to open the Release PR (titled `chore(main): release vX.Y.Z`).
|
||||||
|
- [ ] Review and optionally enrich the auto-generated CHANGELOG entry in the Release PR.
|
||||||
|
- [ ] Merge the Release PR → tag is created → Docker Hub `latest` + semver tags are published automatically.
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# Code of Conduct
|
||||||
|
|
||||||
|
This project follows the **Contributor Covenant Code of Conduct v2.1**.
|
||||||
|
|
||||||
|
The full text is available at: https://www.contributor-covenant.org/version/2/1/code_of_conduct/
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
We are committed to providing a friendly, safe, and welcoming environment for all contributors, regardless of experience level, identity, or background.
|
||||||
|
|
||||||
|
## Enforcement
|
||||||
|
|
||||||
|
Instances of unacceptable behavior may be reported to the project maintainers at **conduct@sencho.io**.
|
||||||
|
|
||||||
|
All reports will be reviewed and investigated promptly and fairly. Project maintainers are obligated to respect the privacy and security of the reporter.
|
||||||
|
|
||||||
|
## Attribution
|
||||||
|
|
||||||
|
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 2.1.
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
# Contributing to Sencho
|
||||||
|
|
||||||
|
Thank you for your interest in contributing to Sencho!
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
1. Fork the repository
|
||||||
|
2. Clone your fork: `git clone https://github.com/YOUR_USERNAME/Sencho.git`
|
||||||
|
3. Create a branch: `git checkout -b feature/your-feature`
|
||||||
|
4. Install dependencies:
|
||||||
|
```bash
|
||||||
|
cd backend && npm install
|
||||||
|
cd ../frontend && npm install
|
||||||
|
```
|
||||||
|
5. Start the dev servers:
|
||||||
|
```bash
|
||||||
|
cd backend && npm run dev # Express + nodemon on :3000
|
||||||
|
cd frontend && npm run dev # Vite on :5173
|
||||||
|
```
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
- **Backend:** Node.js + Express + TypeScript in `backend/`
|
||||||
|
- **Frontend:** React 19 + Vite + TypeScript in `frontend/`
|
||||||
|
- **Tests:** `cd backend && npm test` (Vitest) and `npm run test:e2e` (Playwright)
|
||||||
|
- **Lint:** `npm run lint` in both `backend/` and `frontend/`
|
||||||
|
|
||||||
|
## Pull Request Process
|
||||||
|
|
||||||
|
- All PRs target `main`
|
||||||
|
- Ensure CI passes before requesting review
|
||||||
|
- Use [Conventional Commits](https://www.conventionalcommits.org/) for commit messages
|
||||||
|
- Update documentation if your change affects user-facing behavior
|
||||||
|
- Add tests for new functionality
|
||||||
|
- Keep PRs focused — one feature or fix per PR
|
||||||
|
- Update `CHANGELOG.md` under `## [Unreleased]` for user-facing changes
|
||||||
|
|
||||||
|
## Reporting Bugs
|
||||||
|
|
||||||
|
Use the [bug report template](https://github.com/AnsoCode/Sencho/issues/new?template=bug_report.yml). Include: deployment method, Sencho version, browser (for UI issues), steps to reproduce, and expected vs actual behavior.
|
||||||
|
|
||||||
|
## Code Style
|
||||||
|
|
||||||
|
- TypeScript with `strict: true` — no `any` casts or `@ts-ignore`
|
||||||
|
- ESLint 9 flat config for both backend and frontend
|
||||||
|
- Tailwind CSS + shadcn/ui for frontend styling
|
||||||
|
- Follow existing patterns in the codebase
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
License pending — see https://github.com/AnsoCode/Sencho/issues/100
|
||||||
|
|
||||||
|
This project's license has not yet been finalized. The license decision is
|
||||||
|
being tracked in the issue linked above.
|
||||||
|
|
||||||
|
Until a license is chosen, all rights are reserved by the project maintainers.
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
# Manual Steps Required
|
||||||
|
|
||||||
|
These actions could not be performed automatically and need to be done manually in the GitHub UI.
|
||||||
|
|
||||||
|
## 1. Branch Protection Rules for `main`
|
||||||
|
|
||||||
|
Go to **Settings > Branches > Add branch ruleset** for `main`:
|
||||||
|
|
||||||
|
- [x] Require a pull request before merging
|
||||||
|
- Required approvals: 0 (solo dev — you merge your own PRs after CI passes)
|
||||||
|
- Dismiss stale reviews when new commits are pushed: ON
|
||||||
|
- [x] Require status checks to pass before merging
|
||||||
|
- Add these job names: `Backend (Build, Test, Lint)`, `Frontend (Build, Lint)`, `Docker Build & Scan`, `E2E Tests (Playwright)`
|
||||||
|
- [x] Require conversation resolution before merging
|
||||||
|
- [x] Do not allow bypassing the above settings (even you must go through PRs)
|
||||||
|
- [x] Do not allow deletions
|
||||||
|
- [ ] Require signed commits (optional — future improvement)
|
||||||
|
|
||||||
|
## 2. Repository Settings
|
||||||
|
|
||||||
|
Go to **Settings > General > Pull Requests**:
|
||||||
|
- [x] Check **"Automatically delete head branches"**
|
||||||
|
- [x] Set **squash merge** as default merge strategy
|
||||||
|
|
||||||
|
## 3. Security Settings
|
||||||
|
|
||||||
|
Go to **Settings > Code security and analysis**:
|
||||||
|
- [x] Enable **Dependabot alerts**
|
||||||
|
- [x] Enable **Dependabot security updates**
|
||||||
|
- [x] Enable **Secret scanning**
|
||||||
|
- [x] Enable **Secret scanning push protection**
|
||||||
|
- [x] Enable **Private vulnerability reporting**
|
||||||
|
|
||||||
|
## 4. Default Branch
|
||||||
|
|
||||||
|
Verify that `main` is set as the default branch:
|
||||||
|
- Go to **Settings > Branches > Default branch**
|
||||||
|
- Should already be `main`
|
||||||
|
|
||||||
|
## 5. Delete `develop` Branch (When Ready)
|
||||||
|
|
||||||
|
The `develop` branch has 1 unmerged commit (`37f751c docs: refresh screenshots`).
|
||||||
|
|
||||||
|
**Before deleting**, decide whether to:
|
||||||
|
- Cherry-pick that commit to main via a PR, OR
|
||||||
|
- Let it go (it's just a screenshot refresh)
|
||||||
|
|
||||||
|
Then delete via: **Branches page > delete `develop`**
|
||||||
|
|
||||||
|
Also clean up stale feature branches that have been merged:
|
||||||
|
- `chore/refresh-screenshots`
|
||||||
|
- `fix/editor-loading`
|
||||||
|
- `fix/release-please-config`
|
||||||
|
- `feat/automated-versioning`
|
||||||
|
- `fix/docker-publish-tag-trigger`
|
||||||
|
- `feat/arm64-docker-build`
|
||||||
|
- `chore/migrate-to-docs-json`
|
||||||
|
- `fix/sync-docs-rsync-excludes-git`
|
||||||
|
- `fix/ci-docs-jobs`, `fix/ci-docs-jobs-v2`
|
||||||
|
|
||||||
|
## 6. Delete This File
|
||||||
|
|
||||||
|
Once all manual steps are complete, delete `MANUAL_STEPS.md` from the repo.
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
# Sencho
|
||||||
|
|
||||||
|
[](https://github.com/AnsoCode/Sencho/actions/workflows/ci.yml)
|
||||||
|
[](https://hub.docker.com/r/saelix/sencho)
|
||||||
|
[](#license)
|
||||||
|
|
||||||
|
A self-hosted Docker Compose management dashboard. Manage your stacks, containers, images, volumes, and networks through a modern web UI.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Stack Management** — Create, edit, start, stop, and remove Docker Compose stacks with a built-in Monaco code editor
|
||||||
|
- **Multi-Node Support** — Manage remote Sencho instances through a transparent HTTP/WebSocket proxy (Distributed API model)
|
||||||
|
- **App Store** — One-click deployment from LinuxServer.io templates with editable ports, volumes, and environment variables
|
||||||
|
- **Resource Hub** — Browse and manage images, volumes, and networks with managed/external/unused classification
|
||||||
|
- **Live Logs** — Aggregated real-time log streaming across all containers with search and filtering
|
||||||
|
- **Dashboard** — Container stats, CPU/RAM metrics, health checks, and image update notifications
|
||||||
|
- **Alerts** — Configurable threshold alerts for CPU, RAM, and disk usage
|
||||||
|
- **Terminal** — In-browser host console and container exec via WebSocket
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
sencho:
|
||||||
|
image: saelix/sencho:latest
|
||||||
|
container_name: sencho
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- ./data:/app/data
|
||||||
|
# 1:1 Compose Path Rule: host path MUST match container path
|
||||||
|
- /opt/docker:/opt/docker
|
||||||
|
environment:
|
||||||
|
- COMPOSE_DIR=/opt/docker
|
||||||
|
- DATA_DIR=/app/data
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
Then open `http://your-server:3000` and create your admin account.
|
||||||
|
|
||||||
|
See the [full documentation](https://docs.sencho.io) for configuration details, multi-node setup, and more.
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Backend (Express + TypeScript)
|
||||||
|
cd backend && npm install && npm run dev
|
||||||
|
|
||||||
|
# Frontend (React + Vite)
|
||||||
|
cd frontend && npm install && npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
The frontend dev server proxies `/api` requests to the backend on port 3000.
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and PR guidelines.
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
See [SECURITY.md](SECURITY.md) for vulnerability reporting. **Do not open public issues for security vulnerabilities.**
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
License pending. See [issue #100](https://github.com/AnsoCode/Sencho/issues/100) for the license decision discussion and [LICENSE](LICENSE) for current status.
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
# Security Policy
|
||||||
|
|
||||||
|
## Supported Versions
|
||||||
|
|
||||||
|
| Version | Supported |
|
||||||
|
| ------- | ------------------ |
|
||||||
|
| 0.2.x | Yes |
|
||||||
|
| < 0.2 | No |
|
||||||
|
|
||||||
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
**Please do not open a public issue for security vulnerabilities.**
|
||||||
|
|
||||||
|
Instead, use GitHub's private vulnerability reporting:
|
||||||
|
|
||||||
|
1. Go to the [Security tab](https://github.com/AnsoCode/Sencho/security) of this repository
|
||||||
|
2. Click **"Report a vulnerability"**
|
||||||
|
3. Provide details including: steps to reproduce, impact assessment, and any suggested fixes
|
||||||
|
|
||||||
|
You can expect an initial response within 72 hours. We will work with you to understand and address the issue before any public disclosure.
|
||||||
|
|
||||||
|
## Security Considerations
|
||||||
|
|
||||||
|
Sencho manages Docker containers and has access to the Docker socket. When deploying:
|
||||||
|
|
||||||
|
- Always run behind a reverse proxy with TLS in production
|
||||||
|
- Use strong passwords and rotate JWT secrets
|
||||||
|
- Restrict network access to the Sencho port
|
||||||
|
- Review the [security configuration docs](https://docs.sencho.io) for hardening guidance
|
||||||
+1
-1
@@ -14,7 +14,7 @@
|
|||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "SEE LICENSE IN LICENSE",
|
||||||
"type": "commonjs",
|
"type": "commonjs",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/AnsoCode/Sencho/issues"
|
"url": "https://github.com/AnsoCode/Sencho/issues"
|
||||||
|
|||||||
Reference in New Issue
Block a user