@settlemint/dalp-cli 3.1.32-main.42600267094 → 3.1.32-main.42608383459

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@settlemint/dalp-cli",
3
- "version": "3.1.32-main.42600267094",
3
+ "version": "3.1.32-main.42608383459",
4
4
  "private": false,
5
5
  "description": "CLI for the Digital Asset Lifecycle Platform — manage tokens, identities, compliance, and more from the command line.",
6
6
  "homepage": "https://settlemint.com",
@@ -50,14 +50,14 @@
50
50
  },
51
51
  "dependencies": {
52
52
  "@modelcontextprotocol/server": "2.4.0",
53
- "@settlemint/dalp-sdk": "3.1.32-main.42600267094",
53
+ "@settlemint/dalp-sdk": "3.1.32-main.42608383459",
54
54
  "incur": "0.7.1",
55
55
  "zod": "4.6.7"
56
56
  },
57
57
  "devDependencies": {
58
58
  "@arethetypeswrong/cli": "0.18.5",
59
- "@testkit/effect-bun-test": "3.1.32-main.42600267094",
60
- "@tools/typescript-config": "3.1.32-main.42600267094",
59
+ "@testkit/effect-bun-test": "3.1.32-main.42608383459",
60
+ "@tools/typescript-config": "3.1.32-main.42608383459",
61
61
  "@types/bun": "1.4.4",
62
62
  "publint": "0.3.25"
63
63
  },
@@ -8,6 +8,9 @@ const KEYCHAIN_ENTRY_SEPARATOR_PATTERN = /\n(?=keychain:)/u;
8
8
  const ACCOUNT_PATTERN = /"acct"<blob>="([^"]*)"/u;
9
9
 
10
10
  const SERVICE_NAME = "dalp-cli";
11
+ const SECURITY_INTERACTIVE_MAX_LINE_BYTES = 4094;
12
+ const SECURITY_QUOTED_ESCAPE_PATTERN = /["\\]/gu;
13
+ const SECURITY_LINE_BREAK_PATTERN = /[\n\r\0]/u;
11
14
 
12
15
  const StoredCredentialsSchema = z.object({
13
16
  apiKey: z.string().min(1),
@@ -24,14 +27,20 @@ export interface CredentialStoreOptions {
24
27
  readonly configDir?: string;
25
28
  readonly platform?: NodeJS.Platform;
26
29
  readonly runSecurity?: (
27
- args: ReadonlyArray<string>
30
+ args: ReadonlyArray<string>,
31
+ stdin?: string
28
32
  ) => Promise<{ readonly exitCode: number; readonly stdout: string }>;
29
33
  }
30
34
 
31
35
  const defaultRunSecurity = async (
32
- args: ReadonlyArray<string>
36
+ args: ReadonlyArray<string>,
37
+ stdin?: string
33
38
  ): Promise<{ readonly exitCode: number; readonly stdout: string }> => {
34
- const proc = Bun.spawn(["security", ...args], { stdout: "pipe", stderr: "pipe" });
39
+ const proc = Bun.spawn(["security", ...args], {
40
+ stdin: stdin === undefined ? "ignore" : new TextEncoder().encode(stdin),
41
+ stdout: "pipe",
42
+ stderr: "pipe",
43
+ });
35
44
  const [stdout, exitCode] = await Promise.all([new Response(proc.stdout).text(), proc.exited]);
36
45
  return { exitCode, stdout };
37
46
  };
@@ -76,6 +85,43 @@ async function deleteKeychainAccount(
76
85
  }
77
86
  }
78
87
 
88
+ function quoteSecurityArgument(value: string): string {
89
+ return `"${value.replaceAll(SECURITY_QUOTED_ESCAPE_PATTERN, (character) => `\\${character}`)}"`;
90
+ }
91
+
92
+ async function addKeychainPassword(
93
+ runSecurity: NonNullable<CredentialStoreOptions["runSecurity"]>,
94
+ account: string,
95
+ password: string
96
+ ): Promise<void> {
97
+ const command = [
98
+ "add-generic-password",
99
+ "-s",
100
+ quoteSecurityArgument(SERVICE_NAME),
101
+ "-a",
102
+ quoteSecurityArgument(account),
103
+ "-X",
104
+ Buffer.from(password, "utf8").toString("hex"),
105
+ "-U",
106
+ ].join(" ");
107
+ if (
108
+ SECURITY_LINE_BREAK_PATTERN.test(account) ||
109
+ Buffer.byteLength(command, "utf8") > SECURITY_INTERACTIVE_MAX_LINE_BYTES
110
+ ) {
111
+ throw makeCliError({
112
+ code: "kit.cli.CREDENTIAL_STORE_FAILED",
113
+ message: `The ${SERVICE_NAME} keychain item for ${JSON.stringify(account)} cannot be passed to the macOS security tool as one command line.`,
114
+ });
115
+ }
116
+ const result = await runSecurity(["-i"], `${command}\n`);
117
+ if (result.exitCode !== 0) {
118
+ throw makeCliError({
119
+ code: "kit.cli.CREDENTIAL_STORE_FAILED",
120
+ message: `Keychain save failed with exit code ${result.exitCode}`,
121
+ });
122
+ }
123
+ }
124
+
79
125
  function resolvePlatform(options: CredentialStoreOptions): NodeJS.Platform {
80
126
  if (options.platform !== undefined) {
81
127
  return options.platform;
@@ -99,22 +145,7 @@ export async function saveCredentials(
99
145
 
100
146
  if (platform === "darwin") {
101
147
  const existing = await keychainAccounts(runSecurity);
102
- const result = await runSecurity([
103
- "add-generic-password",
104
- "-s",
105
- SERVICE_NAME,
106
- "-a",
107
- parsed.userEmail,
108
- "-w",
109
- encoded,
110
- "-U",
111
- ]);
112
- if (result.exitCode !== 0) {
113
- throw makeCliError({
114
- code: "kit.cli.CREDENTIAL_STORE_FAILED",
115
- message: `Keychain save failed with exit code ${result.exitCode}`,
116
- });
117
- }
148
+ await addKeychainPassword(runSecurity, parsed.userEmail, encoded);
118
149
  try {
119
150
  for (const account of existing.filter((name) => name !== parsed.userEmail)) {
120
151
  await deleteKeychainAccount(runSecurity, account);