Metadata-Version: 2.4
Name: nommo_fingerprint
Version: 0.1.0
Summary: Create, register, and verify Nommo fingerprints
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: requests>=2.31

# nommo_fingerprint

Create, register, and verify Nommo fingerprints — small provenance records that
can be embedded into a `.3mf`.

The source file is never uploaded to Nommo. A fingerprint holds a message you
write, and optionally a link to your Nommo account and asset plus a public EAS
attestation proving Nommo issued it.

## Install

```bash
pip install nommo_fingerprint
```

## Use

```python
from nommo_fingerprint import create_fingerprint, register_fingerprint, verify_fingerprint
```

### A local fingerprint

No account, no network, no blockchain:

```python
fingerprint = create_fingerprint(message="Prototype ring — September 2026")
# {"spec": "nommo_fingerprint", "version": 1, "message": "Prototype ring — September 2026"}
```

Embed it into a `.3mf` yourself and you are done. Registering is optional.

### A registered fingerprint

```python
registered = register_fingerprint(
    fingerprint,
    {"email": "alice@example.com", "password": "..."},
    asset_id="optional-nommo-asset-uuid",
)
```

The result adds Nommo's verified metadata and the attestation UID:

```python
{
  "spec": "nommo_fingerprint",
  "version": 1,
  "message": "Prototype ring — September 2026",
  "nommo": {"asset_id": "...", "user_id": "..."},
  "eas_attestation_uid": "0x...",
}
```

`nommo` appears only when you pass an `asset_id` and Nommo confirms you own that
asset. `user_id` always comes from the authenticated account, never from input.

### Verifying

```python
verify_fingerprint(registered)   # True
```

Returns `True` only when the attestation exists, is unrevoked, uses the Nommo
Fingerprint schema, was issued by Nommo's attester, and its contents match the
fingerprint exactly. Change so much as one character of the message and it
returns `False`.

Only registered fingerprints can be verified — a local one has nothing to check
against, and raises `MISSING_ATTESTATION`.

## Credentials

`user_credentials` is a dict with `password` and `email`:

```python
{"email": "alice@example.com", "password": "..."}
```

Credentials go directly to Nommo's auth service and are exchanged for a
short-lived token. They are never stored by this library, never written to the
fingerprint, never logged, and never included in exception messages. The library
holds no blockchain wallet credentials of any kind; attestations are signed by
Nommo's backend.

`user_name` is **not** supported — the auth service authenticates by email only.
Passing one raises `UNSUPPORTED_CREDENTIALS`.

## Errors

Every failure raises a `NommoFingerprintError` carrying a stable `.code`:

| Code | Meaning |
|---|---|
| `INVALID_FINGERPRINT` | Not a fingerprint, or an unsupported spec/version |
| `INVALID_MESSAGE` | Message is not a string, or is over 1000 characters |
| `INVALID_CREDENTIALS` | Missing password, or neither email nor user_name |
| `UNSUPPORTED_CREDENTIALS` | `user_name` was supplied without an email |
| `AUTH_FAILED` / `AUTH_REQUEST_FAILED` | Login rejected, or auth service unreachable |
| `MISSING_ATTESTATION` | Tried to verify an unregistered fingerprint |
| `BACKEND_ERROR` / `BACKEND_UNREACHABLE` | The Nommo backend rejected the call or could not be reached |

Catch the base class to handle any of them:

```python
from nommo_fingerprint import NommoFingerprintError

try:
    registered = register_fingerprint(fingerprint, credentials)
except NommoFingerprintError as e:
    print(e.code, e.message)
```

## Configuration

Defaults point at a locally running Nommo backend. Override with environment
variables:

| Variable | Default |
|---|---|
| `NOMMO_API_URL` | `http://localhost:8080` |
| `NOMMO_SUPABASE_URL` | Nommo's Supabase project |
| `NOMMO_SUPABASE_PUBLISHABLE_KEY` | Nommo's publishable key |
| `NOMMO_REQUEST_TIMEOUT` | `180` seconds |

Registration waits on a blockchain transaction, so the default timeout is
generous.
