moddux commited on
Commit
b27c811
·
verified ·
1 Parent(s): d649ba6

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +393 -300
index.html CHANGED
@@ -1,14 +1,17 @@
1
  <!DOCTYPE html>
2
  <html lang="en">
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>AETHER // ARCHITECTURE DOSSIER</title>
7
  <!-- Import Fonts -->
8
  <link rel="preconnect" href="https://fonts.googleapis.com">
9
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10
- <link href="https://fonts.googleapis.com/css2?family=Rajdhani:wght@400;500;600;700&family=Share+Tech+Mono&family=Space+Mono:ital,wght@0,400;0,700;1,400&display=swap" rel="stylesheet">
11
-
 
 
12
  <style>
13
  /* --- CSS VARIABLES & RESET --- */
14
  :root {
@@ -16,10 +19,10 @@
16
  --bg-panel: #0e1016;
17
  --bg-card: #14161f;
18
  --border-subtle: #2a2f3d;
19
-
20
  --text-main: #e0e6ed;
21
  --text-muted: #94a3b8;
22
-
23
  --font-body: 'Rajdhani', sans-serif;
24
  --font-mono: 'Share Tech Mono', monospace;
25
  --font-meta: 'Space Mono', monospace;
@@ -56,7 +59,7 @@
56
  width: 100%;
57
  height: 100vh;
58
  z-index: -1;
59
- background-image:
60
  linear-gradient(rgba(0, 240, 255, 0.03) 1px, transparent 1px),
61
  linear-gradient(90deg, rgba(0, 240, 255, 0.03) 1px, transparent 1px);
62
  background-size: 40px 40px;
@@ -64,19 +67,46 @@
64
  }
65
 
66
  /* --- TYPOGRAPHY UTILS --- */
67
- h1, h2, h3, h4 {
 
 
 
68
  text-transform: uppercase;
69
  letter-spacing: 1px;
70
  }
71
-
72
- .mono { font-family: var(--font-mono); }
73
- .meta { font-family: var(--font-meta); font-size: 0.85rem; }
74
- .text-cyan { color: var(--cyan); }
75
- .text-green { color: var(--green); }
76
- .text-orange { color: var(--orange); }
77
- .text-gold { color: var(--gold); }
78
- .text-purple { color: var(--purple); }
79
- .text-red { color: var(--red); }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
 
81
  /* --- HEADER --- */
82
  .header {
@@ -133,9 +163,21 @@
133
  border-radius: 2px;
134
  text-transform: uppercase;
135
  }
136
-
137
- .badge.cyan { border-color: var(--cyan); color: var(--cyan); }
138
- .badge.gold { border-color: var(--gold); color: var(--gold); }
 
 
 
 
 
 
 
 
 
 
 
 
139
 
140
  /* --- STICKY NAV --- */
141
  .nav-container {
@@ -148,10 +190,13 @@
148
  padding: 0.5rem 2rem;
149
  overflow-x: auto;
150
  white-space: nowrap;
151
- -ms-overflow-style: none; /* IE and Edge */
152
- scrollbar-width: none; /* Firefox */
 
 
 
 
153
  }
154
- .nav-container::-webkit-scrollbar { display: none; }
155
 
156
  .nav-btn {
157
  background: transparent;
@@ -168,7 +213,7 @@
168
 
169
  .nav-btn:hover {
170
  color: var(--text-main);
171
- background: rgba(255,255,255,0.03);
172
  }
173
 
174
  .nav-btn.active {
@@ -188,14 +233,21 @@
188
  display: none;
189
  animation: fadeIn 0.4s ease-out;
190
  }
191
-
192
  .section.active {
193
  display: block;
194
  }
195
 
196
  @keyframes fadeIn {
197
- from { opacity: 0; transform: translateY(10px); }
198
- to { opacity: 1; transform: translateY(0); }
 
 
 
 
 
 
 
199
  }
200
 
201
  .section-header {
@@ -225,7 +277,7 @@
225
  }
226
 
227
  .card:hover {
228
- border-color: rgba(255,255,255,0.1);
229
  }
230
 
231
  .card::before {
@@ -237,12 +289,29 @@
237
  width: 3px;
238
  }
239
 
240
- .card.cyan::before { background: var(--cyan); }
241
- .card.green::before { background: var(--green); }
242
- .card.orange::before { background: var(--orange); }
243
- .card.gold::before { background: var(--gold); }
244
- .card.purple::before { background: var(--purple); }
245
- .card.red::before { background: var(--red); }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
246
 
247
  .card-title {
248
  font-family: var(--font-mono);
@@ -255,13 +324,35 @@
255
  }
256
 
257
  /* --- GRIDS --- */
258
- .grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; }
259
- .grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.5rem; }
260
- .grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.5rem; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
261
 
262
  @media (max-width: 900px) {
263
- .grid-2, .grid-3, .grid-4 { grid-template-columns: 1fr; }
264
- .header-title { font-size: 2.2rem; }
 
 
 
 
 
 
 
 
265
  }
266
 
267
  /* --- ROLE CARDS --- */
@@ -322,45 +413,6 @@
322
  color: var(--text-muted);
323
  }
324
 
325
- /* --- TIMELINE --- */
326
- .timeline {
327
- position: relative;
328
- padding-left: 2rem;
329
- border-left: 2px solid var(--border-subtle);
330
- }
331
-
332
- .timeline-item {
333
- position: relative;
334
- margin-bottom: 2rem;
335
- }
336
-
337
- .timeline-marker {
338
- position: absolute;
339
- left: -2.6rem;
340
- top: 0;
341
- width: 1rem;
342
- height: 1rem;
343
- border-radius: 50%;
344
- background: var(--bg-dark);
345
- border: 2px solid var(--text-muted);
346
- }
347
-
348
- .timeline-item.done .timeline-marker { background: var(--green); border-color: var(--green); box-shadow: 0 0 10px rgba(0, 255, 157, 0.3); }
349
- .timeline-item.active .timeline-marker { background: var(--cyan); border-color: var(--cyan); box-shadow: 0 0 10px rgba(0, 240, 255, 0.5); }
350
- .timeline-item.next .timeline-marker { background: transparent; border-color: var(--text-muted); border-style: dashed; }
351
-
352
- .timeline-date {
353
- font-family: var(--font-meta);
354
- font-size: 0.75rem;
355
- color: var(--text-muted);
356
- margin-bottom: 0.2rem;
357
- }
358
-
359
- .timeline-title {
360
- font-size: 1.2rem;
361
- font-weight: 600;
362
- }
363
-
364
  /* --- SIGNALS & TAGS --- */
365
  .signal {
366
  display: inline-block;
@@ -371,32 +423,29 @@
371
  border-radius: 2px;
372
  vertical-align: middle;
373
  }
374
- .sig-ref { color: var(--cyan); border: 1px solid var(--cyan); }
375
- .sig-block { color: var(--red); border: 1px solid var(--red); }
376
- .sig-done { color: var(--green); border: 1px solid var(--green); }
377
- .sig-gate { color: var(--gold); border: 1px solid var(--gold); }
378
 
379
- /* --- SNAPSHOTS --- */
380
- .snapshot {
381
- border-top: 3px solid var(--purple);
382
- background: rgba(189, 0, 255, 0.05);
383
- padding: 1.5rem;
384
- font-family: var(--font-meta);
385
- font-size: 0.85rem;
386
- color: #d8b4fe;
387
  }
388
- .snapshot-header {
389
- display: flex;
390
- justify-content: space-between;
391
- border-bottom: 1px solid rgba(189, 0, 255, 0.2);
392
- padding-bottom: 0.5rem;
393
- margin-bottom: 1rem;
394
- font-size: 0.75rem;
395
- text-transform: uppercase;
 
396
  }
397
 
398
- /* --- PSEUDOCODE --- */
399
- .pseudo {
 
 
 
 
 
400
  background: #000;
401
  border: 1px solid var(--border-subtle);
402
  padding: 1rem;
@@ -404,12 +453,18 @@
404
  font-size: 0.85rem;
405
  overflow-x: auto;
406
  color: #d4d4d4;
 
 
 
407
  }
408
- .ps-kw { color: #569cd6; } /* Keyword */
409
- .ps-fn { color: #dcdcaa; } /* Function */
410
- .ps-cmt { color: #6a9955; } /* Comment */
411
- .ps-type { color: #4ec9b0; } /* Type */
412
- .ps-str { color: #ce9178; } /* String */
 
 
 
413
 
414
  /* --- DIAGRAMS (CSS ONLY) --- */
415
  .diagram-box {
@@ -418,9 +473,10 @@
418
  justify-content: center;
419
  gap: 1rem;
420
  padding: 2rem;
421
- background: rgba(0,0,0,0.2);
422
  border: 1px dashed var(--border-subtle);
423
  }
 
424
  .diag-node {
425
  border: 1px solid var(--cyan);
426
  background: rgba(0, 240, 255, 0.1);
@@ -428,6 +484,7 @@
428
  font-family: var(--font-mono);
429
  font-size: 0.8rem;
430
  }
 
431
  .diag-arrow {
432
  color: var(--cyan);
433
  font-size: 1.2rem;
@@ -444,13 +501,14 @@
444
  border-radius: 4px;
445
  transition: color 0.2s;
446
  }
 
447
  .anycoder-link:hover {
448
  color: var(--cyan);
449
  border-color: var(--cyan);
450
  }
451
-
452
  </style>
453
  </head>
 
454
  <body>
455
 
456
  <!-- Background Grid -->
@@ -459,31 +517,30 @@
459
  <!-- Header -->
460
  <header class="header">
461
  <div class="header-top">
462
- <span>SYS_REF: AETHER_V2.4</span>
463
  <span>
464
  <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="anycoder-link">Built with anycoder</a>
465
  </span>
466
  </div>
467
  <div class="header-main">
468
- <h1 class="header-title">Project <span>AETHER</span> // ARCHITECTURE DOSSIER</h1>
469
- <p class="header-subtitle">High-density technical operations blueprint. Modular system design, neural architecture reference, and implementation schema.</p>
470
  <div class="badges">
471
- <span class="badge cyan">STATUS: ACTIVE_DEV</span>
472
- <span class="badge gold">PHASE: 2</span>
473
- <span class="badge">SECURITY: L3</span>
474
- <span class="badge">LAST_COMMIT: 2H AGO</span>
475
  </div>
476
  </div>
477
  </header>
478
 
479
  <!-- Navigation -->
480
  <nav class="nav-container">
481
- <button class="nav-btn active" onclick="showSection('overview')">Overview</button>
482
- <button class="nav-btn" onclick="showSection('team')">Team & Roles</button>
483
- <button class="nav-btn" onclick="showSection('architecture')">Architecture</button>
484
- <button class="nav-btn" onclick="showSection('timeline')">Lifecycle</button>
485
- <button class="nav-btn" onclick="showSection('schema')">Schema & Data</button>
486
- <button class="nav-btn" onclick="showSection('pseudocode')">Implementation</button>
487
  </nav>
488
 
489
  <!-- Main Content -->
@@ -492,165 +549,141 @@
492
  <!-- SECTION: OVERVIEW -->
493
  <div id="overview" class="section active">
494
  <div class="section-header">
495
- <h2 class="section-title">System Overview</h2>
496
- <span class="section-desc">:: EXEC_SUMMARY :: High-level abstraction of the core processing engine.</span>
497
  </div>
498
 
499
  <div class="grid-2">
500
  <div class="card cyan">
501
  <div class="card-title">
502
- <span>North Star Objective</span>
503
- <span class="signal sig-gate">GATE</span>
504
  </div>
505
- <p>Achieve sub-50ms latency in neural inference while maintaining 99.9% accuracy on edge devices. The system must be modular, allowing hot-swapping of transformer layers without downtime.</p>
506
  </div>
507
 
508
- <div class="card purple">
509
  <div class="card-title">
510
- <span>Current Constraints</span>
511
- <span class="signal sig-block">BLOCK</span>
512
  </div>
513
- <p>Memory bandwidth on legacy hardware is the primary bottleneck. Optimization focus is currently on quantization strategies and KV-cache management.</p>
514
  </div>
515
  </div>
516
 
517
  <div style="margin-top: 2rem;">
518
- <div class="card gold">
519
  <div class="card-title">
520
- <span>Core Architecture Diagram</span>
521
  <span class="signal sig-ref">REF</span>
522
  </div>
523
  <div class="diagram-box">
524
- <div class="diag-node">INPUT_STREAM</div>
525
  <div class="diag-arrow">→</div>
526
- <div class="diag-node" style="border-color: var(--purple);">TOKENIZER</div>
527
  <div class="diag-arrow">→</div>
528
- <div class="diag-node" style="border-color: var(--green);">INFERENCE_ENGINE</div>
529
  <div class="diag-arrow">→</div>
530
- <div class="diag-node">OUTPUT_VECTOR</div>
531
  </div>
532
  </div>
533
  </div>
534
  </div>
535
 
536
- <!-- SECTION: TEAM -->
537
- <div id="team" class="section">
538
  <div class="section-header">
539
- <h2 class="section-title">Team & Roles</h2>
540
- <span class="section-desc">:: ORG_CHART :: Ownership matrix and responsibility assignments.</span>
541
  </div>
542
 
543
  <div class="grid-3">
544
- <!-- Role 1 -->
545
  <div class="card cyan role-card">
546
- <div class="role-watermark">LEAD</div>
547
- <span class="role-tag">SYS_ADMIN</span>
548
- <h3 class="role-name">Dr. Aris Thorne</h3>
549
- <div class="role-handle">@aris_core</div>
550
  <ul class="role-list">
551
- <li>System Architecture</li>
552
- <li>Security Protocols</li>
553
- <li>Final Code Review</li>
554
  </ul>
555
  </div>
556
 
557
- <!-- Role 2 -->
558
  <div class="card green role-card">
559
- <div class="role-watermark">DEV</div>
560
- <span class="role-tag">BACKEND</span>
561
- <h3 class="role-name">J. Mercer</h3>
562
- <div class="role-handle">@j_mercer_ops</div>
563
  <ul class="role-list">
564
- <li>API Implementation</li>
565
- <li>Database Sharding</li>
566
- <li>Load Balancing</li>
567
  </ul>
568
  </div>
569
 
570
- <!-- Role 3 -->
571
  <div class="card orange role-card">
572
- <div class="role-watermark">QA</div>
573
- <span class="role-tag">TESTING</span>
574
- <h3 class="role-name">Unit 734</h3>
575
- <div class="role-handle">@unit_734_bot</div>
576
  <ul class="role-list">
577
- <li>Automated Regression</li>
578
- <li>Stress Testing</li>
579
- <li>Edge Case Detection</en>
580
  </ul>
581
  </div>
582
- </div>
583
- </div>
584
 
585
- <!-- SECTION: ARCHITECTURE -->
586
- <div id="architecture" class="section">
587
- <div class="section-header">
588
- <h2 class="section-title">UML & Logic Flow</h2>
589
- <span class="section-desc">:: STRUCTURE :: Component relationships and data propagation paths.</span>
590
- </div>
591
-
592
- <div class="grid-2">
593
- <div class="card">
594
- <div class="card-title">Sequence: Data Ingestion</div>
595
- <div style="font-family: var(--font-mono); font-size: 0.8rem; color: var(--text-muted);">
596
- <div style="margin-bottom: 0.5rem;"><span class="text-cyan">Client</span> -> <span class="text-green">Gateway</span>: POST /ingest</div>
597
- <div style="margin-bottom: 0.5rem;"><span class="text-green">Gateway</span> -> <span class="text-purple">Validator</span>: check_schema()</div>
598
- <div style="margin-bottom: 0.5rem;"><span class="text-purple">Validator</span> -->> <span class="text-green">Gateway</span>: 200 OK</div>
599
- <div style="margin-bottom: 0.5rem;"><span class="text-green">Gateway</span> -> <span class="text-orange">Queue</span>: push_job()</div>
600
- </div>
601
- </div>
602
-
603
- <div class="card">
604
- <div class="card-title">State Machine: Node Health</div>
605
- <div style="display: flex; gap: 0.5rem; flex-wrap: wrap;">
606
- <span class="badge cyan">IDLE</span>
607
- <span class="diag-arrow" style="font-size: 0.8rem">→</span>
608
- <span class="badge orange">LOADING</span>
609
- <span class="diag-arrow" style="font-size: 0.8rem">→</span>
610
- <span class="badge green">ACTIVE</span>
611
- <div style="width: 100%; height: 1px; background: var(--border-subtle); margin: 0.5rem 0;"></div>
612
- <span class="badge green">ACTIVE</span>
613
- <span class="diag-arrow" style="font-size: 0.8rem">→</span>
614
- <span class="badge red">CRITICAL</span>
615
- <span class="diag-arrow" style="font-size: 0.8rem">→</span>
616
- <span class="badge cyan">REBOOT</span>
617
- </div>
618
  </div>
619
  </div>
620
  </div>
621
 
622
- <!-- SECTION: TIMELINE -->
623
- <div id="timeline" class="section">
624
  <div class="section-header">
625
- <h2 class="section-title">Project Lifecycle</h2>
626
- <span class="section-desc">:: CHRONOLOGY :: Phase gates and delivery milestones.</span>
627
  </div>
628
 
629
  <div class="timeline">
630
  <div class="timeline-item done">
631
  <div class="timeline-marker"></div>
632
- <div class="timeline-date">2023-10-01</div>
633
- <div class="timeline-title">Phase 1: Core Infrastructure</div>
634
  <div class="card" style="margin-top: 0.5rem; border: none; background: rgba(255,255,255,0.02); padding: 1rem;">
635
- <span class="signal sig-done">DONE</span> Database schema finalized. Kubernetes cluster provisioned.
636
  </div>
637
  </div>
638
 
639
  <div class="timeline-item active">
640
  <div class="timeline-marker"></div>
641
- <div class="timeline-date">2023-11-15 (CURRENT)</div>
642
- <div class="timeline-title">Phase 2: Neural Integration</div>
643
  <div class="card" style="margin-top: 0.5rem; border: none; background: rgba(255,255,255,0.02); padding: 1rem;">
644
- <span class="signal sig-gate">GATE</span> Integrating transformer weights. Optimizing CUDA kernels.
645
  </div>
646
  </div>
647
 
648
  <div class="timeline-item next">
649
  <div class="timeline-marker"></div>
650
- <div class="timeline-date">2024-01-10</div>
651
- <div class="timeline-title">Phase 3: Public Beta</div>
652
  <div class="card" style="margin-top: 0.5rem; border: none; background: rgba(255,255,255,0.02); padding: 1rem;">
653
- <span class="signal sig-ref">REF</span> API documentation draft. Rate limiting implementation.
654
  </div>
655
  </div>
656
  </div>
@@ -659,107 +692,167 @@
659
  <!-- SECTION: SCHEMA -->
660
  <div id="schema" class="section">
661
  <div class="section-header">
662
- <h2 class="section-title">Data Schema</h2>
663
- <span class="section-desc">:: STRUCT :: SQL definitions and JSON contracts.</span>
664
  </div>
665
 
666
  <div class="card cyan">
667
- <div class="card-title">Table: Users_Context</div>
668
- <pre style="font-family: var(--font-mono); font-size: 0.85rem; color: var(--text-main); overflow-x: auto;">
669
- CREATE TABLE users_context (
670
- id UUID PRIMARY KEY,
671
- user_hash VARCHAR(64) NOT NULL,
672
- session_id VARCHAR(32),
673
- vector_ref BIGINT,
674
- created_at TIMESTAMP DEFAULT NOW(),
675
- status SMALLINT DEFAULT 1 -- 1: Active, 0: Archived
676
- );
677
-
678
- CREATE INDEX idx_user_hash ON users_context(user_hash);
679
- CREATE INDEX idx_vector ON users_context(vector_ref);
680
- </pre>
 
 
 
 
 
 
681
  </div>
682
 
683
- <div class="snapshot" style="margin-top: 2rem;">
684
- <div class="snapshot-header">
685
- <span>SNAPSHOT_ID: #88291A</span>
686
- <span>TIMESTAMP: 14:02:55 UTC</span>
 
 
 
 
 
 
687
  </div>
688
- <div><strong>CONTEXT_STATE:</strong> The current vector store is experiencing high latency. Recommendation: Switch read-replicas to Region-East.</div>
689
- <div style="margin-top: 0.5rem; color: var(--cyan);"><strong>UNRESOLVED:</strong> Memory leak in the garbage collection thread (PID 4421).</div>
690
  </div>
691
  </div>
692
 
693
- <!-- SECTION: PSEUDOCODE -->
694
- <div id="pseudocode" class="section">
695
  <div class="section-header">
696
- <h2 class="section-title">Implementation Logic</h2>
697
- <span class="section-desc">:: ALGO :: Language-agnostic processing steps.</span>
698
  </div>
699
 
700
  <div class="card gold">
701
- <div class="card-title">Function: Process_Inference_Batch</div>
702
- <div class="pseudo">
703
- <span class="ps-kw">function</span> <span class="ps-fn">ProcessBatch</span>(input_batch, model_weights):
704
- <span class="ps-cmt">// Validate input dimensions</span>
705
- <span class="ps-kw">if</span> input_batch.shape[0] != expected_dim:
706
- <span class="ps-kw">return</span> <span class="ps-type">Error</span>(<span class="ps-str">"Dimension Mismatch"</span>)
707
-
708
- <span class="ps-cmt">// Acquire GPU Lock</span>
709
- lock = <span class="ps-fn">GPU_Manager.acquire</span>()
710
-
711
- <span class="ps-kw">try</span>:
712
- <span class="ps-cmt">// Forward Pass</span>
713
- hidden_state = <span class="ps-fn">model.forward</span>(input_batch, weights)
714
-
715
- <span class="ps-cmt">// Apply Softmax</span>
716
- probs = <span class="ps-fn">softmax</span>(hidden_state)
717
-
718
- <span class="ps-kw">return</span> <span class="ps-fn">Decode</span>(probs)
719
-
720
- <span class="ps-kw">except</span> OutOfMemory:
721
- <span class="ps-fn">GPU_Manager.flush_cache</span>()
722
- <span class="ps-kw">raise</span> <span class="ps-type">RetryException</span>()
723
-
724
- <span class="ps-kw">finally</span>:
725
- lock.release()
726
  </div>
727
- </div>
728
- </div>
729
-
730
- </div>
731
-
732
- <!-- JavaScript for Interactivity -->
733
- <script>
734
- function showSection(sectionId) {
735
- // Hide all sections
736
- const sections = document.querySelectorAll('.section');
737
- sections.forEach(sec => {
738
- sec.classList.remove('active');
739
- });
740
-
741
- // Remove active class from nav buttons
742
- const navBtns = document.querySelectorAll('.nav-btn');
743
- navBtns.forEach(btn => {
744
- btn.classList.remove('active');
745
- });
746
-
747
- // Show target section
748
- document.getElementById(sectionId).classList.add('active');
749
-
750
- // Highlight corresponding nav button
751
- // Find the button that calls this function with the specific ID
752
- const activeBtn = Array.from(navBtns).find(btn => btn.getAttribute('onclick').includes(sectionId));
753
- if (activeBtn) {
754
- activeBtn.classList.add('active');
755
- }
756
-
757
- // Scroll to top of content smoothly
758
- window.scrollTo({
759
- top: 0,
760
- behavior: 'smooth'
761
- });
762
- }
763
- </script>
764
- </body>
765
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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>PROJECT: I.O.S. D.F.I.R. // ENHANCEMENT SKELETON</title>
8
  <!-- Import Fonts -->
9
  <link rel="preconnect" href="https://fonts.googleapis.com">
10
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
11
+ <link
12
+ href="https://fonts.googleapis.com/css2?family=Rajdhani:wght@400;500;600;700&family=Share+Tech+Mono&family=Space+Mono:ital,wght@0,400;0,700;1,400&display=swap"
13
+ rel="stylesheet">
14
+
15
  <style>
16
  /* --- CSS VARIABLES & RESET --- */
17
  :root {
 
19
  --bg-panel: #0e1016;
20
  --bg-card: #14161f;
21
  --border-subtle: #2a2f3d;
22
+
23
  --text-main: #e0e6ed;
24
  --text-muted: #94a3b8;
25
+
26
  --font-body: 'Rajdhani', sans-serif;
27
  --font-mono: 'Share Tech Mono', monospace;
28
  --font-meta: 'Space Mono', monospace;
 
59
  width: 100%;
60
  height: 100vh;
61
  z-index: -1;
62
+ background-image:
63
  linear-gradient(rgba(0, 240, 255, 0.03) 1px, transparent 1px),
64
  linear-gradient(90deg, rgba(0, 240, 255, 0.03) 1px, transparent 1px);
65
  background-size: 40px 40px;
 
67
  }
68
 
69
  /* --- TYPOGRAPHY UTILS --- */
70
+ h1,
71
+ h2,
72
+ h3,
73
+ h4 {
74
  text-transform: uppercase;
75
  letter-spacing: 1px;
76
  }
77
+
78
+ .mono {
79
+ font-family: var(--font-mono);
80
+ }
81
+
82
+ .meta {
83
+ font-family: var(--font-meta);
84
+ font-size: 0.85rem;
85
+ }
86
+
87
+ .text-cyan {
88
+ color: var(--cyan);
89
+ }
90
+
91
+ .text-green {
92
+ color: var(--green);
93
+ }
94
+
95
+ .text-orange {
96
+ color: var(--orange);
97
+ }
98
+
99
+ .text-gold {
100
+ color: var(--gold);
101
+ }
102
+
103
+ .text-purple {
104
+ color: var(--purple);
105
+ }
106
+
107
+ .text-red {
108
+ color: var(--red);
109
+ }
110
 
111
  /* --- HEADER --- */
112
  .header {
 
163
  border-radius: 2px;
164
  text-transform: uppercase;
165
  }
166
+
167
+ .badge.cyan {
168
+ border-color: var(--cyan);
169
+ color: var(--cyan);
170
+ }
171
+
172
+ .badge.gold {
173
+ border-color: var(--gold);
174
+ color: var(--gold);
175
+ }
176
+
177
+ .badge.green {
178
+ border-color: var(--green);
179
+ color: var(--green);
180
+ }
181
 
182
  /* --- STICKY NAV --- */
183
  .nav-container {
 
190
  padding: 0.5rem 2rem;
191
  overflow-x: auto;
192
  white-space: nowrap;
193
+ -ms-overflow-style: none;
194
+ scrollbar-width: none;
195
+ }
196
+
197
+ .nav-container::-webkit-scrollbar {
198
+ display: none;
199
  }
 
200
 
201
  .nav-btn {
202
  background: transparent;
 
213
 
214
  .nav-btn:hover {
215
  color: var(--text-main);
216
+ background: rgba(255, 255, 255, 0.03);
217
  }
218
 
219
  .nav-btn.active {
 
233
  display: none;
234
  animation: fadeIn 0.4s ease-out;
235
  }
236
+
237
  .section.active {
238
  display: block;
239
  }
240
 
241
  @keyframes fadeIn {
242
+ from {
243
+ opacity: 0;
244
+ transform: translateY(10px);
245
+ }
246
+
247
+ to {
248
+ opacity: 1;
249
+ transform: translateY(0);
250
+ }
251
  }
252
 
253
  .section-header {
 
277
  }
278
 
279
  .card:hover {
280
+ border-color: rgba(255, 255, 255, 0.1);
281
  }
282
 
283
  .card::before {
 
289
  width: 3px;
290
  }
291
 
292
+ .card.cyan::before {
293
+ background: var(--cyan);
294
+ }
295
+
296
+ .card.green::before {
297
+ background: var(--green);
298
+ }
299
+
300
+ .card.orange::before {
301
+ background: var(--orange);
302
+ }
303
+
304
+ .card.gold::before {
305
+ background: var(--gold);
306
+ }
307
+
308
+ .card.purple::before {
309
+ background: var(--purple);
310
+ }
311
+
312
+ .card.red::before {
313
+ background: var(--red);
314
+ }
315
 
316
  .card-title {
317
  font-family: var(--font-mono);
 
324
  }
325
 
326
  /* --- GRIDS --- */
327
+ .grid-2 {
328
+ display: grid;
329
+ grid-template-columns: 1fr 1fr;
330
+ gap: 1.5rem;
331
+ }
332
+
333
+ .grid-3 {
334
+ display: grid;
335
+ grid-template-columns: repeat(3, 1fr);
336
+ gap: 1.5rem;
337
+ }
338
+
339
+ .grid-4 {
340
+ display: grid;
341
+ grid-template-columns: repeat(4, 1fr);
342
+ gap: 1.5rem;
343
+ }
344
 
345
  @media (max-width: 900px) {
346
+
347
+ .grid-2,
348
+ .grid-3,
349
+ .grid-4 {
350
+ grid-template-columns: 1fr;
351
+ }
352
+
353
+ .header-title {
354
+ font-size: 2.2rem;
355
+ }
356
  }
357
 
358
  /* --- ROLE CARDS --- */
 
413
  color: var(--text-muted);
414
  }
415
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
416
  /* --- SIGNALS & TAGS --- */
417
  .signal {
418
  display: inline-block;
 
423
  border-radius: 2px;
424
  vertical-align: middle;
425
  }
 
 
 
 
426
 
427
+ .sig-ref {
428
+ color: var(--cyan);
429
+ border: 1px solid var(--cyan);
 
 
 
 
 
430
  }
431
+
432
+ .sig-block {
433
+ color: var(--red);
434
+ border: 1px solid var(--red);
435
+ }
436
+
437
+ .sig-done {
438
+ color: var(--green);
439
+ border: 1px solid var(--green);
440
  }
441
 
442
+ .sig-gate {
443
+ color: var(--gold);
444
+ border: 1px solid var(--gold);
445
+ }
446
+
447
+ /* --- CODE BLOCKS --- */
448
+ .code-block {
449
  background: #000;
450
  border: 1px solid var(--border-subtle);
451
  padding: 1rem;
 
453
  font-size: 0.85rem;
454
  overflow-x: auto;
455
  color: #d4d4d4;
456
+ max-height: 600px;
457
+ overflow-y: auto;
458
+ white-space: pre;
459
  }
460
+
461
+ /* Python Syntax Highlighting */
462
+ .py-kw { color: #569cd6; }
463
+ .py-fn { color: #dcdcaa; }
464
+ .py-cmt { color: #6a9955; }
465
+ .py-type { color: #4ec9b0; }
466
+ .py-str { color: #ce9178; }
467
+ .py-dec { color: #c586c0; }
468
 
469
  /* --- DIAGRAMS (CSS ONLY) --- */
470
  .diagram-box {
 
473
  justify-content: center;
474
  gap: 1rem;
475
  padding: 2rem;
476
+ background: rgba(0, 0, 0, 0.2);
477
  border: 1px dashed var(--border-subtle);
478
  }
479
+
480
  .diag-node {
481
  border: 1px solid var(--cyan);
482
  background: rgba(0, 240, 255, 0.1);
 
484
  font-family: var(--font-mono);
485
  font-size: 0.8rem;
486
  }
487
+
488
  .diag-arrow {
489
  color: var(--cyan);
490
  font-size: 1.2rem;
 
501
  border-radius: 4px;
502
  transition: color 0.2s;
503
  }
504
+
505
  .anycoder-link:hover {
506
  color: var(--cyan);
507
  border-color: var(--cyan);
508
  }
 
509
  </style>
510
  </head>
511
+
512
  <body>
513
 
514
  <!-- Background Grid -->
 
517
  <!-- Header -->
518
  <header class="header">
519
  <div class="header-top">
520
+ <span>SYS_REF: DFIR_IOS_V1.0</span>
521
  <span>
522
  <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="anycoder-link">Built with anycoder</a>
523
  </span>
524
  </div>
525
  <div class="header-main">
526
+ <h1 class="header-title">Project <span>DFIR</span> // iOS ENHANCEMENT</h1>
527
+ <p class="header-subtitle">Structured SQLite-backed iOS backup extractor pipeline. Artifact hashing, logging, and extensible parser modules.</p>
528
  <div class="badges">
529
+ <span class="badge cyan">STATUS: SKELETON</span>
530
+ <span class="badge gold">LANG: PYTHON3</span>
531
+ <span class="badge green">LOGGING: ENABLED</span>
532
+ <span class="badge">HASHING: SHA256</span>
533
  </div>
534
  </div>
535
  </header>
536
 
537
  <!-- Navigation -->
538
  <nav class="nav-container">
539
+ <button class="nav-btn active" onclick="showSection('overview')">Manifesto</button>
540
+ <button class="nav-btn" onclick="showSection('modules')">Modules</button>
541
+ <button class="nav-btn" onclick="showSection('pipeline')">Pipeline</button>
542
+ <button class="nav-btn" onclick="showSection('schema')">Data Structs</button>
543
+ <button class="nav-btn" onclick="showSection('source')">Source Code</button>
 
544
  </nav>
545
 
546
  <!-- Main Content -->
 
549
  <!-- SECTION: OVERVIEW -->
550
  <div id="overview" class="section active">
551
  <div class="section-header">
552
+ <h2 class="section-title">System Manifesto</h2>
553
+ <span class="section-desc">:: EXEC_SUMMARY :: Purpose and operational goals of the DFIR skeleton.</span>
554
  </div>
555
 
556
  <div class="grid-2">
557
  <div class="card cyan">
558
  <div class="card-title">
559
+ <span>Primary Objective</span>
560
+ <span class="signal sig-gate">CORE</span>
561
  </div>
562
+ <p>Upgrade simple SQLite-backed iOS backup extractors into a structured DFIR pipeline. Preserve analyst visibility, logging, and artifact hashing.</p>
563
  </div>
564
 
565
+ <div class="card gold">
566
  <div class="card-title">
567
+ <span>Current Status</span>
568
+ <span class="signal sig-ref">DEV</span>
569
  </div>
570
+ <p>This file is intentionally verbose. Several modules are scaffolded as placeholders (Stubs) for future parser implementation.</p>
571
  </div>
572
  </div>
573
 
574
  <div style="margin-top: 2rem;">
575
+ <div class="card purple">
576
  <div class="card-title">
577
+ <span>Operational Flow</span>
578
  <span class="signal sig-ref">REF</span>
579
  </div>
580
  <div class="diagram-box">
581
+ <div class="diag-node">CLI_ARGS</div>
582
  <div class="diag-arrow">→</div>
583
+ <div class="diag-node" style="border-color: var(--purple);">MANIFEST_DB</div>
584
  <div class="diag-arrow">→</div>
585
+ <div class="diag-node" style="border-color: var(--green);">PARSER_MODULES</div>
586
  <div class="diag-arrow">→</div>
587
+ <div class="diag-node">TIMELINE_CSV</div>
588
  </div>
589
  </div>
590
  </div>
591
  </div>
592
 
593
+ <!-- SECTION: MODULES -->
594
+ <div id="modules" class="section">
595
  <div class="section-header">
596
+ <h2 class="section-title">Parser Modules</h2>
597
+ <span class="section-desc">:: AGENTS :: Specialized extraction subroutines.</span>
598
  </div>
599
 
600
  <div class="grid-3">
601
+ <!-- Module 1 -->
602
  <div class="card cyan role-card">
603
+ <div class="role-watermark">CORE</div>
604
+ <span class="role-tag">CONTACTS</span>
605
+ <h3 class="role-name">AddressBook Parser</h3>
606
+ <div class="role-handle">export_contacts()</div>
607
  <ul class="role-list">
608
+ <li>Modern & Legacy Schema</li>
609
+ <li>Phone Normalization</li>
610
+ <li>CSV/JSON Export</li>
611
  </ul>
612
  </div>
613
 
614
+ <!-- Module 2 -->
615
  <div class="card green role-card">
616
+ <div class="role-watermark">CORE</div>
617
+ <span class="role-tag">MESSAGING</span>
618
+ <h3 class="role-name">SMS / iMessage</h3>
619
+ <div class="role-handle">extract_sms()</div>
620
  <ul class="role-list">
621
+ <li>Handle Resolution</li>
622
+ <li>AttributedBody Stub</li>
623
+ <li>Timeline Event Gen</li>
624
  </ul>
625
  </div>
626
 
627
+ <!-- Module 3 -->
628
  <div class="card orange role-card">
629
+ <div class="role-watermark">GEO</div>
630
+ <span class="role-tag">LOCATION</span>
631
+ <h3 class="role-name">LocationD / Cache</h3>
632
+ <div class="role-handle">extract_locations()</div>
633
  <ul class="role-list">
634
+ <li>RTCL Location MO</li>
635
+ <li>Visit MO Parsing</li>
636
+ <li>Cell Tower Logs</li>
637
  </ul>
638
  </div>
 
 
639
 
640
+ <!-- Module 4 -->
641
+ <div class="card red role-card">
642
+ <div class="role-watermark">STUB</div>
643
+ <span class="role-tag">FUTURE</span>
644
+ <h3 class="role-name">Safari / Notes</h3>
645
+ <div class="role-handle">extract_safari_stub()</div>
646
+ <ul class="role-list">
647
+ <li>History / Downloads</li>
648
+ <li>Rich Notes</li>
649
+ <li>App Containers</li>
650
+ </ul>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
651
  </div>
652
  </div>
653
  </div>
654
 
655
+ <!-- SECTION: PIPELINE -->
656
+ <div id="pipeline" class="section">
657
  <div class="section-header">
658
+ <h2 class="section-title">Execution Pipeline</h2>
659
+ <span class="section-desc">:: LOGIC :: The `run()` orchestration sequence.</span>
660
  </div>
661
 
662
  <div class="timeline">
663
  <div class="timeline-item done">
664
  <div class="timeline-marker"></div>
665
+ <div class="timeline-date">STEP 1</div>
666
+ <div class="timeline-title">Initialization</div>
667
  <div class="card" style="margin-top: 0.5rem; border: none; background: rgba(255,255,255,0.02); padding: 1rem;">
668
+ <span class="signal sig-done">DONE</span> Setup Logging. Validate Backup Root. Parse CLI Arguments.
669
  </div>
670
  </div>
671
 
672
  <div class="timeline-item active">
673
  <div class="timeline-marker"></div>
674
+ <div class="timeline-date">STEP 2</div>
675
+ <div class="timeline-title">Manifest Indexing</div>
676
  <div class="card" style="margin-top: 0.5rem; border: none; background: rgba(255,255,255,0.02); padding: 1rem;">
677
+ <span class="signal sig-gate">ACTIVE</span> Load `Manifest.db`. Search for `sms.db`, `AddressBook`, and Location artifacts.
678
  </div>
679
  </div>
680
 
681
  <div class="timeline-item next">
682
  <div class="timeline-marker"></div>
683
+ <div class="timeline-date">STEP 3</div>
684
+ <div class="timeline-title">Extraction & Export</div>
685
  <div class="card" style="margin-top: 0.5rem; border: none; background: rgba(255,255,255,0.02); padding: 1rem;">
686
+ <span class="signal sig-ref">NEXT</span> Run Parser Modules. Generate CSV/JSON. Build Unified Timeline.
687
  </div>
688
  </div>
689
  </div>
 
692
  <!-- SECTION: SCHEMA -->
693
  <div id="schema" class="section">
694
  <div class="section-header">
695
+ <h2 class="section-title">Data Structures</h2>
696
+ <span class="section-desc">:: STRUCT :: Python Dataclasses used for typing.</span>
697
  </div>
698
 
699
  <div class="card cyan">
700
+ <div class="card-title">Config & Metadata</div>
701
+ <div class="code-block" style="max-height: 400px;">
702
+ <span class="py-dec">@dataclass</span>
703
+ <span class="py-kw">class</span> <span class="py-type">CaseMetadata</span>:
704
+ case_name: <span class="py-type">str</span> = <span class="py-str">"UNSPECIFIED_CASE"</span>
705
+ examiner: <span class="py-type">str</span> = <span class="py-str">"UNSPECIFIED_EXAMINER"</span>
706
+ evidence_id: <span class="py-type">str</span> = <span class="py-str">"UNSPECIFIED_EVIDENCE"</span>
707
+
708
+ <span class="py-dec">@dataclass</span>
709
+ <span class="py-kw">class</span> <span class="py-type">AppConfig</span>:
710
+ backup_root: <span class="py-type">Path</span>
711
+ manifest_db: <span class="py-type">Path</span>
712
+ output_root: <span class="py-type">Path</span>
713
+ query_terms: <span class="py-type">List</span>[<span class="py-type">str</span>] = field(default_factory=<span class="py-type">list</span>)
714
+ verbose: <span class="py-type">bool</span> = <span class="py-kw">False</span>
715
+ hash_exports: <span class="py-type">bool</span> = <span class="py-kw">True</span>
716
+ copy_raw_files: <span class="py-type">bool</span> = <span class="py-kw">True</span>
717
+ export_csv: <span class="py-type">bool</span> = <span class="py-kw">True</span>
718
+ export_jsonl: <span class="py-type">bool</span> = <span class="py-kw">True</span>
719
+ </div>
720
  </div>
721
 
722
+ <div class="card purple" style="margin-top: 1.5rem;">
723
+ <div class="card-title">Timeline Event Model</div>
724
+ <div class="code-block" style="max-height: 300px;">
725
+ <span class="py-dec">@dataclass</span>
726
+ <span class="py-kw">class</span> <span class="py-type">TimelineEvent</span>:
727
+ timestamp: <span class="py-type">Optional</span>[<span class="py-type">str</span>]
728
+ artifact_type: <span class="py-type">str</span>
729
+ source_file: <span class="py-type">str</span>
730
+ summary: <span class="py-type">str</span>
731
+ attributes: <span class="py-type">Dict</span>[<span class="py-type">str</span>, <span class="py-type">Any</span>] = field(default_factory=<span class="py-type">dict</span>)
732
  </div>
 
 
733
  </div>
734
  </div>
735
 
736
+ <!-- SECTION: SOURCE -->
737
+ <div id="source" class="section">
738
  <div class="section-header">
739
+ <h2 class="section-title">Source Implementation</h2>
740
+ <span class="section-desc">:: CODE :: The complete Python script logic.</span>
741
  </div>
742
 
743
  <div class="card gold">
744
+ <div class="card-title">
745
+ <span>dfir_ios_enhancement.py</span>
746
+ <span class="signal sig-done">READY</span>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
747
  </div>
748
+ <div class="code-block" style="font-size: 0.75rem; line-height: 1.4;">
749
+ <span class="py-cmt">#!/usr/bin/env python3</span>
750
+ <span class="py-cmt">""" DFIR iOS Backup Enhancement Skeleton """</span>
751
+
752
+ <span class="py-kw">from</span> __future__ <span class="py-kw">import</span> annotations
753
+ <span class="py-kw">import</span> argparse, csv, dataclasses, hashlib, json, logging, os, shutil, sqlite3, sys, traceback
754
+ <span class="py-kw">from</span> dataclasses <span class="py-kw">import</span> dataclass, field
755
+ <span class="py-kw">from</span> datetime <span class="py-kw">import</span> datetime, timedelta, timezone
756
+ <span class="py-kw">from</span> pathlib <span class="py-kw">import</span> Path
757
+ <span class="py-kw">from</span> typing <span class="py-kw">import</span> Any, Dict, Iterable, List, Optional, Tuple
758
+
759
+ <span class="py-type">APPLE_EPOCH</span> = datetime(<span class="py-str">2001</span>, <span class="py-str">1</span>, <span class="py-str">1</span>, tzinfo=timezone.utc)
760
+
761
+ <span class="py-cmt"># ============================================================</span>
762
+ <span class="py-cmt"># CONFIG / DATA MODELS</span>
763
+ <span class="py-cmt"># ============================================================</span>
764
+
765
+ <span class="py-dec">@dataclass</span>
766
+ <span class="py-kw">class</span> <span class="py-type">CaseMetadata</span>:
767
+ case_name: <span class="py-type">str</span> = <span class="py-str">"UNSPECIFIED_CASE"</span>
768
+ examiner: <span class="py-type">str</span> = <span class="py-str">"UNSPECIFIED_EXAMINER"</span>
769
+ evidence_id: <span class="py-type">str</span> = <span class="py-str">"UNSPECIFIED_EVIDENCE"</span>
770
+ notes: <span class="py-type">str</span> = <span class="py-str">""</span>
771
+
772
+ <span class="py-dec">@dataclass</span>
773
+ <span class="py-kw">class</span> <span class="py-type">AppConfig</span>:
774
+ backup_root: <span class="py-type">Path</span>
775
+ manifest_db: <span class="py-type">Path</span>
776
+ output_root: <span class="py-type">Path</span>
777
+ query_terms: <span class="py-type">List</span>[<span class="py-type">str</span>] = field(default_factory=<span class="py-type">list</span>)
778
+ verbose: <span class="py-type">bool</span> = <span class="py-kw">False</span>
779
+ hash_exports: <span class="py-type">bool</span> = <span class="py-kw">True</span>
780
+ copy_raw_files: <span class="py-type">bool</span> = <span class="py-kw">True</span>
781
+ export_csv: <span class="py-type">bool</span> = <span class="py-kw">True</span>
782
+ export_jsonl: <span class="py-type">bool</span> = <span class="py-kw">True</span>
783
+ export_kml: <span class="py-type">bool</span> = <span class="py-kw">False</span>
784
+ export_geojson: <span class="py-type">bool</span> = <span class="py-kw">False</span>
785
+ case: <span class="py-type">CaseMetadata</span> = field(default_factory=<span class="py-type">CaseMetadata</span>)
786
+
787
+ <span class="py-dec">@dataclass</span>
788
+ <span class="py-kw">class</span> <span class="py-type">LocatedFile</span>:
789
+ file_id: <span class="py-type">str</span>
790
+ relative_path: <span class="py-type">str</span>
791
+ domain: <span class="py-type">Optional</span>[<span class="py-type">str</span>]
792
+ source_path: <span class="py-type">Path</span>
793
+
794
+ <span class="py-dec">@dataclass</span>
795
+ <span class="py-kw">class</span> <span class="py-type">TimelineEvent</span>:
796
+ timestamp: <span class="py-type">Optional</span>[<span class="py-type">str</span>]
797
+ artifact_type: <span class="py-type">str</span>
798
+ source_file: <span class="py-type">str</span>
799
+ summary: <span class="py-type">str</span>
800
+ attributes: <span class="py-type">Dict</span>[<span class="py-type">str</span>, <span class="py-type">Any</span>] = field(default_factory=<span class="py-type">dict</span>)
801
+
802
+ <span class="py-cmt"># ============================================================</span>
803
+ <span class="py-cmt"># LOGGING</span>
804
+ <span class="py-cmt"># ============================================================</span>
805
+
806
+ <span class="py-kw">def</span> <span class="py-fn">setup_logging</span>(output_root: <span class="py-type">Path</span>, verbose: <span class="py-type">bool</span> = <span class="py-kw">False</span>) -> logging.<span class="py-type">Logger</span>:
807
+ output_root.mkdir(parents=<span class="py-kw">True</span>, exist_ok=<span class="py-kw">True</span>)
808
+ log_path = output_root / <span class="py-str">"dfir_run.log"</span>
809
+ logger = logging.getLogger(<span class="py-str">"dfir_ios"</span>)
810
+ logger.setLevel(logging.DEBUG <span class="py-kw">if</span> verbose <span class="py-kw">else</span> logging.INFO)
811
+ logger.handlers.clear()
812
+ fmt = logging.Formatter(<span class="py-str">"%(asctime)s | %(levelname)s | %(message)s"</span>)
813
+ fh = logging.FileHandler(log_path, encoding=<span class="py-str">"utf-8"</span>)
814
+ fh.setLevel(logging.DEBUG)
815
+ fh.setFormatter(fmt)
816
+ logger.addHandler(fh)
817
+ sh = logging.StreamHandler(sys.stdout)
818
+ sh.setLevel(logging.DEBUG <span class="py-kw">if</span> verbose <span class="py-kw">else</span> logging.INFO)
819
+ sh.setFormatter(fmt)
820
+ logger.addHandler(sh)
821
+ logger.debug(<span class="py-str">"Logging initialized"</span>)
822
+ <span class="py-kw">return</span> logger
823
+
824
+ <span class="py-cmt"># ============================================================</span>
825
+ <span class="py-cmt"># UTILS</span>
826
+ <span class="py-cmt"># ============================================================</span>
827
+
828
+ <span class="py-kw">def</span> <span class="py-fn">apple_time_to_datetime</span>(ts: <span class="py-type">Any</span>) -> <span class="py-type">Optional</span>[datetime]:
829
+ <span class="py-kw">if</span> ts <span class="py-kw">is</span> <span class="py-kw">None</span>: <span class="py-kw">return</span> <span class="py-kw">None</span>
830
+ <span class="py-kw">try</span>:
831
+ ts = <span class="py-type">float</span>(ts)
832
+ <span class="py-kw">if</span> ts > <span class="py-str">1e12</span>: ts = ts / <span class="py-str">1e9</span>
833
+ <span class="py-kw">return</span> <span class="py-type">APPLE_EPOCH</span> + timedelta(seconds=ts)
834
+ <span class="py-kw">except</span> <span class="py-type">Exception</span>: <span class="py-kw">return</span> <span class="py-kw">None</span>
835
+
836
+ <span class="py-kw">def</span> <span class="py-fn">normalize_phone</span>(phone: <span class="py-type">Optional</span>[<span class="py-type">str</span>]) -> <span class="py-type">Optional</span>[<span class="py-type">str</span>]:
837
+ <span class="py-kw">if</span> <span class="py-kw">not</span> phone: <span class="py-kw">return</span> phone
838
+ value = <span class="py-type">str</span>(phone).replace(<span class="py-str">"+1"</span>, <span class="py-str">""</span>).replace(<span class="py-str">" "</span>, <span class="py-str">""</span>).replace(<span class="py-str">"-"</span>, <span class="py-str">""</span>).replace(<span class="py-str">"("</span>, <span class="py-str">""</span>).replace(<span class="py-str">")"</span>, <span class="py-str">""</span>)
839
+ <span class="py-kw">return</span> value.strip() <span class="py-kw">or</span> <span class="py-kw">None</span>
840
+
841
+ <span class="py-kw">def</span> <span class="py-fn">sha256_file</span>(path: <span class="py-type">Path</span>, chunk_size: <span class="py-type">int</span> = <span class="py-str">1024</span> * <span class="py-str">1024</span>) -> <span class="py-type">str</span>:
842
+ h = hashlib.sha256()
843
+ <span class="py-kw">with</span> path.open(<span class="py-str">"rb"</span>) <span class="py-kw">as</span> f:
844
+ <span class="py-kw">while</span> <span class="py-kw">True</span>:
845
+ chunk = f.read(chunk_size)
846
+ <span class="py-kw">if</span> <span class="py-kw">not</span> chunk: <span class="py-kw">break</span>
847
+ h.update(chunk)
848
+ <span class="py-kw">return</span> h.hexdigest()
849
+
850
+ <span class="py-cmt"># ... [Manifest Access Layer and Extraction Logic Truncated for Brevity in View] ...</span>
851
+
852
+ <span class="py-cmt"># ============================================================</span>
853
+ <span class="py-cmt"># MAIN ORCHESTRATION</span>
854
+ <span class="py-cmt"># ============================================================</span>
855
+
856
+ <span class="py-kw">def</span> <span class="py-fn">run</span>(cfg: <span class="py-type">AppConfig</span>) -> <span class="py-type">int</span>:
857
+ logger = setup_logging(cfg.output_root, cfg.verbose)
858
+ logger.info(<span class="py-str">"Starting DFIR iOS backup extraction"</span>)