Skip to content

chore(deps): upgrade effect to 4.0.2 - #6999

Merged
kanadgupta merged 34 commits into
developfrom
kanad-claude/effect-v4-upgrade-e27f7d
Oct 9, 2026
Merged

kanadgupta merged 34 commits into
developfrom
kanad-claude/effect-v4-upgrade-e27f7d

Conversation

@kanadgupta

@kanadgupta kanadgupta commented Oct 5, 2026 •

Copy link
Copy Markdown
Member

Bumps effect, @effect/platform-bun, @effect/platform-node, @effect/platform-node-shared, @effect/sql-pg, and @effect/vitest from 4.0.0-rc.112 to the stable 4.0.2 release. @effect/tsgo is unchanged.

The goal is zero change to CLI behaviour. Every edit is either required by a removed or renamed API, or restores a behaviour whose upstream default moved.

Commit layout

The first three commits are the bump plus two scripted rewrites and can be skipped by reviewers:

  • effect/unstable/* import paths moved to effect/* (removed upstream in rc.118, effect#8354).
  • CLI and Config constructors renamed to PascalCase (effect#7453, effect#8121).

The remaining commits are hand migrations, one topic each.

Hand migrations

  • node-postgres pool bridge — @effect/sql-pg 4.0 is a native client and dropped PgClient.fromPool (effect#7426). The remote database session keeps its own node-postgres pool for the zero idle timeout, the per-connection role step-down hook, and raw COPY connections, so db-connection.pool-client.ts is a small SqlClient.make adapter over that pool with the same statement execution, cancellation, and error classification the old bridge had.
  • Stack RPC strictness — parse-option annotations no longer affect decoding (effect#8131) and the RPC transport passes no parse options, so the initialization command and runCommand payload schemas now reject unknown keys through a Record filter ahead of the struct decode, with the same "Expected no excess property" wording. Encoding drops undefined entries first, so optional fields passed as explicit undefined (for example pgProve.workingDir) still cross the RPC JSON codec as they did with the plain struct.
  • One statement per query — the native @effect/sql-pg client sends everything through the extended protocol, which rejects multi-command strings. The realtime schema bootstrap runs as two statements, and the generated ALTER ROLE / ALTER DATABASE batches come back from Postgres as an array and run one at a time inside the same transaction.
  • Socket addresses, file sizes, encoding, sockets — server addresses are NetAddress.SocketAddress values, File.seek and File.Info.size use bigint and ByteSize, Encoding moved to effect/encoding/Base64Url, and the whole-stack WebSocket test helper uses the reader and writer pair.
  • Effect.partition returns [passes, fails]; the stack destroy handler destructures in that order.
  • Management API contracts — packages/api contracts are regenerated; the 4.0.2 schema codegen emits code-point length checks and Unicode-flagged patterns.
  • Config package — SchemaAST.Union.mode moved under options, ToJsonSchemaOptions.additionalProperties became onExcessProperty, and regex patterns need the Unicode flag to be exported into JSON Schema (effect#8482). Peer dependency ranges are untouched and already satisfy 4.0.2.

Preserved defaults

  • The stack's PgClient.layer calls pin idleTimeout: "10 seconds"; the default since 4.0.1 is 60 seconds (effect#8679).
  • The published JSON Schema files (@supabase/config schema.json and project-schema.json, mirrored at apps/docs/public/cli/*.schema.json) are byte-identical to the develop build. toCliConfigJsonSchema passes onExcessProperty: "error" so structs keep additionalProperties: false (effect#8147); the shared document assembler leaves pattern-keyed records open, as the generator has no per-schema setting for that; and bucket tables are modelled so they render as the published object-or-array union.

Behaviour changes reviewed and accepted

These upstream changes have no configuration knob. Each was checked against the repo's call sites and judged not user-visible:

  • Child-process kill and scoped release now wait for the process group, bounded to one second without forceKillAfter (effect#8018). The stack host, bundled Postgres clients, and containers already set forceKillAfter; other spawn sites can only see up to one extra second of teardown when a descendant lingers.
  • Effect.cached treats interruption as abandonment (effect#8719). Every cached effect in the repo is awaited by a single fiber or forked into an owning scope, so the shared-interruption semantics do not apply.
  • Empty bucket tables under storage.analytics.buckets and storage.vector.buckets are modelled as an object-or-array union instead of Schema.Struct({}). Runtime decoding now rejects a primitive bucket value (foo = "x"), which the old schema accepted and ignored; objects and arrays decode as before.
  • HTTP client spans are named after the bare method (GET instead of http.client GET), following the OpenTelemetry convention. Nothing in the repo keys on the old name.
  • Generated Management API string length checks count code points instead of UTF-16 code units, which only differs for characters outside the Basic Multilingual Plane.

Patches

  • Rebased: the @effect/platform-node-shared stdin EPIPE listener, now against 4.0.2. 4.0.2 still removes the stdin sink's error listener before the final end() flush, so a child that exits before reading its input raises an uncaught EPIPE on Linux; effect#7712 and effect#7714 do not cover that path.
  • Rewritten: the @effect/vitest runTest patch. Upstream's finalizer ordering fix (effect#8154) covers the abort hook, so the patch now only layers the two behaviours the stack's effect-timeout tests assert on top of it: rejecting with the pretty errors and reporting a finalizer failure after a timeout.

Test-only changes

  • Stack integration and CLI db reset e2e fixtures that seeded data through PgClient.layer with semicolon-joined statements now issue one statement per call; fixtures that go through psql are unchanged.
  • The db reset e2e fixture reads count(*)::int, since the native client decodes int8 as bigint.

Follow-ups

  • Migrate the remote database session to the native @effect/sql-pg client and delete the pool adapter. That changes result decoding (int8, timestamps, bytea) across the SQL consumers and needs its own review.

kanadgupta and others added 16 commits October 5, 2026 11:26
Drop the rc.112 pnpm patches: the stdin EPIPE listener is covered upstream since
rc.113 (effect PRs 7712 and 7714), and the vitest runTest rewrite is superseded by
upstream's finalizer ordering fix (effect PR 8154). Effect no longer depends on
msgpackr, so its build approval goes too.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Generated with:
  grep -rl 'effect/unstable/' apps packages tools --include='*.ts' \
    | xargs sed -i '' 's#\(["'\''\]\)effect/unstable/#\1effect/#g'

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…scalCase 4.0 names

Flag.string/boolean/integer/choice/choiceWithValue, Argument.string/choice,
Primitive.boolean/integer/keyValuePair, GlobalFlag.setting, and
Config.string/redacted/literals became String/Boolean/Int/Literals/ChoiceWithValue,
KeyValuePair, Setting, and Redacted in effect 4.0.0-rc.113 (effect PRs 7453, 8121).
Generated with a perl word-boundary substitution over apps, packages, and tools.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ss-property option

SchemaAST.Union.mode moved under options (effect PR 8131) and
ToJsonSchemaOptions.additionalProperties became onExcessProperty (effect PR 8147).
The generated document is unchanged.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… Socket APIs

Server addresses are NetAddress.SocketAddress values (effect PR 7524), File.seek and
File.Info.size use bigint and ByteSize (effect PR 8108), Encoding moved to
effect/encoding/Base64Url (effect PR 8356), and Socket.runString was replaced by the
reader and writer pair (effect PR 7487). The Proxy comment now describes the
listener contract instead of naming a release candidate.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ol idle timeout

Parse-option annotations no longer influence decoding (effect PR 8131), so the
initialization command and runCommand payload schemas reject unknown keys through a
Record filter ahead of the struct decode. @effect/sql-pg 4.0.1 raised the default
pool idle timeout from 10 to 60 seconds (effect PR 8679); the stack's Postgres
layers pin the previous value.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ient

@effect/sql-pg 4.0 is a native client and dropped PgClient.fromPool (effect PR 7426).
The remote session keeps its node-postgres pool for the zero idle timeout, the
per-connection role step-down hook, and raw COPY connections, so a local
SqlClient.make adapter over that pool replaces the removed bridge with the same
statement execution, cancellation, and error classification.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ptions

Encoding moved to effect/encoding/Base64Url (effect PR 8356), the Int and Finite
primitives replaced Integer and Float (effect PR 8121), File.Info.size is a ByteSize,
and onExcessProperty "preserve" was removed in favour of the default "ignore"
(effect PR 8131).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…0 paths

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…der effect 4.0

Schema.toJsonSchemaDocument now exports an isPattern check only when its RegExp
uses the Unicode flag (effect PR 8482); without it the compute and function name
patternProperties selectors and the env() pattern disappeared from the published
schema. The flag does not change what these ASCII patterns accept.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…fect 4.0

Schema.toJsonSchemaDocument now leaves unmodeled properties open by default
(effect PR 8147); passing onExcessProperty "error" restores additionalProperties
false on every struct in the published schema.json.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Upstream's finalizer ordering fix (effect PR 8154) covers the abort hook, so the
patch now only adds what the stack's effect-timeout tests assert: rejecting with
the pretty errors themselves and reporting a finalizer failure after a timeout.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… wording

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@effect/sql-pg 4.0 runs every query through the extended protocol, which rejects
multi-command strings (effect PR 7426). The realtime schema bootstrap runs as two
statements, and the generated ALTER ROLE and ALTER DATABASE batches come back from
Postgres as an array and execute one at a time inside the same transaction. Tests
that seeded fixtures through the client do the same.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@kanadgupta kanadgupta added the run-ci Run full develop CI (tests) on drafts and non-develop PRs. label Oct 5, 2026
kanadgupta and others added 5 commits October 5, 2026 14:54
… effect 4.0

The 4.0 generator writes a boolean additionalProperties on pattern-keyed records
and renders an empty struct as not-null (effect PRs 8131 and 8147), neither of
which has a per-schema setting. Both published documents now go through one
assembler that leaves pattern-keyed records open, and empty bucket tables are
modelled as an object-or-array union so they render as before. schema.json and
project-schema.json match the develop build byte for byte.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Re-applies the effect 4.0 import path and constructor rewrites to the files
develop changed, adapts the new TCP listener to NetAddress, the helper scope to
Scope.Closeable, the scheduler probe to fiber.cache, and the cron test to the
scoped listen queue with one statement per query.

Generated with AI

Co-Authored-By: Claude <noreply@anthropic.com>
Patch release only; the vitest runner patch is re-keyed to 4.0.2 with the same
content, and the stack functions bootstrap bundle is regenerated after the merge.

Generated with AI

Co-Authored-By: Claude <noreply@anthropic.com>
The native client rejects batched statements and decodes net.http_get's bigint
request id as a bigint, so the test casts it to text.

Generated with AI

Co-Authored-By: Claude <noreply@anthropic.com>
@kanadgupta kanadgupta changed the title chore(deps): upgrade effect to 4.0.1 chore(deps): upgrade effect to 4.0.2 Oct 8, 2026
jgoux added 7 commits October 9, 2026 09:33
….0.2

4.0.2 still removes the stdin sink's error listener before the final end()
flush, so a child that exits before reading its input raises EPIPE as an
uncaught exception on Linux. Effect PRs 7712 and 7714 did not cover this path.
The 4.0.2 schema codegen emits code-point length checks and Unicode-flagged
patterns.
The excess-key check encodes through an Unknown record, which the RPC JSON
codec rejects when a nested optional field is explicitly undefined. Encoding
now drops undefined entries, as the plain struct codec did.
The reset e2e fixture runs one statement per query and reads count(*) as int,
since the native client rejects batches and decodes int8 as bigint. HTTP client
spans are named after the bare method by default.
Effect 4.0.2 records no HTTP client headers on spans unless a header filter
opts in, so the owner tracing test checks for request spans and that the
secret appears in no span attribute.
…nses

Bun resets a Connection: close client when the response completes before its request body
is fully read, so an upstream that answers early could truncate the proxied response.
The proxy now drains the remaining request body and ends the response afterwards.
…er test

The 200ms timeout also covered the fsync-bound save and fired under load. A leaked lock
still fails the test through the busy error once the lock retry window ends.
@jgoux
jgoux marked this pull request as ready for review October 9, 2026 12:50
@jgoux
jgoux requested review from a team and supabase-oss as code owners October 9, 2026 12:50
@jgoux

jgoux commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

/ai-review

@github-actions github-actions Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Superseded by a newer AI review

🤖 AI Review

Verified all 12 findings and merged three duplicates into nine entries: seven confirmed and two refuted. The main concerns are cancellation through the occupied PostgreSQL pool and stalled delivery of early upstream responses. Payload validation also accepts inherited property names; remaining confirmed concerns are documentation or latent robustness limitations. Full repository tests were not run.

Findings

Severity Location Category Sources Claim
🟠 MAJOR apps/cli/src/command-internal/db-connection.pool-client.ts:203 cancellation codex Cancellation queues behind the statement it must cancel. After five seconds, cleanup can release the still-running connection without destroying it, allowing interrupted SQL to continue executing.
🟠 MAJOR packages/stack/src/HttpProxy.ts:401 http-proxy claude+codex Early upstream responses now wait for the entire incoming request body before the proxy ends its response. For an empty rejection, headers also remain unsent, so a streaming client waiting for that rejection can stall.
🟡 MINOR packages/stack/src/internal/reject-excess-keys.ts:27 input-validation claude+codex The excess-key filter accepts undeclared Object.prototype property names, including constructor, toString, and proto.
⚪ NIT apps/cli/src/command-internal/db-connection.sql-pg.layer.ts:6 documentation claude The layer comments still describe pg as @effect/sql-pg's transitive driver and describe the layer as backed by its pure-JavaScript driver, although the PR replaces that bridge with a local adapter.
⚪ NIT packages/stack/src/internal/reject-excess-keys.ts:3 robustness claude The encoding helper converts every non-array object into a plain object, which would corrupt non-JSON encoded values such as Date or Uint8Array. Current callers do not contain such values.
⚪ NIT .agents/skills/effect/references/CONFIG.md:13 documentation claude+codex The configuration reference only partially migrates its example: Config.String is updated, while Config.redacted and Config.boolean retain the obsolete lowercase constructor names.
⚪ NIT apps/cli/src/command-internal/db-connection.pool-client.ts:188 streaming codex executeStream buffers the complete query result before emitting rows, rather than providing incremental database streaming.
Refuted findings (kept for transparency, not posted as review comments)
  • apps/cli/src/command-internal/db-connection.pool-client.ts:32 (transaction-integrity): The adapter does not pin a physical connection for transactions or reservations, so a multi-client pool could execute transaction statements on different PostgreSQL backends.
    Refuted: The claimed multi-backend failure is prevented by the actual production configuration: the sole caller uses max: 1 with idleTimeoutMillis: 0. Its returned DbSession exposes ordinary execution methods, not withTransaction or reserve, and the SqlClient remains internal. The general limitation is real, but the reported transaction failure has no current call path.
  • packages/stack/src/namespace/Namespace.integration.test.ts:605 (test-coverage): Removing the 200 ms timeout weakens the interrupted-holder test by allowing a leaked lock to be released late within the busy-retry window.
    Refuted: The test establishes holder completion before the second acquisition, and production cleanup releases the lock synchronously within the awaited scope finalizer. There is no later cleanup task that can release a leaked lock during retries. A leaked lock still exhausts the five-second retry window and fails the test. The removed timeout guarded elapsed runtime, rather than adding coverage of the stated leakage regression.

Stats

Claude findings: 6 · Codex findings: 6 · Confirmed: 7 · Refuted: 2 · Uncertain: 0


Models: claude-opus-5-5 + gpt-6.1-sol · Trigger: auto · Workflow run

This review runs once per PR. A maintainer can request another with a /ai-review comment.

Comment thread apps/cli/src/command-internal/db-connection.pool-client.ts
Comment thread packages/stack/src/HttpProxy.ts Outdated
Comment thread packages/stack/src/internal/reject-excess-keys.ts Outdated
Comment thread apps/cli/src/command-internal/db-connection.sql-pg.layer.ts Outdated
Comment thread packages/stack/src/internal/reject-excess-keys.ts
Comment thread .agents/skills/effect/references/CONFIG.md Outdated
Comment thread apps/cli/src/command-internal/db-connection.pool-client.ts
…keys

The proxy flushes upstream response headers immediately, so a client still uploading its body
receives an early rejection instead of waiting for the upload to finish. Strict payloads now
reject undeclared keys that exist on Object.prototype, such as constructor. Also refreshes the
pg driver notes in the CLI database layer and the Config constructor names in the Effect skill.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 AI Review

Verified all nine reported findings and merged two overlapping pairs into seven entries. Confirmed the cancellation failure, early-response hang, excess-key validation gap, and stale driver documentation. Current callers limit the impact of the transaction, streaming, and nonplain-object encoding concerns; transaction severity was reduced to minor. Verification included surrounding code, trusted ADRs, and in-memory checks; full Effect runtime tests were unavailable because dependencies are not installed.

Findings

Severity Location Category Sources Claim
🟠 MAJOR apps/cli/src/command-internal/db-connection.pool-client.ts:198 cancellation claude+codex Interrupting a long query queues cancellation behind the same occupied single-connection pool. After five seconds, cleanup releases the still-executing connection, while the timed-out cancellation request remains queued.
🟠 MAJOR packages/stack/src/HttpProxy.ts:364 http-proxy codex An early chunked upstream response cannot complete until the client finishes uploading its request body, so a client that stops uploading after rejection can hang.
🟡 MINOR apps/cli/src/command-internal/db-connection.pool-client.ts:32 transaction-isolation codex The adapter does not pin a physical pool connection for SQL transactions or reservations.
🟡 MINOR apps/cli/src/command-internal/db-connection.pool-client.ts:188 streaming codex The adapter's executeStream buffers the complete query result before emitting its first row.
🟡 MINOR packages/stack/src/internal/reject-excess-keys.ts:27 input-validation claude+codex The excess-key guard accepts undeclared keys inherited from Object.prototype, including toString and constructor.
⚪ NIT packages/stack/src/internal/reject-excess-keys.ts:3 correctness claude The recursive encoding helper replaces every non-array object with a plain record, corrupting nonplain encoded values if the generic wrapper is used with such schemas.
⚪ NIT apps/cli/src/command-internal/db-connection.sql-pg.layer.ts:6 documentation codex The driver comment incorrectly describes pg as an @effect/sql-pg transitive dependency and requires alignment with a version that package no longer resolves.

Stats

Claude findings: 3 · Codex findings: 6 · Confirmed: 7 · Refuted: 0 · Uncertain: 0


Models: claude-opus-5-5 + gpt-6.1-sol · Trigger: manual · Workflow run

This review runs once per PR. A maintainer can request another with a /ai-review comment.

Comment thread apps/cli/src/command-internal/db-connection.pool-client.ts
Comment thread packages/stack/src/HttpProxy.ts Outdated
Comment thread apps/cli/src/command-internal/db-connection.pool-client.ts
Comment thread apps/cli/src/command-internal/db-connection.pool-client.ts
Comment thread packages/stack/src/internal/reject-excess-keys.ts
Comment thread packages/stack/src/internal/reject-excess-keys.ts
Comment thread apps/cli/src/command-internal/db-connection.sql-pg.layer.ts
A client that stops uploading after an early upstream response no longer holds the proxied
response open: the proxy ends it once the body drains or after two seconds, like a lingering
close.
Comment thread apps/cli/src/command-internal/db-connection.pool-client.ts
@kanadgupta
kanadgupta added this pull request to the merge queue Oct 9, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Oct 9, 2026
jgoux added 2 commits October 9, 2026 15:48
# Conflicts:
#	packages/stack/src/storage/DockerDatabaseStorage.ts
#	packages/stack/tests/helper-owner-fixture.ts
# Conflicts:
#	packages/stack/src/HttpProxy.ts
#	packages/stack/src/Network.integration.test.ts
@kanadgupta
kanadgupta enabled auto-merge October 9, 2026 14:47
@kanadgupta
kanadgupta added this pull request to the merge queue Oct 9, 2026
Merged via the queue into develop with commit b5bba60 Oct 9, 2026
30 checks passed
@kanadgupta
kanadgupta deleted the kanad-claude/effect-v4-upgrade-e27f7d branch October 9, 2026 14:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

run-ci Run full develop CI (tests) on drafts and non-develop PRs.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants