| 1 | # Railway GraphQL migration verification |
| 2 | |
| 3 | The providers use `@distilled.cloud/railway`. Every operation is a |
| 4 | `Query.fn` whose builder reads only the fields it needs; shared projection |
| 5 | functions describe resource attributes, and reconcile plans add only fields |
| 6 | needed for decisions. Nested connection helpers in `src/Railway/GraphQL.ts` |
| 7 | take a projection function and paginate all results with `Query.items`. |
| 8 | Service listing walks actual environment service instances instead of |
| 9 | probing every service/environment combination. |
| 10 | |
| 11 | The SDK's [client guide](../../../../submodules/distilled/packages/railway/README.md) |
| 12 | describes `Query.fn` plans, pagination, per-root typed errors, and retry |
| 13 | behavior. Its [patch evidence](../../../../submodules/distilled/packages/railway/patches/graphql/README.md) |
| 14 | records observed wire errors and the contracts generated from them. |
| 15 | |
| 16 | ## Run isolated live tests |
| 17 | |
| 18 | Use a dedicated project and stage when another worktree might be testing |
| 19 | Railway. The final component of the project name must follow Alchemy's |
| 20 | physical-name suffix rules; `graphqltest` is a valid suffix. |
| 21 | |
| 22 | ```sh |
| 23 | timeout -k 5 240 doppler run --project alchemy-v2 --config dev -- \ |
| 24 | env ALCHEMY_TEST_STAGE=test_graphql_f9c5 \ |
| 25 | RAILWAY_TEST_PROJECT_NAME=alchsuite-graphqltest \ |
| 26 | pnpm test test/Railway/Postgres.test.ts \ |
| 27 | --profile testing --retry 0 --concurrency 1 |
| 28 | ``` |
| 29 | |
| 30 | Tests own separate environments within the project. Use bounded batches; |
| 31 | the command's deadline is a failure, not a reason to repeat it blindly. |
| 32 | Credentials come from the configured profile/environment and never belong |
| 33 | in test output or fixtures. The dedicated project can be removed after all |
| 34 | of its tests finish; do not remove another worktree's shared suite project. |
| 35 | |
| 36 | ## Live flywheel findings |
| 37 | |
| 38 | Verified during the September 12, 2026 migration: |
| 39 | |
| 40 | The run records 52 distinct passing live Railway checks. After standardizing |
| 41 | deletion confirmation, the final affected batches pass 17 lifecycle checks |
| 42 | (two documented gates) and all three database CRUD checks again. |
| 43 | |
| 44 | - Project, environment, variable, group, service, domain, TCP proxy, usage, |
| 45 | login session, audit log, cloud agent, and sandbox test paths use selective |
| 46 | operations. Entitlement probes retain exact tagged failures. |
| 47 | - Bucket CRUD and S3 object round trips pass. Credential creation can lag |
| 48 | bucket creation; its exact observed failure is patched and readiness is |
| 49 | bounded. |
| 50 | - Private-network CRUD/rename and template deployment/list/delete regressions |
| 51 | are enabled and pass. Network identifiers accept the actual BigInt wire |
| 52 | representation. Inaccessible template metadata stays optional. |
| 53 | - Mongo, MySQL, Postgres, and Redis CRUD, query/ping, update, listing, and |
| 54 | deletion pass. Mongo and MySQL deployed Service integrations pass. |
| 55 | Postgres's deployed Service and Function SQL integrations pass. The MySQL |
| 56 | fixture uses an exact dependency record to avoid ambiguous lockfile versions. |
| 57 | - Function canvas lifecycle and async HTTP lifecycle pass. Owned services |
| 58 | are deleted globally; deleting only an environment instance and waiting |
| 59 | for the whole service to disappear was an incorrect convergence check. |
| 60 | - Redis and bucket bindings pass deployed runtime round trips. |
| 61 | - CDN create/update/disable passes direct selective read-back assertions. |
| 62 | It waits for a public domain to be ready and sends Railway's lowercase |
| 63 | HTML-caching values. A pathless generic failure is classified without |
| 64 | inventing a field-specific cause or an entitlement restriction. |
| 65 | - Thirteen website/CDN cases pass: Astro, CDN, Next.js, Nuxt, |
| 66 | Octane, React Router, SolidStart, StaticSite, SvelteKit, TanStack Start, |
| 67 | Vite, Vocs, and Waku. This covers deployment, HTTP serving, and deletion; |
| 68 | the dedicated CDN case also checks update and disablement. |
| 69 | |
| 70 | The Postgres runtime check also exposed a shared SQL-driver compatibility |
| 71 | issue: Railway URLs use `sslmode=no-verify`, which Effect's parser rejects. |
| 72 | `SQL/PostgresTls.ts` normalizes the URL and explicit TLS options together, |
| 73 | preserving caller overrides and redacted credentials. SNI is now handled by |
| 74 | the upstream driver. A parser-level local |
| 75 | regression covers this without opening a network connection. |
| 76 | |
| 77 | ## Local verification |
| 78 | |
| 79 | ```sh |
| 80 | bun test submodules/distilled/packages/core/src/graphql.test.ts \ |
| 81 | submodules/distilled/packages/core/src/codegen/graphql-client.test.ts \ |
| 82 | submodules/distilled/packages/railway/test/graphql.test.ts |
| 83 | pnpm exec tsc -b |
| 84 | timeout -k 5 240 pnpm test test/SQL/PostgresTls.test.ts --profile testing |
| 85 | timeout -k 5 60 pnpm test test/Railway/GraphQL.local.test.ts --retry 0 --sequential |
| 86 | pnpm docs:gen |
| 87 | pnpm docs:check-jsdoc |
| 88 | ``` |
| 89 | |
| 90 | The GraphQL suites cover selected result/error types, aliases, fragments, |
| 91 | partial responses, multiple simultaneous errors, null propagation, variables, |
| 92 | pagination, scalar validation, generated symbol collisions, and deterministic |
| 93 | regeneration. The migration run passes 64 GraphQL tests and 12 TLS tests; |
| 94 | four virtual-clock deletion tests prove that exhausted polling fails explicitly |
| 95 | and preserves typed query errors. The full workspace type-check and JSDoc |
| 96 | check pass. |
| 97 | |
| 98 | These results were recorded on Effect rc.113 before rebasing onto the rc.115 |
| 99 | upgrade in main. The rebase preserves upstream removal of the SNI shim and |
| 100 | adapts the no-verify normalization tests. The rc.115 results below supersede |
| 101 | that earlier validation record. |
| 102 | |
| 103 | ## Single-invocation verification on Effect rc.115 |
| 104 | |
| 105 | Both Foldkit tests are explicitly skipped for the fixture's incompatible Effect |
| 106 | API. The complete Railway directory was then selected in one invocation: |
| 107 | |
| 108 | ```sh |
| 109 | timeout -k 5 240 doppler run --project alchemy-v2 --config dev -- \ |
| 110 | env ALCHEMY_TEST_STAGE=test_graphql_whole \ |
| 111 | RAILWAY_TEST_PROJECT_NAME=alchsuite-graphqlwhole \ |
| 112 | pnpm test test/Railway --profile testing --retry 0 --concurrency 8 --sequential |
| 113 | ``` |
| 114 | |
| 115 | The runner collected 55 files / 85 tests. At the 240-second deadline it had |
| 116 | recorded **64 passed, 5 failed, 9 skipped, and 7 unfinished**; the command |
| 117 | exited 124. This was not a complete run or a passing suite. |
| 118 | |
| 119 | - Group creation and the canvas Function lifecycle failed on |
| 120 | `GraphQLTransportError` with HTTP 503 and a non-GraphQL response. |
| 121 | - The bindings fixture's `beforeAll` failed on the same HTTP 503, preventing |
| 122 | its three tests from running; the runner counted them as failures. |
| 123 | - Template deployment/list/delete passed in the shared single-process run. |
| 124 | - SolidStart, StaticSite, SvelteKit, TanStackStart, Vite, Vocs, and Waku cloud |
| 125 | tests were still running at the deadline; they have no final outcome. |
| 126 | - Nine skips comprise both Foldkit tests and the seven pre-existing gates |
| 127 | described below. No additional tests were disabled. |
| 128 | |
| 129 | The preceding complete rc.115 run in separate batches recorded 74 passed, |
| 130 | 4 failed, and 7 skipped. Those failures were both Foldkit tests, template |
| 131 | service discovery, and StaticSite domain creation. Its separate SDK and TLS |
| 132 | checks passed 64 and 9 tests respectively. The workspace type-check reported |
| 133 | three AWS SigningError contract mismatches in DbAuthToken and S3 presigning. |
| 134 | |
| 135 | ## Explicit coverage limits |
| 136 | |
| 137 | - Three existing Effect-native Function/RPC cases exceed the canvas command's |
| 138 | 96 KiB limit and remain skipped. The smaller Function and runtime binding |
| 139 | cases above are exercised. |
| 140 | - Backup entitlement, connected GitHub repositories, and external ACME DNS |
| 141 | require their documented test environment variables. |
| 142 | - Foldkit's local and cloud tests explicitly use `test.provider.skip`: |
| 143 | installed `foldkit@0.148.2` requires `SchemaTransformation.transformOrFail`, |
| 144 | which is unavailable in the workspace's Effect rc.115. Re-enable both |
| 145 | when the fixture is compatible with the workspace Effect version. |
| 146 | - The existing Vocs local test remains skipped for its fixture cwd issue. |
| 147 | |
| 148 | These limits must not be reported as passing live coverage. |