@visa/cli 5.0.0-rc.409 → 5.0.0-rc.411

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.
@@ -1,22 +1,4 @@
1
1
  export const DEFAULT_RUNTIME_READINESS_TIMEOUT_MS = 60_000
2
- const COMMERCE_RUNTIMES = new Set(['openclaw', 'hermes'])
3
-
4
- /** Fixed argv only: callers cannot substitute a package, command, or script path. */
5
- export function commerceSkillArgs(env = process.env, check = false) {
6
- const runtime = env.VISA_COMMERCE_RUNTIME || ''
7
- if (runtime && !COMMERCE_RUNTIMES.has(runtime)) {
8
- throw new Error('VISA_COMMERCE_RUNTIME must be openclaw or hermes')
9
- }
10
- return [
11
- 'agent',
12
- 'skill',
13
- '--commerce',
14
- ...(runtime ? ['--runtime', runtime] : []),
15
- ...(check ? ['--check'] : []),
16
- '--format',
17
- 'json',
18
- ]
19
- }
20
2
 
21
3
  function isPlainRecord(value) {
22
4
  return typeof value === 'object' && value !== null && !Array.isArray(value)
@@ -57,32 +39,6 @@ export function parseRuntimeReadiness(raw) {
57
39
  }
58
40
  }
59
41
 
60
- export function assertSameShopifyRuntime(actual, expected) {
61
- if (!isPlainRecord(actual)) {
62
- throw new Error('loaded runtime readiness must attest the named shopify-ucp MCP')
63
- }
64
- if (actual.serverName !== 'shopify-ucp') {
65
- throw new Error('loaded runtime readiness did not attest the canonical shopify-ucp mount')
66
- }
67
- for (const field of ['installedVersion', 'toolSchemaFingerprint', 'command']) {
68
- if (actual[field] !== expected[field]) {
69
- throw new Error(`loaded Shopify UCP ${field} does not match the certified local runtime`)
70
- }
71
- }
72
- if (
73
- !Array.isArray(actual.args) ||
74
- actual.args.length !== expected.args.length ||
75
- !actual.args.every((value, index) => value === expected.args[index])
76
- ) {
77
- throw new Error('loaded Shopify UCP command arguments do not match the certified local runtime')
78
- }
79
- if (!Array.isArray(actual.blockedTools) || !actual.blockedTools.includes('checkout_complete')) {
80
- throw new Error(
81
- 'loaded Shopify UCP runtime does not attest the checkout completion deny boundary'
82
- )
83
- }
84
- }
85
-
86
42
  export function resolveRuntimeUpdateConfig(env = process.env) {
87
43
  const restartCommand = env.RUNTIME_RESTART_COMMAND || env.OPENCLAW_RESTART_COMMAND || ''
88
44
  const readinessCommand = env.RUNTIME_READINESS_COMMAND || ''
@@ -25,8 +25,6 @@ import { basename, dirname, isAbsolute, join, relative, resolve } from 'node:pat
25
25
  import { fileURLToPath } from 'node:url'
26
26
  import {
27
27
  assertSameRuntimeBuild,
28
- assertSameShopifyRuntime,
29
- commerceSkillArgs,
30
28
  parseRuntimeReadiness,
31
29
  resolveRuntimeUpdateConfig,
32
30
  runtimeReadinessExecOptions,
@@ -656,105 +654,34 @@ export function recoverInterruptedActivation(managedDir, logger = console) {
656
654
  return true
657
655
  }
658
656
 
659
- function runCommerceInstall(releaseDir, env, execFile, timeout) {
657
+ export function certifyLocalBinary(
658
+ releaseDir,
659
+ env = process.env,
660
+ execFile = execFileSync,
661
+ timeout = DEFAULT_COMMAND_TIMEOUT_MS
662
+ ) {
660
663
  try {
661
- execFile(visaBinary(releaseDir), commerceSkillArgs(env), {
662
- stdio: ['ignore', 'pipe', 'pipe'],
663
- timeout,
664
- })
665
- } catch (error) {
666
- throw new ManagedRuntimeUpdateError(
667
- 'rebuild_or_remount_required',
668
- 'the managed runtime could not refresh its installer-owned commerce mount; rebuild or remount it',
669
- { cause: error }
670
- )
671
- }
672
- }
673
-
674
- function certifyLocalBinary(releaseDir, execFile, timeout) {
675
- const rawCapabilities = execFile(visaBinary(releaseDir), ['capabilities', '--format', 'json'], {
676
- encoding: 'utf8',
677
- stdio: ['ignore', 'pipe', 'pipe'],
678
- timeout,
679
- })
680
- const capabilities = parseJson(rawCapabilities, 'visa capabilities')
681
- const build = capabilities?.data?.build ?? capabilities?.build
682
- if (typeof build?.version !== 'string' || typeof build?.targetEnvironment !== 'string') {
683
- throw new ManagedRuntimeUpdateError(
684
- 'local_readiness_failed',
685
- 'local capabilities omitted build identity'
686
- )
687
- }
688
-
689
- return {
690
- version: build.version,
691
- targetEnvironment: build.targetEnvironment,
692
- minCompatibleVersion: build.minCompatibleVersion || null,
693
- }
694
- }
695
-
696
- function certifyLocalCommerce(releaseDir, env, execFile, timeout) {
697
- let rawCommerce
698
- try {
699
- rawCommerce = execFile(visaBinary(releaseDir), commerceSkillArgs(env, true), {
664
+ const entry = join(releaseDir, 'node_modules', '@visa', 'cli', 'dist', 'mcp-server', 'index.js')
665
+ const raw = execFile(process.execPath, [entry, '--self-check'], {
700
666
  encoding: 'utf8',
701
667
  stdio: ['ignore', 'pipe', 'pipe'],
702
668
  timeout,
669
+ env,
703
670
  })
671
+ if (JSON.parse(raw)?.ok !== true) throw new Error('self-check did not succeed')
672
+ const build = parseRuntimeReadiness(raw)
673
+ return {
674
+ version: build.version,
675
+ targetEnvironment: build.targetEnvironment,
676
+ minCompatibleVersion: null,
677
+ }
704
678
  } catch (error) {
705
679
  throw new ManagedRuntimeUpdateError(
706
- 'commerce_runtime_not_ready',
707
- 'local Shopify UCP runtime readiness command failed',
680
+ 'local_readiness_failed',
681
+ 'staged MCP server failed its self-check',
708
682
  { cause: error }
709
683
  )
710
684
  }
711
- const commerce = parseJson(rawCommerce, 'commerce readiness')
712
- if (
713
- commerce?.localBundleReady !== true ||
714
- commerce?.shopifyRuntime?.status !== 'ready' ||
715
- typeof commerce?.shopifyRuntime?.toolSchemaFingerprint !== 'string'
716
- ) {
717
- throw new ManagedRuntimeUpdateError(
718
- 'commerce_runtime_not_ready',
719
- 'local Shopify UCP runtime did not certify its required tools'
720
- )
721
- }
722
- return commerce.shopifyRuntime
723
- }
724
-
725
- function assessLocalCommerce(releaseDir, env, execFile, timeout) {
726
- try {
727
- runCommerceInstall(releaseDir, env, execFile, timeout)
728
- return {
729
- commerceReady: true,
730
- commerceActionRequired: null,
731
- shopifyRuntime: certifyLocalCommerce(releaseDir, env, execFile, timeout),
732
- }
733
- } catch (error) {
734
- const code =
735
- error instanceof ManagedRuntimeUpdateError && error.code === 'rebuild_or_remount_required'
736
- ? 'rebuild_or_remount_required'
737
- : 'commerce_runtime_not_ready'
738
- return {
739
- commerceReady: false,
740
- commerceActionRequired: code,
741
- shopifyRuntime: null,
742
- }
743
- }
744
- }
745
-
746
- function assessLoadedCommerce(loaded, localCommerce) {
747
- if (!localCommerce.commerceReady) return localCommerce
748
- try {
749
- assertSameShopifyRuntime(loaded.shopifyRuntime, localCommerce.shopifyRuntime)
750
- return localCommerce
751
- } catch {
752
- return {
753
- commerceReady: false,
754
- commerceActionRequired: 'commerce_runtime_not_ready',
755
- shopifyRuntime: null,
756
- }
757
- }
758
685
  }
759
686
 
760
687
  function restartSupervisor(config, dependencies, operation = 'restart') {
@@ -917,7 +844,7 @@ export async function runManagedRuntimeUpdate(env = process.env, dependencies =
917
844
  )
918
845
  targetRelease = stageExactRelease(config, dependencies)
919
846
  const execFile = dependencies.execFileSync ?? execFileSync
920
- const local = certifyLocalBinary(targetRelease, execFile, config.commandTimeoutMs)
847
+ const local = certifyLocalBinary(targetRelease, env, execFile, config.commandTimeoutMs)
921
848
  if (local.version !== config.exactVersion) {
922
849
  throw new ManagedRuntimeUpdateError(
923
850
  'installed_version_mismatch',
@@ -930,27 +857,25 @@ export async function runManagedRuntimeUpdate(env = process.env, dependencies =
930
857
  `staged CLI targets ${local.targetEnvironment}, expected ${config.expectedEnvironment}`
931
858
  )
932
859
  }
933
- const localCommerce = assessLocalCommerce(targetRelease, env, execFile, config.commandTimeoutMs)
934
-
935
860
  const releaseIntegrity = releaseTreeIntegrity(targetRelease)
936
861
  writePendingTransaction(config, targetRelease, previous, correlationId)
937
862
  activateRelease(config.managedDir, targetRelease)
938
863
  activated = true
939
864
  const loaded = restartAndReadLoaded(config, dependencies)
940
865
  assertSameRuntimeBuild(loaded, local)
941
- const commerce = assessLoadedCommerce(loaded, localCommerce)
942
- if (!commerce.commerceReady) {
943
- structuredLog(
944
- 'commerce_action_required',
945
- {
946
- correlationId,
947
- version: local.version,
948
- code: commerce.commerceActionRequired,
949
- checkoutBlocked: true,
950
- },
951
- dependencies.logger
952
- )
953
- }
866
+ // Preserve the receipt contract without invoking the retired Shopify installer.
867
+ // Binary readiness never establishes payment readiness.
868
+ const commerceActionRequired = 'commerce_runtime_removed'
869
+ structuredLog(
870
+ 'commerce_action_required',
871
+ {
872
+ correlationId,
873
+ version: local.version,
874
+ code: commerceActionRequired,
875
+ checkoutBlocked: true,
876
+ },
877
+ dependencies.logger
878
+ )
954
879
 
955
880
  const receipt = {
956
881
  ok: true,
@@ -962,19 +887,10 @@ export async function runManagedRuntimeUpdate(env = process.env, dependencies =
962
887
  releaseDir: targetRelease,
963
888
  previousVersion: previous?.receipt.version ?? null,
964
889
  releaseIntegrity,
965
- commerceReady: commerce.commerceReady,
966
- checkoutBlocked: !commerce.commerceReady,
967
- commerceActionRequired: commerce.commerceActionRequired,
968
- shopifyRuntime: commerce.commerceReady
969
- ? {
970
- serverName: 'shopify-ucp',
971
- installedVersion: commerce.shopifyRuntime.installedVersion,
972
- toolSchemaFingerprint: commerce.shopifyRuntime.toolSchemaFingerprint,
973
- command: commerce.shopifyRuntime.command,
974
- args: commerce.shopifyRuntime.args,
975
- blockedTools: commerce.shopifyRuntime.blockedTools,
976
- }
977
- : null,
890
+ commerceReady: false,
891
+ checkoutBlocked: true,
892
+ commerceActionRequired,
893
+ shopifyRuntime: null,
978
894
  durationMs: Date.now() - startedAt,
979
895
  }
980
896
  try {