From b2500da7de407891b768aa1910d41624b3420304 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 1 Feb 2026 02:03:34 +0200 Subject: [PATCH] Fix npm build permissions and add project docs --- AGENTS.md | 25 +++++++++++++ CONTEXT.md | 35 +++++++++++++++++++ DECISIONS.md | 8 +++++ TODO.md | 8 +++++ VERSION | 2 +- .../Commands/Jabali/UpgradeCommand.php | 35 +++++++++++++++++-- install.sh | 24 +++++++++++-- 7 files changed, 130 insertions(+), 7 deletions(-) create mode 100644 AGENTS.md create mode 100644 CONTEXT.md create mode 100644 DECISIONS.md create mode 100644 TODO.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..4e1850b --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,25 @@ +# AGENTS.md + +Rules and behavior for automated agents working on Jabali. + +## Baseline +- Read `AGENT.md` first; it is the authoritative project guide. +- Work from `/var/www/jabali`. +- Use ASCII in edits unless the file already uses Unicode. + +## Editing +- Prefer `rg` for search; fall back to `grep` if needed. +- Use `apply_patch` for small manual edits. +- Avoid `apply_patch` for generated files (build artifacts, lockfiles, etc.). +- Avoid destructive git commands unless explicitly requested. + +## Git +- Do not push unless the user explicitly asks. +- Bump `VERSION` before every push. +- Keep `install.sh` version fallback in sync with `VERSION`. + +## Operational +- If you add dependencies, update both install and uninstall paths. +- For installer/upgrade changes, consider ownership/permissions for: + - `storage/`, `bootstrap/cache/`, `public/build/`, `node_modules/`. +- Run tests if available; if not, report what is missing. diff --git a/CONTEXT.md b/CONTEXT.md new file mode 100644 index 0000000..b69fa9f --- /dev/null +++ b/CONTEXT.md @@ -0,0 +1,35 @@ +# CONTEXT.md + +Last updated: 2026-02-01 + +## Stack +- Laravel 12, Filament v5, Livewire v4 +- PHP 8.4, Node 20, Vite +- Debian 12/13 target + +## Panels +- Admin panel: `/jabali-admin` +- User panel: `/jabali-panel` + +## Data +- Panel config DB: SQLite at `database/database.sqlite` +- Hosting services use MariaDB/Postfix/Dovecot/etc. as configured by the agent + +## Services & Agents +- Privileged agent: `bin/jabali-agent` (root) +- Health monitor: `bin/jabali-health-monitor` + +## Server Status Charts +- Data source: `app/Services/SysstatMetrics.php` +- Uses sysstat logs under `/var/log/sysstat` + +## Installer / Upgrade +- Installer: `install.sh` + - Clones repo to `/var/www/jabali` + - Uses `www-data` as the runtime user + - Builds assets with Vite to `public/build` + - Sets npm caches under `storage/` +- Upgrade: `php artisan jabali:upgrade` + - Handles git safe.directory + - Runs composer/npm when needed + - Ensures writable permissions for `node_modules` and `public/build` diff --git a/DECISIONS.md b/DECISIONS.md new file mode 100644 index 0000000..d8d5bac --- /dev/null +++ b/DECISIONS.md @@ -0,0 +1,8 @@ +# DECISIONS.md + +## 2026-02-01 +- Server status charts read from sysstat logs via `SysstatMetrics` (no internal server_metrics table). +- Upgrade command manages npm caches in `storage/` and skips puppeteer downloads. +- Asset builds must be writable for `public/build` and `node_modules`; upgrade checks both. +- Installer builds assets as `www-data` to avoid permission issues. +- Default panel database is SQLite (`database/database.sqlite`). diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..4945864 --- /dev/null +++ b/TODO.md @@ -0,0 +1,8 @@ +# TODO.md + +Keep this list current as work progresses. + +- [ ] Verify server updates refresh/upgrade output appears in the accordion. +- [ ] Confirm WAF whitelist + blocked requests tables refresh correctly after changes. +- [ ] Validate sysstat collection interval (10s) and chart intervals align. +- [ ] Audit installer/uninstaller parity for newly added packages. diff --git a/VERSION b/VERSION index 4871c45..6f42e4a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -VERSION=0.9-rc37 +VERSION=0.9-rc39 diff --git a/app/Console/Commands/Jabali/UpgradeCommand.php b/app/Console/Commands/Jabali/UpgradeCommand.php index 688d7c6..de27a97 100644 --- a/app/Console/Commands/Jabali/UpgradeCommand.php +++ b/app/Console/Commands/Jabali/UpgradeCommand.php @@ -187,9 +187,18 @@ class UpgradeCommand extends Command $this->ensureNpmCacheDirectory(); $this->ensureNodeModulesPermissions(); $this->ensurePublicBuildPermissions(); - if (! $this->isNodeModulesWritable()) { - $this->warn('Skipping frontend build because node_modules is not writable by the current user.'); - $this->warn('Run: sudo chown -R www-data:www-data '.$this->getNodeModulesPath()); + $nodeModulesWritable = $this->isNodeModulesWritable(); + $publicBuildWritable = $this->isPublicBuildWritable(); + if (! $nodeModulesWritable || ! $publicBuildWritable) { + $this->warn('Skipping frontend build because asset paths are not writable by the current user.'); + if (! $nodeModulesWritable) { + $this->warn('node_modules is not writable.'); + $this->warn('Run: sudo chown -R www-data:www-data '.$this->getNodeModulesPath()); + } + if (! $publicBuildWritable) { + $this->warn('public/build is not writable.'); + $this->warn('Run: sudo chown -R www-data:www-data '.$this->getPublicBuildPath()); + } } else { $npmInstall = File::exists($this->basePath.'/package-lock.json') ? 'npm ci' : 'npm install'; $installResult = $this->executeCommand($npmInstall, 1200); @@ -537,6 +546,26 @@ class UpgradeCommand extends Command return true; } + protected function isPublicBuildWritable(): bool + { + $buildPath = $this->getPublicBuildPath(); + + if (! File::isDirectory($buildPath)) { + return true; + } + + if (! is_writable($buildPath)) { + return false; + } + + $assetsPath = $buildPath.'/assets'; + if (File::isDirectory($assetsPath) && ! is_writable($assetsPath)) { + return false; + } + + return true; + } + protected function getNpmCacheDir(): string { return $this->basePath.'/storage/npm-cache'; diff --git a/install.sh b/install.sh index d27916a..5efa05f 100755 --- a/install.sh +++ b/install.sh @@ -16,7 +16,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" if [[ -f "$SCRIPT_DIR/VERSION" ]]; then JABALI_VERSION="$(sed -n 's/^VERSION=//p' "$SCRIPT_DIR/VERSION")" fi -JABALI_VERSION="${JABALI_VERSION:-0.9-rc36}" +JABALI_VERSION="${JABALI_VERSION:-0.9-rc39}" # Colors RED='\033[0;31m' @@ -2834,8 +2834,26 @@ ENV mkdir -p "$NPM_CONFIG_CACHE" "$PUPPETEER_CACHE_DIR" "$XDG_CACHE_HOME" chown -R "$JABALI_USER:www-data" "$NPM_CONFIG_CACHE" "$PUPPETEER_CACHE_DIR" "$XDG_CACHE_HOME" chmod -R 775 "$NPM_CONFIG_CACHE" "$PUPPETEER_CACHE_DIR" "$XDG_CACHE_HOME" - npm install - npm run build + mkdir -p "$JABALI_DIR/public/build" "$JABALI_DIR/node_modules" + chown -R "$JABALI_USER:www-data" "$JABALI_DIR/public/build" "$JABALI_DIR/node_modules" + chmod -R 775 "$JABALI_DIR/public/build" "$JABALI_DIR/node_modules" + if command -v sudo &>/dev/null; then + sudo -u "$JABALI_USER" -H env \ + NPM_CONFIG_CACHE="$NPM_CONFIG_CACHE" \ + PUPPETEER_SKIP_DOWNLOAD=1 \ + PUPPETEER_CACHE_DIR="$PUPPETEER_CACHE_DIR" \ + XDG_CACHE_HOME="$XDG_CACHE_HOME" \ + npm install + sudo -u "$JABALI_USER" -H env \ + NPM_CONFIG_CACHE="$NPM_CONFIG_CACHE" \ + PUPPETEER_SKIP_DOWNLOAD=1 \ + PUPPETEER_CACHE_DIR="$PUPPETEER_CACHE_DIR" \ + XDG_CACHE_HOME="$XDG_CACHE_HOME" \ + npm run build + else + npm install + npm run build + fi # Final permissions - ensure everything is correct after all setup chown -R $JABALI_USER:www-data "$JABALI_DIR"