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]
```