# Hvis du vil skrive WebSnap selv

Teknisk opskrift til en kodeagent. Byg et selvstændigt program ud fra denne beskrivelse. Vælg selv sprog og biblioteker.

WebSnap tager PNG-billeder af offentlige HTTPS-sider. En optagelse giver som standard billeder i desktop-, tablet- og mobilstørrelse. Programmet kan køres direkte fra en terminal eller som en privat server, hvor andre programmer bestiller og henter billeder.

## Opgave og brugerflade

- Lav kommandoerne <code>version</code>, <code>capture</code> og <code>serve</code> til Linux, macOS og Windows. Brugeren installerer Chrome eller Chromium særskilt.
- <code>capture --url URL --output-dir MAPPE</code> opretter tre PNG-filer: <code>desktop.png</code> på 1440 × 900, <code>tablet.png</code> på 834 × 1112 og <code>mobile.png</code> på 390 × 844 pixels. Opret outputmappen ved behov. En fejl skal give en klar besked og en exitkode forskellig fra nul.
- Gentagne <code>--viewport navn:BREDDExHØJDE</code> erstatter standardvisningerne. Tillad højst otte entydige navne med små bogstaver, tal og bindestreger. Bredde skal være 320-3840 og højde 240-2160 pixels. Filnavnet følger visningens navn.
- Tilbyd <code>--browser</code> til eksplicit browsersti, <code>--wait</code> til ekstra ventetid efter indlæsning og <code>--timeout</code> pr. visning. Brug 2,5 sekunders ventetid og 30 sekunders timeout som udgangspunkt. Begræns ventetiden til 0-10 sekunder.
- Åbn hver visning i en ny midlertidig browserprofil uden brugerens cookies eller login. Indstil viewporten før optagelsen, skjul rullebjælker, og gem det synlige browserbillede som PNG. Ryd den midlertidige profil efter både succes og fejl.

## Adresser og netværk

Accepter kun offentlige HTTPS-adresser uden brugernavn, adgangskode eller særskilt port. Afvis lokale navne, private og reserverede IP-adresser samt ugyldige adresser før browserstart. Fragmenter er ikke en del af optagelsen.

Browserens netværkstrafik skal også kontrolleres: DNS-opslag, omdirigeringer og underressourcer må ikke give adgang til loopback, lokale net, metadataadresser eller andre private mål. Lad browseren bruge en lokal kontrollerende proxy, som validerer det faktiske forbindelsesmål. En kontrol af den oprindelige URL alene er utilstrækkelig.

WebSnap optager sider, som kan åbnes uden login. Log ikke hemmeligheder fra URL'er eller HTTP-headere. Sæt grænser for tid, samtidige browserprocesser og ressourceforbrug.

## Cookies og resultat

Forsøg som standard at finde én synlig, entydig knap, der afviser valgfrie cookies eller vælger kun nødvendige cookies. Understøt almindelige CMP-kontroller og knaptekster på dansk og flere europæiske sprog. Klik før billedet tages, og vent kort på at siden falder til ro. Hvis der ikke er et entydigt valg, tages billedet uden klik. <code>--reject-cookies=false</code> slår forsøget fra.

Rapportér udfaldet for hver visning, for eksempel afvist, ingen tydelig knap, slået fra eller fejl. Et billede, hvor banneret er væk, er ikke i sig selv bevis for, at siden ikke sætter valgfrie cookies. Brugeren skal kunne kontrollere billedet.

## Privat job-API

<code>serve --listen 127.0.0.1:8787 --data MAPPE --token-file FIL</code> starter en HTTP-server på loopback. Tokenfilen skal være privat og indeholde mindst 32 tilfældige tegn. <code>GET /healthz</code> er åben; alle job- og billedruter kræver <code>Authorization: Bearer &lt;token&gt;</code>. Brug konstanttids-sammenligning og send aldrig tokenet til browserens offentlige JavaScript.

| Metode | Rute | Resultat |
| --- | --- | --- |
| POST | <code>/v1/jobs</code> | Valider JSON, opret job og svar 202 med et stabilt job-id |
| GET | <code>/v1/jobs?limit=50&amp;status=ready</code> | Vis nyeste job med valgfrit statusfilter |
| GET | <code>/v1/jobs/{id}</code> | Vis status <code>queued</code>, <code>running</code>, <code>ready</code> eller <code>failed</code> |
| GET | <code>/v1/jobs/{id}/images/{name}.png</code> | Lever et færdigt PNG-billede med samme tokenkrav |

En anmodning kan nøjes med <code>{"url":"https://example.org/"}</code>. Den kan også angive <code>viewports</code>, <code>waitMs</code> og <code>rejectCookies</code>. Brug de samme grænser som i terminalkommandoen. Kør ét optagelsesjob ad gangen og tillad højst 16 ventende job. Afvis yderligere job tydeligt. Gem jobstatus under datamappen og billeder som særskilte filer. Skriv færdige filer atomisk, så en læser aldrig får et halvt PNG. Markér et job, der var i gang ved genstart, som fejlet; klienten kan bestille det igen. Billederne kræver planlagt oprydning og backup af datamappen.

## Accept

- En offentlig testsides tre standardbilleder har de angivne dimensioner og er gyldige PNG-filer.
- To egne visninger giver præcis to filer med de valgte navne. Ugyldigt navn, størrelse, ventetid og mere end otte visninger afvises før optagelse.
- En URL til loopback, privat IP, HTTP, login eller særskilt port afvises. Det samme gælder en offentlig URL, som omdirigerer til et privat mål, og en offentlig side med en underressource på et privat mål.
- En side uden cookieknap kan stadig optages, og udfaldet fremgår. Funktionen kan slås fra.
- API'et afviser forkert eller manglende token, håndhæver køgrænsen og udleverer kun færdige billeder. Efter genstart står et afbrudt job som fejlet.
- Browserprofilen fjernes efter både fuldført optagelse og timeout. Ingen privat netværksadresse eller adgangstoken fremgår af offentlige svar.
