--- id: PLN-0121 ticket: multi-frontend-serializable-ir title: Add serializable IRBackend reflection guardrails status: done created: 2026-07-15 ref_decisions: [DEC-0044] tags: [compiler, compiler-general, ir, backend, serialization, multi-frontend] --- ## Briefing `DEC-0044` requires lightweight guardrails that prevent the public `IRBackend` handoff from exposing non-serializable process-local shapes. Existing tests already prevent PBS type exposure; this plan expands that guardrail to the broader serializability contract. ## Objective Add reflection-based tests that fail when public `IRBackend` contract types expose callbacks, services, mutable/unordered collections, frontend-owned objects, or other forbidden public shapes. ## Dependencies - Accepted decision: `DEC-0044`. - Recommended predecessor: `PLN-0119` for spec terminology. - Recommended predecessor: `PLN-0120` for the complete contract type list and allowed supporting type classification. - Existing test: `prometeu-compiler/prometeu-frontend-api/src/test/java/p/studio/compiler/models/IRBackendExecutableContractTest.java`. ## Scope 1. Extend the public contract type list to cover all current `IRBackend` handoff types found by `PLN-0120`. 2. Add reflection checks for forbidden package exposure beyond PBS when the exposed type is frontend-owned. 3. Add checks that public API signatures do not expose callbacks, functional interfaces, service-like objects, registries, direct mutable collections, or unordered collection contracts. 4. Add an allowlist for value wrappers that are accepted by `DEC-0044`, such as identifier wrappers, spans, enums, strings, primitives, boxed scalar values where already present, and `ReadOnlyList`. 5. Keep failure messages actionable by reporting the exact contract type and member. ## Non-Goals - Do not assert one mandatory serializer. - Do not reject all non-record classes automatically; reject public exposed shapes that violate the decision. - Do not rewrite model classes in this plan except for tiny test-support adjustments. - Do not use ArchUnit or a new dependency unless repository maintainers separately approve it. ## Execution Method 1. Refactor `IRBackendExecutableContractTest` only enough to support reusable inspection helpers. 2. Keep the existing PBS exposure test intact or fold it into a broader public-contract exposure test with equivalent failure coverage. 3. Implement recursive inspection of public fields, record components, public constructors, and public methods. 4. Treat generic type arguments as part of the public shape. 5. Add explicit classification helpers: - `isAllowedScalarOrValueType`, - `isAllowedCollectionType`, - `isForbiddenCallbackOrServiceShape`, - `isForbiddenFrontendOwnedType`. 6. Run the narrow test suite and fix only test logic defects in this plan. ## Acceptance Criteria 1. A public `IRBackend` contract type exposing a callback or functional interface would fail the test. 2. A public `IRBackend` contract type exposing `java.util.Map`, `java.util.Set`, mutable list classes, or unordered collection interfaces would fail unless explicitly represented as an ordered contract type. 3. A public `IRBackend` contract type exposing frontend-owned AST/parser/token/semantic/editorial objects would fail. 4. Failure output names the exact member that violates the contract. 5. Existing PBS neutrality guardrail coverage is preserved. ## Tests Run the narrow Gradle test task for `IRBackendExecutableContractTest`. If the repo's Gradle structure makes a narrower invocation unreliable, run the smallest module-level test task for `prometeu-frontend-api`. ## Affected Artifacts - `prometeu-compiler/prometeu-frontend-api/src/test/java/p/studio/compiler/models/IRBackendExecutableContractTest.java` - Potential test-only helpers in the same test package.