scp-next 1.1.8 → 1.1.10

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.
@@ -0,0 +1,146 @@
1
+ # Troubleshoot SSH host verification
2
+
3
+ Use this procedure when `scp-next` reports `HostVerificationError`. It applies to SFTP
4
+ transfers and explicit remote-command connections. Troubleshooting never requires disabling
5
+ verification.
6
+
7
+ ## 1. Check the endpoint and trust settings
8
+
9
+ Read the host, port, selected known-hosts file, and explicit-fingerprint status in the error.
10
+ The default port is `22`; the default trust file is `~/.ssh/known_hosts`. `~` expands to the
11
+ current user's home directory. A custom `knownHostsFile` must be accessible even when an
12
+ explicit `hostFingerprint` is configured. An inaccessible default file can be skipped when
13
+ an explicit fingerprint is configured.
14
+
15
+ - **File not found:** check the selected path and the account running the process.
16
+ - **File could not be read:** check permissions and whether the path is a readable file.
17
+ - **No usable matching keys:** the file was read, but supplied no supported matching entries.
18
+ - **Connection-time failure:** the host key could not be verified. This message alone does
19
+ not establish that a previously trusted key changed.
20
+
21
+ Use the same hostname or IP address as the transfer, not an SSH configuration alias that
22
+ resolves to another endpoint. `scp-next` supports exact plain host entries and bracketed
23
+ `[host]:port` entries. It does not interpret hashed hostnames, wildcard patterns, or OpenSSH
24
+ marker entries such as `@cert-authority` and `@revoked`. Ordinary `ssh` can therefore succeed
25
+ with a trust file that `scp-next` cannot use. Use a verified explicit fingerprint or a
26
+ separate plain-entry trust file if those limitations apply. Plain entries expose hostnames
27
+ to anyone who can read the file; keep access appropriately restricted.
28
+
29
+ Do not convert a revoked key into a plain trusted entry or use a fingerprint to bypass
30
+ revocation. If you rely on OpenSSH certificate or revocation policy, resolve the unsupported
31
+ policy with your administrator before using `scp-next`; its parser does not enforce that policy.
32
+
33
+ ## 2. Scan into a temporary file and inspect fingerprints
34
+
35
+ Install OpenSSH's `ssh-keyscan` and `ssh-keygen` commands first. Replace `your-host` and
36
+ `2222` below with the configured hostname or single IP address and port. Do not use a CIDR
37
+ range, an option, or a comma-separated host list. These commands contact the server but do
38
+ not add anything to your trusted file. Do not use `-H`, which hashes hostnames.
39
+
40
+ > Warning: scanning does not authenticate the server. An intercepted scan can return an
41
+ > attacker's keys. Do not trust any result until you complete the independent verification
42
+ > in the next section. See the [OpenSSH ssh-keyscan manual](https://man.openbsd.org/ssh-keyscan).
43
+
44
+ ### POSIX shell (macOS or Linux)
45
+
46
+ Run in a dedicated shell session or script; failure branches exit that session.
47
+
48
+ ```sh
49
+ server_host='your-host'
50
+ server_port='2222'
51
+ scan_file=$(mktemp) || exit 1
52
+
53
+ if ! ssh-keyscan -p "$server_port" "$server_host" > "$scan_file"; then
54
+ echo 'Scan failed; do not update trust.' >&2
55
+ rm -- "$scan_file"
56
+ exit 1
57
+ fi
58
+ if ! awk 'NF >= 3 && $1 !~ /^#/ { found=1 } END { exit !found }' "$scan_file"; then
59
+ echo 'No host keys returned; do not update trust.' >&2
60
+ rm -- "$scan_file"
61
+ exit 1
62
+ fi
63
+ if ! ssh-keygen -l -E sha256 -f "$scan_file"; then
64
+ echo 'Fingerprint inspection failed; do not update trust.' >&2
65
+ rm -- "$scan_file"
66
+ exit 1
67
+ fi
68
+ printf 'Temporary scan file: %s\n' "$scan_file"
69
+ ```
70
+
71
+ ### PowerShell (Windows)
72
+
73
+ Explicit UTF-8 encoding avoids Windows PowerShell's default UTF-16 file output.
74
+
75
+ ```powershell
76
+ $serverHost = 'your-host'
77
+ $serverPort = '2222'
78
+ $scanFile = [System.IO.Path]::GetTempFileName()
79
+ try {
80
+ $scanLines = @(& ssh-keyscan -p "$serverPort" "$serverHost")
81
+ if (-not $? -or $LASTEXITCODE -ne 0) { throw 'Scan failed; do not update trust.' }
82
+ $keyLines = @($scanLines | Where-Object {
83
+ $_ -notmatch '^#' -and $_ -match '^\S+\s+\S+\s+\S+'
84
+ })
85
+ if ($keyLines.Count -eq 0) { throw 'No host keys returned; do not update trust.' }
86
+ [System.IO.File]::WriteAllLines(
87
+ $scanFile, [string[]]$scanLines, [System.Text.UTF8Encoding]::new($false)
88
+ )
89
+ & ssh-keygen -l -E sha256 -f "$scanFile"
90
+ if (-not $? -or $LASTEXITCODE -ne 0) { throw 'Fingerprint inspection failed; do not update trust.' }
91
+ Write-Output "Temporary scan file: $scanFile"
92
+ } catch {
93
+ Remove-Item -LiteralPath $scanFile
94
+ throw
95
+ }
96
+ ```
97
+
98
+ `ssh-keygen -l -E sha256` displays SHA-256 fingerprints for inspection. See the
99
+ [OpenSSH ssh-keygen manual](https://man.openbsd.org/ssh-keygen). A scan may return multiple
100
+ key types or only some of the server's keys; do not assume every key was collected.
101
+
102
+ ## 3. Verify each key independently
103
+
104
+ Compare the fingerprint and key type of every key you intend to trust with values from a
105
+ trusted server console, administrator, or authenticated provider interface. Repeating the
106
+ scan over the same connection is not independent verification. If no trusted source is
107
+ available, stop and contact the administrator.
108
+
109
+ If a previously trusted key differs, investigate before changing trust. Confirm an authorized
110
+ key rotation, server rebuild, or endpoint change through the independent source. Do not
111
+ assume that a changed key is harmless.
112
+
113
+ ## 4. Save only verified keys
114
+
115
+ Review the temporary file in a text editor. Copy only independently verified key lines to
116
+ the exact `knownHostsFile` selected by your configuration. Do not append the entire scan
117
+ automatically. Create the parent directory if necessary and restrict write access to trusted
118
+ accounts. Preserve plain host fields, key types, and base64 keys; save the file as UTF-8.
119
+
120
+ For an authorized replacement, back up the existing file first. Remove only the affected
121
+ obsolete keys, preserving unrelated hosts and aliases. A line can contain several
122
+ comma-separated aliases; split it if necessary rather than deleting trust for other hosts.
123
+ Do not leave obsolete keys trusted merely because adding a new key makes the connection work.
124
+
125
+ Alternatively, configure `hostFingerprint` with a verified `SHA256:...` value. Explicit
126
+ fingerprints and matching known-hosts keys form a combined allowed set; the fingerprint does
127
+ not override the file. Adding a verified file entry does not remove a stale explicit
128
+ fingerprint. Review and update both sources after an authorized rotation.
129
+
130
+ ## 5. Retry and clean up
131
+
132
+ Retry the original transfer. If it still fails, recheck the endpoint, account, selected file,
133
+ explicit fingerprint, and negotiated key type. Do not repeatedly append scan results.
134
+ Remove the temporary file after troubleshooting:
135
+
136
+ ```sh
137
+ # POSIX shell
138
+ rm -- "$scan_file"
139
+ ```
140
+
141
+ ```powershell
142
+ # PowerShell
143
+ Remove-Item -LiteralPath $scanFile
144
+ ```
145
+
146
+ `scp-next` does not run these commands, scan hosts, or write trust files for you.
@@ -1,7 +1,8 @@
1
1
  # Host verification troubleshooting plan
2
2
 
3
- Status: Proposed. Implementation requires user confirmation. Creating this plan does not
4
- authorize changes to runtime code, SSH trust files, or server connections.
3
+ Status: Implemented after user approval. See the
4
+ [host verification troubleshooting guide](HOST_VERIFICATION_TROUBLESHOOTING.md).
5
+ The implementation does not scan hosts, modify SSH trust files, or disable verification.
5
6
 
6
7
  ## Goal
7
8
 
@@ -9,7 +10,7 @@ Replace generic SSH troubleshooting tips with concise guidance to scan, verify,
9
10
  host keys. Show the configured endpoint and trust file, and distinguish missing trust
10
11
  information from a possible key mismatch when the failure path provides that evidence.
11
12
 
12
- ## Current limitations
13
+ ## Baseline limitations (before implementation)
13
14
 
14
15
  - `hostVerificationTroubleshooting()` in `src/client/transport.ts` suggests `ssh <host>`
15
16
  without the configured port or known-hosts path.
@@ -105,3 +106,19 @@ artifact. Inspect the final diff and package contents before handoff.
105
106
 
106
107
  The package currently includes all of `guides` in its published files. This plan will therefore
107
108
  be included in a future package unless its location or packaging policy is deliberately changed.
109
+
110
+ ### Implementation validation
111
+
112
+ Typecheck, lint, all 102 tests, package build, ESM/CommonJS smoke checks, CLI shebang,
113
+ documentation links, the full documentation build (including SEO and PWA checks), and
114
+ `npm pack --dry-run` passed.
115
+
116
+ The initial Webpack schema failure came from a stale installation of Webpack 5.109.2, not
117
+ an invalid configuration. Synchronizing installed dependencies with the committed lockfile
118
+ restored Webpack 5.111.1, which supports `optimization.minimizeOptions`. The production-build
119
+ test now has a 60-second timeout rather than the default five seconds. Manifest and lockfile
120
+ versions and build configuration remain unchanged.
121
+
122
+ The README troubleshooting link uses the repository URL so TypeDoc does not copy the
123
+ handwritten Markdown guide into generated API media. Documentation links are checked again
124
+ after the Pages build to verify the generated output remains free of Markdown source files.
@@ -0,0 +1,205 @@
1
+ # Publish automatically to npm with GitHub Actions OIDC
2
+
3
+ Migrate `scp-next` from `NPM_TOKEN` to npm trusted publishing while preserving automatic
4
+ publication on pushes to `release/v*` branches. This guide assumes the package already
5
+ exists and you have configured its trusted publisher. It describes changes to make; it
6
+ does not mean the repository's workflow has already been migrated.
7
+
8
+ OpenID Connect (OIDC) lets GitHub issue a short-lived, signed workflow identity that npm
9
+ checks before authorizing publication. You do not store a permanent npm publishing token
10
+ in the repository. See [GitHub's OIDC explanation](https://docs.github.com/en/actions/concepts/security/openid-connect).
11
+
12
+ ## 1. Verify the trusted publisher
13
+
14
+ Sign in to npm as `mazeyqian` and open the existing `scp-next` package's settings. Confirm
15
+ that the GitHub Actions trusted publisher has these values:
16
+
17
+ | Field | Value |
18
+ | :------------------- | :---------------- |
19
+ | Organization or user | `chengchuu` |
20
+ | Repository | `scp-next` |
21
+ | Workflow filename | `publish-npm.yml` |
22
+ | Allowed action | Direct publishing |
23
+
24
+ Enable **Allow npm publish**; staging-only permission requires human approval. Enter the
25
+ workflow filename, not `.github/workflows/publish-npm.yml`. If you configured an environment,
26
+ record its exact name for step 3. See [npm's trusted-publisher configuration](https://docs.npmjs.com/trusted-publishers/).
27
+
28
+ The GitHub owner and npm account do not need matching usernames. `mazeyqian` manages the
29
+ npm package; `chengchuu` identifies the GitHub repository owner. Keep the npm package name
30
+ as `scp-next`.
31
+
32
+ ## 2. Preserve the existing triggers and toolchain
33
+
34
+ Open [the publishing workflow](../.github/workflows/publish-npm.yml). Keep:
35
+
36
+ - Push publication from `release/v*` branches.
37
+ - PR validation for `main` and `release/v*` without publication.
38
+ - `needs: test` and the publish job's `github.event_name == 'push'` condition.
39
+ - The current test-only behavior of `workflow_dispatch`.
40
+ - GitHub-hosted `ubuntu-latest` runners, Node 22, npm 11.18.0, and `npm install`.
41
+ - The npm registry URL `https://registry.npmjs.org/` in the publish job's Node setup.
42
+
43
+ OIDC requires Node 22.14.0 or later and npm 11.5.1 or later, so this CI toolchain qualifies.
44
+ See [npm's requirements](https://docs.npmjs.com/trusted-publishers/).
45
+
46
+ Do not upgrade to npm 12 as part of the authentication migration. Its install-time defaults
47
+ change dependency-script, native-build, Git-dependency, and remote-URL behavior; assess those
48
+ separately. See [the npm security announcement](https://github.blog/changelog/2026-07-08-npm-install-time-security-and-gat-bypass2fa-deprecation/).
49
+
50
+ Keep `pnpm-lock.yaml` as the committed lockfile. CI intentionally uses `npm install`, which
51
+ does not consume that lockfile; OIDC does not make dependency resolution reproducible.
52
+
53
+ ## 3. Scope permissions to the publishing job
54
+
55
+ Replace the workflow-level write permissions with:
56
+
57
+ ```yaml
58
+ permissions:
59
+ contents: read
60
+ ```
61
+
62
+ Add this block directly under `jobs.publish`, alongside `needs`, `runs-on`, and `if`:
63
+
64
+ ```yaml
65
+ permissions:
66
+ contents: write
67
+ packages: write
68
+ id-token: write
69
+ ```
70
+
71
+ These permissions have separate purposes:
72
+
73
+ - `id-token: write` enables npm OIDC authentication.
74
+ - `packages: write` preserves GitHub Packages publication.
75
+ - `contents: write` preserves the existing Git-tag creation and push.
76
+
77
+ The test job inherits read-only permissions. Do not grant it publishing permissions.
78
+ See [npm's workflow configuration](https://docs.npmjs.com/trusted-publishers/).
79
+
80
+ If step 1 identified an environment, add that exact `environment` name to the publish job.
81
+ Leave it unset otherwise. Required reviewers would prevent unattended publication.
82
+
83
+ ## 4. Replace only the npm authentication step
84
+
85
+ Replace the current **Publish to npm** step with:
86
+
87
+ ```yaml
88
+ - name: Publish to npm
89
+ run: npm publish --access public
90
+ ```
91
+
92
+ Remove its `NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}` entry. Check that no job-level or
93
+ workflow-level npm write token remains. npm detects OIDC automatically; do not add an npm
94
+ login step or manually request the identity token. See [npm's authentication behavior](https://docs.npmjs.com/trusted-publishers/).
95
+
96
+ Keep the GitHub Packages registry setup, scoped package-name change, and
97
+ `NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}` on its publication step. That registry still
98
+ uses GitHub authentication. Keep the restore step and post-publication Git tag.
99
+ See [GitHub Packages authentication](https://docs.github.com/en/actions/tutorials/publish-packages/publish-nodejs-packages#authenticating-to-the-destination-repository).
100
+
101
+ [The Pages workflow](../.github/workflows/pages.yml) needs no npm-authentication changes.
102
+ Its OIDC permission serves Pages deployment. Do not remove that permission.
103
+
104
+ ## 5. Review release safety before the first push
105
+
106
+ Protect `release/v*` branches and publishing-workflow changes. Anyone who can run altered
107
+ code in the trusted publishing job may be able to publish; OIDC does not establish that
108
+ the code is safe.
109
+
110
+ Consider these separate reliability improvements before enabling unattended releases:
111
+
112
+ - Serialize publishing jobs with a package-wide concurrency group, not one group per branch.
113
+ Do not cancel a publication already running. GitHub's default concurrency behavior replaces
114
+ an older pending run; use `queue: max` if you need multiple pending releases, and account
115
+ for queue limits and ordering. See [GitHub concurrency controls](https://docs.github.com/en/actions/how-tos/write-workflows/choose-when-workflows-run/control-workflow-concurrency).
116
+ - Define whether an already-published version should stop the run or be skipped after verifying
117
+ the expected artifact. Do not treat every registry error as an absent version.
118
+ - Make recovery from partial npm/GitHub Packages publication explicit. Separating registry jobs
119
+ is an option, but not a prerequisite for OIDC.
120
+ - Check existing Git tags against the intended commit; never overwrite a conflicting release tag.
121
+
122
+ The existing workflow does not provide these safeguards. A minimal OIDC migration preserves
123
+ that limitation; decide on hardening separately rather than assuming authentication fixes it.
124
+
125
+ ## 6. Validate the proposed workflow and release
126
+
127
+ Review the YAML diff before merging. Confirm that only the intended npm authentication and
128
+ permission settings changed, and that the snippets were inserted at the correct indentation.
129
+ Use a GitHub Actions-aware validator if one is available.
130
+
131
+ From the repository root, run the established package checks:
132
+
133
+ ```bash
134
+ npm run clean
135
+ npm run typecheck
136
+ npm run lint
137
+ npm test
138
+ npm run build
139
+ npm run docs:links
140
+ npm pack --dry-run
141
+ git diff --check
142
+ ```
143
+
144
+ Inspect the package contents for the ESM/CJS builds, declarations, CLI entry, README, license,
145
+ and guides. Preserve the existing `prepublishOnly` checks; do not disable lifecycle scripts
146
+ to bypass release validation. These checks are instructions for migration, not results
147
+ reported by this document.
148
+
149
+ Prepare an intentional release with an unpublished `package.json.version` and update
150
+ [the changelog](CHANGELOG.md). Check the published versions without publishing:
151
+
152
+ ```bash
153
+ npm view scp-next versions --json --registry=https://registry.npmjs.org/
154
+ ```
155
+
156
+ If the registry lookup fails, resolve the failure before deciding that the version is unused.
157
+ Also check the corresponding GitHub Packages version and Git tag. Branch pushes do not bump
158
+ versions automatically.
159
+
160
+ ## 7. Push the release and verify publication
161
+
162
+ **Warning:** pushing the migrated workflow and release to a matching `release/v*` branch
163
+ can publish a real package version. PR checks and manual workflow runs do not prove that
164
+ OIDC publication works.
165
+
166
+ 1. Commit the approved workflow and release changes.
167
+ 2. Push the intended release commit to the matching release branch.
168
+ 3. Open the **Publish npm Packages** run in GitHub Actions.
169
+ 4. Confirm that validation and the npm publication step succeed without `NPM_TOKEN`.
170
+ 5. Verify the exact version on npm, then verify GitHub Packages and the Git tag independently.
171
+ 6. Check the npm provenance information when publishing a public package from the public repository.
172
+
173
+ Trusted publishing generates provenance automatically when its conditions are met; an explicit
174
+ `--provenance` flag is not required. See [npm provenance documentation](https://docs.npmjs.com/generating-provenance-statements/).
175
+
176
+ Local checks and dry runs cannot verify registry authorization. Do not use `npm whoami`
177
+ as an OIDC publishing test. See [npm's OIDC limitations](https://docs.npmjs.com/trusted-publishers/).
178
+
179
+ ## 8. Remove obsolete credentials after verification
180
+
181
+ After a successful token-free npm publication:
182
+
183
+ 1. Remove the unused `NPM_TOKEN` secret from this repository's Actions secrets.
184
+ 2. Check whether other repositories or tools still use the same token.
185
+ 3. Revoke the npm token only after those consumers have migrated or stopped using it.
186
+
187
+ Keep `GITHUB_TOKEN` authentication for GitHub Packages. Repeat the package-specific trust
188
+ setup and workflow review for other npm repositories; this migration does not authorize them.
189
+
190
+ ## Troubleshoot or pause the rollout
191
+
192
+ - **Authentication fails:** verify the exact owner, repository, workflow filename, environment,
193
+ direct-publish permission, job-level OIDC permission, and toolchain. Confirm that the
194
+ package repository URL still identifies `chengchuu/scp-next`.
195
+ - **npm succeeds but GitHub Packages fails:** record the published version and run commit.
196
+ Do not blindly rerun the combined publish job. Arrange a reviewed recovery that publishes
197
+ only the missing artifact and creates the tag after verifying the release commit.
198
+ - **A version or tag already exists:** inspect its contents or commit before deciding how to
199
+ recover. Do not overwrite it or hide the failure.
200
+ - **You need to stop publishing:** pause the publishing workflow or block release-branch pushes
201
+ while investigating. Reverting YAML does not undo a published package.
202
+
203
+ Treat a published version as immutable. For an incorrect release, plan a corrected version
204
+ and, if appropriate, deprecate the affected version; do not make unpublishing part of routine
205
+ rollback. See [npm's unpublish policy](https://docs.npmjs.com/policies/unpublish/).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scp-next",
3
- "version": "1.1.8",
3
+ "version": "1.1.10",
4
4
  "description": "An SCP CLI and library for secure SSH file transfers using SFTP.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -26,7 +26,6 @@
26
26
  "dist",
27
27
  "README.md",
28
28
  "LICENSE",
29
- "CHANGELOG.md",
30
29
  "guides"
31
30
  ],
32
31
  "scripts": {
@@ -78,7 +77,7 @@
78
77
  },
79
78
  "dependencies": {
80
79
  "commander": "^12.1.0",
81
- "mazey": "^5.6.1",
80
+ "mazey": "^5.10.4",
82
81
  "ssh2": "^1.17.0",
83
82
  "ssh2-sftp-client": "^11.0.0",
84
83
  "zod": "^3.23.8"
@@ -108,7 +107,7 @@
108
107
  "typescript": "^5.7.2",
109
108
  "typescript-eslint": "^8.18.1",
110
109
  "vitest": "^4.1.9",
111
- "webpack": "^5.108.4",
110
+ "webpack": "^5.111.1",
112
111
  "webpack-cli": "^7.2.1",
113
112
  "webpack-dev-server": "^6.0.0"
114
113
  },
File without changes