backbone-storage 3.7.1

Backbone Framework Storage Module - Local file system support
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
# Backbone Storage

๐Ÿฆด **Production-ready local filesystem storage with comprehensive file management**

Backbone Storage provides a robust, feature-rich local filesystem storage solution with support for file uploads, downloads, metadata management, streaming, and security features. Designed for production use with comprehensive error handling and async support.

## ๐Ÿ“‹ Table of Contents

- [Overview]#overview
- [Features]#features
- [Usage]#usage
- [Configuration]#configuration
- [Technical Details]#technical-details
- [Examples]#examples
- [Error Handling]#error-handling
- [Testing]#testing

## ๐ŸŽฏ Overview

Backbone Storage provides a complete file storage solution focused on local filesystem operations. It includes all essential storage features like file uploads, downloads, metadata management, directory traversal, and security scanning capabilities.

### Key Design Principles

- **Local First**: Optimized for reliable local filesystem storage
- **Async Native**: Full async/await support with tokio
- **Security Aware**: Built-in virus scanning and file validation
- **Metadata Rich**: Comprehensive file metadata and statistics
- **Production Ready**: Robust error handling and recovery

## ๐Ÿš€ Features

### ๐Ÿ“ **Core Storage Features**
- **File Upload/Download**: Support for bytes, readers, and file uploads
- **Streaming**: Async file streaming with range support
- **Metadata Management**: Rich file metadata with timestamps and hashes
- **Directory Operations**: File listing with pagination and filtering
- **File Operations**: Copy, move, delete with proper error handling

### ๐Ÿ›ก๏ธ **Security & Safety**
- **Path Sanitization**: Prevents directory traversal attacks
- **File Type Detection**: MIME type detection and validation
- **Hash Verification**: File integrity checking
- **Virus Scanning**: Integration with security analysis (optional)
- **Permission Validation**: Filesystem permission checking

### ๐Ÿ“Š **Advanced Features**
- **Compression**: Built-in file compression support (optional)
- **Presigned URLs**: Generate file access URLs
- **Statistics**: Storage usage and file count analytics
- **Builder Pattern**: Fluent configuration API
- **Generic Trait**: Extensible StorageService trait

## ๐Ÿ“– Usage

### Quick Start

```toml
[dependencies]
backbone-storage = "2.0.0"
tokio = { version = "1.0", features = ["full"] }
bytes = "1.0"
serde = { version = "1.0", features = ["derive"] }
uuid = { version = "1.0", features = ["v4"] }
chrono = { version = "0.4", features = ["serde"] }
```

### Basic File Operations

```rust
use backbone_storage::{StorageService, LocalStorage};
use bytes::Bytes;

// Create local storage service
let storage = LocalStorage::new(config)?;

// Upload file from bytes
let file_data = Bytes::from("Hello, Backbone Storage!");
let uploaded_file = storage.upload_bytes("greeting.txt", file_data, None).await?;
println!("File uploaded: {}", uploaded_file.name);

// Download file as bytes
let downloaded_data = storage.download_bytes("greeting.txt", None).await?;
println!("File content: {}", String::from_utf8_lossy(&downloaded_data));

// Check if file exists
let exists = storage.file_exists("greeting.txt").await?;
println!("File exists: {}", exists);
```

### File Upload from Reader

```rust
use backbone_storage::{StorageService, LocalStorage};
use tokio::fs::File;
use tokio::io::BufReader;

// Create storage service
let storage = LocalStorage::new(config)?;

// Upload file from async reader
let file = File::open("large_file.zip").await?;
let reader = Box::new(BufReader::new(file));

let uploaded_file = storage.upload_reader(
    "uploads/large_file.zip",
    reader,
    Some(1024 * 1024 * 50), // 50MB
    None
).await?;

println!("Large file uploaded: {} ({} bytes)",
         uploaded_file.name, uploaded_file.size);
```

### File Listing and Metadata

```rust
use backbone_storage::{StorageService, LocalStorage};

// Create storage service
let storage = LocalStorage::new(config)?;

// List files in directory
let files = storage.list_files("", Some(20), None).await?;
println!("Found {} files:", files.total_count.unwrap_or(0));

for file in &files.files {
    println!("  {} - {} bytes ({})",
             file.name, file.size, file.content_type);
}

// Get specific file metadata
let file = storage.get_file("documents/report.pdf").await?;
println!("File: {}", file.name);
println!("  Size: {} bytes", file.size);
println!("  Type: {}", file.content_type);
println!("  Created: {}", file.created_at);
println!("  Modified: {:?}", file.updated_at);
println!("  Checksum: {}", file.checksum.as_ref().unwrap_or(&"N/A".to_string()));
```

### File Streaming

```rust
use backbone_storage::{StorageService, LocalStorage};
use futures::StreamExt;

// Create storage service
let storage = LocalStorage::new(config)?;

// Stream file content
let mut stream = storage.stream_file("large_video.mp4", None).await?;

// Process stream in chunks
let mut total_bytes = 0;
while let Some(chunk_result) = stream.next().await {
    match chunk_result {
        Ok(chunk) => {
            total_bytes += chunk.len();
            println!("Received {} bytes (total: {})", chunk.len(), total_bytes);
            // Process chunk...
        }
        Err(e) => {
            eprintln!("Stream error: {}", e);
            break;
        }
    }
}

println!("Streamed {} bytes total", total_bytes);
```

### File Operations

```rust
use backbone_storage::{StorageService, LocalStorage};

// Create storage service
let storage = LocalStorage::new(config)?;

// Copy file
let copied_file = storage.copy_file(
    "source/document.pdf",
    "backup/document_copy.pdf"
).await?;
println!("File copied: {}", copied_file.name);

// Move file
let moved_file = storage.move_file(
    "temp/upload.tmp",
    "documents/final.pdf"
).await?;
println!("File moved: {}", moved_file.name);

// Delete file
let deleted = storage.delete_file("old_file.txt").await?;
println!("File deleted: {}", deleted);
```

### Storage Statistics

```rust
use backbone_storage::{StorageService, LocalStorage};

// Create storage service
let storage = LocalStorage::new(config)?;

// Get storage statistics
let stats = storage.get_stats().await?;
println!("Storage Statistics:");
println!("  Total files: {}", stats.file_count);
println!("  Total size: {} bytes", stats.total_bytes);
println!("  Average file size: {:.2} bytes", stats.average_file_size);
println!("  Last updated: {}", stats.last_updated);

// Backend usage
for (backend, bytes) in &stats.backend_usage {
    println!("  {}: {} bytes", backend, bytes);
}

// Content type distribution
for (content_type, count) in &stats.content_type_counts {
    println!("  {}: {} files", content_type, count);
}
```

## ๐Ÿ”ง Configuration

### Basic Configuration

```rust
use backbone_storage::{LocalStorage, LocalStorageConfig};

// Simple configuration
let config = LocalStorageConfig {
    base_dir: "./storage".to_string(),
    base_path: None,
    compression: false,
    encryption: None,
};

let storage = LocalStorage::new(config)?;
```

### Builder Pattern Configuration

```rust
use backbone_storage::{LocalStorage, LocalStorageBuilder};

// Advanced configuration with builder
let storage = LocalStorage::builder()
    .base_dir("./app_storage")
    .compression(true)
    .build()?;
```

### Directory Structure

```
./storage/
โ”œโ”€โ”€ uploads/
โ”‚   โ”œโ”€โ”€ documents/
โ”‚   โ”‚   โ”œโ”€โ”€ report.pdf
โ”‚   โ”‚   โ””โ”€โ”€ invoice.docx
โ”‚   โ”œโ”€โ”€ images/
โ”‚   โ”‚   โ”œโ”€โ”€ logo.png
โ”‚   โ”‚   โ””โ”€โ”€ banner.jpg
โ”‚   โ””โ”€โ”€ temp/
โ”‚       โ””โ”€โ”€ upload.tmp
โ”œโ”€โ”€ backups/
โ””โ”€โ”€ archives/
```

## ๐Ÿ”ง Technical Details

### Core Traits

#### StorageService Trait

```rust
#[async_trait]
pub trait StorageService: Send + Sync {
    // Upload operations
    async fn upload_bytes(&self, path: &str, data: Bytes, options: Option<UploadOptions>) -> StorageResult<StorageFile>;
    async fn upload_reader(&self, path: &str, reader: Box<dyn AsyncRead + Send + Unpin>, size: Option<u64>, options: Option<UploadOptions>) -> StorageResult<StorageFile>;
    async fn upload_file(&self, path: &str, local_path: &str, options: Option<UploadOptions>) -> StorageResult<StorageFile>;

    // Download operations
    async fn download_bytes(&self, path: &str, options: Option<DownloadOptions>) -> StorageResult<Bytes>;
    async fn download_writer(&self, path: &str, writer: Box<dyn AsyncWrite + Send + Unpin>, options: Option<DownloadOptions>) -> StorageResult<()>;
    async fn download_file(&self, path: &str, local_path: &str, options: Option<DownloadOptions>) -> StorageResult<()>;
    async fn stream_file(&self, path: &str, range: Option<ByteRange>) -> StorageResult<Box<dyn Stream<Item = StorageResult<Bytes>> + Send + Unpin>>;

    // File operations
    async fn get_file(&self, path: &str) -> StorageResult<StorageFile>;
    async fn file_exists(&self, path: &str) -> StorageResult<bool>;
    async fn delete_file(&self, path: &str) -> StorageResult<bool>;
    async fn copy_file(&self, from_path: &str, to_path: &str) -> StorageResult<StorageFile>;
    async fn move_file(&self, from_path: &str, to_path: &str) -> StorageResult<StorageFile>;

    // Directory operations
    async fn list_files(&self, prefix: &str, limit: Option<u32>, continuation_token: Option<String>) -> StorageResult<FileListResult>;

    // Utility operations
    async fn generate_presigned_url(&self, path: &str, options: PresignedUrlOptions) -> StorageResult<String>;
    async fn get_stats(&self) -> StorageResult<StorageStats>;
    async fn test_connection(&self) -> StorageResult<bool>;
}
```

### Data Types

#### StorageFile
```rust
pub struct StorageFile {
    pub id: String,
    pub name: String,
    pub size: u64,
    pub content_type: String,
    pub checksum: Option<String>,
    pub checksum_algorithm: Option<String>,
    pub metadata: HashMap<String, String>,
    pub created_at: DateTime<Utc>,
    pub updated_at: Option<DateTime<Utc>>,
    pub version: Option<String>,
    pub backend: StorageBackend,
    pub bucket: String,
    pub storage_path: String,
    pub encrypted: bool,
    pub compressed: bool,
    pub expires_at: Option<DateTime<Utc>>,
}
```

#### StorageStats
```rust
pub struct StorageStats {
    pub file_count: u64,
    pub total_bytes: u64,
    pub backend_usage: HashMap<String, u64>,
    pub content_type_counts: HashMap<String, u64>,
    pub average_file_size: f64,
    pub largest_file_size: u64,
    pub last_updated: DateTime<Utc>,
}
```

### Error Handling

```rust
#[derive(Debug, thiserror::Error)]
pub enum StorageError {
    #[error("Configuration error: {0}")]
    InvalidConfiguration(String),

    #[error("File not found: {0}")]
    FileNotFound(String),

    #[error("File already exists: {0}")]
    FileAlreadyExists(String),

    #[error("Filesystem error: {0}")]
    FilesystemError(#[from] std::io::Error),

    #[error("File too large: {size} bytes, maximum allowed: {max_size} bytes")]
    FileTooLarge { size: u64, max_size: u64 },

    #[error("Invalid file format: {0}")]
    InvalidFileFormat(String),

    #[error("Security error: {operation} - {message}")]
    SecurityError { operation: String, message: String },

    #[error("Unsupported operation '{operation}' for backend '{backend}'")]
    UnsupportedOperation { operation: String, backend: String },
}
```

## ๐Ÿ“š Examples

### 1. File Upload Service

```rust
use backbone_storage::{StorageService, LocalStorage};
use tokio::fs::File;

async fn upload_user_file(
    storage: &dyn StorageService,
    user_id: &str,
    filename: &str,
    file_path: &str
) -> Result<backbone_storage::StorageFile, Box<dyn std::error::Error>> {
    // Sanitize and construct storage path
    let storage_path = format!("users/{}/files/{}", user_id, filename);

    // Upload file
    let uploaded_file = storage.upload_file(&storage_path, file_path, None).await?;

    println!("File uploaded successfully:");
    println!("  Original: {}", filename);
    println!("  Storage: {}", uploaded_file.storage_path);
    println!("  Size: {} bytes", uploaded_file.size);

    Ok(uploaded_file)
}
```

### 2. Backup Service

```rust
use backbone_storage::{StorageService, LocalStorage};

async fn create_backup(
    storage: &dyn StorageService,
    source_path: &str,
    backup_name: &str
) -> Result<backbone_storage::StorageFile, Box<dyn std::error::Error>> {
    // Generate backup timestamp
    let timestamp = chrono::Utc::now().format("%Y%m%d_%H%M%S");
    let backup_path = format!("backups/{}/{}_{}", backup_name, timestamp, source_path);

    // Copy file to backup location
    let backup_file = storage.copy_file(source_path, &backup_path).await?;

    println!("Backup created: {}", backup_file.storage_path);
    println!("Backup size: {} bytes", backup_file.size);

    Ok(backup_file)
}
```

### 3. File Processing Pipeline

```rust
use backbone_storage::{StorageService, LocalStorage};
use futures::StreamExt;

async fn process_uploaded_file(
    storage: &dyn StorageService,
    file_path: &str
) -> Result<(), Box<dyn std::error::Error>> {
    // Get file metadata
    let file = storage.get_file(file_path).await?;
    println!("Processing file: {} ({} bytes)", file.name, file.size);

    // Stream file for processing
    let mut stream = storage.stream_file(file_path, None).await?;
    let mut processed_bytes = 0;

    while let Some(chunk_result) = stream.next().await {
        match chunk_result {
            Ok(chunk) => {
                // Process chunk (e.g., scan for viruses, transform, etc.)
                processed_bytes += chunk.len();
                println!("Processed {} bytes", processed_bytes);
            }
            Err(e) => {
                eprintln!("Error processing file: {}", e);
                return Err(e.into());
            }
        }
    }

    // Move to processed directory
    let processed_path = file_path.replace("uploads/", "processed/");
    let final_file = storage.move_file(file_path, &processed_path).await?;

    println!("File processing complete: {}", final_file.storage_path);
    Ok(())
}
```

### 4. Storage Monitoring

```rust
use backbone_storage::StorageService;

async fn monitor_storage_usage(storage: &dyn StorageService) -> Result<(), Box<dyn std::error::Error>> {
    let stats = storage.get_stats().await?;

    println!("๐Ÿ“Š Storage Usage Report");
    println!("======================");
    println!("Total files: {}", stats.file_count);
    println!("Total size: {:.2} MB", stats.total_bytes as f64 / 1024.0 / 1024.0);
    println!("Average file size: {:.2} KB", stats.average_file_size / 1024.0);
    println!("Last updated: {}", stats.last_updated);

    println!("\n๐Ÿ“ File Types:");
    let mut content_types: Vec<_> = stats.content_type_counts.iter().collect();
    content_types.sort_by(|a, b| b.1.cmp(a.1)); // Sort by count

    for (content_type, count) in content_types.iter().take(10) {
        println!("  {}: {} files", content_type, count);
    }

    // Storage usage warning
    const SIZE_LIMIT_MB: u64 = 1024; // 1GB limit
    let size_mb = stats.total_bytes / 1024 / 1024;

    if size_mb > SIZE_LIMIT_MB {
        println!("\nโš ๏ธ  Storage usage warning: {:.2} MB used (limit: {} MB)",
                 size_mb, SIZE_LIMIT_MB);
    }

    Ok(())
}
```

## ๐Ÿ”ง Error Handling

### Comprehensive Error Recovery

```rust
use backbone_storage::{StorageService, StorageError};

async fn safe_file_operation(
    storage: &dyn StorageService,
    operation: String
) -> Result<(), Box<dyn std::error::Error>> {
    match storage.test_connection().await {
        Ok(true) => println!("โœ… Storage service is healthy"),
        Ok(false) => {
            println!("โŒ Storage service connection failed");
            return Err("Storage service unavailable".into());
        }
        Err(e) => {
            println!("โŒ Storage service error: {}", e);
            return Err(e.into());
        }
    }

    // Perform operation with error handling
    match storage.file_exists("test.txt").await {
        Ok(exists) => println!("File exists check: {}", exists),
        Err(StorageError::FileNotFound(path)) => {
            println!("File not found: {}", path);
        }
        Err(StorageError::FilesystemError(e)) => {
            eprintln!("Filesystem error: {}", e);
            return Err(e.into());
        }
        Err(e) => {
            eprintln!("Unexpected error: {}", e);
            return Err(e.into());
        }
    }

    Ok(())
}
```

## ๐Ÿงช Testing

### Unit Tests

```bash
# Run all backbone-storage tests
cargo test --package backbone-storage

# Run specific tests
cargo test --package backbone-storage -- -- upload
cargo test --package backbone-storage -- -- download
cargo test --package backbone-storage -- -- metadata
```

### Integration Tests

```rust
use backbone_storage::{StorageService, LocalStorage};
use tempfile::TempDir;

#[tokio::test]
async fn test_file_operations() -> Result<(), Box<dyn std::error::Error>> {
    // Create temporary directory for testing
    let temp_dir = TempDir::new()?;
    let config = backbone_storage::LocalStorageConfig {
        base_dir: temp_dir.path().to_string_lossy().to_string(),
        base_path: None,
        compression: false,
        encryption: None,
    };

    let storage = LocalStorage::new(config)?;

    // Test upload
    let data = bytes::Bytes::from("Hello, World!");
    let uploaded = storage.upload_bytes("test.txt", data.clone(), None).await?;
    assert_eq!(uploaded.name, "test.txt");
    assert_eq!(uploaded.size, data.len() as u64);

    // Test download
    let downloaded = storage.download_bytes("test.txt", None).await?;
    assert_eq!(downloaded, data);

    // Test file exists
    assert!(storage.file_exists("test.txt").await?);

    // Test delete
    let deleted = storage.delete_file("test.txt").await?;
    assert!(deleted);
    assert!(!storage.file_exists("test.txt").await?);

    Ok(())
}
```

## ๐Ÿ”— Configuration

### Environment Variables

```bash
# Local Storage Configuration
LOCAL_STORAGE_DIR=./storage
LOCAL_STORAGE_BASE_PATH=/app/storage
LOCAL_STORAGE_COMPRESSION=true
LOCAL_STORAGE_MAX_FILE_SIZE=104857600  # 100MB
```

### YAML Configuration

```yaml
# backbone-storage configuration
storage:
  backend: "local"

  local:
    base_dir: "${LOCAL_STORAGE_DIR}"
    base_path: "${LOCAL_STORAGE_BASE_PATH}"
    compression: ${LOCAL_STORAGE_COMPRESSION}
    max_file_size: ${LOCAL_STORAGE_MAX_FILE_SIZE}

  # Upload settings
  upload:
    chunk_size: 8388608  # 8MB
    multipart_threshold: 104857600  # 100MB
    calculate_checksum: true

  # Security settings
  security:
    enable_virus_scanning: false
    allowed_file_types: ["pdf", "doc", "docx", "jpg", "png"]
    max_file_size: 104857600  # 100MB

  # Compression settings
  compression:
    enabled: true
    algorithms: ["gzip", "brotli"]
    quality: 6
```

## ๐Ÿ“Š Performance Considerations

### File I/O Optimization

```rust
use backbone_storage::{StorageService, LocalStorage};
use std::sync::Arc;

// Create storage with optimal settings
let storage = Arc::new(
    LocalStorage::builder()
        .base_dir("./fast_storage")
        .compression(false) // Disable compression for performance
        .build()?
);

// Concurrent file operations
let mut handles = vec![];

for i in 0..10 {
    let storage = storage.clone();
    let handle = tokio::spawn(async move {
        let data = format!("File content {}", i);
        let bytes = bytes::Bytes::from(data);

        storage.upload_bytes(&format!("file_{}.txt", i), bytes, None).await
    });

    handles.push(handle);
}

// Wait for all operations to complete
for handle in handles {
    let result = handle.await?;
    println!("Upload result: {:?}", result);
}
```

## ๐Ÿ”„ Version History

### Current Version: 2.0.0

**Features:**
- โœ… Complete local filesystem storage implementation
- โœ… Async file streaming with range support
- โœ… Rich metadata and statistics collection
- โœ… Security features and path sanitization
- โœ… Builder pattern configuration
- โœ… Comprehensive error handling
- โœ… File upload/download/copy/move/delete operations
- โœ… Directory listing with pagination

**Breaking Changes from v1.x:**
- Simplified to local storage only
- Updated API to use async/await throughout
- Enhanced metadata structure
- Improved error handling with context
- Removed cloud storage complexity

## ๐Ÿ“„ License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

## ๐Ÿ”— Related Projects

- **[Backbone Core]../backbone-core/** - Generic CRUD foundation
- **[Backbone Email]../backbone-email/** - SMTP email services
- **[Backbone CLI]../backbone-cli/** - Code generation tools
- **[Framework Documentation]../../docs/technical/** - Complete framework guide

---

**๐Ÿฆด Backbone Storage - Reliable local filesystem storage**

*Local First โ€ข Async Native โ€ข Production Ready*