codeam-cli 2.39.15 → 2.39.17

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
@@ -4,6 +4,18 @@ All notable changes to `codeam-cli` are documented here.
4
4
 
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [2.39.16] — 2026-06-14
8
+
9
+ ### Added
10
+
11
+ - **jetbrains-plugin:** Proof-of-possession secret for /status + /reconnect (SEC crit1)
12
+
13
+ ## [2.39.15] — 2026-06-14
14
+
15
+ ### Added
16
+
17
+ - **vsc-plugin:** Proof-of-possession secret for /status + /reconnect (SEC crit1)
18
+
7
19
  ## [2.39.14] — 2026-06-14
8
20
 
9
21
  ### Added
package/dist/index.js CHANGED
@@ -498,7 +498,7 @@ var import_qrcode_terminal = __toESM(require("qrcode-terminal"));
498
498
  // package.json
499
499
  var package_default = {
500
500
  name: "codeam-cli",
501
- version: "2.39.15",
501
+ version: "2.39.17",
502
502
  description: "Workflow-continuity bridge for AI coding agents. Wrap Claude Code or Codex in a PTY and supervise, approve, and redirect the session from any device \u2014 async. The terminal companion for CodeAgent Mobile.",
503
503
  type: "commonjs",
504
504
  main: "dist/index.js",
@@ -989,7 +989,7 @@ async function _postJson(url, body, extraHeaders) {
989
989
  req.end();
990
990
  });
991
991
  }
992
- async function _getJson(url) {
992
+ async function _getJson(url, extraHeaders) {
993
993
  return new Promise((resolve7, reject) => {
994
994
  const u2 = new URL(url);
995
995
  const transport = u2.protocol === "https:" ? https : http;
@@ -999,7 +999,7 @@ async function _getJson(url) {
999
999
  port: u2.port || (u2.protocol === "https:" ? 443 : 80),
1000
1000
  path: u2.pathname + u2.search,
1001
1001
  method: "GET",
1002
- headers: { ...vercelBypassHeader() },
1002
+ headers: { ...vercelBypassHeader(), ...extraHeaders ?? {} },
1003
1003
  timeout: 1e4
1004
1004
  },
1005
1005
  (res) => {
@@ -5908,7 +5908,7 @@ function readAnonId() {
5908
5908
  }
5909
5909
  function superProperties() {
5910
5910
  return {
5911
- cliVersion: true ? "2.39.15" : "0.0.0-dev",
5911
+ cliVersion: true ? "2.39.17" : "0.0.0-dev",
5912
5912
  nodeVersion: process.version,
5913
5913
  platform: process.platform,
5914
5914
  arch: process.arch,
@@ -6111,7 +6111,12 @@ var CommandRelayService = class {
6111
6111
  port: url.port || (url.protocol === "https:" ? 443 : 80),
6112
6112
  path: `${url.pathname}${url.search}`,
6113
6113
  method: "GET",
6114
- headers: { Accept: "text/event-stream", "Cache-Control": "no-cache", ...vercelBypassHeader() },
6114
+ headers: {
6115
+ Accept: "text/event-stream",
6116
+ "Cache-Control": "no-cache",
6117
+ ...vercelBypassHeader(),
6118
+ ...this.pollSecretHeader()
6119
+ },
6115
6120
  timeout: 35e3
6116
6121
  },
6117
6122
  (res) => {
@@ -6264,9 +6269,27 @@ var CommandRelayService = class {
6264
6269
  this.pollTimer = setTimeout(() => this.pollLoop(), delay);
6265
6270
  }
6266
6271
  }
6272
+ // SEC crit1 (#8): the command-delivery endpoints are gated on the
6273
+ // per-pairing pollSecret when the backend enforces it. Look it up from
6274
+ // the persisted session (keyed by this relay's pluginId) and replay it
6275
+ // as X-Plugin-Poll-Secret. Empty {} for legacy sessions / older
6276
+ // backends (which ignore it).
6277
+ pollSecretHeader() {
6278
+ try {
6279
+ const secret = loadCliConfig().sessions.find(
6280
+ (s) => s.pluginId === this.pluginId
6281
+ )?.pollSecret;
6282
+ return secret ? { "X-Plugin-Poll-Secret": secret } : {};
6283
+ } catch {
6284
+ return {};
6285
+ }
6286
+ }
6267
6287
  async pollOnce() {
6268
6288
  try {
6269
- const data = await _getJson(`${API_BASE2}/api/commands/pending?pluginId=${this.pluginId}`);
6289
+ const data = await _getJson(
6290
+ `${API_BASE2}/api/commands/pending?pluginId=${this.pluginId}`,
6291
+ this.pollSecretHeader()
6292
+ );
6270
6293
  const commands = data?.data;
6271
6294
  this.pollFailures = 0;
6272
6295
  if (!Array.isArray(commands) || commands.length === 0) {
@@ -16661,7 +16684,7 @@ var http4 = __toESM(require("http"));
16661
16684
  var API_BASE3 = resolveApiBaseUrl();
16662
16685
  var PAIR_TIMEOUT_MS = 5 * 60 * 1e3;
16663
16686
  var dispatchers = /* @__PURE__ */ new Set();
16664
- function subscribeToPairCompletion(pluginId, onPaired, onTimeout) {
16687
+ function subscribeToPairCompletion(pluginId, onPaired, onTimeout, pollSecret) {
16665
16688
  let stopped = false;
16666
16689
  let req = null;
16667
16690
  let timeoutTimer = null;
@@ -16696,7 +16719,8 @@ function subscribeToPairCompletion(pluginId, onPaired, onTimeout) {
16696
16719
  headers: {
16697
16720
  Accept: "text/event-stream",
16698
16721
  "Cache-Control": "no-cache",
16699
- ...vercelBypassHeader()
16722
+ ...vercelBypassHeader(),
16723
+ ...pollSecret ? { "X-Plugin-Poll-Secret": pollSecret } : {}
16700
16724
  },
16701
16725
  timeout: 35e3
16702
16726
  },
@@ -24340,7 +24364,10 @@ async function pair(args2 = []) {
24340
24364
  capture("pair_timed_out", { agentId, pluginId });
24341
24365
  showError("Pairing timed out after 5 minutes. Run codeam pair to try again.");
24342
24366
  process.exit(1);
24343
- }
24367
+ },
24368
+ // SEC crit1 (#8): replay this pairing's secret on the pre-pair
24369
+ // subscription so it passes the command-endpoint gate when enforced.
24370
+ pollSecret
24344
24371
  );
24345
24372
  process.once("SIGINT", sigintHandler);
24346
24373
  });
@@ -27017,7 +27044,7 @@ function checkChokidar() {
27017
27044
  }
27018
27045
  async function doctor(args2 = []) {
27019
27046
  const json = args2.includes("--json");
27020
- const cliVersion = true ? "2.39.15" : "0.0.0-dev";
27047
+ const cliVersion = true ? "2.39.17" : "0.0.0-dev";
27021
27048
  const apiBase = resolveApiBaseUrl();
27022
27049
  const diagnosticId = (0, import_node_crypto8.randomUUID)();
27023
27050
  log.info("doctor", `run id=${diagnosticId} cli=${cliVersion}`);
@@ -27216,7 +27243,7 @@ async function completion(args2) {
27216
27243
  // src/commands/version.ts
27217
27244
  var import_picocolors13 = __toESM(require("picocolors"));
27218
27245
  function version2() {
27219
- const v = true ? "2.39.15" : "unknown";
27246
+ const v = true ? "2.39.17" : "unknown";
27220
27247
  console.log(`${import_picocolors13.default.bold("codeam-cli")} ${import_picocolors13.default.cyan(v)}`);
27221
27248
  }
27222
27249
 
@@ -27502,7 +27529,7 @@ function checkForUpdates() {
27502
27529
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
27503
27530
  if (process.env.CI) return;
27504
27531
  if (!process.stdout.isTTY) return;
27505
- const current = true ? "2.39.15" : null;
27532
+ const current = true ? "2.39.17" : null;
27506
27533
  if (!current) return;
27507
27534
  const cache = readCache();
27508
27535
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.39.15",
3
+ "version": "2.39.17",
4
4
  "description": "Workflow-continuity bridge for AI coding agents. Wrap Claude Code or Codex in a PTY and supervise, approve, and redirect the session from any device — async. The terminal companion for CodeAgent Mobile.",
5
5
  "type": "commonjs",
6
6
  "main": "dist/index.js",