Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions .github/workflows/connected-microcosm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ jobs:

- name: Checkout SEC Portal for workspace inspection
uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
continue-on-error: true
with:
repository: high-cde/ZDOS-SEC-PORTAL
ref: 47247dfd3eff79fbd0078b4187547dba37ac4818
Expand All @@ -46,6 +47,7 @@ jobs:

- name: Checkout Cybercore for workspace inspection
uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
continue-on-error: true
with:
repository: high-cde/Z-CYBERCORE
ref: e8637a4e59e454a0b8bc0f748d4ed0d9bd5de4a0
Expand All @@ -66,11 +68,11 @@ jobs:

- name: Assert external checkout presence and cleanliness
run: |
test -d Zlang && test -d zdos-organism && test -d ZDOS-SEC-PORTAL && test -d Z-CYBERCORE
test -d Zlang && test -d zdos-organism
test -z "$(git -C Zlang status --porcelain)"
test -z "$(git -C zdos-organism status --porcelain)"
test -z "$(git -C ZDOS-SEC-PORTAL status --porcelain)"
test -z "$(git -C Z-CYBERCORE status --porcelain)"
if [ -d ZDOS-SEC-PORTAL ]; then test -z "$(git -C ZDOS-SEC-PORTAL status --porcelain)"; fi
if [ -d Z-CYBERCORE ]; then test -z "$(git -C Z-CYBERCORE status --porcelain)"; fi

- name: Validate local entrypoints and release policy
run: ./microcosm/zdos-microctl gate
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ python3 zretro/ide/zretro.py run zretro/projects/meteor-patrol/main.zretro
python3 zretro/ide/zretro.py build zretro/projects/meteor-patrol/main.zretro
```

Il preview terminale è già operativo. La pipeline produce IR e manifest verificabili; i backend per binari nativi e emulatori vengono attivati soltanto quando cc65/ca65, vasm, VICE, Altirra o FS-UAE sono presenti nel nodo. La specifica è in [`docs/ZRETRO.md`](docs/ZRETRO.md).
Il preview terminale è già operativo. La pipeline produce IR e manifest verificabili; i backend per binari nativi e emulatori vengono attivati soltanto quando cc65/ca65, vasm, VICE, Altirra o FS-UAE sono presenti nel nodo. Il catalogo [`zretro/packages/official/`](zretro/packages/official/) contiene i primi software ufficiali **ZRetro by ZDOS** per Commodore 64 e Amiga. I terminali possono collegarsi e scambiarsi messaggi sul bus locale `zretro.local` con `l`, `s` e `i`; il bus è filesystem-scoped, append-only e senza rete implicita. La specifica è in [`docs/ZRETRO.md`](docs/ZRETRO.md).

Il launcher operativo è [`tools/zdos-launcher.sh`](tools/zdos-launcher.sh), con documentazione in [`docs/ZDOS_LAUNCHER.md`](docs/ZDOS_LAUNCHER.md). Il progetto originale [`Castel Goblin`](zretro/projects/castel-goblin/README.md) è organizzato in tre livelli progressivi e può essere avviato dal launcher dopo la rilevazione dell’ambiente.

Expand Down
131 changes: 131 additions & 0 deletions docs/ZDOS_ANONYMOUS_OVERLAY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# ZDOS Anonymous Overlay

## Stato del documento

**Versione:** 0.1
**Stato:** laboratorio e validazione
**Profilo ZLang:** `zdos.anonymous-overlay.v0.1`
**Compatibilità Tor:** non dichiarata
**Traffico pubblico:** disabilitato

## Decisione progettuale

ZDOS Anonymous Overlay è un progetto di rete a circuiti ispirato a principi di minimizzazione della conoscenza dei relay. Non è Tor, non dichiara compatibilità con Tor e non promette anonimato assoluto. La prima versione è una policy ZLang verificabile. Non è ancora un trasporto anonimo operativo.

ZLang descrive ruoli, capacità, transizioni, limiti e rifiuti. Un sottosistema esterno implementerà in seguito il trasporto usando primitive crittografiche mature e librerie sottoposte a revisione. La policy non può aprire socket, leggere chiavi, modificare il filesystem o avviare processi.

> **Regola di sicurezza:** nessuna capacità di rete viene concessa implicitamente. Ogni azione deve essere presente nella policy e verificata dal runtime.

## Scopo della versione 0.1

La versione 0.1 definisce un client di laboratorio con circuito minimo di tre ruoli: guard, middle ed exit. Il circuito è valido solo quando il consenso firmato è recente, i link sono autenticati e i relay non condividono lo stesso operatore o la stessa famiglia amministrativa quando tale informazione è disponibile.

Il profilo consente solo flussi TCP verso le porte 80 e 443. Il DNS diretto viene rifiutato. UDP, TUN, servizi onion, pubblicazione e listener pubblico sono disabilitati. Questa restrizione evita di trasformare una policy di laboratorio in un proxy generale non controllato.

| Area | Decisione v0.1 |
|---|---|
| Ruolo | client |
| Circuito minimo | guard → middle → exit |
| Trasporto applicativo | TCP mediato |
| Porte di uscita | 80 e 443 |
| DNS | solo attraverso circuito |
| UDP | rifiutato |
| TUN | disabilitato |
| Onion services | disabilitati |
| Listener pubblico | disabilitato |
| Pubblicazione directory | disabilitata |
| Modalità | validate-only / laboratorio |

## Strati del sistema

| Strato | Responsabilità | Non deve fare |
|---|---|---|
| ZLang policy layer | Ruoli, capacità, limiti, stati e rifiuti | Implementare crittografia o socket |
| Node runtime | Identità del nodo, consenso e macchine a stati | Ignorare una policy valida o inventare transizioni |
| Link protocol | Collegamento autenticato tra due relay | Riutilizzare chiavi tra hop |
| Circuit protocol | Creazione, estensione e chiusura del circuito | Esporre l’indirizzo del client a ogni relay |
| Application gateway | Proxy TCP limitato e osservabile | Consentire DNS diretto, UDP o porte non autorizzate |

## Stato e transizioni

Il profilo definisce una macchina a stati deterministica:

```text
startup
→ directory-verified
→ link-authenticated
→ circuit-ready
→ stream-open
→ closing
→ halted
```

Il runtime deve rifiutare consenso obsoleto, firme invalide, versioni sconosciute, campi duplicati, frame non canonici, handshake scaduti e transizioni non dichiarate. Un errore irreversibile deve chiudere esplicitamente lo stream e il circuito interessato.

## Crittografia e segreti

La policy non introduce primitive crittografiche. Il trasporto dovrà usare librerie mature con parametri fissati, gestione esplicita delle versioni e API strette. Le chiavi private dovranno essere generate dal CSPRNG del sistema operativo. Non dovranno essere presenti nel sorgente ZLang, nei log, nei manifest pubblici o nei file di configurazione ordinari.

Le chiavi di identità del relay, le chiavi di sessione del link, le chiavi del circuito e le chiavi derivate dello stream devono avere scopi distinti. Una chiave non deve essere riutilizzata tra hop o tra circuiti. La rotazione e la revoca devono essere rappresentate nel consenso firmato prima di qualsiasi uso dei metadati.

## Formato minimo dei messaggi

Il formato binario futuro dovrà essere versionato e canonico. Ogni frame dovrà contenere almeno versione, tipo, identificatore del circuito, identificatore dello stream, lunghezza dichiarata, contatore anti-replay, payload autenticato e tag di autenticazione.

Il parser deve avere limiti rigidi di lunghezza e memoria. Deve rifiutare campi duplicati, versioni sconosciute, lunghezze incoerenti e rappresentazioni non canoniche. Il parser non deve usare ricorsione non necessaria. Il fuzzing e il property-based testing devono essere prerequisiti prima di collegare il trasporto a Internet.

## Minacce e contromisure

| Minaccia | Contromisura prevista |
|---|---|
| Relay malevolo | Handshake autenticato, identità verificata e consenso firmato |
| Directory manipolata | Firme multiple, verifica temporale e rifiuto di documenti incoerenti |
| Replay | Nonce, contatori monotoni e finestre temporali |
| Parser exploit | Parser piccolo, limiti rigidi, fuzzing e assenza di ricorsione inutile |
| Correlazione globale | Padding e multiplexing solo dopo specifica; nessuna promessa assoluta |
| DNS leak | Risoluzione attraverso circuito o rifiuto della modalità |
| Bypass overlay | Policy per applicazione e TUN disabilitato nella v0.1 |
| Flooding | Quote, backpressure, limite circuiti e rate limit |
| Nodo compromesso | Privilegi ridotti, segreti minimizzati e aggiornamenti firmati |
| Errori applicativi | Isolamento del client, contenuti attivi esclusi e limiti documentati |

La selezione dei relay deve ridurre, quando i dati sono disponibili, la probabilità di scegliere nodi sotto lo stesso operatore o nella stessa famiglia amministrativa. La diversità geografica non è una prova di indipendenza.

## Capacità ZLang

Il file [`network/zlang/zdos-anonymous-overlay-policy.zlang`](../network/zlang/zdos-anonymous-overlay-policy.zlang) è il profilo dichiarativo di riferimento. Le capacità iniziali sono `directory.read`, `circuit.create`, `circuit.extend`, `stream.open` e `stream.close`.

Il profilo non concede `socket.open`, `key.read`, `key.export`, `filesystem.write`, `process.exec`, `policy.publish`, `service.onion` o `tun.enable`. Queste capacità sono fuori dal perimetro della versione 0.1.

Il runtime deve produrre eventi osservabili per policy accettata, directory verificata, circuito creato, circuito esteso, stream aperto, stream chiuso, policy rifiutata e violazione di sicurezza. Gli eventi non devono contenere segreti, payload applicativi o credenziali.

## Roadmap controllata

| Fase | Risultato | Gate |
|---|---|---|
| A | Specifica, policy e modello di minaccia | Revisione della policy e test negativi |
| B | Wrapper crittografici e parser | Fuzzing, limiti di risorsa e API review |
| C | Rete locale deterministica | Relay di laboratorio e test di creazione/estensione |
| D | Directory e consenso | Firme, scadenza, revoca e relay malevoli simulati |
| E | Proxy TCP limitato | Solo porte dichiarate, DNS attraverso circuito e backpressure |
| F | Revisione indipendente | Audit, test di carico e decisione esplicita sul rilascio |

Nessuna fase autorizza automaticamente la successiva. Il passaggio a una rete pubblica richiede revisione indipendente, audit crittografico, disclosure process e verifica di due implementazioni indipendenti del formato.

## Criteri di accettazione v0.1

La policy è accettata quando ogni messaggio invalido viene rifiutato senza crescita illimitata della memoria, nessuna chiave o credenziale appare nei log, un relay non presente in un consenso valido viene rifiutato, le firme e le versioni invalide vengono respinte e ogni circuito ha chiavi distinte per hop.

Devono inoltre essere verificati chiusura su timeout, errori e revoca, divieto di DNS diretto, limiti di memoria, banda, circuiti e stream, oltre a test indipendenti contro il gateway. Un audit esterno non deve lasciare vulnerabilità critiche aperte. La documentazione deve distinguere privacy del percorso, anonimato dell’utente e sicurezza dell’endpoint.

## Limiti dichiarati

Questa versione non offre anonimato assoluto. Non protegge da un osservatore globale, da endpoint compromessi, da correlazione temporale avanzata, da errori applicativi o da una rete con relay collusi in modo significativo. Non deve essere usata per traffico pubblico, elusione, abuso o attività non autorizzate.

## Riferimenti

[1]: ../network/zlang/zdos-anonymous-overlay-policy.zlang "ZDOS Anonymous Overlay Policy v0.1"

[2]: https://www.z-lang.org/ "ZLang project reference"

[3]: https://www.torproject.org/about/history/ "Tor project background and public scope"
22 changes: 19 additions & 3 deletions docs/ZRETRO.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ b <file> valida e prepara pacchetti target
r <file> preview terminale retro
t target supportati
a panoramica asset
l <id> <peer> collega due terminali sul bus locale
s <to> <messaggio> invia messaggio ZRetro local-only
i <id> legge la inbox del terminale
p pubblicazione esplicita del manifest su Hub
q uscita
```
Expand All @@ -47,7 +50,20 @@ python3 zretro/ide/zretro.py run zretro/projects/meteor-patrol/main.zretro
python3 zretro/ide/zretro.py build zretro/projects/meteor-patrol/main.zretro
```

La console mostra il prompt nativo `x@zdos /zretro` e instrada i comandi brevi verso init, preview, build e catalogo target.
La console mostra il prompt nativo `x@zdos /zretro` e instrada i comandi brevi verso init, preview, build, catalogo target e bus locale.

## Software ufficiale ZDOS per Amiga e Commodore 64

Il catalogo [`zretro/packages/official/`](../zretro/packages/official/) contiene i primi pacchetti **ZRetro by ZDOS**: `zretro-terminal-c64` per Commodore 64 e `zretro-terminal-amiga` per Amiga. Sono sorgenti DSL e manifesti verificabili, non ROM o immagini proprietarie: il builder produce IR e provenance; l’emissione di `.prg` e `.adf` richiede toolchain native installate e viene dichiarata solo dopo una build verificata.

I terminali possono essere creatori e comunicativi tramite `zretro.local`. Il bus è append-only JSONL nella directory di progetto o in `ZDOS_ZRETRO_BUS_DIR`; non apre socket, non usa credenziali e non abilita rete implicita. L’interconnessione è esplicita:

```sh
python3 zretro/ide/zretro.py console --root /tmp/zdos-bus
# l c64-01 amiga-01
# s amiga-01 hello from C64
# i amiga-01
```

## Target e backend

Expand All @@ -57,7 +73,7 @@ La console mostra il prompt nativo `x@zdos /zretro` e instrada i comandi brevi v
| Atari 8-bit | 6502 | `.xex` | cc65/ca65 e Altirra |
| Amiga | 68000 | `.adf` | vasm + disk builder e FS-UAE |

La prima versione genera un IR ZRetro e manifest target verificabili. Il preview terminale è operativo; l’emissione di binari nativi e la chiamata agli emulatori sono backend successivi, da attivare soltanto quando gli strumenti sono presenti nel nodo.
La versione attuale genera un IR ZRetro, manifest target verificabili e messaggi locali tra terminali. Il preview e il bus sono operativi; l’emissione di binari nativi e la chiamata agli emulatori sono backend successivi, da attivare soltanto quando gli strumenti sono presenti nel nodo.

La scelta dei backend è coerente con gli strumenti pubblici: cc65 supporta target 6502 tra cui Commodore e Atari [1]; Altirra documenta immagini Atari come ATR, ATX, XFD, ROM e BIN [2]; FS-UAE è un emulatore Amiga multipiattaforma focalizzato sui giochi [3].

Expand All @@ -71,7 +87,7 @@ Il progetto è confinato alla propria root. La DSL non esegue shell arbitraria,

## Roadmap

La roadmap tecnica è: editor TUI nativo, parser ZRetro completo, asset pipeline palette/sprite/sound, backend cc65 per C64/Atari, backend 68000 per Amiga, launcher emulatore locale, manifest firmati e pannello ZRetro nella War Room/Hub.
La roadmap tecnica residua è: editor TUI nativo, parser ZRetro completo, asset pipeline palette/sprite/sound, backend cc65 per C64, backend 68000 per Amiga, launcher emulatore locale, manifest firmati e pannello ZRetro nella War Room/Hub. Il contratto di comunicazione locale e il catalogo sorgente ufficiale sono già attivi e testati.

## Riferimenti

Expand Down
3 changes: 2 additions & 1 deletion interface/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
},
"scripts": {
"start": "node server/server.js",
"check": "node --check server/server.js"
"check": "node --check server/server.js && node --check server/zretro-chat.js && node --check web/js/app.js",
"test": "node --test server/zretro-chat.test.js"
},
"dependencies": {
"express": "5.2.1"
Expand Down
24 changes: 24 additions & 0 deletions interface/web/server/server.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const express = require("express");
const path = require("path");
const { snapshot } = require("./zretro-chat");

const app = express();
const port = Number.parseInt(process.env.PORT || "8080", 10);
Expand Down Expand Up @@ -32,6 +33,29 @@ app.get("/status", (_req, res) => {
});
});

app.get("/zretro/chat", (_req, res) => {
res.json(snapshot());
});

app.get("/zretro/chat/stream", (req, res) => {
res.writeHead(200, {
"Cache-Control": "no-store",
"Content-Type": "text/event-stream",
Connection: "keep-alive",
"X-Accel-Buffering": "no",
});
let closed = false;
const publish = () => {
if (!closed) res.write(`event: snapshot\ndata: ${JSON.stringify(snapshot())}\n\n`);
};
publish();
const timer = setInterval(publish, 1000);
req.on("close", () => {
closed = true;
clearInterval(timer);
});
});

app.use((_req, res) => {
res.status(404).json({ error: "not_found" });
});
Expand Down
45 changes: 45 additions & 0 deletions interface/web/server/zretro-chat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
const fs = require("fs");
const path = require("path");

const CHAT_CHANNEL = "zretro.chat";
const MAX_MESSAGES = 500;

function busDirectory() {
return path.resolve(process.env.ZDOS_ZRETRO_BUS_DIR || path.join(__dirname, "../../../zretro/build/bus"));
}

function readMessages() {
const file = path.join(busDirectory(), "messages.jsonl");
if (!fs.existsSync(file)) return [];
return fs.readFileSync(file, "utf8")
.split("\n")
.filter(Boolean)
.slice(-MAX_MESSAGES)
.flatMap((line) => {
try { return [JSON.parse(line)]; } catch { return []; }
})
.filter((message) => message.schema === "zdos-zretro-bus/v1" && message.channel === CHAT_CHANNEL);
}

function snapshot() {
const messages = readMessages();
const nodes = new Set();
messages.forEach((message) => {
nodes.add(message.sender);
nodes.add(message.recipient);
});
return {
schema: "zdos-zretro-chat-dashboard/v1",
status: "LOCAL_READ_ONLY",
channel: CHAT_CHANNEL,
bus_directory: busDirectory(),
generated_at: new Date().toISOString(),
node_count: nodes.size,
message_count: messages.length,
nodes: [...nodes].sort(),
messages,
disclaimer: "Feed locale osservativo; nessuna mutazione, rete o capability remota viene abilitata.",
};
}

module.exports = { CHAT_CHANNEL, busDirectory, readMessages, snapshot };
29 changes: 29 additions & 0 deletions interface/web/server/zretro-chat.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
const assert = require("node:assert/strict");
const fs = require("node:fs");
const os = require("node:os");
const path = require("node:path");
const test = require("node:test");

const modulePath = require.resolve("./zretro-chat");

test("snapshot exposes only valid zretro.chat traffic", () => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), "zdos-chat-"));
const previous = process.env.ZDOS_ZRETRO_BUS_DIR;
process.env.ZDOS_ZRETRO_BUS_DIR = root;
try {
fs.writeFileSync(path.join(root, "messages.jsonl"), [
JSON.stringify({ schema: "zdos-zretro-bus/v1", id: "chat-1", sender: "c64-01", recipient: "amiga-01", channel: "zretro.chat", body: "hello", created_at: "1000000000" }),
JSON.stringify({ schema: "zdos-zretro-bus/v1", id: "other-1", sender: "c64-01", recipient: "amiga-01", channel: "zretro.system", body: "hidden", created_at: "1000000001" }),
].join("\n") + "\n");
delete require.cache[modulePath];
const { snapshot } = require("./zretro-chat");
const data = snapshot();
assert.equal(data.channel, "zretro.chat");
assert.equal(data.message_count, 1);
assert.deepEqual(data.nodes, ["amiga-01", "c64-01"]);
assert.equal(data.messages[0].body, "hello");
} finally {
if (previous === undefined) delete process.env.ZDOS_ZRETRO_BUS_DIR;
else process.env.ZDOS_ZRETRO_BUS_DIR = previous;
}
});
Loading