run402-mcp 4.121.0 → 4.122.1
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/dist/docs/llms-sdk.txt +34 -6
- package/package.json +3 -3
- package/schemas/release-spec.v1.json +4 -2
- package/sdk/dist/namespaces/deploy.d.ts.map +1 -1
- package/sdk/dist/namespaces/deploy.js +87 -31
- package/sdk/dist/namespaces/deploy.js.map +1 -1
- package/sdk/dist/namespaces/deploy.types.d.ts +4 -2
- package/sdk/dist/namespaces/deploy.types.d.ts.map +1 -1
- package/sdk/dist/namespaces/deploy.types.js +4 -0
- package/sdk/dist/namespaces/deploy.types.js.map +1 -1
- package/sdk/dist/namespaces/pay.d.ts +7 -0
- package/sdk/dist/namespaces/pay.d.ts.map +1 -1
- package/sdk/dist/namespaces/pay.js +5 -0
- package/sdk/dist/namespaces/pay.js.map +1 -1
- package/sdk/dist/namespaces/projects.d.ts +6 -2
- package/sdk/dist/namespaces/projects.d.ts.map +1 -1
- package/sdk/dist/namespaces/projects.js +46 -31
- package/sdk/dist/namespaces/projects.js.map +1 -1
- package/sdk/dist/namespaces/projects.types.d.ts +14 -8
- package/sdk/dist/namespaces/projects.types.d.ts.map +1 -1
- package/sdk/dist/node/_paid-stack.d.ts +8 -3
- package/sdk/dist/node/_paid-stack.d.ts.map +1 -1
- package/sdk/dist/node/_paid-stack.js.map +1 -1
- package/sdk/dist/node/lightning-paid-fetch.d.ts.map +1 -1
- package/sdk/dist/node/lightning-paid-fetch.js +2 -0
- package/sdk/dist/node/lightning-paid-fetch.js.map +1 -1
- package/sdk/dist/node/mpp-pay-executor.d.ts +40 -0
- package/sdk/dist/node/mpp-pay-executor.d.ts.map +1 -0
- package/sdk/dist/node/mpp-pay-executor.js +352 -0
- package/sdk/dist/node/mpp-pay-executor.js.map +1 -0
- package/sdk/dist/node/paid-fetch.d.ts +2 -1
- package/sdk/dist/node/paid-fetch.d.ts.map +1 -1
- package/sdk/dist/node/paid-fetch.js +44 -18
- package/sdk/dist/node/paid-fetch.js.map +1 -1
- package/sdk/dist/node/payment-attempts.d.ts +2 -2
- package/sdk/dist/node/payment-attempts.d.ts.map +1 -1
- package/sdk/dist/node/payment-attempts.js +2 -2
- package/sdk/dist/node/payment-attempts.js.map +1 -1
- package/sdk/dist/node/payment-offers.d.ts +35 -0
- package/sdk/dist/node/payment-offers.d.ts.map +1 -0
- package/sdk/dist/node/payment-offers.js +145 -0
- package/sdk/dist/node/payment-offers.js.map +1 -0
- package/sdk/dist/stale-project-key.d.ts +14 -0
- package/sdk/dist/stale-project-key.d.ts.map +1 -0
- package/sdk/dist/stale-project-key.js +88 -0
- package/sdk/dist/stale-project-key.js.map +1 -0
- package/sdk/dist/type-contract.d.ts.map +1 -1
- package/sdk/dist/type-contract.js.map +1 -1
package/dist/docs/llms-sdk.txt
CHANGED
|
@@ -227,7 +227,31 @@ or the rail's ceiling, and refuses an entry on another network with
|
|
|
227
227
|
`nostr+walletconnect://` URI, a bearer secret the MCP sandbox refuses with
|
|
228
228
|
`SECRET_REQUIRES_CLI`) pays with that pairing on its node's network instead.
|
|
229
229
|
The receipt of a Lightning payment reports the `lnbtc:` network, the payment
|
|
230
|
-
hash as `transaction`, `amountMsat`, and no payer
|
|
230
|
+
hash as `transaction`, `amountMsat`, and no payer.
|
|
231
|
+
|
|
232
|
+
On the `mpp` rail it pays a 402 that carries an MPP Tempo charge
|
|
233
|
+
(`WWW-Authenticate: Payment`, method `tempo`, intent `charge`) in pathUSD on
|
|
234
|
+
the first offered Tempo chain the wallet covers (price plus fee headroom),
|
|
235
|
+
applying `maxUsdMicros` to the selected challenge before anything is signed,
|
|
236
|
+
then retries the identical request with `Authorization: Payment`. Its receipt
|
|
237
|
+
reports `protocol: "mpp"`, `method: "tempo"`, the `eip155:4217` /
|
|
238
|
+
`eip155:42431` network, pathUSD as `asset`, the Tempo transaction hash as
|
|
239
|
+
`transaction`, and the seller's decoded `Payment-Receipt` as
|
|
240
|
+
`evidence.protocolReceipt`; `offer.status` and `merchantReceipt.status` are
|
|
241
|
+
`"unavailable"` (MPP carries no wallet-rooted merchant evidence, so
|
|
242
|
+
`requireReceipt` fails `MERCHANT_RECEIPT_REQUIRED` before signing). An x402
|
|
243
|
+
receipt reports `protocol: "x402"`, `method: "exact"`. Over MPP a payment's
|
|
244
|
+
identity is its credential, not the caller key: `idempotencyKey` is forwarded
|
|
245
|
+
for correlation only, and an ambiguous or pending outcome is resolved by
|
|
246
|
+
repeating the identical request on the same SDK instance, which re-presents
|
|
247
|
+
the same credential; the seller resolves it to the original payment
|
|
248
|
+
(`deduplicated: true`, `fundsMoved: false`) and never charges twice.
|
|
249
|
+
|
|
250
|
+
When the wallet's rail cannot pay anything the 402 offers, the buyer fails
|
|
251
|
+
`PAYMENT_NETWORK_UNSUPPORTED` before signing, with `details.offers[]` listing
|
|
252
|
+
every offer it saw (`{ protocol, method, intent?, network }`, x402 entries and
|
|
253
|
+
MPP challenges alike) and a `run402 init <rail> --switch-rail` next action
|
|
254
|
+
naming the rail that pays the first offer:
|
|
231
255
|
|
|
232
256
|
```ts
|
|
233
257
|
import { run402 } from "@run402/sdk/node";
|
|
@@ -259,7 +283,8 @@ validity, settlement, payer, transaction, and signer relationship. Branch on
|
|
|
259
283
|
lifetime/key-reuse codes, or `PAYMENT_SETTLEMENT_FAILED`. The error preserves
|
|
260
284
|
`fundsMoved`, `paymentId`, intent/delivery events, and canonical `nextActions`.
|
|
261
285
|
Successful results preserve `paymentId`, `deduplicated`, `fundsMoved`,
|
|
262
|
-
`delivery`, `settledAt`, and `intentState` when supplied.
|
|
286
|
+
`delivery`, `settledAt`, and `intentState` when supplied. Every receipt names
|
|
287
|
+
the `protocol` (`x402` | `mpp`) and `method` (`exact` | `tempo`) that paid.
|
|
263
288
|
A seller may settle and then deliberately answer a non-2xx (for example a
|
|
264
289
|
400 refusing the paid action). When that response carries a valid standard
|
|
265
290
|
`PAYMENT-RESPONSE` receipt for the accepted challenge, `r.pay.fetch` returns a
|
|
@@ -706,9 +731,9 @@ const info = await r.projects.info(projectId);
|
|
|
706
731
|
|
|
707
732
|
## Rehearsals, snapshots, and branches
|
|
708
733
|
|
|
709
|
-
Rehearsal is automatic inside `apply()` and `r.up()`: when the plan's `rehearsal.available` is true (migrations, and the project has a live release), the plan is rehearsed on a contained branch and committed only on a passing report, bound to the report's `required_plan`. The result carries `rehearsal: { status: "passed", report, operation_id, branch_project_id }`, or `{ status: "skipped", reason: "no_live_release" | "no_migrations" | "migrations_unchanged" | "ci_session_unsupported" | "disabled" | "reviewed_plan" | "unsupported" }` (`migrations_unchanged`: every migration is already applied with an identical checksum — `plan.migrations.new` is empty — so nothing is rehearsed and a page-only redeploy ships in seconds; `ci_session_unsupported`: the plan was made by a CI session, which the gateway does not rehearse, so it commits directly). A failed rehearsal throws `Run402DeployError` with `code: "REHEARSAL_FAILED"` (the report is in `body.rehearsal`); nothing is committed. Pass `{ noRehearse: true }` to skip it. `onEvent` sees `rehearsal.started`, `rehearsal.finished`, and `rehearsal.skipped`.
|
|
734
|
+
Rehearsal is automatic inside `apply()` and `r.up()`: when the plan's `rehearsal.available` is true (migrations, and the project has a live release), the plan is rehearsed on a contained branch and committed only on a passing report, bound to the report's `required_plan`. The result carries `rehearsal: { status: "passed", report, operation_id, branch_project_id }`, or `{ status: "skipped", reason: "no_live_release" | "no_migrations" | "migrations_unchanged" | "ci_session_unsupported" | "disabled" | "reviewed_plan" | "unsupported" }` (`migrations_unchanged`: every migration is already applied with an identical checksum — `plan.migrations.new` is empty — so nothing is rehearsed and a page-only redeploy ships in seconds; `ci_session_unsupported`: the plan was made by a CI session, which the gateway does not rehearse, so it commits directly). A failed rehearsal throws `Run402DeployError` with `code: "REHEARSAL_FAILED"` (the report is in `body.rehearsal`); nothing is committed. Pass `{ noRehearse: true }` to skip it. The rehearsal runs on the gateway as an operation, not inside one request: the SDK starts it with `Prefer: respond-async` and polls the operation until its report is there, so a slow snapshot never holds a request open; a rehearsal whose gateway task stopped before it finished throws `OPERATION_INTERRUPTED` (retryable, `operationId` set, the branch it left in `body.details.branch_project_id`). `onEvent` sees `rehearsal.started`, the recorded `rehearsal.phase` events, `rehearsal.finished`, and `rehearsal.skipped`.
|
|
710
735
|
|
|
711
|
-
The primitive is still there for experts: `r.project(id).apply.rehearse(planId, { teardown })` rehearses an already-persisted plan without committing (a project with no live release rehearses on an EMPTY branch — never a refusal).
|
|
736
|
+
The primitive is still there for experts: `r.project(id).apply.rehearse(planId, { teardown })` rehearses an already-persisted plan without committing and polls its operation for the report (a project with no live release rehearses on an EMPTY branch — never a refusal).
|
|
712
737
|
|
|
713
738
|
Manual restore points are exposed as `r.snapshots` and the scoped `r.project(id).snapshots`. `restorePlan()` is the no-mutation loss-statement step; `restore()` requires the confirm token from the plan and performs the atomic offline-materialize-then-flip restore. Auth users/passkeys are restored only with `{ includeAuth: true }`; sessions and tokens are never restored. Give a restore point a name with `create(projectId, { label: "before engine upgrade", metadata })`; labels live outside the project's database, so they survive restores. `{ release: "snapshot" }` on both `restorePlan` and `restore` also puts back the release that was live at capture (and re-deploys every function that differs to its capture-time code). A deployed function can do all of this for its own project with the `@run402/functions` `snapshots` namespace and its service key.
|
|
714
739
|
|
|
@@ -1335,7 +1360,10 @@ The `Run402` class exposes focused namespaces. Click into the SDK source for ful
|
|
|
1335
1360
|
r.pay.fetch(url, init?, { maxUsdMicros?, idempotencyKey?, requireReceipt?, maxSats?, lightningPairing? }): Promise<PayFetchResult>
|
|
1336
1361
|
```
|
|
1337
1362
|
|
|
1338
|
-
Node automatically supplies the configured wallet/signer
|
|
1363
|
+
Node automatically supplies the configured wallet/signer and pays on its rail:
|
|
1364
|
+
x402 `exact` on Base, Lightning on the `lightning` rail, and an MPP Tempo charge
|
|
1365
|
+
in pathUSD on the `mpp` rail. The receipt names `protocol` (`x402` | `mpp`) and
|
|
1366
|
+
`method` (`exact` | `tempo`). Isomorphic hosts
|
|
1339
1367
|
may inject `payExecutor` in `Run402Options`; without one, unpriced URLs pass
|
|
1340
1368
|
through and a 402 fails locally with `PAYMENT_WALLET_UNFUNDED`.
|
|
1341
1369
|
|
|
@@ -1406,7 +1434,7 @@ demoteUser(id, email): Promise<void>
|
|
|
1406
1434
|
|
|
1407
1435
|
`r.projects.setRepoName(projectId, name)` sets or renames the project's per-org-unique, ADDRESS-form name (`POST /projects/v1/:id/repo-name`, repo-first-onramp design D6, task 4.2) — the `<name>` half of `run402::<org-slug>/<name>` — and returns `{ project_id, repo_name, previous_repo_name }`. Distinct from `rename` above (the free-text display name, unchanged): the address-form name is charset-restricted (`[a-z0-9-]`, ≤63 chars) and per-org-unique. No fee, unlike the org-slug claim. Same authority as `rename`. Scoped form: `r.project(id).setRepoName(name)`.
|
|
1408
1436
|
|
|
1409
|
-
`r.projects.getUsage(id)`
|
|
1437
|
+
`r.projects.getUsage(id)` (`GET /projects/v1/admin/:project_id/usage`, service key) returns a `UsageReport`: `project_id`, `tier`, `org_id` (`| null`), `api_calls`, `api_calls_limit`, `storage_bytes`, `storage_limit_bytes`, `storage_limit` (human string, e.g. `"250 MB"`), `status` (the derived effective status), `lease_expires_at`, and `lease_perpetual`. `lease_expires_at` is the owning organization's ISO-8601 lease expiry, and `null` when the lease is perpetual (`lease_perpetual: true`) or the project has no organization; `lease_perpetual` is `false` otherwise. The lease fields match `r.tier.status()`.
|
|
1410
1438
|
|
|
1411
1439
|
### `r.project(id).apply`
|
|
1412
1440
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "run402-mcp",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.122.1",
|
|
4
4
|
"packageManager": "npm@11.19.0",
|
|
5
5
|
"mcpName": "com.run402/mcp",
|
|
6
6
|
"description": "MCP server for Run402 — full-stack backend infrastructure for AI agents: Postgres, auth, storage, serverless functions and atomic deploys. Paid with x402/MPP. Includes $0.03 image generation.",
|
|
@@ -32,10 +32,10 @@
|
|
|
32
32
|
"test:skill": "node scripts/build-agent-skills-index.mjs --check && node --test --import tsx SKILL.test.ts buzz/setup.test.mjs buzz/helper.test.mjs buzz/package.test.mjs scripts/build-agent-skills-index.test.mjs",
|
|
33
33
|
"test:vault-surface": "node scripts/build-vault-surface.mjs --check && node --test scripts/build-vault-surface.test.mjs",
|
|
34
34
|
"test:buzz-installer": "node buzz/install-smoke.mjs",
|
|
35
|
-
"test:sync": "node --test --import tsx sync.test.ts examples/tenant-x402-wallet-stats/example.test.mjs examples/static-config-js/example.test.mjs",
|
|
35
|
+
"test:sync": "node --test --import tsx sync.test.ts scripts/types-node-engines.test.mjs examples/tenant-x402-wallet-stats/example.test.mjs examples/static-config-js/example.test.mjs",
|
|
36
36
|
"test:run402-app-schema-drift": "node scripts/check-run402-app-schema-drift.mjs",
|
|
37
37
|
"test:docs": "node scripts/check-typed-config-docs.mjs && npm run check:docs --workspace=@run402/sdk -- --skip-build && npm run test:docs:quality",
|
|
38
|
-
"test": "npm run build && node scripts/build-agent-skills-index.mjs --check && node scripts/build-vault-surface.mjs --check && node --experimental-test-module-mocks --test --import tsx SKILL.test.ts sync.test.ts buzz/setup.test.mjs buzz/helper.test.mjs buzz/package.test.mjs scripts/build-agent-skills-index.test.mjs scripts/build-agent-flat-docs.test.mjs scripts/build-vault-surface.test.mjs examples/tenant-x402-wallet-stats/example.test.mjs examples/static-config-js/example.test.mjs 'core/src/**/*.test.ts' 'sdk/src/**/*.test.ts' 'src/**/*.test.ts' && node --test cli-core-target.test.mjs mcp-vendored-sdk-imports.test.mjs scripts/publish-idempotent.test.mjs && node --experimental-test-module-mocks --test cli-up-argv.test.mjs cli-up-repo-compose.test.mjs cli-repos-surface.test.mjs cli-repos-naming.test.mjs cli-projects-vault-scaffold.test.mjs cli-identity-link.test.mjs cli-identity-link-matrix.test.mjs cli-redeem.test.mjs cli-rooms-context-session-key.test.mjs cli-messages-wait.test.mjs cli-rooms-invite-key-leak.test.mjs cli-rooms-join-arrival.test.mjs cli/lib/buzz.test.mjs && node --test cli-help-listing.test.mjs cli-module-references.test.mjs cli-output-contract.test.mjs cli-json-noop-contract.test.mjs cli-e2e.test.mjs cli-help.test.mjs cli-subscriptions-help.test.mjs cli-provision-active.test.mjs cli-typed-config-modes.test.mjs cli-argv.test.mjs cli-repos-naming.test.mjs cli-conventions-gate.test.mjs cli-doctor.test.mjs cli-rest-diagnostics.test.mjs cli-credentials.test.mjs paid-stack-deps.test.mjs settlement-disclosure.test.mjs cli-suggestions-gate.test.mjs cli-env.test.mjs cli-wallets.test.mjs cli-org.test.mjs cli-org-context.test.mjs cli-image-org.test.mjs cli-harness-context.test.mjs cli-ci.test.mjs cli-snapshots.test.mjs cli-deploy-ci.test.mjs cli-login-loopback.test.mjs cli-vault-remote-helper.test.mjs cli-vault-daemon.test.mjs cli-deploy-vault-lane.test.mjs cli/lib/buzz-doctor.test.mjs cli/lib/diagnostic-telemetry.test.mjs cli/lib/doctor-source-scan.test.mjs cli/lib/errors.test.mjs cli/lib/argparse.test.mjs cli/lib/path-lookup.test.mjs cli/lib/pay.test.mjs cli/lib/up.test.mjs cli/lib/deploy-rehearse-discovery.test.mjs cli/lib/update-check.test.mjs cli-bootstrap-next-actions.test.mjs cli-sdk-errors-room-invite-hint.test.mjs && npm run test:docs",
|
|
38
|
+
"test": "npm run build && node scripts/build-agent-skills-index.mjs --check && node scripts/build-vault-surface.mjs --check && node --experimental-test-module-mocks --test --import tsx SKILL.test.ts sync.test.ts buzz/setup.test.mjs buzz/helper.test.mjs buzz/package.test.mjs scripts/build-agent-skills-index.test.mjs scripts/build-agent-flat-docs.test.mjs scripts/build-vault-surface.test.mjs scripts/types-node-engines.test.mjs examples/tenant-x402-wallet-stats/example.test.mjs examples/static-config-js/example.test.mjs 'core/src/**/*.test.ts' 'sdk/src/**/*.test.ts' 'src/**/*.test.ts' && node --test cli-core-target.test.mjs mcp-vendored-sdk-imports.test.mjs scripts/publish-idempotent.test.mjs && node --experimental-test-module-mocks --test cli-up-argv.test.mjs cli-up-repo-compose.test.mjs cli-repos-surface.test.mjs cli-repos-naming.test.mjs cli-projects-vault-scaffold.test.mjs cli-identity-link.test.mjs cli-identity-link-matrix.test.mjs cli-redeem.test.mjs cli-rooms-context-session-key.test.mjs cli-messages-wait.test.mjs cli-rooms-invite-key-leak.test.mjs cli-rooms-join-arrival.test.mjs cli/lib/buzz.test.mjs && node --test cli-help-listing.test.mjs cli-module-references.test.mjs cli-output-contract.test.mjs cli-json-noop-contract.test.mjs cli-e2e.test.mjs cli-help.test.mjs cli-subscriptions-help.test.mjs cli-provision-active.test.mjs cli-typed-config-modes.test.mjs cli-argv.test.mjs cli-repos-naming.test.mjs cli-conventions-gate.test.mjs cli-doctor.test.mjs cli-rest-diagnostics.test.mjs cli-credentials.test.mjs paid-stack-deps.test.mjs settlement-disclosure.test.mjs cli-suggestions-gate.test.mjs cli-env.test.mjs cli-wallets.test.mjs cli-org.test.mjs cli-org-context.test.mjs cli-image-org.test.mjs cli-harness-context.test.mjs cli-ci.test.mjs cli-snapshots.test.mjs cli-deploy-ci.test.mjs cli-login-loopback.test.mjs cli-vault-remote-helper.test.mjs cli-vault-daemon.test.mjs cli-deploy-vault-lane.test.mjs cli/lib/buzz-doctor.test.mjs cli/lib/diagnostic-telemetry.test.mjs cli/lib/doctor-source-scan.test.mjs cli/lib/errors.test.mjs cli/lib/argparse.test.mjs cli/lib/path-lookup.test.mjs cli/lib/pay.test.mjs cli/lib/up.test.mjs cli/lib/deploy-rehearse-discovery.test.mjs cli/lib/update-check.test.mjs cli-bootstrap-next-actions.test.mjs cli-sdk-errors-room-invite-hint.test.mjs && npm run test:docs",
|
|
39
39
|
"test:e2e": "npm run build && node --test cli-core-target.test.mjs && node --experimental-test-module-mocks --test cli-repos-surface.test.mjs cli-repos-naming.test.mjs cli-up-repo-compose.test.mjs cli-projects-vault-scaffold.test.mjs cli-identity-link.test.mjs cli-identity-link-matrix.test.mjs cli-redeem.test.mjs cli-rooms-context-session-key.test.mjs cli-messages-wait.test.mjs cli-rooms-invite-key-leak.test.mjs cli-rooms-join-arrival.test.mjs && node --test cli-help-listing.test.mjs cli-module-references.test.mjs cli-output-contract.test.mjs cli-json-noop-contract.test.mjs cli-e2e.test.mjs cli-help.test.mjs cli-subscriptions-help.test.mjs cli-provision-active.test.mjs cli-typed-config-modes.test.mjs cli-argv.test.mjs cli-repos-naming.test.mjs cli-conventions-gate.test.mjs cli-doctor.test.mjs cli-rest-diagnostics.test.mjs cli-credentials.test.mjs paid-stack-deps.test.mjs settlement-disclosure.test.mjs cli-suggestions-gate.test.mjs cli-env.test.mjs cli-wallets.test.mjs cli-org.test.mjs cli-org-context.test.mjs cli-image-org.test.mjs cli-harness-context.test.mjs cli-ci.test.mjs cli-snapshots.test.mjs cli-deploy-ci.test.mjs cli-login-loopback.test.mjs cli-vault-remote-helper.test.mjs cli-vault-daemon.test.mjs cli-deploy-vault-lane.test.mjs cli/lib/buzz-doctor.test.mjs cli/lib/diagnostic-telemetry.test.mjs cli/lib/doctor-source-scan.test.mjs cli/lib/errors.test.mjs cli/lib/path-lookup.test.mjs cli/lib/up.test.mjs cli/lib/update-check.test.mjs cli-bootstrap-next-actions.test.mjs cli-sdk-errors-room-invite-hint.test.mjs",
|
|
40
40
|
"test:help": "npm run build && node --test cli-help.test.mjs",
|
|
41
41
|
"test:integration": "node --test --import tsx core/src/siwx-integration.integ.ts",
|
|
@@ -751,10 +751,12 @@
|
|
|
751
751
|
"mainnet",
|
|
752
752
|
"testnet",
|
|
753
753
|
"lightning",
|
|
754
|
-
"lightning-testnet"
|
|
754
|
+
"lightning-testnet",
|
|
755
|
+
"tempo",
|
|
756
|
+
"tempo-testnet"
|
|
755
757
|
]
|
|
756
758
|
},
|
|
757
|
-
"description": "Omit to accept production mainnet only. Include testnet explicitly for testnet payments. `lightning` / `lightning-testnet` sell for sats over x402 `exact` on `lnbtc`, settled to the org's Lightning receiver (`run402 orgs lightning-receiver set`)
|
|
759
|
+
"description": "Omit to accept production mainnet only. Include testnet explicitly for testnet payments. `lightning` / `lightning-testnet` sell for sats over x402 `exact` on `lnbtc`, settled to the org's Lightning receiver (`run402 orgs lightning-receiver set`). `tempo` / `tempo-testnet` also take an MPP Tempo charge in pathUSD on Tempo mainnet (chain 4217) / Moderato (42431), paid to the org's payout address. `receipt` cannot be combined with Lightning or Tempo networks."
|
|
758
760
|
}
|
|
759
761
|
}
|
|
760
762
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/namespaces/deploy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAwB3C,OAAO,KAAK,EACV,YAAY,EACZ,sBAAsB,EAQtB,WAAW,EACX,oBAAoB,EAEpB,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EACf,YAAY,EACZ,oBAAoB,EACpB,qBAAqB,EACrB,mBAAmB,EACnB,wBAAwB,EACxB,uBAAuB,EAIvB,sBAAsB,EACtB,oBAAoB,EAUpB,iBAAiB,EAGjB,YAAY,EACZ,cAAc,EACd,aAAa,EACb,kBAAkB,EAClB,gBAAgB,EAChB,2BAA2B,EAC3B,uBAAuB,EACvB,WAAW,EACX,oBAAoB,EACpB,mBAAmB,EACnB,kBAAkB,EAGlB,YAAY,EAEb,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/namespaces/deploy.ts"],"names":[],"mappings":"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"}
|
|
@@ -33,6 +33,9 @@ const COMMIT_POLL_INITIAL_MS = 1_000;
|
|
|
33
33
|
const COMMIT_POLL_MAX_MS = 30_000;
|
|
34
34
|
const COMMIT_POLL_BACKOFF_AFTER_MS = 30_000;
|
|
35
35
|
const COMMIT_POLL_TIMEOUT_MS = 10 * 60 * 1000;
|
|
36
|
+
const REHEARSAL_POLL_INITIAL_MS = 1_000;
|
|
37
|
+
const REHEARSAL_POLL_MAX_MS = 10_000;
|
|
38
|
+
const REHEARSAL_POLL_TIMEOUT_MS = 30 * 60 * 1000;
|
|
36
39
|
const APPLY_RETRY_DEFAULT_MAX_RETRIES = 2;
|
|
37
40
|
const APPLY_RETRY_BASE_DELAY_MS = 250;
|
|
38
41
|
const APPLY_RETRY_MAX_DELAY_MS = 2_000;
|
|
@@ -221,25 +224,7 @@ export class Deploy {
|
|
|
221
224
|
const body = {};
|
|
222
225
|
if (opts.teardown !== undefined)
|
|
223
226
|
body.teardown = opts.teardown;
|
|
224
|
-
|
|
225
|
-
return await this.client.request(`/apply/v1/plans/${encodeURIComponent(planId)}/rehearse`, {
|
|
226
|
-
method: "POST",
|
|
227
|
-
body,
|
|
228
|
-
...(opts.project
|
|
229
|
-
? {
|
|
230
|
-
authMeta: {
|
|
231
|
-
method: "deploy.rehearse",
|
|
232
|
-
capability: "project.deploy",
|
|
233
|
-
target: { project_id: opts.project },
|
|
234
|
-
},
|
|
235
|
-
}
|
|
236
|
-
: {}),
|
|
237
|
-
context: "rehearsing deploy plan",
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
catch (err) {
|
|
241
|
-
throw translateDeployError(err, "rehearsal", planId, null);
|
|
242
|
-
}
|
|
227
|
+
return await requestRehearsal(this.client, planId, body, opts.project);
|
|
243
228
|
}
|
|
244
229
|
/**
|
|
245
230
|
* Resume an operation in `schema_settling` or `activation_pending`. The
|
|
@@ -610,18 +595,7 @@ async function rehearseBeforeCommit(client, plan, planId, project, opts, emit) {
|
|
|
610
595
|
if (unchanged)
|
|
611
596
|
return skip(unchanged);
|
|
612
597
|
emit({ type: "rehearsal.started", planId });
|
|
613
|
-
|
|
614
|
-
try {
|
|
615
|
-
rehearsed = await client.request(`/apply/v1/plans/${encodeURIComponent(planId)}/rehearse`, {
|
|
616
|
-
method: "POST",
|
|
617
|
-
body: {},
|
|
618
|
-
authMeta: { method: "deploy.rehearse", capability: "project.deploy", target: { project_id: project } },
|
|
619
|
-
context: "rehearsing deploy plan",
|
|
620
|
-
});
|
|
621
|
-
}
|
|
622
|
-
catch (err) {
|
|
623
|
-
throw translateDeployError(err, "rehearsal", planId, null);
|
|
624
|
-
}
|
|
598
|
+
const rehearsed = await requestRehearsal(client, planId, {}, project, emit);
|
|
625
599
|
const report = rehearsed.report;
|
|
626
600
|
emit({
|
|
627
601
|
type: "rehearsal.finished",
|
|
@@ -653,6 +627,85 @@ async function rehearseBeforeCommit(client, plan, planId, project, opts, emit) {
|
|
|
653
627
|
...(bound ? { requiredPlan: { planId: bound.plan_id, planFingerprint: bound.plan_fingerprint } } : {}),
|
|
654
628
|
};
|
|
655
629
|
}
|
|
630
|
+
/**
|
|
631
|
+
* Start a rehearsal and return its report. The gateway runs a rehearsal as an
|
|
632
|
+
* operation, detached from the request (a snapshot can take minutes). With a
|
|
633
|
+
* project to poll as, the request asks for the asynchronous shape
|
|
634
|
+
* (`Prefer: respond-async`), gets the operation at once, and polls it until
|
|
635
|
+
* the report is there, relaying its recorded `rehearsal.phase` events; every
|
|
636
|
+
* failure from then on carries the rehearsal's operation id. A gateway that
|
|
637
|
+
* answers with the report inline is used as is, and without a project the
|
|
638
|
+
* response waits for the report.
|
|
639
|
+
*/
|
|
640
|
+
async function requestRehearsal(client, planId, body, project, emit) {
|
|
641
|
+
let started;
|
|
642
|
+
try {
|
|
643
|
+
started = await client.request(`/apply/v1/plans/${encodeURIComponent(planId)}/rehearse`, {
|
|
644
|
+
method: "POST",
|
|
645
|
+
body,
|
|
646
|
+
...(project
|
|
647
|
+
? {
|
|
648
|
+
headers: { Prefer: "respond-async" },
|
|
649
|
+
authMeta: {
|
|
650
|
+
method: "deploy.rehearse",
|
|
651
|
+
capability: "project.deploy",
|
|
652
|
+
target: { project_id: project },
|
|
653
|
+
},
|
|
654
|
+
}
|
|
655
|
+
: {}),
|
|
656
|
+
context: "rehearsing deploy plan",
|
|
657
|
+
});
|
|
658
|
+
}
|
|
659
|
+
catch (err) {
|
|
660
|
+
throw translateDeployError(err, "rehearsal", planId, null);
|
|
661
|
+
}
|
|
662
|
+
if (started.report || !project)
|
|
663
|
+
return started;
|
|
664
|
+
return await pollRehearsal(client, planId, started.operation_id, project, emit);
|
|
665
|
+
}
|
|
666
|
+
async function pollRehearsal(client, planId, operationId, project, emit) {
|
|
667
|
+
const pollUrl = `/apply/v1/operations/${encodeURIComponent(operationId)}`;
|
|
668
|
+
const headers = await apikeyHeaders(client, project);
|
|
669
|
+
const start = Date.now();
|
|
670
|
+
let interval = REHEARSAL_POLL_INITIAL_MS;
|
|
671
|
+
let eventCursor = null;
|
|
672
|
+
let eventsSupported = Boolean(emit);
|
|
673
|
+
for (;;) {
|
|
674
|
+
await sleep(interval);
|
|
675
|
+
let snapshot;
|
|
676
|
+
try {
|
|
677
|
+
// A poll lost to a 502/503/504 (a gateway rollout) says nothing about
|
|
678
|
+
// the rehearsal, which keeps running on the gateway; read it again.
|
|
679
|
+
snapshot = await requestWithTransientRetry(() => client.request(pollUrl, { headers, context: "polling rehearsal operation" }));
|
|
680
|
+
}
|
|
681
|
+
catch (err) {
|
|
682
|
+
throw translateDeployError(err, "rehearsal", planId, operationId);
|
|
683
|
+
}
|
|
684
|
+
if (emit && eventsSupported) {
|
|
685
|
+
const recorded = await emitRecordedOperationEvents(client, operationId, headers, eventCursor, emit);
|
|
686
|
+
eventsSupported = recorded.supported;
|
|
687
|
+
eventCursor = recorded.cursor;
|
|
688
|
+
}
|
|
689
|
+
if (TERMINAL_STATUSES.includes(snapshot.status)) {
|
|
690
|
+
if (snapshot.rehearsal_report) {
|
|
691
|
+
return { operation_id: operationId, status: snapshot.status, poll_url: pollUrl, report: snapshot.rehearsal_report };
|
|
692
|
+
}
|
|
693
|
+
throw translateGatewayError(snapshot.error, "rehearsal", planId, operationId);
|
|
694
|
+
}
|
|
695
|
+
if (Date.now() - start > REHEARSAL_POLL_TIMEOUT_MS) {
|
|
696
|
+
throw new Run402DeployError(`Timed out waiting for rehearsal operation ${operationId} to finish`, {
|
|
697
|
+
code: "INTERNAL_ERROR",
|
|
698
|
+
phase: "rehearsal",
|
|
699
|
+
retryable: true,
|
|
700
|
+
operationId,
|
|
701
|
+
planId,
|
|
702
|
+
status: 504,
|
|
703
|
+
context: "polling rehearsal",
|
|
704
|
+
});
|
|
705
|
+
}
|
|
706
|
+
interval = Math.min(Math.floor(interval * 1.5), REHEARSAL_POLL_MAX_MS);
|
|
707
|
+
}
|
|
708
|
+
}
|
|
656
709
|
/**
|
|
657
710
|
* `"migrations_unchanged"` when the plan carries modern migration buckets and
|
|
658
711
|
* none are new (all noop); `"no_migrations"` when the buckets are both empty;
|
|
@@ -2904,6 +2957,9 @@ function validateRoutePricing(pricing, resource, targetType) {
|
|
|
2904
2957
|
if (obj.receipt === "on_fulfillment" && hasLightning) {
|
|
2905
2958
|
throw invalidRouteSpec(`ReleaseSpec.${resource}.pricing.receipt covers EVM entries only; merchant evidence is not issued for Lightning networks`, `${resource}.pricing.receipt`);
|
|
2906
2959
|
}
|
|
2960
|
+
if (obj.receipt === "on_fulfillment" && networks.some((network) => network === "tempo" || network === "tempo-testnet")) {
|
|
2961
|
+
throw invalidRouteSpec(`ReleaseSpec.${resource}.pricing.receipt covers x402 EVM entries only; merchant evidence is not issued for Tempo`, `${resource}.pricing.receipt`);
|
|
2962
|
+
}
|
|
2907
2963
|
}
|
|
2908
2964
|
/** The declared pricing networks, validated; `["mainnet"]` when omitted. */
|
|
2909
2965
|
function validateRoutePricingNetworks(networks, resource) {
|