A place to cache linked articles (think custom and personal wayback machine)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.html 13KB

  1. <!doctype html><!-- This is a valid HTML5 document. -->
  2. <!-- Screen readers, SEO, extensions and so on. -->
  3. <html lang="fr">
  4. <!-- Has to be within the first 1024 bytes, hence before the <title>
  5. See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
  6. <meta charset="utf-8">
  7. <!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
  8. <!-- The viewport meta is quite crowded and we are responsible for that.
  9. See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
  10. <meta name="viewport" content="width=device-width,initial-scale=1">
  11. <!-- Required to make a valid HTML5 document. -->
  12. <title>App Assisted Contact Tracing (archive) — David Larlet</title>
  13. <meta name="description" content="Publication mise en cache pour en conserver une trace.">
  14. <!-- That good ol' feed, subscribe :). -->
  15. <link rel="alternate" type="application/atom+xml" title="Feed" href="/david/log/">
  16. <!-- Generated from https://realfavicongenerator.net/ such a mess. -->
  17. <link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons2/apple-touch-icon.png">
  18. <link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons2/favicon-32x32.png">
  19. <link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons2/favicon-16x16.png">
  20. <link rel="manifest" href="/static/david/icons2/site.webmanifest">
  21. <link rel="mask-icon" href="/static/david/icons2/safari-pinned-tab.svg" color="#07486c">
  22. <link rel="shortcut icon" href="/static/david/icons2/favicon.ico">
  23. <meta name="msapplication-TileColor" content="#f0f0ea">
  24. <meta name="msapplication-config" content="/static/david/icons2/browserconfig.xml">
  25. <meta name="theme-color" content="#f0f0ea">
  26. <!-- Documented, feel free to shoot an email. -->
  27. <link rel="stylesheet" href="/static/david/css/style_2020-06-19.css">
  28. <!-- See https://www.zachleat.com/web/comprehensive-webfonts/ for the trade-off. -->
  29. <link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
  30. <link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
  31. <link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
  32. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  33. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  34. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  35. <script type="text/javascript">
  36. function toggleTheme(themeName) {
  37. document.documentElement.classList.toggle(
  38. 'forced-dark',
  39. themeName === 'dark'
  40. )
  41. document.documentElement.classList.toggle(
  42. 'forced-light',
  43. themeName === 'light'
  44. )
  45. }
  46. const selectedTheme = localStorage.getItem('theme')
  47. if (selectedTheme !== 'undefined') {
  48. toggleTheme(selectedTheme)
  49. }
  50. </script>
  51. <meta name="robots" content="noindex, nofollow">
  52. <meta content="origin-when-cross-origin" name="referrer">
  53. <!-- Canonical URL for SEO purposes -->
  54. <link rel="canonical" href="https://lucumr.pocoo.org/2020/4/3/contact-tracing/">
  55. <body class="remarkdown h1-underline h2-underline h3-underline hr-center ul-star pre-tick">
  56. <article>
  57. <header>
  58. <h1>App Assisted Contact Tracing</h1>
  59. </header>
  60. <nav>
  61. <p class="center">
  62. <a href="/david/" title="Aller à l’accueil">🏠</a> •
  63. <a href="https://lucumr.pocoo.org/2020/4/3/contact-tracing/" title="Lien vers le contenu original">Source originale</a>
  64. </p>
  65. </nav>
  66. <hr>
  67. <main>
  68. <p class=date>written on Friday, April 3, 2020
  69. <p>I don't know how I thought the world would look like 10 years ago, but a
  70. pandemic that prevents us from going outside was not what I was picturing.
  71. It's about three weeks now that I and my family are spending at home in
  72. Austria instead of going to work or having the kids at daycare, two of
  73. those weeks were under mandatory social distancing because of SARS-CoV-2.</p>
  74. <p>And as cute as <a class="reference external" href="https://en.wikipedia.org/wiki/Social_distancing">social distancing</a>
  75. and “flattening the curve” sounds at first, the consequences to our daily
  76. lives are beyond anything I could have imagined would happen in my
  77. lifetime.</p>
  78. <p>What is still conveniently forgotten is that the curve really only stays
  79. flat if we're doing this for a very, very long time. And quite frankly,
  80. I'm not sure for how long our society will be able to do this. Even just
  81. closing restaurants is costing tens of thousands of jobs and closing
  82. schools is going to set back the lives of many children growing up. Many
  83. people are currently separated from their loved ones with no easy way to
  84. get to them because international travel grinded to a halt.</p>
  85. <div class="section" id="technology-to-the-rescue">
  86. <h2>Technology to the Rescue</h2>
  87. <p>So to cut a very long story short: we can get away without social
  88. distancing with the help of technology. This is why: the most efficient
  89. way to fight the outbreak of a pandemic is isolating cases. If you can
  90. catch them before they can infect others you can starve the virus. Now
  91. the issue with this is obviously that you have people running around with
  92. the virus who can infect others but are not symptomatic. So we can only
  93. do the second next best thing: if we can find all the people they had
  94. contact with when they finally become symptomatic, we can narrow down the
  95. search radius for tests.</p>
  96. <p>So a very successful approach could be:</p>
  97. <ol class="arabic simple">
  98. <li>find a covid-19 suspect</li>
  99. <li>test the person</li>
  100. <li>when they are positive, test all of their close contacts</li>
  101. </ol>
  102. <p>So how do we find their cases? The tool of choice in many countries
  103. already are apps. They send out a beacon signal and collect beacon
  104. signals of other users around. When someone tests positive, healthcare
  105. services can notice contacts.</p>
  106. </div>
  107. <div class="section" id="avoiding-orwell">
  108. <h2>Avoiding Orwell</h2>
  109. <p>Now this is where it gets interesting. Let's take Austria for instance
  110. where I live. We have around 9 million residents here. Let's assume
  111. we're aiming for 60% of resident using that app. That sounds like a
  112. surveillance state and scalability nightmare for a country known for
  113. building scalable apps.</p>
  114. <p>But let's think for a moment what is actually necessary to achieve our
  115. goal: it turns out we could largely achieve what we want without a
  116. centralized infrastructure.</p>
  117. <p>Let's set the window of people we care about to something like 5 days.
  118. This means that if someone tests positive, that person's contacts of the
  119. last 5 days ideally get informed about a covid case they had contact with.
  120. How do we design such a system that it's not a privacy invading behemoth?</p>
  121. <p>The app upon installation would roll a random ID and store it. Then it
  122. encrypts the ID it just created with the public key of a central
  123. governmental authority and broadcasts it to other people around via
  124. bluetooth. It then cycles this ID in regular intervals.</p>
  125. <p>When another device (the infected person) sees this ID it measures signal
  126. strength and time observed. When enough time was spent with the other
  127. person and that contact was “close enough” it records the broadcast
  128. (encrypted ID) on the device. The device also just deletes records older
  129. than 5 days.</p>
  130. <p>When person is identified as infected they need to export the contacts
  131. from their app and send it to the health ministry. They could use their
  132. private key to decrypt the IDs and then get in contact with the
  133. potential contacts.</p>
  134. <p>How do they do that? One option does involve a system like a push
  135. notification service. That would obviously require the device to register
  136. their unique ID with a central server and a push notification channel but
  137. this would not reveal much.</p>
  138. <p>Another option could be to do the check in manually which would work for
  139. non connected IoT type of solutions. You could implement such a system as
  140. a token you need to regularly bring to a place to check if you are now
  141. considered a contact person. For instance one could deploy check-in
  142. stations at public transport hubs where you hold your token against and if
  143. one of your contacts was infected it would beep.</p>
  144. <p>Either way the central authority would not know who you are. Your only
  145. point of contact would be when you become a covid case. Most importantly
  146. this system could be created in a way where it's completely useless for
  147. tracking people but still be useful for contact tracing.</p>
  148. </div>
  149. <div class="section" id="the-phone-in-your-pocket">
  150. <h2>The Phone in your Pocket</h2>
  151. <p>I had conversations with a lot of people over the last few days about
  152. contact tracing apps and I noticed —&nbsp;particularly from technically minded
  153. people — an aversion against the idea of contact tracing via apps. This
  154. does not surprise me, because it's an emotional topic. However it does
  155. hammer home a point that people are very good at misjudging data privacy.</p>
  156. <p>Almost every person I know uses Google maps on their phone with location
  157. history enabled. With that, they also participate in a large data
  158. collection project where their location is constantly being transmitted to
  159. Google. They use this information to judge how fluid traffic is on the
  160. road, how many people are at stores, how busy public transit is etc. All
  161. that data is highly valuable and people love to use this data. I know I
  162. do. I'm also apparently entirely okay with that, even though I know there
  163. is an associated risk.</p>
  164. </div>
  165. <div class="section" id="the-future">
  166. <h2>The Future</h2>
  167. <p>My point here is a simple one: contact tracing if done well is
  168. significantly less privacy infringing than what many tech companies
  169. already do where we're okay with.</p>
  170. <p>I also believe that contact tracing via apps or hardware tokens is our
  171. best chance to return to a largely normal life without giving up all our
  172. civil liberties. I really hope that we're going to have informed and
  173. reasonable technical discussions about how to do contact tracing right and
  174. give this a fair chance.</p>
  175. </div>
  176. </main>
  177. </article>
  178. <hr>
  179. <footer>
  180. <p>
  181. <a href="/david/" title="Aller à l’accueil">🏠</a> •
  182. <a href="/david/log/" title="Accès au flux RSS">🤖</a> •
  183. <a href="http://larlet.com" title="Go to my English profile" data-instant>🇨🇦</a> •
  184. <a href="mailto:david%40larlet.fr" title="Envoyer un courriel">📮</a> •
  185. <abbr title="Hébergeur : Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33184162340">🧚</abbr>
  186. </p>
  187. <template id="theme-selector">
  188. <form>
  189. <fieldset>
  190. <legend>Thème</legend>
  191. <label>
  192. <input type="radio" value="auto" name="chosen-color-scheme" checked> Auto
  193. </label>
  194. <label>
  195. <input type="radio" value="dark" name="chosen-color-scheme"> Foncé
  196. </label>
  197. <label>
  198. <input type="radio" value="light" name="chosen-color-scheme"> Clair
  199. </label>
  200. </fieldset>
  201. </form>
  202. </template>
  203. </footer>
  204. <script type="text/javascript">
  205. function loadThemeForm(templateName) {
  206. const themeSelectorTemplate = document.querySelector(templateName)
  207. const form = themeSelectorTemplate.content.firstElementChild
  208. themeSelectorTemplate.replaceWith(form)
  209. form.addEventListener('change', (e) => {
  210. const chosenColorScheme = e.target.value
  211. localStorage.setItem('theme', chosenColorScheme)
  212. toggleTheme(chosenColorScheme)
  213. })
  214. const selectedTheme = localStorage.getItem('theme')
  215. if (selectedTheme && selectedTheme !== 'undefined') {
  216. form.querySelector(`[value="${selectedTheme}"]`).checked = true
  217. }
  218. }
  219. const prefersColorSchemeDark = '(prefers-color-scheme: dark)'
  220. window.addEventListener('load', () => {
  221. let hasDarkRules = false
  222. for (const styleSheet of Array.from(document.styleSheets)) {
  223. let mediaRules = []
  224. for (const cssRule of styleSheet.cssRules) {
  225. if (cssRule.type !== CSSRule.MEDIA_RULE) {
  226. continue
  227. }
  228. // WARNING: Safari does not have/supports `conditionText`.
  229. if (cssRule.conditionText) {
  230. if (cssRule.conditionText !== prefersColorSchemeDark) {
  231. continue
  232. }
  233. } else {
  234. if (cssRule.cssText.startsWith(prefersColorSchemeDark)) {
  235. continue
  236. }
  237. }
  238. mediaRules = mediaRules.concat(Array.from(cssRule.cssRules))
  239. }
  240. // WARNING: do not try to insert a Rule to a styleSheet you are
  241. // currently iterating on, otherwise the browser will be stuck
  242. // in a infinite loop…
  243. for (const mediaRule of mediaRules) {
  244. styleSheet.insertRule(mediaRule.cssText)
  245. hasDarkRules = true
  246. }
  247. }
  248. if (hasDarkRules) {
  249. loadThemeForm('#theme-selector')
  250. }
  251. })
  252. </script>
  253. </body>
  254. </html>