Status: Normative procedure. Owner-gated — this is a coordinated cross-tool release, not a self-service migration. Do not fire it unilaterally; it is scheduled by the suite owner once Filigree and Wardline are ready to cut at the same time.
Authority: Weft SEI conformance standard §7 / §7.1; Loomweave ADR-038.
The Weft suite is moving every cross-tool binding off the mutable locator
({plugin}:{kind}:{qualname}) and onto the durable, opaque SEI
(loomweave:eid:<hex>). Before the cutover, producers store and emit locators;
after it, they store and emit SEIs. There is deliberately no mixed-format
window — a single hard cutover, because one owner controls all four release
cycles (§7.1). A feed that emitted a mix of locators and SEIs would be
uninterpretable, since every consumer treats the id as opaque.
| Subsystem | Role in the cutover |
|---|---|
| Loomweave (authority) | Mints an SEI for every current entity on its first SEI-aware analyze run, and serves resolve(locator) so producers can re-key. This is the only Loomweave action — it has no cross-tool bindings of its own to re-key. |
| Filigree | Re-keys every stored loomweave_entity_id association from its locator to the resolved SEI. |
| Wardline | Re-keys every stored taint fact (and dossier handle) from its locator to the resolved SEI. |
| legis (when present) | Re-keys governance attestations onto SEIs. |
- Mint-all-on-first-run. The analyze SEI mint pass (ADR-038 §3) mints an
alivesei_bindingsrow for every current entity on the first SEI-aware run, and carries (never re-mints) them on every subsequent unchanged run. No separate "backfill job" is needed on Loomweave's side — minting is the first-run behaviour, and it is idempotent (a re-run carries every SEI; proven byanalyze_carries_sei_on_unchanged_rerun). - Resolution surface.
POST /api/v1/identity/resolvemaps a locator to its alive SEI. Producers drive their re-key off this endpoint. - Reserved-prefix rejection (REQ-F-02) — the safety interlock.
resolverejects any SEI-shaped input (reservedloomweave:eid:prefix) with400. This is what makes each producer's backfill idempotent and resumable: an already-migrated row whose value is now an SEI is rejected, never mis-resolved, so re-running a partially-completed backfill is safe.
Each producer owns its own progress cursor (a rowid or a migration-state side table). No Loomweave-side generation marker is required.
For each stored binding the producer holds:
- Read the stored id. If it already begins with
loomweave:eid:, it is already migrated — skip (this is why the backfill is resumable). - Call
POST /api/v1/identity/resolve(or…/resolve:batch) with the locator. - On
{ alive: true, sei }→ rewrite the stored id tosei, advance the cursor. - On
{ alive: false }→ the locator no longer resolves (already orphaned by a past rename). Flag it ORPHAN for human review — never silently drop it (the suite's no-false-green ethos, §7). - On
400(REQ-F-02 rejection) → the value was already an SEI; treat as already-migrated and skip.
A backfill that fails partway is simply re-run: already-migrated rows are skipped (step 1 / step 5), so it converges.
- Freeze. Quiesce writes across the producers being cut.
- Loomweave cuts first. Deploy SEI-aware Loomweave and run analyze so every
entity has an alive SEI (verify via
_capabilities.sei.supported: trueand a non-emptysei_bindings). - Producers backfill their stored ids locator→SEI (protocol above), each to completion, surfacing ORPHANs.
- Flip the feeds. Every federation feed that carries entity ids
(e.g. Filigree's
affected_entitiesonGET /api/weft/changes) switches to emitting only SEIs — never a mix. - Unfreeze. Resume writes; from here all new bindings key on SEIs.
- Conformance: the shared SEI oracle
(
fixtures/sei-conformance-oracle.json) must pass for each subsystem before it is declared conformant (no grandfathering). Loomweave's pass:cargo test -p loomweave-storage --test sei_conformance_oracle. - Idempotency / resumability rests entirely on the REQ-F-02 rejection contract; do not relax it.
- Rollback is a coordinated re-deploy of the prior producer builds; because the backfill rewrites ids in place, a rollback that needs the original locators must restore from the pre-cutover backup taken at step 1. Take that backup.
This procedure is surfaced for owner scheduling, not executed here. It runs
only when Filigree and Wardline are both ready to cut in the same release. Until
then Loomweave mints and serves SEIs additively (enrich-only); consumers that have
not yet cut keep working on locators and degrade on _capabilities.sei.