feat: integrate exact cross-assignment mailbox UUID navigation with native administrator device consent schemas and focused identity lookup regressions

This commit is contained in:
Matthew Meszaros
2026-10-10 06:41:21 +00:00
parent 4db93bf292
commit 7bb0ff289d
11 changed files with 80 additions and 14 deletions
@@ -0,0 +1,35 @@
import { act } from "react";
import { createRoot } from "react-dom/client";
import { MemoryRouter } from "react-router-dom";
import { afterEach, expect, it, vi } from "vitest";
import MailboxesPage from "./MailboxesPage";
const calls = vi.hoisted(() => ({ search: vi.fn(), queries: vi.fn() }));
vi.mock("@/lib/api/client/admin/mailboxes", () => ({ searchMailboxes: calls.search }));
vi.mock("@/lib/api/client/admin/fleetNodes", () => ({ listFleetNodes: vi.fn() }));
vi.mock("@/components/data/DataTable", () => ({ DataTable: () => <div>Mailbox results</div> }));
vi.mock("@tanstack/react-query", () => ({ keepPreviousData: vi.fn(), useQuery: (options: { queryKey: string[]; queryFn: () => unknown }) => {
calls.queries(options);
if (options.queryKey[1] === "mailboxes") options.queryFn();
return { data: { data: [], pagination: {} }, isLoading: false };
} }));
afterEach(() => { vi.clearAllMocks(); vi.unstubAllGlobals(); });
it("looks up an exact mailbox across inactive/moved assignments without old filters or placeholder rows", async () => {
vi.stubGlobal("IS_REACT_ACT_ENVIRONMENT", true);
const mailbox = "33333333-3333-4333-8333-333333333333";
const host = document.createElement("div");
document.body.append(host);
const root = createRoot(host);
try {
await act(async () => root.render(<MemoryRouter initialEntries={[`/mailboxes?mailbox_id=${mailbox}&worker=old-worker&q=old-search&org=old-org`]}><MailboxesPage /></MemoryRouter>));
expect(calls.search).toHaveBeenCalledWith({ mailbox_id: mailbox, status: "all", limit: 50 });
expect(calls.queries.mock.calls.filter(([options]) => options.queryKey[1] === "mailboxes").every(([options]) => options.placeholderData === undefined)).toBe(true);
expect(host.textContent).toContain("Exact identity lookup");
expect(host.textContent).toContain(mailbox);
expect(host.querySelector("input")).toBeNull();
} finally {
await act(async () => root.unmount());
host.remove();
}
});
+13 -3
View File
@@ -177,6 +177,7 @@ export default function MailboxesPage() {
const orgId = params.get("org") || undefined;
const userId = params.get("user") || undefined;
const workerParam = params.get("worker") || "";
const mailboxId = params.get("mailbox_id") || undefined;
// `?q=` seeds the search box so the command palette can land here on a
// mailbox; a status of "all" keeps a disabled mailbox findable that way.
@@ -225,7 +226,7 @@ export default function MailboxesPage() {
];
const filterKey = JSON.stringify({
query, status, provider, warmup, workerId, riskBand, pool, synced, orgId, userId,
query, status, provider, warmup, workerId, riskBand, pool, synced, orgId, userId, mailboxId,
warmupPaused, trackingVerified, hasTrackingDomain, hasOrg, signatureSync, hasOAuth, hasSmtp,
capMin, capMax, gapMin, gapMax, connected, lastSynced, sort,
});
@@ -237,7 +238,7 @@ export default function MailboxesPage() {
const { data, isLoading, error, refetch } = useQuery({
queryKey: ["admin", "mailboxes", filterKey, pager.cursor],
queryFn: () =>
searchMailboxes({
searchMailboxes(mailboxId ? { mailbox_id: mailboxId, status: "all", limit: 50 } : {
q: query.trim() || undefined,
status,
provider: provider || undefined,
@@ -270,7 +271,7 @@ export default function MailboxesPage() {
sort_desc: sort.by ? sort.desc : undefined,
}),
staleTime: 30_000,
placeholderData: keepPreviousData,
placeholderData: mailboxId ? undefined : keepPreviousData,
});
const rows = data?.data ?? [];
@@ -330,6 +331,15 @@ export default function MailboxesPage() {
setParams(next, { replace: true });
}
if (mailboxId) return <div>
<PageHeader title="Mailbox" description="Exact identity lookup across current assignments, including inactive mailboxes. Existing browse filters do not apply." />
<p className="mb-4 break-all font-mono text-xs">{mailboxId}</p>
<Button variant="outline" className="mb-4" onClick={() => clearParam("mailbox_id")}>Return to mailbox browser</Button>
<DataTable columns={columns} rows={rows} getRowId={(m) => m.id} loading={isLoading} error={error}
onRetry={() => refetch()} errorTitle="Mailbox lookup failed" noun="mailboxes"
emptyTitle="Mailbox not found" emptyHint="This mailbox is no longer registered on this instance." />
</div>;
return (
<div>
<PageHeader
+1 -1
View File
@@ -280,7 +280,7 @@ export default function WorkerDetailPage() {
</Section>
)}
<NodeDiagnostics node={node} mailboxes={mailboxes} />
<NodeDiagnostics node={node} />
<Section
title="Version"
@@ -12,7 +12,6 @@ import { useMe } from "@/hooks/useMe";
import useBrowseState from "@/hooks/useBrowseState";
import { AdminPerm, hasAdminPerm } from "@/lib/auth/permissions";
import type { FleetNode } from "@/lib/api/client/admin/fleetNodes";
import type { AdminWorkerEmail } from "@/lib/api/models/admin";
import { getNodeLogs, getNodeBroker, type NodeBrokerSource, type NodeLogFilters } from "@/lib/api/client/admin/nodeDiagnostics";
import { diagnosticReason, emptyLogFilters, eventLabels, isUUID, logFilterError, parseLogFilters, safeCount, safeLogEvent, validTime, validatedBroker } from "@/lib/nodeDiagnostics";
@@ -52,7 +51,7 @@ function BrokerScope({ title, source, group, topic }: { title: string; source: N
</Panel>;
}
export function NodeDiagnostics({ node, mailboxes }: { node: FleetNode; mailboxes: AdminWorkerEmail[] }) {
export function NodeDiagnostics({ node }: { node: FleetNode }) {
const { data: me } = useMe();
const canViewBroker = !!me && hasAdminPerm(me.admin_permissions, AdminPerm.ViewAnalytics);
const canViewMailboxes = !!me && hasAdminPerm(me.admin_permissions, AdminPerm.ViewUsers);
@@ -121,7 +120,6 @@ export function NodeDiagnostics({ node, mailboxes }: { node: FleetNode; mailboxe
<div className="mt-4 overflow-x-auto"><table className="w-full text-left text-xs" aria-label="Redacted node events">
<thead><tr className="border-b text-muted-foreground"><th className="p-2">Observed</th><th className="p-2">Level</th><th className="p-2">Evidence</th><th className="p-2">Mailbox</th></tr></thead>
<tbody>{events.map((event) => {
const mailbox = mailboxes.find((m) => m.id === event.mailbox_id);
const mailboxID = isUUID(event.mailbox_id ?? "") ? event.mailbox_id : null;
return <tr key={event.id} className="border-b align-top">
<td className="whitespace-nowrap p-2"><Timestamp value={event.observed_at} /></td>
@@ -129,7 +127,7 @@ export function NodeDiagnostics({ node, mailboxes }: { node: FleetNode; mailboxe
<td className="p-2"><div className="font-medium">{eventLabels[event.event].title}</div><div className="mt-1 text-muted-foreground">{event.category.replaceAll("_", " ")}
{event.event === "sync_control_plane_held" && safeCount(event.http_status) && event.http_status >= 100 && event.http_status <= 599 && ` · HTTP ${event.http_status}`}
{safeCount(event.count) && event.count <= 1000000 && ` · count ${event.count}`}</div></td>
<td className="p-2 font-mono">{mailboxID ? mailbox && canViewMailboxes ? <Link className="text-[var(--admin-accent-strong)] underline underline-offset-2" to={`/mailboxes?q=${encodeURIComponent(mailbox.email)}&worker=${node.id}`} title="Open assigned mailbox in the mailbox browser">{mailboxID}</Link> : <span title="Mailbox identity is not in the currently loaded assignment page, or mailbox access is not permitted.">{mailboxID}</span> : "Not provided"}</td>
<td className="p-2 font-mono">{mailboxID ? canViewMailboxes ? <Link className="text-[var(--admin-accent-strong)] underline underline-offset-2" to={`/mailboxes?mailbox_id=${encodeURIComponent(mailboxID)}`} title="Look up this exact mailbox, regardless of current assignment">{mailboxID}</Link> : <span title="Mailbox access is not permitted.">{mailboxID}</span> : "Not provided"}</td>
</tr>;
})}</tbody>
</table></div>}
+1
View File
@@ -190,6 +190,7 @@ export interface AdminMailboxesResult {
}
export interface AdminMailboxSearch {
mailbox_id?: string;
q?: string;
status?: string;
provider?: string;
+6 -5
View File
@@ -232,9 +232,10 @@ Returned when:
This backend flow is separate from workspace API-key authorization. Platform
admin access uses a normal bearer session, never an organization API key.
The admin UI and CLI implement this contract in a separate rollout stage;
these endpoints alone do not provide a consent page or CLI command. The CLI
never listens on an HTTP port or receives a browser redirect.
Use [remote `warmblyctl` login](/development/warmblyctl/#remote-administrator-commands)
and the administrator website's `/device` consent page. Deploy the backend
before upgrading the admin UI and CLI. The CLI never listens on an HTTP port
or receives a browser redirect.
### Endpoint contract
@@ -298,8 +299,8 @@ and request. A different session cannot spend it. If decide returns
again; never auto-approve when login/reauth returns.
Poll no faster than every five seconds. Pending/denied responses contain
`status: "pending"` or `"denied"`, no `token`; the existing UUID serializer may
include a zero `user_id`, which is not an identity. An approving poll returns:
`status: "pending"` or `"denied"`, with neither `token` nor `user_id`.
An approving poll returns:
```json
{
+1
View File
@@ -623,6 +623,7 @@ Alongside them, `api_url` is this API's own public base (for a copyable example
- `GET /admin/warmup-content/overview` includes effective generation controls and requires `view_warmup_pool`; `PUT /admin/warmup-content/settings` writes effective controls with `manage_settings`. These are platform-admin routes, not organization API-key scopes. See [effective generation policy and stopping](/development/warmup-generation/).
- `POST /admin/organizations/:id/sample-data`: `manage_testers` and an MFA-verified admin session. Adds the [reviewer sample dataset](/development/accounts-and-access/#adding-sample-data) only to an active dedicated Test workspace. No request body. Returns `200` with `organization_id`, `created` (false when already seeded) and `seeded_at`; retries preserve edits and deletions. An ordinary workspace, revoked or expired tester, or missing/expired managed Test grant returns `400`. Inserts and the admin audit marker commit together. No mailbox connection, email delivery, external request or credit spend occurs.
- `GET /admin/testers`: `view_users` and an MFA-verified admin session. Each tester in `data` may include `test_workspace_id` for its owned dedicated Test workspace and `sample_data_seeded_at` when populated. These fields are absent for a tester merely attached to an ordinary workspace.
- `GET /admin/mailboxes`: `view_users` and an MFA-verified admin session. Optional `mailbox_id` filters by exact UUID; `status=all` includes inactive mailboxes. Node evidence links use `/mailboxes?mailbox_id=UUID`, regardless of loaded worker assignments or earlier browse filters. Deleted identities return an empty result, not a substitute mailbox.
`POST /subscription/checkout`, `POST /subscription/portal`, `POST /subscription/cancel`, `POST /subscription/change-plan` and `GET /subscription/preview-change` require the `MANAGE_BILLING` organization permission; reading the subscription, its limits, trial and features needs only membership. `POST /subscription/portal` requires an existing Stripe billing customer. A workspace without one receives `400` with code `bad_request` and a message to complete checkout first; free and operator-granted plans alone do not create a billing customer.
+1
View File
@@ -435,6 +435,7 @@ type AdminMailboxesResult struct {
// All fields optional; empty status = active, "all" returns every
// status. provider lets ops filter to "all gmail mailboxes" quickly.
type AdminMailboxSearch struct {
MailboxID *ParamUUID `form:"mailbox_id"`
Query string `form:"q"`
Status string `form:"status"`
Provider string `form:"provider"`
+14
View File
@@ -38,6 +38,20 @@ func TestParamUUIDRejectsGarbage(t *testing.T) {
}
}
func TestAdminMailboxExactIdentityBindsAndRejectsInvalidUUID(t *testing.T) {
id := uuid.New()
var search AdminMailboxSearch
if err := bindQuery(t, "mailbox_id="+id.String()+"&status=all", &search); err != nil {
t.Fatal(err)
}
if search.MailboxID == nil || search.MailboxID.UUID != id || search.Status != "all" || search.WorkerID != nil {
t.Fatalf("exact mailbox lookup changed identity or placement scope: %+v", search)
}
if err := bindQuery(t, "mailbox_id=not-a-uuid", &AdminMailboxSearch{}); err == nil {
t.Fatal("invalid exact mailbox identity accepted")
}
}
// Every admin search struct must bind its ids and cursor together, so a field
// typed as a bare uuid.UUID cannot 400 an explorer again.
func TestAdminSearchStructsBindIDsAndCursor(t *testing.T) {
+5
View File
@@ -1913,6 +1913,11 @@ func (r *adminRepository) SearchMailboxesForAdmin(ctx context.Context, search *m
args := []interface{}{}
argNum := 1
where := "WHERE 1=1"
if search.MailboxID != nil {
where += " AND ea.id = $" + itoa(argNum)
args = append(args, search.MailboxID.UUID)
argNum++
}
if search.Query != "" {
where += ` AND (ea.email ILIKE $` + itoa(argNum) +
+1 -1
View File
@@ -122,7 +122,7 @@ test("admin CLI consent and redacted node diagnostics with disclosed local respo
await expect(logs.getByRole("table", { name: "Redacted node events", exact: true })).toBeVisible();
await expect(logs.getByText("Control-plane sync held", { exact: true })).toBeVisible();
await expect(logs).toContainText("HTTP 503"); await expect(logs).toContainText("Partial coverage"); await expect(logs).toContainText("per process run");
await expect(logs.getByRole("link", { name: mailbox, exact: true })).toHaveAttribute("href", new RegExp("/mailboxes\\?q=fixture-mailbox%40example.test"));
await expect(logs.getByRole("link", { name: mailbox, exact: true })).toHaveAttribute("href", `/mailboxes?mailbox_id=${mailbox}`);
await proof.chapter("Redacted operational evidence", "All node capture/log/offset responses are synthetic localhost fixtures. They do not establish production sampling, provider health, delivery or the cause of an arrival 503.");
await logs.getByRole("table", { name: "Redacted node events", exact: true }).scrollIntoViewIfNeeded();
await proof.shot("admin-node-redacted-evidence", { caption: "Synthetic capture and allowlisted events: timestamps, partial coverage, retention bounds, three known per-run drops, numeric control-plane HTTP 503 and native mailbox link." });