@fased/fased 0.1.68 → 0.1.69

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.
Files changed (103) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +20 -22
  3. package/config/sat-runtime.env +6 -2
  4. package/config/signer-protocol-v2.json +6 -0
  5. package/dist/agents/tools/wallet-action-tool.js +2 -0
  6. package/dist/agents/tools/wallet-tool.js +5 -3
  7. package/dist/brand.js +1 -1
  8. package/dist/build-info.json +3 -3
  9. package/dist/canvas-host/a2ui/.bundle.hash +1 -1
  10. package/dist/cli/program/register.wallet.js +88 -5
  11. package/dist/commands/wallet.js +842 -57
  12. package/dist/config/sat-runtime-ids.js +6 -1
  13. package/dist/control-ui/assets/{app-DyPTS0oM.js → app-BLFLoFPk.js} +8 -8
  14. package/dist/control-ui/assets/{federation-DgA9e-Pn.js → federation-SGMAnM_8.js} +2 -2
  15. package/dist/control-ui/assets/{index-Cu13yYHr.js → index-S88kp5ZQ.js} +3 -3
  16. package/dist/control-ui/assets/{mining-Dg-3ll0F.js → mining-ClI8RW4u.js} +2 -2
  17. package/dist/control-ui/assets/{wallet-ByKBcYhm.js → wallet-CRIhDQbW.js} +201 -116
  18. package/dist/control-ui/index.html +1 -1
  19. package/dist/control-ui/version.json +1 -1
  20. package/dist/gateway/server-http.js +46 -9
  21. package/dist/mining/mainnet-sync.js +67 -5
  22. package/dist/operator/operator-readiness.js +1 -1
  23. package/dist/plugin-sdk/{audio-preflight-_FVQjR1r.js → audio-preflight-CS7Q_7-R.js} +2 -2
  24. package/dist/plugin-sdk/channel-plugin-common.d.ts +2 -2
  25. package/dist/plugin-sdk/{chunk-items-LH4uKSnh.js → chunk-items-BLBZNORg.js} +1 -1
  26. package/dist/plugin-sdk/command-status.js +2 -2
  27. package/dist/plugin-sdk/{config-schema-DjU_uD-6.js → config-schema-BiBOUW89.js} +255 -47
  28. package/dist/plugin-sdk/device-pair.d.ts +1 -1
  29. package/dist/plugin-sdk/discord.d.ts +4 -4
  30. package/dist/plugin-sdk/index.d.ts +16 -16
  31. package/dist/plugin-sdk/index.js +2 -2
  32. package/dist/plugin-sdk/{monitor-DUMMbG4h.js → monitor-WXdn4mR-.js} +4 -4
  33. package/dist/plugin-sdk/{monitor-DXIM16Hj.js → monitor-xzVAPbg2.js} +6 -6
  34. package/dist/plugin-sdk/{openresponses-http-C8lKwta1.js → openresponses-http-DnI1LFgq.js} +2 -2
  35. package/dist/plugin-sdk/{pairing-message-mKO92L-M.d.ts → pairing-message-CiTcdD6m.d.ts} +1 -1
  36. package/dist/plugin-sdk/provider-web-search-config-contract.d.ts +1 -1
  37. package/dist/plugin-sdk/{pw-ai-DJ_gTc4M.js → pw-ai-DZYLDC-S.js} +1 -1
  38. package/dist/plugin-sdk/{runtime-dependency-nup8niQL.js → runtime-dependency-DczkvPxn.js} +9 -9
  39. package/dist/plugin-sdk/sat-runtime.d.ts +89 -10
  40. package/dist/plugin-sdk/sat-runtime.js +2 -2
  41. package/dist/plugin-sdk/{slack-B-nOOLM0.js → slack-CkIRVDUK.js} +4 -4
  42. package/dist/plugin-sdk/slack.d.ts +4 -4
  43. package/dist/plugin-sdk/{sticker-cache-BLiId8Em.js → sticker-cache-Dpap5ce_.js} +2 -2
  44. package/dist/plugin-sdk/{telegram-actions-1X9A32Dn.js → telegram-actions-Cewdga8H.js} +3 -3
  45. package/dist/plugin-sdk/telegram.d.ts +4 -4
  46. package/dist/plugin-sdk/{tmp-fased-dir-BkpWlGUe.d.ts → tmp-fased-dir-BSEHc8MQ.d.ts} +2 -2
  47. package/dist/plugin-sdk/{types-DtCOO_hW.d.ts → types-BakzIzGN.d.ts} +1 -1
  48. package/dist/plugin-sdk/{types-B-zL9gSv.d.ts → types-CzF0YQqK.d.ts} +2 -2
  49. package/dist/plugin-sdk/{web-BvjNyYBz.js → web-DGWi7i3B.js} +2 -2
  50. package/dist/plugin-sdk/whatsapp.d.ts +9 -9
  51. package/dist/plugin-sdk/{zod-schema.providers-core-BCDlgtls.d.ts → zod-schema.providers-core-CIzCjXH9.d.ts} +63 -63
  52. package/dist/wallet/local-socket-signer-lifecycle.js +79 -3
  53. package/dist/wallet/local-socket-signer-protocol.js +70 -10
  54. package/dist/wallet/mining-wallet-retirement.js +256 -0
  55. package/dist/wallet/providers/local-socket-signer-adapter.js +2 -0
  56. package/dist/wallet/signer-protocol-v2.generated.js +6 -0
  57. package/dist/wallet/wallet-agent-selection.js +6 -10
  58. package/dist/wallet/wallet-provider-registry.js +70 -29
  59. package/dist/wallet/wallet-send-approvals.js +6 -2
  60. package/dist/wallet/wallet-status.js +56 -1
  61. package/dist/wizard/onboarding.js +32 -30
  62. package/dist/wizard/onboarding.wallet.js +10 -1
  63. package/extensions/acpx/package.json +1 -1
  64. package/extensions/bluebubbles/package.json +1 -1
  65. package/extensions/copilot-proxy/package.json +1 -1
  66. package/extensions/diagnostics-otel/package.json +1 -1
  67. package/extensions/fased-federation/package.json +1 -1
  68. package/extensions/google-gemini-cli-auth/package.json +1 -1
  69. package/extensions/imessage/package.json +1 -1
  70. package/extensions/irc/package.json +1 -1
  71. package/extensions/line/package.json +1 -1
  72. package/extensions/llm-task/package.json +1 -1
  73. package/extensions/lobster/package.json +1 -1
  74. package/extensions/matrix/CHANGELOG.md +6 -0
  75. package/extensions/matrix/package.json +1 -1
  76. package/extensions/mattermost/package.json +1 -1
  77. package/extensions/memory-core/package.json +2 -2
  78. package/extensions/memory-lancedb/package.json +1 -1
  79. package/extensions/minimax-portal-auth/package.json +1 -1
  80. package/extensions/msteams/CHANGELOG.md +6 -0
  81. package/extensions/msteams/package.json +1 -1
  82. package/extensions/nextcloud-talk/package.json +1 -1
  83. package/extensions/nostr/CHANGELOG.md +6 -0
  84. package/extensions/nostr/package.json +1 -1
  85. package/extensions/open-prose/package.json +1 -1
  86. package/extensions/sat-mining/package.json +1 -1
  87. package/extensions/signal/package.json +1 -1
  88. package/extensions/synology-chat/package.json +1 -1
  89. package/extensions/tlon/package.json +1 -1
  90. package/extensions/twitch/CHANGELOG.md +6 -0
  91. package/extensions/twitch/package.json +1 -1
  92. package/extensions/voice-call/CHANGELOG.md +6 -0
  93. package/extensions/voice-call/package.json +1 -1
  94. package/extensions/zalo/CHANGELOG.md +6 -0
  95. package/extensions/zalo/package.json +1 -1
  96. package/extensions/zalouser/CHANGELOG.md +6 -0
  97. package/extensions/zalouser/package.json +1 -1
  98. package/install.sh +276 -103
  99. package/package.json +4 -3
  100. package/scripts/install-fased-signerd.sh +4 -8
  101. package/scripts/install-runtime-profile.sh +27 -0
  102. package/scripts/start-managed.sh +13 -1
  103. package/scripts/fased-signer-wallet-import-hosting.sh +0 -78
@@ -479,9 +479,6 @@ function upsertNamedWallet(params) {
479
479
  updatedAt: now
480
480
  };
481
481
  registry.wallets = [...registry.wallets.filter((entry) => entry.id !== next.id), next].toSorted((a, b) => a.createdAt.localeCompare(b.createdAt));
482
- if (!registry.defaultWalletId || !registry.wallets.some((wallet) => wallet.id === registry.defaultWalletId)) {
483
- registry.defaultWalletId = resolveWalletUserRole(next) === "agent" ? next.id : undefined;
484
- }
485
482
  writeWalletProviderRegistry(registry, env);
486
483
  return next;
487
484
  }
@@ -497,6 +494,10 @@ function deleteNamedWallet(params) {
497
494
  walletId,
498
495
  env
499
496
  });
497
+ const targetWallet = registry.wallets.find((wallet) => wallet.id === walletId);
498
+ if (resolveWalletUserRole(targetWallet) === "mining") {
499
+ throw new Error("Mining wallets cannot be deleted directly; use Retire and replace Mining wallet so signer acknowledgement precedes registry detachment");
500
+ }
500
501
  const before = registry.wallets.length;
501
502
  registry.wallets = registry.wallets.filter((entry) => entry.id !== walletId);
502
503
  for (const [agentId, assignedWalletId] of Object.entries(registry.assignments)) {
@@ -514,6 +515,50 @@ function deleteNamedWallet(params) {
514
515
  registry
515
516
  };
516
517
  }
518
+ function replaceRetiredMiningWallet(params) {
519
+ const env = params.env ?? process.env;
520
+ const registry = readWalletProviderRegistry(env);
521
+ const sourceWalletId = params.sourceWalletId.trim();
522
+ if (!/^sha256:[0-9a-f]{64}$/u.test(params.signerAcknowledgement.rotationId) || !/^sha256:[0-9a-f]{64}$/u.test(params.signerAcknowledgement.sourceRetiredPolicyHash) || !/^sha256:[0-9a-f]{64}$/u.test(params.signerAcknowledgement.successorPolicyHash) || params.signerAcknowledgement.successorPublicKey !== params.successor.addresses?.solana || params.successor.metadata?.rotationId !== params.signerAcknowledgement.rotationId || params.successor.metadata?.policyHash !== params.signerAcknowledgement.successorPolicyHash) {
523
+ throw new Error("signer retirement acknowledgement is missing or does not match the successor");
524
+ }
525
+ const sourceIndex = registry.wallets.findIndex((wallet) => wallet.id === sourceWalletId);
526
+ if (sourceIndex < 0) {
527
+ const existing = registry.wallets.find((wallet) => wallet.id === params.successor.id);
528
+ if (existing?.providerId === "local-socket-signer" && existing.addresses?.solana === params.successor.addresses?.solana && resolveWalletUserRole(existing) === "mining") {
529
+ return existing;
530
+ }
531
+ throw new Error("retired Mining source registration is missing");
532
+ }
533
+ const source = registry.wallets[sourceIndex];
534
+ if (resolveWalletUserRole(source) !== "mining") {
535
+ throw new Error("source registration is not the active Mining wallet");
536
+ }
537
+ if (params.successor.id === sourceWalletId || registry.wallets.some((wallet) => wallet.id === params.successor.id)) {
538
+ throw new Error("Mining successor registration must use a new wallet id");
539
+ }
540
+ assertNamedWalletDeletionSafe({
541
+ walletId: sourceWalletId,
542
+ env
543
+ });
544
+ const now = nowIso();
545
+ const successor = {
546
+ ...params.successor,
547
+ createdAt: now,
548
+ updatedAt: now
549
+ };
550
+ registry.wallets.splice(sourceIndex, 1, successor);
551
+ for (const [agentId, assignedWalletId] of Object.entries(registry.assignments)) {
552
+ if (assignedWalletId === sourceWalletId) {
553
+ delete registry.assignments[agentId];
554
+ }
555
+ }
556
+ if (registry.defaultWalletId === sourceWalletId) {
557
+ registry.defaultWalletId = undefined;
558
+ }
559
+ writeWalletProviderRegistry(registry, env);
560
+ return successor;
561
+ }
517
562
  function setAgentWalletAssignment(params) {
518
563
  const env = params.env ?? process.env;
519
564
  const registry = readWalletProviderRegistry(env);
@@ -527,9 +572,13 @@ function setAgentWalletAssignment(params) {
527
572
  writeWalletProviderRegistry(registry, env);
528
573
  return registry;
529
574
  }
530
- if (!registry.wallets.some((wallet) => wallet.id === walletId)) {
575
+ const wallet = registry.wallets.find((entry) => entry.id === walletId);
576
+ if (!wallet) {
531
577
  throw new Error("walletId does not exist");
532
578
  }
579
+ if (resolveWalletUserRole(wallet) !== "agent") {
580
+ throw new Error("only Agent wallets can be assigned to an Agent");
581
+ }
533
582
  registry.assignments[agentId] = walletId;
534
583
  writeWalletProviderRegistry(registry, env);
535
584
  return registry;
@@ -548,23 +597,9 @@ function setDefaultWallet(params) {
548
597
  throw new Error("walletId does not exist");
549
598
  }
550
599
  const purpose = resolveWalletUserRole(targetWallet);
551
- if (purpose && purpose !== "agent") {
552
- throw new Error("only Agent wallets can become the primary Agent fallback");
600
+ if (purpose !== "agent") {
601
+ throw new Error("only an explicit Agent wallet can become the Default Agent wallet fallback");
553
602
  }
554
- registry.wallets = registry.wallets.map((wallet) => {
555
- if (wallet.id !== walletId) {
556
- return wallet;
557
- }
558
- return {
559
- ...wallet,
560
- metadata: {
561
- ...wallet.metadata,
562
- role: "agent",
563
- purpose: "agent"
564
- },
565
- updatedAt: nowIso()
566
- };
567
- });
568
603
  registry.defaultWalletId = walletId;
569
604
  writeWalletProviderRegistry(registry, env);
570
605
  return registry;
@@ -588,12 +623,15 @@ function setNamedWalletRole(params) {
588
623
  },
589
624
  updatedAt: nowIso()
590
625
  } : wallet);
591
- if (params.role === "agent" && !registry.defaultWalletId) {
592
- registry.defaultWalletId = walletId;
626
+ if (params.role !== "agent" && registry.defaultWalletId === walletId) {
627
+ registry.defaultWalletId = undefined;
593
628
  }
594
- if (params.role === "vault" && registry.defaultWalletId === walletId) {
595
- const nextDefault = registry.wallets.find((wallet) => wallet.id !== walletId && resolveWalletUserRole(wallet) === "agent");
596
- registry.defaultWalletId = nextDefault?.id;
629
+ if (params.role !== "agent") {
630
+ for (const [agentId, assignedWalletId] of Object.entries(registry.assignments)) {
631
+ if (assignedWalletId === walletId) {
632
+ delete registry.assignments[agentId];
633
+ }
634
+ }
597
635
  }
598
636
  writeWalletProviderRegistry(registry, env);
599
637
  return registry;
@@ -603,7 +641,8 @@ function resolveWalletSelectionForAgent(params) {
603
641
  const registry = readWalletProviderRegistry(env);
604
642
  const directAgent = params.agentId?.trim();
605
643
  const directWalletId = directAgent ? registry.assignments[directAgent] : undefined;
606
- const walletId = directWalletId ?? registry.defaultWalletId;
644
+ const skillWalletId = params.skillWalletId?.trim();
645
+ const walletId = skillWalletId ?? directWalletId ?? registry.defaultWalletId;
607
646
  if (!walletId) {
608
647
  return {};
609
648
  }
@@ -614,7 +653,8 @@ function resolveWalletSelectionForAgent(params) {
614
653
  return {
615
654
  walletId: wallet.id,
616
655
  walletName: wallet.name,
617
- providerId: wallet.providerId
656
+ providerId: wallet.providerId,
657
+ source: skillWalletId ? "skill" : directWalletId ? "agent" : "default"
618
658
  };
619
659
  }
620
660
  function resolveWalletSelection(params) {
@@ -676,16 +716,17 @@ function resolveWalletSelection(params) {
676
716
  }
677
717
  const fallback = resolveWalletSelectionForAgent({
678
718
  agentId: params.agentId,
719
+ skillWalletId: params.skillWalletId,
679
720
  env
680
721
  });
681
722
  if (fallback.walletId || fallback.providerId) {
682
723
  return {
683
724
  ...fallback,
684
- source: "fallback"
725
+ source: fallback.source ?? "fallback"
685
726
  };
686
727
  }
687
728
  return { source: "none" };
688
729
  }
689
730
 
690
731
  //#endregion
691
- export { WALLET_PROVIDER_IDS, checkNamedWalletDeletionSafety, deleteNamedWallet, normalizeWalletUserRole, readWalletProviderRegistry, resolveWalletSelection, resolveWalletUserRole, setAgentWalletAssignment, setDefaultWallet, setNamedWalletRole, setWalletProviderEnabled, setWalletProvidersEnabled, upsertNamedWallet };
732
+ export { WALLET_PROVIDER_IDS, checkNamedWalletDeletionSafety, deleteNamedWallet, normalizeWalletUserRole, readWalletProviderRegistry, replaceRetiredMiningWallet, resolveWalletSelection, resolveWalletUserRole, setAgentWalletAssignment, setDefaultWallet, setNamedWalletRole, setWalletProviderEnabled, setWalletProvidersEnabled, upsertNamedWallet, writeWalletProviderRegistry };
@@ -2126,7 +2126,11 @@ async function approveWalletSendRequest(params) {
2126
2126
  request
2127
2127
  };
2128
2128
  }
2129
- if (storedReview.state === "prepared" && !params.reviewAuthorization) {
2129
+ const controlUIAuthorization = storedReview.state === "prepared" && !params.reviewAuthorization && (storedReview.intentType === "solana.nativeTransfer" || storedReview.intentType === "solana.splTransferChecked") ? {
2130
+ type: "control-ui",
2131
+ proof: { proofId: storedReview.nonce }
2132
+ } : undefined;
2133
+ if (storedReview.state === "prepared" && !params.reviewAuthorization && !controlUIAuthorization) {
2130
2134
  if (claim.recovered && request.status === "executing") {
2131
2135
  await withApprovalMutationLock(env, () => {
2132
2136
  file = loadFile(env);
@@ -2151,7 +2155,7 @@ async function approveWalletSendRequest(params) {
2151
2155
  request
2152
2156
  };
2153
2157
  }
2154
- const executionAuthorization = storedReview.state === "prepared" ? params.reviewAuthorization : undefined;
2158
+ const executionAuthorization = storedReview.state === "prepared" ? params.reviewAuthorization ?? controlUIAuthorization : undefined;
2155
2159
  let executed;
2156
2160
  try {
2157
2161
  executed = await provider.executeSignerReview({
@@ -1,10 +1,12 @@
1
1
  import { loadConfig } from "../config/io.js";
2
2
  import "../config/config.js";
3
- import { ensureWalletStateDir, resolveWalletRuntimeConfig, resolveWalletStatePaths } from "./wallet-runtime-config.js";
3
+ import { ensureWalletStateDir, resolveLocalSignerSocketPath, resolveWalletRuntimeConfig, resolveWalletStatePaths } from "./wallet-runtime-config.js";
4
4
  import { readWalletProviderRegistry } from "./wallet-provider-registry.js";
5
5
  import { resolveWalletPolicyConfig } from "./wallet-policy.js";
6
6
  import { redactWalletDiagnosticText, walletDiagnosticErrorMessage, walletDiagnosticErrorString } from "./wallet-redaction.js";
7
7
  import { createWalletProviderAdapter, resolveWalletProviderId } from "./wallet-provider-resolver.js";
8
+ import { readSignerOwnedWalletReadiness } from "./local-socket-signer-lifecycle.js";
9
+ import { normalizeNativeSignerWalletId } from "./native-signer-wallet-id.js";
8
10
  import { readWalletApprovalAuthSnapshot } from "./wallet-approval-auth.js";
9
11
 
10
12
  //#region src/wallet/wallet-status.ts
@@ -26,6 +28,7 @@ async function readWalletStatusSnapshot(params) {
26
28
  const statePaths = resolveWalletStatePaths(effectiveEnv);
27
29
  const approvalAuth = readWalletApprovalAuthSnapshot(effectiveEnv, cfg);
28
30
  const checkedAt = new Date().toISOString();
31
+ const registeredWallets = params?.walletId ? providerRegistry.wallets.filter((wallet) => wallet.id === params.walletId) : providerRegistry.wallets;
29
32
  let providerHealth = {
30
33
  ok: false,
31
34
  provider: providerId,
@@ -77,6 +80,58 @@ async function readWalletStatusSnapshot(params) {
77
80
  summary: "Real-chain settlement depends on the configured wallet provider and RPC connectivity."
78
81
  },
79
82
  chains: resolved.chains,
83
+ wallets: await Promise.all(registeredWallets.map(async (wallet) => {
84
+ if (wallet.providerId !== "local-socket-signer") {
85
+ return {
86
+ id: wallet.id,
87
+ name: wallet.name,
88
+ providerId: wallet.providerId,
89
+ addresses: wallet.addresses,
90
+ readiness: {
91
+ keystore: Boolean(wallet.addresses?.solana),
92
+ rpc: serviceHealthy,
93
+ ready: serviceHealthy && Boolean(wallet.addresses?.solana)
94
+ }
95
+ };
96
+ }
97
+ const metadataSignerWalletId = typeof wallet.metadata?.signerWalletId === "string" ? wallet.metadata.signerWalletId.trim() : "";
98
+ const signerWalletId = metadataSignerWalletId || normalizeNativeSignerWalletId(wallet.id);
99
+ try {
100
+ const signer = await readSignerOwnedWalletReadiness({
101
+ socketPath: resolveLocalSignerSocketPath(effectiveEnv),
102
+ walletId: signerWalletId
103
+ });
104
+ const addressMatches = typeof wallet.addresses?.solana === "string" && wallet.addresses.solana === signer.publicKey;
105
+ const roleMatches = typeof wallet.metadata?.role === "string" && wallet.metadata.role === signer.role;
106
+ const ready = signer.ready && addressMatches && roleMatches;
107
+ return {
108
+ id: wallet.id,
109
+ name: wallet.name,
110
+ providerId: wallet.providerId,
111
+ addresses: wallet.addresses,
112
+ readiness: {
113
+ keystore: signer.keyReady,
114
+ rpc: signer.networkReady,
115
+ ready,
116
+ ...!ready && signer.ready ? { error: "registry address or immutable role does not match live signer state" } : {},
117
+ signer
118
+ }
119
+ };
120
+ } catch (error) {
121
+ return {
122
+ id: wallet.id,
123
+ name: wallet.name,
124
+ providerId: wallet.providerId,
125
+ addresses: wallet.addresses,
126
+ readiness: {
127
+ keystore: false,
128
+ rpc: false,
129
+ ready: false,
130
+ error: walletDiagnosticErrorMessage(error)
131
+ }
132
+ };
133
+ }
134
+ })),
80
135
  service: {
81
136
  host: resolved.service.host,
82
137
  port: resolved.service.port,
@@ -8,7 +8,7 @@ import { readConfigFileSnapshot, writeConfigFile } from "../config/io.js";
8
8
  import "../config/config.js";
9
9
  import "../agents/auth-profiles.js";
10
10
  import { ensureWalletStateDir, resolveLocalSignerMaterialRootDir, resolveLocalSignerSocketPath } from "../wallet/wallet-runtime-config.js";
11
- import { checkNamedWalletDeletionSafety, deleteNamedWallet, readWalletProviderRegistry, resolveWalletUserRole, setDefaultWallet, setNamedWalletRole, upsertNamedWallet } from "../wallet/wallet-provider-registry.js";
11
+ import { checkNamedWalletDeletionSafety, deleteNamedWallet, readWalletProviderRegistry, resolveWalletUserRole, setNamedWalletRole, upsertNamedWallet } from "../wallet/wallet-provider-registry.js";
12
12
  import { DEFAULT_WORKSPACE, applyWizardMetadata, ensureWorkspaceAndSessions, handleOnboardingRepair, printWizardHeader, probeGatewayReachable, summarizeExistingConfig } from "../commands/onboard-helpers.js";
13
13
  import { configureSignerOwnedWalletNetwork } from "../wallet/signer-network-admin.js";
14
14
  import { configureWalletForOnboarding, installSignerdBinary, resolveSignerdBinaryPath, restartLocalSocketSigner } from "./onboarding.wallet.js";
@@ -947,7 +947,11 @@ async function runOnboardingWizard(opts, runtime = defaultRuntime, prompter) {
947
947
  label: currentBondWalletId && currentBondWalletId !== walletId ? "Switch bond Vault here" : "Use for Fased Network bond",
948
948
  hint: currentBondWalletId && currentBondWalletId !== walletId ? `Current bond Vault: ${currentBondWalletId}` : "Use this Vault wallet for longer-lived SAT bond authority."
949
949
  }] : [],
950
- {
950
+ targetWalletPurpose === "mining" ? {
951
+ value: "retire-mining",
952
+ label: "Retire and replace Mining wallet",
953
+ hint: "Stop and drain Mining, verify recovery and balances, tombstone the old signer wallet, then attach a ready successor."
954
+ } : {
951
955
  value: "archive",
952
956
  label: "Archive/remove from Fased",
953
957
  hint: "Disable signer use first, then remove this wallet registration."
@@ -1008,6 +1012,19 @@ async function runOnboardingWizard(opts, runtime = defaultRuntime, prompter) {
1008
1012
  });
1009
1013
  continue;
1010
1014
  }
1015
+ if (manageAction === "retire-mining") {
1016
+ await prompter.note([
1017
+ "Mining retirement is a coordinated replacement, never a registry-only delete.",
1018
+ `Run: fased wallet recovery export --wallet-id ${targetWallet.id} --output <absolute-recovery-path>`,
1019
+ `Then run: fased wallet retire --wallet-id ${targetWallet.id} --successor-wallet-id <new-id> --successor-wallet-name <name> --recovery-file <absolute-recovery-path> --rpc-url <url>`,
1020
+ "The command stops new jobs, waits for Clearing and reconciliation, records balances, commits the signer tombstone, and attaches the ready successor."
1021
+ ].join("\n"), "Retire and replace Mining wallet");
1022
+ addAnotherWallet = await prompter.confirm({
1023
+ message: "Run another wallet setup action?",
1024
+ initialValue: false
1025
+ });
1026
+ continue;
1027
+ }
1011
1028
  if (manageAction === "attach-federation-bond") {
1012
1029
  const agentDefaultWallet = readAgentDefaultWallet();
1013
1030
  if (targetWalletPurpose !== "vault") {
@@ -1046,6 +1063,14 @@ async function runOnboardingWizard(opts, runtime = defaultRuntime, prompter) {
1046
1063
  });
1047
1064
  continue;
1048
1065
  }
1066
+ if (resolveWalletUserRole(targetWallet) === "mining") {
1067
+ await prompter.note("Mining wallets cannot be archived or deleted directly. Use Retire and replace Mining wallet so the signer tombstone is committed before registry detachment.", "Mining retirement required");
1068
+ addAnotherWallet = await prompter.confirm({
1069
+ message: "Run another wallet setup action?",
1070
+ initialValue: false
1071
+ });
1072
+ continue;
1073
+ }
1049
1074
  const archiveEnv = {
1050
1075
  ...process.env,
1051
1076
  ...nextConfig.env?.vars,
@@ -1192,20 +1217,6 @@ async function runOnboardingWizard(opts, runtime = defaultRuntime, prompter) {
1192
1217
  });
1193
1218
  const walletName = walletIdentity.walletName;
1194
1219
  const walletId = walletIdentity.walletId || undefined;
1195
- if (selfHostedAction === "import" && hostProfile === "hosting") {
1196
- const signerWalletId = (walletId ?? walletPurpose).trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
1197
- await prompter.note([
1198
- "Hosting keeps plaintext wallet keys outside the app/Gateway OS account.",
1199
- "From the VPS provider root console, place the Solana keypair in /root/wallet.json with mode 600, then run:",
1200
- `/usr/local/sbin/fased-signer-wallet-import --wallet-id ${shellQuote(signerWalletId)} --locked-role ${shellQuote(walletPurpose)} < /root/wallet.json`,
1201
- "Return to the app account, rerun onboarding, and choose Create with the same role and wallet ID. The signer reuses only that exact existing deny-all wallet, then activates the one RPC and registers it."
1202
- ].join("\n"), "Signer-owned Hosting import");
1203
- addAnotherWallet = await prompter.confirm({
1204
- message: "Run another wallet setup action?",
1205
- initialValue: false
1206
- });
1207
- continue;
1208
- }
1209
1220
  const importFile = selfHostedAction === "import" ? (await prompter.text({
1210
1221
  message: "Absolute path to owner-only Solana keypair JSON",
1211
1222
  validate: (value) => value.trim().startsWith("/") ? undefined : "Enter an absolute path and run chmod 600 on the file first"
@@ -1323,20 +1334,11 @@ async function runOnboardingWizard(opts, runtime = defaultRuntime, prompter) {
1323
1334
  await restartLocalSocketSigner(ensureWalletStateDir(process.env).rootDir);
1324
1335
  const isAgentWallet = walletPurpose === "agent";
1325
1336
  if (walletPurpose === "agent") {
1326
- const currentPrimary = String(agentDefaultBefore.walletId ?? "").trim();
1327
- if (!currentPrimary || currentPrimary === walletId) {
1328
- setDefaultWallet({
1329
- walletId: walletId ?? "default",
1330
- env: process.env
1331
- });
1332
- await prompter.note(`Primary Agent wallet set to ${walletName} (${walletId ?? "default"}).`, "Wallet");
1333
- } else {
1334
- await prompter.note([
1335
- `Agent wallet created as ${walletName} (${walletId ?? "default"}).`,
1336
- `Primary Agent wallet remains ${describeWalletRef(agentDefaultBefore)}.`,
1337
- `Use @wallet:${walletId ?? "default"} when you want this wallet explicitly.`
1338
- ].join("\n"), "Wallet");
1339
- }
1337
+ await prompter.note([
1338
+ `Agent wallet created as ${walletName} (${walletId ?? "default"}).`,
1339
+ `Default Agent wallet fallback remains ${describeWalletRef(agentDefaultBefore)}.`,
1340
+ `Use @wallet:${walletId ?? "default"} explicitly, assign it to an Agent or skill, or set it as the optional fallback in Wallet.`
1341
+ ].join("\n"), "Wallet");
1340
1342
  }
1341
1343
  if (walletId) {
1342
1344
  setNamedWalletRole({
@@ -5,6 +5,7 @@ import "../config/config.js";
5
5
  import { hasLegacyEmbeddedKeystoreMaterialHint, throwLegacyEmbeddedKeystoreMigrationRequired } from "../wallet/legacy-embedded-keystore.js";
6
6
  import { ensureWalletStateDir, isLocalSignerExternallyManaged, resolveLocalSignerControlSocketPath, resolveLocalSignerMasterKeyPath, resolveLocalSignerMaterialRootDir, resolveLocalSignerSidecarPaths, resolveLocalSignerSocketPath, resolveLocalSignerStateDbPath } from "../wallet/wallet-runtime-config.js";
7
7
  import { WALLET_PROVIDER_IDS, readWalletProviderRegistry, setWalletProvidersEnabled } from "../wallet/wallet-provider-registry.js";
8
+ import { SAT_RUNTIME_ENV_KEYS, SAT_RUNTIME_TRUST_ENV_KEYS } from "../config/sat-runtime-ids.js";
8
9
  import { callLocalSocketSigner } from "../wallet/providers/local-socket-signer-adapter.js";
9
10
  import { resolveWalletProviderId } from "../wallet/wallet-provider-resolver.js";
10
11
  import { fileURLToPath } from "node:url";
@@ -400,7 +401,7 @@ function resolveSignerChildEnv(materialDir, env = process.env, cfg = loadConfig(
400
401
  }
401
402
  for (const [key, rawValue] of Object.entries(mergedEnv)) {
402
403
  const value = String(rawValue ?? "").trim();
403
- const isSignerRuntimeConfig = key.startsWith("FASED_WALLET_LOCAL_SIGNER_RATE_") || key === "FASED_WALLET_LOCAL_SIGNER_AUDIT_MAX_BYTES" || key === "FASED_WALLET_SOLANA_CONFIRM_TIMEOUT_MS" || key === "FASED_WALLET_SOLANA_WRITE_RPC_TIMEOUT_MS";
404
+ const isSignerRuntimeConfig = key.startsWith("FASED_WALLET_LOCAL_SIGNER_RATE_") || key === "FASED_WALLET_LOCAL_SIGNER_AUDIT_MAX_BYTES" || key === "FASED_WALLET_SOLANA_CONFIRM_TIMEOUT_MS" || key === "FASED_WALLET_SOLANA_WRITE_RPC_TIMEOUT_MS" || [...Object.values(SAT_RUNTIME_ENV_KEYS), ...Object.values(SAT_RUNTIME_TRUST_ENV_KEYS)].includes(key);
404
405
  if (value && isSignerRuntimeConfig) {
405
406
  childEnv[key] = value;
406
407
  }
@@ -486,6 +487,14 @@ function renderLocalSignerEnvFile(params) {
486
487
  ...materialDir !== walletRoot ? [`export FASED_WALLET_SIGNER_STATE_DIR=${quoteSignerEnvValue(materialDir)}`] : [],
487
488
  `export FASED_WALLET_CHAINS=${quoteSignerEnvValue(String(childEnv.FASED_WALLET_CHAINS ?? "solana").trim() || "solana")}`,
488
489
  ...webAuthn ? [`export FASED_WALLET_WEBAUTHN_RP_ID=${quoteSignerEnvValue(webAuthn.rpId)}`, `export FASED_WALLET_WEBAUTHN_ORIGINS=${quoteSignerEnvValue(webAuthn.origins)}`] : [],
490
+ ...Object.values(SAT_RUNTIME_ENV_KEYS).flatMap((key) => {
491
+ const value = String(childEnv[key] ?? "").trim();
492
+ return value ? [`export ${key}=${quoteSignerEnvValue(value)}`] : [];
493
+ }),
494
+ ...Object.values(SAT_RUNTIME_TRUST_ENV_KEYS).flatMap((key) => {
495
+ const value = String(childEnv[key] ?? "").trim();
496
+ return value ? [`export ${key}=${quoteSignerEnvValue(value)}`] : [];
497
+ }),
489
498
  "",
490
499
  `${quoteSignerEnvValue(signerBinPath)} --socket "$FASED_WALLET_LOCAL_SIGNER_SOCKET" --control-socket "$FASED_WALLET_LOCAL_SIGNER_CONTROL_SOCKET" --state-db "$FASED_WALLET_LOCAL_SIGNER_STATE_DB" --master-key "$FASED_WALLET_LOCAL_SIGNER_MASTER_KEY"`
491
500
  ];
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fased/acpx",
3
- "version": "0.1.68",
3
+ "version": "0.1.69",
4
4
  "description": "FasedAgent ACP runtime backend via acpx",
5
5
  "type": "module",
6
6
  "dependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fased/bluebubbles",
3
- "version": "0.1.68",
3
+ "version": "0.1.69",
4
4
  "description": "FasedAgent BlueBubbles channel plugin",
5
5
  "type": "module",
6
6
  "fased": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fased/copilot-proxy",
3
- "version": "0.1.68",
3
+ "version": "0.1.69",
4
4
  "private": true,
5
5
  "description": "FasedAgent Copilot Proxy provider plugin",
6
6
  "type": "module",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fased/diagnostics-otel",
3
- "version": "0.1.68",
3
+ "version": "0.1.69",
4
4
  "description": "FasedAgent diagnostics OpenTelemetry exporter",
5
5
  "type": "module",
6
6
  "dependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fased/fased-federation",
3
- "version": "0.1.68",
3
+ "version": "0.1.69",
4
4
  "private": true,
5
5
  "description": "Fased federation adapter package scaffold (A2A + admission helpers)",
6
6
  "type": "module",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fased/google-gemini-cli-auth",
3
- "version": "0.1.68",
3
+ "version": "0.1.69",
4
4
  "private": true,
5
5
  "description": "FasedAgent Gemini CLI OAuth provider plugin",
6
6
  "type": "module",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fased/imessage",
3
- "version": "0.1.68",
3
+ "version": "0.1.69",
4
4
  "private": true,
5
5
  "description": "FasedAgent iMessage channel plugin",
6
6
  "type": "module",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fased/irc",
3
- "version": "0.1.68",
3
+ "version": "0.1.69",
4
4
  "description": "FasedAgent IRC channel plugin",
5
5
  "type": "module",
6
6
  "fased": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fased/line",
3
- "version": "0.1.68",
3
+ "version": "0.1.69",
4
4
  "private": true,
5
5
  "description": "FasedAgent LINE channel plugin",
6
6
  "type": "module",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fased/llm-task",
3
- "version": "0.1.68",
3
+ "version": "0.1.69",
4
4
  "private": true,
5
5
  "description": "FasedAgent JSON-only LLM task plugin",
6
6
  "type": "module",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fased/lobster",
3
- "version": "0.1.68",
3
+ "version": "0.1.69",
4
4
  "description": "Lobster workflow tool plugin (typed pipelines + resumable approvals)",
5
5
  "type": "module",
6
6
  "fased": {
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.69
4
+
5
+ ### Changes
6
+
7
+ - Version alignment with core FasedAgent release numbers.
8
+
3
9
  ## 0.1.68
4
10
 
5
11
  ### Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fased/matrix",
3
- "version": "0.1.68",
3
+ "version": "0.1.69",
4
4
  "description": "FasedAgent Matrix channel plugin",
5
5
  "type": "module",
6
6
  "dependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fased/mattermost",
3
- "version": "0.1.68",
3
+ "version": "0.1.69",
4
4
  "description": "FasedAgent Mattermost channel plugin",
5
5
  "type": "module",
6
6
  "fased": {
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@fased/memory-core",
3
- "version": "0.1.68",
3
+ "version": "0.1.69",
4
4
  "private": true,
5
5
  "description": "FasedAgent core memory search plugin",
6
6
  "type": "module",
7
7
  "peerDependencies": {
8
- "@fased/fased": "^0.1.68"
8
+ "@fased/fased": "^0.1.69"
9
9
  },
10
10
  "fased": {
11
11
  "extensions": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fased/memory-lancedb",
3
- "version": "0.1.68",
3
+ "version": "0.1.69",
4
4
  "private": true,
5
5
  "description": "FasedAgent LanceDB-backed long-term memory plugin with auto-recall/capture",
6
6
  "type": "module",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fased/minimax-portal-auth",
3
- "version": "0.1.68",
3
+ "version": "0.1.69",
4
4
  "private": true,
5
5
  "description": "FasedAgent MiniMax Portal OAuth provider plugin",
6
6
  "type": "module",
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.69
4
+
5
+ ### Changes
6
+
7
+ - Version alignment with core FasedAgent release numbers.
8
+
3
9
  ## 0.1.68
4
10
 
5
11
  ### Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fased/msteams",
3
- "version": "0.1.68",
3
+ "version": "0.1.69",
4
4
  "description": "FasedAgent Microsoft Teams channel plugin",
5
5
  "type": "module",
6
6
  "dependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fased/nextcloud-talk",
3
- "version": "0.1.68",
3
+ "version": "0.1.69",
4
4
  "description": "FasedAgent Nextcloud Talk channel plugin",
5
5
  "type": "module",
6
6
  "fased": {
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.69
4
+
5
+ ### Changes
6
+
7
+ - Version alignment with core FasedAgent release numbers.
8
+
3
9
  ## 0.1.68
4
10
 
5
11
  ### Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fased/nostr",
3
- "version": "0.1.68",
3
+ "version": "0.1.69",
4
4
  "description": "FasedAgent Nostr channel plugin for NIP-04 encrypted DMs",
5
5
  "type": "module",
6
6
  "dependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fased/open-prose",
3
- "version": "0.1.68",
3
+ "version": "0.1.69",
4
4
  "private": true,
5
5
  "description": "OpenProse VM skill pack plugin (slash command + telemetry).",
6
6
  "type": "module",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fased/sat-mining",
3
- "version": "0.1.68",
3
+ "version": "0.1.69",
4
4
  "private": true,
5
5
  "description": "SAT mining plugin scaffold for FasedAgent",
6
6
  "type": "module",