Skip to content

chore: merge main into dev (reconcile)#55

Closed
ottobot-ai wants to merge 8 commits into
Constellation-Labs:devfrom
ottobot-ai:chore/merge-main-into-dev
Closed

chore: merge main into dev (reconcile)#55
ottobot-ai wants to merge 8 commits into
Constellation-Labs:devfrom
ottobot-ai:chore/merge-main-into-dev

Conversation

@ottobot-ai

Copy link
Copy Markdown
Contributor

Summary

Reconcile maindev so dev is the complete release branch. The merge is clean — no conflicts (Dependencies.scala is identical on both; both are on tessellation 4.0.0, and dev already contains main's substantive fixes — null-drop-before-canonicalize and the JSON depth limit — by content).

What main uniquely brings: the PR template, CODEOWNERS, and the sbt 1.8.0 → 1.9.8 bump (plus the historical tessellation 3.5.x chores, already superseded by 4.0.0 on both).

Mostly this establishes the ancestry so main and dev stay reconciled going into the v1.8.0-rc.6 tag.

⚠️ Merge method

Merge with a merge commit (not squash) — this PR is a real merge (two parents); squashing would re-introduce the divergence. CI will verify the build/tests.

🤖 Generated with Claude Code

scasplte2 and others added 8 commits November 4, 2025 11:20
When Circe encodes case classes with Option[T] fields set to None,
it produces null values in the JSON. These nulls were being preserved
during canonicalization, causing signature verification to fail when
the sender omitted the optional field entirely.

This change filters out null values from JSON objects before
canonicalization in JsonBinaryCodec, ensuring that:

1. Option[T] = None produces the same canonical form as omitted field
2. Signature hashes match between sender (field omitted) and receiver
   (field decoded as None then re-encoded)

This matches the behavior of TypeScript's JSON serialization which
typically omits undefined/null fields.

Added tests to verify:
- Null values are dropped from serialization
- Round-trip works correctly with Option fields
- None produces same bytes as omitted field (signature compatibility)
- Replace deprecated mapValues with collect pattern (single-pass)
- Add note about array null preservation to scaladoc
- Add TestDataUpdateComplex model with Option field
- Add tests for DataUpdate codec null-dropping behavior
- Add test for DataUpdate round-trip with Option fields

Code review by: OttoThink agent
Adds protection against stack overflow attacks from deeply nested JSON:

- MaxDepthExceededException for when depth limit exceeded
- DefaultMaxDepth = 64 (configurable via deriveWithMaxDepth)
- jsonDepth() uses tail-recursive traversal (scalafix-compliant)
- validateDepth() checks depth before decoding to case classes
- deriveWithMaxDepth() and deriveDataUpdateWithMaxDepth() for custom limits
- 6 new tests covering depth limit enforcement

This addresses the code review concern about stack safety in dropNulls
by ensuring excessively deep JSON is rejected early in the pipeline.
Aligns sbt version with tessellation (1.9.8) for compatibility.

Note: JsonBinaryHasherSuite has one test checking a hardcoded hash
that may need updating - the expected hash was computed with sbt 1.8.0
dependencies.
Merge dev branch into main, bringing all v1.7.0 work:
- JLVM let operator, gas metering, property testing
- JSON depth limit, null value canonicalization fixes
- Evaluator discrepancy fixes and test suites
- Tessellation updated to v4.0.0

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

# Conflicts:
#	project/Dependencies.scala
@scasplte2 scasplte2 closed this Jun 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants