Metadata-Version: 2.1
Name: wj-diode-quantum
Version: 1.0.0b3
Summary: Quantum random numbers from ANU, pushed across a data diode and served on the other side
Home-page: https://github.com/WaterJuice/wj-diode-quantum
Author: WaterJuice
License: Unlicense
Requires-Python: >=3.7
Classifier: Programming Language :: Go
Description-Content-Type: text/markdown
# wj-diode-quantum

Collects quantum random numbers from the Australian National University, streams them across a data
diode, and serves them one at a time on the protected side. Each value is 1024 bits.

A data diode only carries data one way, so a machine behind one cannot ask ANU for random numbers
itself. This program splits the job in two: one side collects and pushes, the other stockpiles what
arrives and hands it out on request.

## Quick start

Two machines, one command each.

### Machine 1 — internet side

```sh
uv tool install wj-diode-quantum
wj-diode-quantum setup send
wj-diode-quantum collect -c config.json
```

### Machine 2 — protected side

```sh
uv tool install wj-diode-quantum
wj-diode-quantum setup recv
wj-diode-quantum serve -c config.json
```

### Check it works

```sh
curl localhost:8099/api/status    # numbers are arriving
curl localhost:8099/api/random    # take one
```

```json
{
  "value": "74b033a4332c7112cf0c3ff5...67f6b30ee",
  "timestamp": "2026-08-02T04:14:58Z",
  "source": "quantumnumbers"
}
```

`value` is your 1024-bit random number, 256 lowercase hex characters. `timestamp` is when it was
collected. You will never be given that number again.

Open `http://localhost:8099/` in a browser for the same thing with live pool figures.

Full documentation: [docs.waterjuice.org/wj-diode-quantum](https://docs.waterjuice.org/wj-diode-quantum/latest/)

## Features

- **Nothing is written to disk** — on either side. The numbers exist only in pipes and in memory.
- **Both ANU APIs** — the current keyed service and the older unkeyed one, each on its own schedule
  sized to its rate limit. Enable either or both.
- **Any diode tool** — the transfer is a configured external command reading and writing a stream.
  Built against `diodetool`, but nothing about it is hard-coded.
- **Never serves the same number twice** — for as long as the server is running, which is as long as
  the pool exists.
- **Bounded, self-trimming pool** — newest served first, oldest discarded at capacity.
- **One process per machine** — the receiving side runs the diode tool for you.
- **Damage is contained** — a diode cannot retransmit, so a corrupted value is dropped and the
  stream resynchronises rather than losing everything behind it.
- **Zero dependencies** — a single static binary, Go standard library only.

## Requirements

- A tool that can move a file across your diode, on both sides.
- An ANU API key from [quantumnumbers.anu.edu.au](https://quantumnumbers.anu.edu.au/api-key), free
  with an account. Optional if you only use the legacy endpoint.

## Building

```sh
make build        # wheels for all platforms, plus documentation
make check        # tests, format check, and vet
make dev          # run from source via a .venv launcher
```

## How it fits together

```
  internet side                     diode                  protected side
  ─────────────                     ─────                  ──────────────
  ANU ──> collect ──> [ stream-send ] ══════> [ stream-recv ] ──> serve ──> GET /api/random
                            stdin                  stdout          │
                                                                   v
                                                            in-memory pool
```

Nothing comes back, so the collector never learns whether anything arrived. Nothing is stored: a
transfer the diode will not take is retried and then discarded, and the pool is lost on restart and
refills from the far side's next cycle.

## Security

There is **no authentication on the API**. Anyone who can reach the port can drain the pool. The
default binds to `127.0.0.1` — keep it on loopback or a trusted network, or put a reverse proxy in
front of it. Supply is finite, so a rate limit matters as much as authentication.

Diode passwords are written to a file with mode `0600` and passed with `--password-file` rather than
on a command line, where `ps` would expose them.

Because a diode carries nothing back, the collector cannot be told the server is running low. Watch
`/api/status`, the root page, or `wj-diode-quantum stats` on the protected side.

## Licence

Released under the [Unlicense](https://unlicense.org/) — public domain.

