Under the hood
Effect integration workflows
Understand bounded integration execution, interruption, resource ownership, and fail-closed recovery.
v0.3.0 referenceReviewed
On this page
Hopya uses stable Effect 4.0.0 on Node 24 (upstream review: 2026-10-02). The API declares ^4.0.0; its lockfile pins the release.
| Owner | Responsibility |
|---|---|
| Adonis / Lucid | Authentication, permissions, SQL transactions, migrations |
| Effect | Integration failures, resource lifetimes, bounded concurrency |
Native v4 migration
| Native API | Behavior |
|---|---|
Effect.result | Success.success / Failure.failure, replacing either and Right/Left |
Effect.callback | Node callbacks with interruption finalizer |
catch / catchCause | Native v4 failure/cause handling |
timeoutOrElse({duration,orElse}) | Native deadline handling |
Semaphore | Bounded admission/concurrency |
fnUntraced | Reusable integration generators; runtime execution at Promise/worker boundaries |
| Graph actions | Compose HTTP, credential, SMTP Effects directly |
Expected failures belong in try, tryPromise, or fail. Exceptions from sync/gen or rejected promise calls are defects; result handles expected failures, not defects. This migration does not reclassify a database outage as invalid credentials.
Cause identity and Promise boundaries
- v4 Causes use flat
reasons; nativerunPromise/runSyncsquash to original failures/defects, not v3’sFiberFailure. - Hopya’s
runSyncThrow/runPromiseThrowinspectExit, preserve original identity includingHttpError, and normalize interruption-only causes toAbortError. The Promise bridge accepts an abort signal and still supports intentionally propagated database/security defects.
Durable automation execution
| Boundary | Behavior |
|---|---|
| Queue | Database authoritative; event enqueue commits with originating audited mutation |
| Versions | Immutable; task updates use publisher’s workspace service with causation/re-entry limits |
| Claims | Four-run batches, concurrency four |
| Failure isolation | Each run captures its own Exit, including defects; siblings continue |
| Failed attempt | Running nodes/steps fail, untouched ones skip in one lease-checked transaction; delivered output retained |
| Completion / legacy acknowledgment | Current lease required |
| Expired graph, linear, webhook lease | Fail closed; no automatic replay |
| Recovery storage unavailable | Keep lease for fail-closed expiry, never report success |
Failure does not prove a remote write failed. Inspect its outcome before explicitly starting another attempt. No delivery, token exchange, SQL write, or task mutation is blindly retried.
Database lifetime and SQLite worker serialization
- Lucid Promises cannot be cancelled. Wait for their actual outcome before releasing worker ownership or terminal recovery on interruption.
- SQLite state operations serialize separately from concurrent network work: synchronous
better-sqlite3busy waits otherwise block another same-event-loop transaction’s commit. - PostgreSQL keeps concurrent state operations. Stored-data/state-I/O errors are explicit sanitized failures.
Transport and credential lifetimes
| Workflow | Admission / deadline | Resource and security ownership |
|---|---|---|
| DNS | Five seconds | Cancellable resolver, concurrent A/AAAA checks; both families checked before address pin |
| Pinned HTTP | Absolute/socket deadlines; body/output bounds | Fresh socket per resolution; no redirects; destroy request/response on interruption; native header/config errors sanitized |
| Graph dispatch | Publisher checks before each node and after DNS/OAuth | Lease guards task writes/outcomes; credential origin/path/workspace binding, encryption/revocation/redaction remain enforced |
| OAuth | Four permits; 20 seconds including admission | Await single-flight refresh through encrypted-token persistence before releasing ownership/lock; SQLite persistence serialized |
| SMTP | Two permits; 15 seconds including admission | Abort controller, transport, actual connection/TLS sockets; cleanup on success/failure/timeout/interruption; native errors sanitized |
Nodemailer’s close() alone cannot stop active delivery; cleanup also aborts/destroys sockets during connection and TLS upgrade.
Other reviewed boundaries
| Boundary | Review |
|---|---|
| Agent | Effect interruption + browser disconnect + 45-second deadline; admission before awaited context query closes four-request race; bounded response/current permissions retained |
| Origin middleware | Expected rejection uses failure channel, not Promise defect |
| OIDC | Native outer deadline plus SDK request timeout; outer interruption does not itself abort openid-client’s Promise; shared discovery/config not mutated per caller |
| Live SQL | Shared failure bridge, request-owned clients, driver deadlines, finally; no blanket timeout/retry around writes |
| Pure validation / OpenAPI / bulk admission | Native API migration only |
| Storage / appearance | Collector database-error accounting and expected missing-logo failure channel |
Verification boundaries
Historical upstream records, not checks newly run for this documentation site:
| Evidence | Recorded result |
|---|---|
| Focused Node24 API work | Typecheck + 54 tests across automations/transport/core/accounts/SSO/agent-lifecycle/HTTP; real 45-second deadline |
| Integrated 2026-10-02 check | API/web/operator typechecks; 125 API, 73 web unit, eight initializer tests; both builds |
| Stream | Real deadline + complete 42,707,557-byte / 800-item snapshot |
| Packaging | Compose config/whitespace pass; existing Vite large-chunk advisory |
| Dependencies | Only Effect 4.0.0; zero reported audit vulnerabilities |
| Unverified external behavior | Actual SMTP/TLS deployments, OAuth/OIDC providers, PostgreSQL worker execution, DNS failure modes, process-kill recovery |
| Browser | No Playwright/browser workflow verification |
Regression coverage and local fixture evidence
- Coverage: failure/defect identity, cleanup, invalid-header isolation, DNS cancellation, local SMTP interruption/permit reuse/delivery, bounded claims, acknowledgment failure after remote acceptance, sibling completion, expired-lease non-replay.
- Existing tests retain immutable version/branch/lease/permission/secret/OAuth-state/request/re-entry checks.
- Disposable implicit-TLS SMTP fixture verified post-handshake cleanup and subsequent delivery. Self-signed trust bypass was fixture-only; key/certificate removed.
- Initial automation runs exposed SQLite worker locking, repaired before passing rerun. Local fixtures and simulated stale leases are limited evidence, not production-readiness certification.
Official references
- npm stable tags and 4.0.0 metadata
- Effect 4.0 announcement
- Migration guide, error handling, flat Cause
- Upstream installed release declarations/source in
node_modules/effect/distandnode_modules/effect/srccorroborated callback/deadline/finalizer/semaphore/Cause APIs.