Aftershock: From Data Lineage to Governed Operational Recovery
Primary challenge category: Agents That Do Real Work
Project/test URL: https://aftershock.phantombugz.com
Source repository: https://github.com/PhantomBugz/aftershock
Demo video: https://youtu.be/yopSGs_kx5s
Inspiration
Data-quality tools can identify an unreliable dataset, and lineage can show which systems are downstream. But an automated job may already be acting on that data. In the demonstrated scenario, bad pricing has already issued a purchase order. Repairing the table does not cancel it or stop the next one. We call that unresolved operational follow-up Action Debt.
What it does
Aftershock is a deterministic, auditable agent loop built on DataHub:
- Observe: read downstream lineage and entity context through DataHub MCP.
- Decide: resolve structured playbook metadata and require an exact operator grant for the target URN, entity type, business action, and endpoint.
- Act: invoke a bounded compensating control and require a factual terminal receipt rather than inferring success from HTTP alone.
- Persist: write the incident, action receipt, and related assets back to DataHub, then independently read them back.
The demonstrated decision loop is policy-driven, autonomous after its trigger, and reproducible from governed context and policy.
How DataHub is foundational
Aftershock extends DataHub instead of rebuilding its catalog:
get_lineage(upstream=false)discovers downstream exposure.get_entitiesresolves assets plus the governed structured propertiesaftershock.businessActionandaftershock.remediationWebhook.search_documentslocates a verified prior incident record for duplicate-resistant replay.save_documentcreates or updates durable incident memory related to the source dataset and downstream job.- post-write
search_documentsproves the returned document URN and exact title. grep_documentsproves the incident and external receipt IDs were persisted.- a second
get_entitiesread proves both related assets link back to the saved document.
The implementation uses the official mcp-server-datahub==0.6.0 through
FastMCP. Live failures fail closed and never switch to fixture data.
Functioning live demonstration
The primary demo runs against a local DataHub OSS Quickstart v1.6.0 instance
and a built-in loopback-only receiver. The receiver starts with purchase order
PO-AFTERSHOCK-001 already issued and further issuance enabled. Aftershock
reads the seeded lineage and playbook metadata, authorizes exactly one
ISSUE_PO compensation, and sends the cancellation control.
The receiver returns one canonical, PO-bound terminal v1 receipt, changes the
order from issued to canceled, disables further issuance, and increments
apply_count from zero to one. Sequential and concurrent retries resolve to
the same receipt rather than manufacturing additional success. Aftershock then
saves that receipt summary to DataHub and requires all three independent
read-back checks to pass before displaying
LIVE DATAHUB READBACK VERIFIED.
On August 4, 2026, the complete OBSERVE/DECIDE/ACT/PERSIST path succeeded. The
saved record was visible in the local DataHub UI and linked to both the dataset
and DataJob. A separate opt-in live MCP contract test also passed (1 passed).
The deterministic offline suite passed 309 tests with the one live
test skipped only when its explicit opt-in was absent.
The August 5 release hardening passes 320 tests with that same opt-in test
skipped. Two consecutive real MCP runs reused one canonical incident Document,
kept the existing exact-title record count unchanged, and passed all three
read-back gates. The receiver idempotency key and DataHub record key are stable
replay controls, not a claim of globally atomic exactly-once execution.
Receipts, not inferred outcomes
A control succeeds only when the receiver returns the strict terminal contract:
{"receipt_version": 1, "status": "succeeded", "receipt_id": "..."}
Aftershock distinguishes succeeded, accepted, failed, skipped, and
outcome_unknown. HTTP 202 is nonterminal unless its body carries a valid v1
terminal receipt. Ambiguous timeouts and 5xx responses remain unknown unless a
valid terminal receipt proves the outcome. A stable
idempotency key supports safe receiver-side replay, while bounded concurrency,
a workflow deadline, disabled redirects, and a 64 KiB response limit constrain
execution.
Overall completion requires every discovered target to succeed and the DataHub write-back to succeed.
Why it is different
Most lineage tools stop at “what might be affected?” Aftershock turns governed catalog context into a bounded operational response and returns the evidence to the catalog. Action Debt names the real-world gap between finding unreliable data and settling the downstream actions it already triggered.
The purchase-order scenario makes that value concrete: a bad pricing feed can be discovered in DataHub, the exposed ordering job can be identified, an already-issued order can be canceled, further issuance can be stopped through an exact grant, and the resulting PO-bound receipt can be preserved for the next operator or agent.
Challenges we ran into
The hardest part was proving outcomes instead of inferring them. An HTTP
success code does not prove that a business action finished, and retries can
create duplicate controls or incident records. We therefore defined a terminal
receipt contract, treated ambiguous timeouts and 5xx responses as
outcome_unknown, enforced exact remediation grants, and added
duplicate-resistant DataHub write-back with independent read-back checks.
What we learned
DataHub becomes more than a catalog when an agent can use it as both governed context and durable memory. Lineage and structured properties can constrain what the agent is allowed to do; writing verified receipts back gives the next operator or agent evidence of what actually happened. We also learned that stable idempotency keys make retries safer but do not prove globally atomic exactly-once execution, so Aftershock states that boundary explicitly.
Technical execution and safety
- Exact immutable grants bind asset, entity type, business action, and endpoint.
- Plain HTTP is permitted only on loopback; nonloopback controls require HTTPS.
- User information and fragments are rejected and redirects are disabled.
- The receiver exposes an observable before/after state and deterministic replay behavior.
- Distinct sequential or concurrent retry keys return the one canonical cancellation receipt; retarget attempts fail.
- MCP payloads and document read-back are strictly validated and deadline-bound.
- Credentials never belong in DataHub properties, URLs, screenshots, or proof transcripts.
DataHub RBAC, production receiver authentication, and infrastructure egress policy remain operator responsibilities.
Current boundary and next step
The FastAPI endpoint begins after an authenticated, normalized incident trigger.
A production deployment would translate a DataHub incidentInfo
MetadataChangeLogEvent through a custom DataHub Action; that adapter is future
integration work.
The MVP proves system-level exposure and compensating-control receipts, not row-level causality. The proposed Action-Provenance Ledger would add stable action IDs, incident windows, and coverage evidence for more selective recovery.
Built with
Python 3.12, DataHub OSS, DataHub MCP Server, FastMCP, FastAPI, HTTPX, Rich, and pytest. The project is open source under Apache License 2.0.
AI-assistance disclosure
Standard AI coding assistants were used during development to help scaffold, test, review, and document the project. The project concept, acceptance criteria, architecture decisions, and submission decisions remain under human direction and review.
Built With
- datahub-mcp-server
- datahub-oss
- fastapi
- fastmcp
- httpx
- pytest
- python
- rich
Log in or sign up for Devpost to join the conversation.