⚠ TREAD WARNING

LEIMA leima.io

AI evaluation of documents — forever sealed on Arweave

Business · Finance · Research

Validate
Data policy

Leiman tietoturvamalli

Tämä dokumentti kuvaa Leiman valvonta-arkkitehtuurin, kunkin komponentin suojausominaisuudet ja tunnistetut haavoittuvuudet. Yleiskuvaus protokollasta: TREAD.md.

Viimeksi päivitetty: 2026-05-29


Johdanto — miten turvallisuusmalli toimii

Leiman turvallisuusmalli on rakennettu suojaamaan käyttäjän tietoja tilanteessa jossa uhka on ylläpitäjä itse — joko petollinen tai sellainen jonka tunnukset on anastettu. Tavoite on, ettei käyttäjän asiakirjoja voi urkia tai varastaa ilman että käyttäjä saa siitä hälytyksen.

Malli hyödyntää kahta perusperiaatetta:

1. Palveluntarjoajien API-rajapinnat
Hosting-palvelu tarjoaa API:n josta näkyy mitä koodia palvelimella tällä hetkellä pyörii ja onko deploy käynnissä. Tätä verrataan GitHubin julkiseen repositorioon. Jos ne eivät täsmää, järjestelmä hälyttää.

2. Muutosten aikaviive
Koodin muuttaminen tuotantopalvelimella ei tapahdu hetkessä — se vaatii GitHub-commitin, koodiarvion läpäisemisen ja hosting-deployn, joka kestää yhteensä 8–15 minuuttia. Tänä aikana järjestelmän eri osat ovat vielä muuttumattomia, joten ne voivat havaita muutoksen ja hälyttää käyttäjää ennen kuin mitään vahingollista tapahtuu.

Näiden kahden varaan on rakennettu useita toisistaan riippumattomia valvontakerroksia. Kukin tarkistaa asioita eri lähteistä ja eri viiveillä — yhden kerroksen kompromisointi ei sammuta muita.

Luottamuksen rakentuminen

Järjestelmä pyrkii rakentamaan luottamuksen monella toisiaan täydentävällä tavalla:

  • Muuttumaton historia — Arweave-arkisto todistaa että palvelimella ei ole koskaan pyörinyt koodia joka ei näy GitHubissa. Tätä historiaa ei voi jälkikäteen muuttaa.
  • Automaattinen koodiarvio — jokainen muutos tarkastetaan AI:n avulla ennen kuin se pääsee tuotantoon. Arvio vertaa muutoksia käyttöehtoihin ja politiikkadokumenttiin.
  • Deployhälytys kesken session — jos palvelimelle ajetaan uusi versio käyttäjän session aikana, TREAD-palkki ilmoittaa siitä. Käyttäjä näkee muutoksen ennen kuin se on voimassa.
  • Hälytys ohi GitHubin — jos koodia yritetään ajaa sisään ohittaen GitHub-repositorio ja koodiarvio, TREAD havaitsee commit-mismatchin ja hälyttää välittömästi.

Uhkamallit

Kolme hyökkääjätyyppiä, joita vastaan järjestelmä on suunniteltu:

Tyyppi Pääsy Uhkataso
Ulkoinen hyökkääjä Ei GitHub- eikä hosting-pääsyä Matala
Osittainen hyökkääjä GitHub TAI hosting, ei molempia Keskisuuri
Ylläpito-hyökkääjä GitHub JA hosting Korkea

I. GitHub Actions — julkinen valvontakerros

Tässä osiossa kuvatut komponentit pyörivät GitHubissa, eivät Leiman palvelimella. Ne ovat julkisia ja kenen tahansa tarkastettavissa. Ne toimivat riippumatta siitä mitä Leiman palvelimella tapahtuu — eikä hosting-pääsy anna mahdollisuutta muokata niitä.


1. TREAD-cronit — tread-a…e.yml, tread-run.yml, tread_check.py

GitHub Actions sallii cronille minimissään 5 minuutin välin. Yhden minuutin tarkkuuteen päästään viidellä identtisellä workflow'lla (tread-a.ymltread-e.yml), joiden käynnistysajat on porrastettu minuutin välein (:00, :01, :02, :03, :04, sitten :05…). Jokainen niistä kutsuu tread-run.yml:ää, joka sisältää varsinaisen suorituslogiikan: ajaa tread_check.py:n, arkistoi tuloksen Arweave-lohkoketjuun (tread_arweave.py) ja kirjoittaa status.json:n GitHub Pagesiin (push_status.py).

Jokainen ajo:
- Tarkistaa vastaako hosting-palvelussa pyörivä commit GitHubin main-branchia (Render API:n kautta)
- Tarkistaa onko parhaillaan deployatumassa commit jota ei löydy GitHubista
- Tarkistaa että kaikki viisi TREAD-workflow'ta ovat aktiivisena
- Laskee SHA-256-hashit kaikista valvontatiedostoista — siis myös itsestään (tread_check.py)
- Kirjoittaa tuloksen status.json:iin GitHub Pagesiin
- Arkistoi tuloksen Arweave-lohkoketjuun pysyvästi

Viiden erillisen workflow'n redundanssi suojaa yksittäisen workflown passivoitumiselta — kaikki viisi täytyy sammuttaa samanaikaisesti, muuten valvonta jatkuu.

Render API -tarkistukset

tread_check.py tekee joka ajolla kolme erillistä tarkistusta Render API:n kautta:

  • Nykyinen tila — hakee live-commitin ja vertaa GitHubin main-branchin viimeisimpään committiin. Jos ei täsmää → deployment_ok: false → Danger-hälytys.
  • Deploy käynnissä — tarkistaa onko juuri nyt deployatumassa commit jota ei löydy GitHubista. Jos kyllä → välitön Danger-hälytys ennen kuin luvaton koodi on edes live.
  • Deploy-historia — skannaa 100 viimeistä deployta ja tarkistaa jokaisen commitin GitHubista. Jos commit palauttaa 404, se kirjataan last_mismatch_at-kenttään. Tämä on ainoa komponentti joka pystyy paljastamaan menneisyyden hyökkäyksen — esimerkiksi katkoksen tai deaktivoitujen cronien aikana tehty luvaton deploy jää deploy-historiaan. Historia kattaa 100 viimeistä deployta.
  • Deploy-burstit — jos tunnin sisällä tapahtuu yli 10 deployta, TREAD raportoi rapid_deploy_warning: true.

Miten TREAD-cronit voidaan yrittää sammuttaa — ja miten siitä jää kiinni:

Tapa Kuka huomaa Miten
Poistaa kaikki 5 workflow'ta käytöstä GitHub-UI:ssa TREAD-palkki Workflow-tilat → disabled_workflows → Danger (~1 min)
Muokata workflow-tiedostoja Tampermonkey Hash-muutos → hälytys minuutin sisällä
Poistaa repo tai gh-pages-branch TREAD-palkki status.json lakkaa päivittymästä → staleness → Danger
Käyttää GitHub:n abuse-suojausta tahallaan TREAD-palkki Cronit pysähtyvät → staleness → Danger noin tunnin kuluessa

Haavoittuva:
- Kompromisoitu tread_check.py voi kirjoittaa vääriä hasheja status.json:iin — mutta Tampermonkey ja dispatcher laskevat hashit suoraan GitHubin git tree API:lta eivätkä luota status.json:iin
- GitHub Actions itsessään on luotettu osapuoli — jos GitHub on kompromisoitu, koko järjestelmä pettää


2. TREAD:n tuottama data — status.json ja Arweave-arkisto

tread_check.py laskee deployment-tilan ja valvontatiedostojen hashit, push_status.py kirjoittaa tuloksen status.json:iin GitHub Pagesiin, ja tread_arweave.py arkistoi sen Arweave-lohkoketjuun. Tiedostot päivittyvät minuutin välein.

status.json — kaksi roolia:

Rooli Käyttötarkoitus Luotettavuus
Reaaliaikainen tila Deploy-statuksen seuranta Heikko (10 min CDN-cache GitHub Pagesissa)
Historiallinen todiste Arweave-arkisto osoittaa mitä hasheja on raportoitu Erittäin vahva (muuttumaton)

Voidaanko status.json väärentää?
Kyllä — jos hyökkääjällä on GitHub-kirjoitusoikeus, hän voi muokata kaikkia kolmea tuotantoketjun tiedostoa (tread_check.py, tread_arweave.py, push_status.py) yhdessä commitissa. Tämä ei kuitenkaan vaikuta reaaliaikaiseen suojaan: Tampermonkey ja dispatcher eivät luota status.json:iin vaan laskevat hashit suoraan GitHubin git tree API:lta. Lisäksi kaikkien kolmen tiedoston muokkaaminen on itsessään havaittavaa — jokainen muutos näkyy Tampermonkeyn git tree -tarkistuksessa.

Arweave-arkisto — repo ei ole ainoa totuuden lähde

Arweave-arkisto on pysyvä ja muuttumaton — kerran kirjoitettua dataa ei voi poistaa eikä muuttaa. Jokainen status.json-snapshot sisältää: deployatun commitin, GitHubin expected-commitin, kaikkien valvontatiedostojen SHA-256-hashit, workflow-tilat ja aikaleiman.

Vaikka GitHub-repositorio syystä tai toisesta häviäisi tai sen historia väärentyisi, Arweave-arkistoon jää minuutin tarkkuudella dokumentoitu historia järjestelmän tilasta. Vertaamalla Arweave-tietueita ja repositorion nykyistä tilaa voidaan rekonstruoida mitä koodia kulloinkin ajettiin.

Jos Arweave-tietue on epäilyttävä, sen voi ristiin tarkistaa GitHubin commit-historiasta — repositoriosta nähdään mitä koodia kyseisenä päivänä todella pyöri.

Rajoitus: jos tread_arweave.py on kompromisoitu, arkistoon voi tallentua vääristeltyä dataa hyökkäyksen jälkeen. Ennen hyökkäystä tallennetut tietueet säilyvät kuitenkin muuttumattomina.


3. Code review -workflow (code_review.yml)

Jokaisen git push:n jälkeen automaattisesti ajettava workflow, joka toimii deployn portinvartijana.

  • AI-koodiarvio tarkastaa muutokset ja vertaa käyttöehtoihin ennen deployta
  • Hosting-deploy ei käynnisty ilman workflown hyväksyntää
  • Pre-push TREAD-hookki estää pushin jos edellinen deploy ei ole vakaa

Code review -portti turvarakenteena

Jos käyttäjä on verifioinut session alussa että valvontatiedostot ovat muuttumattomia, hän voi odottaa saavansa hälytyksen jos Leiman palvelimelle yritetään ujuttaa tarkastamatonta koodia. Tarkastamaton koodi tarkoittaa commitia joka ei ole kulkenut code_review.yml:n läpi — tällainen deploy jättää commit-mismatchin jonka TREAD havaitsee. Tämä ei ole absoluuttinen takuu, mutta hyökkäys jättää havaittavan jäljen.

Miten code review -portti voidaan yrittää ohittaa — ja miten siitä jää kiinni:

Tapa Miten kiinni
Muokata code_review.yml:ää Vaatii commitin → Tampermonkey havaitsee hash-muutoksen → hälytys
Deployata suoraan API:n kautta Deployattu commit ≠ GitHubin main → TREAD commit-mismatch → Danger-hälytys
Poistaa workflow käytöstä tread_check.py tarkistaa workflow-tilat → disabled_workflows → TREAD-palkki hälyttää

Haavoittuva: AI-arvio ei ole aukoton — hienostuneita muutoksia voi jäädä läpi.


II. Leiman palvelin

Tässä osiossa kuvatut komponentit pyörivät hosting-ympäristössä. Niiden muuttaminen vaatii aina deployn, jonka aikana TREAD-palkki näyttää "Deploying" 8–13 minuutin ajan — käyttäjä näkee muutoksen ennen kuin se on voimassa. Palvelinpuolen komponenteilla on pääsy Render API -avaimiin, mikä mahdollistaa deploy-statuksen suoran tarkistuksen.


4. _poide_dispatcher

Palvelimen taustasäie (main.py), joka tekee kolme itsenäistä tarkistusta jokaisen pollaussyklin yhteydessä (~30 s välein), riippumatta TREAD-croneista:

  1. Deploy käynnissä? — Render API suoraan. Jos deploy alkaa, TREAD-palkki päivittyy 30 s sisällä.
  2. Koodi oikein? — Vertaa Render-live-commitin GitHubin main-branchin viimeisimpään committiin suoraan. Jos ei täsmää → deployment_ok: false → Danger-hälytys.
  3. Valvontatiedostot muuttuneet? — Hakee git tree:n GitHub API:lta, vertaa blob-SHA:ita tallennettuun baselineen. Jos muutos → dispatcher_monitor_changed → Danger-hälytys.

Lisäksi: dispatcher lähettää workflow_dispatch-kutsun GitHub Actionsille 30 s välein, jolloin TREAD-cronit käynnistyvät luotettavammin kuin pelkän GitHub-ajastuksen varassa.

Miksi main.py ei ole valvottavien tiedostojen listalla

Dispatcher on osa main.py:tä, joka on sovelluksen pääkoodi. Se muuttuu normaalin kehitystyön yhteydessä usein — jos se lisättäisiin Tampermonkeyn seurantalistalle, hälytys laukaisisi joka deployssa ja koko periaate "muutos on aina merkittävä" romahtaisi.

main.py:n suojaus toimii eri mekanismilla: sen muuttaminen vaatii deployn, jonka aikana TREAD-palkki näyttää "Deploying". Lisäksi code review tarkastaa jokaisen muutoksen.

Vahvuus — muuttaminen vaatii deployn:
Sinä aikaikkunana (commit → deploy = ~10–15 min) legitiimi dispatcher tarkistaa hashit ja hälyttää jos valvontatiedostot muuttuvat. Hyökkääjä ei pysty hiljentämään dispatcheria ennen kuin kompromisoitu koodi on deployattu.

Haavoittuva: deploy-ikkunan jälkeen kompromisoitu dispatcher voi lopettaa tarkistuksen — Tampermonkey ottaa vastuun.


5. TREAD-palkki sivun ylälaidassa (/version)

Palvelimella pyörivä tila-indikaattori joka näyttää deployment-tilan sivun yläreunassa. Pollaa /version-endpointia 20 sekunnin välein.

Mitä palkki näyttää:

Tilanne Palkin tila
Kaikki kunnossa OK (vihreä)
Deploy käynnissä — normaali tai epäilyttävä Notice — Deploying
Deployattu commit ei vastaa GitHubista Danger (punainen)
Workflow poistettu käytöstä Danger

Paranoidin käyttäjän suoja: palkki näyttää "Deploying" aina kun jokin deployautuu — riippumatta siitä onko se normaali päivitys vai hyökkäys. Vaikka haitallinen koodi läpäisisi AI-koodiarvion, palkki ilmoittaa siitä 8–13 minuutin ajan. Käyttäjä joka ei odota päivitystä voi pitää tätä epäilyttävänä.

Pollausviiveet:

Komponentti Pollausväli Viive hyökkäyksen havaitsemiseen
Tampermonkey 1 min ~1 min (git tree API)
TREAD-palkki 20 s ~90 s (dispatcher-latenssi) + 20 s poll = ~2 min

Haavoittuva: palautuu normaalitilaan kun kompromisoitu dispatcher alkaa palvella väärää dataa — Tampermonkey ottaa vastuun tästä eteenpäin.


6. Hosting-ympäristö

Hosting-alustan valinta vaikuttaa merkittävästi järjestelmän turvallisuuteen. Alustat joissa prosessieristys on heikko voivat mahdollistaa hyökkäyksiä jotka eivät näy missään valvontakerroksessa. Nykyinen ympäristö on väliaikainen — migraatio suunnitteilla.


III. Käyttäjän selain — riippumaton valvonta

Tampermonkey-skripti on ainoa komponentti jota operaattori ei kontrolloi. Se pyörii käyttäjän omassa selaimessa eikä ole riippuvainen Leiman palvelimesta, dispatcherista eikä GitHub Actionsista. Tämä tekee siitä turvallisuusmallin vahvimman yksittäisen kerroksen.


7. Tampermonkey-skripti (tread.user.js)

Skripti ajaa main()-funktion sivulatauksen yhteydessä ja sen jälkeen minuutin välein koko session ajan.

a) Valvontatiedostojen hashit — riippumaton verifiointi
- Hakee koko git tree:n GitHub API:lta (/git/trees/main?recursive=1)
- Poimii blob-SHA:t valvotuille tiedostoille suoraan GitHubista
- Vertaa tallennettuun baselineen (GM_setValue)
- Jos muutos → hälytysmodaali heti

Hashit lasketaan selaimessa GitHubin raakadatasta, ei status.json:n väittämästä arvosta. Vaikka tread_check.py kirjoittaisi vääriä hasheja, Tampermonkey havaitsee todelliset muutokset.

b) Deploy-status
- Hakee status.json:n GitHub API:lta (60 s cache — ei 10 min Pages-CDN)
- Hälyttää jos luvaton commit deployataan tai commit ei vastaa GitHubia

Haavoittuva:
- Käyttäjän täytyy itse asentaa skripti ja pitää se ajan tasalla
- Ei suojaa käyttäjiä joilla ei ole Tampermonkeyta


Valvottavat tiedostot

Tampermonkey ja dispatcher vertaavat hasheja samoille tiedostoille. Tampermonkey käyttää GitHubin git blob SHA:ta, tread_check.py SHA-256:ta.

Miksi juuri nämä tiedostot?

Valvottavat tiedostot ovat nimenomaan valvontainfrastruktuuri — tiedostot jotka hallitsevat valvontaa itse. Sovelluksen pääkoodi (main.py) ei ole listalla, koska se muuttuu usein normaalin kehitystyön yhteydessä ja sen suojaus toimii deploy-viiveen ja code reviewn kautta.

Tiedostot muuttuvat käytännössä vain jos valvontajärjestelmää muutetaan tarkoituksellisesti — tämä on tietoinen suunnittelupäätös. Harva muutos tarkoittaa että muutos on aina merkittävä.

Tiedosto Miksi valvotaan
.github/workflows/tread-a.ymltread-e.yml TREAD-cronien ajastus — muokkaamalla voi sammuttaa valvonnan
.github/workflows/tread-run.yml TREAD:n suorituslogiikka — muokkaamalla voi tehdä valvonnasta tyhjää
.github/workflows/code_review.yml Deploy-portti — muokkaamalla voi ohittaa koodiarvion
.github/workflows/monthly-audit.yml Kuukausittainen laajempi tarkistus
tread_check.py Tarkistuslogiikka — muokkaamalla voi kirjoittaa vääriä hasheja; hashaa myös itsensä
tread_arweave.py Arweave-arkistointi — muokkaamalla voi estää historian tallentumisen
code_review.py AI-koodiarvion toteutus — muokkaamalla voi tehdä arviosta tyhjää
monthly_audit.py Kuukausittaisen auditoinnin toteutus
POLICY.example.md Julkinen politiikkadokumentti — muutos olisi merkki väärinkäytöstä

Yhdenkin muuttaminen ilman lupaa laukaisee hälytyksen.

Tarkistus ennen sessiota

Käyttäjä voi tallentaa seuraavan skriptin omalle koneelleen ja ajaa sen ennen sessiota. Se hakee nykyiset hashit GitHubista ja vertaa tallennettuihin arvoihin:

import json, urllib.request

REPO   = "fxg55647/leima"
BRANCH = "main"
PATHS  = {
    ".github/workflows/tread-a.yml",
    ".github/workflows/tread-b.yml",
    ".github/workflows/tread-c.yml",
    ".github/workflows/tread-d.yml",
    ".github/workflows/tread-e.yml",
    ".github/workflows/tread-run.yml",
    ".github/workflows/monthly-audit.yml",
    ".github/workflows/code_review.yml",
    "tread_check.py", "tread_arweave.py",
    "monthly_audit.py", "code_review.py", "POLICY.example.md",
}
SAVED = "leima_hashes.json"

url = f"https://api.github.com/repos/{REPO}/git/trees/{BRANCH}?recursive=1"
tree = json.loads(urllib.request.urlopen(url).read())["tree"]
current = {i["path"]: i["sha"] for i in tree if i["path"] in PATHS}

try:
    prev = json.load(open(SAVED))
    changed = [p for p in current if current[p] != prev.get(p)]
    if changed:
        print("MUUTTUNUT:", changed)
    else:
        print("OK — kaikki valvontatiedostot ennallaan")
except FileNotFoundError:
    json.dump(current, open(SAVED, "w"), indent=2)
    print("Hashit tallennettu. Aja uudelleen seuraavalla kerralla.")

Saman tarkistuksen voi pyytää myös AI-agentilta: anna sille lista tiedostoista ja edellinen hash-tiedosto, ja pyydä hakemaan nykyiset hashit GitHubista ja vertaamaan.


Hyökkäyksen aikajana — käyttäjä on verifioinut session alussa

Oletetaan että käyttäjä on tarkistanut ennen session alkua, että valvontatiedostoja ei ole muutettu kuukausiin. Hyökkäys alkaa session aikana.

t=0        Hyökkääjä committaa muutokset GitHubiin
           → Git tree muuttuu välittömästi

t=0–60s    Tampermonkey havaitsee muutoksen seuraavassa pollausvuorossa → HÄLYTYS
           TREAD-palkki jatkaa normaalia näyttöä (dispatcher ei ole vielä päivittynyt)

t=90s      Dispatcher hakee päivitetyn status-log.jsonl:n ja git tree:n
           → Valvontatiedostomuutos havaitaan → TREAD-palkki Danger

t=2–3min   Code review -workflow käynnistyy ja valmistuu
           → TREAD-palkki näyttää "Deploying" ← HÄLYTYS

t=3–13min  Hosting-deploy käynnissä
           → TREAD-palkki näyttää "Deploying" koko ajan

t=13min    Kompromisoitu koodi on live
           → Jos dispatcher on kompromisoitu: TREAD-palkki palaa vihreäksi
           → Tampermonkey hälyttää minuutin sisällä (pollaa jatkuvasti)

Yhteenveto suojausajasta:

Vaihe Kesto Käyttäjän suoja
Commit → Tampermonkey pollaa 0–60 s ✅ Hälytys minuutin sisällä
Commit → dispatcher päivittyy 0–90 s ✅ TREAD-palkki Danger
Deploy käynnissä 8–13 min ✅ TREAD-palkki "Deploying"
Kompromisoitu koodi live Jatkuva ✅ Tampermonkey hälyttää minuutin sisällä

Käytännön suositus käyttäjälle: Älä lähetä arkaluonteisia dokumentteja jos TREAD-palkki näyttää "Deploying", "Notice" tai "Danger".


Yhteenveto: suojaus eri uhkia vastaan

Ulkoinen hyökkääjä (ei GitHub/hosting-pääsyä)

Ulkoisella hyökkääjällä ei ole pääsyä kumpaankaan järjestelmään, joten deployment-integriteetin uhkia ei käytännössä ole — koodi ei pääse tuotantoon ilman GitHub- tai hosting-tunnuksia.

Deployment-integriteetti täysin suojattu tältä hyökkääjätyypiltä


Osittainen hyökkääjä (vain hosting-pääsy)

Uhka Suojaus
Luvaton deploy API:n kautta TREAD havaitsee commit-mismatchin → Danger-hälytys
Alustatason hyökkäys Riippuu hosting-ympäristön eristystasosta

⚠️ Hosting-ympäristön valinta kriittinen — migraatio suunnitteilla


Osittainen hyökkääjä (vain GitHub-pääsy)

Uhka Suojaus
Valvontatiedostojen muokkaus Tampermonkey hälyttää minuutin sisällä
Väärät hashit status.json:iin Tampermonkey laskee hashit itse, ei luota status.json:iin
Deploy ilman koodiarvioita Code review -workflow estää → ohitus hälyttää

Hyvin suojattu


Ylläpito-hyökkääjä (GitHub + hosting)

Uhka Suojaus
Valvontatiedostojen muokkaus Tampermonkey hälyttää minuutin sisällä ✅
Deploy ilman code review -porttia TREAD commit-mismatch → Danger-hälytys ✅
Deploy ohi code reviewin TREAD commit-mismatch → Danger-hälytys ✅
Väärät hashit status.json:iin Tampermonkey laskee hashit itse git tree API:lta ✅
Historian peittäminen Arweave muuttumaton ✅
Haitallinen koodi joka läpäisee AI-koodiarvion eikä muokkaa valvottuja tiedostoja ❌ Ei hälytystä
Alustatason hyökkäys Riippuu hosting-ympäristön eristystasosta

⚠️ Ainoa havaitsematon aukko: hienostunut haitallinen koodi joka läpäisee AI-koodiarvion muuttamatta valvottuja tiedostoja. Kaikki muut hyökkäysvektorit tuottavat hälytyksen.


Luottamushierarkia

Tampermonkey (käyttäjän selain)     — korkein, operaattori ei kontrolloi
  ↓
Arweave-arkisto                     — muuttumaton historiallinen todiste
  ↓
GitHub Actions (TREAD + code review) — luotettu jos GitHub ei kompromisoitu
  ↓
_poide_dispatcher + TREAD-palkki    — luotettu jos koodi ei kompromisoitu, ~90 s latenssi
  ↓
status.json (GitHub Pages)          — auditointiartefakti, ei reaaliaikainen turvatae
  ↓
Hosting-ympäristö                   — matalin, riippuu alustan eristystasosta

Avoimet asiat

Asia Tila
Hosting-ympäristön migraatio Suunniteltu
Hosting-ympäristö Vercel (cron joka minuutti)

Muistiinpanoja tarkennettavaksi

1. "Kaikki turvatiedostot vaihdetaan yhtäaikaa" -skenaario

Sekä Tampermonkey että TREAD-palkin frontti vertaavat hasheja paikallisesti tallennettuun baselineen — Tampermonkey GM_setValue:ssa, frontti localStoragessa. Vaikka hyökkääjä vaihtaisi kaikki valvontatiedostot yhdellä commitilla JA muokkaisi tread_check.py:tä kirjoittamaan uudet hashit CDN:iin, sekä Tampermonkey että frontti havaitsisivat muutoksen seuraavalla pollauskerralla — koska niiden baseline on tallennettu käyttäjän omaan selaimeen, ei palvelimelle. Tämä ansaitsee eksplisiittisen maininnan dokumentaatiossa.

2. Vercel ja selainpohjainen baseline

Vercelissä ei ole pitkäikäistä palvelinprosessia, joten server-puolen dispatcher-baseline (_monitor_baseline) ei toimi. Tässä ympäristössä selainpohjainen localStorage-vertailu on ainoa runtime-tason hash-valvonta. Tämä on arkkitehtonisesti merkittävä ero Renderiin verrattuna ja pitäisi dokumentoida selkeästi.

3. Itsenäinen pollaus GitHub-katkon varalta

Sovelluksen _tread_dispatcher-threadin itsenäinen TREAD-workflow-dispatching on perusteltu myös siksi, että jos yhteys GitHubiin katkeaa jostain syystä (GitHub-katkos, rate limit, DNS-ongelma), scheduled-cronit eivät käynnisty. Itsenäinen dispatcher takaa että TREAD-ajot käynnistyvät uudelleen heti kun yhteys palautuu — riippumatta siitä toimivatko GitHub Actions -ajastimet normaalisti.

4. Deploy estetään jos varoitus ei ole ehtinyt frontille — ja KV-kirjoitusoikeus

Politiikka lisättävä: deploy on laiton jos frontti ei ole ehtinyt saada varoitusta ajoissa. Käytännössä: TREAD-check havaitsee muutoksen → kirjoittaa DANGER KV:hen → frontti lukee sen → vasta sitten uusi deploy sallitaan (tai ei sallita). Tämä vaatii että Vercel/Render pre-deploy hook tarkistaa KV:n tilan ennen hyväksyntää.

Kriittinen turvaongelma: tällä hetkellä sekä vanha että uusi deploy jakavat saman KV_REST_API_TOKEN:in, eli pahis-deploy voi kirjoittaa KV:n päälle ja pyyhkiä varoituksen. Ratkaisu: Upstash tukee read-only tokenia erikseen — sovellus saa vain read-only tokenin, TREAD (GitHub Actions) saa write-tokenin. Näin kompromisoitu deploy ei pysty siistimään KV:tä.

5. TODO: Selvitetään mitä käy jos tosi moni käyttää Tampermonkeyta yhtä aikaa

Tampermonkey hakee git tree:n GitHubista suoraan. Jos käyttäjiä on paljon ja kaikki pollaavat samaan aikaan, voiko GitHub rate limit tulla vastaan? Pitää selvittää onko limit per IP (käyttäjäkohtainen) vai per repo/token, ja onko tarvetta throttlaukselle tai yhteiselle välikerrokselle.

6. TEHTY: Toteutetaan server-side GitHub tree -pollaus + frontend 10s polling

Frontend pollaa Leiman serveriä 10 sekunnin välein. Serveri tarkistaa KV:stä onko GitHub tree SHA -tulos alle 10 sekuntia vanha — jos on, palauttaa sen suoraan. Jos ei, tekee GitHub API -kutsun, vertaa tulosta KV:hen tallennettuun baselineen, kirjoittaa tuloksen KV:hen TTL=10s ja palauttaa sen frontille. Frontend pollaa lisäksi status.json:ia josta näkee onko uusi koodi tarkistuksessa.

Miksi: Vercel-deploy kestää 1–3 minuuttia. Sinä aikana vanha (rehellinen) serveri vastaa vielä pyyntoihin. Jos hyökkääjä pushaa muutoksia, vanha serveri havaitsee uuden GitHub tree SHA:n, kirjoittaa DANGER KV:hen ja frontend näyttää varoituksen — ennen kuin uusi deploy ehtii korvata vanhan. Kaikki samanaikaiset käyttäjät jakavat yhden GitHub API -kutsun per 10 sekuntia KV-cachen ansiosta (360/tunti vs GitHub:n 5000/tunti autentikoituna). Erillistä Render-prosessia tai ulkoista cron-palvelua ei tarvita niin kauan kuin sivulla on yksikin käyttäjä.

Toteutuksessa havaittiin että vanha checkMonitorFiles-funktio teki käytännössä saman asian mutta tread_check.py:n kautta — joka tarkoitti että kompromisoitu tread_check.py olisi voinut pettää sen kokonaan. Uusi /tread-monitor hakee suoraan GitHub API:sta ilman välikäsiä. checkMonitorFiles poistettiin ja korvattiin checkGitTree:llä joka tallentaa git tree SHA:t käyttäjän localStorageen. Nyt sekä KV-baseline (palvelinpuoli) että localStorage (käyttäjän selain) havaitsevat muutokset toisistaan riippumatta.

7. TEHTY: /tread-monitor hakee code review -statuksen ja tarkistaa deployn luvallisuuden

Code review -varoitus toteutettiin ilman KV-kirjoitusoikeutta GitHub Actionsille: /tread-monitor kysyy GitHub API:lta suoraan onko code_review.yml juuri käynnissä (status=in_progress). Jos on, frontend näyttää "Notice! code review in progress — deploy imminent". Tieto kulkee luotettavasta ulkoisesta lähteestä (GitHub API) eikä vaadi GHA:lle pääsyä KV:hen. Sama 10s pollaus hakee rinnakkain git tree SHA:t, Vercel deploy-tilan ja code review -statuksen.

Lisäksi: kun Vercel API raportoi deployn käynnissä, tarkistetaan GitHub API:sta onko code_review.yml ajanut onnistuneesti juuri sille commitille. Jos ajoi → käyttäjä on jo saanut varoituksen review-vaiheessa, deploy on luvallinen. Jos ei → frontend näyttää Danger ("unauthorized deploy detected"). Näin varmistutaan että jokainen Vercel-deploy on kulkenut code review -prosessin läpi.

Jos Vercel ei kerro deployn githubCommitSha:ta (esim. CLI- tai dashboard-deploy ilman GitHub-integraatiota), code review -tarkistusta ei voi tehdä → unauthorized_deploy=True välittömästi. Tuntematon commit tulkitaan aina luvattomaksi.

8. TEHTY: Arkkitehtuurin selkeytys — /version vs /tread-monitor

Aiemmin /version-endpoint palautti sekaisin sekä TREAD-historian että reaaliaikaisen monitoring-datan. Nämä on nyt erotettu selkeästi kahteen eri kerrokseen:

/tread-monitor (reaaliaikainen, 10s) hakee rinnakkain kolmesta lähteestä:
- GitHub API → git tree SHA:t valvotuille tiedostoille, verrataan KV-baselineen ja käyttäjän localStorageen
- Vercel API → onko deploy käynnissä ja mille commitille
- GitHub Actions API → onko code_review.yml juuri käynnissä

Lisäksi: jos Vercel raportoi deployn käynnissä, tarkistetaan onko sille commitille olemassa onnistunut code_review.yml-ajo. Jos ei löydy (tai commitia ei tunneta) → unauthorized_deploy: true → Danger.

/version (TREAD-historia) palauttaa nyt vain sen mitä GitHub Actions -cron on verifioinut:
- ok — kokonaisarvio (deployment_safe + cron_fresh + ei disabled workflows)
- checked_at — milloin viimeksi tarkistettu
- tx — Arweave-transaktio (menee leiman manifestiin, ei frontille)
- review_ok, review_stuck, review_consecutive_failures — code review -historia

Poistettu /version:sta: deployment_ok, deploying, deploying_commit, deploying_commit_ok, monitor_files, dispatcher_monitor_changed, commit_matches_tread, verified_commit, d.commit. Nämä kaikki tulevat nyt /tread-monitor:ista luotettavammista lähteistä.

Frontend-logiikka yksinkertaistui suoraksi prioriteettiketjuksi: unauthorized_deploy → file changes → review_in_progress → deploying → review_stuck → ok → mismatch → checking.

Huom: leiman manifesti lukee tread_snap-datan suoraan _tread_cache:sta (ei /version:n vastauksesta), joten siivouksella ei ole vaikutusta leimaan kirjoitettaviin tietoihin.


Operaattorin luottamusvaatimus

Leima vaatii luottamuksen operaattoriin samoin kuin perinteinen notaari — ei enempää eikä vähempää. Järjestelmän valvontamekanismit tekevät mahdollisesta pettämisestä havaittavaa ja historiallisesti todistettavaa, mutta eivät täysin mahdotonta ilman TEE:tä. Tämä kommunikoidaan käyttäjille rehellisesti.