@needmoretruth/nmts-cli 0.36.1 → 0.36.2
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 +9 -0
- package/README.ko.md +1 -1
- package/README.md +1 -1
- package/dist/artifact-about.d.ts +1 -1
- package/dist/commands/platform.js +35 -6
- package/dist/commands/share.js +1 -1
- package/dist/product.d.ts +1 -1
- package/dist/product.js +1 -1
- package/dist/upload-steps.js +1 -1
- package/dist/wallet-grant.js +1 -1
- package/docs/commands/platform.md +2 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,15 @@
|
|
|
3
3
|
Each version's entry is what changed for the person or the program using `nmts`. The product's own
|
|
4
4
|
update history, which covers the site and the server too, is at https://nmts.me/updates.
|
|
5
5
|
|
|
6
|
+
## 0.36.2 — 2026-09-19
|
|
7
|
+
|
|
8
|
+
- On Windows, `platform keygen` now restricts the key file instead of only reporting that no file
|
|
9
|
+
mode applies: it removes the permissions inherited from the folder and grants your account
|
|
10
|
+
alone (`icacls`). The file is written wherever the command runs, which may be a shared folder.
|
|
11
|
+
If that step fails the command says so and the file is still written.
|
|
12
|
+
- Three filler words are gone from the advice printed by `share`, a resumed upload and a wallet
|
|
13
|
+
agreement that asks for too long a term.
|
|
14
|
+
|
|
6
15
|
## 0.36.1 — 2026-09-19
|
|
7
16
|
|
|
8
17
|
- On Windows, `platform keygen` says that the key file inherits its folder's permissions, because
|
package/README.ko.md
CHANGED
|
@@ -50,7 +50,7 @@ nmts --help
|
|
|
50
50
|
|
|
51
51
|
```sh
|
|
52
52
|
npm install -g github:needmoretruth/nmts-cli # 기본 브랜치
|
|
53
|
-
npm install -g github:needmoretruth/nmts-cli#v0.36.
|
|
53
|
+
npm install -g github:needmoretruth/nmts-cli#v0.36.2 # 버전을 고정할 때
|
|
54
54
|
npm install -g https://github.com/needmoretruth/nmts-cli/releases/latest/download/nmts.tgz
|
|
55
55
|
```
|
|
56
56
|
|
package/README.md
CHANGED
|
@@ -51,7 +51,7 @@ default branch, from a pinned version, or from the tarball attached to the
|
|
|
51
51
|
|
|
52
52
|
```sh
|
|
53
53
|
npm install -g github:needmoretruth/nmts-cli # the default branch
|
|
54
|
-
npm install -g github:needmoretruth/nmts-cli#v0.36.
|
|
54
|
+
npm install -g github:needmoretruth/nmts-cli#v0.36.2 # a pinned version
|
|
55
55
|
npm install -g https://github.com/needmoretruth/nmts-cli/releases/latest/download/nmts.tgz
|
|
56
56
|
```
|
|
57
57
|
|
package/dist/artifact-about.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ export declare const CRYPTO_SPEC_URL = "https://github.com/needmoretruth/nmts-re
|
|
|
11
11
|
* is the field's own contract — what the writer says about itself — and a person holding two
|
|
12
12
|
* copies of one account's artefacts can then tell which program made each.
|
|
13
13
|
*/
|
|
14
|
-
export declare const WRITTEN_BY = "nmts-cli 0.36.
|
|
14
|
+
export declare const WRITTEN_BY = "nmts-cli 0.36.2";
|
|
15
15
|
/** Which of the three artefacts a wrapper is. A reader holding several can sort them. */
|
|
16
16
|
export type ArtifactKind = "recovery-list" | "file-list" | "recovery-kit";
|
|
17
17
|
/**
|
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
// ⛔ AND THE FILE IS NEVER REPLACED. `--force` does not open it: the file it would overwrite may
|
|
13
13
|
// hold the only copy of a key a business is already registered under, and replacing it locks
|
|
14
14
|
// that business out of its own door with nothing able to bring the key back.
|
|
15
|
+
import { spawnSync } from "node:child_process";
|
|
15
16
|
import { mkdirSync, statSync, writeFileSync } from "node:fs";
|
|
17
|
+
import { userInfo } from "node:os";
|
|
16
18
|
import { isAbsolute, resolve } from "node:path";
|
|
17
19
|
import { modesAreEnforced } from "../credentials.js";
|
|
18
20
|
import { NmtsError } from "../errors.js";
|
|
@@ -45,14 +47,42 @@ function keygen(out, say) {
|
|
|
45
47
|
writeKeyFile(path, keys);
|
|
46
48
|
say(`Public key: ${keys.publicKey}`);
|
|
47
49
|
say(`Written to: ${path}`);
|
|
48
|
-
// The same sentence `nmts doctor` uses for a stored key: where no mode applies, say so.
|
|
49
50
|
if (!modesAreEnforced()) {
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
// ⚠ THIS FILE LANDS WHEREVER THE COMMAND WAS RUN, which may be a shared folder — unlike the
|
|
52
|
+
// stored NMTS key, which lives under the user's own profile. So on Windows the mode is not
|
|
53
|
+
// merely reported as absent: the file is cut off from the folder's permissions.
|
|
54
|
+
say(restrictToCurrentUser(path)
|
|
55
|
+
? `Inherited permissions were removed; only your Windows account can open this file.`
|
|
56
|
+
: `Windows applies no POSIX file mode, and restricting the file with icacls failed, so it ` +
|
|
57
|
+
`inherits its folder's permissions. Move it somewhere only you can read.`);
|
|
52
58
|
}
|
|
53
59
|
say(`Register the public key at ${HOME_URL} — ${REGISTER_PATH}. The private half stays in that file.`);
|
|
54
60
|
return 0;
|
|
55
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* Windows only: drop the inherited entries and grant the current account alone.
|
|
64
|
+
*
|
|
65
|
+
* ⛔ `icacls`, NOT A HAND-ROLLED ACL. It ships with every supported Windows, and this is the shape
|
|
66
|
+
* OpenSSH asks of a private key there. One invocation does both halves, so there is no moment
|
|
67
|
+
* with the inheritance gone and nobody granted.
|
|
68
|
+
* ⚠ A FAILURE IS REPORTED, NOT THROWN: the pair is already written and is the only copy, so the
|
|
69
|
+
* command must still print the public half and say plainly what protects the file.
|
|
70
|
+
*/
|
|
71
|
+
function restrictToCurrentUser(path) {
|
|
72
|
+
try {
|
|
73
|
+
const name = userInfo().username;
|
|
74
|
+
const domain = process.env.USERDOMAIN;
|
|
75
|
+
const account = domain === undefined || domain === "" ? name : `${domain}\\${name}`;
|
|
76
|
+
const done = spawnSync("icacls", [path, "/inheritance:r", "/grant:r", `${account}:F`], {
|
|
77
|
+
windowsHide: true,
|
|
78
|
+
stdio: "ignore",
|
|
79
|
+
});
|
|
80
|
+
return done.status === 0;
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
56
86
|
/**
|
|
57
87
|
* Say where registering happens, and stop.
|
|
58
88
|
*
|
|
@@ -101,9 +131,8 @@ function targetFor(out) {
|
|
|
101
131
|
* ⚠ `wx` FAILS IF THE NAME APPEARED SINCE THE CHECK ABOVE, which is the point of using it rather
|
|
102
132
|
* than trusting that check: between the two, something else may have written there.
|
|
103
133
|
*
|
|
104
|
-
* ⚠ ON WINDOWS THE MODE IS IGNORED
|
|
105
|
-
*
|
|
106
|
-
* platform does not give.
|
|
134
|
+
* ⚠ ON WINDOWS THE MODE IS IGNORED; `keygen` restricts the file afterwards with `icacls` and says
|
|
135
|
+
* which of the two happened.
|
|
107
136
|
*/
|
|
108
137
|
function writeKeyFile(path, keys) {
|
|
109
138
|
mkdirSync(resolve(path, ".."), { recursive: true, mode: 0o700 });
|
package/dist/commands/share.js
CHANGED
|
@@ -114,7 +114,7 @@ export async function share(target, typedAddress, options = {}) {
|
|
|
114
114
|
if (typeof identityB64 !== "string") {
|
|
115
115
|
throw new NmtsError("That public code has never published an identity to share to.", {
|
|
116
116
|
exitCode: 4,
|
|
117
|
-
nextStep: "Nothing was shared. The code may be right and
|
|
117
|
+
nextStep: "Nothing was shared. The code may be right and unused — somebody has to open " +
|
|
118
118
|
"their account once before anything can be encrypted to them.",
|
|
119
119
|
});
|
|
120
120
|
}
|
package/dist/product.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export declare const BINARY_NAME = "nmts";
|
|
|
9
9
|
* beside it. Here rather than in `main.ts` because the MCP server has to say it too, and a
|
|
10
10
|
* command importing the entry point is a cycle waiting to bite.
|
|
11
11
|
*/
|
|
12
|
-
export declare const VERSION = "0.36.
|
|
12
|
+
export declare const VERSION = "0.36.2";
|
|
13
13
|
/** Where the product lives, for messages that need to send somebody somewhere real. */
|
|
14
14
|
export declare const HOME_URL = "https://nmts.me";
|
|
15
15
|
/** The source, so a person holding only the built program can find what it was built from. */
|
package/dist/product.js
CHANGED
|
@@ -18,7 +18,7 @@ export const BINARY_NAME = "nmts";
|
|
|
18
18
|
* beside it. Here rather than in `main.ts` because the MCP server has to say it too, and a
|
|
19
19
|
* command importing the entry point is a cycle waiting to bite.
|
|
20
20
|
*/
|
|
21
|
-
export const VERSION = "0.36.
|
|
21
|
+
export const VERSION = "0.36.2";
|
|
22
22
|
/** Where the product lives, for messages that need to send somebody somewhere real. */
|
|
23
23
|
export const HOME_URL = "https://nmts.me";
|
|
24
24
|
/** The source, so a person holding only the built program can find what it was built from. */
|
package/dist/upload-steps.js
CHANGED
|
@@ -49,7 +49,7 @@ export async function pushPart(input, step) {
|
|
|
49
49
|
message: why(error),
|
|
50
50
|
paid: true,
|
|
51
51
|
nextStep: "The bytes are on the network. Certifying moves no money, so running the same command " +
|
|
52
|
-
"again
|
|
52
|
+
"again finishes the job.",
|
|
53
53
|
});
|
|
54
54
|
}
|
|
55
55
|
}
|
package/dist/wallet-grant.js
CHANGED
|
@@ -80,7 +80,7 @@ export function parseWalletGrant(input, now, version) {
|
|
|
80
80
|
if (expiresMs > ceiling) {
|
|
81
81
|
throw new NmtsError(`A wallet agreement lasts at most ${MAX_GRANT_DAYS} days.`, {
|
|
82
82
|
exitCode: 2,
|
|
83
|
-
nextStep: `Grant it again when it runs out.
|
|
83
|
+
nextStep: `Grant it again when it runs out. An agreement ends on its own so that one nobody remembers giving does not stay open.`,
|
|
84
84
|
});
|
|
85
85
|
}
|
|
86
86
|
return {
|
|
@@ -4,7 +4,8 @@ Commands: platform
|
|
|
4
4
|
Tiers: platform=none · platform.keygen=medium
|
|
5
5
|
|
|
6
6
|
`platform keygen` makes an Ed25519 key pair and writes both halves to `nmts-business-key.json`, or
|
|
7
|
-
to `--out <file>`, with mode 0600 (Windows
|
|
7
|
+
to `--out <file>`, with mode 0600 (on Windows, where no file mode applies, it removes the inherited
|
|
8
|
+
permissions with `icacls` and leaves your account alone on the file, and says so if that fails). It
|
|
8
9
|
refuses a name that already exists, whatever `--force` says, and prints only the public half.
|
|
9
10
|
`platform register` cannot register it: that needs a signed-in browser session at nmts.me, under
|
|
10
11
|
Settings › Developer › Platform, and the command prints that path and exits 2.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@needmoretruth/nmts-cli",
|
|
3
|
-
"version": "0.36.
|
|
3
|
+
"version": "0.36.2",
|
|
4
4
|
"description": "Command-line and MCP access to NMTS (NeedMoreTruthStorage, https://nmts.me): open-source, end-to-end encrypted storage on the Walrus network. No fee to NMTS; you pay the network from your own wallet. For people and for their agents.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"publishConfig": {
|