opencode-harness-kit 0.3.9 → 0.4.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 CHANGED
@@ -14,6 +14,52 @@ is not happening.
14
14
 
15
15
  ## [Unreleased]
16
16
 
17
+ ## [0.4.1] — 2026-10-20
18
+
19
+ ### Added
20
+
21
+ - **The trusted publisher is configured**, so the release path holds no
22
+ secret: the tag triggers the workflow, the tests run, and the publish job
23
+ exchanges the runner's OIDC identity for a short-lived publish token. There
24
+ is no npm token in the repository to leak, rotate or expire.
25
+
26
+ ## [0.4.0] — 2026-10-20
27
+
28
+ ### Fixed
29
+
30
+ - **The create could not be completed at all.** npm prints the two-factor
31
+ challenge as `auth/cli/***` - masked - in text mode, and only puts the URL
32
+ that can be opened in the JSON body. The list asked for JSON and worked; the
33
+ create did not, and failed with a message that said nothing about why. Every
34
+ npm trust call asks for JSON now.
35
+ - **Each npm command gets its own two-factor challenge.** The code a browser
36
+ flow returns is valid for the challenge that asked for it and for nothing
37
+ else, so carrying one from one command to the next made the second command
38
+ send a code that was already spent - and the registry answered that with a
39
+ different challenge, one that wants an authenticator code rather than a
40
+ browser. The failure looked like "npm wants something else now" and nothing
41
+ like the cause.
42
+ - **The URLs come from the response body, not from a guess.** The done URL
43
+ was rebuilt from the id, which sent a real request to the registry with a
44
+ made-up id; the registry answered "forbidden", which is not a token, so the
45
+ wait ran its full length and then reported that nobody had answered.
46
+ - **`OC_TRUST_NO_BROWSER` turns the browser off.** A test that opens a
47
+ browser on the machine it runs on is a test that breaks whatever the
48
+ person at the keyboard was doing.
49
+
50
+ ### The release path, end to end
51
+
52
+ The publish is now automatic and holds no secret:
53
+
54
+ - The tag triggers the workflow; the tests run; the publish job exchanges the
55
+ runner's OIDC identity for a short-lived publish token, so there is no npm
56
+ token in the repository to leak, rotate or expire.
57
+ - A token still works when `NPM_TOKEN` is set, for the case where OIDC is not
58
+ configured.
59
+ - `oc-harness trust` sets the trusted publisher up, and completes the
60
+ two-factor challenge in a browser - which works with an authenticator app, a
61
+ security key, or a code sent to the email.
62
+
17
63
  ## [0.3.9] — 2026-10-20
18
64
 
19
65
  ### Fixed
@@ -377,7 +423,9 @@ silent in the worst way:
377
423
 
378
424
  ---
379
425
 
380
- [Unreleased]: https://github.com/pham-canh/space-harness/compare/v0.3.9...HEAD
426
+ [Unreleased]: https://github.com/pham-canh/space-harness/compare/v0.4.1...HEAD
427
+ [0.4.1]: https://github.com/pham-canh/space-harness/compare/v0.4.0...v0.4.1
428
+ [0.4.0]: https://github.com/pham-canh/space-harness/compare/v0.3.9...v0.4.0
381
429
  [0.3.9]: https://github.com/pham-canh/space-harness/compare/v0.3.8...v0.3.9
382
430
  [0.3.8]: https://github.com/pham-canh/space-harness/compare/v0.3.7...v0.3.8
383
431
  [0.3.7]: https://github.com/pham-canh/space-harness/compare/v0.3.6...v0.3.7
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-harness-kit",
3
- "version": "0.3.9",
3
+ "version": "0.4.1",
4
4
  "description": "Harness kit for OpenCode: capability profiles, a fleet of job lanes with one free model each, role-based reasoning effort, context pruning, and measured baselines.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/pham-canh/space-harness#readme",
package/src/trust.js CHANGED
@@ -127,8 +127,13 @@ function npmCaptured(args, extra = []) {
127
127
  * @returns {Promise<{ out: string, code: number }>}
128
128
  */
129
129
  async function npmWithOtp(args, state = {}) {
130
+ // JSON, always. In text mode npm prints the challenge as
131
+ // `auth/cli/***` - masked - and the URL that can be opened is only in the
132
+ // JSON body. Without this flag the create cannot be completed at all, and
133
+ // the failure says nothing about why.
134
+ const withJson = args.includes("--json") ? [] : ["--json"]
130
135
  const userOtp = state.otp ? [`--otp=${state.otp}`] : []
131
- let result = npmCaptured(args, userOtp)
136
+ let result = npmCaptured([...args, ...withJson], userOtp)
132
137
  if (result.code === 0) return result
133
138
 
134
139
  // The URLs come FROM the body, not from a guess. Guessing the done URL
@@ -169,7 +174,7 @@ async function npmWithOtp(args, state = {}) {
169
174
  return result
170
175
  }
171
176
  // The code is used for THIS call only.
172
- result = npmCaptured(args, [`--otp=${token}`])
177
+ result = npmCaptured([...args, ...withJson], [`--otp=${token}`])
173
178
  return result
174
179
  }
175
180