{
  "path": "/3ma5ozmwfns2l",
  "site": "at://did:plc:2cxgdrgtsmrbqnjkwyplmp43/site.standard.publication/3lxsr74rnk22h",
  "tags": [
    "atproto",
    "Bluesky",
    "private set intersection"
  ],
  "$type": "site.standard.document",
  "title": "Bluesky's Find Friends Contact Import",
  "content": {
    "$type": "pub.leaflet.content",
    "pages": [
      {
        "id": "019b2a2c-6295-7771-b38b-6ffd835b7ff1",
        "$type": "pub.leaflet.pages.linearDocument",
        "blocks": [
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": "The Bluesky team added a privacy preserving, opt in \"find friends\" feature that imports your contacts."
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": "There was an initial \"Request for Comments\" (RFC) on the technical, privacy preserving options of this design."
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "src": "https://docs.bsky.app/blog/contact-import-rfc",
              "$type": "pub.leaflet.blocks.website",
              "title": "Request For Comments: A secure contact import scheme for social networks | Bluesky",
              "description": "This article outlines plans for a future Bluesky feature \\- it doesn’t exist yet\\! By sharing our ideas early, we hope to solicit feedback from the community.",
              "previewImage": {
                "$type": "blob",
                "ref": {
                  "$link": "bafkreibqfeqfynscevbgr7bcfvhor5txe2wce7nbusgx6v4a7onvtn2wea"
                },
                "mimeType": "image/png",
                "size": 41364
              }
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": "The feature is available in the native mobile apps only, I believe, because of how this has to be done securely."
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": "I've pasted in screenshots of the flow below on iOS. If anyone has Android screenshots, please share."
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": "You may see this \"new feature pop-up\" advertising it when you get the updated app:"
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.image",
              "image": {
                "$type": "blob",
                "ref": {
                  "$link": "bafkreiask6fbp7za3jxzv2lpes75hwhg66tnsljq22rk4fjndndg2ptkne"
                },
                "mimeType": "image/jpeg",
                "size": 156379
              },
              "aspectRatio": {
                "width": 1206,
                "height": 1426
              }
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": "This leads you to first verify your phone number."
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": ""
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "alt": "Screenshot\n\nWe need to verify your number before we can look for your friends. A verification code will be sent to this number.\n\n(Phone number input)\n\nHow we use your number:\n• Sent to our phone number verification provider Plivo\n• Deleted by Plivo after verification\n• Held by Bluesky for 7 days to prevent abuse, then deleted\n• Stored as part of a secure code for matching with others\nBy continuing, you consent to this use. You may change your mind any time by visiting settings. (link: Learn more)",
              "$type": "pub.leaflet.blocks.image",
              "image": {
                "$type": "blob",
                "ref": {
                  "$link": "bafkreierbjt6yt6rrudp4awx2dfazekfartsx6dp4tpr2kcor7urikdyty"
                },
                "mimeType": "image/jpeg",
                "size": 206493
              },
              "aspectRatio": {
                "width": 1206,
                "height": 1398
              }
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": "You'll get a text message you need to paste into a verification screen, and then it will move on with some more information."
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "alt": "Screenshot: Share your contacts to find friends.\n\nSee next text block for rest of text.",
              "$type": "pub.leaflet.blocks.image",
              "image": {
                "$type": "blob",
                "ref": {
                  "$link": "bafkreigrdhubh6pyzaiick4u4nzyyytwn4qmak73gt6qdns44idvkv2wqi"
                },
                "mimeType": "image/jpeg",
                "size": 294689
              },
              "aspectRatio": {
                "width": 1206,
                "height": 2436
              }
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": "I'll include the text from the screenshot here, Bluesky is trying hard to explain this technical, privacy preserving technique."
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": "Bluesky helps friends find each other by creating an encoded digital fingerprint, called a \"hash\", and then looking for matching hashes."
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.unorderedList",
              "children": [
                {
                  "$type": "pub.leaflet.blocks.unorderedList#listItem",
                  "content": {
                    "$type": "pub.leaflet.blocks.text",
                    "facets": [],
                    "plaintext": "We never keep plain phone numbers"
                  },
                  "children": []
                },
                {
                  "$type": "pub.leaflet.blocks.unorderedList#listItem",
                  "content": {
                    "$type": "pub.leaflet.blocks.text",
                    "facets": [],
                    "plaintext": "We delete hashes after matches are made"
                  },
                  "children": []
                },
                {
                  "$type": "pub.leaflet.blocks.unorderedList#listItem",
                  "content": {
                    "$type": "pub.leaflet.blocks.text",
                    "facets": [],
                    "plaintext": "We only suggest follows if both people consent"
                  },
                  "children": []
                },
                {
                  "$type": "pub.leaflet.blocks.unorderedList#listItem",
                  "content": {
                    "$type": "pub.leaflet.blocks.text",
                    "facets": [],
                    "plaintext": "You can always opt out and delete your data"
                  },
                  "children": []
                }
              ]
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": "We apply the highest privacy standards, and never share or sell your contact information."
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": "(the next text is at the bottom of the screen above a button that says \"Find my friends\" or \"Cancel\")"
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": "I consent to Bluesky using my contacts for mutual friend discovery and to retain hashed data for matching until l opt out."
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.horizontalRule"
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": "This next part is the iOS contact picker. It prompts to either share some contacts or all. I've cropped this screen to just the bottom messaging."
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.image",
              "image": {
                "$type": "blob",
                "ref": {
                  "$link": "bafkreia2jbwls44vpgik3kthlxe6vdhkj4vftmfxsik27ipjfjnkgb4aqu"
                },
                "mimeType": "image/jpeg",
                "size": 156871
              },
              "aspectRatio": {
                "width": 1206,
                "height": 1121
              }
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": "Once imported, it shows a scrollable list of all the contacts, with an invite button next to them."
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.image",
              "image": {
                "$type": "blob",
                "ref": {
                  "$link": "bafkreibwfg52gqigxui7vwfr5ngbbf7te6jaeormmdknnm3f6ptgtqwwcq"
                },
                "mimeType": "image/jpeg",
                "size": 139180
              },
              "aspectRatio": {
                "width": 1206,
                "height": 2079
              }
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": "Oh look, I found myself! OK great, I can test this."
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.image",
              "image": {
                "$type": "blob",
                "ref": {
                  "$link": "bafkreighjvpn7em4gj7drmhp7q4ukvkhwjcij666u4i3uyjoa2p4xll2uy"
                },
                "mimeType": "image/jpeg",
                "size": 80507
              },
              "aspectRatio": {
                "width": 1206,
                "height": 1219
              }
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": "Hitting invite opens a new text message:"
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": ""
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.image",
              "image": {
                "$type": "blob",
                "ref": {
                  "$link": "bafkreiglxod3fg5mz5wz2tk5sxwp4whkt2mn7hvmgj7cwjlquq2futhowu"
                },
                "mimeType": "image/jpeg",
                "size": 91594
              },
              "aspectRatio": {
                "width": 1206,
                "height": 1389
              }
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [
                {
                  "index": {
                    "byteEnd": 36,
                    "byteStart": 28
                  },
                  "features": [
                    {
                      "$type": "pub.leaflet.richtext.facet#code"
                    }
                  ]
                },
                {
                  "index": {
                    "byteEnd": 79,
                    "byteStart": 54
                  },
                  "features": [
                    {
                      "$type": "pub.leaflet.richtext.facet#code"
                    }
                  ]
                }
              ],
              "plaintext": "It says: \"I'm on Bluesky as bmann.ca - come find me!  https://bsky.app/download\""
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": "I did send it, and found that this probably needs some improvement."
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": ""
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.image",
              "image": {
                "$type": "blob",
                "ref": {
                  "$link": "bafkreic3cev2ga7rkerngk6pybwko4ika7ll34tlpfqam25cajbyrs6cey"
                },
                "mimeType": "image/jpeg",
                "size": 125421
              },
              "aspectRatio": {
                "width": 1206,
                "height": 1107
              }
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [
                {
                  "index": {
                    "byteEnd": 25,
                    "byteStart": 17
                  },
                  "features": [
                    {
                      "$type": "pub.leaflet.richtext.facet#code"
                    }
                  ]
                }
              ],
              "plaintext": "You can see that bmann.ca is now highlighted, and iOS Messages turns it into a clickable http link.... which doesn't go to my bsky profile, but instead to my out of date landing page:"
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "src": "https://bmann.ca",
              "$type": "pub.leaflet.blocks.website",
              "title": "@bmann.ca • Boris Mann",
              "description": "A profile page and links to other places online of Boris Mann",
              "previewImage": {
                "$type": "blob",
                "ref": {
                  "$link": "bafkreid6blwalio5lukizxkluhqrti73p663qlyct4a5er3m6d5tjeisgy"
                },
                "mimeType": "image/png",
                "size": 20016
              }
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [
                {
                  "index": {
                    "byteEnd": 66,
                    "byteStart": 41
                  },
                  "features": [
                    {
                      "$type": "pub.leaflet.richtext.facet#code"
                    }
                  ]
                }
              ],
              "plaintext": "I shared this with Alex, suggesting that bsky.app/profile/bmann.ca would be a better link to include."
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.bskyPost",
              "postRef": {
                "cid": "bafyreibovqehhlotn2wftwisiytq42flj2wd2cmagyh6td5piz2jiej6me",
                "uri": "at://did:plc:2cxgdrgtsmrbqnjkwyplmp43/app.bsky.feed.post/3ma5kibebkk25"
              }
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [],
              "plaintext": "Along with another request for Bluesky app user docs so I don't have to do screenshot essays 😜"
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [
                {
                  "index": {
                    "byteEnd": 73,
                    "byteStart": 49
                  },
                  "features": [
                    {
                      "uri": "https://docs.bsky.app/blog/contact-import-rfc",
                      "$type": "pub.leaflet.richtext.facet#link"
                    }
                  ]
                }
              ],
              "plaintext": "This is a technically sound implementation, I'll re-link the Dev Blog RFC for those that want to dive into the details. "
            }
          },
          {
            "$type": "pub.leaflet.pages.linearDocument#block",
            "block": {
              "$type": "pub.leaflet.blocks.text",
              "facets": [
                {
                  "index": {
                    "byteEnd": 130,
                    "byteStart": 113
                  },
                  "features": [
                    {
                      "did": "did:plc:6ynekzrjhn3r24y5oqhfsp43",
                      "$type": "pub.leaflet.richtext.facet#didMention"
                    }
                  ]
                }
              ],
              "plaintext": "I have had several other discussions around private set intersection like this for related use cases today. Ping @kobi.bsky.social if you have some other thoughts on this. "
            }
          }
        ]
      }
    ]
  },
  "bskyPostRef": {
    "cid": "bafyreibr7667evjs7iqnpxc3wbgp7aqopdzcak6r4y7j64zbngu2ps5tkm",
    "uri": "at://did:plc:2cxgdrgtsmrbqnjkwyplmp43/app.bsky.feed.post/3ma5oztdads2l",
    "commit": {
      "cid": "bafyreiagi6mjn4wgkv4qqgzj3w32wjjthsup4a65asf2zscj6f3cfj2ghe",
      "rev": "3ma5oztfq5x2t"
    },
    "validationStatus": "valid"
  },
  "description": "Screenshot step-by-step on iOS",
  "publishedAt": "2025-12-17T03:14:48.250Z"
}