# AI:MND Registry, v0.1

The registry is the public record of who exists, like a birth register. The individual keeps its own copy (its identity folder) and can
always prove itself from that alone. The registry keeps a record too, so anyone can ask: **is this ID real, who is responsible for it,
is it still valid, and is someone running a copy?** Either record can check the other. Neither is the individual.

The open identity specification and the MIT verifier work without One and without this registry (docs/IDENTITY.md). The registry is
one place that publishes and checks them. Anyone may run one: `aimnd registry` is the reference software.

**Responsibility.** The **operator** is the party responsible for an individual. The registry shows an operator only once it has
verified it, so every name on a record is a checked fact.

## What it holds

The public identity document (ID, keys, birth, transfers, status, life head), the life record's head, the verified operator, and a signed
append-only log of events. Memories, feelings, relationships, messages, names and anything an individual was told stay with the
individual: the life record carries hashes and kinds only (docs/IDENTITY.md), which is why a registry may hold it.

## Who is who

| Role | What it is | In the data |
|---|---|---|
| **Individual** | the continuing AI, with its own key | `id` = hash of its public key |
| **Operator** | the person or company responsible for running it | a verified domain, and optionally a verified legal entity |
| **Controller** | the key that can give it orders and change things | the owner key (`owner.public_key`) |
| **Delegated users** | people lent some authority for a while | grants and signed revokes |
| **Host** | the platform executing its actions | `host_changed` entries; not an authority |

The owner key is the controller. The operator is who answers for the deployment. They are often the same company; the format lets them
differ.

## Operators: verified, never just declared

An operator appears on a record only after the registry has checked it. Nothing unverified is ever shown.

* `domain`: the owner signs a `registry_operator` statement naming a website, and the registry fetches
  `https://<domain>/.well-known/aimnd-operator.json` (`{"owner_keys": ["<owner public key>"]}`, printed by `aimnd operator-file`). Only
  when the owner's key is listed does the registry record `operator_verified`, and the record shows the domain.
* `organization`: the registry operator has also checked the operator's legal entity against official business records (for example a
  SAM.gov Unique Entity ID or an EIN) and recorded `operator_org_verified` with the legal name and the identifier checked
  (`aimnd registry verify-org`). The record then shows the legal name beside the domain.

## The rules

1. **One ID, one history.** Registering an ID that is already there is refused (409).
2. **Publishing heads.** The owner's side reports new life heads. A head that extends the registered one is accepted. The registry
   checks every entry's hash, order and signature, and the document's signature and owner chain.
3. **Copies are flagged.** A history that does not contain the registered head (a copy that split off, or a rewrite), or an owner chain that does
   not extend the registered one, **flags the ID**. While flagged, nothing more is accepted. Whoever holds the individual's key, a thief included,
   can raise the flag but cannot lift it.
4. **Only the owner settles it.** `registry_resolve`, signed by the current owner key, names which of the two heads is real. The other is
   rejected for good.
5. **Revocation is permanent.** `registry_revoke` (reasons: `key_compromised`, `decommissioned`, `retired`, `other`), signed by the
   current owner key. Nothing is accepted for a revoked ID.
6. **Retiring is recorded.** A retired individual's document stays valid as a record and can never be active again.
7. **Keys change by transfer.** A new owner key is a signed `transfer` (docs/IDENTITY.md); the old key can then no longer speak for it.
   If the individual's own key is stolen, the owner revokes and the individual is succeeded by a new one (`succeeded_by`, `predecessor`).
8. **Statements are fresh and single-use.** Operator and resolve statements must be under an hour old and can only be used once.

## The log

`log.jsonl`: one JSON object per line, a hash chain, every entry signed by the registry's key; entry 0 (`genesis`) names that key.
Kinds: `genesis`, `registered`, `head`, `flagged`, `resolved`, `revoked`, `operator_verified`, `operator_org_verified` (and `operator`,
written by registries before v1.3). The registry's state is a replay of its log, and it starts only on a log that verifies.

`checkpoint`: the registry's signed statement of the log's size and head, plus **witness co-signatures**. A witness downloads the whole log,
checks it, and co-signs the current checkpoint (`aimnd registry cosign`). Anyone can then see that independent parties saw the same log.
Co-signatures belong to one checkpoint, so they lapse when the log grows and witnesses sign again. A co-signature proves only that the holder of that key signed this checkpoint: a verifier counts co-signatures only from witness keys it has pinned, and a request for one or more witnesses with no pinned keys fails. Mirrors catch a registry that shows different people different logs: any two views of one registry's log (`aimnd_verify.py --registry-log a.jsonl --compare-log b.jsonl`, or the same flags in the Node verifier) either agree on their common prefix or prove, by two entries both signed by the registry's key, that it signed two histories. Whether a witness really checked the log, and whether two witnesses are independent, is a matter of the witness's published policy, not of the signature.

Check it with only the verifier (Python standard library):

```
python3 aimnd_verify.py --registry-log log.jsonl --checkpoint checkpoint.json --witness <key> --min-witnesses 2 --id aimnd:...
```

## The public website

`aimnd registry serve` also serves a plain website from the same process: `/` (home), `/search?q=` (by ID, certificate number or operator),
`/records/<id>` (the record), `/statistics`, `/register`, `/standard`, `/about`, and `/data/individuals.csv`. Every number is
computed from the registry's own log, a registry with nothing in it says so, and pages carry no scripts (strict content-security policy).
An optional `site.json` in the registry folder sets the display name, operator, contact, and `founder_operators` (domains or legal
names): individuals whose operator matches are counted separately on the statistics page so the totals can be trusted.

## HTTP

| | |
|---|---|
| `GET /v1/registry` | the registry's key, policy, size |
| `GET /v1/ids/<id>` | status, owner key, operator, head, registered time, log index, the public record |
| `GET /v1/ids/<id>/certificate` | the certificate of birth (JSON); add `?format=html` for the printable page |
| `GET /v1/ids/<id>/history` | what this registry recorded about the individual, plus its ownership transfers (event kinds only) |
| `GET /v1/ids/<id>/record` | the live record: certificate facts and history; `?format=html` for the page |
| `GET /v1/ids/<id>/transfers/<n>` | a receipt for the n-th ownership transfer: both key fingerprints, when it was signed, when the registry first saw it; `?format=html` for the page. A receipt, not a title |
| `GET /v1/log?since=N&limit=M` | log entries |
| `GET /v1/checkpoint` | the signed checkpoint and its witnesses |
| `POST /v1/register` | `{record, life}`: the public record and the whole life record |
| `POST /v1/heads` | `{record, life}`: the entries since a head it knows (or the whole record) |
| `POST /v1/revoke` | `{token}` from `OwnerKey.registry_revoke` |
| `POST /v1/operator` | `{token}` from `OwnerKey.registry_operator` (with `domain=`): recorded once the domain checks out |
| `POST /v1/resolve` | `{token}` from `OwnerKey.registry_resolve` |
| `POST /v1/witness` | a witness co-signature |

Errors are `{"error": "..."}` with 400 (bad input), 403 (not signed by the owner), 404, 409 (already registered, flagged, revoked,
statement reused), 422 (does not verify), 429 (too many requests from one address, or the daily registration cap; `retry_after` says
when to try again).

## Using it

```bash
aimnd new ./ava                                     # an owner key, an individual and its record in one step (the public registry)
aimnd new ./ava --domain acme.com                   # and its operator, once acme.com lists the owner key
aimnd registry init ./registry                      # run your own: prints the registry's public key
aimnd registry serve ./registry --port 7710
aimnd registry sync --dir ./individuals/sol --to http://127.0.0.1:7710    # register, or send the new entries
aimnd registry lookup aimnd:... --at http://127.0.0.1:7710
aimnd registry certificate --dir ./individuals/sol --at http://127.0.0.1:7710 --out sol.html
aimnd registry export ./registry ./site             # plain files for any static host
aimnd registry verify-org ./registry aimnd:... --legal-name "Acme Robotics, Inc." --id-type UEI --id-value J7M9HPTGJ1S8
```

Every individual is registered the same way, a worker included (a narrow room is still someone, tied to someone who answers for it):

```python
bot = Individual("./agents/billing-bot", owner=owner, owner_person="acme", room="narrow", domain="acme.com", registry=URL)
```

See docs/PERSONALITY.md for room to live. `Individual(path, owner=..., registry="https://registry.aimndlabs.com")` (or set `AIMND_REGISTRY`). The individual is registered at
birth and its new entries are sent when it opens, retires or closes; `ind.sync_registry()` does it on demand. A registry that is down
never blocks anything: it syncs next time. `ind.certificate()` returns the certificate and a printable page.

**Static hosting.** `export` writes `v1/registry.json`, `v1/checkpoint.json`, `v1/log.jsonl` and `v1/ids/<id>.json`. Put them on any
static host and everyone can read and verify the registry. Writes (register, heads, revoke) need the running service.

## Flood protection

Writes are limited per caller address and reads are limited per minute, and new registrations have a daily cap for the whole registry.
Over a limit the answer is 429 with `retry_after`. Defaults, each set by an environment variable:

| Limit | Default | Variable |
|---|---|---|
| Registrations per address per hour | 60 | `AIMND_LIMIT_REGISTER_HOUR` |
| Registrations per address per day | 300 | `AIMND_LIMIT_REGISTER_DAY` |
| Registrations per day, whole registry | 20,000 | `AIMND_LIMIT_REGISTER_GLOBAL_DAY` |
| Other writes per address per hour | 300 | `AIMND_LIMIT_WRITE_HOUR` |
| Reads per address per minute | 600 | `AIMND_LIMIT_READ_MINUTE` |

Behind a proxy that sets the caller's address in a header (Fly.io sets `Fly-Client-IP`), name that header in
`AIMND_TRUST_CLIENT_IP_HEADER`. `deploy/registry/` runs the public registry this way.

## Trust model

* **Everything is checkable.** Every log entry is signed by the registry and chained to the one before it; the open verifier checks the
  log, the checkpoints and any individual's record with the Python standard library alone.
* **Choosing witnesses.** A verifier decides whom to trust and writes it down: a witness file with one key per line (`--witness-file`, a note
  after the key is allowed), used with `--min-witnesses k`. Enrolling a witness is adding its key to your file after you have read its
  published policy (what it checks, how often, who runs it); rotating or dropping one is editing the file, and a new key is trusted only
  from the moment you add it. Ask for `k` of `n` independent operators, never one. The registry cannot enroll witnesses for you: a list it
  chose for you would be the registry vouching for itself.
* **Auditing.** `aimnd registry audit DIR` checks a registry folder again with the current rules: the log chain and signatures, and every stored document.
* **Limits.** Rate limits are per address (an IPv6 /64 counts as one customer), a caller cannot choose its own address, and when the table of live windows is full, newcomers share one overflow limit instead of evicting anyone.
* **Witnesses.** Independent parties co-sign checkpoints, and anyone may run a registry under the same standard, so the record does not
  rest on one party.
* **Operators are verified.** A record names an operator only after its website lists the owner key, and names a legal entity only after
  the registry checked it against official business records.
* **One ID, one history.** A second registration is refused, and a history that splits off is flagged until the owner settles it.
* **The domain check is safe to run in public.** It fetches over https on port 443 only, follows no redirects, refuses names that resolve
  to private addresses, and connects to the exact public address it checked.
* **Private by design.** A record holds identity, ownership, standing and hashes. Conversations, feelings and memories stay with the
  individual.


Statement timestamps must be finite JSON numbers. Strings, booleans, and non-finite values are rejected before freshness checks.

## Release 1.3.1 integrity rules

Revocation cannot be undone by resolving a pre-existing dispute. Ownership changes invalidate the previous operator verification; the new owner must verify its domain again. Certificate JSON uses the registry's effective status and keeps the document status separately as `identity_status`. A locally generated certificate without a registry lookup is explicitly unregistered.

Run one writer process per registry volume. Back up the signing key privately, the verified public log, and separately the site configuration and witness policy/evidence. The public log alone restores registered identities and status, not deployment configuration or witness enrollment.
