# net.anisota.chronicle.milestone

> Published by [anisota.net](https://lexicon.garden/identity/did:plc:lcieujcfkv4jx7gehsvok3pr)

## Links

- [View on Lexicon Garden](https://lexicon.garden/lexicon/did:plc:lcieujcfkv4jx7gehsvok3pr/net.anisota.chronicle.milestone)
- [Documentation](https://lexicon.garden/lexicon/did:plc:lcieujcfkv4jx7gehsvok3pr/net.anisota.chronicle.milestone/docs)
- [Examples](https://lexicon.garden/lexicon/did:plc:lcieujcfkv4jx7gehsvok3pr/net.anisota.chronicle.milestone/examples)

## Definitions

### `net.anisota.chronicle.milestone`

**Type**: `record`

A milestone reached in the field, shown on the Fieldwork page's Milestones tab. Successor to net.anisota.chronicle.achievement (legacy records in that collection remain readable but no new ones are written). rkey is the milestone ID (e.g. level-50, expedition-first-light). Created once with createRecord when the milestone is reached. Immutable.

**Key**: `any`

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `name` | `string` | No | Display name of the milestone |
| `tier` | `integer` | No | Tier or threshold value (e.g. 50 for level-50) |
| `rarity` | `string` | No | Rarity tier of the milestone |
| `context` | `ref` → `#milestoneContext` | No |  |
| `category` | `string` | Yes | Category of the milestone |
| `xpReward` | `integer` | No | XP awarded for this milestone |
| `createdAt` | `string` (datetime) | Yes | When the milestone record was created |
| `signature` | `ref` → `#chronicleSignature` | Yes |  |
| `unlockedAt` | `string` (datetime) | Yes | When the milestone was reached |
| `description` | `string` | No | Description of what was reached |
| `milestoneId` | `string` | Yes | Unique identifier for the milestone (e.g. 'level-50', 'expedition-first-light') |
| `dailyRecordRef` | `string` | No | AT URI of the daily record when the milestone was reached |

### `net.anisota.chronicle.milestone#milestoneContext`

**Type**: `object`

Contextual data at the time the milestone was reached

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `level` | `integer` | No | Player level when the milestone was reached |
| `totalXP` | `integer` | No | Total XP when the milestone was reached |
| `postCount` | `integer` | No | Post count when the milestone was reached |
| `specimenCount` | `integer` | No | Specimen count when the milestone was reached |

### `net.anisota.chronicle.milestone#chronicleSignature`

**Type**: `object`

ES256 cryptographic signature proving record authenticity. The signature itself proves legitimacy - no separate verification lexicons needed.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `alg` | `string` | Yes | Signing algorithm (ES256) |
| `kid` | `string` | Yes | Key identifier for the signing key |
| `sig` | `string` | Yes | Base64-encoded ES256 signature |
| `nonce` | `string` | Yes | Unique random nonce to prevent replay |
| `version` | `integer` | Yes | Signature schema version |
| `signedAt` | `string` (datetime) | Yes | When the record was signed |

## Raw Schema

```json
{
  "id": "net.anisota.chronicle.milestone",
  "defs": {
    "main": {
      "key": "any",
      "type": "record",
      "record": {
        "type": "object",
        "required": [
          "milestoneId",
          "category",
          "unlockedAt",
          "signature",
          "createdAt"
        ],
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 100,
            "description": "Display name of the milestone"
          },
          "tier": {
            "type": "integer",
            "minimum": 0,
            "description": "Tier or threshold value (e.g. 50 for level-50)"
          },
          "rarity": {
            "enum": [
              "common",
              "uncommon",
              "rare",
              "epic",
              "legendary"
            ],
            "type": "string",
            "description": "Rarity tier of the milestone"
          },
          "context": {
            "ref": "#milestoneContext",
            "type": "ref"
          },
          "category": {
            "enum": [
              "level",
              "social",
              "collection",
              "patterns",
              "special",
              "expedition"
            ],
            "type": "string",
            "description": "Category of the milestone"
          },
          "xpReward": {
            "type": "integer",
            "minimum": 0,
            "description": "XP awarded for this milestone"
          },
          "createdAt": {
            "type": "string",
            "format": "datetime",
            "description": "When the milestone record was created"
          },
          "signature": {
            "ref": "#chronicleSignature",
            "type": "ref"
          },
          "unlockedAt": {
            "type": "string",
            "format": "datetime",
            "description": "When the milestone was reached"
          },
          "description": {
            "type": "string",
            "maxLength": 500,
            "description": "Description of what was reached"
          },
          "milestoneId": {
            "type": "string",
            "maxLength": 100,
            "description": "Unique identifier for the milestone (e.g. 'level-50', 'expedition-first-light')"
          },
          "dailyRecordRef": {
            "type": "string",
            "description": "AT URI of the daily record when the milestone was reached"
          }
        }
      },
      "description": "A milestone reached in the field, shown on the Fieldwork page's Milestones tab. Successor to net.anisota.chronicle.achievement (legacy records in that collection remain readable but no new ones are written). rkey is the milestone ID (e.g. level-50, expedition-first-light). Created once with createRecord when the milestone is reached. Immutable."
    },
    "milestoneContext": {
      "type": "object",
      "properties": {
        "level": {
          "type": "integer",
          "minimum": 1,
          "description": "Player level when the milestone was reached"
        },
        "totalXP": {
          "type": "integer",
          "minimum": 0,
          "description": "Total XP when the milestone was reached"
        },
        "postCount": {
          "type": "integer",
          "minimum": 0,
          "description": "Post count when the milestone was reached"
        },
        "specimenCount": {
          "type": "integer",
          "minimum": 0,
          "description": "Specimen count when the milestone was reached"
        }
      },
      "description": "Contextual data at the time the milestone was reached"
    },
    "chronicleSignature": {
      "type": "object",
      "required": [
        "sig",
        "alg",
        "kid",
        "signedAt",
        "nonce",
        "version"
      ],
      "properties": {
        "alg": {
          "type": "string",
          "description": "Signing algorithm (ES256)"
        },
        "kid": {
          "type": "string",
          "description": "Key identifier for the signing key"
        },
        "sig": {
          "type": "string",
          "description": "Base64-encoded ES256 signature"
        },
        "nonce": {
          "type": "string",
          "description": "Unique random nonce to prevent replay"
        },
        "version": {
          "type": "integer",
          "description": "Signature schema version"
        },
        "signedAt": {
          "type": "string",
          "format": "datetime",
          "description": "When the record was signed"
        }
      },
      "description": "ES256 cryptographic signature proving record authenticity. The signature itself proves legitimacy - no separate verification lexicons needed."
    }
  },
  "$type": "com.atproto.lexicon.schema",
  "lexicon": 1
}
```
