games.cavu.tier-madness.clientFrame

chris.pardy.family

{
  "$type": "com.atproto.lexicon.schema",
  "defs": {
    "addBot": {
      "description": "Host only, in the lobby: seat a bot (Jev, TypeSafe's System One model) that plays like anyone else. One per game; remove it with #kick.",
      "properties": {},
      "type": "object"
    },
    "advance": {
      "description": "Host only: move the reveal along (next card, next screen).",
      "properties": {},
      "type": "object"
    },
    "auth": {
      "description": "Sign in as a player: an atproto service-auth JWT from the player's PDS (com.atproto.server.getServiceAuth) with aud = the game server's DID and lxm = games.cavu.tier-madness.subscribeGame. Spectators don't sign in.",
      "properties": {
        "token": {
          "maxLength": 4096,
          "type": "string"
        }
      },
      "required": [
        "token"
      ],
      "type": "object"
    },
    "create": {
      "description": "Signed in: host a new game. The server replies with #created (the join code, and the hash the host puts in its lobby record).",
      "properties": {
        "initials": {
          "maxLength": 3,
          "minLength": 3,
          "type": "string"
        },
        "totalRounds": {
          "maximum": 20,
          "minimum": 1,
          "type": "integer"
        }
      },
      "required": [
        "initials"
      ],
      "type": "object"
    },
    "double": {
      "description": "Double down on one placed card, or none.",
      "properties": {
        "item": {
          "maxLength": 300,
          "type": "string"
        }
      },
      "type": "object"
    },
    "join": {
      "description": "Signed in: join a game's lobby by its 4-character code (Crockford base32; case and separators don't matter). Attempts are rate limited.",
      "properties": {
        "code": {
          "maxLength": 9,
          "minLength": 4,
          "type": "string"
        },
        "initials": {
          "maxLength": 3,
          "minLength": 3,
          "type": "string"
        }
      },
      "required": [
        "code",
        "initials"
      ],
      "type": "object"
    },
    "kick": {
      "description": "Host only, in the lobby: remove a player.",
      "properties": {
        "did": {
          "format": "did",
          "type": "string"
        }
      },
      "required": [
        "did"
      ],
      "type": "object"
    },
    "leave": {
      "description": "Leave the lobby (before the game starts).",
      "properties": {},
      "type": "object"
    },
    "main": {
      "description": "Frames a client sends up the games.cavu.tier-madness.subscribeGame socket. Intents only: the server validates each, records it in the player's own PDS (secret move + public commitment), and only then applies it.",
      "properties": {
        "frame": {
          "refs": [
            "#auth",
            "#create",
            "#join",
            "#spectate",
            "#leave",
            "#start",
            "#vote",
            "#pickCriteria",
            "#place",
            "#swap",
            "#double",
            "#advance",
            "#kick",
            "#addBot",
            "#setRounds",
            "#skip",
            "#rematch"
          ],
          "type": "union"
        }
      },
      "required": [
        "frame"
      ],
      "type": "object"
    },
    "pickCriteria": {
      "description": "The round's criteria picker chooses one of the offered criteria. Not secret.",
      "properties": {
        "criteria": {
          "maxLength": 300,
          "type": "string"
        }
      },
      "required": [
        "criteria"
      ],
      "type": "object"
    },
    "place": {
      "description": "Place the card dealt at `index` into a tier. Final once accepted; the next card is dealt.",
      "properties": {
        "index": {
          "maximum": 19,
          "minimum": 0,
          "type": "integer"
        },
        "tier": {
          "ref": "games.cavu.tier-madness.defs#tier",
          "type": "ref"
        }
      },
      "required": [
        "index",
        "tier"
      ],
      "type": "object"
    },
    "rematch": {
      "description": "Signed in, at game over: start a rematch with the same table, hosted by whoever asks first (with the same number of rounds, and the bot if there was one). If one's already started, join it. The old game's view points everyone at it (#rematch in gameView).",
      "properties": {},
      "type": "object"
    },
    "setRounds": {
      "description": "Host only, in the lobby: how many rounds the game will have.",
      "properties": {
        "totalRounds": {
          "maximum": 7,
          "minimum": 3,
          "type": "integer"
        }
      },
      "required": [
        "totalRounds"
      ],
      "type": "object"
    },
    "skip": {
      "description": "Host only: stop waiting on stalled players now (as if the deadline passed): unvoted players don't vote, an absent picker's criteria is picked for them, unfinished players sit the round out.",
      "properties": {},
      "type": "object"
    },
    "spectate": {
      "description": "Watch a game by its code, anonymously: no sign-in, and only what anyone may see. Attempts are rate limited.",
      "properties": {
        "code": {
          "maxLength": 9,
          "minLength": 4,
          "type": "string"
        }
      },
      "required": [
        "code"
      ],
      "type": "object"
    },
    "start": {
      "description": "Host only: start the game.",
      "properties": {},
      "type": "object"
    },
    "swap": {
      "description": "The round's one swap: two placed cards in different tiers, or none.",
      "properties": {
        "items": {
          "items": {
            "maxLength": 300,
            "type": "string"
          },
          "maxLength": 2,
          "minLength": 0,
          "type": "array"
        }
      },
      "required": [
        "items"
      ],
      "type": "object"
    },
    "vote": {
      "description": "Secret pre-game vote: up to 3 categories from the ballot.",
      "properties": {
        "categories": {
          "items": {
            "maxLength": 300,
            "type": "string"
          },
          "maxLength": 3,
          "minLength": 1,
          "type": "array"
        }
      },
      "required": [
        "categories"
      ],
      "type": "object"
    }
  },
  "id": "games.cavu.tier-madness.clientFrame",
  "lexicon": 1
}

Validate Record

Validate a record against games.cavu.tier-madness.clientFrame

Validation Options
Automatically resolve and include external schemas for full validation
Treat any remaining unresolved references as valid

Metadata

DID
did:plc:dp7v5b5kejmmzzpwmqyf5wj6
CID
bafyreiepvvdvy37xo62tw4jks7o4fzcoffaydktczq5taxtjbffevg4rzm
Indexed At
2026-10-05 15:12 UTC
AT-URI
at://did:plc:dp7v5b5kejmmzzpwmqyf5wj6/com.atproto.lexicon.schema/games.cavu.tier-madness.clientFrame

Version History (3 versions)

Referenced Schemas (1)

Similar Lexicons

Lexicons whose schemas describe something close to this one. Check them before publishing a new one that overlaps.

  • Frames a client sends up the games.cavu.subscribeSession socket (DAG-CBOR event-stream framing: header {op:1, t:'#join'|'#intent'|'#ping'} + body).

  • A game's live channel. The socket is bidirectional: the client sends games.cavu.tier-madness.clientFrame frames (#auth then #create/#join to play, or just #spectate to watch); the server sends a #snapshot of the game as…

  • An end-of-game superlative and the bonus points it paid.

Lexicon Garden

@