# Enterprise integration & safe change — working copy

Original LockedIn Labs practice. Synthetic cases only. Python 3.11+, standard library. The lab creates two SQLite databases in a temporary directory and removes them after execution. It makes no network calls and touches no production systems.

Curriculum: https://training.lockedinlabs.ai/training/curriculum?stage=2#integration

Download and inspect the [Python lab](https://training.lockedinlabs.ai/templates/fde-enterprise-integration.py), then run:

```sh
python3 --version
python3 fde-enterprise-integration.py
```

## 1. Map the agreement

Draw a source case service and a receiving work queue. Identify the authoritative record, business ID, operation ID, caller identity, permitted scope, freshness requirement and recovery owner. Choose synchronous, queued or batch exchange. Describe the state shown to the operator if the receiver commits but its acknowledgement is lost.

## 2. Inspect the transaction boundaries

The source transaction updates case-42 and inserts an outbox event together. Its injected failure occurs between those statements. Verify that the status remains `new` and there are zero outbox rows after rollback.

The receiving transaction stores an event identity and creates a task together. Its injected failure occurs before task insertion. Verify that the identity row also rolls back, so a later delivery can still create the task. Explain why inserting the deduplication marker in a separate transaction could lose work.

## 3. Repeat delivery without repeating the effect

The lab delivers event-42 twice. Expect `created`, then `duplicate`, with exactly one receiving task. It then reuses event-42 for case-99; verify the conflict is rejected.

In a copy of the lab, generate a new event ID for every retry and inspect the resulting task count. Explain why this changes the meaning of a retry. Define the key's tenant scope and retention before applying the pattern to a real service. A local outbox and receiver do not prove distributed exactly-once processing, ordering or safe remote side effects.

For an independent experiment, save this as `integration_experiment.py` beside the downloaded lab and run `python3 integration_experiment.py`:

```python
import runpy
import sqlite3
lab = runpy.run_path("fde-enterprise-integration.py")
source = sqlite3.connect(":memory:")
receiver = sqlite3.connect(":memory:")
try:
    lab["prepare"](source, receiver)
    payload = lab["commit_case"](source, "original")
    print(lab["receive"](receiver, "original", payload))
    print(lab["receive"](receiver, "original", payload))
    print(receiver.execute("SELECT count(*) FROM tasks").fetchone()[0])
    print(lab["receive"](receiver, "new-retry-id", payload))
    print(receiver.execute("SELECT count(*) FROM tasks").fetchone()[0])
finally:
    source.close()
    receiver.close()
```

Explain why the counts move from one to two when the operation identity changes, even though the business payload does not.

## 4. Bound retries and replay

Fill a table for invalid payload, denied permission, connection failure, unknown write outcome and overload. For each, record retryability, maximum attempts, elapsed-time budget and next owner. Include backoff, jitter and reconciliation. Define queue-age and capacity limits. Before replay, recheck current authorization, version, expiry and operation identity.

Changed condition: the source permission was revoked while work waited. State why the stored event alone is insufficient authority to execute now.

## 5. Preserve old consumers during migration

The migration adds `owner_display_name` beside `owner_name`, backfills old rows and maintains both on new writes. Inspect old and new reader results. The deliberately broken scenario writes `Queue B` only to the new field, leaving the old reader with `Unassigned`. Explain why an old application image would not repair that semantic incompatibility.

Design a large-table version: bounded batches, restart cursor, safe reruns, concurrent-write handling, lag and lock monitoring, rollback/forward-repair decision. State the evidence required before removing the old column. Do not run this example as a migration against an existing database.

## 6. Receiving review

Packet: interface map, contract with units/errors, operation-key policy, before/after rows, old/new compatibility matrix and reconciliation runbook.

Have a reviewer select duplicate delivery, conflicting payload, old consumer or revoked permission. Predict the result, run the relevant local check and explain the safe next action. Record observed acceptance and unresolved work with owners. Do not describe the synthetic exercise as a partner service guarantee.

References: [HTTP semantics](https://www.rfc-editor.org/rfc/rfc9110.html), [AWS transactional outbox](https://docs.aws.amazon.com/prescriptive-guidance/latest/cloud-design-patterns/transactional-outbox.html), [AWS retries](https://aws.amazon.com/builders-library/timeouts-retries-and-backoff-with-jitter/), [Evolutionary database design](https://martinfowler.com/articles/evodb.html). Checked 2026-10-23.
