@askexenow/exe-os 0.9.371 → 0.9.373

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (463) hide show
  1. package/deploy/compose/.env.customer.example +17 -0
  2. package/deploy/compose/.env.example +18 -1
  3. package/deploy/compose/docker-compose.yml +81 -21
  4. package/deploy/compose/generate-env.ts +20 -3
  5. package/deploy/compose/sso-edge/default.conf.template +39 -7
  6. package/deploy/compose/sso-edge/sso-redirect.conf +73 -13
  7. package/deploy/stack-manifests/v0.9.30-apps.json +1 -1
  8. package/deploy/stack-manifests/v0.9.json +117 -2
  9. package/dist/.dist-verified.json +3 -3
  10. package/dist/{active-agent-JEUX2MHE.js → active-agent-BVREYGFJ.js} +7 -6
  11. package/dist/{active-agent-JXOH2JBH.js → active-agent-HLV7IEU3.js} +7 -6
  12. package/dist/{agent-defs-generator-J6A57TL6.js → agent-defs-generator-TFBUJ67B.js} +6 -5
  13. package/dist/{agent-loop-FOK2IRZQ.js → agent-loop-CYDFBCNA.js} +1 -1
  14. package/dist/{agentic-ontology-DRUE3NUX.js → agentic-ontology-WZKVHOUV.js} +1 -1
  15. package/dist/{artifact-backup-767STHSW.js → artifact-backup-WXZNB7KE.js} +2 -1
  16. package/dist/{backfill-gate-VX2RZTQV.js → backfill-gate-KWJQ35YX.js} +3 -2
  17. package/dist/{backfill-metadata-BZ7LEKAR.js → backfill-metadata-FN3YMSKC.js} +8 -7
  18. package/dist/{background-jobs-LTPWCMA3.js → background-jobs-6VMD55PK.js} +3 -2
  19. package/dist/{backup-verify-MYRJCSDR.js → backup-verify-76235AHA.js} +4 -3
  20. package/dist/{behavior-injection-BHCOAC4O.js → behavior-injection-76FH424R.js} +15 -14
  21. package/dist/{behaviors-352X5WJ6.js → behaviors-33WKK3BG.js} +19 -12
  22. package/dist/bin/age-ontology-load.js +3 -2
  23. package/dist/bin/agentic-ontology-backfill.js +10 -9
  24. package/dist/bin/agentic-reflection-backfill.js +11 -10
  25. package/dist/bin/agentic-semantic-label.js +10 -9
  26. package/dist/bin/backfill-conversations.js +11 -10
  27. package/dist/bin/backfill-responses.js +11 -10
  28. package/dist/bin/backfill-vectors.js +15 -14
  29. package/dist/bin/bulk-sync-postgres.js +20 -19
  30. package/dist/bin/cc-doctor.js +10 -9
  31. package/dist/bin/cleanup-stale-review-tasks.js +27 -25
  32. package/dist/bin/cli.js +41 -26
  33. package/dist/bin/deferred-daemon-restart.js +111 -108
  34. package/dist/bin/exe-agent-config.js +6 -5
  35. package/dist/bin/exe-agent.js +124 -31
  36. package/dist/bin/exe-assign.js +13 -12
  37. package/dist/bin/exe-boot.js +67 -55
  38. package/dist/bin/exe-call.js +8 -7
  39. package/dist/bin/exe-cloud.js +22 -21
  40. package/dist/bin/exe-config-dump.js +6 -5
  41. package/dist/bin/exe-dispatch.js +28 -26
  42. package/dist/bin/exe-doctor.js +12 -10
  43. package/dist/bin/exe-export-behaviors.js +17 -16
  44. package/dist/bin/exe-forget.js +10 -9
  45. package/dist/bin/exe-gateway.js +199 -19
  46. package/dist/bin/exe-grant.js +5 -5
  47. package/dist/bin/exe-healthcheck.js +10 -9
  48. package/dist/bin/exe-heartbeat.js +33 -31
  49. package/dist/bin/exe-kill.js +32 -30
  50. package/dist/bin/exe-launch-agent.js +124 -53
  51. package/dist/bin/exe-mcp.js +6 -5
  52. package/dist/bin/exe-memory-reads.js +8 -7
  53. package/dist/bin/exe-new-employee.js +12 -11
  54. package/dist/bin/exe-os-mcp-proxy.js +6 -5
  55. package/dist/bin/exe-pending-messages.js +28 -26
  56. package/dist/bin/exe-pending-notifications.js +27 -25
  57. package/dist/bin/exe-pending-reviews.js +28 -26
  58. package/dist/bin/exe-rename.js +8 -7
  59. package/dist/bin/exe-repo-truth.js +369 -0
  60. package/dist/bin/exe-review.js +31 -29
  61. package/dist/bin/exe-search.js +9 -8
  62. package/dist/bin/exe-session-cleanup.js +33 -31
  63. package/dist/bin/exe-settings.js +22 -21
  64. package/dist/bin/exe-start-codex.js +135 -54
  65. package/dist/bin/exe-start-opencode.js +119 -22
  66. package/dist/bin/exe-status.js +29 -27
  67. package/dist/bin/exe-support.js +5 -4
  68. package/dist/bin/exe-team.js +7 -6
  69. package/dist/bin/exe-watchdog.js +19 -10
  70. package/dist/bin/generate-hook-manifest.js +44 -7
  71. package/dist/bin/git-sweep.js +29 -27
  72. package/dist/bin/graph-backfill.js +88 -34
  73. package/dist/bin/graph-export.js +9 -8
  74. package/dist/bin/import-history.js +13 -12
  75. package/dist/bin/install.js +133 -110
  76. package/dist/bin/intercom-check.js +5 -5
  77. package/dist/bin/mcp-sessions.js +2 -2
  78. package/dist/bin/orchestration-metrics.js +7 -6
  79. package/dist/bin/postgres-agentic-reflection-backfill.js +5 -4
  80. package/dist/bin/postgres-agentic-semantic-backfill.js +4 -3
  81. package/dist/bin/pre-publish.js +1 -1
  82. package/dist/bin/reconcile-backlog.js +2 -2
  83. package/dist/bin/registry-proxy.js +1 -1
  84. package/dist/bin/scan-tasks.js +27 -25
  85. package/dist/bin/setup.js +5 -4
  86. package/dist/bin/shard-migrate.js +9 -8
  87. package/dist/bin/stack-update.js +39 -9
  88. package/dist/bin/verify-stack.js +2 -2
  89. package/dist/bin/vps-health-gate.js +1 -1
  90. package/dist/{boot-generation-ZLU4WCQM.js → boot-generation-QY4H2VST.js} +6 -5
  91. package/dist/{boot-review-sections-N6BNB6XH.js → boot-review-sections-ITQVY2ZQ.js} +26 -24
  92. package/dist/branch-hygiene-U5GFRSTP.js +308 -0
  93. package/dist/{branding-GH43W3PU.js → branding-I6KIMB7F.js} +3 -2
  94. package/dist/budget-fallback-XJRPMP2D.js +11 -0
  95. package/dist/build-manifest.json +1282 -1217
  96. package/dist/{capability-cards-KQOG53EI.js → capability-cards-JDJTJX4D.js} +5 -4
  97. package/dist/{capacity-monitor-AUDIPQFT.js → capacity-monitor-GK5IB6FJ.js} +28 -26
  98. package/dist/{catchup-brief-HRSMXUUZ.js → catchup-brief-ROSFMS46.js} +32 -30
  99. package/dist/{chunk-V7CLIEDZ.js → chunk-2HB5U5QT.js} +2 -2
  100. package/dist/{chunk-MWWSJ5FO.js → chunk-2W5J4T2F.js} +338 -5
  101. package/dist/{chunk-IDZPQG2D.js → chunk-3FLDC2ZI.js} +2 -2
  102. package/dist/{chunk-R5YGJRSH.js → chunk-3J37XIWU.js} +45 -28
  103. package/dist/{chunk-75R6NMW5.js → chunk-3LQVIRGL.js} +1 -1
  104. package/dist/{chunk-JTB5V6BV.js → chunk-3SXHEQ7X.js} +1 -1
  105. package/dist/{chunk-ZVDF4Y6O.js → chunk-3W7U6ZKY.js} +51 -21
  106. package/dist/{chunk-BN7NSTFF.js → chunk-45KCQK24.js} +2 -2
  107. package/dist/{chunk-CDUB5Q6J.js → chunk-4IK2K3B3.js} +1 -1
  108. package/dist/{chunk-7MXJXYJS.js → chunk-4IZ2ELU7.js} +1 -1
  109. package/dist/{chunk-WTDNYATC.js → chunk-4VB6NJOL.js} +60 -18
  110. package/dist/{chunk-QESZNU5H.js → chunk-4XUPFJNB.js} +4 -4
  111. package/dist/{chunk-ZWHDGIHV.js → chunk-4Y523526.js} +244 -49
  112. package/dist/{chunk-PVEM537A.js → chunk-4YLBKEL5.js} +2 -2
  113. package/dist/chunk-4YNA3CM6.js +872 -0
  114. package/dist/{chunk-MCBPDKWB.js → chunk-52EK7KIA.js} +719 -28
  115. package/dist/{chunk-DRFRUDML.js → chunk-5SDE2HWI.js} +4 -4
  116. package/dist/{chunk-HK6BHPXG.js → chunk-6D5KMMK4.js} +5 -5
  117. package/dist/{chunk-QYV6JWP3.js → chunk-6F4QFV4Q.js} +9 -3
  118. package/dist/{chunk-Q7YSVIJL.js → chunk-6KS57E66.js} +3 -3
  119. package/dist/{chunk-5Y43SCSF.js → chunk-6WMJHNGN.js} +1 -1
  120. package/dist/{chunk-TCTED52S.js → chunk-6WUXRDTF.js} +57 -1
  121. package/dist/{chunk-XPRZ6LLL.js → chunk-72Y3I24H.js} +2 -2
  122. package/dist/{chunk-X7IU6JM7.js → chunk-7HNQK2JA.js} +1 -1
  123. package/dist/{chunk-DVUQYAUC.js → chunk-7P6YUA53.js} +1 -1
  124. package/dist/{chunk-2CWS374F.js → chunk-7RI2CNXJ.js} +1 -1
  125. package/dist/{chunk-WNHGHO7M.js → chunk-7TIAQUBH.js} +1 -1
  126. package/dist/{chunk-DSOQUQTV.js → chunk-A27Q27CT.js} +27 -0
  127. package/dist/{chunk-3SL3C2GZ.js → chunk-AMPNM6SB.js} +44 -14
  128. package/dist/{chunk-VHUIVLOZ.js → chunk-AWKZRRPX.js} +6 -6
  129. package/dist/{chunk-UINNP65J.js → chunk-BZYEOIT3.js} +9 -9
  130. package/dist/{chunk-QCQT5RXR.js → chunk-C2L622QJ.js} +184 -6
  131. package/dist/{chunk-TX3Q2GIL.js → chunk-C5HUMAA7.js} +24 -1
  132. package/dist/{chunk-X2P43TB2.js → chunk-D2AR5PXE.js} +1 -1
  133. package/dist/{chunk-NYEJOJVS.js → chunk-DMPIS4BY.js} +3 -3
  134. package/dist/{chunk-YKXQT3ZW.js → chunk-DRXO46LA.js} +1 -1
  135. package/dist/{chunk-WSOA3WMC.js → chunk-E426DOSY.js} +161 -4
  136. package/dist/{chunk-ZGSAKOMA.js → chunk-E7DFTCUW.js} +3 -3
  137. package/dist/{chunk-RIECV7SR.js → chunk-EKYYMIVT.js} +1 -1
  138. package/dist/{chunk-GC2AIMNA.js → chunk-EM7NP2AC.js} +51 -6
  139. package/dist/{chunk-UYAQRBHY.js → chunk-FGHPLZDF.js} +4 -4
  140. package/dist/{chunk-GKFO2ASR.js → chunk-FLNUXH6H.js} +3 -3
  141. package/dist/{chunk-YYA5LXCT.js → chunk-FNEZ4BWT.js} +1 -1
  142. package/dist/{chunk-3LI2UY56.js → chunk-G6P45SFB.js} +3 -3
  143. package/dist/{chunk-6656BVBH.js → chunk-GJD7D6HM.js} +30 -17
  144. package/dist/{chunk-AAMGHW5W.js → chunk-GLQEJOXE.js} +1 -0
  145. package/dist/{chunk-XTWHNLGD.js → chunk-GZOG2MAX.js} +1 -1
  146. package/dist/{chunk-E5HAY3DQ.js → chunk-HDLAB7W3.js} +1 -1
  147. package/dist/{chunk-VV5EZZNT.js → chunk-HTBEVCO2.js} +1 -1
  148. package/dist/{chunk-6HYV622V.js → chunk-HTUEAERH.js} +33 -14
  149. package/dist/{chunk-ZBT3C2WH.js → chunk-HWKSG33T.js} +3 -3
  150. package/dist/{chunk-QCCAOLAS.js → chunk-I422WQ3A.js} +2 -2
  151. package/dist/{chunk-QZL6E4UB.js → chunk-I73AHVH5.js} +2 -2
  152. package/dist/chunk-IBS2FAI4.js +195 -0
  153. package/dist/{chunk-AXVUURYS.js → chunk-ICHQULGD.js} +17 -3
  154. package/dist/{chunk-J5EYOBFF.js → chunk-IHXW4VUI.js} +1 -1
  155. package/dist/{chunk-KWMCCRM6.js → chunk-IMX3VIIT.js} +329 -164
  156. package/dist/{chunk-JK6LGA62.js → chunk-J4C442ZT.js} +1 -1
  157. package/dist/{chunk-ZWDWRWQW.js → chunk-J7RIPMDI.js} +7 -3
  158. package/dist/{chunk-4DGM3F7F.js → chunk-JG4IOKQE.js} +5 -5
  159. package/dist/{chunk-UUVRBSH4.js → chunk-JKLA7AUZ.js} +3 -3
  160. package/dist/{chunk-HVL53G6O.js → chunk-JS5XMVXY.js} +1 -1
  161. package/dist/{chunk-PRKEHXGC.js → chunk-JVKIRKLC.js} +3 -3
  162. package/dist/{chunk-2ADYTOHQ.js → chunk-K4ESASPL.js} +1 -1
  163. package/dist/{chunk-4YUQNYOJ.js → chunk-KBRHGXE7.js} +4 -4
  164. package/dist/{chunk-NQZUSEAR.js → chunk-KEC47ERR.js} +129 -16
  165. package/dist/{chunk-LNOS24GV.js → chunk-KXBMR4ZD.js} +5 -1
  166. package/dist/{chunk-LBRBL5S3.js → chunk-KXIYWHBU.js} +1 -1
  167. package/dist/{chunk-YAT5IEQK.js → chunk-L67OHDSD.js} +258 -13
  168. package/dist/{chunk-DZYDMHI5.js → chunk-L6MLYKY5.js} +1 -1
  169. package/dist/{chunk-OBY6D44R.js → chunk-L6WHOLGP.js} +7 -7
  170. package/dist/{chunk-XPDAFAS7.js → chunk-LFKRM3RK.js} +1 -1
  171. package/dist/{chunk-CQPXU7TX.js → chunk-LSY2JAFY.js} +12 -4
  172. package/dist/{chunk-H74466TM.js → chunk-M7O7TGGU.js} +1 -1
  173. package/dist/chunk-MJCSEIFI.js +54 -0
  174. package/dist/{chunk-FUPE3KJA.js → chunk-MJKWLOCW.js} +1 -1
  175. package/dist/{chunk-X5E5CVJG.js → chunk-MLYG3TI6.js} +5 -5
  176. package/dist/{chunk-ZQEHMWGI.js → chunk-MQAHDPU5.js} +2 -1
  177. package/dist/{chunk-FRLKE6CX.js → chunk-NFFCNZVD.js} +2 -2
  178. package/dist/{chunk-ZTZ6DM2M.js → chunk-NLGEFBND.js} +1 -1
  179. package/dist/chunk-NMICTLJK.js +261 -0
  180. package/dist/{chunk-B353FGPH.js → chunk-NMOEWLJY.js} +6 -6
  181. package/dist/{chunk-UOOCN72R.js → chunk-NY75HDWW.js} +1 -1
  182. package/dist/{chunk-ZLKDEKK5.js → chunk-O5HTTJ2X.js} +10 -2
  183. package/dist/{chunk-PNU7BPJ6.js → chunk-ODOLBT7W.js} +5 -5
  184. package/dist/{chunk-GBNB4EWD.js → chunk-ORM7ZFKC.js} +16 -0
  185. package/dist/{chunk-EIJRPAUS.js → chunk-OTJVG7JM.js} +2 -2
  186. package/dist/{chunk-SWYONKEF.js → chunk-P3DQL6JT.js} +1 -1
  187. package/dist/{chunk-UQUUNGTP.js → chunk-P5YTFPCV.js} +6 -6
  188. package/dist/{chunk-KCO4NVOF.js → chunk-PBVBMZGO.js} +18 -4
  189. package/dist/{chunk-E5QQZDQN.js → chunk-PFLDEJJJ.js} +358 -136
  190. package/dist/{chunk-3CIMDFXG.js → chunk-PFQ3VEEM.js} +1 -1
  191. package/dist/{chunk-PRMGNTW3.js → chunk-PHA3OES7.js} +1 -1
  192. package/dist/{chunk-SBJV2PCU.js → chunk-PHBU4LGO.js} +1 -1
  193. package/dist/{chunk-LQW7BZLZ.js → chunk-PLSY7Y5F.js} +2 -2
  194. package/dist/{chunk-THIJIOE2.js → chunk-PY3FOMRN.js} +18 -6
  195. package/dist/{chunk-5AOQEERG.js → chunk-Q3AXXKDF.js} +5 -5
  196. package/dist/chunk-QLZ46RCK.js +45 -0
  197. package/dist/{chunk-MIVFYHZM.js → chunk-QSAAN3H6.js} +30 -8
  198. package/dist/{chunk-UHPMK6QZ.js → chunk-R3CZWFFC.js} +10 -2
  199. package/dist/chunk-RH4AH3YB.js +80 -0
  200. package/dist/{chunk-CO4LNMLT.js → chunk-RHNIWSOP.js} +3 -3
  201. package/dist/{chunk-O7BGW45J.js → chunk-RHRK3VDF.js} +2 -2
  202. package/dist/{chunk-G5D62GZA.js → chunk-S37PAH7F.js} +5 -5
  203. package/dist/{chunk-A6BXK7AQ.js → chunk-SCHARPXE.js} +2 -2
  204. package/dist/{chunk-IBPCNS6U.js → chunk-SMGSSWCW.js} +94 -23
  205. package/dist/{chunk-JDDT3G7L.js → chunk-SNW6E3Y4.js} +1 -1
  206. package/dist/{chunk-IRYOOXZQ.js → chunk-SWK6MNAI.js} +20 -3
  207. package/dist/{chunk-LBDOJAGX.js → chunk-T35RCQFE.js} +6 -6
  208. package/dist/{chunk-IBFCSUJV.js → chunk-T7AZ5K5K.js} +1 -1
  209. package/dist/{chunk-CW2UCKHS.js → chunk-TADAO3HV.js} +2 -2
  210. package/dist/{chunk-S5W4OAVN.js → chunk-TN2AXREB.js} +1 -1
  211. package/dist/{chunk-ELSZZPKV.js → chunk-TRMR77JJ.js} +32 -10
  212. package/dist/chunk-TTELLO3M.js +131 -0
  213. package/dist/{chunk-6OJVMXAC.js → chunk-U45XMFOM.js} +4 -4
  214. package/dist/{chunk-OL3QP3AU.js → chunk-U6RXHPK4.js} +1 -1
  215. package/dist/{chunk-H37FSTF2.js → chunk-UBMZ3YQU.js} +1 -1
  216. package/dist/{chunk-6IWLAQ7O.js → chunk-UCUOGVDX.js} +4 -0
  217. package/dist/{chunk-V4SLIPZS.js → chunk-UEZQNJET.js} +1 -1
  218. package/dist/{chunk-PGLPUP37.js → chunk-UMNMC3DZ.js} +1 -1
  219. package/dist/{chunk-ZNUJFX7L.js → chunk-UQGSBM3U.js} +1 -1
  220. package/dist/{chunk-AGML75Y4.js → chunk-USMESBOR.js} +109 -13
  221. package/dist/{chunk-5RTDR52E.js → chunk-UUPAOKEO.js} +3 -3
  222. package/dist/{chunk-ZZXMB5F2.js → chunk-UZDF6FLJ.js} +1 -1
  223. package/dist/{chunk-JU5CF53A.js → chunk-V6KKNYF2.js} +64 -149
  224. package/dist/{chunk-UXLO7VHX.js → chunk-VI4ATC6I.js} +1 -1
  225. package/dist/{chunk-LAHOHXHD.js → chunk-VYNY7K44.js} +9 -9
  226. package/dist/{chunk-SQVBAWJ6.js → chunk-WC6WL52H.js} +2 -2
  227. package/dist/{chunk-ASERE4BL.js → chunk-WZFVNICF.js} +2 -2
  228. package/dist/{chunk-WLOAKBUB.js → chunk-X36BZYJ3.js} +4 -4
  229. package/dist/{chunk-PZBYI3ED.js → chunk-X63RNRZF.js} +22 -35
  230. package/dist/{chunk-XRFTLVRV.js → chunk-X65OJFQM.js} +1 -1
  231. package/dist/{chunk-6O73T44R.js → chunk-X7HB4KLA.js} +1 -1
  232. package/dist/{chunk-L2KHIVNA.js → chunk-XEPLZKEB.js} +3 -3
  233. package/dist/{chunk-FBSTMK4X.js → chunk-XPPQ4PBN.js} +828 -607
  234. package/dist/{chunk-KSQUNVPJ.js → chunk-XXNSHYPO.js} +3 -3
  235. package/dist/{chunk-QS6HI4B6.js → chunk-YKC7QDZH.js} +40 -13
  236. package/dist/{chunk-AJTRBGIC.js → chunk-YRC4NV2C.js} +2 -2
  237. package/dist/{chunk-VGMRL522.js → chunk-ZFFRW73K.js} +92 -14
  238. package/dist/{chunk-5ROSYSRQ.js → chunk-ZFXOA2CF.js} +33 -35
  239. package/dist/{chunk-QMSEL5YS.js → chunk-ZIG7VPJV.js} +28 -76
  240. package/dist/{chunk-Y72EP2Q7.js → chunk-ZN3FAXDX.js} +6 -6
  241. package/dist/{cleanup-graph-garbage-6DD6TADI.js → cleanup-graph-garbage-6IJ6GJY2.js} +10 -9
  242. package/dist/{cloud-sync-command-YXA4IEKT.js → cloud-sync-command-TZVPTKZV.js} +2 -2
  243. package/dist/{cloud-sync-db-init-H6QPNK3Z.js → cloud-sync-db-init-2QLU6GCD.js} +1 -1
  244. package/dist/{cloud-sync-shutdown-A6T7RQT2.js → cloud-sync-shutdown-OPCDMH4L.js} +5 -4
  245. package/dist/{co-activation-HSKIFJHU.js → co-activation-YMDKMDZ6.js} +5 -4
  246. package/dist/{co-occurrence-UW563FHZ.js → co-occurrence-VYWPQSLC.js} +8 -7
  247. package/dist/{code-context-index-D4MJ4VFX.js → code-context-index-QLJDRL7B.js} +6 -5
  248. package/dist/{codex-consolidation-PPXNBXCV.js → codex-consolidation-SH4UKFBQ.js} +2 -1
  249. package/dist/{conversation-entity-extractor-LFDOCVKB.js → conversation-entity-extractor-KGW4UEY4.js} +3 -3
  250. package/dist/{conversation-wiki-populator-EBUZXYEU.js → conversation-wiki-populator-OS4C6W54.js} +1 -1
  251. package/dist/conversations-retention-C4BLKFEL.js +54 -0
  252. package/dist/coordinator-notice-MHUY7AQB.js +55 -0
  253. package/dist/{crdt-sync-MGP67KLW.js → crdt-sync-QS2DHTKW.js} +1 -1
  254. package/dist/{crm-webhook-6DZSEFSP.js → crm-webhook-5PNRCVO2.js} +2 -2
  255. package/dist/{cto-delegation-gate-QPPDJGLY.js → cto-delegation-gate-LD4XTG6U.js} +27 -25
  256. package/dist/{daemon-auth-SSPY5ODS.js → daemon-auth-QZHEO7IQ.js} +3 -2
  257. package/dist/{daemon-orchestration-MXWB4ZOF.js → daemon-orchestration-XC2VTPVI.js} +34 -33
  258. package/dist/{daemon-ready-OT2VQLS7.js → daemon-ready-3WSKI3R5.js} +1 -1
  259. package/dist/{db-integrity-events-5DTASXJF.js → db-integrity-events-2DTFO37N.js} +3 -2
  260. package/dist/{db-restore-events-2FI4ZMKA.js → db-restore-events-G6NOQOVE.js} +2 -1
  261. package/dist/{destructive-data-guard-5SKHIZNN.js → destructive-data-guard-BVFWPPIS.js} +1 -1
  262. package/dist/doc-graph-extractor-6TVQTBLO.js +367 -0
  263. package/dist/{documents-KG5AACEM.js → documents-4WQ5MQR2.js} +13 -12
  264. package/dist/{dreaming-3VQVED4S.js → dreaming-SO4VH44W.js} +31 -29
  265. package/dist/{employee-boot-brief-CHKXWH4B.js → employee-boot-brief-Z4WTZVUC.js} +35 -33
  266. package/dist/{exe-drift-CSD2AAVQ.js → exe-drift-BWSUUAEA.js} +6 -5
  267. package/dist/{exe-export-DCJSNQXL.js → exe-export-4WPMVRNO.js} +15 -14
  268. package/dist/{exe-import-NLT7ABRP.js → exe-import-7C3SS62E.js} +15 -14
  269. package/dist/{exe-key-2DFWB3RD.js → exe-key-NFHZNJU6.js} +113 -110
  270. package/dist/{exe-org-6GZ54U6N.js → exe-org-5HYTAUH6.js} +24 -23
  271. package/dist/{exe-snapshot-PRLVRLLN.js → exe-snapshot-REKNH2WI.js} +34 -32
  272. package/dist/{fast-db-init-Y2MMNYVV.js → fast-db-init-OW6Z4YDB.js} +1 -1
  273. package/dist/{founder-context-7IEVQPD7.js → founder-context-6FAAM5LY.js} +4 -3
  274. package/dist/{founder-monitor-envelope-5KTKNL5G.js → founder-monitor-envelope-TFKRGCFE.js} +5 -4
  275. package/dist/{fts-integrity-LKAZEZJE.js → fts-integrity-4YB34KWX.js} +3 -2
  276. package/dist/gateway/index.js +19 -17
  277. package/dist/{git-main-guard-TGK3RQY3.js → git-main-guard-VTW4N3CM.js} +17 -1
  278. package/dist/{git-staleness-VXP474EL.js → git-staleness-ELGGOVRV.js} +5 -4
  279. package/dist/{global-procedures-XT7FBDNK.js → global-procedures-JBMGJRR6.js} +7 -6
  280. package/dist/{graph-auto-extract-DAWMUOJT.js → graph-auto-extract-O6IIL5O3.js} +8 -7
  281. package/dist/{graph-rag-F35FMFDG.js → graph-rag-WHZ6EPMW.js} +5 -3
  282. package/dist/{hook-integrity-Y3OAZFSH.js → hook-integrity-UU5OXONF.js} +14 -4
  283. package/dist/{hook-prefetch-A4WNG6CH.js → hook-prefetch-VWHIZBTX.js} +27 -25
  284. package/dist/hooks/bug-report-worker.js +32 -29
  285. package/dist/hooks/codex-stop-task-finalizer.js +34 -31
  286. package/dist/hooks/commit-complete.js +31 -29
  287. package/dist/hooks/error-recall.js +12 -11
  288. package/dist/hooks/exe-heartbeat-hook.js +8 -7
  289. package/dist/hooks/ingest-worker.js +21 -10
  290. package/dist/hooks/ingest.js +18 -17
  291. package/dist/hooks/instructions-loaded.js +10 -9
  292. package/dist/hooks/manifest.json +20 -20
  293. package/dist/hooks/notification.js +9 -8
  294. package/dist/hooks/post-compact.js +8 -7
  295. package/dist/hooks/post-tool-combined.js +26 -15
  296. package/dist/hooks/pre-compact.js +31 -29
  297. package/dist/hooks/pre-tool-use.js +402 -45
  298. package/dist/hooks/prompt-submit.js +55 -46
  299. package/dist/hooks/session-end.js +38 -40
  300. package/dist/hooks/session-start.js +21 -20
  301. package/dist/hooks/stop.js +38 -36
  302. package/dist/hooks/subagent-stop.js +36 -34
  303. package/dist/hooks/summary-worker.js +37 -35
  304. package/dist/hyde-MP4QNMU5.js +80 -0
  305. package/dist/index.js +42 -38
  306. package/dist/{installer-N4IBPKQP.js → installer-A3V2W3NV.js} +8 -7
  307. package/dist/{installer-OIJ5K2AR.js → installer-OYBQQ7BY.js} +8 -7
  308. package/dist/{installer-MMMNOFLS.js → installer-RYW65FRY.js} +8 -7
  309. package/dist/intercom-ack-VCW755TN.js +13 -0
  310. package/dist/{intercom-queue-S2PK53WU.js → intercom-queue-XBS5WVJM.js} +26 -24
  311. package/dist/{key-backup-status-6L2ARCXW.js → key-backup-status-LQPINQ3W.js} +2 -1
  312. package/dist/lib/agent-config.js +3 -2
  313. package/dist/lib/cloud-sync.js +24 -19
  314. package/dist/lib/config.js +2 -1
  315. package/dist/lib/consolidation.js +16 -9
  316. package/dist/lib/database.js +7 -4
  317. package/dist/lib/db-backup.js +17 -2
  318. package/dist/lib/db-daemon-client.js +6 -5
  319. package/dist/lib/db-write-worker-client.js +3 -1
  320. package/dist/lib/db-write-worker.js +20 -3
  321. package/dist/lib/db.js +7 -4
  322. package/dist/lib/device-registry.js +3 -2
  323. package/dist/lib/embed-worker.js +2 -1
  324. package/dist/lib/embedder.js +6 -5
  325. package/dist/lib/employee-templates.js +8 -7
  326. package/dist/lib/employees.js +5 -4
  327. package/dist/lib/exe-daemon-client.js +5 -4
  328. package/dist/lib/exe-daemon.js +360 -220
  329. package/dist/lib/hybrid-search.js +9 -8
  330. package/dist/lib/identity.js +5 -4
  331. package/dist/lib/license.js +6 -3
  332. package/dist/lib/messaging.js +27 -25
  333. package/dist/lib/post-tool-memory.js +16 -2
  334. package/dist/lib/registry-proxy.js +3 -1
  335. package/dist/lib/reminders.js +6 -5
  336. package/dist/lib/schedules.js +9 -8
  337. package/dist/lib/session-registry.js +7 -6
  338. package/dist/lib/skill-learning.js +14 -13
  339. package/dist/lib/stack-invariants.js +7 -1
  340. package/dist/lib/status-brief.js +5 -4
  341. package/dist/lib/store.js +10 -7
  342. package/dist/lib/task-router.js +6 -5
  343. package/dist/lib/tasks.js +29 -26
  344. package/dist/lib/tmux-routing.js +38 -24
  345. package/dist/lib/tmux-status.js +3 -1
  346. package/dist/lib/tmux-transport.js +2 -1
  347. package/dist/lib/token-spend.js +6 -5
  348. package/dist/lib/transport.js +3 -2
  349. package/dist/{license-gate-TQUNTYGQ.js → license-gate-EOLMF7J5.js} +5 -4
  350. package/dist/{license-sync-MELIT6GE.js → license-sync-ELY6PKEU.js} +4 -3
  351. package/dist/mcp/register-tools.js +110 -107
  352. package/dist/mcp/server.js +112 -109
  353. package/dist/mcp/tools/complete-reminder.js +7 -6
  354. package/dist/mcp/tools/create-reminder.js +7 -6
  355. package/dist/mcp/tools/create-task.js +32 -29
  356. package/dist/mcp/tools/deactivate-behavior.js +16 -15
  357. package/dist/mcp/tools/list-reminders.js +7 -6
  358. package/dist/mcp/tools/list-tasks.js +32 -29
  359. package/dist/mcp/tools/send-message.js +30 -28
  360. package/dist/mcp/tools/update-task.js +30 -27
  361. package/dist/mcp-child-registry-FVGV5XSB.js +24 -0
  362. package/dist/{mcp-http-config-V4CGMP2O.js → mcp-http-config-4PHK6RHB.js} +6 -5
  363. package/dist/{mcp-session-identity-6CI2MVTG.js → mcp-session-identity-5DBVDLQR.js} +26 -24
  364. package/dist/{memory-cards-LTM7NC52.js → memory-cards-WJM4NG3Q.js} +13 -8
  365. package/dist/{memory-graph-extractor-653465YU.js → memory-graph-extractor-TSTO7PYI.js} +9 -8
  366. package/dist/{memory-poisoning-defense-XEF6EJFZ.js → memory-poisoning-defense-BWVA5OBI.js} +5 -4
  367. package/dist/{memory-pressure-watchdog-CCTRSTCP.js → memory-pressure-watchdog-GES7RFL3.js} +27 -25
  368. package/dist/{memory-queue-QJNWKWKG.js → memory-queue-YF7IDSFY.js} +3 -2
  369. package/dist/{memory-queue-client-COA4ABEV.js → memory-queue-client-62NS3U56.js} +7 -6
  370. package/dist/{memory-reflection-A4XN5LJB.js → memory-reflection-6UAL4IHM.js} +32 -6
  371. package/dist/{monitor-grants-BW2WL4IU.js → monitor-grants-EV747HMW.js} +4 -3
  372. package/dist/{notification-ledger-LYFY6J6T.js → notification-ledger-E2WOQ3WQ.js} +28 -26
  373. package/dist/{notifications-CRMZYTZD.js → notifications-IHLUYF3E.js} +26 -24
  374. package/dist/{oauth-server-KEWQDSQ7.js → oauth-server-ZP5ZXRL7.js} +25 -4
  375. package/dist/{orchestration-events-BG7ECYYB.js → orchestration-events-TKZV4PAI.js} +6 -5
  376. package/dist/{orchestration-phase-UDS24CVQ.js → orchestration-phase-T2WD45UA.js} +3 -2
  377. package/dist/{orchestrator-CXBMAJ3V.js → orchestrator-MQXUNOS2.js} +28 -26
  378. package/dist/{org-brief-session-PGYGY47D.js → org-brief-session-7KKLV5OW.js} +13 -12
  379. package/dist/{org-consent-policy-3PNMR2ML.js → org-consent-policy-7AHSKB6L.js} +1 -1
  380. package/dist/{org-join-E5V5QFJ4.js → org-join-POWUG25F.js} +9 -8
  381. package/dist/{org-key-admin-FZW2PUZB.js → org-key-admin-E7EMDOZZ.js} +9 -8
  382. package/dist/{org-key-pin-5WUSPGVN.js → org-key-pin-WHWHVWUO.js} +4 -3
  383. package/dist/{org-membership-ESALTLLN.js → org-membership-WRT2IHJK.js} +5 -4
  384. package/dist/{org-partner-config-YKHPDPZR.js → org-partner-config-B7T4CL2T.js} +7 -6
  385. package/dist/{org-partner-runtime-Z7E3FAW4.js → org-partner-runtime-EVZKR2SJ.js} +13 -12
  386. package/dist/{org-row-visibility-G2K3XPZJ.js → org-row-visibility-GUMNPRK7.js} +1 -1
  387. package/dist/{pipeline-router-6ITGNPKO.js → pipeline-router-E5XQUJGU.js} +6 -5
  388. package/dist/{plan-limits-43MY7ZUK.js → plan-limits-AJ6K2P6R.js} +8 -7
  389. package/dist/{platform-procedures-I57ITMDC.js → platform-procedures-7YSCLF4Z.js} +1 -1
  390. package/dist/{postinstall-failure-B2JHNFPM.js → postinstall-failure-O6TSSNJB.js} +3 -2
  391. package/dist/{project-boot-A5SF6NXB.js → project-boot-5ZXAIOBB.js} +2 -1
  392. package/dist/project-name-FQKW5SFG.js +30 -0
  393. package/dist/{projection-worker-QXUIZL72.js → projection-worker-UKSYJ4PG.js} +5 -4
  394. package/dist/{prospective-memory-JF4KX7SB.js → prospective-memory-S22KIIBP.js} +5 -4
  395. package/dist/{push-notifications-7PXAAEA5.js → push-notifications-T5SJMFL4.js} +27 -25
  396. package/dist/reproject-worktree-memories-G6QO5J3X.js +398 -0
  397. package/dist/{reranker-43VKZIKQ.js → reranker-NYOFY5FK.js} +3 -2
  398. package/dist/{retrieval-health-PDXYWW4G.js → retrieval-health-LWDBIBWJ.js} +4 -3
  399. package/dist/{review-polling-6CZ2Q5LG.js → review-polling-BSZXGHER.js} +27 -25
  400. package/dist/runtime/index.js +36 -33
  401. package/dist/{session-events-APEFXOYX.js → session-events-EO7BFQ73.js} +29 -25
  402. package/dist/{session-kill-telemetry-7RHDZE2H.js → session-kill-telemetry-FXUGITZK.js} +27 -25
  403. package/dist/{session-mcp-config-F7KATWOF.js → session-mcp-config-SC5BLWZG.js} +3 -2
  404. package/dist/{session-scope-H5S6SIWW.js → session-scope-B3VWUG4G.js} +26 -24
  405. package/dist/{setup-wizard-5SC3DNUD.js → setup-wizard-3JEJSXXN.js} +5 -4
  406. package/dist/{shard-manager-UROHZE46.js → shard-manager-OE36A4MY.js} +3 -2
  407. package/dist/{skill-refinement-WXER7O2B.js → skill-refinement-5DDEQHGM.js} +6 -5
  408. package/dist/{stack-promote-KANK5AB6.js → stack-promote-KPEARCCS.js} +7 -6
  409. package/dist/{stack-release-PXLJNV7I.js → stack-release-FMGC57AD.js} +7 -6
  410. package/dist/{stack-update-NICYINJ3.js → stack-update-TZ4P6EXU.js} +50 -5
  411. package/dist/{steward-gate-YXVHUILI.js → steward-gate-PC6MD5VP.js} +6 -5
  412. package/dist/{subagent-brief-injection-YQEH65XW.js → subagent-brief-injection-NBSQ5IBS.js} +42 -35
  413. package/dist/{subagent-spawn-ledger-USYZXU3M.js → subagent-spawn-ledger-E6U3OY6Z.js} +3 -2
  414. package/dist/{support-inbox-7H25MDCH.js → support-inbox-M3HDZFVF.js} +20 -5
  415. package/dist/{task-enforcement-UO6YWPWA.js → task-enforcement-LXNIF3US.js} +27 -25
  416. package/dist/{task-request-inbox-4HJRWUJ6.js → task-request-inbox-3EFDJT4E.js} +1 -1
  417. package/dist/{task-scope-HYLP4GNF.js → task-scope-ERJTOAS4.js} +26 -24
  418. package/dist/{tasks-crud-FBDDZ7AA.js → tasks-crud-GUP437HH.js} +26 -24
  419. package/dist/{tasks-notify-Y24O7NUS.js → tasks-notify-AXFFZTI2.js} +27 -25
  420. package/dist/{tasks-review-WW6W3TNM.js → tasks-review-AYNV37GQ.js} +26 -24
  421. package/dist/{telemetry-upload-WZBHZLC6.js → telemetry-upload-4IP7KKIR.js} +10 -9
  422. package/dist/{token-budget-ANESTRO5.js → token-budget-UJD5CHUG.js} +6 -5
  423. package/dist/{tool-capability-index-ED5OAPMW.js → tool-capability-index-TCTWUUBO.js} +1 -1
  424. package/dist/{tool-gates-7PLIOLAL.js → tool-gates-JWVSAYTW.js} +1 -1
  425. package/dist/{tool-gates-2OZY3GZM.js → tool-gates-VXITVRFQ.js} +1 -1
  426. package/dist/{tool-telemetry-GUMN5D45.js → tool-telemetry-YRVOD2RP.js} +1 -1
  427. package/dist/tui/App.js +41 -39
  428. package/dist/{tui-data-TAXTMZSL.js → tui-data-ZUFCSQ3G.js} +26 -24
  429. package/dist/{update-support-WWGWPCU3.js → update-support-V5LF2KMQ.js} +20 -19
  430. package/dist/{whatsapp-QW3X7OCN.js → whatsapp-YM4A2CSK.js} +3 -1
  431. package/dist/{work-claims-XXHRJI5N.js → work-claims-2BECZ5GA.js} +6 -5
  432. package/dist/{work-state-heartbeat-PFPOZLVI.js → work-state-heartbeat-7TMN2GSO.js} +1 -1
  433. package/dist/{worker-gate-MRQ44Y4I.js → worker-gate-WUX2AYYZ.js} +3 -2
  434. package/dist/{workflow-engine-QIBHWCIH.js → workflow-engine-HDEYIAWI.js} +4 -2
  435. package/dist/{worktree-O3AE77YT.js → worktree-ZMNKH46X.js} +9 -6
  436. package/dist/worktree-ownership-guard-OUWJROW2.js +88 -0
  437. package/dist/{worktree-sweep-KX75U5TO.js → worktree-sweep-ZNX6R25W.js} +8 -7
  438. package/package.json +13 -4
  439. package/release-notes.json +16 -30
  440. package/src/commands/exe/call.md +1 -1
  441. package/stack.release.json +4 -4
  442. package/dist/branch-hygiene-HFJ3HA62.js +0 -232
  443. package/dist/chunk-KZXMP6JG.js +0 -319
  444. package/dist/chunk-W2IRQJ6R.js +0 -67
  445. package/dist/doc-graph-extractor-4XUPW4SI.js +0 -149
  446. package/dist/project-name-ILJTETUE.js +0 -14
  447. package/dist/reproject-worktree-memories-IXYGHTGA.js +0 -224
  448. /package/dist/{chunk-7XGXRD22.js → chunk-B72KXFDR.js} +0 -0
  449. /package/dist/{chunk-E4NB3B2R.js → chunk-D2Q3AYMB.js} +0 -0
  450. /package/dist/{chunk-IX6ZFC3M.js → chunk-DHWJMFR6.js} +0 -0
  451. /package/dist/{chunk-4XFQTDUS.js → chunk-IUXVUUIA.js} +0 -0
  452. /package/dist/{chunk-V4S5XV3S.js → chunk-NP62DK7V.js} +0 -0
  453. /package/dist/{chunk-25T6EERD.js → chunk-NZH5VSBC.js} +0 -0
  454. /package/dist/{chunk-XWJXNIBG.js → chunk-OJTF4SV7.js} +0 -0
  455. /package/dist/{chunk-FZQWVQJG.js → chunk-RWTYLRNY.js} +0 -0
  456. /package/dist/{chunk-6PDPYOAV.js → chunk-SBMBWO2Y.js} +0 -0
  457. /package/dist/{core-memory-NOF6XESC.js → core-memory-33XVE547.js} +0 -0
  458. /package/dist/{entity-boost-MT336PI3.js → entity-boost-JY3KNTO2.js} +0 -0
  459. /package/dist/{memory-isolation-SANJ4VHY.js → memory-isolation-Q3DSVL72.js} +0 -0
  460. /package/dist/{message-queue-client-MVBTYCSV.js → message-queue-client-VMVKIPV7.js} +0 -0
  461. /package/dist/{webhook-pipe-UQSEHFPO.js → webhook-pipe-W2FVXY7M.js} +0 -0
  462. /package/dist/{wiki-acl-XZMUIGP4.js → wiki-acl-EICCXRAK.js} +0 -0
  463. /package/dist/{wiki-client-AXNM5FWY.js → wiki-client-W65IOSWF.js} +0 -0
@@ -61,6 +61,23 @@ AUTH_DEFAULT_PRODUCT=AUTH
61
61
  # the sign-up UI/route instead of showing a form that always fails.
62
62
  AUTH_DISABLE_SIGNUP=true
63
63
 
64
+ # --- Session cookie contract (exe-auth v0.6.0) — INFORMATIONAL, not settings ---
65
+ # Recorded here because operators reason about XSS blast radius from this file,
66
+ # and an earlier draft of these notes described the OPPOSITE of what ships.
67
+ # exe-auth performs the GoTrue token exchange server-side in njs and sets:
68
+ # exe_sess HttpOnly Secure SameSite=Lax — the real access token
69
+ # exe_sess_refresh HttpOnly Secure SameSite=Lax — the real refresh token
70
+ # exe_access_token JS-readable, value literally "1" — presence sentinel only
71
+ # All three are scoped to the apex (AUTH_COOKIE_DOMAIN) so they are shared
72
+ # across product subdomains.
73
+ #
74
+ # The credentials are HttpOnly ON PURPOSE (security bug 368bf916): page
75
+ # JavaScript CANNOT read them, so an XSS on any subdomain cannot exfiltrate a
76
+ # session token from document.cookie. The only JS-readable cookie is the
77
+ # sentinel, whose value is the constant "1" and is not a credential.
78
+ # Apps must NOT read a token from document.cookie — send credentialed
79
+ # same-site requests and let the HttpOnly cookie ride along.
80
+
64
81
  # --- Centralized role administration (permissions) ---
65
82
  # The apps refuse to let an unmanaged first login mint its own admin
66
83
  # (exe-crm#102 / exe-wiki#45). Both flags below are therefore left at their
@@ -59,7 +59,7 @@ GOTRUE_EXTERNAL_URL=https://auth.CHANGEME_DOMAIN
59
59
  # Bug 51086951: JWT issuer pinned to the public auth URL so signer + consumers agree.
60
60
  GOTRUE_JWT_ISSUER=https://auth.CHANGEME_DOMAIN
61
61
  # SSO redirect allow-list (bug 66f8e10a) — app origins for unified SSO.
62
- GOTRUE_URI_ALLOW_LIST=https://crm.CHANGEME_DOMAIN,https://wiki.CHANGEME_DOMAIN,https://erp.CHANGEME_DOMAIN
62
+ GOTRUE_URI_ALLOW_LIST=https://crm.CHANGEME_DOMAIN,https://wiki.CHANGEME_DOMAIN,https://erp.CHANGEME_DOMAIN,https://dashboard.CHANGEME_DOMAIN,https://gateway.CHANGEME_DOMAIN
63
63
  # Bug 0327b017: parent-domain cookie → session shared across all subdomains.
64
64
  GOTRUE_COOKIE_DOMAIN=.CHANGEME_DOMAIN
65
65
  GOTRUE_COOKIE_KEY=exe-auth
@@ -95,6 +95,23 @@ AUTH_DEFAULT_PRODUCT=AUTH
95
95
  # the sign-up UI/route instead of showing a form that always fails.
96
96
  AUTH_DISABLE_SIGNUP=true
97
97
 
98
+ # --- Session cookie contract (exe-auth v0.6.0) — INFORMATIONAL, not settings ---
99
+ # Recorded here because operators reason about XSS blast radius from this file,
100
+ # and an earlier draft of these notes described the OPPOSITE of what ships.
101
+ # exe-auth performs the GoTrue token exchange server-side in njs and sets:
102
+ # exe_sess HttpOnly Secure SameSite=Lax — the real access token
103
+ # exe_sess_refresh HttpOnly Secure SameSite=Lax — the real refresh token
104
+ # exe_access_token JS-readable, value literally "1" — presence sentinel only
105
+ # All three are scoped to the apex (AUTH_COOKIE_DOMAIN) so they are shared
106
+ # across product subdomains.
107
+ #
108
+ # The credentials are HttpOnly ON PURPOSE (security bug 368bf916): page
109
+ # JavaScript CANNOT read them, so an XSS on any subdomain cannot exfiltrate a
110
+ # session token from document.cookie. The only JS-readable cookie is the
111
+ # sentinel, whose value is the constant "1" and is not a credential.
112
+ # Apps must NOT read a token from document.cookie — send credentialed
113
+ # same-site requests and let the HttpOnly cookie ride along.
114
+
98
115
  # --- Centralized role administration (permissions) ---
99
116
  # The apps refuse to let an unmanaged first login mint its own admin
100
117
  # (exe-crm#102 / exe-wiki#45). Both flags below are therefore left at their
@@ -176,6 +176,17 @@ services:
176
176
  GOTRUE_API_PORT: ${GOTRUE_API_PORT:-9999}
177
177
  GOTRUE_DB_DRIVER: postgres
178
178
  GOTRUE_DB_DATABASE_URL: postgres://${POSTGRES_USER:-exe}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}@exe-db:5432/${POSTGRES_DB:-exedb}?sslmode=disable&search_path=auth
179
+ # Bug 5c3023a2: GoTrue's DB pool kept connections forever (Go database/sql
180
+ # ConnMaxLifetime defaults to 0). When exe-db (Postgres) restarts during a
181
+ # deploy, GoTrue reused a dead pooled socket for the next `error finding
182
+ # user` query → "write tcp ... broken pipe" → random 500 on /token
183
+ # (founder-visible sign-in failure). exe-db sets NO finite server-side idle
184
+ # timeout, so these bounds sit well below Postgres's ceiling and below any
185
+ # network idle reap: recycle every connection within 5m and drop an idle
186
+ # one after 60s, so a connection killed by a restart is retired, not reused.
187
+ GOTRUE_DB_MAX_POOL_SIZE: ${GOTRUE_DB_MAX_POOL_SIZE:-10}
188
+ GOTRUE_DB_CONN_MAX_LIFETIME: ${GOTRUE_DB_CONN_MAX_LIFETIME:-300s}
189
+ GOTRUE_DB_CONN_MAX_IDLE_TIME: ${GOTRUE_DB_CONN_MAX_IDLE_TIME:-60s}
179
190
  # Bug ae113b23: never fall back to a hardcoded domain here.
180
191
  # GOTRUE_SITE_URL must be set in .env by generate-env.ts. An empty/missing
181
192
  # value is intentionally rejected at runtime so misconfigured stacks fail
@@ -319,7 +330,11 @@ services:
319
330
  # the live exe-db-jkt container (image v0.9.4): /app/beszel exists,
320
331
  # /beszel does not → the old `/beszel` healthcheck failed on every probe
321
332
  # (permanent false-unhealthy). Match the image's own HEALTHCHECK path.
322
- test: ["CMD", "/app/beszel", "health", "--url", "http://127.0.0.1:8090"]
333
+ # bug f9fc272b: the healthcheck binary is coupled to the image generation.
334
+ # stack-update writes MONITOR_HUB_HEALTH_BIN from the pinned manifest image
335
+ # so the probe follows the deployed generation; the default matches the
336
+ # v0.9.4 compose-default image.
337
+ test: ["CMD", "${MONITOR_HUB_HEALTH_BIN:-/app/beszel}", "health", "--url", "http://127.0.0.1:8090"]
323
338
  interval: 30s
324
339
  timeout: 5s
325
340
  start_period: 15s
@@ -879,6 +894,16 @@ services:
879
894
  # with (pinned on the gotrue service), NOT the internal GOTRUE_URL above, so
880
895
  # the gateway accepts real browser SSO tokens. Same public value, one default.
881
896
  GOTRUE_JWT_ISSUER: ${GOTRUE_JWT_ISSUER:-${GOTRUE_EXTERNAL_URL:?GOTRUE_EXTERNAL_URL is required — set to https://auth.<your-domain> in .env}}
897
+ # Bug 550d6ab7, third occurrence of the same defect (after exe-wiki
898
+ # 0c0d5187 and exe-crm). The gateway verifies GoTrue tokens IN-PROCESS:
899
+ # src/gotrue-auth.ts verifyGoTrueJWT reads the JWKS first and, because our
900
+ # GoTrue signs symmetrically and therefore publishes `{"keys":[]}` by
901
+ # design, falls back to getSymmetricKey() — which returns null unless
902
+ # GOTRUE_JWT_SECRET is in this container's environment. Without this line
903
+ # the fallback that makes gateway SSO possible at all is unsatisfiable in
904
+ # the stack customers actually run, and every token is rejected by a
905
+ # silent `return null`. Fail loud rather than boot with no key material.
906
+ GOTRUE_JWT_SECRET: ${GOTRUE_JWT_SECRET:?GOTRUE_JWT_SECRET is required}
882
907
  EXE_GATEWAY_WHATSAPP_VERIFY_TOKEN: ${EXE_GATEWAY_WHATSAPP_VERIFY_TOKEN:?EXE_GATEWAY_WHATSAPP_VERIFY_TOKEN is required}
883
908
  EXE_GATEWAY_WS_RELAY_ENABLED: "true"
884
909
  EXE_GATEWAY_WS_RELAY_HOST: "0.0.0.0"
@@ -1060,7 +1085,11 @@ services:
1060
1085
  # The binary-native `health` subcommand checks the freshness of the
1061
1086
  # agent's health file, which only stays fresh while it is actively
1062
1087
  # reporting to the hub.
1063
- test: ["CMD", "/app/beszel-agent", "health"]
1088
+ # bug f9fc272b: the healthcheck binary is coupled to the image generation.
1089
+ # stack-update writes MONITOR_AGENT_HEALTH_BIN from the pinned manifest image
1090
+ # so the probe follows the deployed generation; the default matches the
1091
+ # v0.9.4 compose-default image.
1092
+ test: ["CMD", "${MONITOR_AGENT_HEALTH_BIN:-/app/beszel-agent}", "health"]
1064
1093
  interval: 30s
1065
1094
  timeout: 5s
1066
1095
  start_period: 30s
@@ -1296,7 +1325,7 @@ services:
1296
1325
  # 4 services: gunicorn API, websocket, RQ worker, scheduler.
1297
1326
 
1298
1327
  exe-erp:
1299
- image: ${ERP_IMAGE_TAG:-ghcr.io/askexe/exe-erp:v0.2.2@sha256:00fecc790ff848bfd4b7d87f42f859edfeb6090a7ca26bf2359dc6cb96767afb}
1328
+ image: ${ERP_IMAGE_TAG:?ERP_IMAGE_TAG must be set by stack-update (the digest-pinned ERP image from the signed manifest) — refusing to fall back to an untested image}
1300
1329
  container_name: exe-erp
1301
1330
  restart: unless-stopped
1302
1331
  entrypoint: ["/usr/local/bin/entrypoint.sh"]
@@ -1437,7 +1466,7 @@ services:
1437
1466
  options: { max-size: "10m", max-file: "3" }
1438
1467
 
1439
1468
  exe-erp-websocket:
1440
- image: ${ERP_IMAGE_TAG:-ghcr.io/askexe/exe-erp:v0.2.2@sha256:00fecc790ff848bfd4b7d87f42f859edfeb6090a7ca26bf2359dc6cb96767afb}
1469
+ image: ${ERP_IMAGE_TAG:?ERP_IMAGE_TAG must be set by stack-update (the digest-pinned ERP image from the signed manifest) — refusing to fall back to an untested image}
1441
1470
  container_name: exe-erp-websocket
1442
1471
  restart: unless-stopped
1443
1472
  entrypoint: []
@@ -1499,7 +1528,7 @@ services:
1499
1528
  options: { max-size: "10m", max-file: "3" }
1500
1529
 
1501
1530
  exe-erp-queue:
1502
- image: ${ERP_IMAGE_TAG:-ghcr.io/askexe/exe-erp:v0.2.2@sha256:00fecc790ff848bfd4b7d87f42f859edfeb6090a7ca26bf2359dc6cb96767afb}
1531
+ image: ${ERP_IMAGE_TAG:?ERP_IMAGE_TAG must be set by stack-update (the digest-pinned ERP image from the signed manifest) — refusing to fall back to an untested image}
1503
1532
  container_name: exe-erp-queue
1504
1533
  restart: unless-stopped
1505
1534
  entrypoint: []
@@ -1531,15 +1560,41 @@ services:
1531
1560
  - backend
1532
1561
  healthcheck:
1533
1562
  # Liveness = the RQ worker process (PID 1) is still running.
1534
- # bug ed19883e: the slim Frappe base has NEITHER pgrep NOR ps/procps
1535
- # (exit 127 "not found") the process-table probes were permanently
1536
- # false-unhealthy 180s stack-update gate rollback. Also `bench
1537
- # worker` runs the RQ worker in-process (frappe.utils.background_jobs
1538
- # .start_worker Worker.work()); PID 1 argv stays "bench worker", so a
1539
- # `rq worker` grep would miss it even if ps existed. Use python (the
1540
- # image base is python:3.14-slim) to read PID 1's argv directly — this
1541
- # matches the exe-erp repo's own docker-compose.yml probe.
1542
- test: ["CMD-SHELL", "python -c \"import sys; cmd=open('/proc/1/cmdline','rb').read().replace(b'\\0', b' '); sys.exit(0 if b'bench worker' in cmd else 1)\""]
1563
+ #
1564
+ # TWO RULES, both learned the hard way. A probe must not (1) name a binary
1565
+ # this image does not ship, nor (2) match a literal PID 1 never contains.
1566
+ # Three generations shipped violating one or the other; each was aborted by
1567
+ # the 180s stack-update health gate and auto-rolled-back, and none was ever
1568
+ # diagnosed together they account for >=8 dead erp deploys, Aug 7-10 2026:
1569
+ #
1570
+ # gen 1 pgrep -f 'bench worker'
1571
+ # pgrep is absent from the slim base (exit 127) false-unhealthy.
1572
+ # gen 2 ps -ef | grep -q '[r]q worker' (bug c8fb434f)
1573
+ # Shipped as the FIX for gen 1, asserting "ps + grep are present".
1574
+ # ps is ALSO absent. This is what killed stack 0.9.33
1575
+ # (deploy-p1b.log:1592) and 0.9.34 (deploy-0.9.34.log:1698) on
1576
+ # exe-erp-queue. exe-erp itself came up healthy in both runs, so
1577
+ # the erp IMAGE was never at fault — only this probe was.
1578
+ # gen 3 python … b'bench worker' in /proc/1/cmdline (bug ed19883e, #580)
1579
+ # Shipped as the FIX for gen 2 and verified only against a
1580
+ # SYNTHETIC PID1 argv. Its comment claimed 'PID 1 argv stays
1581
+ # "bench worker"'. THAT CLAIM IS FALSE, and is the whole bug:
1582
+ # `bench` execs away into the bench_helper module, so real PID 1 is
1583
+ # /home/frappe/frappe-bench/env/bin/python -m frappe.utils.bench_helper frappe worker --queue=…
1584
+ # The literal "bench worker" never appears. Measured exit 1 against
1585
+ # the live, genuinely-healthy production container on 2026-08-14.
1586
+ #
1587
+ # gen 4 (below) matches what PID 1 ACTUALLY is: "frappe worker". Measured
1588
+ # exit 0 against that same live container, and proven end-to-end by
1589
+ # recreating exe-erp-queue under Docker's own healthcheck runner: healthy in
1590
+ # 10s, where gen 2 had burned the full 180s twice.
1591
+ #
1592
+ # The `tr` is LOAD-BEARING: /proc/1/cmdline is NUL-separated, so a bare
1593
+ # `grep -q 'frappe worker' /proc/1/cmdline` returns 1 (also measured). Only
1594
+ # sh, tr and grep are used — all three verified present in this image.
1595
+ # Enforced by tests/deploy/compose/deploy-validation.test.ts, which checks
1596
+ # every erp probe against a recorded inventory of the image's binaries.
1597
+ test: ["CMD-SHELL", "tr '\\0' ' ' < /proc/1/cmdline | grep -q 'frappe worker'"]
1543
1598
  interval: 30s
1544
1599
  timeout: 5s
1545
1600
  start_period: 30s
@@ -1553,7 +1608,7 @@ services:
1553
1608
  options: { max-size: "10m", max-file: "3" }
1554
1609
 
1555
1610
  exe-erp-scheduler:
1556
- image: ${ERP_IMAGE_TAG:-ghcr.io/askexe/exe-erp:v0.2.2@sha256:00fecc790ff848bfd4b7d87f42f859edfeb6090a7ca26bf2359dc6cb96767afb}
1611
+ image: ${ERP_IMAGE_TAG:?ERP_IMAGE_TAG must be set by stack-update (the digest-pinned ERP image from the signed manifest) — refusing to fall back to an untested image}
1557
1612
  container_name: exe-erp-scheduler
1558
1613
  restart: unless-stopped
1559
1614
  entrypoint: []
@@ -1585,12 +1640,17 @@ services:
1585
1640
  - backend
1586
1641
  healthcheck:
1587
1642
  # Liveness = the scheduler process (PID 1) is still running.
1588
- # bug ed19883e: the slim Frappe base has NEITHER pgrep NOR ps/procps
1589
- # (exit 127 "not found") the process-table probe was permanently
1590
- # false-unhealthy 180s stack-update gaterollback. Use python (the
1591
- # image base is python:3.14-slim) to read PID 1's argv directly — this
1592
- # matches the exe-erp repo's own docker-compose.yml probe.
1593
- test: ["CMD-SHELL", "python -c \"import sys; cmd=open('/proc/1/cmdline','rb').read().replace(b'\\0', b' '); sys.exit(0 if b'bench schedule' in cmd else 1)\""]
1643
+ #
1644
+ # Same three-generation history as exe-erp-queue above read that comment
1645
+ # for the full account (pgrep absent ps absent wrong literal). The
1646
+ # short version: `bench schedule` execs away, so real PID 1 is
1647
+ # /home/frappe/frappe-bench/env/bin/python -m frappe.utils.bench_helper frappe schedule
1648
+ # and the literal "bench schedule" never appears (measured exit 1 against
1649
+ # the live container on 2026-08-14). Match "frappe schedule" instead —
1650
+ # measured exit 0, and healthy in 10s on a real recreate.
1651
+ # The `tr` is load-bearing: /proc/1/cmdline is NUL-separated.
1652
+ # Enforced by tests/deploy/compose/deploy-validation.test.ts.
1653
+ test: ["CMD-SHELL", "tr '\\0' ' ' < /proc/1/cmdline | grep -q 'frappe schedule'"]
1594
1654
  interval: 30s
1595
1655
  timeout: 5s
1596
1656
  start_period: 30s
@@ -172,8 +172,8 @@ export function generateEnv(options: GenerateEnvOptions): string {
172
172
  "# http://gotrue:9999 and can reject browser tokens as iss-mismatch.",
173
173
  `GOTRUE_JWT_ISSUER=https://auth.${normalizedDomain}`,
174
174
  "# SSO redirect allow-list (bug 66f8e10a): app origins the gateway may bounce",
175
- "# users back to via ?redirect=. Required for unified SSO across crm/wiki/erp.",
176
- `GOTRUE_URI_ALLOW_LIST=https://crm.${normalizedDomain},https://wiki.${normalizedDomain},https://erp.${normalizedDomain}`,
175
+ "# users back to via ?redirect=. Required for unified SSO across crm/wiki/erp/dashboard/gateway (bug 2d2de534).",
176
+ `GOTRUE_URI_ALLOW_LIST=https://crm.${normalizedDomain},https://wiki.${normalizedDomain},https://erp.${normalizedDomain},https://dashboard.${normalizedDomain},https://gateway.${normalizedDomain}`,
177
177
  "# Bug 0327b017: scope the session cookie to the PARENT apex domain so it is",
178
178
  "# shared across crm/wiki/erp/auth subdomains → true SSO (no re-login).",
179
179
  `GOTRUE_COOKIE_DOMAIN=.${normalizedDomain}`,
@@ -466,7 +466,7 @@ export function generateExampleEnv(): string {
466
466
  "# Bug 51086951: JWT issuer pinned to the public auth URL so signer + consumers agree.",
467
467
  "GOTRUE_JWT_ISSUER=https://auth.CHANGEME_DOMAIN",
468
468
  "# SSO redirect allow-list (bug 66f8e10a) — app origins for unified SSO.",
469
- "GOTRUE_URI_ALLOW_LIST=https://crm.CHANGEME_DOMAIN,https://wiki.CHANGEME_DOMAIN,https://erp.CHANGEME_DOMAIN",
469
+ "GOTRUE_URI_ALLOW_LIST=https://crm.CHANGEME_DOMAIN,https://wiki.CHANGEME_DOMAIN,https://erp.CHANGEME_DOMAIN,https://dashboard.CHANGEME_DOMAIN,https://gateway.CHANGEME_DOMAIN",
470
470
  "# Bug 0327b017: parent-domain cookie → session shared across all subdomains.",
471
471
  "GOTRUE_COOKIE_DOMAIN=.CHANGEME_DOMAIN",
472
472
  "GOTRUE_COOKIE_KEY=exe-auth",
@@ -502,6 +502,23 @@ export function generateExampleEnv(): string {
502
502
  "# the sign-up UI/route instead of showing a form that always fails.",
503
503
  "AUTH_DISABLE_SIGNUP=true",
504
504
  "",
505
+ "# --- Session cookie contract (exe-auth v0.6.0) \u2014 INFORMATIONAL, not settings ---",
506
+ "# Recorded here because operators reason about XSS blast radius from this file,",
507
+ "# and an earlier draft of these notes described the OPPOSITE of what ships.",
508
+ "# exe-auth performs the GoTrue token exchange server-side in njs and sets:",
509
+ "# exe_sess HttpOnly Secure SameSite=Lax \u2014 the real access token",
510
+ "# exe_sess_refresh HttpOnly Secure SameSite=Lax \u2014 the real refresh token",
511
+ "# exe_access_token JS-readable, value literally \"1\" \u2014 presence sentinel only",
512
+ "# All three are scoped to the apex (AUTH_COOKIE_DOMAIN) so they are shared",
513
+ "# across product subdomains.",
514
+ "#",
515
+ "# The credentials are HttpOnly ON PURPOSE (security bug 368bf916): page",
516
+ "# JavaScript CANNOT read them, so an XSS on any subdomain cannot exfiltrate a",
517
+ "# session token from document.cookie. The only JS-readable cookie is the",
518
+ "# sentinel, whose value is the constant \"1\" and is not a credential.",
519
+ "# Apps must NOT read a token from document.cookie \u2014 send credentialed",
520
+ "# same-site requests and let the HttpOnly cookie ride along.",
521
+ "",
505
522
  ...MANAGED_PERMS_ENV_BLOCK,
506
523
  "",
507
524
  "# --- CRM ---",
@@ -37,15 +37,47 @@ map $request_uri $sso_uri_access_token {
37
37
  "~[?&]access_token=(?<tok>[^&]+)" $tok;
38
38
  }
39
39
 
40
- # Extract the shared GoTrue session cookie (exe-auth, domain .${DOMAIN}) from
41
- # the Cookie header. Cross-app logout: GoTrue POST /logout clears this cookie
42
- # on the parent domain, so its absence signals a globally-revoked session.
43
- # The gate checks this alongside the app-native cookie if the app cookie is
44
- # present but the GoTrue cookie is gone, the session was revoked on another app
45
- # and the edge forces re-auth (return 401 login redirect).
40
+ # Extract the shared apex SSO cookie from the Cookie header.
41
+ #
42
+ # THE COOKIE IS `exe_access_token` (bug 21ae2388). This map previously matched
43
+ # `exe-auth` a name NOTHING has ever set. That made the cross-app-logout arm
44
+ # below fire on every single request, so any visitor holding a valid app-native
45
+ # session was bounced back to auth forever. It is the FOURTH instance of one
46
+ # recurring bug class: gating on a cookie name nothing mints. The first three
47
+ # all gated on the retired `exe_sso_token` — exe-wiki f1bb40d8, exe-crm
48
+ # 9f60e8e6, exe-erp 3938ac3d. See .github/workflows/sso-cookie-contract-monitor.yml.
49
+ #
50
+ # THE REAL CONTRACT (exe-auth v0.6.0, auth.njs.js setSessionCookies):
51
+ # exe_sess HttpOnly Secure SameSite=Lax — the real access_token
52
+ # exe_sess_refresh HttpOnly Secure SameSite=Lax — the real refresh_token
53
+ # exe_access_token JS-readable, value literally "1" — presence sentinel
54
+ # All three are scoped to the registrable apex (".${DOMAIN}") via
55
+ # AUTH_COOKIE_DOMAIN, so they are presented across every product subdomain.
56
+ # The two credentials are HttpOnly deliberately (security bug 368bf916) and are
57
+ # therefore unusable as an edge signal; the sentinel is the one that is visible
58
+ # here and is exactly what a presence gate needs.
59
+ #
60
+ # Cross-app logout: exe-auth's logout handler (clearSessionCookies) expires
61
+ # exe_access_token on the apex, so its absence alongside a live app-native
62
+ # cookie means the session was revoked on another app — the edge forces re-auth
63
+ # (return 401 → login redirect).
64
+ #
65
+ # PRESENCE SIGNAL ONLY. The value is the literal "1", not a token. Never treat
66
+ # it as a bearer credential and never forward it as one — the gate below tests
67
+ # only whether it is empty. Token validation is step 3's GoTrue /user call.
46
68
  map $http_cookie $sso_gotrue_cookie {
47
69
  default "";
48
- "~(?:^|;\s*)exe-auth=([^\s;]+)" $1;
70
+ "~(?:^|;\s*)exe_access_token=([^\s;]+)" $1;
71
+ }
72
+
73
+ # Static-asset exemption for the gate (see sso-redirect.conf step 0). Genuine
74
+ # asset extensions only — every other path (HTML documents, all /api/* calls)
75
+ # stays gated. Exempting assets is required for the SPA to boot at all: the
76
+ # app sets its session cookie only after its JS runs, so gating app.js hands a
77
+ # session-bearing document auth HTML in place of its script → blank page.
78
+ map $uri $sso_is_static {
79
+ default "";
80
+ "~*\.(?:js|mjs|css|map|png|jpe?g|gif|svg|ico|webp|woff2?|ttf)$" "static";
49
81
  }
50
82
 
51
83
  map $http_upgrade $sso_conn_upgrade {
@@ -7,13 +7,17 @@
7
7
  # advertised "single front door" does not exist.
8
8
  #
9
9
  # ── How it works ────────────────────────────────────────────────────────────
10
- # 1. Every request runs the edge auth gate (auth_request → /_sso_gate).
10
+ # 0. Static assets (JS/CSS/images/fonts, via the $sso_is_static map) are
11
+ # exempted from the gate and answered 204 — see step 0 inside /_sso_gate
12
+ # for why gating them deadlocks first page load.
13
+ # 1. Every other request runs the edge auth gate (auth_request → /_sso_gate).
11
14
  # 2. If the app session cookie is present the request passes (the app validates
12
15
  # its own session server-side — the cookie name differs per app; set it via
13
16
  # $sso_session_cookie below). Cross-app logout: the edge also checks for the
14
- # shared GoTrue cookie (exe-auth on .${DOMAIN}); if the app cookie is present
15
- # but the GoTrue cookie is gone, the session was revoked on another app and
16
- # the edge forces re-auth.
17
+ # shared apex SSO cookie `exe_access_token` (set on .${DOMAIN} by exe-auth's
18
+ # njs handlers a NON-CREDENTIAL presence sentinel whose value is literally
19
+ # "1"); if the app cookie is present but that sentinel is gone, the session
20
+ # was revoked on another app and the edge forces re-auth.
17
21
  # 3. If the request carries ?access_token= (the SSO callback), the edge
18
22
  # VALIDATES the token against the shared GoTrue (`GET /user` with
19
23
  # `Authorization: Bearer <token>`) before letting it through. P0 bug
@@ -22,6 +26,8 @@
22
26
  # trusted — only a token GoTrue accepts passes.
23
27
  # 4. Anything else 401s inside the gate and is 302-redirected to:
24
28
  # https://auth.<domain>/?product=<App>&redirect=https://<app>.<domain><uri>
29
+ # A 403 from the GoTrue /user validation subrequest is mapped to the same
30
+ # login redirect, so it is never leaked raw to the browser.
25
31
  # 5. The gateway authenticates against the shared GoTrue and bounces the user
26
32
  # back to the app URL with ?access_token=<jwt>&refresh_token=<...>. The app
27
33
  # consumes the token and sets its session cookie — subsequent requests carry
@@ -31,7 +37,7 @@
31
37
  # These are templated values — replace before installing, or render with envsubst
32
38
  # (DOMAIN, APP_NAME, APP_SUBDOMAIN, APP_SESSION_COOKIE):
33
39
  #
34
- # # TWO http-context declarations MUST exist once per nginx config (the
40
+ # # FOUR http-context declarations MUST exist once per nginx config (the
35
41
  # # compose edge ships them in sso-edge/default.conf.template; host-nginx
36
42
  # # installs add them next to their `include`s — see sso-redirect.README.md):
37
43
  # #
@@ -45,6 +51,19 @@
45
51
  # default "";
46
52
  # "~[?&]access_token=(?<tok>[^&]+)" $tok;
47
53
  # }
54
+ # # 3. The shared apex SSO cookie — the cross-app-logout signal. The name is
55
+ # # `exe_access_token` (bug 21ae2388: this used to read a nonexistent
56
+ # # `exe-auth`, which 401'd every authenticated request). Presence only —
57
+ # # the value is the literal "1", never a bearer token:
58
+ # map $http_cookie $sso_gotrue_cookie {
59
+ # default "";
60
+ # "~(?:^|;\s*)exe_access_token=([^\s;]+)" $1;
61
+ # }
62
+ # # 4. The static-asset exemption (see step 0 inside /_sso_gate):
63
+ # map $uri $sso_is_static {
64
+ # default "";
65
+ # "~*\.(?:js|mjs|css|map|png|jpe?g|gif|svg|ico|webp|woff2?|ttf)$" "static";
66
+ # }
48
67
  #
49
68
  # server {
50
69
  # server_name crm.${DOMAIN};
@@ -70,9 +89,30 @@
70
89
  # are app-native sessions the edge cannot verify against GoTrue); each app fully
71
90
  # validates its own session server-side. The edge gate's job is the login funnel
72
91
  # plus never letting an unvalidated bearer token skip it (bug 462d3273).
73
- # Cross-app logout adds a GoTrue-cookie check: if the app-native cookie is present
74
- # but the shared GoTrue cookie is absent, the edge 401s — the session was revoked
75
- # on another app and the app-native cookie is stale.
92
+ # Cross-app logout adds a sentinel-cookie check: if the app-native cookie is
93
+ # present but the shared apex `exe_access_token` sentinel is absent, the edge
94
+ # 401s — the session was revoked on another app and the app-native cookie is
95
+ # stale. This is ALWAYS ON; it is the mechanism that makes "log out once, out
96
+ # everywhere" real across crm/wiki/erp/dashboard.
97
+ #
98
+ # ── SECURITY TRADEOFF: the static-asset exemption ────────────────────────────
99
+ # Step 0 exempts requests from the gate by FILE EXTENSION, matching on $uri.
100
+ # That is a URL-shape test, not a content test, so ANY application path whose
101
+ # URI ends in .js/.mjs/.css/.map/.png/.jpe?g/.gif/.svg/.ico/.webp/.woff2?/.ttf
102
+ # bypasses the edge gate — including user-uploaded content served under those
103
+ # extensions, such as CRM attachments and wiki images.
104
+ #
105
+ # This is a deliberate, accepted tradeoff, on two grounds:
106
+ # 1. Every app validates its own session server-side. The edge gate is the
107
+ # LOGIN FUNNEL, not the authorization boundary — an exempted request still
108
+ # reaches an app that will refuse to serve it to an unauthenticated user.
109
+ # 2. Without the exemption the stack does not work at all: the SPA only sets
110
+ # its session cookie after its JS runs, so gating app.js returns auth HTML
111
+ # in place of the script and the app never boots (blank page).
112
+ #
113
+ # The limit of that reasoning: if you front something with this gate that does
114
+ # NOT do its own authorization and serves secrets from an asset-extension URL,
115
+ # the edge will not protect it. Do not rely on the edge gate in that case.
76
116
  # ─────────────────────────────────────────────────────────────────────────────
77
117
 
78
118
  # Run the gate for every request on this vhost. The gate is a zero-cost local
@@ -82,6 +122,11 @@
82
122
  # official nginx / nginx:alpine builds).
83
123
  auth_request /_sso_gate;
84
124
  error_page 401 = @sso_login;
125
+ # A 403 from the gate's GoTrue /user validation must funnel to login too, not
126
+ # leak raw to the browser. Safe: proxy_intercept_errors is not enabled on the
127
+ # app proxy_pass blocks, so a genuine 403 from an upstream app is NOT converted
128
+ # — only the auth_request subrequest's own status reaches this mapping.
129
+ error_page 403 = @sso_login;
85
130
 
86
131
  location = /_sso_gate {
87
132
  internal;
@@ -93,12 +138,27 @@ location = /_sso_gate {
93
138
  # which auth_request rejects ("auth request unexpected status: 302").
94
139
  error_page 401 = @sso_gate_deny;
95
140
 
141
+ # 0. Static assets (JS/CSS/images/fonts via the $sso_is_static http-context
142
+ # map) pass BEFORE any cookie check. Assets are non-sensitive — all SPA
143
+ # data flows only via the authenticated APIs, which stay fully gated —
144
+ # and gating them deadlocks first page load: the SPA sets its session
145
+ # cookie only AFTER it boots, so answering app.js with the auth HTML
146
+ # leaves a session-bearing document that can never boot (blank page).
147
+ # See the SECURITY TRADEOFF note in the header for the limits of this.
148
+ if ($sso_is_static) {
149
+ return 204;
150
+ }
151
+
96
152
  # 1. App session cookie present → check for cross-app logout.
97
- # The GoTrue cookie (exe-auth, domain .${DOMAIN}) is shared across all
98
- # subdomains. GoTrue POST /logout clears it globally. If the app-native
99
- # cookie is present but the GoTrue cookie is gone, the session was
100
- # revoked on another app force re-auth instead of trusting the stale
101
- # app cookie.
153
+ # The shared apex cookie is `exe_access_token` (domain .${DOMAIN}), set
154
+ # by exe-auth's njs login handler and expired by its logout handler. It
155
+ # is a NON-CREDENTIAL presence sentinel its value is literally "1", so
156
+ # only its presence is meaningful and it is never used as a bearer token.
157
+ # If the app-native cookie is present but the sentinel is gone, the
158
+ # session was revoked on another app — force re-auth instead of trusting
159
+ # the stale app cookie.
160
+ # Bug 21ae2388: this arm matched a cookie named `exe-auth` that nothing
161
+ # has ever minted, so it fired unconditionally and 401'd every request.
102
162
  set $sso_auth_check "";
103
163
  if ($sso_session_cookie) {
104
164
  set $sso_auth_check "app";
@@ -52,7 +52,7 @@
52
52
  "env": "ERP_IMAGE_TAG",
53
53
  "composeService": "exe-erp",
54
54
  "healthUrl": "http://127.0.0.1:8069/api/method/ping",
55
- "healthHost": "erp.askexe.com",
55
+ "healthHost": "${ERP_SITE_NAME:-erp.localhost}",
56
56
  "required": false,
57
57
  "category": "app",
58
58
  "description": "Enterprise Resource Planning"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "latest": "0.9.35",
3
+ "latest": "0.9.36",
4
4
  "stacks": {
5
5
  "0.9.0": {
6
6
  "version": "0.9.0",
@@ -2689,11 +2689,126 @@
2689
2689
  }
2690
2690
  },
2691
2691
  "rolloutStage": "ga"
2692
+ },
2693
+ "0.9.36": {
2694
+ "version": "0.9.36",
2695
+ "releasedAt": "2026-08-14T06:50:39Z",
2696
+ "notes": "SECURITY. exe-auth v0.6.0 — closes GoTrue's service_role admin API, which was publicly reachable on the customer auth host. Probed live against auth.askexe.com on v0.5.0: GET /api/admin/users returned 401 carrying x-sb-error-code: no_authorization — GoTrue ANSWERING, i.e. the request was proxied through to the admin API. nginx now returns a flat 404 for /api/admin/* and /api/invite/* (verified in the shipped image and at runtime); /api/settings and the user endpoints still proxy normally. Also: query strings are redacted from nginx access AND error logs (no token material in logs), the org-invite accept landing closes the dead link from exe-os #659, and the G2 build-provenance gate is armed fail-closed with its label reader fixed — v0.6.0 is the FIRST exe-auth image whose provenance was verified rather than assumed (all four checks green against this exact digest). v0.5.0 shipped 874941df and every fix landed the next day, so 0.9.35 has been serving the vulnerable build. Bumps the auth image digest ONLY; every other pin is identical to 0.9.35.",
2697
+ "npmVersion": "0.9.324",
2698
+ "services": {
2699
+ "exe-db": {
2700
+ "image": "update.askexe.com/askexe/pgvector:0.8.0-pg16@sha256:a132765ec351c65111b5b675928a3a0515a466a40f97277329db8b8209ad8bc9",
2701
+ "env": "EXE_DB_IMAGE",
2702
+ "composeService": "exe-db",
2703
+ "required": true,
2704
+ "category": "core",
2705
+ "description": "Postgres (pgvector) — digest-pinned (bug 32d6e02f; was tag-only in 0.9.25, regressed from 0.9.24)"
2706
+ },
2707
+ "exe-os": {
2708
+ "image": "update.askexe.com/askexe/exe-os:v0.9.324@sha256:3ce6406e0f7f279ff2568bbbb7d55de51a46fdf35c49691f24fd959d6fd2d3fa",
2709
+ "env": "EXE_OS_IMAGE_TAG",
2710
+ "composeService": "exe-os",
2711
+ "healthUrl": "http://127.0.0.1:8765/health",
2712
+ "required": true,
2713
+ "category": "core",
2714
+ "description": "exe-os daemon + MCP server"
2715
+ },
2716
+ "crm": {
2717
+ "image": "update.askexe.com/askexe/exe-crm:v0.9.53@sha256:a586dcc8bbd992538e3caa18c44e772d30f31155dfef0a2b7466ca3fc7c553d8",
2718
+ "env": "CRM_IMAGE_TAG",
2719
+ "composeService": "exe-crm",
2720
+ "healthUrl": "http://127.0.0.1:3000/healthz",
2721
+ "category": "app"
2722
+ },
2723
+ "wiki": {
2724
+ "image": "update.askexe.com/askexe/exe-wiki:v0.9.28@sha256:61856a4c6b97ce62c62ecdc3a377139287be5860eb807d9fbb737115758d7856",
2725
+ "env": "WIKI_IMAGE_TAG",
2726
+ "composeService": "exe-wiki",
2727
+ "healthUrl": "http://127.0.0.1:3001/api/ping",
2728
+ "category": "app"
2729
+ },
2730
+ "gateway": {
2731
+ "image": "update.askexe.com/askexe/exe-gateway:v2026.08.07-c15f093-stamped@sha256:1bc11a2a0ad1f3929d59d2685696f22a72042b9fca9c75e15c02dc7d3c640105",
2732
+ "env": "GATEWAY_IMAGE_TAG",
2733
+ "composeService": "exe-gateway",
2734
+ "healthUrl": "http://127.0.0.1:3100/health",
2735
+ "category": "app",
2736
+ "description": "WhatsApp/messaging gateway — provenance-stamped rebuild of main (outbound message persistence fix); pinned by digest, dated immutable tag.",
2737
+ "gitSha": "c15f093a0f59730bd5c2c73791ff77059dfa7cc1"
2738
+ },
2739
+ "monitorAgent": {
2740
+ "image": "update.askexe.com/askexe/exe-monitor-agent:v2026.08.09-10660eb4-stamped@sha256:29fbd445f79484df04f000603e4ff445e76f0380f86d687a0033e3a0ef7d1b7a",
2741
+ "env": "MONITOR_AGENT_IMAGE_TAG",
2742
+ "composeService": "exe-monitor-agent",
2743
+ "category": "monitoring",
2744
+ "gitSha": "10660eb4abdeffbcba2aad13549aa58e208ac7a3"
2745
+ },
2746
+ "monitorHub": {
2747
+ "image": "update.askexe.com/askexe/exe-monitor-hub:v2026.08.09-10660eb4-stamped@sha256:c9a9218c2713b8dffea7e1cf8c0702a614657d311a7a4e821c6a543bab29bb97",
2748
+ "env": "MONITOR_HUB_IMAGE_TAG",
2749
+ "composeService": "exe-monitor-hub",
2750
+ "healthUrl": "http://127.0.0.1:8090/api/health",
2751
+ "category": "monitoring",
2752
+ "gitSha": "10660eb4abdeffbcba2aad13549aa58e208ac7a3"
2753
+ },
2754
+ "auth": {
2755
+ "image": "update.askexe.com/askexe/exe-auth:v0.6.1@sha256:89670a15bc59255299be695525863e66f949694eec1dd8886038dc3659a4a941",
2756
+ "env": "AUTH_IMAGE_TAG",
2757
+ "composeService": "exe-auth",
2758
+ "healthUrl": "http://127.0.0.1:3300/api/health",
2759
+ "category": "auth",
2760
+ "description": "exe-auth v0.6.1 — the v0.6.0 hardening (GoTrue admin API no longer public; nginx 404s /api/admin|invite; query strings redacted from access + error logs) PLUS the four fixes that merged after v0.6.0 was tagged and had never been built into any image (bug 9e054a59): /api/recover CORS + method restriction (0f9fbebe); a recovery link can no longer mint a session and link hashes are sent as token_hash (056abf8d, c9b62c91); the Secure cookie flag fails closed and HSTS is set (bb99ceda); the session token is kept out of upstream request lines, shape-checked, and a service_role JWT is refused (bff591fe). Verified inside this exact digest, not from a green badge.",
2761
+ "gitSha": "633e7a4d9930aad8b0ce6783a1b3bc2f96b454a8"
2762
+ },
2763
+ "erp": {
2764
+ "image": "update.askexe.com/askexe/exe-erp:v2026.08.07-d185286-stamped@sha256:1c655f3f7819c797afd13c79561354f0276cf337403f32aee3e406a497e8827b",
2765
+ "env": "ERP_IMAGE_TAG",
2766
+ "composeService": "exe-erp",
2767
+ "healthUrl": "http://127.0.0.1:8069/api/method/ping",
2768
+ "healthHost": "localhost",
2769
+ "required": false,
2770
+ "category": "app",
2771
+ "description": "Enterprise Resource Planning",
2772
+ "gitSha": "d185286873dcfa11e4b3f9672c4e23efea240cc5"
2773
+ },
2774
+ "gotrue": {
2775
+ "image": "update.askexe.com/askexe/gotrue:v2.172.1@sha256:b0dd7aa28dd1f9a8bd31f136c8b912661f701d9b863171e5843cb08f18f49de4",
2776
+ "composeService": "gotrue",
2777
+ "healthUrl": "http://127.0.0.1:9999/health",
2778
+ "category": "infra"
2779
+ },
2780
+ "redis": {
2781
+ "image": "update.askexe.com/askexe/redis:7.4-alpine@sha256:6ab0b6e7381779332f97b8ca76193e45b0756f38d4c0dcda72dbb3c32061ab99",
2782
+ "composeService": "redis",
2783
+ "category": "infra"
2784
+ },
2785
+ "clickhouse": {
2786
+ "image": "update.askexe.com/askexe/clickhouse-server:24.8.4.13-alpine@sha256:88a45f9e328549b2579256c46ee38e5c0e25ae58303d9eb6d9c7ed8d6d2bbf3c",
2787
+ "composeService": "clickhouse",
2788
+ "category": "infra"
2789
+ },
2790
+ "cloudflared": {
2791
+ "image": "update.askexe.com/askexe/cloudflared:2026-07@sha256:ba461b8aa9c042156dbd39c38657fe7431bafa063220eab8d5330a523863da9f",
2792
+ "composeService": "cloudflared",
2793
+ "category": "infra"
2794
+ },
2795
+ "exe-sso-edge": {
2796
+ "image": "update.askexe.com/askexe/nginx:alpine@sha256:20316569d8f81a160065d7d2a5eeffc7ca97d79022462ee255fd23fa103a6b5c",
2797
+ "composeService": "exe-sso-edge",
2798
+ "category": "infra"
2799
+ },
2800
+ "exe-otel-collector": {
2801
+ "image": "update.askexe.com/askexe/otel-collector-contrib:0.114.0@sha256:37fa87091cfaaec7234a27e4e395a40c31c2bfaea97a349a4afef6d9e9681197",
2802
+ "composeService": "exe-otel-collector",
2803
+ "category": "infra"
2804
+ }
2805
+ },
2806
+ "rolloutStage": "ga"
2692
2807
  }
2693
2808
  },
2694
2809
  "signature": {
2695
2810
  "keyId": "exe-stack-1",
2696
2811
  "alg": "ed25519",
2697
- "signature": "pm9jH5HQp+Wo+eSqsFKBYekhFmSFUdJp1YYyBMqaufsnbOxj7JXakBGL4ssrzzi8s+xuNRY6SVXgXTT4biIpAg=="
2812
+ "signature": "zJx3MxMUaco9bPRAPvmMs8qFXScuuAS9xWXSQBgtzKJB3ERe5aNvb+f6O39jWjxAvoPUQUObPjCuhwbu0aD8AQ=="
2698
2813
  }
2699
2814
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 1,
3
- "verified_at": "2026-08-14T03:02:39.069Z",
4
- "manifest_sha256": "b29361778e3f781e393bbba4e4f24be7d1abff6d656d6d05b3740ac6e16d34c7",
5
- "package_version": "0.9.371"
3
+ "verified_at": "2026-08-20T15:06:40.858Z",
4
+ "manifest_sha256": "b7074eb6ef6a4f0ce2cb5872b7c05033ee96e568c411773c0dfb9d7cc4a76f4b",
5
+ "package_version": "0.9.373"
6
6
  }