feat(enterprise): add data drains for continuous export to S3 / webhook (#4440)

* feat(enterprise): add data drains for continuous export to S3 / webhook

* chore(data-drains): regenerate migration on top of staging + bump route baseline

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(data-drains): clarify retention pairing is user-coupled, not enforced

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(data-drains): preserve explicit forcePathStyle=false + reserve x-sim-signature

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* test(data-drains): drift guard ensures every webhook header is reserved

Asserts that any header buildHeaders writes is rejected when reused as a
custom signatureHeader. Adding a new metadata header without mirroring it
into RESERVED_SIGNATURE_HEADER_NAMES now fails CI.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Waleed
2026-05-05 18:04:02 -07:00
committed by GitHub
co-authored by Claude Opus 4.7
parent d517415c77
commit d721dc3358
53 changed files with 20179 additions and 11 deletions
+6
View File
@@ -56,6 +56,11 @@ export const auditMock = {
CUSTOM_TOOL_CREATED: 'custom_tool.created',
CUSTOM_TOOL_UPDATED: 'custom_tool.updated',
CUSTOM_TOOL_DELETED: 'custom_tool.deleted',
DATA_DRAIN_CREATED: 'data_drain.created',
DATA_DRAIN_UPDATED: 'data_drain.updated',
DATA_DRAIN_DELETED: 'data_drain.deleted',
DATA_DRAIN_RAN: 'data_drain.ran',
DATA_DRAIN_TESTED: 'data_drain.tested',
CONNECTOR_DOCUMENT_RESTORED: 'connector_document.restored',
CONNECTOR_DOCUMENT_EXCLUDED: 'connector_document.excluded',
DOCUMENT_UPLOADED: 'document.uploaded',
@@ -156,6 +161,7 @@ export const auditMock = {
CREDENTIAL: 'credential',
CREDENTIAL_SET: 'credential_set',
CUSTOM_TOOL: 'custom_tool',
DATA_DRAIN: 'data_drain',
DOCUMENT: 'document',
ENVIRONMENT: 'environment',
FILE: 'file',
+31
View File
@@ -1223,6 +1223,37 @@ export const schemaMock = {
metadata: 'metadata',
createdAt: 'createdAt',
},
dataDrains: {
id: 'id',
organizationId: 'organizationId',
name: 'name',
source: 'source',
destinationType: 'destinationType',
destinationConfig: 'destinationConfig',
destinationCredentials: 'destinationCredentials',
scheduleCadence: 'scheduleCadence',
enabled: 'enabled',
cursor: 'cursor',
lastRunAt: 'lastRunAt',
lastSuccessAt: 'lastSuccessAt',
createdBy: 'createdBy',
createdAt: 'createdAt',
updatedAt: 'updatedAt',
},
dataDrainRuns: {
id: 'id',
drainId: 'drainId',
status: 'status',
trigger: 'trigger',
startedAt: 'startedAt',
finishedAt: 'finishedAt',
rowsExported: 'rowsExported',
bytesWritten: 'bytesWritten',
cursorBefore: 'cursorBefore',
cursorAfter: 'cursorAfter',
error: 'error',
locators: 'locators',
},
/** Custom type export for tsvector */
tsvector: 'tsvector',
}