{
  "endpoints" : [
    {
      "address" : "https://parallex.mandip.dev/api/v1/releases/latest",
      "from" : "the app",
      "id" : "update-check",
      "kind" : "parallex",
      "literals" : [
        "https://parallex.mandip.dev/api/v1/releases/latest"
      ],
      "managedKeys" : [
        "AutomaticUpdateChecks",
        "AppUpdatesAllowed"
      ],
      "method" : "GET",
      "purpose" : "Whether there's a new version of Parallex, as a signed answer (key f1).",
      "sends" : "Parallex's version, macOS's version, the chip, whether it's the first check today, this week or this month, a number from 0 to 99 picked once, and a random Mac number picked once. When a release needs a license, a second request carries the license token, the versions, the chip and the 0 to 99 number, and never the Mac number.",
      "turnOff" : "Settings › About › Check for updates automatically. Managed: AutomaticUpdateChecks false, or AppUpdatesAllowed false for no update checks or installs at all.",
      "when" : "Every few hours while the app runs, when the Mac wakes, and when you choose Check for Updates."
    },
    {
      "address" : "https://parallex.mandip.dev/download/…/Parallex-….zip (with .sig, .manifest and .manifest.sig)",
      "from" : "the app",
      "id" : "update-download",
      "kind" : "parallex",
      "literals" : [

      ],
      "managedKeys" : [
        "AppUpdatesAllowed"
      ],
      "method" : "GET",
      "purpose" : "The update itself, its signature and its signed manifest, at the addresses the signed answer named.",
      "sends" : "Nothing beyond a download request. The server adds one to that file's download count.",
      "turnOff" : "Don't install updates. Managed: AppUpdatesAllowed false.",
      "when" : "When you install an update."
    },
    {
      "address" : "https://parallex.mandip.dev/advisories.json (and .sig)",
      "from" : "the app, and parallex notices",
      "id" : "notices",
      "kind" : "parallex",
      "literals" : [
        "https://parallex.mandip.dev/advisories.json",
        "https://parallex.mandip.dev/advisories.json.sig"
      ],
      "managedKeys" : [
        "AutomaticUpdateChecks",
        "AppUpdatesAllowed"
      ],
      "method" : "GET",
      "purpose" : "A signed list of notices about apps whose copies misbehave. The same file for everyone.",
      "sends" : "Nothing beyond Parallex's name and version (User-Agent).",
      "turnOff" : "Settings › About › Check for updates automatically turns the automatic fetch off too. Managed: AutomaticUpdateChecks false, or AppUpdatesAllowed false.",
      "when" : "A little after the app starts and twice a day, only while it checks for updates automatically; and when you choose Check for Updates or run parallex notices."
    },
    {
      "address" : "https://parallex.mandip.dev/api/v2/report",
      "from" : "the app (what the parallex command did is counted in it)",
      "id" : "usage-report",
      "kind" : "parallex",
      "literals" : [
        "https://parallex.mandip.dev/api/v2/report"
      ],
      "managedKeys" : [
        "TelemetrySharing"
      ],
      "method" : "POST",
      "purpose" : "The anonymous usage report.",
      "sends" : "A random install number (renewed every 180 days), the versions and chip, counts of instances and features, well-known apps copied, what happened since the last report (counted), and Parallex's own crash frames. Never names, paths, contents or the license.",
      "turnOff" : "Settings › About › Share anonymous usage, or parallex usage --no-share. Managed: TelemetrySharing false.",
      "when" : "Once a day, with the update check, only while sharing is on."
    },
    {
      "address" : "https://parallex.mandip.dev/api/v1/feedback",
      "from" : "the app (Something's Off)",
      "id" : "feedback",
      "kind" : "parallex",
      "literals" : [
        "https://parallex.mandip.dev/api/v1/feedback"
      ],
      "managedKeys" : [

      ],
      "method" : "POST",
      "purpose" : "A note you write.",
      "sends" : "Your words, the versions and chip, and for an instance you pick, its kind, a well-known app's ID and version, and how it has been doing. An email address only if you type one. See What's Sent shows it all first.",
      "turnOff" : "Don't send one.",
      "when" : "Only when you press Send."
    },
    {
      "address" : "https://parallex.mandip.dev/api/v1/licence/… (trial, activate, deactivate, refresh, challenge, founding, account, upgrade/link, prices, breaker)",
      "from" : "the app and the parallex command",
      "id" : "licence",
      "kind" : "parallex",
      "literals" : [
        "https://parallex.mandip.dev"
      ],
      "managedKeys" : [
        "LicenceKey"
      ],
      "method" : "POST, and GET for prices and breaker",
      "purpose" : "Your license: starting the trial, adding or taking a Mac off a license, the daily token refresh, an optional account, and the current prices.",
      "sends" : "As the request needs: the license key (activating), the token (refreshing), a code made on this Mac from its hardware ID by a one-way function, a name for the Mac, Parallex's and macOS's versions, and on macOS 27 an App Attest proof. Prices and breaker send nothing but Parallex's name and version.",
      "turnOff" : "Needed to make and change instances with a license. Copies you've made keep opening without it. Managed: LicenceKey adds Macs to a license without anyone typing it.",
      "when" : "When you start a trial, activate, sign in or free a Mac; about once a day to refresh the token; prices when a purchase screen shows them; breaker when a license can't be confirmed, and every 3 hours while licensing is paused."
    },
    {
      "address" : "https://parallex.mandip.dev/",
      "from" : "Doctor (the app's Diagnostics and parallex doctor)",
      "id" : "doctor-reachability",
      "kind" : "parallex",
      "literals" : [
        "https://parallex.mandip.dev/"
      ],
      "managedKeys" : [

      ],
      "method" : "HEAD",
      "purpose" : "Whether Parallex's server answers, for the checkup.",
      "sends" : "Nothing beyond Parallex's name and version. Nothing is counted or kept.",
      "turnOff" : "Don't run Doctor.",
      "when" : "Only when you run Doctor or open Diagnostics."
    },
    {
      "address" : "https://parallex.mandip.dev/no-updates.xml",
      "from" : "a copy's own updater (not Parallex)",
      "id" : "copy-updater",
      "kind" : "parallex",
      "literals" : [
        "https://parallex.mandip.dev/no-updates.xml"
      ],
      "managedKeys" : [

      ],
      "method" : "GET",
      "purpose" : "Where a copy's own updater is pointed, so the vendor's build can't replace the copy. The file never has an update.",
      "sends" : "Whatever that app's updater sends, if it asks at all. Nothing is counted or kept.",
      "turnOff" : "Use plain instances (they keep the app's own updater), not copies.",
      "when" : "When a copy's own updater looks for updates."
    },
    {
      "address" : "Apple's App Attest service (through macOS)",
      "from" : "the app and the parallex command",
      "id" : "app-attest",
      "kind" : "apple",
      "literals" : [

      ],
      "managedKeys" : [

      ],
      "method" : "—",
      "purpose" : "On macOS 27 and later, proof for the license server that this is the signed Parallex on a real Mac.",
      "sends" : "What macOS sends to Apple for App Attest, under Apple's privacy policy.",
      "turnOff" : "Comes with licensing on macOS 27.",
      "when" : "With license requests that start something (trial, activation, account sign-in)."
    },
    {
      "address" : "The websites you add as web instances (presets: WhatsApp, Slack, Discord, Gmail, Outlook, Teams, Telegram, Messenger)",
      "from" : "Parallex Web (a web instance's small browser)",
      "id" : "websites",
      "kind" : "yours",
      "literals" : [
        "https://web.whatsapp.com",
        "https://app.slack.com/client",
        "https://discord.com/app",
        "https://mail.google.com",
        "https://outlook.office.com/mail/",
        "https://teams.microsoft.com",
        "https://web.telegram.org",
        "https://www.messenger.com",
        "https://"
      ],
      "managedKeys" : [

      ],
      "method" : "Any, as a browser",
      "purpose" : "The site itself, like any browser.",
      "sends" : "What any browser sends to that site.",
      "turnOff" : "Don't make web instances, or remove them.",
      "when" : "While a web instance is open."
    },
    {
      "address" : "The website you're adding",
      "from" : "the app and the parallex command",
      "id" : "site-icon",
      "kind" : "yours",
      "literals" : [

      ],
      "managedKeys" : [

      ],
      "method" : "GET",
      "purpose" : "The site's icon, for a new web instance.",
      "sends" : "A plain request for its home page and icon.",
      "turnOff" : "Choose your own icon instead.",
      "when" : "When you create a web instance."
    },
    {
      "address" : "The proxy a workspace or your organization sets (WorkspaceProxy)",
      "from" : "copies and agent runs in that workspace",
      "id" : "workspace-proxy",
      "kind" : "yours",
      "literals" : [

      ],
      "managedKeys" : [
        "WorkspaceProxy"
      ],
      "method" : "Any",
      "purpose" : "Their own traffic goes through the proxy you chose. Parallex sends nothing of its own there.",
      "sends" : "That app's or agent's own traffic.",
      "turnOff" : "Remove the workspace's proxy. Managed: WorkspaceProxy.",
      "when" : "While those copies or runs are open."
    },
    {
      "address" : "http://127.0.0.1:… (a port picked per run)",
      "from" : "agent runs",
      "id" : "agent-proxy",
      "kind" : "local",
      "literals" : [
        "http://127.0.0.1:\\(port",
        "http://agent:\\(credential)@127.0.0.1:\\(port",
        "http://\\(authority)\\(path",
        "http://"
      ],
      "managedKeys" : [
        "AgentWorkspacesAllowed"
      ],
      "method" : "Any",
      "purpose" : "Each agent run's own proxy, on this Mac: a sealed run can reach only the hosts it allows, and every request is in the run's proxy log. It passes on what the agent asks for, and nothing of Parallex's own.",
      "sends" : "The agent's own traffic, to the hosts it asks for.",
      "turnOff" : "Don't run agents through Parallex. Managed: AgentWorkspacesAllowed false.",
      "when" : "While an agent run is going."
    }
  ],
  "neverContacted" : [
    {
      "literal" : "http://proxy.example:8080",
      "why" : "An example in help text"
    },
    {
      "literal" : "http://proxy.example.com:8080",
      "why" : "An example in help text"
    },
    {
      "literal" : "http://proxy.client.example:8080",
      "why" : "An example in help text"
    },
    {
      "literal" : "http://host:port",
      "why" : "An example in help text"
    },
    {
      "literal" : "https://example.com",
      "why" : "An example"
    },
    {
      "literal" : "https://example.com/a.zip",
      "why" : "A stand-in for review shots (debug builds only)"
    },
    {
      "literal" : "https://example.com/a.zip.sig",
      "why" : "A stand-in for review shots (debug builds only)"
    },
    {
      "literal" : "https://www.Northwind.com/x",
      "why" : "An example in a comment"
    },
    {
      "literal" : "https://github.com/x",
      "why" : "An example in a comment"
    },
    {
      "literal" : "https://github.com\\",
      "why" : "A host a credential is recognized for"
    },
    {
      "literal" : "https://user:pass@…",
      "why" : "Words in a comment about credentials taken out of backups"
    },
    {
      "literal" : "https://token@…",
      "why" : "Words in a comment about credentials taken out of backups"
    },
    {
      "literal" : "https://user:token@host",
      "why" : "Words in a comment about credentials Carry leaves behind"
    },
    {
      "literal" : "https://parallex.mandip.dev/r#…",
      "why" : "Help text"
    },
    {
      "literal" : "https://(?:ptb\\.|canary\\.)?discord(?:app)?\\.com/api/webhooks/)[0-9]+/[A-Za-z0-9_\\-]+",
      "why" : "A pattern secrets are recognized by"
    },
    {
      "literal" : "https://hooks\\.slack\\.com/(?:services|workflows|triggers)/)[A-Za-z0-9/_\\-]+",
      "why" : "A pattern secrets are recognized by"
    },
    {
      "literal" : "https://\\(canaryHost(record))/v1\\n",
      "why" : "A decoy written into honeytoken files (a .invalid name, which never resolves)"
    },
    {
      "literal" : "https://\\(canaryHost(record))\\n",
      "why" : "A decoy written into honeytoken files (a .invalid name, which never resolves)"
    },
    {
      "literal" : "http://parallex-seal-check.invalid/",
      "why" : "The sealed self-test asks the run's own proxy for this .invalid name, which never resolves"
    }
  ],
  "note" : "Every network address Parallex can contact, made from NetworkInventory.swift by `parallex network --json`. The tests keep the two the same.",
  "opened" : [
    {
      "literal" : "https://parallex.mandip.dev/how-it-works",
      "why" : "How it works"
    },
    {
      "literal" : "https://parallex.mandip.dev/privacy",
      "why" : "What leaves your Mac"
    },
    {
      "literal" : "https://parallex.mandip.dev/license",
      "why" : "The license agreement"
    },
    {
      "literal" : "https://parallex.mandip.dev/compatibility",
      "why" : "Which apps work"
    },
    {
      "literal" : "https://parallex.mandip.dev/managed-fleets",
      "why" : "Parallex in managed fleets"
    },
    {
      "literal" : "https://parallex.mandip.dev/releases",
      "why" : "Release notes"
    },
    {
      "literal" : "https://parallex.mandip.dev/r",
      "why" : "A setup shared as a link (the setup is in the # part, which browsers never send)"
    },
    {
      "literal" : "https://parallex.mandip.dev/r#",
      "why" : "A setup link, as it's made"
    },
    {
      "literal" : "https://github.com/settings/keys",
      "why" : "GitHub's SSH keys page, for an agent's key"
    },
    {
      "literal" : "https://github.com/settings/ssh/new",
      "why" : "GitHub's new SSH key page"
    },
    {
      "literal" : "https://github.com/settings/personal-access-tokens",
      "why" : "GitHub's tokens page"
    },
    {
      "literal" : "https://github.com/settings/personal-access-tokens/new",
      "why" : "GitHub's new token page"
    },
    {
      "literal" : "https://github.com/",
      "why" : "GitHub, for an agent's account"
    },
    {
      "literal" : "https://github.com/\\(repository)/issues/new?\\(query",
      "why" : "Report How It Works: a GitHub issue filled in, sent only if you submit it there"
    }
  ]
}
