a73x

specs/001-gpg-event-signing/data-model.md

Ref:   Size: 2.9 KiB

# Data Model: Ed25519 Signing for Event Commits

## Entities

### Event (existing — unchanged)

| Field | Type | Description |
|-------|------|-------------|
| timestamp | String (RFC3339) | UTC timestamp of event creation |
| author | Author | Name and email of event creator |
| action | Action (tagged enum) | The event action with type-specific fields |

### Author (existing — unchanged)

| Field | Type | Description |
|-------|------|-------------|
| name | String | Display name |
| email | String | Email address |

### SignedEvent (new — serialized as event.json)

| Field | Type | Description |
|-------|------|-------------|
| *(all Event fields)* | *(flattened)* | Event content via serde flatten |
| signature | String (base64) | Ed25519 signature over canonical Event JSON |
| pubkey | String (base64) | Ed25519 public key of signer (32 bytes, base64) |

### SigningKey (new — stored on disk)

| Attribute | Value |
|-----------|-------|
| Algorithm | Ed25519 |
| Private key size | 32 bytes (expanded to 64 internally by ed25519-dalek) |
| Public key size | 32 bytes |
| Storage format | Base64-encoded raw bytes |
| Private key path | `~/.config/git-collab/signing-key` |
| Public key path | `~/.config/git-collab/signing-key.pub` |
| File permissions | 0o600 (private), 0o644 (public) |

### SignatureVerificationResult (new — runtime only, not persisted)

| Field | Type | Description |
|-------|------|-------------|
| commit_id | Oid | Git commit OID being verified |
| status | VerifyStatus | Valid, Invalid, Missing, UnknownKey |
| pubkey | Option\<String\> | Public key that signed (if present) |
| error | Option\<String\> | Human-readable error detail |

### VerifyStatus (enum)

| Variant | Description |
|---------|-------------|
| Valid | Signature verified successfully against the embedded public key |
| Invalid | Signature present but verification failed (tampered or wrong key) |
| Missing | No signature or pubkey field in event.json |

## Relationships

```
Event 1──1 SignedEvent (wrapper adds signature fields)
SignedEvent ──▶ event.json blob in git commit
SigningKey 1──* SignedEvent (one key signs many events)
SignedEvent ──▶ SignatureVerificationResult (on verification)
```

## State Transitions

### Key Lifecycle

```
[No Key] ──collab init-key──▶ [Key Exists]
[Key Exists] ──sign event──▶ [Key Exists] (no state change)
```

### Event Signing Lifecycle

```
[Event Created] ──serialize──▶ [Canonical JSON]
[Canonical JSON] ──sign──▶ [SignedEvent]
[SignedEvent] ──serialize──▶ [event.json blob]
[event.json blob] ──commit──▶ [Git Commit]
```

### Verification Lifecycle (per ref during sync)

```
[Fetch Remote Ref]
  ──walk DAG──▶ [For Each Commit]
    ──read event.json──▶ [Parse SignedEvent]
      ──extract sig+key──▶ [Verify]
        ──Valid──▶ [Accept Commit]
        ──Invalid/Missing/UnknownKey──▶ [Reject Entire Ref]
```