import { describe, expect, test, spyOn } from "bun:test"; import { inspect } from "node:util"; import * as Cause from "effect/Cause"; import * as Effect from "effect/Effect"; import * as Exit from "effect/Exit"; import * as Layer from "effect/Layer"; import * as Redacted from "effect/Redacted"; import * as Schema from "effect/Schema"; import * as Stream from "effect/Stream"; import * as HttpClient from "effect/http/HttpClient"; import * as HttpClientRequest from "effect/http/HttpClientRequest"; import * as HttpClientResponse from "effect/http/HttpClientResponse"; import * as FetchHttpClient from "effect/http/FetchHttpClient"; import { fromApiKey } from "./credentials.ts"; import * as Neon from "./services/neon.ts"; import { Retry } from "./retry.ts"; const scope = { project_id: "project-fixture", branch_id: "br-fixture" }; const harness = ( respond: (request: HttpClientRequest.HttpClientRequest) => Response, ) => Layer.mergeAll( fromApiKey({ apiKey: "fixture-account-secret" }), Layer.succeed(Retry, { while: () => false }), Layer.succeed( HttpClient.HttpClient, HttpClient.make((request) => Effect.sync(() => HttpClientResponse.fromWeb(request, respond(request)), ), ), ), ); const secret = { token_id: "nak_fixture", token_id_short: "fixture", api_token: "fixture-api-secret", s3_secret_access_key: "fixture-s3-secret", scopes: ["storage:read"], branch_id: scope.branch_id, principal_type: "user", created_at: "2026-09-17T00:00:00Z", }; const deployment = { id: 7, status: "completed", memory_mib: 256, runtime: "nodejs24", created_at: "2026-09-17T00:00:00Z", environment: ["SECRET"], }; const roundTrip = (codec: Schema.Codec, value: A): A => Schema.encodeSync(codec)(Schema.decodeUnknownSync(codec)(value)); describe("Neon backend wire contracts", () => { test("hard_delete remains an optional query parameter, never a body field", async () => { for (const hard_delete of [true, false, undefined]) { await Effect.runPromise( Neon.deleteProjectBranch({ ...scope, hard_delete }).pipe( Effect.provide( harness((request) => { expect(request.method).toBe("DELETE"); expect(new URL(request.url).searchParams.get("hard_delete")).toBe( hard_delete === undefined ? null : String(hard_delete), ); expect(request.body._tag).toBe("Empty"); return Response.json({ branch: { id: scope.branch_id }, operations: [], }); }), ), ), ); } }); test("sensitive environment codecs validate and encode plain or redacted strings", () => { const plain = JSON.stringify({ SECRET: "fixture-env-secret" }); const codec = Neon.CreateProjectBranchFunctionDeploymentRequest; const decode = Schema.decodeUnknownSync(codec); const encode = Schema.encodeSync(codec); const encodeJson = Schema.encodeSync(Schema.toCodecJson(codec)); for (const environment of [ plain, Redacted.make(plain), Redacted.make(plain, { label: "environment" }), ]) { const input = { ...scope, slug: "fixture", environment }; const label = typeof environment === "string" ? undefined : environment.label; const decoded = decode(input); for (const output of [decoded, encode(decoded)]) { if (typeof environment === "string") { expect(output.environment).toBe(plain); } else { // Effect may rebuild a Redacted wrapper around the decoded value. if (!Redacted.isRedacted(output.environment)) { throw new Error("Expected a redacted environment"); } expect(Redacted.value(output.environment)).toBe(plain); expect(output.environment.label).toBe(label); expect(JSON.stringify(output)).not.toContain("fixture-env-secret"); expect(inspect(output)).not.toContain("fixture-env-secret"); expect(() => encodeJson(output)).toThrow(); expect(Redacted.value(environment)).toBe(plain); expect(environment.label).toBe(label); } expect(input.environment).toBe(environment); } } expect(() => decode({ ...scope, slug: "fixture", environment: Redacted.make(123) }), ).toThrow(); expect(() => decode({ ...scope, slug: "fixture", environment: 123 }), ).toThrow(); }); test("returned credential and presign codecs preserve redaction when validating and encoding", async () => { const layer = harness(() => Response.json(secret)); const issued = await Effect.runPromise( Neon.createCredential({ ...scope, principal_type: "user", scopes: ["storage:read"], }).pipe(Effect.provide(layer)), ); const revealed = await Effect.runPromise( Neon.revealCredential({ ...scope, token_id: secret.token_id }).pipe( Effect.provide(layer), ), ); const rotated = await Effect.runPromise( Neon.rotateCredential({ ...scope, token_id: secret.token_id }).pipe( Effect.provide(layer), ), ); for (const value of [ roundTrip(Neon.CreateCredentialResponse, issued), roundTrip(Neon.CredentialSecret, revealed), roundTrip(Neon.RotateCredentialResponse, rotated), ]) { expect(Redacted.isRedacted(value.api_token)).toBe(true); expect(Redacted.isRedacted(value.s3_secret_access_key)).toBe(true); expect(JSON.stringify(value)).not.toContain("fixture-api-secret"); expect(JSON.stringify(value)).not.toContain("fixture-s3-secret"); } const presign = await Effect.runPromise( Neon.presignProjectBranchBucketObject({ ...scope, bucket_name: "fixture", object_key: "file.bin", operation: "upload", }).pipe( Effect.provide( harness(() => Response.json({ url: "https://fixture.test/?signature=fixture-secret", method: "PUT", headers: {}, expires_at: "2026-09-17T00:15:00Z", }), ), ), ), ); const encoded = roundTrip(Neon.PresignResponse, presign); expect(Redacted.isRedacted(encoded.url)).toBe(true); expect(JSON.stringify(encoded)).not.toContain("fixture-secret"); expect(() => Schema.encodeSync(Schema.toCodecJson(Neon.PresignResponse))(presign), ).toThrow(); expect(() => Schema.decodeUnknownSync(Neon.CredentialSecret)({ ...revealed, api_token: Redacted.make(123), }), ).toThrow(); expect(() => Schema.decodeUnknownSync(Neon.PresignResponse)({ ...presign, url: Redacted.make(123), }), ).toThrow(); }); test("ZIP bytes and one JSON environment string survive the generated operation", async () => { const zip = new File([new Uint8Array([80, 75, 0, 255])], "bundle.zip", { type: "application/zip", }); const environment = JSON.stringify({ SECRET: "fixture-env-secret", REMOVE: "", }); let form: FormData | undefined; const result = await Effect.runPromise( Neon.createProjectBranchFunctionDeployment({ ...scope, slug: "fixture", zip, environment: Redacted.make(environment), }).pipe( Effect.provide( harness((request) => { expect(request.headers.authorization).toBe( "Bearer fixture-account-secret", ); if (request.body._tag !== "FormData") throw new Error("Expected multipart"); form = request.body.formData; expect(form.getAll("environment")).toEqual([environment]); expect((form.get("zip") as File).name).toBe("bundle.zip"); return Response.json({ deployment }); }), ), ), ); expect( new Uint8Array(await (form!.get("zip") as File).arrayBuffer()), ).toEqual(new Uint8Array([80, 75, 0, 255])); expect(result.deployment.id).toBe(7); expect(result.deployment.environment).toEqual(["SECRET"]); }); test("config-only deployment omits ZIP and preserves empty deletion values", async () => { await Effect.runPromise( Neon.createProjectBranchFunctionDeployment({ ...scope, slug: "fixture", environment: JSON.stringify({ REMOVE: "" }), }).pipe( Effect.provide( harness((request) => { if (request.body._tag !== "FormData") throw new Error("Expected multipart"); expect(request.body.formData.has("zip")).toBe(false); expect(request.body.formData.getAll("environment")).toEqual([ '{"REMOVE":""}', ]); return Response.json({ deployment }); }), ), ), ); }); test("declared Function and Trigger not-found errors retain their typed class", async () => { const functionMessage = "function not visible on branch"; const functionError = await Effect.runPromise( Neon.getProjectBranchFunction({ ...scope, slug: "missing" }).pipe( Effect.flip, Effect.provide( harness(() => Response.json({ message: functionMessage }, { status: 404 }), ), ), ), ); expect(functionError).toBeInstanceOf(Neon.NotFound); expect(functionError.message).toBe(functionMessage); const triggerMessage = "function trigger not visible on branch"; const triggerError = await Effect.runPromise( Neon.getProjectBranchTrigger({ ...scope, trigger_id: "missing" }).pipe( Effect.flip, Effect.provide( harness(() => Response.json({ message: triggerMessage }, { status: 404 }), ), ), ), ); expect(triggerError).toBeInstanceOf(Neon.NotFound); expect(triggerError.message).toBe(triggerMessage); }); test("nullable Function/deployment fields validate without inventing values", () => { const empty = Schema.decodeUnknownSync(Neon.NeonFunction)({ id: "fixture", slug: "fixture", name: "fixture", invocation_url: "", created_at: "2026-09-17T00:00:00Z", current_deployment: null, active_deployment: null, }); expect(empty.current_deployment).toBeNull(); expect(empty.active_deployment).toBeNull(); const pending = Schema.decodeUnknownSync(Neon.NeonFunctionDeployment)({ ...deployment, status: "pending", environment: null, error: null, }); expect(pending.error).toBeNull(); expect(pending.environment).toBeNull(); }); test("issue, reveal and rotate redact both credential secrets", async () => { const layer = harness(() => Response.json(secret)); for (const operation of [ Neon.createCredential({ ...scope, principal_type: "user", scopes: ["storage:read"], }), Neon.revealCredential({ ...scope, token_id: secret.token_id }), Neon.rotateCredential({ ...scope, token_id: secret.token_id }), ]) { const result = await Effect.runPromise( operation.pipe(Effect.provide(layer)), ); expect(Redacted.isRedacted(result.api_token)).toBe(true); expect(Redacted.isRedacted(result.s3_secret_access_key)).toBe(true); expect(JSON.stringify(result)).not.toContain("fixture-api-secret"); expect(JSON.stringify(result)).not.toContain("fixture-s3-secret"); } }); test("binary downloads preserve invalid UTF-8 and nested object keys", async () => { const bytes = new Uint8Array([0, 255, 128, 80, 75]); const result = await Effect.runPromise( Neon.getProjectBranchBucketObject({ ...scope, bucket_name: "fixture", object_key: "nested/file.bin", }).pipe( Effect.provide( harness((request) => { expect(request.url).toContain("nested%2Ffile.bin/download"); return new Response(bytes, { headers: { "content-type": "application/octet-stream" }, }); }), ), ), ); expect(result).toEqual(bytes); }); test("binary body-read failures use the same defect channel as text responses", async () => { const exit = await Effect.runPromiseExit( Neon.getProjectBranchBucketObject({ ...scope, bucket_name: "fixture", object_key: "broken.bin", }).pipe( Effect.provide( harness( () => new Response( new ReadableStream({ start(controller) { controller.error(new Error("body read failed")); }, }), ), ), ), ), ); expect(Exit.isFailure(exit)).toBe(true); if (Exit.isFailure(exit)) { expect(Cause.hasDies(exit.cause)).toBe(true); expect(Cause.hasFails(exit.cause)).toBe(false); } }); test("download redirects preserve bytes without forwarding account credentials across origins", async () => { const bytes = new Uint8Array([0, 255, 128, 80, 75]); let authorization: string | null | undefined; const storage = Bun.serve({ hostname: "127.0.0.1", port: 0, fetch(request) { authorization = request.headers.get("authorization"); return new Response(bytes, { headers: { "content-type": "application/octet-stream" }, }); }, }); const api = Bun.serve({ hostname: "127.0.0.1", port: 0, fetch() { return Response.redirect(storage.url, 302); }, }); try { const result = await Effect.runPromise( Neon.getProjectBranchBucketObject({ ...scope, bucket_name: "fixture", object_key: "file.bin", }).pipe( Effect.timeout("5 seconds"), Effect.provide( Layer.mergeAll( fromApiKey({ apiKey: "fixture-account-secret", apiBaseUrl: api.url.origin, }), FetchHttpClient.layer, Layer.succeed(Retry, { while: () => false }), ), ), ), ); expect(result).toEqual(bytes); expect(authorization).toBeNull(); } finally { await api.stop(true); await storage.stop(true); } }); test("bodyless trigger deletion decodes 204", async () => { await Effect.runPromise( Neon.deleteProjectBranchTrigger({ ...scope, trigger_id: "tr-fixture", }).pipe( Effect.provide( harness((request) => { expect(request.method).toBe("DELETE"); expect(request.body._tag).toBe("Empty"); return new Response(null, { status: 204 }); }), ), ), ); }); test("function pagination terminates at an empty cursor", async () => { let calls = 0; const pages = await Effect.runPromise( Neon.listProjectBranchFunctions.pages({ ...scope, limit: 1 }).pipe( Stream.runCollect, Effect.provide( harness((request) => { calls++; expect(calls).toBeLessThanOrEqual(2); if (calls === 2) expect(request.url).toContain("cursor=next"); return Response.json({ functions: [], pagination: { next: calls === 1 ? "next" : "" }, }); }), ), ), ); expect(pages).toHaveLength(2); expect(calls).toBe(2); }); test("debug diagnostics never emit request or response secrets", async () => { const previous = process.env.DISTILLED_DEBUG_HTTP; const logs: string[] = []; const spy = spyOn(console, "error").mockImplementation((...args) => { logs.push(args.join(" ")); }); process.env.DISTILLED_DEBUG_HTTP = "1"; try { await Effect.runPromise( Neon.createCredential({ ...scope, principal_type: "user", scopes: ["storage:read"], name: "private-label", }).pipe(Effect.provide(harness(() => Response.json(secret)))), ); expect(logs.length).toBeGreaterThan(0); const text = logs.join("\n"); for (const value of [ "fixture-account-secret", "fixture-api-secret", "fixture-s3-secret", "private-label", ]) expect(text).not.toContain(value); } finally { spy.mockRestore(); if (previous === undefined) delete process.env.DISTILLED_DEBUG_HTTP; else process.env.DISTILLED_DEBUG_HTTP = previous; } }); }); describe("Neon Auth email provider contracts", () => { const standard = { type: "standard" as const, host: "smtp.fixture.test", port: 587, username: "fixture-user", password: "fixture-smtp-secret", sender_email: "auth@fixture.test", sender_name: "Fixture Auth", }; test("redacted SMTP passwords reach the PATCH wire as plaintext", async () => { for (const password of [ standard.password, Redacted.make(standard.password), ]) { const result = await Effect.runPromise( Neon.updateNeonAuthEmailProvider({ ...scope, body: { ...standard, password }, }).pipe( Effect.provide( harness((request) => { expect(request.method).toBe("PATCH"); expect(request.url).toContain("/auth/email_provider"); if (request.body._tag !== "Uint8Array") throw new Error("Expected JSON bytes"); expect( JSON.parse(new TextDecoder().decode(request.body.body)), ).toEqual(standard); return Response.json({ ...standard, password: "" }); }), ), ), ); expect(result.type).toBe("standard"); if (result.type !== "standard") throw new Error("Expected SMTP response"); expect(Redacted.isRedacted(result.password)).toBe(true); } }); test("partial standard and shared updates preserve omitted fields on the wire", async () => { for (const body of [ { type: "standard" as const }, { type: "shared" as const }, ]) { await Effect.runPromise( Neon.updateNeonAuthEmailProvider({ ...scope, body }).pipe( Effect.provide( harness((request) => { if (request.body._tag !== "Uint8Array") throw new Error("Expected JSON bytes"); expect( JSON.parse(new TextDecoder().decode(request.body.body)), ).toEqual(body); return Response.json( body.type === "standard" ? { ...standard, password: "" } : body, ); }), ), ), ); } }); test("returned SMTP passwords stay redacted through codecs, JSON and diagnostics", async () => { const previous = process.env.DISTILLED_DEBUG_HTTP; const logs: string[] = []; const spy = spyOn(console, "error").mockImplementation((...args) => { logs.push(args.join(" ")); }); process.env.DISTILLED_DEBUG_HTTP = "1"; try { const result = await Effect.runPromise( Neon.getNeonAuthEmailProvider(scope).pipe( Effect.provide(harness(() => Response.json(standard))), ), ); for (const value of [ roundTrip(Neon.NeonAuthEmailServerConfigResponse, result), roundTrip(Neon.GetNeonAuthEmailProviderResponse, result), roundTrip(Neon.UpdateNeonAuthEmailProviderResponse, result), ]) { if (value.type !== "standard") throw new Error("Expected SMTP response"); expect(Redacted.isRedacted(value.password)).toBe(true); if (!Redacted.isRedacted(value.password)) throw new Error("Expected redacted password"); expect(Redacted.value(value.password)).toBe(standard.password); expect(JSON.stringify(value)).not.toContain(standard.password); expect(Bun.inspect(value)).not.toContain(standard.password); } expect(() => Schema.encodeSync( Schema.toCodecJson(Neon.NeonAuthEmailServerConfigResponse), )(result), ).toThrow(); expect(logs.length).toBeGreaterThan(0); expect(logs.join("\n")).not.toContain(standard.password); } finally { spy.mockRestore(); if (previous === undefined) delete process.env.DISTILLED_DEBUG_HTTP; else process.env.DISTILLED_DEBUG_HTTP = previous; } }); test("request and response unions validate required standard/shared discriminators", () => { const request = Schema.decodeUnknownSync(Neon.NeonAuthEmailServerConfig); const response = Schema.decodeUnknownSync( Neon.NeonAuthEmailServerConfigResponse, ); expect(request(standard)).toEqual(standard); expect(request({ type: "standard" })).toEqual({ type: "standard" }); expect(response(standard)).toEqual(standard); for (const decode of [request, response]) { expect(decode({ type: "shared" })).toEqual({ type: "shared" }); expect(decode({ type: "shared", sender_name: "Fixture" })).toEqual({ type: "shared", sender_name: "Fixture", }); for (const value of [ {}, { ...standard, type: "unsupported" }, { ...standard, type: null }, { type: "shared", sender_name: null }, { ...standard, password: null }, { ...standard, password: 123 }, { ...standard, password: Redacted.make(123) }, ]) expect(() => decode(value)).toThrow(); } expect(() => response({ type: "standard", sender_email: "auth@fixture.test" }), ).toThrow(); expect(() => Schema.decodeUnknownSync(Neon.StandardEmailServer)({ ...standard, type: "shared", }), ).toThrow(); expect(() => Schema.decodeUnknownSync(Neon.StandardEmailServerResponse)({ ...standard, type: "shared", }), ).toThrow(); expect(() => Schema.decodeUnknownSync(Neon.SharedEmailServer)({ type: "standard" }), ).toThrow(); }); test("request codecs preserve sensitive unions without permitting generic JSON encoding", () => { for (const password of [ standard.password, Redacted.make(standard.password), ]) { const body = { ...standard, password }; expect(roundTrip(Neon.NeonAuthEmailServerConfig, body)).toEqual(body); expect( roundTrip(Neon.UpdateNeonAuthEmailProviderRequest, { ...scope, body }) .body, ).toEqual(body); } expect(() => Schema.encodeSync( Schema.toCodecJson(Neon.UpdateNeonAuthEmailProviderRequest), )({ ...scope, body: { ...standard, password: Redacted.make(standard.password) }, }), ).toThrow(); }); }); describe("Neon trigger schemas", () => { test("both discriminated forms validate and mismatches fail", () => { const decode = Schema.decodeUnknownSync(Neon.TriggerCreateRequest); expect( decode({ type: "schedule", function_slug: "fixture", name: "daily", schedule: { cron: "0 0 * * *" }, }).type, ).toBe("schedule"); expect( decode({ type: "storage_object_created", function_slug: "fixture", name: "uploads", storage_object_created: { bucket_name: "uploads", prefix: "incoming/" }, }).type, ).toBe("storage_object_created"); expect(() => decode({ type: "schedule", function_slug: "fixture", name: "wrong", storage_object_created: { bucket_name: "uploads" }, }), ).toThrow(); expect(() => decode({ type: "unsupported", function_slug: "fixture", name: "wrong", schedule: { cron: "0 0 * * *" }, }), ).toThrow(); }); test("disabled and inherited schedules accept a null next occurrence", () => { const trigger = Schema.decodeUnknownSync(Neon.Trigger)({ type: "schedule", trigger_id: "tr-fixture", function_slug: "fixture", name: "daily", function_path: "/", schedule: { cron: "0 0 * * *" }, enabled: false, version: 1, next_run_at: null, inherited: true, }); expect(trigger.type).toBe("schedule"); }); });