241 lines
8.6 KiB
Markdown
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>
|