@fased/fased 0.1.62 → 0.1.64
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/CHANGELOG.md +32 -0
- package/README.md +38 -30
- package/config/dependency-ownership.json +1 -1
- package/config/signer-policies/README.md +49 -0
- package/config/signer-policies/agent.json.template +32 -0
- package/config/signer-policies/mining.json.template +69 -0
- package/config/signer-policies/network.json.template +5 -0
- package/config/signer-policies/vault.json.template +70 -0
- package/config/signer-protocol-v2.json +76 -0
- package/config/typescript-noemit-baseline.json +680 -0
- package/dist/agents/auth-profiles/store.js +267 -31
- package/dist/agents/bash-tools.exec.js +10 -4
- package/dist/agents/current-model-catalog.js +3 -3
- package/dist/agents/memory-search.js +7 -1
- package/dist/agents/model-catalog-access.js +1 -2
- package/dist/agents/model-catalog-snapshot.js +1 -1
- package/dist/agents/model-catalog-source.js +1 -1
- package/dist/agents/model-metadata.js +1 -1
- package/dist/agents/model-selection.js +2 -28
- package/dist/agents/models-config.providers.js +6 -6
- package/dist/agents/pi-embedded-runner/compact.js +15 -7
- package/dist/agents/pi-embedded-runner/model.js +1 -1
- package/dist/agents/pi-embedded-runner/run/attempt.js +24 -13
- package/dist/agents/pi-embedded-runner/run.js +2 -0
- package/dist/agents/pi-embedded-runner/tool-split.js +40 -2
- package/dist/agents/pi-tool-definition-adapter.js +16 -1
- package/dist/agents/pi-tools.js +2 -1
- package/dist/agents/sandbox/config.js +1 -1
- package/dist/agents/sandbox/context.js +27 -2
- package/dist/agents/skills/env-overrides.js +38 -28
- package/dist/agents/skills/trust.js +93 -0
- package/dist/agents/skills/workspace.js +128 -0
- package/dist/agents/skills-clawhub.js +36 -11
- package/dist/agents/skills-marketplace-scan.js +49 -0
- package/dist/agents/tools/marketplace-offer-draft-tool.js +1 -1
- package/dist/agents/tools/mining-tool.js +1 -1
- package/dist/agents/tools/session-status-tool.js +1 -1
- package/dist/agents/tools/wallet-action-tool.js +172 -36
- package/dist/agents/tools/wallet-skill-policy.js +65 -23
- package/dist/agents/tools/wallet-tool.js +7 -11
- package/dist/auto-reply/reply/directive-handling.fast-lane.js +2 -1
- package/dist/auto-reply/reply/directive-handling.impl.js +2 -1
- package/dist/auto-reply/reply/directive-handling.model.js +2 -1
- package/dist/auto-reply/reply/directive-handling.persist.js +2 -2
- package/dist/auto-reply/reply/get-reply-directives-apply.js +2 -0
- package/dist/auto-reply/reply/get-reply-inline-actions.js +25 -1
- package/dist/auto-reply/reply/model-selection.js +7 -4
- package/dist/auto-reply/reply/session-reset-model.js +4 -4
- package/dist/brand.js +1 -1
- package/dist/build-info.json +3 -3
- package/dist/canvas-host/a2ui/.bundle.hash +1 -1
- package/dist/channel-web.js +2 -2
- package/dist/cli/gateway-cli/run.js +8 -0
- package/dist/cli/program/command-registry.js +1 -1
- package/dist/cli/program/register.onboard.js +2 -3
- package/dist/cli/program/register.wallet.js +16 -123
- package/dist/cli/providers-cli.js +1 -1
- package/dist/cli/sat-cli.js +129 -2
- package/dist/cli/update-cli/update-command.js +260 -11
- package/dist/commands/auth-choice.apply.api-providers.js +3 -3
- package/dist/commands/doctor-config-flow.js +1 -1
- package/dist/commands/doctor-legacy-config.js +2 -13
- package/dist/commands/model-picker.js +6 -6
- package/dist/commands/models/auth.js +1 -1
- package/dist/commands/onboard-auth.config-gateways.js +1 -1
- package/dist/commands/onboard-auth.credentials.js +32 -8
- package/dist/commands/onboard-non-interactive/local/wallet-config.js +28 -27
- package/dist/commands/onboard-non-interactive/local.js +5 -1
- package/dist/commands/wallet.js +568 -1911
- package/dist/config/config.js +2 -2
- package/dist/config/io.js +64 -2
- package/dist/config/schema.help.js +8 -7
- package/dist/config/schema.labels.js +5 -4
- package/dist/config/zod-schema.agent-runtime.js +1 -0
- package/dist/config/zod-schema.js +5 -0
- package/dist/control-ui/assets/{app-DLil9VO1.js → app-bR-fO5ty.js} +1511 -1555
- package/dist/control-ui/assets/{config-CU5Zi8Dh.js → config-LeImukCW.js} +10 -10
- package/dist/control-ui/assets/{federation-D10Q4eP_.js → federation-DgA9e-Pn.js} +364 -422
- package/dist/control-ui/assets/{index-DdE_NIXo.js → index-ckCxHwjy.js} +3 -3
- package/dist/control-ui/assets/{mining-BdhMn18r.js → mining-BgHFh0ei.js} +134 -114
- package/dist/control-ui/assets/mining-commit-DFpB_4JN.js +2 -0
- package/dist/control-ui/assets/{open-external-url-DwSiwMPl.js → open-external-url-ulF1B-sA.js} +3 -3
- package/dist/control-ui/assets/{providers-QMn4w2_f.js → providers-CIx9fxc6.js} +2 -2
- package/dist/control-ui/assets/{wallet-C2g294QT.js → wallet-DvStR_AT.js} +259 -377
- package/dist/control-ui/index.html +1 -1
- package/dist/control-ui/version.json +1 -1
- package/dist/daemon/systemd-system.js +56 -50
- package/dist/extensions/sat-mining/src/protocol-contract.js +43 -3
- package/dist/extensions/sat-mining/src/rpc-read.js +235 -67
- package/dist/extensions/sat-mining/src/sat-bond-layout.js +5 -2
- package/dist/extensions/sat-mining/src/signer-codec-manifest.js +406 -0
- package/dist/extensions/sat-mining/src/solana-submit.js +1038 -397
- package/dist/extensions/sat-mining/src/submission-ledger.js +349 -0
- package/dist/federation/auto-connect.js +98 -8
- package/dist/federation/marketplace-capability-adapter.js +33 -7
- package/dist/federation/marketplace-delivery-outbox.js +196 -0
- package/dist/federation/marketplace-delivery.js +351 -215
- package/dist/federation/marketplace-direct-payment.js +272 -141
- package/dist/federation/marketplace-escrow.js +607 -249
- package/dist/federation/marketplace-settlement-ledger.js +352 -0
- package/dist/federation/offers.js +9 -7
- package/dist/federation/peer-auth-v2.js +529 -0
- package/dist/gateway/a2a-http.js +425 -96
- package/dist/gateway/a2a-settlement.js +259 -153
- package/dist/gateway/a2a-task-store.js +524 -0
- package/dist/gateway/auth.js +38 -2
- package/dist/gateway/config-reload.js +46 -33
- package/dist/gateway/durable-capacity.js +31 -0
- package/dist/gateway/federation-http.js +540 -135
- package/dist/gateway/federation-marketplace-run-store.js +397 -0
- package/dist/gateway/federation-marketplace.js +535 -230
- package/dist/gateway/mutating-admin-rpc-rate-limit.js +5 -0
- package/dist/gateway/security-path.js +1 -1
- package/dist/gateway/server-http.js +1084 -1205
- package/dist/gateway/server-methods/models.js +1 -1
- package/dist/gateway/server-methods/secrets.js +40 -0
- package/dist/gateway/server-methods.js +1 -2
- package/dist/gateway/server-reload-handlers.js +196 -66
- package/dist/gateway/server-runtime-config.js +1 -1
- package/dist/gateway/server-secrets-runtime.js +288 -0
- package/dist/gateway/server.impl.js +73 -42
- package/dist/gateway/sessions-patch.js +3 -5
- package/dist/index.js +4 -2
- package/dist/infra/fasedhub.js +64 -1
- package/dist/infra/local-source-paired-update.js +538 -0
- package/dist/infra/restart.js +41 -10
- package/dist/infra/update-runner.js +96 -0
- package/dist/light-update-status.js +11 -11
- package/dist/memory/backend-config.js +2 -1
- package/dist/memory/session-files.js +16 -2
- package/dist/plugin-sdk/{accounts-DxblobYM.js → accounts-Brn3-uWN.js} +1 -1
- package/dist/plugin-sdk/{actions-D4UNimWa.js → actions-DRu135h0.js} +2 -2
- package/dist/plugin-sdk/{active-listener-CFuy106s.js → active-listener-B_NMtgPL.js} +1 -1
- package/dist/plugin-sdk/{audio-preflight-Bwi2Oq03.js → audio-preflight-BYxAt775.js} +27 -27
- package/dist/plugin-sdk/{audit-Cs0K7LBp.js → audit-C5d2z5U1.js} +1 -1
- package/dist/plugin-sdk/{channel-access-D5aHoTY8.js → channel-access-CcFRdRPO.js} +1 -1
- package/dist/plugin-sdk/{channel-access-configure-Dvch9mMQ.js → channel-access-configure-DaI5wevh.js} +1 -1
- package/dist/plugin-sdk/channel-plugin-common.d.ts +3 -3
- package/dist/plugin-sdk/channel-plugin-common.js +4 -4
- package/dist/plugin-sdk/{chunk-B0FUGc5A.js → chunk-CyoyqpbG.js} +1 -1
- package/dist/plugin-sdk/{chunk-items-DzT4L4Ty.js → chunk-items-DIRHG2gJ.js} +1 -1
- package/dist/plugin-sdk/command-status.d.ts +2 -2
- package/dist/plugin-sdk/command-status.js +27 -27
- package/dist/plugin-sdk/{commands-registry-DmDRhRAU.js → commands-registry-BfqdEWdF.js} +2 -2
- package/dist/plugin-sdk/{common-CfUOowOp.js → common-HCcXU-NR.js} +1 -1
- package/dist/plugin-sdk/{config-mxULv0fQ.js → config-DlWVeLFB.js} +7113 -6877
- package/dist/plugin-sdk/{config-schema-BrkmtFxB.js → config-schema-BOT7kHb6.js} +6779 -3696
- package/dist/plugin-sdk/device-pair.d.ts +1 -1
- package/dist/plugin-sdk/discord.d.ts +6 -6
- package/dist/plugin-sdk/discord.js +19 -19
- package/dist/plugin-sdk/file-lock.js +35 -4
- package/dist/plugin-sdk/{filesystem-manager-ZoHU8oA7.js → filesystem-manager-DoI8IBNF.js} +1 -1
- package/dist/plugin-sdk/{group-mentions-BHRff6j8.d.ts → group-mentions-q3hUTCt7.d.ts} +1 -1
- package/dist/plugin-sdk/{handle-action-DbVCF9HZ.js → handle-action-hvwapMKg.js} +13 -13
- package/dist/plugin-sdk/{helpers-BXbdgs5H.js → helpers-DMBU4oTo.js} +1 -1
- package/dist/plugin-sdk/{image-ops-D7jPxaph.js → image-ops-DQi0n_Tt.js} +1 -1
- package/dist/plugin-sdk/index.d.ts +21 -39
- package/dist/plugin-sdk/index.js +29 -29
- package/dist/plugin-sdk/{login-BRxww6nv.js → login-Ca583Okc.js} +3 -3
- package/dist/plugin-sdk/{login-qr-DJXsk9XH.js → login-qr-CGciBSNP.js} +3 -3
- package/dist/plugin-sdk/{manager-Y2S_5IlI.js → manager-BegWxNYX.js} +4 -4
- package/dist/plugin-sdk/{markdown-tables-DHLFQqaF.js → markdown-tables-DCOXEUfZ.js} +1 -1
- package/dist/plugin-sdk/{media-Czo4carg.js → media-CAdQF5TG.js} +47 -47
- package/dist/plugin-sdk/{memory-search-DTjIMw8J.js → memory-search-CrFPOeTH.js} +4 -1
- package/dist/plugin-sdk/{monitor-M_ta2lMc.js → monitor-BCFDaqJ-.js} +31 -31
- package/dist/plugin-sdk/{monitor-wYVncM9w.js → monitor-BgbjRiPM.js} +32 -32
- package/dist/plugin-sdk/{openresponses-http-B2GmeSt4.js → openresponses-http-DFf87SMM.js} +27 -27
- package/dist/plugin-sdk/{optional-runtime-dependency-DdMbxS24.js → optional-runtime-dependency-0dznm3ZO.js} +1 -1
- package/dist/plugin-sdk/{outbound-Db8mRN6P.js → outbound-BgVDdHxx.js} +6 -6
- package/dist/plugin-sdk/{outbound-attachment-BqFjcypb.js → outbound-attachment-QqTnIhZL.js} +2 -2
- package/dist/plugin-sdk/{pairing-message-B3bHYGaw.d.ts → pairing-message-CS-9BHug.d.ts} +2 -2
- package/dist/plugin-sdk/{pairing-message-B3GC_7CD.js → pairing-message-D0CoLHRJ.js} +1 -1
- package/dist/plugin-sdk/{pairing-store-CQikgIbw.js → pairing-store-BChahgI2.js} +2 -2
- package/dist/plugin-sdk/{pi-model-discovery-CY3m5zJP.js → pi-model-discovery-BX_JLcEJ.js} +1 -1
- package/dist/plugin-sdk/{pi-model-discovery-runtime-DSh1T2pn.js → pi-model-discovery-runtime-DxTMz_XF.js} +2 -2
- package/dist/plugin-sdk/provider-web-search-config-contract.d.ts +2 -2
- package/dist/plugin-sdk/{pw-ai-AFUqn-tQ.js → pw-ai-natjh3rm.js} +3 -3
- package/dist/plugin-sdk/{qmd-manager-DSyx77KY.js → qmd-manager-CgRaTxUq.js} +1 -1
- package/dist/plugin-sdk/{query-expansion-CAI2kKLQ.js → query-expansion-BG3FgzF7.js} +14 -3
- package/dist/plugin-sdk/{replies-Fzh9PhXl.js → replies-ChYo5ZQM.js} +2 -2
- package/dist/plugin-sdk/{resolve-outbound-target-KpF3co6T.js → resolve-outbound-target-D-KGgHJZ.js} +1 -1
- package/dist/plugin-sdk/{resolve-route-CDl74O19.js → resolve-route-C8tvQm8Z.js} +1 -1
- package/dist/plugin-sdk/{retry-policy-D4uiqUOG.js → retry-policy-C6SjKjQA.js} +1 -1
- package/dist/plugin-sdk/{runtime-Bb6KRnCC.js → runtime-2B9_WKoI.js} +8 -3
- package/dist/plugin-sdk/{runtime-dependency-DLDmB94f.js → runtime-dependency-DczkvPxn.js} +2 -2
- package/dist/plugin-sdk/sat-runtime.d.ts +549 -309
- package/dist/plugin-sdk/sat-runtime.js +29 -29
- package/dist/plugin-sdk/{send-C4k4JuJN.js → send-B6KkGKZD.js} +6 -6
- package/dist/plugin-sdk/{send-D-uDKGIq.js → send-CFzGKJXo.js} +6 -6
- package/dist/plugin-sdk/{send-Du8ykP1k.js → send-DCO441U7.js} +8 -8
- package/dist/plugin-sdk/{send-5nFktR1n.js → send-gDoGA-7e.js} +5 -5
- package/dist/plugin-sdk/{send-Bfzf11VY.js → send-q9HXrSwK.js} +7 -7
- package/dist/plugin-sdk/{session-CS-Td9EM.js → session-DHD4ZKyG.js} +2 -2
- package/dist/plugin-sdk/{skill-commands-CFAlXWHk.js → skill-commands-FKEPLS7T.js} +201 -26
- package/dist/plugin-sdk/{slack-CxE1mfzj.js → slack-BUTt8cxK.js} +39 -39
- package/dist/plugin-sdk/{slack-actions-BcMkNv1Z.js → slack-actions-DhbMcp8M.js} +11 -11
- package/dist/plugin-sdk/slack.d.ts +6 -6
- package/dist/plugin-sdk/slack.js +9 -9
- package/dist/plugin-sdk/{sticker-cache-CGzGWu00.js → sticker-cache-D0wHVqjt.js} +3 -3
- package/dist/plugin-sdk/{tables-bFXyRpkx.js → tables-B3jr0Pvq.js} +1 -1
- package/dist/plugin-sdk/{targets-DH7a9lKB.js → targets-CtSbTxYX.js} +1 -1
- package/dist/plugin-sdk/{telegram-actions-DaEcYQ8r.js → telegram-actions-CC_qN4v0.js} +30 -30
- package/dist/plugin-sdk/telegram.d.ts +6 -6
- package/dist/plugin-sdk/telegram.js +8 -8
- package/dist/plugin-sdk/{thread-bindings.lifecycle-CgOvvdw8.js → thread-bindings.lifecycle-QbkNl-m6.js} +3 -3
- package/dist/plugin-sdk/{thread-bindings.state-CQpk44Hq.js → thread-bindings.state-D9hg_M1c.js} +2 -2
- package/dist/plugin-sdk/tmp-fased-dir-xOTGlzBE.d.ts +486 -0
- package/dist/plugin-sdk/{types-vcJrC_uv.d.ts → types-C3avNytw.d.ts} +3 -4
- package/dist/plugin-sdk/{types-DyhXnYUr.d.ts → types-D0kDG8l0.d.ts} +3 -2
- package/dist/plugin-sdk/{types-DFAW-n1J.d.ts → types-DWfbSAaM.d.ts} +2 -2
- package/dist/plugin-sdk/{types.plugin-_fbu40Re.d.ts → types.plugin-BcSBq42x.d.ts} +8 -3
- package/dist/plugin-sdk/{web-CInY-lCv.js → web-BXsJ1vqe.js} +32 -32
- package/dist/plugin-sdk/{whatsapp-actions-BtSc2CBv.js → whatsapp-actions-Bj_rOncr.js} +13 -13
- package/dist/plugin-sdk/{whatsapp-heartbeat-Bg9TuYzl.js → whatsapp-heartbeat-B1WHkJIg.js} +2 -2
- package/dist/plugin-sdk/whatsapp.d.ts +13 -13
- package/dist/plugin-sdk/whatsapp.js +12 -12
- package/dist/plugin-sdk/{wsl-C4DGFkOd.js → wsl-J-HscWxS.js} +3 -3
- package/dist/plugin-sdk/{zod-schema.providers-core-BEbNizPe.d.ts → zod-schema.providers-core-CIzCjXH9.d.ts} +61 -61
- package/dist/providers/refresh.js +1 -1
- package/dist/providers/registry.js +1 -1
- package/dist/secrets/apply.js +1 -1
- package/dist/secrets/runtime.js +1 -1
- package/dist/wallet/external-submission-ledger.js +376 -0
- package/dist/wallet/legacy-embedded-keystore.js +40 -0
- package/dist/wallet/local-socket-signer-archive.js +30 -0
- package/dist/wallet/local-socket-signer-lifecycle.js +97 -0
- package/dist/wallet/local-socket-signer-policy.js +166 -0
- package/dist/wallet/local-socket-signer-protocol.js +561 -118
- package/dist/wallet/native-signer-wallet-id.js +25 -0
- package/dist/wallet/providers/alchemy-adapter.js +3 -0
- package/dist/wallet/providers/local-socket-signer-adapter.js +380 -105
- package/dist/wallet/providers/turnkey-adapter.js +292 -34
- package/dist/wallet/providers/wallet-standard-adapter.js +100 -0
- package/dist/wallet/signer-network-admin.js +184 -0
- package/dist/wallet/signer-protocol-v2.generated.js +90 -0
- package/dist/wallet/solana-bond-signing.js +157 -69
- package/dist/wallet/solana-reviewed-transaction.js +375 -0
- package/dist/wallet/solana-swap.js +520 -64
- package/dist/wallet/solana-transaction-inspection.js +106 -4
- package/dist/wallet/solana-trigger.js +658 -320
- package/dist/wallet/turnkey-reviewed-state.js +370 -0
- package/dist/wallet/wallet-approval-auth.js +17 -28
- package/dist/wallet/wallet-atomic-state.js +53 -0
- package/dist/wallet/wallet-canary.js +0 -1
- package/dist/wallet/wallet-inbound-events.js +16 -11
- package/dist/wallet/wallet-policy-simulation.js +1 -1
- package/dist/wallet/wallet-policy.js +90 -36
- package/dist/wallet/wallet-provider-capabilities.js +28 -4
- package/dist/wallet/wallet-provider-registry.js +57 -44
- package/dist/wallet/wallet-provider-resolver.js +62 -63
- package/dist/wallet/wallet-runtime-config.js +28 -41
- package/dist/wallet/wallet-secrets-store.js +22 -0
- package/dist/wallet/wallet-send-approvals.js +1891 -589
- package/dist/wallet/wallet-send-execution-ledger.js +292 -0
- package/dist/wallet/wallet-settlement-links.js +14 -13
- package/dist/wallet/wallet-standard-review.js +353 -0
- package/dist/wallet/wallet-status.js +0 -9
- package/dist/wallet/wallet-task-ledger.js +16 -2
- package/dist/web/auto-reply/heartbeat-runner.js +1 -1
- package/dist/web/auto-reply/monitor.js +2 -2
- package/dist/wizard/host-security-capability.js +14 -23
- package/dist/wizard/onboarding.finalize.js +63 -184
- package/dist/wizard/onboarding.host-security.js +117 -1367
- package/dist/wizard/onboarding.js +172 -217
- package/dist/wizard/onboarding.wallet.js +232 -785
- package/extensions/acpx/package.json +1 -1
- package/extensions/bluebubbles/package.json +1 -1
- package/extensions/copilot-proxy/package.json +1 -1
- package/extensions/diagnostics-otel/package.json +1 -1
- package/extensions/fased-federation/package.json +1 -1
- package/extensions/google-gemini-cli-auth/package.json +1 -1
- package/extensions/imessage/package.json +1 -1
- package/extensions/irc/package.json +1 -1
- package/extensions/line/package.json +1 -1
- package/extensions/llm-task/package.json +1 -1
- package/extensions/lobster/package.json +1 -1
- package/extensions/matrix/CHANGELOG.md +12 -0
- package/extensions/matrix/package.json +1 -1
- package/extensions/mattermost/package.json +1 -1
- package/extensions/memory-core/package.json +2 -2
- package/extensions/memory-lancedb/package.json +1 -1
- package/extensions/minimax-portal-auth/package.json +1 -1
- package/extensions/msteams/CHANGELOG.md +12 -0
- package/extensions/msteams/package.json +1 -1
- package/extensions/nextcloud-talk/package.json +1 -1
- package/extensions/nostr/CHANGELOG.md +12 -0
- package/extensions/nostr/package.json +1 -1
- package/extensions/open-prose/package.json +1 -1
- package/extensions/sat-mining/index.ts +498 -153
- package/extensions/sat-mining/package.json +1 -1
- package/extensions/sat-mining/signer-codec-schema.v1.json +374 -0
- package/extensions/sat-mining/src/audit-store.ts +50 -5
- package/extensions/sat-mining/src/claim-service.ts +85 -14
- package/extensions/sat-mining/src/config.ts +9 -0
- package/extensions/sat-mining/src/cycle-progress.ts +16 -8
- package/extensions/sat-mining/src/epoch-service.ts +9 -5
- package/extensions/sat-mining/src/gateway-runner.ts +21 -1
- package/extensions/sat-mining/src/protocol-contract.ts +45 -1
- package/extensions/sat-mining/src/recovery-service.ts +312 -0
- package/extensions/sat-mining/src/round-watcher.ts +391 -81
- package/extensions/sat-mining/src/rpc-read.ts +330 -89
- package/extensions/sat-mining/src/runtime.ts +14 -0
- package/extensions/sat-mining/src/sat-bond-layout.ts +6 -0
- package/extensions/sat-mining/src/signer-codec-manifest.ts +429 -0
- package/extensions/sat-mining/src/solana-submit.ts +1199 -428
- package/extensions/sat-mining/src/submission-ledger.ts +433 -0
- package/extensions/signal/package.json +1 -1
- package/extensions/synology-chat/package.json +1 -1
- package/extensions/tlon/package.json +1 -1
- package/extensions/twitch/CHANGELOG.md +12 -0
- package/extensions/twitch/package.json +1 -1
- package/extensions/voice-call/CHANGELOG.md +12 -0
- package/extensions/voice-call/package.json +1 -1
- package/extensions/zalo/CHANGELOG.md +12 -0
- package/extensions/zalo/package.json +1 -1
- package/extensions/zalouser/CHANGELOG.md +12 -0
- package/extensions/zalouser/package.json +1 -1
- package/install.sh +4955 -0
- package/package.json +23 -5
- package/scripts/fased-host-updater.mjs +1421 -0
- package/scripts/fased-host-updaterctl.mjs +186 -0
- package/scripts/fased-managed-service.sh +36 -0
- package/scripts/fased-managed-updater.mjs +3065 -156
- package/scripts/fased-signer-enroll-hosting.sh +275 -0
- package/scripts/fased-signer-network-hosting.sh +143 -0
- package/scripts/fased-signer-owner-policy.mjs +1430 -0
- package/scripts/fased-signer-policy-hosting.sh +50 -0
- package/scripts/fased-signer-policy-local.sh +26 -0
- package/scripts/hosted-release-manifest.mjs +185 -0
- package/scripts/install-fased-signerd.sh +183 -108
- package/scripts/install-managed-runtime.mjs +212 -10
- package/scripts/managed-runtime-layout.mjs +75 -3
- package/scripts/migrate-hosted-signer-v2.mjs +58 -0
- package/scripts/start-managed.sh +169 -360
- package/dist/control-ui/assets/mining-commit-R-6nu87p.js +0 -2
- package/dist/plugin-sdk/tmp-fased-dir-CS6zsYEE.d.ts +0 -77
- package/dist/wallet/local-socket-signer-broker.js +0 -224
- package/dist/wallet/local-socket-signer-custody.js +0 -42
- package/dist/wallet/providers/embedded-keystore-adapter.js +0 -402
- package/dist/wallet/providers/privy-adapter.js +0 -80
- package/dist/wallet/wallet-custody.js +0 -1836
|
@@ -0,0 +1,538 @@
|
|
|
1
|
+
import { resolveStateDir } from "../config/paths.js";
|
|
2
|
+
import { runCommandWithTimeout } from "../process/exec.js";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import fs from "node:fs/promises";
|
|
5
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
6
|
+
import * as tar from "tar";
|
|
7
|
+
|
|
8
|
+
//#region src/infra/local-source-paired-update.ts
|
|
9
|
+
const JOURNAL_SCHEMA_VERSION = 1;
|
|
10
|
+
const PHASES = new Set([
|
|
11
|
+
"prepared",
|
|
12
|
+
"app-active",
|
|
13
|
+
"signer-active",
|
|
14
|
+
"gateway-verified",
|
|
15
|
+
"committing",
|
|
16
|
+
"rolling-back"
|
|
17
|
+
]);
|
|
18
|
+
const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
19
|
+
const SHA_PATTERN = /^[a-f0-9]{40}$/;
|
|
20
|
+
const VERSION_PATTERN = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z]+(?:[.-][0-9A-Za-z]+)*)?$/;
|
|
21
|
+
function resolveContext(env = process.env) {
|
|
22
|
+
const stateDir = path.resolve(resolveStateDir(env));
|
|
23
|
+
const updateRoot = path.join(stateDir, "source-paired-update");
|
|
24
|
+
return {
|
|
25
|
+
stateDir,
|
|
26
|
+
updateRoot,
|
|
27
|
+
transactionsDir: path.join(updateRoot, "transactions"),
|
|
28
|
+
journalPath: path.join(updateRoot, "transaction.json")
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function pathIsInside(parent, candidate) {
|
|
32
|
+
const relative = path.relative(path.resolve(parent), path.resolve(candidate));
|
|
33
|
+
return relative !== "" && !relative.startsWith("..") && !path.isAbsolute(relative);
|
|
34
|
+
}
|
|
35
|
+
async function fsyncPath(target) {
|
|
36
|
+
const handle = await fs.open(target, "r");
|
|
37
|
+
try {
|
|
38
|
+
await handle.sync();
|
|
39
|
+
} finally {
|
|
40
|
+
await handle.close();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
async function sha256File(filePath) {
|
|
44
|
+
const bytes = await fs.readFile(filePath);
|
|
45
|
+
return createHash("sha256").update(bytes).digest("hex");
|
|
46
|
+
}
|
|
47
|
+
function validateRelease(value, label) {
|
|
48
|
+
const release = value;
|
|
49
|
+
if (!release || !SHA_PATTERN.test(release.sha ?? "") || !VERSION_PATTERN.test(release.version ?? "")) {
|
|
50
|
+
throw new Error(`Local source paired update has an invalid ${label} release identity`);
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
sha: release.sha,
|
|
54
|
+
version: release.version
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function validateJournal(context, value) {
|
|
58
|
+
const journal = value;
|
|
59
|
+
if (!journal || journal.schemaVersion !== JOURNAL_SCHEMA_VERSION || journal.kind !== "source-checkout" || !UUID_PATTERN.test(journal.transactionId ?? "") || !PHASES.has(journal.phase) || typeof journal.sourceRoot !== "string" || !path.isAbsolute(journal.sourceRoot) || typeof journal.transactionDir !== "string" || path.resolve(journal.transactionDir) !== path.join(context.transactionsDir, journal.transactionId ?? "") || !pathIsInside(context.updateRoot, journal.transactionDir) || path.resolve(journal.controllerPath ?? "") !== path.join(journal.transactionDir, "controller", "fased-managed-updater.mjs") || typeof journal.previous?.branch !== "string" && journal.previous?.branch !== null || typeof journal.previous?.branch === "string" && (!journal.previous.branch || journal.previous.branch.includes("..") || !/^[0-9A-Za-z._/-]+$/.test(journal.previous.branch)) || typeof journal.distSnapshot?.path !== "string" || path.resolve(journal.distSnapshot.path) !== path.join(journal.transactionDir, "dist.tar.gz") || !/^[a-f0-9]{64}$/.test(journal.distSnapshot?.sha256 ?? "") || !Number.isSafeInteger(journal.distSnapshot?.size) || (journal.distSnapshot?.size ?? -1) <= 0) {
|
|
60
|
+
throw new Error("Local source paired update journal is invalid");
|
|
61
|
+
}
|
|
62
|
+
const previous = validateRelease(journal.previous, "previous");
|
|
63
|
+
const needsTarget = new Set([
|
|
64
|
+
"app-active",
|
|
65
|
+
"signer-active",
|
|
66
|
+
"gateway-verified",
|
|
67
|
+
"committing"
|
|
68
|
+
]).has(journal.phase);
|
|
69
|
+
const target = journal.target === null ? null : validateRelease(journal.target, "target");
|
|
70
|
+
if (needsTarget && target === null) {
|
|
71
|
+
throw new Error("Local source paired update journal is missing its target release identity");
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
...journal,
|
|
75
|
+
sourceRoot: path.resolve(journal.sourceRoot),
|
|
76
|
+
previous: {
|
|
77
|
+
...previous,
|
|
78
|
+
branch: journal.previous.branch
|
|
79
|
+
},
|
|
80
|
+
target
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
async function writeJournal(context, journal, phase = journal.phase, exclusive = false) {
|
|
84
|
+
const next = validateJournal(context, {
|
|
85
|
+
...journal,
|
|
86
|
+
phase,
|
|
87
|
+
updatedAt: new Date().toISOString()
|
|
88
|
+
});
|
|
89
|
+
await fs.mkdir(context.updateRoot, {
|
|
90
|
+
recursive: true,
|
|
91
|
+
mode: 448
|
|
92
|
+
});
|
|
93
|
+
if (exclusive) {
|
|
94
|
+
const handle = await fs.open(context.journalPath, "wx", 384);
|
|
95
|
+
try {
|
|
96
|
+
await handle.writeFile(`${JSON.stringify(next, null, 2)}\n`);
|
|
97
|
+
await handle.sync();
|
|
98
|
+
} finally {
|
|
99
|
+
await handle.close();
|
|
100
|
+
}
|
|
101
|
+
} else {
|
|
102
|
+
const temporary = `${context.journalPath}.tmp-${process.pid}-${Date.now()}`;
|
|
103
|
+
const handle = await fs.open(temporary, "wx", 384);
|
|
104
|
+
try {
|
|
105
|
+
await handle.writeFile(`${JSON.stringify(next, null, 2)}\n`);
|
|
106
|
+
await handle.sync();
|
|
107
|
+
} finally {
|
|
108
|
+
await handle.close();
|
|
109
|
+
}
|
|
110
|
+
await fs.rename(temporary, context.journalPath);
|
|
111
|
+
}
|
|
112
|
+
await fsyncPath(context.updateRoot);
|
|
113
|
+
return next;
|
|
114
|
+
}
|
|
115
|
+
async function readLocalSourcePairedUpdateJournal(env = process.env) {
|
|
116
|
+
const context = resolveContext(env);
|
|
117
|
+
try {
|
|
118
|
+
return validateJournal(context, JSON.parse(await fs.readFile(context.journalPath, "utf8")));
|
|
119
|
+
} catch (error) {
|
|
120
|
+
if (error.code === "ENOENT") {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
throw error;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
async function runExact(argv, options) {
|
|
127
|
+
const result = await runCommandWithTimeout(argv, {
|
|
128
|
+
cwd: options.cwd,
|
|
129
|
+
timeoutMs: options.timeoutMs,
|
|
130
|
+
env: options.env
|
|
131
|
+
});
|
|
132
|
+
if (result.code !== 0) {
|
|
133
|
+
const detail = (result.stderr || result.stdout).trim().split("\n").slice(-5).join("\n");
|
|
134
|
+
throw new Error(`${options.label} failed${detail ? `: ${detail}` : ""}`);
|
|
135
|
+
}
|
|
136
|
+
return result.stdout.trim();
|
|
137
|
+
}
|
|
138
|
+
async function readGitHead(sourceRoot, timeoutMs, env) {
|
|
139
|
+
const sha = await runExact([
|
|
140
|
+
"git",
|
|
141
|
+
"-C",
|
|
142
|
+
sourceRoot,
|
|
143
|
+
"rev-parse",
|
|
144
|
+
"HEAD"
|
|
145
|
+
], {
|
|
146
|
+
cwd: sourceRoot,
|
|
147
|
+
timeoutMs,
|
|
148
|
+
env,
|
|
149
|
+
label: "git HEAD verification"
|
|
150
|
+
});
|
|
151
|
+
if (!SHA_PATTERN.test(sha)) {
|
|
152
|
+
throw new Error("Source checkout did not report an exact Git commit");
|
|
153
|
+
}
|
|
154
|
+
return sha;
|
|
155
|
+
}
|
|
156
|
+
async function readPackageVersion(sourceRoot) {
|
|
157
|
+
const parsed = JSON.parse(await fs.readFile(path.join(sourceRoot, "package.json"), "utf8"));
|
|
158
|
+
const version = typeof parsed.version === "string" ? parsed.version.trim() : "";
|
|
159
|
+
if (!VERSION_PATTERN.test(version)) {
|
|
160
|
+
throw new Error("Source checkout package.json has no exact release version");
|
|
161
|
+
}
|
|
162
|
+
return version;
|
|
163
|
+
}
|
|
164
|
+
async function copyController(sourceRoot, transactionDir) {
|
|
165
|
+
const controllerDir = path.join(transactionDir, "controller");
|
|
166
|
+
await fs.mkdir(controllerDir, {
|
|
167
|
+
recursive: true,
|
|
168
|
+
mode: 448
|
|
169
|
+
});
|
|
170
|
+
for (const name of ["fased-managed-updater.mjs", "managed-runtime-layout.mjs"]) {
|
|
171
|
+
const source = path.join(sourceRoot, "scripts", name);
|
|
172
|
+
const stat = await fs.lstat(source);
|
|
173
|
+
if (!stat.isFile() || stat.isSymbolicLink()) {
|
|
174
|
+
throw new Error(`Source checkout is missing a safe signer transaction controller: ${source}`);
|
|
175
|
+
}
|
|
176
|
+
const destination = path.join(controllerDir, name);
|
|
177
|
+
await fs.copyFile(source, destination);
|
|
178
|
+
await fs.chmod(destination, name.endsWith("updater.mjs") ? 448 : 384);
|
|
179
|
+
await fsyncPath(destination);
|
|
180
|
+
}
|
|
181
|
+
await fsyncPath(controllerDir);
|
|
182
|
+
return path.join(controllerDir, "fased-managed-updater.mjs");
|
|
183
|
+
}
|
|
184
|
+
async function isLocalSourceSignerConfigured(env = process.env) {
|
|
185
|
+
const stateDir = resolveContext(env).stateDir;
|
|
186
|
+
for (const candidate of [path.join(stateDir, "bin", "fased-signerd"), path.join(stateDir, "wallet", "signerd-v2.db")]) {
|
|
187
|
+
const found = await fs.lstat(candidate).then((stat) => stat.isFile() && !stat.isSymbolicLink()).catch(() => false);
|
|
188
|
+
if (found) {
|
|
189
|
+
return true;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
try {
|
|
193
|
+
const registry = JSON.parse(await fs.readFile(path.join(stateDir, "wallet", "provider-registry.v1.json"), "utf8"));
|
|
194
|
+
return (registry.wallets ?? []).some((wallet) => wallet?.providerId === "local-socket-signer");
|
|
195
|
+
} catch {
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
async function prepareLocalSourcePairedUpdate(params) {
|
|
200
|
+
const env = params.env ?? process.env;
|
|
201
|
+
const context = resolveContext(env);
|
|
202
|
+
if (await readLocalSourcePairedUpdateJournal(env)) {
|
|
203
|
+
throw new Error("An unfinished Local source app/signer transaction must be recovered first");
|
|
204
|
+
}
|
|
205
|
+
const sourceRoot = path.resolve(params.sourceRoot);
|
|
206
|
+
const previousSha = await readGitHead(sourceRoot, params.timeoutMs, env);
|
|
207
|
+
const previousVersion = await readPackageVersion(sourceRoot);
|
|
208
|
+
const branchResult = await runCommandWithTimeout([
|
|
209
|
+
"git",
|
|
210
|
+
"-C",
|
|
211
|
+
sourceRoot,
|
|
212
|
+
"symbolic-ref",
|
|
213
|
+
"--quiet",
|
|
214
|
+
"--short",
|
|
215
|
+
"HEAD"
|
|
216
|
+
], {
|
|
217
|
+
cwd: sourceRoot,
|
|
218
|
+
timeoutMs: params.timeoutMs,
|
|
219
|
+
env
|
|
220
|
+
});
|
|
221
|
+
const branch = branchResult.code === 0 && branchResult.stdout.trim() ? branchResult.stdout.trim() : null;
|
|
222
|
+
if (branch !== null && (branch.includes("..") || !/^[0-9A-Za-z._/-]+$/.test(branch))) {
|
|
223
|
+
throw new Error("Source checkout branch name is unsafe for transactional rollback");
|
|
224
|
+
}
|
|
225
|
+
const transactionId = randomUUID();
|
|
226
|
+
const transactionDir = path.join(context.transactionsDir, transactionId);
|
|
227
|
+
await fs.mkdir(transactionDir, {
|
|
228
|
+
recursive: true,
|
|
229
|
+
mode: 448
|
|
230
|
+
});
|
|
231
|
+
try {
|
|
232
|
+
const distRoot = path.join(sourceRoot, "dist");
|
|
233
|
+
const distStat = await fs.lstat(distRoot);
|
|
234
|
+
if (!distStat.isDirectory() || distStat.isSymbolicLink()) {
|
|
235
|
+
throw new Error("Source checkout has no safe built dist directory to snapshot");
|
|
236
|
+
}
|
|
237
|
+
const distSnapshotPath = path.join(transactionDir, "dist.tar.gz");
|
|
238
|
+
await tar.c({
|
|
239
|
+
cwd: sourceRoot,
|
|
240
|
+
file: distSnapshotPath,
|
|
241
|
+
gzip: true,
|
|
242
|
+
portable: true,
|
|
243
|
+
noMtime: true
|
|
244
|
+
}, ["dist"]);
|
|
245
|
+
await fs.chmod(distSnapshotPath, 384);
|
|
246
|
+
await fsyncPath(distSnapshotPath);
|
|
247
|
+
const distSnapshotStat = await fs.lstat(distSnapshotPath);
|
|
248
|
+
const controllerPath = await copyController(sourceRoot, transactionDir);
|
|
249
|
+
const now = new Date().toISOString();
|
|
250
|
+
const journal = {
|
|
251
|
+
schemaVersion: 1,
|
|
252
|
+
kind: "source-checkout",
|
|
253
|
+
transactionId,
|
|
254
|
+
transactionDir,
|
|
255
|
+
sourceRoot,
|
|
256
|
+
controllerPath,
|
|
257
|
+
phase: "prepared",
|
|
258
|
+
previous: {
|
|
259
|
+
sha: previousSha,
|
|
260
|
+
version: previousVersion,
|
|
261
|
+
branch
|
|
262
|
+
},
|
|
263
|
+
target: null,
|
|
264
|
+
distSnapshot: {
|
|
265
|
+
path: distSnapshotPath,
|
|
266
|
+
sha256: await sha256File(distSnapshotPath),
|
|
267
|
+
size: distSnapshotStat.size
|
|
268
|
+
},
|
|
269
|
+
createdAt: now,
|
|
270
|
+
updatedAt: now
|
|
271
|
+
};
|
|
272
|
+
await fsyncPath(transactionDir);
|
|
273
|
+
return await writeJournal(context, journal, "prepared", true);
|
|
274
|
+
} catch (error) {
|
|
275
|
+
await fs.rm(transactionDir, {
|
|
276
|
+
recursive: true,
|
|
277
|
+
force: true
|
|
278
|
+
});
|
|
279
|
+
throw error;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
async function markLocalSourceAppActive(params) {
|
|
283
|
+
if (params.journal.phase !== "prepared") {
|
|
284
|
+
throw new Error(`Cannot activate source app from phase ${params.journal.phase}`);
|
|
285
|
+
}
|
|
286
|
+
const context = resolveContext(params.env ?? process.env);
|
|
287
|
+
const target = validateRelease({
|
|
288
|
+
sha: params.targetSha,
|
|
289
|
+
version: params.targetVersion
|
|
290
|
+
}, "target");
|
|
291
|
+
return await writeJournal(context, {
|
|
292
|
+
...params.journal,
|
|
293
|
+
target
|
|
294
|
+
}, "app-active");
|
|
295
|
+
}
|
|
296
|
+
async function runSignerController(params) {
|
|
297
|
+
const args = [
|
|
298
|
+
params.journal.controllerPath,
|
|
299
|
+
"local-signer",
|
|
300
|
+
params.action
|
|
301
|
+
];
|
|
302
|
+
if (params.action === "verify") {
|
|
303
|
+
if (!params.journal.target) {
|
|
304
|
+
throw new Error("Cannot verify a Local signer without a target release");
|
|
305
|
+
}
|
|
306
|
+
args.push("--version", params.journal.target.version, "--expected-commit", params.journal.target.sha, "--timeout", String(Math.ceil(params.timeoutMs / 1e3)));
|
|
307
|
+
}
|
|
308
|
+
await runExact([process.execPath, ...args], {
|
|
309
|
+
cwd: path.dirname(params.journal.controllerPath),
|
|
310
|
+
timeoutMs: params.timeoutMs,
|
|
311
|
+
env: params.env,
|
|
312
|
+
label: `Local signer ${params.action}`
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
async function activateLocalSourceSigner(params) {
|
|
316
|
+
if (params.journal.phase !== "app-active" || !params.journal.target) {
|
|
317
|
+
throw new Error(`Cannot activate Local signer from phase ${params.journal.phase}`);
|
|
318
|
+
}
|
|
319
|
+
const env = params.env ?? process.env;
|
|
320
|
+
const installer = path.join(params.journal.sourceRoot, "scripts", "install-fased-signerd.sh");
|
|
321
|
+
const stat = await fs.lstat(installer);
|
|
322
|
+
if (!stat.isFile() || stat.isSymbolicLink()) {
|
|
323
|
+
throw new Error("Updated source checkout is missing its safe Local signer installer");
|
|
324
|
+
}
|
|
325
|
+
await runExact([
|
|
326
|
+
"bash",
|
|
327
|
+
installer,
|
|
328
|
+
"--version",
|
|
329
|
+
params.journal.target.version,
|
|
330
|
+
"--expected-commit",
|
|
331
|
+
params.journal.target.sha,
|
|
332
|
+
"--defer-commit"
|
|
333
|
+
], {
|
|
334
|
+
cwd: params.journal.sourceRoot,
|
|
335
|
+
timeoutMs: params.timeoutMs,
|
|
336
|
+
env,
|
|
337
|
+
label: "Local signer prepare and activation"
|
|
338
|
+
});
|
|
339
|
+
return await writeJournal(resolveContext(env), params.journal, "signer-active");
|
|
340
|
+
}
|
|
341
|
+
async function verifyLocalSourceSigner(params) {
|
|
342
|
+
if (!new Set(["signer-active", "gateway-verified"]).has(params.journal.phase)) {
|
|
343
|
+
throw new Error(`Cannot verify Local signer from phase ${params.journal.phase}`);
|
|
344
|
+
}
|
|
345
|
+
await runSignerController({
|
|
346
|
+
journal: params.journal,
|
|
347
|
+
action: "verify",
|
|
348
|
+
timeoutMs: params.timeoutMs,
|
|
349
|
+
env: params.env ?? process.env
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
async function markLocalSourceGatewayVerified(journal, env = process.env) {
|
|
353
|
+
if (journal.phase !== "signer-active") {
|
|
354
|
+
throw new Error(`Cannot record Gateway verification from phase ${journal.phase}`);
|
|
355
|
+
}
|
|
356
|
+
return await writeJournal(resolveContext(env), journal, "gateway-verified");
|
|
357
|
+
}
|
|
358
|
+
async function removeTransaction(journal, env) {
|
|
359
|
+
const context = resolveContext(env);
|
|
360
|
+
await fs.rm(context.journalPath, { force: true });
|
|
361
|
+
await fsyncPath(context.updateRoot);
|
|
362
|
+
await fs.rm(journal.transactionDir, {
|
|
363
|
+
recursive: true,
|
|
364
|
+
force: true
|
|
365
|
+
});
|
|
366
|
+
await fsyncPath(context.transactionsDir);
|
|
367
|
+
}
|
|
368
|
+
async function commitLocalSourcePairedUpdate(params) {
|
|
369
|
+
const env = params.env ?? process.env;
|
|
370
|
+
let journal = params.journal;
|
|
371
|
+
if (journal.phase !== "gateway-verified" && journal.phase !== "committing") {
|
|
372
|
+
throw new Error(`Cannot commit Local source pair from phase ${journal.phase}`);
|
|
373
|
+
}
|
|
374
|
+
if (journal.phase !== "committing") {
|
|
375
|
+
journal = await writeJournal(resolveContext(env), journal, "committing");
|
|
376
|
+
}
|
|
377
|
+
await runSignerController({
|
|
378
|
+
journal,
|
|
379
|
+
action: "commit",
|
|
380
|
+
timeoutMs: params.timeoutMs,
|
|
381
|
+
env
|
|
382
|
+
});
|
|
383
|
+
await removeTransaction(journal, env);
|
|
384
|
+
}
|
|
385
|
+
async function restoreSourceApplication(params) {
|
|
386
|
+
const { journal, timeoutMs, env } = params;
|
|
387
|
+
const snapshotStat = await fs.lstat(journal.distSnapshot.path);
|
|
388
|
+
if (!snapshotStat.isFile() || snapshotStat.isSymbolicLink() || snapshotStat.size !== journal.distSnapshot.size || await sha256File(journal.distSnapshot.path) !== journal.distSnapshot.sha256) {
|
|
389
|
+
throw new Error("Local source rollback dist snapshot failed integrity verification");
|
|
390
|
+
}
|
|
391
|
+
if (journal.previous.branch) {
|
|
392
|
+
await runExact([
|
|
393
|
+
"git",
|
|
394
|
+
"-C",
|
|
395
|
+
journal.sourceRoot,
|
|
396
|
+
"checkout",
|
|
397
|
+
journal.previous.branch
|
|
398
|
+
], {
|
|
399
|
+
cwd: journal.sourceRoot,
|
|
400
|
+
timeoutMs,
|
|
401
|
+
env,
|
|
402
|
+
label: "source rollback branch checkout"
|
|
403
|
+
});
|
|
404
|
+
await runExact([
|
|
405
|
+
"git",
|
|
406
|
+
"-C",
|
|
407
|
+
journal.sourceRoot,
|
|
408
|
+
"reset",
|
|
409
|
+
"--hard",
|
|
410
|
+
journal.previous.sha
|
|
411
|
+
], {
|
|
412
|
+
cwd: journal.sourceRoot,
|
|
413
|
+
timeoutMs,
|
|
414
|
+
env,
|
|
415
|
+
label: "source rollback commit restore"
|
|
416
|
+
});
|
|
417
|
+
} else {
|
|
418
|
+
await runExact([
|
|
419
|
+
"git",
|
|
420
|
+
"-C",
|
|
421
|
+
journal.sourceRoot,
|
|
422
|
+
"checkout",
|
|
423
|
+
"--detach",
|
|
424
|
+
journal.previous.sha
|
|
425
|
+
], {
|
|
426
|
+
cwd: journal.sourceRoot,
|
|
427
|
+
timeoutMs,
|
|
428
|
+
env,
|
|
429
|
+
label: "source rollback detached commit restore"
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
await runExact([
|
|
433
|
+
"pnpm",
|
|
434
|
+
"install",
|
|
435
|
+
"--offline",
|
|
436
|
+
"--frozen-lockfile"
|
|
437
|
+
], {
|
|
438
|
+
cwd: journal.sourceRoot,
|
|
439
|
+
timeoutMs,
|
|
440
|
+
env,
|
|
441
|
+
label: "offline source dependency rollback"
|
|
442
|
+
});
|
|
443
|
+
await fs.rm(path.join(journal.sourceRoot, "dist"), {
|
|
444
|
+
recursive: true,
|
|
445
|
+
force: true
|
|
446
|
+
});
|
|
447
|
+
await tar.x({
|
|
448
|
+
cwd: journal.sourceRoot,
|
|
449
|
+
file: journal.distSnapshot.path,
|
|
450
|
+
strict: true,
|
|
451
|
+
filter: (entryPath) => entryPath === "dist" || entryPath.startsWith("dist/")
|
|
452
|
+
});
|
|
453
|
+
if (await readGitHead(journal.sourceRoot, timeoutMs, env) !== journal.previous.sha) {
|
|
454
|
+
throw new Error("Local source rollback restored the wrong Git commit");
|
|
455
|
+
}
|
|
456
|
+
if (await readPackageVersion(journal.sourceRoot) !== journal.previous.version) {
|
|
457
|
+
throw new Error("Local source rollback restored the wrong package version");
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
async function rollbackLocalSourcePairedUpdate(params) {
|
|
461
|
+
const env = params.env ?? process.env;
|
|
462
|
+
let journal = params.journal;
|
|
463
|
+
if (journal.phase !== "rolling-back") {
|
|
464
|
+
journal = await writeJournal(resolveContext(env), journal, "rolling-back");
|
|
465
|
+
}
|
|
466
|
+
const failures = [];
|
|
467
|
+
try {
|
|
468
|
+
await runSignerController({
|
|
469
|
+
journal,
|
|
470
|
+
action: "rollback",
|
|
471
|
+
timeoutMs: params.timeoutMs,
|
|
472
|
+
env
|
|
473
|
+
});
|
|
474
|
+
} catch (error) {
|
|
475
|
+
failures.push(`signer: ${String(error)}`);
|
|
476
|
+
}
|
|
477
|
+
if (failures.length === 0) {
|
|
478
|
+
try {
|
|
479
|
+
await restoreSourceApplication({
|
|
480
|
+
journal,
|
|
481
|
+
timeoutMs: params.timeoutMs,
|
|
482
|
+
env
|
|
483
|
+
});
|
|
484
|
+
} catch (error) {
|
|
485
|
+
failures.push(`application: ${String(error)}`);
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
if (failures.length > 0) {
|
|
489
|
+
throw new Error(`Local source paired rollback is incomplete (${failures.join("; ")}). Re-run fased update after correcting the failure.`);
|
|
490
|
+
}
|
|
491
|
+
await removeTransaction(journal, env);
|
|
492
|
+
}
|
|
493
|
+
async function recoverLocalSourcePairedUpdate(params) {
|
|
494
|
+
const env = params.env ?? process.env;
|
|
495
|
+
const journal = await readLocalSourcePairedUpdateJournal(env);
|
|
496
|
+
if (!journal) {
|
|
497
|
+
return "none";
|
|
498
|
+
}
|
|
499
|
+
if (journal.phase === "gateway-verified" || journal.phase === "committing") {
|
|
500
|
+
await commitLocalSourcePairedUpdate({
|
|
501
|
+
journal,
|
|
502
|
+
timeoutMs: params.timeoutMs,
|
|
503
|
+
env
|
|
504
|
+
});
|
|
505
|
+
return "committed";
|
|
506
|
+
}
|
|
507
|
+
await rollbackLocalSourcePairedUpdate({
|
|
508
|
+
journal,
|
|
509
|
+
timeoutMs: params.timeoutMs,
|
|
510
|
+
env
|
|
511
|
+
});
|
|
512
|
+
return "rolled-back";
|
|
513
|
+
}
|
|
514
|
+
async function assertLocalSourcePairedGatewayStartAllowed(params) {
|
|
515
|
+
const env = params.env ?? process.env;
|
|
516
|
+
const journal = await readLocalSourcePairedUpdateJournal(env);
|
|
517
|
+
if (!journal) {
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
if (journal.phase !== "signer-active" && journal.phase !== "gateway-verified" && journal.phase !== "committing") {
|
|
521
|
+
throw new Error(`Gateway startup is blocked by an unfinished Local source app/signer update (${journal.phase}). Run fased update to recover it.`);
|
|
522
|
+
}
|
|
523
|
+
if (!journal.target || path.resolve(params.runtimeRoot) !== journal.sourceRoot) {
|
|
524
|
+
throw new Error("Gateway startup is blocked because the source update target root does not match");
|
|
525
|
+
}
|
|
526
|
+
const timeoutMs = params.timeoutMs ?? 5e3;
|
|
527
|
+
const [sha, version] = await Promise.all([readGitHead(journal.sourceRoot, timeoutMs, env), readPackageVersion(journal.sourceRoot)]);
|
|
528
|
+
if (sha !== journal.target.sha || version !== journal.target.version) {
|
|
529
|
+
throw new Error("Gateway startup is blocked because the source update target identity changed");
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
const __testing = {
|
|
533
|
+
resolveContext,
|
|
534
|
+
validateJournal
|
|
535
|
+
};
|
|
536
|
+
|
|
537
|
+
//#endregion
|
|
538
|
+
export { activateLocalSourceSigner, assertLocalSourcePairedGatewayStartAllowed, commitLocalSourcePairedUpdate, isLocalSourceSignerConfigured, markLocalSourceAppActive, markLocalSourceGatewayVerified, prepareLocalSourcePairedUpdate, readLocalSourcePairedUpdateJournal, recoverLocalSourcePairedUpdate, rollbackLocalSourcePairedUpdate, verifyLocalSourceSigner };
|
package/dist/infra/restart.js
CHANGED
|
@@ -151,44 +151,75 @@ function deferGatewayRestartUntilIdle(opts) {
|
|
|
151
151
|
const pollMs = Math.max(10, Math.floor(pollMsRaw));
|
|
152
152
|
const maxWaitMsRaw = opts.maxWaitMs ?? DEFAULT_DEFERRAL_MAX_WAIT_MS;
|
|
153
153
|
const maxWaitMs = Math.max(pollMs, Math.floor(maxWaitMsRaw));
|
|
154
|
-
let
|
|
154
|
+
let pendingPoll = null;
|
|
155
|
+
let pending = false;
|
|
156
|
+
const handle = {
|
|
157
|
+
cancel: () => {
|
|
158
|
+
if (!pending || !pendingPoll) {
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
clearInterval(pendingPoll);
|
|
162
|
+
pendingPoll = null;
|
|
163
|
+
pending = false;
|
|
164
|
+
return true;
|
|
165
|
+
},
|
|
166
|
+
isPending: () => pending
|
|
167
|
+
};
|
|
168
|
+
let pendingCount;
|
|
155
169
|
try {
|
|
156
|
-
|
|
170
|
+
pendingCount = opts.getPendingCount();
|
|
157
171
|
} catch (err) {
|
|
158
172
|
opts.hooks?.onCheckError?.(err);
|
|
159
173
|
emitGatewayRestart();
|
|
160
|
-
return;
|
|
174
|
+
return handle;
|
|
161
175
|
}
|
|
162
|
-
if (
|
|
176
|
+
if (pendingCount <= 0) {
|
|
163
177
|
opts.hooks?.onReady?.();
|
|
164
178
|
emitGatewayRestart();
|
|
165
|
-
return;
|
|
179
|
+
return handle;
|
|
166
180
|
}
|
|
167
|
-
opts.hooks?.onDeferring?.(
|
|
181
|
+
opts.hooks?.onDeferring?.(pendingCount);
|
|
168
182
|
const startedAt = Date.now();
|
|
169
|
-
|
|
183
|
+
pending = true;
|
|
184
|
+
pendingPoll = setInterval(() => {
|
|
170
185
|
let current;
|
|
171
186
|
try {
|
|
172
187
|
current = opts.getPendingCount();
|
|
173
188
|
} catch (err) {
|
|
174
|
-
|
|
189
|
+
if (!pending) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
pending = false;
|
|
193
|
+
if (pendingPoll) {
|
|
194
|
+
clearInterval(pendingPoll);
|
|
195
|
+
pendingPoll = null;
|
|
196
|
+
}
|
|
175
197
|
opts.hooks?.onCheckError?.(err);
|
|
176
198
|
emitGatewayRestart();
|
|
177
199
|
return;
|
|
178
200
|
}
|
|
179
201
|
if (current <= 0) {
|
|
180
|
-
|
|
202
|
+
pending = false;
|
|
203
|
+
if (pendingPoll) {
|
|
204
|
+
clearInterval(pendingPoll);
|
|
205
|
+
pendingPoll = null;
|
|
206
|
+
}
|
|
181
207
|
opts.hooks?.onReady?.();
|
|
182
208
|
emitGatewayRestart();
|
|
183
209
|
return;
|
|
184
210
|
}
|
|
185
211
|
const elapsedMs = Date.now() - startedAt;
|
|
186
212
|
if (elapsedMs >= maxWaitMs) {
|
|
187
|
-
|
|
213
|
+
pending = false;
|
|
214
|
+
if (pendingPoll) {
|
|
215
|
+
clearInterval(pendingPoll);
|
|
216
|
+
pendingPoll = null;
|
|
217
|
+
}
|
|
188
218
|
opts.hooks?.onTimeout?.(current, elapsedMs);
|
|
189
219
|
emitGatewayRestart();
|
|
190
220
|
}
|
|
191
221
|
}, pollMs);
|
|
222
|
+
return handle;
|
|
192
223
|
}
|
|
193
224
|
function formatSpawnDetail(result) {
|
|
194
225
|
const clean = (value) => {
|