5.0 KiB
Integration -- Interfaces
Module: Integration (Cross-cutting) Tables: 2
Provided Interfaces
Structural: NONE
Neither webhook_events nor integration_outbox is referenced by foreign key from any table in any module. No other module has a structural dependency on the integration module.
Behavioral
While no structural interfaces exist, the integration module provides two behavioral interfaces that other modules consume at runtime:
webhook_events: Sync Pipeline Entry Point
The webhook_events table is the entry point for the inbound sync pipeline that populates projection tables across the system. Under the Stripe strategy (Decision 90), Category B billing tables -- subscriptions, subscription_items, subscription_changes, invoices, invoice_line_items, payments, payment_methods, refunds, disputes, products, prices, coupons, promotion_codes, discounts -- are populated via webhook events processed by Temporal workflows.
Behavioral consumers:
| Module | Relationship | Notes |
|---|---|---|
| billing | Primary consumer. Webhook events drive the sync pipeline that populates Category B projection tables. Temporal workflows read from webhook_events, transform provider objects, and write to core billing tables. |
This is the highest-volume behavioral interface in the system. |
| entitlements | Future consumer. Infrastructure provisioning callbacks (e.g., Nextcloud reporting instance creation complete) arrive as webhook events and update resource_provisions state. |
Not yet active; depends on infrastructure provider integration. |
integration_outbox: Outbound Event Relay
The integration_outbox captures domain state changes from any module that require external action. Any module may write to the outbox within its domain transactions.
Behavioral consumers:
| Module | Relationship | Notes |
|---|---|---|
| All modules | Any module may INSERT into integration_outbox within its domain transaction to trigger external actions. The outbox is a general-purpose relay, not scoped to a specific module. |
Examples: billing writes outbox entries for Stripe product sync; entitlements writes entries for Nextcloud provisioning; organization could write entries for notification delivery. |
Consumed Interfaces
Structural: NONE
Neither webhook_events nor integration_outbox contains a foreign key reference to any table in any module. Both tables use text fields for entity identification:
webhook_events.providerandwebhook_events.provider_event_idare text fields identifying the source provider and its event identifier.integration_outbox.aggregate_typeandintegration_outbox.aggregate_idare a text discriminator and UUID identifying the originating domain entity, with no FK constraint.integration_outbox.target_provideris a text field identifying the destination provider.
This text-based identification follows the same rationale as the audit log's bare polymorphic association on entity references (Decision 23): these tables must accept references to any entity type in the system, and FK constraints would be structurally impractical.
Interface Contracts
Idempotency Guarantee
The UNIQUE(provider, provider_event_id) constraint on webhook_events guarantees that duplicate webhook deliveries are detected at insert time. Consumers of the sync pipeline can rely on this invariant: a given provider event will appear at most once in the table. The webhook endpoint returns HTTP 200 on constraint violation, signaling to the provider that the event was already received.
At-Least-Once Delivery Semantics
The integration_outbox guarantees at-least-once delivery for outbound integration actions. Because the outbox INSERT occurs in the same transaction as the domain state change, any committed domain change will have a corresponding outbox entry. The background polling worker may deliver the same event more than once (e.g., if it crashes after executing the external action but before marking the entry completed). Provider handlers must be idempotent.
Payload PII-Free Invariant
Both webhook_events.payload and integration_outbox.payload are governed by the JSONB Governance Policy (Decision 34): PII is categorically prohibited in all JSONB columns. Webhook payloads containing PII must be scrubbed before storage; outbox payloads must be composed without PII. This invariant enables the integration tables to participate in retention and archival policies without triggering GDPR anonymization obligations.
Isolation Guarantee
The integration module imposes no structural constraints on any other module. No module need consult the integration tables to answer a domain question. The self-sufficiency principle (applied via Decision 87 and the five boundary heuristics) ensures that every business-answerable concept has a domain module representation. The integration module's coupling to other modules is entirely behavioral and unidirectional at the schema level.