[Foundry] foundry_links document-mapping table for idempotent push #146
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Motivation/Context
Every push path in the Foundry pillar — Phase 1 member sync (#8), Phase 2 NPC push (#9), Phase 3 writeback (#14), and live push — needs to know whether a given Quest Board entity has already been pushed to Foundry, so repeated pushes update the existing document instead of spawning duplicates. Today nothing in the codebase tracks this relationship. This is shared plumbing, not specific to any one push feature, and the live-push investigation (2026-07-15) calls it out as a hard prerequisite for "Send to live scene" (its update semantics depend entirely on knowing which Foundry Actor a given
LoreEntryalready maps to).Approach
Add a
foundry_linkstable with columns:campaign_id,lore_entry_id(nullable — also used formember_idfor #8/#14 sync),foundry_document_type(e.g.actor,journal_entry,item),foundry_document_id,last_pushed_at,last_push_hash.Push flow: on any push operation, check for an existing link for
(campaign_id, source_entity, foundry_document_type). If found, call the adapter's update path against the existingfoundry_document_id; if not found, create and record a new link row.last_push_hashlets callers cheaply detect whether the source entity changed since the last push (used later by a future "stale push" indicator for live-push update semantics).On the Foundry side, stamp every pushed document with a module flag —
flags.questboard.entryId— so the mapping can be re-derived if thefoundry_linksrow is lost or the Foundry world is re-imported/restored from backup. This stamping is the module-side half of the idempotency guarantee and should be validated during the same module-testing pass as #143 (connection topology decision).Update semantics (which fields get overwritten on re-push, confirmation requirements, etc.) belong to each specific push feature, not this table — this issue is just the mapping/lookup layer plus the flag-stamping mechanism.
Dependencies
foundry/client.pyHTTP layer to call the module's flag-setting/document APIs.Out of scope
LoreEntry/memberto a document (Actor, JournalEntry, Item), not to a placed token instance on a scene.Acceptance criteria
foundry_linkstable exists with the columns above, scoped per campaign.foundry_document_idfor update, or signals create-and-record.flags.questboard.entryId(or equivalent), verified against the real Foundry instance.sidebar_fields, #130) intonpc_to_actor#148