Let a containerized coder reach a dev server on its host

f1eae73635e5 · AtlantisPleb · · parent 0dbb23cc2e0b

Let a containerized coder reach a dev server on its host

http is allowed only for loopback, and inside a local Docker container
the host machine's loopback is reachable only as host.docker.internal —
the Gym's Harbor lane runs the coder in benchmark containers against
the dev forge on the host. Reaching anything beyond the developer's own
machine still requires HTTPS.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GoYpb8FEmdxVErsv7ABCYi
Co-Authored-By
Claude Fable 5 <noreply@anthropic.com>

Deploy story

What this commit did to the running system — joined from the forge receipt chain, the part a commit page elsewhere cannot show.

Not deployed through the forge lane

No push, promotion, build, or deploy receipt references this commit (receipts are scanned over a bounded recent window). Changes shipped by full node replacement carry their proof in the release gate receipt instead.

Changed files

  • modified packages/openagents-cli/src/endpoint.ts
  • modified packages/openagents-cli/test/endpoint.test.ts

Diff

2 files changed, +14 -1

packages/openagents-cli/src/endpoint.ts modified +8 -1

@@ -34,7 +34,14 @@ export const loopbackHostname = (hostname: string): boolean => {

34 34
    normalized === "127.0.0.1" ||
35 35
    normalized.startsWith("127.") ||
36 36
    normalized === "[::1]" ||
37
    normalized === "::1"
37
    normalized === "::1" ||
38
    // The container-to-host development path: inside a local Docker
39
    // container, the host machine's loopback is reachable only by this
40
    // name. A benchmark container running the coder against a dev server
41
    // on the host (the Gym's Harbor lane) has no other address for it.
42
    // Reaching anything beyond the developer's own machine still requires
43
    // HTTPS.
44
    normalized === "host.docker.internal"
38 45
  );
39 46
};
40 47
packages/openagents-cli/test/endpoint.test.ts modified +6

@@ -73,6 +73,12 @@ describe("endpoint configuration", () => {

73 73
    );
74 74
  });
75 75
76
  it("allows the container-to-host development name over HTTP", async () => {
77
    await expect(
78
      Effect.runPromise(normalizeApiOrigin("http://host.docker.internal:4000")),
79
    ).resolves.toBe("http://host.docker.internal:4000");
80
  });
81
76 82
  it("refuses non-loopback HTTP and URL paths", async () => {
77 83
    const insecure = await Effect.runPromiseExit(normalizeApiOrigin("http://openagents.com"));
78 84
    const path = await Effect.runPromiseExit(normalizeApiOrigin("https://openagents.com/api"));

This page updates live while a promote is in flight · changelog