create-workframe 0.1.0 → 0.1.1

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 (206) hide show
  1. package/LICENSE +201 -201
  2. package/NOTICE +12 -12
  3. package/README.md +8 -92
  4. package/SECURITY.md +40 -40
  5. package/bin/workframe.js +329 -329
  6. package/docs/workspace-instructions/WORKFRAME_ONBOARDING.md +1 -1
  7. package/docs/workspace-instructions/WORKFRAME_ROUTING.md +8 -8
  8. package/package.json +3 -6
  9. package/profiles/architect/AGENTS.md +29 -29
  10. package/profiles/architect/SOUL.md +2 -2
  11. package/profiles/architect/skills/devops/kanban-worker/SKILL.md +27 -27
  12. package/profiles/designer/AGENTS.md +26 -26
  13. package/profiles/designer/skills/devops/kanban-worker/SKILL.md +27 -27
  14. package/profiles/dev/AGENTS.md +28 -28
  15. package/profiles/dev/skills/devops/kanban-worker/SKILL.md +27 -27
  16. package/profiles/docs/AGENTS.md +27 -27
  17. package/profiles/docs/skills/devops/kanban-worker/SKILL.md +27 -27
  18. package/profiles/research/AGENTS.md +26 -26
  19. package/profiles/research/skills/devops/kanban-worker/SKILL.md +27 -27
  20. package/profiles/visionary/AGENTS.md +25 -25
  21. package/profiles/visionary/skills/devops/kanban-worker/SKILL.md +27 -27
  22. package/profiles/workframe-agent/AGENTS.md +37 -37
  23. package/profiles/workframe-agent/skills/devops/botfather/SKILL.md +85 -85
  24. package/profiles/workframe-agent/skills/devops/kanban-handoff-pattern/SKILL.md +58 -58
  25. package/profiles/workframe-agent/skills/devops/workframe-cohort/SKILL.md +54 -54
  26. package/rules/workspace-README.md +5 -5
  27. package/scripts/apply-update-hermes.sh +17 -17
  28. package/scripts/apply-update-workframe.sh +77 -77
  29. package/scripts/bootstrap-workspace-link.sh +8 -8
  30. package/scripts/bundle-workframe-ui.mjs +3 -3
  31. package/scripts/compose-docker-host.sh +37 -37
  32. package/scripts/ensure-compose-host-paths.mjs +51 -51
  33. package/scripts/fix-zk-encryption-key.sh +35 -35
  34. package/scripts/lib/install-identity.mjs +212 -212
  35. package/scripts/restart-gateway-hermes.sh +12 -12
  36. package/scripts/set-compose-public-url.mjs +92 -92
  37. package/scripts/setup-stack-secrets.sh +50 -50
  38. package/scripts/sync-canonical-to-package.mjs +8 -7
  39. package/scripts/verify-public-deploy.sh +105 -105
  40. package/shared/WORKFRAME_AGENT_LIBRARY.md +17 -17
  41. package/shared/WORKFRAME_AGENT_OPERATIONS.md +15 -15
  42. package/shared/WORKFRAME_AGENT_PACKS.json +18 -18
  43. package/shared/WORKFRAME_AGENT_PACKS.yaml +8 -8
  44. package/shared/WORKFRAME_SKILL_CURATION.md +4 -4
  45. package/workframe-api/README.md +28 -28
  46. package/workframe-api/action_proxy.py +131 -131
  47. package/workframe-api/auth_rate_limit.py +49 -49
  48. package/workframe-api/credential_vault.py +445 -445
  49. package/workframe-api/data/avatar-catalog.json +41 -41
  50. package/workframe-api/email_sender.py +220 -220
  51. package/workframe-api/google_auth.py +90 -90
  52. package/workframe-api/install_api.py +359 -359
  53. package/workframe-api/internal_proxy_auth.py +150 -150
  54. package/workframe-api/llm_proxy.py +277 -277
  55. package/workframe-api/oidc_jwt.py +108 -108
  56. package/workframe-api/package.json +12 -13
  57. package/workframe-api/public/assets/index-DPXu_lGn.css +1 -1
  58. package/workframe-api/public/assets/index-DYnLrCZZ.js +8 -8
  59. package/workframe-api/requirements.txt +2 -2
  60. package/workframe-api/site_meta.py +271 -271
  61. package/workframe-api/stack_config.py +427 -427
  62. package/workframe-api/time-bind-chat.py +99 -99
  63. package/workframe-api/turn_credentials.py +226 -226
  64. package/workframe-api/updates.py +417 -417
  65. package/workframe-api/vault_kek.py +159 -159
  66. package/workframe-api/zk_auth.py +633 -633
  67. package/workframe-supervisor/Dockerfile +11 -11
  68. package/workframe-supervisor/server.py +787 -787
  69. package/workframe-ui/docker/nginx.conf +85 -85
  70. package/workframe-ui/public/assets/{arc-CBDYvkAF.js → arc-COAT3laO.js} +1 -1
  71. package/workframe-ui/public/assets/architecture-7EHR7CIX-DUyH3hWG.js +1 -0
  72. package/workframe-ui/public/assets/{architectureDiagram-3BPJPVTR-XnBRKeW0.js → architectureDiagram-3BPJPVTR-BFjWV24l.js} +1 -1
  73. package/workframe-ui/public/assets/{blockDiagram-GPEHLZMM-VYHUfVhd.js → blockDiagram-GPEHLZMM-DSQLPfrj.js} +1 -1
  74. package/workframe-ui/public/assets/{c4Diagram-AAUBKEIU-BTjUcJpm.js → c4Diagram-AAUBKEIU-DKEHv1t2.js} +1 -1
  75. package/workframe-ui/public/assets/channel-g7r_RGaY.js +1 -0
  76. package/workframe-ui/public/assets/{chunk-2J33WTMH-w7uu7R-b.js → chunk-2J33WTMH-DHZg-DUi.js} +1 -1
  77. package/workframe-ui/public/assets/{chunk-3OPIFGDE-Cb9LtnDX.js → chunk-3OPIFGDE-BB-OYTfp.js} +1 -1
  78. package/workframe-ui/public/assets/{chunk-4BX2VUAB-DiQ-qCwH.js → chunk-4BX2VUAB-C93q0YIm.js} +1 -1
  79. package/workframe-ui/public/assets/{chunk-55IACEB6-C-mLFr7z.js → chunk-55IACEB6-MAYniqik.js} +1 -1
  80. package/workframe-ui/public/assets/{chunk-5ZQYHXKU-DOesfiCI.js → chunk-5ZQYHXKU-ChgN6YJs.js} +1 -1
  81. package/workframe-ui/public/assets/{chunk-727SXJPM-BJ3oBZuz.js → chunk-727SXJPM-B_FYwdAv.js} +1 -1
  82. package/workframe-ui/public/assets/{chunk-AQP2D5EJ-CCA6xpGs.js → chunk-AQP2D5EJ-1_Hw_h1A.js} +1 -1
  83. package/workframe-ui/public/assets/{chunk-BSJP7CBP-a0cMNFb2.js → chunk-BSJP7CBP-CFiDQ1Rv.js} +1 -1
  84. package/workframe-ui/public/assets/{chunk-CSCIHK7Q-kuqN8EIY.js → chunk-CSCIHK7Q-DZ9UMTlB.js} +1 -1
  85. package/workframe-ui/public/assets/{chunk-FMBD7UC4-DyPgYHCg.js → chunk-FMBD7UC4-DlMlyFgw.js} +1 -1
  86. package/workframe-ui/public/assets/{chunk-KSCS5N6A-CdUuvR0V.js → chunk-KSCS5N6A-DHXtQ_Hf.js} +1 -1
  87. package/workframe-ui/public/assets/{chunk-L5ZTLDWV-Dq9NoWmK.js → chunk-L5ZTLDWV-CuQzg-QG.js} +1 -1
  88. package/workframe-ui/public/assets/{chunk-LZXEDZCA-p74rddlO.js → chunk-LZXEDZCA-BHzjzCGg.js} +2 -2
  89. package/workframe-ui/public/assets/{chunk-ND2GUHAM-DBD2u1Gz.js → chunk-ND2GUHAM-DHXx05n2.js} +1 -1
  90. package/workframe-ui/public/assets/{chunk-NZK2D7GU-BeIeYFnd.js → chunk-NZK2D7GU-CV5pmDM_.js} +1 -1
  91. package/workframe-ui/public/assets/{chunk-O5CBEL6O-ClHc56ib.js → chunk-O5CBEL6O-6tkCHxsV.js} +1 -1
  92. package/workframe-ui/public/assets/chunk-QZHKN3VN-C5UQehWY.js +1 -0
  93. package/workframe-ui/public/assets/chunk-WU5MYG2G-DhWllrI8.js +1 -0
  94. package/workframe-ui/public/assets/{chunk-XPW4576I-EFr8R_1p.js → chunk-XPW4576I-BClwIiCp.js} +1 -1
  95. package/workframe-ui/public/assets/classDiagram-4FO5ZUOK-BBM_8T8E.js +1 -0
  96. package/workframe-ui/public/assets/classDiagram-v2-Q7XG4LA2-BBM_8T8E.js +1 -0
  97. package/workframe-ui/public/assets/{cose-bilkent-S5V4N54A-C7aPBODd.js → cose-bilkent-S5V4N54A-DOrGV6DQ.js} +1 -1
  98. package/workframe-ui/public/assets/{dagre-BM42HDAG-BdU1Rv-H.js → dagre-BM42HDAG-DXTPvJkX.js} +1 -1
  99. package/workframe-ui/public/assets/{diagram-2AECGRRQ-DWowSo85.js → diagram-2AECGRRQ-xX_v-pbf.js} +1 -1
  100. package/workframe-ui/public/assets/{diagram-5GNKFQAL-MnxBbceO.js → diagram-5GNKFQAL-Cd2pXbBe.js} +1 -1
  101. package/workframe-ui/public/assets/{diagram-KO2AKTUF-DQaLRXFf.js → diagram-KO2AKTUF-Df3XvUtk.js} +1 -1
  102. package/workframe-ui/public/assets/{diagram-LMA3HP47-CQaBud9k.js → diagram-LMA3HP47-CsijIPaD.js} +1 -1
  103. package/workframe-ui/public/assets/{diagram-OG6HWLK6-D8bAXbY9.js → diagram-OG6HWLK6-aq5fmfHd.js} +1 -1
  104. package/workframe-ui/public/assets/{dist-DGpTLHr_.js → dist-D1c0mkbB.js} +1 -1
  105. package/workframe-ui/public/assets/{erDiagram-TEJ5UH35-1E-xSvBK.js → erDiagram-TEJ5UH35-DnFysVRY.js} +1 -1
  106. package/workframe-ui/public/assets/eventmodeling-FCH6USID-Ci8mdb44.js +1 -0
  107. package/workframe-ui/public/assets/{flowDiagram-I6XJVG4X-CgOVD5hu.js → flowDiagram-I6XJVG4X-C6Ebi3su.js} +1 -1
  108. package/workframe-ui/public/assets/{ganttDiagram-6RSMTGT7-JFYAIauo.js → ganttDiagram-6RSMTGT7-BQXQtUpa.js} +1 -1
  109. package/workframe-ui/public/assets/{gitGraph-WXDBUCRP-B9REenIl.js → gitGraph-WXDBUCRP-Dt0zIs_M.js} +1 -1
  110. package/workframe-ui/public/assets/{gitGraphDiagram-PVQCEYII-BQ7NcMSn.js → gitGraphDiagram-PVQCEYII-BF8gHzRn.js} +1 -1
  111. package/workframe-ui/public/assets/index-DpoUZAxh.css +1 -0
  112. package/workframe-ui/public/assets/{index-Dnw6vjqb.js → index-lRpzpNPT.js} +2 -2
  113. package/workframe-ui/public/assets/{info-J43DQDTF-CL6-eTjH.js → info-J43DQDTF-CSmszQJT.js} +1 -1
  114. package/workframe-ui/public/assets/{infoDiagram-5YYISTIA-LJTODW4W.js → infoDiagram-5YYISTIA-CVTKGW6p.js} +1 -1
  115. package/workframe-ui/public/assets/{ishikawaDiagram-YF4QCWOH-bchrQVuo.js → ishikawaDiagram-YF4QCWOH-Z8pT09Lv.js} +1 -1
  116. package/workframe-ui/public/assets/{journeyDiagram-JHISSGLW-DkrvYuxP.js → journeyDiagram-JHISSGLW-r3wD68_T.js} +1 -1
  117. package/workframe-ui/public/assets/{kanban-definition-UN3LZRKU-DFRbj0IG.js → kanban-definition-UN3LZRKU-Il8VglqN.js} +1 -1
  118. package/workframe-ui/public/assets/{line-Vd48P7-O.js → line-oyjpfz2A.js} +1 -1
  119. package/workframe-ui/public/assets/{linear-Ckizh2G7.js → linear-Cf7p5tVp.js} +1 -1
  120. package/workframe-ui/public/assets/{mermaid-parser.core-Bkimsnqj.js → mermaid-parser.core-YmbZ-AfY.js} +2 -2
  121. package/workframe-ui/public/assets/{mermaid.core-x0TvVuPo.js → mermaid.core-BFdCAqCo.js} +3 -3
  122. package/workframe-ui/public/assets/{mindmap-definition-RKZ34NQL-6ykAFPEz.js → mindmap-definition-RKZ34NQL-Cy2iCtEl.js} +1 -1
  123. package/workframe-ui/public/assets/{packet-YPE3B663-Dw3xgMDt.js → packet-YPE3B663-DwOBZL6K.js} +1 -1
  124. package/workframe-ui/public/assets/{pie-LRSECV5Y-DATysawG.js → pie-LRSECV5Y-04PPhnKK.js} +1 -1
  125. package/workframe-ui/public/assets/{pieDiagram-4H26LBE5-SJKD1S0S.js → pieDiagram-4H26LBE5-LxIpgHqi.js} +1 -1
  126. package/workframe-ui/public/assets/{quadrantDiagram-W4KKPZXB-BrYDZX8q.js → quadrantDiagram-W4KKPZXB-0nBYfYm4.js} +1 -1
  127. package/workframe-ui/public/assets/{radar-GUYGQ44K-BmWYPCds.js → radar-GUYGQ44K-D2-vBqps.js} +1 -1
  128. package/workframe-ui/public/assets/{requirementDiagram-4Y6WPE33-DwL9Mc8e.js → requirementDiagram-4Y6WPE33-DbuU0nlu.js} +1 -1
  129. package/workframe-ui/public/assets/{sankeyDiagram-5OEKKPKP-DYIFsL8h.js → sankeyDiagram-5OEKKPKP-B2hQ6B2x.js} +1 -1
  130. package/workframe-ui/public/assets/{sequenceDiagram-3UESZ5HK-0-FPkFk8.js → sequenceDiagram-3UESZ5HK-BBrU30e1.js} +1 -1
  131. package/workframe-ui/public/assets/{src-B_od6b6h.js → src-BJEDmV70.js} +1 -1
  132. package/workframe-ui/public/assets/{stateDiagram-AJRCARHV-BQCiBk6u.js → stateDiagram-AJRCARHV-7FGO4kkH.js} +1 -1
  133. package/workframe-ui/public/assets/stateDiagram-v2-BHNVJYJU-DLTSizMg.js +1 -0
  134. package/workframe-ui/public/assets/{timeline-definition-PNZ67QCA-DS3tFcXj.js → timeline-definition-PNZ67QCA-ptDm4rCN.js} +1 -1
  135. package/workframe-ui/public/assets/{treeView-BLDUP644-DSyUCKLY.js → treeView-BLDUP644-CS6Z-0q8.js} +1 -1
  136. package/workframe-ui/public/assets/{treemap-LRROVOQU-CEZaNh5Y.js → treemap-LRROVOQU-DqV4Y2VA.js} +1 -1
  137. package/workframe-ui/public/assets/{vennDiagram-CIIHVFJN-CD-Vc9NF.js → vennDiagram-CIIHVFJN-C0UrZJYt.js} +1 -1
  138. package/workframe-ui/public/assets/{wardley-L42UT6IY-Drq5w1Mc.js → wardley-L42UT6IY-bNDN3_Sa.js} +1 -1
  139. package/workframe-ui/public/assets/{wardleyDiagram-YWT4CUSO-DouXDJoF.js → wardleyDiagram-YWT4CUSO-jWiJsefM.js} +1 -1
  140. package/workframe-ui/public/assets/{xychartDiagram-2RQKCTM6-DDf_Lol5.js → xychartDiagram-2RQKCTM6-Dsh_fLCy.js} +1 -1
  141. package/workframe-ui/public/favicon.svg +7 -7
  142. package/workframe-ui/public/index.html +50 -50
  143. package/workframe-ui/public/workframe-config.json +3 -3
  144. package/scripts/security_audit.py +0 -156
  145. package/scripts/test-scaffold.mjs +0 -390
  146. package/workframe-api/tests/__init__.py +0 -0
  147. package/workframe-api/tests/db_setup.py +0 -13
  148. package/workframe-api/tests/test_admin_updates_gated.py +0 -30
  149. package/workframe-api/tests/test_agent_dm_bootstrap.py +0 -196
  150. package/workframe-api/tests/test_agent_profile_sync.py +0 -76
  151. package/workframe-api/tests/test_auth_email.py +0 -222
  152. package/workframe-api/tests/test_auth_hole_fix_selfcheck.py +0 -99
  153. package/workframe-api/tests/test_auth_rate_limit.py +0 -19
  154. package/workframe-api/tests/test_avatar_resolve.py +0 -77
  155. package/workframe-api/tests/test_child_soul_template.py +0 -71
  156. package/workframe-api/tests/test_credential_canary.py +0 -135
  157. package/workframe-api/tests/test_credential_isolation.py +0 -448
  158. package/workframe-api/tests/test_credential_resolution.py +0 -206
  159. package/workframe-api/tests/test_device_oauth.py +0 -108
  160. package/workframe-api/tests/test_doctor_repair.py +0 -103
  161. package/workframe-api/tests/test_ensure_profile_api.py +0 -77
  162. package/workframe-api/tests/test_gateway_compose_security.py +0 -136
  163. package/workframe-api/tests/test_install_secure_host.py +0 -39
  164. package/workframe-api/tests/test_internal_proxy_auth.py +0 -125
  165. package/workframe-api/tests/test_invite_runtime_bootstrap.py +0 -72
  166. package/workframe-api/tests/test_kanban_delegation.py +0 -185
  167. package/workframe-api/tests/test_llm_proxy.py +0 -155
  168. package/workframe-api/tests/test_login_access_policy.py +0 -183
  169. package/workframe-api/tests/test_mvp_model_bootstrap.py +0 -75
  170. package/workframe-api/tests/test_onboarding_bootstrap.py +0 -248
  171. package/workframe-api/tests/test_platform_auth.py +0 -47
  172. package/workframe-api/tests/test_profile_config_path.py +0 -56
  173. package/workframe-api/tests/test_profile_config_yaml_repair.py +0 -63
  174. package/workframe-api/tests/test_profile_create.py +0 -72
  175. package/workframe-api/tests/test_profile_identity_overlay.py +0 -61
  176. package/workframe-api/tests/test_profile_install_health.py +0 -45
  177. package/workframe-api/tests/test_profile_secret_policy.py +0 -57
  178. package/workframe-api/tests/test_profile_workspace_cwd.py +0 -34
  179. package/workframe-api/tests/test_provider_bootstrap.py +0 -75
  180. package/workframe-api/tests/test_provider_connect.py +0 -54
  181. package/workframe-api/tests/test_room_crud.py +0 -192
  182. package/workframe-api/tests/test_room_tenancy.py +0 -701
  183. package/workframe-api/tests/test_runtime_identity_backfill.py +0 -34
  184. package/workframe-api/tests/test_site_meta.py +0 -81
  185. package/workframe-api/tests/test_soul_stub.py +0 -42
  186. package/workframe-api/tests/test_space_member_sync.py +0 -99
  187. package/workframe-api/tests/test_stripe_stack_config.py +0 -37
  188. package/workframe-api/tests/test_supervisor_lifecycle.py +0 -52
  189. package/workframe-api/tests/test_turn_credential_vault.py +0 -125
  190. package/workframe-api/tests/test_updates.py +0 -176
  191. package/workframe-api/tests/test_user_cohort.py +0 -113
  192. package/workframe-api/tests/test_vault_envelope.py +0 -110
  193. package/workframe-api/tests/test_workspace_members.py +0 -183
  194. package/workframe-api/tests/test_workspace_messaging_sync.py +0 -125
  195. package/workframe-api/tests/test_workspace_provider_list.py +0 -57
  196. package/workframe-supervisor/tests/test_exec_guard.py +0 -42
  197. package/workframe-supervisor/tests/test_server_import.py +0 -21
  198. package/workframe-ui/public/assets/architecture-7EHR7CIX-CtbQKTuT.js +0 -1
  199. package/workframe-ui/public/assets/channel-Dy4Z4-jn.js +0 -1
  200. package/workframe-ui/public/assets/chunk-QZHKN3VN-CtBEchFK.js +0 -1
  201. package/workframe-ui/public/assets/chunk-WU5MYG2G-B9pBtriN.js +0 -1
  202. package/workframe-ui/public/assets/classDiagram-4FO5ZUOK-BMAEA8jI.js +0 -1
  203. package/workframe-ui/public/assets/classDiagram-v2-Q7XG4LA2-BMAEA8jI.js +0 -1
  204. package/workframe-ui/public/assets/eventmodeling-FCH6USID-D75cstNT.js +0 -1
  205. package/workframe-ui/public/assets/index-DpAGxump.css +0 -1
  206. package/workframe-ui/public/assets/stateDiagram-v2-BHNVJYJU-B89jAMFF.js +0 -1
@@ -1,77 +1,77 @@
1
- #!/usr/bin/env bash
2
- # Safe Workframe update — sync npm template (optional), rebuild API/supervisor/UI containers. Never wipes runtime/DB.
3
- set -euo pipefail
4
- SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
5
- # shellcheck source=compose-docker-host.sh
6
- source "$SCRIPT_DIR/compose-docker-host.sh"
7
-
8
- workframe_compose_prepare
9
- PROJECT_ROOT="${WORKFRAME_HOST_PROJECT_ROOT:-${WORKFRAME_PROJECT_ROOT:-$compose_cd}}"
10
-
11
- echo "=== Workframe update (API + supervisor + UI) ==="
12
- echo "Project root: $PROJECT_ROOT"
13
- echo "Preserves: Agents/, Files/, .env, workframe-api/data, gateway/Hermes profiles"
14
-
15
- TARGET_VERSION="${WORKFRAME_UPDATE_VERSION:-}"
16
- NPM_PACKAGE="${WORKFRAME_NPM_PACKAGE:-create-workframe}"
17
-
18
- if [[ "${WORKFRAME_UPDATE_SKIP_NPM:-1}" == "1" ]] && [[ "${WORKFRAME_UPDATE_ALLOW_NPM:-}" != "1" ]]; then
19
- echo "Skipping npm template sync (WORKFRAME_UPDATE_SKIP_NPM=1; set WORKFRAME_UPDATE_ALLOW_NPM=1 to fetch)"
20
- elif command -v npm >/dev/null 2>&1; then
21
- if [[ "${WORKFRAME_UPDATE_ALLOW_NPM:-}" == "1" ]] && [[ -z "$TARGET_VERSION" ]]; then
22
- echo "WORKFRAME_UPDATE_VERSION is required when WORKFRAME_UPDATE_ALLOW_NPM=1" >&2
23
- exit 1
24
- fi
25
- TMP="$(mktemp -d)"
26
- trap 'rm -rf "$TMP"' EXIT
27
- echo "Fetching ${NPM_PACKAGE}@${TARGET_VERSION:-latest} from npm..."
28
- (cd "$TMP" && npm pack "${NPM_PACKAGE}@${TARGET_VERSION:-latest}" --silent)
29
- TARBALL="$(ls -1 "$TMP"/${NPM_PACKAGE}-*.tgz 2>/dev/null | head -n1 || true)"
30
- if [[ -n "$TARBALL" ]]; then
31
- EXPECTED="$(npm view "${NPM_PACKAGE}@${TARGET_VERSION:-latest}" dist.integrity --silent 2>/dev/null || true)"
32
- if [[ -n "$EXPECTED" ]]; then
33
- ACTUAL="sha512-$(sha512sum "$TARBALL" | awk '{print $1}' | xxd -r -p | base64 | tr -d '\n')"
34
- if [[ "$ACTUAL" != "$EXPECTED" ]]; then
35
- echo "integrity mismatch for ${NPM_PACKAGE}@${TARGET_VERSION:-latest}" >&2
36
- exit 1
37
- fi
38
- echo "integrity ok: ${NPM_PACKAGE}@${TARGET_VERSION:-latest}"
39
- fi
40
- tar -xf "$TARBALL" -C "$TMP"
41
- PKG="$TMP/package"
42
- for dir in workframe-api workframe-supervisor; do
43
- if [[ -d "$PKG/$dir" ]]; then
44
- echo "Syncing $dir/"
45
- mkdir -p "$PROJECT_ROOT/$dir"
46
- cp -a "$PKG/$dir/." "$PROJECT_ROOT/$dir/"
47
- fi
48
- done
49
- if [[ -d "$PKG/workframe-ui/public" ]]; then
50
- echo "Syncing workframe-ui/public/"
51
- mkdir -p "$PROJECT_ROOT/workframe-ui/public"
52
- cp -a "$PKG/workframe-ui/public/." "$PROJECT_ROOT/workframe-ui/public/"
53
- fi
54
- for script in apply-update-hermes.sh apply-update-workframe.sh restart-gateway-hermes.sh compose-docker-host.sh update-hermes.sh; do
55
- if [[ -f "$PKG/scripts/$script" ]]; then
56
- cp -a "$PKG/scripts/$script" "$PROJECT_ROOT/scripts/workframe/$script"
57
- chmod +x "$PROJECT_ROOT/scripts/workframe/$script" 2>/dev/null || true
58
- fi
59
- done
60
- else
61
- echo "npm pack produced no tarball — skipping template sync"
62
- fi
63
- else
64
- echo "Skipping npm template sync (npm missing or WORKFRAME_UPDATE_SKIP_NPM=1)"
65
- fi
66
-
67
- echo "Rebuilding workframe-api and workframe-supervisor..."
68
- workframe_compose build workframe-api workframe-supervisor
69
- workframe_compose up -d --build --no-deps workframe-api workframe-supervisor
70
-
71
- if workframe_compose config --services 2>/dev/null | grep -qx workframe-ui; then
72
- workframe_compose up -d --no-deps workframe-ui || workframe_compose restart workframe-ui || true
73
- elif workframe_compose config --services 2>/dev/null | grep -qx workframe; then
74
- workframe_compose up -d --no-deps workframe || workframe_compose restart workframe || true
75
- fi
76
-
77
- echo "=== Workframe update complete ==="
1
+ #!/usr/bin/env bash
2
+ # Safe Workframe update — sync npm template (optional), rebuild API/supervisor/UI containers. Never wipes runtime/DB.
3
+ set -euo pipefail
4
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
5
+ # shellcheck source=compose-docker-host.sh
6
+ source "$SCRIPT_DIR/compose-docker-host.sh"
7
+
8
+ workframe_compose_prepare
9
+ PROJECT_ROOT="${WORKFRAME_HOST_PROJECT_ROOT:-${WORKFRAME_PROJECT_ROOT:-$compose_cd}}"
10
+
11
+ echo "=== Workframe update (API + supervisor + UI) ==="
12
+ echo "Project root: $PROJECT_ROOT"
13
+ echo "Preserves: Agents/, Files/, .env, workframe-api/data, gateway/Hermes profiles"
14
+
15
+ TARGET_VERSION="${WORKFRAME_UPDATE_VERSION:-}"
16
+ NPM_PACKAGE="${WORKFRAME_NPM_PACKAGE:-create-workframe}"
17
+
18
+ if [[ "${WORKFRAME_UPDATE_SKIP_NPM:-1}" == "1" ]] && [[ "${WORKFRAME_UPDATE_ALLOW_NPM:-}" != "1" ]]; then
19
+ echo "Skipping npm template sync (WORKFRAME_UPDATE_SKIP_NPM=1; set WORKFRAME_UPDATE_ALLOW_NPM=1 to fetch)"
20
+ elif command -v npm >/dev/null 2>&1; then
21
+ if [[ "${WORKFRAME_UPDATE_ALLOW_NPM:-}" == "1" ]] && [[ -z "$TARGET_VERSION" ]]; then
22
+ echo "WORKFRAME_UPDATE_VERSION is required when WORKFRAME_UPDATE_ALLOW_NPM=1" >&2
23
+ exit 1
24
+ fi
25
+ TMP="$(mktemp -d)"
26
+ trap 'rm -rf "$TMP"' EXIT
27
+ echo "Fetching ${NPM_PACKAGE}@${TARGET_VERSION:-latest} from npm..."
28
+ (cd "$TMP" && npm pack "${NPM_PACKAGE}@${TARGET_VERSION:-latest}" --silent)
29
+ TARBALL="$(ls -1 "$TMP"/${NPM_PACKAGE}-*.tgz 2>/dev/null | head -n1 || true)"
30
+ if [[ -n "$TARBALL" ]]; then
31
+ EXPECTED="$(npm view "${NPM_PACKAGE}@${TARGET_VERSION:-latest}" dist.integrity --silent 2>/dev/null || true)"
32
+ if [[ -n "$EXPECTED" ]]; then
33
+ ACTUAL="sha512-$(sha512sum "$TARBALL" | awk '{print $1}' | xxd -r -p | base64 | tr -d '\n')"
34
+ if [[ "$ACTUAL" != "$EXPECTED" ]]; then
35
+ echo "integrity mismatch for ${NPM_PACKAGE}@${TARGET_VERSION:-latest}" >&2
36
+ exit 1
37
+ fi
38
+ echo "integrity ok: ${NPM_PACKAGE}@${TARGET_VERSION:-latest}"
39
+ fi
40
+ tar -xf "$TARBALL" -C "$TMP"
41
+ PKG="$TMP/package"
42
+ for dir in workframe-api workframe-supervisor; do
43
+ if [[ -d "$PKG/$dir" ]]; then
44
+ echo "Syncing $dir/"
45
+ mkdir -p "$PROJECT_ROOT/$dir"
46
+ cp -a "$PKG/$dir/." "$PROJECT_ROOT/$dir/"
47
+ fi
48
+ done
49
+ if [[ -d "$PKG/workframe-ui/public" ]]; then
50
+ echo "Syncing workframe-ui/public/"
51
+ mkdir -p "$PROJECT_ROOT/workframe-ui/public"
52
+ cp -a "$PKG/workframe-ui/public/." "$PROJECT_ROOT/workframe-ui/public/"
53
+ fi
54
+ for script in apply-update-hermes.sh apply-update-workframe.sh restart-gateway-hermes.sh compose-docker-host.sh update-hermes.sh; do
55
+ if [[ -f "$PKG/scripts/$script" ]]; then
56
+ cp -a "$PKG/scripts/$script" "$PROJECT_ROOT/scripts/workframe/$script"
57
+ chmod +x "$PROJECT_ROOT/scripts/workframe/$script" 2>/dev/null || true
58
+ fi
59
+ done
60
+ else
61
+ echo "npm pack produced no tarball — skipping template sync"
62
+ fi
63
+ else
64
+ echo "Skipping npm template sync (npm missing or WORKFRAME_UPDATE_SKIP_NPM=1)"
65
+ fi
66
+
67
+ echo "Rebuilding workframe-api and workframe-supervisor..."
68
+ workframe_compose build workframe-api workframe-supervisor
69
+ workframe_compose up -d --build --no-deps workframe-api workframe-supervisor
70
+
71
+ if workframe_compose config --services 2>/dev/null | grep -qx workframe-ui; then
72
+ workframe_compose up -d --no-deps workframe-ui || workframe_compose restart workframe-ui || true
73
+ elif workframe_compose config --services 2>/dev/null | grep -qx workframe; then
74
+ workframe_compose up -d --no-deps workframe || workframe_compose restart workframe || true
75
+ fi
76
+
77
+ echo "=== Workframe update complete ==="
@@ -1,8 +1,8 @@
1
- #!/bin/sh
2
- # Hermes sets HERMES_WRITE_SAFE_ROOT=/opt/data — user artifacts must resolve under it.
3
- # Bind host Files at /opt/data/workspace; keep /workspace as a symlink for agents and API.
4
- mkdir -p /opt/data/workspace
5
- if [ -L /workspace ] || [ ! -e /workspace ]; then
6
- rm -rf /workspace 2>/dev/null || true
7
- ln -sfn /opt/data/workspace /workspace
8
- fi
1
+ #!/bin/sh
2
+ # Hermes sets HERMES_WRITE_SAFE_ROOT=/opt/data — user artifacts must resolve under it.
3
+ # Bind host Files at /opt/data/workspace; keep /workspace as a symlink for agents and API.
4
+ mkdir -p /opt/data/workspace
5
+ if [ -L /workspace ] || [ ! -e /workspace ]; then
6
+ rm -rf /workspace 2>/dev/null || true
7
+ ln -sfn /opt/data/workspace /workspace
8
+ fi
@@ -2,7 +2,7 @@
2
2
  /**
3
3
  * Build apps/web and copy dist into create-workframe/workframe-ui/public for npm publish.
4
4
  * Canonical UI pipeline: apps/web `npm run build` → dist (same as monorepo `pnpm build:web`).
5
- * Run from ProjectX root: node packages/create-workframe/scripts/bundle-workframe-ui.mjs
5
+ * Run from repository root: node packages/create-workframe/scripts/bundle-workframe-ui.mjs
6
6
  */
7
7
  import fs from 'node:fs';
8
8
  import path from 'node:path';
@@ -11,8 +11,8 @@ import { spawnSync } from 'node:child_process';
11
11
 
12
12
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
13
13
  const PKG_ROOT = path.resolve(__dirname, '..');
14
- const PROJECTX_ROOT = path.resolve(PKG_ROOT, '../..');
15
- const UI_SRC = path.join(PROJECTX_ROOT, 'apps/web');
14
+ const REPO_ROOT = path.resolve(PKG_ROOT, '../..');
15
+ const UI_SRC = path.join(REPO_ROOT, 'apps/web');
16
16
  const UI_DEST = path.join(PKG_ROOT, 'workframe-ui', 'public');
17
17
 
18
18
  function npmCmd() {
@@ -1,37 +1,37 @@
1
- #!/usr/bin/env bash
2
- # Shared docker compose invocation for in-container apply (docker.sock on host).
3
- set -euo pipefail
4
-
5
- workframe_compose_prepare() {
6
- compose_cd=""
7
- compose_files=()
8
-
9
- # Host-bindings overlay: docker.sock apply from supervisor uses WORKFRAME_HOST_* paths.
10
- if [[ -n "${WORKFRAME_HOST_COMPOSE_DIR:-}" && -n "${WORKFRAME_COMPOSE_DIR:-}" \
11
- && -f "${WORKFRAME_COMPOSE_DIR}/docker-compose.yml" \
12
- && -f "${WORKFRAME_COMPOSE_DIR}/docker-compose.host-bindings.yml" ]]; then
13
- compose_cd="${WORKFRAME_COMPOSE_DIR}"
14
- compose_files=(-f docker-compose.yml -f docker-compose.host-bindings.yml)
15
- return 0
16
- fi
17
-
18
- # ponytail: docker Desktop resolves WORKFRAME_HOST_* via socket even when path is not visible in this container.
19
- if [[ -n "${WORKFRAME_HOST_COMPOSE_DIR:-}" ]]; then
20
- compose_cd="${WORKFRAME_HOST_COMPOSE_DIR}"
21
- compose_files=(-f docker-compose.yml)
22
- return 0
23
- fi
24
-
25
- compose_cd="${WORKFRAME_COMPOSE_DIR:-${WORKFRAME_PROJECT_ROOT:-.}}"
26
- compose_files=(-f docker-compose.yml)
27
- }
28
-
29
- workframe_compose() {
30
- workframe_compose_prepare
31
- cd "$compose_cd"
32
- if [[ ! -f docker-compose.yml ]]; then
33
- echo "docker-compose.yml not found in $compose_cd" >&2
34
- exit 1
35
- fi
36
- docker compose "${compose_files[@]}" "$@"
37
- }
1
+ #!/usr/bin/env bash
2
+ # Shared docker compose invocation for in-container apply (docker.sock on host).
3
+ set -euo pipefail
4
+
5
+ workframe_compose_prepare() {
6
+ compose_cd=""
7
+ compose_files=()
8
+
9
+ # Host-bindings overlay: docker.sock apply from supervisor uses WORKFRAME_HOST_* paths.
10
+ if [[ -n "${WORKFRAME_HOST_COMPOSE_DIR:-}" && -n "${WORKFRAME_COMPOSE_DIR:-}" \
11
+ && -f "${WORKFRAME_COMPOSE_DIR}/docker-compose.yml" \
12
+ && -f "${WORKFRAME_COMPOSE_DIR}/docker-compose.host-bindings.yml" ]]; then
13
+ compose_cd="${WORKFRAME_COMPOSE_DIR}"
14
+ compose_files=(-f docker-compose.yml -f docker-compose.host-bindings.yml)
15
+ return 0
16
+ fi
17
+
18
+ # ponytail: docker Desktop resolves WORKFRAME_HOST_* via socket even when path is not visible in this container.
19
+ if [[ -n "${WORKFRAME_HOST_COMPOSE_DIR:-}" ]]; then
20
+ compose_cd="${WORKFRAME_HOST_COMPOSE_DIR}"
21
+ compose_files=(-f docker-compose.yml)
22
+ return 0
23
+ fi
24
+
25
+ compose_cd="${WORKFRAME_COMPOSE_DIR:-${WORKFRAME_PROJECT_ROOT:-.}}"
26
+ compose_files=(-f docker-compose.yml)
27
+ }
28
+
29
+ workframe_compose() {
30
+ workframe_compose_prepare
31
+ cd "$compose_cd"
32
+ if [[ ! -f docker-compose.yml ]]; then
33
+ echo "docker-compose.yml not found in $compose_cd" >&2
34
+ exit 1
35
+ fi
36
+ docker compose "${compose_files[@]}" "$@"
37
+ }
@@ -1,51 +1,51 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Ensure WORKFRAME_HOST_* paths exist in compose .env (VPS in-app publish/sync).
4
- * Usage: node ensure-compose-host-paths.mjs --project-root /opt/workframe/ProjectX [--env path]
5
- */
6
- import fs from 'node:fs';
7
- import path from 'node:path';
8
-
9
- const args = process.argv.slice(2);
10
- const rootFlag = args.indexOf('--project-root');
11
- const envFlag = args.indexOf('--env');
12
- const projectRoot =
13
- rootFlag >= 0 ? args[rootFlag + 1] : '/opt/workframe/ProjectX';
14
- const envPath =
15
- envFlag >= 0
16
- ? args[envFlag + 1]
17
- : path.join(projectRoot, 'infra/compose/workframe/.env');
18
- const composeDir = path.join(projectRoot, 'infra/compose/workframe');
19
-
20
- function setIfEmpty(text, key, val) {
21
- const esc = key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
22
- const re = new RegExp(`^${esc}=(.*)$`, 'm');
23
- const m = text.match(re);
24
- if (m && String(m[1] || '').trim()) return text;
25
- const line = `${key}=${val}`;
26
- if (m) return text.replace(re, line);
27
- return `${text}${text.endsWith('\n') || !text ? '' : '\n'}${line}\n`;
28
- }
29
-
30
- if (!fs.existsSync(envPath)) {
31
- console.error(`Missing env file: ${envPath}`);
32
- process.exit(1);
33
- }
34
-
35
- let text = fs.readFileSync(envPath, 'utf8');
36
- text = setIfEmpty(text, 'WORKFRAME_HOST_PROJECT_ROOT', projectRoot.replace(/\\/g, '/'));
37
- text = setIfEmpty(text, 'WORKFRAME_HOST_COMPOSE_DIR', composeDir.replace(/\\/g, '/'));
38
- fs.writeFileSync(envPath, text);
39
-
40
- console.log(
41
- JSON.stringify(
42
- {
43
- ok: true,
44
- env: envPath,
45
- project_root: projectRoot.replace(/\\/g, '/'),
46
- compose_dir: composeDir.replace(/\\/g, '/'),
47
- },
48
- null,
49
- 2,
50
- ),
51
- );
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Ensure WORKFRAME_HOST_* paths exist in compose .env (VPS in-app publish/sync).
4
+ * Usage: node ensure-compose-host-paths.mjs --project-root /opt/workframe/repo [--env path]
5
+ */
6
+ import fs from 'node:fs';
7
+ import path from 'node:path';
8
+
9
+ const args = process.argv.slice(2);
10
+ const rootFlag = args.indexOf('--project-root');
11
+ const envFlag = args.indexOf('--env');
12
+ const projectRoot =
13
+ rootFlag >= 0 ? args[rootFlag + 1] : '/opt/workframe/repo';
14
+ const envPath =
15
+ envFlag >= 0
16
+ ? args[envFlag + 1]
17
+ : path.join(projectRoot, 'infra/compose/workframe/.env');
18
+ const composeDir = path.join(projectRoot, 'infra/compose/workframe');
19
+
20
+ function setIfEmpty(text, key, val) {
21
+ const esc = key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
22
+ const re = new RegExp(`^${esc}=(.*)$`, 'm');
23
+ const m = text.match(re);
24
+ if (m && String(m[1] || '').trim()) return text;
25
+ const line = `${key}=${val}`;
26
+ if (m) return text.replace(re, line);
27
+ return `${text}${text.endsWith('\n') || !text ? '' : '\n'}${line}\n`;
28
+ }
29
+
30
+ if (!fs.existsSync(envPath)) {
31
+ console.error(`Missing env file: ${envPath}`);
32
+ process.exit(1);
33
+ }
34
+
35
+ let text = fs.readFileSync(envPath, 'utf8');
36
+ text = setIfEmpty(text, 'WORKFRAME_HOST_PROJECT_ROOT', projectRoot.replace(/\\/g, '/'));
37
+ text = setIfEmpty(text, 'WORKFRAME_HOST_COMPOSE_DIR', composeDir.replace(/\\/g, '/'));
38
+ fs.writeFileSync(envPath, text);
39
+
40
+ console.log(
41
+ JSON.stringify(
42
+ {
43
+ ok: true,
44
+ env: envPath,
45
+ project_root: projectRoot.replace(/\\/g, '/'),
46
+ compose_dir: composeDir.replace(/\\/g, '/'),
47
+ },
48
+ null,
49
+ 2,
50
+ ),
51
+ );
@@ -1,35 +1,35 @@
1
- #!/usr/bin/env bash
2
- # Fix ZK_AUTH_ENCRYPTION_KEY when it was generated as hex instead of base64.
3
- set -euo pipefail
4
- ENV_FILE="${1:-/opt/workframe/MyBusiness/.env}"
5
- FORCE="${2:-}"
6
- python3 - "$ENV_FILE" "$FORCE" <<'PY'
7
- import base64, os, re, sys
8
- from pathlib import Path
9
- env, force = Path(sys.argv[1]), sys.argv[2] == "--force"
10
- text = env.read_text(encoding="utf-8")
11
- m = re.search(r"^ZK_AUTH_ENCRYPTION_KEY=(.*)$", text, re.M)
12
- if not m:
13
- print("ZK_AUTH_ENCRYPTION_KEY missing"); sys.exit(1)
14
- val = m.group(1).strip()
15
- try:
16
- ok = len(base64.b64decode(val)) == 32
17
- except Exception:
18
- ok = False
19
- if ok:
20
- print("ZK_AUTH_ENCRYPTION_KEY already valid"); sys.exit(0)
21
-
22
- zk_db = Path(os.environ.get("WORKFRAME_API_DATA_DIR", "/app/data")) / "zk_auth.db"
23
- if zk_db.is_file() and not force:
24
- import sqlite3
25
- n = sqlite3.connect(str(zk_db)).execute("SELECT COUNT(*) FROM identities").fetchone()[0]
26
- if n > 0:
27
- print(f"REFUSING: {n} encrypted identities present. Regenerating the KEK will lock "
28
- f"out every existing user. Re-run with --force to proceed.", file=sys.stderr)
29
- sys.exit(1)
30
-
31
- new_key = base64.b64encode(os.urandom(32)).decode()
32
- text = re.sub(r"^ZK_AUTH_ENCRYPTION_KEY=.*$", f"ZK_AUTH_ENCRYPTION_KEY={new_key}", text, flags=re.M)
33
- env.write_text(text, encoding="utf-8")
34
- print("ZK_AUTH_ENCRYPTION_KEY regenerated (was invalid base64)")
35
- PY
1
+ #!/usr/bin/env bash
2
+ # Fix ZK_AUTH_ENCRYPTION_KEY when it was generated as hex instead of base64.
3
+ set -euo pipefail
4
+ ENV_FILE="${1:-/opt/workframe/MyBusiness/.env}"
5
+ FORCE="${2:-}"
6
+ python3 - "$ENV_FILE" "$FORCE" <<'PY'
7
+ import base64, os, re, sys
8
+ from pathlib import Path
9
+ env, force = Path(sys.argv[1]), sys.argv[2] == "--force"
10
+ text = env.read_text(encoding="utf-8")
11
+ m = re.search(r"^ZK_AUTH_ENCRYPTION_KEY=(.*)$", text, re.M)
12
+ if not m:
13
+ print("ZK_AUTH_ENCRYPTION_KEY missing"); sys.exit(1)
14
+ val = m.group(1).strip()
15
+ try:
16
+ ok = len(base64.b64decode(val)) == 32
17
+ except Exception:
18
+ ok = False
19
+ if ok:
20
+ print("ZK_AUTH_ENCRYPTION_KEY already valid"); sys.exit(0)
21
+
22
+ zk_db = Path(os.environ.get("WORKFRAME_API_DATA_DIR", "/app/data")) / "zk_auth.db"
23
+ if zk_db.is_file() and not force:
24
+ import sqlite3
25
+ n = sqlite3.connect(str(zk_db)).execute("SELECT COUNT(*) FROM identities").fetchone()[0]
26
+ if n > 0:
27
+ print(f"REFUSING: {n} encrypted identities present. Regenerating the KEK will lock "
28
+ f"out every existing user. Re-run with --force to proceed.", file=sys.stderr)
29
+ sys.exit(1)
30
+
31
+ new_key = base64.b64encode(os.urandom(32)).decode()
32
+ text = re.sub(r"^ZK_AUTH_ENCRYPTION_KEY=.*$", f"ZK_AUTH_ENCRYPTION_KEY={new_key}", text, flags=re.M)
33
+ env.write_text(text, encoding="utf-8")
34
+ print("ZK_AUTH_ENCRYPTION_KEY regenerated (was invalid base64)")
35
+ PY