# NetOps To-Do — Handoff / Project context > Også egnet som `CLAUDE.md` for fremtidige Claude-sesjoner som jobber videre med koden. > **Merk (2026-06-12):** Det finnes nå en videreutviklet Node/npm-versjon i > `../netops-todo-node/` med WebSocket-sanntidssynk, kanban-tavle, kommentarer, > aktivitetslogg og konfliktdeteksjon. Se `CLAUDE.md` der. Denne PHP-versjonen > beholdes som den er for ren Apache/mod_php-hosting. ## Hva er dette En enkel, selvstendig to-do-applikasjon tilpasset en network engineer som jobber bredt: L1 felt-kabling, L2 switching, L3 ruting, L4 lastbalansering, BGP, peering, security, NMS, automatisering, dokumentasjon, incident og prosjekt. Hver oppgave har prioritet (P1–P4), estimert tid, status, lokasjon/site, frist, tags og eier. Det finnes **to versjoner** levert i samme arbeidsstrøm: | Versjon | Fil | Lagring | Bruksområde | |---|---|---|---| | Standalone | `netops-todo.html` (ligger ved siden av denne mappa) | `localStorage` i nettleseren | Personlig bruk på én maskin, ingen server nødvendig | | Server / Apache | Hele `netops-todo-server/`-mappa | `data/tasks.json` på server, fil-låst | Delt for et team, auth i Apache eller proxy | Server-versjonen er der man kommer til å være etter første "single user, deretter delt"-overgang. ## Filer i server-pakka ``` netops-todo-server/ ├── index.php Frontend (HTML + JS). Tynt PHP-lag øverst leser brukernavn fra Apache. ├── api.php REST-API (single file). Alle actions ligger i én switch. ├── seed.json 16 eksempel-oppgaver. Lastes via "Last inn eksempel-data"-knappen. ├── .htaccess Auth-skeleton + sperrer data/ for direkte web-tilgang. ├── data/ │ ├── .htaccess Nekter all web-tilgang til lagringskatalogen. │ ├── tasks.json Opprettes av api.php ved første skriv. Liste av task-objekter. │ └── known_users.json Liste over brukere som har vært innom (for owner-dropdown). ├── INSTALL.txt Installasjonsguide for Apache. └── CLAUDE.md (denne filen) ``` ## Arkitektur Frontend er én HTML-side med vanilig JS (ingen rammeverk) og Chart.js fra CDN. Backend er to PHP-filer, null dependencies, kjører rett på Apache mod_php / php-fpm. ### Dataflyt 1. Apache autentiserer brukeren (Basic Auth, ekstern proxy, eller hva enn man velger). 2. `index.php` leser `REMOTE_USER` / `PHP_AUTH_USER` / `HTTP_X_REMOTE_USER`, injiserer det i siden som `CURRENT_USER`. 3. JS kaller `api.php?action=list` ved oppstart, så `create` / `update` / `delete` ved endringer. 4. `api.php` validerer input mot whitelister, normaliserer task-objektet, og skriver `data/tasks.json` med `flock(LOCK_EX)`. 5. Hvert minutt pollere frontend `list`-endepunktet for å hente endringer fra andre brukere. ### API Alle endepunkt: `POST api.php?action=` med JSON-body. `list` godtar også GET. | Action | Body | Svar | |----------|---------------------|--------------------------------------------| | list | — | `{ user, tasks: [...], known_users: [...] }` | | create | task uten id | `{ task }` (med tildelt id og audit-felt) | | update | task med id | `{ task }` | | delete | `{ id }` | `{ ok: true }` | | replace | array av tasks | `{ ok: true, count }` (for import) | | seed | — | `{ ok: true, count }` (kun hvis db er tom) | ### Task-skjema (kanonisk form) ```json { "id": "t_abc123", "title": "string ≤200", "desc": "string ≤4000", "category": "L1|L2|L3|L4|BGP|PEER|SEC|NMS|AUTO|DOC|INC|PROJ", "priority": "P1|P2|P3|P4", "status": "todo|progress|blocked|done", "estHours": 0, "location": "string ≤120", "deadline": "YYYY-MM-DD eller tom", "tags": ["≤20 strings, hver ≤40"], "owner": "brukernavn eller tom = utildelt", "created": "ISO timestamp", "createdBy": "brukernavn", "updated": "ISO timestamp", "updatedBy": "brukernavn", "completed": "YYYY-MM-DD eller null", "completedBy": "brukernavn eller null" } ``` `normalize_task()` i `api.php` er kilden til sannhet. Den whitelister enums, klamper strenger, valider deadline-format, og setter audit-feltene automatisk basert på `current_user()`. ## Designvalg som er verdt å vite - **Ingen database.** JSON-fil + `flock` holder fint helt opp i tusenvis av oppgaver. Hvis det skulle bli ytelsestrøbbel, er det enkleste å bytte til SQLite (PHP `pdo_sqlite` følger med). - **Auth utenfor koden.** Innloggings-logikk er bevisst utelatt. Apache / proxy gjør jobben. Det gjør at koden er trivielt enkel å revidere og bytte ut. - **Felles datalager, ikke per-bruker.** Brukerne ser samme oppgaveliste, men `owner` per oppgave + audit-felt gir attribusjon. - **No-framework frontend.** Holdt bevisst gammeldags vanlig JS for at det skal være lett å patche av neste vakthavende. - **Polling, ikke websocket.** En `list`-request hvert 60s er nok for et team. Hvis flere skal jobbe samtidig kan intervallet senkes, men brukerne kan også trykke ↻. ## Sikkerhetsstatus | Risiko | Tiltak | |---|---| | XSS i task-tekst | `escapeHtml()` i alle render-paths, `htmlspecialchars()` for brukernavn i PHP | | Path traversal | Filsti er hardkodet (`__DIR__ . '/data/tasks.json'`), ingen brukerinput i path | | Direct read av tasks.json | Egen `.htaccess` i `data/` med `Require all denied` | | Race conditions | `flock(LOCK_EX)` ved skriving, `LOCK_SH` ved lesing | | Injection i enums | Whitelist-validering: `in_array($val, $VALID_*, true)` | | Sanitering av brukernavn | `preg_replace('/[^A-Za-z0-9._@\-]/', '', $user)`, maks 64 tegn | | CSRF | Ikke håndtert eksplisitt. For en intern admin-side bak proxy med Basic Auth er det typisk akseptabelt, men hvis det monteres på offentlig nett bør det legges til en `X-Requested-With`-sjekk eller token. | ## Vanlige utvidelser Hvis du jobber videre med dette, dette er de mest sannsynlige neste stegene og hvor du putter dem: **Nye kategorier eller prioriteter:** - Frontend: legg til i `CATEGORIES`-array og `CAT_COLORS`-map i `index.php` (JS-delen). - Backend: legg til i `$VALID_CATEGORIES` / `$VALID_PRIORITIES` i `api.php`. **Nytt felt per oppgave:** - Legg til input i modal i `index.php`. - Plukk opp i `saveForm()` (JS) og send med i body. - Legg til i `normalize_task()` (PHP) med passende sanitering. - Vis det i `renderTable()` om ønskelig. **Bedre samarbeid:** - Server-Sent Events fra PHP: ny `?action=stream` som holder en åpen koblet med `Cache-Control: no-cache`, sjekker fil-mtime og pusher endringer. - Eller bare senke `setInterval(loadAll, 60000)` i `init()`. **Audit-logg / historikk:** - I `normalize_task()` legg til append til `data/audit.log` med `[$updatedBy] $action $taskId`. - Vis logg under hver oppgave-modal med en ny `?action=history&id=...`. **Per-bruker syn:** - Endre `list` til å filtrere på `$user` hvis et flagg er satt. - Eller bare la frontend defaulte filter "Eier=Meg" — enklere. **SQLite-migrering** (hvis JSON blir tregt): - Bytt `read_tasks()` og `write_tasks()` mot PDO-kall. - Skjemaet matcher allerede et fornuftig SQL-skjema. ## Kjente begrensninger - Ingen optimistisk locking på enkeltoppgave-nivå. Hvis to brukere lagrer samme oppgave samtidig, vinner den siste. Dette er hentet inn ved at filen i sin helhet låses, men man får ikke conflict-deteksjon. - Ikke i18n. Norsk er hardkodet i UI. Strings er samlet, så det er ikke vondt å trekke ut. - Ingen pagination i tabellen. Fungerer fint opp til noen hundre åpne oppgaver, deretter bør man legge til virtual scrolling eller side-knapper. - Klokken nederst i hover er klient-tid, ikke server-tid. ## Testing-status - PHP-syntaks verifisert med AST-parser (`php-parser` via node, PHP 8-modus). - Kryssreferanse JS ↔ PHP: alle `api('X')`-kall fra frontend har matchende `case 'X':` i api.php. - Kryssreferanse DOM-IDer ↔ JS: alle `getElementById('x')` har matchende `id="x"` i HTML. - Onclick-handlere ↔ funksjonsdefinisjoner: ingen referanser til udefinerte funksjoner. - Ikke kjørt end-to-end (sandbox manglet PHP-runtime). Første ekte test bør være: `php -S localhost:8080` i mappa og åpne i nettleser. ## Hurtigreferanse — installasjon ```bash # 1. Kopier til server sudo cp -r netops-todo-server /var/www/netops-todo # 2. Skriverettigheter for data/ sudo chown -R www-data:www-data /var/www/netops-todo/data sudo chmod 750 /var/www/netops-todo/data # 3. Basic Auth-brukere (utenfor docroot!) sudo htpasswd -c /etc/apache2/netops.htpasswd jon sudo htpasswd /etc/apache2/netops.htpasswd kari # 4. Aktiver auth-blokken i .htaccess (kommenter ut linjene under "1) Basic Auth") sudo nano /var/www/netops-todo/.htaccess # 5. Sørg for at AllowOverride All er aktivt i vhost # # AllowOverride All # Require all granted # sudo systemctl reload apache2 # Åpne http://din-server.no/netops-todo/ → "Last inn eksempel-data" ``` Se `INSTALL.txt` for fyldigere variant og feilsøking.