Point RELEASE-003 at the origin check production runs

6b20baad3688 · AtlantisPleb · · parent 82e7ebb30f7f

Point RELEASE-003 at the origin check production runs

The invariant cited OpenAgentsWeb.AllowedOrigins and its test. Nothing
called that module: production origin validation is
OpenAgents.RuntimeConfig, reached from config/runtime.exs, and the
cited test covered code you could delete without changing behavior —
while the code that does the work was covered by nothing cited.

The dead module and its test are gone, RuntimeConfig's validation
gains the tests the claim needs (insecure origins, path-bearing
origins, query, fragment, and missing scheme all refused at startup),
and the evidence line and proof index name what actually runs.

The rewrite found a real hole while it was there: an origin with an
empty host passed validation, because the guard checked only that the
host was a binary. It now requires a non-empty one.

Built by a Devin child through the openagents coder's delegate tool;
1,704 web and runtime tests re-run before landing.

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.

pushed
by user · WAL seq 338 · 2026-08-25T05:22:02.171432Z

Changed files

  • modified INVARIANTS.md
  • modified lib/openagents/runtime_config.ex
  • deleted lib/openagents_web/allowed_origins.ex
  • modified test/openagents/runtime_config_test.exs
  • deleted test/openagents_web/allowed_origins_test.exs

Diff

5 files changed, +39 -79

INVARIANTS.md modified +3 -3

@@ -3264,8 +3264,8 @@ Production accepts the primary `PHX_HOST` plus explicitly configured HTTPS

3264 3264
aliases for Phoenix origin checks. Invalid, insecure, or path-bearing origins
3265 3265
fail startup rather than silently weakening socket validation.
3266 3266
3267
Evidence: `OpenAgentsWeb.AllowedOrigins`, `OpenAgentsWeb.AllowedOriginsTest`, and the
3268
production WebSocket read-back.
3267
Evidence: `OpenAgents.RuntimeConfig`, `config/runtime.exs`, and
3268
`test/openagents/runtime_config_test.exs`.
3269 3269
3270 3270
### RELEASE-004 — CI runs on owned infrastructure only, and gates every release
3271 3271

@@ -5252,7 +5252,7 @@ contract; the invariant prose above defines the assertion, not the filename.

5252 5252
| RELEASE-001 | `ops/ci/release-smoke.sh`, `test/openagents_web/controllers/health_controller_test.exs` |
5253 5253
| RELEASE-002 | `test/openagents/github_oauth/runtime_config_test.exs`, `ops/ci/reference-check.sh` |
5254 5254
| VAULT-001 | `test/openagents/machines/token_vault_test.exs`, `test/openagents/runtime_config_test.exs` |
5255
| RELEASE-003 | `test/openagents_web/allowed_origins_test.exs`, `ops/ci/release-smoke.sh` |
5255
| RELEASE-003 | `lib/openagents/runtime_config.ex`, `config/runtime.exs`, `test/openagents/runtime_config_test.exs` |
5256 5256
| RELEASE-004 | `ops/ci/gate.sh`, `test/openagents/forge/gate_receipt_test.exs`, `test/openagents/hosted_ci_absence_test.exs` |
5257 5257
| RELEASE-005 | `test/openagents/forge/relup_deployment_test.exs`, `test/openagents/forge/relup_node_test.exs`, `test/openagents/release/appup_test.exs`, `test/openagents/cluster/code_change_test.exs`, `test/openagents/forge/rolling_replacement_test.exs` |
5258 5258
| RELEASE-006 | `test/openagents/forge/rolling_boot_convergence_test.exs`, `test/openagents/forge/rolling_replacement_test.exs`, `test/openagents/forge/target_lifecycle_test.exs`, `test/openagents/forge/boot_converge_test.exs` |
lib/openagents/runtime_config.ex modified +1 -1

@@ -831,7 +831,7 @@ defmodule OpenAgents.RuntimeConfig do

831 831
    case URI.new(origin) do
832 832
      {:ok,
833 833
       %URI{scheme: "https", host: host, path: path, query: nil, fragment: nil, userinfo: nil}}
834
      when is_binary(host) and path in [nil, "", "/"] ->
834
      when is_binary(host) and host != "" and path in [nil, "", "/"] ->
835 835
        true
836 836
837 837
      _invalid ->
lib/openagents_web/allowed_origins.ex deleted -54

@@ -1,54 +0,0 @@

1
defmodule OpenAgentsWeb.AllowedOrigins do
2
  @moduledoc """
3
  Validates and normalizes the CORS/check origin allow-list for production.
4
5
  The primary host is always allowed. The optional alias list comes from a
6
  comma-separated environment string and is intended for Cloud Run generated
7
  URLs.
8
  """
9
10
  @primary_scheme "https"
11
12
  @doc """
13
  Returns a list of allowed origins for production.
14
15
  `primary_host` is the canonical host (e.g. `staging.openagents.com`); it is
16
  always returned as `https://` first. `aliases` is a comma-separated string
17
  of `https://` origins. Each alias is validated: it must use `https` and
18
  must not contain a path.
19
  """
20
  @spec for_production(String.t(), String.t()) :: [String.t()]
21
  def for_production(primary_host, aliases) when is_binary(primary_host) do
22
    primary = "#{@primary_scheme}://#{primary_host}"
23
24
    parsed_aliases =
25
      aliases
26
      |> String.split(",")
27
      |> Enum.map(&String.trim/1)
28
      |> Enum.reject(&(&1 == ""))
29
      |> Enum.map(&validate_origin!/1)
30
      |> Enum.reject(&(&1 == primary))
31
32
    [primary | parsed_aliases]
33
  end
34
35
  defp validate_origin!(""), do: raise(ArgumentError, "origin cannot be empty")
36
37
  defp validate_origin!(origin) do
38
    uri = URI.parse(origin)
39
40
    cond do
41
      uri.scheme != "https" ->
42
        raise ArgumentError, "origin must use https: #{origin}"
43
44
      not is_nil(uri.path) and uri.path != "" ->
45
        raise ArgumentError, "origin must not contain a path: #{origin}"
46
47
      is_nil(uri.host) or uri.host == "" ->
48
        raise ArgumentError, "origin must include a host: #{origin}"
49
50
      true ->
51
        origin
52
    end
53
  end
54
end
test/openagents/runtime_config_test.exs modified +35

@@ -162,6 +162,41 @@ defmodule OpenAgents.RuntimeConfigTest do

162 162
    assert {:ok, _config} = RuntimeConfig.validate(settings)
163 163
  end
164 164
165
  test "staging rejects an insecure allowed origin" do
166
    settings =
167
      staging_settings()
168
      |> put_endpoint(:check_origin, ["https://staging.openagents.com", "http://other.example"])
169
170
    assert {:error, %{setting: :allowed_origins}} = RuntimeConfig.validate(settings)
171
  end
172
173
  test "staging rejects a path-bearing allowed origin" do
174
    settings =
175
      staging_settings()
176
      |> put_endpoint(:check_origin, [
177
        "https://staging.openagents.com",
178
        "https://other.example/path"
179
      ])
180
181
    assert {:error, %{setting: :allowed_origins}} = RuntimeConfig.validate(settings)
182
  end
183
184
  test "staging rejects allowed origins with query, fragment, or missing scheme" do
185
    for origin <- [
186
          "https://other.example?query=1",
187
          "https://other.example#fragment",
188
          "https://",
189
          "other.example"
190
        ] do
191
      settings =
192
        staging_settings()
193
        |> put_endpoint(:check_origin, ["https://staging.openagents.com", origin])
194
195
      assert {:error, %{setting: :allowed_origins}} = RuntimeConfig.validate(settings),
196
             "expected #{origin} to be rejected"
197
    end
198
  end
199
165 200
  test "enabled OpenAI features require the centralized provider secret" do
166 201
    settings =
167 202
      staging_settings()
test/openagents_web/allowed_origins_test.exs deleted -21

@@ -1,21 +0,0 @@

1
defmodule OpenAgentsWeb.AllowedOriginsTest do
2
  use ExUnit.Case, async: true
3
  alias OpenAgentsWeb.AllowedOrigins
4
5
  test "includes the primary host and configured Cloud Run aliases" do
6
    assert AllowedOrigins.for_production(
7
             "openagents.example",
8
             "https://openagents-123.run.app, https://openagents.example"
9
           ) == ["https://openagents.example", "https://openagents-123.run.app"]
10
  end
11
12
  test "rejects origins containing paths or an insecure scheme" do
13
    assert_raise ArgumentError, fn ->
14
      AllowedOrigins.for_production("openagents.example", "https://other.example/path")
15
    end
16
17
    assert_raise ArgumentError, fn ->
18
      AllowedOrigins.for_production("openagents.example", "http://other.example")
19
    end
20
  end
21
end

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