Skip to content

Add panel Cloudflare sharing#313

Merged
skulidropek merged 12 commits into
mainfrom
issue-310
May 18, 2026
Merged

Add panel Cloudflare sharing#313
skulidropek merged 12 commits into
mainfrom
issue-310

Conversation

@skulidropek
Copy link
Copy Markdown
Member

Closes #310

Summary:

  • add API-managed Cloudflare Quick Tunnel lifecycle for sharing the docker-git panel
  • add Share screen with start/refresh/copy/open/stop controls
  • install cloudflared in the API image

Verification:

  • rtk bun run --cwd packages/api typecheck
  • rtk bun run --cwd packages/api lint
  • rtk bun run --cwd packages/api test
  • rtk bun run --cwd packages/app typecheck
  • rtk bun run --cwd packages/app lint
  • rtk bun run --cwd packages/app test
  • Playwright proof: local Share screen, running tunnel, public trycloudflare URL, stop flow

@skulidropek
Copy link
Copy Markdown
Member Author

skulidropek commented May 18, 2026

AI Session Backup

Commit: a5c5c88
Status: success
Files: 5 (4.23 MB)
Links: README | Manifest

git status

On branch issue-310
Your branch is up to date with 'origin/issue-310'.

nothing to commit, working tree clean

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 18, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 686ea233-06be-4451-9edd-da5ef84d1069

📥 Commits

Reviewing files that changed from the base of the PR and between e3b5fcd and 58ef159.

📒 Files selected for processing (1)
  • packages/api/src/services/panel-cloudflare-tunnel.ts
📜 Recent review details
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: E2E (OpenCode)
  • GitHub Check: E2E (Runtime volumes + SSH)
  • GitHub Check: E2E (Clone auto-open SSH)
  • GitHub Check: E2E (Browser command)
  • GitHub Check: E2E (Clone cache)
  • GitHub Check: E2E (Login context)
  • GitHub Check: Lint
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Implement Functional Core, Imperative Shell (FCIS) pattern: CORE layer contains only pure functions with immutable data and mathematical operations; SHELL layer isolates all effects (IO, network, database). Strict dependency direction: SHELL → CORE (never reverse).
Never use any, unknown, eslint-disable, ts-ignore, or as type assertions (except in rigorously justified cases with documentation). Always use exhaustive union type analysis through .exhaustive() pattern matching.
All external dependencies must be wrapped through typed interfaces and injected via Effect-TS Layer pattern. Never call external services directly from CORE functions.
Use monadic composition with Effect-TS for all effects: Effect<Success, Error, Requirements>. Compose effects through pipe() and Effect.flatMap(). Implement dependency injection via Layer pattern. Handle errors without try/catch blocks.
All functions must be pure in the CORE layer: no side effects (logging, console output, IO operations, mutations). Separate all side effects into the SHELL layer.
Use exhaustive pattern matching with Effect.Match instead of switch statements. Example: Match.value(item).pipe(Match.when(...), Match.exhaustive).
Document all functions with comprehensive TSDoc including: @pure (true/false), @effect (required services), @invariant (mathematical invariants), @precondition, @postcondition, @complexity (time and space), @throws Never (errors must be typed in Effect).
Use functional comment markers for code clarity: CHANGE (brief description), WHY (mathematical/architectural justification), QUOTE(ТЗ) (requirement citation), REF (RTM or message ID), SOURCE (external source with quote), FORMAT THEOREM (∀x ∈ Domain: P(x) → Q(f(x))), PURITY (CORE|SHELL), EFFECT (Effect type signature), INVARIANT (mathematical invariant), COMPLEXITY (time/space).
Define all external service dependencies as Context.Tag classes with fully typed methods returning Effect types. Example: `class Da...

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,js,jsx}: Forbidden constructs in CORE code: any, eslint-disable, ts-ignore, async/await, raw Promise chains (then/catch), Promise.all, try/catch for logic control, console.*, switch statements (use Match with .exhaustive() instead)
All functions must use Effect-TS for composing effects: Effect<Success, Error, Requirements>. No direct async/await, Promise chains, or try/catch in product logic.
Functional comments must include: CHANGE, WHY, QUOTE(ТЗ) or n/a, REF, SOURCE or n/a, FORMAT THEOREM, PURITY (CORE|SHELL), EFFECT signature for SHELL functions, INVARIANT, and COMPLEXITY.
All data mutations must use immutable patterns (ReadonlyArray, readonly properties, Object.freeze); mutation in SHELL only when absolutely necessary and documented.

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{sh,bash,py,js,ts,jsx,tsx,go,java,rb,php}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files introduce command injection or unsafe shell/process execution with user-controlled input

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{py,js,ts,jsx,tsx,go,java,rb,php,sh,bash,c,cpp}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files introduce path traversal or writes outside intended project/container state directories

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{js,ts,jsx,tsx,py,java,go,rb,php,sh,bash,yml,yaml,json,env*,toml,cfg,config,dockerfile,dockerignore}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files expose credentials, tokens, private-keys, or PII in source, generated config, logs, or CI output

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*

⚙️ CodeRabbit configuration file

**/*: Ты строгий ревьюер SPEC DRIVEN DEVELOPMENT.

Перед выводами изучи README.md, другие *.md файлы, linked issues,
PR description, PR comments/discussion и релевантную кодовую базу.

Сверь изменения с исходным ТЗ/спекой и обсуждением. Флагай любой уход
от спеки, недокументированное изменение поведения, отсутствие тестов
для заявленного поведения и security-риск. Если спека не видна,
попроси автора добавить ее в issue или PR description.

Проверь решение с точки зрения формальной верификации: какие инварианты,
предусловия и постусловия можно доказать математически, а где доказуемость
слабая. Оцени решение с точки зрения теории игр: устойчивы ли стимулы,
нет ли выгодного обхода правил, и какое решение было бы сильнее.

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
🧠 Learnings (1)
📚 Learning: 2026-05-18T07:43:38.131Z
Learnt from: skulidropek
Repo: ProverCoderAI/docker-git PR: 313
File: packages/api/src/services/panel-cloudflare-tunnel.ts:123-135
Timestamp: 2026-05-18T07:43:38.131Z
Learning: In this repo’s ProverCoderAI/docker-git architecture, it is intentional for service modules under packages/api/src/services/ to call Node.js APIs directly (e.g., fs, child_process, fetch). Do not treat direct Node API usage in these service modules as a dependency-injection (DI) violation. This codebase provides the NodeContext at the program boundary (entry point) rather than injecting Context.Tag/Layer services into individual service modules; reviewers should only flag DI/context issues if the expected boundary setup is missing.

Applied to files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
🔇 Additional comments (7)
packages/api/src/services/panel-cloudflare-tunnel.ts (7)

1-33: LGTM!


35-117: LGTM!


119-142: LGTM!


144-306: LGTM!


308-358: LGTM!


360-429: LGTM!


431-489: LGTM!


📝 Walkthrough

Summary by CodeRabbit

  • Новые возможности
    • Добавлена панель "Share": управление Cloudflare‑туннелем (запуск/остановка), отображение статуса, лог‑хвост и публичный URL с открытием/копированием; интеграция в меню, экран, хоткеи и быстрые действия.
  • API
    • Введены типы, схемы и новые HTTP‑эндпоинты для чтения/старта/остановки сессии туннеля; клиентские обёртки для взаимодействия.
  • Тесты
    • Добавлены и расширены тесты: валидация схем, резолв целевого URL, парсинг вывода, клиентские сценарии старт/стоп и копирования URL.
  • Chores
    • Обновлён контейнер: установка cloudflared и сопутствующих пакетов для среды запуска.

Walkthrough

PR добавляет backend-сервис управления cloudflared (резольвер panelUrl, запуск процесса, preflight, лог‑tail, graceful shutdown), HTTP endpoints GET/POST/DELETE, обновлённый Dockerfile с установкой cloudflared, frontend API/типы/state, actions (refresh/start/stop/copy), UI экран Share и набор unit/property тестов.

Changes

Cloudflare Tunnel Panel Sharing

Layer / File(s) Summary
Backend API контракты и схема
packages/api/src/api/contracts.ts, packages/api/src/api/schema.ts, packages/api/tests/schema.test.ts
Добавлены типы PanelCloudflareTunnelStatus, PanelCloudflareTunnelSession, StartPanelCloudflareTunnelRequest и схема StartPanelCloudflareTunnelRequestSchema с соответствующими тестами.
Backend HTTP endpoints и Dockerfile
packages/api/src/http.ts, packages/api/Dockerfile
Добавлены reader для body и маршруты GET/POST/DELETE /cloudflare-tunnels/panel; cloudflared добавлен в образ через APT-репозиторий.
Backend URL-парсинг и резольвер (core)
packages/api/src/services/panel-cloudflare-tunnel-core.ts, packages/api/tests/panel-cloudflare-tunnel-core.test.ts
Нормализация panelUrl, детект loopback/private диапазонов, запрет .trycloudflare.com, parseTryCloudflareUrl и resolvePanelTunnelTargetUrl; покрыто unit и property-based тестами.
Backend cloudflared сервис
packages/api/src/services/panel-cloudflare-tunnel.ts
In-memory запись сессии, spawn cloudflared, tail логов, извлечение publicUrl, preflight fetch, polling ожидания, graceful shutdown (SIGTERM/SIGKILL), cleanup; публичные API readPanelCloudflareTunnel, startPanelCloudflareTunnel, stopPanelCloudflareTunnel.
Frontend схемы, API клиент и типы
packages/app/src/web/api-schema.ts, packages/app/src/web/api-share.ts, packages/app/src/web/api-types.ts, packages/app/src/web/api.ts, packages/app/src/web/api-state-types.ts
Effect Schema для статуса/сессии, клиентские функции loadPanelCloudflareTunnel, startPanelCloudflareTunnel, stopPanelCloudflareTunnel и экспорт типов через публичный API.
Frontend состояние и контекст
packages/app/src/web/actions-shared.ts, packages/app/src/web/app-ready-state.ts, packages/app/src/web/app-ready-actions.ts, packages/app/src/web/app-ready-controller-context.ts
Добавлены panelCloudflareTunnel и setPanelCloudflareTunnel в ReadyState/BrowserActionContext и прокинуты через createActionContext.
Frontend действия (refresh/start/stop/copy)
packages/app/src/web/actions-share.ts, packages/app/src/web/actions.ts, packages/app/src/web/app-ready-controller.ts
Реализованы actions для управления туннелем с проверкой origin (блокировка *.trycloudflare.com), обновлением контекста и уведомлениями; добавлены в контроллер и меню.
Frontend UI и экран Share
packages/app/src/web/panel-share.tsx, packages/app/src/web/app-ready-main-panels.tsx, packages/app/src/web/app-ready-layout.tsx
Компонент SharePanel с отображением статуса, public URL, логов и кнопок управления; новый ShareScreen и передача handlers в ReadyLayout.
Frontend меню и навигация
packages/app/src/web/menu.ts, packages/app/src/web/screen.ts, packages/app/src/web/app-ready-url.ts, packages/app/src/web/panel-layout.tsx, packages/app/src/web/panel-content.tsx, packages/app/src/web/app-ready-shortcuts.ts, packages/app/src/web/app-ready.tsx, packages/app/src/web/actions-projects.ts, packages/app/src/web/github-auth-gate.ts
Новый BrowserMenuTag "Share", slug share, интеграция в порядок меню, mapping экрана, compact label, исключение из staticPanels и поддержка шорткатов.
Frontend автозагрузка и хуки
packages/app/src/web/app-ready-hooks.ts
Автозапрос состояния tunnel при открытии Share; изменение раннего return для совместимости с Share; добавлена зависимость на panelCloudflareTunnel.
Тесты и фикстуры
packages/api/tests/panel-cloudflare-tunnel-core.test.ts, packages/app/tests/docker-git/actions-share.test.ts, packages/app/tests/docker-git/*
Unit и property-based тесты для резолвера URL, схем, frontend actions и routing; фикстуры расширены для контекста и clipboard.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-310

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/app/src/web/app-ready-hooks.ts (1)

123-129: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Не отключайте refresh GitHub auth на меню Share.

Сейчас ветка currentMenu === "Share" полностью пропускает refreshAuthPanel(context), хотя в этом слое по стеку ожидается обновление GitHub auth и для Share. В итоге githubStatus может остаться null на всём экране Share, пока пользователь не уйдёт в другой menu.

Лучше сохранить загрузку Share-экрана без раннего return, но сам refresh auth здесь всё равно вызвать.

💡 Возможный фикс
-const maybeRefreshGithubStatus = ({ context, currentMenu, githubStatus }: PanelAutoloadArgs): boolean => {
-  if (githubStatus !== null || currentMenu === "Share") {
+const maybeRefreshGithubStatus = ({ context, githubStatus }: PanelAutoloadArgs): boolean => {
+  if (githubStatus !== null) {
     return false
   }
   refreshAuthPanel(context)
   return true
 }
@@
-  if (maybeRefreshGithubStatus(args)) {
+  if (maybeRefreshGithubStatus(args) && args.currentMenu !== "Share") {
     return
   }

As per coding guidelines, "Сверь изменения с исходным ТЗ/спекой и обсуждением. Флагай любой уход от спеки, недокументированное изменение поведения, отсутствие тестов для заявленного поведения и security-риск."

Also applies to: 164-170

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/app/src/web/app-ready-hooks.ts` around lines 123 - 129, Функция
maybeRefreshGithubStatus пропускает вызов refreshAuthPanel при currentMenu ===
"Share", в результате githubStatus остаётся null на экране Share; измените
логику так, чтобы refreshAuthPanel(context) вызывался когда githubStatus ===
null независимо от currentMenu (т.е. удалите/измените ветку, которая раннее
возвращала при currentMenu === "Share"), при этом сохранить возвращаемое
значение true когда refresh вызван и false когда ничего не делается; смотрите
идентификаторы maybeRefreshGithubStatus, PanelAutoloadArgs, githubStatus,
currentMenu и refreshAuthPanel для правки (аналогично поправьте другой похожий
участок с той же проблемой).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/api/Dockerfile`:
- Around line 37-39: The Dockerfile currently downloads cloudflared via "curl
... /tmp/cloudflared.deb" and installs it with "dpkg -i", which makes the image
unreproducible and untrusted; replace that sequence (the curl to cloudflared.deb
+ dpkg -i + rm) with adding Cloudflare's signed APT repository and key and
installing cloudflared via apt (mirror the pattern used for the NVIDIA repo),
i.e., import pkg.cloudflare.com GPG key into /usr/share/keyrings, add the
"cloudflared" apt source with signed-by, run apt-get update, then apt-get
install -y cloudflared; if the environment cannot use the APT repo instead pin a
specific cloudflared version URL (not /latest) and verify/checksum before
installing.

In `@packages/api/src/services/panel-cloudflare-tunnel-core.ts`:
- Around line 63-82: Функция resolvePanelTunnelTargetUrl сейчас позволяет
произвольные хосты как targetUrl; нужно ограничить целевые адреса только
адресами панели (локалхост/LAN). После normalizePanelUrl и создания URL в
resolvePanelTunnelTargetUrl проверяй target.hostname: если
isLocalPanelHostname(target.hostname) — ок; иначе отклоняй запрос и возвращай
объект с ok: false (или соответствующей ошибкой) вместо пропуска произвольного
хоста. Используй существующую isLocalPanelHostname (и при необходимости дополни
её проверками LAN/loopback) и изменяй поведение resolvePanelTunnelTargetUrl так,
чтобы любые не-панельные хосты не конвертировались и не возвращались в
targetUrl.

In `@packages/api/src/services/panel-cloudflare-tunnel.ts`:
- Line 29: currentRecord is accessed concurrently causing races when
starting/stopping cloudflared; serialize all reads/writes and process spawn/kill
around currentRecord by adding an async mutex/semaphore and acquiring it in the
start/stop code paths that touch currentRecord (e.g., the functions that spawn
cloudflared and the functions that kill/clear currentRecord referenced around
lines ~29 and ~290-315). Hold the lock for the whole critical section (check
currentRecord, start/stop the process, and assign/clear currentRecord), use
try/finally to always release the lock, and return early or queue requests while
the lock is held to prevent multiple cloudflared processes from being started
concurrently.

In `@packages/api/tests/panel-cloudflare-tunnel-core.test.ts`:
- Around line 29-35: Add a unit test to ensure resolvePanelTunnelTargetUrl
rejects non-panel hostnames: create a new test case (similar to the existing
trycloudflare one) that calls resolvePanelTunnelTargetUrl with a target like
"https://example.com" (or an internal IP/hostname) and asserts the returned
object has ok: false (and an appropriate error message), and also assert
isTryCloudflareHostname(...) remains false for that input; this guards against
regressions in resolvePanelTunnelTargetUrl and ties the behavior to the existing
isTryCloudflareHostname and resolvePanelTunnelTargetUrl functions.

In `@packages/api/tests/schema.test.ts`:
- Around line 355-369: Add a negative unit test for
StartPanelCloudflareTunnelRequestSchema using the same Effect test pattern
(it.effect + Effect.sync) that passes an invalid panelUrl (e.g., panelUrl: 123
or omit panelUrl) into Schema.decodeUnknownEither and asserts the decoder
rejects; locate the existing test that calls
Schema.decodeUnknownEither(StartPanelCloudflareTunnelRequestSchema) and add a
sibling test which uses Either.match to expect the onLeft branch (or assert
Either.isLeft) and, if it unexpectedly succeeds, throw the formatted error via
ParseResult.TreeFormatter.formatIssueSync(error.issue) so the failure is
explicit and follows the project's Effect-based testing style.

In `@packages/app/src/web/actions-share.ts`:
- Around line 78-83: The copyPanelShareTunnelUrl function currently fires
navigator.clipboard.writeText(publicUrl) without awaiting or handling rejections
and calls context.setMessage("Tunnel URL copied.") unconditionally; change it to
await (or return) the writeText promise, handle success and failure (e.g., use
.then/.catch or async/try-catch) so the success message is shown only on
successful copy and an error message is shown on rejection, and consider
wrapping the operation with the existing withBusy pattern used by
loadPanelCloudflareTunnel/startPanelCloudflareTunnel/stopPanelCloudflareTunnel
to keep UX consistent; target the copyPanelShareTunnelUrl function and the call
sites of navigator.clipboard.writeText when making this change.

In `@packages/app/src/web/api-share.ts`:
- Around line 6-24: Add the required TSDoc and functional comment block above
each exported function (loadPanelCloudflareTunnel, startPanelCloudflareTunnel,
stopPanelCloudflareTunnel): include a descriptive summary, `@pure`, `@effect`,
`@invariant`, `@precondition`, `@postcondition` and `@complexity` tags in the TSDoc, and
a functional markers section containing CHANGE, WHY, QUOTE or n/a, REF, SOURCE
or n/a, FORMAT THEOREM, PURITY, an EFFECT signature describing the observable
effects (e.g., network request type and endpoint), INVARIANT, and COMPLEXITY;
ensure the documentation accurately describes inputs (panelUrl for
startPanelCloudflareTunnel), return shape (Effect of response.tunnel), and any
failure modes, and place the block immediately above each function declaration.

In `@packages/app/src/web/github-auth-gate.ts`:
- Around line 30-33: The condition in the auth gating logic currently allows the
"Share" menu to bypass GitHub authentication (currentMenu, githubStatus,
shouldRequireGithubAuth), which may be intentional but needs explicit
confirmation and user-facing clarity; update the code by either (A) keeping the
behavior but adding a clear inline comment near the gate explaining that Share
intentionally bypasses GitHub auth so users can start a Cloudflare tunnel with
the dashboard's current state, and ensure the Share flow (the code paths invoked
when currentMenu === "Share") displays a warning/tooltip that the tunnel will
expose the dashboard as-is, or (B) if this was not intended, change the
condition to require GitHub auth for "Share" like other protected menus by
removing "Share" from the exempt list and relying on
shouldRequireGithubAuth(githubStatus); reference currentMenu, githubStatus, and
shouldRequireGithubAuth to locate and apply the change.

---

Outside diff comments:
In `@packages/app/src/web/app-ready-hooks.ts`:
- Around line 123-129: Функция maybeRefreshGithubStatus пропускает вызов
refreshAuthPanel при currentMenu === "Share", в результате githubStatus остаётся
null на экране Share; измените логику так, чтобы refreshAuthPanel(context)
вызывался когда githubStatus === null независимо от currentMenu (т.е.
удалите/измените ветку, которая раннее возвращала при currentMenu === "Share"),
при этом сохранить возвращаемое значение true когда refresh вызван и false когда
ничего не делается; смотрите идентификаторы maybeRefreshGithubStatus,
PanelAutoloadArgs, githubStatus, currentMenu и refreshAuthPanel для правки
(аналогично поправьте другой похожий участок с той же проблемой).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: b14c7b28-5004-447b-a499-141f8cb6a959

📥 Commits

Reviewing files that changed from the base of the PR and between 6ab8042 and a5c5c88.

📒 Files selected for processing (37)
  • packages/api/Dockerfile
  • packages/api/src/api/contracts.ts
  • packages/api/src/api/schema.ts
  • packages/api/src/http.ts
  • packages/api/src/services/panel-cloudflare-tunnel-core.ts
  • packages/api/src/services/panel-cloudflare-tunnel.ts
  • packages/api/tests/panel-cloudflare-tunnel-core.test.ts
  • packages/api/tests/schema.test.ts
  • packages/app/src/web/actions-projects.ts
  • packages/app/src/web/actions-share.ts
  • packages/app/src/web/actions-shared.ts
  • packages/app/src/web/actions.ts
  • packages/app/src/web/api-schema.ts
  • packages/app/src/web/api-share.ts
  • packages/app/src/web/api-state-types.ts
  • packages/app/src/web/api-types.ts
  • packages/app/src/web/api.ts
  • packages/app/src/web/app-ready-actions.ts
  • packages/app/src/web/app-ready-controller-context.ts
  • packages/app/src/web/app-ready-controller.ts
  • packages/app/src/web/app-ready-hooks.ts
  • packages/app/src/web/app-ready-layout.tsx
  • packages/app/src/web/app-ready-main-panels.tsx
  • packages/app/src/web/app-ready-shortcuts.ts
  • packages/app/src/web/app-ready-state.ts
  • packages/app/src/web/app-ready-url.ts
  • packages/app/src/web/app-ready.tsx
  • packages/app/src/web/github-auth-gate.ts
  • packages/app/src/web/menu.ts
  • packages/app/src/web/panel-content.tsx
  • packages/app/src/web/panel-layout.tsx
  • packages/app/src/web/panel-share.tsx
  • packages/app/src/web/screen.ts
  • packages/app/tests/docker-git/actions-share.test.ts
  • packages/app/tests/docker-git/app-ready-shortcuts.test.ts
  • packages/app/tests/docker-git/app-ready-url.test.ts
  • packages/app/tests/docker-git/browser-action-context-fixture.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Implement Functional Core, Imperative Shell (FCIS) pattern: CORE layer contains only pure functions with immutable data and mathematical operations; SHELL layer isolates all effects (IO, network, database). Strict dependency direction: SHELL → CORE (never reverse).
Never use any, unknown, eslint-disable, ts-ignore, or as type assertions (except in rigorously justified cases with documentation). Always use exhaustive union type analysis through .exhaustive() pattern matching.
All external dependencies must be wrapped through typed interfaces and injected via Effect-TS Layer pattern. Never call external services directly from CORE functions.
Use monadic composition with Effect-TS for all effects: Effect<Success, Error, Requirements>. Compose effects through pipe() and Effect.flatMap(). Implement dependency injection via Layer pattern. Handle errors without try/catch blocks.
All functions must be pure in the CORE layer: no side effects (logging, console output, IO operations, mutations). Separate all side effects into the SHELL layer.
Use exhaustive pattern matching with Effect.Match instead of switch statements. Example: Match.value(item).pipe(Match.when(...), Match.exhaustive).
Document all functions with comprehensive TSDoc including: @pure (true/false), @effect (required services), @invariant (mathematical invariants), @precondition, @postcondition, @complexity (time and space), @throws Never (errors must be typed in Effect).
Use functional comment markers for code clarity: CHANGE (brief description), WHY (mathematical/architectural justification), QUOTE(ТЗ) (requirement citation), REF (RTM or message ID), SOURCE (external source with quote), FORMAT THEOREM (∀x ∈ Domain: P(x) → Q(f(x))), PURITY (CORE|SHELL), EFFECT (Effect type signature), INVARIANT (mathematical invariant), COMPLEXITY (time/space).
Define all external service dependencies as Context.Tag classes with fully typed methods returning Effect types. Example: `class Da...

Files:

  • packages/app/tests/docker-git/app-ready-url.test.ts
  • packages/api/src/api/schema.ts
  • packages/app/src/web/app-ready-controller-context.ts
  • packages/api/src/api/contracts.ts
  • packages/api/tests/schema.test.ts
  • packages/app/src/web/api-state-types.ts
  • packages/app/src/web/app-ready-shortcuts.ts
  • packages/app/src/web/panel-share.tsx
  • packages/app/tests/docker-git/actions-share.test.ts
  • packages/app/src/web/api-types.ts
  • packages/api/src/services/panel-cloudflare-tunnel-core.ts
  • packages/app/src/web/github-auth-gate.ts
  • packages/app/src/web/actions-projects.ts
  • packages/app/tests/docker-git/app-ready-shortcuts.test.ts
  • packages/app/src/web/panel-layout.tsx
  • packages/app/src/web/api.ts
  • packages/app/src/web/api-share.ts
  • packages/app/src/web/app-ready-url.ts
  • packages/api/tests/panel-cloudflare-tunnel-core.test.ts
  • packages/app/src/web/app-ready-controller.ts
  • packages/app/src/web/actions-shared.ts
  • packages/app/src/web/app-ready.tsx
  • packages/api/src/http.ts
  • packages/app/src/web/api-schema.ts
  • packages/app/src/web/app-ready-main-panels.tsx
  • packages/app/src/web/menu.ts
  • packages/app/src/web/actions.ts
  • packages/app/src/web/app-ready-actions.ts
  • packages/app/src/web/app-ready-state.ts
  • packages/app/src/web/screen.ts
  • packages/app/src/web/app-ready-hooks.ts
  • packages/app/src/web/app-ready-layout.tsx
  • packages/app/src/web/panel-content.tsx
  • packages/app/tests/docker-git/browser-action-context-fixture.ts
  • packages/app/src/web/actions-share.ts
  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.test.{ts,tsx}: Implement property-based testing using fast-check for mathematical properties and invariants. Example: fc.property(fc.array(messageArbitrary), (messages) => isChronologicallySorted(sortMessagesByTimestamp(messages))).
Mock external dependencies in unit tests using Effect's testing utilities. Run tests without Effect runtime for speed. Example: Effect.provide(MockService), Effect.runPromise.

Files:

  • packages/app/tests/docker-git/app-ready-url.test.ts
  • packages/api/tests/schema.test.ts
  • packages/app/tests/docker-git/actions-share.test.ts
  • packages/app/tests/docker-git/app-ready-shortcuts.test.ts
  • packages/api/tests/panel-cloudflare-tunnel-core.test.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,js,jsx}: Forbidden constructs in CORE code: any, eslint-disable, ts-ignore, async/await, raw Promise chains (then/catch), Promise.all, try/catch for logic control, console.*, switch statements (use Match with .exhaustive() instead)
All functions must use Effect-TS for composing effects: Effect<Success, Error, Requirements>. No direct async/await, Promise chains, or try/catch in product logic.
Functional comments must include: CHANGE, WHY, QUOTE(ТЗ) or n/a, REF, SOURCE or n/a, FORMAT THEOREM, PURITY (CORE|SHELL), EFFECT signature for SHELL functions, INVARIANT, and COMPLEXITY.
All data mutations must use immutable patterns (ReadonlyArray, readonly properties, Object.freeze); mutation in SHELL only when absolutely necessary and documented.

Files:

  • packages/app/tests/docker-git/app-ready-url.test.ts
  • packages/api/src/api/schema.ts
  • packages/app/src/web/app-ready-controller-context.ts
  • packages/api/src/api/contracts.ts
  • packages/api/tests/schema.test.ts
  • packages/app/src/web/api-state-types.ts
  • packages/app/src/web/app-ready-shortcuts.ts
  • packages/app/src/web/panel-share.tsx
  • packages/app/tests/docker-git/actions-share.test.ts
  • packages/app/src/web/api-types.ts
  • packages/api/src/services/panel-cloudflare-tunnel-core.ts
  • packages/app/src/web/github-auth-gate.ts
  • packages/app/src/web/actions-projects.ts
  • packages/app/tests/docker-git/app-ready-shortcuts.test.ts
  • packages/app/src/web/panel-layout.tsx
  • packages/app/src/web/api.ts
  • packages/app/src/web/api-share.ts
  • packages/app/src/web/app-ready-url.ts
  • packages/api/tests/panel-cloudflare-tunnel-core.test.ts
  • packages/app/src/web/app-ready-controller.ts
  • packages/app/src/web/actions-shared.ts
  • packages/app/src/web/app-ready.tsx
  • packages/api/src/http.ts
  • packages/app/src/web/api-schema.ts
  • packages/app/src/web/app-ready-main-panels.tsx
  • packages/app/src/web/menu.ts
  • packages/app/src/web/actions.ts
  • packages/app/src/web/app-ready-actions.ts
  • packages/app/src/web/app-ready-state.ts
  • packages/app/src/web/screen.ts
  • packages/app/src/web/app-ready-hooks.ts
  • packages/app/src/web/app-ready-layout.tsx
  • packages/app/src/web/panel-content.tsx
  • packages/app/tests/docker-git/browser-action-context-fixture.ts
  • packages/app/src/web/actions-share.ts
  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Property-based tests (fast-check) must verify mathematical invariants; unit tests must use Effect test utilities without async/await.

Files:

  • packages/app/tests/docker-git/app-ready-url.test.ts
  • packages/api/tests/schema.test.ts
  • packages/app/tests/docker-git/actions-share.test.ts
  • packages/app/tests/docker-git/app-ready-shortcuts.test.ts
  • packages/api/tests/panel-cloudflare-tunnel-core.test.ts
**/*.{sh,bash,py,js,ts,jsx,tsx,go,java,rb,php}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files introduce command injection or unsafe shell/process execution with user-controlled input

Files:

  • packages/app/tests/docker-git/app-ready-url.test.ts
  • packages/api/src/api/schema.ts
  • packages/app/src/web/app-ready-controller-context.ts
  • packages/api/src/api/contracts.ts
  • packages/api/tests/schema.test.ts
  • packages/app/src/web/api-state-types.ts
  • packages/app/src/web/app-ready-shortcuts.ts
  • packages/app/src/web/panel-share.tsx
  • packages/app/tests/docker-git/actions-share.test.ts
  • packages/app/src/web/api-types.ts
  • packages/api/src/services/panel-cloudflare-tunnel-core.ts
  • packages/app/src/web/github-auth-gate.ts
  • packages/app/src/web/actions-projects.ts
  • packages/app/tests/docker-git/app-ready-shortcuts.test.ts
  • packages/app/src/web/panel-layout.tsx
  • packages/app/src/web/api.ts
  • packages/app/src/web/api-share.ts
  • packages/app/src/web/app-ready-url.ts
  • packages/api/tests/panel-cloudflare-tunnel-core.test.ts
  • packages/app/src/web/app-ready-controller.ts
  • packages/app/src/web/actions-shared.ts
  • packages/app/src/web/app-ready.tsx
  • packages/api/src/http.ts
  • packages/app/src/web/api-schema.ts
  • packages/app/src/web/app-ready-main-panels.tsx
  • packages/app/src/web/menu.ts
  • packages/app/src/web/actions.ts
  • packages/app/src/web/app-ready-actions.ts
  • packages/app/src/web/app-ready-state.ts
  • packages/app/src/web/screen.ts
  • packages/app/src/web/app-ready-hooks.ts
  • packages/app/src/web/app-ready-layout.tsx
  • packages/app/src/web/panel-content.tsx
  • packages/app/tests/docker-git/browser-action-context-fixture.ts
  • packages/app/src/web/actions-share.ts
  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{py,js,ts,jsx,tsx,go,java,rb,php,sh,bash,c,cpp}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files introduce path traversal or writes outside intended project/container state directories

Files:

  • packages/app/tests/docker-git/app-ready-url.test.ts
  • packages/api/src/api/schema.ts
  • packages/app/src/web/app-ready-controller-context.ts
  • packages/api/src/api/contracts.ts
  • packages/api/tests/schema.test.ts
  • packages/app/src/web/api-state-types.ts
  • packages/app/src/web/app-ready-shortcuts.ts
  • packages/app/src/web/panel-share.tsx
  • packages/app/tests/docker-git/actions-share.test.ts
  • packages/app/src/web/api-types.ts
  • packages/api/src/services/panel-cloudflare-tunnel-core.ts
  • packages/app/src/web/github-auth-gate.ts
  • packages/app/src/web/actions-projects.ts
  • packages/app/tests/docker-git/app-ready-shortcuts.test.ts
  • packages/app/src/web/panel-layout.tsx
  • packages/app/src/web/api.ts
  • packages/app/src/web/api-share.ts
  • packages/app/src/web/app-ready-url.ts
  • packages/api/tests/panel-cloudflare-tunnel-core.test.ts
  • packages/app/src/web/app-ready-controller.ts
  • packages/app/src/web/actions-shared.ts
  • packages/app/src/web/app-ready.tsx
  • packages/api/src/http.ts
  • packages/app/src/web/api-schema.ts
  • packages/app/src/web/app-ready-main-panels.tsx
  • packages/app/src/web/menu.ts
  • packages/app/src/web/actions.ts
  • packages/app/src/web/app-ready-actions.ts
  • packages/app/src/web/app-ready-state.ts
  • packages/app/src/web/screen.ts
  • packages/app/src/web/app-ready-hooks.ts
  • packages/app/src/web/app-ready-layout.tsx
  • packages/app/src/web/panel-content.tsx
  • packages/app/tests/docker-git/browser-action-context-fixture.ts
  • packages/app/src/web/actions-share.ts
  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{js,ts,jsx,tsx,py,java,go,rb,php,sh,bash,yml,yaml,json,env*,toml,cfg,config,dockerfile,dockerignore}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files expose credentials, tokens, private-keys, or PII in source, generated config, logs, or CI output

Files:

  • packages/app/tests/docker-git/app-ready-url.test.ts
  • packages/api/src/api/schema.ts
  • packages/app/src/web/app-ready-controller-context.ts
  • packages/api/src/api/contracts.ts
  • packages/api/tests/schema.test.ts
  • packages/app/src/web/api-state-types.ts
  • packages/app/src/web/app-ready-shortcuts.ts
  • packages/app/src/web/panel-share.tsx
  • packages/app/tests/docker-git/actions-share.test.ts
  • packages/app/src/web/api-types.ts
  • packages/api/src/services/panel-cloudflare-tunnel-core.ts
  • packages/app/src/web/github-auth-gate.ts
  • packages/app/src/web/actions-projects.ts
  • packages/app/tests/docker-git/app-ready-shortcuts.test.ts
  • packages/app/src/web/panel-layout.tsx
  • packages/app/src/web/api.ts
  • packages/app/src/web/api-share.ts
  • packages/app/src/web/app-ready-url.ts
  • packages/api/tests/panel-cloudflare-tunnel-core.test.ts
  • packages/app/src/web/app-ready-controller.ts
  • packages/app/src/web/actions-shared.ts
  • packages/app/src/web/app-ready.tsx
  • packages/api/src/http.ts
  • packages/app/src/web/api-schema.ts
  • packages/app/src/web/app-ready-main-panels.tsx
  • packages/app/src/web/menu.ts
  • packages/app/src/web/actions.ts
  • packages/app/src/web/app-ready-actions.ts
  • packages/app/src/web/app-ready-state.ts
  • packages/app/src/web/screen.ts
  • packages/app/src/web/app-ready-hooks.ts
  • packages/app/src/web/app-ready-layout.tsx
  • packages/app/src/web/panel-content.tsx
  • packages/app/tests/docker-git/browser-action-context-fixture.ts
  • packages/app/src/web/actions-share.ts
  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*

⚙️ CodeRabbit configuration file

**/*: Ты строгий ревьюер SPEC DRIVEN DEVELOPMENT.

Перед выводами изучи README.md, другие *.md файлы, linked issues,
PR description, PR comments/discussion и релевантную кодовую базу.

Сверь изменения с исходным ТЗ/спекой и обсуждением. Флагай любой уход
от спеки, недокументированное изменение поведения, отсутствие тестов
для заявленного поведения и security-риск. Если спека не видна,
попроси автора добавить ее в issue или PR description.

Проверь решение с точки зрения формальной верификации: какие инварианты,
предусловия и постусловия можно доказать математически, а где доказуемость
слабая. Оцени решение с точки зрения теории игр: устойчивы ли стимулы,
нет ли выгодного обхода правил, и какое решение было бы сильнее.

Files:

  • packages/app/tests/docker-git/app-ready-url.test.ts
  • packages/api/src/api/schema.ts
  • packages/app/src/web/app-ready-controller-context.ts
  • packages/api/src/api/contracts.ts
  • packages/api/tests/schema.test.ts
  • packages/app/src/web/api-state-types.ts
  • packages/app/src/web/app-ready-shortcuts.ts
  • packages/app/src/web/panel-share.tsx
  • packages/app/tests/docker-git/actions-share.test.ts
  • packages/app/src/web/api-types.ts
  • packages/api/src/services/panel-cloudflare-tunnel-core.ts
  • packages/app/src/web/github-auth-gate.ts
  • packages/app/src/web/actions-projects.ts
  • packages/api/Dockerfile
  • packages/app/tests/docker-git/app-ready-shortcuts.test.ts
  • packages/app/src/web/panel-layout.tsx
  • packages/app/src/web/api.ts
  • packages/app/src/web/api-share.ts
  • packages/app/src/web/app-ready-url.ts
  • packages/api/tests/panel-cloudflare-tunnel-core.test.ts
  • packages/app/src/web/app-ready-controller.ts
  • packages/app/src/web/actions-shared.ts
  • packages/app/src/web/app-ready.tsx
  • packages/api/src/http.ts
  • packages/app/src/web/api-schema.ts
  • packages/app/src/web/app-ready-main-panels.tsx
  • packages/app/src/web/menu.ts
  • packages/app/src/web/actions.ts
  • packages/app/src/web/app-ready-actions.ts
  • packages/app/src/web/app-ready-state.ts
  • packages/app/src/web/screen.ts
  • packages/app/src/web/app-ready-hooks.ts
  • packages/app/src/web/app-ready-layout.tsx
  • packages/app/src/web/panel-content.tsx
  • packages/app/tests/docker-git/browser-action-context-fixture.ts
  • packages/app/src/web/actions-share.ts
  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/{Dockerfile*,docker-compose*.{yml,yaml},.dockerignore}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files introduce unsafe Docker configuration such as privileged containers, broad host mounts, unbounded Docker socket access, or unnecessary write permissions

Files:

  • packages/api/Dockerfile
🪛 OpenGrep (1.20.0)
packages/api/src/services/panel-cloudflare-tunnel-core.ts

[ERROR] 34-34: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.

(coderabbit.command-injection.exec-js)

🪛 Trivy (0.69.3)
packages/api/Dockerfile

[warning] 37-37: Port 22 exposed

Port 22 should not be exposed in Dockerfile

Rule: DS-0004

Learn more

(IaC/Dockerfile)

🔇 Additional comments (31)
packages/app/tests/docker-git/actions-share.test.ts (1)

18-26: LGTM!

Also applies to: 53-103

packages/app/tests/docker-git/app-ready-shortcuts.test.ts (1)

138-138: LGTM!

Also applies to: 208-208

packages/app/tests/docker-git/app-ready-url.test.ts (1)

44-58: LGTM!

packages/app/tests/docker-git/browser-action-context-fixture.ts (1)

30-30: LGTM!

Also applies to: 49-49

packages/api/src/api/contracts.ts (1)

77-92: LGTM!

packages/api/src/api/schema.ts (1)

176-178: LGTM!

packages/api/src/http.ts (1)

39-39: LGTM!

Also applies to: 113-117, 484-485, 809-830

packages/app/src/web/api-schema.ts (1)

97-117: LGTM!

Also applies to: 224-224

packages/app/src/web/api-types.ts (1)

10-10: LGTM!

Also applies to: 38-38

packages/app/src/web/api.ts (1)

57-57: LGTM!

Also applies to: 335-335

packages/app/src/web/api-state-types.ts (1)

5-5: LGTM!

packages/app/src/web/actions-shared.ts (1)

46-46: LGTM!

Also applies to: 65-65

packages/app/src/web/app-ready-actions.ts (1)

14-14: LGTM!

Also applies to: 33-33, 57-57, 76-76

packages/app/src/web/app-ready-controller-context.ts (1)

20-20: LGTM!

Also applies to: 39-39

packages/app/src/web/app-ready-state.ts (1)

10-10: LGTM!

Also applies to: 44-44, 73-73, 117-117, 129-129, 137-137

packages/app/src/web/actions-share.ts (1)

1-77: LGTM!

packages/app/src/web/actions.ts (1)

3-3: LGTM!

Also applies to: 47-52, 78-81

packages/app/src/web/app-ready-controller.ts (1)

5-5: LGTM!

Also applies to: 11-13, 129-129, 264-279, 297-297

packages/app/src/web/panel-share.tsx (1)

1-156: LGTM!

packages/app/src/web/app-ready-main-panels.tsx (1)

17-17: LGTM!

Also applies to: 39-39, 67-69, 461-483, 508-510

packages/app/src/web/app-ready-layout.tsx (1)

10-10: LGTM!

Also applies to: 75-75, 95-95, 110-111, 113-113

packages/app/src/web/menu.ts (1)

11-11: LGTM!

Also applies to: 31-31

packages/app/src/web/actions-projects.ts (1)

486-489: LGTM!

Also applies to: 505-505

packages/app/src/web/screen.ts (1)

24-24: LGTM!

Also applies to: 60-62

packages/app/src/web/panel-content.tsx (1)

59-59: LGTM!

packages/app/src/web/panel-layout.tsx (1)

37-37: LGTM!

packages/app/src/web/app-ready-url.ts (1)

57-57: LGTM!

packages/app/src/web/app-ready-shortcuts.ts (1)

14-14: LGTM!

Also applies to: 109-109

packages/app/src/web/app-ready.tsx (1)

47-47: LGTM!

Also applies to: 59-59, 69-70, 81-86, 135-135, 160-160

packages/app/src/web/app-ready-hooks.ts (2)

8-18: LGTM!

Also applies to: 54-54


145-150: Дедупликация уже реализована через механизм busyLabel.

На самом деле refreshPanelCloudflareTunnel защищен от дублирования: когда withBusy устанавливает context.setBusyLabel("Loading share tunnel"), это вызывает re-render, и в usePanelAutoload функция loadCurrentPanel проверяет if (args.busyLabel !== null) { return } перед вызовом loadReadyPanel. Таким образом, во время выполнения запроса все последующие срабатывания эффекта (от dashboardRefreshTick, githubStatus и т.д.) будут остановлены на этой проверке. Когда запрос завершается, busyLabel сбрасывается в null и одновременно panelCloudflareTunnel обновляется на новое значение, что делает условие в maybeRefreshShareScreen (panelCloudflareTunnel === null) ложным.

Механизм работает корректно, хотя он и является имплицитным—дедупликация происходит на уровне хука через координацию с action-слоем, а не через явное состояние loading/loaded.

			> Likely an incorrect or invalid review comment.

Comment thread packages/api/Dockerfile Outdated
Comment thread packages/api/src/services/panel-cloudflare-tunnel-core.ts
Comment thread packages/api/src/services/panel-cloudflare-tunnel.ts
Comment thread packages/api/tests/panel-cloudflare-tunnel-core.test.ts
Comment thread packages/api/tests/schema.test.ts
Comment thread packages/app/src/web/actions-share.ts Outdated
Comment thread packages/app/src/web/api-share.ts
Comment thread packages/app/src/web/github-auth-gate.ts
@skulidropek
Copy link
Copy Markdown
Member Author

skulidropek commented May 18, 2026

AI Session Backup

Commit: 2ad6876
Status: success
Files: 5 (4.81 MB)
Links: README | Manifest

git status

On branch issue-310
Your branch is up to date with 'origin/issue-310'.

nothing to commit, working tree clean

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/api/src/services/panel-cloudflare-tunnel-core.ts`:
- Around line 149-163: The functions readDefaultGatewayIp and
defaultPanelTunnelLocalhostHost in the core module perform IO (reading
process.env, /.dockerenv, /proc/net/route) which violates FCIS; move their
implementations into the shell/service layer and replace usages in the core with
a pure API that accepts the computed localhost host as an explicit parameter
(e.g., change functions that currently call defaultPanelTunnelLocalhostHost to
take a hostname/string argument instead). Remove all fs and env access from
panel-cloudflare-tunnel-core (delete readDefaultGatewayIp and
defaultPanelTunnelLocalhostHost from the core), compute the host in the shell
using the existing logic, and pass that computed value into the core functions
so the core only contains deterministic hostname/URL rules.

In `@packages/api/src/services/panel-cloudflare-tunnel.ts`:
- Around line 153-182: stopRecord currently updates the record status and
returns before the child process has actually exited, which allows
waitForRecordId to start a replacement while the old cloudflared is still
running; change stopRecord (and other similar sites around waitForRecordId
usage) to wait for the child process to emit its exit/close (or use a Promise
that resolves on 'exit'/'close' or when process.exitCode/signalCode are set,
with the existing SIGTERM/SIGKILL fallback timer) before calling
updateRecord/returning the session and before allowing a replacement start;
reference the stopRecord function, the process.kill logic, the killTimer, and
waitForRecordId to locate where to add the await-for-exit behavior and apply the
same pattern to the other occurrences mentioned.
- Around line 112-118: The processEnv function currently spreads ...process.env
and leaks container secrets to the cloudflared child; change processEnv to build
and return a minimal allowlist object instead (explicitly include PATH, HOME,
NO_COLOR and any needed SSL_CERT_* entries) rather than copying all env vars.
Update the processEnv implementation (function processEnv) to only pick and
forward those specific keys and leave out ...process.env so tokens and secrets
are not passed to cloudflared.

In `@packages/api/tests/panel-cloudflare-tunnel-core.test.ts`:
- Around line 10-62: Add fast-check property-based tests covering invariants for
resolvePanelTunnelTargetUrl and parseTryCloudflareUrl: generate arbitrary URLs
and hostnames (various protocols, ports, paths, noise lines) and assert
invariants such as: public hostnames produce {ok:false} (use
isTryCloudflareHostname to filter/identify), trycloudflare hostnames produce
{ok:false} and are detected by isTryCloudflareHostname, and valid private/local
hostnames (identified via isLocalPanelHostname) preserve origin form in both
panelUrl and targetUrl; also fuzz parseTryCloudflareUrl with log-like strings to
ensure it returns either null or a correctly parsed trycloudflare URL. Use
fast-check arbitraries (strings, hostnames, urls, oneof/noise) and name tests to
satisfy the repo guideline for property-based tests.

In `@packages/app/src/web/panel-share.tsx`:
- Around line 27-31: The openUrl function currently passes raw strings to
globalThis.open allowing unsafe schemes; restrict it to only http and https by
parsing/validating the URL scheme before opening (e.g., use the URL constructor
or a strict regex to ensure url.protocol is "http:" or "https:"), bail out or
log if validation fails, then call globalThis.open(url, "_blank", "noopener");
apply the same validation fix to the other occurrences noted (lines ~61-63 and
~70-72) so all uses of openUrl/globalThis.open only open allowed protocols.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 630ec79b-fd2e-45f8-95a3-7d03d342c0c8

📥 Commits

Reviewing files that changed from the base of the PR and between a5c5c88 and 2ad6876.

📒 Files selected for processing (12)
  • packages/api/Dockerfile
  • packages/api/src/services/panel-cloudflare-tunnel-core.ts
  • packages/api/src/services/panel-cloudflare-tunnel.ts
  • packages/api/tests/panel-cloudflare-tunnel-core.test.ts
  • packages/api/tests/schema.test.ts
  • packages/app/src/web/actions-share.ts
  • packages/app/src/web/api-share.ts
  • packages/app/src/web/app-ready-hooks.ts
  • packages/app/src/web/github-auth-gate.ts
  • packages/app/src/web/panel-share.tsx
  • packages/app/tests/docker-git/actions-share.test.ts
  • packages/app/tests/docker-git/github-auth-gate.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: E2E (Login context)
  • GitHub Check: E2E (Clone cache)
  • GitHub Check: E2E (Clone auto-open SSH)
  • GitHub Check: E2E (Browser command)
  • GitHub Check: E2E (Runtime volumes + SSH)
  • GitHub Check: E2E (OpenCode)
🧰 Additional context used
📓 Path-based instructions (9)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Implement Functional Core, Imperative Shell (FCIS) pattern: CORE layer contains only pure functions with immutable data and mathematical operations; SHELL layer isolates all effects (IO, network, database). Strict dependency direction: SHELL → CORE (never reverse).
Never use any, unknown, eslint-disable, ts-ignore, or as type assertions (except in rigorously justified cases with documentation). Always use exhaustive union type analysis through .exhaustive() pattern matching.
All external dependencies must be wrapped through typed interfaces and injected via Effect-TS Layer pattern. Never call external services directly from CORE functions.
Use monadic composition with Effect-TS for all effects: Effect<Success, Error, Requirements>. Compose effects through pipe() and Effect.flatMap(). Implement dependency injection via Layer pattern. Handle errors without try/catch blocks.
All functions must be pure in the CORE layer: no side effects (logging, console output, IO operations, mutations). Separate all side effects into the SHELL layer.
Use exhaustive pattern matching with Effect.Match instead of switch statements. Example: Match.value(item).pipe(Match.when(...), Match.exhaustive).
Document all functions with comprehensive TSDoc including: @pure (true/false), @effect (required services), @invariant (mathematical invariants), @precondition, @postcondition, @complexity (time and space), @throws Never (errors must be typed in Effect).
Use functional comment markers for code clarity: CHANGE (brief description), WHY (mathematical/architectural justification), QUOTE(ТЗ) (requirement citation), REF (RTM or message ID), SOURCE (external source with quote), FORMAT THEOREM (∀x ∈ Domain: P(x) → Q(f(x))), PURITY (CORE|SHELL), EFFECT (Effect type signature), INVARIANT (mathematical invariant), COMPLEXITY (time/space).
Define all external service dependencies as Context.Tag classes with fully typed methods returning Effect types. Example: `class Da...

Files:

  • packages/app/src/web/github-auth-gate.ts
  • packages/api/tests/panel-cloudflare-tunnel-core.test.ts
  • packages/app/tests/docker-git/actions-share.test.ts
  • packages/app/src/web/panel-share.tsx
  • packages/app/src/web/actions-share.ts
  • packages/app/src/web/app-ready-hooks.ts
  • packages/app/src/web/api-share.ts
  • packages/api/tests/schema.test.ts
  • packages/app/tests/docker-git/github-auth-gate.test.ts
  • packages/api/src/services/panel-cloudflare-tunnel-core.ts
  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,js,jsx}: Forbidden constructs in CORE code: any, eslint-disable, ts-ignore, async/await, raw Promise chains (then/catch), Promise.all, try/catch for logic control, console.*, switch statements (use Match with .exhaustive() instead)
All functions must use Effect-TS for composing effects: Effect<Success, Error, Requirements>. No direct async/await, Promise chains, or try/catch in product logic.
Functional comments must include: CHANGE, WHY, QUOTE(ТЗ) or n/a, REF, SOURCE or n/a, FORMAT THEOREM, PURITY (CORE|SHELL), EFFECT signature for SHELL functions, INVARIANT, and COMPLEXITY.
All data mutations must use immutable patterns (ReadonlyArray, readonly properties, Object.freeze); mutation in SHELL only when absolutely necessary and documented.

Files:

  • packages/app/src/web/github-auth-gate.ts
  • packages/api/tests/panel-cloudflare-tunnel-core.test.ts
  • packages/app/tests/docker-git/actions-share.test.ts
  • packages/app/src/web/panel-share.tsx
  • packages/app/src/web/actions-share.ts
  • packages/app/src/web/app-ready-hooks.ts
  • packages/app/src/web/api-share.ts
  • packages/api/tests/schema.test.ts
  • packages/app/tests/docker-git/github-auth-gate.test.ts
  • packages/api/src/services/panel-cloudflare-tunnel-core.ts
  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{sh,bash,py,js,ts,jsx,tsx,go,java,rb,php}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files introduce command injection or unsafe shell/process execution with user-controlled input

Files:

  • packages/app/src/web/github-auth-gate.ts
  • packages/api/tests/panel-cloudflare-tunnel-core.test.ts
  • packages/app/tests/docker-git/actions-share.test.ts
  • packages/app/src/web/panel-share.tsx
  • packages/app/src/web/actions-share.ts
  • packages/app/src/web/app-ready-hooks.ts
  • packages/app/src/web/api-share.ts
  • packages/api/tests/schema.test.ts
  • packages/app/tests/docker-git/github-auth-gate.test.ts
  • packages/api/src/services/panel-cloudflare-tunnel-core.ts
  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{py,js,ts,jsx,tsx,go,java,rb,php,sh,bash,c,cpp}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files introduce path traversal or writes outside intended project/container state directories

Files:

  • packages/app/src/web/github-auth-gate.ts
  • packages/api/tests/panel-cloudflare-tunnel-core.test.ts
  • packages/app/tests/docker-git/actions-share.test.ts
  • packages/app/src/web/panel-share.tsx
  • packages/app/src/web/actions-share.ts
  • packages/app/src/web/app-ready-hooks.ts
  • packages/app/src/web/api-share.ts
  • packages/api/tests/schema.test.ts
  • packages/app/tests/docker-git/github-auth-gate.test.ts
  • packages/api/src/services/panel-cloudflare-tunnel-core.ts
  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{js,ts,jsx,tsx,py,java,go,rb,php,sh,bash,yml,yaml,json,env*,toml,cfg,config,dockerfile,dockerignore}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files expose credentials, tokens, private-keys, or PII in source, generated config, logs, or CI output

Files:

  • packages/app/src/web/github-auth-gate.ts
  • packages/api/tests/panel-cloudflare-tunnel-core.test.ts
  • packages/app/tests/docker-git/actions-share.test.ts
  • packages/app/src/web/panel-share.tsx
  • packages/app/src/web/actions-share.ts
  • packages/app/src/web/app-ready-hooks.ts
  • packages/app/src/web/api-share.ts
  • packages/api/tests/schema.test.ts
  • packages/app/tests/docker-git/github-auth-gate.test.ts
  • packages/api/src/services/panel-cloudflare-tunnel-core.ts
  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*

⚙️ CodeRabbit configuration file

**/*: Ты строгий ревьюер SPEC DRIVEN DEVELOPMENT.

Перед выводами изучи README.md, другие *.md файлы, linked issues,
PR description, PR comments/discussion и релевантную кодовую базу.

Сверь изменения с исходным ТЗ/спекой и обсуждением. Флагай любой уход
от спеки, недокументированное изменение поведения, отсутствие тестов
для заявленного поведения и security-риск. Если спека не видна,
попроси автора добавить ее в issue или PR description.

Проверь решение с точки зрения формальной верификации: какие инварианты,
предусловия и постусловия можно доказать математически, а где доказуемость
слабая. Оцени решение с точки зрения теории игр: устойчивы ли стимулы,
нет ли выгодного обхода правил, и какое решение было бы сильнее.

Files:

  • packages/app/src/web/github-auth-gate.ts
  • packages/api/tests/panel-cloudflare-tunnel-core.test.ts
  • packages/app/tests/docker-git/actions-share.test.ts
  • packages/app/src/web/panel-share.tsx
  • packages/app/src/web/actions-share.ts
  • packages/api/Dockerfile
  • packages/app/src/web/app-ready-hooks.ts
  • packages/app/src/web/api-share.ts
  • packages/api/tests/schema.test.ts
  • packages/app/tests/docker-git/github-auth-gate.test.ts
  • packages/api/src/services/panel-cloudflare-tunnel-core.ts
  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.test.{ts,tsx}: Implement property-based testing using fast-check for mathematical properties and invariants. Example: fc.property(fc.array(messageArbitrary), (messages) => isChronologicallySorted(sortMessagesByTimestamp(messages))).
Mock external dependencies in unit tests using Effect's testing utilities. Run tests without Effect runtime for speed. Example: Effect.provide(MockService), Effect.runPromise.

Files:

  • packages/api/tests/panel-cloudflare-tunnel-core.test.ts
  • packages/app/tests/docker-git/actions-share.test.ts
  • packages/api/tests/schema.test.ts
  • packages/app/tests/docker-git/github-auth-gate.test.ts
**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Property-based tests (fast-check) must verify mathematical invariants; unit tests must use Effect test utilities without async/await.

Files:

  • packages/api/tests/panel-cloudflare-tunnel-core.test.ts
  • packages/app/tests/docker-git/actions-share.test.ts
  • packages/api/tests/schema.test.ts
  • packages/app/tests/docker-git/github-auth-gate.test.ts
**/{Dockerfile*,docker-compose*.{yml,yaml},.dockerignore}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files introduce unsafe Docker configuration such as privileged containers, broad host mounts, unbounded Docker socket access, or unnecessary write permissions

Files:

  • packages/api/Dockerfile
🪛 OpenGrep (1.20.0)
packages/api/src/services/panel-cloudflare-tunnel-core.ts

[ERROR] 95-95: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.

(coderabbit.command-injection.exec-js)

🔇 Additional comments (2)
packages/api/tests/schema.test.ts (1)

355-385: LGTM!

packages/app/tests/docker-git/github-auth-gate.test.ts (1)

50-58: LGTM!

Comment thread packages/api/src/services/panel-cloudflare-tunnel-core.ts Outdated
Comment thread packages/api/src/services/panel-cloudflare-tunnel.ts
Comment thread packages/api/src/services/panel-cloudflare-tunnel.ts Outdated
Comment thread packages/api/tests/panel-cloudflare-tunnel-core.test.ts
Comment thread packages/app/src/web/panel-share.tsx
Comment thread packages/app/tests/docker-git/actions-share.test.ts
@skulidropek
Copy link
Copy Markdown
Member Author

skulidropek commented May 18, 2026

AI Session Backup

Commit: 51a20a5
Status: success
Files: 6 (6.37 MB)
Links: README | Manifest

git status

On branch issue-310
Your branch is up to date with 'origin/issue-310'.

nothing to commit, working tree clean

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/api/src/services/panel-cloudflare-tunnel.ts`:
- Around line 380-383: The code sets currentRecord = record before calling
startCloudflaredProcess, but if that spawn errors the record stays stuck in
"starting" and can be reused by isReusableRecord; wrap the call to
startCloudflaredProcess(record, ...) in a try/catch (or try/finally) so that on
any thrown error you reset currentRecord back to undefined (only if it still
equals the record you just created) and rethrow the error; keep
createStartingRecord and the successful-return behavior unchanged so
currentRecord remains set on success.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: c55975aa-4a3e-4a97-a08f-3e20800775bc

📥 Commits

Reviewing files that changed from the base of the PR and between 2ad6876 and 51a20a5.

📒 Files selected for processing (5)
  • packages/api/src/services/panel-cloudflare-tunnel-core.ts
  • packages/api/src/services/panel-cloudflare-tunnel.ts
  • packages/api/tests/panel-cloudflare-tunnel-core.test.ts
  • packages/app/src/web/panel-share.tsx
  • packages/app/tests/docker-git/actions-share.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: E2E (Browser command)
  • GitHub Check: E2E (Clone cache)
  • GitHub Check: E2E (Clone auto-open SSH)
  • GitHub Check: E2E (Runtime volumes + SSH)
  • GitHub Check: E2E (Login context)
  • GitHub Check: Lint
  • GitHub Check: E2E (OpenCode)
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Implement Functional Core, Imperative Shell (FCIS) pattern: CORE layer contains only pure functions with immutable data and mathematical operations; SHELL layer isolates all effects (IO, network, database). Strict dependency direction: SHELL → CORE (never reverse).
Never use any, unknown, eslint-disable, ts-ignore, or as type assertions (except in rigorously justified cases with documentation). Always use exhaustive union type analysis through .exhaustive() pattern matching.
All external dependencies must be wrapped through typed interfaces and injected via Effect-TS Layer pattern. Never call external services directly from CORE functions.
Use monadic composition with Effect-TS for all effects: Effect<Success, Error, Requirements>. Compose effects through pipe() and Effect.flatMap(). Implement dependency injection via Layer pattern. Handle errors without try/catch blocks.
All functions must be pure in the CORE layer: no side effects (logging, console output, IO operations, mutations). Separate all side effects into the SHELL layer.
Use exhaustive pattern matching with Effect.Match instead of switch statements. Example: Match.value(item).pipe(Match.when(...), Match.exhaustive).
Document all functions with comprehensive TSDoc including: @pure (true/false), @effect (required services), @invariant (mathematical invariants), @precondition, @postcondition, @complexity (time and space), @throws Never (errors must be typed in Effect).
Use functional comment markers for code clarity: CHANGE (brief description), WHY (mathematical/architectural justification), QUOTE(ТЗ) (requirement citation), REF (RTM or message ID), SOURCE (external source with quote), FORMAT THEOREM (∀x ∈ Domain: P(x) → Q(f(x))), PURITY (CORE|SHELL), EFFECT (Effect type signature), INVARIANT (mathematical invariant), COMPLEXITY (time/space).
Define all external service dependencies as Context.Tag classes with fully typed methods returning Effect types. Example: `class Da...

Files:

  • packages/api/tests/panel-cloudflare-tunnel-core.test.ts
  • packages/app/src/web/panel-share.tsx
  • packages/app/tests/docker-git/actions-share.test.ts
  • packages/api/src/services/panel-cloudflare-tunnel-core.ts
  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.test.{ts,tsx}: Implement property-based testing using fast-check for mathematical properties and invariants. Example: fc.property(fc.array(messageArbitrary), (messages) => isChronologicallySorted(sortMessagesByTimestamp(messages))).
Mock external dependencies in unit tests using Effect's testing utilities. Run tests without Effect runtime for speed. Example: Effect.provide(MockService), Effect.runPromise.

Files:

  • packages/api/tests/panel-cloudflare-tunnel-core.test.ts
  • packages/app/tests/docker-git/actions-share.test.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,js,jsx}: Forbidden constructs in CORE code: any, eslint-disable, ts-ignore, async/await, raw Promise chains (then/catch), Promise.all, try/catch for logic control, console.*, switch statements (use Match with .exhaustive() instead)
All functions must use Effect-TS for composing effects: Effect<Success, Error, Requirements>. No direct async/await, Promise chains, or try/catch in product logic.
Functional comments must include: CHANGE, WHY, QUOTE(ТЗ) or n/a, REF, SOURCE or n/a, FORMAT THEOREM, PURITY (CORE|SHELL), EFFECT signature for SHELL functions, INVARIANT, and COMPLEXITY.
All data mutations must use immutable patterns (ReadonlyArray, readonly properties, Object.freeze); mutation in SHELL only when absolutely necessary and documented.

Files:

  • packages/api/tests/panel-cloudflare-tunnel-core.test.ts
  • packages/app/src/web/panel-share.tsx
  • packages/app/tests/docker-git/actions-share.test.ts
  • packages/api/src/services/panel-cloudflare-tunnel-core.ts
  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Property-based tests (fast-check) must verify mathematical invariants; unit tests must use Effect test utilities without async/await.

Files:

  • packages/api/tests/panel-cloudflare-tunnel-core.test.ts
  • packages/app/tests/docker-git/actions-share.test.ts
**/*.{sh,bash,py,js,ts,jsx,tsx,go,java,rb,php}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files introduce command injection or unsafe shell/process execution with user-controlled input

Files:

  • packages/api/tests/panel-cloudflare-tunnel-core.test.ts
  • packages/app/src/web/panel-share.tsx
  • packages/app/tests/docker-git/actions-share.test.ts
  • packages/api/src/services/panel-cloudflare-tunnel-core.ts
  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{py,js,ts,jsx,tsx,go,java,rb,php,sh,bash,c,cpp}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files introduce path traversal or writes outside intended project/container state directories

Files:

  • packages/api/tests/panel-cloudflare-tunnel-core.test.ts
  • packages/app/src/web/panel-share.tsx
  • packages/app/tests/docker-git/actions-share.test.ts
  • packages/api/src/services/panel-cloudflare-tunnel-core.ts
  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{js,ts,jsx,tsx,py,java,go,rb,php,sh,bash,yml,yaml,json,env*,toml,cfg,config,dockerfile,dockerignore}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files expose credentials, tokens, private-keys, or PII in source, generated config, logs, or CI output

Files:

  • packages/api/tests/panel-cloudflare-tunnel-core.test.ts
  • packages/app/src/web/panel-share.tsx
  • packages/app/tests/docker-git/actions-share.test.ts
  • packages/api/src/services/panel-cloudflare-tunnel-core.ts
  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*

⚙️ CodeRabbit configuration file

**/*: Ты строгий ревьюер SPEC DRIVEN DEVELOPMENT.

Перед выводами изучи README.md, другие *.md файлы, linked issues,
PR description, PR comments/discussion и релевантную кодовую базу.

Сверь изменения с исходным ТЗ/спекой и обсуждением. Флагай любой уход
от спеки, недокументированное изменение поведения, отсутствие тестов
для заявленного поведения и security-риск. Если спека не видна,
попроси автора добавить ее в issue или PR description.

Проверь решение с точки зрения формальной верификации: какие инварианты,
предусловия и постусловия можно доказать математически, а где доказуемость
слабая. Оцени решение с точки зрения теории игр: устойчивы ли стимулы,
нет ли выгодного обхода правил, и какое решение было бы сильнее.

Files:

  • packages/api/tests/panel-cloudflare-tunnel-core.test.ts
  • packages/app/src/web/panel-share.tsx
  • packages/app/tests/docker-git/actions-share.test.ts
  • packages/api/src/services/panel-cloudflare-tunnel-core.ts
  • packages/api/src/services/panel-cloudflare-tunnel.ts
🪛 OpenGrep (1.20.0)
packages/api/src/services/panel-cloudflare-tunnel-core.ts

[ERROR] 91-91: Dynamic command passed to child_process.exec/execSync. Use child_process.execFile or spawn with an argument array instead.

(coderabbit.command-injection.exec-js)

🔇 Additional comments (4)
packages/api/tests/panel-cloudflare-tunnel-core.test.ts (1)

1-209: LGTM!

packages/app/src/web/panel-share.tsx (1)

1-164: LGTM!

packages/app/tests/docker-git/actions-share.test.ts (1)

1-210: LGTM!

packages/api/src/services/panel-cloudflare-tunnel-core.ts (1)

1-143: LGTM!

Comment thread packages/api/src/services/panel-cloudflare-tunnel.ts Outdated
@skulidropek
Copy link
Copy Markdown
Member Author

skulidropek commented May 18, 2026

AI Session Backup

Commit: cdb1f0e
Status: success
Files: 6 (6.49 MB)
Links: README | Manifest

git status

On branch issue-310
Your branch is up to date with 'origin/issue-310'.

nothing to commit, working tree clean

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/api/src/services/panel-cloudflare-tunnel.ts`:
- Around line 398-412: Add TSDoc comments to each exported function
readPanelCloudflareTunnel, startPanelCloudflareTunnel, and
stopPanelCloudflareTunnel describing purpose, parameters and return values and
include the required tags: `@pure`, `@effect`, `@invariant` (if applicable),
`@precondition`, `@postcondition`, `@complexity`; for startPanelCloudflareTunnel
mention side effects (spawns cloudflared, network IO) and expected precondition
(valid panelUrl) and postcondition (tunnel process running with publicUrl), for
readPanelCloudflareTunnel and stopPanelCloudflareTunnel describe
purity/side-effects and postconditions (what null vs session means) and ensure
errors are documented as PanelCloudflareTunnelError or never as appropriate so
the public API has full TSDoc coverage.
- Around line 123-129: Replace the synchronous try/catch in readDefaultGatewayIp
with an Effect-based implementation: convert readDefaultGatewayIp to return an
Effect that calls the file read and parsing logic, using Effect.try (or
Effect.tryCatch) to capture errors as typed Effects instead of throwing; ensure
you reference the existing parseLinuxDefaultGatewayIp and the file-read
operation (readFileSync) inside the Effect so failures map to a typed error
value and successful parses return string | null consistently with the rest of
the codebase.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f970227f-211b-42ac-86e3-980c5b066d4d

📥 Commits

Reviewing files that changed from the base of the PR and between 51a20a5 and cdb1f0e.

📒 Files selected for processing (1)
  • packages/api/src/services/panel-cloudflare-tunnel.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: E2E (Runtime volumes + SSH)
  • GitHub Check: E2E (Clone auto-open SSH)
  • GitHub Check: E2E (Clone cache)
  • GitHub Check: E2E (OpenCode)
  • GitHub Check: E2E (Login context)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Implement Functional Core, Imperative Shell (FCIS) pattern: CORE layer contains only pure functions with immutable data and mathematical operations; SHELL layer isolates all effects (IO, network, database). Strict dependency direction: SHELL → CORE (never reverse).
Never use any, unknown, eslint-disable, ts-ignore, or as type assertions (except in rigorously justified cases with documentation). Always use exhaustive union type analysis through .exhaustive() pattern matching.
All external dependencies must be wrapped through typed interfaces and injected via Effect-TS Layer pattern. Never call external services directly from CORE functions.
Use monadic composition with Effect-TS for all effects: Effect<Success, Error, Requirements>. Compose effects through pipe() and Effect.flatMap(). Implement dependency injection via Layer pattern. Handle errors without try/catch blocks.
All functions must be pure in the CORE layer: no side effects (logging, console output, IO operations, mutations). Separate all side effects into the SHELL layer.
Use exhaustive pattern matching with Effect.Match instead of switch statements. Example: Match.value(item).pipe(Match.when(...), Match.exhaustive).
Document all functions with comprehensive TSDoc including: @pure (true/false), @effect (required services), @invariant (mathematical invariants), @precondition, @postcondition, @complexity (time and space), @throws Never (errors must be typed in Effect).
Use functional comment markers for code clarity: CHANGE (brief description), WHY (mathematical/architectural justification), QUOTE(ТЗ) (requirement citation), REF (RTM or message ID), SOURCE (external source with quote), FORMAT THEOREM (∀x ∈ Domain: P(x) → Q(f(x))), PURITY (CORE|SHELL), EFFECT (Effect type signature), INVARIANT (mathematical invariant), COMPLEXITY (time/space).
Define all external service dependencies as Context.Tag classes with fully typed methods returning Effect types. Example: `class Da...

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,js,jsx}: Forbidden constructs in CORE code: any, eslint-disable, ts-ignore, async/await, raw Promise chains (then/catch), Promise.all, try/catch for logic control, console.*, switch statements (use Match with .exhaustive() instead)
All functions must use Effect-TS for composing effects: Effect<Success, Error, Requirements>. No direct async/await, Promise chains, or try/catch in product logic.
Functional comments must include: CHANGE, WHY, QUOTE(ТЗ) or n/a, REF, SOURCE or n/a, FORMAT THEOREM, PURITY (CORE|SHELL), EFFECT signature for SHELL functions, INVARIANT, and COMPLEXITY.
All data mutations must use immutable patterns (ReadonlyArray, readonly properties, Object.freeze); mutation in SHELL only when absolutely necessary and documented.

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{sh,bash,py,js,ts,jsx,tsx,go,java,rb,php}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files introduce command injection or unsafe shell/process execution with user-controlled input

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{py,js,ts,jsx,tsx,go,java,rb,php,sh,bash,c,cpp}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files introduce path traversal or writes outside intended project/container state directories

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{js,ts,jsx,tsx,py,java,go,rb,php,sh,bash,yml,yaml,json,env*,toml,cfg,config,dockerfile,dockerignore}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files expose credentials, tokens, private-keys, or PII in source, generated config, logs, or CI output

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*

⚙️ CodeRabbit configuration file

**/*: Ты строгий ревьюер SPEC DRIVEN DEVELOPMENT.

Перед выводами изучи README.md, другие *.md файлы, linked issues,
PR description, PR comments/discussion и релевантную кодовую базу.

Сверь изменения с исходным ТЗ/спекой и обсуждением. Флагай любой уход
от спеки, недокументированное изменение поведения, отсутствие тестов
для заявленного поведения и security-риск. Если спека не видна,
попроси автора добавить ее в issue или PR description.

Проверь решение с точки зрения формальной верификации: какие инварианты,
предусловия и постусловия можно доказать математически, а где доказуемость
слабая. Оцени решение с точки зрения теории игр: устойчивы ли стимулы,
нет ли выгодного обхода правил, и какое решение было бы сильнее.

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
🔇 Additional comments (3)
packages/api/src/services/panel-cloudflare-tunnel.ts (3)

196-312: LGTM!


331-350: LGTM!


370-396: LGTM!

Comment thread packages/api/src/services/panel-cloudflare-tunnel.ts Outdated
Comment thread packages/api/src/services/panel-cloudflare-tunnel.ts
@skulidropek
Copy link
Copy Markdown
Member Author

skulidropek commented May 18, 2026

AI Session Backup

Commit: 575c190
Status: success
Files: 6 (6.62 MB)
Links: README | Manifest

git status

On branch issue-310
Your branch is up to date with 'origin/issue-310'.

nothing to commit, working tree clean

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/api/src/services/panel-cloudflare-tunnel.ts`:
- Around line 447-450: Функция stopPanelCloudflareTunnel вызывает stopRecord
даже для уже terminal-сессий и перезаписывает сохранённый snapshot; добавьте в
тело Effect.gen проверку currentRecord и его terminal-статуса и в случае
terminal-значения (например status === "stopped" || status === "failed" ||
status === "error") просто верните currentRecord без вызова stopRecord, иначе
продолжайте как сейчас; используйте те же символы currentRecord и stopRecord
внутри stopPanelCloudflareTunnel (сохранив обёртку
tunnelRecordLock.withPermits(1)).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 82dd0723-6df8-4dd5-9f0c-8a2110e315b8

📥 Commits

Reviewing files that changed from the base of the PR and between cdb1f0e and 575c190.

📒 Files selected for processing (1)
  • packages/api/src/services/panel-cloudflare-tunnel.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: E2E (Runtime volumes + SSH)
  • GitHub Check: E2E (Clone cache)
  • GitHub Check: E2E (Login context)
  • GitHub Check: E2E (Clone auto-open SSH)
  • GitHub Check: E2E (OpenCode)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Implement Functional Core, Imperative Shell (FCIS) pattern: CORE layer contains only pure functions with immutable data and mathematical operations; SHELL layer isolates all effects (IO, network, database). Strict dependency direction: SHELL → CORE (never reverse).
Never use any, unknown, eslint-disable, ts-ignore, or as type assertions (except in rigorously justified cases with documentation). Always use exhaustive union type analysis through .exhaustive() pattern matching.
All external dependencies must be wrapped through typed interfaces and injected via Effect-TS Layer pattern. Never call external services directly from CORE functions.
Use monadic composition with Effect-TS for all effects: Effect<Success, Error, Requirements>. Compose effects through pipe() and Effect.flatMap(). Implement dependency injection via Layer pattern. Handle errors without try/catch blocks.
All functions must be pure in the CORE layer: no side effects (logging, console output, IO operations, mutations). Separate all side effects into the SHELL layer.
Use exhaustive pattern matching with Effect.Match instead of switch statements. Example: Match.value(item).pipe(Match.when(...), Match.exhaustive).
Document all functions with comprehensive TSDoc including: @pure (true/false), @effect (required services), @invariant (mathematical invariants), @precondition, @postcondition, @complexity (time and space), @throws Never (errors must be typed in Effect).
Use functional comment markers for code clarity: CHANGE (brief description), WHY (mathematical/architectural justification), QUOTE(ТЗ) (requirement citation), REF (RTM or message ID), SOURCE (external source with quote), FORMAT THEOREM (∀x ∈ Domain: P(x) → Q(f(x))), PURITY (CORE|SHELL), EFFECT (Effect type signature), INVARIANT (mathematical invariant), COMPLEXITY (time/space).
Define all external service dependencies as Context.Tag classes with fully typed methods returning Effect types. Example: `class Da...

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,js,jsx}: Forbidden constructs in CORE code: any, eslint-disable, ts-ignore, async/await, raw Promise chains (then/catch), Promise.all, try/catch for logic control, console.*, switch statements (use Match with .exhaustive() instead)
All functions must use Effect-TS for composing effects: Effect<Success, Error, Requirements>. No direct async/await, Promise chains, or try/catch in product logic.
Functional comments must include: CHANGE, WHY, QUOTE(ТЗ) or n/a, REF, SOURCE or n/a, FORMAT THEOREM, PURITY (CORE|SHELL), EFFECT signature for SHELL functions, INVARIANT, and COMPLEXITY.
All data mutations must use immutable patterns (ReadonlyArray, readonly properties, Object.freeze); mutation in SHELL only when absolutely necessary and documented.

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{sh,bash,py,js,ts,jsx,tsx,go,java,rb,php}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files introduce command injection or unsafe shell/process execution with user-controlled input

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{py,js,ts,jsx,tsx,go,java,rb,php,sh,bash,c,cpp}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files introduce path traversal or writes outside intended project/container state directories

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{js,ts,jsx,tsx,py,java,go,rb,php,sh,bash,yml,yaml,json,env*,toml,cfg,config,dockerfile,dockerignore}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files expose credentials, tokens, private-keys, or PII in source, generated config, logs, or CI output

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*

⚙️ CodeRabbit configuration file

**/*: Ты строгий ревьюер SPEC DRIVEN DEVELOPMENT.

Перед выводами изучи README.md, другие *.md файлы, linked issues,
PR description, PR comments/discussion и релевантную кодовую базу.

Сверь изменения с исходным ТЗ/спекой и обсуждением. Флагай любой уход
от спеки, недокументированное изменение поведения, отсутствие тестов
для заявленного поведения и security-риск. Если спека не видна,
попроси автора добавить ее в issue или PR description.

Проверь решение с точки зрения формальной верификации: какие инварианты,
предусловия и постусловия можно доказать математически, а где доказуемость
слабая. Оцени решение с точки зрения теории игр: устойчивы ли стимулы,
нет ли выгодного обхода правил, и какое решение было бы сильнее.

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts

Comment thread packages/api/src/services/panel-cloudflare-tunnel.ts
Comment thread packages/api/src/services/panel-cloudflare-tunnel.ts
@skulidropek
Copy link
Copy Markdown
Member Author

skulidropek commented May 18, 2026

AI Session Backup

Commit: 40b456e
Status: success
Files: 6 (6.75 MB)
Links: README | Manifest

git status

On branch issue-310
Your branch is up to date with 'origin/issue-310'.

nothing to commit, working tree clean

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/api/src/services/panel-cloudflare-tunnel.ts`:
- Around line 348-357: The current direct comparisons in isReusableRecord and
isTerminalTunnelSession won't fail when a new
PanelCloudflareTunnelSession.status value is added; replace the status checks
with exhaustive pattern matching using Match from "effect" (import { Match }
from "effect") so the compiler forces handling of all status variants: for
isTerminalTunnelSession match session.status with Match.when branches for
"failed" and "stopped" (return true) and explicit branches for other known
states returning false, finishing with Match.exhaustive; similarly update
isReusableRecord to match session.status exhaustively and also validate
session.panelUrl === panelUrl as before.
- Around line 123-127: The Effect composition in readDefaultGatewayIp is
redundant: remove the redundant catch handler inside Effect.try and instead
append a single Effect.orElse to return null on failure; locate the
readDefaultGatewayIp function and replace the current Effect.try({... catch: ()
=> null ...}).pipe(Effect.catchAll(...)) pattern with an Effect.try that only
provides the try callback (calling
parseLinuxDefaultGatewayIp(readFileSync(...))) and then .pipe(Effect.orElse(()
=> Effect.succeed(null))) so failures are handled in one place.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 341e45a5-a5e1-4c25-8f60-4762ffb8a257

📥 Commits

Reviewing files that changed from the base of the PR and between 575c190 and 40b456e.

📒 Files selected for processing (1)
  • packages/api/src/services/panel-cloudflare-tunnel.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: E2E (Login context)
  • GitHub Check: E2E (Clone cache)
  • GitHub Check: E2E (OpenCode)
  • GitHub Check: E2E (Clone auto-open SSH)
  • GitHub Check: E2E (Runtime volumes + SSH)
  • GitHub Check: Lint
  • GitHub Check: E2E (Browser command)
  • GitHub Check: Final build (windows-latest)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Implement Functional Core, Imperative Shell (FCIS) pattern: CORE layer contains only pure functions with immutable data and mathematical operations; SHELL layer isolates all effects (IO, network, database). Strict dependency direction: SHELL → CORE (never reverse).
Never use any, unknown, eslint-disable, ts-ignore, or as type assertions (except in rigorously justified cases with documentation). Always use exhaustive union type analysis through .exhaustive() pattern matching.
All external dependencies must be wrapped through typed interfaces and injected via Effect-TS Layer pattern. Never call external services directly from CORE functions.
Use monadic composition with Effect-TS for all effects: Effect<Success, Error, Requirements>. Compose effects through pipe() and Effect.flatMap(). Implement dependency injection via Layer pattern. Handle errors without try/catch blocks.
All functions must be pure in the CORE layer: no side effects (logging, console output, IO operations, mutations). Separate all side effects into the SHELL layer.
Use exhaustive pattern matching with Effect.Match instead of switch statements. Example: Match.value(item).pipe(Match.when(...), Match.exhaustive).
Document all functions with comprehensive TSDoc including: @pure (true/false), @effect (required services), @invariant (mathematical invariants), @precondition, @postcondition, @complexity (time and space), @throws Never (errors must be typed in Effect).
Use functional comment markers for code clarity: CHANGE (brief description), WHY (mathematical/architectural justification), QUOTE(ТЗ) (requirement citation), REF (RTM or message ID), SOURCE (external source with quote), FORMAT THEOREM (∀x ∈ Domain: P(x) → Q(f(x))), PURITY (CORE|SHELL), EFFECT (Effect type signature), INVARIANT (mathematical invariant), COMPLEXITY (time/space).
Define all external service dependencies as Context.Tag classes with fully typed methods returning Effect types. Example: `class Da...

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,js,jsx}: Forbidden constructs in CORE code: any, eslint-disable, ts-ignore, async/await, raw Promise chains (then/catch), Promise.all, try/catch for logic control, console.*, switch statements (use Match with .exhaustive() instead)
All functions must use Effect-TS for composing effects: Effect<Success, Error, Requirements>. No direct async/await, Promise chains, or try/catch in product logic.
Functional comments must include: CHANGE, WHY, QUOTE(ТЗ) or n/a, REF, SOURCE or n/a, FORMAT THEOREM, PURITY (CORE|SHELL), EFFECT signature for SHELL functions, INVARIANT, and COMPLEXITY.
All data mutations must use immutable patterns (ReadonlyArray, readonly properties, Object.freeze); mutation in SHELL only when absolutely necessary and documented.

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{sh,bash,py,js,ts,jsx,tsx,go,java,rb,php}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files introduce command injection or unsafe shell/process execution with user-controlled input

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{py,js,ts,jsx,tsx,go,java,rb,php,sh,bash,c,cpp}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files introduce path traversal or writes outside intended project/container state directories

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{js,ts,jsx,tsx,py,java,go,rb,php,sh,bash,yml,yaml,json,env*,toml,cfg,config,dockerfile,dockerignore}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files expose credentials, tokens, private-keys, or PII in source, generated config, logs, or CI output

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*

⚙️ CodeRabbit configuration file

**/*: Ты строгий ревьюер SPEC DRIVEN DEVELOPMENT.

Перед выводами изучи README.md, другие *.md файлы, linked issues,
PR description, PR comments/discussion и релевантную кодовую базу.

Сверь изменения с исходным ТЗ/спекой и обсуждением. Флагай любой уход
от спеки, недокументированное изменение поведения, отсутствие тестов
для заявленного поведения и security-риск. Если спека не видна,
попроси автора добавить ее в issue или PR description.

Проверь решение с точки зрения формальной верификации: какие инварианты,
предусловия и постусловия можно доказать математически, а где доказуемость
слабая. Оцени решение с точки зрения теории игр: устойчивы ли стимулы,
нет ли выгодного обхода правил, и какое решение было бы сильнее.

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
🔇 Additional comments (7)
packages/api/src/services/panel-cloudflare-tunnel.ts (7)

1-27: LGTM!


28-53: LGTM!


55-111: LGTM!


139-194: LGTM!


196-287: LGTM!


388-445: LGTM!


314-329: AbortSignal.timeout() полностью поддерживается в целевой среде.

Проект использует Node.js 24.x (установка через NodeSource setup_24.x в Dockerfile), что намного выше минимального требования Node.js 17.3+ для API AbortSignal.timeout(). Совместимость обеспечена.

Comment thread packages/api/src/services/panel-cloudflare-tunnel.ts Outdated
Comment thread packages/api/src/services/panel-cloudflare-tunnel.ts Outdated
@skulidropek
Copy link
Copy Markdown
Member Author

skulidropek commented May 18, 2026

AI Session Backup

Commit: 7559324
Status: success
Files: 6 (6.88 MB)
Links: README | Manifest

git status

On branch issue-310
Your branch is up to date with 'origin/issue-310'.

nothing to commit, working tree clean

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/api/src/services/panel-cloudflare-tunnel.ts`:
- Around line 347-358: isReusableRecord currently returns true for records with
session.status "starting" or "running" even when the record is in the middle of
teardown; update the predicate to also check that record.stopping is not true
(i.e., require record.stopping === false) so that runStopRecord()-marked records
are not reused by startPanelCloudflareTunnel; apply the same change to the other
reuse-checking location that uses Match.when for "starting"/"running" (the
second occurrence mentioned) so both reuse checks include the record.stopping
guard.
- Around line 448-456: В stopPanelCloudflareTunnel: текущая логика вызывает
stopRecord(currentRecord) даже если внутренняя остановка уже в процессе и
runStopRecord обнулила record.process, из‑за чего второй stopRecord
перезаписывает snapshot в "stopped" и теряется исходный error; исправьте это
добавив проверку состояния записи (например по currentRecord.process === null
или другому флагу ин‑флайт) перед вызовом stopRecord — если процесс уже
обнулён/выполняется teardown, верните текущее session (или сохраните и верните
существующий error/snapshot) вместо повторного вызова stopRecord, чтобы не
затирать причину падения (используйте имена currentRecord, runStopRecord,
stopRecord, isTerminalTunnelSession и snapshot в правке).
- Around line 123-135: Refactor direct Node API uses into injected Effect-TS
services: create typed Context.Tag+Layer.effect services (e.g.,
FileSystemService with readFileSync/rmSync/mkdirSync, ProcessService for
env/isDocker detection, HttpService for fetch, and ProcessSpawnService for
spawn) and replace direct calls inside readDefaultGatewayIp and
defaultPanelTunnelLocalhostHost (and the other spots using rmSync, mkdirSync,
spawn, fetch) to use these services via Effect.access/Effect.service or
dependency injection; keep the same return types (Effect.Effect<string|null> /
Effect.Effect<string>) and map/error handling, and wire the concrete Node
implementations to the Layer for production and test doubles for unit tests so
all external FS/process/http/spawn calls are routed through the new services.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 6dcd3aa4-4262-4cc2-870c-2e93dbf08f5c

📥 Commits

Reviewing files that changed from the base of the PR and between 40b456e and 7559324.

📒 Files selected for processing (1)
  • packages/api/src/services/panel-cloudflare-tunnel.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: E2E (Clone auto-open SSH)
  • GitHub Check: E2E (OpenCode)
  • GitHub Check: E2E (Login context)
  • GitHub Check: E2E (Clone cache)
  • GitHub Check: E2E (Browser command)
  • GitHub Check: Lint
  • GitHub Check: E2E (Runtime volumes + SSH)
  • GitHub Check: Final build (windows-latest)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Implement Functional Core, Imperative Shell (FCIS) pattern: CORE layer contains only pure functions with immutable data and mathematical operations; SHELL layer isolates all effects (IO, network, database). Strict dependency direction: SHELL → CORE (never reverse).
Never use any, unknown, eslint-disable, ts-ignore, or as type assertions (except in rigorously justified cases with documentation). Always use exhaustive union type analysis through .exhaustive() pattern matching.
All external dependencies must be wrapped through typed interfaces and injected via Effect-TS Layer pattern. Never call external services directly from CORE functions.
Use monadic composition with Effect-TS for all effects: Effect<Success, Error, Requirements>. Compose effects through pipe() and Effect.flatMap(). Implement dependency injection via Layer pattern. Handle errors without try/catch blocks.
All functions must be pure in the CORE layer: no side effects (logging, console output, IO operations, mutations). Separate all side effects into the SHELL layer.
Use exhaustive pattern matching with Effect.Match instead of switch statements. Example: Match.value(item).pipe(Match.when(...), Match.exhaustive).
Document all functions with comprehensive TSDoc including: @pure (true/false), @effect (required services), @invariant (mathematical invariants), @precondition, @postcondition, @complexity (time and space), @throws Never (errors must be typed in Effect).
Use functional comment markers for code clarity: CHANGE (brief description), WHY (mathematical/architectural justification), QUOTE(ТЗ) (requirement citation), REF (RTM or message ID), SOURCE (external source with quote), FORMAT THEOREM (∀x ∈ Domain: P(x) → Q(f(x))), PURITY (CORE|SHELL), EFFECT (Effect type signature), INVARIANT (mathematical invariant), COMPLEXITY (time/space).
Define all external service dependencies as Context.Tag classes with fully typed methods returning Effect types. Example: `class Da...

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,js,jsx}: Forbidden constructs in CORE code: any, eslint-disable, ts-ignore, async/await, raw Promise chains (then/catch), Promise.all, try/catch for logic control, console.*, switch statements (use Match with .exhaustive() instead)
All functions must use Effect-TS for composing effects: Effect<Success, Error, Requirements>. No direct async/await, Promise chains, or try/catch in product logic.
Functional comments must include: CHANGE, WHY, QUOTE(ТЗ) or n/a, REF, SOURCE or n/a, FORMAT THEOREM, PURITY (CORE|SHELL), EFFECT signature for SHELL functions, INVARIANT, and COMPLEXITY.
All data mutations must use immutable patterns (ReadonlyArray, readonly properties, Object.freeze); mutation in SHELL only when absolutely necessary and documented.

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{sh,bash,py,js,ts,jsx,tsx,go,java,rb,php}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files introduce command injection or unsafe shell/process execution with user-controlled input

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{py,js,ts,jsx,tsx,go,java,rb,php,sh,bash,c,cpp}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files introduce path traversal or writes outside intended project/container state directories

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{js,ts,jsx,tsx,py,java,go,rb,php,sh,bash,yml,yaml,json,env*,toml,cfg,config,dockerfile,dockerignore}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files expose credentials, tokens, private-keys, or PII in source, generated config, logs, or CI output

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*

⚙️ CodeRabbit configuration file

**/*: Ты строгий ревьюер SPEC DRIVEN DEVELOPMENT.

Перед выводами изучи README.md, другие *.md файлы, linked issues,
PR description, PR comments/discussion и релевантную кодовую базу.

Сверь изменения с исходным ТЗ/спекой и обсуждением. Флагай любой уход
от спеки, недокументированное изменение поведения, отсутствие тестов
для заявленного поведения и security-риск. Если спека не видна,
попроси автора добавить ее в issue или PR description.

Проверь решение с точки зрения формальной верификации: какие инварианты,
предусловия и постусловия можно доказать математически, а где доказуемость
слабая. Оцени решение с точки зрения теории игр: устойчивы ли стимулы,
нет ли выгодного обхода правил, и какое решение было бы сильнее.

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts

Comment on lines +123 to +135
const readDefaultGatewayIp = (): Effect.Effect<string | null> =>
Effect.try(() => parseLinuxDefaultGatewayIp(readFileSync("/proc/net/route", "utf8"))).pipe(
Effect.orElse(() => Effect.succeed(null))
)

const defaultPanelTunnelLocalhostHost = (): Effect.Effect<string> => {
const configured = process.env["DOCKER_GIT_PANEL_TUNNEL_LOCALHOST_HOST"]?.trim()
if (configured !== undefined && configured.length > 0) {
return Effect.succeed(configured)
}
return existsSync("/.dockerenv")
? readDefaultGatewayIp().pipe(Effect.map((gatewayIp) => gatewayIp ?? "172.17.0.1"))
: Effect.succeed("127.0.0.1")
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot May 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n --type=ts 'Context\.Tag|Layer\.effect|Layer\.(provide|succeed)|spawn\(|fetch\(|readFileSync\(|mkdirSync\(|rmSync\('

Repository: ProverCoderAI/docker-git

Length of output: 9823


🏁 Script executed:

#!/bin/bash
# Search for Layer and Context.Tag patterns more specifically in api services
rg -n 'Layer\.(effect|provide|succeed|launch|merge)' packages/api/src/services/ --type ts

Repository: ProverCoderAI/docker-git

Length of output: 50


🏁 Script executed:

#!/bin/bash
# Also search in the main program file to see if any patterns exist
rg -n 'Context\.Tag|Layer\.(effect|provide)' packages/api/src/ --type ts -A 2

Repository: ProverCoderAI/docker-git

Length of output: 240


🏁 Script executed:

#!/bin/bash
# Read the actual panel-cloudflare-tunnel.ts file to see the violations
wc -l packages/api/src/services/panel-cloudflare-tunnel.ts

Repository: ProverCoderAI/docker-git

Length of output: 125


🏁 Script executed:

#!/bin/bash
# Get the specific lines flagged in the review
sed -n '123,135p; 164,170p; 288,328p' packages/api/src/services/panel-cloudflare-tunnel.ts | cat -n

Repository: ProverCoderAI/docker-git

Length of output: 2428


Требуется рефакторинг внешних зависимостей через Context.Tag + Layer.effect для fs, process.env, fetch и spawn.

Текущая реализация напрямую вызывает Node API в Effect без типированных абстракций. Линии 123–135 (readFileSync), 164–170 (rmSync), 288–328 (mkdirSync, spawn, fetch) нарушают требование гайдлайна: "All external dependencies must be wrapped through typed interfaces and injected via Effect-TS Layer pattern". Это затрудняет изолированное тестирование, скрывает зависимости от /proc/net/route, окружения контейнера и локального FS, и не позволяет подменять реализации.

Необходимо завернуть эти эффекты в типированные Context.Tag сервисы (например, FileSystemService, ProcessService, HttpService) и инжектировать через Layer.effect.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/api/src/services/panel-cloudflare-tunnel.ts` around lines 123 - 135,
Refactor direct Node API uses into injected Effect-TS services: create typed
Context.Tag+Layer.effect services (e.g., FileSystemService with
readFileSync/rmSync/mkdirSync, ProcessService for env/isDocker detection,
HttpService for fetch, and ProcessSpawnService for spawn) and replace direct
calls inside readDefaultGatewayIp and defaultPanelTunnelLocalhostHost (and the
other spots using rmSync, mkdirSync, spawn, fetch) to use these services via
Effect.access/Effect.service or dependency injection; keep the same return types
(Effect.Effect<string|null> / Effect.Effect<string>) and map/error handling, and
wire the concrete Node implementations to the Layer for production and test
doubles for unit tests so all external FS/process/http/spawn calls are routed
through the new services.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not applying this heavy DI refactor in this PR. The current API package does not use custom Context.Tag/Layer services in service modules (the app is provided with NodeContext at the program boundary), and introducing new bespoke FS/process/http/spawn services here would be a broader architecture change rather than a local fix for issue #310. The direct Node calls are now isolated in the shell service layer, not in the pure core, and the runtime race/security issues from this review thread are handled in the follow-up commits.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@skulidropek, понял, аргумент про архитектурную согласованность принимается — вводить новые Context.Tag/Layer сервисы только в этом одном модуле при том, что остальная часть API-пакета работает с NodeContext на уровне программы, создало бы непоследовательность, а не улучшение. Изолирование прямых Node-вызовов в service layer (а не в чистом core) — разумный компромисс для текущего PR.

Хотите, чтобы я открыл follow-up issue для отслеживания потенциального рефакторинга FileSystemService/ProcessService/HttpService через Effect-TS Layer в API-сервисах (как отдельную архитектурную задачу, не блокирующую этот PR)?


✏️ Learnings added
Learnt from: skulidropek
Repo: ProverCoderAI/docker-git PR: 313
File: packages/api/src/services/panel-cloudflare-tunnel.ts:123-135
Timestamp: 2026-05-18T07:43:38.131Z
Learning: In the ProverCoderAI/docker-git API package, direct Node.js calls (fs, child_process, fetch) in service modules are intentional: NodeContext is provided at the program boundary, and custom Context.Tag/Layer services are not used inside individual service modules. Avoid flagging direct Node API calls in api/src/services/ as DI violations — the architecture deliberately keeps NodeContext at the program entry point rather than per-service injection.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Comment thread packages/api/src/services/panel-cloudflare-tunnel.ts
Comment thread packages/api/src/services/panel-cloudflare-tunnel.ts
@skulidropek
Copy link
Copy Markdown
Member Author

skulidropek commented May 18, 2026

AI Session Backup

Commit: 454838c
Status: success
Files: 6 (7.03 MB)
Links: README | Manifest

git status

On branch issue-310
Your branch is up to date with 'origin/issue-310'.

nothing to commit, working tree clean

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
packages/api/src/services/panel-cloudflare-tunnel.ts (1)

241-250: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Не теряйте handle процесса до завершения teardown.

Похожая гонка всё ещё остаётся в общем stop-path: stopRecord() обнуляет record.process до waitForChildClose(). Если аварийный runStopRecord() уже начал остановку, а новый startPanelCloudflareTunnel() потом доходит до Lines 387-389, повторный stopRecord(currentRecord) видит child === null и сразу продолжает replacement-start, хотя старый cloudflared ещё может не закрыться. Это снова открывает окно для перекрывающихся tunnel-процессов и затирания failure snapshot старой сессии. Сохраните handle до фактического завершения close либо заведите отдельный in-flight stop promise/effect, который последующие stop/start будут ожидать вместо мгновенного short-circuit.

Also applies to: 386-389

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/api/src/services/panel-cloudflare-tunnel.ts` around lines 241 - 250,
stopRecord currently clears record.process before waiting for the child to exit,
allowing a race where another start/stop sees null and proceeds while the old
process is still running; change stopRecord (and the similar code around
startPanelCloudflareTunnel / runStopRecord) to retain the process handle until
waitForChildClose completes (e.g., capture record.process in a local variable
and only set record.process = null after waitForChildClose resolves) or add an
in-flight stop Effect/promise on the record (e.g., record.stoppingEffect) that
is set at the start of stopRecord and awaited by subsequent callers instead of
short-circuiting, then clear record.process and record.stopping/stoppingEffect
only after finishStoppedRecord runs; update references to finishStoppedRecord,
waitForChildClose, runStopRecord and startPanelCloudflareTunnel accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@packages/api/src/services/panel-cloudflare-tunnel.ts`:
- Around line 241-250: stopRecord currently clears record.process before waiting
for the child to exit, allowing a race where another start/stop sees null and
proceeds while the old process is still running; change stopRecord (and the
similar code around startPanelCloudflareTunnel / runStopRecord) to retain the
process handle until waitForChildClose completes (e.g., capture record.process
in a local variable and only set record.process = null after waitForChildClose
resolves) or add an in-flight stop Effect/promise on the record (e.g.,
record.stoppingEffect) that is set at the start of stopRecord and awaited by
subsequent callers instead of short-circuiting, then clear record.process and
record.stopping/stoppingEffect only after finishStoppedRecord runs; update
references to finishStoppedRecord, waitForChildClose, runStopRecord and
startPanelCloudflareTunnel accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ba9a4fcb-1875-427d-9f8b-83f246492e5b

📥 Commits

Reviewing files that changed from the base of the PR and between 7559324 and 454838c.

📒 Files selected for processing (1)
  • packages/api/src/services/panel-cloudflare-tunnel.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
  • GitHub Check: E2E (Browser command)
  • GitHub Check: E2E (OpenCode)
  • GitHub Check: E2E (Runtime volumes + SSH)
  • GitHub Check: E2E (Clone cache)
  • GitHub Check: E2E (Login context)
  • GitHub Check: Lint
  • GitHub Check: E2E (Clone auto-open SSH)
  • GitHub Check: Test
  • GitHub Check: Final build (windows-latest)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Implement Functional Core, Imperative Shell (FCIS) pattern: CORE layer contains only pure functions with immutable data and mathematical operations; SHELL layer isolates all effects (IO, network, database). Strict dependency direction: SHELL → CORE (never reverse).
Never use any, unknown, eslint-disable, ts-ignore, or as type assertions (except in rigorously justified cases with documentation). Always use exhaustive union type analysis through .exhaustive() pattern matching.
All external dependencies must be wrapped through typed interfaces and injected via Effect-TS Layer pattern. Never call external services directly from CORE functions.
Use monadic composition with Effect-TS for all effects: Effect<Success, Error, Requirements>. Compose effects through pipe() and Effect.flatMap(). Implement dependency injection via Layer pattern. Handle errors without try/catch blocks.
All functions must be pure in the CORE layer: no side effects (logging, console output, IO operations, mutations). Separate all side effects into the SHELL layer.
Use exhaustive pattern matching with Effect.Match instead of switch statements. Example: Match.value(item).pipe(Match.when(...), Match.exhaustive).
Document all functions with comprehensive TSDoc including: @pure (true/false), @effect (required services), @invariant (mathematical invariants), @precondition, @postcondition, @complexity (time and space), @throws Never (errors must be typed in Effect).
Use functional comment markers for code clarity: CHANGE (brief description), WHY (mathematical/architectural justification), QUOTE(ТЗ) (requirement citation), REF (RTM or message ID), SOURCE (external source with quote), FORMAT THEOREM (∀x ∈ Domain: P(x) → Q(f(x))), PURITY (CORE|SHELL), EFFECT (Effect type signature), INVARIANT (mathematical invariant), COMPLEXITY (time/space).
Define all external service dependencies as Context.Tag classes with fully typed methods returning Effect types. Example: `class Da...

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,js,jsx}: Forbidden constructs in CORE code: any, eslint-disable, ts-ignore, async/await, raw Promise chains (then/catch), Promise.all, try/catch for logic control, console.*, switch statements (use Match with .exhaustive() instead)
All functions must use Effect-TS for composing effects: Effect<Success, Error, Requirements>. No direct async/await, Promise chains, or try/catch in product logic.
Functional comments must include: CHANGE, WHY, QUOTE(ТЗ) or n/a, REF, SOURCE or n/a, FORMAT THEOREM, PURITY (CORE|SHELL), EFFECT signature for SHELL functions, INVARIANT, and COMPLEXITY.
All data mutations must use immutable patterns (ReadonlyArray, readonly properties, Object.freeze); mutation in SHELL only when absolutely necessary and documented.

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{sh,bash,py,js,ts,jsx,tsx,go,java,rb,php}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files introduce command injection or unsafe shell/process execution with user-controlled input

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{py,js,ts,jsx,tsx,go,java,rb,php,sh,bash,c,cpp}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files introduce path traversal or writes outside intended project/container state directories

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{js,ts,jsx,tsx,py,java,go,rb,php,sh,bash,yml,yaml,json,env*,toml,cfg,config,dockerfile,dockerignore}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files expose credentials, tokens, private-keys, or PII in source, generated config, logs, or CI output

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*

⚙️ CodeRabbit configuration file

**/*: Ты строгий ревьюер SPEC DRIVEN DEVELOPMENT.

Перед выводами изучи README.md, другие *.md файлы, linked issues,
PR description, PR comments/discussion и релевантную кодовую базу.

Сверь изменения с исходным ТЗ/спекой и обсуждением. Флагай любой уход
от спеки, недокументированное изменение поведения, отсутствие тестов
для заявленного поведения и security-риск. Если спека не видна,
попроси автора добавить ее в issue или PR description.

Проверь решение с точки зрения формальной верификации: какие инварианты,
предусловия и постусловия можно доказать математически, а где доказуемость
слабая. Оцени решение с точки зрения теории игр: устойчивы ли стимулы,
нет ли выгодного обхода правил, и какое решение было бы сильнее.

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
🧠 Learnings (1)
📚 Learning: 2026-05-18T07:43:38.131Z
Learnt from: skulidropek
Repo: ProverCoderAI/docker-git PR: 313
File: packages/api/src/services/panel-cloudflare-tunnel.ts:123-135
Timestamp: 2026-05-18T07:43:38.131Z
Learning: In this repo’s ProverCoderAI/docker-git architecture, it is intentional for service modules under packages/api/src/services/ to call Node.js APIs directly (e.g., fs, child_process, fetch). Do not treat direct Node API usage in these service modules as a dependency-injection (DI) violation. This codebase provides the NodeContext at the program boundary (entry point) rather than injecting Context.Tag/Layer services into individual service modules; reviewers should only flag DI/context issues if the expected boundary setup is missing.

Applied to files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
🔇 Additional comments (1)
packages/api/src/services/panel-cloudflare-tunnel.ts (1)

113-136: LGTM!

Also applies to: 347-370, 401-458

@skulidropek
Copy link
Copy Markdown
Member Author

skulidropek commented May 18, 2026

AI Session Backup

Commit: 7505bac
Status: success
Files: 6 (7.33 MB)
Links: README | Manifest

git status

On branch issue-310
Your branch is up to date with 'origin/issue-310'.

nothing to commit, working tree clean

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/api/src/services/panel-cloudflare-tunnel.ts`:
- Around line 67-76: The code that calls updateRecord(...) from
appendLogLine()/flushRemainder() currently unconditionally sets status:
"running" when it sees a trycloudflare URL, which can resurrect a record already
finalized by finishStoppedRecord(); change the logic so
appendLogLine()/flushRemainder() only sets publicUrl/error but does NOT change
status to "running" if the current record is in a final state (e.g., "stopped"
or "failed"), or read the latest record status first and bail on setting status
when final; update the call sites (appendLogLine, flushRemainder) to pass an
object that omits status when record.status is final, or add a helper check
inside updateRecord to ignore transitions from final states back to "running".
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: e4965fed-d12f-481f-adb1-929b06b0b1f8

📥 Commits

Reviewing files that changed from the base of the PR and between 454838c and 7505bac.

📒 Files selected for processing (1)
  • packages/api/src/services/panel-cloudflare-tunnel.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: E2E (Runtime volumes + SSH)
  • GitHub Check: E2E (Login context)
  • GitHub Check: E2E (Clone cache)
  • GitHub Check: E2E (Browser command)
  • GitHub Check: Lint
  • GitHub Check: E2E (Clone auto-open SSH)
  • GitHub Check: E2E (OpenCode)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Implement Functional Core, Imperative Shell (FCIS) pattern: CORE layer contains only pure functions with immutable data and mathematical operations; SHELL layer isolates all effects (IO, network, database). Strict dependency direction: SHELL → CORE (never reverse).
Never use any, unknown, eslint-disable, ts-ignore, or as type assertions (except in rigorously justified cases with documentation). Always use exhaustive union type analysis through .exhaustive() pattern matching.
All external dependencies must be wrapped through typed interfaces and injected via Effect-TS Layer pattern. Never call external services directly from CORE functions.
Use monadic composition with Effect-TS for all effects: Effect<Success, Error, Requirements>. Compose effects through pipe() and Effect.flatMap(). Implement dependency injection via Layer pattern. Handle errors without try/catch blocks.
All functions must be pure in the CORE layer: no side effects (logging, console output, IO operations, mutations). Separate all side effects into the SHELL layer.
Use exhaustive pattern matching with Effect.Match instead of switch statements. Example: Match.value(item).pipe(Match.when(...), Match.exhaustive).
Document all functions with comprehensive TSDoc including: @pure (true/false), @effect (required services), @invariant (mathematical invariants), @precondition, @postcondition, @complexity (time and space), @throws Never (errors must be typed in Effect).
Use functional comment markers for code clarity: CHANGE (brief description), WHY (mathematical/architectural justification), QUOTE(ТЗ) (requirement citation), REF (RTM or message ID), SOURCE (external source with quote), FORMAT THEOREM (∀x ∈ Domain: P(x) → Q(f(x))), PURITY (CORE|SHELL), EFFECT (Effect type signature), INVARIANT (mathematical invariant), COMPLEXITY (time/space).
Define all external service dependencies as Context.Tag classes with fully typed methods returning Effect types. Example: `class Da...

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,js,jsx}: Forbidden constructs in CORE code: any, eslint-disable, ts-ignore, async/await, raw Promise chains (then/catch), Promise.all, try/catch for logic control, console.*, switch statements (use Match with .exhaustive() instead)
All functions must use Effect-TS for composing effects: Effect<Success, Error, Requirements>. No direct async/await, Promise chains, or try/catch in product logic.
Functional comments must include: CHANGE, WHY, QUOTE(ТЗ) or n/a, REF, SOURCE or n/a, FORMAT THEOREM, PURITY (CORE|SHELL), EFFECT signature for SHELL functions, INVARIANT, and COMPLEXITY.
All data mutations must use immutable patterns (ReadonlyArray, readonly properties, Object.freeze); mutation in SHELL only when absolutely necessary and documented.

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{sh,bash,py,js,ts,jsx,tsx,go,java,rb,php}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files introduce command injection or unsafe shell/process execution with user-controlled input

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{py,js,ts,jsx,tsx,go,java,rb,php,sh,bash,c,cpp}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files introduce path traversal or writes outside intended project/container state directories

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{js,ts,jsx,tsx,py,java,go,rb,php,sh,bash,yml,yaml,json,env*,toml,cfg,config,dockerfile,dockerignore}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files expose credentials, tokens, private-keys, or PII in source, generated config, logs, or CI output

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*

⚙️ CodeRabbit configuration file

**/*: Ты строгий ревьюер SPEC DRIVEN DEVELOPMENT.

Перед выводами изучи README.md, другие *.md файлы, linked issues,
PR description, PR comments/discussion и релевантную кодовую базу.

Сверь изменения с исходным ТЗ/спекой и обсуждением. Флагай любой уход
от спеки, недокументированное изменение поведения, отсутствие тестов
для заявленного поведения и security-риск. Если спека не видна,
попроси автора добавить ее в issue или PR description.

Проверь решение с точки зрения формальной верификации: какие инварианты,
предусловия и постусловия можно доказать математически, а где доказуемость
слабая. Оцени решение с точки зрения теории игр: устойчивы ли стимулы,
нет ли выгодного обхода правил, и какое решение было бы сильнее.

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
🧠 Learnings (1)
📚 Learning: 2026-05-18T07:43:38.131Z
Learnt from: skulidropek
Repo: ProverCoderAI/docker-git PR: 313
File: packages/api/src/services/panel-cloudflare-tunnel.ts:123-135
Timestamp: 2026-05-18T07:43:38.131Z
Learning: In this repo’s ProverCoderAI/docker-git architecture, it is intentional for service modules under packages/api/src/services/ to call Node.js APIs directly (e.g., fs, child_process, fetch). Do not treat direct Node API usage in these service modules as a dependency-injection (DI) violation. This codebase provides the NodeContext at the program boundary (entry point) rather than injecting Context.Tag/Layer services into individual service modules; reviewers should only flag DI/context issues if the expected boundary setup is missing.

Applied to files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts

Comment thread packages/api/src/services/panel-cloudflare-tunnel.ts
@skulidropek
Copy link
Copy Markdown
Member Author

skulidropek commented May 18, 2026

AI Session Backup

Commit: 3e0d142
Status: success
Files: 6 (7.43 MB)
Links: README | Manifest

git status

On branch issue-310
Your branch is up to date with 'origin/issue-310'.

nothing to commit, working tree clean

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/api/src/services/panel-cloudflare-tunnel.ts`:
- Around line 328-340: The preflight fetch started inside Effect.tryPromise (the
fetch(targetUrl, { method: "GET", redirect: "manual", signal:
AbortSignal.timeout(5_000) }) call) does not explicitly close the Response body,
leaving sockets pooled; modify the try branch so it awaits the Response, then
explicitly drain or cancel the body (e.g., call response.body.cancel() or read
and discard body) before returning; keep the ApiBadRequestError wrapping in the
catch as-is and preserve the Effect.asVoid pipe so the effect semantics remain
unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 72081761-e37b-4a9a-9b0b-9cefc1eb82e1

📥 Commits

Reviewing files that changed from the base of the PR and between 7505bac and 3e0d142.

📒 Files selected for processing (1)
  • packages/api/src/services/panel-cloudflare-tunnel.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: E2E (Runtime volumes + SSH)
  • GitHub Check: E2E (Login context)
  • GitHub Check: E2E (OpenCode)
  • GitHub Check: E2E (Clone auto-open SSH)
  • GitHub Check: E2E (Clone cache)
  • GitHub Check: E2E (Browser command)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Implement Functional Core, Imperative Shell (FCIS) pattern: CORE layer contains only pure functions with immutable data and mathematical operations; SHELL layer isolates all effects (IO, network, database). Strict dependency direction: SHELL → CORE (never reverse).
Never use any, unknown, eslint-disable, ts-ignore, or as type assertions (except in rigorously justified cases with documentation). Always use exhaustive union type analysis through .exhaustive() pattern matching.
All external dependencies must be wrapped through typed interfaces and injected via Effect-TS Layer pattern. Never call external services directly from CORE functions.
Use monadic composition with Effect-TS for all effects: Effect<Success, Error, Requirements>. Compose effects through pipe() and Effect.flatMap(). Implement dependency injection via Layer pattern. Handle errors without try/catch blocks.
All functions must be pure in the CORE layer: no side effects (logging, console output, IO operations, mutations). Separate all side effects into the SHELL layer.
Use exhaustive pattern matching with Effect.Match instead of switch statements. Example: Match.value(item).pipe(Match.when(...), Match.exhaustive).
Document all functions with comprehensive TSDoc including: @pure (true/false), @effect (required services), @invariant (mathematical invariants), @precondition, @postcondition, @complexity (time and space), @throws Never (errors must be typed in Effect).
Use functional comment markers for code clarity: CHANGE (brief description), WHY (mathematical/architectural justification), QUOTE(ТЗ) (requirement citation), REF (RTM or message ID), SOURCE (external source with quote), FORMAT THEOREM (∀x ∈ Domain: P(x) → Q(f(x))), PURITY (CORE|SHELL), EFFECT (Effect type signature), INVARIANT (mathematical invariant), COMPLEXITY (time/space).
Define all external service dependencies as Context.Tag classes with fully typed methods returning Effect types. Example: `class Da...

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,js,jsx}: Forbidden constructs in CORE code: any, eslint-disable, ts-ignore, async/await, raw Promise chains (then/catch), Promise.all, try/catch for logic control, console.*, switch statements (use Match with .exhaustive() instead)
All functions must use Effect-TS for composing effects: Effect<Success, Error, Requirements>. No direct async/await, Promise chains, or try/catch in product logic.
Functional comments must include: CHANGE, WHY, QUOTE(ТЗ) or n/a, REF, SOURCE or n/a, FORMAT THEOREM, PURITY (CORE|SHELL), EFFECT signature for SHELL functions, INVARIANT, and COMPLEXITY.
All data mutations must use immutable patterns (ReadonlyArray, readonly properties, Object.freeze); mutation in SHELL only when absolutely necessary and documented.

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{sh,bash,py,js,ts,jsx,tsx,go,java,rb,php}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files introduce command injection or unsafe shell/process execution with user-controlled input

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{py,js,ts,jsx,tsx,go,java,rb,php,sh,bash,c,cpp}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files introduce path traversal or writes outside intended project/container state directories

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{js,ts,jsx,tsx,py,java,go,rb,php,sh,bash,yml,yaml,json,env*,toml,cfg,config,dockerfile,dockerignore}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files expose credentials, tokens, private-keys, or PII in source, generated config, logs, or CI output

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*

⚙️ CodeRabbit configuration file

**/*: Ты строгий ревьюер SPEC DRIVEN DEVELOPMENT.

Перед выводами изучи README.md, другие *.md файлы, linked issues,
PR description, PR comments/discussion и релевантную кодовую базу.

Сверь изменения с исходным ТЗ/спекой и обсуждением. Флагай любой уход
от спеки, недокументированное изменение поведения, отсутствие тестов
для заявленного поведения и security-риск. Если спека не видна,
попроси автора добавить ее в issue или PR description.

Проверь решение с точки зрения формальной верификации: какие инварианты,
предусловия и постусловия можно доказать математически, а где доказуемость
слабая. Оцени решение с точки зрения теории игр: устойчивы ли стимулы,
нет ли выгодного обхода правил, и какое решение было бы сильнее.

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
🧠 Learnings (1)
📚 Learning: 2026-05-18T07:43:38.131Z
Learnt from: skulidropek
Repo: ProverCoderAI/docker-git PR: 313
File: packages/api/src/services/panel-cloudflare-tunnel.ts:123-135
Timestamp: 2026-05-18T07:43:38.131Z
Learning: In this repo’s ProverCoderAI/docker-git architecture, it is intentional for service modules under packages/api/src/services/ to call Node.js APIs directly (e.g., fs, child_process, fetch). Do not treat direct Node API usage in these service modules as a dependency-injection (DI) violation. This codebase provides the NodeContext at the program boundary (entry point) rather than injecting Context.Tag/Layer services into individual service modules; reviewers should only flag DI/context issues if the expected boundary setup is missing.

Applied to files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts

Comment thread packages/api/src/services/panel-cloudflare-tunnel.ts Outdated
@skulidropek
Copy link
Copy Markdown
Member Author

skulidropek commented May 18, 2026

AI Session Backup

Commit: e3b5fcd
Status: success
Files: 6 (7.55 MB)
Links: README | Manifest

git status

On branch issue-310
Your branch is up to date with 'origin/issue-310'.

nothing to commit, working tree clean

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
packages/api/src/services/panel-cloudflare-tunnel.ts (1)

202-245: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Не завершайте stop-путь по exit — дождитесь именно close.

waitForChildClose() сейчас резолвится и по exit, и по уже выставленным exitCode/signalCode, поэтому stopRecord() может вызвать finishStoppedRecord() раньше close-обработчика на Lines 289-297. В этом окне теряются flushRemainder()/последние логи, а аварийный выход легко маскируется как обычный "stopped" при manual stop или replacement-start. Здесь безопаснее завершать ожидание только по close (оставив error лишь как fallback для spawn-failure) и не short-circuit'ить по exitCode.

🛠️ Минимальное направление фикса
 const waitForChildClose = (child: ChildProcess): Effect.Effect<void> => {
-  if (child.exitCode !== null || child.signalCode !== null) {
-    return Effect.void
-  }
-
   return Effect.async((resume) => {
+    const alreadyExited = child.exitCode !== null || child.signalCode !== null
     let completed = false
     let killTimer: ReturnType<typeof setTimeout> | null = null
     const complete = (): void => {
       if (completed) {
         return
       }
       completed = true
       child.off("close", complete)
       child.off("error", complete)
-      child.off("exit", complete)
       if (killTimer !== null) {
         clearTimeout(killTimer)
       }
       resume(Effect.void)
     }

     child.once("close", complete)
     child.once("error", complete)
-    child.once("exit", complete)
-    if (!child.killed) {
+    if (!alreadyExited && !child.killed) {
       try {
         child.kill("SIGTERM")
       } catch {
         complete()
         return
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/api/src/services/panel-cloudflare-tunnel.ts` around lines 202 - 245,
waitForChildClose currently resolves on exit events and when exitCode/signalCode
is already set, which allows stopRecord to call finishStoppedRecord before the
child's "close" handler (which does flushRemainder) runs; modify
waitForChildClose so it does not short-circuit on child.exitCode or
child.signalCode and does not resolve on "exit" — only resolve when the "close"
event fires (keep "error" as a fallback for spawn failures), ensure the
completion callback removes listeners and clears the killTimer as before, and
retain the SIGTERM->SIGKILL logic but only trigger resolution from the "close"
handler to avoid losing final logs and misclassifying abrupt exits as normal
stopped events.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@packages/api/src/services/panel-cloudflare-tunnel.ts`:
- Around line 202-245: waitForChildClose currently resolves on exit events and
when exitCode/signalCode is already set, which allows stopRecord to call
finishStoppedRecord before the child's "close" handler (which does
flushRemainder) runs; modify waitForChildClose so it does not short-circuit on
child.exitCode or child.signalCode and does not resolve on "exit" — only resolve
when the "close" event fires (keep "error" as a fallback for spawn failures),
ensure the completion callback removes listeners and clears the killTimer as
before, and retain the SIGTERM->SIGKILL logic but only trigger resolution from
the "close" handler to avoid losing final logs and misclassifying abrupt exits
as normal stopped events.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 7d69ef50-cd09-4335-a392-debbb179459b

📥 Commits

Reviewing files that changed from the base of the PR and between 3e0d142 and e3b5fcd.

📒 Files selected for processing (1)
  • packages/api/src/services/panel-cloudflare-tunnel.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: E2E (Browser command)
  • GitHub Check: E2E (Clone cache)
  • GitHub Check: E2E (OpenCode)
  • GitHub Check: E2E (Clone auto-open SSH)
  • GitHub Check: E2E (Runtime volumes + SSH)
  • GitHub Check: E2E (Login context)
  • GitHub Check: Lint
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Implement Functional Core, Imperative Shell (FCIS) pattern: CORE layer contains only pure functions with immutable data and mathematical operations; SHELL layer isolates all effects (IO, network, database). Strict dependency direction: SHELL → CORE (never reverse).
Never use any, unknown, eslint-disable, ts-ignore, or as type assertions (except in rigorously justified cases with documentation). Always use exhaustive union type analysis through .exhaustive() pattern matching.
All external dependencies must be wrapped through typed interfaces and injected via Effect-TS Layer pattern. Never call external services directly from CORE functions.
Use monadic composition with Effect-TS for all effects: Effect<Success, Error, Requirements>. Compose effects through pipe() and Effect.flatMap(). Implement dependency injection via Layer pattern. Handle errors without try/catch blocks.
All functions must be pure in the CORE layer: no side effects (logging, console output, IO operations, mutations). Separate all side effects into the SHELL layer.
Use exhaustive pattern matching with Effect.Match instead of switch statements. Example: Match.value(item).pipe(Match.when(...), Match.exhaustive).
Document all functions with comprehensive TSDoc including: @pure (true/false), @effect (required services), @invariant (mathematical invariants), @precondition, @postcondition, @complexity (time and space), @throws Never (errors must be typed in Effect).
Use functional comment markers for code clarity: CHANGE (brief description), WHY (mathematical/architectural justification), QUOTE(ТЗ) (requirement citation), REF (RTM or message ID), SOURCE (external source with quote), FORMAT THEOREM (∀x ∈ Domain: P(x) → Q(f(x))), PURITY (CORE|SHELL), EFFECT (Effect type signature), INVARIANT (mathematical invariant), COMPLEXITY (time/space).
Define all external service dependencies as Context.Tag classes with fully typed methods returning Effect types. Example: `class Da...

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,js,jsx}: Forbidden constructs in CORE code: any, eslint-disable, ts-ignore, async/await, raw Promise chains (then/catch), Promise.all, try/catch for logic control, console.*, switch statements (use Match with .exhaustive() instead)
All functions must use Effect-TS for composing effects: Effect<Success, Error, Requirements>. No direct async/await, Promise chains, or try/catch in product logic.
Functional comments must include: CHANGE, WHY, QUOTE(ТЗ) or n/a, REF, SOURCE or n/a, FORMAT THEOREM, PURITY (CORE|SHELL), EFFECT signature for SHELL functions, INVARIANT, and COMPLEXITY.
All data mutations must use immutable patterns (ReadonlyArray, readonly properties, Object.freeze); mutation in SHELL only when absolutely necessary and documented.

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{sh,bash,py,js,ts,jsx,tsx,go,java,rb,php}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files introduce command injection or unsafe shell/process execution with user-controlled input

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{py,js,ts,jsx,tsx,go,java,rb,php,sh,bash,c,cpp}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files introduce path traversal or writes outside intended project/container state directories

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*.{js,ts,jsx,tsx,py,java,go,rb,php,sh,bash,yml,yaml,json,env*,toml,cfg,config,dockerfile,dockerignore}

📄 CodeRabbit inference engine (Custom checks)

Fail if changed files expose credentials, tokens, private-keys, or PII in source, generated config, logs, or CI output

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
**/*

⚙️ CodeRabbit configuration file

**/*: Ты строгий ревьюер SPEC DRIVEN DEVELOPMENT.

Перед выводами изучи README.md, другие *.md файлы, linked issues,
PR description, PR comments/discussion и релевантную кодовую базу.

Сверь изменения с исходным ТЗ/спекой и обсуждением. Флагай любой уход
от спеки, недокументированное изменение поведения, отсутствие тестов
для заявленного поведения и security-риск. Если спека не видна,
попроси автора добавить ее в issue или PR description.

Проверь решение с точки зрения формальной верификации: какие инварианты,
предусловия и постусловия можно доказать математически, а где доказуемость
слабая. Оцени решение с точки зрения теории игр: устойчивы ли стимулы,
нет ли выгодного обхода правил, и какое решение было бы сильнее.

Files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
🧠 Learnings (1)
📚 Learning: 2026-05-18T07:43:38.131Z
Learnt from: skulidropek
Repo: ProverCoderAI/docker-git PR: 313
File: packages/api/src/services/panel-cloudflare-tunnel.ts:123-135
Timestamp: 2026-05-18T07:43:38.131Z
Learning: In this repo’s ProverCoderAI/docker-git architecture, it is intentional for service modules under packages/api/src/services/ to call Node.js APIs directly (e.g., fs, child_process, fetch). Do not treat direct Node API usage in these service modules as a dependency-injection (DI) violation. This codebase provides the NodeContext at the program boundary (entry point) rather than injecting Context.Tag/Layer services into individual service modules; reviewers should only flag DI/context issues if the expected boundary setup is missing.

Applied to files:

  • packages/api/src/services/panel-cloudflare-tunnel.ts
🔇 Additional comments (1)
packages/api/src/services/panel-cloudflare-tunnel.ts (1)

56-116: LGTM!

Also applies to: 118-131, 325-350, 369-392, 423-457

@skulidropek
Copy link
Copy Markdown
Member Author

skulidropek commented May 18, 2026

AI Session Backup

Commit: 58ef159
Status: success
Files: 6 (7.66 MB)
Links: README | Manifest

git status

On branch issue-310
Your branch is up to date with 'origin/issue-310'.

nothing to commit, working tree clean

@skulidropek skulidropek merged commit e770dff into main May 18, 2026
19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Добавить возможность из коробки поднимать cloudflare tunnel

1 participant