hakanai-lib 2.12.2

Client library for Hakanai, a secure secret sharing service.
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
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
# Hakanai (儚い)

![Banner](banner.svg)

A minimalist one-time secret sharing service built on zero-knowledge principles.

## Philosophy

Hakanai embodies the Japanese concept of transience - secrets that exist only for a moment before vanishing forever. No accounts, no tracking, no permanent storage. Just ephemeral data transfer with mathematical privacy guarantees and automatic expiration.

## Core Principles

- **Zero-Knowledge**: The server never sees your data. All encryption happens client-side.
- **Single View**: Secrets self-destruct after one access. No second chances.
- **No Metadata**: We store only encrypted bytes and an ID. Nothing else.
- **Minimalist**: One function only - share secrets that disappear.
- **Content Integrity**: hash verification ensures secrets haven't been tampered with.

## How It Works

1. Your client (CLI or browser) encrypts the secret locally
2. Sends only the ciphertext to our server
3. You share the link with the decryption key (either embedded in URL or separately)
4. Recipient views once, then it's gone forever

### Enhanced Security Mode

With the `--separate-key` option, Hakanai provides enhanced security by separating the secret URL from the decryption key:

1. **Traditional mode**: One URL contains both secret ID and key (`/s/uuid#key:hash`)
2. **Separate key mode**: Secret URL (`/s/uuid`) and key are provided separately
3. **Defense in depth**: Share URL and key through different communication channels
4. **Reduced attack surface**: No cryptographic material in any single URL

## Security Model

We implement true client-side encryption - your secrets are encrypted before leaving your device and decrypted only after retrieval. The server is just a temporary dead drop that forgets everything.

**Content Integrity**: Hakanai automatically verifies that secrets haven't been tampered with using SHA-256 hashes truncated to 128 bits. This is a deliberate tradeoff between cryptographic security and usability - the 22-character hash keeps URLs manageable and QR codes scannable while still providing strong tamper detection. All URLs must use the format `#key:hash` where the hash validates the decrypted content for security.

**Note**: This project focuses on the application-layer encryption. Transport security (HTTPS/TLS) should be handled by a reverse proxy or load balancer in front of the server.

Built for those who believe privacy isn't about having something to hide - it's about having something to protect.

## Installation

### Kubernetes Deployment (Helm)

The easiest way to deploy Hakanai is using our Helm chart:

```bash
# Add the Hakanai Helm repository
helm repo add hakanai https://czerwonk.github.io/hakanai
helm repo update

# Install with default values (secure by default)
helm install hakanai hakanai/hakanai

# Or with custom configuration
helm install hakanai hakanai/hakanai \
  --set ingress.hosts[0].host=secrets.example.com \
  --set redis.replica.replicaCount=3
```

The Helm chart includes:
- Redis with Sentinel for high availability
- Automatic TLS with ingress-nginx
- Rate limiting and security headers
- Network policies and pod security
- Horizontal pod autoscaling support

See the [Helm chart documentation](helm/hakanai/README.md) for detailed configuration options.

### Manual Installation

#### Prerequisites
- Rust 1.89 or later (stable toolchain)
- Redis server (for backend storage)
- Node.js and npm (for TypeScript bundling)
- Standard Rust toolchain (`cargo`, `rustc`)

### From Source

```bash
# Clone the repository
git clone https://github.com/czerwonk/hakanai
cd hakanai

# Install npm dependencies for TypeScript bundling
npm install

# Build all components (includes automatic TypeScript bundling)
cargo build --release --workspace

# Binaries will be in:
# - ./target/release/hakanai (CLI)
# - ./target/release/hakanai-server (Server)
```

### Using Docker Compose

The easiest way to run Hakanai is with Docker Compose, which includes both the server and a Valkey (Redis-compatible) database:

```bash
# Start the services
docker-compose up -d

# The server will be available at http://localhost:8080

# View logs
docker-compose logs -f

# Stop the services
docker-compose down

# Stop and remove volumes (clears all stored secrets)
docker-compose down -v
```

For production deployment, create your own `docker-compose.override.yml`:

```yaml
services:
  hakanai:
    environment:
      HAKANAI_ALLOW_ANONYMOUS: "true"
      HAKANAI_ANONYMOUS_UPLOAD_SIZE_LIMIT: "64"
```

## Usage

### Server

```bash
# Start with default settings (port 8080, Redis on localhost)
# Admin token will be generated and logged on first startup
hakanai-server

# Or with custom configuration
hakanai-server --port 3000 --listen 0.0.0.0 --redis-dsn redis://redis.example.com:6379/

# Enable anonymous access (allows public secret creation with size limits)
hakanai-server --allow-anonymous

# Configure anonymous size limits (humanized format)
hakanai-server --allow-anonymous --anonymous-size-limit 64k

# Enable admin token system for token management (requires trusted IP ranges)
hakanai-server --enable-admin-token --trusted-ip-ranges "127.0.0.0/8,10.0.0.0/8"

# Production setup with admin token and monitoring
hakanai-server --enable-admin-token --trusted-ip-ranges "192.168.1.0/24" --allow-anonymous --anonymous-size-limit 32k --upload-size-limit 10m

# With webhook notifications for audit/monitoring (v2.8+)
hakanai-server --webhook-url https://example.com/webhook --webhook-token "token123"
```

**Token System:**
- **Admin token**: Optional admin API access (use `--enable-admin-token`)
- **User tokens**: Auto-created on first startup with 30-day TTL
- **Anonymous access**: Optional public access with size limits
- **Token recovery**: Use `--reset-admin-token` or `--reset-default-token` flags

**Webhook Notifications (v2.8+):**
- **Lifecycle events**: Get notified when secrets are created or retrieved
- **Zero-knowledge preserved**: Only metadata (UUID, headers) sent, never secret content
- **Extensible**: Corporate deployments can implement custom observers for audit trails
- **Fire-and-forget**: Webhooks don't block secret operations

### CLI

#### Sending a Secret

```bash
# Send from stdin (default: 24 hour expiration)
echo "my secret data" | hakanai send

# Send from a file
hakanai send --file secret.txt
hakanai send -f /path/to/secret.dat

# Send multiple files (automatically creates ZIP archive)
hakanai send -f document.pdf -f image.png -f data.csv
hakanai send --file report.pdf --file appendix.docx

# Send with custom TTL
echo "temporary password" | hakanai send --ttl 30m

# Send to custom server
echo "secret" | hakanai send --server https://hakanai.example.com

# Send with authentication token (required if server has token whitelist)
echo "secret" | HAKANAI_TOKEN=my-auth-token hakanai send
# Or using token file
echo "secret" | hakanai send --token-file /path/to/token.txt

# Generate separate key for enhanced security (key and URL shared via different channels)
echo "sensitive data" | hakanai send --separate-key

# Restrict access to specific IP addresses or CIDR ranges
echo "restricted secret" | hakanai send --allow-ip 192.168.1.0/24 --allow-ip 10.0.0.1
echo "office only" | hakanai send --allow-ip 203.0.113.0/24 --allow-ip 2001:db8:85a3::/48

# Restrict access to specific countries (ISO 3166-1 alpha-2 codes)
echo "US/Canada only" | hakanai send --allow-country US --allow-country CA
echo "EU restricted" | hakanai send --allow-country DE --allow-country FR --allow-country NL

# Restrict access to specific ASNs (Autonomous System Numbers)
echo "Cloudflare only" | hakanai send --allow-asn 13335
echo "Multiple ISPs" | hakanai send --allow-asn 13335 --allow-asn 15169 --allow-asn 32934

# Require passphrase for access (phone call/out-of-band sharing)
echo "sensitive document" | hakanai send --require-passphrase mypassword123

# Combine all restriction types including passphrase
echo "comprehensive restrictions" | hakanai send --allow-ip 192.168.1.0/24 --allow-country DE --allow-asn 202739 --require-passphrase secret123
# Output:
# Secret sent successfully!
# 
# Secret link: https://hakanai.example.com/s/uuid
# Key:         base64-encoded-key

# Display URL as QR code for easy mobile sharing
echo "secret" | hakanai send --qr-code

# Combine options
HAKANAI_TOKEN=my-token hakanai send -f secret.txt -s https://hakanai.example.com --ttl 1h
```

#### Retrieving a Secret

```bash
# Get using the full URL returned by send
hakanai get https://hakanai.example.com/secret/550e8400-e29b-41d4-a716-446655440000

# Get using the short link format
hakanai get https://hakanai.example.com/s/550e8400-e29b-41d4-a716-446655440000

# Get using separate key (when --separate-key was used)
hakanai get https://hakanai.example.com/s/550e8400-e29b-41d4-a716-446655440000 --key base64-encoded-key

# Get passphrase-protected secret
hakanai get https://hakanai.example.com/s/550e8400-e29b-41d4-a716-446655440000 --passphrase mypassword123
hakanai get https://hakanai.example.com/s/550e8400 -p secret123

# Save to a specific file instead of using payload filename
hakanai get https://hakanai.example.com/s/550e8400 --filename custom-name.txt

# Save files to a custom directory instead of current directory
hakanai get https://hakanai.example.com/s/550e8400 --output-dir /path/to/downloads/

# Extract ZIP archives to specified directory
hakanai get https://hakanai.example.com/s/550e8400 --extract --output-dir /path/to/extract/

# Output to stdout (useful for piping to other commands)
hakanai get https://hakanai.example.com/s/550e8400 --to-stdout

# Secret is displayed and immediately destroyed on server
```

#### Creating User Tokens (Admin Only)

```bash
# Create a user token with admin privileges (will prompt for admin token)
hakanai token --limit 5m --ttl 7d

# Create token with humanized size limits
hakanai token --limit 500k    # 500 KB
hakanai token --limit 1m      # 1 MB
hakanai token --limit 1024    # 1024 bytes

# Create token with custom server and settings
hakanai token --server https://hakanai.example.com --limit 2m --ttl 30d
```

**Size Format Options:**
- Plain numbers: bytes (e.g., `1024`)
- 'k' suffix: kilobytes (e.g., `500k`)
- 'm' suffix: megabytes (e.g., `1m`)
- Decimal values supported (e.g., `1.5m`, `2.5k`)

**Note**: You can also retrieve secrets using a web browser by visiting the server URL and pasting the secret link.

## Web Interface

Hakanai now includes a web interface for users who prefer not to use the CLI:
- Visit the server root (e.g., `https://hakanai.example.com/`) to access the web interface
- Create new secrets at `/create` - supports both text and file uploads with comprehensive access restrictions
- Paste a hakanai URL to retrieve secrets directly in your browser - passphrase input appears automatically when required
- Use `/share` for clipboard-based sharing (perfect for iOS Shortcuts integration)
- The same zero-knowledge encryption is maintained - all encryption/decryption happens in your browser
- **Access Restrictions**: Full web UI support for IP/country/ASN restrictions and passphrase protection
- **Passphrase Support**: Seamless inline prompts for passphrase-protected secrets during retrieval
- **Dark/Light Mode Toggle**: Automatic system preference detection with manual override
- Mobile-friendly responsive design
- Multi-language support (English and German) with automatic browser language detection

### Clipboard-Based Sharing

The `/share` endpoint enables seamless integration with automation tools like iOS Shortcuts and provides Safari web view compatibility:

#### **Method 1: URL Fragment (Safari Web View Compatible)**
```
https://hakanai.example.com/share#data=base64data&filename=test.txt&token=authtoken&ttl=3600
```
- **Works in Safari web views** (no clipboard permissions needed)
-**Zero-knowledge** - data stays client-side in URL fragment
-**Auto-processes** - no user interaction required
- ⚠️ **Size limit:** ~5KB payload (Mobile Safari ~8KB fragment limit)

#### **Method 2: Clipboard JSON (Fallback)**
1. **Copy JSON payload to clipboard**:
   ```json
   {
     "data": "base64-encoded-content",
     "filename": "document.pdf",  // optional
     "token": "auth-token",        // optional  
     "ttl": 86400,                // optional (seconds)
     "restrictions": {            // optional
       "allowed_ips": ["192.168.1.0/24"],
       "allowed_countries": ["US", "CA"], 
       "allowed_asns": [13335],
       "passphrase": "plaintext-passphrase"
     }
   }
   ```

2. **Visit `/share`** - the page reads and validates clipboard content
3. **Review the preview** - shows file size, filename, expiration time, and any access restrictions
4. **Click "Create Secret"** - encrypts client-side, hashes passphrase if provided, and generates the shareable URL
5. **URL is copied to clipboard** automatically for easy sharing
6. **Restriction details displayed** - shows applied IP/country/ASN restrictions and passphrase requirement for recipients

**iOS Shortcuts Integration**: Use fragment URLs for small secrets (< 5KB) or clipboard method for larger content. Both maintain zero-knowledge architecture. For detailed setup instructions and the ready-to-use shortcut file, see [docs/shortcuts-README.md](docs/shortcuts-README.md).

## API Reference

**📚 For complete API documentation, visit `/docs` on your running server.**

The documentation is automatically generated from the OpenAPI specification, ensuring it always reflects the current API state. Both human-readable docs and machine-readable specs are kept in perfect sync.

### POST /api/v1/secret
Create a new secret.

**Headers:**
- `Authorization: Bearer {token}` (required if server has token whitelist)

**Request:**
```json
{
  "data": "base64-encoded-secret",
  "expires_in": 3600,  // seconds
  "restrictions": {    // optional
    "allowed_ips": ["192.168.1.0/24", "10.0.0.1"],
    "allowed_countries": ["US", "DE", "CA"],
    "allowed_asns": [13335, 15169, 202739],
    "passphrase_hash": "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8"
  }
}
```

**Response:**
```json
{
  "id": "550e8400-e29b-41d4-a716-446655440000"
}
```

**Error Responses:**
- `401 Unauthorized`: Invalid or missing token when server requires authentication
- `400 Bad Request`: Invalid request body

### GET /api/v1/secret/{id}
Retrieve a secret (one-time access).

**Headers (when required):**
- `X-Secret-Passphrase: sha256-hash-of-passphrase` (required for passphrase-protected secrets)

**Response:**
- `200 OK`: Plain text secret data
- `401 Unauthorized`: Missing or incorrect passphrase
- `403 Forbidden`: Access denied due to restrictions (IP, country, ASN)
- `404 Not Found`: Secret doesn't exist or has expired
- `410 Gone`: Secret was already accessed by someone else


### POST /api/v1/admin/tokens
Create user tokens (admin authentication and trusted IP required).

**Headers:**
- `Authorization: Bearer {admin-token}` (required)
- Request must originate from trusted IP range configured with `--trusted-ip-ranges`

**Request:**
```json
{
  "upload_size_limit": 5242880,  // optional, in bytes
  "ttl_seconds": 2592000         // optional, default 30 days
}
```

**Response:**
```json
{
  "token": "user-token-string"
}
```

**Error Responses:**
- `401 Unauthorized`: Invalid or missing admin token
- `400 Bad Request`: Invalid request body

### GET /ready
Readiness check endpoint - returns 200 OK when the server is ready to accept requests.

### GET /healthy
Health check endpoint - returns 200 OK when the server and all dependencies (Redis) are healthy.

## Development

### Project Structure

```
hakanai/
├── lib/          # Core library (client, crypto, models)
├── cli/          # Command-line interface
├── server/       # Actix-web server
└── Cargo.toml    # Workspace configuration
```

### Building

```bash
# Build entire workspace (includes automatic TypeScript bundling via Rollup)
cargo build --workspace --verbose

# Build release version
cargo build --release --workspace

# Manual TypeScript bundling (optional - automatically done by cargo build)
npm run build

# Clean TypeScript compiled files
make clean-ts

# TypeScript type checking only (no compilation)
tsc --noEmit
```

**Build Process:**
- `cargo build` automatically handles TypeScript compilation via `build.rs`
- TypeScript files are bundled using Rollup for optimal performance
- Single JavaScript bundle per page reduces HTTP requests
- Tree shaking eliminates unused code for smaller file sizes


### Testing

```bash
# Run all tests
cargo test --verbose

# Run specific test
cargo test test_name --package hakanai-lib

# Run TypeScript tests
npm test --prefix tests

# Run tests with coverage (if cargo-tarpaulin installed)
cargo tarpaulin --verbose
```

The project includes comprehensive test coverage with 200+ tests across all components.

### Code Quality

```bash
# Format code
cargo fmt

# Run linter (warnings as errors)
RUSTFLAGS="-Dwarnings" cargo clippy --workspace

# TypeScript compilation (automatically checks types)
tsc
```

## Architecture

Hakanai implements a zero-knowledge architecture:

1. **Client-side encryption**: All encryption/decryption happens in the client
2. **Server ignorance**: Server only stores encrypted blobs with UUIDs
3. **Automatic destruction**: Secrets self-destruct after first access or TTL
4. **Temporary storage**: Redis-based temporary persistence with automatic expiration and no permanent backups

### Components

- **hakanai-lib**: Core library with encryption, client traits, and shared models
- **hakanai** (CLI): Command-line interface for sending and retrieving secrets
- **hakanai-server**: RESTful API server with Redis backend
- **TypeScript Client**: Browser-based client with the same zero-knowledge architecture

### Security & Deployment Notes

#### Security Architecture
Hakanai follows a **separation of concerns** security model:
- **Application Layer**: Zero-knowledge encryption, secure token handling, input validation
- **Infrastructure Layer**: TLS termination, rate limiting, DDoS protection (handled by reverse proxy)

#### Production Deployment
The server is designed to run behind a reverse proxy (nginx, Caddy, etc.) which handles:
- **TLS termination and HTTPS enforcement**
- **Rate limiting and DDoS protection**
- **Request filtering and header sanitization**
- **Response compression** (gzip, etc.) for improved performance

For production deployments:
1. **Always use authentication tokens** to prevent unauthorized secret creation
2. **Configure reverse proxy** for TLS, rate limiting, and security headers
3. **Monitor server logs** (structured logging with tracing middleware included)
4. **Set appropriate Redis memory limits** and eviction policies
5. **Enable OpenTelemetry** for comprehensive observability

## Configuration

### Size Limits

**Important:** All size limits apply to the **secret data** before any encryption or encoding. The server automatically accounts for encryption and base64 encoding overhead (approximately 50% additional space), so you can configure limits based on your actual data sizes without worrying about the technical overhead.

For example:
- Setting `--upload-size-limit 10m` allows users to upload files up to 10MB in size
- The server internally handles up to ~15MB to account for encryption/encoding overhead
- This prevents legitimate uploads from failing due to encoding overhead

### Server Environment Variables

- `HAKANAI_PORT`: Server port (default: 8080)
- `HAKANAI_LISTEN_ADDRESS`: Bind address (default: 127.0.0.1)
- `HAKANAI_REDIS_DSN`: Redis connection string (default: redis://127.0.0.1:6379/)
- `HAKANAI_UPLOAD_SIZE_LIMIT`: Maximum upload size for secret data before encryption (default: 10m, supports humanized format like 1m, 500k, 1024)
- `HAKANAI_ALLOW_ANONYMOUS`: Allow anonymous access (default: false)
- `HAKANAI_ANONYMOUS_UPLOAD_SIZE_LIMIT`: Upload size limit for anonymous users' secret data before encryption (default: 32k, supports humanized format)
- `HAKANAI_ENABLE_ADMIN_TOKEN`: Enable admin token system (default: false)
- `HAKANAI_CORS_ALLOWED_ORIGINS`: Comma-separated allowed CORS origins (default: none)
- `HAKANAI_MAX_TTL`: Maximum allowed TTL in seconds (default: 604800, 7 days)
- `HAKANAI_IMPRESSUM_FILE`: Path to impressum/legal information text file (displays impressum link in footer when provided)
- `HAKANAI_PRIVACY_FILE`: Path to privacy policy/data protection text file (displays privacy policy link in footer when provided)
- `HAKANAI_WEBHOOK_URL`: Webhook URL for secret lifecycle notifications (optional)
- `HAKANAI_WEBHOOK_TOKEN`: Bearer token for webhook authentication (optional)
- `HAKANAI_WEBHOOK_HEADERS`: Comma-separated list of HTTP headers to include in webhook requests (default: user-agent,x-forwarded-for,x-forwarded-proto,x-real-ip,x-request-id)
- `HAKANAI_SHOW_TOKEN_INPUT`: Show authentication token input field in web interface (default: false)
- `HAKANAI_TRUSTED_IP_RANGES`: Comma-separated IP ranges (CIDR notation) that bypass size limits (optional)
- `HAKANAI_TRUSTED_IP_HEADER`: HTTP header to check for client IP when behind a proxy (default: x-forwarded-for)
- `HAKANAI_COUNTRY_HEADER`: HTTP header to check for client country code (optional, enables geo-restrictions when set)
- `HAKANAI_ASN_HEADER`: HTTP header to check for client ASN (optional, enables ASN-based restrictions when set)
- `OTEL_EXPORTER_OTLP_ENDPOINT`: OpenTelemetry collector endpoint (optional, enables OTEL when set)

### CLI Environment Variables

- `HAKANAI_SERVER`: Default server URL for CLI commands
- `HAKANAI_TOKEN`: Authentication token for CLI operations
- `HAKANAI_TTL`: Default TTL for send command
- `HAKANAI_TOKEN_TTL`: Default TTL for token command
- `HAKANAI_QR_CODE`: Enable QR code output by default
- `HAKANAI_TO_STDOUT`: Output secrets to stdout by default
- `HAKANAI_OUTPUT_DIR`: Default output directory for retrieved secrets and extracted files

### CLI Command-line Options

#### Send Command Options
- `-s, --server`: Hakanai server URL (default: http://localhost:8080)
- `--ttl`: Time after the secret vanishes (default: 24h, supports humanized format like 30m, 1h, 7d)
- `--token-file`: File containing authorization token (environment variable takes precedence)
- `-f, --file`: File to read the secret from (can be specified multiple times for multiple files)
- `-a, --as-file`: Send the secret as a file (auto-detected for binary content)
- `--filename`: Custom filename when sending as a file
- `--separate-key`: Print key separately for enhanced security (share via different channels)
- `--allow-ip`: IP addresses/CIDR ranges allowed to access the secret (can be specified multiple times)
- `--allow-country`: Country codes (ISO 3166-1 alpha-2) allowed to access the secret (can be specified multiple times)
- `--allow-asn`: Autonomous System Numbers (ASNs) allowed to access the secret (can be specified multiple times)
- `-q, --qr-code`: Display URL as QR code for easy mobile sharing

#### Get Command Options  
- `-k, --key`: Base64 encoded secret key (when not included in URL fragment)
- `--to-stdout`: Output secret to stdout (useful for piping to other commands)
- `-f, --filename`: Save to specific file (overrides payload filename)
- `-e, --extract`: Extract ZIP archives to current directory
- `-o, --output-dir`: Save files to this directory instead of current directory

#### Token Command Options (Admin Only)
- `-s, --server`: Hakanai server URL (default: http://localhost:8080) 
- `--ttl`: Token expiration time (default: 30d, supports humanized format)
- `-l, --limit`: Upload size limit for the token (supports humanized format like 1m, 500k)

### Server Command-line Options

- `--port`: Override the port number
- `--listen`: Override the listen address
- `--redis-dsn`: Override the Redis connection string
- `--allow-anonymous`: Allow anonymous access without authentication
- `--anonymous-size-limit`: Set upload size limit for anonymous users (supports humanized format like 32k, 1m)
- `--enable-admin-token`: Enable admin token system for token management (requires --trusted-ip-ranges)
- `--reset-admin-token`: Force regenerate admin token (requires --enable-admin-token) without starting the server
- `--reset-user-tokens`: Clear all user tokens and create new default token without starting the server
- `--impressum-file`: Path to impressum/legal information text file (displays impressum link in footer when provided)
- `--privacy-file`: Path to privacy policy/data protection text file (displays privacy policy link in footer when provided)
- `--webhook-url`: Webhook URL for secret lifecycle notifications
- `--webhook-token`: Bearer token for webhook authentication
- `--show-token-input`: Show authentication token input field in web interface
- `--trusted-ip-ranges`: IP ranges (CIDR notation) that bypass size limits
- `--trusted-ip-header`: HTTP header to check for client IP when behind a proxy (default: x-forwarded-for)
- `--country-header`: HTTP header to check for client country code (enables geo-restrictions)
- `--asn-header`: HTTP header to check for client ASN (enables ASN-based restrictions)

### Access Control & Geo-Restrictions

#### Secret-Level Access Restrictions

Hakanai supports restricting individual secrets to specific IP addresses/CIDR ranges, countries, and/or Autonomous System Numbers (ASNs). This provides additional security layers by ensuring only authorized networks, geographic locations, and network providers can access the secret.

**Geographic Restrictions:**
Country-based restrictions use the `CF-IPCountry` header (commonly provided by Cloudflare and other CDNs) or a configurable country header to determine the client's location. This requires proper reverse proxy configuration.

**Country Header Configuration:**
```bash
# Cloudflare (most common)
hakanai-server --country-header cf-ipcountry

# Custom CDN or proxy setup
hakanai-server --country-header x-country-code

# Environment variable
export HAKANAI_COUNTRY_HEADER="cf-ipcountry"
```

**ASN-based Restrictions:**
ASN restrictions use HTTP headers to determine the client's Autonomous System Number, allowing filtering based on network provider (ISP, cloud provider, CDN, etc.). This is useful for restricting access to specific hosting providers or ISPs.

**Header Configuration:**
```bash
# For ASN detection (requires custom proxy/CDN setup)
hakanai-server --asn-header x-asn-number

# Environment variable
export HAKANAI_ASN_HEADER="x-asn-number"
```

**Note:** Geographic and ASN restrictions require server-side detection via HTTP headers. For deployments behind Cloudflare or similar CDNs that provide geo/ASN information, configure the appropriate headers. Without proper header configuration, these restrictions will return HTTP 501 Not Implemented.

**CLI Usage:**
```bash
# Restrict to specific IPs and networks
hakanai send --allow-ip 192.168.1.0/24 --allow-ip 10.0.0.1 --allow-ip 2001:db8::/32

# Office network and VPN endpoint
echo "sensitive data" | hakanai send --allow-ip 203.0.113.0/24 --allow-ip 198.51.100.1

# Restrict by country (ISO 3166-1 alpha-2 codes)
echo "US only" | hakanai send --allow-country US
echo "EU access" | hakanai send --allow-country DE --allow-country FR --allow-country NL

# Restrict by ASN (network provider)
echo "Cloudflare only" | hakanai send --allow-asn 13335
echo "Major CDNs" | hakanai send --allow-asn 13335 --allow-asn 15169 --allow-asn 16509

# Combine all restriction types
echo "comprehensive restrictions" | hakanai send --allow-ip 10.0.0.0/8 --allow-country DE --allow-asn 202739
```

**Web Interface:**
The web interface includes optional restriction fields:
- "IP Address Restrictions": Enter IP addresses or CIDR ranges (one per line)
- "Country Restrictions": Enter ISO 3166-1 alpha-2 country codes (one per line, e.g., US, DE, CA)
- "ASN Restrictions": Enter Autonomous System Numbers (one per line, e.g., 13335, 15169, 202739)

**API Usage:**
```json
{
  "data": "encrypted_secret_data", 
  "expires_in": 3600,
  "restrictions": {
    "allowed_ips": ["192.168.1.0/24", "10.0.0.1", "2001:db8::/32"],
    "allowed_countries": ["US", "DE", "CA"],
    "allowed_asns": [13335, 15169, 202739]
  }
}
```

**Supported IP Formats:**
- IPv4 addresses: `192.168.1.100`
- IPv4 CIDR: `192.168.1.0/24`
- IPv6 addresses: `2001:db8::1`
- IPv6 CIDR: `2001:db8::/32`

**Supported Country Formats:**
- ISO 3166-1 alpha-2 codes: `US`, `DE`, `CA`, `GB`, `FR`, `JP`, `AU`, etc.
- Must be exactly 2 uppercase letters
- Examples: `US` (United States), `DE` (Germany), `CA` (Canada), `GB` (United Kingdom)

**Supported ASN Formats:**
- 32-bit unsigned integers: `0` to `4294967295`
- Examples: `13335` (Cloudflare), `15169` (Google), `16509` (Amazon), `32934` (Facebook), `202739` (example German ASN)

#### Server-Level IP Whitelisting

Hakanai supports server-level IP whitelisting that serves two purposes:
1. **Bypass upload size limits** for trusted networks (internal services, monitoring systems, backup operations)
2. **Required for admin API access** when `--enable-admin-token` is used

This provides defense-in-depth security by ensuring administrative operations can only be performed from trusted networks.

**Configuration:**
```bash
# Single IPv4 range
--trusted-ip-ranges 10.0.0.0/8

# Multiple IPv4 and IPv6 ranges
--trusted-ip-ranges 10.0.0.0/8,192.168.1.0/24,2001:db8::/32,::1/128

# Environment variable
export HAKANAI_TRUSTED_IP_RANGES="172.16.0.0/12,2001:db8:85a3::/48"

# Custom proxy header (for Cloudflare, nginx, etc.)
--trusted-ip-header cf-connecting-ip
```

**Common IPv6 ranges:**
- `::1/128` - IPv6 localhost
- `2001:db8::/32` - IPv6 documentation prefix
- `2001::/16` - Global unicast prefix
- `fe80::/10` - Link-local addresses
- `::/0` - All IPv6 addresses (use with caution)

**Security considerations:**
- CIDR notation is validated at server startup
- IPs are extracted from configurable proxy headers (default: `x-forwarded-for`)
- Falls back to connection peer address if header is missing
- Invalid CIDR ranges prevent server startup
- Admin API requires both valid admin token AND trusted IP (defense in depth)
- Admin token system cannot be enabled without configuring trusted IP ranges

### Security Features

- Zero-knowledge architecture with client-side AES-256-GCM encryption
- One-time access with automatic secret deletion
- Token-based authentication with SHA-256 hashing
- IP-based whitelisting for trusted networks
- Security headers (X-Frame-Options, X-Content-Type-Options, HSTS)
- Restrictive CORS policy requiring explicit origin allowlist

### Observability

When `OTEL_EXPORTER_OTLP_ENDPOINT` is set, Hakanai exports:
- **Traces**: Distributed tracing for all HTTP requests
- **Metrics**: Application performance and usage metrics
- **Logs**: Structured logs with trace correlation

The server automatically detects service name and version from Cargo metadata and includes resource information about the OS, process, and runtime environment.

## Contributing

Contributions are welcome! Please:

1. Fork the repository
2. Create a feature branch
3. Write tests for new functionality
4. Ensure all tests pass and clippy is happy
5. Submit a pull request

## License

Licensed under the [Apache License, Version 2.0](LICENSE).

See [NOTICE](NOTICE) for attribution requirements.