Legg til Node/npm-versjon med sanntidssynk + Debian 13-oppsettsskript
Ny app i netops-todo-node/: Express + ws, WebSocket-push i stedet for polling, kanban med drag & drop, kommentarer, aktivitetslogg, optimistisk låsing, quick-add-parsing og presence. 12 integrasjonstester (node:test). setup-debian13.sh setter opp alt på en fersk LXC; README dekker Nginx Proxy Manager-oppsett. PHP-versjonen er uendret (kun handoff-peker). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
72a78b55fb
commit
6b9dbf8254
15 changed files with 3814 additions and 0 deletions
127
netops-todo-node/CLAUDE.md
Normal file
127
netops-todo-node/CLAUDE.md
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
# NetOps To-Do (Node) — Handoff / Project context
|
||||
|
||||
> Egnet som `CLAUDE.md` for fremtidige Claude-sesjoner. Dette er
|
||||
> videreutviklingen av PHP-versjonen i `../netops-todo-server/` — samme formål
|
||||
> og datamodell, men ombygd til Node/npm med sanntidssynk og flere
|
||||
> samarbeidsfunksjoner. PHP-versjonen ligger urørt ved siden av.
|
||||
|
||||
## Hva er dette
|
||||
|
||||
To-do-applikasjon for en network engineer / et lite driftsteam. Kategorier
|
||||
L1–L4, BGP, peering, security, NMS, automatisering, dokumentasjon, incident,
|
||||
prosjekt. Hver oppgave har prioritet (P1–P4), status, estimat, lokasjon, frist,
|
||||
tags, eier, kommentarer og audit-felter.
|
||||
|
||||
Nytt mot PHP-versjonen:
|
||||
|
||||
- **WebSocket-sanntidssynk** (erstatter 60s-polling) + presence + "redigerer nå"
|
||||
- **Kanban-tavle** med drag & drop, i tillegg til tabellvisning
|
||||
- **Kommentarer** per oppgave
|
||||
- **Aktivitetslogg** (hvem gjorde hva, server-side, capped til 400 entries)
|
||||
- **Optimistisk låsing** — `v`-felt per oppgave, 409 ved konflikt
|
||||
- **Hurtig-registrering** med token-parsing (`#kat @eier p1 !frist ~timer loc:sted`)
|
||||
- **Angre sletting**, tastatursnarveier, persistente filtre (localStorage)
|
||||
|
||||
## Filer
|
||||
|
||||
```
|
||||
netops-todo-node/
|
||||
├── server.js Express + ws. REST-API, WebSocket-hub, auth-oppslag.
|
||||
├── lib/store.js Datalager: normalisering, validering, aktivitetslogg,
|
||||
│ atomisk JSON-persistens. Kilden til sannhet for skjema.
|
||||
├── public/
|
||||
│ ├── index.html Markup. Ingen templating — app.js fyller alt.
|
||||
│ ├── app.js All frontend-logikk (vanilla JS, ingen rammeverk).
|
||||
│ └── style.css Mørkt tema, samme visuelle identitet som PHP-versjonen.
|
||||
├── seed.json 16 eksempel-oppgaver.
|
||||
├── test/api.test.js Integrasjonstester (node:test) — REST + WS ende-til-ende.
|
||||
├── data/ Opprettes ved kjøring: tasks.json, activity.json, users.json.
|
||||
└── README.md Installasjon, proxy-oppsett, API-referanse.
|
||||
```
|
||||
|
||||
## Arkitektur
|
||||
|
||||
- **Alle mutasjoner via REST** (lett å curl-e/feilsøke). WebSocket (`/ws`)
|
||||
brukes kun til push: endringer, presence, editing-signaler.
|
||||
- Én node-prosess eier datakatalogen. Lagring i minnet, skriv til disk er
|
||||
atomisk (tmp + rename) og serialisert gjennom en promise-kjede i `store.js`.
|
||||
- Auth ligger utenfor appen: `X-Remote-User`-header > Basic Auth > cookie
|
||||
(`netops_user`, kan skrus av med `DISABLE_COOKIE_AUTH=1`) > `anon`.
|
||||
Samme oppslag for HTTP og WS-upgrade (`userFromRequest` i server.js).
|
||||
|
||||
### WebSocket-protokoll (server → klient)
|
||||
|
||||
| type | Innhold | Når |
|
||||
|---|---|---|
|
||||
| `hello` | `user`, `online[]`, `editing{}` | Ved tilkobling |
|
||||
| `sync` | `tasks[]`, `activity[]`, evt. `by` | Ved tilkobling + etter replace/seed |
|
||||
| `task` | `op: create/update/delete`, `task`/`id`, `by`, `activity` | Etter hver mutasjon |
|
||||
| `presence` | `online[]` | Når noen kobler til/fra |
|
||||
| `editing` | `editing{}` = `{taskId: [brukere]}` | Når noen åpner/lukker modal |
|
||||
|
||||
Klient → server: kun `{ type: 'editing', id, active }`.
|
||||
|
||||
### Task-skjema (kanonisk form — `normalizeTask()` i lib/store.js)
|
||||
|
||||
Som PHP-versjonen, pluss:
|
||||
|
||||
```json
|
||||
{
|
||||
"v": 3,
|
||||
"comments": [{ "id": "c_…", "by": "jon", "at": "ISO", "text": "≤1000" }]
|
||||
}
|
||||
```
|
||||
|
||||
`v` bumpes ved hver felt-oppdatering (ikke ved kommentarer — bevisst, så en
|
||||
kommentar ikke gir falsk konflikt for noen som redigerer felter samtidig).
|
||||
Klienten sender `v` den redigerte fra; mismatch → 409 med serverens task i
|
||||
svaret. Frontend håndterer det i `handleSaveError()`: oppdaterer visningen,
|
||||
viser varsel, og lar brukeren lagre på nytt (som da overskriver bevisst).
|
||||
|
||||
## Designvalg verdt å vite
|
||||
|
||||
- **Ingen database, ingen frontend-rammeverk, to npm-avhengigheter**
|
||||
(express, ws). Samme "lett å patche for neste vakthavende"-filosofi som før.
|
||||
- **Broadcast går til alle, inkludert avsender.** Klienten upserter idempotent
|
||||
på id, så dobbel oppdatering er harmløs. REST-svaret brukes også, slik at
|
||||
UI-et fungerer selv om WS er nede (da poller frontend hvert 30s).
|
||||
- **Delvis update er lov:** `PUT /api/tasks/:id` med bare `{v, status}` —
|
||||
normalisering merger mot eksisterende. Quick-actions bruker dette.
|
||||
- **Kommentar-sletting er begrenset til egen bruker** (eneste
|
||||
autorisasjonsregel i appen — alt annet er åpent for alle innloggede).
|
||||
- Chart.js fra CDN; frontend degraderer pent (skjuler grafer) uten nett.
|
||||
|
||||
## Sikkerhetsstatus
|
||||
|
||||
Som PHP-versjonen (XSS-escaping i alle render-paths, whitelist-enums,
|
||||
strenglengde-klamping, brukernavn-regex `[A-Za-z0-9._@-]{1,64}`), pluss:
|
||||
|
||||
- `/api/login` avviser ugyldige navn i stedet for å sanitere stille.
|
||||
- Cookie settes med `SameSite=Lax` — gir grunnleggende CSRF-vern for
|
||||
cookie-auth-modus. Bak proxy-auth gjelder samme vurdering som før
|
||||
(intern bruk OK; offentlig nett → legg på token).
|
||||
- `express.json({ limit: '2mb' })` begrenser payload (import av store lister).
|
||||
|
||||
## Vanlige utvidelser
|
||||
|
||||
- **Nytt felt per oppgave:** input i modal (index.html) → `saveForm()` og
|
||||
`parseQuickAdd()` om ønskelig (app.js) → `normalizeTask()` (store.js) →
|
||||
`diffDetail()` for aktivitetsloggen → `renderCard()`/`renderTable()`.
|
||||
- **Ny kategori:** `CATEGORIES`/`CAT_COLORS` i app.js + `VALID_CATEGORIES`
|
||||
i store.js.
|
||||
- **SQLite:** bytt persistens i `Store` (load/_persist) mot `node:sqlite` —
|
||||
resten av appen er uberørt siden alt går gjennom Store-metodene.
|
||||
- **Varsler ved frist:** server har allerede deadline per task; en
|
||||
`setInterval` i server.js som broadcaster `{type:'due', …}` + Notification
|
||||
API i frontend er den naturlige veien.
|
||||
|
||||
## Testing-status
|
||||
|
||||
- `npm test`: 12 integrasjonstester (node:test), booter ekte server på
|
||||
tilfeldig port med temp-datakatalog. Dekker normalisering, versjonskonflikt,
|
||||
kommentar-autorisasjon, aktivitetslogg, WS-broadcast, persistens på disk,
|
||||
cookie-auth. Alle grønne per 2026-06-12 (Node 25).
|
||||
- Manuell røyk-test utført: `/healthz`, statiske filer, seed, state, og
|
||||
WS-push av REST-endring verifisert ende-til-ende.
|
||||
- Ikke testet i nettleser med flere samtidige brukere — første ekte test bør
|
||||
være to nettleservinduer mot `npm start` og flytte kort på tavla.
|
||||
Loading…
Add table
Add a link
Reference in a new issue