← Files DataARCHIVED FILE

templates/data-app/base/tests/presentation.test.mjs

110 KB · Sep 30, 2026 · 23:19 UTC

↓ Download file

import assert from "node:assert/strict";
import { createHash } from "node:crypto";
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import test from "node:test";
import { pathToFileURL } from "node:url";

import { componentPermalinkId, componentPermalinkShortId } from "../src/chart-permalink.js";
import { semanticColor } from "../src/charting/chart-theme.js";
import { createDataAppWorker, validatePresentation as validateWorkerPresentation } from "../src/data-app-worker.js";
import { VERIFICATION_REMINDER_COOKIE, readVerificationReminderDismissed, rememberVerificationReminderDismissed } from "../src/verification-reminder.js";
import {
  mergePresentationChanges, normalizeAppearance, normalizePresentation, presentationStorageKey,
  presentationVersion, readLocalPresentation, readViewerAppearance, validatePresentation,
  writeLocalPresentation, writeViewerAppearance,
  editHistoryValue, recordPresentationEdit, presentationBeforeEdits,
} from "../src/presentation-state.js";

test("edit history restores deletion/layout changes, branches after undo and excludes reviewed state", () => {
  const original = editHistoryValue({ title: "Test", hiddenBlocks: [], queries: { secret: 1 }, filters: { plan: "A" } });
  const deleted = editHistoryValue({ title: "Test", hiddenBlocks: ["kpi"] });
  let history = { entries: [original], index: 0 };
  history = recordPresentationEdit(history, deleted);
  assert.deepEqual(JSON.parse(history.entries[0]), { title: "Test", hiddenBlocks: [] });
  assert.equal(recordPresentationEdit(history, deleted), history);
  const undone = { ...history, index: 0 };
  assert.equal(JSON.parse(undone.entries[undone.index]).hiddenBlocks.length, 0);
  const moved = editHistoryValue({ title: "Test", blockLayouts: { canvas: { order: ["b", "a"] } } });
  history = recordPresentationEdit(undone, moved);
  assert.deepEqual(history.entries, [original, moved], "New edits discard the redo branch");
  for (let i = 0; i < 120; i++) history = recordPresentationEdit(history, editHistoryValue({ title: `Edit ${i}` }));
  assert.equal(history.entries.length, 101);
  assert.deepEqual(recordPresentationEdit(history, original, false), { entries: [original], index: 0 });
});

function memoryStorage() {
  const values = new Map();
  return { getItem: (key) => values.get(key) ?? null, setItem: (key, value) => values.set(key, value),
    removeItem: (key) => values.delete(key), values };
}

let presentationHookHarnessIndex = 0;

async function presentationPersistenceHarness(initialPresentation, { deferResponses = false } = {}) {
  const binding = `__dataAppPresentationHookHarness${process.pid}_${presentationHookHarnessIndex += 1}`;
  const hooks = [];
  const effects = [];
  const timers = new Map();
  const requests = [];
  const pendingResponses = [];
  const endpoints = [];
  const cookies = { value: "", reads: 0, writes: [], blocked: false, denied: false };
  const reminderEnvironment = {
    location: new URL("https://dashboard.example.chatgpt.site/"),
    document: {
      get cookie() {
        cookies.reads += 1;
        if (cookies.denied) throw new Error("Cookies unavailable");
        return cookies.value;
      },
      set cookie(value) {
        cookies.writes.push(value);
        if (cookies.denied) throw new Error("Cookies unavailable");
        if (!cookies.blocked) cookies.value = value.split(";")[0];
      },
    },
  };
  const snapshot = { id: `presentation-hook-${presentationHookHarnessIndex}` };
  const server = { presentation: structuredClone(initialPresentation), revision: 0 };
  let cursor = 0;
  let nextTimer = 0;
  let pendingEffects = [];
  let deferred = deferResponses;

  function response(status, value) {
    return { status, ok: status >= 200 && status < 300, json: async () => structuredClone(value) };
  }

  globalThis[binding] = {
    useState(initial) {
      const index = cursor++;
      if (!Object.hasOwn(hooks, index)) hooks[index] = typeof initial === "function" ? initial() : initial;
      return [hooks[index], (next) => {
        hooks[index] = typeof next === "function" ? next(hooks[index]) : next;
      }];
    },
    useRef(initial) {
      const index = cursor++;
      if (!Object.hasOwn(hooks, index)) hooks[index] = { current: initial };
      return hooks[index];
    },
    useEffect(effect, dependencies) {
      const index = cursor++;
      if (!effects[index] || dependencies.some((dependency, position) =>
        !Object.is(dependency, effects[index].dependencies[position]))) {
        pendingEffects.push({ index, effect, dependencies });
      }
    },
    setTimeout(callback, delay) {
      assert.equal(delay, 300);
      const id = ++nextTimer;
      timers.set(id, callback);
      return id;
    },
    clearTimeout(id) {
      timers.delete(id);
    },
    async fetch(endpoint, options) {
      endpoints.push(endpoint);
      assert.equal(endpoint, "/api/presentation");
      const request = JSON.parse(options.body);
      requests.push(structuredClone(request));
      if (deferred) {
        return new Promise((resolve, reject) => pendingResponses.push({ request, resolve, reject }));
      }
      if (request.revision !== server.revision) {
        return response(409, { presentation: server.presentation, revision: server.revision });
      }
      const existingVerification = server.presentation.verification;
      server.presentation = structuredClone(request.presentation);
      if (request.verificationAction === "verify") {
        server.presentation.verification = existingVerification ?? {
          verifiedBy: "server-owner@example.com", verifiedAt: "2026-08-17T19:34:56.789Z",
        };
      } else if (request.verificationAction === "remove") {
        delete server.presentation.verification;
      }
      server.revision += 1;
      return response(200, { presentation: server.presentation, revision: server.revision });
    },
  };

  const source = (await readFile(new URL("../src/use-presentation.js", import.meta.url), "utf8"))
    .replace('import { useEffect, useLayoutEffect, useRef, useState } from "react";',
      `const { useEffect, useRef, useState, setTimeout, clearTimeout, fetch } = globalThis[${JSON.stringify(binding)}];`)
    .replace('import { editHistoryValue, recordPresentationEdit, mergePresentationChanges, normalizePresentation, validatePresentation, writeLocalPresentation } from "./presentation-state.js";',
      `import { editHistoryValue, recordPresentationEdit, mergePresentationChanges, normalizePresentation, validatePresentation, writeLocalPresentation } from "${
        new URL("../src/presentation-state.js", import.meta.url).href
      }";`)
    .replace('from "./verification-reminder.js";', `from "${new URL("../src/verification-reminder.js", import.meta.url).href}";`)
    .replace('from "./refresh-coachmark.js";', `from "${new URL("../src/refresh-coachmark.js", import.meta.url).href}";`);
  const directory = await mkdtemp(join(tmpdir(), "data-app-presentation-hook-"));
  const modulePath = join(directory, "use-presentation.mjs");
  let usePresentationPersistence, useVerificationReminder;
  try {
    await writeFile(modulePath, source);
    ({ usePresentationPersistence, useVerificationReminder } = await import(pathToFileURL(modulePath).href));
  } catch (error) {
    delete globalThis[binding];
    throw error;
  } finally {
    await rm(directory, { recursive: true, force: true });
  }

  return {
    requests,
    server,
    timers,
    pendingResponses,
    endpoints,
    cookies,
    renderReminder(environment = reminderEnvironment) {
      cursor = 0;
      pendingEffects = [];
      const value = useVerificationReminder(environment);
      assert.equal(pendingEffects.length, 0, "Reminder state must not schedule rendering side effects");
      return value;
    },
    render(presentation, options = {}) {
      cursor = 0;
      pendingEffects = [];
      usePresentationPersistence({ snapshot, hosted: true, presentation, initialPresentation, ...options });
      for (const { index, effect, dependencies } of pendingEffects) {
        effects[index]?.cleanup?.();
        effects[index] = { dependencies, cleanup: effect() };
      }
    },
    async flush() {
      const scheduled = [...timers.values()];
      timers.clear();
      await Promise.all(scheduled.map((callback) => callback()));
    },
    start() {
      const scheduled = [...timers.values()];
      timers.clear();
      assert.equal(scheduled.length, 1);
      return scheduled[0]();
    },
    respond(index, { status = 200, presentation, revision, error } = {}) {
      const pending = pendingResponses[index];
      assert.ok(pending, `Deferred response ${index} does not exist`);
      if (status >= 200 && status < 300 && revision >= server.revision) {
        server.presentation = structuredClone(presentation);
        server.revision = revision;
      }
      pending.resolve(response(status, status >= 200 && status < 300 || status === 409
        ? { presentation, revision } : { error: error ?? "A stale request failed." }));
    },
    resumeResponses() {
      deferred = false;
    },
    status() {
      return hooks[0];
    },
    dispose() {
      for (const effect of effects) effect?.cleanup?.();
      delete globalThis[binding];
    },
  };
}

test("reminder rendering never reads cookies, requests data, or schedules work", async () => {
  const harness = await presentationPersistenceHarness({});
  try {
    harness.cookies.denied = true;
    for (let render = 0; render < 100; render += 1) assert.equal(harness.renderReminder().dismissed, false);
    assert.equal(harness.cookies.reads, 0);
    assert.equal(harness.cookies.writes.length, 0);
    assert.equal(harness.endpoints.length, 0);
    assert.equal(harness.timers.size, 0);
  } finally { harness.dispose(); }
});

test("verification clicks observe workspace cookie changes without polling or shared writes", async () => {
  const harness = await presentationPersistenceHarness({ title: "Unchanged" });
  try {
    assert.equal(harness.renderReminder().check(), false);
    assert.equal(harness.cookies.reads, 1);
    assert.equal(harness.cookies.writes.length, 0);
    assert.equal(harness.renderReminder().remember(), true);
    assert.equal(harness.cookies.writes.length, 1);
    const readsAfterConfirm = harness.cookies.reads;
    for (let render = 0; render < 100; render += 1) assert.equal(harness.renderReminder().dismissed, true);
    assert.equal(harness.cookies.reads, readsAfterConfirm);
    harness.cookies.value = "";
    assert.equal(harness.renderReminder().check(), false, "Clearing the cookie re-enables confirmation on the next click");
    assert.equal(harness.renderReminder().dismissed, false);
    harness.cookies.value = `${VERIFICATION_REMINDER_COOKIE}=1`;
    assert.equal(harness.renderReminder().check(), true, "Already-open dashboards observe another dashboard's dismissal");
    assert.equal(harness.cookies.writes.length, 1, "Reading a dismissal never renews or rewrites the cookie");
    assert.equal(harness.endpoints.length, 0);
    assert.equal(harness.timers.size, 0);
    assert.deepEqual(harness.server, { presentation: { title: "Unchanged" }, revision: 0 });
  } finally { harness.dispose(); }
});

test("blocked cookie writes keep confirmation enabled and can recover without network requests", async () => {
  for (const failure of ["blocked", "denied"]) {
    const harness = await presentationPersistenceHarness({});
    try {
      harness.cookies[failure] = true;
      assert.equal(harness.renderReminder().remember(), false);
      assert.equal(harness.renderReminder().dismissed, false);
      assert.equal(harness.renderReminder().check(), false);
      harness.cookies[failure] = false;
      assert.equal(harness.renderReminder().remember(), true);
      assert.equal(harness.renderReminder().dismissed, true);
      assert.equal(harness.cookies.writes.length, 2);
      assert.equal(harness.endpoints.length, 0);
    } finally { harness.dispose(); }
  }
});

test("dashboard appearance validates author defaults and keeps viewer overrides local", () => {
  const snapshot = { id: "appearance-dashboard" };
  const storage = memoryStorage();
  assert.equal(normalizeAppearance("unknown"), "system");
  assert.deepEqual(validatePresentation({ appearance: "dark" }), { appearance: "dark" });
  assert.throws(() => validatePresentation({ appearance: "unknown" }), /Appearance must be/);
  assert.equal(writeViewerAppearance(snapshot, "light", storage), true);
  assert.equal(readViewerAppearance(snapshot, storage), "light");
  assert.equal(readViewerAppearance({ id: "other-dashboard" }, storage), "");
  assert.equal(writeViewerAppearance(snapshot, "", storage), true);
  assert.equal(readViewerAppearance(snapshot, storage), "");
});

test("semantic chart colors preserve dimension identity across reviewed queries and reordering", () => {
  assert.equal(semanticColor({ dimension: "plan", value: "Pro" }),
    semanticColor({ dimension: "plan", value: "Pro", index: 7 }));
  assert.notEqual(semanticColor({ dimension: "plan", value: "Pro" }),
    semanticColor({ dimension: "product", value: "Pro" }));
  assert.equal(semanticColor({ field: "revenue", explicitColor: "#123456" }), "#123456");
});

test("presentation rejects removed chart annotations rather than persisting nested reviewed data", () => {
  assert.throws(() => validatePresentation({ chartOverrides: {
    trend: { referenceLines: [{ axis: "y", value: 1, rows: [{ amount: 1 }] }] },
  } }), /annotations are not supported/);
});

test("presentation preserves bounded authored annotation references without accepting data payloads", () => {
  const spec = { type: "line", x: "date", y: "value", annotations: [
    { id: "target", kind: "benchmark", label: "Reviewed target", field: "target", measure: "value" },
  ] };
  assert.deepEqual(validatePresentation({ chartOverrides: { trend: spec } }).chartOverrides.trend, spec);
  for (const extra of [{ rows: [{ value: 2 }] }, { value: 42 }, { sql: "select 1" }, { source: { secret: true } }]) {
    assert.throws(() => validatePresentation({ chartOverrides: { trend: {
      ...spec, annotations: [{ ...spec.annotations[0], ...extra }],
    } } }), /unsupported fields/u);
  }
});

test("annotation visibility is an optional boolean and never bypasses annotation validation", () => {
  const spec = { type: "line", x: "date", y: "value", annotations: [
    { id: "target", kind: "benchmark", label: "Reviewed target", field: "target", measure: "value" },
  ] };
  const validate = (chart) => validatePresentation({ chartOverrides: { trend: chart } }).chartOverrides.trend;
  assert.equal(Object.hasOwn(validate(spec), "showAnnotations"), false);
  for (const showAnnotations of [false, true]) {
    assert.deepEqual(validate({ ...spec, showAnnotations }), { ...spec, showAnnotations });
  }
  for (const showAnnotations of [null, undefined, "false", "true", 0, 1, [], {}]) {
    assert.throws(() => validate({ ...spec, showAnnotations }), /boolean/i);
  }
  assert.throws(() => validate({ ...spec, showAnnotations: false,
    annotations: [{ ...spec.annotations[0], rows: [{ value: 42 }] }],
  }), /unsupported fields/u);
});

test("local annotation visibility round trips without changing reviewed data or authored annotations", () => {
  const snapshot = { id: "annotation-visibility", queries: { reviewed: { rows: [{ value: 42, target: 50 }] } } };
  const before = structuredClone(snapshot);
  const spec = { type: "line", x: "date", y: "value", annotations: [
    { id: "target", kind: "benchmark", label: "Reviewed target", field: "target", measure: "value" },
  ] };
  const storage = memoryStorage();
  for (const setting of [{}, { showAnnotations: false }, { showAnnotations: true }]) {
    const presentation = { chartOverrides: { trend: { ...spec, ...setting } } };
    assert.equal(writeLocalPresentation(snapshot, presentation, storage), true);
    assert.deepEqual(readLocalPresentation(snapshot, storage), presentation);
    assert.deepEqual(readLocalPresentation(snapshot, storage).chartOverrides.trend.annotations, spec.annotations);
  }
  assert.deepEqual(snapshot, before);
});

test("presentation text edits and component titles accept only bounded authored strings", () => {
  for (const key of ["componentTitles", "textEdits"]) {
    assert.deepEqual(validatePresentation({ [key]: { "component:label": "Reviewed label" } }), {
      [key]: { "component:label": "Reviewed label" },
    });
    for (const invalid of [{ value: { rows: [{ amount: 42 }] } }, { value: 42 },
      { value: "   " }, { value: "x".repeat(20_001) }, { " ": "Visible copy" },
      { ["x".repeat(201)]: "Visible copy" }]) {
      assert.throws(() => validatePresentation({ [key]: invalid }), /bounded text values/u);
    }
    assert.deepEqual(normalizePresentation({ [key]: {
      keep: "Visible copy", nested: { rows: [{ amount: 42 }] }, empty: " ",
    } }), { [key]: { keep: "Visible copy" } });
  }
});

test("cleared narrative text survives validation and local storage without allowing empty titles", () => {
  const presentation = { textEdits: { "finding:body": "" } };
  assert.deepEqual(validatePresentation(presentation), presentation);
  const snapshot = { id: "cleared-narrative" };
  const storage = memoryStorage();
  assert.equal(writeLocalPresentation(snapshot, presentation, storage), true);
  assert.deepEqual(readLocalPresentation(snapshot, storage), presentation);
  assert.throws(() => validatePresentation({ componentTitles: { finding: "" } }), /nonempty titles/u);
  assert.deepEqual(normalizePresentation({ componentTitles: { finding: "" } }), { componentTitles: {} });
});

test("dashboard verification accepts only a bounded creator email and canonical UTC timestamp", () => {
  const verification = { verifiedBy: "creator@example.com", verifiedAt: "2026-08-17T19:34:56.789Z" };
  assert.deepEqual(validatePresentation({ verification }), { verification });
  assert.deepEqual(normalizePresentation({ verification: {
    verifiedBy: "  CREATOR@EXAMPLE.COM  ", verifiedAt: verification.verifiedAt,
  } }), { verification });

  for (const invalid of [
    null, "verified", true, [], {},
    { verifiedBy: verification.verifiedBy },
    { verifiedAt: verification.verifiedAt },
    { ...verification, rows: [{ amount: 42 }] },
    { ...verification, provenance: "fabricated" },
    { ...verification, verifiedBy: "" },
    { ...verification, verifiedBy: "   " },
    { ...verification, verifiedBy: "creator" },
    { ...verification, verifiedBy: "creator@example" },
    { ...verification, verifiedBy: `${"x".repeat(245)}@example.com` },
    { ...verification, verifiedBy: 42 },
    { ...verification, verifiedAt: "" },
    { ...verification, verifiedAt: "2026-08-17" },
    { ...verification, verifiedAt: "2026-08-17T19:34:56Z" },
    { ...verification, verifiedAt: "2026-08-17T19:34:56.789+00:00" },
    { ...verification, verifiedAt: "2026-02-30T19:34:56.789Z" },
    { ...verification, verifiedAt: 1_787_017_896_789 },
  ]) {
    assert.throws(() => validatePresentation({ verification: invalid }), /Verification must contain/u);
    assert.deepEqual(normalizePresentation({ verification: invalid }), {});
  }
});

test("verified dashboard metadata persists and merges as one protected presentation field", () => {
  const snapshot = { id: "verified-dashboard" };
  const verification = { verifiedBy: "creator@example.com", verifiedAt: "2026-08-17T19:34:56.789Z" };
  const original = { title: "Reviewed dashboard", verification };
  const storage = memoryStorage();

  assert.equal(writeLocalPresentation(snapshot, original, storage), true);
  assert.deepEqual(readLocalPresentation(snapshot, storage), original);
  assert.deepEqual(mergePresentationChanges(original, { ...original, title: "Updated dashboard" }, original), {
    title: "Updated dashboard", verification,
  });
  assert.deepEqual(mergePresentationChanges(original, { title: original.title }, original), {
    title: original.title,
  });
  assert.deepEqual(mergePresentationChanges({ title: original.title }, original, {
    title: "Concurrent update",
  }), { title: "Concurrent update", verification });
});

test("debounced hosted saves retain rapid verification changes and unrelated creator edits", async () => {
  const verification = { verifiedBy: "creator@example.com", verifiedAt: "2026-08-17T19:34:56.789Z" };
  for (const { label, initial, toggled, edited } of [
    {
      label: "verify",
      initial: { title: "Reviewed dashboard" },
      toggled: { title: "Reviewed dashboard", verification },
      edited: { title: "Updated dashboard", verification },
    },
    {
      label: "unverify",
      initial: { title: "Reviewed dashboard", verification },
      toggled: { title: "Reviewed dashboard" },
      edited: { title: "Updated dashboard" },
    },
  ]) {
    const harness = await presentationPersistenceHarness(initial);
    try {
      harness.render(initial);
      harness.render(toggled);
      assert.equal(harness.timers.size, 1, `${label}: toggling should schedule one hosted save`);
      harness.render(edited);
      assert.equal(harness.timers.size, 1, `${label}: a rapid edit should replace the earlier debounce timer`);
      await harness.flush();

      assert.equal(harness.requests.length, 1, `${label}: both creator changes should use one hosted write`);
      assert.deepEqual(harness.requests[0], { presentation: edited, revision: 0 },
        `${label}: the later edit must not discard a verification toggle from its canceled timer`);
      assert.deepEqual(harness.server.presentation, edited);
    } finally {
      harness.dispose();
    }
  }
});

test("debounced verification writes preserve conflict merges and later acknowledged creator edits", async () => {
  const initial = { title: "Reviewed dashboard", theme: "original" };
  const verification = { verifiedBy: "creator@example.com", verifiedAt: "2026-08-17T19:34:56.789Z" };
  const toggled = { ...initial, verification };
  const edited = { ...toggled, title: "Updated dashboard" };
  const harness = await presentationPersistenceHarness(initial);
  try {
    harness.render(initial);
    harness.render(toggled);
    harness.render(edited);
    harness.server.presentation = { ...initial, theme: "scientific-blue" };
    harness.server.revision = 1;
    await harness.flush();

    assert.equal(harness.requests.length, 2, "A stale verification write must retry its server conflict once");
    assert.deepEqual(harness.requests.map(({ revision }) => revision), [0, 1]);
    assert.deepEqual(harness.server.presentation, {
      title: "Updated dashboard", theme: "scientific-blue", verification,
    }, "A debounced verification and title change must retain the concurrent server-side theme");

    const subsequent = { ...edited, componentTitles: { revenue: "Recognized revenue" } };
    harness.render(subsequent);
    await harness.flush();
    assert.deepEqual(harness.server.presentation, {
      title: "Updated dashboard", theme: "scientific-blue", verification,
      componentTitles: { revenue: "Recognized revenue" },
    }, "Later acknowledged edits must remain rebased on the earlier conflict merge");
  } finally {
    harness.dispose();
  }
});

test("verification intents expose only server-acknowledged badge metadata and preserve immediate creator edits", async () => {
  const initial = { title: "Reviewed dashboard" };
  const acknowledgements = [];
  const onAcknowledged = (presentation, action) => acknowledgements.push({
    presentation: structuredClone(presentation), action,
  });
  const harness = await presentationPersistenceHarness(initial);
  try {
    harness.render(initial, { onAcknowledged });
    harness.render(initial, { verificationAction: "verify", onAcknowledged });
    assert.equal(harness.timers.size, 1,
      "A server-side verification intent must schedule a save without fabricated local badge metadata");

    const edited = { title: "Updated dashboard" };
    harness.render(edited, { verificationAction: "verify", onAcknowledged });
    assert.equal(harness.timers.size, 1,
      "An immediate creator edit must preserve the pending verification action in the same debounced save");
    assert.equal(acknowledgements.length, 0,
      "The creator must not see verified metadata before the trusted Worker acknowledges its stamp");
    await harness.flush();

    assert.deepEqual(harness.requests[0], {
      presentation: edited, revision: 0, verificationAction: "verify",
    }, "Verification requests must carry only an explicit action, never a client-fabricated identity");
    assert.deepEqual(acknowledgements, [{
      action: "verify", presentation: { ...edited, verification: {
        verifiedBy: "server-owner@example.com", verifiedAt: "2026-08-17T19:34:56.789Z",
      } },
    }], "The displayed badge must use only the Worker-returned authoritative verification record");

    const acknowledged = acknowledgements[0].presentation;
    harness.render(acknowledged, { onAcknowledged });
    assert.equal(harness.timers.size, 0,
      "Applying the server-stamped verification acknowledgement must not schedule a redundant save");
    harness.render(acknowledged, { verificationAction: "remove", onAcknowledged });
    const removalEdit = { ...acknowledged, title: "Unverified dashboard" };
    harness.render(removalEdit, { verificationAction: "remove", onAcknowledged });
    assert.equal(acknowledgements.length, 1,
      "A persisted badge must remain displayed until server-side removal is acknowledged");
    await harness.flush();

    assert.deepEqual(harness.requests[1], {
      presentation: removalEdit, revision: 1, verificationAction: "remove",
    }, "Removal must remain explicit and preserve creator edits while the old badge is still acknowledged");
    assert.deepEqual(acknowledgements[1], {
      action: "remove", presentation: { title: "Unverified dashboard" },
    }, "Only the trusted Worker may acknowledge that shared dashboard verification was removed");
  } finally {
    harness.dispose();
  }
});

test("server verification acknowledgements do not save again when the shell reorders presentation fields", async () => {
  const initial = {
    title: "Reviewed dashboard", blockLayouts: { main: { order: ["chart"] } },
    tabs: [{ id: "overview", label: "Overview" }], filters: { region: "all" },
  };
  const acknowledgements = [];
  const onAcknowledged = (saved) => acknowledgements.push(structuredClone(saved));
  const harness = await presentationPersistenceHarness(initial);
  try {
    harness.render(initial, { onAcknowledged });
    harness.render(initial, { verificationAction: "verify", onAcknowledged });
    await harness.flush();
    assert.equal(harness.requests.length, 1);
    assert.equal(acknowledgements.length, 1);

    harness.render({
      title: initial.title,
      verification: acknowledgements[0].verification,
      blockLayouts: initial.blockLayouts,
      tabs: initial.tabs,
      filters: initial.filters,
    }, { onAcknowledged });
    assert.equal(harness.timers.size, 0, "Verification insertion order must not schedule a no-op save");
    await harness.flush();
    assert.equal(harness.requests.length, 1, "Only the explicit verification action should write");
    assert.equal(harness.server.revision, 1);
    assert.equal(acknowledgements.length, 1);
    assert.equal(harness.status(), "saved");
  } finally { harness.dispose(); }
});

test("overlapping stale autosave acknowledgements cannot roll back a newer conflict-preserving baseline", async () => {
  for (const staleResult of ["success", "failure"]) {
    const initial = { title: "Reviewed dashboard", theme: "original" };
    const older = { title: "Older title", theme: "original" };
    const newer = { title: "Newer title", theme: "local-brand" };
    const acknowledgements = [];
    const errors = [];
    const options = {
      onAcknowledged: (presentation) => acknowledgements.push(structuredClone(presentation)),
      onError: (error) => errors.push(error),
    };
    const harness = await presentationPersistenceHarness(initial, { deferResponses: true });
    try {
      harness.render(initial, options);
      harness.render(older, options);
      const olderSave = harness.start();
      harness.render(newer, options);
      const newerSave = harness.start();
      assert.equal(harness.pendingResponses.length, 2,
        `${staleResult}: both in-flight autosaves must overlap`);

      harness.respond(1, { presentation: newer, revision: 2 });
      await newerSave;
      assert.deepEqual(acknowledgements, [newer]);
      assert.equal(harness.status(), "saved");

      if (staleResult === "success") {
        harness.respond(0, { presentation: older, revision: 1 });
      } else {
        harness.respond(0, { status: 500, error: "A stale request failed." });
      }
      await olderSave;
      assert.deepEqual(acknowledgements, [newer],
        `A stale ${staleResult} must not replace a newer authoritative acknowledgement`);
      assert.deepEqual(errors, [], `A stale ${staleResult} must not surface an obsolete autosave error`);
      assert.equal(harness.status(), "saved",
        `A stale ${staleResult} must not roll back a successfully acknowledged save status`);

      harness.resumeResponses();
      harness.server.presentation = { ...newer, theme: "concurrent-remote-brand" };
      harness.server.revision = 3;
      const subsequent = { ...newer, title: "Latest title" };
      harness.render(subsequent, options);
      await harness.flush();

      assert.deepEqual(harness.requests.slice(-2).map(({ revision }) => revision), [2, 3],
        `A stale ${staleResult} must not roll back the next autosave's acknowledged revision`);
      assert.deepEqual(harness.server.presentation, {
        title: "Latest title", theme: "concurrent-remote-brand",
      }, `A stale ${staleResult} must not replay old local changes over a newer concurrent server edit`);
    } finally {
      harness.dispose();
    }
  }
});

test("older successful saves preserve the server baseline without acknowledging a newer failed draft", async () => {
  for (const olderCompletesFirst of [true, false]) {
    const initial = { title: "Original", theme: "original" };
    const older = { ...initial, theme: "first-theme" };
    const newer = { ...initial, theme: "second-theme" };
    const acknowledgements = [];
    const errors = [];
    const options = {
      onAcknowledged: (saved) => acknowledgements.push(structuredClone(saved)),
      onError: (error) => errors.push(error),
    };
    const harness = await presentationPersistenceHarness(initial, { deferResponses: true });
    try {
      harness.render(initial, options);
      harness.render(older, options);
      const olderSave = harness.start();
      harness.render(newer, options);
      const newerSave = harness.start();

      if (olderCompletesFirst) {
        harness.respond(0, { presentation: older, revision: 1 });
        await olderSave;
        assert.equal(harness.status(), "saving", "The newer request is still pending");
        assert.deepEqual(acknowledgements, [], "The older response cannot acknowledge the pending draft");
      }
      harness.respond(1, { status: 500, error: "The newer save failed." });
      await newerSave;
      if (!olderCompletesFirst) {
        harness.respond(0, { presentation: older, revision: 1 });
        await olderSave;
      }
      assert.equal(harness.status(), "error", "An older success must not clear the newer save error");
      assert.deepEqual(errors, ["The newer save failed."]);
      assert.deepEqual(acknowledgements, []);

      harness.resumeResponses();
      harness.server.presentation = { ...older, componentTitles: { remote: "Concurrent title" } };
      harness.server.revision = 2;
      const subsequent = { ...newer, title: "Latest title" };
      harness.render(subsequent, options);
      await harness.flush();
      assert.deepEqual(harness.requests.slice(-2).map(({ revision }) => revision), [1, 2],
        "The older success still supplies the latest known revision for the next save");
      assert.deepEqual(harness.server.presentation, {
        ...subsequent, componentTitles: { remote: "Concurrent title" },
      }, "A later save retains the failed draft and concurrent server changes");
      assert.deepEqual(acknowledgements, [harness.server.presentation]);
      assert.equal(harness.status(), "saved");
    } finally { harness.dispose(); }
  }
});

test("overlapping saves preserve reverted and retained local fields in either response order", async () => {
  const changes = ["restore-theme", "restore-theme-and-edit-title", "retain-theme-and-edit-title"];
  const completionOrders = ["older-before-restore-starts", "older-before-restore-response", "restore-first"];
  for (const { change, completionOrder } of changes.flatMap((change) =>
    completionOrders.map((completionOrder) => ({ change, completionOrder })))) {
    const initial = { title: "Original", theme: "original" };
    const older = { ...initial, theme: "scientific-blue" };
    const current = change === "restore-theme" ? initial
      : { ...(change === "restore-theme-and-edit-title" ? initial : older), title: "Edited title" };
    const acknowledgements = [];
    const errors = [];
    const options = {
      onAcknowledged: (saved) => acknowledgements.push(structuredClone(saved)),
      onError: (error) => errors.push(error),
    };
    const harness = await presentationPersistenceHarness(initial, { deferResponses: true });
    try {
      harness.render(initial, options);
      harness.render(older, options);
      const olderSave = harness.start();
      harness.render(current, options);
      assert.equal(harness.timers.size, 1,
        "Restored and retained fields must remain a pending save while a different draft is in flight");

      if (completionOrder === "older-before-restore-starts") {
        harness.respond(0, { presentation: older, revision: 1 });
        await olderSave;
        assert.deepEqual(acknowledgements, [], "The earlier theme cannot acknowledge the restored theme");
      }
      const restoredSave = harness.start();
      assert.deepEqual(harness.requests[1].presentation, current);
      if (completionOrder === "older-before-restore-response") {
        harness.respond(0, { presentation: older, revision: 1 });
        await olderSave;
        assert.deepEqual(acknowledgements, []);
        assert.equal(harness.status(), "saving");
        harness.server.presentation = { ...older, componentTitles: { remote: "Concurrent title" } };
        harness.server.revision = 2;
        harness.resumeResponses();
        harness.respond(1, { status: 409, presentation: harness.server.presentation, revision: 2 });
        await restoredSave;
        assert.deepEqual(harness.requests.map(({ revision }) => revision), [0, 0, 2]);
        assert.deepEqual(harness.server.presentation, {
          ...current, componentTitles: { remote: "Concurrent title" },
        }, "A conflict retry preserves every desired field and concurrent server edits");
      } else {
        const revision = completionOrder === "restore-first" ? 1 : 2;
        harness.respond(1, { presentation: current, revision });
        await restoredSave;
        if (completionOrder === "restore-first") {
          harness.respond(0, { status: 409, presentation: current, revision });
          await olderSave;
          assert.equal(harness.requests.length, 2, "The superseded theme must not retry after the restoration wins");
        }
        assert.deepEqual(harness.server.presentation, current);
      }
      assert.deepEqual(errors, []);
      assert.deepEqual(acknowledgements, [harness.server.presentation]);
      assert.equal(harness.status(), "saved");
    } finally { harness.dispose(); }
  }
});

test("pending autosave reversions preserve the existing structural layout merge and remote additions", () => {
  const previous = { theme: "original", blockLayouts: { main: { order: ["a", "b", "c", "d"] } } };
  const pending = { theme: "scientific-blue", blockLayouts: { main: { order: ["a", "c", "b", "d"] } } };
  const latest = { ...pending, blockLayouts: {
    main: { order: ["a", "c", "b", "d", "remote"], spans: { remote: 6 } },
    remote: { order: ["summary"] },
  } };
  for (const current of [previous, {
    ...previous, blockLayouts: { main: { order: ["a", "b", "d", "c"] } },
  }]) {
    const existingMerge = mergePresentationChanges(previous, current, latest);
    const withPending = mergePresentationChanges(previous, current, latest, [pending]);
    assert.equal(withPending.theme, "original", "Ordinary autosave fields still replay the creator's reversion");
    assert.deepEqual(withPending.blockLayouts, existingMerge.blockLayouts,
      "Pending autosaves must not apply structural layout edits a second time");
    assert.ok(withPending.blockLayouts.main.order.includes("remote"));
    assert.equal(withPending.blockLayouts.main.spans.remote, 6);
    assert.deepEqual(withPending.blockLayouts.remote, { order: ["summary"] });
  }
});

test("dashboard descriptions remain optional while previously authored descriptions persist and reload", () => {
  const snapshot = { id: "optional-description-dashboard", title: "Product adoption" };
  const storage = memoryStorage();

  assert.deepEqual(normalizePresentation({ title: "Product adoption" }), { title: "Product adoption" });
  assert.equal(writeLocalPresentation(snapshot, { title: "Product adoption" }, storage), true);
  assert.equal(Object.hasOwn(readLocalPresentation(snapshot, storage), "description"), false);

  const authored = { title: "Product adoption", description: "Paid workspaces; excludes trials" };
  assert.equal(writeLocalPresentation(snapshot, authored, storage), true);
  assert.deepEqual(readLocalPresentation(snapshot, storage), authored);
});

test("disabled chart zero baselines persist and reload without becoming enabled", () => {
  const snapshot = { id: "focused-waterfall-dashboard", title: "Product adoption" };
  const presentation = { chartOverrides: {
    "growth-drivers": { type: "waterfall", x: "driver", y: "change", startAtZero: false },
  } };
  const storage = memoryStorage();

  assert.equal(writeLocalPresentation(snapshot, presentation, storage), true);
  assert.deepEqual(readLocalPresentation(snapshot, storage), presentation);
});

test("presentation stores only bounded presentation changes and isolates dashboard identities", () => {
  const snapshot = { id: "reviewed-dashboard", title: "Original dashboard title" };
  const presentation = {
    theme: "scientific-blue", title: "Edited title", description: "Edited description",
    hiddenBlocks: ["forecast", "forecast"], componentTitles: { revenue: "Recognized revenue" },
    textEdits: { "p:2": "An edited analysis." }, chartOverrides: { trend: { type: "bar" } },
    filters: { region: "West" }, assumptions: { conversion: 12 }, notes: "## Reviewed notes",
    tabs: [{ id: "overview", label: "Overview" }, { id: "details", label: "Details" }],
  };
  const storage = memoryStorage();
  assert.equal(writeLocalPresentation(snapshot, presentation, storage), true);
  assert.deepEqual(readLocalPresentation(snapshot, storage), { ...presentation, hiddenBlocks: ["forecast"] });
  assert.deepEqual(readLocalPresentation({ ...snapshot, id: "another-dashboard" }, storage), {});
  const record = JSON.parse([...storage.values.values()][0]);
  assert.equal(record.version, presentationVersion);
  assert.equal(presentationStorageKey(snapshot, "/one") === presentationStorageKey(snapshot, "/two"), false);
  assert.throws(() => validatePresentation({ rows: [{ amount: 42 }] }), /Unsupported presentation fields/);
  assert.throws(() => validatePresentation({ chartOverrides: { trend: { type: "line", rows: [{ amount: 42 }] } } }),
    /reviewed data or provenance/);
  const malformed = { ...presentation, chartOverrides: { trend: {
    type: "line", x: "week", y: ["siteA", "siteB"],
  } } };
  assert.throws(() => validatePresentation(malformed), /Invalid chart "trend": chart\.y.*not an array/u);
  assert.equal(writeLocalPresentation(snapshot, malformed, storage), false);
  assert.deepEqual(readLocalPresentation(snapshot, storage), { ...presentation, hiddenBlocks: ["forecast"] },
    "A malformed chart edit cannot replace the previous saved presentation");
  const fields = Array.from({ length: 41 }, (_, index) => `reviewed-${"column-".repeat(30)}${index}`);
  const widePresentation = { chartOverrides: { trend: { type: "line", x: "week", y: fields[0], fields } } };
  assert.equal(writeLocalPresentation(snapshot, widePresentation, storage), true);
  assert.deepEqual(readLocalPresentation(snapshot, storage), widePresentation,
    "Inline payload budgets must not limit saved durable chart bindings");
  assert.throws(() => validatePresentation({ hiddenBlocks: [4] }), /Hidden blocks/);
  assert.throws(() => validatePresentation({ notes: "x".repeat(128_001) }), /size limit/);
  assert.throws(() => validatePresentation({ tabs: [{ id: "overview", label: "Overview" },
    { id: "overview", label: "Duplicate" }] }), /Tabs must be a bounded list/);
  assert.throws(() => validatePresentation({ tabs: [{ id: "overview", label: "" }] }),
    /Tabs must be a bounded list/);
  assert.deepEqual(normalizePresentation({ theme: "dark-pixel", queries: { secret: true } }), {
    theme: "dark-pixel",
  });
});

test("an explicit legacy title migrates the complete valid presentation without deleting its old record", () => {
  const legacy = { surface: "report", title: "Original report question?" };
  const snapshot = { surface: "report", id: "report-stable-123", title: "A clearer conclusion",
    legacyPresentationTitle: legacy.title };
  const presentation = {
    theme: "scientific-blue", appearance: "dark", title: "My edited title", description: "My description",
    hiddenBlocks: ["risk"], componentTitles: { revenue: "Recognized revenue" },
    textEdits: { "finding:body": "My complete edited recommendation." },
    chartOverrides: { trend: { type: "bar" } }, filters: { region: "West" },
    assumptions: { conversion: 12 }, notes: "## Notes",
    refreshSchedule: { frequency: "daily", time: "09:00" },
    tabs: [{ id: "overview", label: "Overview" }],
    blockLayouts: { story: { order: ["finding", "risk"] } },
  };
  const storage = memoryStorage();
  assert.equal(writeLocalPresentation(legacy, presentation, storage), true);
  assert.equal(writeViewerAppearance(legacy, "light", storage), true);
  const oldKey = presentationStorageKey(legacy);
  const stableKey = presentationStorageKey(snapshot);
  const originalRecord = storage.getItem(oldKey);

  assert.deepEqual(readLocalPresentation(snapshot, storage), presentation);
  assert.equal(storage.getItem(stableKey), originalRecord);
  assert.equal(storage.getItem(oldKey), originalRecord);
  assert.equal(readViewerAppearance(snapshot, storage), "light");
  assert.equal(storage.getItem(`${stableKey}:viewer-appearance`), "light");
  assert.equal(storage.getItem(`${oldKey}:viewer-appearance`), "light");
  assert.deepEqual(readLocalPresentation({ ...snapshot, title: "Renamed again" }, storage), presentation);
  assert.equal(presentationStorageKey({ ...snapshot, title: "Renamed again" }), stableKey);
});

test("stable presentation and appearance records win independently, including explicit resets and corrupt records", () => {
  const legacy = { title: "Old report" };
  const snapshot = { id: "stable-report", title: "New report", legacyPresentationTitle: legacy.title };
  const storage = memoryStorage();
  writeLocalPresentation(legacy, { title: "Legacy title", textEdits: { body: "Legacy text" } }, storage);
  writeViewerAppearance(legacy, "dark", storage);
  writeLocalPresentation(snapshot, { title: "Current title" }, storage);
  assert.deepEqual(readLocalPresentation(snapshot, storage), { title: "Current title" });
  assert.equal(readViewerAppearance(snapshot, storage), "dark");
  assert.equal(writeViewerAppearance(snapshot, "", storage), true);
  assert.equal(readViewerAppearance(snapshot, storage), "");
  assert.equal(storage.getItem(`${presentationStorageKey(snapshot)}:viewer-appearance`), "");
  assert.equal(storage.getItem(`${presentationStorageKey(legacy)}:viewer-appearance`), "dark");

  const key = presentationStorageKey(snapshot);
  storage.setItem(key, "{corrupt current record");
  assert.deepEqual(readLocalPresentation(snapshot, storage), {});
  assert.equal(storage.getItem(key), "{corrupt current record");
  storage.setItem(`${key}:viewer-appearance`, "invalid-current-value");
  assert.equal(readViewerAppearance(snapshot, storage), "");
  assert.equal(storage.getItem(`${key}:viewer-appearance`), "invalid-current-value");
  writeLocalPresentation(snapshot, {}, storage);
  assert.deepEqual(readLocalPresentation(snapshot, storage), {});
});

test("legacy lookup requires one bounded exact alias and a safe stable ID", () => {
  const legacy = { title: "Old report" };
  const stored = memoryStorage();
  writeLocalPresentation(legacy, { title: "Legacy title" }, stored);
  const invalid = [
    { title: "New report", legacyPresentationTitle: legacy.title },
    { id: "stable-report", title: "New report" },
    ...["", " ", "../report", "report/id", "report:id", "x".repeat(201), 4]
      .map((id) => ({ id, title: "New report", legacyPresentationTitle: legacy.title })),
    ...["", " ", "x".repeat(301), "Old\nreport", "Old\u007freport", [legacy.title], 4]
      .map((legacyPresentationTitle) => ({ id: "stable-report", title: "New report", legacyPresentationTitle })),
  ];
  for (const snapshot of invalid) {
    const reads = [];
    const storage = { getItem(key) { reads.push(key); return stored.getItem(key); },
      setItem() { assert.fail("Invalid identity must not migrate"); } };
    assert.deepEqual(readLocalPresentation(snapshot, storage), {});
    assert.deepEqual(reads, [presentationStorageKey(snapshot)]);
  }
  const exactTitle = "  Original title with spaces  ";
  const storage = memoryStorage();
  writeLocalPresentation({ title: exactTitle }, { title: "Keep the exact old key" }, storage);
  assert.deepEqual(readLocalPresentation({ id: "stable-exact", legacyPresentationTitle: exactTitle }, storage),
    { title: "Keep the exact old key" });
});

test("legacy migration stays at the same canonical artifact path and never enumerates storage", () => {
  const previousLocation = Object.getOwnPropertyDescriptor(globalThis, "location");
  const legacy = { title: "Shared title" };
  const snapshot = { id: "specific-report", legacyPresentationTitle: legacy.title };
  const values = new Map([
    [presentationStorageKey(legacy, "/one/index.html"), JSON.stringify({
      version: presentationVersion, presentation: { title: "Report one" },
    })],
    [presentationStorageKey(legacy, "/two/index.html"), JSON.stringify({
      version: presentationVersion, presentation: { title: "Report two" },
    })],
  ]);
  const reads = [];
  const storage = { getItem(key) { reads.push(key); return values.get(key) ?? null; },
    setItem: (key, value) => values.set(key, value),
    key() { assert.fail("Must not enumerate browser storage"); },
    get length() { assert.fail("Must not enumerate browser storage"); } };
  try {
    Object.defineProperty(globalThis, "location", { configurable: true, value: { pathname: "/one/index.html" } });
    assert.deepEqual(readLocalPresentation(snapshot, storage), { title: "Report one" });
    assert.ok(reads.every((key) => key.includes(":/one/index.html:")));
    assert.equal(values.has(presentationStorageKey(snapshot, "/two/index.html")), false);
  } finally {
    if (previousLocation) Object.defineProperty(globalThis, "location", previousLocation);
    else delete globalThis.location;
  }
});

test("invalid legacy records are not copied and unavailable storage fails safely", () => {
  const legacy = { title: "Old report" };
  const snapshot = { id: "stable-report", legacyPresentationTitle: legacy.title };
  const oldKey = presentationStorageKey(legacy);
  const key = presentationStorageKey(snapshot);
  for (const value of ["not json", "null", JSON.stringify({ version: 2, presentation: {} }),
    JSON.stringify({ version: presentationVersion, presentation: { rows: [{ secret: true }] } }),
    JSON.stringify({ version: presentationVersion, presentation: { textEdits: { body: "x".repeat(20_001) } } }),
    " ".repeat(132_097)]) {
    const storage = memoryStorage();
    storage.setItem(oldKey, value);
    assert.deepEqual(readLocalPresentation(snapshot, storage), {});
    assert.equal(storage.getItem(key), null);
    assert.equal(storage.getItem(oldKey), value);
  }
  const legacyValue = JSON.stringify({ version: presentationVersion, presentation: { title: "Keep readable edits" } });
  const readonly = { getItem: (candidate) => candidate === oldKey ? legacyValue : null,
    setItem() { throw new Error("Quota or write denied"); } };
  assert.deepEqual(readLocalPresentation(snapshot, readonly), { title: "Keep readable edits" });
  const unavailable = { getItem() { throw new Error("Storage denied"); }, setItem() { throw new Error("Storage denied"); } };
  assert.deepEqual(readLocalPresentation(snapshot, unavailable), {});
  assert.equal(readViewerAppearance(snapshot, unavailable), "");
  assert.equal(writeLocalPresentation(snapshot, {}, unavailable), false);
  assert.equal(writeViewerAppearance(snapshot, "dark", unavailable), false);
});

test("a stable record arriving during legacy lookup is never overwritten", () => {
  const legacy = { title: "Old report" };
  const snapshot = { id: "stable-report", legacyPresentationTitle: legacy.title };
  const key = presentationStorageKey(snapshot);
  const oldKey = presentationStorageKey(legacy);
  const encode = (title) => JSON.stringify({ version: presentationVersion, presentation: { title } });
  let stableReads = 0;
  const storage = { getItem(candidate) {
    if (candidate === oldKey) return encode("Legacy");
    if (candidate === key) return ++stableReads === 1 ? null : encode("Current");
    return null;
  }, setItem() { assert.fail("Must not replace the current stable record"); } };
  assert.deepEqual(readLocalPresentation(snapshot, storage), { title: "Current" });
});

test("valid widget and chart permalinks share their dashboard presentation without merging unrelated paths", () => {
  const snapshot = { id: "reviewed-dashboard" };
  const dashboardKey = presentationStorageKey(snapshot, "/");
  const componentUuid = componentPermalinkId("https://dashboard.chatgpt.site", "active-users");
  const chartUuid = componentPermalinkId("https://dashboard.chatgpt.site", "usage-trend");
  const componentShortId = componentPermalinkShortId("https://dashboard.chatgpt.site", "active-users");
  const chartShortId = componentPermalinkShortId("https://dashboard.chatgpt.site", "usage-trend");

  assert.equal(presentationStorageKey(snapshot, `/_data/components/${componentShortId}`), dashboardKey);
  assert.equal(presentationStorageKey(snapshot, `/_data/charts/${chartShortId}`), dashboardKey);
  assert.equal(presentationStorageKey(snapshot, `/_data/charts/${chartShortId}/detail`), dashboardKey);
  assert.equal(presentationStorageKey(snapshot, `/_data/components/${componentUuid}`), dashboardKey);
  assert.equal(presentationStorageKey(snapshot, `/_data/charts/${chartUuid}`), dashboardKey);
  assert.equal(presentationStorageKey(snapshot, `/_data/charts/${chartUuid}/detail`), dashboardKey);
  assert.equal(presentationStorageKey(snapshot, "/_data/components/active-users"), dashboardKey);
  assert.equal(presentationStorageKey(snapshot, "/_data/components/usage-details"), dashboardKey);
  assert.equal(presentationStorageKey(snapshot, "/_data/components/Revenue%20growth"), dashboardKey);
  assert.equal(presentationStorageKey(snapshot, "/_data/charts/usage-trend"), dashboardKey);
  assert.equal(presentationStorageKey(snapshot, "/_data/charts/usage-trend/detail"), dashboardKey);
  assert.equal(presentationStorageKey(snapshot, "/_data/charts/Revenue%20growth"), dashboardKey);
  assert.notEqual(presentationStorageKey(snapshot, "/_data/components/parent%2Fchild"), dashboardKey);
  assert.notEqual(presentationStorageKey(snapshot, "/_data/components/active-users/detail"), dashboardKey);
  assert.notEqual(presentationStorageKey(snapshot, "/_data/components/active-users/"), dashboardKey);
  assert.notEqual(presentationStorageKey(snapshot, "/_data/charts/parent%2Fchild"), dashboardKey);
  assert.notEqual(presentationStorageKey(snapshot, "/_data/charts/usage-trend/"), dashboardKey);
  assert.notEqual(presentationStorageKey(snapshot, "/one"), presentationStorageKey(snapshot, "/two"));
  assert.notEqual(presentationStorageKey({ id: "another-dashboard" }, "/_data/components/active-users"),
    dashboardKey);
  assert.notEqual(presentationStorageKey({ id: "another-dashboard" }, "/_data/charts/usage-trend"), dashboardKey);
});

test("tab order merges as one shared presentation change", () => {
  const previous = { tabs: [{ id: "overview", label: "Overview" }, { id: "details", label: "Details" }] };
  const next = { tabs: [{ id: "details", label: "Details" }, { id: "overview", label: "Overview" }] };
  assert.deepEqual(mergePresentationChanges(previous, next, previous), next);
});

test("creator refresh schedules persist separately from reviewed data and reject invalid settings", () => {
  const snapshot = { id: "source-backed-dashboard" };
  for (const [schedule, expected] of [
    [
      { frequency: "custom", time: "09:17", days: ["SU", "WE", "MO"] },
      { frequency: "custom", time: "09:17", days: ["MO", "WE", "SU"] },
    ],
    [{ frequency: "hourly" }, { frequency: "hourly" }],
    [{ frequency: "hourly", time: "09:00", days: ["MO"] }, { frequency: "hourly" }],
  ]) {
    const storage = memoryStorage();
    const presentation = { refreshSchedule: schedule };
    assert.deepEqual(validatePresentation(presentation), { refreshSchedule: expected });
    assert.deepEqual(validateWorkerPresentation(presentation), { refreshSchedule: expected });
    assert.equal(writeLocalPresentation(snapshot, presentation, storage), true);
    assert.deepEqual(readLocalPresentation(snapshot, storage), { refreshSchedule: expected });
    assert.deepEqual(mergePresentationChanges({}, presentation, { title: "Reviewed title" }), {
      title: "Reviewed title", refreshSchedule: expected,
    });
  }
  assert.throws(() => validatePresentation({ refreshSchedule: { frequency: "daily", time: "29:00" } }),
    /Refresh schedule must include/);
  assert.throws(() => validatePresentation({ refreshSchedule: { frequency: "custom", time: "09:00", days: [] } }),
    /Refresh schedule must include/);
});

test("concurrent presentation edits merge changed fields without discarding another editor", () => {
  const previous = { theme: "original", componentTitles: { revenue: "Revenue" }, filters: { region: "all" } };
  const mine = { theme: "scientific-blue", componentTitles: { revenue: "Recognized revenue" }, filters: { region: "all" } };
  const theirs = { theme: "original", componentTitles: { revenue: "Revenue", costs: "Operating costs" },
    filters: { region: "West" }, hiddenBlocks: ["forecast"] };
  assert.deepEqual(mergePresentationChanges(previous, mine, theirs), {
    theme: "scientific-blue", hiddenBlocks: ["forecast"],
    componentTitles: { revenue: "Recognized revenue", costs: "Operating costs" }, filters: { region: "West" },
  });
});

test("unrelated hosted owner edits preserve an existing verified refresh schedule", () => {
  const schedule = { frequency: "weekdays", time: "09:00" };
  const original = { theme: "original", title: "Reviewed dashboard", refreshSchedule: schedule };
  const edited = { ...original, title: "Edited dashboard" };

  assert.deepEqual(mergePresentationChanges(original, edited, original), {
    theme: "original", title: "Edited dashboard", refreshSchedule: schedule,
  });
});

test("later owner edits remain rebased on an earlier cross-session conflict merge", async () => {
  const original = { theme: "original", title: "Reviewed dashboard", componentTitles: { revenue: "Revenue" } };
  const firstLocal = { ...original, title: "Edited dashboard" };
  const concurrentRemote = {
    ...original, theme: "dark-pixel", componentTitles: { revenue: "Revenue", costs: "Operating costs" },
  };
  const firstMerged = mergePresentationChanges(original, firstLocal, concurrentRemote);
  const secondLocal = { ...firstLocal, componentTitles: { revenue: "Recognized revenue" } };
  const secondMerged = mergePresentationChanges(firstLocal, secondLocal, firstMerged);
  assert.deepEqual(secondMerged, {
    theme: "dark-pixel", title: "Edited dashboard",
    componentTitles: { revenue: "Recognized revenue", costs: "Operating costs" },
  }, "A second local edit cannot silently overwrite fields preserved during the earlier conflict");

  const harness = await presentationPersistenceHarness(original);
  try {
    harness.render(original);
    harness.server.presentation = concurrentRemote;
    harness.server.revision = 1;
    harness.render(firstLocal);
    await harness.flush();
    assert.deepEqual(harness.server.presentation, firstMerged);
    harness.render(secondLocal);
    await harness.flush();
    assert.deepEqual(harness.requests.map(({ revision }) => revision), [0, 1, 2]);
    assert.deepEqual(harness.server.presentation, secondMerged,
      "Later owner saves preserve the local delta and fields retained during an earlier 409 merge");
  } finally { harness.dispose(); }
});

function fakeDatabase() {
  const state = { snapshot: null, queries: new Map(), rows: new Map(), presentation: null, maxBoundParameters: 0 };
  return {
    state,
    prepare(sql) {
      const statement = {
        values: [],
        bind(...values) {
          this.values = values;
          state.maxBoundParameters = Math.max(state.maxBoundParameters, values.length);
          return this;
        },
        async run() {
          if (sql.startsWith("SELECT metadata_json")) return { results: [await this.first()] };
          if (sql.startsWith("SELECT")) return this.all();
          if (this.values.length > 100) throw new Error("D1 statements accept at most 100 parameters.");
          if (sql.startsWith("DELETE FROM data_app_query_rows")) {
            if (this.values.length) {
              for (const [key, row] of state.rows) {
                if (row.query_id === this.values[0]) state.rows.delete(key);
              }
            } else {
              state.rows.clear();
            }
          }
          if (sql.startsWith("DELETE FROM data_app_queries")) state.queries.clear();
          if (sql.startsWith("INSERT INTO data_app_snapshots")) {
            const [, metadata_json, seed_sha256] = this.values;
            state.snapshot = { metadata_json, seed_sha256 };
          }
          if (sql.startsWith("INSERT INTO data_app_queries")) {
            const [id, position, query_json] = this.values;
            state.queries.set(id, { id, position, query_json });
          }
          if (sql.startsWith("INSERT INTO data_app_query_rows")) {
            for (let index = 0; index < this.values.length; index += 3) {
              const [query_id, position, row_json] = this.values.slice(index, index + 3);
              state.rows.set(`${query_id}:${position}`, { query_id, position, row_json });
            }
          }
          if (sql.startsWith("UPDATE data_app_snapshots")) {
            state.snapshot.metadata_json = JSON.stringify({
              ...JSON.parse(state.snapshot.metadata_json), generatedAt: this.values[0],
            });
          }
          if (sql.startsWith("INSERT INTO data_app_presentation_v1")) {
            if (!state.presentation) {
              const [, presentation, revision, updatedAt] = this.values;
              state.presentation = { presentation_json: presentation, revision, updated_at: updatedAt };
            }
          }
          if (sql.startsWith("UPDATE data_app_presentation_v1")) {
            const [presentation, updatedAt, , revision] = this.values;
            if (state.presentation.revision !== revision) return { meta: { changes: 0 } };
            state.presentation = { presentation_json: presentation, revision: revision + 1, updated_at: updatedAt };
            return { meta: { changes: 1 } };
          }
          return { meta: { changes: 0 } };
        },
        async first() {
          if (sql.includes("SELECT presentation_json")) return state.presentation;
          if (sql.includes("SELECT seed_sha256")) {
            return state.snapshot && { seed_sha256: state.snapshot.seed_sha256 };
          }
          if (sql.includes("SELECT metadata_json")) {
            return state.snapshot && { metadata_json: state.snapshot.metadata_json };
          }
          return null;
        },
        async all() {
          if (sql.includes("FROM data_app_queries")) {
            return { results: [...state.queries.values()].sort((a, b) => a.position - b.position) };
          }
          if (sql.includes("FROM data_app_query_rows")) {
            return { results: [...state.rows.values()].sort((a, b) =>
              a.query_id.localeCompare(b.query_id) || a.position - b.position) };
          }
          return { results: [] };
        },
      };
      return statement;
    },
    async batch(statements) {
      const previous = {
        snapshot: state.snapshot && { ...state.snapshot },
        queries: new Map(state.queries),
        rows: new Map(state.rows),
        presentation: state.presentation && { ...state.presentation },
      };
      try {
        const results = [];
        for (const statement of statements) results.push(await statement.run());
        return results;
      } catch (error) {
        Object.assign(state, previous);
        throw error;
      }
    },
  };
}

async function loadDashboardWorker(seed, initialPresentation = {}) {
  return createDataAppWorker({
    html: "<main>Dashboard</main>",
    seedSnapshot: seed,
    initialPresentation,
  });
}

test("the hosted Worker adds one trusted Sites project reference to dashboard HTML", async () => {
  const worker = createDataAppWorker({
    html: "<!doctype html><html><head><title>Dashboard</title></head><body></body></html>",
    projectId: "appgprj_123",
    seedSnapshot: { queries: {} },
  });
  const response = await worker.fetch(new Request("https://dashboard.chatgpt.site/_data/charts/active-users"), {});
  const html = await response.text();
  assert.equal(html.match(/data-app-sites-project/gu)?.length, 1);
  assert.match(html, /<head><meta name="data-app-sites-project" content="appgprj_123">/u);
  assert.throws(
    () => createDataAppWorker({
      html: '<head><meta name="data-app-sites-project" content="forged"></head>',
      projectId: "appgprj_123",
      seedSnapshot: { queries: {} },
    }),
    /must not define its Sites project identity/u,
  );
  assert.throws(
    () => createDataAppWorker({ html: "<head></head>", projectId: "../private", seedSnapshot: { queries: {} } }),
    /Sites project ID is invalid/u,
  );
});

test("the hosted Worker ignores Sites marker text in scripts and comments", async () => {
  const reviewedHtml = `<!doctype html><html><head>
    <!-- <meta name="data-app-sites-project" content="comment"> -->
    <script>const example = '</head><meta name="data-app-sites-project" content="script">';</script>
    <style>head::after { content: 'meta[name="data-app-sites-project"]'; }</style>
    <meta name="description" content='Example: name="data-app-sites-project"'>
    </head><body>
    <script>document.querySelectorAll('meta[name="data-app-sites-project"]');</script>
    </body></html>`;
  const worker = createDataAppWorker({
    html: reviewedHtml,
    projectId: "appgprj_123",
    seedSnapshot: { queries: {} },
  });
  const html = await (await worker.fetch(new Request("https://dashboard.chatgpt.site/"), {})).text();
  assert.equal(html, reviewedHtml.replace("<head>", '<head><meta name="data-app-sites-project" content="appgprj_123">'));
  assert.throws(
    () => createDataAppWorker({
      html: '<head><META content="forged > identity" NAME = data-app-sites-project></head>',
      projectId: "appgprj_123",
      seedSnapshot: { queries: {} },
    }),
    /must not define its Sites project identity/u,
  );
});

test("the reusable Worker validates and seeds presentation without replacing later D1 edits", async () => {
  assert.equal(validateWorkerPresentation, validatePresentation);
  assert.throws(() => createDataAppWorker({
    html: "<main>Dashboard</main>", seedSnapshot: { queries: {} },
    initialPresentation: { appearance: "invalid" },
  }), /Appearance must be/u);
  const database = fakeDatabase();
  const first = await loadDashboardWorker({ queries: {} }, { title: "Reviewed initial title",
    verification: { verifiedBy: "forged@example.com", verifiedAt: "2026-08-17T19:34:56.789Z" } });
  const request = new Request("https://dashboard.chatgpt.site/api/presentation");
  const initial = await (await first.fetch(request, { DB: database })).json();
  assert.equal(initial.presentation.title, "Reviewed initial title");
  assert.equal(Object.hasOwn(initial.presentation, "verification"), false);
  const redeployed = await loadDashboardWorker({ queries: {} }, { title: "New source default" });
  const preserved = await (await redeployed.fetch(request, { DB: database })).json();
  assert.deepEqual(preserved.presentation, initial.presentation);
  assert.equal(preserved.revision, 0);
});


test("hosted edit authorization rejects missing, malformed, and overlong trusted emails", async () => {
  const seed = { title: "Reviewed dashboard", queries: {} };
  const environment = {
    DB: { prepare() { assert.fail("Invalid caller identity must not touch dashboard storage."); } },
  };

  for (const email of [null, "", " \t ", "not-an-email", "owner@@example.com", "owner@example",
    "ow ner@example.com", "owner\0@example.com", "owner\x7f@example.com", "\towner@example.com",
    "owner@example.com\n", "owner\u0085@example.com", `${"x".repeat(245)}@example.com`]) {
    const emailHash = createHash("sha256").update(email?.trim().toLowerCase() ?? "").digest("hex");
    environment.DATA_APP_OWNER_EMAIL_SHA256 = emailHash;
    const worker = await loadDashboardWorker(seed);
    const request = (path, method = "GET") => ({
      url: `https://dashboard.chatgpt.site${path}`,
      method,
      headers: { get(name) {
        if (name === "oai-authenticated-user-email") return email;
        if (name === "oai-authenticated-user-id") return "SiteUser_CurrentOwner";
        return null;
      } },
    });
    assert.equal((await worker.fetch(request("/api/presentation", "PUT"), environment)).status, 403);
    assert.equal((await worker.fetch(request("/api/queries/reviewed", "PUT"), environment)).status, 403);
  }
});

test("missing or malformed owner environment hashes keep every write read-only despite packaged identity", async () => {
  const email = "owner@example.com";
  const emailHash = createHash("sha256").update(email).digest("hex");
  const environment = {
    DB: { prepare() { assert.fail("An invalid owner configuration must not touch dashboard storage."); } },
  };
  const headers = { "oai-authenticated-user-email": email };
  for (const ownerValue of [undefined, "", "invalid", emailHash.toUpperCase(), ` ${emailHash}`, `${emailHash}\n`, null, 42, [emailHash]]) {
    environment.DATA_APP_OWNER_EMAIL_SHA256 = ownerValue;
    const worker = createDataAppWorker({ html: "<main>Dashboard</main>", seedSnapshot: { queries: {} }, ownerEmailSha256: emailHash });
    for (const path of ["/api/presentation", "/api/queries/reviewed", "/api/queries"]) {
      assert.equal((await worker.fetch(new Request(`https://dashboard.chatgpt.site${path}`, {
        method: "PUT", headers, body: "{}",
      }), environment)).status, 403);
    }
  }
});

test("editor republishing cannot replace the managed owner or overwrite persisted presentation and rows", async () => {
  const owner = "owner-a@example.com", editor = "editor-b@example.com";
  const hash = email => createHash("sha256").update(email).digest("hex");
  const seed = { title: "Reviewed dashboard", queries: { reviewed: { rows: [{ amount: 42 }] } } };
  const environment = { DB: fakeDatabase(seed), DATA_APP_OWNER_EMAIL_SHA256: hash(owner) };
  const configuration = { html: "<main>Dashboard</main>", seedSnapshot: seed };
  const original = createDataAppWorker(configuration);
  const fetch = (worker, path, email, body) => worker.fetch(new Request(`https://dashboard.chatgpt.site${path}`, {
    method: body === undefined ? "GET" : "PUT",
    headers: { "oai-authenticated-user-email": email, "content-type": "application/json" },
    ...(body === undefined ? {} : { body: JSON.stringify(body) }),
  }), environment);
  const savedPresentation = { title: "Owner's saved presentation" }, savedRows = [{ amount: 84 }];
  assert.equal((await fetch(original, "/api/presentation", owner, { revision: 0, presentation: savedPresentation })).status, 200);
  assert.equal((await fetch(original, "/api/queries/reviewed", owner, { rows: savedRows })).status, 200);

  const republished = createDataAppWorker({
    ...configuration,
    ownerEmailSha256: hash(editor),
    initialPresentation: { title: "Editor's packaged default" },
  });
  for (const [email, expectedCanEdit] of [[owner, true], [editor, false]]) {
    const response = await (await fetch(republished, "/api/presentation", email)).json();
    assert.equal(response.canEdit, expectedCanEdit);
    assert.equal(response.ownerEnvironmentConfigured, true);
    assert.deepEqual(response.presentation, savedPresentation);
    assert.equal(response.revision, 1);
    assert.equal(JSON.stringify(response).includes(hash(owner)), false, "Readiness must not expose the owner hash");
    assert.equal(JSON.stringify(response).includes(owner), false, "Readiness must not expose the owner email");
  }
  assert.equal((await fetch(republished, "/api/presentation", editor, { revision: 1, presentation: {} })).status, 403);
  assert.equal((await fetch(republished, "/api/queries/reviewed", editor, { rows: [] })).status, 403);
  assert.equal((await fetch(republished, "/api/queries", editor, {
    updates: [{ queryId: "reviewed", rows: [], executedAt: "2026-09-09T00:00:00Z" }],
  })).status, 403);
  assert.deepEqual((await (await fetch(republished, "/api/snapshot", editor)).json()).queries.reviewed.rows, savedRows);
  assert.equal((await fetch(republished, "/api/presentation", owner, { revision: 1, presentation: savedPresentation })).status, 200);
  assert.equal((await fetch(republished, "/api/queries/reviewed", owner, { rows: savedRows })).status, 200);

  for (const invalidValue of [undefined, "invalid"]) {
    environment.DATA_APP_OWNER_EMAIL_SHA256 = invalidValue;
    const response = await (await fetch(republished, "/api/presentation", editor)).json();
    assert.equal(response.ownerEnvironmentConfigured, false);
    assert.equal(response.canEdit, false);
    assert.deepEqual(response.presentation, savedPresentation);
  }
});

test("hosted widget, chart, and detail permalinks serve only safe GET and bodyless HEAD dashboard routes", async () => {
  const worker = await loadDashboardWorker({ title: "Reviewed dashboard", queries: {} });
  const componentUuid = componentPermalinkId("https://dashboard.chatgpt.site", "active-users");
  const chartUuid = componentPermalinkId("https://dashboard.chatgpt.site", "usage-trend");
  const componentShortId = componentPermalinkShortId("https://dashboard.chatgpt.site", "active-users");
  const chartShortId = componentPermalinkShortId("https://dashboard.chatgpt.site", "usage-trend");
  const environment = {
    DB: { prepare() { assert.fail("Component permalink HTML must not read or change dashboard data."); } },
  };
  const fetch = (path, options = {}) => worker.fetch(
    new Request(`https://dashboard.chatgpt.site${path}`, options), environment,
  );
  const root = await fetch("/");
  const expectedHtml = await root.text();

  for (const path of [
    `/_data/components/${componentShortId}`, `/_data/charts/${chartShortId}`, `/_data/charts/${chartShortId}/detail`,
    `/_data/components/${componentUuid}`, `/_data/charts/${chartUuid}`, `/_data/charts/${chartUuid}/detail`,
    "/_data/components/active-users", "/_data/components/notes", "/_data/components/usage-details",
    "/_data/components/detail", "/_data/components/Revenue%20%26%20growth",
    "/_data/components/%F0%9F%93%88", "/_data/components/%252F", "/_data/components/missing-widget",
    `/_data/components/${"x".repeat(200)}`, "/_data/components/active-users?token=private#draft",
    "/_data/charts/usage-trend", "/_data/charts/usage-trend/detail",
    "/_data/charts/Revenue%20%26%20growth", "/_data/charts/%F0%9F%93%88/detail",
    "/_data/charts/%252F", "/_data/charts/missing-chart", `/_data/charts/${"x".repeat(200)}`,
    "/_data/charts/usage-trend?token=private#draft",
  ]) {
    const response = await fetch(path);
    assert.equal(response.status, 200, path);
    assert.equal(response.headers.get("content-type"), "text/html; charset=utf-8", path);
    assert.equal(await response.text(), expectedHtml, path);
  }

  for (const path of [
    `/_data/components/${componentShortId}`, `/_data/charts/${chartShortId}`, `/_data/charts/${chartShortId}/detail`,
    `/_data/components/${componentUuid}`, `/_data/charts/${chartUuid}`, `/_data/charts/${chartUuid}/detail`,
    "/_data/components/active-users", "/_data/components/notes",
    "/_data/charts/usage-trend", "/_data/charts/usage-trend/detail",
  ]) {
    const response = await fetch(path, { method: "HEAD" });
    assert.equal(response.status, 200, path);
    assert.equal(response.headers.get("content-type"), "text/html; charset=utf-8", path);
    assert.equal(await response.text(), "", path);
  }

  for (const path of [
    `/_data/components/${componentShortId}/detail`, `/_data/charts/${chartShortId}/detail/extra`,
    `/_data/components/${componentUuid}/detail`, `/_data/charts/${chartUuid}/detail/extra`,
    "/_data/components", "/_data/components/", "/_data/components//detail",
    "/_data/components/active-users/", "/_data/components/active-users/detail",
    "/_data/components/active-users/detail/", "/_data/components/active-users/extra",
    "/_data/components/.", "/_data/components/..", "/_data/components/%2e",
    "/_data/components/%2E%2e", "/_data/components/%2F", "/_data/components/%2f",
    "/_data/components/parent%2Fchild", "/_data/components/%5C", "/_data/components/parent%5cchild",
    "/_data/components/%00", "/_data/components/widget%00name", "/_data/components/%20",
    "/_data/components/%", "/_data/components/%E0%A4%A", `/_data/components/${"x".repeat(201)}`,
    "/nested/_data/components/active-users", "/_DATA/components/active-users",
    "/_data/component/active-users", "/_data/COMPONENTS/active-users",
    "/_data/charts", "/_data/charts/", "/_data/charts//detail", "/_data/charts/usage-trend/",
    "/_data/charts/usage-trend/details", "/_data/charts/usage-trend/detail/",
    "/_data/charts/usage-trend/detail/extra", "/_data/charts/.", "/_data/charts/..",
    "/_data/charts/%2e", "/_data/charts/%2E%2e", "/_data/charts/%2F", "/_data/charts/%2f",
    "/_data/charts/parent%2Fchild", "/_data/charts/%5C", "/_data/charts/parent%5cchild",
    "/_data/charts/%00", "/_data/charts/trend%00chart", "/_data/charts/%20",
    "/_data/charts/%", "/_data/charts/%E0%A4%A", `/_data/charts/${"x".repeat(201)}`,
    "/nested/_data/charts/usage-trend", "/_DATA/charts/usage-trend", "/_data/chart/usage-trend",
  ]) {
    assert.equal((await fetch(path)).status, 404, path);
  }

  for (const method of ["POST", "PUT", "PATCH", "DELETE", "OPTIONS"]) {
    assert.equal((await fetch(`/_data/components/${componentShortId}`, { method })).status, 404, method);
    assert.equal((await fetch(`/_data/charts/${chartShortId}`, { method })).status, 404, method);
    assert.equal((await fetch(`/_data/components/${componentUuid}`, { method })).status, 404, method);
    assert.equal((await fetch(`/_data/charts/${chartUuid}`, { method })).status, 404, method);
    assert.equal((await fetch("/_data/components/active-users", { method })).status, 404, method);
    assert.equal((await fetch("/_data/components/active-users/detail", { method })).status, 404, method);
    assert.equal((await fetch("/_data/charts/usage-trend", { method })).status, 404, method);
    assert.equal((await fetch("/_data/charts/usage-trend/detail", { method })).status, 404, method);
  }
});

test("hosted presentation allows only its environment-configured Site owner and keeps reviewed rows separate", async () => {
  const seed = { title: "Reviewed dashboard", queries: { reviewed: { rows: [{ amount: 42 }] } } };
  const ownerEmail = "new-address@example.com";
  const ownerHash = createHash("sha256").update(ownerEmail).digest("hex");
  const worker = await loadDashboardWorker(seed);
  const database = fakeDatabase(seed);
  const fetch = (path, options = {}) => worker.fetch(new Request(`https://dashboard.chatgpt.site${path}`, options), {
    DB: database, DATA_APP_OWNER_EMAIL_SHA256: ownerHash,
  });
  assert.deepEqual((await (await fetch("/api/snapshot")).json()).queries.reviewed.rows, [{ amount: 42 }]);
  const firstResponse = await fetch("/api/presentation");
  assert.equal(firstResponse.headers.get("cache-control"), "private, no-store");
  const first = await firstResponse.json();
  assert.deepEqual(first.presentation, {});
  assert.equal(first.revision, 0);
  assert.equal(first.canEdit, false);
  assert.equal(Object.hasOwn(first, "viewerEmail"), false);

  const viewerHeaders = {
    "content-type": "application/json",
    "oai-authenticated-user-email": "publisher@example.com",
  };
  const viewerResponse = await fetch("/api/presentation", { headers: viewerHeaders });
  assert.equal(viewerResponse.headers.get("cache-control"), "private, no-store");
  const viewer = await viewerResponse.json();
  assert.equal(viewer.canEdit, false);
  assert.equal(Object.hasOwn(viewer, "viewerEmail"), false);

  const body = JSON.stringify({ presentation: { theme: "dark-pixel", title: "Edited title" }, revision: 0 });
  assert.equal((await fetch("/api/presentation", { method: "PUT", body })).status, 403);
  assert.equal((await fetch("/api/presentation", { method: "PUT", headers: viewerHeaders, body })).status, 403);
  assert.equal((await fetch("/api/queries/reviewed", {
    method: "PUT", headers: viewerHeaders, body: JSON.stringify({ rows: [] }),
  })).status, 403);
  for (const untrustedHeaders of [
    { "oai-authenticated-user-id": "SiteUser_CurrentOwner" },
    { "x-owner-email": ownerEmail, "cf-access-authenticated-user-email": ownerEmail },
  ]) {
    assert.equal((await (await fetch("/api/presentation", { headers: untrustedHeaders })).json()).canEdit, false);
    assert.equal((await fetch("/api/presentation", { method: "PUT", headers: untrustedHeaders, body })).status, 403);
  }
  const headers = {
    "content-type": "application/json",
    "oai-authenticated-user-email": `  ${ownerEmail.toUpperCase()}  `,
  };
  const ownerResponse = await fetch("/api/presentation", { headers });
  assert.equal(ownerResponse.headers.get("cache-control"), "private, no-store");
  const owner = await ownerResponse.json();
  assert.equal(owner.canEdit, true);
  assert.equal(Object.hasOwn(owner, "viewerEmail"), false,
    "Authenticated owner email must never be disclosed to dashboard-authored browser code");
  assert.equal(JSON.stringify(owner).includes(ownerEmail), false,
    "An unverified dashboard must not reveal its authenticated owner's identity");
  const saved = await fetch("/api/presentation", { method: "PUT", headers, body });
  assert.equal(saved.status, 200);
  assert.equal(saved.headers.get("cache-control"), "private, no-store");
  assert.equal((await saved.json()).revision, 1);
  assert.equal((await fetch("/api/presentation", { method: "PUT", headers, body })).status, 409);
  assert.equal((await fetch("/api/presentation", {
    method: "PUT", headers, body: JSON.stringify({ presentation: { rows: [{ amount: 1 }] }, revision: 1 }),
  })).status, 400);
  assert.deepEqual((await (await fetch("/api/presentation")).json()).presentation, {
    theme: "dark-pixel", title: "Edited title",
  });
  assert.deepEqual((await (await fetch("/api/snapshot")).json()).queries.reviewed.rows, [{ amount: 42 }]);
});

test("hosted annotation visibility round trips without dropping authored evidence or changing reviewed rows", async () => {
  const seed = { title: "Annotation visibility", queries: { reviewed: { rows: [{ amount: 42, target: 50 }] } } };
  const ownerEmail = "annotation-owner@example.com";
  const worker = await loadDashboardWorker(seed);
  const database = fakeDatabase();
  const fetch = (path, options = {}) => worker.fetch(new Request(`https://dashboard.chatgpt.site${path}`, options), {
    DB: database, DATA_APP_OWNER_EMAIL_SHA256: createHash("sha256").update(ownerEmail).digest("hex"),
  });
  const headers = { "content-type": "application/json", "oai-authenticated-user-email": ownerEmail };
  const spec = { type: "line", x: "date", y: "amount", annotations: [
    { id: "target", kind: "benchmark", label: "Reviewed target", field: "target", measure: "amount" },
  ] };
  let revision = 0;
  let lastPresentation;
  for (const setting of [{}, { showAnnotations: false }, { showAnnotations: true }]) {
    const presentation = { chartOverrides: { trend: { ...spec, ...setting } } };
    const saved = await fetch("/api/presentation", {
      method: "PUT", headers, body: JSON.stringify({ presentation, revision }),
    });
    assert.equal(saved.status, 200);
    assert.equal((await saved.json()).revision, ++revision);
    const readback = await (await fetch("/api/presentation")).json();
    assert.deepEqual(readback.presentation, presentation,
      "Readers receive the saved visibility and all authored annotation references");
    assert.equal(readback.revision, revision);
    assert.equal(readback.canEdit, false);
    lastPresentation = presentation;
  }
  for (const chart of [
    { ...spec, showAnnotations: "false" },
    { ...spec, showAnnotations: false, annotations: [{ ...spec.annotations[0], rows: [{ amount: 1 }] }] },
    { ...spec, y: ["amount", "target"] },
    { ...spec, fields: ["amount", ["target"]] },
    { ...spec, series: ["region"] },
  ]) {
    const response = await fetch("/api/presentation", {
      method: "PUT", headers,
      body: JSON.stringify({ presentation: { chartOverrides: { trend: chart } }, revision }),
    });
    assert.equal(response.status, 400);
  }
  const readback = await (await fetch("/api/presentation")).json();
  assert.deepEqual(readback.presentation, lastPresentation);
  assert.equal(readback.revision, revision, "Rejected settings do not create a new revision");
  assert.deepEqual((await (await fetch("/api/snapshot")).json()).queries.reviewed.rows, seed.queries.reviewed.rows);
});

test("authorization follows the current request environment without rebuilding", async () => {
  const seed = { title: "Transferred dashboard", queries: { reviewed: { rows: [{ amount: 42 }] } } };
  const originalOwnerEmail = "original-owner@example.com";
  const nextOwnerEmail = "next-owner@example.com";
  const ownerHash = (email) => createHash("sha256").update(email).digest("hex");
  const database = fakeDatabase(seed);
  const environment = { DB: database, DATA_APP_OWNER_EMAIL_SHA256: ownerHash(originalOwnerEmail) };
  const fetch = (worker, path, email, options = {}) => worker.fetch(
    new Request(`https://dashboard.chatgpt.site${path}`, {
      ...options,
      headers: {
        "content-type": "application/json",
        "oai-authenticated-user-email": email,
      },
    }), environment,
  );
  const originalWorker = await loadDashboardWorker(seed);
  const originalOwner = await (await fetch(originalWorker, "/api/presentation", originalOwnerEmail)).json();
  assert.equal(originalOwner.canEdit, true);
  assert.equal(Object.hasOwn(originalOwner, "viewerEmail"), false);
  assert.equal((await (await fetch(originalWorker, "/api/presentation", nextOwnerEmail)).json()).canEdit, false);

  const requestedVerification = {
    verifiedBy: "spoofed@example.com", verifiedAt: "2000-01-01T00:00:00.000Z",
  };
  const originalVerification = await (await fetch(originalWorker, "/api/presentation", originalOwnerEmail, {
    method: "PUT", body: JSON.stringify({
      presentation: { title: "Originally verified dashboard" }, revision: 0, verificationAction: "verify",
    }),
  })).json();
  assert.equal(originalVerification.presentation.verification.verifiedBy, originalOwnerEmail);

  environment.DATA_APP_OWNER_EMAIL_SHA256 = ownerHash(nextOwnerEmail);
  const transferredWorker = originalWorker;
  assert.equal((await (await fetch(transferredWorker, "/api/presentation", originalOwnerEmail)).json()).canEdit, false);
  assert.equal((await (await fetch(transferredWorker, "/api/presentation", nextOwnerEmail)).json()).canEdit, true);

  const body = JSON.stringify({ presentation: {
    title: "Transferred ownership", verification: requestedVerification,
  }, revision: 1 });
  assert.equal((await fetch(transferredWorker, "/api/presentation", originalOwnerEmail, {
    method: "PUT", body,
  })).status, 403);

  assert.equal((await fetch(transferredWorker, "/api/queries/reviewed", originalOwnerEmail, {
    method: "PUT", body: JSON.stringify({ rows: [] }),
  })).status, 403);
  const transferredPresentation = await fetch(transferredWorker, "/api/presentation", nextOwnerEmail, {
    method: "PUT", body,
  });
  assert.equal(transferredPresentation.status, 200);
  assert.deepEqual((await transferredPresentation.json()).presentation.verification,
    originalVerification.presentation.verification,
    "The new owner's ordinary edits must preserve the original trusted verification record");
  assert.equal((await fetch(transferredWorker, "/api/queries/reviewed", nextOwnerEmail, {
    method: "PUT", body: JSON.stringify({ rows: [{ amount: 84 }] }),
  })).status, 200);

  const removal = JSON.stringify({ presentation: {
    title: "Transferred ownership", verification: requestedVerification,
  }, revision: 2, verificationAction: "remove" });
  assert.equal((await fetch(transferredWorker, "/api/presentation", originalOwnerEmail, {
    method: "PUT", body: removal,
  })).status, 403,
  "A transferred-away owner cannot remove the existing verified dashboard badge");
  assert.equal((await fetch(transferredWorker, "/api/presentation", nextOwnerEmail, {
    method: "PUT", body: removal,
  })).status, 200, "Only the current owner may remove the transferred dashboard badge");

  const reverify = JSON.stringify({ presentation: {
    title: "Transferred ownership",
  }, revision: 3, verificationAction: "verify" });
  assert.equal((await fetch(transferredWorker, "/api/presentation", originalOwnerEmail, {
    method: "PUT", body: reverify,
  })).status, 403,
  "The previous owner cannot verify the transferred dashboard");
  const nextVerification = await fetch(transferredWorker, "/api/presentation", nextOwnerEmail, {
    method: "PUT", body: reverify,
  });
  assert.equal(nextVerification.status, 200);
  assert.equal((await nextVerification.json()).presentation.verification.verifiedBy, nextOwnerEmail,
    "A transferred dashboard's new badge must be stamped with the current owner's authenticated email");
});

test("an unconfigured owner stays read-only and preserves D1 until the owner environment is configured", async () => {
  const seed = { title: "Existing dashboard", queries: { reviewed: { rows: [{ amount: 42 }] } } };
  const oldOwnerEmail = "previous-owner@example.com";
  const nextOwnerEmail = "current-owner@example.com";
  const oldOwnerHash = createHash("sha256").update(oldOwnerEmail).digest("hex");
  const database = fakeDatabase(seed);
  const environment = { DB: database, DATA_APP_OWNER_EMAIL_SHA256: oldOwnerHash };
  const fetch = (worker, path, email, options = {}) => worker.fetch(
    new Request(`https://dashboard.chatgpt.site${path}`, {
      ...options,
      headers: {
        "content-type": "application/json",
        "oai-authenticated-user-email": email,
      },
    }), environment,
  );

  const originalWorker = await loadDashboardWorker(seed);
  await fetch(originalWorker, "/api/snapshot", oldOwnerEmail);
  const originalPresentation = await (await fetch(originalWorker, "/api/presentation", oldOwnerEmail, {
    method: "PUT",
    body: JSON.stringify({
      presentation: { title: "Saved presentation", filters: { week: "latest" } },
      revision: 0,
      verificationAction: "verify",
    }),
  })).json();
  assert.equal((await fetch(originalWorker, "/api/queries/reviewed", oldOwnerEmail, {
    method: "PUT", body: JSON.stringify({ rows: [{ amount: 84 }] }),
  })).status, 200);
  const savedState = structuredClone(database.state);

  delete environment.DATA_APP_OWNER_EMAIL_SHA256;
  const unconfiguredWorker = originalWorker;
  assert.deepEqual(database.state, savedState,
    "An unconfigured deployment must neither reset persisted data nor claim ownership");
  for (const email of [oldOwnerEmail, nextOwnerEmail]) {
    const presentation = await (await fetch(unconfiguredWorker, "/api/presentation", email)).json();
    assert.equal(presentation.canEdit, false);
    assert.deepEqual(presentation.presentation, originalPresentation.presentation);
    assert.equal(presentation.revision, originalPresentation.revision);
    assert.equal((await fetch(unconfiguredWorker, "/api/presentation", email, {
      method: "PUT", body: JSON.stringify({ presentation: {}, revision: presentation.revision }),
    })).status, 403);
  }

  // Only the managed environment can set the owner; visitors cannot claim the app.
  const nextOwnerHash = createHash("sha256").update(nextOwnerEmail).digest("hex");
  environment.DATA_APP_OWNER_EMAIL_SHA256 = nextOwnerHash;
  const repairedWorker = originalWorker;
  const repaired = await (await fetch(repairedWorker, "/api/presentation", nextOwnerEmail)).json();
  assert.equal(repaired.canEdit, true);
  assert.deepEqual(repaired.presentation, originalPresentation.presentation);
  assert.equal(repaired.revision, originalPresentation.revision);
  assert.deepEqual((await (await fetch(repairedWorker, "/api/snapshot", nextOwnerEmail)).json())
    .queries.reviewed.rows, [{ amount: 84 }]);
  assert.equal((await (await fetch(repairedWorker, "/api/presentation", oldOwnerEmail)).json()).canEdit, false);
  assert.equal((await fetch(repairedWorker, "/api/queries/reviewed", oldOwnerEmail, {
    method: "PUT", body: JSON.stringify({ rows: [] }),
  })).status, 403);
  assert.equal((await fetch(repairedWorker, "/api/presentation", nextOwnerEmail, {
    method: "PUT",
    body: JSON.stringify({
      presentation: repaired.presentation,
      revision: repaired.revision,
      verificationAction: "remove",
    }),
  })).status, 200);
});

test("hosted dashboard verification is creator-only, server-stamped, stable, and removable", async () => {
  const ownerEmail = "publisher@example.com";
  const ownerHash = createHash("sha256").update(ownerEmail).digest("hex");
  const worker = await loadDashboardWorker({ title: "Reviewed dashboard", queries: {} });
  const database = fakeDatabase();
  const ownerHeaders = {
    "content-type": "application/json",
    "oai-authenticated-user-email": "  PUBLISHER@EXAMPLE.COM  ",
  };
  const viewerHeaders = {
    "content-type": "application/json",
    "oai-authenticated-user-email": "viewer@example.com",
  };
  const fetch = (path, options = {}) => worker.fetch(new Request(`https://dashboard.chatgpt.site${path}`, options), {
    DB: database, DATA_APP_OWNER_EMAIL_SHA256: ownerHash,
  });
  const spoofed = { verifiedBy: "impostor@example.com", verifiedAt: "2000-01-01T00:00:00.000Z" };
  const body = JSON.stringify({
    presentation: { title: "Reviewed dashboard" }, revision: 0, verificationAction: "verify",
  });

  assert.equal((await fetch("/api/presentation", { method: "PUT", body })).status, 403);
  assert.equal((await fetch("/api/presentation", { method: "PUT", headers: viewerHeaders, body })).status, 403);
  const actualOwner = await (await fetch("/api/presentation", { headers: ownerHeaders })).json();
  assert.equal(actualOwner.canEdit, true);
  assert.equal(Object.hasOwn(actualOwner, "viewerEmail"), false,
    "Even the authenticated owner must not receive their private identity before opting into verification");
  assert.equal(JSON.stringify(actualOwner).includes(ownerEmail), false);
  for (const invalidAction of [null, true, false, 0, {}, [], "", "VERIFY", "delete"]) {
    assert.equal((await fetch("/api/presentation", {
      method: "PUT", headers: ownerHeaders, body: JSON.stringify({
        presentation: { title: "Reviewed dashboard" }, revision: 0, verificationAction: invalidAction,
      }),
    })).status, 400, `Malformed verification action must fail closed: ${JSON.stringify(invalidAction)}`);
  }
  assert.equal((await fetch("/api/presentation", {
    method: "PUT", headers: ownerHeaders,
    body: JSON.stringify({ presentation: { title: "Reviewed dashboard", verification: spoofed }, revision: 0 }),
  })).status, 400, "An authored dashboard cannot fabricate a verified badge without an explicit server action");
  assert.equal((await fetch("/api/presentation", {
    method: "PUT", headers: ownerHeaders,
    body: JSON.stringify({ presentation: {
      verification: { ...spoofed, rows: [{ secret: true }] },
    }, revision: 0, verificationAction: "verify" }),
  })).status, 400, "Malformed verification metadata must be rejected before creator stamping");

  const beforeVerification = Date.now();
  const verifiedResponse = await fetch("/api/presentation", { method: "PUT", headers: ownerHeaders, body });
  assert.equal(verifiedResponse.status, 200);
  const verified = await verifiedResponse.json();
  assert.equal(verified.revision, 1);
  assert.equal(verified.presentation.verification.verifiedBy, ownerEmail);
  assert.notEqual(verified.presentation.verification.verifiedAt, spoofed.verifiedAt);
  assert.ok(Date.parse(verified.presentation.verification.verifiedAt) >= beforeVerification);
  assert.equal(verified.presentation.verification.verifiedAt, verified.updatedAt,
    "The verification timestamp must be generated by the trusted Worker");

  const publicVerification = await (await fetch("/api/presentation")).json();
  assert.equal(publicVerification.canEdit, false);
  assert.equal(Object.hasOwn(publicVerification, "viewerEmail"), false);
  assert.deepEqual(publicVerification.presentation.verification, verified.presentation.verification,
    "Every authorized dashboard viewer must see the persisted verifier identity and timestamp");
  const viewer = await (await fetch("/api/presentation", { headers: viewerHeaders })).json();
  assert.equal(Object.hasOwn(viewer, "viewerEmail"), false);
  assert.deepEqual(viewer.presentation.verification, verified.presentation.verification);
  const reloadedWorker = await loadDashboardWorker({ title: "Reviewed dashboard", queries: {} });
  const reloaded = await reloadedWorker.fetch(new Request("https://dashboard.chatgpt.site/api/presentation"), {
    DB: database, DATA_APP_OWNER_EMAIL_SHA256: ownerHash,
  });
  assert.deepEqual((await reloaded.json()).presentation.verification, verified.presentation.verification,
    "Verification must persist across Worker reloads and deployments");

  const outdated = await fetch("/api/presentation", {
    method: "PUT", headers: ownerHeaders,
    body: JSON.stringify({ presentation: { verification: spoofed }, revision: 0 }),
  });
  assert.equal(outdated.status, 409);
  assert.deepEqual((await outdated.json()).presentation.verification, verified.presentation.verification,
    "Conflicting writes must return the authoritative verification record without replacing it");

  const unchanged = await fetch("/api/presentation", {
    method: "PUT", headers: ownerHeaders,
    body: JSON.stringify({ presentation: { title: "Updated dashboard", verification: spoofed }, revision: 1 }),
  });
  assert.equal(unchanged.status, 200);
  const updated = await unchanged.json();
  assert.equal(updated.revision, 2);
  assert.equal(updated.presentation.title, "Updated dashboard");
  assert.deepEqual(updated.presentation.verification, verified.presentation.verification,
    "Unrelated edits and spoofed client metadata must preserve the original server verification exactly");

  const removal = JSON.stringify({ presentation: {
    title: "Updated dashboard", verification: spoofed,
  }, revision: 2, verificationAction: "remove" });
  assert.equal((await fetch("/api/presentation", {
    method: "PUT", headers: viewerHeaders, body: removal,
  })).status, 403, "A read-only viewer must never remove dashboard verification");
  const cleared = await fetch("/api/presentation", { method: "PUT", headers: ownerHeaders, body: removal });
  assert.equal(cleared.status, 200);
  assert.equal((await cleared.json()).revision, 3);
  assert.equal(Object.hasOwn((await (await fetch("/api/presentation")).json()).presentation, "verification"), false,
    "Removing verification must clear the shared dashboard badge for every viewer");

  const reverified = await fetch("/api/presentation", {
    method: "PUT", headers: ownerHeaders,
    body: JSON.stringify({
      presentation: { title: "Updated dashboard" }, revision: 3, verificationAction: "verify",
    }),
  });
  assert.equal(reverified.status, 200);
  assert.equal((await reverified.json()).presentation.verification.verifiedBy, ownerEmail);
});

test("hosted reviewed data stores each result separately and stays within D1 statement limits", async () => {
  const rows = Array.from({ length: 35 }, (_, index) => ({ index, evidence: "reviewed ".repeat(4_000) }));
  const seed = {
    title: "Large reviewed dashboard",
    generatedAt: "2026-08-11T12:00:00.000Z",
    queries: {
      reviewed: { source: { label: "Reviewed evidence" }, rows },
      summary: { source: { label: "Summary" }, rows: [{ total: rows.length }] },
    },
  };
  assert.ok(JSON.stringify(seed).length * 2 > 2_000_000,
    "The previous duplicated snapshot record would exceed D1's maximum row size");

  const worker = await loadDashboardWorker(seed);
  const database = fakeDatabase();
  const snapshot = await (await worker.fetch(new Request("https://dashboard.chatgpt.site/api/snapshot"), {
    DB: database,
  })).json();

  assert.deepEqual(snapshot, seed);
  assert.equal(database.state.rows.size, rows.length + 1);
  assert.equal(database.state.queries.size, 2);
  assert.equal(Object.hasOwn(JSON.parse(database.state.snapshot.metadata_json), "queries"), false);
  assert.match(database.state.snapshot.seed_sha256, /^[a-f\d]{64}$/u);
  assert.equal(database.state.maxBoundParameters, 90);
  assert.ok([...database.state.rows.values()].every(({ row_json }) => row_json.length < 2_000_000));
});

test("hosted query updates preserve other results until a newly reviewed seed replaces them", async () => {
  const ownerEmail = "publisher@example.com";
  const ownerHash = createHash("sha256").update(ownerEmail).digest("hex");
  const seed = {
    title: "Reviewed dashboard",
    generatedAt: "2026-08-11T12:00:00.000Z",
    queries: {
      reviewed: {
        source: { label: "Reviewed evidence", evidenceFlow: [{
          title: "Synthetic API source", detail: "Call fixture_totals for the last seven complete UTC days; sum amount.",
        }] },
        methods: [{ language: "calculation", code: "amount = sum(record.amount for record in response.records)" }],
        rows: [{ amount: 42 }],
      },
      unchanged: { source: { label: "Unchanged evidence" }, rows: [{ amount: 7 }] },
    },
  };
  const database = fakeDatabase();
  const headers = { "content-type": "application/json", "oai-authenticated-user-email": ownerEmail };
  const fetch = (worker, path, options = {}) => worker.fetch(
    new Request(`https://dashboard.chatgpt.site${path}`, options), { DB: database, DATA_APP_OWNER_EMAIL_SHA256: ownerHash },
  );
  const worker = await loadDashboardWorker(seed);
  const reviewedRows = Array.from({ length: 32 }, (_, amount) => ({ amount }));
  const result = await (await fetch(worker, "/api/queries/reviewed", {
    method: "PUT", headers, body: JSON.stringify({ rows: reviewedRows }),
  })).json();

  assert.deepEqual(result.rows, reviewedRows);
  const saved = await (await fetch(worker, "/api/snapshot")).json();
  assert.deepEqual(saved.queries.reviewed.rows, reviewedRows);
  assert.deepEqual(saved.queries.unchanged.rows, seed.queries.unchanged.rows);
  assert.equal(saved.generatedAt, result.generatedAt);

  const reloaded = await loadDashboardWorker(seed);
  const reopened = await (await fetch(reloaded, "/api/snapshot")).json();
  assert.deepEqual(reopened.queries.reviewed, { ...seed.queries.reviewed, rows: reviewedRows },
    "A fresh reader must retain source requests and calculations after a row update");

  const nextSeed = {
    ...seed,
    queries: { reviewed: { source: { label: "New reviewed evidence" }, rows: [{ amount: 100 }] } },
  };
  const redeployed = await loadDashboardWorker(nextSeed);
  assert.deepEqual(await (await fetch(redeployed, "/api/snapshot")).json(), nextSeed);
});

test("a dashboard without owner environment remains read-only for every authenticated viewer", async () => {
  const seed = { title: "Unseeded dashboard", queries: {} };
  const worker = await loadDashboardWorker(seed);
  const database = fakeDatabase(seed);
  const headers = {
    "content-type": "application/json",
    "oai-authenticated-user-id": "SiteUser_FirstViewer",
    "oai-authenticated-user-email": "first-viewer@example.com",
  };
  const response = await worker.fetch(new Request("https://dashboard.chatgpt.site/api/presentation", { headers }), {
    DB: database,
  });
  assert.equal((await response.json()).canEdit, false);
  const denied = await worker.fetch(new Request("https://dashboard.chatgpt.site/api/presentation", {
    method: "PUT", headers, body: JSON.stringify({ presentation: { title: "Taken over" }, revision: 0 }),
  }), { DB: database });
  assert.equal(denied.status, 403);
});

test("editing sessions defer layout/text/chart persistence and cancel without rolling back personal filters", async () => {
  const initial = { title: "Original", chartOverrides: {}, hiddenBlocks: [], theme: "original", filters: { plan: "all" } };
  const baseline = JSON.parse(editHistoryValue(initial));
  const changed = { ...initial, title: "Changed", hiddenBlocks: ["chart"],
    chartOverrides: { chart: { type: "bar", x: "date", y: "value" } },
    blockLayouts: { region: { order: ["b", "a"] } }, filters: { plan: "selected" } };
  const held = presentationBeforeEdits(changed, baseline);
  assert.equal(held.title, initial.title);
  assert.deepEqual(held.chartOverrides, {});
  assert.equal(held.blockLayouts, undefined);
  assert.deepEqual(held.filters, changed.filters);
  const harness = await presentationPersistenceHarness(initial);
  try {
    harness.render(initial);
    // Hosted personal filters are provided separately by the shell; only shared
    // presentation fields should be compared at this boundary.
    harness.render(presentationBeforeEdits({ ...changed, filters: initial.filters }, baseline));
    await harness.flush();
    assert.equal(harness.requests.length, 0, "typing and rearranging do not write to the Site");
    harness.render(initial);
    await harness.flush();
    assert.equal(harness.requests.length, 0, "Cancel does not send a rollback write");
    let committed = false;
    harness.render(changed, { onAcknowledged() { committed = true; } });
    await harness.flush();
    assert.equal(harness.requests.length, 1, "Save uses the existing revision-checked endpoint once");
    assert.equal(harness.server.presentation.title, "Changed");
    assert.equal(committed, true);
  } finally { harness.dispose(); }
});

test("failed explicit saves keep the baseline and can retry the same edits", async () => {
  const initial = { title: "Original" };
  const changed = { title: "Changed" };
  const harness = await presentationPersistenceHarness(initial, { deferResponses: true });
  let acknowledged = false;
  try {
    harness.render(initial);
    harness.render(changed, { onAcknowledged() { acknowledged = true; } });
    const pending = harness.start();
    harness.respond(0, { status: 500 });
    await pending;
    assert.equal(acknowledged, false);
    assert.equal(harness.status(), "error");
    harness.render(presentationBeforeEdits(changed, initial));
    await harness.flush();
    assert.equal(harness.requests.length, 1);
    harness.resumeResponses();
    harness.render(changed, { onAcknowledged() { acknowledged = true; } });
    await harness.flush();
    assert.equal(acknowledged, true);
    assert.equal(harness.server.presentation.title, "Changed");
  } finally { harness.dispose(); }
});

test("invalid authored saves keep the draft editable without discarding or acknowledging text", async () => {
  const initial = { title: "Original", textEdits: { body: "Previously saved" }, componentTitles: {} };
  const cases = [
    { textEdits: { body: "x".repeat(20_001) } },
    { componentTitles: { chart: "x".repeat(20_001) } },
    { textEdits: Object.fromEntries(Array.from({ length: 7 }, (_, index) => [String(index), "x".repeat(19_000)])) },
    { textEdits: Object.fromEntries(Array.from({ length: 501 }, (_, index) => [String(index), "A short edit"])) },
  ];
  for (const hosted of [true, false]) {
    for (const invalid of cases) {
      const harness = await presentationPersistenceHarness(initial);
      const draft = { ...initial, ...invalid };
      const draftBeforeSaving = structuredClone(draft);
      const errors = [];
      const acknowledgements = [];
      let editing = true;
      let saving = false;
      const options = {
        hosted,
        onAcknowledged: (saved) => { acknowledgements.push(saved); editing = false; },
        onError: (error) => { errors.push(error); saving = false; },
      };
      try {
        harness.render(initial, options);
        harness.render(presentationBeforeEdits(draft, initial), options);
        await harness.flush();
        assert.equal(errors.length, 0, "Typing keeps provisional edits out of persistence");
        saving = true;
        assert.doesNotThrow(() => harness.render(draft, options), "Invalid drafts must not throw from a render or effect");
        await harness.flush();

        assert.equal(harness.status(), "error");
        assert.equal(errors.length, 1);
        assert.match(errors[0], /bounded|size limit/u);
        assert.equal(saving, false, "The existing error callback unlocks the draft for correction");
        assert.equal(editing, true, "Validation failures must not end the edit session");
        assert.deepEqual(draft, draftBeforeSaving, "The complete invalid text remains in the draft");
        assert.deepEqual(acknowledgements, []);
        assert.deepEqual(harness.requests, []);
        assert.deepEqual(harness.server.presentation, initial);

        harness.render(presentationBeforeEdits(draft, initial), options);
        const corrected = { ...initial, textEdits: { body: "Corrected text" } };
        harness.render(corrected, options);
        await harness.flush();
        assert.equal(harness.status(), "saved");
        assert.deepEqual(acknowledgements, [corrected]);
        assert.equal(editing, false);
        assert.equal(harness.requests.length, hosted ? 1 : 0);
      } finally { harness.dispose(); }
    }
  }
});

test("local caching rejects oversized drafts without throwing or replacing the prior saved value", () => {
  const snapshot = { id: "bounded-local-draft" };
  const storage = memoryStorage();
  const initial = { textEdits: { body: "Previously saved" } };
  writeLocalPresentation(snapshot, initial, storage);
  assert.equal(writeLocalPresentation(snapshot, { textEdits: { body: "x".repeat(20_001) } }, storage), false);
  assert.equal(writeLocalPresentation(snapshot, { textEdits: Object.fromEntries(
    Array.from({ length: 7 }, (_, index) => [String(index), "x".repeat(19_000)]),
  ) }, storage), false);
  assert.deepEqual(readLocalPresentation(snapshot, storage), initial);

  storage.setItem(presentationStorageKey(snapshot), JSON.stringify({
    version: presentationVersion,
    presentation: { textEdits: { body: "Previously saved", legacy: "x".repeat(20_001) } },
  }));
  assert.deepEqual(readLocalPresentation(snapshot, storage), initial,
    "Persisted older data still uses permissive normalization when read");
});

test("an older in-flight save cannot acknowledge a newer draft rejected by validation", async () => {
  const initial = { textEdits: { body: "Initial text" } };
  const older = { textEdits: { body: "Earlier valid draft" } };
  const invalid = { textEdits: { body: "x".repeat(20_001) } };
  const errors = [];
  const acknowledgements = [];
  const options = {
    onError: (error) => errors.push(error),
    onAcknowledged: (saved) => acknowledgements.push(saved),
  };
  const harness = await presentationPersistenceHarness(initial, { deferResponses: true });
  try {
    harness.render(initial, options);
    harness.render(older, options);
    const olderSave = harness.start();
    harness.render(invalid, options);
    assert.equal(harness.status(), "error");
    assert.equal(harness.timers.size, 0);
    harness.respond(0, { presentation: older, revision: 1 });
    await olderSave;
    assert.equal(harness.status(), "error");
    assert.equal(errors.length, 1);
    assert.deepEqual(acknowledgements, []);
    assert.equal(harness.requests.length, 1, "Only the earlier valid draft was sent to the server");
    assert.equal(invalid.textEdits.body.length, 20_001);
  } finally { harness.dispose(); }
});

test("conflict merges reject combined size and entry limits before a retry can discard text", async () => {
  for (const { localCount, remoteCount, text } of [
    { localCount: 4, remoteCount: 3, text: "x".repeat(19_000) },
    { localCount: 400, remoteCount: 200, text: "A short edit" },
  ]) {
    const initial = { textEdits: {} };
    const local = { textEdits: Object.fromEntries(Array.from({ length: localCount }, (_, index) => [`local-${index}`, text])) };
    const remote = { textEdits: Object.fromEntries(Array.from({ length: remoteCount }, (_, index) => [`remote-${index}`, text])) };
    const harness = await presentationPersistenceHarness(initial);
    const errors = [];
    const acknowledgements = [];
    const options = {
      onError: (error) => errors.push(error),
      onAcknowledged: (saved) => acknowledgements.push(saved),
    };
    try {
      harness.render(initial, options);
      harness.server.presentation = remote;
      harness.server.revision = 1;
      harness.render(local, options);
      await harness.flush();
      assert.equal(harness.status(), "error");
      assert.equal(errors.length, 1);
      assert.match(errors[0], /bounded|size limit/u);
      assert.equal(harness.requests.length, 1, "The stale first request must not be retried with a lossy merged payload");
      assert.deepEqual(acknowledgements, []);
      assert.deepEqual(harness.server.presentation, remote, "The concurrent saved text remains intact");
    } finally { harness.dispose(); }
  }
});


test("verification education preference survives reload on non-workspace origins", () => {
  const storage = memoryStorage();
  const location = { protocol: "http:", hostname: "127.0.0.1" };
  assert.equal(readVerificationReminderDismissed({ storage, location }), false);
  assert.equal(rememberVerificationReminderDismissed({ storage, location }), true);
  assert.equal(readVerificationReminderDismissed({ storage, location }), true);
  assert.equal(readVerificationReminderDismissed({ storage: memoryStorage(), location }), false);
  const blocked = { getItem() { throw new Error("blocked"); }, setItem() { throw new Error("blocked"); } };
  assert.equal(rememberVerificationReminderDismissed({ storage: blocked, location }), false);
  assert.equal(readVerificationReminderDismissed({ storage: blocked, location }), false);
});

SHA-256: 88a4f1bb28975c7c458f2ced84692386a1fb0a35ad7d9e3f7d9717eea9bf9f9c