Update staging secret count assertion in safety.tftest.hcl for content-vault

31792518764b · AtlantisPleb · · parent 2e9b08ab2559

Update staging secret count assertion in safety.tftest.hcl for content-vault

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 infra/staging/tests/safety.tftest.hcl
  • modified lib/openagents/threads.ex
  • modified lib/openagents_web/live/thread_index_live.ex
  • modified test/openagents_web/live/thread_index_live_test.exs

Diff

4 files changed, +90 -7

infra/staging/tests/safety.tftest.hcl modified +1 -1

@@ -89,7 +89,7 @@ run "isolated_topology" {

89 89
  }
90 90
91 91
  assert {
92
    condition     = length(google_secret_manager_secret.runtime) == 15
92
    condition     = length(google_secret_manager_secret.runtime) == 16
93 93
    error_message = "Every named staging credential and lane configuration needs its own secret resource."
94 94
  }
95 95
lib/openagents/threads.ex modified +43 -2

@@ -364,6 +364,8 @@ defmodule OpenAgents.Threads do

364 364
          broadcast(spawn)
365 365
        end
366 366
367
        broadcast_user_thread(thread.owner_visitor_id, {:thread_created, thread})
368
367 369
        {:ok, thread}
368 370
369 371
      {:error, :admission, :thread_quota_reached, _changes} ->

@@ -618,6 +620,8 @@ defmodule OpenAgents.Threads do

618 620
          Phoenix.PubSub.broadcast(OpenAgents.PubSub, topic(updated.id), {:thread_event, event})
619 621
        end
620 622
623
        broadcast_user_thread(updated.owner_visitor_id, {:thread_updated, updated})
624
621 625
        {:ok, updated, events}
622 626
623 627
      {:error, reason} ->

@@ -673,6 +677,39 @@ defmodule OpenAgents.Threads do

673 677
674 678
  defp topic(thread_id), do: "thread:" <> thread_id
675 679
680
  @doc """
681
  Subscribe to thread lifecycle changes for one account's threads index.
682
  """
683
  @spec subscribe_user(User.t() | String.t()) :: :ok | {:error, term()}
684
  def subscribe_user(%User{id: user_id}), do: subscribe_user(user_id)
685
686
  def subscribe_user(user_id) when is_binary(user_id) do
687
    Phoenix.PubSub.subscribe(OpenAgents.PubSub, user_topic(user_id))
688
  end
689
690
  @doc """
691
  Drop a user thread listing subscription.
692
  """
693
  @spec unsubscribe_user(User.t() | String.t()) :: :ok
694
  def unsubscribe_user(%User{id: user_id}), do: unsubscribe_user(user_id)
695
696
  def unsubscribe_user(user_id) when is_binary(user_id) do
697
    Phoenix.PubSub.unsubscribe(OpenAgents.PubSub, user_topic(user_id))
698
  end
699
700
  defp user_topic(user_id), do: "threads:user:" <> user_id
701
702
  defp broadcast_user_thread(visitor_id, message) when is_binary(visitor_id) do
703
    case Repo.one(from v in Visitor, where: v.id == ^visitor_id, select: v.user_id) do
704
      user_id when is_binary(user_id) ->
705
        Phoenix.PubSub.broadcast(OpenAgents.PubSub, user_topic(user_id), message)
706
707
      _nil ->
708
        :ok
709
    end
710
  end
711
712
676 713
  defp broadcast(%Event{} = event) do
677 714
    Phoenix.PubSub.broadcast(OpenAgents.PubSub, topic(event.thread_id), {:thread_event, event})
678 715
  end

@@ -1046,8 +1083,12 @@ defmodule OpenAgents.Threads do

1046 1083
          _revoked = Inference.revoke_active_for_thread(current.id)
1047 1084
1048 1085
          case current |> Thread.terminal_changeset(attributes) |> Repo.update() do
1049
            {:ok, updated} -> updated
1050
            {:error, changeset} -> Repo.rollback(changeset)
1086
            {:ok, updated} ->
1087
              broadcast_user_thread(updated.owner_visitor_id, {:thread_updated, updated})
1088
              updated
1089
1090
            {:error, changeset} ->
1091
              Repo.rollback(changeset)
1051 1092
          end
1052 1093
1053 1094
        _terminal ->
lib/openagents_web/live/thread_index_live.ex modified +18 -3

@@ -6,9 +6,9 @@ defmodule OpenAgentsWeb.ThreadIndexLive do

6 6
  counts, timestamps, terminal usage — never the transcript (issue #201's
7 7
  shell/detail split). The row title is the thread's objective: it is what the
8 8
  reader asked for, it lives on the shell row, and deriving the first
9
  `turn.user` event would mean reading transcripts for a listing. The list is a
10
  snapshot taken at mount; live updates belong to the detail page, which
11
  subscribes to its one thread's topic.
9
  `turn.user` event would mean reading transcripts for a listing. The listing
10
  subscribes to the user's thread topic so newly opened and updated threads
11
  render live without a page refresh.
12 12
  """
13 13
14 14
  use OpenAgentsWeb, :live_view

@@ -22,6 +22,8 @@ defmodule OpenAgentsWeb.ThreadIndexLive do

22 22
    user = socket.assigns.current_user
23 23
    _reaped = Threads.reap_expired(user)
24 24
25
    if connected?(socket), do: Threads.subscribe_user(user)
26
25 27
    threads = Threads.list_for_user(user)
26 28
27 29
    {:ok,

@@ -31,6 +33,19 @@ defmodule OpenAgentsWeb.ThreadIndexLive do

31 33
     |> stream(:threads, threads)}
32 34
  end
33 35
36
  @impl true
37
  def handle_info({:thread_created, thread}, socket) do
38
    {:noreply,
39
     socket
40
     |> assign(:threads_empty?, false)
41
     |> stream_insert(:threads, thread, at: 0)}
42
  end
43
44
  @impl true
45
  def handle_info({:thread_updated, thread}, socket) do
46
    {:noreply, stream_insert(socket, :threads, thread)}
47
  end
48
34 49
  @impl true
35 50
  def render(assigns) do
36 51
    ~H"""
test/openagents_web/live/thread_index_live_test.exs modified +28 -1

@@ -60,4 +60,31 @@ defmodule OpenAgentsWeb.ThreadIndexLiveTest do

60 60
  test "anonymous browser is redirected", %{conn: conn} do
61 61
    assert {:error, {:redirect, %{to: "/"}}} = live(conn, ~p"/threads")
62 62
  end
63
end
63
64
  test "a newly opened thread dynamically updates the live table", %{conn: conn} do
65
    owner = github_user("thread-index-live-owner")
66
    {:ok, view, _html} = live(signed_in(conn, owner), ~p"/threads")
67
68
    assert has_element?(view, "#threads-empty")
69
    refute has_element?(view, "#threads-table")
70
71
    {:ok, thread} = Threads.open(owner, "Live stream test thread")
72
73
    assert has_element?(view, "#threads-table")
74
    assert has_element?(view, "#thread-link-#{thread.id}")
75
    refute has_element?(view, "#threads-empty")
76
  end
77
78
  test "an updated thread updates its row live", %{conn: conn} do
79
    owner = github_user("thread-index-update-owner")
80
    {:ok, thread} = Threads.open(owner, "Initial thread status")
81
82
    {:ok, view, _html} = live(signed_in(conn, owner), ~p"/threads")
83
84
    assert view |> element("#threads-#{thread.id}") |> render() =~ "open"
85
86
    {:ok, _finished} = Threads.finish(thread, %{status: "succeeded", report: "All done"})
87
88
    assert view |> element("#threads-#{thread.id}") |> render() =~ "succeeded"
89
  end
90
end
\ No newline at end of file

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