Skip to content

feat(java): add resource proxies with signed references#349

Merged
pratyush618 merged 6 commits into
masterfrom
feat/java-proxies
Jul 1, 2026
Merged

feat(java): add resource proxies with signed references#349
pratyush618 merged 6 commits into
masterfrom
feat/java-proxies

Conversation

@pratyush618

@pratyush618 pratyush618 commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

What

Adds org.byteveda.taskito.proxies — deconstruct a non-serializable resource into a compact, HMAC-signed reference on the producer, then verify and reconstruct it on the worker. Lets a task "carry" a file handle, client, etc. by reference without serializing the object.

  • Proxies — registry built with a shared HMAC key.
    • register(handler) — one ProxyHandler per resource type (unique id).
    • deconstruct(value) — first handler that handles(value) produces a reference map; returns a ProxyRef{handler, reference, signature}. HMAC-SHA256 over id \n canonical-json(reference) (map keys sorted → stable signature).
    • reconstruct(ref) / resolve(ref) — constant-time signature check (MessageDigest.isEqual) before rebuilding; rejects unknown handler or signature mismatch with ProxyException.
  • ProxyHandler<T> SPI, ProxyRef record, FileProxyHandler (path reference), ProxyException.

Signing prevents a worker from reconstructing a tampered/forged reference. Node's proxy equivalent, adapted to Java.

Test

ProxyTest — round-trip via FileProxyHandler, signature-mismatch rejection, unknown-handler rejection, no-handler rejection.

./gradlew build green (JDK 17 build leg + 21/25 test legs).

Summary by CodeRabbit

  • New Features
    • Added a Java SDK mechanism to pass non-serializable resources through jobs by reference using signed ProxyRef objects.
    • Introduced pluggable ProxyHandler support plus a Proxies registry for deconstructing and reconstructing references.
    • Added FileProxyHandler with optional allowlist enforcement and symlink-aware path validation.
  • Bug Fixes
    • Strengthened validation by rejecting unknown handlers, tampered signatures, and invalid reference payloads.
  • Documentation
    • Added package-level guidance for using resource references in the Java SDK.
  • Tests
    • Added coverage for round-trip behavior, security checks, allowlist enforcement, and duplicate handler ID handling.

Pass non-serializable resources by reference: deconstruct a value into a
HMAC-signed, serializable ProxyRef on the producer and reconstruct it in
the handler. ProxyHandler SPI + a FileProxyHandler with a path allowlist;
explicit (no implicit graph-walking) to fit typed payloads.
File round-trip across the wire, tamper + allowlist rejection, unknown handler.
@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 66aef0b1-6c50-4f2e-a7fd-44ee3bff1d6d

📥 Commits

Reviewing files that changed from the base of the PR and between ecbd4c0 and 60f77aa.

📒 Files selected for processing (3)
  • sdks/java/src/main/java/org/byteveda/taskito/proxies/FileProxyHandler.java
  • sdks/java/src/main/java/org/byteveda/taskito/proxies/Proxies.java
  • sdks/java/src/test/java/org/byteveda/taskito/ProxyTest.java
🚧 Files skipped from review as they are similar to previous changes (2)
  • sdks/java/src/main/java/org/byteveda/taskito/proxies/FileProxyHandler.java
  • sdks/java/src/main/java/org/byteveda/taskito/proxies/Proxies.java

📝 Walkthrough

Walkthrough

This PR adds a proxy system for non-serializable resources: a handler contract, signed proxy references, a registry for deconstruction/reconstruction, a file-based handler with path allowlisting, a proxy exception type, package documentation, and tests.

Changes

Proxy referencing system

Layer / File(s) Summary
ProxyException type
sdks/java/src/main/java/org/byteveda/taskito/errors/ProxyException.java
Adds ProxyException extending TaskitoException with message-only and message-with-cause constructors.
Proxy contracts and reference shape
sdks/java/src/main/java/org/byteveda/taskito/proxies/ProxyHandler.java, sdks/java/src/main/java/org/byteveda/taskito/proxies/ProxyRef.java, sdks/java/src/main/java/org/byteveda/taskito/proxies/package-info.java
Defines the ProxyHandler<T> contract, the ProxyRef record, and package documentation for the by-reference proxy flow.
Registry, signing, and reconstruction
sdks/java/src/main/java/org/byteveda/taskito/proxies/Proxies.java
Implements handler registration, proxy deconstruction/reconstruction, HMAC signing, signature verification, and typed resolution.
File proxy handler
sdks/java/src/main/java/org/byteveda/taskito/proxies/FileProxyHandler.java
Serializes File values as path references and reconstructs them with normalization, real-path handling, and optional allowlist checks.
Proxy tests
sdks/java/src/test/java/org/byteveda/taskito/ProxyTest.java
Covers round-trip behavior, tamper detection, allowlist enforcement, symlink escape rejection, unknown handler handling, null handling, and duplicate registration.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

  • ByteVeda/taskito#334: Adds typed exceptions in the same org.byteveda.taskito.errors package hierarchy that ProxyException extends.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 32.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding Java resource proxies backed by signed references.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/java-proxies

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai 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.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@sdks/java/src/main/java/org/byteveda/taskito/proxies/FileProxyHandler.java`:
- Around line 23-28: The allowlist check in FileProxyHandler can be bypassed via
symlinked ancestors because the constructor only stores normalized paths and the
containment check later relies on lexical startsWith behavior. Update
FileProxyHandler so the allowed roots and the candidate path’s nearest existing
ancestor are resolved to real filesystem paths before the access check, and make
the check use those resolved values instead of only normalize().startsWith().
Add a regression test around the existing allowlist logic to cover a symlink
escape case where a path under an allowed root resolves outside it.
- Around line 47-50: Reject a null reference map at the start of
FileProxyHandler.reconstruct before accessing "path". Add an explicit null check
for the reference argument and throw ProxyException with the same malformed-ref
handling used for the existing path validation, so a null ProxyRef reference
fails through the intended error path instead of triggering
NullPointerException.

In `@sdks/java/src/main/java/org/byteveda/taskito/proxies/Proxies.java`:
- Around line 41-48: Update Proxies.deconstruct(Object value) to handle null
explicitly before iterating handlers or calling value.getClass(). If value is
null, throw a ProxyException with a clear message instead of letting a
NullPointerException escape; keep the existing ProxyRef construction path
unchanged for non-null values. Use the deconstruct method in Proxies as the fix
location.
- Around line 33-36: The Proxies.register(ProxyHandler<?> handler) method
currently accepts null ids and silently overwrites existing handlers in
handlers.put, which can break the ProxyRef/handler contract. Update register to
fail fast by validating handler.id() is non-null and rejecting duplicate ids
before mutating the handlers map, using the existing Proxies and ProxyHandler
symbols so callers get an immediate error instead of silently changing
semantics.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 23b77562-ae80-401a-986d-ff717d613c22

📥 Commits

Reviewing files that changed from the base of the PR and between 6d0d260 and ecbd4c0.

📒 Files selected for processing (7)
  • sdks/java/src/main/java/org/byteveda/taskito/errors/ProxyException.java
  • sdks/java/src/main/java/org/byteveda/taskito/proxies/FileProxyHandler.java
  • sdks/java/src/main/java/org/byteveda/taskito/proxies/Proxies.java
  • sdks/java/src/main/java/org/byteveda/taskito/proxies/ProxyHandler.java
  • sdks/java/src/main/java/org/byteveda/taskito/proxies/ProxyRef.java
  • sdks/java/src/main/java/org/byteveda/taskito/proxies/package-info.java
  • sdks/java/src/test/java/org/byteveda/taskito/ProxyTest.java

Comment thread sdks/java/src/main/java/org/byteveda/taskito/proxies/Proxies.java Outdated
Comment thread sdks/java/src/main/java/org/byteveda/taskito/proxies/Proxies.java
@pratyush618 pratyush618 merged commit 5600c15 into master Jul 1, 2026
19 checks passed
@pratyush618 pratyush618 deleted the feat/java-proxies branch July 1, 2026 16:26
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.

1 participant