Appearance
Character and encounter commands
Character and encounter requests use the public command bridge. These readonly SDK DTOs describe retained requests; they do not import domain records, database drivers or private encounter bindings.
The adapter forwards the exact envelope with its original campaign or table:
ts
import type {
CharacterCommandEnvelope,
CharacterCommandRequest,
EncounterCommandEnvelope,
EncounterCommandRequest,
} from '@talerook/sdk';
export function characterRequest(
campaignId: string,
command: CharacterCommandEnvelope,
): CharacterCommandRequest {
return { type: 'character.command', payload: { campaignId, command } };
}
export function encounterRequest(
tableId: string,
command: EncounterCommandEnvelope,
): EncounterCommandRequest {
return { type: 'encounter.command', payload: { tableId, command } };
}A command contribution passes that request to CommandContext.dispatch. Preserve the command ID, routing identity, revisions and body on an uncertain retry. Do not rebuild the target from a newly selected character, table or scene.
Character envelope
Every CharacterCommandEnvelope has commandId and intent. Updates require expectedVersion, the character record revision; creation has no expected version.
| Intent | Fields in addition to type |
|---|---|
character.create | kind: 'character' | 'creature', name, source |
character.details.set | characterId, name, source |
character.portrait.set | characterId, assetId: string | null |
character.access.set | characterId, accountId, level: 'observer' | 'owner' | null |
source is JsonValue owned and validated by the selected system. The generic host does not invent a character schema or derive authority from that JSON. Portrait and access nulls clear their respective binding or grant.
Encounter envelope
EncounterCommandEnvelope supports two exact intents:
encounter.attack.declarehascommandIdand an intent containingactionId,sceneId,sourceTokenId,targetTokenId,attackId,expectedSourcePlacementId,expectedTargetPlacementId,expectedSourceRevision,expectedAssignmentRevisionandexpectedStateRevision. It has noexpectedVersionfield.encounter.damage.applyhascommandId,expectedVersion(the action revision), and intent fieldsactionIdandexpectedStateRevision.
Placement IDs are opaque guards captured from an authorized projection. They prevent a replacement piece from inheriting an old action; they are not private character/source bindings or a grant of control. The server resolves current authority, rules, dice and effects. No caller-selected hit, damage result or private binding DTO is part of these requests.
These contracts do not define a character-placement command. A placement workflow must use its separately agreed retained table/scene contract. As with all rich UI requests, local cancellation does not prove an already admitted server write rolled back.