@visa/cli 1.0.3 → 1.0.4-rc.3
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/README.md +87 -115
- package/dist/cli.js +52 -13
- package/dist/mcp-server/index.js +54 -10
- package/native/visa-keychain.m +46 -4
- package/package.json +5 -4
- package/LICENSE +0 -8
package/native/visa-keychain.m
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#import <Foundation/Foundation.h>
|
|
2
2
|
#import <Security/Security.h>
|
|
3
3
|
#import <LocalAuthentication/LocalAuthentication.h>
|
|
4
|
+
#import <AppKit/AppKit.h>
|
|
4
5
|
|
|
5
6
|
// SPKI DER header for P-256 (prime256v1) uncompressed public key
|
|
6
7
|
static const unsigned char SPKI_HEADER[] = {
|
|
@@ -132,21 +133,62 @@ int cmd_sign(const char *challenge, const char *reason) {
|
|
|
132
133
|
return 1;
|
|
133
134
|
}
|
|
134
135
|
|
|
135
|
-
// Touch ID
|
|
136
|
+
// Authentication gate (Touch ID OR password — whichever the user has).
|
|
137
|
+
//
|
|
138
|
+
// We use LAPolicyDeviceOwnerAuthentication, which presents a single
|
|
139
|
+
// system dialog: Touch ID on enrolled hardware, password fallback
|
|
140
|
+
// everywhere else (including users who skipped biometric setup and
|
|
141
|
+
// Macs without a Touch ID sensor). This front-focus fix applies to
|
|
142
|
+
// BOTH dialogs — they are the same system-level window, just with
|
|
143
|
+
// different input modes. If we only fixed the Touch ID path we would
|
|
144
|
+
// still be burying the password prompt behind the terminal for every
|
|
145
|
+
// non-biometric user.
|
|
146
|
+
//
|
|
147
|
+
// Front-focus fix: bare CLI binaries have no NSApplication, so the
|
|
148
|
+
// system LAContext dialog gets parented to whichever process happens to
|
|
149
|
+
// be frontmost (usually the terminal or Claude Code), which puts the
|
|
150
|
+
// prompt *behind* the user's current window — users never see it, time
|
|
151
|
+
// out, and their spend gets cancelled.
|
|
152
|
+
//
|
|
153
|
+
// Making the binary an Accessory-policy NSApplication and explicitly
|
|
154
|
+
// calling activateIgnoringOtherApps: before evaluatePolicy tells the
|
|
155
|
+
// window server this process is the new frontmost app, so the auth
|
|
156
|
+
// prompt (biometric or password) is raised on top of all other
|
|
157
|
+
// windows. Accessory policy means no Dock icon, no menu bar — the
|
|
158
|
+
// binary stays invisible except for the dialog itself.
|
|
159
|
+
[NSApplication sharedApplication];
|
|
160
|
+
[NSApp setActivationPolicy:NSApplicationActivationPolicyAccessory];
|
|
161
|
+
[NSApp activateIgnoringOtherApps:YES];
|
|
162
|
+
|
|
136
163
|
LAContext *ctx = [[LAContext alloc] init];
|
|
137
164
|
NSString *reasonStr = reason
|
|
138
165
|
? [NSString stringWithUTF8String:reason]
|
|
139
166
|
: @"approve payment";
|
|
140
167
|
|
|
141
|
-
|
|
168
|
+
__block BOOL done = NO;
|
|
142
169
|
__block BOOL authOk = NO;
|
|
143
170
|
[ctx evaluatePolicy:LAPolicyDeviceOwnerAuthentication
|
|
144
171
|
localizedReason:reasonStr
|
|
145
172
|
reply:^(BOOL success, NSError *err) {
|
|
146
173
|
authOk = success;
|
|
147
|
-
|
|
174
|
+
done = YES;
|
|
148
175
|
}];
|
|
149
|
-
|
|
176
|
+
|
|
177
|
+
// Pump the main run loop while waiting for the reply block. Using
|
|
178
|
+
// dispatch_semaphore_wait here would freeze the main thread and
|
|
179
|
+
// prevent the WindowServer from delivering the activation we just
|
|
180
|
+
// requested — the dialog would come up, but not on top.
|
|
181
|
+
NSDate *timeout = [NSDate dateWithTimeIntervalSinceNow:55.0];
|
|
182
|
+
while (!done) {
|
|
183
|
+
@autoreleasepool {
|
|
184
|
+
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
|
|
185
|
+
beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.05]];
|
|
186
|
+
if ([[NSDate date] compare:timeout] == NSOrderedDescending) {
|
|
187
|
+
printf("ERROR:Authentication timed out\n");
|
|
188
|
+
return 1;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
150
192
|
|
|
151
193
|
if (!authOk) {
|
|
152
194
|
printf("ERROR:Authentication cancelled by user\n");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@visa/cli",
|
|
3
|
-
"version": "1.0.3",
|
|
3
|
+
"version": "1.0.4-rc.3",
|
|
4
4
|
"description": "AI-powered payments for Claude Code",
|
|
5
5
|
"bin": {
|
|
6
6
|
"visa-cli": "./bin/visa-cli.js"
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
"test:smoke": "VISA_AUTH_URL=https://auth.visacli.sh jest --config jest.smoke.config.js",
|
|
17
17
|
"test:integration": "jest --config jest.integration.config.js",
|
|
18
18
|
"test:e2e": "jest --config jest.e2e.config.js",
|
|
19
|
+
"test:catalog-e2e": "jest --config jest.catalog-e2e.config.js",
|
|
19
20
|
"test:all": "npm run test:unit && npm run test:integration && npm run test:e2e",
|
|
20
|
-
"prepare": "husky",
|
|
21
21
|
"prepublishOnly": "npm run build && npm test",
|
|
22
22
|
"lint": "eslint src/**/*.ts",
|
|
23
23
|
"format": "prettier --write \"src/**/*.ts\"",
|
|
@@ -37,7 +37,9 @@
|
|
|
37
37
|
"license": "SEE LICENSE IN LICENSE",
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
40
|
-
"
|
|
40
|
+
"@visa-cli/tools": "workspace:*",
|
|
41
|
+
"commander": "^12.1.0",
|
|
42
|
+
"zod": "^3.23.0"
|
|
41
43
|
},
|
|
42
44
|
"devDependencies": {
|
|
43
45
|
"@changesets/changelog-git": "^0.2.1",
|
|
@@ -51,7 +53,6 @@
|
|
|
51
53
|
"express": "^4.21.0",
|
|
52
54
|
"eslint": "^10.0.2",
|
|
53
55
|
"eslint-config-prettier": "^10.1.8",
|
|
54
|
-
"husky": "^9.1.7",
|
|
55
56
|
"jest": "^29.7.0",
|
|
56
57
|
"prettier": "^3.8.1",
|
|
57
58
|
"ts-jest": "^29.2.0",
|
package/LICENSE
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
Copyright (c) 2026 Visa International Service Association. All rights reserved.
|
|
2
|
-
|
|
3
|
-
Use of this software is governed by the Visa CLI Terms of Use, available at:
|
|
4
|
-
https://auth.visacli.sh/legal/terms
|
|
5
|
-
|
|
6
|
-
This software is proprietary and confidential. Unauthorized copying, distribution,
|
|
7
|
-
or use of this software, in whole or in part, is strictly prohibited except as
|
|
8
|
-
expressly permitted by the Visa CLI Terms of Use.
|