Schemas Declarativos & Isolamento de Dados
1. Princípio da Imutabilidade do Núcleo
No Adventure Keeper, o núcleo operacional do Game Master (título da campanha, número da sessão, editor de texto narrativo TipTap, nomes e notas canônicas de entidades) nunca pode ser modificado ou sobrescrito por um módulo.
Isso significa que:
- O módulo não altera as colunas nativas das tabelas principais (
entities,campaigns,sessions). - Todos os dados providos por módulos são armazenados em tabelas de extensão dedicadas:
entity_module_data: indexada pela chave composta(entity_id, module_id).campaign_module_data: indexada pela chave composta(campaign_id, module_id).
2. Definindo um Schema JSON
Cada extensão referenciada no manifesto module.json aponta para um arquivo JSON Schema válido (Draft-07 ou Draft 2020-12).
Exemplo: schemas/character-stats.json
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Pathfinder 2e Character Stats",
"type": "object",
"properties": {
"level": {
"type": "integer",
"minimum": 1,
"maximum": 20,
"title": "pf2e.fields.level"
},
"attributes": {
"type": "object",
"properties": {
"strength": { "type": "integer", "default": 10 },
"dexterity": { "type": "integer", "default": 10 },
"constitution": { "type": "integer", "default": 10 },
"intelligence": { "type": "integer", "default": 10 },
"wisdom": { "type": "integer", "default": 10 },
"charisma": { "type": "integer", "default": 10 }
},
"required": ["strength", "dexterity", "constitution", "intelligence", "wisdom", "charisma"]
},
"hitPoints": {
"type": "object",
"properties": {
"current": { "type": "integer", "minimum": 0 },
"max": { "type": "integer", "minimum": 1 }
},
"required": ["current", "max"]
}
},
"required": ["level", "attributes", "hitPoints"],
"additionalProperties": false
}
3. Validação no Backend
Antes de persistir qualquer informação submetida por um módulo na tabela entity_module_data, o backend do Adventure Keeper executa duas camadas de verificação:
- Validação Estrutural: O payload deve satisfazer estritamente o JSON Schema compilado do módulo.
- Prevenção de Colisão: O valor de
module_idé verificado contra a lista de módulos ativos na campanha. Nenhum módulo pode ler ou gravar em registros que pertençam a outromodule_id.
4. Slots de Renderização na Interface
Os dados do módulo são renderizados automaticamente em abas ou cartões secundários na tela de detalhes da entidade (/campaigns/:id/entities/:entityId), sem poluir ou interferir no diário narrativo da sessão.