Skip to main content

max / mnw-cli

4.9 KB · 126 lines History Blame Raw
1 # mnw-cli
2
3 SSH-based CLI and TUI for the Makenotwork creator platform. Authenticates via SSH key fingerprint, provides an interactive terminal UI for managing projects, and supports non-interactive commands for scripting.
4
5 ## Prerequisites
6
7 - **Rust** (stable toolchain, 2024 edition)
8 - **Cross-compilation** (for deployment): `zig`, `cargo-zigbuild`, `x86_64-unknown-linux-gnu` target
9
10 ## Build and Run
11
12 ```sh
13 # Local development (needs MNW server running on localhost:3000)
14 cargo run
15
16 # Run with custom port
17 SSH_PORT=2222 MNW_API_URL=http://localhost:3000 MNW_SERVICE_TOKEN=<token> cargo run
18
19 # Cross-compile for production
20 cargo zigbuild --release --target x86_64-unknown-linux-gnu
21 ```
22
23 ## Architecture
24
25 mnw-cli is an SSH server built on [russh]https://docs.rs/russh. Each connection spawns an independent handler that authenticates via SSH key fingerprint lookup against the MNW API, then dispatches to either the interactive TUI or a non-interactive command.
26
27 | Layer | Modules | Role |
28 |-------|---------|------|
29 | SSH | `ssh/handler.rs`, `ssh/mod.rs` | Connection handling, public key auth, channel dispatch |
30 | TUI | `tui/mod.rs` + 9 screen modules | Interactive terminal UI via [ratatui]https://ratatui.rs/ |
31 | Commands | `commands.rs` | Non-interactive text output for scripting |
32 | API | `api.rs` | HTTP client for MNW internal API (50+ methods) |
33 | SFTP | `ssh/sftp.rs` | File upload handling with per-user staging |
34 | Git | `ssh/git.rs` | Git proxy (upload-pack, receive-pack) via subprocess |
35 | Staging | `staging.rs` | 1 GB per-user upload quota, 24h TTL auto-cleanup |
36
37 ### Authentication
38
39 1. Client presents SSH public key
40 2. Server computes SHA-256 fingerprint
41 3. Calls MNW internal API to look up the fingerprint
42 4. Returns user info (username, creator tier, suspended status)
43 5. Suspended users are rejected at auth stage
44
45 ## Interactive TUI
46
47 Connect via `ssh cli.makenot.work` for a full terminal interface with these screens:
48
49 | Screen | Features |
50 |--------|----------|
51 | Home | Project list, revenue/sales/follower stats with period comparison |
52 | Project | Items in a project, publish/unpublish, navigation |
53 | Upload | SFTP staged files, metadata editor, S3 presigned upload flow |
54 | Item | Item details, versions, edit fields, delete |
55 | Blog | Blog posts, create with markdown, publish/draft toggle |
56 | Promo | Promo codes, create with discount %, delete |
57 | Keys | License keys, generate, revoke |
58 | Analytics | Timeseries revenue, period comparison, top projects |
59 | Settings | SSH keys, storage usage, profile info |
60
61 Navigation: vim keys (h/j/k/l), Enter to select, q/Esc to go back, Tab to switch sections.
62
63 ## Non-Interactive Commands
64
65 ```sh
66 ssh cli.makenot.work projects # List projects (table format)
67 ssh cli.makenot.work projects --json # JSON output for scripting
68 ssh cli.makenot.work analytics # Revenue stats (7d default)
69 ssh cli.makenot.work analytics --range=30 # 30-day analytics
70 ssh cli.makenot.work transactions # Recent transactions
71 ssh cli.makenot.work export sales # Export sales as CSV
72 ssh cli.makenot.work promo list # List promo codes
73 ssh cli.makenot.work promo create CODE 20 # Create 20% discount code
74 ssh cli.makenot.work blog list SLUG # List blog posts for a project
75 ssh cli.makenot.work help # Show all commands
76 ```
77
78 All commands support `--json` for machine-readable output.
79
80 ## File Upload Flow
81
82 1. Upload file via SFTP to the SSH server
83 2. File lands in per-user staging directory (1 GB quota)
84 3. TUI shows staged files with type classification
85 4. Fill in metadata (title, project, price)
86 5. Server gets presigned S3 URL, uploads file, confirms with MNW API
87 6. Staging directory auto-cleaned on 24-hour TTL
88
89 ## Configuration
90
91 | Variable | Default | Purpose |
92 |----------|---------|---------|
93 | `SSH_PORT` | 2222 | SSH listen port |
94 | `MNW_API_URL` | `http://localhost:3000` | MNW server base URL |
95 | `MNW_SERVICE_TOKEN` | *(required)* | Bearer token for internal API |
96 | `SSH_HOST_KEY` | `host_ed25519` | Path to host key (auto-generated if missing) |
97 | `STAGING_DIR` | `/var/lib/mnw-cli/staging` | Per-user upload staging |
98 | `GIT_SUDO_USER` | `git` | System user for git subprocess ops |
99
100 ## Deployment
101
102 ```sh
103 ./deploy/deploy.sh # Full: build + upload + config + restart
104 ./deploy/deploy.sh --quick # Build + binary + restart
105 ./deploy/deploy.sh --config # Config files only
106 ```
107
108 Deploys to hetzner (`100.120.174.96`) as a systemd service with security hardening (ProtectSystem=strict, PrivateTmp, NoNewPrivileges).
109
110 ## Key Paths
111
112 | What | Where |
113 |------|-------|
114 | SSH server + auth | `src/ssh/handler.rs` |
115 | TUI app state + event loop | `src/tui/mod.rs` |
116 | API client (50+ methods) | `src/api.rs` |
117 | Non-interactive commands | `src/commands.rs` |
118 | SFTP + staging | `src/ssh/sftp.rs`, `src/staging.rs` |
119 | Git proxy | `src/ssh/git.rs` |
120 | Deploy script | `deploy/deploy.sh` |
121 | systemd unit | `deploy/mnw-cli.service` |
122
123 ## License
124
125 PolyForm Noncommercial 1.0.0
126