'0.11.0', // Deployed commit + branch. install.sh bakes these into .env from the host's .git (the prod // image ships no .git); the Versions page prefers them and falls back to a live .git read in // dev. Empty in dev (no install.sh run) → the .git fallback fills them in. 'build' => [ 'sha' => env('CLUSEV_BUILD_SHA') ?: null, 'branch' => env('CLUSEV_BUILD_BRANCH') ?: null, ], // Single stable release channel — users only ever receive finalized vX.Y.Z releases. 'channel' => 'stable', // Install-time panel domain (APP_DOMAIN). The dashboard Setting overrides it; this // is the fallback so a domain set during install still gets automatic TLS. 'domain' => env('APP_DOMAIN'), // Public documentation site. The dashboard's "Hilfe" entry (sidebar + command palette + // the `g h` shortcut) opens this instead of duplicating docs in-panel. Canonical for every // install; env-overridable for a private/mirrored docs host. 'docs_url' => env('CLUSEV_DOCS_URL', 'https://docs.clusev.com'), // Update source. Defaults to the PUBLIC repo (safe to ship — it is public). install.sh overrides // it via CLUSEV_REPOSITORY, derived from the clone origin: dev points at the private upstream, // staging at the private mirror, public users at the public repo. Private (upstream/mirror) URLs live // ONLY in the gitignored .env — never in tracked files, so the public repo exposes no private URL. 'repository' => env('CLUSEV_REPOSITORY', 'https://github.com/clusev/clusev'), // Dev-only release controls (the dashboard "Release" page + host git-push bridge). OFF by default // so customer/staging installs never expose release controls. Set true ONLY in the dev .env. 'release_controls' => env('CLUSEV_RELEASE_CONTROLS', false), // Live pipeline status (dev Release page). Read-only GitHub token + the GitHub-private staging // repo slug — BOTH private, so empty tracked default and set ONLY in the dev .env (never tracked). 'github_token' => env('GIT_STAGING_ACCESS_TOKEN', ''), 'staging_slug' => env('CLUSEV_STAGING_SLUG', ''), // Public repo (for promotion targets + reading published tags). PUBLIC, so a tracked default is // fine. The dispatch ref is the branch the promote/yank workflows live on (mirrored to staging). 'public_slug' => env('CLUSEV_PUBLIC_SLUG', 'clusev/clusev'), 'release_branch' => env('CLUSEV_RELEASE_BRANCH', 'feat/v1-foundation'), // Shared secret the terminal sidecar presents to the internal resolve endpoint (which hands out // decrypted SSH credentials). Set in .env; the sidecar gets the SAME value. Empty = endpoint 403s // (terminal disabled). install.sh generates it alongside the other secrets. 'terminal_secret' => env('TERMINAL_SIDECAR_SECRET', ''), // Shared secret used to AUTHENTICATE the update-request marker the app drops for the host updater. // The app signs the marker (HMAC-SHA256) and the host-side watch.sh verifies it before running a // root update, so a stray/limited write to the shared ./run dir cannot drive one. install.sh // generates it alongside the other secrets; the host reads the SAME value from .env. 'update_hmac_key' => env('UPDATE_HMAC_KEY', ''), 'honeypot' => [ // Deception layer for unauthenticated attacker probes. ON by default: legit users never hit // decoy paths, so there are no false positives. Set CLUSEV_HONEYPOT=false to disable. 'enabled' => (bool) env('CLUSEV_HONEYPOT', true), // Per-install RANDOM canary secret values (install.sh generates them into .env). EMPTY here so // no guessable/public constant ships; empty => honeytoken detection is OFF (the served fake .env // still uses plausible static values, they are just not registered as detectable canaries). 'canaries' => array_filter([ 'app_key' => (string) env('CLUSEV_HONEYPOT_CANARY_APP', ''), 'db_password' => (string) env('CLUSEV_HONEYPOT_CANARY_DB', ''), 'api_key' => (string) env('CLUSEV_HONEYPOT_CANARY_API', ''), ]), ], 'license' => 'AGPL-3.0', ];