Liking cljdoc? Tell your friends :D

game.protocols.avatar

Avatar Protocol — each player owns and drives a rich avatar persona (persona fields, a generated portrait, and a public profile) as a first-class game capability.

The protocol is PROVIDER-AGNOSTIC. It owns the :avatar game-state and the event contract, but never talks to an avatar service directly. A command validates, records the player's local mirror as :pending, and emits a provider-neutral :avatar/* effect. The GM-side interceptor (game.handlers/execute-avatar-effects) resolves the configured provider (see game.protocols.avatar-provider; Yvatar is the first implementation), runs the call holding the service credentials, and folds the normalized result back into this protocol via the avatar/succeeded / avatar/failed system callbacks — the exact analog of coseller's ledger-settlement callbacks.

Player↔avatar mapping is automatic: the interceptor passes provider = game-name, external-user-id = player-name, so each player owns exactly one avatar per game with no extra input. No provider name appears anywhere in this namespace or its state — a second provider needs zero changes here.

Avatar Protocol — each player owns and drives a rich avatar persona (persona
fields, a generated portrait, and a public profile) as a first-class game
capability.

The protocol is PROVIDER-AGNOSTIC. It owns the `:avatar` game-state and the
event contract, but never talks to an avatar service directly. A command
validates, records the player's local mirror as `:pending`, and emits a
provider-neutral `:avatar/*` effect. The GM-side interceptor
(`game.handlers/execute-avatar-effects`) resolves the configured provider (see
`game.protocols.avatar-provider`; Yvatar is the first implementation), runs the
call holding the service credentials, and folds the normalized result back into
this protocol via the `avatar/succeeded` / `avatar/failed` system callbacks —
the exact analog of coseller's ledger-settlement callbacks.

Player↔avatar mapping is automatic: the interceptor passes `provider =
game-name`, `external-user-id = player-name`, so each player owns exactly one
avatar per game with no extra input. No provider name appears anywhere in this
namespace or its state — a second provider needs zero changes here.
raw docstring

game.protocols.avatar-provider

Provider seam for the Avatar Protocol.

The Avatar Protocol (game.protocols.avatar) is provider-agnostic: it owns the game-state and the event contract, but never talks to an avatar service directly. Every outbound call goes through this AvatarProvider seam, and the GM-side interceptor (game.handlers) resolves the configured implementation and runs it (holding the service credentials — the withdrawal/Stripe "key locality" pattern). Yvatar is the first implementation (game.protocols.providers.yvatar); adding another provider later means a new defrecord + a factory case, and nothing in the protocol layer changes.

Context map

Every method takes a provider-neutral ctx: {:provider <string> ; e.g. the game-name — maps to Yvatar external_provider :external-user-id <string>} ; e.g. the player-name — maps to Yvatar external_user_id

Normalized result

Every method returns ONE of: {:ok? true :avatar {:avatar-id :public-handle :portrait-url :pending-portrait-url :public-url :name :status ;; draft-post / regenerate-post / fetch-post-status ;; also return: :post-id :post-status :prompt :caption :preview-url ;; confirm-publish also returns: :platform :post-url :platform-post-id ...}} {:ok? false :status <int|keyword> :error <any>} The :avatar map is already provider-neutral (kebab-case keys); the protocol layer and interceptor only ever see this shape, never provider-specific JSON.

Provider seam for the Avatar Protocol.

The Avatar Protocol (`game.protocols.avatar`) is provider-agnostic: it owns the
game-state and the event contract, but never talks to an avatar service
directly. Every outbound call goes through this `AvatarProvider` seam, and the
GM-side interceptor (`game.handlers`) resolves the configured implementation and
runs it (holding the service credentials — the withdrawal/Stripe "key locality"
pattern). Yvatar is the first implementation
(`game.protocols.providers.yvatar`); adding another provider later means a new
`defrecord` + a factory case, and nothing in the protocol layer changes.

## Context map
Every method takes a provider-neutral `ctx`:
  {:provider         <string>   ; e.g. the game-name — maps to Yvatar external_provider
   :external-user-id <string>}  ; e.g. the player-name — maps to Yvatar external_user_id

## Normalized result
Every method returns ONE of:
  {:ok? true  :avatar {:avatar-id :public-handle :portrait-url
                       :pending-portrait-url :public-url :name :status
                       ;; draft-post / regenerate-post / fetch-post-status
                       ;; also return:
                       :post-id :post-status :prompt :caption :preview-url
                       ;; confirm-publish also returns:
                       :platform :post-url :platform-post-id ...}}
  {:ok? false :status <int|keyword> :error <any>}
The `:avatar` map is already provider-neutral (kebab-case keys); the protocol
layer and interceptor only ever see this shape, never provider-specific JSON.
raw docstring

game.protocols.coseller

Coseller Protocol — a referral economy layered on top of Market.

Authorized players (:coseller role) share trackable URLs to game assets (a Market capability, or an external website/app). A buyer's clicks become touches. When the GM settles a paid checkout, a GM-configured portion of each order's existing Market commission becomes a coseller pool, which is distributed across the buyer's chain-of-influence via a pluggable attribution algorithm (see game.protocols.coseller-attribution).

Coseller is a pure distribution layer: it never changes the buyer's price or the seller's net. It reads Market orders/checkouts from the shared game-state and writes only its own :coseller namespace. Settlement is a manual, idempotent GM command — no auto-fire on payment.

Coseller Protocol — a referral economy layered on top of Market.

Authorized players (`:coseller` role) share trackable URLs to game assets
(a Market capability, or an external website/app). A buyer's clicks become
`touches`. When the GM settles a paid checkout, a GM-configured *portion* of
each order's existing Market commission becomes a `coseller pool`, which is
distributed across the buyer's chain-of-influence via a pluggable attribution
algorithm (see `game.protocols.coseller-attribution`).

Coseller is a pure distribution layer: it never changes the buyer's price or
the seller's net. It reads Market orders/checkouts from the shared game-state
and writes only its own `:coseller` namespace. Settlement is a manual,
idempotent GM command — no auto-fire on payment.
raw docstring

game.protocols.coseller-attribution

Pluggable chain-of-influence attribution for the Coseller Protocol.

weigh-chain is a multimethod dispatched on the algorithm name (a string). It turns a buyer's touches into an ordered chain of cosellers with relative weights. allocate then distributes an integer pool across those weights using the largest-remainder method so the splits always sum exactly to the pool — no rounding drift, no minted or lost units.

Adding a new attribution model = one new defmethod weigh-chain plus a new value the GM may set as :algorithm on the policy. Nothing else changes.

Pluggable chain-of-influence attribution for the Coseller Protocol.

`weigh-chain` is a multimethod dispatched on the algorithm name (a string).
It turns a buyer's touches into an ordered chain of cosellers with relative
weights. `allocate` then distributes an integer pool across those weights
using the largest-remainder method so the splits always sum exactly to the
pool — no rounding drift, no minted or lost units.

Adding a new attribution model = one new `defmethod weigh-chain` plus a new
value the GM may set as `:algorithm` on the policy. Nothing else changes.
raw docstring

game.protocols.discoverability

Public discovery from a trusted GM adapter; no I/O or model calls. :discoverability/context is supplied by the GM, never by event/data.

Public discovery from a trusted GM adapter; no I/O or model calls.
:discoverability/context is supplied by the GM, never by event/data.
raw docstring

game.protocols.market

game.protocols.market-authority

The Market authority bridge: the seam where a Mandate becomes commercially load-bearing.

Market assumes a seller owns what they sell. Mandate answers the earlier question — why is this representative allowed to act for this principal, for this subject, within these limits? This namespace joins them at the moment a representative acts: a CLAIM in the event data, a VERIFICATION against live Mandate state in the same transition, and a durable RECORD of the verdict.

It lives apart from market.clj so that a 6,000-line namespace running in production gains only a require and four small call sites.

Two things it deliberately is not:

  • An explicit Mandate claim requires a canonical MoM caller matching the Market actor. Unclaimed self-owned Market paths still need their own caller and inventory ownership policy before a Game exposes them.
  • It does NOT route money. A represented sale still pays the representative.

Market writes only {:market ...}; nothing here ever writes Mandate state.

The Market authority bridge: the seam where a Mandate becomes commercially
load-bearing.

Market assumes a seller owns what they sell. Mandate answers the earlier
question — why is this representative allowed to act for this principal, for
this subject, within these limits? This namespace joins them at the moment a
representative acts: a CLAIM in the event data, a VERIFICATION against live
Mandate state in the same transition, and a durable RECORD of the verdict.

It lives apart from `market.clj` so that a 6,000-line namespace running in
production gains only a require and four small call sites.

Two things it deliberately is not:

- An explicit Mandate claim requires a canonical MoM caller matching the
  Market actor. Unclaimed self-owned Market paths still need their own
  caller and inventory ownership policy before a Game exposes them.
- It does NOT route money. A represented sale still pays the representative.

Market writes only `{:market ...}`; nothing here ever writes Mandate state.
raw docstring

game.protocols.market-quote-proof

Authenticates Woo quotes recorded through MoM's legacy action route.

Authenticates Woo quotes recorded through MoM's legacy action route.
raw docstring

game.protocols.providers.yvatar

Yvatar implementation of the AvatarProvider seam.

This is the ONLY place that knows the Yvatar Developer Platform API — its endpoints, its snake_case JSON, and its error codes. It maps the protocol's provider-neutral ctx/persona to Yvatar's external_provider / external_user_id mapping and back to the normalized result documented in game.protocols.avatar-provider.

Endpoints (all under /api/v1/platform/users/:external-user-id/yvatar): PUT . upsert persona GET . fetch full persona POST ./portrait generate a pending portrait POST ./portrait/accept promote pending -> accepted GET ./public embed-safe public shape POST ./content start a video post (async — returns generating_video) GET ./content check the pending post's status (on-demand, not a poll loop) POST ./content/regenerate redraft the current pending post (async) POST ./content/publish publish the current draft post to a platform

The ./content* endpoints are video-only — Yvatar's Platform API does not support image posts (the content studio's session-authenticated UI does, but that surface is not exposed here). Video generation is asynchronous: POST ./content and POST ./content/regenerate return immediately with status "generating_video"; GET ./content is how a caller checks whether it finished, intended for a caller-side "refresh" action rather than a background polling loop.

Auth: Authorization: Bearer <yvtr_ token> (developer-owned token).

Yvatar implementation of the `AvatarProvider` seam.

This is the ONLY place that knows the Yvatar Developer Platform API — its
endpoints, its snake_case JSON, and its error codes. It maps the protocol's
provider-neutral `ctx`/persona to Yvatar's `external_provider` /
`external_user_id` mapping and back to the normalized result documented in
`game.protocols.avatar-provider`.

Endpoints (all under /api/v1/platform/users/:external-user-id/yvatar):
  PUT    .              upsert persona
  GET    .              fetch full persona
  POST   ./portrait     generate a pending portrait
  POST   ./portrait/accept  promote pending -> accepted
  GET    ./public       embed-safe public shape
  POST   ./content              start a video post (async — returns generating_video)
  GET    ./content              check the pending post's status (on-demand, not a poll loop)
  POST   ./content/regenerate   redraft the current pending post (async)
  POST   ./content/publish      publish the current draft post to a platform

The ./content* endpoints are video-only — Yvatar's Platform API does not
support image posts (the content studio's session-authenticated UI does, but
that surface is not exposed here). Video generation is asynchronous: POST
./content and POST ./content/regenerate return immediately with
status "generating_video"; GET ./content is how a caller checks whether it
finished, intended for a caller-side "refresh" action rather than a
background polling loop.

Auth: `Authorization: Bearer <yvtr_ token>` (developer-owned token).
raw docstring

game.protocols.scope

Reusable discovery and response scope for request-shaped protocols.

Reusable discovery and response scope for request-shaped protocols.
raw docstring

game.protocols.withdrawal

Withdrawal Protocol — lets a player move their shadow-ledger balance out of the game to their own bank via Stripe Connect.

The GM never talks to Stripe; it only produces the atomic ledger moves as MoM ledger/batch effects (so they run under the game's GM authority, never a direct ledger HTTP call). The actual Stripe Transfer is performed by the game's HTTP layer (game.payments) between the reserve and settle steps:

request -> ledger/batch player -> @withdrawals-pending (game.payments calls Stripe create-transfer) settle -> ledger/batch @withdrawals-pending -> @withdrawals-paid (success) reverse -> ledger/batch @withdrawals-pending -> player (failure)

A single withdrawal-id (minted by game.payments) keys the reserve ledger move and the Stripe Idempotency-Key; settle/reverse derive :settle/:reverse suffixed keys so replays are exactly-once. Records live in game-state under :withdrawal :records and are advanced by MoM's on-success callbacks.

Withdrawal Protocol — lets a player move their shadow-ledger balance out of the
game to their own bank via Stripe Connect.

The GM never talks to Stripe; it only produces the atomic ledger moves as MoM
`ledger/batch` effects (so they run under the game's GM authority, never a
direct ledger HTTP call). The actual Stripe Transfer is performed by the game's
HTTP layer (game.payments) between the reserve and settle steps:

  request  -> ledger/batch  player            -> @withdrawals-pending
  (game.payments calls Stripe create-transfer)
  settle   -> ledger/batch  @withdrawals-pending -> @withdrawals-paid   (success)
  reverse  -> ledger/batch  @withdrawals-pending -> player              (failure)

A single `withdrawal-id` (minted by game.payments) keys the reserve ledger
move and the Stripe Idempotency-Key; settle/reverse derive `:settle`/`:reverse`
suffixed keys so replays are exactly-once. Records live in game-state under
`:withdrawal :records` and are advanced by MoM's on-success callbacks.
raw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
←Move to previous article
→Move to next article
Ctrl+/Jump to the search field
× close