@bnbagent/studio-cli 0.0.6-alpha.4 → 0.0.6-alpha.6

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.
@@ -3,7 +3,7 @@ name: bnbagent-studio-selling-via-b402
3
3
  description: When the user wants a bnbagent-studio agent to sell paid or FREE HTTP requests through the B402-backed x402 rail. Owns the explicit pricing choice and, for PAID mode, per-agent merchant onboarding, RSA key preparation, egress-IP allowlisting, sandbox/production separation, B402 environment setup, seller status checks, and activation by redeploy (managed platform or self-hosted AgentCore).
4
4
  ---
5
5
 
6
- > **Reference file** of the `bnbagent-studio` router skill installed at
6
+ > **Reference file** of the `bnbagent-studio` router skill, installed at
7
7
  > `bnbagent-studio/references/` and loaded on demand (not a standalone skill).
8
8
  > Route here via the router's decision tree.
9
9
 
@@ -19,10 +19,9 @@ agent wallets, or mix sandbox and production values.
19
19
  - The agent wallet already exists. In PAID mode its address receives U.
20
20
  - The project targets the managed platform or self-hosted AgentCore
21
21
  (azure-foundry cannot activate the rail).
22
- - PAID managed platform only: a platform bearer token is available for reading the
23
- platform egress IPs the GitHub-login access token from
24
- `bag platform login`, or a `bnbk_…` API token minted once by
25
- `bag platform token`.
22
+ - PAID managed platform only: an interactive GitHub-login session from
23
+ `bag platform login` is available for reading the platform Relay egress
24
+ IPs. A `bnbk_…` CI token does not satisfy this endpoint's GitHub-user check.
26
25
  - `[payments.x402_seller]` exists. If not, run
27
26
  `bag x402 sell init`.
28
27
 
@@ -59,66 +58,86 @@ call under the
59
58
  the runtime signs each request automatically once the credentials are stored.
60
59
 
61
60
  Work from the workspace root. Keep private material under `.studio/`, which is
62
- excluded from source and deploy artifacts:
61
+ excluded from source and deploy artifacts. Generate a separate key pair for
62
+ each environment:
63
63
 
64
64
  ```bash
65
65
  umask 077
66
- mkdir -p .studio/b402
67
- openssl genrsa -out .studio/b402/private.pem 2048
68
- openssl pkey -in .studio/b402/private.pem -pubout \
69
- -out .studio/b402/public.pem
70
- openssl pkey -in .studio/b402/private.pem -pubout -outform DER |
71
- openssl base64 -A > .studio/b402/public.der.b64
72
- openssl pkcs8 -topk8 -nocrypt -in .studio/b402/private.pem -outform DER |
73
- openssl base64 -A > .studio/b402/private.der.b64
74
- chmod 600 .studio/b402/private.pem .studio/b402/private.der.b64
66
+ b402_env=sandbox
67
+ mkdir -p ".studio/b402/$b402_env"
68
+ openssl genpkey -algorithm RSA \
69
+ -out ".studio/b402/$b402_env/private.pem" \
70
+ -pkeyopt rsa_keygen_bits:1024
71
+ openssl pkey -in ".studio/b402/$b402_env/private.pem" -pubout \
72
+ -out ".studio/b402/$b402_env/public.pem"
73
+ openssl pkey -in ".studio/b402/$b402_env/private.pem" -pubout -outform DER |
74
+ openssl base64 -A > ".studio/b402/$b402_env/public.der.b64"
75
+ openssl pkcs8 -topk8 -nocrypt \
76
+ -in ".studio/b402/$b402_env/private.pem" -outform DER |
77
+ openssl base64 -A > ".studio/b402/$b402_env/private.der.b64"
78
+ chmod 600 ".studio/b402/$b402_env/private.pem" \
79
+ ".studio/b402/$b402_env/private.der.b64"
75
80
  ```
76
81
 
77
82
  Do not print the private key or its base64 form. Submit only the public key
78
83
  material to B402.
79
84
 
80
- Studio generates a 2048-bit RSA key. The current B402 application form text
81
- mentions 1024 bits, while 2048-bit acceptance still requires confirmation from
82
- the B402 operator. Confirm that field with the operator; do not silently
83
- downgrade the key.
85
+ The current B402 request-signing contract explicitly requires a 1024-bit RSA
86
+ key and RSA-SHA256. Follow that protocol requirement even if a larger RSA key
87
+ would normally be preferred elsewhere. Repeat with `b402_env=production`
88
+ instead of reusing the sandbox pair.
84
89
 
85
90
  ## Collect the IP allowlist
86
91
 
87
- B402 allowlists the merchant's **outbound** (egress) IPs the addresses the
92
+ B402 allowlists the merchant's **outbound** (egress) IPs, the addresses the
88
93
  agent's facilitator calls come FROM. Submit every part that applies to your
89
94
  deployment target:
90
95
 
91
- 1. **Platform egress IPs (managed-platform deploys)** the addresses
92
- deployed-agent requests reach B402 from. Authenticated read (bearer from
93
- the Preconditions):
96
+ 1. **Platform Relay egress IPs (managed-platform deploys)**: the addresses
97
+ that the platform B402 Relay uses to reach the facilitator. The managed
98
+ deployment worker points only the AgentCore runtime copy of
99
+ `B402_BASE_URL` at this Relay. Refresh and read the interactive session
100
+ without printing its bearer:
94
101
 
95
102
  ```bash
96
- curl -H "Authorization: Bearer $BNBAGENT_API_TOKEN" \
97
- "https://bnbagent-api.bnbchain.world/v1/b402/whitelist-ips"
103
+ bag platform whoami >/dev/null
104
+ platform_session="$HOME/.bnbagent-deploy/bnb/session.json"
105
+ platform_access_token="$(jq -er '.access_token' "$platform_session")"
106
+ platform_api_url="$(jq -er '.apiUrl' "$platform_session")"
107
+ curl -H "Authorization: Bearer $platform_access_token" \
108
+ "$platform_api_url/v1/b402/whitelist-ips"
109
+ unset platform_access_token
98
110
  # → {"whitelist_ips": ["13.115.15.190", …], "cache_ttl_seconds": 300}
99
111
  ```
100
112
 
101
113
  Submit every address in `whitelist_ips`. The list is served with a short
102
- cache TTL and can rotate re-read it right before submitting the form.
103
- Set `BAG_PLATFORM_API_BASE` to target a non-production platform
104
- environment.
114
+ cache TTL and can rotate, so re-read it right before submitting the form.
115
+ The login session is stored mode `0600`. Do not echo, log, or paste its
116
+ access or refresh token. `bnbk_` tokens from `bag platform token` are
117
+ deliberately rejected by this GitHub-login-only endpoint.
105
118
 
106
- 2. **Your local public IP** required so a local `bag dev` run can reach
119
+ 2. **Your local public IP**: required so a local `bag dev` run can reach
107
120
  B402:
108
121
 
109
122
  ```bash
110
123
  curl ipinfo.io/ip
111
124
  ```
112
125
 
113
- 3. **Self-hosted AgentCore egress (self-deploys)** AgentCore gives the
114
- container no fixed egress IP, so there is no address to submit directly.
115
- Route the facilitator egress through a fixed-IP forward proxy you control
116
- and submit THAT IP: set `HTTPS_PROXY` on the runtime and enable proxy
117
- support for Node's fetch, which ignores proxy env vars by default —
118
- install an undici `EnvHttpProxyAgent` global dispatcher in the agent
119
- entrypoint, or run the container on Node 24+ with `--use-env-proxy`.
120
- Without this, every verify/settle call is rejected as an unallowlisted
121
- IP even though the deploy summary reports the rail ACTIVE.
126
+ 3. **Self-hosted AgentCore egress (self-deploys)**: operate a restricted B402
127
+ Relay on a host with a fixed public egress IP, such as a user-managed VPS,
128
+ and submit that IP. Set the runtime `B402_BASE_URL` to the Relay base URL.
129
+ The Relay exposes only
130
+ `supported`, `verify`, and `settle`, fixes the upstream facilitator, and
131
+ forwards the signed body and Tesla header allowlist without holding the
132
+ merchant private key or automatically retrying a settlement transport
133
+ failure. See the
134
+ [self-hosted x402 gateway guide](https://github.com/bnb-chain/bnbagent-studio/blob/main/docs/guides/self-hosted-x402-gateway.md)
135
+ for a TypeScript example.
136
+
137
+ As an alternative, use AWS-supported AgentCore VPC mode with a private subnet, NAT
138
+ Gateway, and Elastic IP. Submit the Elastic IP and keep
139
+ `B402_BASE_URL` pointed at the facilitator. Studio does not deploy or
140
+ manage that AWS network.
122
141
 
123
142
  Do not add the public inbound gateway IP, a transient build-runner IP, or
124
143
  guessed addresses. If the whitelist endpoint is unreachable, stop onboarding
@@ -134,10 +153,11 @@ production. Fill the form as follows:
134
153
  | Field | Value |
135
154
  |---|---|
136
155
  | Business Name | Your agent or business display name |
137
- | Website | Your project or service URL |
138
- | Wallet | The agent wallet address |
139
- | RSA Public Key | The contents of `.studio/b402/public.der.b64` in the format the operator confirms |
140
- | IP allowlist | Every platform egress IP from `/v1/b402/whitelist-ips` plus your local public IP (see "Collect the IP allowlist") |
156
+ | Email | Primary contact email address |
157
+ | Wallet address | The agent wallet for that environment |
158
+ | Public key | The contents of `.studio/b402/<environment>/public.der.b64` |
159
+ | IP allowlist | For managed deploys, every platform Relay IP from `/v1/b402/whitelist-ips`; for self-hosted deploys, the user's Relay or NAT Elastic IP; add the local public IP when `bag dev` must reach B402 directly |
160
+ | Webhook callback URL | Supply only when the integration uses callbacks |
141
161
 
142
162
  Keep the two environments isolated:
143
163
 
@@ -152,20 +172,28 @@ Open the workspace `.studio/.env.local` in an editor and fill exactly four
152
172
  values:
153
173
 
154
174
  ```dotenv
155
- B402_BASE_URL=https://qacb.sdtaop.com
175
+ B402_BASE_URL=
156
176
  B402_CLIENT_ID=
157
177
  B402_ACCESS_TOKEN=
158
178
  B402_PRIVATE_KEY_B64=
159
179
  ```
160
180
 
161
181
  Copy the single-line DER value from
162
- `.studio/b402/private.der.b64` into `B402_PRIVATE_KEY_B64`. Do not include the
163
- value in shell history, terminal output, source files, TOML, screenshots, or
164
- support tickets.
182
+ `.studio/b402/<environment>/private.der.b64` into `B402_PRIVATE_KEY_B64`.
183
+ `B402_BASE_URL`, `B402_CLIENT_ID`, and `B402_ACCESS_TOKEN` are the values
184
+ issued together for that environment. Do not include any value in shell
185
+ history, terminal output, source files, TOML, screenshots, or support tickets.
165
186
 
166
187
  `B402_PRIVATE_KEY` accepts the PEM representation as an alternative. Keep
167
188
  exactly one private-key form; do not set both.
168
189
 
190
+ For the current managed BSC Testnet path, the platform-supported upstream is
191
+ `https://qacb.sdtaop.com`; the worker projects only the AgentCore runtime copy
192
+ to its Relay. For a generic self-hosted environment, use the authenticated
193
+ base URL issued during onboarding. With your own Relay, set the runtime
194
+ `B402_BASE_URL` to that Relay base URL and configure the Relay's fixed upstream
195
+ to the issued URL.
196
+
169
197
  ## Verify and activate
170
198
 
171
199
  For PAID mode, check names and presence without exposing values:
@@ -197,22 +225,34 @@ On the managed platform the deploy summary must say `x402 rail is ACTIVE` (or
197
225
  `ACTIVE in FREE mode`) and print the anonymous `/x402` URL. On a self-hosted
198
226
  AgentCore deploy it says `x402 rail is ACTIVE (self-hosted AgentCore)` or
199
227
  `ACTIVE in FREE mode (self-hosted AgentCore)`: the rail runs in-process, but
200
- there is no anonymous URL operate your own HTTP front that relays envelope-v1
201
- JSON over SigV4-signed `InvokeAgentRuntime` calls (see
202
- `docs/guides/x402-selling.md`, "Self-hosted AgentCore access"). A dormant or
203
- forced-dormant summary means the rail was not activated; fix the named
204
- credential, runtime, network, or tunnel condition and redeploy.
228
+ there is no anonymous URL. Operate your own HTTP front that relays envelope-v1
229
+ JSON through an authenticated AgentCore invocation. The default Bag
230
+ self-deploy uses Cognito OAuth over raw HTTPS; AWS SDK/SigV4 is only for a
231
+ runtime deliberately configured with IAM authorization. PAID also needs your
232
+ own fixed-egress B402 Relay or equivalent network path. The complete gateway
233
+ wrapper, response parser, Relay example, and direct-invocation fallback are in
234
+ the
235
+ [self-hosted x402 gateway guide](https://github.com/bnb-chain/bnbagent-studio/blob/main/docs/guides/self-hosted-x402-gateway.md).
236
+ A dormant or forced-dormant summary means the rail was not activated; fix the
237
+ named credential, runtime, network, or tunnel condition and redeploy.
205
238
 
206
239
  ## Hard rules
207
240
 
208
241
  - Never log or print any B402 value or private key.
209
242
  - Never put a B402 value in `studio.toml` or a deploy descriptor.
210
- - Never retry a settlement whose outcome is unknown. Follow
243
+ - Never replay a paid HTTP request whose outcome is unknown. Follow
211
244
  `docs/guides/x402-selling.md` and reconcile `(nonce, network, payer)` first.
245
+ - Binance `/settle` is asynchronous. A parseable `success: false` response
246
+ with a transaction is pending and requires an idempotent poll with the same
247
+ settlement payload. Studio v0.0.6 and the latest
248
+ `@bnb-chain/b402@0.1.0` do not yet perform that poll; they classify pending
249
+ as unknown. Do not claim current mainnet readiness until this is updated.
212
250
  - Settlement happens before work. A later work failure retains the payment and
213
251
  does not trigger an automatic refund.
214
252
  - The rail activates on AgentCore targets only (managed platform or
215
253
  self-hosted); azure-foundry stays forced dormant.
216
- - PAID payout wallets must use `wallet.kind` `evm-local` or `twak`; FREE has
217
- no payout and does not apply this B402-specific allowlist.
254
+ - PAID B402 payout wallets must use `wallet.kind` `evm-local` (private-key
255
+ wallet stored as an encrypted keystore) or `twak`. Altana is unsupported.
256
+ FREE x402 bypasses B402, has no payout, and must not be described as Altana
257
+ B402 support.
218
258
  - Never describe FREE as a zero-value B402 settlement. It bypasses B402.
@@ -199,8 +199,11 @@ bag deploy destroy --provider aws --execute # delegated teardown (add --purge)
199
199
  - b402/x402 selling on self-hosted AgentCore: the rail activates in-process
200
200
  with complete B402 credentials for PAID, or without them when explicit zero
201
201
  selects FREE. There is no anonymous URL — operate your own HTTP front that
202
- relays envelope-v1 over `InvokeAgentRuntime`. See
203
- `bnbagent-studio-selling-via-b402` and `docs/guides/x402-selling.md`.
202
+ relays envelope-v1 through the runtime's configured authorizer. The default
203
+ Bag deploy uses Cognito OAuth over HTTPS, not SDK/SigV4. PAID also needs a
204
+ fixed-egress B402 Relay or VPC/NAT/Elastic-IP path. See
205
+ `bnbagent-studio-selling-via-b402` and
206
+ `docs/guides/self-hosted-x402-gateway.md`.
204
207
  - `bag deploy --help` / `bag deploy <command> --help` (authoritative for commands + flags)
205
208
  - `agentcore/agentcore.json` — name (resource naming continuity), protocol, authorizer, envVars
206
209
  - `agentcore/aws-targets.json` — AWS account + region
@@ -27,8 +27,8 @@ bag init <name> --wallet-kind altana --destination self --no-onboard
27
27
  # Non-TTY defaults to OpenRouter. In a TTY, choose OpenRouter, OpenAI, or
28
28
  # Anthropic from the provider menu; a flag remains available when desired:
29
29
  # bag init <name> --wallet-kind altana --llm-provider anthropic --destination self
30
+ # Edit <name>/.studio/.env.local and set WALLET_PASSWORD first.
30
31
  cd <name>/app/agent
31
- export WALLET_PASSWORD='<strong password>'
32
32
  bag wallet new
33
33
  # fund the printed admin address with gas + U
34
34
  bag wallet session grant
@@ -31,8 +31,9 @@ with "unknown option"); `bag doctor` and `bag deploy prepare` verify the floor.
31
31
 
32
32
  ## 2. Create the wallet — one time, in YOUR terminal
33
33
 
34
- studio can't create it for you (the twak CLI takes the password on argv, upstream
35
- S-8, and studio never puts secrets on argv). Do these steps yourself.
34
+ `bag wallet twak-init` drives creation for you (step 3) so you never type the
35
+ password on a command line; the NaaS setup wizard below still has to be run by
36
+ hand once, because it is interactive.
36
37
 
37
38
  **Every twak command is prefixed with the dedicated home.** Without `HOME=$DH`,
38
39
  twak uses your real `~/.twak` (your MAIN wallet) and macOS pops a login-keychain
@@ -64,20 +65,22 @@ DH=<workspace>/.studio/twak # e.g. ~/proj/.studio/twak
64
65
  your main/real wallet).
65
66
 
66
67
  **3. Create the wallet** (password UPPER + lower + digit, e.g. `Mypasswd01`;
67
- `mypasswd01` is rejected). **RECOMMENDED — let studio drive it with the
68
- password OFF argv** (it resolves the project home from studio.toml, so no
69
- `HOME=` juggling):
68
+ `mypasswd01` is rejected). **RECOMMENDED — let studio drive it so you never
69
+ type the password on a command line** (it resolves the project home from
70
+ studio.toml, so no `HOME=` juggling):
70
71
  ```bash
71
72
  bag wallet twak-init # interactive hidden prompt
72
73
  printf %s "$PW" | bag wallet twak-init --password-stdin # CI / scripts
73
74
  bag wallet twak-init --password-file pw.txt # file must be chmod 600
74
75
  ```
75
- It wraps `twak wallet create --no-keychain` (password reaches twak via env +
76
- piped stdin only), tightens `wallet.json` to mode 600, and adopts the
77
- address into studio.toml in one go so steps 5's `bag wallet new` is
78
- already done.
79
-
80
- Manual alternative (password lands on argv → `ps` / shell history;
76
+ It seeds this home's `credentials.json` from `~/.twak` when step 2 was run
77
+ there, wraps `twak wallet create --password --no-keychain` (twak requires
78
+ the flag on its own argv, so the value reaches that short-lived child — it
79
+ never lands in YOUR shell history), tightens `wallet.json` to mode 600, and
80
+ adopts the address into studio.toml in one go — so step 5's `bag wallet new`
81
+ is already done.
82
+
83
+ Manual alternative (you type the password on argv → `ps` / shell history;
81
84
  acceptable only for a throwaway hot wallet):
82
85
  ```bash
83
86
  HOME="$DH" twak wallet create --password '<StrongPw>' --no-keychain
@@ -249,8 +252,11 @@ registers a `Container` runtime and `app/agent/Dockerfile` builds the image
249
252
  | Custom ERC-8183 targets unavailable | upstream feature request | twak v0.20.0 has no Commerce/Router/Policy address option. Studio doctor/prepare and the SDK fail closed instead of silently executing on canonical contracts; use `evm-local` for a custom ERC-8183 deployment. |
250
253
  | No generic EIP-712 signing | P0 (won't fix) | `[wallet.signing]` is ignored; payments go through the delegated payer's own prechecks + `--max-payment`. Endpoints needing an `Authorization` header *and* x402 are unavailable (e.g. `bag llm key new --initial-usd > 0` — use `--initial-usd 0` + topup + allocate instead, same end state). |
251
254
  | No wallet import | S-6 | Switching wallet kinds changes your address → re-run `bag 8004 register` (new on-chain identity). |
252
- | Programmatic wallet creation forces password onto argv | S-8 | Bridged by `bag wallet twak-init` (password via stdin / 0600 file / hidden prompt never argv); the manual twak commands remain a fallback. |
255
+ | Programmatic wallet creation forces password onto argv | S-8 | Bridged by `bag wallet twak-init` (you supply it via stdin / 0600 file / hidden prompt; studio forwards it on the child's argv because twak requires the flag); the manual twak commands remain a fallback. |
253
256
  | CLI has no daily/monthly caps | — | Studio's policy layer (`[budget].max_per_day_usd`, host allowlist, per-request caps) is the spend authority for both wallet kinds. |
257
+ | `twak wallet balance --chain bsctestnet` rejects the chain | BUG-031 | Fails with `CHAIN_UNSUPPORTED` even though `wallet address` and `erc8183` accept `bsctestnet`. Use `bag wallet balance` (RPC-based, works on testnet), or raw RPC: `eth_getBalance` for tBNB and an `eth_call` of `balanceOf(address)` on the U token for token balance. |
258
+ | `twak tx <hash> --chain bsctestnet` rejects the chain | BUG-032 | Same chain-registry gap on the readback path: transactions twak itself just mined on `bsctestnet` cannot be inspected with `twak tx`. Use public RPC (`eth_getTransactionByHash` / `eth_getTransactionReceipt`) or BscScan testnet instead. |
259
+ | Raw `twak erc8183 create-job` has no expiry preflight | BUG-030 | An `--expires-at` inside the policy's dispute window is accepted, all four funding steps succeed, and only the final `submit` reverts `SubmissionTooLate()` (`0x15e5dd74`). Prefer the SDK path (`ERC8183Client` preflights this); if you must use the raw CLI, set `expires_at ≥ now + deadline + dispute_window` — on testnet's 24h window, `now + 172800` (48h) is a safe floor. |
254
260
 
255
261
  ## 7. Quick health checks
256
262