@topolo/sdk 0.21.1 → 0.21.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.
@@ -481,6 +481,8 @@ var import_node_fs = require("fs");
481
481
  var import_node_os = require("os");
482
482
  var import_node_path = require("path");
483
483
  var KEYCHAIN_SERVICE = "topolo-external-agent-installation";
484
+ var MACOS_KEYCHAIN_CHUNK_SIZE = 96;
485
+ var MACOS_KEYCHAIN_CHUNK_PREFIX = "topolo-keychain-chunks:v1:";
484
486
  var MACOS_KEYCHAIN_WRITE_SCRIPT = [
485
487
  "log_user 0",
486
488
  "set timeout 10",
@@ -521,40 +523,73 @@ function createPlatformInstallationSecretBackend(options = {}) {
521
523
  const spawn = options.spawn ?? ((command, args, spawnOptions) => (0, import_node_child_process.spawnSync)(command, args, spawnOptions));
522
524
  const root = options.root ?? installationStorePath();
523
525
  if (platform2 === "darwin") {
526
+ const write = (account, value) => runOrThrow(spawn("/usr/bin/expect", ["-c", MACOS_KEYCHAIN_WRITE_SCRIPT], {
527
+ input: `${value}
528
+ `,
529
+ encoding: "utf8",
530
+ env: {
531
+ ...process.env,
532
+ TOPOLO_KEYCHAIN_ACCOUNT: account,
533
+ TOPOLO_KEYCHAIN_SERVICE: KEYCHAIN_SERVICE
534
+ }
535
+ }), "macOS Keychain write");
536
+ const read = (account) => {
537
+ const result = spawn("security", [
538
+ "find-generic-password",
539
+ "-a",
540
+ account,
541
+ "-s",
542
+ KEYCHAIN_SERVICE,
543
+ "-w"
544
+ ], { encoding: "utf8" });
545
+ if (result.status === 44) return null;
546
+ return runOrThrow(result, "macOS Keychain read");
547
+ };
548
+ const remove = (account) => {
549
+ const result = spawn("security", [
550
+ "delete-generic-password",
551
+ "-a",
552
+ account,
553
+ "-s",
554
+ KEYCHAIN_SERVICE
555
+ ], { encoding: "utf8" });
556
+ if (result.status !== 44) runOrThrow(result, "macOS Keychain delete");
557
+ };
558
+ const chunkAccount = (account, index) => `${account}:chunk:${index}`;
559
+ const chunkCount = (value) => {
560
+ if (!value?.startsWith(MACOS_KEYCHAIN_CHUNK_PREFIX)) return 0;
561
+ const count = Number(value.slice(MACOS_KEYCHAIN_CHUNK_PREFIX.length));
562
+ if (!Number.isSafeInteger(count) || count < 1) throw new Error("macOS Keychain chunk manifest is invalid.");
563
+ return count;
564
+ };
524
565
  return {
525
566
  async set(account, value) {
526
- runOrThrow(spawn("/usr/bin/expect", ["-c", MACOS_KEYCHAIN_WRITE_SCRIPT], {
527
- input: `${value}
528
- `,
529
- encoding: "utf8",
530
- env: {
531
- ...process.env,
532
- TOPOLO_KEYCHAIN_ACCOUNT: account,
533
- TOPOLO_KEYCHAIN_SERVICE: KEYCHAIN_SERVICE
534
- }
535
- }), "macOS Keychain write");
567
+ const previousCount = chunkCount(read(account));
568
+ const chunks = Array.from(
569
+ { length: Math.max(1, Math.ceil(value.length / MACOS_KEYCHAIN_CHUNK_SIZE)) },
570
+ (_, index) => value.slice(index * MACOS_KEYCHAIN_CHUNK_SIZE, (index + 1) * MACOS_KEYCHAIN_CHUNK_SIZE)
571
+ );
572
+ try {
573
+ chunks.forEach((chunk, index) => write(chunkAccount(account, index), chunk));
574
+ write(account, `${MACOS_KEYCHAIN_CHUNK_PREFIX}${chunks.length}`);
575
+ for (let index = chunks.length; index < previousCount; index += 1) remove(chunkAccount(account, index));
576
+ } catch (error) {
577
+ chunks.forEach((_, index) => remove(chunkAccount(account, index)));
578
+ throw error;
579
+ }
536
580
  },
537
581
  async get(account) {
538
- const result = spawn("security", [
539
- "find-generic-password",
540
- "-a",
541
- account,
542
- "-s",
543
- KEYCHAIN_SERVICE,
544
- "-w"
545
- ], { encoding: "utf8" });
546
- if (result.status === 44) return null;
547
- return runOrThrow(result, "macOS Keychain read");
582
+ const manifest = read(account);
583
+ const count = chunkCount(manifest);
584
+ if (!count) return manifest;
585
+ const chunks = Array.from({ length: count }, (_, index) => read(chunkAccount(account, index)));
586
+ if (chunks.some((chunk) => chunk === null)) throw new Error("macOS Keychain installation secret is incomplete.");
587
+ return chunks.join("");
548
588
  },
549
589
  async delete(account) {
550
- const result = spawn("security", [
551
- "delete-generic-password",
552
- "-a",
553
- account,
554
- "-s",
555
- KEYCHAIN_SERVICE
556
- ], { encoding: "utf8" });
557
- if (result.status !== 44) runOrThrow(result, "macOS Keychain delete");
590
+ const count = chunkCount(read(account));
591
+ for (let index = 0; index < count; index += 1) remove(chunkAccount(account, index));
592
+ remove(account);
558
593
  }
559
594
  };
560
595
  }
@@ -428,6 +428,8 @@ import { existsSync } from "fs";
428
428
  import { homedir, platform as hostPlatform } from "os";
429
429
  import { dirname, join } from "path";
430
430
  var KEYCHAIN_SERVICE = "topolo-external-agent-installation";
431
+ var MACOS_KEYCHAIN_CHUNK_SIZE = 96;
432
+ var MACOS_KEYCHAIN_CHUNK_PREFIX = "topolo-keychain-chunks:v1:";
431
433
  var MACOS_KEYCHAIN_WRITE_SCRIPT = [
432
434
  "log_user 0",
433
435
  "set timeout 10",
@@ -468,40 +470,73 @@ function createPlatformInstallationSecretBackend(options = {}) {
468
470
  const spawn = options.spawn ?? ((command, args, spawnOptions) => spawnSync(command, args, spawnOptions));
469
471
  const root = options.root ?? installationStorePath();
470
472
  if (platform2 === "darwin") {
473
+ const write = (account, value) => runOrThrow(spawn("/usr/bin/expect", ["-c", MACOS_KEYCHAIN_WRITE_SCRIPT], {
474
+ input: `${value}
475
+ `,
476
+ encoding: "utf8",
477
+ env: {
478
+ ...process.env,
479
+ TOPOLO_KEYCHAIN_ACCOUNT: account,
480
+ TOPOLO_KEYCHAIN_SERVICE: KEYCHAIN_SERVICE
481
+ }
482
+ }), "macOS Keychain write");
483
+ const read = (account) => {
484
+ const result = spawn("security", [
485
+ "find-generic-password",
486
+ "-a",
487
+ account,
488
+ "-s",
489
+ KEYCHAIN_SERVICE,
490
+ "-w"
491
+ ], { encoding: "utf8" });
492
+ if (result.status === 44) return null;
493
+ return runOrThrow(result, "macOS Keychain read");
494
+ };
495
+ const remove = (account) => {
496
+ const result = spawn("security", [
497
+ "delete-generic-password",
498
+ "-a",
499
+ account,
500
+ "-s",
501
+ KEYCHAIN_SERVICE
502
+ ], { encoding: "utf8" });
503
+ if (result.status !== 44) runOrThrow(result, "macOS Keychain delete");
504
+ };
505
+ const chunkAccount = (account, index) => `${account}:chunk:${index}`;
506
+ const chunkCount = (value) => {
507
+ if (!value?.startsWith(MACOS_KEYCHAIN_CHUNK_PREFIX)) return 0;
508
+ const count = Number(value.slice(MACOS_KEYCHAIN_CHUNK_PREFIX.length));
509
+ if (!Number.isSafeInteger(count) || count < 1) throw new Error("macOS Keychain chunk manifest is invalid.");
510
+ return count;
511
+ };
471
512
  return {
472
513
  async set(account, value) {
473
- runOrThrow(spawn("/usr/bin/expect", ["-c", MACOS_KEYCHAIN_WRITE_SCRIPT], {
474
- input: `${value}
475
- `,
476
- encoding: "utf8",
477
- env: {
478
- ...process.env,
479
- TOPOLO_KEYCHAIN_ACCOUNT: account,
480
- TOPOLO_KEYCHAIN_SERVICE: KEYCHAIN_SERVICE
481
- }
482
- }), "macOS Keychain write");
514
+ const previousCount = chunkCount(read(account));
515
+ const chunks = Array.from(
516
+ { length: Math.max(1, Math.ceil(value.length / MACOS_KEYCHAIN_CHUNK_SIZE)) },
517
+ (_, index) => value.slice(index * MACOS_KEYCHAIN_CHUNK_SIZE, (index + 1) * MACOS_KEYCHAIN_CHUNK_SIZE)
518
+ );
519
+ try {
520
+ chunks.forEach((chunk, index) => write(chunkAccount(account, index), chunk));
521
+ write(account, `${MACOS_KEYCHAIN_CHUNK_PREFIX}${chunks.length}`);
522
+ for (let index = chunks.length; index < previousCount; index += 1) remove(chunkAccount(account, index));
523
+ } catch (error) {
524
+ chunks.forEach((_, index) => remove(chunkAccount(account, index)));
525
+ throw error;
526
+ }
483
527
  },
484
528
  async get(account) {
485
- const result = spawn("security", [
486
- "find-generic-password",
487
- "-a",
488
- account,
489
- "-s",
490
- KEYCHAIN_SERVICE,
491
- "-w"
492
- ], { encoding: "utf8" });
493
- if (result.status === 44) return null;
494
- return runOrThrow(result, "macOS Keychain read");
529
+ const manifest = read(account);
530
+ const count = chunkCount(manifest);
531
+ if (!count) return manifest;
532
+ const chunks = Array.from({ length: count }, (_, index) => read(chunkAccount(account, index)));
533
+ if (chunks.some((chunk) => chunk === null)) throw new Error("macOS Keychain installation secret is incomplete.");
534
+ return chunks.join("");
495
535
  },
496
536
  async delete(account) {
497
- const result = spawn("security", [
498
- "delete-generic-password",
499
- "-a",
500
- account,
501
- "-s",
502
- KEYCHAIN_SERVICE
503
- ], { encoding: "utf8" });
504
- if (result.status !== 44) runOrThrow(result, "macOS Keychain delete");
537
+ const count = chunkCount(read(account));
538
+ for (let index = 0; index < count; index += 1) remove(chunkAccount(account, index));
539
+ remove(account);
505
540
  }
506
541
  };
507
542
  }
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@topolo/sdk",
3
3
  "packageManager": "pnpm@10.17.1",
4
- "version": "0.21.1",
5
- "topoloPublishedVersion": "0.21.1",
4
+ "version": "0.21.2",
5
+ "topoloPublishedVersion": "0.21.2",
6
6
  "description": "Typed client SDK for the Topolo platform. Used by TopoloCli, TopoloMCP, and third-party agents.",
7
7
  "license": "UNLICENSED",
8
8
  "author": "Topolo",