@vizamodo/modo-dispatcher 1.1.77

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 (109) hide show
  1. package/README.md +43 -0
  2. package/dist/artifacts/builders.d.ts +32 -0
  3. package/dist/artifacts/builders.js +72 -0
  4. package/dist/artifacts/downloader.d.ts +28 -0
  5. package/dist/artifacts/downloader.js +102 -0
  6. package/dist/artifacts/normalizer.d.ts +22 -0
  7. package/dist/artifacts/normalizer.js +65 -0
  8. package/dist/artifacts/types.d.ts +94 -0
  9. package/dist/artifacts/types.js +1 -0
  10. package/dist/auth/identity/extract-identity.d.ts +8 -0
  11. package/dist/auth/identity/extract-identity.js +15 -0
  12. package/dist/auth/identity/normalize-teams.d.ts +1 -0
  13. package/dist/auth/identity/normalize-teams.js +5 -0
  14. package/dist/auth/identity/validate-claims.d.ts +2 -0
  15. package/dist/auth/identity/validate-claims.js +5 -0
  16. package/dist/auth/jwt/parse.d.ts +2 -0
  17. package/dist/auth/jwt/parse.js +16 -0
  18. package/dist/auth/jwt/verify.d.ts +1 -0
  19. package/dist/auth/jwt/verify.js +9 -0
  20. package/dist/auth/oauth/auth-error.d.ts +12 -0
  21. package/dist/auth/oauth/auth-error.js +47 -0
  22. package/dist/auth/oauth/auth-session-store.d.ts +30 -0
  23. package/dist/auth/oauth/auth-session-store.js +46 -0
  24. package/dist/auth/oauth/callback-server.d.ts +21 -0
  25. package/dist/auth/oauth/callback-server.js +319 -0
  26. package/dist/auth/oauth/github.d.ts +14 -0
  27. package/dist/auth/oauth/github.js +100 -0
  28. package/dist/auth/oauth/sse.d.ts +11 -0
  29. package/dist/auth/oauth/sse.js +67 -0
  30. package/dist/auth/oauth/templates/failed.html +629 -0
  31. package/dist/auth/oauth/templates/pending.html +620 -0
  32. package/dist/auth/oauth/templates/success.html +577 -0
  33. package/dist/auth/session/access-token.d.ts +15 -0
  34. package/dist/auth/session/access-token.js +64 -0
  35. package/dist/auth/session/login.d.ts +18 -0
  36. package/dist/auth/session/login.js +144 -0
  37. package/dist/auth/session/logout.d.ts +3 -0
  38. package/dist/auth/session/logout.js +21 -0
  39. package/dist/auth/session/refresh-token.d.ts +8 -0
  40. package/dist/auth/session/refresh-token.js +16 -0
  41. package/dist/auth/session/refresh.d.ts +2 -0
  42. package/dist/auth/session/refresh.js +61 -0
  43. package/dist/auth/session/rotate.d.ts +4 -0
  44. package/dist/auth/session/rotate.js +4 -0
  45. package/dist/auth/session/session-manager.d.ts +16 -0
  46. package/dist/auth/session/session-manager.js +54 -0
  47. package/dist/auth/session/token-state.d.ts +20 -0
  48. package/dist/auth/session/token-state.js +55 -0
  49. package/dist/auth/session/types.d.ts +35 -0
  50. package/dist/auth/session/types.js +1 -0
  51. package/dist/auth/storage/keychain.d.ts +16 -0
  52. package/dist/auth/storage/keychain.js +107 -0
  53. package/dist/auth/storage/memory.d.ts +10 -0
  54. package/dist/auth/storage/memory.js +15 -0
  55. package/dist/auth/storage/types.d.ts +5 -0
  56. package/dist/auth/storage/types.js +1 -0
  57. package/dist/config/defaults.d.ts +94 -0
  58. package/dist/config/defaults.js +116 -0
  59. package/dist/core/auth-bootstrap.d.ts +15 -0
  60. package/dist/core/auth-bootstrap.js +33 -0
  61. package/dist/core/bootstrap.d.ts +73 -0
  62. package/dist/core/bootstrap.js +248 -0
  63. package/dist/core/dispatcher.d.ts +2 -0
  64. package/dist/core/dispatcher.js +28 -0
  65. package/dist/core/ensure-bootstrap.d.ts +3 -0
  66. package/dist/core/ensure-bootstrap.js +25 -0
  67. package/dist/core/errors.d.ts +69 -0
  68. package/dist/core/errors.js +121 -0
  69. package/dist/core/runtime-orchestrator.d.ts +17 -0
  70. package/dist/core/runtime-orchestrator.js +47 -0
  71. package/dist/core/runtime.d.ts +16 -0
  72. package/dist/core/runtime.js +52 -0
  73. package/dist/core/validation.d.ts +2 -0
  74. package/dist/core/validation.js +21 -0
  75. package/dist/crypto/encrypt.d.ts +12 -0
  76. package/dist/crypto/encrypt.js +80 -0
  77. package/dist/flows/email-otp-flow.d.ts +7 -0
  78. package/dist/flows/email-otp-flow.js +249 -0
  79. package/dist/gateway/auth-header.d.ts +2 -0
  80. package/dist/gateway/auth-header.js +21 -0
  81. package/dist/gateway/client.d.ts +7 -0
  82. package/dist/gateway/client.js +24 -0
  83. package/dist/gateway/dispatch-with-bootstrap-retry.d.ts +25 -0
  84. package/dist/gateway/dispatch-with-bootstrap-retry.js +157 -0
  85. package/dist/gateway/dispatch.d.ts +23 -0
  86. package/dist/gateway/dispatch.js +110 -0
  87. package/dist/gateway/session-waiter.d.ts +11 -0
  88. package/dist/gateway/session-waiter.js +126 -0
  89. package/dist/gateway/session.d.ts +21 -0
  90. package/dist/gateway/session.js +74 -0
  91. package/dist/gateway/types.d.ts +113 -0
  92. package/dist/gateway/types.js +19 -0
  93. package/dist/index.d.ts +22 -0
  94. package/dist/index.js +21 -0
  95. package/dist/runtime/runtime-context.d.ts +6 -0
  96. package/dist/runtime/runtime-context.js +1 -0
  97. package/dist/types/dispatcher.d.ts +275 -0
  98. package/dist/types/dispatcher.js +1 -0
  99. package/dist/types/payload.d.ts +5 -0
  100. package/dist/types/payload.js +2 -0
  101. package/dist/types/runtime-env.d.ts +2 -0
  102. package/dist/types/runtime-env.js +5 -0
  103. package/dist/ui/banner.d.ts +4 -0
  104. package/dist/ui/banner.js +20 -0
  105. package/dist/utils/request-dedup.d.ts +75 -0
  106. package/dist/utils/request-dedup.js +102 -0
  107. package/dist/utils/type-guards.d.ts +173 -0
  108. package/dist/utils/type-guards.js +232 -0
  109. package/package.json +43 -0
@@ -0,0 +1,629 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>Viza Development Platform — Authentication Failed</title>
8
+ <link href="https://fonts.googleapis.com/css2?family=Syne:wght@400;600;700;800&family=DM+Mono:wght@300;400;500&display=swap"
9
+ rel="stylesheet" />
10
+ <style>
11
+ :root {
12
+ --bg: #0d1117;
13
+ --surface: #161b22;
14
+ --surface2: #1f242d;
15
+ --border: rgba(255, 255, 255, 0.08);
16
+ --border-accent: rgba(239, 68, 68, 0.18);
17
+ --text-primary: #e6edf3;
18
+ --text-secondary: #9aa4b2;
19
+ --text-muted: #6b7280;
20
+ --accent: #ef4444;
21
+ --accent-dim: rgba(239, 68, 68, 0.06);
22
+ --accent-glow: rgba(239, 68, 68, 0.05);
23
+ --warning: #f59e0b;
24
+ --mono: 'DM Mono', monospace;
25
+ --sans: 'Syne', sans-serif;
26
+ }
27
+
28
+ @media (prefers-color-scheme: light) {
29
+ :root {
30
+ --bg: #eef2f6;
31
+ --surface: #ffffff;
32
+ --surface2: #f3f5f8;
33
+ --border: rgba(0, 0, 0, 0.08);
34
+ --border-accent: rgba(220, 38, 38, 0.16);
35
+ --text-primary: #0f1117;
36
+ --text-secondary: #5a6476;
37
+ --text-muted: #a0aab8;
38
+ --accent: #dc2626;
39
+ --accent-dim: rgba(220, 38, 38, 0.05);
40
+ --accent-glow: rgba(220, 38, 38, 0.04);
41
+ --warning: #d97706;
42
+ }
43
+ }
44
+
45
+ *,
46
+ *::before,
47
+ *::after {
48
+ box-sizing: border-box;
49
+ margin: 0;
50
+ padding: 0;
51
+ }
52
+
53
+ html,
54
+ body {
55
+ height: 100%;
56
+ background: var(--bg);
57
+ color: var(--text-primary);
58
+ font-family: var(--sans);
59
+ display: flex;
60
+ align-items: center;
61
+ justify-content: center;
62
+ padding: 24px;
63
+ }
64
+
65
+ /* Subtle background grid */
66
+ body::before {
67
+ content: '';
68
+ position: fixed;
69
+ inset: 0;
70
+ background-image:
71
+ linear-gradient(var(--border) 1px, transparent 1px),
72
+ linear-gradient(90deg, var(--border) 1px, transparent 1px);
73
+ background-size: 72px 72px;
74
+ opacity: 0.28;
75
+ pointer-events: none;
76
+ z-index: 0;
77
+ }
78
+
79
+ body::after {
80
+ content: '';
81
+ position: fixed;
82
+ inset: 0;
83
+ background: radial-gradient(ellipse 55% 45% at 50% 50%, var(--accent-glow), transparent 75%);
84
+ pointer-events: none;
85
+ z-index: 0;
86
+ }
87
+
88
+ .card {
89
+ position: relative;
90
+ z-index: 1;
91
+ width: 100%;
92
+ max-width: 760px;
93
+ width: min(760px, calc(100vw - 32px));
94
+ background: var(--surface);
95
+ border: 1px solid var(--border);
96
+ border-radius: 20px;
97
+ padding: 36px 36px 32px;
98
+ box-shadow:
99
+ 0 0 0 1px var(--border),
100
+ 0 18px 48px rgba(0, 0, 0, 0.28),
101
+ 0 0 0 1px rgba(255,255,255,0.02);
102
+ animation: fadeUp 0.6s cubic-bezier(0.16, 1, 0.3, 1) both;
103
+ }
104
+
105
+ @keyframes fadeUp {
106
+ from {
107
+ opacity: 0;
108
+ transform: translateY(20px) scale(0.98);
109
+ }
110
+
111
+ to {
112
+ opacity: 1;
113
+ transform: translateY(0) scale(1);
114
+ }
115
+ }
116
+
117
+ /* Header */
118
+ .header {
119
+ display: flex;
120
+ align-items: center;
121
+ gap: 12px;
122
+ margin-bottom: 13px;
123
+ padding-bottom: 18px;
124
+ border-bottom: 1px solid var(--border);
125
+ }
126
+
127
+ .logo {
128
+ width: 36px;
129
+ height: 36px;
130
+ background: var(--accent);
131
+ border-radius: 10px;
132
+ display: flex;
133
+ align-items: center;
134
+ justify-content: center;
135
+ flex-shrink: 0;
136
+ }
137
+
138
+ .logo svg {
139
+ width: 20px;
140
+ height: 20px;
141
+ }
142
+
143
+ .brand {
144
+ display: flex;
145
+ flex-direction: column;
146
+ gap: 1px;
147
+ }
148
+
149
+ .brand-name {
150
+ font-size: 13px;
151
+ font-weight: 700;
152
+ letter-spacing: 0.08em;
153
+ text-transform: uppercase;
154
+ color: var(--text-primary);
155
+ }
156
+
157
+ .brand-sub {
158
+ font-family: var(--mono);
159
+ font-size: 11px;
160
+ color: var(--text-muted);
161
+ letter-spacing: 0.04em;
162
+ }
163
+
164
+ /* Success badge */
165
+ .status-badge {
166
+ margin-left: auto;
167
+ display: flex;
168
+ align-items: center;
169
+ gap: 6px;
170
+ background: var(--accent-dim);
171
+ border: 1px solid var(--border-accent);
172
+ border-radius: 100px;
173
+ padding: 5px 12px 5px 8px;
174
+ font-family: var(--mono);
175
+ font-size: 11px;
176
+ font-weight: 500;
177
+ color: #ff6b6b;
178
+ letter-spacing: 0.03em;
179
+ animation: fadeIn 0.4s 0.4s both;
180
+ }
181
+
182
+ @keyframes fadeIn {
183
+ from {
184
+ opacity: 0;
185
+ }
186
+
187
+ to {
188
+ opacity: 1;
189
+ }
190
+ }
191
+
192
+ .dot {
193
+ width: 7px;
194
+ height: 7px;
195
+ border-radius: 50%;
196
+ background: var(--accent);
197
+ animation: pulse 2s ease-in-out infinite;
198
+ }
199
+
200
+ @keyframes pulse {
201
+
202
+ 0%,
203
+ 100% {
204
+ opacity: 1;
205
+ transform: scale(1);
206
+ }
207
+
208
+ 50% {
209
+ opacity: 0.5;
210
+ transform: scale(0.8);
211
+ }
212
+ }
213
+
214
+ /* Title area */
215
+ .title-area {
216
+ margin-bottom: 8px;
217
+ animation: fadeUp 0.5s 0.15s cubic-bezier(0.16, 1, 0.3, 1) both;
218
+ padding-bottom: 8px;
219
+ }
220
+
221
+ .check-icon {
222
+ width: 48px;
223
+ height: 48px;
224
+ border-radius: 14px;
225
+ background: var(--accent-dim);
226
+ border: 1px solid var(--border-accent);
227
+ display: flex;
228
+ align-items: center;
229
+ justify-content: center;
230
+ margin-bottom: 20px;
231
+ }
232
+
233
+ .check-icon svg {
234
+ width: 24px;
235
+ height: 24px;
236
+ color: var(--accent);
237
+ }
238
+
239
+ h1 {
240
+ font-size: 28px;
241
+ font-weight: 700;
242
+ letter-spacing: -0.04em;
243
+ color: var(--text-primary);
244
+ line-height: 1.2;
245
+ margin-bottom: 8px;
246
+ }
247
+
248
+ .subtitle {
249
+ font-family: var(--mono);
250
+ font-size: 12px;
251
+ color: var(--text-secondary);
252
+ line-height: 1.8;
253
+ }
254
+
255
+ /* Info rows */
256
+ .info-block {
257
+ background: var(--surface2);
258
+ border: 1px solid var(--border);
259
+ border-radius: 12px;
260
+ overflow: hidden;
261
+ margin-bottom: 20px;
262
+ animation: fadeUp 0.5s 0.25s cubic-bezier(0.16, 1, 0.3, 1) both;
263
+ backdrop-filter: blur(8px);
264
+ }
265
+
266
+ .info-row {
267
+ display: grid;
268
+ grid-template-columns: 120px minmax(0, 1fr);
269
+ align-items: start;
270
+ padding: 16px 18px;
271
+ gap: 12px;
272
+ }
273
+
274
+ .info-row+.info-row {
275
+ border-top: 1px solid var(--border);
276
+ }
277
+
278
+ .info-label {
279
+ font-family: var(--mono);
280
+ font-size: 10px;
281
+ color: var(--text-muted);
282
+ text-transform: uppercase;
283
+ letter-spacing: 0.07em;
284
+ flex-shrink: 0;
285
+ }
286
+
287
+ .info-value {
288
+ font-family: var(--mono);
289
+ font-size: 13px;
290
+ color: var(--text-secondary);
291
+ text-align: left;
292
+ line-height: 1.5;
293
+ word-break: break-word;
294
+ }
295
+
296
+ .info-value.highlight {
297
+ color: var(--text-primary);
298
+ font-weight: 500;
299
+ }
300
+
301
+ .avatar-row {
302
+ display: flex;
303
+ align-items: center;
304
+ gap: 8px;
305
+ }
306
+
307
+ .avatar {
308
+ width: 22px;
309
+ height: 22px;
310
+ border-radius: 50%;
311
+ background: var(--accent-dim);
312
+ border: 1px solid var(--border-accent);
313
+ display: flex;
314
+ align-items: center;
315
+ justify-content: center;
316
+ overflow: hidden;
317
+ flex-shrink: 0;
318
+ }
319
+
320
+ .avatar img {
321
+ width: 100%;
322
+ height: 100%;
323
+ object-fit: cover;
324
+ }
325
+
326
+ .avatar-placeholder {
327
+ font-size: 11px;
328
+ font-weight: 700;
329
+ color: var(--accent);
330
+ font-family: var(--sans);
331
+ }
332
+
333
+ /* Scope tags */
334
+ .scopes {
335
+ display: flex;
336
+ flex-wrap: wrap;
337
+ gap: 6px;
338
+ justify-content: flex-end;
339
+ }
340
+
341
+ .scope-tag {
342
+ font-family: var(--mono);
343
+ font-size: 10px;
344
+ padding: 3px 8px;
345
+ border-radius: 4px;
346
+ background: rgba(239, 68, 68, 0.05);
347
+ border: 1px solid var(--border-accent);
348
+ color: var(--accent);
349
+ letter-spacing: 0.03em;
350
+ }
351
+
352
+ .error-code {
353
+ font-family: var(--mono);
354
+ font-size: 10px;
355
+ padding: 4px 8px;
356
+ border-radius: 5px;
357
+ background: rgba(239, 68, 68, 0.08);
358
+ border: 1px solid rgba(239, 68, 68, 0.16);
359
+ color: #ff6b6b;
360
+ letter-spacing: 0.03em;
361
+ }
362
+
363
+ .debug-list {
364
+ display: flex;
365
+ flex-direction: column;
366
+ gap: 10px;
367
+ width: 100%;
368
+ }
369
+
370
+ .debug-item {
371
+ grid-template-columns: 140px minmax(0, 1fr);
372
+ display: grid;
373
+ align-items: start;
374
+ gap: 12px;
375
+ }
376
+
377
+ .debug-key {
378
+ font-family: var(--mono);
379
+ font-size: 11px;
380
+ color: var(--text-muted);
381
+ text-transform: uppercase;
382
+ letter-spacing: 0.06em;
383
+ flex-shrink: 0;
384
+ }
385
+
386
+ .debug-value {
387
+ font-family: var(--mono);
388
+ font-size: 12px;
389
+ color: var(--text-primary);
390
+ text-align: left;
391
+ word-break: break-word;
392
+ line-height: 1.45;
393
+ }
394
+ @media (max-width: 720px) {
395
+ .card {
396
+ max-width: 100%;
397
+ padding: 28px 20px 24px;
398
+ border-radius: 16px;
399
+ }
400
+
401
+ .header {
402
+ align-items: flex-start;
403
+ flex-wrap: wrap;
404
+ gap: 14px;
405
+ }
406
+
407
+ .status-badge {
408
+ margin-left: 0;
409
+ }
410
+
411
+ .info-row {
412
+ grid-template-columns: 1fr;
413
+ gap: 10px;
414
+ }
415
+
416
+ .debug-item {
417
+ grid-template-columns: 1fr;
418
+ gap: 6px;
419
+ }
420
+
421
+ .debug-key,
422
+ .info-label {
423
+ font-size: 10px;
424
+ }
425
+
426
+ .debug-value,
427
+ .info-value {
428
+ font-size: 12px;
429
+ }
430
+
431
+ .scopes {
432
+ justify-content: flex-start;
433
+ }
434
+
435
+ .close-hint {
436
+ align-items: flex-start;
437
+ }
438
+
439
+ .footer {
440
+ flex-direction: column;
441
+ align-items: flex-start;
442
+ gap: 10px;
443
+ }
444
+ }
445
+
446
+ .debug-value.subtle {
447
+ color: var(--text-secondary);
448
+ }
449
+
450
+ /* Close hint */
451
+ .close-hint {
452
+ display: flex;
453
+ align-items: center;
454
+ gap: 10px;
455
+ padding: 14px 16px;
456
+ background: var(--surface2);
457
+ border: 1px solid var(--border);
458
+ border-radius: 12px;
459
+ animation: fadeUp 0.5s 0.35s cubic-bezier(0.16, 1, 0.3, 1) both;
460
+ }
461
+
462
+ .close-hint svg {
463
+ color: var(--text-muted);
464
+ flex-shrink: 0;
465
+ width: 16px;
466
+ height: 16px;
467
+ }
468
+
469
+ .close-hint-text {
470
+ font-family: var(--mono);
471
+ font-size: 12px;
472
+ color: var(--text-secondary);
473
+ line-height: 1.4;
474
+ }
475
+
476
+ .close-hint-text strong {
477
+ color: var(--text-primary);
478
+ font-weight: 500;
479
+ }
480
+
481
+ /* Footer */
482
+ .footer {
483
+ margin-top: 28px;
484
+ display: flex;
485
+ align-items: center;
486
+ justify-content: space-between;
487
+ animation: fadeIn 0.4s 0.5s both;
488
+ }
489
+
490
+ .timestamp {
491
+ font-family: var(--mono);
492
+ font-size: 11px;
493
+ color: var(--text-muted);
494
+ }
495
+
496
+ .security-badge {
497
+ display: flex;
498
+ align-items: center;
499
+ gap: 5px;
500
+ font-family: var(--mono);
501
+ font-size: 10px;
502
+ color: var(--text-muted);
503
+ letter-spacing: 0.04em;
504
+ }
505
+
506
+ .security-badge svg {
507
+ width: 12px;
508
+ height: 12px;
509
+ }
510
+ </style>
511
+ </head>
512
+
513
+ <body>
514
+ <div class="card">
515
+
516
+ <!-- Header -->
517
+ <div class="header">
518
+ <div class="logo">
519
+ <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
520
+ <circle cx="12" cy="12" r="9" stroke="#0a0c10" stroke-width="2.5"></circle>
521
+ <path d="M9 9l6 6" stroke="#0a0c10" stroke-width="2.5"
522
+ stroke-linecap="round" stroke-linejoin="round" />
523
+ <path d="M15 9l-6 6" stroke="#0a0c10" stroke-width="2.5"
524
+ stroke-linecap="round" stroke-linejoin="round" />
525
+ </svg>
526
+ </div>
527
+ <div class="brand">
528
+ <span class="brand-name">Viza Development Platform</span>
529
+ <span class="brand-sub">github.com · oauth2</span>
530
+ </div>
531
+ <div class="status-badge" aria-live="polite">
532
+ <span class="dot"></span>
533
+ FAILED
534
+ </div>
535
+ </div>
536
+
537
+ <!-- Title -->
538
+ <div class="title-area">
539
+ <h1>Authentication Failed</h1>
540
+ <div style="display:flex;align-items:center;gap:10px;margin-bottom:12px;flex-wrap:wrap;">
541
+ <span class="error-code">__ERROR_CODE__</span>
542
+ <span style="font-family:var(--mono);font-size:12px;color:var(--text-secondary);">
543
+ GitHub OAuth authentication rejected
544
+ </span>
545
+ </div>
546
+ <p class="subtitle">
547
+ Viza could not complete your authentication request.<br />Review the account details below and retry authentication.
548
+ </p>
549
+ </div>
550
+
551
+ <!-- Info block -->
552
+ <div class="info-block" aria-live="polite">
553
+ <div class="info-row">
554
+ <span class="info-label">Provider</span>
555
+ <span class="info-value highlight">GitHub OAuth</span>
556
+ </div>
557
+ <div class="info-row">
558
+ <span class="info-label">Status</span>
559
+ <span class="info-value highlight">Authorization rejected</span>
560
+ </div>
561
+ <div class="info-row">
562
+ <span class="info-label">Error</span>
563
+ <div class="debug-list">
564
+ <div class="debug-item">
565
+ <span class="debug-key">Message</span>
566
+ <span class="debug-value">__ERROR_MESSAGE__</span>
567
+ </div>
568
+ <div class="debug-item">
569
+ <span class="debug-key">GitHub User</span>
570
+ <span class="debug-value">__GITHUB_LOGIN__</span>
571
+ </div>
572
+ <div class="debug-item">
573
+ <span class="debug-key">GitHub ID</span>
574
+ <span class="debug-value subtle">__GITHUB_USER_ID__</span>
575
+ </div>
576
+ <div class="debug-item">
577
+ <span class="debug-key">Suggested Action</span>
578
+ <span class="debug-value subtle">__SUGGESTION__</span>
579
+ </div>
580
+ </div>
581
+ </div>
582
+ <div class="info-row">
583
+ <span class="info-label">Security</span>
584
+ <div class="scopes">
585
+ <span class="scope-tag">PKCE</span>
586
+ <span class="scope-tag">TLS 1.3</span>
587
+ <span class="scope-tag">AUDITED</span>
588
+ </div>
589
+ </div>
590
+ </div>
591
+
592
+ <!-- Close hint -->
593
+ <div class="close-hint">
594
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
595
+ stroke-linejoin="round">
596
+ <rect x="3" y="3" width="18" height="18" rx="3" />
597
+ <path d="M9 3v18M15 3v18M3 9h18M3 15h18" opacity="0.4" />
598
+ <path d="M9 12h6" />
599
+ </svg>
600
+ <span class="close-hint-text">
601
+ <strong>Authentication was not completed.</strong>
602
+ Verify that you selected the correct GitHub account and completed any required GitHub security verification before retrying from the CLI.
603
+ </span>
604
+ </div>
605
+
606
+ <!-- Footer -->
607
+ <div class="footer">
608
+ <span class="timestamp" id="timestamp">—</span>
609
+ <div class="security-badge">
610
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
611
+ stroke-linecap="round" stroke-linejoin="round">
612
+ <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" />
613
+ </svg>
614
+ OAuth 2.0 · TLS 1.3
615
+ </div>
616
+ </div>
617
+
618
+ </div>
619
+
620
+ <script>
621
+ const timestampEl = document.getElementById("timestamp");
622
+
623
+ if (timestampEl) {
624
+ timestampEl.textContent = new Date().toLocaleString();
625
+ }
626
+ </script>
627
+ </body>
628
+
629
+ </html>