Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Integration Engine Laravel Package

carlosgude/integration-engine

IntegrationEngine forces every Symfony integration into the same predictable shape: each endpoint is just a Request and a Response, with facades, mappers, and YAML action maps generated for you. No ad-hoc HTTP clients or scattered mapping logic.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Framing correction. The brief labels this a "Laravel/PHP package." It is not. carlosgude/integration-engine is a Symfony bundle: it self-registers via Symfony Flex, is configured through config/packages/integration_engine.yaml, ships bin/console make:integration and debug:integration commands, discovers adapters and middleware through Symfony DI service tags, and requires Symfony 6.4+ (7.x, 8.x). If our estate is Laravel-first, out-of-the-box fit is zero and the real decision is "do we fund a Laravel bridge?" rather than "do we adopt this package?" If we are on Symfony, it is a native, low-friction integration.

Architecture fit. The package enforces a genuinely useful discipline: every external API becomes a directory of endpoints, each endpoint is exactly one Action (request) + one Response + one Mapper, wired by a YAML action map and exposed through a thin facade ({Name}Integration) plus an Anti-Corruption-Layer Gateway that is the only class aware of both the vendor DTOs and our domain model. That is a textbook ports-and-adapters shape and fits cleanly into a hexagonal or DDD-flavoured Symfony codebase with a dedicated integration/infrastructure layer. It fits poorly where teams want a thin generic HTTP wrapper, where integration logic is intentionally co-located with application services, or where the domain model is already the transport model.

Integration feasibility. Low for a Symfony team: composer require, scaffold one integration, define base URL and client type, register in YAML, done. The README plus DOCUMENTATION.md, a working demo repo (REST, GraphQL, dynamic OAuth2), ADRs and an upgrade guide are a reasonable on-ramp for a package at this maturity. Escape hatches remain credible — custom adapters via ClientAdapterInterface, custom middleware via AbstractClientMiddleware, custom clients via client_service, project adapters overriding built-ins — so we adopt a pattern and a small runtime, not a black box.

What v9.4.0 changes (and does not). The release is small and additive. It restores a pre-mapping timing split: a new ResponseReceived lifecycle event fires once the client returns a response and before mapping, in send() (static and dynamic auth) and per sendMany() item. ResponseMapped::timestamp − ResponseReceived::timestamp gives mapping time; ResponseReceived followed by RequestFailed means "the API answered, our mapper failed." This is a meaningful narrowing of the observability gap flagged below — it is now possible to separate vendor slowness from our own mapping slowness without bolting on our own timers. It also ships a real bug fix: debug:integration <name> no longer fails with "Unable to inspect actions" on integrations that declare the v9.3.0 defaults: section. The rest is documentation: a upgrade-9.0.md guide for the v9.0.0 context-only path resolution change, and corrections to examples that did not compile (lowercase Symfony HttpClient header names, maxAttempts vs maxRetries on ExponentialBackoff, a GraphQL body missing create()), plus a webhook doc fix noting an accepted webhook event is dispatched to Messenger before the 202, so with the default synchronous bus the consumer runs inside the webhook request.

Technical risk. High, and mostly non-technical:

  • Adoption/sustainability. 10 stars, 0 dependents, a single maintainer, opportunity score 17.15. This is pre-traction software. Bus factor is 1; no evidence of a funded entity behind it despite the dedicated website. Positives worth weighing: an ADR practice, an upgrade guide, measured-quality docs, and a release cadence of roughly five tagged releases since v9.0.0 (v9.4.0 published 2026-09-24). That is a maintainer doing the right things at small scale, not an assurance of continuity.
  • Event-surface churn. ResponseReceived is explicitly a restoration of the pre-mapping split that v7's HttpResponseReceived provided and that the v8 event rework dropped. Three majors, three different shapes of the same observability hook. Treat the event API as unstable at major boundaries and do not let it become load-bearing for billing, SLAs or alerting without an internal adapter.
  • Framework lock-in. The core value (registry, engine, contracts) may be portable, but all wiring is Symfony-coupled. A Laravel or framework-agnostic path requires re-implementing bundle wiring, config loading, command registration and DI tag discovery.
  • Testability gap. No documented fake/in-memory adapter, no HTTP record-replay, no contract-test harness. For a layer whose entire job is talking to unreliable third parties, this remains the largest functional hole and will be our cost, not the package's. Note the new event is a timer, not a test double.
  • Observability gap (narrowed, not closed). Latency decomposition now exists; structured logging, tracing, redaction and metrics are still not first-class and must be built as middleware. Critically, ResponseReceived is not emitted for transport failures or for the 401 that triggers a token refresh — so the exact requests you most want to see in an auth-degradation incident are invisible in this split. No documented timeout, retry/backoff or circuit-breaker defaults.
  • Token cache semantics. Default cache.app is process-local under PHP-FPM, so every worker fetches its own OAuth token; strict token-endpoint rate limits require a shared Redis pool and multi-connection integrations cache per connection. Documented, but easy to get wrong at scale — and now harder to detect, per the previous bullet.
  • Batch concurrency caveat. sendMany() is only truly concurrent when the client implements BatchClientInterface; the REST client does, GraphQL does not. GraphQL fan-out silently degrades. v9.4.0 emits ResponseReceived per batch item, which gives us per-item transport timing to prove or disprove this in staging.
  • Dual source of truth. Endpoint definition lives in both a PHP class and the YAML action map. The scaffold command maintains both; the debug:integration fix suggests the tooling is being exercised, but hand edits will still drift and there is no documented validation-at-boot guarantee.
  • Error taxonomy is thin. Only the 401-before-TTL evict-and-retry-once path is specified. 429/5xx handling, partial-batch semantics beyond hasFailures()/errors(), and DTO shape drift are ours to solve.

Key questions.

  1. Is the target application Symfony 6.4/7.x/8.x, or Laravel? What is the actual PHP version floor across the estate?
  2. Who maintains this besides the single listed maintainer, and is there a stated stability/BC policy? Specifically: is the lifecycle-event API now frozen for the 9.x line, or should we expect another reshape at v10?
  3. Are the core contracts free of Symfony dependencies, i.e. how much of a Laravel bridge is glue versus rewrite?
  4. How is REST batch concurrency implemented (Symfony HttpClient async vs. curl-multi), and what are the default timeouts and connection limits?
  5. What are the built-in timeout, retry and idempotency behaviours for POST/PUT, and what is the guidance for non-idempotent retries?
  6. Is there any secret redaction in logs/middleware and in the Symfony profiler panel (bodyClass, profiler_payloads opt-in are documented — confirm they are off by default in production)?
  7. Does the token cache key include tenant/connection identity, and is there stampede protection (locking) on the token endpoint?
  8. Is there a sanctioned testing story — fakes, recorded fixtures, or a test client adapter?
  9. Do webhooks carry production traffic today, and are we comfortable that a synchronous Messenger bus runs consumer work inside the webhook request (202 latency, retry semantics on upstream timeout)?

Integration Approach

Stack fit.

Stack Fit Notes
Symfony 6.4–8.x, PHP 8.2+ Native Bundle, Flex recipe, DI tags, make:/debug: commands all work as advertised
Symfony with legacy Guzzle clients Good Needs a ClientAdapterInterface shim; built-ins target Symfony HttpClient
Laravel / Lumen Poor Requires a service provider, config publishing, container wiring, command port and removal of bundle assumptions
Framework-agnostic PHP services Partial Core engine reusable; all wiring must be hand-built
Mixed estate Per-service No cross-language story; this is PHP-only

Migration path. Treat this as a strangler around existing clients, not a rewrite. v9.4.0 improves the middle of this path, not the ends.

  1. Pilot (single integration, read-only). Pick one low-blast-radius GET-only REST integration. Scaffold with make:integration, implement facade + gateway, keep the legacy client live behind a feature flag. Verify debug:integration <name> against a YAML file that uses defaults: — that was broken until this release.
  2. Parity harness. Run old and new side by side in staging, log and diff typed responses, and agree a tolerance for mapper-level differences. Do not proceed without this — it is our substitute for the missing test-double story. Subscribe to ResponseReceived and ResponseMapped here: the delta between them is the fastest way to attribute a parity failure to transport or to our mapper.
  3. Write endpoints. Move to POST/PUT only after idempotency and retry semantics are decided; the package gives body: path-parameter extraction that strips consumed keys from the payload, which is a nice touch but must be verified against each API.
  4. Auth. Introduce static auth first; add dynamic OAuth2 with a shared Redis cache_service and verify the 401-evict-and-retry-once path in a chaos test. Do not rely on ResponseReceived to observe this path — it is deliberately silent there.
  5. Fan-out. Enable sendMany() only where the client supports BatchClientInterface; bound batch size and test worker memory. Confirm per-item ResponseReceived timings show real concurrency before declaring a batch path "done."
  6. Wave rollout. Remaining integrations by domain area, each with the gateway boundary enforced by review rule: nothing outside Gateway may import an integration facade or its DTOs.

Compatibility. Verify at spike time: PHP 8.2+ floor against our oldest supported service; Symfony minor version matrix; whether it coexists with our existing HTTP client configuration (proxy, mTLS, base timeouts); compatibility with our static analysis level (typed class constants pin PHP 8.3+ in places); config cache warm-up behaviour in CI; and whether Composer constraints permit our Symfony version without --with-all-dependencies churn. Add one item this cycle: if we already consume lifecycle events, re-check any assertion of an exact event sequence — ResponseReceived now sits between RequestSent and ResponseMapped, which is additive but will break order-sensitive listeners and tests.

Sequencing. Spike (1–2 days, now including event-ordering and profiler review) → architecture decision (1 day) → pilot + parity (3–5 days) → middleware baseline: timeouts, retry/backoff, rate limiting, structured logging (3–5 days, ours to build) → token caching hardening (2–3 days) → rollout waves (1–3 days per integration once conventions exist). Laravel bridge, if required, is a separate 8–15 day workstream with ongoing maintenance burden. Add ~1 day to consume v9.4.0's timing events into the parity harness and a first-cut latency dashboard.

Adoption of the upgrade. Low risk: ResponseReceived is additive, and the debug:integration fix is a bug fix. Pin to 9.4.* only after confirming no listener in our codebase assumes a two-event (RequestSent → ResponseMapped) sequence, and read docs/upgrade-9.0.md even though we are starting at 9.x — it documents the context-only path resolution change that any copied sample code predating v9.0.0 will get wrong.

Operational Impact

Maintenance. Low code volume, high ownership concentration. Plan to pin exact versions (to the minor, e.g. 9.4.*, given an active patch cadence), keep a fork-and-patch capability, and budget roughly one engineer-day per quarter for dependency bumps and upstream review. If we build middleware, test doubles or a Laravel bridge, we become the de facto maintainer of that surface with no upstream guarantee it won't be broken. Treat the lifecycle-event API as version-fragile: it has now changed shape at v7 → v8 → v9, and our internal adapters should be the only consumers.

Support. Community-only: GitHub issues, docs, ADRs and a demo repo. No SLA, no documented security disclosure policy, no LTS. Mitigation is internal: a named owner, an internal "integration standards" guide built on top of this pattern, and a decision log. Escalation to the maintainer is not a viable plan. The documentation and ADR hygiene visible in this release raises confidence in comprehensibility but not in continuity.

Scaling. Three concrete limits. (1) Token endpoint pressure — cache.app is per-worker under FPM, so N workers means N token fetches on cold start; move to shared Redis and consider a lock to prevent stampede. (2) Fan-out memory and socket pressure — cap batch size, verify the REST adapter's concurrency ceiling, and note GraphQL cannot parallelise at all. (3) Rate limiting across workers — a per-process limiter in middleware is not sufficient; use a shared store. Beyond that, throughput is bounded by Symfony HttpClient, which is fine for typical B2B integration volumes and wrong for high-QPS public API proxying.

Failure modes. Watch for: upstream schema drift surfacing as mapper exceptions (no schema validation layer) — now partially diagnosable via ResponseReceived → RequestFailed; token revocation mid-flight (one retry, then hard failure) with no ResponseReceived emitted, so auth-refresh latency and volume are a blind spot in any dashboard built on the new event; token endpoint 429 cascades at scale-out; partially successful batches where callers ignore hasFailures(); missing default timeouts starving PHP-FPM workers; YAML/PHP action-map drift producing "unknown action" at runtime rather than boot; middleware ordering bugs silently disabling retry or auth; secrets leaking into logs or the Symfony profiler panel absent explicit redaction — check profiler_payloads is not enabled in any shared environment; and, new this release, order-sensitive event listeners or tests breaking on the inserted ResponseReceived event, or on the defaults:-section YAML shape the fixed debug:integration now tolerates.

Ramp-up. A mid-level Symfony developer scaffolds their first integration in under a day and is productive within a week, because the pattern is small, uniform and demonstrated by the demo repo. The real learning curve is cultural, not technical: the facade-plus-gateway rule is the whole value proposition and is trivially bypassed if reviews don't enforce it. Budget an extra two to three days per team for middleware conventions and test fixtures — and allow half a day for the timing-event semantics, since "ResponseReceived absent" has three distinct meanings (transport failure, 401 refresh, event not wired) that a new team will get wrong once. Treat "no direct registry or facade calls from controllers" as a lint-level rule.

Recommendation. Unchanged: conditional go for Symfony services on PHP 8.2+. Adopt on a pilot with the gateway boundary enforced, shared-cache tokens, a self-built observability/retry middleware baseline, pinned versions and a named internal owner. v9.4.0 makes this marginally more attractive — it closes part of the observability gap we called the second-largest functional hole, and the debug:integration fix removes a first-week papercut — but it does not move adoption, testability, or support risk, and the event-surface history across three majors reinforces that we must own the observability layer rather than depend on it. No-go for Laravel-first estates unless a Laravel bridge is separately funded and staffed, and no-go as a platform-wide standard until at least two integrations have run in production for a quarter.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
andydefer/laravel-notification
adachsoft/cli-process-tester
jhaskell13/laraflow
sebastienheyd/boilerplate-media-manager
ccast/tagixo-primix
pretendtrue/laravel-builder
sawmainek/laravel-scout-tntsearch-driver
tomshaw/laravel-calendar-table
dibakar/laravel-ownership
steadrun/laravel-monitor
labyrinthe/connect-laravel
elmogy/layan
drewdan/sentinel-client
dskripchenko/laravel-llm
fatryst/nuonuo
stevenay/myanfont
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc