Skip to content

JITSU-181: export integration tests + zod output validation for admin config exports - #1478

Merged
absorbb merged 2 commits into
newjitsufrom
ildar/jitsu-181-export-tests-zod-output
Aug 24, 2026
Merged

JITSU-181: export integration tests + zod output validation for admin config exports#1478
absorbb merged 2 commits into
newjitsufrom
ildar/jitsu-181-export-tests-zod-output

Conversation

@absorbb

@absorbb absorbb commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Covers postmortem action items 4 and 5 of JITSU-158 (prevent). Linear: JITSU-181

Output validation (item 5)

  • New lib/schema/export-contracts.ts: per-variant consumer contracts (BulkerConnectionRow, BackupConnectionRow, RotorConnectionRow, RotorDestinationRow), enforced at every write site of bulker-connections / rotor-connections before a row reaches the response stream. A violating row is skipped-and-logged with the System error: alerting marker — never shipped malformed. The previously-verbatim otlp and ee-api backup rows are validated too.
  • parseLinkData now rejects corrupt (non-object/array) stored roots outright, so the incident shape can't collapse to {}-options in any export that uses it (incl. streams-with-destinations, where a corrupt link now drops only itself — never the stream row, which would have cut off the site's ingest routing).
  • Contract deliberately tolerates two legacy prod realities so day-one enforcement changes nothing that currently ships (verified against live prod exports: 0 violations in 5,984 bulker + 6,539 rotor rows): empty streamId (one legacy row) and nullable destinationId (profile builders).

Integration tests (item 4)

__tests__/integration/admin-exports.test.ts against seeded testcontainers Postgres, covering the incident shapes: null-data link, {} link (both materialize destination-schema defaults, frequency correctly absent), wrong-typed fields (tolerant fallback ships stored fields as-is), full round-trip (stored options + materialized defaults), corrupt-root rows skipped-and-logged end-to-end in both connection exports, stream row survival with a corrupt link, and contract-level rejection of the {data_}-typo regression shape.

🤖 Generated with Claude Code

absorbb and others added 2 commits August 24, 2026 15:53
…exports

Every bulker-connections / rotor-connections row is validated against its
consumer contract before it reaches the response stream; a violating row is
skipped-and-logged with the System error marker instead of shipping
malformed. Integration tests cover the JITSU-158 incident shapes against a
seeded testcontainers Postgres.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…link guard in streams export, redact backup log, relax destinationId

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@jitsu-code-review jitsu-code-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the changes in , , and the new integration coverage in .

I focused on correctness, regression risk, and failure-path behavior around export row materialization/validation and per-entity error handling. I did not find actionable bugs, security issues, or user-visible regressions in this patch.

@jitsu-code-review jitsu-code-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the changes in webapps/console/pages/api/admin/export/[name]/index.ts, webapps/console/lib/schema/export-contracts.ts, and the new integration coverage in webapps/console/tests/integration/admin-exports.test.ts.

I focused on correctness, regression risk, and failure-path behavior around export row materialization/validation and per-entity error handling. I did not find actionable bugs, security issues, or user-visible regressions in this patch.

@absorbb absorbb added canary:console Build per-PR canary console image (deployed at pr<N>.use.jitsu.com) deploy:console Auto-deploy console to beta when this PR merges (JITSU-68) labels Aug 24, 2026
@absorbb
absorbb merged commit f7cb892 into newjitsu Aug 24, 2026
13 checks passed
@absorbb
absorbb deleted the ildar/jitsu-181-export-tests-zod-output branch August 24, 2026 13:42
@github-actions

Copy link
Copy Markdown
Contributor

🚀 deploy:console label detected — triggered a beta console deployment to jitsu-cloud-infra. Track it in the deploy runs (newest at top): https://github.com/jitsucom/jitsu-cloud-infra/actions/workflows/deploy.yaml?query=event%3Aworkflow_dispatch

absorbb added a commit that referenced this pull request Aug 24, 2026
…order (#1480)

Follow-up to the config-keeper circuit breaker (#1476), from today's
prod field experience. Linear: `JITSU-182`.

## Why
Within hours of the breaker going live, #1478's deploy reordered JSON
keys in every export row (zod `parse` emits schema keys first). Content
was byte-for-byte identical after key normalization — but the breaker
hashes raw row bytes, so it read 100% mass change and tripped fleet-wide
on both replicas (correctly per its design, but the "serializer changes
are rare" trade-off documented in the code did not survive day one). The
breaker is currently disabled in prod pending this fix — all repos must
survive field reorders.

## What
- `hashRows` now hashes each row **canonically**: object keys sorted,
',' separator + length-prefixed keys (uniquely decodable — an
encoding-collision construction from review is closed), type-tagged
values, numbers by literal via `json.Number` (no float64 precision
loss), decoder-normalized string escapes.
- Key-order changes at any nesting depth are invisible to the breaker;
real value changes still trip. Number-literal formatting changes (`1` vs
`1.0`) still trip by design — single stable producer, and that failure
mode is a confirmation, not a miss.
- **No baseline migration needed**: seeding re-hashes the cached payload
with the new function, so deploying this cannot itself trip — even onto
a payload that byte-changed since the cache was written.
- The whole-payload `lastRejected` short-circuit deliberately stays
byte-based (it only suppresses re-parsing of a byte-identical rejected
generation).

Tests: reorder-immunity end-to-end (incl. clearing a held state with a
reordered good payload), collision-resistance of the encoding
(string/number/boundary/precision cases), escape normalization, literal
sensitivity. 25 config-keeper tests green.

After deploy, re-enable with `CFGKPR_BREAKER_ENABLED=true` in
jitsu-cloud-infra.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

canary:console Build per-PR canary console image (deployed at pr<N>.use.jitsu.com) deploy:console Auto-deploy console to beta when this PR merges (JITSU-68)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant