[TT-17786] Backport multi-bundle plugin composition (gRPC + Go) to release-5.13#8505
[TT-17786] Backport multi-bundle plugin composition (gRPC + Go) to release-5.13#8505sedkis wants to merge 2 commits into
Conversation
…rivers Ports the engine-agnostic bundle merge layer from master onto release-5.13: parseBundleNames, FetchBundleByName, the loadBundleWithFs dispatcher, loadSingleBundle (5.13's existing single-bundle body, unchanged), loadOneBundleForMerge, loadBundleManifestNamed, mergeBundleManifest and bundleSubdirName. A comma-separated custom_middleware_bundle now fetches each bundle into its own subdirectory and merges their manifests in order. Scoped to the gRPC and native Go drivers, which dispatch by remote hook name and per-.so symbol respectively and need no shared-runtime isolation. The goja/JavaScript handler-isolation work is deliberately excluded, as are the Python and Lua drivers (broken on the merge path on master). Single-bundle behavior and the MD5 on-disk cache layout are unchanged; the merge path is gated behind two or more comma-separated names. Co-Authored-By: Claude <noreply@anthropic.com>
|
This PR backports the multi-bundle plugin composition feature to the The implementation is fully backward-compatible. When only a single bundle is specified, the existing legacy logic is used, ensuring no change in behavior or on-disk cache layout for current setups. The changes are primarily in Files Changed Analysis
Architecture & Impact Assessment
graph TD
A["Start: loadBundleWithFs(spec)"] --> B{Parse spec.CustomMiddlewareBundle};
B --> C{"Is it a multi-bundle list?"};
C -- "No (single bundle)" --> D["loadSingleBundle (legacy path)"];
C -- "Yes (multiple bundles)" --> E[Loop through bundleNames];
E --> F["loadOneBundleForMerge(name)"];
F --> G[Fetch & Unpack bundle to subdir];
G --> H[Load manifest.json];
H --> I["mergeBundleManifest(spec, manifest)"];
I --> E;
E -- "all bundles processed" --> J[Initialize driver with merged middleware];
J --> K[End];
D --> K[End];
Scope Discovery & Context Expansion
Metadata
Powered by Visor from Probelabs Last updated: 2026-07-21T15:22:19.929Z | Triggered by: pr_updated | Commit: 42353f8 💡 TIP: You can chat with Visor using |
✅ Architecture Check PassedNo architecture issues found – changes LGTM. Performance Issues (1)
✅ Architecture Check PassedNo architecture issues found – changes LGTM. \n\nPerformance Issues (1)
Powered by Visor from Probelabs Last updated: 2026-07-21T15:21:51.196Z | Triggered by: pr_updated | Commit: 42353f8 💡 TIP: You can chat with Visor using |
|
SentinelOne CNS Hardcoded Secret Detector SentinelOne CNS is a cloud-agnostic, agentless CSPM & CWPP solution that continuously detects and prevents vulnerabilities that have the highest probability of being exploited in Azure, AWS, Google Cloud, and Kubernetes. |
|



Summary
Backports multi-bundle plugin composition to the 5.13 LTS line, scoped to the gRPC and native Go (goplugin) drivers. A
custom_middleware_bundlevalue may now be a comma-separated list of bundle filenames; each bundle is fetched into its own subdirectory and their middleware manifests are merged in declaration order.The merge machinery is engine-agnostic (it operates on
spec.CustomMiddlewarehook slices and the filesystem). gRPC dispatches each merged hook to the remote server by hook name and native Go resolves each symbol from its own.so, so neither needs shared-runtime isolation. The goja/JavaScript handler-isolation work from TT-16948 is not included, and the Python and Lua drivers are out of scope (they are broken on the merge path onmaster).Ticket: https://tyktech.atlassian.net/browse/TT-17786
What's ported (from
master, intogateway/coprocess_bundle.go)parseBundleNames- split on commas, trim, drop emptiesFetchBundle/FetchBundleByNamesplitloadBundleWithFsdispatcher: 1 name -> legacyloadSingleBundle(5.13 body unchanged); >= 2 names -> merge pathloadOneBundleForMerge,loadBundleManifestNamedmergeBundleManifest- concat Pre/Post/PostKeyAuth/Response, single AuthCheck, uniform Driver, first-wins IdExtractor, subdir-prefixed pathsbundleSubdirNameCustomMiddlewareBundleinapidef/api_definitions.go(no new schema field)Backward compatibility
Test plan
go test ./gateway/ -run 'Bundle|MultiBundle|Merge' -count=1TestParseBundleNames- trimming, empty/comma/whitespace handling (incl. the untrimmed-single-name edge case)TestMergeBundleManifestAppendsHooks- cross-bundle + within-bundle ordering, subdir path prefixingTestMergeBundleManifestRejectsDuplicateAuthCheck,...RejectsDriverMismatch,...EmptyPathNotPrefixedTestBundleSubdirNameStripsExtAndCollapsesSlashesTestMultiBundleMerge_GRPC,TestMultiBundleMerge_GoPlugin- real fetch -> unzip -> DeepVerify -> merge against two registered bundles, asserting both bundles' hooks land with subdir-prefixed pathsTestBundleLoader,TestLoadBundleWithFs_*) passes unchangedAll pass locally against Redis. Note: the integration tests verify spec-composition of the merged manifest; request-time dispatch through a live gRPC server / real
.sois unchanged by this backport and not exercised end-to-end here.🤖 Generated with Claude Code
Ticket Details
TT-17786
Generated at: 2026-07-21 15:19:46