@nightowne/tas-cli 2.4.1 → 3.0.1
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 +162 -0
- package/FAQ.md +33 -0
- package/QUICKSTART.md +47 -0
- package/README.md +94 -93
- package/package.json +12 -5
- package/src/cli.js +760 -214
- package/src/db/index.js +307 -24
- package/src/fuse/macfuse.cjs +235 -0
- package/src/fuse/mount.js +338 -175
- package/src/index.js +208 -150
- 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 +13 -12
- 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,162 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to TAS (Telegram as Storage) will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## [3.0.1] - 2026-09-25
|
|
6
|
+
|
|
7
|
+
### Fixed — current macFUSE mount support (#4)
|
|
8
|
+
- **System macFUSE build** — TAS no longer accepts the bundled OSXFUSE 3 library. On macOS it detects `/Library/Filesystems/macfuse.fs`, selects the installed `libfuse` headers and library, and rebuilds the optional `fuse-native` addon for the active CPU.
|
|
9
|
+
- **Apple Silicon support path** — the rebuilt addon uses macFUSE's supported v2 API surface rather than the legacy binary with no arm64 slice. TAS never installs, replaces, or removes a FUSE kernel extension.
|
|
10
|
+
- **Strict runtime guard** — TAS inspects the loaded native addon and refuses mount if it still links to `libosxfuse` or lacks a system-macFUSE build. `tas doctor` then performs the real mount → readdir → unmount smoke test.
|
|
11
|
+
- **Install guidance** — macOS requires current macFUSE and Xcode Command Line Tools before TAS is installed. A failed native build leaves push, pull, sync, and share available while mount stays disabled.
|
|
12
|
+
|
|
13
|
+
## [3.0.0] - 2026-09-24
|
|
14
|
+
|
|
15
|
+
### Fixed — FUSE and path correctness
|
|
16
|
+
- **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.
|
|
17
|
+
- **Disk-backed FUSE writes** — pending writes use private temp files instead of buffering the entire file in Node.js memory.
|
|
18
|
+
- **Safe truncate** — uncached remote content is downloaded before truncation; TAS no longer substitutes an empty buffer and silently destroys the rest of the file.
|
|
19
|
+
- **Duplicate-content paths** — migrated away from the legacy `UNIQUE(hash)` constraint, so identical bytes can exist at different logical paths without orphaning Telegram messages.
|
|
20
|
+
- **Safe unmount** — replaced interpolated shell commands with `execFileSync()` argument arrays.
|
|
21
|
+
|
|
22
|
+
### Changed — platform support (#4)
|
|
23
|
+
- **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.
|
|
24
|
+
- **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.
|
|
25
|
+
|
|
26
|
+
### Added — multi-bot and recovery
|
|
27
|
+
- **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.
|
|
28
|
+
- **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.
|
|
29
|
+
- **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.
|
|
30
|
+
- **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.
|
|
31
|
+
|
|
32
|
+
### Security and protocol correctness
|
|
33
|
+
- **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.
|
|
34
|
+
- **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.
|
|
35
|
+
- **Serialized per-bot sends** — concurrent sync workers share one bot pool and one send queue per bot instead of bursting through independent client limiters.
|
|
36
|
+
- **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.
|
|
37
|
+
|
|
38
|
+
### Tests
|
|
39
|
+
- 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.
|
|
40
|
+
|
|
41
|
+
## [2.5.0] - 2026-09-17
|
|
42
|
+
|
|
43
|
+
### Fixed — reliability (failed uploads no longer brick files)
|
|
44
|
+
- **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).
|
|
45
|
+
- **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.
|
|
46
|
+
- **Exact-match lookup first** — `findByName`/`findByHash` now try exact match before LIKE fallback, so duplicate filenames resolve deterministically.
|
|
47
|
+
- **`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.
|
|
48
|
+
- **`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.
|
|
49
|
+
- **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.
|
|
50
|
+
- **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.
|
|
51
|
+
- **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.
|
|
52
|
+
- **Share download counting** — count increments after a successful stream (aborted connections no longer burn single-use links) and responses carry `Content-Length`.
|
|
53
|
+
- **`tas push <files...>`** — batch uploads with per-file results and a summary line; password verified once.
|
|
54
|
+
|
|
55
|
+
### Added — adoption (time-to-first-success)
|
|
56
|
+
- **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.
|
|
57
|
+
- **`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.
|
|
58
|
+
- **`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.
|
|
59
|
+
- **Honest delete prompts** — default delete says the Telegram copy is retained; `--hard` warns `file_id` blobs can outlive the message.
|
|
60
|
+
- **npm discoverability** — added `telegram-bot`, `zero-knowledge`, `end-to-end-encryption`, `offsite-backup`, `file-sharing`, `dropbox-alternative` keywords.
|
|
61
|
+
|
|
62
|
+
### Tests
|
|
63
|
+
- **78/78 passing** (was 71): new `tests/reliability.test.js` covers dotfile ignore rules, exact-match lookup, incomplete-upload detection, and cascade delete.
|
|
64
|
+
|
|
65
|
+
## [2.4.1] - 2026-06-30
|
|
66
|
+
|
|
67
|
+
### Security
|
|
68
|
+
- **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
|
|
69
|
+
- **0 vulnerabilities** in full dependency tree after upgrade
|
|
70
|
+
|
|
71
|
+
### Fixed
|
|
72
|
+
- **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)
|
|
73
|
+
- **Missing `node_modules`** — `better-sqlite3` was not resolvable, causing `share`, `sync`, and `tags` test suites to fail with `ERR_MODULE_NOT_FOUND`
|
|
74
|
+
|
|
75
|
+
### Tests
|
|
76
|
+
- **71/71 passing** after all fixes (was 41/71 due to missing dependency)
|
|
77
|
+
|
|
78
|
+
## [2.4.0] - 2026-06-04
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
### Security
|
|
82
|
+
- **Timing-safe password comparison** — `verifyPasswordHash` now uses `crypto.timingSafeEqual()` instead of `===` for both PBKDF2 and legacy SHA-256 paths, closing a timing side-channel
|
|
83
|
+
- **Config file permissions** — `config.json` is now `chmod 600` after creation, preventing other system users from reading your encrypted token and password hash
|
|
84
|
+
- **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
|
|
85
|
+
|
|
86
|
+
### Fixed
|
|
87
|
+
- **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
|
|
88
|
+
|
|
89
|
+
### Added
|
|
90
|
+
- **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
|
|
91
|
+
- **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`
|
|
92
|
+
|
|
93
|
+
### Changed
|
|
94
|
+
- **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
|
|
95
|
+
- Internal download code in `index.js`, `server.js`, and `mount.js` now uses the shared pipeline instead of duplicated stream wiring
|
|
96
|
+
|
|
97
|
+
## [2.3.0] - 2026-05-30
|
|
98
|
+
|
|
99
|
+
### Added
|
|
100
|
+
- Landing page (`docs/index.html`) for GitHub Pages — dark/light theme, responsive, no frameworks
|
|
101
|
+
- `tas doctor` — Self-diagnostic command that checks Node.js version, config, database health, disk space, encryption parameters
|
|
102
|
+
- `tas verify` — Verify all uploaded files still exist and are intact on Telegram
|
|
103
|
+
- JSON output for `tas list --json` and `tas status --json`
|
|
104
|
+
|
|
105
|
+
### Changed
|
|
106
|
+
- README rewritten for Product Hunt — comparison table, collapsible CLI reference, security details table
|
|
107
|
+
- Config v2: bot token encrypted at rest with user's password (AES-256-GCM)
|
|
108
|
+
- PBKDF2 iterations raised to 600,000 (OWASP 2025 recommendation)
|
|
109
|
+
|
|
110
|
+
### Fixed
|
|
111
|
+
- ARM64 install crash (#1) — fuse-native moved to `optionalDependencies`
|
|
112
|
+
- 413 Request Entity Too Large (#2) — chunk size reduced to 49 MB
|
|
113
|
+
|
|
114
|
+
## [2.0.0] - 2026-02-12
|
|
115
|
+
|
|
116
|
+
### Added
|
|
117
|
+
- **`tas share`** — Temporary encrypted file sharing via local HTTP server
|
|
118
|
+
- Create one-time download links with expiry (`--expire 1h/24h/7d`)
|
|
119
|
+
- Configurable download limits (`--max-downloads`)
|
|
120
|
+
- Dark-themed download page with file info
|
|
121
|
+
- `tas share list` and `tas share revoke` for management
|
|
122
|
+
- **FUSE mount** — Mount Telegram storage as a local folder (`tas mount`)
|
|
123
|
+
- **Folder sync** — Dropbox-style auto-sync with file watching (`tas sync start`)
|
|
124
|
+
|
|
125
|
+
### Changed
|
|
126
|
+
- Major version bump for new feature set
|
|
127
|
+
|
|
128
|
+
## [1.2.0] - 2026-01-24
|
|
129
|
+
|
|
130
|
+
### Added
|
|
131
|
+
- Password automation — Use `-p/--password` flag or `TAS_PASSWORD` env var to skip prompts
|
|
132
|
+
- Batch operations — Upload multiple files without password prompts for each one
|
|
133
|
+
- CI/CD ready — Works with GitHub Actions, GitLab CI, Docker, cron jobs
|
|
134
|
+
- Config validation — Better error messages for missing/invalid configuration
|
|
135
|
+
|
|
136
|
+
### Changed
|
|
137
|
+
- All password-required commands now support automated workflows
|
|
138
|
+
- Improved config loading with detailed error reporting
|
|
139
|
+
|
|
140
|
+
## [1.1.0] - 2026-01-21
|
|
141
|
+
|
|
142
|
+
### Added
|
|
143
|
+
- **Progress bars with speed** — See actual MB/s during uploads/downloads
|
|
144
|
+
- **`tas search`** — Search files by name or content
|
|
145
|
+
- **Resume uploads** — Interrupted uploads can be resumed with `tas resume`
|
|
146
|
+
- **Streaming FUSE reads** — Large files no longer buffer entirely in RAM
|
|
147
|
+
|
|
148
|
+
### Changed
|
|
149
|
+
- README rewritten with technical focus (security model, architecture, limitations)
|
|
150
|
+
|
|
151
|
+
### Fixed
|
|
152
|
+
- FUSE mount stability improvements
|
|
153
|
+
|
|
154
|
+
## [1.0.0] - 2026-01-21
|
|
155
|
+
|
|
156
|
+
### Added
|
|
157
|
+
- Initial release
|
|
158
|
+
- AES-256-GCM encryption with PBKDF2 key derivation
|
|
159
|
+
- FUSE filesystem mount support
|
|
160
|
+
- File tagging system
|
|
161
|
+
- Dropbox-style folder sync
|
|
162
|
+
- 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
|
+
Yes with current macFUSE, Xcode Command Line Tools, and a locally rebuilt native addon. TAS never installs or replaces macFUSE; its install hook selects the system `libfuse` and compiles the optional addon for the active CPU. Run `tas doctor` before use. If the real mount/readdir/unmount smoke test does not pass, do not mount data.
|
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` needs a native FUSE runtime. On Linux install `fuse` and `libfuse-dev`. On macOS install current macFUSE and Xcode Command Line Tools before installing TAS; TAS rebuilds its optional native addon against the installed macFUSE library. Run `tas doctor` first and mount only when its real mount/readdir/unmount smoke test passes.
|
package/README.md
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
<img src="assets/demo.gif" alt="TAS — Telegram as Storage CLI demo" width="680">
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
|
-
<h1 align="center">📦 TAS
|
|
5
|
+
<h1 align="center">📦 TAS</h1>
|
|
6
6
|
|
|
7
7
|
<h3 align="center">
|
|
8
|
-
|
|
9
|
-
<strong>
|
|
8
|
+
Encrypted file transport for data you already keep backed up.<br>
|
|
9
|
+
<strong>Local index. Verifiable restores. Explicit provider risk.</strong>
|
|
10
10
|
</h3>
|
|
11
11
|
|
|
12
12
|
<p align="center">
|
|
@@ -18,13 +18,13 @@
|
|
|
18
18
|
<a href="https://github.com/ixchio/tas/network/members"><img src="https://img.shields.io/github/forks/ixchio/tas?style=social" alt="GitHub Forks"></a>
|
|
19
19
|
<img src="https://img.shields.io/badge/node-%3E%3D18-brightgreen?logo=node.js" alt="Node.js >= 18">
|
|
20
20
|
<img src="https://img.shields.io/badge/encryption-AES--256--GCM-blueviolet?logo=shield" alt="AES-256-GCM">
|
|
21
|
-
<img src="https://img.shields.io/badge/tests-
|
|
21
|
+
<img src="https://img.shields.io/badge/tests-101%20passing-success" alt="101 Tests Passing">
|
|
22
22
|
</p>
|
|
23
23
|
|
|
24
24
|
<p align="center">
|
|
25
25
|
<a href="QUICKSTART.md"><strong>📚 Quick Start</strong></a> •
|
|
26
26
|
<a href="FAQ.md">FAQ</a> •
|
|
27
|
-
<a href="
|
|
27
|
+
<a href="#why-tas">Why TAS?</a> •
|
|
28
28
|
<a href="#-features">Features</a> •
|
|
29
29
|
<a href="#-security-model">Security</a> •
|
|
30
30
|
<a href="#-cli-reference">CLI Docs</a> •
|
|
@@ -34,30 +34,21 @@
|
|
|
34
34
|
|
|
35
35
|
---
|
|
36
36
|
|
|
37
|
-
> **
|
|
37
|
+
> **TAS 3.0** — One `npm install`, one `tas init`, then `tas push yourfile.pdf`. TAS encrypts content locally and sends round-trip-safe chunks through the Bot API. It is experimental transport, not a durable backup service: Telegram can limit, remove, or terminate access. Keep an independent backup.
|
|
38
38
|
|
|
39
39
|
---
|
|
40
40
|
|
|
41
|
-
##
|
|
41
|
+
## What TAS Is
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
TAS is a local-first CLI for moving encrypted file blobs through your own Telegram bots. Its SQLite index lives on your machine; content is encrypted before upload; completed mutations publish an encrypted recovery manifest you can use to rebuild the index.
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|---|---|---|---|---|
|
|
47
|
-
| Google Drive | 15 GB | ✅ Yes (indexes for ads) | ❌ | ❌ |
|
|
48
|
-
| Dropbox | 2 GB | ✅ Can access | ❌ | ❌ |
|
|
49
|
-
| iCloud | 5 GB | ✅ Apple ToS | ❌ | ❌ |
|
|
50
|
-
| Mega | 20 GB | ❓ Closed-source E2EE | ❌ | ❓ |
|
|
51
|
-
| Backblaze B2 | 10 GB | ❌ | ✅ | ❌ (you add it) |
|
|
52
|
-
| **TAS + Telegram** | **♾️ Unlimited** | **❌ Impossible (AES-256)** | **✅ First-class** | **✅ Always** |
|
|
53
|
-
|
|
54
|
-
Meanwhile, Telegram gives every bot **unlimited file storage** via its public Bot API — and almost nobody is using it.
|
|
45
|
+
> **Operating boundary.** TAS is not unlimited storage, a backup guarantee, or a Telegram-supported cloud drive. Telegram provides no TAS quota, retention SLA, recovery service, or account guarantee. Its [Bot Developer Terms](https://telegram.org/tos/bot-developers) also restrict external apps that diverge into cloud-storage use cases. Use TAS only for data that already has an independent backup.
|
|
55
46
|
|
|
56
47
|
---
|
|
57
48
|
|
|
58
|
-
##
|
|
49
|
+
## How It Works
|
|
59
50
|
|
|
60
|
-
**TAS** compresses, encrypts (AES-256-GCM), chunks, and uploads
|
|
51
|
+
**TAS** compresses, encrypts (AES-256-GCM), chunks, and uploads files to private bot chats. Your password stays local. Content, filenames, original sizes, and the recovery manifest are encrypted or omitted from Telegram-visible chunk metadata. Telegram still sees bot/chat identity, timing, chunk count, and encrypted sizes.
|
|
61
52
|
|
|
62
53
|
```
|
|
63
54
|
Your Machine Telegram Cloud
|
|
@@ -71,14 +62,14 @@ Meanwhile, Telegram gives every bot **unlimited file storage** via its public Bo
|
|
|
71
62
|
│ (SHA-256 verified) │←── decomp ←──│ ← Stream on demand │
|
|
72
63
|
│ │ │ │
|
|
73
64
|
└─────────────────────────────┘ └──────────────────────────┘
|
|
74
|
-
SQLite Index
|
|
65
|
+
SQLite Index Remote Bot Messages
|
|
75
66
|
```
|
|
76
67
|
|
|
77
68
|
---
|
|
78
69
|
|
|
79
70
|
## ⚡ Quick Start
|
|
80
71
|
|
|
81
|
-
**Three commands
|
|
72
|
+
**Three commands to try it. Keep another copy of every file.**
|
|
82
73
|
|
|
83
74
|
```bash
|
|
84
75
|
# 1. Install globally
|
|
@@ -97,36 +88,15 @@ tas list # See everything you've stored
|
|
|
97
88
|
|
|
98
89
|
---
|
|
99
90
|
|
|
100
|
-
##
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
-
|
|
108
|
-
-
|
|
109
|
-
- iCloud locks you into the Apple ecosystem
|
|
110
|
-
- Self-hosting (Nextcloud, MinIO) costs VPS money + maintenance time
|
|
111
|
-
- S3 / B2 needs encryption wiring and costs per GB transferred
|
|
112
|
-
- rclone + any backend still needs a paid backend
|
|
113
|
-
|
|
114
|
-
</td>
|
|
115
|
-
<td width="50%" valign="top">
|
|
116
|
-
|
|
117
|
-
### ✅ TAS gives you
|
|
118
|
-
- **$0/month** — forever, no storage caps, no bandwidth fees
|
|
119
|
-
- **Zero-knowledge** — only you hold the decryption key
|
|
120
|
-
- **AES-256-GCM** — same cipher used by banks and governments
|
|
121
|
-
- **FUSE mount** — Telegram storage appears as a real folder
|
|
122
|
-
- **Auto-sync** — Dropbox-style folder watcher built-in
|
|
123
|
-
- **Expiring share links** — send files without sharing your password
|
|
124
|
-
- **CLI-first** — pipe to `jq`, run in cron, automate everything
|
|
125
|
-
- **Open source** — audit every single line of crypto code
|
|
126
|
-
|
|
127
|
-
</td>
|
|
128
|
-
</tr>
|
|
129
|
-
</table>
|
|
91
|
+
## Why TAS?
|
|
92
|
+
|
|
93
|
+
TAS is for people who want a small, inspectable command-line transport rather than another account, dashboard, or opaque sync daemon. It makes the important state visible and keeps the recovery path in your hands.
|
|
94
|
+
|
|
95
|
+
- **A local source of truth.** The index is SQLite, paths are exact, and nested directories behave consistently in sync and FUSE.
|
|
96
|
+
- **A recovery story.** TAS writes an authenticated, encrypted remote manifest after completed changes; `tas index rebuild` can restore the file-to-message map when the local index is gone.
|
|
97
|
+
- **A clean automation surface.** Push, pull, search, tags, sync, and JSON output work from a shell, cron job, or CI runner.
|
|
98
|
+
- **Deliberate multi-bot routing.** Each chunk records its owner, so a pool is inspectable and reversible instead of a hidden round-robin trick.
|
|
99
|
+
- **No false promise.** The product is precise about the provider boundary: Telegram is not your storage vendor, and multi-bot mode is not a way around its rules.
|
|
130
100
|
|
|
131
101
|
---
|
|
132
102
|
|
|
@@ -143,7 +113,7 @@ cp report.pdf ~/cloud/ # Drop files in — auto-encrypted and uploaded
|
|
|
143
113
|
tas unmount ~/cloud # Clean unmount when done
|
|
144
114
|
```
|
|
145
115
|
|
|
146
|
-
> **
|
|
116
|
+
> **Native FUSE is verified, not assumed:** Linux needs `fuse`/`libfuse-dev`. macOS uses current macFUSE and rebuilds the optional native addon against the installed system library on first install. Install Xcode Command Line Tools before TAS, then run `tas doctor`; mount is available only when its real mount → readdir → unmount smoke test passes.
|
|
147
117
|
|
|
148
118
|
---
|
|
149
119
|
|
|
@@ -160,6 +130,33 @@ tas sync status # See what's queued / synced / pending
|
|
|
160
130
|
|
|
161
131
|
---
|
|
162
132
|
|
|
133
|
+
### 🤖 Experimental Multi-Bot Pool
|
|
134
|
+
|
|
135
|
+
TAS can distribute new chunks deterministically across multiple bots and records the owning bot on every chunk. Disabled bots remain configured for reads; a bot cannot be removed while indexed chunks or the recovery manifest depend on it.
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
tas bot add --name archive-2 # Interactive token/chat setup + risk acknowledgement
|
|
139
|
+
tas bot list # IDs, state, chat, and dependent chunk counts
|
|
140
|
+
tas bot disable archive-2 # Stop new writes; old chunks remain readable
|
|
141
|
+
tas bot enable archive-2
|
|
142
|
+
tas bot remove archive-2 # Refuses unless no data depends on it
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
> **Use at your own risk.** Multiple bots do not guarantee more quota, durability, ban avoidance, or Terms compliance. Do not use this feature to evade Telegram limits. All bots remain under Telegram's control, so this is distribution—not redundancy.
|
|
146
|
+
|
|
147
|
+
### 🧯 Index Recovery
|
|
148
|
+
|
|
149
|
+
Every completed storage mutation publishes a gzip-compressed, AES-256-GCM-authenticated manifest containing the file/chunk mapping and tags. Ephemeral share tokens are deliberately excluded. The latest pointer is stored in `config.json`.
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
tas index backup # Publish a fresh encrypted recovery point
|
|
153
|
+
tas index rebuild # Authenticate and rebuild index.db
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Keep `config.json` and your password separately: recovery cannot discover the latest manifest if both the database and config are lost.
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
163
160
|
### 🔗 Expiring Share Links
|
|
164
161
|
|
|
165
162
|
Generate time-limited, download-limited share links. Recipients get a clean dark-themed download page. **Your password is never shared — files are decrypted on-the-fly by the local server.**
|
|
@@ -192,11 +189,12 @@ tas search -t secrets # Quickly find your credentials
|
|
|
192
189
|
```bash
|
|
193
190
|
tas doctor
|
|
194
191
|
# ✓ Node.js 20.11.0
|
|
195
|
-
# ✓ Config
|
|
192
|
+
# ✓ Config v3 (encrypted multi-bot token set)
|
|
196
193
|
# ✓ Database: 42 files, 1.3 GB total across 28 chunks
|
|
197
194
|
# ✓ Disk space: 50 GB free (32% used)
|
|
198
195
|
# ✓ Encryption: AES-256-GCM · PBKDF2-SHA512 · 600,000 iterations (OWASP 2025)
|
|
199
|
-
# ✓
|
|
196
|
+
# ✓ FUSE runtime: mount → readdir → unmount passed
|
|
197
|
+
# ✓ Telegram connectivity: 2/2 bots OK
|
|
200
198
|
# ✨ All systems go!
|
|
201
199
|
```
|
|
202
200
|
|
|
@@ -272,7 +270,7 @@ jobs:
|
|
|
272
270
|
|
|
273
271
|
## 🛡️ Security Model
|
|
274
272
|
|
|
275
|
-
TAS
|
|
273
|
+
TAS applies **client-side authenticated encryption**. TAS has no hosted service that receives your password, but this is not a formal zero-knowledge protocol and it does not hide all traffic metadata from Telegram.
|
|
276
274
|
|
|
277
275
|
| Layer | Implementation | Standard |
|
|
278
276
|
|---|---|---|
|
|
@@ -281,45 +279,47 @@ TAS implements **zero-knowledge encryption** — we can't read your data, Telegr
|
|
|
281
279
|
| **Salt** | 32 bytes, `crypto.randomBytes()` — unique per file | No rainbow tables |
|
|
282
280
|
| **IV/Nonce** | 12 bytes, `crypto.randomBytes()` — unique per file | No nonce reuse |
|
|
283
281
|
| **Auth Tag** | 16 bytes GCM tag — any tampered bit = instant rejection | Tamper detection |
|
|
284
|
-
| **Bot
|
|
282
|
+
| **Bot Tokens** | Encrypted independently at rest in `config.json` | Config v3 |
|
|
285
283
|
| **Password Verification** | `crypto.timingSafeEqual()` on both PBKDF2 and legacy paths | Timing-safe |
|
|
286
284
|
| **Config Permissions** | `chmod 600 config.json` on creation | No world-readable secrets |
|
|
287
|
-
| **
|
|
285
|
+
| **Recovery Manifest** | gzip + AES-256-GCM; authenticated before SQLite import | Remote index recovery |
|
|
286
|
+
| **Integrity** | SHA-256 hash verified on completed downloads | Detects mismatch/corruption |
|
|
288
287
|
| **Share Server** | Binds `127.0.0.1` by default, XSS-escaped, RFC 6266 filenames | LAN-safe |
|
|
289
288
|
|
|
290
289
|
### What Telegram Actually Sees
|
|
291
290
|
|
|
292
291
|
```
|
|
293
|
-
|
|
292
|
+
chunk-000000.tas — 12.4 MB — caption: tas:c1:42:1/2
|
|
294
293
|
```
|
|
295
294
|
|
|
296
|
-
|
|
295
|
+
New uploads expose no user filename or original size in the document name, caption, or public WAS1 routing header. Telegram can still observe encrypted size, chunk count, timing, bot/chat identity, IP/network data, and message identifiers. Files uploaded by TAS 2.5 and older may still expose filename/size metadata until re-uploaded.
|
|
297
296
|
|
|
298
297
|
### Threat Model
|
|
299
298
|
|
|
300
299
|
| Threat | Mitigated? | How |
|
|
301
300
|
|---|---|---|
|
|
302
|
-
| Telegram reads
|
|
303
|
-
|
|
|
304
|
-
|
|
|
305
|
-
| Tampered download |
|
|
306
|
-
|
|
|
307
|
-
| Share link exposure |
|
|
301
|
+
| Telegram reads plaintext content | Mitigated | AES-256-GCM, assuming a strong password and uncompromised client |
|
|
302
|
+
| Telegram observes traffic metadata | Not mitigated | Bot/chat, timing, encrypted sizes, and chunk counts remain visible |
|
|
303
|
+
| Someone steals `config.json` | Partly mitigated | Tokens are encrypted; an offline password attack is still possible |
|
|
304
|
+
| Tampered download | Mitigated | GCM authentication plus final SHA-256 verification |
|
|
305
|
+
| Local machine compromise | Not mitigated | A process with password/filesystem access can read plaintext and tokens |
|
|
306
|
+
| Share link exposure | Limited | Localhost default, expiry, and download limits; the local server decrypts content |
|
|
308
307
|
|
|
309
308
|
---
|
|
310
309
|
|
|
311
310
|
## 🔄 Reliability
|
|
312
311
|
|
|
313
|
-
|
|
312
|
+
Reliability mechanisms implemented by TAS (not an SLA):
|
|
314
313
|
|
|
315
314
|
| Feature | Implementation |
|
|
316
315
|
|---|---|
|
|
317
316
|
| **Exponential Backoff** | Auto-retry with jitter on Telegram 429 errors and network timeouts |
|
|
318
|
-
| **Rate Limiting** |
|
|
317
|
+
| **Rate Limiting** | One serialized send queue per configured bot within a TAS process; parallel TAS processes and Telegram's dynamic limits still apply |
|
|
319
318
|
| **Integrity Verification** | SHA-256 hash verified after every single download |
|
|
320
|
-
| **Resume Uploads** | `tas resume`
|
|
321
|
-
| **
|
|
322
|
-
| **
|
|
319
|
+
| **Resume Uploads** | Network-stage chunks are staged on disk and persisted in `pending_uploads`; `tas resume` continues them |
|
|
320
|
+
| **Index Recovery** | Authenticated encrypted remote manifest; `tas index rebuild` restores file/chunk ownership |
|
|
321
|
+
| **Graceful Shutdown** | SIGINT/SIGTERM handled; staged chunks and SQLite WAL reduce partial-state risk |
|
|
322
|
+
| **Self-Diagnostics** | Checks config/database/chunk limits, all bots, and a real native FUSE smoke mount |
|
|
323
323
|
|
|
324
324
|
---
|
|
325
325
|
|
|
@@ -329,16 +329,20 @@ Built with the same philosophy as professional backup tools (restic, borg, rclon
|
|
|
329
329
|
<summary><strong>Core Commands</strong></summary>
|
|
330
330
|
|
|
331
331
|
```bash
|
|
332
|
-
tas init
|
|
333
|
-
tas push <
|
|
332
|
+
tas init [--token T --chat ID --password PW] # 🚀 Wizard, or fully non-interactive for CI/Docker
|
|
333
|
+
tas push <files...> # ⬆️ Encrypt + compress + upload (batch supported)
|
|
334
334
|
tas pull <file|hash> # ⬇️ Download + decrypt + verify
|
|
335
335
|
tas list [-l] [--json] # 📋 List all stored files
|
|
336
336
|
tas delete <file|hash> # 🗑️ Remove from index (--hard removes from Telegram)
|
|
337
337
|
tas status [--json] # 📊 Storage stats & database health
|
|
338
338
|
tas search <query> [-t tag] # 🔍 Find by filename or tag
|
|
339
339
|
tas resume # 🔄 Resume interrupted uploads
|
|
340
|
-
tas verify # ✅
|
|
340
|
+
tas verify # ✅ Check every Telegram file reference
|
|
341
|
+
tas verify --deep # ✅ Download/decrypt/hash every file (slow and bandwidth-heavy)
|
|
341
342
|
tas doctor # 🩺 Full system health check
|
|
343
|
+
tas index backup # 🧯 Publish encrypted recovery manifest
|
|
344
|
+
tas index rebuild # 🧯 Restore index.db from that manifest
|
|
345
|
+
tas bot add|list|enable|disable|remove # 🤖 Manage experimental bot pool
|
|
342
346
|
```
|
|
343
347
|
|
|
344
348
|
</details>
|
|
@@ -347,7 +351,7 @@ tas doctor # 🩺 Full system health check
|
|
|
347
351
|
<summary><strong>Mount & Sync</strong></summary>
|
|
348
352
|
|
|
349
353
|
```bash
|
|
350
|
-
# FUSE Mount
|
|
354
|
+
# FUSE Mount (Linux/libfuse or macOS/current macFUSE)
|
|
351
355
|
tas mount <path> # Mount Telegram storage as a local folder
|
|
352
356
|
tas unmount <path> # Clean unmount
|
|
353
357
|
|
|
@@ -365,7 +369,7 @@ tas sync status # Show sync queue and status
|
|
|
365
369
|
|
|
366
370
|
```bash
|
|
367
371
|
# Expiring Share Links
|
|
368
|
-
tas share create <file> [--expire 1h|24h|7d] [--max-downloads N]
|
|
372
|
+
tas share create <file> [--expire 1h|24h|7d] [--max-downloads N] [--host 0.0.0.0] [--port 3000]
|
|
369
373
|
tas share list # Active links with expiry countdown
|
|
370
374
|
tas share revoke <token> # Instantly revoke a share
|
|
371
375
|
|
|
@@ -395,12 +399,14 @@ TAS_DATA_DIR="/custom/path" # Override default ~/.tas data directory
|
|
|
395
399
|
src/
|
|
396
400
|
├── cli.js # Commander-based CLI — all commands defined here
|
|
397
401
|
├── index.js # Core streaming upload/download pipeline
|
|
402
|
+
├── manifest.js # Encrypted remote index backup/rebuild
|
|
398
403
|
├── crypto/
|
|
399
404
|
│ └── encryption.js # AES-256-GCM + PBKDF2-SHA512 (600k iterations)
|
|
400
405
|
├── db/
|
|
401
406
|
│ └── index.js # SQLite index: files, chunks, tags, shares, sync
|
|
402
407
|
├── telegram/
|
|
403
|
-
│
|
|
408
|
+
│ ├── client.js # Bot API wrapper — retry + serialized send queue
|
|
409
|
+
│ └── pool.js # Stable per-chunk multi-bot routing
|
|
404
410
|
├── fuse/
|
|
405
411
|
│ └── mount.js # FUSE filesystem — mount Telegram as a local folder
|
|
406
412
|
├── share/
|
|
@@ -410,7 +416,8 @@ src/
|
|
|
410
416
|
└── utils/
|
|
411
417
|
├── download-stream.js # Shared Telegram→Decrypt→Decompress pipeline
|
|
412
418
|
├── compression.js # Smart gzip (skips already-compressed formats)
|
|
413
|
-
├── chunker.js #
|
|
419
|
+
├── chunker.js # 19 MiB payloads + metadata-free public WAS1 headers
|
|
420
|
+
├── logical-path.js # Portable exact paths + virtual directory tree
|
|
414
421
|
├── progress.js # Terminal progress bars with MB/s + ETA
|
|
415
422
|
├── throttle.js # Bandwidth limiter (stream transform)
|
|
416
423
|
├── branding.js # ASCII art + version display
|
|
@@ -434,24 +441,17 @@ src/
|
|
|
434
441
|
| 💾 **Offsite backup** | Nightly database dumps, system configs via cron |
|
|
435
442
|
| 🤖 **CI/CD artifacts** | Store build outputs, test reports, deployment keys |
|
|
436
443
|
|
|
437
|
-
**Not
|
|
444
|
+
**Not appropriate for:** the only copy of any data, mission-critical/business backups, regulated retention, team storage, or workloads that require an SLA. Telegram can remove messages or terminate access without giving TAS a recovery channel.
|
|
438
445
|
|
|
439
446
|
---
|
|
440
447
|
|
|
441
448
|
## ❓ Is This Allowed? (The Legal Question)
|
|
442
449
|
|
|
443
|
-
###
|
|
444
|
-
|
|
445
|
-
**No.** Here's the complete picture:
|
|
450
|
+
### Can Telegram restrict or terminate this use?
|
|
446
451
|
|
|
447
|
-
|
|
448
|
-
- ✅ **You're sending to your own private bot chat** — not a public channel, not spamming
|
|
449
|
-
- ✅ **Content is encrypted** — Telegram cannot detect what you're storing
|
|
450
|
-
- ✅ **No published storage limits** — individual files cap at 2 GB (TAS chunks automatically)
|
|
451
|
-
- ✅ **Strong precedent** — thousands of file-sharing bots, backup tools, and media archives use this API
|
|
452
|
-
- ⚠️ **Worst case** — Telegram might prune old messages to free infrastructure space. They won't ban you for using a documented API
|
|
452
|
+
**Yes.** The Bot API supports sending documents, but that technical capability is not permission or a storage guarantee. Telegram's current [Bot Developer Terms](https://telegram.org/tos/bot-developers) explicitly restrict external applications that diverge into cloud-storage use cases, prohibit circumventing rate limits, and allow bot/account termination. TAS cannot promise that one bot—or a multi-bot pool—will remain available.
|
|
453
453
|
|
|
454
|
-
|
|
454
|
+
Use TAS only at your own risk, do not use multiple bots to evade limits, follow all applicable laws and Telegram terms, and keep a tested independent backup. Encryption protects content confidentiality; it does not make the usage invisible or policy-compliant.
|
|
455
455
|
|
|
456
456
|
---
|
|
457
457
|
|
|
@@ -460,9 +460,10 @@ src/
|
|
|
460
460
|
| | |
|
|
461
461
|
|---|---|
|
|
462
462
|
| 📌 **Not a replacement for backups** | Telegram can purge old messages. Use TAS alongside, not instead of, real backup solutions. |
|
|
463
|
-
| 📌 **
|
|
464
|
-
| 📌 **
|
|
465
|
-
| 📌 **
|
|
463
|
+
| 📌 **19 MiB payload chunks** | Hosted Bot API uploads permit more, but `getFile` documents only 20 MB downloads. TAS stays below the read limit. |
|
|
464
|
+
| 📌 **Multi-bot is experimental** | It distributes chunks and preserves ownership mapping; it is not redundancy or ban protection. |
|
|
465
|
+
| 📌 **macOS needs a native build** | Install current macFUSE and Xcode Command Line Tools before installing TAS. `tas doctor` must pass its real FUSE smoke test before you mount data. |
|
|
466
|
+
| 📌 **Recovery needs config** | `index.db` can be rebuilt from the encrypted manifest only if `config.json`, password, manifest message, and owning bot survive. |
|
|
466
467
|
| 📌 **No versioning (yet)** | Overwriting a file replaces the previous version. |
|
|
467
468
|
| 📌 **Internet required** | Telegram-backed — offline access requires files pulled locally first. |
|
|
468
469
|
|
|
@@ -474,7 +475,7 @@ src/
|
|
|
474
475
|
git clone https://github.com/ixchio/tas
|
|
475
476
|
cd tas && npm install
|
|
476
477
|
|
|
477
|
-
npm test # Run all
|
|
478
|
+
npm test # Run all 97 tests (crypto, paths, migrations, multi-bot, resume, manifest, sync, shares)
|
|
478
479
|
npm test -- --watch # Watch mode for active development
|
|
479
480
|
```
|
|
480
481
|
|