kimai-plugin-heatmap/.planning/phases/01-dev-environment/01-01-PLAN.md
Christopher Mühl 5bdb8bf3f5
docs(01): create phase 1 dev environment plans
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 11:05:45 +02:00

241 lines
8.6 KiB
Markdown

---
phase: 01-dev-environment
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
- flake.nix
- dev/process-compose.yaml
- dev/setup.sh
- .gitignore
- .envrc
autonomous: true
requirements:
- DEV-01
must_haves:
truths:
- "nix develop drops into a shell with PHP 8.2+, Composer 2.x, Node 22.x, MariaDB, symfony-cli, and process-compose"
- "process-compose up starts MariaDB on port 3307 with a local data directory and Symfony dev server"
- "setup.sh clones Kimai, installs deps, creates DB, loads fixtures, and symlinks plugin"
artifacts:
- path: "flake.nix"
provides: "Nix devshell with all required packages and PHP extensions"
contains: "php82"
- path: "dev/process-compose.yaml"
provides: "MariaDB + Symfony dev server process definitions"
contains: "mariadb"
- path: "dev/setup.sh"
provides: "One-time Kimai bootstrap script"
contains: "kimai:reset:dev"
- path: ".gitignore"
provides: "Ignore dev artifacts (kimai clone, mariadb data, node_modules)"
contains: "dev/kimai"
key_links:
- from: "dev/process-compose.yaml"
to: "dev/.mariadb-data"
via: "mysqld --datadir"
pattern: "mariadb-data"
- from: "dev/setup.sh"
to: "dev/kimai"
via: "git clone kimai"
pattern: "git clone.*kimai"
---
<objective>
Create the Nix flake, process-compose config, and bootstrap script for the Kimai dev environment.
Purpose: Provide a reproducible, one-command dev setup that gives the developer PHP 8.2+, MariaDB, Composer, Node, and all tooling needed for Kimai plugin development.
Output: flake.nix, dev/process-compose.yaml, dev/setup.sh, .gitignore
</objective>
<execution_context>
@/home/toph/code/toph/kimai-heatmap/.claude/get-shit-done/workflows/execute-plan.md
@/home/toph/code/toph/kimai-heatmap/.claude/get-shit-done/templates/summary.md
</execution_context>
<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/phase-1/RESEARCH.md
</context>
<tasks>
<task type="auto">
<name>Task 1: Create Nix flake with devshell</name>
<files>flake.nix, .envrc, .gitignore</files>
<action>
Create `flake.nix` with a devshell providing:
**Packages:**
- PHP 8.2 with extensions: gd, intl, mbstring, pdo, pdo_mysql, xml, xsl, zip, tokenizer (use `pkgs.php82.buildEnv { extensions = { enabled, all }: enabled ++ (with all; [ xsl pdo_mysql ]); }`)
- `pkgs.php82Packages.composer` for Composer
- `pkgs.nodejs` (22.x) for JS tooling
- `pkgs.mariadb` (11.4.x) for database
- `pkgs.symfony-cli` for Symfony dev server
- `pkgs.process-compose` for multi-service management
**Flake structure:**
- Use `flake-utils.lib.eachDefaultSystem` for portability
- Input: `nixpkgs` (use `github:NixOS/nixpkgs/nixpkgs-unstable`)
- Single devShell output
- Shell hook: print a short message with available commands (setup, start)
**Also create:**
- `.envrc` with `use flake` for direnv integration
- `.gitignore` with entries for:
- `dev/kimai/` (cloned Kimai instance)
- `dev/.mariadb-data/` (MariaDB data directory)
- `dev/.mariadb.sock` (MariaDB socket)
- `dev/.mariadb.pid` (MariaDB PID file)
- `node_modules/`
- `vendor/`
- `.direnv/`
- `result` (nix build output)
- `*.js.map` (source maps)
- `dist/` (built JS output)
</action>
<verify>
<automated>cd /home/toph/code/toph/kimai-heatmap && nix develop --command bash -c "php --version && composer --version && node --version && mysqld --version && symfony version && process-compose version" 2>&1 | head -20</automated>
</verify>
<done>nix develop provides PHP 8.2+, Composer, Node 22.x, MariaDB, symfony-cli, and process-compose. All commands resolve.</done>
</task>
<task type="auto">
<name>Task 2: Create process-compose config and setup script</name>
<files>dev/process-compose.yaml, dev/setup.sh</files>
<action>
**Create `dev/process-compose.yaml`:**
```yaml
version: "0.5"
processes:
mariadb:
command: |
mysqld --datadir=$PWD/dev/.mariadb-data \
--socket=$PWD/dev/.mariadb.sock \
--port=3307 \
--skip-grant-tables \
--skip-networking=false \
--bind-address=127.0.0.1
readiness_probe:
exec:
command: mysqladmin --socket=$PWD/dev/.mariadb.sock ping
initial_delay_seconds: 2
period_seconds: 1
shutdown:
command: mysqladmin --socket=$PWD/dev/.mariadb.sock shutdown
kimai:
command: symfony server:start --no-tls --dir=$PWD/dev/kimai --port=8010
depends_on:
mariadb:
condition: process_healthy
```
Use port 8010 for Kimai to avoid conflicts. Use `$PWD` for paths so process-compose works from project root.
**Create `dev/setup.sh`** (make executable with `chmod +x`):
The script should:
1. Check if already set up (if `dev/kimai` exists, skip clone)
2. Initialize MariaDB data directory if not present:
```bash
mysql_install_db --datadir=./dev/.mariadb-data --auth-root-authentication-method=normal
```
3. Start MariaDB temporarily for setup (background, wait for ready):
```bash
mysqld --datadir=./dev/.mariadb-data --socket=./dev/.mariadb.sock --port=3307 --skip-grant-tables --bind-address=127.0.0.1 &
MARIADB_PID=$!
# Wait for MariaDB to be ready
for i in $(seq 1 30); do mysqladmin --socket=./dev/.mariadb.sock ping 2>/dev/null && break; sleep 1; done
```
4. Create the `kimai` database:
```bash
mysql --socket=./dev/.mariadb.sock -e "CREATE DATABASE IF NOT EXISTS kimai;"
```
5. Clone Kimai 2.52.0:
```bash
git clone -b 2.52.0 --depth 1 https://github.com/kimai/kimai.git dev/kimai
```
6. Configure Kimai `.env.local` (NOT .env -- .env.local overrides):
```bash
cat > dev/kimai/.env.local << 'ENVEOF'
DATABASE_URL=mysql://root@127.0.0.1:3307/kimai?charset=utf8mb4&serverVersion=11.4.8-MariaDB
APP_SECRET=change-me-dev-only-not-production
APP_ENV=dev
ENVEOF
```
7. Run Composer install in Kimai:
```bash
cd dev/kimai && composer install --no-interaction
```
8. Run Kimai install (creates schema):
```bash
bin/console kimai:install -n
```
9. Load dev fixtures (seeds test data):
```bash
bin/console kimai:reset:dev -n
```
10. Symlink plugin directory:
```bash
mkdir -p var/plugins
ln -sf "$(cd ../.. && pwd)" var/plugins/KimaiHeatmapBundle
```
11. Clear Kimai cache:
```bash
bin/console cache:clear
```
12. Stop temporary MariaDB:
```bash
kill $MARIADB_PID 2>/dev/null
wait $MARIADB_PID 2>/dev/null
```
13. Print success message with instructions to run `process-compose -f dev/process-compose.yaml up`
**Important details:**
- Use `set -euo pipefail` at the top
- Use `127.0.0.1` NOT `localhost` in DATABASE_URL (localhost triggers Unix socket mode on Linux)
- The symlink target name MUST be `KimaiHeatmapBundle` (matches bundle class name)
- Use `--skip-grant-tables` for MariaDB since this is local dev only
- The script must be idempotent: skip steps that are already done (check for existing directories)
</action>
<verify>
<automated>cd /home/toph/code/toph/kimai-heatmap && test -x dev/setup.sh && test -f dev/process-compose.yaml && head -5 dev/process-compose.yaml | grep -q "version" && echo "OK"</automated>
</verify>
<done>dev/process-compose.yaml defines MariaDB + Kimai processes with health checks. dev/setup.sh is executable and contains the full bootstrap sequence (clone, install, seed, symlink).</done>
</task>
</tasks>
<threat_model>
## Trust Boundaries
| Boundary | Description |
|----------|-------------|
| Local dev only | No external network exposure; MariaDB binds to 127.0.0.1, Kimai on localhost:8010 |
## STRIDE Threat Register
| Threat ID | Category | Component | Disposition | Mitigation Plan |
|-----------|----------|-----------|-------------|-----------------|
| T-01-01 | Information Disclosure | MariaDB --skip-grant-tables | accept | Local dev only, bound to 127.0.0.1, no production data. Acceptable for dev environment. |
| T-01-02 | Information Disclosure | APP_SECRET in .env.local | accept | Dev-only value, .env.local is gitignored inside dev/kimai/ (Kimai's own .gitignore), not committed to plugin repo |
</threat_model>
<verification>
1. `nix develop` provides all required tools (PHP 8.2+, Composer, Node, MariaDB, symfony-cli, process-compose)
2. `dev/setup.sh` exists, is executable, and contains the complete bootstrap sequence
3. `dev/process-compose.yaml` defines MariaDB and Kimai processes with dependency ordering
4. `.gitignore` excludes dev artifacts
</verification>
<success_criteria>
Running `nix develop` enters a shell with all dev tools. The setup script and process-compose config are ready to be executed in Plan 02.
</success_criteria>
<output>
After completion, create `.planning/phases/01-dev-environment/01-01-SUMMARY.md`
</output>