@askexenow/exe-os 0.9.382 → 0.9.384
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/delivery/catalog.json +1254 -0
- package/deploy/compose/.env.customer.example +5 -5
- package/deploy/compose/.env.example +3 -3
- package/deploy/compose/docker-compose.yml +1 -1
- package/deploy/compose/generate-env.ts +65 -9
- package/deploy/compose/setup.sh +205 -7
- package/deploy/compose/sso-edge/default.conf.template +45 -0
- package/deploy/compose/sso-edge/sso-redirect.conf +11 -2
- package/deploy/stack-manifests/v0.9.30-apps.json +1 -1
- package/deploy/stack-manifests/v0.9.json +254 -2
- package/dist/.dist-verified.json +3 -3
- package/dist/{active-agent-GFUUCFLD.js → active-agent-F5V4E4UL.js} +7 -7
- package/dist/{active-agent-LE6FE6SO.js → active-agent-YTBB4ZQM.js} +7 -7
- package/dist/{agent-defs-generator-EIUA3SH5.js → agent-defs-generator-7TFISIJQ.js} +6 -6
- package/dist/{agent-loop-7ZRH56EX.js → agent-loop-EZ7LDAGD.js} +1 -1
- package/dist/{agentic-ontology-67JGSP7G.js → agentic-ontology-XVTUVV7W.js} +1 -1
- package/dist/{artifact-backup-NYXAYASJ.js → artifact-backup-TF6YWQT2.js} +5 -5
- package/dist/{backfill-gate-KWJQ35YX.js → backfill-gate-FWYLCGNJ.js} +3 -3
- package/dist/{backfill-metadata-RQYG2WUJ.js → backfill-metadata-J6MXIDCW.js} +10 -10
- package/dist/{background-jobs-6VMD55PK.js → background-jobs-V3DZRFKU.js} +3 -3
- package/dist/{backup-verify-HC4YDSGN.js → backup-verify-6DVBQMDP.js} +67 -18
- package/dist/{behavior-injection-6HSXP43Q.js → behavior-injection-XDA7ZCYN.js} +21 -20
- package/dist/{behavior-promotion-SJDQ2Y3U.js → behavior-promotion-4VLQ7LXK.js} +20 -19
- package/dist/{behaviors-6ITLA2CK.js → behaviors-SCCZP7RZ.js} +19 -18
- package/dist/bin/age-ontology-load.js +3 -3
- package/dist/bin/agentic-ontology-backfill.js +12 -12
- package/dist/bin/agentic-reflection-backfill.js +13 -13
- package/dist/bin/agentic-semantic-label.js +12 -12
- package/dist/bin/backfill-conversations.js +17 -16
- package/dist/bin/backfill-responses.js +17 -16
- package/dist/bin/backfill-vectors.js +23 -22
- package/dist/bin/bulk-sync-postgres.js +28 -27
- package/dist/bin/cc-doctor.js +17 -16
- package/dist/bin/cleanup-stale-review-tasks.js +29 -28
- package/dist/bin/cli.js +35 -26
- package/dist/bin/deferred-daemon-restart.js +124 -123
- package/dist/bin/exe-actions.js +1 -1
- package/dist/bin/exe-agent-config.js +6 -6
- package/dist/bin/exe-agent.js +22 -22
- package/dist/bin/exe-assign.js +19 -18
- package/dist/bin/exe-boot.js +57 -56
- package/dist/bin/exe-call.js +7 -7
- package/dist/bin/exe-cicd.js +38 -8
- package/dist/bin/exe-cloud.js +30 -29
- package/dist/bin/exe-config-dump.js +6 -6
- package/dist/bin/exe-dispatch.js +30 -29
- package/dist/bin/exe-doctor.js +11 -11
- package/dist/bin/exe-export-behaviors.js +23 -22
- package/dist/bin/exe-forget.js +13 -13
- package/dist/bin/exe-gateway.js +47 -14
- package/dist/bin/exe-grant.js +6 -6
- package/dist/bin/exe-healthcheck.js +17 -16
- package/dist/bin/exe-heartbeat.js +41 -35
- package/dist/bin/exe-kill.js +35 -34
- package/dist/bin/exe-launch-agent.js +43 -42
- package/dist/bin/exe-mcp.js +9 -9
- package/dist/bin/exe-memory-reads.js +10 -10
- package/dist/bin/exe-new-employee.js +11 -11
- package/dist/bin/exe-os-mcp-proxy.js +9 -9
- package/dist/bin/exe-pending-messages.js +30 -29
- package/dist/bin/exe-pending-notifications.js +29 -28
- package/dist/bin/exe-pending-reviews.js +30 -29
- package/dist/bin/exe-preflight.js +1 -1
- package/dist/bin/exe-rename.js +9 -9
- package/dist/bin/exe-review.js +34 -33
- package/dist/bin/exe-search.js +12 -12
- package/dist/bin/exe-session-cleanup.js +35 -34
- package/dist/bin/exe-settings.js +29 -28
- package/dist/bin/exe-start-codex.js +30 -29
- package/dist/bin/exe-start-opencode.js +27 -26
- package/dist/bin/exe-status.js +31 -30
- package/dist/bin/exe-support.js +5 -5
- package/dist/bin/exe-team.js +7 -7
- package/dist/bin/exe-verify-running-images.js +1 -1
- package/dist/bin/exe-watchdog.js +8 -8
- package/dist/bin/generate-hook-manifest.js +7 -1
- package/dist/bin/git-sweep.js +30 -29
- package/dist/bin/graph-backfill.js +12 -12
- package/dist/bin/graph-export.js +11 -11
- package/dist/bin/hooks-cli.js +1 -1
- package/dist/bin/import-history.js +15 -15
- package/dist/bin/install.js +130 -129
- package/dist/bin/intercom-check.js +11 -7
- package/dist/bin/mcp-sessions.js +2 -2
- package/dist/bin/orchestration-metrics.js +7 -7
- package/dist/bin/postgres-agentic-reflection-backfill.js +5 -5
- package/dist/bin/postgres-agentic-semantic-backfill.js +4 -4
- package/dist/bin/reconcile-backlog.js +2 -2
- package/dist/bin/registry-proxy.js +1 -1
- package/dist/bin/repair-document-chunks.js +161 -0
- package/dist/bin/scan-tasks.js +30 -29
- package/dist/bin/setup.js +5 -5
- package/dist/bin/shard-migrate.js +11 -11
- package/dist/bin/stack-update.js +625 -33
- package/dist/bin/update.js +96 -22
- package/dist/bin/verify-stack.js +2 -2
- package/dist/bin/vps-health-gate.js +1 -1
- package/dist/{boot-generation-L55QANCX.js → boot-generation-Q7LGQ3AO.js} +6 -6
- package/dist/{boot-review-sections-AON5ZCR2.js → boot-review-sections-G5774FR5.js} +28 -27
- package/dist/{branch-hygiene-QLD77IMJ.js → branch-hygiene-44WLSOZR.js} +2 -2
- package/dist/{branding-I6KIMB7F.js → branding-KMWCY5HZ.js} +3 -3
- package/dist/build-manifest.json +1259 -1219
- package/dist/{capability-cards-WTOXY7O6.js → capability-cards-I3RHCF4F.js} +5 -5
- package/dist/{capacity-monitor-ZLG7FSWM.js → capacity-monitor-7I7GDONU.js} +30 -29
- package/dist/{catchup-brief-QHY7D7N2.js → catchup-brief-3T5PARIR.js} +39 -36
- package/dist/check-image-pullability-2AIVB4BX.js +338 -0
- package/dist/{chunk-CTCCYKOV.js → chunk-2FKU4ZEO.js} +55 -29
- package/dist/{chunk-M7O7TGGU.js → chunk-2NW4LRDU.js} +1 -1
- package/dist/{chunk-XTFM4KMW.js → chunk-2PZTMSMG.js} +6 -6
- package/dist/{chunk-UWX6MMCX.js → chunk-3B6FLNLV.js} +1 -1
- package/dist/{chunk-GPJIBLP4.js → chunk-3DAEZILW.js} +1 -1
- package/dist/{chunk-NY6SBR4O.js → chunk-3FGBBJYM.js} +15 -3
- package/dist/{chunk-C4OZVVSG.js → chunk-3OX34OC3.js} +50 -18
- package/dist/{chunk-TXTXC3QG.js → chunk-3RGTLZNO.js} +12 -12
- package/dist/{chunk-PYRO25A5.js → chunk-3SUPEE6H.js} +10 -11
- package/dist/{chunk-PPMGQFLJ.js → chunk-3XY57PKT.js} +2 -2
- package/dist/{chunk-CRHI5QTZ.js → chunk-46VSBDUW.js} +2 -2
- package/dist/{chunk-VZT66WWP.js → chunk-4AAMFWJT.js} +2 -2
- package/dist/{chunk-4GZTBLJG.js → chunk-4AR5XKCH.js} +1 -1
- package/dist/{chunk-IHXW4VUI.js → chunk-5IADGFGR.js} +1 -1
- package/dist/{chunk-GLQEJOXE.js → chunk-5MVKTNZP.js} +57 -0
- package/dist/{chunk-AVMLC2MR.js → chunk-5U2IJBFV.js} +290 -41
- package/dist/{chunk-JUKDL5MF.js → chunk-6BJCDWSM.js} +1 -1
- package/dist/{chunk-6WWNK7UX.js → chunk-6FIC57PH.js} +1 -1
- package/dist/{chunk-ASUICGPX.js → chunk-6YDY6ZTD.js} +4 -4
- package/dist/{chunk-FU5O2REK.js → chunk-72V3S44T.js} +108 -29
- package/dist/{chunk-LTIIZHNA.js → chunk-7J2ZQ4XN.js} +1 -1
- package/dist/{chunk-7RI2CNXJ.js → chunk-7OTR2OET.js} +1 -1
- package/dist/{chunk-ZVBVPX4W.js → chunk-7UHZBVP3.js} +82 -51
- package/dist/{chunk-PTY2N23C.js → chunk-AGC2V7JS.js} +26 -13
- package/dist/{chunk-44VR3PFW.js → chunk-AHESD3KW.js} +1 -1
- package/dist/{chunk-NPGV4MZ3.js → chunk-ALRHGEAJ.js} +1 -1
- package/dist/{chunk-WJC6AAJN.js → chunk-ANVHWV2X.js} +2 -2
- package/dist/{chunk-AGZSGAEN.js → chunk-APL7HUE3.js} +105 -32
- package/dist/{chunk-7UH2JWBF.js → chunk-AZSTIAVL.js} +176 -11
- package/dist/chunk-AZXMR25O.js +545 -0
- package/dist/{chunk-WPWEBZ37.js → chunk-B7AMNZTC.js} +2 -2
- package/dist/{chunk-4CF5KUWH.js → chunk-BPVFZ6Q4.js} +3 -3
- package/dist/{chunk-XTQ7R2PA.js → chunk-BV2IET6B.js} +73 -17
- package/dist/{chunk-4F5CNI65.js → chunk-C5ISP5FO.js} +2 -2
- package/dist/{chunk-NPWNXJ3U.js → chunk-CH7BUBP3.js} +7 -7
- package/dist/{chunk-X5Q66EOG.js → chunk-CHIUS5QB.js} +16 -16
- package/dist/{chunk-ZG62LIK3.js → chunk-CIPDQRFO.js} +1 -1
- package/dist/{chunk-4PYIRIU6.js → chunk-CM7N5MBY.js} +5 -5
- package/dist/{chunk-L5YDAFUH.js → chunk-CYCIX7AW.js} +5 -5
- package/dist/{chunk-76YRJKKF.js → chunk-D3LXVAIQ.js} +28 -16
- package/dist/{chunk-2GNAHBRD.js → chunk-DMUOTCDN.js} +1 -1
- package/dist/{chunk-QMUFSRQX.js → chunk-DN3ZR3UE.js} +1 -1
- package/dist/{chunk-V3WLC5TJ.js → chunk-DRTJCG6B.js} +1 -1
- package/dist/{chunk-275WHBEN.js → chunk-DYVLEMKS.js} +1 -1
- package/dist/{chunk-O34F5EP5.js → chunk-DZN7SDY2.js} +1 -1
- package/dist/{chunk-ZDIXMHY7.js → chunk-E3ZM32LF.js} +8 -8
- package/dist/{chunk-N2HXR5MB.js → chunk-E7C2WNR5.js} +4 -4
- package/dist/{chunk-VVGXWVZU.js → chunk-EGOEB42T.js} +3 -3
- package/dist/{chunk-QV5CQLQH.js → chunk-EIOGV75A.js} +2 -2
- package/dist/{chunk-ZY4IGUOS.js → chunk-ELCRJGCH.js} +3 -3
- package/dist/{chunk-5QCIWWFA.js → chunk-ELEGH4DX.js} +130 -14
- package/dist/{chunk-S7CTCPSW.js → chunk-EOTZSAQL.js} +1 -1
- package/dist/{chunk-PPLQ4ECD.js → chunk-EUGEFBGV.js} +3 -3
- package/dist/{chunk-UFNCL6MS.js → chunk-EYMFVITZ.js} +1 -1
- package/dist/{chunk-F6H7GP2O.js → chunk-F4BBMIPG.js} +3 -3
- package/dist/{chunk-FNEZ4BWT.js → chunk-FEU6QEEL.js} +1 -1
- package/dist/{chunk-JKOC2L6P.js → chunk-FHIFTSPL.js} +1 -1
- package/dist/{chunk-4RTKETV3.js → chunk-FMIYFHLE.js} +3 -3
- package/dist/{chunk-TK544DEW.js → chunk-FVLNNNH6.js} +3 -3
- package/dist/{chunk-AY2U4NZ5.js → chunk-GL47M7NY.js} +85 -17
- package/dist/{chunk-DN24VTS5.js → chunk-GSLFH4AI.js} +25 -13
- package/dist/{chunk-CHO5SNWR.js → chunk-HA63SH5W.js} +1 -1
- package/dist/{chunk-4IK2K3B3.js → chunk-HME6ITKV.js} +1 -1
- package/dist/{chunk-H2T6TFJZ.js → chunk-HU3VD4MQ.js} +2 -2
- package/dist/{chunk-ZW32RI66.js → chunk-I5XIW2BP.js} +49 -11
- package/dist/{chunk-3CL2I3RG.js → chunk-IGJMS7C5.js} +2 -2
- package/dist/{chunk-BRPO6GOH.js → chunk-JA3Y5TV6.js} +2 -2
- package/dist/{chunk-SFFXAPYK.js → chunk-JDDM6C57.js} +1 -1
- package/dist/{chunk-W4EGAQXW.js → chunk-JFJP6ATJ.js} +2 -2
- package/dist/{chunk-ENCUOZXX.js → chunk-JFTUAV4J.js} +1 -1
- package/dist/{chunk-3UOQH2DJ.js → chunk-JJTPPAZY.js} +2568 -345
- package/dist/{chunk-A6QBAUJH.js → chunk-KILR4FBR.js} +4 -4
- package/dist/{chunk-CGFGNHSP.js → chunk-KTKIFXIP.js} +1 -1
- package/dist/{chunk-NCJBPXGM.js → chunk-KXYKSLW4.js} +108 -24
- package/dist/{chunk-3MUARHPO.js → chunk-L3VUW5M4.js} +1 -1
- package/dist/{chunk-GZOG2MAX.js → chunk-L5EPGGDP.js} +1 -1
- package/dist/{chunk-T7VSKWES.js → chunk-L63V25HS.js} +6 -5
- package/dist/{chunk-R4VNGRKU.js → chunk-LFBLQE2P.js} +1 -1
- package/dist/{chunk-W5MCOZTW.js → chunk-LFUBEHFW.js} +12 -2
- package/dist/{chunk-AIBIEP4R.js → chunk-LKTN22L6.js} +61 -25
- package/dist/{chunk-3KFQCFQB.js → chunk-LR5O2XWZ.js} +5 -5
- package/dist/{chunk-VUOAPKPI.js → chunk-LSNBTGW4.js} +1 -1
- package/dist/{chunk-P5U3GAWU.js → chunk-MB47DRF5.js} +2 -2
- package/dist/{chunk-HZESME3B.js → chunk-MC4IM2CC.js} +16 -13
- package/dist/{chunk-ZKJ5S23O.js → chunk-MFAOAIUE.js} +12 -9
- package/dist/{chunk-62J64CHO.js → chunk-MKM6D7JM.js} +26 -7
- package/dist/{chunk-ZIG7VPJV.js → chunk-MMS2HBRT.js} +15 -3
- package/dist/{chunk-FHSV4BSW.js → chunk-MOANZQXF.js} +12 -4
- package/dist/{chunk-RTZZBWQC.js → chunk-MPZ2AVNS.js} +16 -5
- package/dist/{chunk-AZ6KLVDX.js → chunk-MROSARM5.js} +2 -2
- package/dist/{chunk-RV2FFCDS.js → chunk-MUAWCFW6.js} +6 -2
- package/dist/{chunk-K4ESASPL.js → chunk-MUCNYSJP.js} +1 -1
- package/dist/{chunk-5QGKMP6T.js → chunk-NF5FOSLD.js} +1 -1
- package/dist/{chunk-CKOJP7JI.js → chunk-NKEFYE4R.js} +2 -2
- package/dist/{chunk-3SXHEQ7X.js → chunk-NPXIS2RY.js} +1 -1
- package/dist/{chunk-A5USSF66.js → chunk-NVFNADTX.js} +12 -8
- package/dist/{chunk-VVUO3RJS.js → chunk-NYLJQ2M2.js} +4 -4
- package/dist/{chunk-HIVOLPLD.js → chunk-OAFENIHN.js} +1 -1
- package/dist/{chunk-PMZHZQ6K.js → chunk-OBBO6EJR.js} +1 -1
- package/dist/{chunk-SS6EMDLL.js → chunk-P2UY34XE.js} +6 -6
- package/dist/{chunk-Y4T5IUEP.js → chunk-P3QQ52QK.js} +2 -2
- package/dist/{chunk-GGEKMY6G.js → chunk-P3UX5EH4.js} +4 -4
- package/dist/{chunk-F7IRZU5G.js → chunk-P4PIZOL2.js} +3 -3
- package/dist/{chunk-GEPFKUUR.js → chunk-P4XLIPB7.js} +1 -1
- package/dist/{chunk-GPUOUUHA.js → chunk-PCV52RYM.js} +1 -1
- package/dist/{chunk-XR3773KZ.js → chunk-PL4CFSQ7.js} +1 -1
- package/dist/{chunk-LLZNPOGB.js → chunk-PLII76NJ.js} +58 -0
- package/dist/{chunk-FT5PPV2C.js → chunk-PRDDPQLC.js} +5 -5
- package/dist/{chunk-BZ546I4Q.js → chunk-PUBA5B4M.js} +24 -0
- package/dist/{chunk-2TGJ5XCV.js → chunk-PWC3C5ME.js} +4 -4
- package/dist/{chunk-A4YCLD3L.js → chunk-QFAFKEB5.js} +40 -4
- package/dist/{chunk-CL4J4757.js → chunk-QH5ZQ5SJ.js} +26 -0
- package/dist/{chunk-UJWZYK46.js → chunk-QNZ4562V.js} +1 -1
- package/dist/{chunk-IPHLUZ37.js → chunk-QPTSA4PP.js} +2 -2
- package/dist/{chunk-O3YJTHWI.js → chunk-R5E7WNAC.js} +3 -3
- package/dist/{chunk-V3M4LJRA.js → chunk-RB3J2WYQ.js} +1 -1
- package/dist/{chunk-IUCWOI4Y.js → chunk-RDWIKDMY.js} +237 -11
- package/dist/{chunk-ENN6DY4T.js → chunk-RVO5O5SR.js} +46 -21
- package/dist/{chunk-LY4AXCYJ.js → chunk-RZN2LEAK.js} +6 -6
- package/dist/{chunk-2YIB75UQ.js → chunk-S26CV7BE.js} +57 -13
- package/dist/{chunk-XC36HYP6.js → chunk-SDYWZRPN.js} +1 -1
- package/dist/{chunk-PHBU4LGO.js → chunk-SNHYZYGZ.js} +1 -1
- package/dist/{chunk-4KTTBKWQ.js → chunk-T5FEAQES.js} +1 -1
- package/dist/{chunk-XU57KFD6.js → chunk-T5SM4RXY.js} +5 -1
- package/dist/{chunk-KUV5VBAO.js → chunk-TKAU7IJ2.js} +1 -1
- package/dist/{chunk-KBR5LIWD.js → chunk-TKS5GMYA.js} +1 -1
- package/dist/{chunk-5DFE2NAF.js → chunk-TNS63ATU.js} +96 -22
- package/dist/{chunk-RFPMXR6B.js → chunk-U4GMOT4M.js} +1 -1
- package/dist/{chunk-CO5ZVE3D.js → chunk-UOPCVFVR.js} +17 -17
- package/dist/{chunk-22LNFCDF.js → chunk-UX2EO653.js} +1 -1
- package/dist/{chunk-LGC6TBA3.js → chunk-UXN4BICC.js} +2 -2
- package/dist/{chunk-7J5X4AK7.js → chunk-VF2KRROX.js} +1 -1
- package/dist/{chunk-7THUQU44.js → chunk-VF3BZOZK.js} +5 -2
- package/dist/{chunk-M2B35MUK.js → chunk-VHHX4UCP.js} +1 -1
- package/dist/{chunk-AZBJXATK.js → chunk-VJEJ7JNB.js} +1 -1
- package/dist/{chunk-4TRVALTR.js → chunk-VLBHZ6TF.js} +2 -2
- package/dist/{chunk-7BMSBACY.js → chunk-VOVFUKEB.js} +5 -5
- package/dist/{chunk-MDPGZS6C.js → chunk-VROK4X2L.js} +1 -1
- package/dist/{chunk-J6ABJDZ4.js → chunk-W3KPQE7H.js} +4 -4
- package/dist/{chunk-3Q7NEDHB.js → chunk-W6BZ4UGA.js} +48 -9
- package/dist/{chunk-IZ3IFLL2.js → chunk-XEBKIWI7.js} +14 -14
- package/dist/{chunk-UZDF6FLJ.js → chunk-XHU3KOKJ.js} +1 -1
- package/dist/{chunk-PA37MXV5.js → chunk-XSUALA32.js} +2 -2
- package/dist/{chunk-GR5WJPKF.js → chunk-XUZK23V7.js} +11 -6
- package/dist/{chunk-IDB3EZLW.js → chunk-YLB365YX.js} +148 -5
- package/dist/{chunk-JDQ7JU3A.js → chunk-YLFCH3VA.js} +24 -16
- package/dist/{chunk-ZJJL2Z23.js → chunk-YRQ26MNP.js} +4 -4
- package/dist/chunk-YRUZK2QA.js +35 -0
- package/dist/{chunk-7HLJ4BSF.js → chunk-ZAEUEDTN.js} +2 -2
- package/dist/{chunk-NY74W3S4.js → chunk-ZBPZDADW.js} +313 -43
- package/dist/{chunk-ZLPS3GR7.js → chunk-ZJQ56DZZ.js} +42 -1
- package/dist/{chunk-VMZZTFXT.js → chunk-ZOTTYCP5.js} +4 -4
- package/dist/{chunk-MP4ST7RO.js → chunk-ZPP63JSQ.js} +51 -11
- package/dist/{chunk-N4J5WHO2.js → chunk-ZT4LFTUJ.js} +1 -1
- package/dist/{cleanup-graph-garbage-GE2DYOTB.js → cleanup-graph-garbage-VQAJ2RBT.js} +11 -11
- package/dist/{cloud-sync-command-T6KF3ARK.js → cloud-sync-command-J7NEFUY7.js} +2 -2
- package/dist/{cloud-sync-db-init-RSHCCY74.js → cloud-sync-db-init-KWEMNMGA.js} +1 -1
- package/dist/{cloud-sync-shutdown-6IVCSLM5.js → cloud-sync-shutdown-P63AUTUI.js} +5 -5
- package/dist/{co-activation-AF7RCJPX.js → co-activation-7IHRPBZN.js} +5 -5
- package/dist/{co-occurrence-DMOOGBVV.js → co-occurrence-R5AG4OAU.js} +9 -9
- package/dist/{code-context-index-LIDOFKOR.js → code-context-index-WFLLZBVB.js} +10 -9
- package/dist/{code-context-watcher-4F7K2N3U.js → code-context-watcher-3QAPHO7N.js} +10 -9
- package/dist/{codex-consolidation-SH4UKFBQ.js → codex-consolidation-ONZ2AQFX.js} +2 -2
- package/dist/{consent-passphrase-WV7MZPMO.js → consent-passphrase-5ZBDJ5G7.js} +2 -2
- package/dist/{content-extractor-DJM5EUDA.js → content-extractor-ZLXC6GNR.js} +2 -2
- package/dist/{conversation-entity-extractor-4UG7BKWL.js → conversation-entity-extractor-7FRKLLBD.js} +4 -4
- package/dist/{conversation-wiki-populator-OS4C6W54.js → conversation-wiki-populator-YAOVCUGO.js} +1 -1
- package/dist/{crdt-sync-VL4KXZB7.js → crdt-sync-IFRZOEIS.js} +4 -4
- package/dist/{crm-webhook-IDBJ7X5Y.js → crm-webhook-L2S63ASV.js} +2 -2
- package/dist/{cto-delegation-gate-4FLSHSLO.js → cto-delegation-gate-3WU7OHX7.js} +29 -28
- package/dist/{daemon-auth-PNKHERLV.js → daemon-auth-OWLFYEFR.js} +3 -3
- package/dist/{daemon-orchestration-HFCB6OK4.js → daemon-orchestration-3VQYKLOR.js} +33 -32
- package/dist/{daemon-ready-BN6EZLTQ.js → daemon-ready-VZ6ZHA2C.js} +1 -1
- package/dist/{db-integrity-events-GYGANKZV.js → db-integrity-events-7NKWS5MT.js} +3 -3
- package/dist/{db-restore-events-G6NOQOVE.js → db-restore-events-XYL6CGPC.js} +2 -2
- package/dist/{destructive-data-guard-HHWUBIGS.js → destructive-data-guard-JDUJ2ULM.js} +58 -2
- package/dist/{dispatch-ack-X4DXUSKP.js → dispatch-ack-UYEAKON5.js} +2 -1
- package/dist/{doc-graph-extractor-E36PQUCS.js → doc-graph-extractor-YIR5E7OF.js} +9 -9
- package/dist/{documents-SCKKHDR7.js → documents-QEHPTYIY.js} +19 -18
- package/dist/{dreaming-Q26JBH56.js → dreaming-LNFE7DTN.js} +34 -33
- package/dist/{employee-boot-brief-XU6EI2EO.js → employee-boot-brief-ZTXDYNWM.js} +39 -38
- package/dist/{entity-boost-VNQLLR3Q.js → entity-boost-R5N6JWXD.js} +1 -1
- package/dist/{exe-drift-YZ6OIUAY.js → exe-drift-WYSJVZFO.js} +6 -6
- package/dist/{exe-export-HHRQMLSS.js → exe-export-GOLNAEAV.js} +20 -19
- package/dist/{exe-import-5XR4NQAB.js → exe-import-U4BSI6OH.js} +20 -19
- package/dist/{exe-key-5XOFVP3I.js → exe-key-V42G3NGO.js} +152 -130
- package/dist/{exe-org-TPAX4AAK.js → exe-org-U4GLQ6OP.js} +27 -27
- package/dist/{exe-snapshot-GIRP3XCJ.js → exe-snapshot-U7ONBYNY.js} +38 -37
- package/dist/{fast-db-init-MGY6VCLG.js → fast-db-init-W3NGKAEU.js} +1 -1
- package/dist/{founder-context-WD72OL2P.js → founder-context-ZSIBRVDM.js} +4 -4
- package/dist/{founder-monitor-envelope-XGYMHT4W.js → founder-monitor-envelope-L3IWZLFY.js} +7 -7
- package/dist/{fts-integrity-PLAL6NMG.js → fts-integrity-PHCKKOBC.js} +3 -3
- package/dist/gateway/index.js +23 -22
- package/dist/{gateway-client-VO3BRLV5.js → gateway-client-DJFCVIPT.js} +1 -1
- package/dist/{git-staleness-KGZABPP3.js → git-staleness-OF24QXFZ.js} +5 -5
- package/dist/{global-procedures-KOU6A5E5.js → global-procedures-WSIOWO43.js} +6 -6
- package/dist/{graph-auto-extract-OZNRDAHE.js → graph-auto-extract-IEVVN3L3.js} +9 -9
- package/dist/{graph-query-36K6VXFF.js → graph-query-JDZWAVCU.js} +1 -1
- package/dist/{graph-rag-TZLH3CTQ.js → graph-rag-BKAD2XQA.js} +4 -4
- package/dist/{hook-integrity-BWFFISJV.js → hook-integrity-TPWDGX2M.js} +3 -1
- package/dist/{hook-prefetch-MFUJRAIM.js → hook-prefetch-FD6VGJJA.js} +29 -28
- package/dist/hooks/bug-report-worker.js +34 -33
- package/dist/hooks/codex-stop-task-finalizer.js +36 -35
- package/dist/hooks/commit-complete.js +40 -36
- package/dist/hooks/error-recall.js +15 -15
- package/dist/hooks/exe-heartbeat-hook.js +8 -8
- package/dist/hooks/ingest-worker.js +21 -20
- package/dist/hooks/ingest.js +23 -23
- package/dist/hooks/instructions-loaded.js +10 -10
- package/dist/hooks/manifest.json +20 -20
- package/dist/hooks/notification.js +9 -9
- package/dist/hooks/post-compact.js +8 -8
- package/dist/hooks/post-tool-combined.js +15 -15
- package/dist/hooks/pre-compact.js +33 -32
- package/dist/hooks/pre-tool-use.js +2 -2
- package/dist/hooks/prompt-submit.js +52 -51
- package/dist/hooks/session-end.js +38 -37
- package/dist/hooks/session-start.js +25 -22
- package/dist/hooks/stop.js +40 -39
- package/dist/hooks/subagent-stop.js +36 -35
- package/dist/hooks/summary-worker.js +41 -40
- package/dist/index.js +43 -42
- package/dist/{inrun-inbox-DRKVDPLY.js → inrun-inbox-RGNFFGMU.js} +5 -0
- package/dist/{installer-RM4ASY7U.js → installer-NMOBSEZ2.js} +11 -11
- package/dist/{installer-IESPHXVH.js → installer-OTI5SA43.js} +11 -11
- package/dist/{installer-SQZRVD36.js → installer-SRJGE4GU.js} +11 -11
- package/dist/{intercom-queue-DGLAC224.js → intercom-queue-4FFXCBHO.js} +28 -27
- package/dist/{key-backup-status-LQPINQ3W.js → key-backup-status-6U7D5GOD.js} +2 -2
- package/dist/lib/agent-config.js +3 -3
- package/dist/lib/cloud-sync.js +28 -27
- package/dist/lib/config.js +4 -2
- package/dist/lib/consolidation.js +14 -12
- package/dist/lib/crypto.js +5 -3
- package/dist/lib/database.js +5 -5
- package/dist/lib/db-backup.js +11 -3
- package/dist/lib/db-daemon-client.js +11 -10
- package/dist/lib/db-write-worker.js +4 -4
- package/dist/lib/db.js +5 -5
- package/dist/lib/delivery-catalog.js +431 -0
- package/dist/lib/delivery-schemas.js +62 -0
- package/dist/lib/delivery-truth.js +1 -1
- package/dist/lib/device-registry.js +3 -3
- package/dist/lib/embed-worker.js +2 -2
- package/dist/lib/embedder.js +10 -9
- package/dist/lib/employee-templates.js +7 -7
- package/dist/lib/employees.js +5 -5
- package/dist/lib/exe-daemon-client.js +9 -8
- package/dist/lib/exe-daemon.js +186 -117
- package/dist/lib/hybrid-search.js +12 -12
- package/dist/lib/identity.js +5 -5
- package/dist/lib/keychain.js +13 -1
- package/dist/lib/license.js +8 -4
- package/dist/lib/messaging.js +39 -30
- package/dist/lib/post-tool-memory.js +9 -9
- package/dist/lib/registry-proxy.js +9 -1
- package/dist/lib/reminders.js +6 -6
- package/dist/lib/schedules.js +11 -11
- package/dist/lib/session-registry.js +7 -7
- package/dist/lib/skill-learning.js +20 -19
- package/dist/lib/status-brief.js +5 -4
- package/dist/lib/store.js +10 -10
- package/dist/lib/task-router.js +6 -6
- package/dist/lib/tasks.js +30 -29
- package/dist/lib/tmux-routing.js +28 -27
- package/dist/lib/tmux-status.js +3 -1
- package/dist/lib/token-spend.js +6 -6
- package/dist/lib/ws-client.js +1 -1
- package/dist/{license-gate-E6GTRYBA.js → license-gate-R4JWTWM4.js} +5 -5
- package/dist/{license-recheck-RBAO6Z2H.js → license-recheck-3MBJ4IJX.js} +1 -1
- package/dist/{license-sync-ZCZ2LIHK.js → license-sync-BVSG3WMW.js} +4 -4
- package/dist/local-secret-inventory-JWNBHZZ4.js +20 -0
- package/dist/mailbox-inbox-MTAT4MXX.js +13 -0
- package/dist/{mailbox-outbox-DNDDP2HW.js → mailbox-outbox-OY4IU6S4.js} +2 -1
- package/dist/mcp/register-tools.js +121 -120
- package/dist/mcp/server.js +123 -122
- package/dist/mcp/tools/complete-reminder.js +7 -7
- package/dist/mcp/tools/create-reminder.js +7 -7
- package/dist/mcp/tools/create-task.js +35 -32
- package/dist/mcp/tools/deactivate-behavior.js +22 -21
- package/dist/mcp/tools/list-reminders.js +7 -7
- package/dist/mcp/tools/list-tasks.js +33 -32
- package/dist/mcp/tools/send-message.js +32 -31
- package/dist/mcp/tools/update-task.js +31 -30
- package/dist/{mcp-child-registry-DVHYAHPW.js → mcp-child-registry-TIZERM7O.js} +5 -5
- package/dist/{mcp-health-B5EKRCZG.js → mcp-health-4ZHU67LM.js} +9 -3
- package/dist/{mcp-http-config-ME67QDOF.js → mcp-http-config-VUMSFWFH.js} +12 -12
- package/dist/{mcp-session-identity-DNG4ULAE.js → mcp-session-identity-DZHWEJRV.js} +28 -27
- package/dist/{memory-cards-WCISXY62.js → memory-cards-JVXTMSAT.js} +10 -10
- package/dist/{memory-graph-extractor-GXIK4QUF.js → memory-graph-extractor-PPBJMYFJ.js} +10 -10
- package/dist/{memory-poisoning-defense-25LZ5FJI.js → memory-poisoning-defense-K5Q74XQ4.js} +5 -5
- package/dist/{memory-pressure-watchdog-XGXI7WGE.js → memory-pressure-watchdog-YMJH5CSA.js} +29 -28
- package/dist/{memory-queue-YF7IDSFY.js → memory-queue-2MA67TAA.js} +3 -3
- package/dist/{memory-queue-client-QC2OTMJB.js → memory-queue-client-4G7HVRSX.js} +11 -10
- package/dist/{memory-reflection-GFGT44NT.js → memory-reflection-7BZWIHRE.js} +10 -10
- package/dist/{monitor-grants-Z2SEFE6E.js → monitor-grants-Q7X3MYQP.js} +6 -6
- package/dist/{monitor-identity-AEMHCVHV.js → monitor-identity-ZQB4IXEE.js} +2 -2
- package/dist/{notification-ledger-ETQBGRP7.js → notification-ledger-XRAXL5OI.js} +32 -29
- package/dist/{notifications-LPRCFJYY.js → notifications-JE3PX55X.js} +28 -27
- package/dist/{orchestration-events-T2GXV2NG.js → orchestration-events-JCQ5F5IJ.js} +6 -6
- package/dist/{orchestration-phase-T2WD45UA.js → orchestration-phase-QKTGQ2YT.js} +3 -3
- package/dist/{orchestrator-HY2IB3NA.js → orchestrator-X65INDTR.js} +30 -29
- package/dist/{org-brief-session-UWFCFEEB.js → org-brief-session-3PQ22UIX.js} +19 -18
- package/dist/{org-consent-policy-XXMST37J.js → org-consent-policy-VGELJ7K7.js} +7 -6
- package/dist/{org-join-72QKM7JR.js → org-join-6TO5ZYUZ.js} +12 -12
- package/dist/{org-key-admin-YCIAYP7V.js → org-key-admin-XHYVRRAZ.js} +12 -12
- package/dist/{org-key-pin-F7BQPI5P.js → org-key-pin-TTTYGTQL.js} +6 -6
- package/dist/{org-membership-JQSU4Z5P.js → org-membership-Y7T2BS57.js} +7 -7
- package/dist/{org-partner-config-PVJ45SLC.js → org-partner-config-OP4NEUNF.js} +10 -10
- package/dist/{org-partner-runtime-U4CTLWLC.js → org-partner-runtime-YNVUNT2R.js} +20 -19
- package/dist/{org-row-visibility-WUX4N3FX.js → org-row-visibility-JBBXNYXD.js} +1 -1
- package/dist/{pipeline-router-2RMBCBRM.js → pipeline-router-EIBB7QNG.js} +6 -6
- package/dist/{plan-limits-Z47XYEJR.js → plan-limits-MEWXYLEN.js} +8 -8
- package/dist/{postinstall-failure-O6TSSNJB.js → postinstall-failure-VETYYWEZ.js} +3 -3
- package/dist/{pre-tool-use-impl-JPE6XMRJ.js → pre-tool-use-impl-C6KJY22W.js} +60 -49
- package/dist/{project-boot-UFQDAFU5.js → project-boot-VEYFCCSL.js} +2 -2
- package/dist/{project-name-V4IREGHO.js → project-name-UYORSNGE.js} +6 -6
- package/dist/{projection-worker-HAD6H3VJ.js → projection-worker-WYFDWS57.js} +5 -5
- package/dist/{prospective-memory-KIF4JLFF.js → prospective-memory-E6XBQFJA.js} +5 -5
- package/dist/{push-notifications-GDKRTYXH.js → push-notifications-M7YU63FY.js} +29 -28
- package/dist/{reproject-worktree-memories-SG4BZJ3Z.js → reproject-worktree-memories-B5XMGJSD.js} +28 -27
- package/dist/{reranker-G2AZ67JP.js → reranker-SRA4BR7N.js} +3 -3
- package/dist/{retrieval-health-GBJRXTBZ.js → retrieval-health-P2JPZUPV.js} +4 -4
- package/dist/{review-polling-VUZPAAGT.js → review-polling-KQPN7IQE.js} +29 -28
- package/dist/runtime/index.js +37 -36
- package/dist/{session-events-BI6NIFIR.js → session-events-6LDDKKY3.js} +29 -28
- package/dist/{session-kill-telemetry-HPBDOPHT.js → session-kill-telemetry-5DSRGWCL.js} +29 -28
- package/dist/{session-mcp-config-WFZAH6R5.js → session-mcp-config-F7RCERUG.js} +3 -3
- package/dist/{session-scope-UB3HA5E7.js → session-scope-XG5R3P3D.js} +28 -27
- package/dist/{setup-wizard-6XULOT3L.js → setup-wizard-7QFLZIKT.js} +5 -5
- package/dist/{shard-manager-DYEJ6ETD.js → shard-manager-HHHHV2KZ.js} +3 -3
- package/dist/{skill-refinement-MKBQIWZ6.js → skill-refinement-I5RMAHSC.js} +6 -6
- package/dist/{stack-generate-manifest-7ODQ6W2O.js → stack-generate-manifest-AKMZ3AUX.js} +246 -13
- package/dist/stack-init-5VKL5PL5.js +136 -0
- package/dist/{stack-promote-3UKJBJSP.js → stack-promote-34CE2HHF.js} +7 -6
- package/dist/{stack-release-5CVXMJM5.js → stack-release-5PGWV5D4.js} +123 -12
- package/dist/{stack-update-Z53KG2P5.js → stack-update-ZQQ5YYPJ.js} +20 -5
- package/dist/{steward-gate-OKUYYIX6.js → steward-gate-AQJ6KT2C.js} +6 -6
- package/dist/{subagent-brief-injection-T2CVQLAS.js → subagent-brief-injection-3GU7YAWY.js} +50 -42
- package/dist/{subagent-spawn-ledger-E6U3OY6Z.js → subagent-spawn-ledger-52I66CLW.js} +3 -3
- package/dist/{supervisor-handoff-SGLEPOCY.js → supervisor-handoff-BWJW6CKZ.js} +4 -4
- package/dist/{support-inbox-WJIDCKJC.js → support-inbox-NY5TB3FN.js} +12 -12
- package/dist/{support-outbox-G2NG2U5K.js → support-outbox-KNI3FR3G.js} +3 -2
- package/dist/{task-enforcement-JL5ADPS6.js → task-enforcement-CAA6D2MH.js} +29 -28
- package/dist/{task-request-inbox-54BRRFHZ.js → task-request-inbox-QBZVU66E.js} +9 -6
- package/dist/{task-scope-OBPZBID5.js → task-scope-NHXB4ZRN.js} +32 -27
- package/dist/{tasks-crud-YBCPT7TY.js → tasks-crud-JHSWL5NM.js} +28 -27
- package/dist/{tasks-notify-CEEQSDJF.js → tasks-notify-7PBE4U7T.js} +29 -28
- package/dist/{tasks-review-JIEI656P.js → tasks-review-PPPVEE62.js} +28 -27
- package/dist/{telemetry-upload-ZZSEZR2U.js → telemetry-upload-YU2VRNHX.js} +10 -10
- package/dist/{token-budget-AUFMEMQ2.js → token-budget-QCMWKG3K.js} +6 -6
- package/dist/{tool-capability-index-6HLZU437.js → tool-capability-index-7AWQAJRP.js} +1 -1
- package/dist/{tool-gates-VXITVRFQ.js → tool-gates-5Q3RSQEG.js} +1 -1
- package/dist/{tool-gates-JWVSAYTW.js → tool-gates-QD26D2NE.js} +1 -1
- package/dist/{tool-telemetry-RHSEK2TO.js → tool-telemetry-LTOIC64I.js} +1 -1
- package/dist/tui/App.js +43 -42
- package/dist/{tui-data-PBZNN5YB.js → tui-data-NDBXD6U7.js} +32 -31
- package/dist/{update-support-V3ZCJR6L.js → update-support-BMJM4NG7.js} +27 -26
- package/dist/{whatsapp-NAM2CRVQ.js → whatsapp-QQLDAHUX.js} +2 -2
- package/dist/{wiki-acl-NUBAPLCD.js → wiki-acl-W6WDCVCP.js} +1 -1
- package/dist/{work-claims-Q2NU6JON.js → work-claims-6DM32MGO.js} +6 -6
- package/dist/{work-state-heartbeat-HAQRV3RK.js → work-state-heartbeat-HG7D4AWJ.js} +1 -1
- package/dist/{worker-gate-NUUSQMBT.js → worker-gate-FTMW7GBB.js} +3 -3
- package/dist/{workflow-engine-GEWPU5YR.js → workflow-engine-ZWC6CCXE.js} +2 -2
- package/dist/{worktree-C7LFMRKW.js → worktree-EMQCPGFE.js} +7 -7
- package/dist/{worktree-ownership-guard-4LKMW6PW.js → worktree-ownership-guard-O6JQF2CL.js} +2 -2
- package/dist/{worktree-sweep-SYF62ANH.js → worktree-sweep-XVUJZBXV.js} +8 -8
- package/package.json +23 -7
- package/release-notes.json +39 -12
- package/stack.release.json +4 -4
- package/dist/mailbox-inbox-XE72D3AX.js +0 -10
- /package/dist/{chunk-QIEYJ4KZ.js → chunk-2KY7WZZF.js} +0 -0
- /package/dist/{chunk-T3667X2B.js → chunk-2Q2CD6CD.js} +0 -0
- /package/dist/{chunk-JZJZYKMW.js → chunk-AJK2PVQW.js} +0 -0
- /package/dist/{chunk-ZEGEFBZV.js → chunk-AWWDKF22.js} +0 -0
- /package/dist/{chunk-QNTKRGJ6.js → chunk-GIRD7O5X.js} +0 -0
- /package/dist/{chunk-FWA4MYTA.js → chunk-JRIH6I7D.js} +0 -0
- /package/dist/{chunk-C7H2D7LX.js → chunk-M4XY4JRK.js} +0 -0
- /package/dist/{chunk-Q3DN5J6F.js → chunk-P2VVMGMI.js} +0 -0
- /package/dist/{chunk-BRAIWGMF.js → chunk-Q46NYJ77.js} +0 -0
- /package/dist/{chunk-3LQ2N4H7.js → chunk-U2D6PJ5T.js} +0 -0
- /package/dist/{chunk-3O6OGZL3.js → chunk-XDVOGDBC.js} +0 -0
- /package/dist/{core-memory-UNCAPGD4.js → core-memory-O6D5UC3T.js} +0 -0
- /package/dist/{hook-tamper-log-Z4PWC7N4.js → hook-tamper-log-ARGWCXKJ.js} +0 -0
- /package/dist/{memory-isolation-ALPJWLR5.js → memory-isolation-EBFFC6HF.js} +0 -0
- /package/dist/{oauth-server-AC2KB7NB.js → oauth-server-ZKBUHDFI.js} +0 -0
- /package/dist/{webhook-pipe-W2FVXY7M.js → webhook-pipe-PXH5MBRM.js} +0 -0
- /package/dist/{wiki-client-W65IOSWF.js → wiki-client-DD2NVWK2.js} +0 -0
|
@@ -13,9 +13,12 @@ import {
|
|
|
13
13
|
checkImageVersionLabels,
|
|
14
14
|
isFirstPartyImage
|
|
15
15
|
} from "./chunk-L25OAFOU.js";
|
|
16
|
+
import {
|
|
17
|
+
declaredArtifactsFromManifest
|
|
18
|
+
} from "./chunk-LFUBEHFW.js";
|
|
16
19
|
import {
|
|
17
20
|
loadLicense
|
|
18
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-TNS63ATU.js";
|
|
19
22
|
|
|
20
23
|
// src/lib/stack-update.ts
|
|
21
24
|
import { execFileSync, spawnSync } from "child_process";
|
|
@@ -26,6 +29,97 @@ import https from "https";
|
|
|
26
29
|
import net from "net";
|
|
27
30
|
import path from "path";
|
|
28
31
|
import { fileURLToPath } from "url";
|
|
32
|
+
import { parseDocument as parseYamlDocument } from "yaml";
|
|
33
|
+
|
|
34
|
+
// src/lib/service-env-contract.ts
|
|
35
|
+
import { parse as parseYaml } from "yaml";
|
|
36
|
+
var SERVICE_ENV_CONTRACT = [
|
|
37
|
+
{
|
|
38
|
+
service: "exe-gateway",
|
|
39
|
+
keys: ["GOTRUE_JWT_SECRET"],
|
|
40
|
+
consequence: "gotrue-auth.ts getSymmetricKey() refuses every HS256 GoTrue token, so all SSO-authenticated requests (including /query tenant auth and /pair-login) are rejected with 401 while the service still reports healthy"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
service: "exe-crm",
|
|
44
|
+
keys: ["GOTRUE_JWT_SECRET"],
|
|
45
|
+
consequence: "getGoTrueSymmetricVerificationKey cannot verify SSO tokens, so GoTrue logins are rejected"
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
service: "exe-wiki",
|
|
49
|
+
keys: ["GOTRUE_JWT_SECRET"],
|
|
50
|
+
consequence: "getGoTrueJwtSecret cannot verify SSO tokens, so GoTrue logins are rejected"
|
|
51
|
+
}
|
|
52
|
+
];
|
|
53
|
+
function parseComposeServiceEnvKeys(composeYaml) {
|
|
54
|
+
const byService = /* @__PURE__ */ new Map();
|
|
55
|
+
let doc;
|
|
56
|
+
try {
|
|
57
|
+
doc = parseYaml(composeYaml, { merge: true });
|
|
58
|
+
} catch {
|
|
59
|
+
return byService;
|
|
60
|
+
}
|
|
61
|
+
const services = doc?.services;
|
|
62
|
+
if (!services || typeof services !== "object") return byService;
|
|
63
|
+
for (const [name, rawDef] of Object.entries(services)) {
|
|
64
|
+
const keys = /* @__PURE__ */ new Set();
|
|
65
|
+
const env = rawDef?.environment;
|
|
66
|
+
if (Array.isArray(env)) {
|
|
67
|
+
for (const entry of env) {
|
|
68
|
+
if (typeof entry !== "string") continue;
|
|
69
|
+
const eq = entry.indexOf("=");
|
|
70
|
+
const key = (eq === -1 ? entry : entry.slice(0, eq)).trim();
|
|
71
|
+
if (key) keys.add(key);
|
|
72
|
+
}
|
|
73
|
+
} else if (env && typeof env === "object") {
|
|
74
|
+
for (const key of Object.keys(env)) keys.add(key);
|
|
75
|
+
}
|
|
76
|
+
byService.set(name, keys);
|
|
77
|
+
}
|
|
78
|
+
return byService;
|
|
79
|
+
}
|
|
80
|
+
function collectServiceEnvGaps(composeYaml, contract = SERVICE_ENV_CONTRACT) {
|
|
81
|
+
const byService = parseComposeServiceEnvKeys(composeYaml);
|
|
82
|
+
const gaps = [];
|
|
83
|
+
for (const requirement of contract) {
|
|
84
|
+
const declared = byService.get(requirement.service);
|
|
85
|
+
if (!declared) continue;
|
|
86
|
+
const missingKeys = requirement.keys.filter((key) => !declared.has(key));
|
|
87
|
+
if (missingKeys.length > 0) {
|
|
88
|
+
gaps.push({ service: requirement.service, missingKeys: [...missingKeys].sort(), consequence: requirement.consequence });
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return gaps.sort((a, b) => a.service.localeCompare(b.service));
|
|
92
|
+
}
|
|
93
|
+
function describeGaps(gaps) {
|
|
94
|
+
return gaps.map((gap) => ` - ${gap.service}: ${gap.missingKeys.join(", ")}
|
|
95
|
+
without it, ${gap.consequence}`).join("\n");
|
|
96
|
+
}
|
|
97
|
+
function assertServiceEnvContract(composeYaml, source) {
|
|
98
|
+
const gaps = collectServiceEnvGaps(composeYaml);
|
|
99
|
+
if (gaps.length === 0) return;
|
|
100
|
+
throw new Error(
|
|
101
|
+
`Stack update aborted before any changes: ${source} does not hand ${gaps.length} service(s) an environment key they cannot work without.
|
|
102
|
+
${describeGaps(gaps)}
|
|
103
|
+
Compose bans env_file: for these services, so a key present in .env but absent from the service's own environment: block never reaches the container. Add the key to that block.`
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
function reportDeployedServiceEnvGaps(deployedComposeYaml, composeFile, willRefreshTemplate, write = (line) => process.stderr.write(line)) {
|
|
107
|
+
const gaps = collectServiceEnvGaps(deployedComposeYaml);
|
|
108
|
+
if (gaps.length === 0) return gaps;
|
|
109
|
+
const remedy = willRefreshTemplate ? "This update refreshes the compose template, which is expected to restore the key(s); re-check after it completes." : `This update does NOT refresh ${composeFile}, so the gap will PERSIST. Update the deployed compose template.`;
|
|
110
|
+
write(
|
|
111
|
+
`
|
|
112
|
+
[stack-update] WARNING (bug 7e811acf): the DEPLOYED compose at ${composeFile} does not hand ${gaps.length} running service(s) an environment key they cannot work without:
|
|
113
|
+
${describeGaps(gaps)}
|
|
114
|
+
These services do not crash without it \u2014 they return clean 401s and keep reporting healthy, which is why this can go unnoticed indefinitely.
|
|
115
|
+
${remedy}
|
|
116
|
+
|
|
117
|
+
`
|
|
118
|
+
);
|
|
119
|
+
return gaps;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// src/lib/stack-update.ts
|
|
29
123
|
var SLOW_SERVICE_HEALTH_DEFAULTS = {
|
|
30
124
|
// Frappe `bench migrate` on every boot can take well over the 180s default.
|
|
31
125
|
"exe-erp": 900
|
|
@@ -184,61 +278,127 @@ function isCloudflaredTunnelMisconfigured(composeFile, envFile) {
|
|
|
184
278
|
return true;
|
|
185
279
|
}
|
|
186
280
|
var INGRESS_DEFAULT_PORTS = { http: 80, https: 443 };
|
|
187
|
-
function
|
|
188
|
-
|
|
189
|
-
v = v.replace(/\s+#.*$/, "").trim();
|
|
190
|
-
if (v.startsWith('"') && v.endsWith('"') || v.startsWith("'") && v.endsWith("'")) {
|
|
191
|
-
v = v.slice(1, -1);
|
|
192
|
-
}
|
|
193
|
-
return v.trim();
|
|
281
|
+
function findUnauditableIngressSyntax(configYml) {
|
|
282
|
+
return walkCloudflaredIngress(configYml).unmodelled;
|
|
194
283
|
}
|
|
195
284
|
function parseCloudflaredIngressTargets(configYml) {
|
|
196
|
-
|
|
285
|
+
return walkCloudflaredIngress(configYml).targets;
|
|
286
|
+
}
|
|
287
|
+
function ruleLabel(hostname, service) {
|
|
288
|
+
return `${hostname ? `hostname: ${hostname}` : "(no hostname)"} -> service: ${service.slice(0, 60)}`;
|
|
289
|
+
}
|
|
290
|
+
function walkCloudflaredIngress(configYml) {
|
|
197
291
|
const targets = [];
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
292
|
+
const rules = [];
|
|
293
|
+
const unmodelled = [];
|
|
294
|
+
const emitTarget = (service, hostname) => {
|
|
295
|
+
const m = /^([a-z][a-z0-9+.\-]*):\/\/(?:\[([^\]]+)\]|([^/:\s]+))(?::(\d+))?/i.exec(service.trim());
|
|
296
|
+
if (!m) {
|
|
297
|
+
rules.push({ hostname, service });
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
205
300
|
const scheme = (m[1] ?? "").toLowerCase();
|
|
206
301
|
const host = m[2] ?? m[3] ?? "";
|
|
207
302
|
const port = m[4] ? Number(m[4]) : INGRESS_DEFAULT_PORTS[scheme];
|
|
208
|
-
if (!host)
|
|
303
|
+
if (!host) {
|
|
304
|
+
rules.push({ hostname, service });
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
rules.push({ hostname, service, host });
|
|
209
308
|
if (port === void 0 || !Number.isFinite(port) || port <= 0 || port > 65535) return;
|
|
210
|
-
targets.push({ hostname
|
|
309
|
+
targets.push({ hostname, service, host, port });
|
|
211
310
|
};
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
const
|
|
215
|
-
if (
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
311
|
+
let root;
|
|
312
|
+
try {
|
|
313
|
+
const doc = parseYamlDocument(configYml, { merge: true, uniqueKeys: true });
|
|
314
|
+
if (doc.errors.length > 0) {
|
|
315
|
+
unmodelled.push(`config.yml does not parse as YAML: ${doc.errors[0]?.message ?? "unknown error"}`);
|
|
316
|
+
return { targets, rules, unmodelled };
|
|
317
|
+
}
|
|
318
|
+
root = doc.toJS({ maxAliasCount: 100 });
|
|
319
|
+
} catch (err) {
|
|
320
|
+
unmodelled.push(`config.yml could not be read as YAML: ${err instanceof Error ? err.message : String(err)}`);
|
|
321
|
+
return { targets, rules, unmodelled };
|
|
322
|
+
}
|
|
323
|
+
if (root === null || root === void 0) return { targets, rules, unmodelled };
|
|
324
|
+
if (typeof root !== "object" || Array.isArray(root)) {
|
|
325
|
+
unmodelled.push("top level of config.yml is not a mapping, so its `ingress:` cannot be located");
|
|
326
|
+
return { targets, rules, unmodelled };
|
|
327
|
+
}
|
|
328
|
+
const ingress = root.ingress;
|
|
329
|
+
if (ingress === void 0 || ingress === null) return { targets, rules, unmodelled };
|
|
330
|
+
if (!Array.isArray(ingress)) {
|
|
331
|
+
unmodelled.push("`ingress:` is not a sequence of rules");
|
|
332
|
+
return { targets, rules, unmodelled };
|
|
333
|
+
}
|
|
334
|
+
for (const rule of ingress) {
|
|
335
|
+
if (rule === null || typeof rule !== "object" || Array.isArray(rule)) {
|
|
336
|
+
unmodelled.push(`ingress rule is not a mapping: ${JSON.stringify(rule).slice(0, 120)}`);
|
|
337
|
+
continue;
|
|
338
|
+
}
|
|
339
|
+
const entry = rule;
|
|
340
|
+
const rawHostname = entry.hostname;
|
|
341
|
+
const rawService = entry.service;
|
|
342
|
+
let hostname;
|
|
343
|
+
if (rawHostname !== void 0 && rawHostname !== null) {
|
|
344
|
+
if (typeof rawHostname !== "string") {
|
|
345
|
+
unmodelled.push(`ingress rule \`hostname:\` is not a string: ${JSON.stringify(rawHostname).slice(0, 120)}`);
|
|
346
|
+
continue;
|
|
347
|
+
}
|
|
348
|
+
const trimmedHostname = rawHostname.trim();
|
|
349
|
+
hostname = trimmedHostname === "" ? void 0 : trimmedHostname;
|
|
350
|
+
}
|
|
351
|
+
if (rawService === void 0 || rawService === null) {
|
|
352
|
+
if (hostname !== void 0) {
|
|
353
|
+
unmodelled.push(`ingress rule for ${hostname} has no \`service:\``);
|
|
219
354
|
}
|
|
220
355
|
continue;
|
|
221
356
|
}
|
|
222
|
-
if (
|
|
223
|
-
|
|
357
|
+
if (typeof rawService !== "string") {
|
|
358
|
+
unmodelled.push(`ingress rule \`service:\` is not a string: ${JSON.stringify(rawService).slice(0, 120)}`);
|
|
224
359
|
continue;
|
|
225
360
|
}
|
|
226
|
-
const
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
} else {
|
|
235
|
-
const hm = /^hostname\s*:\s*(.+)$/i.exec(t);
|
|
236
|
-
const sm = /^service\s*:\s*(.+)$/i.exec(t);
|
|
237
|
-
if (hm) currentHostname = stripYamlScalar(hm[1] ?? "");
|
|
238
|
-
else if (sm) flushService(sm[1] ?? "");
|
|
361
|
+
const svc = rawService.trim();
|
|
362
|
+
const builtIn = /^(?:http_status:\d+|hello_world)$/i.test(svc);
|
|
363
|
+
const networkUrl = /^[a-z][a-z0-9+.\-]*:\/\//i.test(svc);
|
|
364
|
+
if (entry.path !== void 0 && entry.path !== null && !builtIn) {
|
|
365
|
+
unmodelled.push(
|
|
366
|
+
`rule ${ruleLabel(hostname, svc)}: has a \`path:\` (${JSON.stringify(entry.path).slice(0, 40)}) AND serves an application, so it covers only part of that hostname and some later rule covers the rest \u2014 which is how a path-scoped edge route hid an unrestricted direct route below it. A \`path:\` is fine on a DENY rule (\`service: http_status:404\`); on a serving rule, drop the path.`
|
|
367
|
+
);
|
|
368
|
+
continue;
|
|
239
369
|
}
|
|
370
|
+
if (hostname !== void 0 && hostname.includes("*")) {
|
|
371
|
+
unmodelled.push(
|
|
372
|
+
`rule ${ruleLabel(hostname, svc)}: the hostname is a WILDCARD, so it serves product hostnames it does not name \u2014 including the SSO-gated ones \u2014 and which rule wins depends on ordering this gate does not resolve. Write one rule per concrete hostname.`
|
|
373
|
+
);
|
|
374
|
+
continue;
|
|
375
|
+
}
|
|
376
|
+
if (hostname === void 0) {
|
|
377
|
+
if (!builtIn) {
|
|
378
|
+
unmodelled.push(
|
|
379
|
+
`rule ${ruleLabel(hostname, svc)}: a CATCH-ALL (no hostname) that serves an application. It serves every product hostname no earlier rule claims, including the SSO-gated ones, so it can route a product around the edge without naming it. Give it a hostname, or make the catch-all a terminator (\`service: http_status:404\`).`
|
|
380
|
+
);
|
|
381
|
+
continue;
|
|
382
|
+
}
|
|
383
|
+
rules.push({ hostname, service: svc });
|
|
384
|
+
continue;
|
|
385
|
+
}
|
|
386
|
+
if (!builtIn && !networkUrl) {
|
|
387
|
+
unmodelled.push(
|
|
388
|
+
`rule ${ruleLabel(hostname, svc)}: the service is not a \`scheme://host\` URL, so this gate cannot resolve what it points at. A unix socket or bastion still serves the application, so it must not be read as serving nothing. Route it through \`http://<container>:<port>\`.`
|
|
389
|
+
);
|
|
390
|
+
continue;
|
|
391
|
+
}
|
|
392
|
+
const authority = svc.slice(svc.indexOf("://") + 3).split("/")[0] ?? "";
|
|
393
|
+
if (!builtIn && !/^(?:\[[0-9A-Fa-f:.]+\]|[A-Za-z0-9._-]+)(?::\d+)?$/.test(authority)) {
|
|
394
|
+
unmodelled.push(
|
|
395
|
+
`rule ${ruleLabel(hostname, svc)}: the service authority ${JSON.stringify(authority.slice(0, 60))} is not a plain \`host\` or \`host:port\`. Userinfo (\`user:pass@host\`), escapes and other URL syntax are read differently by this gate than by cloudflared \u2014 \`http://edge:tok@app:80\` names the EDGE here and routes to the APP there \u2014 so it cannot be audited. Write \`scheme://<container>:<port>\` with no credentials.`
|
|
396
|
+
);
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
399
|
+
emitTarget(rawService, hostname);
|
|
240
400
|
}
|
|
241
|
-
return targets;
|
|
401
|
+
return { targets, rules, unmodelled };
|
|
242
402
|
}
|
|
243
403
|
async function findUnreachableIngressTargets(targets, probe) {
|
|
244
404
|
const results = await Promise.all(
|
|
@@ -246,6 +406,56 @@ async function findUnreachableIngressTargets(targets, probe) {
|
|
|
246
406
|
);
|
|
247
407
|
return results.filter((r) => !r.reachable).map((r) => r.t);
|
|
248
408
|
}
|
|
409
|
+
var SSO_GATED_HOSTNAME_LABELS = ["crm", "wiki", "erp", "dashboard"];
|
|
410
|
+
var SSO_EDGE_SERVICE_HOST = "exe-sso-edge";
|
|
411
|
+
function findSsoUngatedIngressHostnames(configYml) {
|
|
412
|
+
const { rules } = walkCloudflaredIngress(configYml);
|
|
413
|
+
const offenders = [];
|
|
414
|
+
for (const rule of rules) {
|
|
415
|
+
if (!rule.hostname) continue;
|
|
416
|
+
const label = rule.hostname.split(".")[0]?.toLowerCase() ?? "";
|
|
417
|
+
if (!SSO_GATED_HOSTNAME_LABELS.includes(label)) continue;
|
|
418
|
+
if (rule.host === void 0) continue;
|
|
419
|
+
if (rule.host.toLowerCase() === SSO_EDGE_SERVICE_HOST) continue;
|
|
420
|
+
offenders.push({ hostname: rule.hostname, label, service: rule.service, host: rule.host });
|
|
421
|
+
}
|
|
422
|
+
return offenders;
|
|
423
|
+
}
|
|
424
|
+
function verifySsoGatedIngressRouting(configYml) {
|
|
425
|
+
if (!configYml || configYml.trim() === "") return;
|
|
426
|
+
const unmodelled = findUnauditableIngressSyntax(configYml);
|
|
427
|
+
if (unmodelled.length > 0) {
|
|
428
|
+
throw new Error(
|
|
429
|
+
`[stack-update] cloudflared ingress: this config cannot be audited for SSO-edge routing.
|
|
430
|
+
|
|
431
|
+
${unmodelled.map((u) => ` - ${u}`).join("\n")}
|
|
432
|
+
|
|
433
|
+
THE SHAPE THIS GATE CAN AUDIT \u2014 one rule per concrete hostname, no \`path:\` on a rule that
|
|
434
|
+
serves an application, and a \`scheme://host\` service:
|
|
435
|
+
|
|
436
|
+
ingress:
|
|
437
|
+
- hostname: erp.example.com
|
|
438
|
+
service: http://exe-sso-edge:80
|
|
439
|
+
- hostname: monitor.example.com # a \`path:\` is fine on a DENY rule
|
|
440
|
+
path: /_/*
|
|
441
|
+
service: http_status:404
|
|
442
|
+
- service: http_status:404 # terminator, serves nothing
|
|
443
|
+
|
|
444
|
+
WHY IT REFUSES RATHER THAN GUESSES (bug 3fce7502): wildcards, path-scoped app routes,
|
|
445
|
+
app-serving catch-alls and socket services all decide which rule serves a product by rules
|
|
446
|
+
this gate does not resolve. Reporting "no offenders" for routing nobody could read is how a
|
|
447
|
+
product ends up served around the SSO edge with its cross-app logout silently dead.`
|
|
448
|
+
);
|
|
449
|
+
}
|
|
450
|
+
const offenders = findSsoUngatedIngressHostnames(configYml);
|
|
451
|
+
if (offenders.length === 0) return;
|
|
452
|
+
const lines = offenders.map((o) => ` - ${o.hostname} -> ${o.service} (should be http://${SSO_EDGE_SERVICE_HOST}:80)`).join("\n");
|
|
453
|
+
throw new Error(
|
|
454
|
+
`[stack-update] cloudflared ingress: SSO-gated hostname(s) bypass the SSO edge:
|
|
455
|
+
${lines}
|
|
456
|
+
These hostnames must route through exe-sso-edge, which selects the app by Host header. Routing straight at the app container skips the unauthenticated 302 to auth.<domain> AND the cross-app-logout check, so a user who signs out at the apex stays signed in to that app (bug 3fce7502). Point the rule at http://exe-sso-edge:80 and re-deploy.`
|
|
457
|
+
);
|
|
458
|
+
}
|
|
249
459
|
function resolveTransitiveDeps(selected, depsMap) {
|
|
250
460
|
const resolved = new Set(selected);
|
|
251
461
|
const queue = [...selected];
|
|
@@ -2139,15 +2349,39 @@ function randomSecret(bytes = 32) {
|
|
|
2139
2349
|
function randomHexSecret(bytes = 24) {
|
|
2140
2350
|
return randomBytes(bytes).toString("hex");
|
|
2141
2351
|
}
|
|
2352
|
+
var EXTERNAL_INPUT_ENV_KEYS = /* @__PURE__ */ new Set([
|
|
2353
|
+
"API_ROUTER_KEY",
|
|
2354
|
+
"MONITOR_AGENT_KEY",
|
|
2355
|
+
"MONITOR_AGENT_TOKEN",
|
|
2356
|
+
"CLOUDFLARE_TUNNEL_TOKEN",
|
|
2357
|
+
"R2_MEDIA_ACCESS_KEY",
|
|
2358
|
+
"R2_MEDIA_SECRET_KEY",
|
|
2359
|
+
"SSH_PUBLIC_KEY",
|
|
2360
|
+
"SSH_PRIVATE_KEY"
|
|
2361
|
+
]);
|
|
2362
|
+
function isExternalInputKey(key) {
|
|
2363
|
+
return EXTERNAL_INPUT_ENV_KEYS.has(key) || key.endsWith("_API_KEY");
|
|
2364
|
+
}
|
|
2365
|
+
function deriveDeviceId(domain, rand = () => randomBytes(4).toString("hex")) {
|
|
2366
|
+
const label = domain.trim().toLowerCase().replace(/^https?:\/\//, "").split("/")[0]?.split(".")[0] ?? "";
|
|
2367
|
+
const slug = label.replace(/[^a-z0-9-]/g, "");
|
|
2368
|
+
return slug ? `vps-${slug}` : `vps-${rand()}`;
|
|
2369
|
+
}
|
|
2142
2370
|
function hydrateEnv(raw, opts) {
|
|
2143
2371
|
let next = raw;
|
|
2144
2372
|
const license = opts.licenseKey || process.env.EXE_LICENSE_KEY || loadLicense() || "";
|
|
2145
2373
|
const domain = opts.domain || process.env.EXE_STACK_DOMAIN || process.env.CUSTOMER_DOMAIN || "";
|
|
2374
|
+
const adminEmail = (opts.adminEmail || process.env.EXE_STACK_ADMIN_EMAIL || "").trim();
|
|
2146
2375
|
const replacements = {};
|
|
2147
2376
|
const env = parseEnv(raw);
|
|
2377
|
+
const wikiProvider = (env.get("WIKI_LLM_PROVIDER") ?? "").trim().toLowerCase();
|
|
2378
|
+
const wikiUsesAnthropic = wikiProvider === "anthropic" || wikiProvider === "";
|
|
2148
2379
|
for (const [key, value] of env.entries()) {
|
|
2149
2380
|
if (!/CHANGEME/.test(value)) continue;
|
|
2150
2381
|
if (key === "EXE_LICENSE_KEY" && license) replacements[key] = license;
|
|
2382
|
+
else if ((key === "EXE_CRM_ADMIN_EMAIL" || key === "MONITOR_HUB_ADMIN_EMAIL") && adminEmail) replacements[key] = adminEmail;
|
|
2383
|
+
else if (key === "EXED_DEVICE_ID") replacements[key] = deriveDeviceId(domain);
|
|
2384
|
+
else if (key === "WIKI_ANTHROPIC_API_KEY" && !wikiUsesAnthropic) replacements[key] = "";
|
|
2151
2385
|
else if (key === "MONITOR_AGENT_TOKEN" || key === "MONITOR_AGENT_KEY") continue;
|
|
2152
2386
|
else if (key === "CLOUDFLARE_TUNNEL_TOKEN") continue;
|
|
2153
2387
|
else if (key === "EXE_GATEWAY_WS_RELAY_AUTH_TOKEN") replacements[key] = randomHexSecret(24);
|
|
@@ -2155,7 +2389,8 @@ function hydrateEnv(raw, opts) {
|
|
|
2155
2389
|
else if (key.endsWith("_TOKEN")) replacements[key] = randomHexSecret(32);
|
|
2156
2390
|
else if (key.endsWith("_SECRET") || key.endsWith("_SALT")) replacements[key] = randomSecret(32);
|
|
2157
2391
|
else if (key === "EXE_MONITOR_KEY") replacements[key] = randomSecret(32);
|
|
2158
|
-
else if (
|
|
2392
|
+
else if (isExternalInputKey(key)) continue;
|
|
2393
|
+
else if (key.endsWith("_KEY") && key !== "EXE_LICENSE_KEY") replacements[key] = randomSecret(32);
|
|
2159
2394
|
}
|
|
2160
2395
|
if (domain) next = next.replaceAll("CHANGEME_DOMAIN", domain);
|
|
2161
2396
|
next = patchEnv(next, replacements);
|
|
@@ -2574,6 +2809,13 @@ function applyPostgresInitSql(composeArgs, envFile, composeFile, exec) {
|
|
|
2574
2809
|
]);
|
|
2575
2810
|
console.log("[stack-update] \u2713 Postgres init SQL applied");
|
|
2576
2811
|
}
|
|
2812
|
+
var LIVE_ARTIFACT_MATCHES_MANIFEST_CHECK = "Live artifact matches signed manifest";
|
|
2813
|
+
function isFatalLiveArtifactFailure(result) {
|
|
2814
|
+
if (result.check !== LIVE_ARTIFACT_MATCHES_MANIFEST_CHECK) return false;
|
|
2815
|
+
if (result.status !== "fail") return false;
|
|
2816
|
+
if (!result.verdicts) return true;
|
|
2817
|
+
return (result.verdicts.disagrees ?? 0) > 0;
|
|
2818
|
+
}
|
|
2577
2819
|
async function runStackUpdate(options) {
|
|
2578
2820
|
const exec = options.exec ?? defaultExec;
|
|
2579
2821
|
const now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
@@ -2768,6 +3010,10 @@ ${lines.join("\n")}`
|
|
|
2768
3010
|
allowUnmanifestedServices: options.allowUnmanifestedServices
|
|
2769
3011
|
});
|
|
2770
3012
|
}
|
|
3013
|
+
if (!options.dryRun) {
|
|
3014
|
+
assertServiceEnvContract(stagedCompose.raw, `the compose template at ${stagedCompose.templatePath}`);
|
|
3015
|
+
}
|
|
3016
|
+
reportDeployedServiceEnvGaps(composeRaw, options.composeFile, stagedCompose.shouldRefresh);
|
|
2771
3017
|
const previousVersion = readCurrentStackVersion(lockFile);
|
|
2772
3018
|
if (options.verifyImages) {
|
|
2773
3019
|
const endPhase = startPhase("verify images");
|
|
@@ -3246,6 +3492,7 @@ Push the missing image(s) to the registry, or re-run with --break-glass <reason>
|
|
|
3246
3492
|
defaultIngressReachabilityProbe,
|
|
3247
3493
|
makeDefaultComposeServiceProbe(composeArgs)
|
|
3248
3494
|
);
|
|
3495
|
+
verifySsoGatedIngressRouting(cfIngressConfigYml);
|
|
3249
3496
|
}
|
|
3250
3497
|
const stackEnv = existsSync(options.envFile) ? parseEnv(readFileSync(options.envFile, "utf8")) : void 0;
|
|
3251
3498
|
const partialRun = failedManifestServices.size > 0;
|
|
@@ -3354,7 +3601,21 @@ Push the missing image(s) to the registry, or re-run with --break-glass <reason>
|
|
|
3354
3601
|
if (!options.verifyStack) {
|
|
3355
3602
|
throw new Error("verifyStack hook not provided");
|
|
3356
3603
|
}
|
|
3357
|
-
|
|
3604
|
+
let expectedArtifacts;
|
|
3605
|
+
try {
|
|
3606
|
+
expectedArtifacts = declaredArtifactsFromManifest(
|
|
3607
|
+
{ latest: plan.targetVersion, stacks: { [plan.targetVersion]: plan.release } },
|
|
3608
|
+
{ stackVersion: plan.targetVersion }
|
|
3609
|
+
);
|
|
3610
|
+
} catch {
|
|
3611
|
+
expectedArtifacts = void 0;
|
|
3612
|
+
}
|
|
3613
|
+
const verifyReport = await options.verifyStack({
|
|
3614
|
+
composeFile: options.composeFile,
|
|
3615
|
+
envFile: options.envFile,
|
|
3616
|
+
stackVersion: plan.targetVersion,
|
|
3617
|
+
expectedArtifacts
|
|
3618
|
+
});
|
|
3358
3619
|
const securityFailures = [];
|
|
3359
3620
|
for (const r of verifyReport.results) {
|
|
3360
3621
|
if (r.status === "fail") {
|
|
@@ -3362,6 +3623,8 @@ Push the missing image(s) to the registry, or re-run with --break-glass <reason>
|
|
|
3362
3623
|
const isTruncatedRun = r.check === "Total timeout";
|
|
3363
3624
|
if (isTruncatedRun || /security|auth|signup|password|ssl|tls|bind|exposed/i.test(r.check)) {
|
|
3364
3625
|
securityFailures.push(`${r.check}: ${r.message}`);
|
|
3626
|
+
} else if (isFatalLiveArtifactFailure(r)) {
|
|
3627
|
+
securityFailures.push(`${r.check}: ${r.message}`);
|
|
3365
3628
|
}
|
|
3366
3629
|
}
|
|
3367
3630
|
}
|
|
@@ -4121,8 +4384,11 @@ export {
|
|
|
4121
4384
|
parseComposeServiceNames,
|
|
4122
4385
|
isUsableTunnelToken,
|
|
4123
4386
|
isCloudflaredTunnelMisconfigured,
|
|
4387
|
+
findUnauditableIngressSyntax,
|
|
4124
4388
|
parseCloudflaredIngressTargets,
|
|
4125
4389
|
findUnreachableIngressTargets,
|
|
4390
|
+
findSsoUngatedIngressHostnames,
|
|
4391
|
+
verifySsoGatedIngressRouting,
|
|
4126
4392
|
resolveTransitiveDeps,
|
|
4127
4393
|
filterServicesBySelection,
|
|
4128
4394
|
buildDefaultServiceSelection,
|
|
@@ -4184,10 +4450,14 @@ export {
|
|
|
4184
4450
|
assertImageVersionLabels,
|
|
4185
4451
|
applyGatewayOverlays,
|
|
4186
4452
|
backupStackConfig,
|
|
4453
|
+
deriveDeviceId,
|
|
4454
|
+
hydrateEnv,
|
|
4187
4455
|
pairMonitorAgent,
|
|
4188
4456
|
bootstrapStackHost,
|
|
4189
4457
|
assertHostReadyForApply,
|
|
4190
4458
|
hardenHost,
|
|
4459
|
+
LIVE_ARTIFACT_MATCHES_MANIFEST_CHECK,
|
|
4460
|
+
isFatalLiveArtifactFailure,
|
|
4191
4461
|
runStackUpdate,
|
|
4192
4462
|
readCurrentStackVersion,
|
|
4193
4463
|
listAvailableVersions,
|
|
@@ -30,6 +30,16 @@ function updateLoadWindow(samples, nowMs, load1m, wallElapsedMs, keepMs) {
|
|
|
30
30
|
blockStartMs
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
|
+
var NOT_SCHEDULED_CPU_FLOOR = 0.02;
|
|
34
|
+
var HOST_SUSPENDED_TICK_CEILING = 0.5;
|
|
35
|
+
function isHostSuspendedWindow(lagMs, severeThresholdMs, selfCpuBusyFraction, hostTickFraction, cpuFloor = NOT_SCHEDULED_CPU_FLOOR, tickCeiling = HOST_SUSPENDED_TICK_CEILING) {
|
|
36
|
+
if (!Number.isFinite(lagMs) || lagMs <= severeThresholdMs) return false;
|
|
37
|
+
if (typeof selfCpuBusyFraction !== "number" || !Number.isFinite(selfCpuBusyFraction)) return false;
|
|
38
|
+
if (typeof hostTickFraction !== "number" || !Number.isFinite(hostTickFraction)) return false;
|
|
39
|
+
const selfLimit = Number.isFinite(cpuFloor) && cpuFloor >= 0 ? cpuFloor : NOT_SCHEDULED_CPU_FLOOR;
|
|
40
|
+
const hostLimit = Number.isFinite(tickCeiling) && tickCeiling >= 0 ? tickCeiling : HOST_SUSPENDED_TICK_CEILING;
|
|
41
|
+
return selfCpuBusyFraction <= selfLimit && hostTickFraction < hostLimit;
|
|
42
|
+
}
|
|
33
43
|
function decideDaemonSelfHeal(s) {
|
|
34
44
|
const alive = s.processAlive ?? true;
|
|
35
45
|
if (!alive) {
|
|
@@ -76,6 +86,16 @@ function decideDaemonSelfHeal(s) {
|
|
|
76
86
|
selfInflictedSuppressedMsAfter: sumInWindow
|
|
77
87
|
};
|
|
78
88
|
}
|
|
89
|
+
if (isHostSuspendedWindow(
|
|
90
|
+
s.lagMs,
|
|
91
|
+
s.severeThresholdMs,
|
|
92
|
+
s.selfCpuBusyFraction,
|
|
93
|
+
s.hostTickFraction,
|
|
94
|
+
s.notScheduledCpuFloor,
|
|
95
|
+
s.hostSuspendedTickCeiling
|
|
96
|
+
)) {
|
|
97
|
+
return { restart: false, reason: "host_suspended_backoff", consecutiveSevereAfter: 0, ...carry };
|
|
98
|
+
}
|
|
79
99
|
if (s.lagMs > s.singleBlockMs) {
|
|
80
100
|
return { restart: true, reason: "single_block", consecutiveSevereAfter: 0, ...cleared };
|
|
81
101
|
}
|
|
@@ -134,13 +154,34 @@ function computeBootRetryAfterSeconds(nowMs, readyEtaMs, opts = {}) {
|
|
|
134
154
|
const maxS = opts.maxS ?? 60;
|
|
135
155
|
return Math.min(maxS, Math.max(minS, Math.ceil((readyEtaMs - nowMs) / 1e3)));
|
|
136
156
|
}
|
|
157
|
+
function totalHostCpuMs(cpus) {
|
|
158
|
+
if (!Array.isArray(cpus) || cpus.length === 0) return void 0;
|
|
159
|
+
let total = 0;
|
|
160
|
+
for (const c of cpus) {
|
|
161
|
+
const t = c?.times;
|
|
162
|
+
if (!t) return void 0;
|
|
163
|
+
total += t.user + t.nice + t.sys + t.idle + t.irq;
|
|
164
|
+
}
|
|
165
|
+
return Number.isFinite(total) ? total : void 0;
|
|
166
|
+
}
|
|
167
|
+
function hostTickFractionFor(previousTotalMs, currentTotalMs, coreCount, wallElapsedMs) {
|
|
168
|
+
if (typeof previousTotalMs !== "number" || !Number.isFinite(previousTotalMs)) return void 0;
|
|
169
|
+
if (typeof currentTotalMs !== "number" || !Number.isFinite(currentTotalMs)) return void 0;
|
|
170
|
+
if (typeof coreCount !== "number" || !Number.isFinite(coreCount) || coreCount <= 0) return void 0;
|
|
171
|
+
if (!Number.isFinite(wallElapsedMs)) return void 0;
|
|
172
|
+
if (wallElapsedMs <= 0) return 1;
|
|
173
|
+
return Math.max(0, currentTotalMs - previousTotalMs) / (coreCount * wallElapsedMs);
|
|
174
|
+
}
|
|
137
175
|
|
|
138
176
|
export {
|
|
139
177
|
isHostCpuStarved,
|
|
140
178
|
updateLoadWindow,
|
|
179
|
+
isHostSuspendedWindow,
|
|
141
180
|
decideDaemonSelfHeal,
|
|
142
181
|
decideStarvationDrainGuard,
|
|
143
182
|
decideOrchestrationTickSkip,
|
|
144
183
|
decideBootBackoff,
|
|
145
|
-
computeBootRetryAfterSeconds
|
|
184
|
+
computeBootRetryAfterSeconds,
|
|
185
|
+
totalHostCpuMs,
|
|
186
|
+
hostTickFractionFor
|
|
146
187
|
};
|
|
@@ -9,17 +9,17 @@ import {
|
|
|
9
9
|
import {
|
|
10
10
|
buildClaudeHttpMcpEntry,
|
|
11
11
|
buildClaudeStdioProxyMcpEntry
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-CYCIX7AW.js";
|
|
13
13
|
import {
|
|
14
14
|
ensureAllAgentSymlinks
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-6BJCDWSM.js";
|
|
16
16
|
import {
|
|
17
17
|
MCP_LEGACY_KEY,
|
|
18
18
|
MCP_PRIMARY_KEY
|
|
19
19
|
} from "./chunk-HYZV25LY.js";
|
|
20
20
|
import {
|
|
21
21
|
loadConfigSync
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-MMS2HBRT.js";
|
|
23
23
|
|
|
24
24
|
// src/adapters/claude/installer.ts
|
|
25
25
|
import { readFile, writeFile, mkdir, readdir, rm } from "fs/promises";
|
|
@@ -942,7 +942,7 @@ async function runInstaller(homeDir) {
|
|
|
942
942
|
);
|
|
943
943
|
}
|
|
944
944
|
try {
|
|
945
|
-
const { generateAgentDefs, summarizeAgentDefResults } = await import("./agent-defs-generator-
|
|
945
|
+
const { generateAgentDefs, summarizeAgentDefResults } = await import("./agent-defs-generator-7TFISIJQ.js");
|
|
946
946
|
const defResults = generateAgentDefs({ homeDir: resolvedHome });
|
|
947
947
|
process.stderr.write(`Agent definitions: ${summarizeAgentDefResults(defResults)}
|
|
948
948
|
`);
|