Skip to main content

max / makenotwork

6.2 KB · 151 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 mnw-cli ships as a companion of the server, in lockstep with each Sando promote
103 (`sando.toml` deploys it alongside the `makenotwork` binary on prod-1). There is
104 no separate deploy step and no manual `scp`. See `../sando/deploy/README.md`.
105
106 It runs on hetzner as a systemd service with security hardening
107 (ProtectSystem=strict, PrivateTmp, NoNewPrivileges). The old
108 `deploy/deploy.sh` is a retired reference, not a supported path.
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 (retired) | `deploy/deploy.sh` |
121 | systemd unit | `deploy/mnw-cli.service` |
122
123 ## Contributing
124
125 This project is licensed under PolyForm Noncommercial 1.0.0. Make Creative, LLC owns
126 the codebase and needs to hold clear title to all of it, so contributions work a
127 little differently here than on a permissively licensed project.
128
129 **Found a bug, or something small and obviously wrong?** Open a bug report rather
130 than sending a patch. A clear report of what you did, what happened, and what you
131 expected is worth more to us than a diff, and it saves you the paperwork below.
132
133 **Want to build something substantial?** Write to info@makenot.work first. We are
134 open to paying for contributions that matter, and we would rather agree on scope and
135 terms before you spend your evenings on it than after.
136
137 **Sending code directly?** Any code you submit is covered by the Contributor License
138 Agreement in `CLA.md`, which assigns copyright in the contribution to Make Creative,
139 LLC. Read it before you send anything. Add these lines to your commit message to
140 record that you accept it:
141
142 Make-Creative-CLA: 1.0.0
143 Signed-off-by: Your Name <your@email>
144
145 We may decline a contribution for any reason, including that it is not something we
146 want to maintain.
147
148 ## License
149
150 PolyForm Noncommercial 1.0.0
151