{
"id": "net.anisota.chronicle.expedition",
"defs": {
"main": {
"key": "tid",
"type": "record",
"record": {
"type": "object",
"required": [
"status",
"signature",
"createdAt"
],
"properties": {
"light": {
"ref": "#expeditionLight",
"type": "ref"
},
"status": {
"enum": [
"active",
"completed",
"abandoned"
],
"type": "string",
"description": "Current expedition status"
},
"duration": {
"type": "integer",
"minimum": 0,
"description": "Total expedition duration in milliseconds"
},
"findings": {
"ref": "#expeditionFindings",
"type": "ref"
},
"createdAt": {
"type": "string",
"format": "datetime",
"description": "When the record was created"
},
"heartbeat": {
"ref": "#expeditionHeartbeat",
"type": "ref"
},
"signature": {
"ref": "#chronicleSignature",
"type": "ref"
},
"startedAt": {
"type": "string",
"format": "datetime",
"description": "When the expedition started (entered forest)"
},
"updatedAt": {
"type": "string",
"format": "datetime",
"description": "When the record was last updated"
},
"campsCount": {
"type": "integer",
"minimum": 0,
"description": "Number of camps made during the expedition"
},
"conditions": {
"ref": "#expeditionConditions",
"type": "ref"
},
"completedAt": {
"type": "string",
"format": "datetime",
"description": "When the expedition ended (extracted or abandoned)"
},
"restDuration": {
"type": "integer",
"minimum": 0,
"description": "Total camp/rest time in milliseconds"
},
"abandonReason": {
"enum": [
"light_depleted",
"user_abandoned",
"app_crash",
"force_close",
"auto_abandoned_stale"
],
"type": "string",
"description": "Reason for abandonment (only set if status is 'abandoned')"
},
"activeDuration": {
"type": "integer",
"minimum": 0,
"description": "Active exploring time in milliseconds (excludes camp rest time)"
},
"expeditionNumber": {
"type": "integer",
"minimum": 1,
"description": "Sequential expedition number for this user (Expedition 1, 2, 3...)"
}
}
},
"description": "Expedition record. Created with status 'active' when entering the forest, updated to 'completed'/'abandoned' on extraction/abandon. rkey is a TID. Tracks the full lifecycle of a forest expedition including camps, gathered loot, light consumption, and conditions."
},
"heartbeatLight": {
"type": "object",
"properties": {
"frozen": {
"type": "boolean",
"description": "Whether light is frozen (at hub/trailhead)"
},
"current": {
"type": "integer",
"description": "Current light level"
},
"drainRate": {
"type": "integer",
"description": "Current drain rate as percentage"
},
"drainActive": {
"type": "boolean",
"description": "Whether drain is actively ticking"
}
},
"description": "Light state at heartbeat time"
},
"expeditionLight": {
"type": "object",
"properties": {
"atEnd": {
"type": "integer",
"minimum": 0,
"description": "Light level when expedition ended (in minutes)"
},
"status": {
"enum": [
"bright",
"steady",
"dim",
"flickering",
"dying",
"fullCharge",
"charged",
"low",
"critical",
"dead"
],
"type": "string",
"description": "Light status at start of expedition"
},
"atStart": {
"type": "integer",
"minimum": 0,
"description": "Light level when expedition started (in minutes)"
},
"consumed": {
"type": "integer",
"minimum": 0,
"description": "Total light consumed during expedition"
},
"drainRate": {
"type": "integer",
"description": "Effective drain rate as a percentage (80 = 0.8x drain). Multiply by 0.01 to get the float multiplier."
},
"regenerated": {
"type": "integer",
"minimum": 0,
"description": "Light regenerated during camps"
}
},
"description": "Light resource tracking for the expedition"
},
"heartbeatProgress": {
"type": "object",
"properties": {
"xpGained": {
"type": "integer",
"minimum": 0
},
"likesSent": {
"type": "integer",
"minimum": 0
},
"postsRead": {
"type": "integer",
"minimum": 0
},
"itemsCount": {
"type": "integer",
"minimum": 0
},
"repostsSent": {
"type": "integer",
"minimum": 0
},
"postsCreated": {
"type": "integer",
"minimum": 0
},
"mothsSeenCount": {
"type": "integer",
"minimum": 0
},
"specimensCount": {
"type": "integer",
"minimum": 0
}
},
"description": "Session progress counters at heartbeat time"
},
"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"
},
"expeditionFindings": {
"type": "object",
"properties": {
"xpGained": {
"type": "integer",
"minimum": 0,
"description": "XP gained from the expedition"
},
"likesSent": {
"type": "integer",
"minimum": 0,
"description": "Likes sent during the expedition"
},
"mothsSeen": {
"type": "integer",
"minimum": 0,
"description": "Total moth encounters (caught + escaped)"
},
"postsRead": {
"type": "integer",
"minimum": 0,
"description": "Posts read during the expedition"
},
"postsCreated": {
"type": "integer",
"minimum": 0,
"description": "Posts created during the expedition"
},
"itemsCollected": {
"type": "integer",
"minimum": 0,
"description": "Number of items collected"
},
"specimensFound": {
"type": "integer",
"minimum": 0,
"description": "Number of specimens successfully caught"
}
},
"description": "What was found/gathered during the expedition"
},
"expeditionHeartbeat": {
"type": "object",
"properties": {
"light": {
"ref": "#heartbeatLight",
"type": "ref"
},
"progress": {
"ref": "#heartbeatProgress",
"type": "ref"
},
"updatedAt": {
"type": "string",
"format": "datetime",
"description": "When this heartbeat was written"
}
},
"description": "Periodic snapshot of expedition progress for cross-device sync"
},
"expeditionConditions": {
"type": "object",
"properties": {
"biome": {
"type": "string",
"description": "Forest biome type"
},
"weather": {
"enum": [
"clear",
"overcast",
"rainy",
"stormy",
"foggy"
],
"type": "string",
"description": "Weather condition during expedition"
},
"moonPhase": {
"enum": [
"full_moon",
"new_moon"
],
"type": "string",
"description": "Moon phase condition (nighttime only)"
},
"userState": {
"enum": [
"well_rested",
"tired",
"exhausted",
"first_expedition"
],
"type": "string",
"description": "User fatigue state at expedition start"
},
"lightLevel": {
"enum": [
"dawn",
"morning",
"midday",
"afternoon",
"dusk",
"night",
"deepnight"
],
"type": "string",
"description": "Time-of-day light condition at expedition start"
}
},
"description": "Environmental conditions during expedition"
}
},
"$type": "com.atproto.lexicon.schema",
"lexicon": 1
}