diff --git a/src/components/__tests__/delegated-write-affordances.test.tsx b/src/components/__tests__/delegated-write-affordances.test.tsx
new file mode 100644
index 000000000..ae1f4e03d
--- /dev/null
+++ b/src/components/__tests__/delegated-write-affordances.test.tsx
@@ -0,0 +1,198 @@
+/**
+ * What a delegate is offered, rendered rather than described.
+ *
+ * v1.36.0 shipped sharing read-only and gated it only in the application
+ * chrome. Every feature surface still painted its add button, and a delegate
+ * who tapped one met a 403 from a server that was right to refuse. These
+ * render the real controls to markup and assert the paint, on the three
+ * capability states a session can be in.
+ *
+ * The suite is SSR-only (`@testing-library/react` is not a dependency here),
+ * which bounds what it can prove: it holds the RENDER, never the click. A
+ * control that is absent here cannot be tapped, and that is the whole property
+ * — but a control that is present here is not proven to work, and a submit
+ * path is not proven at all. That leg lives in `e2e/account-sharing.spec.ts`.
+ *
+ * Mutation checks, run:
+ * - `useRecordCapabilities` returning `canAdd: true` unconditionally → the
+ * read-only legs for the intake row and the card menu go red.
+ * - `DeleteButton` dropping its `canManage` bail → "no row delete inside
+ * somebody else's record" goes red.
+ */
+import { describe, expect, it, vi } from "vitest";
+import { renderToStaticMarkup } from "react-dom/server";
+
+import { I18nProvider } from "@/lib/i18n/context";
+import type { AccountAccess } from "@/lib/sharing/account-access-view";
+
+const OWNER = {
+ accountId: "acct-owner",
+ username: "owner",
+ displayName: "Margarethe",
+ access: "read" as const,
+ canWrite: false,
+};
+
+const OWN_RECORD: AccountAccess = {
+ accounts: [OWNER],
+ active: null,
+ canSwitch: true,
+};
+const READ_ONLY: AccountAccess = {
+ accounts: [OWNER],
+ active: OWNER,
+ canSwitch: true,
+};
+const WRITABLE: AccountAccess = {
+ accounts: [OWNER],
+ active: { ...OWNER, access: "write", canWrite: true },
+ canSwitch: true,
+};
+
+const mockAccessRef: { value: AccountAccess } = { value: OWN_RECORD };
+
+vi.mock("@/hooks/use-auth", () => ({
+ useAuth: () => ({
+ user: {
+ id: "delegate",
+ username: "delegate",
+ email: null,
+ role: "USER",
+ avatarUrl: null,
+ modules: {},
+ accountAccess: mockAccessRef.value,
+ },
+ isAuthenticated: true,
+ isLoading: false,
+ refetch: vi.fn(),
+ }),
+}));
+
+import { DeleteButton } from "@/components/data-list/delete-button";
+import { SelectionActionBar } from "@/components/data-list/selection-action-bar";
+import { MedicationCardMenu } from "@/components/medications/medication-card-menu";
+import { MedicationIntakeActions } from "@/components/medications/card-parts/medication-intake-actions";
+import { visibleCaptureKinds } from "@/components/layout/capture-picker";
+
+function render(access: AccountAccess, node: React.ReactNode): string {
+ mockAccessRef.value = access;
+ return renderToStaticMarkup(
+ {node},
+ );
+}
+
+describe("row delete", () => {
+ const node = (
+ {}} title="Delete?" description="Gone." />
+ );
+
+ it("renders in the caller's own record", () => {
+ expect(render(OWN_RECORD, node)).toContain("