aboutsummaryrefslogtreecommitdiff
path: root/README.md
blob: 42e703c8759f9b01846b05b98c058898fc1b9454 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# Plutia

Plutia is a deterministic, verifiable PLC mirror for `plc.directory` with signed checkpoints and a proof-serving API.

## Key Capabilities

- Mirror and resolver modes.
- Pebble-backed state/index storage.
- Compressed append-only operation blocks (`zstd`) in mirror mode.
- Deterministic canonical operation handling and signature-chain verification.
- Signed Merkle checkpoints and DID inclusion proof API.
- Corruption detection and restart-safe ingestion.
- High-density storage scaling around ~1.2KB/op in benchmarked runs.
- ~45x faster than naive replay in benchmarked runs.

## Trust Model

- Plutia mirrors data from `https://plc.directory`.
- Plutia validates operation signature chains and prev-link continuity according to configured verification policy.
- Plutia does **not** alter PLC authority or introduce consensus.
- Checkpoints are mirror commitments about what this mirror observed and verified, not global consensus.

## Modes

- `mirror`: stores full verifiable operation history (`data/ops/*.zst`) + state + proofs/checkpoints.
- `resolver`: stores resolved DID state/index only (no op block archive).

## Quick Start

```bash
go test ./...
go build ./cmd/plutia
./plutia serve --config=config.yaml
```

### CLI Commands

```bash
plutia serve --config=config.yaml [--max-ops=0]
plutia replay --config=config.yaml [--max-ops=0]
plutia verify --config=config.yaml --did=did:plc:example
plutia snapshot --config=config.yaml
plutia bench --config=config.yaml --max-ops=200000
plutia compare --config=config.yaml --remote=https://mirror.example.com
plutia version
```

## Versioning and Reproducible Builds

Plutia follows semantic versioning, starting at `v0.1.0`.

`plutia version` prints:

- `Version` (defaults to `dev` if not injected)
- `Commit`
- `BuildDate` (UTC RFC3339)
- `GoVersion`

Build metadata is injected through ldflags:

```bash
go build -trimpath \
  -ldflags "-X main.version=v0.1.0 -X main.commit=$(git rev-parse --short HEAD) -X main.buildDate=$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
  -o ./bin/plutia ./cmd/plutia
```

`make build` provides the same pattern.

## HTTP API

- `GET /health`
- `GET /metrics` (Prometheus)
- `GET /status` (includes build/version metadata)
- `GET /did/{did}`
- `GET /did/{did}/proof`
- `GET /checkpoints/latest`
- `GET /checkpoints/{sequence}`

## PLC API Compatibility

Plutia includes read-only compatibility endpoints for `plc.directory` API consumers:

- `GET /{did}` (returns `application/did+ld+json`)
- `GET /{did}/log`
- `GET /{did}/log/last`
- `GET /{did}/log/audit`
- `GET /{did}/data`
- `GET /export` (NDJSON, `application/jsonlines`, supports `count` up to `1000`, and `after` RFC3339 filtering based on ingested operation timestamps)

For audit/export compatibility fields, `createdAt` is sourced from the mirror's recorded ingest timestamp for each operation reference.

Write behavior is intentionally unsupported:

- `POST /{did}` returns `405 Method Not Allowed` with `Allow: GET`

Verification features are additive extensions and remain available under:

- `GET /did/{did}`
- `GET /did/{did}/proof`
- `GET /checkpoints/latest`
- `GET /checkpoints/{sequence}`

## Metrics and Observability

Prometheus series exposed at `/metrics` include:

- `ingest_ops_total`
- `ingest_ops_per_second`
- `ingest_lag_ops`
- `verify_failures_total`
- `checkpoint_duration_seconds`
- `checkpoint_sequence`
- `disk_bytes_total`
- `did_count`

Operational hardening includes:

- Per-IP token-bucket rate limits (stricter on proof endpoints).
- Per-request timeout (default `10s`) with cancellation propagation.
- Upstream ingestion retries with exponential backoff and `429` handling.
- Graceful SIGINT/SIGTERM shutdown with flush-before-exit behavior.

## Running Your Own Mirror

### System Requirements

- Go 1.25+
- SSD-backed storage recommended
- RAM: 4GB minimum, 8GB+ recommended for larger throughput
- CPU: multi-core recommended for parallel verification workers

### Disk Projections

Using benchmarked density (~1.2KB/op total):

- 5,000,000 ops: ~6GB
- 10,000,000 ops: ~12GB

Always keep extra headroom for compaction, checkpoints, and operational buffers.

### Example `config.yaml`

See [`config.yaml`](./config.yaml). Core knobs:

- `mode`
- `verify`
- `commit_batch_size`
- `verify_workers`
- `checkpoint_interval`
- `rate_limit.*`
- `request_timeout`

### Example `docker-compose.yml`

```yaml
services:
  plutia:
    image: golang:1.25
    working_dir: /app
    command: sh -lc "go build -trimpath -o /app/bin/plutia ./cmd/plutia && /app/bin/plutia serve --config=/app/config.yaml"
    ports:
      - "8080:8080"
    volumes:
      - ./:/app
      - ./data:/app/data
    restart: unless-stopped
```

### Upgrade and Backup Guidance

- Stop the process cleanly (`SIGTERM`) to flush pending writes.
- Back up `data/index`, `data/ops`, and `data/checkpoints` together.
- Keep the same `mode` per data directory across restarts.
- Upgrade binaries first in staging, then production using the same on-disk data.

## Mirror Comparison

Use:

```bash
plutia compare --config=config.yaml --remote=https://mirror.example.com
```

The command fetches remote `/checkpoints/latest` and compares:

- checkpoint sequence
- DID Merkle root
- signature presence

Behavior:

- same sequence + different root => divergence warning and non-zero exit
- different sequences => reports which mirror is ahead and exits non-zero
- matching sequence/root/signature presence => success

## License

MIT OR Apache-2.0