@agenzo/token-cli 0.3.1 → 0.3.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 CHANGED
@@ -1,7 +1,11 @@
1
1
  # @agenzo/token-cli
2
2
 
3
+ [![npm](https://img.shields.io/npm/v/@agenzo/token-cli.svg)](https://www.npmjs.com/package/@agenzo/token-cli) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](../../LICENSE) ![node](https://img.shields.io/badge/node-%3E%3D22-brightgreen.svg)
4
+
3
5
  > The **payment credential CLI** (runtime plane) for the Agenzo platform. Agents use it to manage payment methods (card details + 3DS verification) and to issue payment tokens (VCN / Network Token / X402) before a transaction.
4
6
 
7
+ **[Installation](#installation)** · **[Authentication](#authentication)** · **[Commands](#command-matrix)** · **[payment-methods](#payment-methods)** · **[payment-tokens](#payment-tokens)** · **[Errors](#output-and-errors)**
8
+
5
9
  Binary: `agenzo-token-cli` | Auth: API Key (`X-Api-Key`)
6
10
 
7
11
  ## Installation
@@ -10,7 +14,7 @@ Binary: `agenzo-token-cli` | Auth: API Key (`X-Api-Key`)
10
14
  npm install -g @agenzo/token-cli
11
15
  ```
12
16
 
13
- The `agenzo-token-cli` command is available after installation. Requires Node.js ≥ 18.
17
+ The `agenzo-token-cli` command is available after installation. Requires Node.js ≥ 22. Upgrade later with `npm install -g @agenzo/token-cli@latest`.
14
18
 
15
19
  ## Authentication
16
20
 
@@ -30,7 +34,7 @@ agenzo-admin-cli keys create --developer-id <dev_id> --key-name "Prod Key" --sco
30
34
  token-cli reuses the environment configuration (API host / path) written by admin-cli; it has no environment-management commands of its own. The default target is production `https://agent.everonet.com`. Switch environments via admin-cli:
31
35
 
32
36
  ```bash
33
- agenzo-admin-cli config set-host https://agent-test.everonet.com # switch to test
37
+ agenzo-admin-cli config set-host https://agent-dev.agenzo.com # switch to the test environment
34
38
  agenzo-admin-cli config show # show current host / path
35
39
  ```
36
40
 
@@ -38,8 +42,8 @@ agenzo-admin-cli config show # show curren
38
42
 
39
43
  | Option | Description |
40
44
  |---|---|
41
- | `--format <json\|table>` | Output format. Default `table` (human-readable); `json` for Agent / script parsing. Can also be set via the `AGENZO_FORMAT` environment variable |
42
- | `--yes` | Skip all confirmation prompts (for automation / AI Agents) |
45
+ | `--format <json\|table>` | Output format. Defaults to `table`; pass `json` (or set `AGENZO_FORMAT=json`) for machine-readable output |
46
+ | `--yes` | Skip all confirmation prompts (non-interactive automation) |
43
47
  | `--verbose` | Print verbose logs to stderr |
44
48
  | `--version` | Print the CLI version |
45
49
 
@@ -49,7 +53,7 @@ agenzo-admin-cli config show # show curren
49
53
 
50
54
  | Noun | Verb | Purpose | Write/Read |
51
55
  |---|---|---|---|
52
- | `payment-methods` | `add` | Add a payment method, then auto-poll 3DS verification (up to 15 min) | W |
56
+ | `payment-methods` | `add` | Add a payment method via `--mode manual` (collect card + 3DS, default) or `--mode dropin` (Drop-in session), then auto-poll verification | W |
53
57
  | `payment-methods` | `list` | List payment methods under the current API Key | R |
54
58
  | `payment-methods` | `get <pm_id>` | Show details of a single payment method | R |
55
59
  | `payment-methods` | `disable <pm_id>` | Disable a payment method (cascades to revoke its issued tokens) | W |
@@ -60,7 +64,14 @@ agenzo-admin-cli config show # show curren
60
64
 
61
65
  ## payment-methods
62
66
 
63
- ### add — add a payment method + 3DS verification
67
+ ### add — add a payment method
68
+
69
+ Two modes, selected with `--mode`:
70
+
71
+ - **`manual`** (default): the CLI collects card details and polls 3DS verification.
72
+ - **`dropin`**: the CLI mints a Drop-in session and polls until the user finishes adding the payment method in their browser — no card details are entered at the terminal.
73
+
74
+ #### Manual mode (default)
64
75
 
65
76
  ```bash
66
77
  agenzo-token-cli payment-methods add \
@@ -75,14 +86,33 @@ agenzo-token-cli payment-methods add \
75
86
  | Flag | Required | Description |
76
87
  |---|---|---|
77
88
  | `--api-key` | Yes | Prompted interactively when omitted |
89
+ | `--mode` | No | `manual` (default) or `dropin` |
78
90
  | `--type` | No | Payment method type, defaults to `card` |
79
91
  | `--email` | Yes | Used to deliver the 3DS email challenge |
80
92
  | `--card-number` | Yes | Card number |
81
93
  | `--expiry` | Yes | Expiry date in `MMYY` format (note: not `MM/YY`) |
82
94
  | `--cvv` | Yes | CVV; piping via stdin is recommended to keep it out of shell history |
95
+ | `--idempotency-key` | Yes (in `--yes`) | Forwarded verbatim as the `Idempotency-Key` header |
83
96
 
84
97
  Returns a `PM ID` with `PENDING` status immediately, then auto-polls 3DS verification (3s interval, 15 min timeout). On success it prints `ACTIVE` status plus card brand, first six and last four. On timeout it suggests continuing with `payment-methods get`.
85
98
 
99
+ #### Drop-in mode
100
+
101
+ ```bash
102
+ agenzo-token-cli payment-methods add \
103
+ --api-key <api_key> \
104
+ --mode dropin \
105
+ --email user@example.com
106
+ ```
107
+
108
+ | Flag | Required | Description |
109
+ |---|---|---|
110
+ | `--api-key` | Yes | Prompted interactively when omitted |
111
+ | `--mode` | Yes | Set to `dropin` |
112
+ | `--email` | Yes | Reference for the Drop-in session |
113
+
114
+ Mints a Drop-in session and prints a `Session ID`. Initialise the add-payment UI in your own front-end with that `Session ID` (the user enters card details and completes verification in the browser). The CLI then polls the same verification endpoint (5s interval, 30 min timeout) and prints `ACTIVE` with brand / first six / last four on success. If the payment method is not added it reports `FAILED` / `EXPIRED` (or a 30-minute timeout) with the `PM ID` and exits non-zero — re-run with the same email to resume. Card flags (`--card-number` / `--expiry` / `--cvv`) and `--idempotency-key` are not used in this mode.
115
+
86
116
  ### list
87
117
 
88
118
  ```bash
@@ -170,7 +200,7 @@ Revokes immediately and prints `REVOKED` plus the revocation time; X402 tokens u
170
200
 
171
201
  ## Output and errors
172
202
 
173
- - **Success**: `table` mode prints human-readable text; `json` mode emits the structured payload to stdout.
203
+ - **Success**: `table` mode prints formatted text; `json` mode emits the structured payload to stdout.
174
204
  - **Failure**: an error envelope is written to stderr. In `json` mode it is `{ "error": { "code", "code_num", "message", "request_id?" } }`; in `table` mode it is `✗ [<code_num>] <message>`.
175
205
  - **Exit codes**: `0` on success, `1`–`5` for different error categories (e.g. user cancellation = `5`).
176
206
 
@@ -178,13 +208,4 @@ Common error codes: `KEY_INVALID` (invalid API Key), `KEY_SCOPE_DENIED` (scope l
178
208
 
179
209
  ## Related
180
210
 
181
- - Full field-level specification: internal design doc `architecture-upgrade/v1/cli-design.md` §3.
182
211
  - Control plane (login / organizations / developers / API Key management): [`@agenzo/admin-cli`](https://www.npmjs.com/package/@agenzo/admin-cli).
183
-
184
- ## Development
185
-
186
- ```bash
187
- npm install # install dependencies from the monorepo root
188
- npm run build # build (tsup, output at dist/index.js)
189
- npm test # run tests (vitest)
190
- ```
package/dist/index.js CHANGED
@@ -697,6 +697,10 @@ var PromptEngine = class {
697
697
  if (flagValue !== void 0) {
698
698
  return flagValue;
699
699
  }
700
+ const envKey = process.env.AGENZO_API_KEY;
701
+ if (envKey) {
702
+ return envKey;
703
+ }
700
704
  if (config.type === "password") {
701
705
  return password({ message: config.message, mask: "*" });
702
706
  }
@@ -744,136 +748,231 @@ async function collectPaymentMethodParams(type, flags) {
744
748
  }
745
749
 
746
750
  // src/payment-methods/add.ts
747
- var POLL_INTERVAL_MS = 3e3;
748
- var POLL_TIMEOUT_MS = 15 * 60 * 1e3;
751
+ var MANUAL_POLL_INTERVAL_MS = 3e3;
752
+ var MANUAL_POLL_TIMEOUT_MS = 15 * 60 * 1e3;
753
+ var DROPIN_POLL_INTERVAL_MS = 5e3;
754
+ var DROPIN_POLL_TIMEOUT_MS = 30 * 60 * 1e3;
755
+ var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["ACTIVE", "FAILED", "EXPIRED"]);
749
756
  function registerAddCommand(parent, deps) {
750
- const cmd = parent.command("add").description("Add a payment method (with 3DS verification)").option("--api-key <key>", "API Key for authentication").option("--type <type>", "Payment method type (default: card)", "card").option("--email <email>", "Email for 3DS verification").option("--card-number <number>", "Card number").option("--expiry <mmyy>", "Expiry date (MMYY format)").option("--cvv <cvv>", "Card CVV").option(
757
+ const cmd = parent.command("add").description("Add a payment method (manual 3DS or Drop-in session)").option("--api-key <key>", "API Key for authentication").option("--type <type>", "Payment method type (default: card)", "card").option(
758
+ "--mode <mode>",
759
+ 'Add mode: "manual" (default; CLI collects card details and polls 3DS) or "dropin" (mint a Drop-in session and poll until the user finishes adding the payment method in the browser)',
760
+ "manual"
761
+ ).option(
762
+ "--email <email>",
763
+ "Manual mode: email for 3DS verification. Dropin mode: email used as the Drop-in session reference."
764
+ ).option("--card-number <number>", "Card number (manual mode only)").option("--expiry <mmyy>", "Expiry date (MMYY format) (manual mode only)").option("--cvv <cvv>", "Card CVV (manual mode only)").option(
751
765
  "--idempotency-key <key>",
752
- "Idempotency key forwarded verbatim as the Idempotency-Key header"
766
+ "Idempotency key forwarded verbatim as the Idempotency-Key header (manual mode only)"
753
767
  );
754
768
  cmd.action(async () => {
755
769
  const opts = cmd.optsWithGlobals();
756
770
  const format = resolveFormat(opts.format);
757
771
  const isYes = Boolean(opts.yes);
758
- const apiKey = await PromptEngine.resolveInput(opts.apiKey, {
759
- message: "API Key:",
760
- type: "password"
761
- });
762
- const type = opts.type || "card";
763
- const flags = {
764
- email: opts.email,
765
- cardNumber: opts.cardNumber,
766
- expiry: opts.expiry,
767
- cvv: opts.cvv
768
- };
769
- const params = await collectPaymentMethodParams(type, flags);
770
- let idempotencyKey = opts.idempotencyKey;
771
- if (!idempotencyKey) {
772
- if (isYes) {
773
- throw new IdempotencyKeyRequiredError("payment-methods add");
774
- }
775
- idempotencyKey = await PromptEngine.resolveInput(void 0, {
776
- message: "Idempotency key (unique per write, for safe retry):",
777
- validate: (v) => v.trim().length > 0 || "Idempotency key is required"
778
- });
772
+ const mode = String(opts.mode ?? "manual").toLowerCase();
773
+ if (mode !== "manual" && mode !== "dropin") {
774
+ throw new CliError(
775
+ "PARAM_INVALID",
776
+ `Unknown --mode "${opts.mode}". Expected "manual" or "dropin".`
777
+ );
779
778
  }
780
- const extraHeaders = {
781
- "Idempotency-Key": idempotencyKey
782
- };
783
- const result = await deps.apiClient.post(
784
- "/payment-methods/create",
785
- { type: "api-key", key: apiKey },
786
- params,
787
- extraHeaders
788
- );
789
- if (!result.success) {
790
- throw CliError.fromApi(result, { auth: "api-key" });
779
+ if (mode === "dropin") {
780
+ await handleDropinMode(deps, opts, format);
781
+ return;
791
782
  }
792
- const pm = result.data;
793
- notify(format, "success", "Payment method created");
794
- const createdResult = {
795
- data: pm,
796
- text: () => {
797
- const lines = [
798
- ["ID", pm.id],
799
- ["Type", pm.type],
800
- ["Status", pm.status]
801
- ];
802
- if (pm.brand) lines.push(["Brand", pm.brand]);
803
- if (pm.first6) lines.push(["First 6", pm.first6]);
804
- if (pm.last4) lines.push(["Last 4", pm.last4]);
805
- return Formatter.keyValue(lines);
806
- }
807
- };
808
- const configManager = new ConfigManager();
809
- await renderWithContext(createdResult, { format }, configManager);
810
- notify(format, "info", "Complete 3DS verification via email to activate");
811
- if (type === "card" && pm.status === "PENDING") {
812
- const finalStatus = await poll3dsVerification(
813
- deps.apiClient,
814
- apiKey,
815
- pm.id,
816
- format
783
+ await handleManualMode(deps, opts, format, isYes);
784
+ });
785
+ }
786
+ async function handleManualMode(deps, opts, format, isYes) {
787
+ const apiKey = await PromptEngine.resolveInput(opts.apiKey, {
788
+ message: "API Key:",
789
+ type: "password"
790
+ });
791
+ const type = opts.type || "card";
792
+ const flags = {
793
+ email: opts.email,
794
+ cardNumber: opts.cardNumber,
795
+ expiry: opts.expiry,
796
+ cvv: opts.cvv
797
+ };
798
+ const params = await collectPaymentMethodParams(type, flags);
799
+ let idempotencyKey = opts.idempotencyKey;
800
+ if (!idempotencyKey) {
801
+ if (isYes) {
802
+ throw new IdempotencyKeyRequiredError("payment-methods add");
803
+ }
804
+ idempotencyKey = await PromptEngine.resolveInput(void 0, {
805
+ message: "Idempotency key (unique per write, for safe retry):",
806
+ validate: (v) => v.trim().length > 0 || "Idempotency key is required"
807
+ });
808
+ }
809
+ const extraHeaders = {
810
+ "Idempotency-Key": idempotencyKey
811
+ };
812
+ const result = await deps.apiClient.post(
813
+ "/payment-methods/create",
814
+ { type: "api-key", key: apiKey },
815
+ params,
816
+ extraHeaders
817
+ );
818
+ if (!result.success) {
819
+ throw CliError.fromApi(result, { auth: "api-key" });
820
+ }
821
+ const pm = result.data;
822
+ notify(format, "success", "Payment method created");
823
+ const createdResult = {
824
+ data: pm,
825
+ text: () => {
826
+ const lines = [
827
+ ["ID", pm.id],
828
+ ["Type", pm.type],
829
+ ["Status", pm.status]
830
+ ];
831
+ if (pm.brand) lines.push(["Brand", pm.brand]);
832
+ if (pm.first6) lines.push(["First 6", pm.first6]);
833
+ if (pm.last4) lines.push(["Last 4", pm.last4]);
834
+ return Formatter.keyValue(lines);
835
+ }
836
+ };
837
+ const configManager = new ConfigManager();
838
+ await renderWithContext(createdResult, { format }, configManager);
839
+ notify(format, "info", "Complete 3DS verification via email to activate");
840
+ if (type === "card" && pm.status === "PENDING") {
841
+ const finalStatus = await poll3dsVerification(deps.apiClient, apiKey, pm.id, format);
842
+ if (finalStatus === "ACTIVE") {
843
+ const getResult = await deps.apiClient.get(
844
+ `/payment-methods/${pm.id}`,
845
+ { type: "api-key", key: apiKey }
817
846
  );
818
- if (finalStatus === "ACTIVE") {
819
- const getResult = await deps.apiClient.get(
820
- `/payment-methods/${pm.id}`,
821
- { type: "api-key", key: apiKey }
822
- );
823
- if (getResult.success) {
824
- const activatedPm = getResult.data;
825
- notify(format, "success", "Payment method activated");
826
- const activatedResult = {
827
- data: activatedPm,
828
- text: () => {
829
- const lines = [
830
- ["ID", activatedPm.id],
831
- ["Type", activatedPm.type],
832
- ["Status", activatedPm.status]
833
- ];
834
- if (activatedPm.brand) lines.push(["Brand", activatedPm.brand]);
835
- if (activatedPm.first6) lines.push(["First 6", activatedPm.first6]);
836
- if (activatedPm.last4) lines.push(["Last 4", activatedPm.last4]);
837
- return Formatter.keyValue(lines);
838
- }
839
- };
840
- await renderWithContext(activatedResult, { format }, configManager);
841
- } else {
842
- notify(format, "success", "Payment method activated");
843
- const degraded = { ...pm, status: "ACTIVE" };
844
- const degradedResult = {
845
- data: degraded,
846
- text: () => {
847
- const lines = [
848
- ["ID", degraded.id],
849
- ["Type", degraded.type],
850
- ["Status", degraded.status]
851
- ];
852
- if (degraded.brand) lines.push(["Brand", degraded.brand]);
853
- if (degraded.first6) lines.push(["First 6", degraded.first6]);
854
- if (degraded.last4) lines.push(["Last 4", degraded.last4]);
855
- return Formatter.keyValue(lines);
856
- }
857
- };
858
- await renderWithContext(degradedResult, { format }, configManager);
859
- }
860
- } else if (finalStatus === "FAILED") {
861
- notify(format, "error", "3DS verification failed");
862
- } else if (finalStatus === "TIMEOUT") {
863
- notify(
864
- format,
865
- "info",
866
- `Verification timed out (15 min). Check status with: agenzo-token-cli payment-methods get ${pm.id} --api-key <your_key>`
867
- );
847
+ if (getResult.success) {
848
+ const activatedPm = getResult.data;
849
+ notify(format, "success", "Payment method activated");
850
+ const activatedResult = {
851
+ data: activatedPm,
852
+ text: () => {
853
+ const lines = [
854
+ ["ID", activatedPm.id],
855
+ ["Type", activatedPm.type],
856
+ ["Status", activatedPm.status]
857
+ ];
858
+ if (activatedPm.brand) lines.push(["Brand", activatedPm.brand]);
859
+ if (activatedPm.first6) lines.push(["First 6", activatedPm.first6]);
860
+ if (activatedPm.last4) lines.push(["Last 4", activatedPm.last4]);
861
+ return Formatter.keyValue(lines);
862
+ }
863
+ };
864
+ await renderWithContext(activatedResult, { format }, configManager);
865
+ } else {
866
+ notify(format, "success", "Payment method activated");
867
+ const degraded = { ...pm, status: "ACTIVE" };
868
+ const degradedResult = {
869
+ data: degraded,
870
+ text: () => {
871
+ const lines = [
872
+ ["ID", degraded.id],
873
+ ["Type", degraded.type],
874
+ ["Status", degraded.status]
875
+ ];
876
+ if (degraded.brand) lines.push(["Brand", degraded.brand]);
877
+ if (degraded.first6) lines.push(["First 6", degraded.first6]);
878
+ if (degraded.last4) lines.push(["Last 4", degraded.last4]);
879
+ return Formatter.keyValue(lines);
880
+ }
881
+ };
882
+ await renderWithContext(degradedResult, { format }, configManager);
868
883
  }
884
+ } else if (finalStatus === "FAILED") {
885
+ notify(format, "error", "3DS verification failed");
886
+ } else if (finalStatus === "TIMEOUT") {
887
+ notify(
888
+ format,
889
+ "info",
890
+ `Verification timed out (15 min). Check status with: agenzo-token-cli payment-methods get ${pm.id} --api-key <your_key>`
891
+ );
869
892
  }
893
+ }
894
+ }
895
+ async function handleDropinMode(deps, opts, format) {
896
+ const apiKey = await PromptEngine.resolveInput(opts.apiKey, {
897
+ message: "API Key:",
898
+ type: "password"
870
899
  });
900
+ const email = await PromptEngine.resolveInput(opts.email, {
901
+ message: "Email:"
902
+ });
903
+ const configManager = new ConfigManager();
904
+ const sessionResult = await deps.apiClient.post(
905
+ "/payment-methods/dropin/create",
906
+ { type: "api-key", key: apiKey },
907
+ { email }
908
+ );
909
+ if (!sessionResult.success) {
910
+ throw CliError.fromApi(sessionResult, { auth: "api-key" });
911
+ }
912
+ const session = sessionResult.data;
913
+ const pmId = session.id;
914
+ notify(format, "success", "Drop-in session created");
915
+ const createdResult = {
916
+ data: session,
917
+ text: () => Formatter.keyValue([["Session ID", session.session_id || "-"]])
918
+ };
919
+ await renderWithContext(createdResult, { format }, configManager);
920
+ notify(
921
+ format,
922
+ "info",
923
+ "Use the Session ID to add the payment method in the browser via the Drop-in SDK"
924
+ );
925
+ const finalPm = await pollVerificationStatus(deps.apiClient, apiKey, pmId, {
926
+ intervalMs: DROPIN_POLL_INTERVAL_MS,
927
+ timeoutMs: DROPIN_POLL_TIMEOUT_MS
928
+ });
929
+ if (finalPm.status === "ACTIVE") {
930
+ notify(format, "success", "Payment method activated");
931
+ const activated = {
932
+ data: finalPm,
933
+ text: () => Formatter.keyValue([
934
+ ["PM ID", finalPm.id],
935
+ ["Brand", finalPm.brand ?? "-"],
936
+ ["First 6", finalPm.first6 ?? "-"],
937
+ ["Last 4", finalPm.last4 ?? "-"],
938
+ ["Status", finalPm.status]
939
+ ])
940
+ };
941
+ await renderWithContext(activated, { format }, configManager);
942
+ return;
943
+ }
944
+ if (finalPm.status === "FAILED") {
945
+ notify(format, "error", "Failed to add payment method");
946
+ await renderPmId(finalPm.id, format, configManager);
947
+ process.exitCode = 1;
948
+ return;
949
+ }
950
+ if (finalPm.status === "EXPIRED") {
951
+ notify(format, "error", "Session expired before the payment method was added");
952
+ await renderPmId(finalPm.id, format, configManager);
953
+ process.exitCode = 1;
954
+ return;
955
+ }
956
+ notify(
957
+ format,
958
+ "error",
959
+ "Adding payment method did not complete within 30 minutes. Re-run with the same email to resume."
960
+ );
961
+ await renderPmId(pmId, format, configManager);
962
+ process.exitCode = 1;
963
+ }
964
+ async function renderPmId(id, format, configManager) {
965
+ const result = {
966
+ data: { id },
967
+ text: () => Formatter.keyValue([["PM ID", id]])
968
+ };
969
+ await renderWithContext(result, { format }, configManager);
871
970
  }
872
971
  async function poll3dsVerification(apiClient, apiKey, paymentMethodId, format) {
873
972
  const startTime = Date.now();
874
973
  notify(format, "info", "Waiting for 3DS verification...");
875
- while (Date.now() - startTime < POLL_TIMEOUT_MS) {
876
- await sleep(POLL_INTERVAL_MS);
974
+ while (Date.now() - startTime < MANUAL_POLL_TIMEOUT_MS) {
975
+ await sleep(MANUAL_POLL_INTERVAL_MS);
877
976
  const result = await apiClient.get(
878
977
  "/payment-methods/verification/status",
879
978
  { type: "api-key", key: apiKey },
@@ -891,6 +990,21 @@ async function poll3dsVerification(apiClient, apiKey, paymentMethodId, format) {
891
990
  }
892
991
  return "TIMEOUT";
893
992
  }
993
+ async function pollVerificationStatus(apiClient, apiKey, pmId, options) {
994
+ const startTime = Date.now();
995
+ while (Date.now() - startTime < options.timeoutMs) {
996
+ const result = await apiClient.get(
997
+ "/payment-methods/verification/status",
998
+ { type: "api-key", key: apiKey },
999
+ { payment_method_id: pmId }
1000
+ );
1001
+ if (result.success && TERMINAL_STATUSES.has(result.data.status)) {
1002
+ return result.data;
1003
+ }
1004
+ await sleep(options.intervalMs);
1005
+ }
1006
+ return { id: pmId, status: "PENDING" };
1007
+ }
894
1008
  function sleep(ms) {
895
1009
  return new Promise((resolve) => setTimeout(resolve, ms));
896
1010
  }
@@ -1032,6 +1146,81 @@ function registerDisableCommand(parent, deps) {
1032
1146
  });
1033
1147
  }
1034
1148
 
1149
+ // src/payment-methods/dropin-create.ts
1150
+ function registerDropinCreateCommand(parent, deps) {
1151
+ const cmd = parent.command("dropin-create").description("Mint a Drop-in session and return the session id (no polling)").option("--api-key <key>", "API Key for authentication").option("--email <email>", "Email used as the Drop-in session reference");
1152
+ cmd.action(async () => {
1153
+ const opts = cmd.optsWithGlobals();
1154
+ const format = resolveFormat(opts.format);
1155
+ const apiKey = await PromptEngine.resolveInput(opts.apiKey, {
1156
+ message: "API Key:",
1157
+ type: "password"
1158
+ });
1159
+ const email = await PromptEngine.resolveInput(opts.email, {
1160
+ message: "Email:"
1161
+ });
1162
+ const sessionResult = await deps.apiClient.post(
1163
+ "/payment-methods/dropin/create",
1164
+ { type: "api-key", key: apiKey },
1165
+ { email }
1166
+ );
1167
+ if (!sessionResult.success) {
1168
+ throw CliError.fromApi(sessionResult, { auth: "api-key" });
1169
+ }
1170
+ const session = sessionResult.data;
1171
+ notify(format, "success", "Drop-in session created");
1172
+ const configManager = new ConfigManager();
1173
+ const result = {
1174
+ data: session,
1175
+ text: () => Formatter.keyValue([
1176
+ ["PM ID", session.id],
1177
+ ["Session ID", session.session_id || "-"],
1178
+ ["Merchant Trans ID", session.merchant_trans_id || "-"],
1179
+ ["Status", session.status]
1180
+ ])
1181
+ };
1182
+ await renderWithContext(result, { format }, configManager);
1183
+ notify(
1184
+ format,
1185
+ "info",
1186
+ "Use the Session ID to add the payment method via the Drop-in SDK, then poll: agenzo-token-cli payment-methods dropin-status <pm_id> --api-key <your_key>"
1187
+ );
1188
+ });
1189
+ }
1190
+
1191
+ // src/payment-methods/dropin-status.ts
1192
+ function registerDropinStatusCommand(parent, deps) {
1193
+ const cmd = parent.command("dropin-status <pm_id>").description("Query the current Drop-in binding status for a payment method (single check)").option("--api-key <key>", "API Key for authentication");
1194
+ cmd.action(async (pmId) => {
1195
+ const opts = cmd.optsWithGlobals();
1196
+ const format = resolveFormat(opts.format);
1197
+ const apiKey = await PromptEngine.resolveInput(opts.apiKey, {
1198
+ message: "API Key:",
1199
+ type: "password"
1200
+ });
1201
+ const result = await deps.apiClient.get(
1202
+ "/payment-methods/verification/status",
1203
+ { type: "api-key", key: apiKey },
1204
+ { payment_method_id: pmId }
1205
+ );
1206
+ if (!result.success) {
1207
+ throw CliError.fromApi(result, { auth: "api-key" });
1208
+ }
1209
+ const pm = result.data;
1210
+ const entries = [["ID", pm.id ?? pmId]];
1211
+ if (pm.brand) entries.push(["Brand", pm.brand]);
1212
+ if (pm.first6) entries.push(["First 6", pm.first6]);
1213
+ if (pm.last4) entries.push(["Last 4", pm.last4]);
1214
+ entries.push(["Status", pm.status]);
1215
+ const configManager = new ConfigManager();
1216
+ const cmdResult = {
1217
+ data: pm,
1218
+ text: () => Formatter.keyValue(entries)
1219
+ };
1220
+ await renderWithContext(cmdResult, { format }, configManager);
1221
+ });
1222
+ }
1223
+
1035
1224
  // src/payment-tokens/create.ts
1036
1225
  import { confirm, select as select2 } from "@inquirer/prompts";
1037
1226
  var DEFAULT_NT_FEE_CENTS = 500;
@@ -1631,6 +1820,8 @@ async function main() {
1631
1820
  registerListCommand(pmCmd, deps);
1632
1821
  registerGetCommand(pmCmd, deps);
1633
1822
  registerDisableCommand(pmCmd, deps);
1823
+ registerDropinCreateCommand(pmCmd, deps);
1824
+ registerDropinStatusCommand(pmCmd, deps);
1634
1825
  const ptCmd = program.command("payment-tokens").description("Payment token management");
1635
1826
  registerCreateCommand(ptCmd, deps);
1636
1827
  registerListCommand2(ptCmd, deps);