Files
shopdb-flask/docs/PLUGIN-HOOKS.md
benjamin.baker 2998e35ddf Add reversible Maximo/WINC machine-adoption import
Machine data arrives as a Maximo asset export (validated against the WINC
site) that must update existing machines in place, not create canonical
per-table rows, so it does not fit the ShopDB-native/Azure/Thor CSV adapter
path. Bulk edits to live machines also need an escape hatch, so the whole
commit is journaled and can be undone as one batch.

Add a dedicated dry-run analyzer, approval packet, resolver/suggest helpers,
and a reversible writer/undo backed by a new importbatches/importjournalentries
schema (with migration). Expose preview/commit/batches/undo settings routes and
a matching frontend source card and panel, and surface the batch/journal
contract through shopdb.api for plugins.
2026-09-03 05:04:22 -04:00

2.2 KiB

Plugin hooks and contract surface

Everything a plugin may import from the core lives in shopdb.api (ADR-001), versioned by __contract_version__ (ADR-002). Adding a name is a minor bump; removing one is major. This file records the non-obvious hooks - the ones a plugin author would not guess from the name alone. It is not the full export list; read shopdb/api/__init__.py for that.

Reversible bulk-import journal

Contract version 0.30.0.

A plugin that drives a bulk import - a site asset adoption, an integration sync - records the primitive changes it makes so the whole batch can be reversed later. The journal is import-agnostic: it stores primitive mutations (set a cell, insert a row) tied to a batch id, and a generic undo replays them in reverse. Nothing in core learns what the import means.

Exposed on shopdb.api:

  • ImportBatch - one row per applied import. batchid is the identity that the approval step, the write, and the undo all reference. status is applied or undone.
  • ImportJournalEntry - one reversible primitive mutation. operation is update (a cell change, carrying oldvalue/newvalue so it can be put back) or insert (a row this batch created, so undo can delete strictly what the import created).
  • BATCH_APPLIED, BATCH_UNDONE - the two ImportBatch.status values.
  • OP_UPDATE, OP_INSERT - the two ImportJournalEntry.operation values.

What a plugin gets from this, and what it does NOT:

  • A plugin's import UI reads ImportBatch to list applied batches (kind, row count, who applied it, when) and offers an "Undo import" per batch.
  • A plugin does NOT write the journal or run undo through these model imports. The write/undo logic lives with the import writer (see scripts/site_imports/journal.py), which records entries in the SAME transaction as the mutation they describe and reverses them conservatively: an update is put back only if the cell still holds the value the import wrote (a value a human changed since is left as-is and reported), and an insert is hard-deleted only when nothing outside the batch still references the created row.

The tables are core-owned (migration 7d37_import_batches_and_journal), so they exist regardless of which plugins are installed.