six-degrees 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (470) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/app-path-routes-manifest.json +10 -0
  3. package/.next/standalone/.next/build-manifest.json +3 -3
  4. package/.next/standalone/.next/prerender-manifest.json +39 -11
  5. package/.next/standalone/.next/required-server-files.json +4 -1
  6. package/.next/standalone/.next/routes-manifest.json +60 -0
  7. package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
  8. package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  9. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  10. package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
  11. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  12. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  13. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  14. package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
  15. package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  16. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  17. package/.next/standalone/.next/server/app/_not-found.rsc +10 -10
  18. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +10 -10
  19. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +9 -9
  20. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  21. package/.next/standalone/.next/server/app/api/admin-delete/route.js +3 -2
  22. package/.next/standalone/.next/server/app/api/admin-delete/route.js.nft.json +1 -1
  23. package/.next/standalone/.next/server/app/api/admin-update/route.js +3 -2
  24. package/.next/standalone/.next/server/app/api/admin-update/route.js.nft.json +1 -1
  25. package/.next/standalone/.next/server/app/api/bridges/route.js +3 -2
  26. package/.next/standalone/.next/server/app/api/bridges/route.js.nft.json +1 -1
  27. package/.next/standalone/.next/server/app/api/bulk-import/route.js +3 -2
  28. package/.next/standalone/.next/server/app/api/bulk-import/route.js.nft.json +1 -1
  29. package/.next/standalone/.next/server/app/api/company-scores/legacy/route/app-paths-manifest.json +3 -0
  30. package/.next/standalone/.next/server/app/api/company-scores/legacy/route/build-manifest.json +12 -0
  31. package/.next/standalone/.next/server/app/api/company-scores/legacy/route/server-reference-manifest.json +4 -0
  32. package/.next/standalone/.next/server/app/api/company-scores/legacy/route.js +9 -0
  33. package/.next/standalone/.next/server/app/api/company-scores/legacy/route.js.map +5 -0
  34. package/.next/standalone/.next/server/app/api/company-scores/legacy/route.js.nft.json +1 -0
  35. package/.next/standalone/.next/server/app/api/company-scores/legacy/route_client-reference-manifest.js +3 -0
  36. package/.next/standalone/.next/server/app/api/company-scores/route.js +3 -2
  37. package/.next/standalone/.next/server/app/api/company-scores/route.js.nft.json +1 -1
  38. package/.next/standalone/.next/server/app/api/connections/route.js +3 -2
  39. package/.next/standalone/.next/server/app/api/connections/route.js.nft.json +1 -1
  40. package/.next/standalone/.next/server/app/api/data/export/route/app-paths-manifest.json +3 -0
  41. package/.next/standalone/.next/server/app/api/data/export/route/build-manifest.json +12 -0
  42. package/.next/standalone/.next/server/app/api/data/export/route/server-reference-manifest.json +4 -0
  43. package/.next/standalone/.next/server/app/api/data/export/route.js +7 -0
  44. package/.next/standalone/.next/server/app/api/data/export/route.js.map +5 -0
  45. package/.next/standalone/.next/server/app/api/data/export/route.js.nft.json +1 -0
  46. package/.next/standalone/.next/server/app/api/data/export/route_client-reference-manifest.js +3 -0
  47. package/.next/standalone/.next/server/app/api/data/import/route/app-paths-manifest.json +3 -0
  48. package/.next/standalone/.next/server/app/api/data/import/route/build-manifest.json +12 -0
  49. package/.next/standalone/.next/server/app/api/data/import/route/server-reference-manifest.json +4 -0
  50. package/.next/standalone/.next/server/app/api/data/import/route.js +8 -0
  51. package/.next/standalone/.next/server/app/api/data/import/route.js.map +5 -0
  52. package/.next/standalone/.next/server/app/api/data/import/route.js.nft.json +1 -0
  53. package/.next/standalone/.next/server/app/api/data/import/route_client-reference-manifest.js +3 -0
  54. package/.next/standalone/.next/server/app/api/data/restart/route/app-paths-manifest.json +3 -0
  55. package/.next/standalone/.next/server/app/api/data/restart/route/build-manifest.json +12 -0
  56. package/.next/standalone/.next/server/app/api/data/restart/route/server-reference-manifest.json +4 -0
  57. package/.next/standalone/.next/server/app/api/data/restart/route.js +8 -0
  58. package/.next/standalone/.next/server/app/api/data/restart/route.js.map +5 -0
  59. package/.next/standalone/.next/server/app/api/data/restart/route.js.nft.json +1 -0
  60. package/.next/standalone/.next/server/app/api/data/restart/route_client-reference-manifest.js +3 -0
  61. package/.next/standalone/.next/server/app/api/data/reveal/route/app-paths-manifest.json +3 -0
  62. package/.next/standalone/.next/server/app/api/data/reveal/route/build-manifest.json +12 -0
  63. package/.next/standalone/.next/server/app/api/data/reveal/route/server-reference-manifest.json +4 -0
  64. package/.next/standalone/.next/server/app/api/data/reveal/route.js +7 -0
  65. package/.next/standalone/.next/server/app/api/data/reveal/route.js.map +5 -0
  66. package/.next/standalone/.next/server/app/api/data/reveal/route.js.nft.json +1 -0
  67. package/.next/standalone/.next/server/app/api/data/reveal/route_client-reference-manifest.js +3 -0
  68. package/.next/standalone/.next/server/app/api/data/route/app-paths-manifest.json +3 -0
  69. package/.next/standalone/.next/server/app/api/data/route/build-manifest.json +12 -0
  70. package/.next/standalone/.next/server/app/api/data/route/server-reference-manifest.json +4 -0
  71. package/.next/standalone/.next/server/app/api/data/route.js +7 -0
  72. package/.next/standalone/.next/server/app/api/data/route.js.map +5 -0
  73. package/.next/standalone/.next/server/app/api/data/route.js.nft.json +1 -0
  74. package/.next/standalone/.next/server/app/api/data/route_client-reference-manifest.js +3 -0
  75. package/.next/standalone/.next/server/app/api/delete-cluster/route.js +3 -2
  76. package/.next/standalone/.next/server/app/api/delete-cluster/route.js.nft.json +1 -1
  77. package/.next/standalone/.next/server/app/api/ingest/route.js +2 -2
  78. package/.next/standalone/.next/server/app/api/ingest/route.js.nft.json +1 -1
  79. package/.next/standalone/.next/server/app/api/network/route.js +3 -2
  80. package/.next/standalone/.next/server/app/api/network/route.js.nft.json +1 -1
  81. package/.next/standalone/.next/server/app/api/notifications/route.js +3 -2
  82. package/.next/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
  83. package/.next/standalone/.next/server/app/api/outreach/route.js +3 -2
  84. package/.next/standalone/.next/server/app/api/outreach/route.js.nft.json +1 -1
  85. package/.next/standalone/.next/server/app/api/queue/route.js +3 -2
  86. package/.next/standalone/.next/server/app/api/queue/route.js.nft.json +1 -1
  87. package/.next/standalone/.next/server/app/api/scraper/route.js +3 -2
  88. package/.next/standalone/.next/server/app/api/scraper/route.js.nft.json +1 -1
  89. package/.next/standalone/.next/server/app/api/settings/route/app-paths-manifest.json +3 -0
  90. package/.next/standalone/.next/server/app/api/settings/route/build-manifest.json +12 -0
  91. package/.next/standalone/.next/server/app/api/settings/route/server-reference-manifest.json +4 -0
  92. package/.next/standalone/.next/server/app/api/settings/route.js +9 -0
  93. package/.next/standalone/.next/server/app/api/settings/route.js.map +5 -0
  94. package/.next/standalone/.next/server/app/api/settings/route.js.nft.json +1 -0
  95. package/.next/standalone/.next/server/app/api/settings/route_client-reference-manifest.js +3 -0
  96. package/.next/standalone/.next/server/app/api/settings/sector-preview/route/app-paths-manifest.json +3 -0
  97. package/.next/standalone/.next/server/app/api/settings/sector-preview/route/build-manifest.json +12 -0
  98. package/.next/standalone/.next/server/app/api/settings/sector-preview/route/server-reference-manifest.json +4 -0
  99. package/.next/standalone/.next/server/app/api/settings/sector-preview/route.js +8 -0
  100. package/.next/standalone/.next/server/app/api/settings/sector-preview/route.js.map +5 -0
  101. package/.next/standalone/.next/server/app/api/settings/sector-preview/route.js.nft.json +1 -0
  102. package/.next/standalone/.next/server/app/api/settings/sector-preview/route_client-reference-manifest.js +3 -0
  103. package/.next/standalone/.next/server/app/api/settings/sector-suggestions/route/app-paths-manifest.json +3 -0
  104. package/.next/standalone/.next/server/app/api/settings/sector-suggestions/route/build-manifest.json +12 -0
  105. package/.next/standalone/.next/server/app/api/settings/sector-suggestions/route/server-reference-manifest.json +4 -0
  106. package/.next/standalone/.next/server/app/api/settings/sector-suggestions/route.js +8 -0
  107. package/.next/standalone/.next/server/app/api/settings/sector-suggestions/route.js.map +5 -0
  108. package/.next/standalone/.next/server/app/api/settings/sector-suggestions/route.js.nft.json +1 -0
  109. package/.next/standalone/.next/server/app/api/settings/sector-suggestions/route_client-reference-manifest.js +3 -0
  110. package/.next/standalone/.next/server/app/api/setup-profile/route.js +3 -2
  111. package/.next/standalone/.next/server/app/api/setup-profile/route.js.nft.json +1 -1
  112. package/.next/standalone/.next/server/app/api/unlock/route.js +3 -2
  113. package/.next/standalone/.next/server/app/api/unlock/route.js.nft.json +1 -1
  114. package/.next/standalone/.next/server/app/api/update/route.js +1 -1
  115. package/.next/standalone/.next/server/app/api/update/route.js.nft.json +1 -1
  116. package/.next/standalone/.next/server/app/api/update-images/route.js +3 -2
  117. package/.next/standalone/.next/server/app/api/update-images/route.js.nft.json +1 -1
  118. package/.next/standalone/.next/server/app/api/users/route.js +3 -2
  119. package/.next/standalone/.next/server/app/api/users/route.js.nft.json +1 -1
  120. package/.next/standalone/.next/server/app/avatars/[file]/route.js +2 -1
  121. package/.next/standalone/.next/server/app/avatars/[file]/route.js.nft.json +1 -1
  122. package/.next/standalone/.next/server/app/favicon.ico/route.js +2 -1
  123. package/.next/standalone/.next/server/app/favicon.ico/route.js.nft.json +1 -1
  124. package/.next/standalone/.next/server/app/import/page.js.nft.json +1 -1
  125. package/.next/standalone/.next/server/app/import/page_client-reference-manifest.js +1 -1
  126. package/.next/standalone/.next/server/app/import.html +1 -1
  127. package/.next/standalone/.next/server/app/import.rsc +12 -12
  128. package/.next/standalone/.next/server/app/import.segments/_full.segment.rsc +12 -12
  129. package/.next/standalone/.next/server/app/import.segments/_tree.segment.rsc +1 -1
  130. package/.next/standalone/.next/server/app/import.segments/import/__PAGE__.segment.rsc +11 -11
  131. package/.next/standalone/.next/server/app/index.html +1 -1
  132. package/.next/standalone/.next/server/app/index.rsc +12 -12
  133. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +11 -11
  134. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +12 -12
  135. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  136. package/.next/standalone/.next/server/app/launch/page.js.nft.json +1 -1
  137. package/.next/standalone/.next/server/app/launch/page_client-reference-manifest.js +1 -1
  138. package/.next/standalone/.next/server/app/launch.html +2 -2
  139. package/.next/standalone/.next/server/app/launch.rsc +12 -12
  140. package/.next/standalone/.next/server/app/launch.segments/_full.segment.rsc +12 -12
  141. package/.next/standalone/.next/server/app/launch.segments/_tree.segment.rsc +1 -1
  142. package/.next/standalone/.next/server/app/launch.segments/launch/__PAGE__.segment.rsc +11 -11
  143. package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
  144. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  145. package/.next/standalone/.next/server/app/paths/page.js.nft.json +1 -1
  146. package/.next/standalone/.next/server/app/paths/page_client-reference-manifest.js +1 -1
  147. package/.next/standalone/.next/server/app/paths.html +1 -1
  148. package/.next/standalone/.next/server/app/paths.rsc +12 -12
  149. package/.next/standalone/.next/server/app/paths.segments/_full.segment.rsc +12 -12
  150. package/.next/standalone/.next/server/app/paths.segments/_tree.segment.rsc +1 -1
  151. package/.next/standalone/.next/server/app/paths.segments/paths/__PAGE__.segment.rsc +11 -11
  152. package/.next/standalone/.next/server/app/profile/page.js.nft.json +1 -1
  153. package/.next/standalone/.next/server/app/profile/page_client-reference-manifest.js +1 -1
  154. package/.next/standalone/.next/server/app/profile.html +1 -1
  155. package/.next/standalone/.next/server/app/profile.rsc +12 -12
  156. package/.next/standalone/.next/server/app/profile.segments/_full.segment.rsc +12 -12
  157. package/.next/standalone/.next/server/app/profile.segments/_tree.segment.rsc +1 -1
  158. package/.next/standalone/.next/server/app/profile.segments/profile/__PAGE__.segment.rsc +11 -11
  159. package/.next/standalone/.next/server/app/queue/page.js.nft.json +1 -1
  160. package/.next/standalone/.next/server/app/queue/page_client-reference-manifest.js +1 -1
  161. package/.next/standalone/.next/server/app/queue.html +1 -1
  162. package/.next/standalone/.next/server/app/queue.rsc +12 -12
  163. package/.next/standalone/.next/server/app/queue.segments/_full.segment.rsc +12 -12
  164. package/.next/standalone/.next/server/app/queue.segments/_tree.segment.rsc +1 -1
  165. package/.next/standalone/.next/server/app/queue.segments/queue/__PAGE__.segment.rsc +11 -11
  166. package/.next/standalone/.next/server/app/settings/page/app-paths-manifest.json +3 -0
  167. package/.next/standalone/.next/server/app/settings/page/build-manifest.json +20 -0
  168. package/.next/standalone/.next/server/app/settings/page/next-font-manifest.json +11 -0
  169. package/.next/standalone/.next/server/app/settings/page/react-loadable-manifest.json +1 -0
  170. package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +4 -0
  171. package/.next/standalone/.next/server/app/settings/page.js +13 -0
  172. package/.next/standalone/.next/server/app/settings/page.js.map +5 -0
  173. package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -0
  174. package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +3 -0
  175. package/.next/standalone/.next/server/app/settings.html +1 -0
  176. package/.next/standalone/.next/server/app/settings.meta +26 -0
  177. package/.next/standalone/.next/server/app/settings.rsc +24 -0
  178. package/.next/standalone/.next/server/app/settings.segments/_full.segment.rsc +24 -0
  179. package/.next/standalone/.next/server/app/settings.segments/_tree.segment.rsc +4 -0
  180. package/.next/standalone/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +28 -0
  181. package/.next/standalone/.next/server/app/setup/page.js.nft.json +1 -1
  182. package/.next/standalone/.next/server/app/setup/page_client-reference-manifest.js +1 -1
  183. package/.next/standalone/.next/server/app/setup.html +1 -1
  184. package/.next/standalone/.next/server/app/setup.rsc +12 -12
  185. package/.next/standalone/.next/server/app/setup.segments/_full.segment.rsc +12 -12
  186. package/.next/standalone/.next/server/app/setup.segments/_tree.segment.rsc +1 -1
  187. package/.next/standalone/.next/server/app/setup.segments/setup/__PAGE__.segment.rsc +11 -11
  188. package/.next/standalone/.next/server/app-paths-manifest.json +10 -0
  189. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0-rnla2._.js +3 -0
  190. package/.next/standalone/.next/server/chunks/[root-of-the-server]__00la_y0._.js +3 -0
  191. package/.next/standalone/.next/server/chunks/[root-of-the-server]__07t47cm._.js +3 -0
  192. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0cj5jqc._.js +3 -0
  193. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0e0fei3._.js +3 -0
  194. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0i5hdu4._.js +3 -0
  195. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ljcioj._.js +3 -0
  196. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ljnyho._.js +3 -0
  197. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o5-tcg._.js +3 -0
  198. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0qrnous._.js +3 -0
  199. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0t3v1a1._.js +3 -0
  200. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0uag-k5._.js +8 -0
  201. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0um1uey._.js +3 -0
  202. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0wmexuc._.js +3 -0
  203. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0xu34sz._.js +3 -0
  204. package/.next/standalone/.next/server/chunks/[root-of-the-server]__133knx1._.js +3 -0
  205. package/.next/standalone/.next/server/chunks/[root-of-the-server]__14ou7j5._.js +3 -0
  206. package/.next/standalone/.next/server/chunks/[root-of-the-server]__15-17hl._.js +3 -0
  207. package/.next/standalone/.next/server/chunks/[root-of-the-server]__16iu0hv._.js +3 -0
  208. package/.next/standalone/.next/server/chunks/[root-of-the-server]__19b7mig._.js +3 -0
  209. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1bbcwub._.js +8 -0
  210. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1eris29._.js +3 -0
  211. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1gjo_cq._.js +3 -0
  212. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1kbl21f._.js +3 -0
  213. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1qcm08_._.js +3 -0
  214. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1rphsdk._.js +3 -0
  215. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1t3rugi._.js +3 -0
  216. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1w25q0m._.js +3 -0
  217. package/.next/standalone/.next/server/chunks/_072jl0y._.js +3 -0
  218. package/.next/standalone/.next/server/chunks/_0lw8_i0._.js +3 -0
  219. package/.next/standalone/.next/server/chunks/_1_fynia._.js +21 -3
  220. package/.next/standalone/.next/server/chunks/_1fn30_l._.js +3 -0
  221. package/.next/standalone/.next/server/chunks/_1itd1o_._.js +2 -1
  222. package/.next/standalone/.next/server/chunks/_1iwkh8t._.js +1 -1
  223. package/.next/standalone/.next/server/chunks/_1mxn_lb._.js +3 -0
  224. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_company-scores_legacy_route_actions_1ncspu_.js +3 -0
  225. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_data_export_route_actions_1lkimty.js +3 -0
  226. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_data_import_route_actions_1eji0kd.js +3 -0
  227. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_data_restart_route_actions_00_-u6o.js +3 -0
  228. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_data_reveal_route_actions_0-moqtn.js +3 -0
  229. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_data_route_actions_0j0w5ep.js +3 -0
  230. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_settings_route_actions_1bpm9ac.js +3 -0
  231. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_settings_sector-preview_route_actions_0w79454.js +3 -0
  232. package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_settings_sector-suggestions_route_actions_1eoqugp.js +3 -0
  233. package/.next/standalone/.next/server/chunks/lib_db-client_15le7cw.js +155 -0
  234. package/.next/standalone/.next/server/chunks/{lib_rpc_0mc73lk.js → lib_rpc_00tx2sm.js} +1 -1
  235. package/.next/standalone/.next/server/chunks/lib_rpc_02-qa4d.js +3 -0
  236. package/.next/standalone/.next/server/chunks/lib_rpc_02ndsg2.js +3 -0
  237. package/.next/standalone/.next/server/chunks/lib_rpc_08q5vp6.js +3 -0
  238. package/.next/standalone/.next/server/chunks/lib_rpc_0_8i3ft.js +3 -0
  239. package/.next/standalone/.next/server/chunks/lib_rpc_0c9d9ti.js +5 -2
  240. package/.next/standalone/.next/server/chunks/lib_rpc_0huvw-3.js +3 -0
  241. package/.next/standalone/.next/server/chunks/lib_rpc_0ip2vdh.js +3 -0
  242. package/.next/standalone/.next/server/chunks/lib_rpc_0jzisgh.js +3 -0
  243. package/.next/standalone/.next/server/chunks/lib_rpc_0yi9xvd.js +3 -0
  244. package/.next/standalone/.next/server/chunks/lib_rpc_1jyhd0o.js +3 -0
  245. package/.next/standalone/.next/server/chunks/lib_rpc_1kn59-i.js +3 -0
  246. package/.next/standalone/.next/server/chunks/lib_rpc_1q2jkza.js +3 -0
  247. package/.next/standalone/.next/server/chunks/lib_rpc_1vpm1sk.js +3 -0
  248. package/.next/standalone/.next/server/chunks/lib_rpc_1x6p_31.js +3 -0
  249. package/.next/standalone/.next/server/chunks/node_modules_next_1zc5q0a._.js +158 -0
  250. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0mocm6d._.js → [root-of-the-server]__0an6blh._.js} +3 -3
  251. package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1m0255u._.js +3 -0
  252. package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0bipr5s._.js → [root-of-the-server]__1z1j3ek._.js} +2 -2
  253. package/.next/standalone/.next/server/chunks/ssr/_07u8byv._.js +3 -0
  254. package/.next/standalone/.next/server/chunks/ssr/_08r_mlf._.js +3 -0
  255. package/.next/standalone/.next/server/chunks/ssr/{_0ggabjc._.js → _0942v8n._.js} +1 -1
  256. package/.next/standalone/.next/server/chunks/ssr/{_1djpk8t._.js → _0hl_t7r._.js} +2 -2
  257. package/.next/standalone/.next/server/chunks/ssr/_0tb83dw._.js +132 -0
  258. package/.next/standalone/.next/server/chunks/ssr/_1-87bs1._.js +3 -0
  259. package/.next/standalone/.next/server/chunks/ssr/_17gui6a._.js +1 -1
  260. package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_settings_page_actions_11x4dq5.js +3 -0
  261. package/.next/standalone/.next/server/chunks/ssr/app_launch_page_19t0dyd.js +2 -2
  262. package/.next/standalone/.next/server/chunks/ssr/app_page_1fazqbf.js +4 -4
  263. package/.next/standalone/.next/server/chunks/ssr/app_profile_page_0u3-l5y.js +1 -1
  264. package/.next/standalone/.next/server/chunks/ssr/app_queue_page_0c6znd6.js +5 -5
  265. package/.next/standalone/.next/server/chunks/ssr/app_settings_page_1f8mjj_.js +3 -0
  266. package/.next/standalone/.next/server/chunks/ssr/app_setup_page_1-282zx.js +2 -2
  267. package/.next/standalone/.next/server/chunks/ssr/lib_0i8v-s3._.js +1 -1
  268. package/.next/standalone/.next/server/chunks/ssr/node_modules_1f8t_rp._.js +23 -0
  269. package/.next/standalone/.next/server/chunks/ssr/node_modules_1nkgb45._.js +2 -2
  270. package/.next/standalone/.next/server/chunks/ssr/{node_modules_01xbj_9._.js → node_modules_1wax83z._.js} +3 -3
  271. package/.next/standalone/.next/server/chunks/ssr/{node_modules_next_dist_00nap8h._.js → node_modules_next_dist_1bunoni._.js} +2 -2
  272. package/.next/standalone/.next/server/edge/chunks/[root-of-the-server]__0pco7a6._.js +2 -2
  273. package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
  274. package/.next/standalone/.next/server/middleware-manifest.json +15 -7
  275. package/.next/standalone/.next/server/next-font-manifest.js +1 -1
  276. package/.next/standalone/.next/server/next-font-manifest.json +4 -0
  277. package/.next/standalone/.next/server/pages/404.html +1 -1
  278. package/.next/standalone/.next/server/pages/500.html +1 -1
  279. package/.next/standalone/.next/server/prefetch-hints.json +14 -0
  280. package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
  281. package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
  282. package/.next/standalone/.next/static/chunks/06x3jiiz96m5t.js +1 -0
  283. package/.next/standalone/.next/static/chunks/{34at5d2ifl62i.js → 0ngx9s6-zgshe.js} +5 -5
  284. package/.next/standalone/.next/static/chunks/0q-_khndfxubv.js +2 -0
  285. package/.next/standalone/.next/static/chunks/1c79veqedvubt.js +1 -0
  286. package/.next/standalone/.next/static/chunks/1chp3nx45meg5.js +44 -0
  287. package/.next/standalone/.next/static/chunks/1irqj0lf-fu3d.js +1 -0
  288. package/.next/standalone/.next/static/chunks/1uadqylrod5_v.js +1 -0
  289. package/.next/standalone/.next/static/chunks/23u0zclgwpc4d.js +1 -0
  290. package/.next/standalone/.next/static/chunks/289ktj97di6zg.js +1 -0
  291. package/.next/standalone/.next/static/chunks/2b3lmf8e6uj8m.js +16 -0
  292. package/.next/standalone/.next/static/chunks/2jz311xl1pp_8.js +1 -0
  293. package/.next/standalone/.next/static/chunks/3npq5yd7c4dmn.js +2 -0
  294. package/.next/standalone/.next/static/qqqcxvzBUizkECrT4swyK/_clientMiddlewareManifest.js +14 -0
  295. package/.next/standalone/CHANGELOG.md +298 -0
  296. package/.next/standalone/CONTRIBUTING.md +5 -2
  297. package/.next/standalone/README.md +138 -30
  298. package/.next/standalone/SECURITY.md +117 -10
  299. package/.next/standalone/app/api/company-scores/legacy/route.js +32 -0
  300. package/.next/standalone/app/api/company-scores/route.js +20 -11
  301. package/.next/standalone/app/api/data/export/route.js +49 -0
  302. package/.next/standalone/app/api/data/import/route.js +83 -0
  303. package/.next/standalone/app/api/data/restart/route.js +37 -0
  304. package/.next/standalone/app/api/data/reveal/route.js +14 -0
  305. package/.next/standalone/app/api/data/route.js +39 -0
  306. package/.next/standalone/app/api/ingest/route.js +15 -47
  307. package/.next/standalone/app/api/scraper/route.js +264 -125
  308. package/.next/standalone/app/api/settings/route.js +58 -0
  309. package/.next/standalone/app/api/settings/sector-preview/route.js +38 -0
  310. package/.next/standalone/app/api/settings/sector-suggestions/route.js +20 -0
  311. package/.next/standalone/app/api/update/route.js +188 -23
  312. package/.next/standalone/app/avatars/[file]/route.js +4 -2
  313. package/.next/standalone/app/components/CompanyScores.js +28 -7
  314. package/.next/standalone/app/components/EmptyState.js +8 -0
  315. package/.next/standalone/app/components/ForceGraph.js +39 -35
  316. package/.next/standalone/app/components/LegacyScoresCard.js +129 -0
  317. package/.next/standalone/app/components/Sidebar.js +11 -10
  318. package/.next/standalone/app/components/UpdatePanel.js +306 -119
  319. package/.next/standalone/app/components/UserProvider.js +4 -3
  320. package/.next/standalone/app/components/settings/DataSection.js +437 -0
  321. package/.next/standalone/app/components/settings/SectorSection.js +445 -0
  322. package/.next/standalone/app/components/ui.js +62 -0
  323. package/.next/standalone/app/launch/page.js +30 -20
  324. package/.next/standalone/app/page.js +13 -0
  325. package/.next/standalone/app/paths/page.js +12 -4
  326. package/.next/standalone/app/profile/page.js +41 -8
  327. package/.next/standalone/app/queue/page.js +8 -2
  328. package/.next/standalone/app/settings/page.js +96 -0
  329. package/.next/standalone/app/setup/page.js +32 -16
  330. package/.next/standalone/bin/args.mjs +44 -0
  331. package/.next/standalone/bin/six-degrees.mjs +9 -15
  332. package/.next/standalone/lib/companies.js +44 -119
  333. package/.next/standalone/lib/csv.js +8 -0
  334. package/.next/standalone/lib/data-export.js +170 -0
  335. package/.next/standalone/lib/data-folder.js +238 -0
  336. package/.next/standalone/lib/data-import.js +878 -0
  337. package/.next/standalone/lib/db-client.js +48 -3
  338. package/.next/standalone/lib/durable.js +73 -0
  339. package/.next/standalone/lib/gate.js +90 -1
  340. package/.next/standalone/lib/ingest.js +40 -0
  341. package/.next/standalone/lib/legacy-offer.js +185 -0
  342. package/.next/standalone/lib/legacy-scores.js +77 -0
  343. package/.next/standalone/lib/linkedin-limits.js +124 -1
  344. package/.next/standalone/lib/rpc.js +121 -13
  345. package/.next/standalone/lib/sample-stats.js +16 -0
  346. package/.next/standalone/lib/scan-progress.js +13 -0
  347. package/.next/standalone/lib/scan-state.js +53 -0
  348. package/.next/standalone/lib/scanner-python.js +685 -0
  349. package/.next/standalone/lib/scanner-setup.js +104 -0
  350. package/.next/standalone/lib/scoring.js +747 -138
  351. package/.next/standalone/lib/scraper-client.js +9 -5
  352. package/.next/standalone/lib/sector-directory.js +1532 -0
  353. package/.next/standalone/lib/sector-focus.js +163 -0
  354. package/.next/standalone/lib/sector-labels.js +81 -0
  355. package/.next/standalone/lib/settings-effects.js +59 -0
  356. package/.next/standalone/lib/settings.js +83 -0
  357. package/.next/standalone/lib/updater-job.js +838 -0
  358. package/.next/standalone/lib/updater.js +494 -0
  359. package/.next/standalone/middleware.js +25 -28
  360. package/.next/standalone/next.config.mjs +19 -3
  361. package/.next/standalone/package-lock.json +2 -2
  362. package/.next/standalone/package.json +1 -2
  363. package/.next/standalone/scripts/apply-update.sh +482 -0
  364. package/.next/standalone/scripts/build-app.mjs +251 -9
  365. package/.next/standalone/scripts/requirements.txt +106 -4
  366. package/.next/standalone/scripts/test-release-server.mjs +143 -0
  367. package/.next/standalone/server.js +1 -1
  368. package/.next/static/chunks/06x3jiiz96m5t.js +1 -0
  369. package/.next/static/chunks/{34at5d2ifl62i.js → 0ngx9s6-zgshe.js} +5 -5
  370. package/.next/static/chunks/0q-_khndfxubv.js +2 -0
  371. package/.next/static/chunks/1c79veqedvubt.js +1 -0
  372. package/.next/static/chunks/1chp3nx45meg5.js +44 -0
  373. package/.next/static/chunks/1irqj0lf-fu3d.js +1 -0
  374. package/.next/static/chunks/1uadqylrod5_v.js +1 -0
  375. package/.next/static/chunks/23u0zclgwpc4d.js +1 -0
  376. package/.next/static/chunks/289ktj97di6zg.js +1 -0
  377. package/.next/static/chunks/2b3lmf8e6uj8m.js +16 -0
  378. package/.next/static/chunks/2jz311xl1pp_8.js +1 -0
  379. package/.next/static/chunks/3npq5yd7c4dmn.js +2 -0
  380. package/.next/static/qqqcxvzBUizkECrT4swyK/_clientMiddlewareManifest.js +14 -0
  381. package/CHANGELOG.md +298 -0
  382. package/README.md +138 -30
  383. package/SECURITY.md +117 -10
  384. package/bin/args.mjs +44 -0
  385. package/bin/six-degrees.mjs +9 -15
  386. package/lib/companies.js +44 -119
  387. package/lib/csv.js +8 -0
  388. package/lib/data-export.js +170 -0
  389. package/lib/data-folder.js +238 -0
  390. package/lib/data-import.js +878 -0
  391. package/lib/db-client.js +48 -3
  392. package/lib/durable.js +73 -0
  393. package/lib/gate.js +90 -1
  394. package/lib/ingest.js +40 -0
  395. package/lib/legacy-offer.js +185 -0
  396. package/lib/legacy-scores.js +77 -0
  397. package/lib/linkedin-limits.js +124 -1
  398. package/lib/rpc.js +121 -13
  399. package/lib/sample-stats.js +16 -0
  400. package/lib/scan-progress.js +13 -0
  401. package/lib/scan-state.js +53 -0
  402. package/lib/scanner-python.js +685 -0
  403. package/lib/scanner-setup.js +104 -0
  404. package/lib/scoring.js +747 -138
  405. package/lib/scraper-client.js +9 -5
  406. package/lib/sector-directory.js +1532 -0
  407. package/lib/sector-focus.js +163 -0
  408. package/lib/sector-labels.js +81 -0
  409. package/lib/settings-effects.js +59 -0
  410. package/lib/settings.js +83 -0
  411. package/lib/updater-job.js +838 -0
  412. package/lib/updater.js +494 -0
  413. package/package.json +1 -2
  414. package/scripts/requirements.txt +106 -4
  415. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0jrmmj-._.js +0 -150
  416. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0qx548g._.js +0 -151
  417. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1an3leo._.js +0 -150
  418. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1m8zedk._.js +0 -155
  419. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1zor0ys._.js +0 -3
  420. package/.next/standalone/.next/server/chunks/_0_rp-01._.js +0 -3
  421. package/.next/standalone/.next/server/chunks/_0hzdk79._.js +0 -3
  422. package/.next/standalone/.next/server/chunks/_0ow7u5r._.js +0 -3
  423. package/.next/standalone/.next/server/chunks/_0t0zc2d._.js +0 -3
  424. package/.next/standalone/.next/server/chunks/_0wa631d._.js +0 -3
  425. package/.next/standalone/.next/server/chunks/_13ccnao._.js +0 -3
  426. package/.next/standalone/.next/server/chunks/_13es063._.js +0 -3
  427. package/.next/standalone/.next/server/chunks/_142872j._.js +0 -3
  428. package/.next/standalone/.next/server/chunks/_18wsb_a._.js +0 -8
  429. package/.next/standalone/.next/server/chunks/_1e-4h5h._.js +0 -3
  430. package/.next/standalone/.next/server/chunks/_1gvvd7n._.js +0 -158
  431. package/.next/standalone/.next/server/chunks/_1moda66._.js +0 -3
  432. package/.next/standalone/.next/server/chunks/_1p6ghzv._.js +0 -3
  433. package/.next/standalone/.next/server/chunks/_1xmmi_v._.js +0 -3
  434. package/.next/standalone/.next/server/chunks/_1z-yrlf._.js +0 -3
  435. package/.next/standalone/.next/server/chunks/ssr/_0bf3x4q._.js +0 -3
  436. package/.next/standalone/.next/server/chunks/ssr/app_paths_page_1ol90m7.js +0 -4
  437. package/.next/standalone/.next/static/ZGTiDrZ5NHGETgGdlhssu/_clientMiddlewareManifest.js +0 -6
  438. package/.next/standalone/.next/static/chunks/0jk64vo17avsb.js +0 -1
  439. package/.next/standalone/.next/static/chunks/0s65dsrthylo6.js +0 -2
  440. package/.next/standalone/.next/static/chunks/0uyfdhi8dek85.js +0 -16
  441. package/.next/standalone/.next/static/chunks/220-ne82aus0c.js +0 -44
  442. package/.next/standalone/.next/static/chunks/229haorf0f19b.js +0 -2
  443. package/.next/standalone/.next/static/chunks/2g54uafnwuakc.js +0 -1
  444. package/.next/standalone/.next/static/chunks/2spwqs6b6dx13.js +0 -1
  445. package/.next/standalone/.next/static/chunks/38dlepuubiox0.js +0 -1
  446. package/.next/standalone/scripts/score-connections.sql +0 -80
  447. package/.next/standalone/scripts/score_new_connections.sql +0 -77
  448. package/.next/standalone/site/app.js +0 -84
  449. package/.next/standalone/site/index.html +0 -221
  450. package/.next/standalone/site/style.css +0 -155
  451. package/.next/standalone/site/video/install-mac-poster.jpg +0 -0
  452. package/.next/standalone/site/video/install-mac.mp4 +0 -0
  453. package/.next/standalone/site/video/linux-poster.jpg +0 -0
  454. package/.next/standalone/site/video/linux.mp4 +0 -0
  455. package/.next/standalone/site/video/scan-poster.jpg +0 -0
  456. package/.next/standalone/site/video/scan.mp4 +0 -0
  457. package/.next/static/ZGTiDrZ5NHGETgGdlhssu/_clientMiddlewareManifest.js +0 -6
  458. package/.next/static/chunks/0jk64vo17avsb.js +0 -1
  459. package/.next/static/chunks/0s65dsrthylo6.js +0 -2
  460. package/.next/static/chunks/0uyfdhi8dek85.js +0 -16
  461. package/.next/static/chunks/220-ne82aus0c.js +0 -44
  462. package/.next/static/chunks/229haorf0f19b.js +0 -2
  463. package/.next/static/chunks/2g54uafnwuakc.js +0 -1
  464. package/.next/static/chunks/2spwqs6b6dx13.js +0 -1
  465. package/.next/static/chunks/38dlepuubiox0.js +0 -1
  466. package/scripts/score_new_connections.sql +0 -77
  467. /package/.next/standalone/.next/static/{ZGTiDrZ5NHGETgGdlhssu → qqqcxvzBUizkECrT4swyK}/_buildManifest.js +0 -0
  468. /package/.next/standalone/.next/static/{ZGTiDrZ5NHGETgGdlhssu → qqqcxvzBUizkECrT4swyK}/_ssgManifest.js +0 -0
  469. /package/.next/static/{ZGTiDrZ5NHGETgGdlhssu → qqqcxvzBUizkECrT4swyK}/_buildManifest.js +0 -0
  470. /package/.next/static/{ZGTiDrZ5NHGETgGdlhssu → qqqcxvzBUizkECrT4swyK}/_ssgManifest.js +0 -0
@@ -1,8 +1,18 @@
1
1
  import { spawn, execFileSync } from 'node:child_process';
2
+ import { accessSync, constants, existsSync } from 'node:fs';
2
3
  import { projectRoot, isGitCheckout, dataDir } from '../../../lib/paths';
3
- import { homedir } from 'node:os';
4
+ import { homedir, tmpdir } from 'node:os';
4
5
  import path from 'node:path';
5
6
  import { repoSlug, compareVersions, installKind, updateCommand } from '../../../lib/release';
7
+ import {
8
+ bundleRefusal, dataRefusal, installerTarget, lastUpdateReport, planFromRelease, releaseSource, runningBundle,
9
+ terminalFallback,
10
+ } from '../../../lib/updater';
11
+ import {
12
+ bundleFacts, cancelUpdate, checkedVersion, cleanLeftovers, confirmStarted, currentUpdate, macFacts,
13
+ othersRunningApp, readStatusFile, rememberCheck, startUpdate, updateActive, updatePaths,
14
+ } from '../../../lib/updater-job';
15
+ import { busyRefusal, scannerJob } from '../../../lib/scan-state';
6
16
  import pkg from '../../../package.json';
7
17
 
8
18
  // Updating, when the app is a git checkout.
@@ -14,6 +24,9 @@ import pkg from '../../../package.json';
14
24
  // already has. It exists because "run git pull first" is a step people forget,
15
25
  // and then they hit bugs that were fixed weeks ago.
16
26
  //
27
+ // The Mac app can also install a release itself, on a second click
28
+ // (installedPost below, lib/updater-job.js).
29
+ //
17
30
  // Gated with the destructive routes: it changes the code that will run next.
18
31
 
19
32
  const GIT_TIMEOUT = 60000;
@@ -88,6 +101,10 @@ async function localState(root) {
88
101
  // compares it with the one baked into this build. One GET to GitHub, only when
89
102
  // the button is pressed, carrying nothing about the user: the spec's invariant 2
90
103
  // names exactly this as permitted. Never call it from anything that runs on its own.
104
+ // In the Mac app a second, separate press ("Install and restart") may then
105
+ // download that release's disk image and SHA256SUMS and install it (invariant 2
106
+ // again). Nothing is downloaded before that press.
107
+
91
108
  // The folder this copy keeps its network in, when it isn't the default one.
92
109
  function customDataDir() {
93
110
  const dir = dataDir();
@@ -97,7 +114,7 @@ function customDataDir() {
97
114
  function installedInfo(root) {
98
115
  const slug = repoSlug(pkg.repository);
99
116
  const kind = installKind(process.env, root || '');
100
- return {
117
+ const info = {
101
118
  supported: false,
102
119
  installed: true,
103
120
  kind,
@@ -105,10 +122,25 @@ function installedInfo(root) {
105
122
  slug,
106
123
  command: slug ? updateCommand(kind, slug, { dataDir: customDataDir() }) : null,
107
124
  };
125
+ if (kind === 'mac-app') {
126
+ // How the last in-app update went (written by scripts/apply-update.sh),
127
+ // and one in progress, so the page can pick it up again. Local files and
128
+ // memory only: this GET runs on every page (StaleServerBanner). The first
129
+ // one after an update also tells the helper this version has started, so
130
+ // it can let go of the previous one (lib/updater-job.js confirmStarted).
131
+ const paths = updatePaths();
132
+ confirmStarted(paths, pkg.version);
133
+ info.lastUpdate = lastUpdateReport(readStatusFile(paths.statusFile), { runningVersion: pkg.version });
134
+ info.job = currentUpdate();
135
+ }
136
+ // A test's release server in place of GitHub is said out loud, never silent.
137
+ const source = releaseSource(process.env);
138
+ if (source.test) info.testReleases = source.apiBase;
139
+ return info;
108
140
  }
109
141
 
110
- async function latestRelease(slug) {
111
- const res = await fetch(`https://api.github.com/repos/${slug}/releases/latest`, {
142
+ async function latestRelease(slug, apiBase) {
143
+ const res = await fetch(`${apiBase}/repos/${slug}/releases/latest`, {
112
144
  headers: { Accept: 'application/vnd.github+json', 'User-Agent': 'six-degrees-update-check' },
113
145
  signal: AbortSignal.timeout(10000),
114
146
  cache: 'no-store',
@@ -119,9 +151,160 @@ async function latestRelease(slug) {
119
151
  return {
120
152
  version: String(d.tag_name || '').replace(/^v/i, ''),
121
153
  url: d.html_url || null,
154
+ release: d, // for the Mac app's install check; not sent to the page
122
155
  };
123
156
  }
124
157
 
158
+ // The Mac app's update helper, shipped inside the app (scripts/build-app.mjs).
159
+ function helperPath(root) {
160
+ const file = root ? path.join(root, 'scripts', 'apply-update.sh') : null;
161
+ return file && existsSync(file) ? file : null;
162
+ }
163
+
164
+ // Can the Mac app replace itself where it is? Every fact is read here, on the
165
+ // server; the page sends only which action it wants.
166
+ function macInstall(root) {
167
+ if (process.platform !== 'darwin') {
168
+ return { refusal: { code: 'not-mac', message: 'Installing an update from here works only in the Mac app.' } };
169
+ }
170
+ const bundle = runningBundle({ app: process.env.SIX_DEGREES_APP, root });
171
+ const refusal = bundleRefusal(bundle, bundleFacts(bundle))
172
+ || dataRefusal({ dataDir: dataDir(), bundle, dbFile: process.env.SIX_DEGREES_DB || null })
173
+ || (helperPath(root) ? null : { code: 'no-helper', message: "This copy doesn't include the update helper, so it can't replace itself." });
174
+ return { bundle, refusal };
175
+ }
176
+
177
+ // What the Terminal line would do for this copy, so the page can say it
178
+ // accurately, or null where it mustn't be offered (lib/updater.js
179
+ // terminalFallback). install.sh installs into /Applications, or ~/Applications
180
+ // when this user can't change /Applications; only a look, nothing is written.
181
+ function fallbackFor(bundle, refusal) {
182
+ let applicationsWritable = true;
183
+ try { accessSync('/Applications', constants.W_OK); } catch { applicationsWritable = false; }
184
+ return terminalFallback({
185
+ bundle,
186
+ refusalCode: refusal?.code || null,
187
+ installsTo: installerTarget({ applicationsWritable, home: homedir() }),
188
+ dataDir: customDataDir(),
189
+ });
190
+ }
191
+
192
+ // What an update cut off half-way left behind (lib/updater-job.js
193
+ // cleanLeftovers), at the next check or install. Never while one runs, and
194
+ // never at the cost of the click that asked.
195
+ function tidyUp(bundle) {
196
+ if (!bundle || updateActive()) return;
197
+ try {
198
+ cleanLeftovers({ bundle, tmpRoot: tmpdir(), ...updatePaths() });
199
+ } catch { /* next time */ }
200
+ }
201
+
202
+ // Updating an installed copy: the Mac app or the npm package.
203
+ //
204
+ // check-release one GET to GitHub for the newest release (the spec's
205
+ // permitted click). For the Mac app it also says whether that
206
+ // release can be installed from here, and if not, why not.
207
+ // install-release the second click, Mac app only: download, check and stage
208
+ // the version the check offered, in the background
209
+ // (lib/updater-job.js), then restart
210
+ // update-status how that is going (local, no network)
211
+ // cancel-install stop it, until it restarts
212
+ async function installedPost(action, root) {
213
+ const info = installedInfo(root);
214
+ // GitHub, or a test's server on 127.0.0.1 (lib/updater.js releaseSource).
215
+ const source = releaseSource(process.env);
216
+
217
+ if (action === 'update-status') return Response.json({ job: currentUpdate() });
218
+ if (action === 'cancel-install') return Response.json({ job: cancelUpdate() });
219
+
220
+ if (action === 'check-release') {
221
+ if (!info.slug) {
222
+ return Response.json({ error: 'This copy does not say where it was published.' }, { status: 400 });
223
+ }
224
+ const mac = info.kind === 'mac-app' ? macInstall(root) : null;
225
+ if (mac) tidyUp(mac.bundle);
226
+ try {
227
+ const latest = await latestRelease(info.slug, source.apiBase);
228
+ const newer = Boolean(latest && compareVersions(latest.version, info.version) > 0);
229
+ let install = null;
230
+ let fallback = null;
231
+ if (newer && mac) {
232
+ const planned = mac.refusal ? null : planFromRelease(latest.release, {
233
+ currentVersion: info.version, chip: macFacts().chip, slug: info.slug, downloadBase: source.downloadBase,
234
+ });
235
+ const why = mac.refusal || planned?.refusal || null;
236
+ install = why ? { possible: false, reason: why.message, code: why.code } : { possible: true, size: planned.plan.dmg.size };
237
+ fallback = fallbackFor(mac.bundle, mac.refusal);
238
+ }
239
+ // Install installs the version this check offered and no other
240
+ // (lib/updater-job.js rememberCheck); none, when it offered none.
241
+ if (mac) rememberCheck(newer ? latest.version : null);
242
+ return Response.json({
243
+ ...info,
244
+ latest: latest && { version: latest.version, url: latest.url },
245
+ newer,
246
+ install,
247
+ fallback,
248
+ });
249
+ } catch (e) {
250
+ return Response.json({ error: `Could not reach GitHub (${e.message}). Try again in a moment.` }, { status: 502 });
251
+ }
252
+ }
253
+
254
+ if (action === 'install-release') {
255
+ if (info.kind !== 'mac-app') {
256
+ return Response.json(
257
+ { error: 'Only the Mac app can install an update itself. Use the line below instead.', command: info.command },
258
+ { status: 400 },
259
+ );
260
+ }
261
+ if (!info.slug) {
262
+ return Response.json({ error: 'This copy does not say where it was published.' }, { status: 400 });
263
+ }
264
+ const { bundle, refusal } = macInstall(root);
265
+ const fallback = fallbackFor(bundle, refusal);
266
+ if (refusal) {
267
+ return Response.json({ error: refusal.message, refusal: refusal.code, fallback, command: info.command }, { status: 409 });
268
+ }
269
+ // Quitting mid-scan (or mid-Install) would stop it half-way; the job looks
270
+ // again just before it restarts. The refusal says which is running.
271
+ const busy = busyRefusal('Let it finish or stop it, then install the update.');
272
+ if (busy) {
273
+ return Response.json({ error: busy, fallback, command: info.command }, { status: 409 });
274
+ }
275
+ // Only the version a check on this server offered (the page names none).
276
+ const expectVersion = checkedVersion();
277
+ if (!expectVersion) {
278
+ return Response.json(
279
+ { error: 'Check for updates first, then install.', refusal: 'not-checked', fallback, command: info.command },
280
+ { status: 409 },
281
+ );
282
+ }
283
+ tidyUp(bundle);
284
+ const mac = macFacts();
285
+ const started = startUpdate({
286
+ slug: info.slug,
287
+ currentVersion: info.version,
288
+ expectVersion,
289
+ chip: mac.chip,
290
+ macosVersion: mac.macosVersion,
291
+ bundle,
292
+ dataDir: dataDir(),
293
+ helper: helperPath(root),
294
+ tmpRoot: tmpdir(),
295
+ ...updatePaths(),
296
+ apiBase: source.apiBase,
297
+ downloadBase: source.downloadBase,
298
+ scanRunning: scannerJob,
299
+ othersRunning: () => othersRunningApp(bundle),
300
+ });
301
+ if (started.error) return Response.json({ error: started.error, job: started.job }, { status: 409 });
302
+ return Response.json({ job: started.job }, { status: 202 });
303
+ }
304
+
305
+ return Response.json({ error: 'Not a git checkout.' }, { status: 400 });
306
+ }
307
+
125
308
  export async function GET() {
126
309
  const root = projectRoot();
127
310
  if (!isGitCheckout()) {
@@ -147,25 +330,7 @@ export async function POST(request) {
147
330
  try { body = await request.json(); } catch {}
148
331
  const action = String(body.action || '');
149
332
 
150
- if (!isGitCheckout()) {
151
- if (action !== 'check-release') {
152
- return Response.json({ error: 'Not a git checkout.' }, { status: 400 });
153
- }
154
- const info = installedInfo(root);
155
- if (!info.slug) {
156
- return Response.json({ error: 'This copy does not say where it was published.' }, { status: 400 });
157
- }
158
- try {
159
- const latest = await latestRelease(info.slug);
160
- return Response.json({
161
- ...info,
162
- latest,
163
- newer: Boolean(latest && compareVersions(latest.version, info.version) > 0),
164
- });
165
- } catch (e) {
166
- return Response.json({ error: `Could not reach GitHub (${e.message}). Try again in a moment.` }, { status: 502 });
167
- }
168
- }
333
+ if (!isGitCheckout()) return installedPost(action, root);
169
334
 
170
335
  if (action === 'check') {
171
336
  const fetched = await git(['fetch', '--quiet', 'origin'], root);
@@ -1,6 +1,7 @@
1
1
  import { readFile } from 'node:fs/promises';
2
2
  import path from 'node:path';
3
3
  import { dataDir } from '../../../lib/db-client';
4
+ import { AVATAR_FILE } from '../../../lib/data-folder';
4
5
 
5
6
  // Avatars are captured by the scraper and live in the user's data directory,
6
7
  // never inside the app package — an installed copy must not write into its own
@@ -10,8 +11,9 @@ import { dataDir } from '../../../lib/db-client';
10
11
  export async function GET(_request, { params }) {
11
12
  const { file } = await params;
12
13
 
13
- // Serve only a plain filename from that one directory.
14
- if (!/^[A-Za-z0-9_-]+\.(webp|jpg|jpeg|png)$/.test(file)) {
14
+ // Serve only a plain filename from that one directory. An export carries
15
+ // and an import accepts exactly the same names (lib/data-folder.js).
16
+ if (!AVATAR_FILE.test(file)) {
15
17
  return new Response('Not found', { status: 404 });
16
18
  }
17
19
 
@@ -5,6 +5,8 @@
5
5
  // Setting a score rescores everyone (app/api/company-scores → lib/scoring.js).
6
6
 
7
7
  import { useCallback, useEffect, useMemo, useState } from 'react';
8
+ import Link from 'next/link';
9
+ import LegacyScoresCard from './LegacyScoresCard';
8
10
 
9
11
  const LINE = '1px solid rgba(255,255,255,0.1)';
10
12
  const SOURCE = {
@@ -36,7 +38,8 @@ export function useCompanyScores() {
36
38
  setCompanies(await fetchScores());
37
39
  return j;
38
40
  }, []);
39
- return { companies, error, setScore };
41
+ const reload = useCallback(async () => setCompanies(await fetchScores()), []);
42
+ return { companies, error, setScore, reload };
40
43
  }
41
44
 
42
45
  /** A 1–10 picker; "auto" hands the score back to the list or the estimate. */
@@ -57,16 +60,29 @@ export function ScorePicker({ company, onSet, compact }) {
57
60
  }
58
61
 
59
62
  export default function CompanyScores({ onRescored }) {
60
- const { companies, error, setScore } = useCompanyScores();
63
+ const { companies, error, setScore, reload } = useCompanyScores();
61
64
  const [query, setQuery] = useState('');
62
65
  const [only, setOnly] = useState('all');
63
66
  const [limit, setLimit] = useState(150);
64
67
  const [toast, setToast] = useState(null);
65
68
 
69
+ const say = (text) => {
70
+ setToast(text);
71
+ setTimeout(() => setToast(null), 3500);
72
+ };
73
+
66
74
  const set = async (name, score) => {
67
75
  const r = await setScore(name, score);
68
- setToast(`${name}: ${score == null ? 'back to auto' : `set to ${score}`} · rescored ${r.scored} people`);
69
- setTimeout(() => setToast(null), 3500);
76
+ say(`${name}: ${score == null ? 'back to auto' : `set to ${score}`} · rescored ${r.scored} people`);
77
+ onRescored?.();
78
+ };
79
+
80
+ // The one-time "keep the old scores" card, answered: kept scores are yours
81
+ // now, so the list and the network reload.
82
+ const legacyAnswered = async ({ kept, scored, error: failed }) => {
83
+ if (!kept.length) return say('Keeping the new built-in scores.');
84
+ say(failed || `Kept ${kept.length} old ${kept.length === 1 ? 'score' : 'scores'} as your own · rescored ${scored} people`);
85
+ await reload().catch(() => {});
70
86
  onRescored?.();
71
87
  };
72
88
 
@@ -84,16 +100,18 @@ export default function CompanyScores({ onRescored }) {
84
100
  return (
85
101
  <div style={{ flex: 1, overflow: 'auto', padding: 16 }}>
86
102
  <div style={{ maxWidth: 980, margin: '0 auto' }}>
103
+ <LegacyScoresCard onAnswered={legacyAnswered} />
87
104
  <div style={{ padding: 14, borderRadius: 10, border: LINE, background: 'rgba(255,255,255,0.03)', fontSize: 12.5, color: '#cfd8d8', lineHeight: 1.6 }}>
88
105
  <b style={{ color: '#fff' }}>How a power score works.</b> power = <b>title</b> × <b>company weight</b> + bonus.
89
106
  The title (student 1 … founder or C-suite 10) comes from someone&rsquo;s current role, with former roles at 70%.
90
- The company weight runs from 0.56 (no company found) to 1.0 (a company scored 10), so seniority counts for more at a bigger company.
91
- The bonus is at most +1.5, for investor, YC or an audience in the millions, and counts half at an unknown company.
107
+ The company weight runs from 0.615 (no company found) to 1.0 (a company scored 10), so seniority counts for more at a bigger company.
108
+ The bonus is at most +1.5, for investor, YC, an audience in the millions or the top award of any field, and counts half at an unknown company.
92
109
  A 1st-degree person whose circle is unusually strong gets up to +1 more.
93
110
  S ≥ 7.5 · A ≥ 5.5 · B ≥ 4 · C ≥ 2.5.
94
111
  <div style={{ marginTop: 6, color: '#8b9a9a' }}>
95
112
  So a VP at a 10 scores 9.0, a founder at an unknown company 6.7, a director at an unknown company 5.0, and an intern at a 10 scores 2.0.
96
113
  Set a company&rsquo;s score below and everyone there is rescored.
114
+ Companies in the sectors you pick in <Link href="/settings#sector" style={{ color: '#3498DB' }}>Settings</Link> get +1 or +2; a score you set is never changed.
97
115
  </div>
98
116
  </div>
99
117
 
@@ -123,7 +141,10 @@ export default function CompanyScores({ onRescored }) {
123
141
  <span style={{ textAlign: 'right', color: c.d1 ? '#00ff88' : '#556' }}>{c.d1}</span>
124
142
  <span style={{ textAlign: 'right', color: c.senior ? '#FFD700' : '#556' }}>{c.senior}</span>
125
143
  <b style={{ textAlign: 'right', fontSize: 15 }}>{c.score}</b>
126
- <span style={{ fontSize: 11, color: SOURCE[c.source]?.color }}>{SOURCE[c.source]?.label}</span>
144
+ <span style={{ fontSize: 11, color: SOURCE[c.source]?.color }}>
145
+ {SOURCE[c.source]?.label}
146
+ {c.sectorBonus > 0 && <span style={{ color: '#00ff88' }}> + {c.sectorBonus} your sector</span>}
147
+ </span>
127
148
  <ScorePicker company={c} onSet={set} compact />
128
149
  </div>
129
150
  ))}
@@ -73,6 +73,14 @@ export default function EmptyState() {
73
73
  {error && (
74
74
  <div style={{ color: '#ff6b6b', fontSize: 13, marginTop: 18 }}>{error}</div>
75
75
  )}
76
+
77
+ {/* The new-computer case: a network saved on the old one is brought in from Settings. */}
78
+ <p style={{ color: 'rgba(255,255,255,0.45)', fontSize: 13, lineHeight: 1.6, margin: '18px 0 0' }}>
79
+ Moving from another computer?{' '}
80
+ <a href="/settings#data" style={{ color: 'rgba(255,255,255,0.75)' }}>
81
+ Import your saved copy in Settings → Your data.
82
+ </a>
83
+ </p>
76
84
  </div>
77
85
  </div>
78
86
  );
@@ -23,6 +23,10 @@ function safeImageUrl(url) {
23
23
  : null;
24
24
  }
25
25
 
26
+ // The id of the node at the centre, you. Not a connection's id (those come from
27
+ // the database), and never shown.
28
+ const CENTER_ID = '__center__';
29
+
26
30
  // Builds the avatar tooltip through the DOM rather than a string, so no value
27
31
  // can break out of the attribute it is written into.
28
32
  function renderPhoto(sel, d, size, borderColor) {
@@ -181,7 +185,7 @@ function createTooltip() {
181
185
 
182
186
  function renderNetworkMode(svg, width, height, connections, onSelect, tierColors, focusNodeRef, savedTransform, zoomTransformRef, userName) {
183
187
  const centerNode = {
184
- id: 'blake', name: userName || 'You', tier: 'center', degree: 0,
188
+ id: CENTER_ID, name: userName || 'You', tier: 'center', degree: 0,
185
189
  power_score: 10, fx: width / 2, fy: height / 2,
186
190
  };
187
191
 
@@ -197,14 +201,14 @@ function renderNetworkMode(svg, width, height, connections, onSelect, tierColors
197
201
  circle_power: c.circle_power, circle_s_count: c.circle_s_count, circle_a_count: c.circle_a_count,
198
202
  }))];
199
203
 
200
- const links = connections.map(c => ({ source: 'blake', target: c.id }));
204
+ const links = connections.map(c => ({ source: CENTER_ID, target: c.id }));
201
205
 
202
206
  const tierRadius = (tier) => {
203
207
  switch (tier) { case 'S': return 150; case 'A': return 250; case 'B': return 350; case 'C': return 450; default: return 520; }
204
208
  };
205
209
 
206
210
  const nodeRadius = (d) => {
207
- if (d.id === 'blake') return 18;
211
+ if (d.id === CENTER_ID) return 18;
208
212
  return Math.max(3, Math.min(12, (d.power_score || 1) * 1.3));
209
213
  };
210
214
 
@@ -250,7 +254,7 @@ function renderNetworkMode(svg, width, height, connections, onSelect, tierColors
250
254
  nodes.forEach(n => { const t = n.tier || 'D'; if (!tierGroups[t]) tierGroups[t] = []; tierGroups[t].push(n); });
251
255
  Object.entries(tierGroups).forEach(([tier, group]) => {
252
256
  group.forEach((n, i) => {
253
- if (n.id === 'blake') { n.x = width / 2; n.y = height / 2; n.fx = n.x; n.fy = n.y; return; }
257
+ if (n.id === CENTER_ID) { n.x = width / 2; n.y = height / 2; n.fx = n.x; n.fy = n.y; return; }
254
258
  const r = tierRadius(tier);
255
259
  const angle = (i / group.length) * Math.PI * 2 - Math.PI / 2;
256
260
  n.x = width / 2 + r * Math.cos(angle);
@@ -262,10 +266,10 @@ function renderNetworkMode(svg, width, height, connections, onSelect, tierColors
262
266
 
263
267
  const simulation = d3.forceSimulation(nodes)
264
268
  .force('link', d3.forceLink(links).id(d => d.id).distance(d => tierRadius(d.target.tier || 'D')).strength(isMobileGraph ? 0 : 0.1))
265
- .force('charge', d3.forceManyBody().strength(isMobileGraph ? 0 : (d => d.id === 'blake' ? -300 : -15)))
269
+ .force('charge', d3.forceManyBody().strength(isMobileGraph ? 0 : (d => d.id === CENTER_ID ? -300 : -15)))
266
270
  .force('center', isMobileGraph ? null : d3.forceCenter(width / 2, height / 2))
267
271
  .force('collision', isMobileGraph ? null : d3.forceCollide().radius(d => nodeRadius(d) + 2))
268
- .force('radial', isMobileGraph ? null : d3.forceRadial(d => d.id === 'blake' ? 0 : tierRadius(d.tier), width / 2, height / 2).strength(0.3));
272
+ .force('radial', isMobileGraph ? null : d3.forceRadial(d => d.id === CENTER_ID ? 0 : tierRadius(d.tier), width / 2, height / 2).strength(0.3));
269
273
 
270
274
  const link = g.append('g').selectAll('line').data(links).join('line')
271
275
  .attr('stroke', d => { const t = nodes.find(n => n.id === (d.target.id || d.target)); return tierColors[t?.tier] || '#333'; })
@@ -291,20 +295,20 @@ function renderNetworkMode(svg, width, height, connections, onSelect, tierColors
291
295
 
292
296
  const node = g.append('g').selectAll('circle').data(nodes).join('circle')
293
297
  .attr('r', nodeRadius)
294
- .attr('fill', d => d.id === 'blake' ? '#fff' : tierColors[d.tier] || '#666')
298
+ .attr('fill', d => d.id === CENTER_ID ? '#fff' : tierColors[d.tier] || '#666')
295
299
  .attr('stroke', d => {
296
- if (d.id === 'blake') return '#FFD700';
300
+ if (d.id === CENTER_ID) return '#FFD700';
297
301
  if (d.is_catalyst) return '#00ff88';
298
302
  return 'none';
299
303
  })
300
304
  .attr('stroke-width', d => {
301
- if (d.id === 'blake') return 3;
305
+ if (d.id === CENTER_ID) return 3;
302
306
  if (d.is_catalyst) return 2.5;
303
307
  return 0;
304
308
  })
305
309
  .style('cursor', 'pointer')
306
310
  .on('click', (event, d) => {
307
- if (d.id === 'blake') return;
311
+ if (d.id === CENTER_ID) return;
308
312
  // Remove previous selection glow
309
313
  g.selectAll('.selected-glow').remove();
310
314
  // Add breathing glow to selected node
@@ -328,7 +332,7 @@ function renderNetworkMode(svg, width, height, connections, onSelect, tierColors
328
332
 
329
333
  node.on('mouseover', function (event, d) {
330
334
  d3.select(this).attr('r', nodeRadius(d) * 1.5);
331
- if (d.profile_image_url && d.id !== 'blake') {
335
+ if (d.profile_image_url && d.id !== CENTER_ID) {
332
336
  const size = Math.max(48, nodeRadius(d) * 5);
333
337
  photoTooltip.style('opacity', 1);
334
338
  renderPhoto(photoTooltip, d, size, tierColors[d.tier] || '#555');
@@ -346,7 +350,7 @@ function renderNetworkMode(svg, width, height, connections, onSelect, tierColors
346
350
  .style('left', (event.clientX + 12) + 'px').style('top', (event.clientY - 10) + 'px');
347
351
  }
348
352
  }).on('mousemove', function (event, d) {
349
- if (d.profile_image_url && d.id !== 'blake') {
353
+ if (d.profile_image_url && d.id !== CENTER_ID) {
350
354
  const size = Math.max(48, nodeRadius(d) * 5);
351
355
  photoTooltip.style('left', (event.clientX - size / 2) + 'px').style('top', (event.clientY - size - 8) + 'px');
352
356
  tooltip.style('left', (event.clientX - 40) + 'px').style('top', (event.clientY + 12) + 'px');
@@ -359,16 +363,16 @@ function renderNetworkMode(svg, width, height, connections, onSelect, tierColors
359
363
  photoTooltip.style('opacity', 0);
360
364
  });
361
365
 
362
- setupDrag(node, simulation, 'blake');
366
+ setupDrag(node, simulation, CENTER_ID);
363
367
 
364
368
  const labels = g.append('g').selectAll('text')
365
- .data(nodes.filter(n => n.id === 'blake' || n.tier === 'S' || n.is_catalyst))
369
+ .data(nodes.filter(n => n.id === CENTER_ID || n.tier === 'S' || n.is_catalyst))
366
370
  .join('text')
367
371
  .text(d => d.is_catalyst && d.tier !== 'S' ? d.name + ' ⚡' : d.name)
368
- .attr('font-size', d => d.id === 'blake' ? 14 : 10)
369
- .attr('font-weight', d => d.id === 'blake' ? 700 : 500)
372
+ .attr('font-size', d => d.id === CENTER_ID ? 14 : 10)
373
+ .attr('font-weight', d => d.id === CENTER_ID ? 700 : 500)
370
374
  .attr('fill', d => {
371
- if (d.id === 'blake') return '#fff';
375
+ if (d.id === CENTER_ID) return '#fff';
372
376
  if (d.is_catalyst) return '#00ff88';
373
377
  return tierColors[d.tier];
374
378
  })
@@ -410,14 +414,14 @@ function renderDegreesMode(svg, width, height, allD1, degree2, onSelect, tierCol
410
414
  const numBridges = Math.max(bridges.length, 1);
411
415
  const cx = width / 2, cy = height / 2;
412
416
 
413
- // Per-tier orbit distance from Blake — S closest, A further, etc.
417
+ // Per-tier orbit distance from the centre (you): S closest, A further, etc.
414
418
  const bridgeTierOrbit = { S: 350, A: 600, B: 820, C: 1000, D: 1150 };
415
419
  const tierRing = { S: 40, A: 70, B: 100, C: 125, D: 145 };
416
420
  const tierOrder = ['S', 'A', 'B', 'C', 'D'];
417
421
 
418
422
  // --- Build nodes ---
419
423
  const centerNode = {
420
- id: 'blake', name: userName || 'You', tier: 'center', degree: 0,
424
+ id: CENTER_ID, name: userName || 'You', tier: 'center', degree: 0,
421
425
  power_score: 10, nodeType: 'center', fx: cx, fy: cy,
422
426
  };
423
427
 
@@ -484,7 +488,7 @@ function renderDegreesMode(svg, width, height, allD1, degree2, onSelect, tierCol
484
488
 
485
489
  const nodes = [centerNode, ...bridgeNodes, ...d2Nodes];
486
490
  const links = [
487
- ...bridgeNodes.map(b => ({ source: 'blake', target: b.id, linkType: 'bridge' })),
491
+ ...bridgeNodes.map(b => ({ source: CENTER_ID, target: b.id, linkType: 'bridge' })),
488
492
  ...d2Nodes.map(d => ({ source: d.source_connection_id, target: d.id, linkType: 'degree2' })),
489
493
  ];
490
494
 
@@ -774,10 +778,10 @@ function renderDegreesMode(svg, width, height, allD1, degree2, onSelect, tierCol
774
778
  return 0; // d2 has NO charge — positions are computed, not physics-driven
775
779
  }))
776
780
  .force('bridgeOrbit', (() => {
777
- let _nodes, _blake;
781
+ let _nodes, _center;
778
782
  const force = (alpha) => {
779
- if (!_blake) return;
780
- const bx = _blake.fx ?? _blake.x, by = _blake.fy ?? _blake.y;
783
+ if (!_center) return;
784
+ const bx = _center.fx ?? _center.x, by = _center.fy ?? _center.y;
781
785
  for (const n of _nodes) {
782
786
  if (n.nodeType !== 'bridge') continue;
783
787
  const targetR = n._orbitRadius || 500;
@@ -788,7 +792,7 @@ function renderDegreesMode(svg, width, height, allD1, degree2, onSelect, tierCol
788
792
  n.vy -= (dy / dist) * diff * alpha * 0.4;
789
793
  }
790
794
  };
791
- force.initialize = (n) => { _nodes = n; _blake = n.find(x => x.id === 'blake'); };
795
+ force.initialize = (n) => { _nodes = n; _center = n.find(x => x.id === CENTER_ID); };
792
796
  return force;
793
797
  })())
794
798
  .force('clusterPositioning', (() => {
@@ -856,8 +860,8 @@ function renderDegreesMode(svg, width, height, allD1, degree2, onSelect, tierCol
856
860
  // Animated boundaries — deform where clusters overlap
857
861
  updateBoundaries();
858
862
  // Bridge connecting lines
859
- const blakeX = centerNode.fx ?? centerNode.x, blakeY = centerNode.fy ?? centerNode.y;
860
- bridgeLines.attr('x1', blakeX).attr('y1', blakeY)
863
+ const centerX = centerNode.fx ?? centerNode.x, centerY = centerNode.fy ?? centerNode.y;
864
+ bridgeLines.attr('x1', centerX).attr('y1', centerY)
861
865
  .attr('x2', d => d.x).attr('y2', d => d.y);
862
866
  // Discovery chain lines
863
867
  chainLines
@@ -883,7 +887,7 @@ function renderDegreesMode(svg, width, height, allD1, degree2, onSelect, tierCol
883
887
  });
884
888
 
885
889
  // --- Drag ---
886
- setupDrag(node, simulation, 'blake');
890
+ setupDrag(node, simulation, CENTER_ID);
887
891
 
888
892
  // --- Tooltip + Photo Hover (same as Network Map) ---
889
893
  const tooltip = createTooltip();
@@ -897,7 +901,7 @@ function renderDegreesMode(svg, width, height, allD1, degree2, onSelect, tierCol
897
901
  d3.select(this).attr('r', nodeRadius(d) * 1.5).attr('filter', 'url(#glow)');
898
902
 
899
903
  // Photo hover
900
- if (d.profile_image_url && d.id !== 'blake') {
904
+ if (d.profile_image_url && d.id !== CENTER_ID) {
901
905
  const size = Math.max(48, nodeRadius(d) * 4);
902
906
  photoTooltip.style('opacity', 1);
903
907
  renderPhoto(photoTooltip, d, size, tierColors[d.tier] || '#555');
@@ -923,7 +927,7 @@ function renderDegreesMode(svg, width, height, allD1, degree2, onSelect, tierCol
923
927
  ].filter(Boolean).join('<br/>'))
924
928
  .style('left', (event.clientX + 12) + 'px').style('top', (event.clientY + 12) + 'px');
925
929
  }).on('mousemove', function (event, d) {
926
- if (d.profile_image_url && d.id !== 'blake') {
930
+ if (d.profile_image_url && d.id !== CENTER_ID) {
927
931
  const size = Math.max(48, nodeRadius(d) * 4);
928
932
  photoTooltip.style('left', (event.clientX - size / 2) + 'px').style('top', (event.clientY - size - 8) + 'px');
929
933
  }
@@ -937,7 +941,7 @@ function renderDegreesMode(svg, width, height, allD1, degree2, onSelect, tierCol
937
941
 
938
942
  // --- Click: select + Connect to Unlock overlay ---
939
943
  node.on('click', (event, d) => {
940
- if (d.id === 'blake') return;
944
+ if (d.id === CENTER_ID) return;
941
945
  // Selection glow
942
946
  g.selectAll('.selected-glow').remove();
943
947
  g.append('circle')
@@ -960,9 +964,9 @@ function renderDegreesMode(svg, width, height, allD1, degree2, onSelect, tierCol
960
964
  const overlay = g.append('g').attr('class', 'unlock-overlay');
961
965
  // Dim non-path nodes
962
966
  node.transition().duration(300)
963
- .attr('opacity', n => (n.id === d.id || n.id === 'blake' || n.id === d.source_connection_id) ? 1 : 0.2);
967
+ .attr('opacity', n => (n.id === d.id || n.id === CENTER_ID || n.id === d.source_connection_id) ? 1 : 0.2);
964
968
  labels.transition().duration(300)
965
- .attr('opacity', n => (n.id === d.id || n.id === 'blake' || n.id === d.source_connection_id) ? 1 : 0.1);
969
+ .attr('opacity', n => (n.id === d.id || n.id === CENTER_ID || n.id === d.source_connection_id) ? 1 : 0.1);
966
970
  // Phantom cluster
967
971
  [30, 55, 80].forEach(r => {
968
972
  overlay.append('circle').attr('cx', ox).attr('cy', oy).attr('r', r)
@@ -977,9 +981,9 @@ function renderDegreesMode(svg, width, height, allD1, degree2, onSelect, tierCol
977
981
  }
978
982
  // Path highlight
979
983
  const bridge = bridgeById[d.source_connection_id];
980
- const blake = centerNode;
981
- if (blake && bridge) {
982
- overlay.append('line').attr('x1', blake.x).attr('y1', blake.y).attr('x2', bridge.x).attr('y2', bridge.y)
984
+ const center = centerNode;
985
+ if (center && bridge) {
986
+ overlay.append('line').attr('x1', center.x).attr('y1', center.y).attr('x2', bridge.x).attr('y2', bridge.y)
983
987
  .attr('stroke', '#FFD700').attr('stroke-width', 2).attr('stroke-opacity', 0.6);
984
988
  overlay.append('line').attr('x1', bridge.x).attr('y1', bridge.y).attr('x2', ox).attr('y2', oy)
985
989
  .attr('stroke', '#FF6B35').attr('stroke-width', 2).attr('stroke-opacity', 0.6);