Merket øverst til venstre går nå til bloggens rot både i admin og på
selve bloggen (der var det allerede relativt til roten). «Innlegg» i
menyen dekker admin-listen.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JcEy43fNYpwg6K6oTKakWR
Forsiden viser første avsnitt av hvert innlegg som ren tekst (nytt
Jinja-filter `excerpt`, tilgjengelig for egne temaer). Favicon har
færre og større former med tykkere streker så det holder seg ved 16 px.
Siste to punkter fra UI-gjennomgangen.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JcEy43fNYpwg6K6oTKakWR
WCAG:
- Mørk modus: --on-accent-token gir mørk tekst på lys aksent (knapper,
badges, valgt fane, skip-lenke) – var 1.8:1, nå ~11:1.
- Editor-feltet har label og aria-describedby; forhåndsvisningen er
ikke lenger aria-live (leste opp hele innlegget for hvert tastetrykk).
- Bilder settes inn med alt-plassholder markert for overskriving, som
eget avsnitt etter gjeldende linje.
- Berøringsmål ≥ 44px (nav, verktøylinje, lenkeknapper, select).
- Faner: roving tabindex + piltaster. Knapper med tekst i stedet for
emoji, aria-keyshortcuts på fet/kursiv. h1 på forsiden.
- code bryter lange stier (innstillinger rullet horisontalt på mobil).
UX:
- Ulagret-vakt dekker også tittelen, med synlig «Ulagrede endringer».
- 413 ved for stor fil gir lesbar melding; brukernavn beholdes ved
feil innlogging; full publiserings-URL vises i editoren; historikk-
lenke i meta-linjen; norsk datoformat i historikken; passord-hint.
Design:
- Header med favicon, større brødtekst/overskrifter, smalere måltekst,
bedre avstander i innlegg og liste, footer som flex uten løse «·»,
nøytral sekundærknapp, innrammet faresone, editor-textarea fyller
panelet, valgt fane henger sammen med panelet.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JcEy43fNYpwg6K6oTKakWR
Funn fra sikkerhetsgjennomgang:
- HØY: post_id ble ikke validert, så en gjest kunne nå andres innlegg
via gjest/../../posts/<slug> (lese utkast, laste opp/slette bilder,
publisere eierens utkast). Slug og gjestenavn valideres nå mot samme
alfabet de lages med, og stien sjekkes etter oppslag.
- Bilder: pikselantall sjekkes før dekoding (maks 40 MP), og
DecompressionBombError håndteres.
- Innlogging: CSRF-token kreves også på login (login-CSRF), og
innloggingsbrems etter 5 feil per brukernavn.
- Passordbytte ugyldiggjør alle andre sesjoner (stempel i cookien).
- Content-Security-Policy og X-Frame-Options på alle sider; admin har
ingen inline script lenger (admin.js).
- Gjestenavn og eier-slugs kan ikke lenger kollidere på /navn/.
- Healthcheck respekterer SOAPBOX_BASE_PATH; login-redirect beholder
base path; run.sh dropper capabilities og setter minnegrense; uv
pinnet til 0.11.
Rettet også en reell feil: existing_slugs() listet feil katalog
(Path / er identitet), så slug-unikhet virket ikke.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JcEy43fNYpwg6K6oTKakWR
public/ ble bare bygd hvis mappen manglet, så etter en oppgradering med
endrede maler var siden utdatert til noen lagret et innlegg.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JcEy43fNYpwg6K6oTKakWR
Bokstaver og tall i alle skriftsystemer beholdes, alt annet blir
bindestrek. NFC-normalisering gir samme slug uansett om ø/å kommer
prekomponert eller som base + kombinerende tegn (macOS). URL-er i
feed.xml percent-encodes siden RSS-lesere krever ASCII.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JcEy43fNYpwg6K6oTKakWR
Temaer slås opp i content/themes/<navn>/ før de innebygde, slik at et
eget tema følger med i git, backup og ved flytting – uten ny container.
Et tema kan være delvis: manglende maler/filer arves fra green (Jinja
ChoiceLoader, static kopieres lagvis). Valget lagres i site.toml;
SOAPBOX_THEME er bare standardverdi.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JcEy43fNYpwg6K6oTKakWR
Lenkes relativt fra temaet (theme/favicon.svg) og fra admin-basen, så
nettleseren slipper å gjette på /favicon.ico.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JcEy43fNYpwg6K6oTKakWR
Redigeringssiden lenker til /admin/history/<id> som lister commits som
har rørt innleggets mappe; klikk på en commit viser diffen fargelagt.
Samme tilgangsregler som editoren (gjester ser bare egne innlegg).
README skiller nå tydelig mellom å kopiere hele data-volumet (ingen nye
brukere) og å klone bare innholdsrepoet (brukere må opprettes på nytt).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JcEy43fNYpwg6K6oTKakWR
AGPL §13 krever at brukere av en nettverkstjeneste kan hente kildekoden;
temaet viser derfor en lenke til repoet på hver side.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JcEy43fNYpwg6K6oTKakWR
build.sh bygger imaget med build-dato og git-revisjon, run.sh starter
containeren idempotent (podman run --replace) med innstillinger fra .env.
compose.yaml leser nå samme .env. Alle variabler har standardverdier;
.env.example dokumenterer dem.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JcEy43fNYpwg6K6oTKakWR
Jinja escaper for HTML, men nettleseren dekoder attributtverdien før
JS-parseren ser den, så en tittel med ' kunne bryte ut av strengen.
Bekreftelser går nå via data-confirm og én delt handler i base.html.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JcEy43fNYpwg6K6oTKakWR
next-parameteren godtok "//evil.com", som nettlesere tolker som en
ekstern URL. Nå godtas bare stier som starter med én skråstrek.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JcEy43fNYpwg6K6oTKakWR
podman stop tok 10 s og endte i SIGKILL fordi waitress ignorerer SIGTERM
som PID 1. Med SIGINT stopper containeren på under et halvt sekund.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JcEy43fNYpwg6K6oTKakWR
Flask-app som genererer statiske sider til public/ og serverer dem
sammen med et admin-grensesnitt (/admin). Innhold ligger som markdown
og bilder i et git-repo (data/content), brukere i sqlite.
- Editor med toolbar, live server-side forhåndsvisning, bildeopplasting
via knapp, dra-og-slipp og lim inn. Bilder nedskaleres og EXIF fjernes.
- Hovedbruker publiserer under /<slug>/, gjester under /<bruker>/<slug>/.
Slug lages fra tittelen og fryses ved publisering.
- Alle interne lenker er relative, så siden kan flyttes mellom domener og
sub-paths (SOAPBOX_BASE_PATH) uten rebuild.
- Tema 'green' med CSS-variabler, mørk modus og WCAG-kontrast.
- Containerfile (python:alpine + git), compose.yaml og Caddyfile-eksempel.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JcEy43fNYpwg6K6oTKakWR