website-xp-phone 1.5.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 (123) hide show
  1. package/.astro/content-assets.mjs +1 -0
  2. package/.astro/content-modules.mjs +1 -0
  3. package/.astro/content.d.ts +199 -0
  4. package/.astro/data-store.json +1 -0
  5. package/.astro/settings.json +8 -0
  6. package/.astro/types.d.ts +1 -0
  7. package/.devcontainer/devcontainer.json +23 -0
  8. package/.env.firebase.example +8 -0
  9. package/.firebaserc +5 -0
  10. package/.gitattributes +2 -0
  11. package/.github/copilot-instructions.md +131 -0
  12. package/.github/dependabot.yml +11 -0
  13. package/.github/workflows/ci.yml +45 -0
  14. package/.github/workflows/deploy-admin.yml +48 -0
  15. package/.github/workflows/static.yml +43 -0
  16. package/.gitmodules +5 -0
  17. package/FIREBASE_SETUP.md +69 -0
  18. package/README.md +63 -0
  19. package/SECURITY.md +11 -0
  20. package/admin/Admin.csproj +7 -0
  21. package/admin/Dockerfile +14 -0
  22. package/admin/Program.cs +8 -0
  23. package/deploy-admin-cloud-run.md +229 -0
  24. package/eslint.config.js +28 -0
  25. package/firebase.json +5 -0
  26. package/firestore.rules +29 -0
  27. package/index.html +52 -0
  28. package/package.json +48 -0
  29. package/pagerts_output.json +1 -0
  30. package/public/5.html +967 -0
  31. package/public/BAHNSCHRIFT.TTF +0 -0
  32. package/public/Beep.ogg +0 -0
  33. package/public/Clippy.png +0 -0
  34. package/public/Layered Network Security Model for Home Networks (slides).pdf +0 -0
  35. package/public/Layered Network Security Model for Home Networks.pdf +0 -0
  36. package/public/TODO.pdf +0 -0
  37. package/public/WoW_Config.zip +3 -0
  38. package/public/addons/energy-swing.txt +1 -0
  39. package/public/addons/lego-yoda-death-readme.txt +11 -0
  40. package/public/addons/lego-yoda-death.mp3 +0 -0
  41. package/public/addons/mana-blast.txt +1 -0
  42. package/public/addons/rage-volley.txt +1 -0
  43. package/public/addons/rueg-cell.txt +1 -0
  44. package/public/addons/rueg-elvui-profile.txt +1 -0
  45. package/public/addons/rueg-grid2.txt +214 -0
  46. package/public/addons/rueg-plater-smol.txt +1 -0
  47. package/public/addons/rueg-plater.txt +1 -0
  48. package/public/addons/rueg-wa-druid.txt +1 -0
  49. package/public/addons/rueg-wa-priest.txt +1 -0
  50. package/public/addons/rueg-wa-rogue.txt +1 -0
  51. package/public/addons/rueg-wa-shaman.txt +1 -0
  52. package/public/addons/rueg-wa-warrior.txt +1 -0
  53. package/public/addons/spirit-smash.txt +1 -0
  54. package/public/avatar.jpg +0 -0
  55. package/public/avatar.png +0 -0
  56. package/public/crunchy_kick.ogg +0 -0
  57. package/public/documents/resume.html +312 -0
  58. package/public/favicon.ico +0 -0
  59. package/public/images/Ateric1.png +0 -0
  60. package/public/images/Ateric2.png +0 -0
  61. package/public/images/equal1.png +0 -0
  62. package/public/images/hyperawareofwhatacatis.png +0 -0
  63. package/public/images/kogg1.png +0 -0
  64. package/public/images/kogg2.png +0 -0
  65. package/public/images/rueg1.png +0 -0
  66. package/public/images/rueg2.png +0 -0
  67. package/public/incorrect_responses.txt +126 -0
  68. package/public/loading.css +51 -0
  69. package/public/resume.pdf +0 -0
  70. package/public/robots.txt +9 -0
  71. package/public/soundcloud.json +57 -0
  72. package/public/spinner.svg +12 -0
  73. package/public/tada.wav +0 -0
  74. package/public/yooh.mp3 +0 -0
  75. package/render.yaml +5 -0
  76. package/scripts/ensure-blog-worktree.mjs +24 -0
  77. package/scripts/generate-soundcloud-json.mjs +198 -0
  78. package/scripts/git-worktree-helper.mjs +122 -0
  79. package/scripts/hoist-dev-blog-local.mjs +149 -0
  80. package/scripts/music-schema.mjs +56 -0
  81. package/scripts/publish-soundcloud-json.mjs +32 -0
  82. package/scripts/sync-music-links-from-worktree.mjs +32 -0
  83. package/src/App.tsx +1500 -0
  84. package/src/addons.json +76 -0
  85. package/src/components/Addon.tsx +223 -0
  86. package/src/components/BlogContent.tsx +103 -0
  87. package/src/components/CopyToClipboardButton.tsx +21 -0
  88. package/src/components/MenuBar.tsx +151 -0
  89. package/src/components/MenuBarWithContext.tsx +6 -0
  90. package/src/components/Modal.tsx +17 -0
  91. package/src/components/MusicContent.tsx +309 -0
  92. package/src/components/NavBarController.tsx +55 -0
  93. package/src/components/NavBarControllerWrapper.tsx +13 -0
  94. package/src/components/Page.tsx +56 -0
  95. package/src/components/SitemapContent.tsx +125 -0
  96. package/src/contacts.json +32 -0
  97. package/src/env.d.ts +13 -0
  98. package/src/lib/assistantStateMachine.ts +80 -0
  99. package/src/lib/audioOverlap.ts +99 -0
  100. package/src/lib/keyboardInputUtils.ts +182 -0
  101. package/src/lib/musicSchema.ts +85 -0
  102. package/src/lib/naggingAssistantClient.ts +241 -0
  103. package/src/lib/resumeAnalytics.ts +163 -0
  104. package/src/main.tsx +35 -0
  105. package/src/pages.json +50 -0
  106. package/src/sections.json +243 -0
  107. package/src/src+addons.zip +3 -0
  108. package/src/styles/main.css +465 -0
  109. package/src/utils/blogSecurity.ts +87 -0
  110. package/src/utils/menuItems.ts +33 -0
  111. package/src/windowing/MinimizedSections.tsx +86 -0
  112. package/src/windowing/Section.tsx +586 -0
  113. package/src/windowing/context.tsx +13 -0
  114. package/src/windowing/hooks.ts +10 -0
  115. package/src/windowing/index.ts +7 -0
  116. package/src/windowing/provider.tsx +74 -0
  117. package/src/windowing/server.ts +3 -0
  118. package/src/windowing/types.ts +33 -0
  119. package/src/windowing/utils.ts +135 -0
  120. package/tests/generate-soundcloud-json.test.mjs +63 -0
  121. package/tests/music-schema.test.mjs +53 -0
  122. package/tsconfig.json +26 -0
  123. package/vite.config.ts +304 -0
package/public/5.html ADDED
@@ -0,0 +1,967 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="generator" content="pandoc">
6
+ <meta name="author" content="Kirill N.">
7
+ <title>Presentation on Sophus Lie, by Kirill N.</title>
8
+ <meta name="apple-mobile-web-app-capable" content="yes">
9
+ <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
10
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui">
11
+ <link rel="stylesheet" href="https://unpkg.com/reveal.js//dist/reset.css">
12
+ <link rel="stylesheet" href="https://unpkg.com/reveal.js//dist/reveal.css">
13
+ <style>
14
+ .reveal .sourceCode { /* see #7635 */
15
+ overflow: visible;
16
+ }
17
+ /* Default styles provided by pandoc.
18
+ ** See https://pandoc.org/MANUAL.html#variables-for-html for config info.
19
+ */
20
+ code{white-space: pre-wrap;}
21
+ span.smallcaps{font-variant: small-caps;}
22
+ div.columns{display: flex; gap: min(4vw, 1.5em);}
23
+ div.column{flex: auto; overflow-x: auto;}
24
+ div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
25
+ /* The extra [class] is a hack that increases specificity enough to
26
+ override a similar rule in reveal.js */
27
+ ul.task-list[class]{list-style: none;}
28
+ ul.task-list li input[type="checkbox"] {
29
+ font-size: inherit;
30
+ width: 0.8em;
31
+ margin: 0 0.8em 0.2em -1.6em;
32
+ vertical-align: middle;
33
+ }
34
+ .display.math{display: block; text-align: center; margin: 0.5rem auto;}
35
+ /* CSS for syntax highlighting */
36
+ html { -webkit-text-size-adjust: 100%; }
37
+ pre > code.sourceCode { white-space: pre; position: relative; }
38
+ pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
39
+ pre > code.sourceCode > span:empty { height: 1.2em; }
40
+ .sourceCode { overflow: visible; }
41
+ code.sourceCode > span { color: inherit; text-decoration: inherit; }
42
+ div.sourceCode { margin: 1em 0; }
43
+ pre.sourceCode { margin: 0; }
44
+ @media screen {
45
+ div.sourceCode { overflow: auto; }
46
+ }
47
+ @media print {
48
+ pre > code.sourceCode { white-space: pre-wrap; }
49
+ pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
50
+ }
51
+ pre.numberSource code
52
+ { counter-reset: source-line 0; }
53
+ pre.numberSource code > span
54
+ { position: relative; left: -4em; counter-increment: source-line; }
55
+ pre.numberSource code > span > a:first-child::before
56
+ { content: counter(source-line);
57
+ position: relative; left: -1em; text-align: right; vertical-align: baseline;
58
+ border: none; display: inline-block;
59
+ -webkit-touch-callout: none; -webkit-user-select: none;
60
+ -khtml-user-select: none; -moz-user-select: none;
61
+ -ms-user-select: none; user-select: none;
62
+ padding: 0 4px; width: 4em;
63
+ color: #aaaaaa;
64
+ }
65
+ pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
66
+ div.sourceCode
67
+ { }
68
+ @media screen {
69
+ pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
70
+ }
71
+ code span.al { color: #ff0000; font-weight: bold; } /* Alert */
72
+ code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
73
+ code span.at { color: #7d9029; } /* Attribute */
74
+ code span.bn { color: #40a070; } /* BaseN */
75
+ code span.bu { color: #008000; } /* BuiltIn */
76
+ code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
77
+ code span.ch { color: #4070a0; } /* Char */
78
+ code span.cn { color: #880000; } /* Constant */
79
+ code span.co { color: #60a0b0; font-style: italic; } /* Comment */
80
+ code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
81
+ code span.do { color: #ba2121; font-style: italic; } /* Documentation */
82
+ code span.dt { color: #902000; } /* DataType */
83
+ code span.dv { color: #40a070; } /* DecVal */
84
+ code span.er { color: #ff0000; font-weight: bold; } /* Error */
85
+ code span.ex { } /* Extension */
86
+ code span.fl { color: #40a070; } /* Float */
87
+ code span.fu { color: #06287e; } /* Function */
88
+ code span.im { color: #008000; font-weight: bold; } /* Import */
89
+ code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
90
+ code span.kw { color: #007020; font-weight: bold; } /* Keyword */
91
+ code span.op { color: #666666; } /* Operator */
92
+ code span.ot { color: #007020; } /* Other */
93
+ code span.pp { color: #bc7a00; } /* Preprocessor */
94
+ code span.sc { color: #4070a0; } /* SpecialChar */
95
+ code span.ss { color: #bb6688; } /* SpecialString */
96
+ code span.st { color: #4070a0; } /* String */
97
+ code span.va { color: #19177c; } /* Variable */
98
+ code span.vs { color: #4070a0; } /* VerbatimString */
99
+ code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
100
+ </style>
101
+ <link rel="stylesheet" href="https://unpkg.com/reveal.js//dist/theme/serif.css" id="theme">
102
+ <style>
103
+ .slides {
104
+ font-size: 0.75em;
105
+ }
106
+ .reveal ul {
107
+ display: block;
108
+ }
109
+ .reveal ol {
110
+ display: block;
111
+ }
112
+
113
+ img {
114
+ max-height: 350px !important;
115
+ }
116
+
117
+ figcaption {
118
+ font-size: 0.6em !important;
119
+ font-style: italic !important;
120
+ }
121
+
122
+ .subtitle {
123
+ font-style: italic !important;
124
+ }
125
+
126
+ .date {
127
+ font-size: 0.75em !important;
128
+ }
129
+ </style>
130
+ </head>
131
+ <body>
132
+ <div class="reveal">
133
+ <div class="slides">
134
+
135
+ <section id="title-slide">
136
+ <h1 class="title">Presentation on Sophus Lie, by Kirill N.</h1>
137
+ <p class="author">Kirill N.</p>
138
+ </section>
139
+
140
+ <section id="my-slide" class="slide level1">
141
+ <h1>My Slide</h1>
142
+ <!-- \begin{frame}
143
+ \setbeamercolor{background}{bg=orange}
144
+
145
+ \color{white}
146
+ This text is white on an orange background.
147
+
148
+ \color{black}
149
+ This text is now black, but the background is still orange.
150
+
151
+ \setbeamercolor{background}{bg=white} % Reset to default background
152
+
153
+ This text is black on a white background.
154
+ \end{frame} -->
155
+ <figure>
156
+ <img data-src="./images/1-sophus-lie.png" alt="cat_speaking_wisdom" />
157
+ <figcaption aria-hidden="true">cat_speaking_wisdom</figcaption>
158
+ </figure>
159
+ <p><strong>:You:</strong></p>
160
+ <p>additional secure model stored on my local network can you please
161
+ help me show my friend how to secure his network</p>
162
+ </section>
163
+ <section class="slide level1">
164
+
165
+ <p><strong>THE AI Model:sec.intro:latest:</strong></p>
166
+ <p>Okay, let’s create a layered security model for your friend’s local
167
+ network, focusing on practical steps. I’ll present this as if
168
+ <em>you</em> are explaining it to your friend. I’ll categorize it for
169
+ clarity and include a “Threat Level” assessment for each step to show
170
+ its impact. I’ll also indicate the level of technical skill needed.</p>
171
+ <p><strong>Important Disclaimer:</strong> No network is 100% secure.
172
+ This model aims to significantly reduce risk, but diligence is key.</p>
173
+ <p><strong>“Okay, so let’s talk about securing your network. It’s not
174
+ about being paranoid, it’s about being prepared. We’ll build this in
175
+ layers.”</strong></p>
176
+ <p><strong>I. Basic Perimeter Security (Threat Level: Medium, Skill
177
+ Level: Beginner)</strong></p>
178
+ <ul>
179
+ <li><strong>Change the Default Router Password:</strong>
180
+ <em>Seriously</em>. This is the biggest mistake people make. The default
181
+ password is publicly known. (Skill: Beginner, Time: 5 minutes). “Your
182
+ router has a default password, like ‘admin’ or ‘password’. We
183
+ <em>have</em> to change that to something strong and unique.”</li>
184
+ <li><strong>Enable Router Firewall:</strong> Most routers have a
185
+ built-in firewall. Make sure it’s enabled. (Skill: Beginner, Time: 2
186
+ minutes). “The firewall acts like a gatekeeper, blocking unwanted
187
+ traffic.”</li>
188
+ <li><strong>Enable WPA3 Encryption (or WPA2 if WPA3 isn’t
189
+ supported):</strong> This secures your Wi-Fi network. (Skill: Beginner,
190
+ Time: 5 minutes). “This scrambles the data sent over your Wi-Fi, so
191
+ someone nearby can’t easily read it.”</li>
192
+ <li><strong>Hide SSID (Optional):</strong> Hiding the network name
193
+ (SSID) makes it slightly harder to find, but it’s not a major security
194
+ measure. (Skill: Beginner, Time: 2 minutes). “This just makes your
195
+ network a little less visible, but it doesn’t stop a determined
196
+ attacker.”</li>
197
+ </ul>
198
+ <p><strong>II. Network Segmentation (Threat Level: Medium, Skill Level:
199
+ Intermediate)</strong></p>
200
+ <ul>
201
+ <li><strong>Guest Network:</strong> Create a separate guest network for
202
+ visitors. This isolates them from your main network. (Skill:
203
+ Intermediate, Time: 15 minutes). “This means if someone’s phone gets
204
+ infected, it won’t be able to access your personal files.”</li>
205
+ <li><strong>IoT Network (Recommended):</strong> If you have smart home
206
+ devices (cameras, thermostats, etc.), put them on a separate network.
207
+ These devices often have weak security. (Skill: Intermediate, Time: 30
208
+ minutes - may require a more advanced router). “Smart devices are often
209
+ easy targets for hackers. Isolating them protects your main
210
+ network.”</li>
211
+ <li><strong>VLANs (Advanced):</strong> If you’re comfortable with
212
+ networking, consider using VLANs (Virtual LANs) to further segment your
213
+ network. (Skill: Advanced).</li>
214
+ </ul>
215
+ <p><strong>III. Device Security (Threat Level: High, Skill Level:
216
+ Intermediate/Advanced)</strong></p>
217
+ <ul>
218
+ <li><strong>Firewall on Each Computer:</strong> Enable the built-in
219
+ firewall on each computer. (Skill: Beginner, Time: 5 minutes per
220
+ computer).</li>
221
+ <li><strong>Antivirus/Anti-Malware Software:</strong> Install and keep
222
+ updated antivirus/anti-malware software on each computer. (Skill:
223
+ Beginner, Time: Varies).</li>
224
+ <li><strong>Keep Software Updated:</strong> Regularly update your
225
+ operating systems, web browsers, and other software. (Skill: Beginner,
226
+ Time: Ongoing). “Updates often include security patches that fix
227
+ vulnerabilities.”</li>
228
+ <li><strong>Strong Passwords &amp; Password Manager:</strong> Use
229
+ strong, unique passwords for each account and consider using a password
230
+ manager. (Skill: Intermediate).</li>
231
+ <li><strong>Enable Two-Factor Authentication (2FA):</strong> Whenever
232
+ possible, enable 2FA on your accounts. (Skill: Intermediate).</li>
233
+ </ul>
234
+ <p><strong>IV. Monitoring &amp; Detection (Threat Level: Medium, Skill
235
+ Level: Intermediate/Advanced)</strong></p>
236
+ <ul>
237
+ <li><strong>Router Logs:</strong> Regularly check your router logs for
238
+ suspicious activity. (Skill: Intermediate).</li>
239
+ <li><strong>Network Monitoring Tools:</strong> Consider using network
240
+ monitoring tools to detect unusual traffic patterns. (Skill: Advanced).
241
+ (Examples: Wireshark, SolarWinds, PRTG – these can be complex to set
242
+ up.)</li>
243
+ <li><strong>Intrusion Detection/Prevention System (IDS/IPS):</strong>
244
+ For more advanced protection, consider an IDS/IPS. (Skill:
245
+ Advanced).</li>
246
+ </ul>
247
+ <p><strong>V. Physical Security (Threat Level: Low/Medium, Skill Level:
248
+ Beginner)</strong></p>
249
+ <ul>
250
+ <li><strong>Secure Router:</strong> Physically secure your router to
251
+ prevent unauthorized access. (Skill: Beginner).</li>
252
+ <li><strong>Wi-Fi Signal Range:</strong> Limit the range of your Wi-Fi
253
+ signal to reduce the risk of unauthorized access from outside your home.
254
+ (Skill: Intermediate).</li>
255
+ </ul>
256
+ <p><strong>“Let’s prioritize. Start with changing the router password,
257
+ enabling the firewall, updating software, and using strong passwords.
258
+ Then we can look at network segmentation and more advanced security
259
+ measures. The key is to be proactive and stay vigilant.”</strong></p>
260
+ <p><strong>Resources:</strong></p>
261
+ <ul>
262
+ <li><strong>StaySafeOnline.org:</strong> <a
263
+ href="https://staysafeonline.org/">https://staysafeonline.org/</a></li>
264
+ <li><strong>National Cyber Security Centre (NCSC - UK):</strong> <a
265
+ href="https://www.ncsc.gov.uk/">https://www.ncsc.gov.uk/</a></li>
266
+ <li><strong>Federal Trade Commission (FTC):</strong> <a
267
+ href="https://www.ftc.gov/">https://www.ftc.gov/</a></li>
268
+ </ul>
269
+ <p><strong>To help your friend even further, you can offer
270
+ to:</strong></p>
271
+ <ul>
272
+ <li>Help them set up their router and firewall.</li>
273
+ <li>Help them choose and install antivirus software.</li>
274
+ <li>Help them create strong passwords and set up a password
275
+ manager.</li>
276
+ <li>Regularly check their security settings and provide updates.</li>
277
+ </ul>
278
+ <p>Remember to emphasize that security is an ongoing process, not a
279
+ one-time fix. Constant vigilance and proactive measures are essential to
280
+ protect their network and data.</p>
281
+ </section>
282
+ <section class="slide level1">
283
+
284
+ <p><strong>:You:</strong></p>
285
+ <p>how can i accept the ngrok access token into my AI client from remote
286
+ workstation, with examples please</p>
287
+ </section>
288
+ <section class="slide level1">
289
+
290
+ <p><strong>:sec.intro:latest:</strong></p>
291
+ <p>Okay, let’s break down how to securely accept an ngrok access token
292
+ from a remote workstation into your AI client. This involves a
293
+ combination of secure communication, token storage, and error handling.
294
+ I’ll present this with pseudocode and Python examples, as Python is
295
+ often used for AI applications and scripting.</p>
296
+ <p><strong>Core Concepts:</strong></p>
297
+ <ul>
298
+ <li><strong>Secure Communication:</strong> Use SSH or a similar secure
299
+ protocol to transfer the token. Avoid sending the token in plain text
300
+ over the network.</li>
301
+ <li><strong>Key Exchange (Optional but Recommended):</strong> For added
302
+ security, use key exchange to establish a secure connection before
303
+ transferring the token.</li>
304
+ <li><strong>Token Storage:</strong> Store the token securely in a
305
+ configuration file, environment variable, or dedicated secret management
306
+ system. <em>Never</em> hardcode the token directly into your AI client’s
307
+ code.</li>
308
+ <li><strong>Error Handling:</strong> Implement robust error handling to
309
+ gracefully handle connection errors, invalid tokens, or other
310
+ issues.</li>
311
+ </ul>
312
+ <p><strong>1. Remote Workstation (Token Provider):</strong></p>
313
+ <p>The remote workstation will be responsible for obtaining the ngrok
314
+ access token (e.g., through the ngrok CLI or web interface) and securely
315
+ sending it to the AI client.</p>
316
+ <div class="sourceCode" id="cb1"><pre
317
+ class="sourceCode python"><code class="sourceCode python"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Remote Workstation - token_provider.py</span></span>
318
+ <span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> subprocess</span>
319
+ <span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> paramiko <span class="co"># For SSH</span></span>
320
+ <span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a></span>
321
+ <span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> get_ngrok_token():</span>
322
+ <span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a> <span class="co">&quot;&quot;&quot;Retrieves the ngrok access token (replace with your method)&quot;&quot;&quot;</span></span>
323
+ <span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a> <span class="cf">try</span>:</span>
324
+ <span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a> result <span class="op">=</span> subprocess.run([<span class="st">&#39;ngrok&#39;</span>, <span class="st">&#39;config&#39;</span>, <span class="st">&#39;add-authtoken&#39;</span>, <span class="st">&#39;YOUR_AUTHTOKEN&#39;</span>], capture_output<span class="op">=</span><span class="va">True</span>, text<span class="op">=</span><span class="va">True</span>, check<span class="op">=</span><span class="va">True</span>)</span>
325
+ <span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a> <span class="co"># Replace &#39;YOUR_AUTHTOKEN&#39; with the actual token</span></span>
326
+ <span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> <span class="st">&quot;YOUR_AUTHTOKEN&quot;</span> <span class="co"># Or read from config file</span></span>
327
+ <span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a> <span class="cf">except</span> subprocess.CalledProcessError <span class="im">as</span> e:</span>
328
+ <span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f&quot;Error getting ngrok token: </span><span class="sc">{</span>e<span class="sc">}</span><span class="ss">&quot;</span>)</span>
329
+ <span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> <span class="va">None</span></span>
330
+ <span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a></span>
331
+ <span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> send_token_via_ssh(token, ssh_host, ssh_user):</span>
332
+ <span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a> <span class="co">&quot;&quot;&quot;Sends the ngrok token to the AI client via SSH.&quot;&quot;&quot;</span></span>
333
+ <span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a> <span class="cf">try</span>:</span>
334
+ <span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a> ssh <span class="op">=</span> paramiko.SSHClient()</span>
335
+ <span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a> ssh.set_missing_host_key_policy(paramiko.AutoAddHostKeyPolicy()) <span class="co">#Be cautious in production</span></span>
336
+ <span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a> ssh.<span class="ex">connect</span>(ssh_host, username<span class="op">=</span>ssh_user)</span>
337
+ <span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a></span>
338
+ <span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a> <span class="co"># Command to execute on the AI client to store the token (example)</span></span>
339
+ <span id="cb1-23"><a href="#cb1-23" aria-hidden="true" tabindex="-1"></a> command <span class="op">=</span> <span class="ss">f&quot;echo &#39;</span><span class="sc">{</span>token<span class="sc">}</span><span class="ss">&#39; &gt; /path/to/ai_client/ngrok_token.txt&quot;</span></span>
340
+ <span id="cb1-24"><a href="#cb1-24" aria-hidden="true" tabindex="-1"></a> stdin, stdout, stderr <span class="op">=</span> ssh.exec_command(command)</span>
341
+ <span id="cb1-25"><a href="#cb1-25" aria-hidden="true" tabindex="-1"></a> output <span class="op">=</span> stdout.read().decode()</span>
342
+ <span id="cb1-26"><a href="#cb1-26" aria-hidden="true" tabindex="-1"></a> error <span class="op">=</span> stderr.read().decode()</span>
343
+ <span id="cb1-27"><a href="#cb1-27" aria-hidden="true" tabindex="-1"></a></span>
344
+ <span id="cb1-28"><a href="#cb1-28" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> error:</span>
345
+ <span id="cb1-29"><a href="#cb1-29" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f&quot;Error sending token: </span><span class="sc">{</span>error<span class="sc">}</span><span class="ss">&quot;</span>)</span>
346
+ <span id="cb1-30"><a href="#cb1-30" aria-hidden="true" tabindex="-1"></a> <span class="cf">else</span>:</span>
347
+ <span id="cb1-31"><a href="#cb1-31" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f&quot;Token sent successfully: </span><span class="sc">{</span>output<span class="sc">}</span><span class="ss">&quot;</span>)</span>
348
+ <span id="cb1-32"><a href="#cb1-32" aria-hidden="true" tabindex="-1"></a></span>
349
+ <span id="cb1-33"><a href="#cb1-33" aria-hidden="true" tabindex="-1"></a> ssh.close()</span>
350
+ <span id="cb1-34"><a href="#cb1-34" aria-hidden="true" tabindex="-1"></a> <span class="cf">except</span> <span class="pp">Exception</span> <span class="im">as</span> e:</span>
351
+ <span id="cb1-35"><a href="#cb1-35" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f&quot;SSH connection error: </span><span class="sc">{</span>e<span class="sc">}</span><span class="ss">&quot;</span>)</span>
352
+ <span id="cb1-36"><a href="#cb1-36" aria-hidden="true" tabindex="-1"></a></span>
353
+ <span id="cb1-37"><a href="#cb1-37" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">&quot;__main__&quot;</span>:</span>
354
+ <span id="cb1-38"><a href="#cb1-38" aria-hidden="true" tabindex="-1"></a> token <span class="op">=</span> get_ngrok_token()</span>
355
+ <span id="cb1-39"><a href="#cb1-39" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> token:</span>
356
+ <span id="cb1-40"><a href="#cb1-40" aria-hidden="true" tabindex="-1"></a> ssh_host <span class="op">=</span> <span class="st">&quot;your_ai_client_ip_address&quot;</span> <span class="co"># Replace with the IP address of the AI client</span></span>
357
+ <span id="cb1-41"><a href="#cb1-41" aria-hidden="true" tabindex="-1"></a> ssh_user <span class="op">=</span> <span class="st">&quot;your_ai_client_username&quot;</span> <span class="co"># Replace with the AI client&#39;s username</span></span>
358
+ <span id="cb1-42"><a href="#cb1-42" aria-hidden="true" tabindex="-1"></a> send_token_via_ssh(token, ssh_host, ssh_user)</span></code></pre></div>
359
+ <p><strong>2. AI Client (Token Receiver):</strong></p>
360
+ <p>The AI client will be responsible for receiving the token and storing
361
+ it securely.</p>
362
+ <div class="sourceCode" id="cb2"><pre
363
+ class="sourceCode python"><code class="sourceCode python"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="co"># AI Client - ai_client.py</span></span>
364
+ <span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> os</span>
365
+ <span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a></span>
366
+ <span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> get_ngrok_token():</span>
367
+ <span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a> <span class="co">&quot;&quot;&quot;Retrieves the ngrok token from a secure location.&quot;&quot;&quot;</span></span>
368
+ <span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a> token_file <span class="op">=</span> <span class="st">&quot;/path/to/ai_client/ngrok_token.txt&quot;</span></span>
369
+ <span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a> <span class="cf">try</span>:</span>
370
+ <span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a> <span class="cf">with</span> <span class="bu">open</span>(token_file, <span class="st">&quot;r&quot;</span>) <span class="im">as</span> f:</span>
371
+ <span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a> token <span class="op">=</span> f.read().strip()</span>
372
+ <span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> token</span>
373
+ <span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a> <span class="cf">except</span> <span class="pp">FileNotFoundError</span>:</span>
374
+ <span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">&quot;ngrok token file not found.&quot;</span>)</span>
375
+ <span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> <span class="va">None</span></span>
376
+ <span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a> <span class="cf">except</span> <span class="pp">Exception</span> <span class="im">as</span> e:</span>
377
+ <span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f&quot;Error reading token: </span><span class="sc">{</span>e<span class="sc">}</span><span class="ss">&quot;</span>)</span>
378
+ <span id="cb2-16"><a href="#cb2-16" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> <span class="va">None</span></span>
379
+ <span id="cb2-17"><a href="#cb2-17" aria-hidden="true" tabindex="-1"></a></span>
380
+ <span id="cb2-18"><a href="#cb2-18" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> main():</span>
381
+ <span id="cb2-19"><a href="#cb2-19" aria-hidden="true" tabindex="-1"></a> ngrok_token <span class="op">=</span> get_ngrok_token()</span>
382
+ <span id="cb2-20"><a href="#cb2-20" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> ngrok_token:</span>
383
+ <span id="cb2-21"><a href="#cb2-21" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f&quot;ngrok token: </span><span class="sc">{</span>ngrok_token<span class="sc">}</span><span class="ss">&quot;</span>)</span>
384
+ <span id="cb2-22"><a href="#cb2-22" aria-hidden="true" tabindex="-1"></a> <span class="co"># Use the ngrok token in your AI application</span></span>
385
+ <span id="cb2-23"><a href="#cb2-23" aria-hidden="true" tabindex="-1"></a> <span class="cf">else</span>:</span>
386
+ <span id="cb2-24"><a href="#cb2-24" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="st">&quot;ngrok token not found. Please ensure it has been sent from the remote workstation.&quot;</span>)</span>
387
+ <span id="cb2-25"><a href="#cb2-25" aria-hidden="true" tabindex="-1"></a></span>
388
+ <span id="cb2-26"><a href="#cb2-26" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="va">__name__</span> <span class="op">==</span> <span class="st">&quot;__main__&quot;</span>:</span>
389
+ <span id="cb2-27"><a href="#cb2-27" aria-hidden="true" tabindex="-1"></a> main()</span></code></pre></div>
390
+ <p><strong>Explanation:</strong></p>
391
+ <ol type="1">
392
+ <li><strong>Remote Workstation (token_provider.py):</strong>
393
+ <ul>
394
+ <li><code>get_ngrok_token()</code>: This function retrieves the ngrok
395
+ token. You’ll need to adapt this to your specific method of obtaining
396
+ the token (e.g., reading from a configuration file, prompting the user,
397
+ or querying an API).</li>
398
+ <li><code>send_token_via_ssh()</code>: This function connects to the AI
399
+ client via SSH. It then executes a command on the AI client to write the
400
+ token to a file.</li>
401
+ </ul></li>
402
+ <li><strong>AI Client (ai_client.py):</strong>
403
+ <ul>
404
+ <li><code>get_ngrok_token()</code>: This function reads the token from
405
+ the file where it was written by the SSH command.</li>
406
+ <li><code>main()</code>: This function calls
407
+ <code>get_ngrok_token()</code> and uses the token in your AI
408
+ application.</li>
409
+ </ul></li>
410
+ </ol>
411
+ <p><strong>Security Considerations:</strong></p>
412
+ <ul>
413
+ <li><strong>SSH Keys:</strong> Use SSH key-based authentication instead
414
+ of passwords for improved security.</li>
415
+ <li><strong>File Permissions:</strong> Restrict access to the
416
+ <code>ngrok_token.txt</code> file to only the user running the AI
417
+ client.</li>
418
+ <li><strong>Encryption:</strong> Consider encrypting the token file or
419
+ using a more secure storage mechanism (e.g., a secret management system
420
+ like HashiCorp Vault).</li>
421
+ <li><strong>Network Security:</strong> Ensure that the network
422
+ connection between the remote workstation and the AI client is secure
423
+ (e.g., use a VPN).</li>
424
+ <li><strong>Token Rotation:</strong> Regularly rotate the ngrok token to
425
+ minimize the impact of a potential compromise.</li>
426
+ <li><strong>Error Handling:</strong> Implement robust error handling to
427
+ prevent sensitive information from being leaked in error messages.</li>
428
+ </ul>
429
+ <p><strong>Alternative Approaches:</strong></p>
430
+ <ul>
431
+ <li><strong>Environment Variables:</strong> You could set an environment
432
+ variable on the AI client instead of writing to a file.</li>
433
+ <li><strong>Secret Management System:</strong> Use a dedicated secret
434
+ management system (e.g., HashiCorp Vault) to store and retrieve the
435
+ token. This is the most secure approach, but it requires more
436
+ setup.</li>
437
+ <li><strong>API Endpoint (Less Secure):</strong> You could create a
438
+ simple API endpoint on the AI client to receive the token. However, this
439
+ is less secure than using SSH or a secret management system, as it
440
+ exposes the token to potential network attacks.</li>
441
+ </ul>
442
+ <p>This detailed explanation and example code should give you a solid
443
+ foundation for securely accepting the ngrok access token into your AI
444
+ client from a remote workstation. Remember to prioritize security and
445
+ adapt the code to your specific needs and environment.</p>
446
+ </section>
447
+ <section class="slide level1">
448
+
449
+ <p><strong>:You:</strong></p>
450
+ <p>we wish to imprint the device access token</p>
451
+ </section>
452
+ <section class="slide level1">
453
+
454
+ <p><strong>:qwen2.5-coder:14b:</strong></p>
455
+ <p>Imprinting a device access token involves securely embedding or
456
+ storing it on a device so that it can be used for authentication and
457
+ authorization purposes. The goal is to ensure that the token is both
458
+ secure and easily accessible by your application. Below are various
459
+ methods to achieve this, each with its own advantages and
460
+ trade-offs.</p>
461
+ <h3 id="environment-variables">1. <strong>Environment
462
+ Variables</strong></h3>
463
+ <p><strong>Advantages:</strong> - Secure (not hardcoded in code). - Easy
464
+ to manage. - Works across different environments (development, staging,
465
+ production).</p>
466
+ <p><strong>Disadvantages:</strong> - Not persistent if the environment
467
+ is restarted or changes. - Limited to single-token use unless managed
468
+ with scripts.</p>
469
+ <p><strong>Example Implementation:</strong></p>
470
+ <div class="sourceCode" id="cb3"><pre
471
+ class="sourceCode bash"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Set environment variable (Linux/Mac)</span></span>
472
+ <span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="bu">export</span> <span class="va">DEVICE_ACCESS_TOKEN</span><span class="op">=</span><span class="st">&quot;your_token_here&quot;</span></span>
473
+ <span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a></span>
474
+ <span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="co"># Use in your application (Python example)</span></span>
475
+ <span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="ex">import</span> os</span>
476
+ <span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a></span>
477
+ <span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a><span class="ex">DEVICE_ACCESS_TOKEN</span> = os.getenv<span class="er">(</span><span class="st">&quot;DEVICE_ACCESS_TOKEN&quot;</span><span class="kw">)</span></span>
478
+ <span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="ex">not</span> DEVICE_ACCESS_TOKEN:</span>
479
+ <span id="cb3-9"><a href="#cb3-9" aria-hidden="true" tabindex="-1"></a> <span class="ex">raise</span> ValueError<span class="er">(</span><span class="st">&quot;DEVICE_ACCESS_TOKEN environment variable is not set.&quot;</span><span class="kw">)</span></span></code></pre></div>
480
+ <h3 id="configuration-files">2. <strong>Configuration
481
+ Files</strong></h3>
482
+ <p><strong>Advantages:</strong> - Persistent storage. - Works well for
483
+ configurations.</p>
484
+ <p><strong>Disadvantages:</strong> - Tokens are stored in plain text
485
+ unless encrypted. - Vulnerable if the configuration file permissions are
486
+ misconfigured.</p>
487
+ <p><strong>Example Implementation (JSON File):</strong></p>
488
+ <div class="sourceCode" id="cb4"><pre
489
+ class="sourceCode json"><code class="sourceCode json"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="er">//</span> <span class="er">config.json</span></span>
490
+ <span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="fu">{</span></span>
491
+ <span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a> <span class="dt">&quot;device_access_token&quot;</span><span class="fu">:</span> <span class="st">&quot;your_token_here&quot;</span></span>
492
+ <span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="fu">}</span></span></code></pre></div>
493
+ <div class="sourceCode" id="cb5"><pre
494
+ class="sourceCode python"><code class="sourceCode python"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Python example to read from JSON</span></span>
495
+ <span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> json</span>
496
+ <span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a></span>
497
+ <span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="cf">with</span> <span class="bu">open</span>(<span class="st">&#39;config.json&#39;</span>, <span class="st">&#39;r&#39;</span>) <span class="im">as</span> f:</span>
498
+ <span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a> config <span class="op">=</span> json.load(f)</span>
499
+ <span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a></span>
500
+ <span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a>DEVICE_ACCESS_TOKEN <span class="op">=</span> config.get(<span class="st">&quot;device_access_token&quot;</span>)</span>
501
+ <span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="kw">not</span> DEVICE_ACCESS_TOKEN:</span>
502
+ <span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a> <span class="cf">raise</span> <span class="pp">ValueError</span>(<span class="st">&quot;Device access token not found in configuration.&quot;</span>)</span></code></pre></div>
503
+ <h3 id="secure-storage-mechanisms">3. <strong>Secure Storage
504
+ Mechanisms</strong></h3>
505
+ <p><strong>Advantages:</strong> - Encryption of stored data. - Better
506
+ security practices.</p>
507
+ <p><strong>Disadvantages:</strong> - More complex to implement and
508
+ manage. - Requires additional dependencies.</p>
509
+ <p><strong>Example Implementation (Using <code>cryptography</code>
510
+ Library for Encryption):</strong></p>
511
+ <div class="sourceCode" id="cb6"><pre
512
+ class="sourceCode python"><code class="sourceCode python"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Install cryptography library if not already installed</span></span>
513
+ <span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="co"># pip install cryptography</span></span>
514
+ <span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a></span>
515
+ <span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> cryptography.fernet <span class="im">import</span> Fernet</span>
516
+ <span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a></span>
517
+ <span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a><span class="co"># Generate a key or use an existing one</span></span>
518
+ <span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a>key <span class="op">=</span> Fernet.generate_key()</span>
519
+ <span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a>cipher_suite <span class="op">=</span> Fernet(key)</span>
520
+ <span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a></span>
521
+ <span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a><span class="co"># Encrypt the token</span></span>
522
+ <span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a>token <span class="op">=</span> <span class="st">&quot;your_token_here&quot;</span></span>
523
+ <span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a>encrypted_token <span class="op">=</span> cipher_suite.encrypt(token.encode())</span>
524
+ <span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a></span>
525
+ <span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a><span class="co"># Save the encrypted token to a file</span></span>
526
+ <span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a><span class="cf">with</span> <span class="bu">open</span>(<span class="st">&#39;secure_token.enc&#39;</span>, <span class="st">&#39;wb&#39;</span>) <span class="im">as</span> f:</span>
527
+ <span id="cb6-16"><a href="#cb6-16" aria-hidden="true" tabindex="-1"></a> f.write(encrypted_token)</span>
528
+ <span id="cb6-17"><a href="#cb6-17" aria-hidden="true" tabindex="-1"></a> <span class="co"># Also save the key securely, e.g., in a separate secure location</span></span>
529
+ <span id="cb6-18"><a href="#cb6-18" aria-hidden="true" tabindex="-1"></a></span>
530
+ <span id="cb6-19"><a href="#cb6-19" aria-hidden="true" tabindex="-1"></a><span class="co"># Decrypt the token when needed</span></span>
531
+ <span id="cb6-20"><a href="#cb6-20" aria-hidden="true" tabindex="-1"></a><span class="cf">with</span> <span class="bu">open</span>(<span class="st">&#39;secure_token.enc&#39;</span>, <span class="st">&#39;rb&#39;</span>) <span class="im">as</span> f:</span>
532
+ <span id="cb6-21"><a href="#cb6-21" aria-hidden="true" tabindex="-1"></a> encrypted_token <span class="op">=</span> f.read()</span>
533
+ <span id="cb6-22"><a href="#cb6-22" aria-hidden="true" tabindex="-1"></a></span>
534
+ <span id="cb6-23"><a href="#cb6-23" aria-hidden="true" tabindex="-1"></a>decrypted_token <span class="op">=</span> cipher_suite.decrypt(encrypted_token).decode()</span>
535
+ <span id="cb6-24"><a href="#cb6-24" aria-hidden="true" tabindex="-1"></a>DEVICE_ACCESS_TOKEN <span class="op">=</span> decrypted_token</span></code></pre></div>
536
+ <h3 id="secrets-management-tools">4. <strong>Secrets Management
537
+ Tools</strong></h3>
538
+ <p><strong>Advantages:</strong> - Centralized management. - Secure
539
+ storage and retrieval. - Integrates with CI/CD pipelines.</p>
540
+ <p><strong>Disadvantages:</strong> - Requires setup and integration. -
541
+ Additional cost for some services.</p>
542
+ <p><strong>Example Implementation (Using AWS Secrets Manager):</strong>
543
+ 1. Store the token in AWS Secrets Manager. 2. Use Boto3 to retrieve the
544
+ token in your application.</p>
545
+ <div class="sourceCode" id="cb7"><pre
546
+ class="sourceCode python"><code class="sourceCode python"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="co"># Install boto3 library if not already installed</span></span>
547
+ <span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="co"># pip install boto3</span></span>
548
+ <span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a></span>
549
+ <span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> boto3</span>
550
+ <span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a></span>
551
+ <span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a><span class="kw">def</span> get_device_access_token():</span>
552
+ <span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a> secret_name <span class="op">=</span> <span class="st">&quot;your_secret_name&quot;</span></span>
553
+ <span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a> region_name <span class="op">=</span> <span class="st">&quot;your_region&quot;</span></span>
554
+ <span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a></span>
555
+ <span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a> session <span class="op">=</span> boto3.session.Session()</span>
556
+ <span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a> client <span class="op">=</span> session.client(</span>
557
+ <span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a> service_name<span class="op">=</span><span class="st">&#39;secretsmanager&#39;</span>,</span>
558
+ <span id="cb7-13"><a href="#cb7-13" aria-hidden="true" tabindex="-1"></a> region_name<span class="op">=</span>region_name</span>
559
+ <span id="cb7-14"><a href="#cb7-14" aria-hidden="true" tabindex="-1"></a> )</span>
560
+ <span id="cb7-15"><a href="#cb7-15" aria-hidden="true" tabindex="-1"></a></span>
561
+ <span id="cb7-16"><a href="#cb7-16" aria-hidden="true" tabindex="-1"></a> <span class="cf">try</span>:</span>
562
+ <span id="cb7-17"><a href="#cb7-17" aria-hidden="true" tabindex="-1"></a> get_secret_value_response <span class="op">=</span> client.get_secret_value(SecretId<span class="op">=</span>secret_name)</span>
563
+ <span id="cb7-18"><a href="#cb7-18" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> <span class="st">&#39;SecretString&#39;</span> <span class="kw">in</span> get_secret_value_response:</span>
564
+ <span id="cb7-19"><a href="#cb7-19" aria-hidden="true" tabindex="-1"></a> secret <span class="op">=</span> get_secret_value_response[<span class="st">&#39;SecretString&#39;</span>]</span>
565
+ <span id="cb7-20"><a href="#cb7-20" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> json.loads(secret).get(<span class="st">&quot;device_access_token&quot;</span>)</span>
566
+ <span id="cb7-21"><a href="#cb7-21" aria-hidden="true" tabindex="-1"></a> <span class="cf">except</span> <span class="pp">Exception</span> <span class="im">as</span> e:</span>
567
+ <span id="cb7-22"><a href="#cb7-22" aria-hidden="true" tabindex="-1"></a> <span class="cf">raise</span> <span class="pp">ValueError</span>(<span class="ss">f&quot;Error retrieving device access token: </span><span class="sc">{</span>e<span class="sc">}</span><span class="ss">&quot;</span>)</span>
568
+ <span id="cb7-23"><a href="#cb7-23" aria-hidden="true" tabindex="-1"></a></span>
569
+ <span id="cb7-24"><a href="#cb7-24" aria-hidden="true" tabindex="-1"></a>DEVICE_ACCESS_TOKEN <span class="op">=</span> get_device_access_token()</span></code></pre></div>
570
+ <h3 id="hardware-security-modules-hsm">5. <strong>Hardware Security
571
+ Modules (HSM)</strong></h3>
572
+ <p><strong>Advantages:</strong> - High-level security for storing
573
+ sensitive data. - Can perform cryptographic operations without exposing
574
+ keys.</p>
575
+ <p><strong>Disadvantages:</strong> - Expensive and complex to set up. -
576
+ Not suitable for all applications.</p>
577
+ <p><strong>Example Implementation (High-Level Concept):</strong> 1. Use
578
+ an HSM to securely store the token. 2. Retrieve and use the token
579
+ through secure APIs provided by the HSM vendor.</p>
580
+ <h3 id="best-practices"><strong>Best Practices</strong></h3>
581
+ <ol type="1">
582
+ <li><strong>Use Strong, Unique Tokens:</strong>
583
+ <ul>
584
+ <li>Ensure tokens are long, random, and unique to prevent unauthorized
585
+ access.</li>
586
+ </ul></li>
587
+ <li><strong>Restrict Token Access:</strong>
588
+ <ul>
589
+ <li>Limit who can read or write the token.</li>
590
+ <li>Use file permissions (e.g., <code>chmod 600</code>) to restrict
591
+ access to the token storage location.</li>
592
+ </ul></li>
593
+ <li><strong>Rotate Tokens Regularly:</strong>
594
+ <ul>
595
+ <li>Implement a rotation policy to minimize the impact of potential
596
+ compromises.</li>
597
+ </ul></li>
598
+ <li><strong>Log and Monitor Token Usage:</strong>
599
+ <ul>
600
+ <li>Keep logs of when tokens are accessed or modified.</li>
601
+ <li>Set up monitoring alerts for unusual activity.</li>
602
+ </ul></li>
603
+ <li><strong>Use HTTPS for Communication:</strong>
604
+ <ul>
605
+ <li>If communicating with services that require authentication, ensure
606
+ that all communication is encrypted using HTTPS to prevent
607
+ interception.</li>
608
+ </ul></li>
609
+ </ol>
610
+ <h3 id="conclusion"><strong>Conclusion</strong></h3>
611
+ <p>The choice of method depends on your specific requirements, such as
612
+ the level of security needed, ease of management, and technical
613
+ expertise available. For most applications, environment variables or
614
+ configuration files secured with encryption are a good balance between
615
+ security and convenience. If you require higher levels of security,
616
+ consider using secrets management tools or hardware security
617
+ modules.</p>
618
+ <p>If you need further assistance with any specific implementation or
619
+ have additional questions, feel free to ask!</p>
620
+ </section>
621
+ <section class="slide level1">
622
+
623
+ <p><strong>:You:</strong></p>
624
+ <p>setting custom header on a msty connection or vscode continue dev
625
+ ext</p>
626
+ </section>
627
+ <section class="slide level1">
628
+
629
+ <p><strong>:qwen3-vl:8b:</strong></p>
630
+ </section>
631
+ <section class="slide level1">
632
+
633
+ <p><strong>:You:</strong></p>
634
+ <p>please continue</p>
635
+ </section>
636
+ <section class="slide level1">
637
+
638
+ <p><strong>:gemma3:27b:</strong></p>
639
+ <p>Okay, let’s dive into setting custom headers with <code>msty</code>
640
+ connections and VS Code’s Remote - SSH extension. There are a couple of
641
+ different methods depending on <em>where</em> you need the headers
642
+ applied and the context of the connection. I’ll cover the most common
643
+ scenarios and provide detailed instructions.</p>
644
+ <p><strong>Understanding the Context</strong></p>
645
+ <ul>
646
+ <li><strong><code>msty</code> (Microsoft Telemetry Service)</strong>:
647
+ <code>msty</code> is often used to establish tunnels and connections to
648
+ remote machines (often for debugging and development). Setting headers
649
+ here influences the requests made <em>through</em> that tunnel. It’s
650
+ less common to customize headers at the <code>msty</code> level
651
+ directly; it’s more likely the <em>application</em> running through the
652
+ tunnel handles the headers.</li>
653
+ <li><strong>VS Code Remote - SSH</strong>: This extension lets you
654
+ connect to a remote machine via SSH and develop as if you were working
655
+ locally. Setting headers here primarily impacts the SSH connection
656
+ itself and any subsequent requests made <em>through</em> that connection
657
+ (e.g., if you’re using VS Code’s integrated terminal to make HTTP
658
+ requests).</li>
659
+ <li><strong>Application-Level Headers:</strong> The most common and
660
+ flexible way is to set headers within the <em>application</em> itself
661
+ (e.g., a Python script making HTTP requests, a Node.js server). This
662
+ gives you the most control and avoids modifying the connection or SSH
663
+ configuration.</li>
664
+ </ul>
665
+ <p><strong>1. Setting Custom Headers in the Application</strong></p>
666
+ <p>This is the <em>recommended</em> approach. It’s the most flexible and
667
+ doesn’t require modifying the connection or SSH configuration.</p>
668
+ <p><strong>Example (Python using <code>requests</code>
669
+ library):</strong></p>
670
+ <div class="sourceCode" id="cb8"><pre
671
+ class="sourceCode python"><code class="sourceCode python"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> requests</span>
672
+ <span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a></span>
673
+ <span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>headers <span class="op">=</span> {</span>
674
+ <span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a> <span class="st">&#39;X-Custom-Header&#39;</span>: <span class="st">&#39;YourValue&#39;</span>,</span>
675
+ <span id="cb8-5"><a href="#cb8-5" aria-hidden="true" tabindex="-1"></a> <span class="st">&#39;Authorization&#39;</span>: <span class="st">&#39;Bearer YourToken&#39;</span></span>
676
+ <span id="cb8-6"><a href="#cb8-6" aria-hidden="true" tabindex="-1"></a>}</span>
677
+ <span id="cb8-7"><a href="#cb8-7" aria-hidden="true" tabindex="-1"></a></span>
678
+ <span id="cb8-8"><a href="#cb8-8" aria-hidden="true" tabindex="-1"></a>response <span class="op">=</span> requests.get(<span class="st">&#39;http://your-remote-server/api/data&#39;</span>, headers<span class="op">=</span>headers)</span>
679
+ <span id="cb8-9"><a href="#cb8-9" aria-hidden="true" tabindex="-1"></a></span>
680
+ <span id="cb8-10"><a href="#cb8-10" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> response.status_code <span class="op">==</span> <span class="dv">200</span>:</span>
681
+ <span id="cb8-11"><a href="#cb8-11" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(response.json())</span>
682
+ <span id="cb8-12"><a href="#cb8-12" aria-hidden="true" tabindex="-1"></a><span class="cf">else</span>:</span>
683
+ <span id="cb8-13"><a href="#cb8-13" aria-hidden="true" tabindex="-1"></a> <span class="bu">print</span>(<span class="ss">f&quot;Error: </span><span class="sc">{</span>response<span class="sc">.</span>status_code<span class="sc">}</span><span class="ss">&quot;</span>)</span></code></pre></div>
684
+ <p><strong>Example (Node.js using <code>node-fetch</code>):</strong></p>
685
+ <div class="sourceCode" id="cb9"><pre
686
+ class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> fetch <span class="op">=</span> <span class="pp">require</span>(<span class="st">&#39;node-fetch&#39;</span>)<span class="op">;</span></span>
687
+ <span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a></span>
688
+ <span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a><span class="kw">const</span> headers <span class="op">=</span> {</span>
689
+ <span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a> <span class="st">&#39;X-Custom-Header&#39;</span><span class="op">:</span> <span class="st">&#39;YourValue&#39;</span><span class="op">,</span></span>
690
+ <span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a> <span class="st">&#39;Authorization&#39;</span><span class="op">:</span> <span class="st">&#39;Bearer YourToken&#39;</span></span>
691
+ <span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>}<span class="op">;</span></span>
692
+ <span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a></span>
693
+ <span id="cb9-8"><a href="#cb9-8" aria-hidden="true" tabindex="-1"></a><span class="fu">fetch</span>(<span class="st">&#39;http://your-remote-server/api/data&#39;</span><span class="op">,</span> {</span>
694
+ <span id="cb9-9"><a href="#cb9-9" aria-hidden="true" tabindex="-1"></a> <span class="dt">headers</span><span class="op">:</span> headers</span>
695
+ <span id="cb9-10"><a href="#cb9-10" aria-hidden="true" tabindex="-1"></a>})</span>
696
+ <span id="cb9-11"><a href="#cb9-11" aria-hidden="true" tabindex="-1"></a><span class="op">.</span><span class="fu">then</span>(response <span class="kw">=&gt;</span> {</span>
697
+ <span id="cb9-12"><a href="#cb9-12" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> (response<span class="op">.</span><span class="at">ok</span>) {</span>
698
+ <span id="cb9-13"><a href="#cb9-13" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> response<span class="op">.</span><span class="fu">json</span>()<span class="op">;</span></span>
699
+ <span id="cb9-14"><a href="#cb9-14" aria-hidden="true" tabindex="-1"></a> } <span class="cf">else</span> {</span>
700
+ <span id="cb9-15"><a href="#cb9-15" aria-hidden="true" tabindex="-1"></a> <span class="cf">throw</span> <span class="kw">new</span> <span class="bu">Error</span>(<span class="vs">`HTTP error! Status: </span><span class="sc">${</span>response<span class="op">.</span><span class="at">status</span><span class="sc">}</span><span class="vs">`</span>)<span class="op">;</span></span>
701
+ <span id="cb9-16"><a href="#cb9-16" aria-hidden="true" tabindex="-1"></a> }</span>
702
+ <span id="cb9-17"><a href="#cb9-17" aria-hidden="true" tabindex="-1"></a>})</span>
703
+ <span id="cb9-18"><a href="#cb9-18" aria-hidden="true" tabindex="-1"></a><span class="op">.</span><span class="fu">then</span>(data <span class="kw">=&gt;</span> {</span>
704
+ <span id="cb9-19"><a href="#cb9-19" aria-hidden="true" tabindex="-1"></a> <span class="bu">console</span><span class="op">.</span><span class="fu">log</span>(data)<span class="op">;</span></span>
705
+ <span id="cb9-20"><a href="#cb9-20" aria-hidden="true" tabindex="-1"></a>})</span>
706
+ <span id="cb9-21"><a href="#cb9-21" aria-hidden="true" tabindex="-1"></a><span class="op">.</span><span class="fu">catch</span>(error <span class="kw">=&gt;</span> {</span>
707
+ <span id="cb9-22"><a href="#cb9-22" aria-hidden="true" tabindex="-1"></a> <span class="bu">console</span><span class="op">.</span><span class="fu">error</span>(<span class="st">&#39;Error:&#39;</span><span class="op">,</span> error)<span class="op">;</span></span>
708
+ <span id="cb9-23"><a href="#cb9-23" aria-hidden="true" tabindex="-1"></a>})<span class="op">;</span></span></code></pre></div>
709
+ <p><strong>2. Setting Custom Headers in SSH (Less Common, More
710
+ Complex)</strong></p>
711
+ <p>You <em>can</em> set SSH configuration options that might affect
712
+ header-like information in certain contexts (e.g., if you’re using SSH
713
+ port forwarding with a web server), but it’s generally not the right
714
+ approach for general HTTP header customization. It’s more for setting
715
+ authentication or other SSH-specific parameters.</p>
716
+ <ul>
717
+ <li><p><strong><code>~/.ssh/config</code>:</strong> You can configure
718
+ SSH options in your <code>~/.ssh/config</code> file. For example:</p>
719
+ <pre><code>Host your_remote_server
720
+ HostName your_remote_server_ip
721
+ User your_username
722
+ # Not directly HTTP headers, but SSH options
723
+ # RequestPty yes # Request a pseudo-terminal
724
+ # ServerAliveInterval 60 # Keep the connection alive</code></pre></li>
725
+ </ul>
726
+ <p><strong>Important:</strong> These SSH configuration options do
727
+ <em>not</em> directly set HTTP headers. They configure the SSH
728
+ connection itself.</p>
729
+ <p><strong>3. Setting Headers via Proxy (If Applicable)</strong></p>
730
+ <p>If you’re using a proxy server between your local machine and the
731
+ remote server, you can configure the proxy to add or modify HTTP
732
+ headers. This is a powerful way to control headers without modifying the
733
+ application or SSH configuration. The configuration details depend on
734
+ the proxy server you’re using (e.g., Squid, Nginx).</p>
735
+ <p><strong>4. msty Specifics (Limited)</strong></p>
736
+ <p><code>msty</code> primarily focuses on establishing secure tunnels.
737
+ Directly setting custom headers at the <code>msty</code> level is
738
+ generally not supported. The headers are typically handled by the
739
+ application running through the tunnel.</p>
740
+ <p><strong>How to Determine the Best Approach</strong></p>
741
+ <ul>
742
+ <li><strong>If you have control over the application code:</strong> The
743
+ <em>application-level</em> approach is the simplest and most
744
+ flexible.</li>
745
+ <li><strong>If you need to modify headers for all traffic to a remote
746
+ server:</strong> A proxy server is a good solution.</li>
747
+ <li><strong>If you’re using SSH port forwarding with a web
748
+ server:</strong> You might be able to configure the web server to add
749
+ custom headers.</li>
750
+ <li><strong>If you’re using <code>msty</code> for tunneling:</strong>
751
+ Focus on setting headers within the application running through the
752
+ tunnel.</li>
753
+ </ul>
754
+ <p><strong>To help me provide more specific instructions, please tell
755
+ me:</strong></p>
756
+ <ul>
757
+ <li><strong>What kind of application are you using (e.g., Python script,
758
+ Node.js server, web browser)?</strong></li>
759
+ <li><strong>What are you trying to achieve by setting the custom headers
760
+ (e.g., authentication, API key, custom data)?</strong></li>
761
+ <li><strong>Are you using SSH port forwarding or any other tunneling
762
+ mechanism?</strong></li>
763
+ <li><strong>Are you using <code>msty</code>? If so, what’s the purpose
764
+ of the tunnel?</strong></li>
765
+ </ul>
766
+ <p>I’ll do my best to guide you through the process and provide the most
767
+ appropriate solution for your needs.</p>
768
+ </section>
769
+ <section class="slide level1">
770
+
771
+ <p><strong>:You:</strong></p>
772
+ <p>share with friends</p>
773
+ </section>
774
+ <section class="slide level1">
775
+
776
+ <p><strong>:gemma3:27b:</strong></p>
777
+ <p>Okay, here are a few ways to share this information with your
778
+ friends, depending on how you want to do it! I’ll give you a few
779
+ options, from simple copy/paste to more shareable formats. I’ll break it
780
+ down by method. I’ll also include a summary you can easily
781
+ copy/paste.</p>
782
+ <p><strong>1. Copy/Paste the Text (Quickest)</strong></p>
783
+ <p>Just select the text of our conversation and copy it (Ctrl+C or
784
+ Cmd+C). Then paste it into:</p>
785
+ <ul>
786
+ <li><strong>Email:</strong> The simplest method.</li>
787
+ <li><strong>Messaging App:</strong> (WhatsApp, Signal, Telegram,
788
+ Messenger, Slack, Discord, etc.) Paste it directly into a chat. Some
789
+ apps may have character limits, so you might need to break it up into
790
+ multiple messages.</li>
791
+ </ul>
792
+ <p><strong>2. Create a Sharable Document (More Organized)</strong></p>
793
+ <ul>
794
+ <li><strong>Google Docs:</strong>
795
+ <ol type="1">
796
+ <li>Copy and paste the text into a new Google Doc.</li>
797
+ <li>Format it for readability (headings, bullet points, etc.).</li>
798
+ <li>Click the “Share” button and grant your friends access (view,
799
+ comment, or edit). You can share it with specific</li>
800
+ </ol></li>
801
+ </ul>
802
+ </section>
803
+ </div>
804
+ </div>
805
+
806
+ <script src="https://unpkg.com/reveal.js//dist/reveal.js"></script>
807
+
808
+ <!-- reveal.js plugins -->
809
+ <script src="https://unpkg.com/reveal.js//plugin/notes/notes.js"></script>
810
+ <script src="https://unpkg.com/reveal.js//plugin/search/search.js"></script>
811
+ <script src="https://unpkg.com/reveal.js//plugin/zoom/zoom.js"></script>
812
+
813
+ <script>
814
+
815
+ // Full list of configuration options available at:
816
+ // https://revealjs.com/config/
817
+ Reveal.initialize({
818
+ // Display controls in the bottom right corner
819
+ controls: true,
820
+
821
+ // Help the user learn the controls by providing hints, for example by
822
+ // bouncing the down arrow when they first encounter a vertical slide
823
+ controlsTutorial: true,
824
+
825
+ // Determines where controls appear, "edges" or "bottom-right"
826
+ controlsLayout: 'bottom-right',
827
+
828
+ // Visibility rule for backwards navigation arrows; "faded", "hidden"
829
+ // or "visible"
830
+ controlsBackArrows: 'faded',
831
+
832
+ // Display a presentation progress bar
833
+ progress: true,
834
+
835
+ // Display the page number of the current slide
836
+ slideNumber: false,
837
+
838
+ // 'all', 'print', or 'speaker'
839
+ showSlideNumber: 'all',
840
+
841
+ // Add the current slide number to the URL hash so that reloading the
842
+ // page/copying the URL will return you to the same slide
843
+ hash: true,
844
+
845
+ // Start with 1 for the hash rather than 0
846
+ hashOneBasedIndex: false,
847
+
848
+ // Flags if we should monitor the hash and change slides accordingly
849
+ respondToHashChanges: true,
850
+
851
+ // Push each slide change to the browser history
852
+ history: false,
853
+
854
+ // Enable keyboard shortcuts for navigation
855
+ keyboard: true,
856
+
857
+ // Enable the slide overview mode
858
+ overview: true,
859
+
860
+ // Disables the default reveal.js slide layout (scaling and centering)
861
+ // so that you can use custom CSS layout
862
+ disableLayout: false,
863
+
864
+ // Vertical centering of slides
865
+ center: true,
866
+
867
+ // Enables touch navigation on devices with touch input
868
+ touch: true,
869
+
870
+ // Loop the presentation
871
+ loop: false,
872
+
873
+ // Change the presentation direction to be RTL
874
+ rtl: false,
875
+
876
+ // see https://revealjs.com/vertical-slides/#navigation-mode
877
+ navigationMode: 'default',
878
+
879
+ // Randomizes the order of slides each time the presentation loads
880
+ shuffle: false,
881
+
882
+ // Turns fragments on and off globally
883
+ fragments: true,
884
+
885
+ // Flags whether to include the current fragment in the URL,
886
+ // so that reloading brings you to the same fragment position
887
+ fragmentInURL: true,
888
+
889
+ // Flags if the presentation is running in an embedded mode,
890
+ // i.e. contained within a limited portion of the screen
891
+ embedded: false,
892
+
893
+ // Flags if we should show a help overlay when the questionmark
894
+ // key is pressed
895
+ help: true,
896
+
897
+ // Flags if it should be possible to pause the presentation (blackout)
898
+ pause: true,
899
+
900
+ // Flags if speaker notes should be visible to all viewers
901
+ showNotes: false,
902
+
903
+ // Global override for autoplaying embedded media (null/true/false)
904
+ autoPlayMedia: null,
905
+
906
+ // Global override for preloading lazy-loaded iframes (null/true/false)
907
+ preloadIframes: null,
908
+
909
+ // Number of milliseconds between automatically proceeding to the
910
+ // next slide, disabled when set to 0, this value can be overwritten
911
+ // by using a data-autoslide attribute on your slides
912
+ autoSlide: 0,
913
+
914
+ // Stop auto-sliding after user input
915
+ autoSlideStoppable: true,
916
+
917
+ // Use this method for navigation when auto-sliding
918
+ autoSlideMethod: null,
919
+
920
+ // Specify the average time in seconds that you think you will spend
921
+ // presenting each slide. This is used to show a pacing timer in the
922
+ // speaker view
923
+ defaultTiming: null,
924
+
925
+ // Enable slide navigation via mouse wheel
926
+ mouseWheel: false,
927
+
928
+ // The display mode that will be used to show slides
929
+ display: 'block',
930
+
931
+ // Hide cursor if inactive
932
+ hideInactiveCursor: true,
933
+
934
+ // Time before the cursor is hidden (in ms)
935
+ hideCursorTime: 5000,
936
+
937
+ // Opens links in an iframe preview overlay
938
+ previewLinks: false,
939
+
940
+ // Transition style (none/fade/slide/convex/concave/zoom)
941
+ transition: 'slide',
942
+
943
+ // Transition speed (default/fast/slow)
944
+ transitionSpeed: 'default',
945
+
946
+ // Transition style for full page slide backgrounds
947
+ // (none/fade/slide/convex/concave/zoom)
948
+ backgroundTransition: 'fade',
949
+
950
+ // Number of slides away from the current that are visible
951
+ viewDistance: 3,
952
+
953
+ // Number of slides away from the current that are visible on mobile
954
+ // devices. It is advisable to set this to a lower number than
955
+ // viewDistance in order to save resources.
956
+ mobileViewDistance: 2,
957
+
958
+ // reveal.js plugins
959
+ plugins: [
960
+ RevealNotes,
961
+ RevealSearch,
962
+ RevealZoom
963
+ ]
964
+ });
965
+ </script>
966
+ </body>
967
+ </html>