OverviewFilesCommitsIssuesDocsReleasesPeers

pearbrowser-desktop / docs / origin-isolation-smoke-plan-peerit-pearfeed-2026-07-02.json

167 lines · json ref:
{
  "ok": true,
  "schemaVersion": 1,
  "kind": "pearbrowser-origin-isolation-smoke-plan",
  "generatedAt": "2026-07-04T13:57:11.924Z",
  "package": {
    "name": "pearbrowser-desktop",
    "version": "0.5.2"
  },
  "featureFlag": "PEARBROWSER_PER_DRIVE_ORIGINS=1",
  "proofKey": "pear-origin-isolation-proof",
  "apps": [
    {
      "url": "hyper://ec6e2d6d9d22b9d6b40e11a9ca3042be3197e4bdca9e9a7f079be6ee830761b4/",
      "driveKey": "ec6e2d6d9d22b9d6b40e11a9ca3042be3197e4bdca9e9a7f079be6ee830761b4",
      "label": "Peerit"
    },
    {
      "url": "hyper://5c2807c5ba1383e55d69a2fe5085fdeb563e2e18f175f363f3f18437219c1aec/",
      "driveKey": "5c2807c5ba1383e55d69a2fe5085fdeb563e2e18f175f363f3f18437219c1aec",
      "label": "Pearfeed"
    }
  ],
  "commands": [
    {
      "id": "launch-feature-flagged-desktop",
      "command": "PEARBROWSER_PER_DRIVE_ORIGINS=1 npm start",
      "evidence": "PearBrowser is launched with PEARBROWSER_PER_DRIVE_ORIGINS=1."
    },
    {
      "id": "runtime-readiness",
      "command": "node scripts/runtime-rpc-smoke.mjs --timeout 20000 --max-storage-percent 100 --json",
      "evidence": "Runtime smoke JSON shows backend readiness, proxy port, and relay status."
    },
    {
      "id": "nonvisual-app-a-navigation",
      "command": "node scripts/release-rpc-story-smoke.mjs --homepage-url 'hyper://ec6e2d6d9d22b9d6b40e11a9ca3042be3197e4bdca9e9a7f079be6ee830761b4/' --json",
      "evidence": "Peerit navigates through the production RPC/proxy path without approving a third-party trust prompt."
    },
    {
      "id": "automated-origin-isolation-evidence",
      "command": "node scripts/generate-origin-isolation-smoke-evidence.mjs --plan 'docs/origin-isolation-smoke-plan-peerit-pearfeed-2026-07-02.json' --out origin-isolation-smoke-evidence.json --json",
      "evidence": "Automated verifier emits a pearbrowser-origin-isolation-smoke-evidence artifact that passes check:origin-isolation-smoke-evidence."
    }
  ],
  "automatedVerifier": {
    "command": "npm run -s generate:origin-isolation-smoke-evidence -- --plan 'docs/origin-isolation-smoke-plan-peerit-pearfeed-2026-07-02.json' --out origin-isolation-smoke-evidence.json --json",
    "validatesWith": "npm run check:origin-isolation-smoke-evidence -- --file origin-isolation-smoke-evidence.json --json",
    "notes": [
      "Runs a local HyperProxy/HttpBridge harness with per-drive origins enabled.",
      "Uses the plan apps as the two drive identities and exercises origin split, strict-CSP injection, storage isolation, listener release, and bridge routes."
    ]
  },
  "manualSteps": [
    {
      "id": "open-both-apps",
      "action": "Open Peerit (hyper://ec6e2d6d9d22b9d6b40e11a9ca3042be3197e4bdca9e9a7f079be6ee830761b4/) and Pearfeed (hyper://5c2807c5ba1383e55d69a2fe5085fdeb563e2e18f175f363f3f18437219c1aec/) in separate PearBrowser tabs while the feature flag is enabled.",
      "evidence": "Screenshots or console output show both tabs loaded."
    },
    {
      "id": "origin-split",
      "action": "In each tab, record `location.origin` from DevTools.",
      "evidence": "The two origins are different loopback origins, normally different `127.0.0.1:<port>` values."
    },
    {
      "id": "storage-write-a",
      "action": "Run the write snippet in Peerit.",
      "evidence": "Peerit reports its origin and writes localStorage, cookie, and IndexedDB proof values."
    },
    {
      "id": "storage-read-b",
      "action": "Run the read snippet in Pearfeed.",
      "evidence": "Pearfeed reports a different origin and reads no pear-origin-isolation-proof value from localStorage, cookie, or IndexedDB."
    },
    {
      "id": "strict-csp-real-app",
      "action": "Load at least one strict-CSP real app under the feature flag.",
      "evidence": "The app loads its assets and Pear bridge without CSP console failures caused by per-drive origin mode."
    },
    {
      "id": "tab-lifecycle",
      "action": "Close Peerit, or navigate its tab to Pearfeed, then keep Pearfeed open.",
      "evidence": "PearBrowser stays responsive and subsequent app navigation still works, confirming the release path did not break tab-origin lifecycle behavior."
    },
    {
      "id": "real-app-bridge",
      "action": "Run a real app bridge flow such as Peerit identity/sync under the feature flag.",
      "evidence": "`/api/identity`, `/api/sync/*`, `/api/swarm/ticket`, and `/api/swarm/events?ticket=` continue to work from the per-drive origin."
    }
  ],
  "snippets": {
    "writeStorageInAppA": "(async () => {\n  const key = \"pear-origin-isolation-proof\"\n  const value = \"peerit-1783173431924\"\n  localStorage.setItem(key, value)\n  document.cookie = key + '=' + value + '; SameSite=Lax'\n  await new Promise((resolve, reject) => {\n    const request = indexedDB.open(key, 1)\n    request.onupgradeneeded = () => request.result.createObjectStore('proof')\n    request.onerror = () => reject(request.error)\n    request.onsuccess = () => {\n      const db = request.result\n      const tx = db.transaction('proof', 'readwrite')\n      tx.objectStore('proof').put(value, 'value')\n      tx.oncomplete = () => { db.close(); resolve() }\n      tx.onerror = () => reject(tx.error)\n    }\n  })\n  return { origin: location.origin, value, localStorage: localStorage.getItem(key), cookie: document.cookie }\n})()",
    "readStorageInAppB": "(async () => {\n  const key = \"pear-origin-isolation-proof\"\n  const indexedValue = await new Promise((resolve) => {\n    const request = indexedDB.open(key)\n    request.onerror = () => resolve(null)\n    request.onupgradeneeded = () => { request.transaction.abort(); resolve(null) }\n    request.onsuccess = () => {\n      const db = request.result\n      if (!db.objectStoreNames.contains('proof')) { db.close(); resolve(null); return }\n      const tx = db.transaction('proof', 'readonly')\n      const get = tx.objectStore('proof').get('value')\n      get.onsuccess = () => { db.close(); resolve(get.result || null) }\n      get.onerror = () => { db.close(); resolve(null) }\n    }\n  })\n  return { origin: location.origin, localStorage: localStorage.getItem(key), cookie: document.cookie, indexedDB: indexedValue }\n})()"
  },
  "evidenceTemplate": {
    "schemaVersion": 1,
    "kind": "pearbrowser-origin-isolation-smoke-evidence",
    "featureFlag": "PEARBROWSER_PER_DRIVE_ORIGINS=1",
    "proofKey": "pear-origin-isolation-proof",
    "apps": [
      {
        "label": "Peerit",
        "url": "hyper://ec6e2d6d9d22b9d6b40e11a9ca3042be3197e4bdca9e9a7f079be6ee830761b4/",
        "driveKey": "ec6e2d6d9d22b9d6b40e11a9ca3042be3197e4bdca9e9a7f079be6ee830761b4",
        "origin": "<record location.origin from app A>"
      },
      {
        "label": "Pearfeed",
        "url": "hyper://5c2807c5ba1383e55d69a2fe5085fdeb563e2e18f175f363f3f18437219c1aec/",
        "driveKey": "5c2807c5ba1383e55d69a2fe5085fdeb563e2e18f175f363f3f18437219c1aec",
        "origin": "<record location.origin from app B>"
      }
    ],
    "storage": {
      "proofKey": "pear-origin-isolation-proof",
      "writtenValue": "<value returned by the app A write snippet>",
      "appA": {
        "localStorage": "<app A localStorage value>",
        "cookie": "<app A document.cookie>",
        "indexedDB": "<app A IndexedDB value>"
      },
      "appB": {
        "localStorage": null,
        "cookie": "<app B document.cookie>",
        "indexedDB": null
      }
    },
    "strictCsp": {
      "status": "<PASS>",
      "evidence": "<screenshot/log path>"
    },
    "tabLifecycle": {
      "status": "<PASS>",
      "evidence": "<screenshot/log path>"
    },
    "realAppBridge": {
      "status": "<PASS>",
      "evidence": "<Peerit or real-app bridge log path>",
      "routes": {
        "identity": true,
        "sync": true,
        "swarmTicket": true,
        "swarmEvents": true
      }
    },
    "artifacts": [
      "<screenshot-or-log-path>"
    ],
    "automatedVerifier": {
      "command": "npm run -s generate:origin-isolation-smoke-evidence -- --plan 'docs/origin-isolation-smoke-plan-peerit-pearfeed-2026-07-02.json' --out origin-isolation-smoke-evidence.json --json",
      "validatesWith": "npm run check:origin-isolation-smoke-evidence -- --file origin-isolation-smoke-evidence.json --json"
    }
  },
  "acceptance": [
    "Feature flag is enabled for the launched desktop process.",
    "Two app tabs report different `location.origin` values.",
    "Data written in App A localStorage, cookie, and IndexedDB is not visible in App B.",
    "Strict-CSP real app compatibility is recorded.",
    "Tab close/navigation-away does not leave the browser in a broken listener state.",
    "At least one real app bridge flow still passes under the feature flag."
  ],
  "remainingIfPassed": [
    "Decide LRU/default-on listener policy.",
    "Record the smoke evidence in the release evidence log before flipping the feature flag default-on."
  ]
}