Download the PHP package evolvex/laravel-remote-operations without Composer
On this page you can find all versions of the php package evolvex/laravel-remote-operations. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download evolvex/laravel-remote-operations
More information about evolvex/laravel-remote-operations
Files in evolvex/laravel-remote-operations
Package laravel-remote-operations
Short Description Correctness infrastructure for durable execution, ambiguity detection, safe recovery, and reconciliation of irreversible remote operations in Laravel.
License MIT
Informations about the package laravel-remote-operations
Evolvex Remote Operations
Correctness infrastructure for durable execution, ambiguity detection, safe recovery, and reconciliation of irreversible remote operations in Laravel.
Use it when a remote side effect may have executed even though your application did not receive a response: withdrawals, refunds, provider wallet operations, casino actions, affiliate payouts, SMS sends, webhooks, external provisioning, and similar operations.
This package does not promise exactly-once execution against arbitrary external systems. It prevents blind retries, makes ambiguous outcomes explicit, uses provider idempotency/status probes when available, and escalates cases that cannot be proven safe.
Guarantees and invariants
UNKNOWNis a first-class state, never treated as a normal exception.- A business operation is locally unique by
(type, business_key). - A retry cannot silently mutate the original command payload.
- The same provider idempotency key cannot be bound to two different operations; a DB unique constraint closes the concurrent race window.
- Remote side effects and direct queue handoffs are blocked while a DB transaction is open.
- Durable async dispatch and all automatic retries are persisted through an outbox.
- Execute and reconcile jobs are generation-fenced; stale delayed jobs cannot consume a future retry.
- Outbox queue handoffs have a reclaim lease, so a lost execute job is safely redelivered instead of stranding a
READYoperation. - A crashed send worker is recovered from
EXECUTINGtoUNKNOWNafter its lease expires. - A crashed probe worker is recovered from
RECONCILINGand safely probed again. - Unknown outcomes are probed before retry whenever the provider supports a status probe.
NOT_FOUNDcan remain non-definitive for eventually-consistent providers.- Idempotent retry respects the provider's idempotency TTL measured from the first send attempt.
- Provider safety capabilities are snapshotted at first send so a later deployment cannot silently reinterpret an in-flight ambiguous operation.
- Capability contracts are validated before the first send; declaring status-probe support without implementing
ProbesRemoteOperationsfails before any remote side effect. - Probe limits/backoff are scoped to the current send episode; a new send gets a fresh ambiguity/probe window.
next_action_atis enforced by workers, so stale/early jobs cannot bypass configured backoff.- Manual/unsafe retry requires explicit duplicate-risk acknowledgement and is audited.
- State transitions are stored append-only until the configured whole-operation retention window expires.
- Terminal command payload/idempotency plaintext can be scrubbed earlier while fingerprints/hashes remain for duplicate detection.
- Events implement Laravel's
ShouldDispatchAfterCommitcontract. - Sensitive command payloads and idempotency keys are encrypted at rest using Laravel's app key.
Installation
Optional publishing:
Requirements: PHP 8.3+ and Laravel 12/13.
Define a durable provider handler
Do not capture an in-memory closure as the only way to contact a provider. Reconciliation may happen in another worker hours later.
Synchronous execution
execute() is intentionally rejected when any resolved Laravel DB connection has an open transaction.
Durable asynchronous execution
dispatch() uses the outbox by default:
If you explicitly want a non-outbox queue handoff, use dispatchDirect(). It is blocked inside DB transactions.
Transactional outbox
By default, if the active business transaction is on a different database connection from the remote-operation tables, the package throws NonAtomicOutboxException.
State model
Recovery rules
| Provider idempotency | Status probe | Ambiguous outcome | Kernel behavior |
|---|---|---|---|
| yes | yes | timeout | wait for visibility window, probe first; same-key retry only when safe |
| yes | no | timeout | retry only while idempotency window is valid |
| no | yes | timeout | probe; never blind-retry |
| no | no | timeout | manual review |
| any | eventual probe | early 404 | wait and probe again until 404 is definitive |
| any | any | request definitely not sent | retry only if retry policy permits |
Scheduler
Operational commands
Manual resolution:
Unsafe retry:
Security
- Command payload is stored using Laravel's encrypted cast.
- Idempotency key is encrypted; a SHA-256 hash is stored separately.
- Attempt/probe metadata passes through
MetadataRedactor. - Raw
endpointmetadata is hashed for attempt correlation and removed from stored metadata. - Do not place PAN/CVV/secrets in metadata.
Testing
Limits
- This is not a payment gateway SDK.
- This is not a generic Saga/workflow engine.
- The provider adapter must classify evidence conservatively.
- A provider with neither idempotency nor a reliable status/reference lookup cannot be made exactly-once.
MANUAL_REVIEWis the safe result.
See docs/correctness-model.md, docs/provider-contract.md, docs/failure-matrix.md, and docs/operations-runbook.md.