@nightowne/tas-cli 2.4.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +154 -0
- package/FAQ.md +33 -0
- package/QUICKSTART.md +47 -0
- package/README.md +356 -196
- package/package.json +11 -5
- package/src/cli.js +758 -213
- package/src/db/index.js +307 -24
- package/src/fuse/mount.js +336 -175
- package/src/index.js +187 -123
- package/src/manifest.js +104 -0
- package/src/share/server.js +7 -9
- package/src/sync/sync.js +105 -34
- package/src/telegram/client.js +10 -3
- package/src/telegram/pool.js +105 -0
- package/src/utils/branding.js +2 -2
- package/src/utils/chunker.js +4 -3
- package/src/utils/cli-helpers.js +90 -10
- package/src/utils/download-stream.js +10 -4
- package/src/utils/logical-path.js +44 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to TAS (Telegram as Storage) will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## [3.0.0] - 2026-09-24
|
|
6
|
+
|
|
7
|
+
### Fixed — FUSE and path correctness
|
|
8
|
+
- **Nested virtual directory tree (#3)** — sync-style names such as `subdir/file.txt` are now exposed as implicit directories. `readdir()` returns immediate children only; `getattr()` reports parent directories; file operations use exact normalized logical paths instead of fuzzy/basename lookup.
|
|
9
|
+
- **Disk-backed FUSE writes** — pending writes use private temp files instead of buffering the entire file in Node.js memory.
|
|
10
|
+
- **Safe truncate** — uncached remote content is downloaded before truncation; TAS no longer substitutes an empty buffer and silently destroys the rest of the file.
|
|
11
|
+
- **Duplicate-content paths** — migrated away from the legacy `UNIQUE(hash)` constraint, so identical bytes can exist at different logical paths without orphaning Telegram messages.
|
|
12
|
+
- **Safe unmount** — replaced interpolated shell commands with `execFileSync()` argument arrays.
|
|
13
|
+
|
|
14
|
+
### Changed — platform support (#4)
|
|
15
|
+
- **macOS mount is explicitly unsupported** in this release. `fuse-native@2.x` targets obsolete OSXFUSE APIs and is not considered compatible with current macFUSE/Apple Silicon. Push, pull, sync, share, and index recovery remain available.
|
|
16
|
+
- **Real FUSE diagnostics** — `tas doctor` calls `Fuse.isConfigured()` and, on supported Linux hosts, performs a temporary mount → async `readdir` → unmount smoke test. Importing the JS module alone no longer counts as success.
|
|
17
|
+
|
|
18
|
+
### Added — multi-bot and recovery
|
|
19
|
+
- **Config v3 bot pool** — `tas bot add/list/enable/disable/remove`, stable bot IDs, deterministic per-chunk routing, persisted `bot_id`, safe reads/deletes through the owning bot, and v1/v2 single-bot compatibility.
|
|
20
|
+
- **Explicit risk gate** — multi-bot setup requires acknowledgement and warns that it does not guarantee quota, durability, ban avoidance, or Terms compliance and must not be used to evade limits.
|
|
21
|
+
- **Encrypted remote manifest** — completed storage mutations publish a gzip-compressed AES-256-GCM manifest for files, chunks, ownership, and tags; ephemeral share tokens are excluded. `tas index backup` refreshes it and `tas index rebuild` authenticates and restores `index.db` while preserving a local backup.
|
|
22
|
+
- **Real resumable uploads** — encrypted chunks are staged on disk before network transfer, and normal uploads populate `pending_uploads`/`pending_chunks`. `tas resume` now continues actual interrupted uploads across bots.
|
|
23
|
+
|
|
24
|
+
### Security and protocol correctness
|
|
25
|
+
- **Opaque chunk metadata** — new uploads omit filename and original size from Telegram-visible WAS1 headers, use generic document names, and use opaque captions. Legacy chunks remain readable.
|
|
26
|
+
- **Hosted Bot API round-trip safety** — payload chunks are 19 MiB so the full document remains below the documented 20 MB `getFile` download limit. `tas doctor` flags legacy oversized chunks.
|
|
27
|
+
- **Serialized per-bot sends** — concurrent sync workers share one bot pool and one send queue per bot instead of bursting through independent client limiters.
|
|
28
|
+
- **Honest product claims** — removed “unlimited,” “free forever,” “zero-knowledge,” and “no ban risk” claims. Documentation now states observed metadata, recovery dependencies, Telegram policy risk, and the independent-backup requirement.
|
|
29
|
+
|
|
30
|
+
### Tests
|
|
31
|
+
- Added nested FUSE path integration tests, legacy schema migration tests, multi-bot routing/ownership tests, send-queue concurrency coverage, resumable-state tests, opaque-metadata tests, and encrypted manifest round-trip/rebuild coverage.
|
|
32
|
+
|
|
33
|
+
## [2.5.0] - 2026-09-17
|
|
34
|
+
|
|
35
|
+
### Fixed — reliability (failed uploads no longer brick files)
|
|
36
|
+
- **Atomic uploads** — `processFile` now deletes the partial `files` row + chunk rows + temp chunk if the pipeline throws, so retrying `tas push` no longer hits a phantom `File already uploaded (duplicate hash)`. DB connection is always closed on failure (was leaked).
|
|
37
|
+
- **Foreign keys enforced** — `FileIndex.init()` now sets `PRAGMA foreign_keys = ON` (SQLite disables it per connection), so `ON DELETE CASCADE` for chunks/tags/shares/sync-state actually works. Also sets `busy_timeout = 5000` for concurrent sync workers.
|
|
38
|
+
- **Exact-match lookup first** — `findByName`/`findByHash` now try exact match before LIKE fallback, so duplicate filenames resolve deterministically.
|
|
39
|
+
- **`tas resume` handles leftovers** — detects pre-2.5 incomplete file rows (`getIncompleteUploads`), offers one-shot cleanup, then resumes legacy `pending_uploads`. Finalize no longer hardcodes `compressed: true` or zero chunk sizes.
|
|
40
|
+
- **`tas sync pull` rewritten** — was skipping on mere existence and miscounting across folders. Now skips only when local content hash matches the index, re-pulls modified files, and downloads to the first registered folder.
|
|
41
|
+
- **Linux recursive watch** — `fs.watch({ recursive: true })` is macOS/Windows-only; `SyncEngine` now watches every subdirectory individually and picks up newly created subdirs. Previously subfolder changes were silently missed on Linux.
|
|
42
|
+
- **Sync no longer ignores dotfiles** — the generic `/^\./` ignore dropped `.env`/SSH keys while the README sells TAS as a secrets vault. Only junk (`.DS_Store`, `.git`, `node_modules`, `~`, `.swp`, `.tmp`) is ignored now.
|
|
43
|
+
- **FUSE large files** — `uploadFile` now chunks at 49MB like `tas push` (was single-chunk, so anything >~50MB failed), uploads atomically, cleans up its Telegram messages on failure, and no longer silently no-ops same-content-different-name copies. `rename` overwrites destination cleanly; `truncate` consults the on-disk cache.
|
|
44
|
+
- **Share download counting** — count increments after a successful stream (aborted connections no longer burn single-use links) and responses carry `Content-Length`.
|
|
45
|
+
- **`tas push <files...>`** — batch uploads with per-file results and a summary line; password verified once.
|
|
46
|
+
|
|
47
|
+
### Added — adoption (time-to-first-success)
|
|
48
|
+
- **Non-interactive `tas init`** — `--token/--chat/--password` flags (plus `TAS_PASSWORD` env). The README's Docker/CI example (`tas init --token … --chat …`) previously referenced flags that didn't exist — now it works.
|
|
49
|
+
- **`tas share create --host`** — bind address flag the 2.4.0 changelog already promised (`--host 0.0.0.0` for LAN). Network URL is only printed when actually reachable, with a warning when bound to all interfaces.
|
|
50
|
+
- **`tas doctor` checks Telegram** — verifies Bot API connectivity when the token is available (plaintext v1, or v2 with `--password`/`TAS_PASSWORD`); otherwise explains how to enable the check.
|
|
51
|
+
- **Honest delete prompts** — default delete says the Telegram copy is retained; `--hard` warns `file_id` blobs can outlive the message.
|
|
52
|
+
- **npm discoverability** — added `telegram-bot`, `zero-knowledge`, `end-to-end-encryption`, `offsite-backup`, `file-sharing`, `dropbox-alternative` keywords.
|
|
53
|
+
|
|
54
|
+
### Tests
|
|
55
|
+
- **78/78 passing** (was 71): new `tests/reliability.test.js` covers dotfile ignore rules, exact-match lookup, incomplete-upload detection, and cascade delete.
|
|
56
|
+
|
|
57
|
+
## [2.4.1] - 2026-06-30
|
|
58
|
+
|
|
59
|
+
### Security
|
|
60
|
+
- **Upgrade `node-telegram-bot-api` 0.66.0 → 1.1.2** — eliminates 9 vulnerabilities (2 critical, 7 moderate) inherited from the legacy `request` dependency: `form-data` CRLF injection, `qs` DoS via memory exhaustion, `tough-cookie` prototype pollution, `uuid` buffer bounds bypass
|
|
61
|
+
- **0 vulnerabilities** in full dependency tree after upgrade
|
|
62
|
+
|
|
63
|
+
### Fixed
|
|
64
|
+
- **Broken navigation anchor** — README `Security` nav link had incorrect URL-encoded variation selector (`#%EF%B8%8F-security-model`); corrected to `#-security-model` (matches GitHub's anchor generation algorithm)
|
|
65
|
+
- **Missing `node_modules`** — `better-sqlite3` was not resolvable, causing `share`, `sync`, and `tags` test suites to fail with `ERR_MODULE_NOT_FOUND`
|
|
66
|
+
|
|
67
|
+
### Tests
|
|
68
|
+
- **71/71 passing** after all fixes (was 41/71 due to missing dependency)
|
|
69
|
+
|
|
70
|
+
## [2.4.0] - 2026-06-04
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
### Security
|
|
74
|
+
- **Timing-safe password comparison** — `verifyPasswordHash` now uses `crypto.timingSafeEqual()` instead of `===` for both PBKDF2 and legacy SHA-256 paths, closing a timing side-channel
|
|
75
|
+
- **Config file permissions** — `config.json` is now `chmod 600` after creation, preventing other system users from reading your encrypted token and password hash
|
|
76
|
+
- **Share server binds to localhost** — Default bind address changed from `0.0.0.0` to `127.0.0.1` so the share server is no longer exposed to your entire LAN out of the box. Use `--host 0.0.0.0` if you need network access
|
|
77
|
+
|
|
78
|
+
### Fixed
|
|
79
|
+
- **Streaming encryption empty-data bug** — `getEncryptStream()` now correctly emits the salt/IV header even when zero bytes are piped through it. Previously, encrypting an empty stream produced malformed output that couldn't be decrypted. The header is now written in `flush()` if `transform()` was never called
|
|
80
|
+
|
|
81
|
+
### Added
|
|
82
|
+
- **31 new tests** — Streaming encryption/decryption (roundtrip, empty data, 1 MB, small-chunk stress, wrong password, truncation, cross-API compat) and WAS1 binary header (roundtrip, Unicode/CJK/emoji truncation, BigInt sizes, boundary values). Test count: 40 → 71
|
|
83
|
+
- **Shared download pipeline** — Extracted the triplicated Telegram→Decrypt→Decompress streaming pattern from `index.js`, `server.js`, and `mount.js` into a single reusable `createDownloadPipeline()` in `src/utils/download-stream.js`
|
|
84
|
+
|
|
85
|
+
### Changed
|
|
86
|
+
- **SECURITY.md rewritten** — Corrected PBKDF2 iterations (was 100,000, actual is 600,000), updated supported versions table to include 2.x, documented config v2 encrypted token storage and share server security model
|
|
87
|
+
- Internal download code in `index.js`, `server.js`, and `mount.js` now uses the shared pipeline instead of duplicated stream wiring
|
|
88
|
+
|
|
89
|
+
## [2.3.0] - 2026-05-30
|
|
90
|
+
|
|
91
|
+
### Added
|
|
92
|
+
- Landing page (`docs/index.html`) for GitHub Pages — dark/light theme, responsive, no frameworks
|
|
93
|
+
- `tas doctor` — Self-diagnostic command that checks Node.js version, config, database health, disk space, encryption parameters
|
|
94
|
+
- `tas verify` — Verify all uploaded files still exist and are intact on Telegram
|
|
95
|
+
- JSON output for `tas list --json` and `tas status --json`
|
|
96
|
+
|
|
97
|
+
### Changed
|
|
98
|
+
- README rewritten for Product Hunt — comparison table, collapsible CLI reference, security details table
|
|
99
|
+
- Config v2: bot token encrypted at rest with user's password (AES-256-GCM)
|
|
100
|
+
- PBKDF2 iterations raised to 600,000 (OWASP 2025 recommendation)
|
|
101
|
+
|
|
102
|
+
### Fixed
|
|
103
|
+
- ARM64 install crash (#1) — fuse-native moved to `optionalDependencies`
|
|
104
|
+
- 413 Request Entity Too Large (#2) — chunk size reduced to 49 MB
|
|
105
|
+
|
|
106
|
+
## [2.0.0] - 2026-02-12
|
|
107
|
+
|
|
108
|
+
### Added
|
|
109
|
+
- **`tas share`** — Temporary encrypted file sharing via local HTTP server
|
|
110
|
+
- Create one-time download links with expiry (`--expire 1h/24h/7d`)
|
|
111
|
+
- Configurable download limits (`--max-downloads`)
|
|
112
|
+
- Dark-themed download page with file info
|
|
113
|
+
- `tas share list` and `tas share revoke` for management
|
|
114
|
+
- **FUSE mount** — Mount Telegram storage as a local folder (`tas mount`)
|
|
115
|
+
- **Folder sync** — Dropbox-style auto-sync with file watching (`tas sync start`)
|
|
116
|
+
|
|
117
|
+
### Changed
|
|
118
|
+
- Major version bump for new feature set
|
|
119
|
+
|
|
120
|
+
## [1.2.0] - 2026-01-24
|
|
121
|
+
|
|
122
|
+
### Added
|
|
123
|
+
- Password automation — Use `-p/--password` flag or `TAS_PASSWORD` env var to skip prompts
|
|
124
|
+
- Batch operations — Upload multiple files without password prompts for each one
|
|
125
|
+
- CI/CD ready — Works with GitHub Actions, GitLab CI, Docker, cron jobs
|
|
126
|
+
- Config validation — Better error messages for missing/invalid configuration
|
|
127
|
+
|
|
128
|
+
### Changed
|
|
129
|
+
- All password-required commands now support automated workflows
|
|
130
|
+
- Improved config loading with detailed error reporting
|
|
131
|
+
|
|
132
|
+
## [1.1.0] - 2026-01-21
|
|
133
|
+
|
|
134
|
+
### Added
|
|
135
|
+
- **Progress bars with speed** — See actual MB/s during uploads/downloads
|
|
136
|
+
- **`tas search`** — Search files by name or content
|
|
137
|
+
- **Resume uploads** — Interrupted uploads can be resumed with `tas resume`
|
|
138
|
+
- **Streaming FUSE reads** — Large files no longer buffer entirely in RAM
|
|
139
|
+
|
|
140
|
+
### Changed
|
|
141
|
+
- README rewritten with technical focus (security model, architecture, limitations)
|
|
142
|
+
|
|
143
|
+
### Fixed
|
|
144
|
+
- FUSE mount stability improvements
|
|
145
|
+
|
|
146
|
+
## [1.0.0] - 2026-01-21
|
|
147
|
+
|
|
148
|
+
### Added
|
|
149
|
+
- Initial release
|
|
150
|
+
- AES-256-GCM encryption with PBKDF2 key derivation
|
|
151
|
+
- FUSE filesystem mount support
|
|
152
|
+
- File tagging system
|
|
153
|
+
- Dropbox-style folder sync
|
|
154
|
+
- Chunked uploads for files >49MB
|
package/FAQ.md
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# TAS 3 FAQ
|
|
2
|
+
|
|
3
|
+
## Is storage unlimited or guaranteed?
|
|
4
|
+
|
|
5
|
+
No. Telegram gives TAS no storage quota, retention SLA, durability promise, or recovery service. Keep another tested copy.
|
|
6
|
+
|
|
7
|
+
## Can Telegram restrict or ban this use?
|
|
8
|
+
|
|
9
|
+
Yes. A documented upload method is not a guarantee that a cloud-storage-style application is permitted. Telegram's current [Bot Developer Terms](https://telegram.org/tos/bot-developers) restrict divergent cloud-storage use cases and rate-limit circumvention. Multi-bot mode does not remove that risk.
|
|
10
|
+
|
|
11
|
+
## Why are chunks 19 MiB when uploads allow more?
|
|
12
|
+
|
|
13
|
+
The hosted Bot API documents a larger upload allowance than its `getFile` download allowance. TAS keeps the payload at 19 MiB plus its 64-byte public routing header so newly uploaded chunks remain below the documented 20 MB read limit.
|
|
14
|
+
|
|
15
|
+
## What metadata can Telegram see?
|
|
16
|
+
|
|
17
|
+
For new TAS 3 uploads, file content, user filename, original size, and remote recovery manifest contents are encrypted or omitted from public chunk fields. Telegram still observes bot/chat identity, timing, IP/network information, chunk count, encrypted sizes, message IDs, and generic TAS protocol captions. TAS 2.x chunks may contain filenames and original sizes in their legacy headers/captions.
|
|
18
|
+
|
|
19
|
+
## Is TAS zero-knowledge?
|
|
20
|
+
|
|
21
|
+
TAS uses client-side AES-256-GCM and has no hosted TAS service, but it is not a formally analyzed zero-knowledge protocol and does not hide traffic metadata. Use a strong unique password and protect the local machine.
|
|
22
|
+
|
|
23
|
+
## What happens if `index.db` is lost?
|
|
24
|
+
|
|
25
|
+
Run `tas index rebuild`. It downloads and authenticates the latest encrypted remote manifest referenced by `config.json`. Recovery still requires the password, config pointer, owning bot, and manifest message.
|
|
26
|
+
|
|
27
|
+
## Does multi-bot mode provide redundancy?
|
|
28
|
+
|
|
29
|
+
No. Each chunk has one owning bot. TAS records that bot so reads and deletes route correctly, but all bots remain controlled by Telegram. A disabled bot stays configured for old chunks; removal is refused while chunks or the manifest depend on it.
|
|
30
|
+
|
|
31
|
+
## Does mount work on macOS?
|
|
32
|
+
|
|
33
|
+
Not in this release. The current `fuse-native@2.x` dependency targets obsolete OSXFUSE APIs and is not validated against current macFUSE or Apple Silicon. Linux users should run `tas doctor` for a real native FUSE smoke test.
|
package/QUICKSTART.md
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# TAS 3 Quick Start
|
|
2
|
+
|
|
3
|
+
TAS is experimental encrypted file transport over Telegram bots. It is not an unlimited-storage or durability service. Telegram can limit or terminate access, and its current [Bot Developer Terms](https://telegram.org/tos/bot-developers) restrict external cloud-storage use cases. Use TAS at your own risk and keep an independent backup.
|
|
4
|
+
|
|
5
|
+
## Install and initialize
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @nightowne/tas-cli
|
|
9
|
+
tas init
|
|
10
|
+
tas doctor --password "$TAS_PASSWORD"
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
`tas init` creates config v3 in `~/.tas/config.json`, encrypts the bot token with your TAS password, and creates the local SQLite index. Keep `config.json` and the password separately; both are needed for remote-manifest recovery.
|
|
14
|
+
|
|
15
|
+
## Push, list, and pull
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
tas push ./report.pdf
|
|
19
|
+
tas list --long
|
|
20
|
+
tas pull report.pdf ./restored-report.pdf
|
|
21
|
+
tas verify
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
New data uses 19 MiB payload chunks so each stored document remains below the hosted Bot API's documented 20 MB `getFile` limit. Interrupted network-stage uploads can be continued with `tas resume`.
|
|
25
|
+
|
|
26
|
+
## Recovery
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
tas index backup
|
|
30
|
+
tas index rebuild
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
TAS updates an authenticated encrypted remote manifest after storage mutations. `rebuild` restores the files/chunks/tags mapping if `index.db` is lost; it cannot help if the manifest message, owning bot, config pointer, or password is also lost.
|
|
34
|
+
|
|
35
|
+
## Optional multi-bot pool
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
tas bot add --name secondary
|
|
39
|
+
tas bot list
|
|
40
|
+
tas bot disable secondary
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Multi-bot mode distributes chunks. It is not redundancy, quota assurance, ban protection, or permission to evade Telegram limits.
|
|
44
|
+
|
|
45
|
+
## Mount support
|
|
46
|
+
|
|
47
|
+
`tas mount` is supported only on validated Linux/libfuse hosts in this release. Run `tas doctor` first; it performs a real mount/readdir/unmount smoke test. macOS mount is disabled until TAS has a maintained current-macFUSE backend and macOS CI.
|