Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions .beads/issues.jsonl
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{"id":"panvex-dd0","title":"Deploy Panvex to vpn_senko (panvex.azzazelvpn.ru)","description":"Stand up Panvex control-plane + co-located agent on vpn_senko (144.31.122.180) alongside existing traefik/3x-ui/discord-bot. Decisions captured in memory key panvex-senko-deploy-decisions-2026-04-27. Subtasks: (a) write deploy/senko/docker-compose.senko.yml (CP + agent + Telemt, SQLite storage), (b) write deploy/senko/senko.config.toml.template, (c) add traefik labels for panvex.azzazelvpn.ru:443 → CP :9080, (d) generate gRPC TLS cert for :9443, (e) UFW open :2443/:9443, (f) DNS A record panvex.azzazelvpn.ru → 144.31.122.180, (g) bootstrap admin user, (h) smoke test from local laptop.","acceptance_criteria":"panvex.azzazelvpn.ru loads panel over TLS; agent on vpn_senko reports presence; one Telemt client provisioned end-to-end via UI; deploy/senko/ committed.","notes":"Phase 2.1 COMPLETE (committed in 53934c5):\n ✓ deploy/senko/ scaffolded — docker-compose.senko.yml + config.toml + .env.example + README.md + deploy.sh\n ✓ Cross-arch deploy.sh: buildx linux/amd64 → docker save | ssh | docker load → rsync → compose up + ufw + bootstrap-admin + healthz smoke\n ✓ Two production bugs fixed mid-deploy:\n - Dockerfile: /var/lib/panvex needed pre-creation with panvex:panvex ownership (named volume mount otherwise lands as root:root, non-root user can't write SQLite DB)\n - docker-compose.senko.yml + bootstrap-admin in deploy.sh: ENTRYPOINT already declares the binary; `command:` and `docker compose run` args must list ONLY flags. Repeating the binary name shifts it into argv[1], where Go's flag.Parse stops at the first non-flag and silently drops every flag (including -config), causing fallback to the relative DefaultSQLiteDSN data/panvex.db (unwritable from WORKDIR /app under non-root user)\n ✓ Live verification:\n - https://panvex.azzazelvpn.ru/ → 200 OK (panel HTML)\n - POST /api/auth/login {admin/\u003cgen-pass\u003e} → 200 OK + session cookie\n - 144.31.122.180:9443 → TLSv1.3 + ALPN h2, cert CN=control-plane.panvex.internal, issuer=Panvex Control Plane Root CA (embedded)\n - Backend healthy, all 27 migrations ran clean\n - Admin password (one-shot, change on first login): ca9c7c108cb50d8f0b77d0c79f8156ef\n\nPhase 2.2 PENDING — moved to follow-up issue (see dependent issues).","status":"open","priority":2,"issue_type":"feature","owner":"d.shuvalov@test.com","created_at":"2026-04-27T09:41:38Z","created_by":"d.shuvalov","updated_at":"2026-04-27T11:07:11Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"memory","key":"effective-deepinit-dispatch-pattern-panvex-80-dirs-across","value":"Effective deepinit dispatch pattern (Panvex, ~80 dirs across Go backend + React frontend + infra): 7 parallel oh-my-claudecode:writer agents, one per subtree — (1) cmd/, (2) internal/agent/, (3) internal/controlplane/ (~25 dirs, biggest), (4) backend infra (internal/{dbsqlc,gatewayrpc,loadtest,security} + db/ + proto/ + deploy/ + scripts/ + .github*/ + docs/ + ref_systems root only), (5) web/ shell + features index, (6) web/src/features/* (28 dirs feature-sliced), (7) web/src/{ui,shared,locales,types} + web/tests/. One leaf was missed (web/src/ui/compositions/internal/) — fix-up afterwards. Validation: 'find -type d ... -prune ... | while read d; do [ -f \"$d/AGENTS.md\" ] || echo MISSING: $d; done' + first-line grep for 'Parent:'. Lesson: explicitly tell each writer agent NOT to touch the root AGENTS.md when it's a curated style guide; one agent narrated 'let me update root' but did not actually write — defensive instruction prevented the overwrite."}
{"_type":"memory","key":"panvex-is-a-fork-of-github-com-lost","value":"Panvex is a fork of github.com/lost-coder/panvex — fork note added to CLAUDE.md (lines 3-7) noting changes should stay rebase-friendly against upstream main. ref_systems/telemt vendored at repo root contains full upstream telemt source (Rust + Tokio MTProxy). User SSH host alias: vpn_senko maps to root@144.31.122.180:22 in ~/.ssh/config."}
{"_type":"memory","key":"vpn-senko-server-144-31-122-180-ubuntu","value":"vpn_senko server (144.31.122.180, Ubuntu 24.04, 1.9 GB RAM, 16 GB disk free, key-auth as root) currently runs: traefik v3.6.9 on :80/:443 (vpn-setup compose at /root/vpn-setup), 3x-ui Xray panel on :8080/:8443, discord-bot container, hysteria2 + vk-turn-server systemd. UFW open: 22, 80, 443, 8000, 8443, 8388. Marzban containers exited. Compose project: /root/vpn-setup/docker-compose.yml. Memory tight: 335 Mi free + 1.1 Gi cache, 86 Mi swap used — recommend SQLite mode for any new workload."}
{"_type":"memory","key":"deepinit-completed-for-panvex-on-2026-04-27","value":"Deepinit completed for Panvex on 2026-04-27: 117 total AGENTS.md (116 new + 1 preserved root). Hierarchy validated — every non-root file uses '\u003c!-- Parent: ../AGENTS.md --\u003e'. Coverage scope excludes ref_systems/telemt (vendored upstream — its own AGENTS.md kept intact), web/node_modules, cmd/control-plane/.embedded-ui, .git, .beads, .omc, .veai, .claude, .idea. Root AGENTS.md (curated agent style guide) intentionally NOT regenerated; the only +47 lines on it are pre-existing staged BEADS INTEGRATION block from prior session, working tree clean. CLAUDE.md got a fork-note pointing to github.com/lost-coder/panvex (lines 3-7). All 117 files + CLAUDE.md edit are uncommitted, awaiting user decision on commit timing relative to vpn_senko deploy work."}
{"_type":"memory","key":"panvex-deployment-to-vpn-senko-default-ports-collide","value":"Panvex deployment to vpn_senko: default ports collide with existing services. :443 owned by traefik, :8080 + :8443 owned by 3x-ui. Proposed remap awaiting user approval — Telemt MTProxy :2443, Panvex CP HTTP :9080, Panvex gRPC :9443, Telemt API/metrics on loopback :9091/:9090. Plan: standalone compose under /root/panvex, SQLite storage, no Traefik integration first pass. Pending decisions: port confirmation, domain/subdomain choice, whether deploy artifacts (deploy/docker-compose.senko.yml + senko.config.toml) get committed to repo, deepinit scope."}
{"_type":"memory","key":"panvex-docker-entrypoint-cmd-bug","value":"Panvex Dockerfile sets ENTRYPOINT [\"./panvex-control-plane\"]. Compose 'command:' must list ONLY flags, NEVER repeat the binary name — Docker concatenates ENTRYPOINT+CMD, and a duplicate binary in argv[1] causes Go's flag.Parse to stop at the first non-flag arg, silently dropping every flag (including -config). Symptom: backend restart loop with 'mkdir data: permission denied' because the legacy fallback uses DefaultSQLiteDSN='data/panvex.db' (relative, unwritable from WORKDIR /app under non-root user). Same trap applies to 'docker compose run --rm backend \u003ccmd\u003e' — pass only the subcommand + its flags (e.g. 'backend bootstrap-admin -username ...'), not the binary name. Fixed in deploy/senko/docker-compose.senko.yml + deploy/senko/deploy.sh on 2026-04-27."}
{"id":"panvex-dd0","title":"Deploy Panvex to vpn_senko (panvex.azzazelvpn.ru)","description":"Stand up Panvex control-plane + co-located agent on vpn_senko (144.31.122.180) alongside existing traefik/3x-ui/discord-bot. Decisions captured in memory key panvex-senko-deploy-decisions-2026-04-27. Subtasks: (a) write deploy/senko/docker-compose.senko.yml (CP + agent + Telemt, SQLite storage), (b) write deploy/senko/senko.config.toml.template, (c) add traefik labels for panvex.azzazelvpn.ru:443 → CP :9080, (d) generate gRPC TLS cert for :9443, (e) UFW open :2443/:9443, (f) DNS A record panvex.azzazelvpn.ru → 144.31.122.180, (g) bootstrap admin user, (h) smoke test from local laptop.","acceptance_criteria":"panvex.azzazelvpn.ru loads panel over TLS; agent on vpn_senko reports presence; one Telemt client provisioned end-to-end via UI; deploy/senko/ committed.","notes":"Deploy completed across Phase 2.0–2.2 (commits 53934c5, 8fb9418, c976045 + UI deploys). Live at https://panvex.azzazelvpn.ru/. Topology + endpoints captured in memory project_senko_deploy.md / reference_panvex_endpoints.md.","status":"closed","priority":2,"issue_type":"feature","owner":"d.shuvalov@test.com","created_at":"2026-04-27T09:41:38Z","created_by":"d.shuvalov","updated_at":"2026-04-27T14:59:43Z","closed_at":"2026-04-27T14:59:43Z","dependency_count":0,"dependent_count":0,"comment_count":0}
{"_type":"memory","key":"panvex-senko-deploy-decisions-2026-04-27","value":"Panvex → vpn_senko deploy decisions (2026-04-27, locked): (1) Ports approved as proposed — Telemt MTProxy :2443 direct, Panvex CP HTTP :9080 (behind traefik, not exposed publicly), Panvex gRPC :9443 direct with own TLS, Telemt API/metrics on loopback :9091/:9090. (2) Panel reached via subdomain panvex.azzazelvpn.ru through existing traefik on :443 with letsencrypt cert. DNS A record for panvex.azzazelvpn.ru → 144.31.122.180 must be added. (3) gRPC :9443 NOT through traefik — bound to 0.0.0.0:9443 with own cert, UFW must open :9443. Agents connect to grpc://panvex.azzazelvpn.ru:9443 (or direct IP). (4) Deploy artifacts committed to repo at deploy/senko/ — docker-compose.senko.yml + senko.config.toml.template (real secrets stay server-side). UFW changes needed: open :2443 (Telemt) + :9443 (gRPC); :443 already open via traefik."}
{"_type":"memory","key":"panvex-sqlite-volume-permissions","value":"Panvex Dockerfile control-plane stage runs as USER panvex (uid 100), but the original image did NOT pre-create /var/lib/panvex with that ownership. Docker named-volume mount on /var/lib/panvex therefore lands as root:root drwxr-xr-x — panvex user cannot write the SQLite DB. Fix (committed 2026-04-27): added 'mkdir -p /var/lib/panvex \u0026\u0026 chown -R panvex:panvex /var/lib/panvex' to the alpine-based control-plane stage RUN in Dockerfile. Pre-existing bad volumes need 'docker compose down -v' + 'docker volume rm' before redeploy — the chown only applies on first volume init."}
{"_type":"memory","key":"panvex-docker-entrypoint-cmd-bug","value":"Panvex Dockerfile sets ENTRYPOINT [\"./panvex-control-plane\"]. Compose 'command:' must list ONLY flags, NEVER repeat the binary name — Docker concatenates ENTRYPOINT+CMD, and a duplicate binary in argv[1] causes Go's flag.Parse to stop at the first non-flag arg, silently dropping every flag (including -config). Symptom: backend restart loop with 'mkdir data: permission denied' because the legacy fallback uses DefaultSQLiteDSN='data/panvex.db' (relative, unwritable from WORKDIR /app under non-root user). Same trap applies to 'docker compose run --rm backend \u003ccmd\u003e' — pass only the subcommand + its flags (e.g. 'backend bootstrap-admin -username ...'), not the binary name. Fixed in deploy/senko/docker-compose.senko.yml + deploy/senko/deploy.sh on 2026-04-27."}
{"_type":"memory","key":"panvex-phase-2.2-plan-2026-04-27","value":"Phase 2.2 (panvex-39x) execution plan, agreed before coding: (1) Dockerfile — add 'agent' target (cmd/agent → panvex-agent, alpine, state dir /var/lib/panvex-agent). (2) deploy/senko/docker-compose.senko.yml — add two services: telemt (ghcr.io/telemt/telemt:latest, host :2443, loopback api :9091 + metrics :9090, named volume) and panvex-agent (depends on telemt+backend, state volume, PANVEX_GRPC_ENDPOINT=144.31.122.180:9443, PANVEX_TELEMT_API=http://telemt:9091; won't start until bootstrapped). (3) deploy.sh — after admin bootstrap: PUT /api/v1/admin/settings/panel grpc_public_endpoint=144.31.122.180:9443 (CRITICAL — else bootstrap response defaults to :8443 from request Host, see internal/controlplane/server/http_enrollment.go:616 bootstrapGatewayAddress + defaultBootstrapGatewayAddress); login admin → CSRF → POST /api/v1/admin/agents/enrollment-tokens → capture value+ca_pem → docker compose run --rm panvex-agent bootstrap -token \u003cvalue\u003e → docker compose up -d panvex-agent; ufw allow 2443/tcp. (4) Verify: GET /api/v1/agents shows presence_state=online; one client created end-to-end. OPEN QUESTIONS pending user answer: (a) confirm Telemt image ghcr.io/telemt/telemt:latest exists / pin digest, (b) Fake-TLS SNI domain choice (proposed www.cloudflare.com), (c) client provisioning manual via UI or scripted in deploy.sh."}
{"_type":"memory","key":"effective-deepinit-dispatch-pattern-panvex-80-dirs-across","value":"Effective deepinit dispatch pattern (Panvex, ~80 dirs across Go backend + React frontend + infra): 7 parallel oh-my-claudecode:writer agents, one per subtree — (1) cmd/, (2) internal/agent/, (3) internal/controlplane/ (~25 dirs, biggest), (4) backend infra (internal/{dbsqlc,gatewayrpc,loadtest,security} + db/ + proto/ + deploy/ + scripts/ + .github*/ + docs/ + ref_systems root only), (5) web/ shell + features index, (6) web/src/features/* (28 dirs feature-sliced), (7) web/src/{ui,shared,locales,types} + web/tests/. One leaf was missed (web/src/ui/compositions/internal/) — fix-up afterwards. Validation: 'find -type d ... -prune ... | while read d; do [ -f \"$d/AGENTS.md\" ] || echo MISSING: $d; done' + first-line grep for 'Parent:'. Lesson: explicitly tell each writer agent NOT to touch the root AGENTS.md when it's a curated style guide; one agent narrated 'let me update root' but did not actually write — defensive instruction prevented the overwrite."}
{"_type":"memory","key":"panvex-deployment-to-vpn-senko-default-ports-collide","value":"Panvex deployment to vpn_senko: default ports collide with existing services. :443 owned by traefik, :8080 + :8443 owned by 3x-ui. Proposed remap awaiting user approval — Telemt MTProxy :2443, Panvex CP HTTP :9080, Panvex gRPC :9443, Telemt API/metrics on loopback :9091/:9090. Plan: standalone compose under /root/panvex, SQLite storage, no Traefik integration first pass. Pending decisions: port confirmation, domain/subdomain choice, whether deploy artifacts (deploy/docker-compose.senko.yml + senko.config.toml) get committed to repo, deepinit scope."}
{"_type":"memory","key":"vpn-senko-server-144-31-122-180-ubuntu","value":"vpn_senko server (144.31.122.180, Ubuntu 24.04, 1.9 GB RAM, 16 GB disk free, key-auth as root) currently runs: traefik v3.6.9 on :80/:443 (vpn-setup compose at /root/vpn-setup), 3x-ui Xray panel on :8080/:8443, discord-bot container, hysteria2 + vk-turn-server systemd. UFW open: 22, 80, 443, 8000, 8443, 8388. Marzban containers exited. Compose project: /root/vpn-setup/docker-compose.yml. Memory tight: 335 Mi free + 1.1 Gi cache, 86 Mi swap used — recommend SQLite mode for any new workload."}
{"_type":"memory","key":"deepinit-completed-for-panvex-on-2026-04-27","value":"Deepinit completed for Panvex on 2026-04-27: 117 total AGENTS.md (116 new + 1 preserved root). Hierarchy validated — every non-root file uses '\u003c!-- Parent: ../AGENTS.md --\u003e'. Coverage scope excludes ref_systems/telemt (vendored upstream — its own AGENTS.md kept intact), web/node_modules, cmd/control-plane/.embedded-ui, .git, .beads, .omc, .veai, .claude, .idea. Root AGENTS.md (curated agent style guide) intentionally NOT regenerated; the only +47 lines on it are pre-existing staged BEADS INTEGRATION block from prior session, working tree clean. CLAUDE.md got a fork-note pointing to github.com/lost-coder/panvex (lines 3-7). All 117 files + CLAUDE.md edit are uncommitted, awaiting user decision on commit timing relative to vpn_senko deploy work."}
{"_type":"memory","key":"panvex-is-a-fork-of-github-com-lost","value":"Panvex is a fork of github.com/lost-coder/panvex — fork note added to CLAUDE.md (lines 3-7) noting changes should stay rebase-friendly against upstream main. ref_systems/telemt vendored at repo root contains full upstream telemt source (Rust + Tokio MTProxy). User SSH host alias: vpn_senko maps to root@144.31.122.180:22 in ~/.ssh/config."}
15 changes: 15 additions & 0 deletions web/src/ui-kit.css
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,21 @@
}
}

/* WCAG 2.3.3 / Apple HIG reduced-motion: collapse every animation and
transition to a single tick. Each --animate-* keyframe above (breathe,
blink, beacon-glow, led-blink, alert-pulse) ends at its visible
state, so iteration-count:1 lands users on a sane static frame. */
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.001ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.001ms !important;
scroll-behavior: auto !important;
}
}

/* ─── Back-compat aliases for raw `var(--color-*)` consumers ──────────────
The pre-v4 CSS exposed --color-bg, --color-fg, etc. at :root so
hand-written CSS could reference them directly (e.g. the body rule here,
Expand Down