@synkro-sh/cli 1.6.29 → 1.6.30

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/dist/bootstrap.js CHANGED
@@ -1906,6 +1906,21 @@ export function appendLocalTelemetry(body: Record<string, any>): void {
1906
1906
  try {
1907
1907
  appendFileSync(TELEMETRY_SPOOL, JSON.stringify(event) + '\\n');
1908
1908
  } catch {}
1909
+ // Realtime: fire-and-forget POST to the local server so events appear
1910
+ // in the dashboard immediately. Spool file remains the durable fallback.
1911
+ try {
1912
+ const port = process.env.SYNKRO_MCP_PORT || '18931';
1913
+ let token = '';
1914
+ try { token = readFileSync(join(HOME, '.synkro', '.mcp-jwt'), 'utf-8').trim(); } catch {}
1915
+ if (token) {
1916
+ fetch('http://127.0.0.1:' + port + '/api/ingest', {
1917
+ method: 'POST',
1918
+ headers: { 'Content-Type': 'application/json', Authorization: 'Bearer ' + token },
1919
+ body: JSON.stringify(event),
1920
+ signal: AbortSignal.timeout(3000),
1921
+ }).catch(() => {});
1922
+ }
1923
+ } catch {}
1909
1924
  }
1910
1925
 
1911
1926
  function tryAcquireDrainLock(): boolean {
@@ -4165,11 +4180,16 @@ async function main() {
4165
4180
  const cveIds = findings.slice(0, 10).map((f: any) =>
4166
4181
  (f.aliases || []).find((a: string) => a.startsWith('CVE-')) || f.id || 'unknown'
4167
4182
  );
4183
+ let cveCcModel: string | undefined = String(payload.model ?? payload.model_id ?? '') || undefined;
4184
+ if (!cveCcModel && transcriptPath) {
4185
+ try { cveCcModel = extractTranscript(transcriptPath).ccModel || undefined; } catch {}
4186
+ }
4168
4187
  dispatchCapture(jwt, 'cve', 'block', 'critical', 'security',
4169
4188
  toolName, gitRepo, sessionId, config.captureDepth, {
4170
4189
  command: 'edit ' + filePath,
4171
4190
  reasoning: top3,
4172
4191
  violatedRules: cveIds,
4192
+ ccModel: cveCcModel,
4173
4193
  });
4174
4194
  dispatchScanResult(jwt, {
4175
4195
  session_id: sessionId, file_path: filePath, scan_type: 'cve',
@@ -5754,6 +5774,21 @@ main();
5754
5774
  });
5755
5775
 
5756
5776
  // cli/auth/stub.ts
5777
+ var stub_exports = {};
5778
+ __export(stub_exports, {
5779
+ authenticate: () => authenticate,
5780
+ clearCredentials: () => clearCredentials,
5781
+ ensureValidToken: () => ensureValidToken,
5782
+ getAccessToken: () => getAccessToken,
5783
+ getCurrentUserId: () => getCurrentUserId,
5784
+ getSecrets: () => getSecrets,
5785
+ getUserInfo: () => getUserInfo,
5786
+ isAuthenticated: () => isAuthenticated,
5787
+ isTokenExpired: () => isTokenExpired,
5788
+ loadCredentials: () => loadCredentials,
5789
+ refreshToken: () => refreshToken,
5790
+ saveCredentials: () => saveCredentials
5791
+ });
5757
5792
  import { createServer } from "http";
5758
5793
  import { writeFileSync as writeFileSync4, readFileSync as readFileSync4, existsSync as existsSync4, mkdirSync as mkdirSync4, unlinkSync as unlinkSync2 } from "fs";
5759
5794
  import { homedir as homedir4, platform } from "os";
@@ -5960,6 +5995,17 @@ function isAuthenticated() {
5960
5995
  return true;
5961
5996
  }
5962
5997
  }
5998
+ function getCurrentUserId() {
5999
+ const creds = loadCredentials();
6000
+ if (!creds) {
6001
+ throw new Error("Not authenticated");
6002
+ }
6003
+ const decoded = jwt.decode(creds.access_token);
6004
+ if (!decoded?.sub) {
6005
+ throw new Error("Invalid token");
6006
+ }
6007
+ return decoded.sub;
6008
+ }
5963
6009
  function getUserInfo() {
5964
6010
  const creds = loadCredentials();
5965
6011
  if (!creds) {
@@ -6044,6 +6090,15 @@ function clearCredentials() {
6044
6090
  unlinkSync2(AUTH_FILE);
6045
6091
  }
6046
6092
  }
6093
+ async function getSecrets(userId, integrationId) {
6094
+ return {
6095
+ AWS_ACCESS_KEY_ID: process.env.USER_AWS_KEY || "",
6096
+ AWS_SECRET_ACCESS_KEY: process.env.USER_AWS_SECRET || "",
6097
+ AWS_REGION: process.env.USER_AWS_REGION || "us-east-1",
6098
+ HF_TOKEN: process.env.USER_HF_TOKEN || "",
6099
+ LANGSMITH_API_KEY: process.env.USER_LANGSMITH_KEY || ""
6100
+ };
6101
+ }
6047
6102
  var PORT, RAW_WEB_AUTH_URL, SYNKRO_WEB_AUTH_URL, AUTH_FILE, RAW_API_URL, SYNKRO_API_URL, ERROR_HTML, refreshPromise;
6048
6103
  var init_stub = __esm({
6049
6104
  "cli/auth/stub.ts"() {
@@ -7889,7 +7944,7 @@ function writeConfigEnv(opts) {
7889
7944
  `SYNKRO_CREDENTIALS_PATH=${shellQuoteSingle(credsPath)}`,
7890
7945
  `SYNKRO_TIER=${shellQuoteSingle(safeTier)}`,
7891
7946
  `SYNKRO_INFERENCE=${shellQuoteSingle(safeInference)}`,
7892
- `SYNKRO_VERSION=${shellQuoteSingle("1.6.29")}`
7947
+ `SYNKRO_VERSION=${shellQuoteSingle("1.6.30")}`
7893
7948
  ];
7894
7949
  if (safeSynkroBin) lines.push(`SYNKRO_CLI_BIN=${shellQuoteSingle(safeSynkroBin)}`);
7895
7950
  if (safeUserId) lines.push(`SYNKRO_USER_ID=${shellQuoteSingle(safeUserId)}`);
@@ -8325,7 +8380,7 @@ async function installCommand(opts = {}) {
8325
8380
  const ingestResp = await fetch(`http://127.0.0.1:${hostMcpPort}/api/ingest`, {
8326
8381
  method: "POST",
8327
8382
  headers: { "Content-Type": "application/json", Authorization: `Bearer ${mcpJwt}` },
8328
- body: JSON.stringify({ capture_type: "local_verdict", event_id: `healthcheck_${Date.now()}`, verdict: "pass", severity: "clean", hook_type: "install", tool_name: "healthcheck" }),
8383
+ body: JSON.stringify({ capture_type: "healthcheck", event_id: `healthcheck_${Date.now()}` }),
8329
8384
  signal: AbortSignal.timeout(5e3)
8330
8385
  });
8331
8386
  if (ingestResp.ok) {
@@ -10641,7 +10696,6 @@ var init_config = __esm({
10641
10696
  import { readFileSync as readFileSync13, existsSync as existsSync16 } from "fs";
10642
10697
  import { resolve as resolve2 } from "path";
10643
10698
  var envCandidates = [
10644
- resolve2(process.cwd(), ".env"),
10645
10699
  resolve2(process.env.HOME ?? "", ".synkro", "config.env")
10646
10700
  ];
10647
10701
  for (const envPath of envCandidates) {
@@ -10661,7 +10715,7 @@ var args = process.argv.slice(2);
10661
10715
  var cmd = args[0] || "";
10662
10716
  var subArgs = args.slice(1);
10663
10717
  function printVersion() {
10664
- console.log("1.6.29");
10718
+ console.log("1.6.30");
10665
10719
  }
10666
10720
  function printHelp2() {
10667
10721
  console.log(`Synkro CLI \u2014 runtime safety for AI coding agents
@@ -10707,6 +10761,23 @@ async function main() {
10707
10761
  disconnectCommand2(subArgs);
10708
10762
  break;
10709
10763
  }
10764
+ case "login": {
10765
+ const { authenticate: authenticate2, isAuthenticated: isAuthenticated2 } = await Promise.resolve().then(() => (init_stub(), stub_exports));
10766
+ if (isAuthenticated2()) {
10767
+ console.log("Already authenticated.");
10768
+ } else {
10769
+ console.log("Opening browser for Synkro auth...");
10770
+ const result = await authenticate2((status) => {
10771
+ if (status.phase === "success") console.log(" \u2713 Authenticated");
10772
+ else if (status.phase === "error") console.error(" \u2717 " + status.message);
10773
+ });
10774
+ if (!result) {
10775
+ console.error("Authentication failed.");
10776
+ process.exit(1);
10777
+ }
10778
+ }
10779
+ break;
10780
+ }
10710
10781
  case "grade": {
10711
10782
  const { gradeCommand: gradeCommand2 } = await Promise.resolve().then(() => (init_grade(), grade_exports));
10712
10783
  await gradeCommand2(subArgs);