procesio-cli 0.1.1__py3-none-any.whl

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 (647) hide show
  1. procesio_cli/__init__.py +18 -0
  2. procesio_cli/_cli.py +71 -0
  3. procesio_cli/agents/__init__.py +0 -0
  4. procesio_cli/agents/_lib/__init__.py +0 -0
  5. procesio_cli/agents/_lib/actiondef.py +24 -0
  6. procesio_cli/agents/_lib/errors.py +40 -0
  7. procesio_cli/agents/_lib/reversibility.py +236 -0
  8. procesio_cli/agents/_lib/toolrunner.py +141 -0
  9. procesio_cli/agents/connector-builder/CONNECTOR-BUILDER-PLAYBOOK.md +62 -0
  10. procesio_cli/agents/connector-builder/CONNECTOR-BUILDER-PROCESIO-INTEROP.md +76 -0
  11. procesio_cli/agents/connector-builder/CONNECTOR-BUILDER-TROUBLESHOOTING.md +60 -0
  12. procesio_cli/agents/connector-builder/README.md +51 -0
  13. procesio_cli/agents/connector-builder/agent.yaml +61 -0
  14. procesio_cli/agents/connector-builder/context.py +19 -0
  15. procesio_cli/agents/connector-builder/handlers/__init__.py +1 -0
  16. procesio_cli/agents/connector-builder/handlers/checklist.py +71 -0
  17. procesio_cli/agents/connector-builder/handlers/guidance.py +37 -0
  18. procesio_cli/agents/connector-builder/handlers/nextstep.py +221 -0
  19. procesio_cli/agents/connector-builder/handlers/status.py +35 -0
  20. procesio_cli/agents/connector-builder/knowledge.py +47 -0
  21. procesio_cli/agents/connector-builder/main.py +93 -0
  22. procesio_cli/agents/connector-builder/tests/conftest.py +95 -0
  23. procesio_cli/agents/connector-builder/tests/test_cba_agent.py +148 -0
  24. procesio_cli/agents/orchestrator/__init__.py +0 -0
  25. procesio_cli/agents/orchestrator/bootstraplib.py +166 -0
  26. procesio_cli/agents/procesio/IMPLEMENTATION-PATTERNS/00-INDEX.md +60 -0
  27. procesio_cli/agents/procesio/IMPLEMENTATION-PATTERNS/01-PROCESSES.md +230 -0
  28. procesio_cli/agents/procesio/IMPLEMENTATION-PATTERNS/02-FORMS.md +287 -0
  29. procesio_cli/agents/procesio/IMPLEMENTATION-PATTERNS/03-INTEGRATIONS.md +384 -0
  30. procesio_cli/agents/procesio/IMPLEMENTATION-PATTERNS/04-DATABASE.md +293 -0
  31. procesio_cli/agents/procesio/PROCESIO-API-RELIABILITY-DOCTRINE.md +113 -0
  32. procesio_cli/agents/procesio/PROCESIO-BEST-PRACTICES.md +316 -0
  33. procesio_cli/agents/procesio/PROCESIO-BUILD-AND-TEST-PLAYBOOK.md +217 -0
  34. procesio_cli/agents/procesio/PROCESIO-DATASTORE.md +72 -0
  35. procesio_cli/agents/procesio/PROCESIO-ENVIRONMENTS.md +62 -0
  36. procesio_cli/agents/procesio/PROCESIO-SCHEDULING.md +47 -0
  37. procesio_cli/agents/procesio/PROCESIO-VISUAL-ORGANIZATION.md +175 -0
  38. procesio_cli/agents/procesio/README.md +97 -0
  39. procesio_cli/agents/procesio/__init__.py +0 -0
  40. procesio_cli/agents/procesio/agent.yaml +73 -0
  41. procesio_cli/agents/procesio/audit.py +226 -0
  42. procesio_cli/agents/procesio/checklist.py +135 -0
  43. procesio_cli/agents/procesio/context.py +19 -0
  44. procesio_cli/agents/procesio/handlers/__init__.py +0 -0
  45. procesio_cli/agents/procesio/handlers/audit.py +39 -0
  46. procesio_cli/agents/procesio/handlers/checklist.py +34 -0
  47. procesio_cli/agents/procesio/handlers/guidance.py +36 -0
  48. procesio_cli/agents/procesio/handlers/status.py +33 -0
  49. procesio_cli/agents/procesio/handlers/verify.py +39 -0
  50. procesio_cli/agents/procesio/knowledge.py +115 -0
  51. procesio_cli/agents/procesio/main.py +89 -0
  52. procesio_cli/agents/procesio/tests/__init__.py +0 -0
  53. procesio_cli/agents/procesio/tests/conftest.py +62 -0
  54. procesio_cli/agents/procesio/tests/test_audit.py +91 -0
  55. procesio_cli/agents/procesio/tests/test_checklist.py +28 -0
  56. procesio_cli/agents/procesio/tests/test_guidance.py +78 -0
  57. procesio_cli/agents/procesio/tests/test_manifest_sync.py +48 -0
  58. procesio_cli/agents/procesio/tests/test_verify.py +134 -0
  59. procesio_cli/agents/procesio/tests/test_workspace_scope.py +97 -0
  60. procesio_cli/agents/procesio/verifylib.py +222 -0
  61. procesio_cli/dashboard/README.md +117 -0
  62. procesio_cli/dashboard/__init__.py +18 -0
  63. procesio_cli/dashboard/serve.py +98 -0
  64. procesio_cli/dashboard/server/__init__.py +1 -0
  65. procesio_cli/dashboard/server/config_schemas.py +92 -0
  66. procesio_cli/dashboard/server/google.py +103 -0
  67. procesio_cli/dashboard/server/handler.py +160 -0
  68. procesio_cli/dashboard/server/inventory.py +213 -0
  69. procesio_cli/dashboard/server/jobs.py +118 -0
  70. procesio_cli/dashboard/server/llmtest.py +181 -0
  71. procesio_cli/dashboard/server/procesio_env.py +94 -0
  72. procesio_cli/dashboard/server/routes.py +74 -0
  73. procesio_cli/dashboard/server/runner.py +150 -0
  74. procesio_cli/dashboard/server/security.py +29 -0
  75. procesio_cli/dashboard/server/setup.py +211 -0
  76. procesio_cli/dashboard/server/validate.py +152 -0
  77. procesio_cli/dashboard/tests/conftest.py +16 -0
  78. procesio_cli/dashboard/tests/test_dashboard.py +225 -0
  79. procesio_cli/dashboard/tests/test_procesio_env.py +159 -0
  80. procesio_cli/dashboard/web/actions.js +274 -0
  81. procesio_cli/dashboard/web/api.js +79 -0
  82. procesio_cli/dashboard/web/app.js +385 -0
  83. procesio_cli/dashboard/web/copilot.js +72 -0
  84. procesio_cli/dashboard/web/google.js +121 -0
  85. procesio_cli/dashboard/web/index.html +67 -0
  86. procesio_cli/dashboard/web/procesio_env.js +187 -0
  87. procesio_cli/dashboard/web/styles.css +207 -0
  88. procesio_cli/registry.py +370 -0
  89. procesio_cli/scripts/build-router.py +249 -0
  90. procesio_cli/scripts/build-tool-skill.py +202 -0
  91. procesio_cli/scripts/check-requirements.py +131 -0
  92. procesio_cli/scripts/check-skill-governance.py +174 -0
  93. procesio_cli/scripts/evaluate-skill-routing.py +217 -0
  94. procesio_cli/scripts/evaluate-skills.py +316 -0
  95. procesio_cli/scripts/get-skill.py +122 -0
  96. procesio_cli/scripts/list-skills.py +68 -0
  97. procesio_cli/scripts/list-tools.py +73 -0
  98. procesio_cli/scripts/run-agent.py +59 -0
  99. procesio_cli/scripts/run-tool.py +123 -0
  100. procesio_cli/scripts/secret_scan.py +584 -0
  101. procesio_cli/scripts/set-credential.py +126 -0
  102. procesio_cli/scripts/validate-skills.py +530 -0
  103. procesio_cli/skills/PORTFOLIO.md +134 -0
  104. procesio_cli/skills/__init__.py +6 -0
  105. procesio_cli/skills/agent-skill-engineer/SKILL.md +226 -0
  106. procesio_cli/skills/agent-skill-engineer/evals/evals.json +422 -0
  107. procesio_cli/skills/agent-skill-engineer/references/authoring-standard.md +178 -0
  108. procesio_cli/skills/agent-skill-engineer/references/decision-framework.md +107 -0
  109. procesio_cli/skills/agent-skill-engineer/references/domain-evidence-protocol.md +248 -0
  110. procesio_cli/skills/agent-skill-engineer/references/evaluation-standard.md +191 -0
  111. procesio_cli/skills/agent-skill-engineer/references/expert-lenses.md +167 -0
  112. procesio_cli/skills/agent-skill-engineer/references/field-gate-standard.md +231 -0
  113. procesio_cli/skills/agent-skill-engineer/references/optimization-protocol.md +233 -0
  114. procesio_cli/skills/agent-skill-engineer/references/optimizer-contract.md +268 -0
  115. procesio_cli/skills/agent-skill-engineer/references/portability-standard.md +99 -0
  116. procesio_cli/skills/agent-skill-engineer/references/research-basis.md +128 -0
  117. procesio_cli/skills/agent-skill-engineer/references/review-standard.md +143 -0
  118. procesio_cli/skills/agent-skill-engineer/scripts/audit_skill.py +959 -0
  119. procesio_cli/skills/agent-skill-engineer/scripts/optimize_skill.py +891 -0
  120. procesio_cli/skills/agent-skill-engineer/scripts/scaffold_skill.py +397 -0
  121. procesio_cli/skills/evals/baseline-catalog.json +14 -0
  122. procesio_cli/skills/evals/baseline-routing-v2.json +38 -0
  123. procesio_cli/skills/evals/baseline.json +37 -0
  124. procesio_cli/skills/evals/behavioral.json +367 -0
  125. procesio_cli/skills/evals/field-boundary-development-v1.json +126 -0
  126. procesio_cli/skills/evals/field-closeout-correction-development-v1.json +23 -0
  127. procesio_cli/skills/evals/field-closeout-development-v1.json +89 -0
  128. procesio_cli/skills/evals/portfolio-pressure-training-v1.json +83 -0
  129. procesio_cli/skills/evals/routing.json +363 -0
  130. procesio_cli/skills/evals/validation-baseline.json +4 -0
  131. procesio_cli/skills/procesio-cli/SKILL.md +134 -0
  132. procesio_cli/skills/procesio-cli/evals/evals.json +111 -0
  133. procesio_cli/skills/procesio-cli/evals/workflows.json +16 -0
  134. procesio_cli/skills/procesio-cli/references/connector-lifecycle.md +47 -0
  135. procesio_cli/skills/procesio-cli/references/credentials-admin.md +113 -0
  136. procesio_cli/skills/procesio-cli/references/data-verification.md +71 -0
  137. procesio_cli/skills/procesio-cli/references/documents-files.md +44 -0
  138. procesio_cli/skills/procesio-cli/references/form-e2e.md +57 -0
  139. procesio_cli/skills/procesio-cli/references/operation-contract.md +138 -0
  140. procesio_cli/skills/procesio-cli/references/process-debugging.md +65 -0
  141. procesio_cli/skills/procesio-cli/references/process-lifecycle.md +88 -0
  142. procesio_cli/skills/procesio-cli/references/schedules-webhooks.md +58 -0
  143. procesio_cli/skills/procesio-cli/references/transport-environments.md +53 -0
  144. procesio_cli/skills/procesio-cli-maintainer/SKILL.md +84 -0
  145. procesio_cli/skills/procesio-cli-maintainer/evals/evals.json +116 -0
  146. procesio_cli/skills/procesio-cli-maintainer/references/change-contract.md +34 -0
  147. procesio_cli/skills/procesio-cli-maintainer/references/mcp-compatibility.md +13 -0
  148. procesio_cli/skills/procesio-cli-maintainer/references/skill-authoring.md +51 -0
  149. procesio_cli/skills/procesio-platform-advisor/SKILL.md +82 -0
  150. procesio_cli/skills/procesio-platform-advisor/evals/evals.json +116 -0
  151. procesio_cli/skills/procesio-platform-advisor/references/capability-map.md +22 -0
  152. procesio_cli/skills/procesio-platform-advisor/references/fit-framework.md +35 -0
  153. procesio_cli/skills/procesio-platform-advisor/references/freshness-policy.md +25 -0
  154. procesio_cli/skills/procesio-platform-advisor/references/sizing-method.md +70 -0
  155. procesio_cli/skills/procesio-platform-advisor/scripts/estimate_capacity.py +99 -0
  156. procesio_cli/skills/procesio-setup/SKILL.md +180 -0
  157. procesio_cli/skills/sql-server-optimizer/SKILL.md +86 -0
  158. procesio_cli/skills/sql-server-optimizer/evals/evals.json +116 -0
  159. procesio_cli/skills/sql-server-optimizer/references/db-context.md +44 -0
  160. procesio_cli/skills/sql-server-optimizer/references/generic-mode.md +32 -0
  161. procesio_cli/skills/sql-server-optimizer/references/procesio-mode.md +40 -0
  162. procesio_cli/skills/sql-server-optimizer/references/sql-rules.md +43 -0
  163. procesio_cli/skills/sql-server-optimizer/scripts/export-indexes.sql +178 -0
  164. procesio_cli/skills/sql-server-optimizer/scripts/export-procs-and-functions.sql +118 -0
  165. procesio_cli/skills/sql-server-optimizer/scripts/export-tables.sql +367 -0
  166. procesio_cli/skills/tests/__init__.py +0 -0
  167. procesio_cli/skills/tests/test_agent_skill_engineer.py +240 -0
  168. procesio_cli/skills/tests/test_auth_failure_stop.py +25 -0
  169. procesio_cli/skills/tests/test_capacity_estimator.py +85 -0
  170. procesio_cli/skills/tests/test_field_boundary_learning.py +100 -0
  171. procesio_cli/skills/tests/test_field_closeout_learning.py +123 -0
  172. procesio_cli/skills/tests/test_field_gate_standard.py +76 -0
  173. procesio_cli/skills/tests/test_operational_playbooks.py +51 -0
  174. procesio_cli/skills/tests/test_portfolio_pressure_training.py +35 -0
  175. procesio_cli/skills/tests/test_process_lifecycle_single_run.py +25 -0
  176. procesio_cli/skills/tests/test_skill_evaluator.py +67 -0
  177. procesio_cli/skills/tests/test_skill_optimizer.py +473 -0
  178. procesio_cli/skills/tests/test_skill_portfolio_review.py +70 -0
  179. procesio_cli/skills/tests/test_skill_release_binding.py +204 -0
  180. procesio_cli/skills/tests/test_skill_routing.py +74 -0
  181. procesio_cli/skills/tests/test_skill_scaffold_v2.py +116 -0
  182. procesio_cli/skills/tests/test_validate_skills.py +115 -0
  183. procesio_cli/tools/__init__.py +0 -0
  184. procesio_cli/tools/_lib/README.md +119 -0
  185. procesio_cli/tools/_lib/__init__.py +0 -0
  186. procesio_cli/tools/_lib/accounting.py +120 -0
  187. procesio_cli/tools/_lib/contacts.py +544 -0
  188. procesio_cli/tools/_lib/creds.py +83 -0
  189. procesio_cli/tools/_lib/creds_backends.py +578 -0
  190. procesio_cli/tools/_lib/dbprofiles.py +147 -0
  191. procesio_cli/tools/_lib/dbquery.py +286 -0
  192. procesio_cli/tools/_lib/dbschema.py +225 -0
  193. procesio_cli/tools/_lib/io.py +54 -0
  194. procesio_cli/tools/_lib/manifest.py +297 -0
  195. procesio_cli/tools/_lib/skill_release.py +127 -0
  196. procesio_cli/tools/_lib/skill_resources.py +118 -0
  197. procesio_cli/tools/_lib/userdata.py +228 -0
  198. procesio_cli/tools/_lib/webserialize/__init__.py +16 -0
  199. procesio_cli/tools/_lib/webserialize/admin.py +61 -0
  200. procesio_cli/tools/_lib/webserialize/client.py +264 -0
  201. procesio_cli/tools/_lib/webserialize/config.py +96 -0
  202. procesio_cli/tools/_lib/webserialize/errors.py +27 -0
  203. procesio_cli/tools/_lib/webserialize/framing.py +45 -0
  204. procesio_cli/tools/_lib/webserialize/registry.py +47 -0
  205. procesio_cli/tools/_lib/webserialize/runtime.py +61 -0
  206. procesio_cli/tools/_lib/webserialize/server.py +510 -0
  207. procesio_cli/tools/_lib/websession.py +194 -0
  208. procesio_cli/tools/connector-builder/CONNECTOR-BUILDER-API-NOTES.md +91 -0
  209. procesio_cli/tools/connector-builder/README.md +101 -0
  210. procesio_cli/tools/connector-builder/SKILL.md +248 -0
  211. procesio_cli/tools/connector-builder/__init__.py +7 -0
  212. procesio_cli/tools/connector-builder/actiondef.py +24 -0
  213. procesio_cli/tools/connector-builder/client.py +251 -0
  214. procesio_cli/tools/connector-builder/errors.py +44 -0
  215. procesio_cli/tools/connector-builder/gen_manifest.py +142 -0
  216. procesio_cli/tools/connector-builder/handlers/__init__.py +1 -0
  217. procesio_cli/tools/connector-builder/handlers/admin.py +182 -0
  218. procesio_cli/tools/connector-builder/handlers/auth.py +74 -0
  219. procesio_cli/tools/connector-builder/handlers/builds.py +396 -0
  220. procesio_cli/tools/connector-builder/handlers/common.py +104 -0
  221. procesio_cli/tools/connector-builder/handlers/files.py +111 -0
  222. procesio_cli/tools/connector-builder/handlers/raw.py +38 -0
  223. procesio_cli/tools/connector-builder/handlers/telemetry.py +39 -0
  224. procesio_cli/tools/connector-builder/main.py +94 -0
  225. procesio_cli/tools/connector-builder/tests/conftest.py +146 -0
  226. procesio_cli/tools/connector-builder/tests/test_cb_client.py +86 -0
  227. procesio_cli/tools/connector-builder/tests/test_cb_dispatch.py +105 -0
  228. procesio_cli/tools/connector-builder/tests/test_cb_manifest_sync.py +76 -0
  229. procesio_cli/tools/connector-builder/tests/test_cb_wait.py +123 -0
  230. procesio_cli/tools/connector-builder/tool.yaml +671 -0
  231. procesio_cli/tools/framework-map/.gitattributes +2 -0
  232. procesio_cli/tools/framework-map/README.md +98 -0
  233. procesio_cli/tools/framework-map/SKILL.md +30 -0
  234. procesio_cli/tools/framework-map/app.js +188 -0
  235. procesio_cli/tools/framework-map/fm_builder.py +476 -0
  236. procesio_cli/tools/framework-map/fm_catalog.py +19 -0
  237. procesio_cli/tools/framework-map/fm_ro_catalog.py +94 -0
  238. procesio_cli/tools/framework-map/fm_strings.py +101 -0
  239. procesio_cli/tools/framework-map/main.py +95 -0
  240. procesio_cli/tools/framework-map/styles.css +214 -0
  241. procesio_cli/tools/framework-map/tests/conftest.py +33 -0
  242. procesio_cli/tools/framework-map/tests/test_fm_build.py +126 -0
  243. procesio_cli/tools/framework-map/tests/test_fm_manifest_sync.py +63 -0
  244. procesio_cli/tools/framework-map/tests/test_fm_store_tree.py +75 -0
  245. procesio_cli/tools/framework-map/tool.yaml +61 -0
  246. procesio_cli/tools/mysql/MOVED-TO-CENTRAL.md +29 -0
  247. procesio_cli/tools/mysql/README.md +196 -0
  248. procesio_cli/tools/mysql/SKILL.md +37 -0
  249. procesio_cli/tools/mysql/__init__.py +0 -0
  250. procesio_cli/tools/mysql/connection.py +191 -0
  251. procesio_cli/tools/mysql/main.py +487 -0
  252. procesio_cli/tools/mysql/profiles.template.json +1 -0
  253. procesio_cli/tools/mysql/schema.py +434 -0
  254. procesio_cli/tools/mysql/tests/__init__.py +0 -0
  255. procesio_cli/tools/mysql/tests/conftest.py +21 -0
  256. procesio_cli/tools/mysql/tests/test_manifest_sync.py +68 -0
  257. procesio_cli/tools/mysql/tests/test_mysql.py +201 -0
  258. procesio_cli/tools/mysql/tests/test_mysql_schema.py +337 -0
  259. procesio_cli/tools/mysql/tool.yaml +112 -0
  260. procesio_cli/tools/procesio/DTO-SUBTOOLS-NOTE.md +360 -0
  261. procesio_cli/tools/procesio/FORM-DEV-GUIDE/00-INDEX.md +67 -0
  262. procesio_cli/tools/procesio/FORM-DEV-GUIDE/01-ANATOMY.md +209 -0
  263. procesio_cli/tools/procesio/FORM-DEV-GUIDE/02-CODE-INJECTION.md +309 -0
  264. procesio_cli/tools/procesio/FORM-DEV-GUIDE/03-DOM-CONTRACT.md +370 -0
  265. procesio_cli/tools/procesio/FORM-DEV-GUIDE/04-INTERACTION-RECIPES.md +600 -0
  266. procesio_cli/tools/procesio/FORM-DEV-GUIDE/05-STEPPER-AND-MOTION.md +426 -0
  267. procesio_cli/tools/procesio/FORM-DEV-GUIDE/06-PROCESS-INTEGRATION.md +347 -0
  268. procesio_cli/tools/procesio/FORM-DEV-GUIDE/07-DEPLOY-WORKFLOW.md +294 -0
  269. procesio_cli/tools/procesio/FORM-DEV-GUIDE/08-PITFALLS.md +569 -0
  270. procesio_cli/tools/procesio/FORM-DEV-GUIDE/09-NAVIGATION-AND-HOSTING.md +308 -0
  271. procesio_cli/tools/procesio/PHASE4-E2E-NOTES.md +594 -0
  272. procesio_cli/tools/procesio/PROCESIO-API-CORRECTIONS.md +295 -0
  273. procesio_cli/tools/procesio/PROCESIO-API-NOTES.md +6976 -0
  274. procesio_cli/tools/procesio/PROCESIO-AUTH-NOTES.md +226 -0
  275. procesio_cli/tools/procesio/PROCESIO-CARD-BUILD-NOTES.md +183 -0
  276. procesio_cli/tools/procesio/PROCESIO-CONNECTORS-NOTES.md +141 -0
  277. procesio_cli/tools/procesio/PROCESIO-CUSTOM-ACTION-NOTES.md +179 -0
  278. procesio_cli/tools/procesio/PROCESIO-DOCS-FIX-REPORT.md +123 -0
  279. procesio_cli/tools/procesio/PROCESIO-ENVIRONMENTS-NOTES.md +94 -0
  280. procesio_cli/tools/procesio/PROCESIO-FE-VALIDATION-NOTES.md +107 -0
  281. procesio_cli/tools/procesio/PROCESIO-FOREACH-NOTES.md +199 -0
  282. procesio_cli/tools/procesio/PROCESIO-FORM-API-HANG-NOTE.md +101 -0
  283. procesio_cli/tools/procesio/PROCESIO-FORM-SUBMISSION-NOTES.md +172 -0
  284. procesio_cli/tools/procesio/PROCESIO-HTML-TO-DOCX-NOTES.md +110 -0
  285. procesio_cli/tools/procesio/PROCESIO-INSTANCE-HISTORY-NOTES.md +242 -0
  286. procesio_cli/tools/procesio/PROCESIO-METERING-NOTES.md +201 -0
  287. procesio_cli/tools/procesio/PROCESIO-NODE-CODE-NOTES.md +279 -0
  288. procesio_cli/tools/procesio/PROCESIO-NODE-MODULE-WHITELIST.md +113 -0
  289. procesio_cli/tools/procesio/PROCESIO-PYTHON-ACTION-NOTES.md +165 -0
  290. procesio_cli/tools/procesio/PROCESIO-QUERY-STORE-NOTES.md +826 -0
  291. procesio_cli/tools/procesio/PROCESIO-RECONCILIATION-PATTERNS.md +104 -0
  292. procesio_cli/tools/procesio/PROCESIO-RESOURCE-MODEL-NOTES.md +1100 -0
  293. procesio_cli/tools/procesio/PROCESIO-SEND-EMAIL-CRED-OPTIONALITY.md +45 -0
  294. procesio_cli/tools/procesio/PROCESIO-SEND-EMAIL-NOTES.md +252 -0
  295. procesio_cli/tools/procesio/PROCESIO-SQL-ACTIONS-NOTES.md +284 -0
  296. procesio_cli/tools/procesio/PROCESIO-USAGE-GUIDE.md +219 -0
  297. procesio_cli/tools/procesio/README.md +341 -0
  298. procesio_cli/tools/procesio/SCHEDULE-INPUT-SECURITY-NOTES.md +63 -0
  299. procesio_cli/tools/procesio/SKILL.md +694 -0
  300. procesio_cli/tools/procesio/__init__.py +1 -0
  301. procesio_cli/tools/procesio/actiondef.py +27 -0
  302. procesio_cli/tools/procesio/assets/html2docx/html2docx.js +2155 -0
  303. procesio_cli/tools/procesio/auth.py +354 -0
  304. procesio_cli/tools/procesio/autogen.py +121 -0
  305. procesio_cli/tools/procesio/client.py +355 -0
  306. procesio_cli/tools/procesio/config.py +96 -0
  307. procesio_cli/tools/procesio/data/endpoints.json +2901 -0
  308. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/01-authentication.md +180 -0
  309. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/02-conventions.md +116 -0
  310. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/ANONYMOUS-SURFACE.md +51 -0
  311. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/README.md +104 -0
  312. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/SYMBOL-INDEX.md +444 -0
  313. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/03-auth-users-workspaces.md +731 -0
  314. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/04-processes.md +913 -0
  315. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/05-actions.md +605 -0
  316. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/06-files.md +237 -0
  317. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/07-forms-documents.md +985 -0
  318. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/08-credentials.md +532 -0
  319. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/09-datastore-datatypes.md +830 -0
  320. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/10-custom-urls.md +319 -0
  321. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/11-subscriptions-resources-analytics.md +455 -0
  322. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/12-webhooks-notifications-misc.md +519 -0
  323. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/13-realtime-signalr.md +153 -0
  324. procesio_cli/tools/procesio/docs_info/API-DOCUMENTATION/endpoints/99-internal-and-other-services.md +52 -0
  325. procesio_cli/tools/procesio/docs_info/FormBuilder mock.ts +5725 -0
  326. procesio_cli/tools/procesio/docs_info/Procesio Platform Actions.json +30219 -0
  327. procesio_cli/tools/procesio/docs_info/form-config-enums.ts +92 -0
  328. procesio_cli/tools/procesio/docs_info/form-theme.ts +1603 -0
  329. procesio_cli/tools/procesio/docs_info/process-validation-reference-1.md +2739 -0
  330. procesio_cli/tools/procesio/dto/__init__.py +13 -0
  331. procesio_cli/tools/procesio/dto/credential/builder.py +179 -0
  332. procesio_cli/tools/procesio/dto/credential/config.schema.json +19 -0
  333. procesio_cli/tools/procesio/dto/credential/description.md +193 -0
  334. procesio_cli/tools/procesio/dto/credential/fixtures/rest.config.json +11 -0
  335. procesio_cli/tools/procesio/dto/credential/fixtures/rest.dto.json +28 -0
  336. procesio_cli/tools/procesio/dto/credential/fixtures/rest.template.json +44 -0
  337. procesio_cli/tools/procesio/dto/credential/template.dto.json +16 -0
  338. procesio_cli/tools/procesio/dto/data/_refresh.py +147 -0
  339. procesio_cli/tools/procesio/dto/data/action_catalog.json +30825 -0
  340. procesio_cli/tools/procesio/dto/data/action_families.json +55 -0
  341. procesio_cli/tools/procesio/dto/data/platform_types.json +182 -0
  342. procesio_cli/tools/procesio/dto/datatype/builder.py +223 -0
  343. procesio_cli/tools/procesio/dto/datatype/config.schema.json +47 -0
  344. procesio_cli/tools/procesio/dto/datatype/description.md +85 -0
  345. procesio_cli/tools/procesio/dto/datatype/fixtures/customer.config.json +41 -0
  346. procesio_cli/tools/procesio/dto/datatype/fixtures/customer.dto.json +164 -0
  347. procesio_cli/tools/procesio/dto/datatype/template.dto.json +37 -0
  348. procesio_cli/tools/procesio/dto/document/builder.py +193 -0
  349. procesio_cli/tools/procesio/dto/document/config.schema.json +33 -0
  350. procesio_cli/tools/procesio/dto/document/description.md +124 -0
  351. procesio_cli/tools/procesio/dto/document/fixtures/invoice.config.json +16 -0
  352. procesio_cli/tools/procesio/dto/document/fixtures/invoice.dto.json +32 -0
  353. procesio_cli/tools/procesio/dto/document/template.dto.json +14 -0
  354. procesio_cli/tools/procesio/dto/form/FORM-STYLING-NOTES.md +142 -0
  355. procesio_cli/tools/procesio/dto/form/GOLDEN-DRIFT-NOTES.md +72 -0
  356. procesio_cli/tools/procesio/dto/form/RUN-PROCESS-RESULT-NOTES.md +80 -0
  357. procesio_cli/tools/procesio/dto/form/addelement.py +277 -0
  358. procesio_cli/tools/procesio/dto/form/builder.py +1009 -0
  359. procesio_cli/tools/procesio/dto/form/capture_goldens.py +106 -0
  360. procesio_cli/tools/procesio/dto/form/code_cipher.py +67 -0
  361. procesio_cli/tools/procesio/dto/form/config.schema.json +76 -0
  362. procesio_cli/tools/procesio/dto/form/data_shell.json +1 -0
  363. procesio_cli/tools/procesio/dto/form/description.md +346 -0
  364. procesio_cli/tools/procesio/dto/form/elements/approval.json +259 -0
  365. procesio_cli/tools/procesio/dto/form/elements/assignee.json +137 -0
  366. procesio_cli/tools/procesio/dto/form/elements/button.json +125 -0
  367. procesio_cli/tools/procesio/dto/form/elements/chart.json +341 -0
  368. procesio_cli/tools/procesio/dto/form/elements/chat.json +199 -0
  369. procesio_cli/tools/procesio/dto/form/elements/checkbox.json +153 -0
  370. procesio_cli/tools/procesio/dto/form/elements/column.json +77 -0
  371. procesio_cli/tools/procesio/dto/form/elements/columns.json +78 -0
  372. procesio_cli/tools/procesio/dto/form/elements/datetime-input.json +304 -0
  373. procesio_cli/tools/procesio/dto/form/elements/divider.json +54 -0
  374. procesio_cli/tools/procesio/dto/form/elements/dropdown.json +130 -0
  375. procesio_cli/tools/procesio/dto/form/elements/dynamic-table-row.json +253 -0
  376. procesio_cli/tools/procesio/dto/form/elements/file-upload.json +196 -0
  377. procesio_cli/tools/procesio/dto/form/elements/file-viewer.json +169 -0
  378. procesio_cli/tools/procesio/dto/form/elements/heading.json +79 -0
  379. procesio_cli/tools/procesio/dto/form/elements/icon.json +107 -0
  380. procesio_cli/tools/procesio/dto/form/elements/image.json +174 -0
  381. procesio_cli/tools/procesio/dto/form/elements/input.json +206 -0
  382. procesio_cli/tools/procesio/dto/form/elements/list.json +202 -0
  383. procesio_cli/tools/procesio/dto/form/elements/number-input.json +202 -0
  384. procesio_cli/tools/procesio/dto/form/elements/paragraph.json +79 -0
  385. procesio_cli/tools/procesio/dto/form/elements/radiobox.json +174 -0
  386. procesio_cli/tools/procesio/dto/form/elements/section.json +114 -0
  387. procesio_cli/tools/procesio/dto/form/elements/select.json +217 -0
  388. procesio_cli/tools/procesio/dto/form/elements/side-panel.json +146 -0
  389. procesio_cli/tools/procesio/dto/form/elements/signature-pad.json +141 -0
  390. procesio_cli/tools/procesio/dto/form/elements/static-table-row.json +84 -0
  391. procesio_cli/tools/procesio/dto/form/elements/step.json +105 -0
  392. procesio_cli/tools/procesio/dto/form/elements/stepper.json +126 -0
  393. procesio_cli/tools/procesio/dto/form/elements/tab.json +77 -0
  394. procesio_cli/tools/procesio/dto/form/elements/table.json +279 -0
  395. procesio_cli/tools/procesio/dto/form/elements/tabs.json +114 -0
  396. procesio_cli/tools/procesio/dto/form/elements/textarea.json +213 -0
  397. procesio_cli/tools/procesio/dto/form/enum_map.json +68 -0
  398. procesio_cli/tools/procesio/dto/form/fieldpath.py +284 -0
  399. procesio_cli/tools/procesio/dto/form/fixtures/reg.config.json +32 -0
  400. procesio_cli/tools/procesio/dto/form/fixtures/reg.elements.json +638 -0
  401. procesio_cli/tools/procesio/dto/form/sync_from_mock.py +386 -0
  402. procesio_cli/tools/procesio/dto/framework.py +125 -0
  403. procesio_cli/tools/procesio/dto/process/builder.py +1991 -0
  404. procesio_cli/tools/procesio/dto/process/config.schema.json +159 -0
  405. procesio_cli/tools/procesio/dto/process/description.md +218 -0
  406. procesio_cli/tools/procesio/dto/process/fixtures/greet.config.json +32 -0
  407. procesio_cli/tools/procesio/dto/process/fixtures/greet.dto.json +317 -0
  408. procesio_cli/tools/procesio/dto/process/naming.py +305 -0
  409. procesio_cli/tools/procesio/dto/process/normalize.py +74 -0
  410. procesio_cli/tools/procesio/dto/process/template.dto.json +32 -0
  411. procesio_cli/tools/procesio/dto/refdata.py +87 -0
  412. procesio_cli/tools/procesio/dto/registry.py +27 -0
  413. procesio_cli/tools/procesio/dto/webhook/builder.py +142 -0
  414. procesio_cli/tools/procesio/dto/webhook/config.schema.json +25 -0
  415. procesio_cli/tools/procesio/dto/webhook/description.md +92 -0
  416. procesio_cli/tools/procesio/dto/webhook/fixtures/order.config.json +10 -0
  417. procesio_cli/tools/procesio/dto/webhook/fixtures/order.dto.json +25 -0
  418. procesio_cli/tools/procesio/dto/webhook/template.dto.json +14 -0
  419. procesio_cli/tools/procesio/environments.py +264 -0
  420. procesio_cli/tools/procesio/errors.py +166 -0
  421. procesio_cli/tools/procesio/flowmodel/README.md +37 -0
  422. procesio_cli/tools/procesio/flowmodel/__init__.py +14 -0
  423. procesio_cli/tools/procesio/flowmodel/digest.py +223 -0
  424. procesio_cli/tools/procesio/flowmodel/families.py +34 -0
  425. procesio_cli/tools/procesio/flowmodel/fevalidation.py +1098 -0
  426. procesio_cli/tools/procesio/flowmodel/formdigest.py +232 -0
  427. procesio_cli/tools/procesio/flowmodel/inspect.py +78 -0
  428. procesio_cli/tools/procesio/flowmodel/model.py +82 -0
  429. procesio_cli/tools/procesio/flowmodel/nodeparam.py +871 -0
  430. procesio_cli/tools/procesio/flowmodel/reader.py +191 -0
  431. procesio_cli/tools/procesio/flowmodel/sqlparam.py +410 -0
  432. procesio_cli/tools/procesio/form_code_keys.py +50 -0
  433. procesio_cli/tools/procesio/formlint.py +292 -0
  434. procesio_cli/tools/procesio/gen_manifest.py +118 -0
  435. procesio_cli/tools/procesio/handlers/__init__.py +1 -0
  436. procesio_cli/tools/procesio/handlers/auth_actions.py +103 -0
  437. procesio_cli/tools/procesio/handlers/catalog.py +147 -0
  438. procesio_cli/tools/procesio/handlers/common.py +90 -0
  439. procesio_cli/tools/procesio/handlers/customaction_ops.py +146 -0
  440. procesio_cli/tools/procesio/handlers/datastore_ops.py +482 -0
  441. procesio_cli/tools/procesio/handlers/datatype_ops.py +275 -0
  442. procesio_cli/tools/procesio/handlers/dto_actions.py +258 -0
  443. procesio_cli/tools/procesio/handlers/environment_admin.py +146 -0
  444. procesio_cli/tools/procesio/handlers/fevalidate.py +236 -0
  445. procesio_cli/tools/procesio/handlers/files.py +141 -0
  446. procesio_cli/tools/procesio/handlers/flowgraph.py +229 -0
  447. procesio_cli/tools/procesio/handlers/flowlint.py +269 -0
  448. procesio_cli/tools/procesio/handlers/form_chains.py +336 -0
  449. procesio_cli/tools/procesio/handlers/form_code.py +277 -0
  450. procesio_cli/tools/procesio/handlers/form_element.py +199 -0
  451. procesio_cli/tools/procesio/handlers/form_events.py +441 -0
  452. procesio_cli/tools/procesio/handlers/form_update.py +270 -0
  453. procesio_cli/tools/procesio/handlers/formprocess.py +211 -0
  454. procesio_cli/tools/procesio/handlers/generic.py +135 -0
  455. procesio_cli/tools/procesio/handlers/layout.py +137 -0
  456. procesio_cli/tools/procesio/handlers/nodeparams.py +1018 -0
  457. procesio_cli/tools/procesio/handlers/process_layout.py +189 -0
  458. procesio_cli/tools/procesio/handlers/process_naming.py +213 -0
  459. procesio_cli/tools/procesio/handlers/processes.py +416 -0
  460. procesio_cli/tools/procesio/handlers/profile_admin.py +184 -0
  461. procesio_cli/tools/procesio/handlers/resource_ops.py +447 -0
  462. procesio_cli/tools/procesio/handlers/schedules.py +320 -0
  463. procesio_cli/tools/procesio/handlers/sqlactions.py +232 -0
  464. procesio_cli/tools/procesio/handlers/transport.py +463 -0
  465. procesio_cli/tools/procesio/handlers/usageguide.py +222 -0
  466. procesio_cli/tools/procesio/layout/README.md +196 -0
  467. procesio_cli/tools/procesio/layout/__init__.py +11 -0
  468. procesio_cli/tools/procesio/layout/adapter.py +736 -0
  469. procesio_cli/tools/procesio/layout/cycles.py +186 -0
  470. procesio_cli/tools/procesio/layout/dispatch.py +39 -0
  471. procesio_cli/tools/procesio/layout/elk/elk_runner.mjs +50 -0
  472. procesio_cli/tools/procesio/layout/elk/package-lock.json +21 -0
  473. procesio_cli/tools/procesio/layout/elk/package.json +11 -0
  474. procesio_cli/tools/procesio/layout/elk_engine.py +568 -0
  475. procesio_cli/tools/procesio/layout/engine.py +1311 -0
  476. procesio_cli/tools/procesio/layout/report.py +187 -0
  477. procesio_cli/tools/procesio/main.py +179 -0
  478. procesio_cli/tools/procesio/profiles.py +193 -0
  479. procesio_cli/tools/procesio/reliability.py +193 -0
  480. procesio_cli/tools/procesio/sqlformat.py +167 -0
  481. procesio_cli/tools/procesio/swagger.py +51 -0
  482. procesio_cli/tools/procesio/tests/__init__.py +0 -0
  483. procesio_cli/tools/procesio/tests/conftest.py +129 -0
  484. procesio_cli/tools/procesio/tests/test_auth.py +200 -0
  485. procesio_cli/tools/procesio/tests/test_autogen.py +78 -0
  486. procesio_cli/tools/procesio/tests/test_builder_attrpath_sqlbind.py +180 -0
  487. procesio_cli/tools/procesio/tests/test_builder_custom_action_catalog.py +72 -0
  488. procesio_cli/tools/procesio/tests/test_client.py +114 -0
  489. procesio_cli/tools/procesio/tests/test_client_reliability.py +139 -0
  490. procesio_cli/tools/procesio/tests/test_customaction.py +103 -0
  491. procesio_cli/tools/procesio/tests/test_customaction_test.py +80 -0
  492. procesio_cli/tools/procesio/tests/test_cycles.py +69 -0
  493. procesio_cli/tools/procesio/tests/test_datastore.py +378 -0
  494. procesio_cli/tools/procesio/tests/test_datastore_node.py +94 -0
  495. procesio_cli/tools/procesio/tests/test_dispatch.py +170 -0
  496. procesio_cli/tools/procesio/tests/test_document_page_size.py +19 -0
  497. procesio_cli/tools/procesio/tests/test_dto.py +734 -0
  498. procesio_cli/tools/procesio/tests/test_edit_dryrun_preview.py +96 -0
  499. procesio_cli/tools/procesio/tests/test_elk_layout.py +221 -0
  500. procesio_cli/tools/procesio/tests/test_environments.py +214 -0
  501. procesio_cli/tools/procesio/tests/test_fevalidate_gate.py +104 -0
  502. procesio_cli/tools/procesio/tests/test_fevalidation.py +317 -0
  503. procesio_cli/tools/procesio/tests/test_fieldpath_variables.py +87 -0
  504. procesio_cli/tools/procesio/tests/test_files.py +72 -0
  505. procesio_cli/tools/procesio/tests/test_flow_digest.py +202 -0
  506. procesio_cli/tools/procesio/tests/test_flowlint.py +114 -0
  507. procesio_cli/tools/procesio/tests/test_flowmodel.py +158 -0
  508. procesio_cli/tools/procesio/tests/test_form_add_element.py +256 -0
  509. procesio_cli/tools/procesio/tests/test_form_approval_gaps.py +319 -0
  510. procesio_cli/tools/procesio/tests/test_form_auto_names.py +60 -0
  511. procesio_cli/tools/procesio/tests/test_form_chains.py +217 -0
  512. procesio_cli/tools/procesio/tests/test_form_code_actions.py +188 -0
  513. procesio_cli/tools/procesio/tests/test_form_code_keys.py +92 -0
  514. procesio_cli/tools/procesio/tests/test_form_code_style.py +178 -0
  515. procesio_cli/tools/procesio/tests/test_form_delete_element.py +99 -0
  516. procesio_cli/tools/procesio/tests/test_form_element_config.py +141 -0
  517. procesio_cli/tools/procesio/tests/test_form_event_maps.py +135 -0
  518. procesio_cli/tools/procesio/tests/test_form_event_ops.py +376 -0
  519. procesio_cli/tools/procesio/tests/test_form_event_replace.py +86 -0
  520. procesio_cli/tools/procesio/tests/test_form_events.py +92 -0
  521. procesio_cli/tools/procesio/tests/test_form_parity.py +171 -0
  522. procesio_cli/tools/procesio/tests/test_form_select_source.py +74 -0
  523. procesio_cli/tools/procesio/tests/test_form_sync.py +35 -0
  524. procesio_cli/tools/procesio/tests/test_form_update.py +133 -0
  525. procesio_cli/tools/procesio/tests/test_formlint.py +155 -0
  526. procesio_cli/tools/procesio/tests/test_formlint_css_scope.py +38 -0
  527. procesio_cli/tools/procesio/tests/test_formlint_field_names.py +83 -0
  528. procesio_cli/tools/procesio/tests/test_guards.py +110 -0
  529. procesio_cli/tools/procesio/tests/test_hidden_setting_types.py +39 -0
  530. procesio_cli/tools/procesio/tests/test_html2docx_asset.py +132 -0
  531. procesio_cli/tools/procesio/tests/test_key_handle_terminology.py +45 -0
  532. procesio_cli/tools/procesio/tests/test_layout.py +574 -0
  533. procesio_cli/tools/procesio/tests/test_layout_report.py +88 -0
  534. procesio_cli/tools/procesio/tests/test_manifest_sync.py +68 -0
  535. procesio_cli/tools/procesio/tests/test_nodedelete.py +151 -0
  536. procesio_cli/tools/procesio/tests/test_nodeparam.py +826 -0
  537. procesio_cli/tools/procesio/tests/test_normalize.py +70 -0
  538. procesio_cli/tools/procesio/tests/test_payload_docs.py +86 -0
  539. procesio_cli/tools/procesio/tests/test_process_action_naming.py +170 -0
  540. procesio_cli/tools/procesio/tests/test_process_call_api_seed.py +46 -0
  541. procesio_cli/tools/procesio/tests/test_process_ext.py +373 -0
  542. procesio_cli/tools/procesio/tests/test_process_invariants.py +183 -0
  543. procesio_cli/tools/procesio/tests/test_process_layout.py +117 -0
  544. procesio_cli/tools/procesio/tests/test_process_naming.py +188 -0
  545. procesio_cli/tools/procesio/tests/test_process_query_store.py +172 -0
  546. procesio_cli/tools/procesio/tests/test_processinfo_variable.py +56 -0
  547. procesio_cli/tools/procesio/tests/test_profiles.py +127 -0
  548. procesio_cli/tools/procesio/tests/test_put_projects.py +41 -0
  549. procesio_cli/tools/procesio/tests/test_reliability.py +107 -0
  550. procesio_cli/tools/procesio/tests/test_removal_gate.py +95 -0
  551. procesio_cli/tools/procesio/tests/test_resource_ops.py +173 -0
  552. procesio_cli/tools/procesio/tests/test_save_validity.py +207 -0
  553. procesio_cli/tools/procesio/tests/test_schedule_cron_shape.py +111 -0
  554. procesio_cli/tools/procesio/tests/test_schedules.py +309 -0
  555. procesio_cli/tools/procesio/tests/test_sqlconvert.py +234 -0
  556. procesio_cli/tools/procesio/tests/test_sqlformat.py +83 -0
  557. procesio_cli/tools/procesio/tests/test_sqlparam.py +187 -0
  558. procesio_cli/tools/procesio/tests/test_superseded_actions.py +54 -0
  559. procesio_cli/tools/procesio/tests/test_surgical_concurrency.py +156 -0
  560. procesio_cli/tools/procesio/tests/test_tier4.py +123 -0
  561. procesio_cli/tools/procesio/tests/test_transport.py +147 -0
  562. procesio_cli/tools/procesio/tests/test_transport_data_stores.py +168 -0
  563. procesio_cli/tools/procesio/tests/test_transport_mapper_repair.py +150 -0
  564. procesio_cli/tools/procesio/tests/test_transport_webhook_strip.py +253 -0
  565. procesio_cli/tools/procesio/tests/test_usage_guide.py +96 -0
  566. procesio_cli/tools/procesio/tool.yaml +12486 -0
  567. procesio_cli/tools/sqlserver/MOVED-TO-CENTRAL.md +29 -0
  568. procesio_cli/tools/sqlserver/README.md +192 -0
  569. procesio_cli/tools/sqlserver/SKILL.md +37 -0
  570. procesio_cli/tools/sqlserver/SQLSERVER-SCHEMA-NOTES.md +284 -0
  571. procesio_cli/tools/sqlserver/__init__.py +0 -0
  572. procesio_cli/tools/sqlserver/connection.py +242 -0
  573. procesio_cli/tools/sqlserver/main.py +521 -0
  574. procesio_cli/tools/sqlserver/profiles.template.json +1 -0
  575. procesio_cli/tools/sqlserver/schema.py +600 -0
  576. procesio_cli/tools/sqlserver/tests/__init__.py +0 -0
  577. procesio_cli/tools/sqlserver/tests/conftest.py +21 -0
  578. procesio_cli/tools/sqlserver/tests/test_connection.py +75 -0
  579. procesio_cli/tools/sqlserver/tests/test_dbprofiles.py +92 -0
  580. procesio_cli/tools/sqlserver/tests/test_dbquery.py +220 -0
  581. procesio_cli/tools/sqlserver/tests/test_manifest_sync.py +68 -0
  582. procesio_cli/tools/sqlserver/tests/test_sqlserver.py +326 -0
  583. procesio_cli/tools/sqlserver/tests/test_sqlserver_schema.py +488 -0
  584. procesio_cli/tools/sqlserver/tool.yaml +123 -0
  585. procesio_cli/tools/web/README.md +381 -0
  586. procesio_cli/tools/web/SKILL.md +37 -0
  587. procesio_cli/tools/web/WEB-AUTOMATION-NOTES.md +277 -0
  588. procesio_cli/tools/web/__init__.py +21 -0
  589. procesio_cli/tools/web/actiondef.py +24 -0
  590. procesio_cli/tools/web/api.py +444 -0
  591. procesio_cli/tools/web/brokered.py +107 -0
  592. procesio_cli/tools/web/driver.py +839 -0
  593. procesio_cli/tools/web/drivercontract.py +44 -0
  594. procesio_cli/tools/web/errors.py +54 -0
  595. procesio_cli/tools/web/handlers/__init__.py +1 -0
  596. procesio_cli/tools/web/handlers/archive.py +367 -0
  597. procesio_cli/tools/web/handlers/browse.py +182 -0
  598. procesio_cli/tools/web/handlers/contacts.py +74 -0
  599. procesio_cli/tools/web/handlers/sessmgmt.py +120 -0
  600. procesio_cli/tools/web/main.py +128 -0
  601. procesio_cli/tools/web/sessions.py +253 -0
  602. procesio_cli/tools/web/steps.py +162 -0
  603. procesio_cli/tools/web/tests/__init__.py +0 -0
  604. procesio_cli/tools/web/tests/conftest.py +197 -0
  605. procesio_cli/tools/web/tests/test_api.py +330 -0
  606. procesio_cli/tools/web/tests/test_archive.py +190 -0
  607. procesio_cli/tools/web/tests/test_brokered.py +138 -0
  608. procesio_cli/tools/web/tests/test_dispatch.py +132 -0
  609. procesio_cli/tools/web/tests/test_errors.py +60 -0
  610. procesio_cli/tools/web/tests/test_manifest_sync.py +76 -0
  611. procesio_cli/tools/web/tests/test_page_contacts.py +68 -0
  612. procesio_cli/tools/web/tests/test_sessions.py +145 -0
  613. procesio_cli/tools/web/tests/test_steps.py +210 -0
  614. procesio_cli/tools/web/tool.yaml +184 -0
  615. procesio_cli/tools/xlsx/README.md +34 -0
  616. procesio_cli/tools/xlsx/SKILL.md +28 -0
  617. procesio_cli/tools/xlsx/__init__.py +0 -0
  618. procesio_cli/tools/xlsx/main.py +129 -0
  619. procesio_cli/tools/xlsx/reader.py +91 -0
  620. procesio_cli/tools/xlsx/tests/__init__.py +0 -0
  621. procesio_cli/tools/xlsx/tests/conftest.py +39 -0
  622. procesio_cli/tools/xlsx/tests/test_xlsx.py +103 -0
  623. procesio_cli/tools/xlsx/tool.yaml +30 -0
  624. procesio_cli/webplatform/aat_mcp/AAT-MCP-NOTES.md +244 -0
  625. procesio_cli/webplatform/aat_mcp/README.md +78 -0
  626. procesio_cli/webplatform/aat_mcp/bridge.py +705 -0
  627. procesio_cli/webplatform/aat_mcp/chat_server.py +194 -0
  628. procesio_cli/webplatform/aat_mcp/chat_surface.snapshot.json +668 -0
  629. procesio_cli/webplatform/aat_mcp/chat_surface.yaml +372 -0
  630. procesio_cli/webplatform/aat_mcp/gate.py +68 -0
  631. procesio_cli/webplatform/aat_mcp/http_server.py +139 -0
  632. procesio_cli/webplatform/aat_mcp/protocol.py +175 -0
  633. procesio_cli/webplatform/aat_mcp/server.py +306 -0
  634. procesio_cli/webplatform/aat_mcp/tests/conftest.py +8 -0
  635. procesio_cli/webplatform/aat_mcp/tests/test_aat_mcp.py +255 -0
  636. procesio_cli/webplatform/aat_mcp/tests/test_chat_surface.py +247 -0
  637. procesio_cli/webplatform/aat_mcp/tests/test_discovery.py +489 -0
  638. procesio_cli/webplatform/aat_mcp/tests/test_multiuser.py +86 -0
  639. procesio_cli/webplatform/aat_mcp/tests/test_progressive_discovery.py +89 -0
  640. procesio_cli/webplatform/aat_mcp/tests/test_protocol.py +180 -0
  641. procesio_cli/webplatform/aat_mcp/tests/test_skill_discovery.py +23 -0
  642. procesio_cli-0.1.1.dist-info/METADATA +467 -0
  643. procesio_cli-0.1.1.dist-info/RECORD +647 -0
  644. procesio_cli-0.1.1.dist-info/WHEEL +4 -0
  645. procesio_cli-0.1.1.dist-info/entry_points.txt +7 -0
  646. procesio_cli-0.1.1.dist-info/licenses/LICENSE +201 -0
  647. procesio_cli-0.1.1.dist-info/licenses/NOTICE +5 -0
@@ -0,0 +1,191 @@
1
+ """Parse a PROCESIO flow (export or live DTO) into a `FlowGraph`.
2
+
3
+ Pure + offline + case-insensitive: exports are PascalCase (`Actions`, `Ports`,
4
+ `CustomData`), the live Web-API is camelCase (`actions`, `ports`, `customData`). Same
5
+ DTOs, different case — so every field access goes through `_g` (case-insensitive get).
6
+ Never mutates the input.
7
+
8
+ The model it produces is documented in tools/procesio/PROCESIO-RESOURCE-MODEL-NOTES.md §1.
9
+ """
10
+ from __future__ import annotations
11
+
12
+ import json
13
+ from typing import Any
14
+
15
+ from tools.procesio.flowmodel.model import (
16
+ Container, Edge, FlowGraph, Node, SubprocessCall, VarRef,
17
+ )
18
+
19
+
20
+ def _g(obj: Any, *names: str, default=None):
21
+ """Case-insensitive get: try each name, matched against lowercased keys."""
22
+ if not isinstance(obj, dict):
23
+ return default
24
+ low = {str(k).lower(): v for k, v in obj.items()}
25
+ for n in names:
26
+ if n.lower() in low:
27
+ return low[n.lower()]
28
+ return default
29
+
30
+
31
+ def _is_bundle(obj: dict) -> bool:
32
+ return _g(obj, "Flows") is not None and _g(obj, "Actions") is None
33
+
34
+
35
+ def _walk_settings(custom_data: dict):
36
+ """Yield every setting dict in an action's CustomData.configuration, recursing into
37
+ side-panel settings whose `value` is itself a list of settings."""
38
+ for tab in _g(custom_data, "configuration", default=[]) or []:
39
+ for s in _g(tab, "settings", default=[]) or []:
40
+ if isinstance(s, dict):
41
+ yield s
42
+ val = _g(s, "value")
43
+ if isinstance(val, list):
44
+ for sub in val:
45
+ if isinstance(sub, dict) and (_g(sub, "label") or _g(sub, "type")):
46
+ yield sub
47
+
48
+
49
+ def _template_name(action: dict) -> str | None:
50
+ return _g(action, "ActionTemplateName", "actionTemplateName") \
51
+ or _g(action, "ActionName", "actionName")
52
+
53
+
54
+ def _read_flow(flow: dict) -> FlowGraph:
55
+ flow_id = _g(flow, "Id")
56
+ fg = FlowGraph(flow_id=flow_id, title=_g(flow, "Title", "Name"))
57
+
58
+ actions = _g(flow, "Actions", default=[]) or []
59
+ area_ids: dict[str, dict] = {} # area node id -> its CustomData
60
+ for a in actions:
61
+ cd = _g(a, "CustomData", default={}) or {}
62
+ aid = _g(a, "Id")
63
+ tmpl = _template_name(a)
64
+ shape = _g(cd, "type")
65
+ pos = _g(cd, "position", default={}) or {}
66
+ asz = _g(cd, "areaSize", default={}) or {}
67
+ node = Node(
68
+ id=aid, template=tmpl, shape=shape, icon=_g(cd, "icon"),
69
+ position={"x": _g(pos, "x", default=0), "y": _g(pos, "y", default=0)},
70
+ size={"w": _g(asz, "width", default=48), "h": _g(asz, "height", default=48)},
71
+ parent_id=_g(a, "ParentId"),
72
+ input_ports=_g(cd, "inputPorts"), output_ports=_g(cd, "outputPorts"),
73
+ disabled=bool(_g(a, "IsDisabled", default=False)),
74
+ )
75
+ fg.nodes.append(node)
76
+ if shape == "area":
77
+ area_ids[aid] = cd
78
+ if tmpl == "Start":
79
+ fg.start_id = aid
80
+ elif tmpl == "Stop":
81
+ fg.stop_ids.append(aid)
82
+
83
+ # edges (stored on the source action)
84
+ for p in _g(a, "Ports", default=[]) or []:
85
+ src = _g(p, "SourceId")
86
+ dst = _g(p, "DestinationId")
87
+ if src and dst:
88
+ pdata = _g(p, "Data", default={}) or {}
89
+ fg.edges.append(Edge(
90
+ source=src, dest=dst, type=int(_g(p, "Type", default=0) or 0),
91
+ is_default=(_g(pdata, "isDefault") == "default")))
92
+
93
+ # subprocess + credential references via the action's settings
94
+ if tmpl in ("Call Subprocess", "Trigger Subprocess"):
95
+ target = None
96
+ for s in _walk_settings(cd):
97
+ if _g(s, "type") == "flow-list":
98
+ target = _g(s, "value")
99
+ break
100
+ fg.subprocess_calls.append(SubprocessCall(
101
+ action_id=aid, target_flow_id=target,
102
+ kind="call" if tmpl == "Call Subprocess" else "trigger"))
103
+ for s in _walk_settings(cd):
104
+ if _g(s, "type") == "credentials":
105
+ gid = _g(s, "value")
106
+ if gid and gid not in fg.resources["credentials"]:
107
+ fg.resources["credentials"].append(gid)
108
+
109
+ # containers: For-Each areas with their parented children
110
+ children_by_parent: dict[str, list[str]] = {}
111
+ for n in fg.nodes:
112
+ if n.parent_id:
113
+ children_by_parent.setdefault(n.parent_id, []).append(n.id)
114
+ for aid, cd in area_ids.items():
115
+ is_foreach = (_g(cd, "name") == "For Each")
116
+ fg.containers.append(Container(
117
+ id=aid, kind="foreach" if is_foreach else "area",
118
+ children=sorted(children_by_parent.get(aid, [])),
119
+ size={"w": _g(_g(cd, "areaSize", default={}) or {}, "width", default=0),
120
+ "h": _g(_g(cd, "areaSize", default={}) or {}, "height", default=0)}))
121
+
122
+ # variables (the flow's contract)
123
+ for v in _g(flow, "Variables", default=[]) or []:
124
+ fg.variables.append(VarRef(
125
+ id=_g(v, "Id"), name=_g(v, "Name"), type=_g(v, "Type"),
126
+ data_type=_g(v, "DataType"),
127
+ is_list=bool(_g(v, "IsList", default=False)),
128
+ is_required=bool(_g(v, "IsRequired", default=False)),
129
+ is_error=bool(_g(v, "IsError", default=False))))
130
+
131
+ # webhooks embedded on the flow
132
+ for w in _g(flow, "Webhooks", default=[]) or []:
133
+ wid = _g(w, "WebhookId", "Id")
134
+ if wid:
135
+ fg.resources["webhooks"].append(wid)
136
+
137
+ # deterministic ordering
138
+ fg.nodes.sort(key=lambda n: n.id or "")
139
+ fg.edges.sort(key=lambda e: (e.source or "", e.dest or "", e.type))
140
+ fg.containers.sort(key=lambda c: c.id or "")
141
+ fg.subprocess_calls.sort(key=lambda s: s.action_id or "")
142
+ return fg
143
+
144
+
145
+ def _coerce(source) -> dict:
146
+ if isinstance(source, dict):
147
+ return source
148
+ if isinstance(source, str):
149
+ return json.loads(source)
150
+ raise TypeError(f"unsupported source type: {type(source).__name__}")
151
+
152
+
153
+ def read_flow(source, flow_id: str | None = None) -> FlowGraph:
154
+ """Read one flow into a FlowGraph. `source` may be a flow dict, a bundle dict, or a
155
+ JSON string of either. `flow_id` is required only to disambiguate a multi-flow bundle.
156
+ """
157
+ obj = _coerce(source)
158
+ if _is_bundle(obj):
159
+ flows = _g(obj, "Flows", default=[]) or []
160
+ if not flows:
161
+ raise ValueError("bundle has no flows")
162
+ if flow_id:
163
+ match = next((f for f in flows if _g(f, "Id") == flow_id), None)
164
+ if match is None:
165
+ raise ValueError(f"flow_id {flow_id} not found in bundle")
166
+ return _read_flow(match)
167
+ if len(flows) > 1:
168
+ ids = [_g(f, "Id") for f in flows]
169
+ raise ValueError(f"bundle has {len(flows)} flows; pass flow_id (one of {ids[:8]}…)")
170
+ return _read_flow(flows[0])
171
+ return _read_flow(obj)
172
+
173
+
174
+ def read_bundle(source) -> dict:
175
+ """Read every flow in a bundle plus the cross-process (process→process) edge list.
176
+
177
+ Returns {"flows": {flow_id: FlowGraph.to_dict()}, "process_edges": [...]}.
178
+ """
179
+ obj = _coerce(source)
180
+ flows = _g(obj, "Flows", default=[]) or ([obj] if _g(obj, "Actions") is not None else [])
181
+ graphs: dict[str, FlowGraph] = {}
182
+ for f in flows:
183
+ fg = _read_flow(f)
184
+ graphs[fg.flow_id] = fg
185
+ process_edges = []
186
+ for fid, fg in graphs.items():
187
+ for sc in fg.subprocess_calls:
188
+ if sc.target_flow_id:
189
+ process_edges.append({"source": fid, "target": sc.target_flow_id, "kind": sc.kind})
190
+ process_edges.sort(key=lambda e: (e["source"] or "", e["target"] or "", e["kind"]))
191
+ return {"flows": {k: v.to_dict() for k, v in graphs.items()}, "process_edges": process_edges}
@@ -0,0 +1,410 @@
1
+ """Parameterize PROCESIO SQL Server actions.
2
+
3
+ The SAFE way to pass flow-variable values into an `Execute Query` / `Execute Command` action is
4
+ NAMED SQL parameters (`@name`) bound via the action's `Parameters config tab` (a `map-parameters`
5
+ setting) — values then travel as typed, driver-escaped SQL parameters. The UNSAFE way (and the wrong
6
+ action config) is to string-interpolate the value into the SQL text as `N'<%N%>'`; that is
7
+ SQL-injection-prone, especially where the value is user text (a contact name, a message, OCR).
8
+
9
+ This module detects inline-`<%N%>` SQL nodes and converts them to the parameterized form. It also
10
+ migrates the deprecated `Execute Query V2` template (inline-only) to `Execute Query` (which carries the
11
+ `Parameters config tab`). Pure: it mutates a raw flow DTO dict in place; callers fetch/validate/put.
12
+
13
+ See tools/procesio/PROCESIO-SQL-ACTIONS-NOTES.md for the full DTO shape and property ids.
14
+ """
15
+ from __future__ import annotations
16
+
17
+ import copy
18
+ import re
19
+
20
+ # 'Execute Query' template property ids (verified live 2026-07-03 on Chat Flow/Resolve Contact).
21
+ EQ_TEMPLATE = "Execute Query"
22
+ EQ_TEMPLATE_ID = "76470756-6dbd-4ab2-a4bf-88b47ed381ba"
23
+ # The deprecated 'Execute Query V2' template. CRUCIAL: the designer renders the action TYPE from the
24
+ # templateId, and the build put many SQL nodes on this template while LABELLING them "Execute Query".
25
+ # The map-parameters binding does NOT exist on V2, so a node must be migrated to EQ_TEMPLATE_ID (which
26
+ # the migration does) or the @params are unbound at runtime. Key it on templateId, never the label.
27
+ PID_CRED = "f96ff811-572f-084a-8cac-a74a2c2e365f" # 'Select Database Server' (credentials)
28
+ PID_SIDEPANEL = "8add0f17-b2b1-4d5f-962b-c5d400a4e2d4" # 'Execute Query' (side-pannel container)
29
+ PID_QUERY = "11350a1d-4139-d942-adcb-a2c2c52e5e22" # 'Query' (code-editor, sql)
30
+ PID_BIND = "73416282-bcfe-4934-9e40-a39f2bb33d2d" # 'Parameters config tab' (map-parameters)
31
+ PID_TIMEOUT = "9ce93b2d-5226-4228-a64d-3693c8d3e0e3" # 'Time Out' (number)
32
+ PID_OUTPUT = "8aa02e91-1a1e-a44a-b09b-6965d67da04d" # 'Output' (any)
33
+
34
+ # 'Execute Command' is a SECOND family with its OWN property ids - notably its own
35
+ # 'Parameters config tab' (0acb249e...), NOT the Execute Query one. Writing the Query binding id onto a
36
+ # Command node leaves every @param unbound at runtime with nothing to show for it, so the bind id must
37
+ # always be looked up per family (verified live 2026-08-22 against GET /api/Actions?getFullAction=true).
38
+ EC_TEMPLATE = "Execute Command"
39
+ EC_TEMPLATE_ID = "a1625da6-c093-4695-a97c-3c3d9a9b0cae"
40
+ EC_PID_CRED = "5f75a4fd-d0f5-4ac1-8257-467e50e7292e" # 'Select Database Server' (credentials)
41
+ EC_PID_SIDEPANEL = "975f25dc-1044-4488-b635-10a2039f8d89"
42
+ EC_PID_COMMAND = "824575f6-7652-4bc2-8186-63b32c92cc22" # 'Command' (code-editor, sql)
43
+ EC_PID_BIND = "0acb249e-8b21-4bfd-946c-1e65e26baa68" # 'Parameters config tab' (map-parameters)
44
+ EC_PID_TIMEOUT = "2be309c6-9144-4b27-a722-fbc9c89735c2" # 'Time Out' (number, required, 60..1800)
45
+ EC_PID_OUTPUT = "e6ffaa2d-2c32-412d-a9d4-b1038ece9d38" # 'Output' (number, required)
46
+
47
+ # role -> property id, per CURRENT template. `timeout_default` fills a required Time Out that a
48
+ # migrated legacy node never had, so the migration cannot leave the designer with an empty required field.
49
+ _CURRENT = {
50
+ EQ_TEMPLATE: {"templateId": EQ_TEMPLATE_ID, "cred": PID_CRED, "sidepanel": PID_SIDEPANEL,
51
+ "sql": PID_QUERY, "bind": PID_BIND, "timeout": PID_TIMEOUT, "output": PID_OUTPUT,
52
+ "timeout_default": None, "output_type": "any",
53
+ "description": "Execute a custom SQL Query on the target database.",
54
+ "labels": {PID_CRED: "Select Database Server", PID_SIDEPANEL: "Execute Query",
55
+ PID_QUERY: "Query", PID_TIMEOUT: "Time Out", PID_OUTPUT: "Output"}},
56
+ EC_TEMPLATE: {"templateId": EC_TEMPLATE_ID, "cred": EC_PID_CRED, "sidepanel": EC_PID_SIDEPANEL,
57
+ "sql": EC_PID_COMMAND, "bind": EC_PID_BIND, "timeout": EC_PID_TIMEOUT,
58
+ "output": EC_PID_OUTPUT, "timeout_default": "300", "output_type": "number",
59
+ "description": "Execute a custom SQL Command on the target database.",
60
+ "labels": {EC_PID_CRED: "Select Database Server", EC_PID_SIDEPANEL: "Execute Command",
61
+ EC_PID_COMMAND: "Command", EC_PID_TIMEOUT: "Time Out",
62
+ EC_PID_OUTPUT: "Output"}},
63
+ }
64
+
65
+ # The property roles a family remap has to move. Order is irrelevant; completeness is not — a role
66
+ # left behind keeps the OLD template's property id on the node, which the designer then ignores.
67
+ _ROLE_KEYS = ("cred", "sidepanel", "sql", "bind", "timeout", "output")
68
+
69
+ # DEPRECATED templateId -> (family, {role: that template's property id}). Every one of these is
70
+ # inline-only (no map-parameters), so a node on one MUST be migrated before it can bind @params.
71
+ # Key on templateId, never the label: nodes on a legacy template are routinely LABELLED with the
72
+ # current template's name (all four collectors in one live workspace were, 2026-08-22).
73
+ _LEGACY = {
74
+ "a9f851c2-e0ba-4fee-9a06-5445ba000001": (EQ_TEMPLATE, { # Execute Query V2
75
+ "cred": "a9f851c2-e0ba-4fee-9a06-5445bc000011",
76
+ "sidepanel": "a9f851c2-e0ba-4fee-9a06-5445bc000012",
77
+ "output": "a9f851c2-e0ba-4fee-9a06-5445bc000013",
78
+ "sql": "a9f851c2-e0ba-4fee-9a06-5445bc000014",
79
+ "timeout": "a9f851c2-e0ba-4fee-9a06-5445bc000015"}),
80
+ "574a2ab1-4d24-4d6c-9483-f61597a6d5ff": (EQ_TEMPLATE, { # Execute Query V1
81
+ "cred": "a9d217b3-6a3c-44c5-81ff-581c860fb560",
82
+ "sidepanel": "0b5bedd7-cd08-49f3-ba70-9d24aa7239ef",
83
+ "output": "459b4db8-25f1-4903-9be8-3239312e93e6",
84
+ "sql": "487bcfdb-67fd-49c0-bf02-0fb614dbb800"}),
85
+ "c2760ff2-cd9e-49b4-b751-c05c88e06dac": (EC_TEMPLATE, { # Execute Command V1
86
+ "cred": "6701cb8b-3bde-4c7e-a45d-c37eaeff5e3d",
87
+ "sidepanel": "fea72099-4718-473d-a091-7749aa38305b",
88
+ "sql": "53896b0d-73a6-412f-9e67-224ca1daae7c",
89
+ "timeout": "f3452b3a-2c10-40df-9d34-2d2779dc6ed6",
90
+ "output": "f3452b3a-2c10-40df-9d34-2d2779dc6ed7"}),
91
+ }
92
+
93
+
94
+ def family_of(node: dict) -> tuple[str, dict | None]:
95
+ """(current-family name, legacy role map or None) for a SQL node, keyed on templateId.
96
+
97
+ Falls back to the label only when the templateId is unknown - a node built against a template
98
+ this table has not seen yet still parameterizes, it just does not migrate.
99
+ """
100
+ tid = str(node.get("templateId") or "")
101
+ if tid in _LEGACY:
102
+ return _LEGACY[tid]
103
+ for fam, spec in _CURRENT.items():
104
+ if tid == spec["templateId"]:
105
+ return fam, None
106
+ label = node.get("actionTemplateName") or ""
107
+ return (EC_TEMPLATE if EC_TEMPLATE in label else EQ_TEMPLATE), None
108
+
109
+
110
+ def bind_pid(node: dict) -> str:
111
+ """The 'Parameters config tab' property id for THIS node's family."""
112
+ return _CURRENT[family_of(node)[0]]["bind"]
113
+
114
+ _SQL_KW = re.compile(r"\b(EXEC|SELECT|UPDATE|INSERT|DELETE|MERGE|DECLARE)\b", re.I)
115
+ _PLACEHOLDER = re.compile(r"<%(\d+)%>")
116
+ _SQL_TEMPLATES = ("Execute Query", "Execute Command") # includes 'Execute Query V2'
117
+
118
+
119
+ def is_sql_node(node: dict) -> bool:
120
+ t = node.get("actionTemplateName", "") or ""
121
+ return any(k in t for k in _SQL_TEMPLATES)
122
+
123
+
124
+ def _query_param(node: dict):
125
+ """the parameters[] entry whose value is the SQL text still holding inline <%N%>."""
126
+ for p in node.get("parameters") or []:
127
+ v = p.get("value")
128
+ if isinstance(v, str) and _PLACEHOLDER.search(v) and _SQL_KW.search(v):
129
+ return p
130
+ return None
131
+
132
+
133
+ def _query_setting(node: dict):
134
+ """(container-setting, query-sub-setting) inside the side-pannel; the designer copy of the SQL."""
135
+ for c in (node.get("customData") or {}).get("configuration") or []:
136
+ for s in c.get("settings") or []:
137
+ if isinstance(s.get("value"), list):
138
+ for sub in s["value"]:
139
+ if isinstance(sub, dict) and str(sub.get("label", "")).lower() in ("query", "command"):
140
+ return s, sub
141
+ return None, None
142
+
143
+
144
+ def is_inline(node: dict) -> bool:
145
+ """True if this SQL node string-interpolates a value as N'<%N%>' (the injectable anti-pattern)."""
146
+ qp = _query_param(node)
147
+ if not qp:
148
+ return False
149
+ return bool(re.search(r"N?'<%\d+%>'", qp["value"]))
150
+
151
+
152
+ def scan(flow: dict) -> list[dict]:
153
+ """List every SQL action in a flow with its inline/parameterized status."""
154
+ out = []
155
+ for a in flow.get("actions") or []:
156
+ if is_sql_node(a):
157
+ out.append({"actionName": a.get("actionName"), "id": a.get("id"),
158
+ "template": a.get("actionTemplateName"), "inline": is_inline(a)})
159
+ return out
160
+
161
+
162
+ def find_node(flow: dict, key: str):
163
+ for a in flow.get("actions") or []:
164
+ if a.get("id") == key or a.get("actionName") == key:
165
+ return a
166
+ return None
167
+
168
+
169
+ def _designate_source(ve: dict) -> str:
170
+ return ve["variableId"] + ("." + ve["attribute"]["attributeId"] if ve.get("attribute") else "")
171
+
172
+
173
+ def parameterize_node(node: dict) -> tuple[bool, str]:
174
+ """Convert one inline-<%N%> SQL node to the parameterized form, in place.
175
+
176
+ Rewrites each `N'<%K%>'` (and the un-quoted forms) to `@pK`, moves the placeholder->variable map
177
+ into a `Parameters config tab` (map-parameters) binding, and — for a deprecated `Execute Query V2`
178
+ node — swaps the template to `Execute Query`. Literals stay inline. Returns (changed, message).
179
+ """
180
+ if not is_sql_node(node):
181
+ return False, "not a SQL Server action (Execute Query / Execute Command)"
182
+ qp = _query_param(node)
183
+ if not qp:
184
+ return False, "already parameterized or no inline <%N%> in the SQL"
185
+ sql = qp["value"]
186
+ varmap = {v["id"]: v for v in (qp.get("variable") or [])}
187
+ idxs = sorted(set(int(m) for m in _PLACEHOLDER.findall(sql)) & set(varmap))
188
+ if not idxs:
189
+ return False, "no bound <%N%> placeholders to parameterize"
190
+
191
+ new_sql = sql
192
+ runtime, designer = [], []
193
+ for k in idxs:
194
+ for form in ("N'<%%%d%%>'" % k, "'<%%%d%%>'" % k, "<%%%d%%>" % k):
195
+ new_sql = new_sql.replace(form, "@p%d" % k)
196
+ ve = varmap[k]
197
+ runtime.append({"id": k,
198
+ "source": {"value": "<%%%d%%>" % k, "variable": [copy.deepcopy(ve)]},
199
+ "destination": {"value": "p%d" % k, "variable": []}})
200
+ designer.append({"id": k, "destination": "p%d" % k, "source": _designate_source(ve)})
201
+
202
+ # Migrate a node on a DEPRECATED template to its family's current one first (role-based id remap):
203
+ # every legacy template is inline-only, so without this the @params have no property to bind to.
204
+ fam, legacy = family_of(node)
205
+ if legacy:
206
+ _migrate_to_current(node, qp, fam, legacy)
207
+ pid_bind = _CURRENT[fam]["bind"]
208
+
209
+ # -- runtime form (what the engine executes) --
210
+ qp["value"] = new_sql
211
+ qp.pop("variable", None)
212
+ params = node.setdefault("parameters", [])
213
+ bp = next((p for p in params if p.get("tabPropertyId") == pid_bind), None)
214
+ if bp:
215
+ bp["value"] = runtime
216
+ else:
217
+ params.append({"tabPropertyId": pid_bind, "value": runtime})
218
+
219
+ # -- designer copy (customData side-pannel) --
220
+ setting, qsub = _query_setting(node)
221
+ if qsub is not None:
222
+ qsub["value"] = new_sql
223
+ lst = setting["value"]
224
+ existing = next((s for s in lst if isinstance(s, dict) and s.get("id") == pid_bind), None)
225
+ if existing:
226
+ existing["value"] = designer
227
+ else:
228
+ lst.insert(1, {"id": pid_bind, "dataTypeId": None, "label": "Parameters config tab",
229
+ "type": "map-parameters", "value": designer})
230
+ return True, "parameterized %d value(s): %s" % (len(idxs), ", ".join("@p%d" % k for k in idxs))
231
+
232
+
233
+ def _roles_of(family: str) -> dict:
234
+ """{role: property id} for a CURRENT template, in the shape _migrate_to_current consumes."""
235
+ spec = _CURRENT[family]
236
+ return {role: spec[role] for role in _ROLE_KEYS if spec.get(role)}
237
+
238
+
239
+ def _output_settings(node: dict, pid: str):
240
+ """Every designer setting carrying the Output property, at either nesting level."""
241
+ for cfg in (node.get("customData") or {}).get("configuration") or []:
242
+ for setting in cfg.get("settings") or []:
243
+ if setting.get("id") == pid:
244
+ yield setting
245
+ if isinstance(setting.get("value"), list):
246
+ for sub in setting["value"]:
247
+ if isinstance(sub, dict) and sub.get("id") == pid:
248
+ yield sub
249
+
250
+
251
+ def convert_family(node: dict, target: str) -> tuple[bool, str]:
252
+ """Move a SQL node between the Execute Command and Execute Query families, in place.
253
+
254
+ `Execute Query` carries a RESULT SET back into a flow variable; `Execute Command` carries
255
+ rows-affected (its Output property is typed `number`). So a Command node pointed at a procedure
256
+ that ends in SELECT throws away everything the procedure returns and still reports success —
257
+ there is no error to see, the output variable is simply a count. Converting the family is the
258
+ only fix, and it is a role-based property-id remap in both the runtime `parameters[]` and the
259
+ designer `customData`, plus the Output setting's type and the labels a later reader will trust.
260
+
261
+ The SQL text, credential, timeout and `@param` binding are carried across untouched. A node on a
262
+ deprecated template is refused rather than half-converted: run `sql-parameterize` first, which
263
+ migrates it onto its family's current template. Returns (changed, message).
264
+ """
265
+ if target not in _CURRENT:
266
+ raise ValueError("unknown SQL action family: %s (expected %r or %r)"
267
+ % (target, EQ_TEMPLATE, EC_TEMPLATE))
268
+ if not is_sql_node(node):
269
+ return False, "not a SQL Server action (Execute Query / Execute Command)"
270
+
271
+ source, legacy = family_of(node)
272
+ if legacy:
273
+ return False, ("node is on a deprecated template (%s) - run sql-parameterize first to "
274
+ "migrate it onto its family's current template" % node.get("templateId"))
275
+ if source == target:
276
+ return False, "already %s" % target
277
+
278
+ src_sql_pid = _CURRENT[source]["sql"]
279
+ sql_param = next((p for p in node.get("parameters") or []
280
+ if p.get("tabPropertyId") == src_sql_pid), None)
281
+ if sql_param is None:
282
+ return False, "no SQL parameter (%s) found on the node" % src_sql_pid
283
+
284
+ cur = _CURRENT[target]
285
+ _migrate_to_current(node, sql_param, target, _roles_of(source))
286
+
287
+ # customData carries three things the role remap does not reach, and each one is what the next
288
+ # reader (or the designer) uses to decide what this node IS.
289
+ custom = node.get("customData") or {}
290
+ if isinstance(custom.get("description"), str):
291
+ custom["description"] = cur["description"]
292
+ for cfg in custom.get("configuration") or []:
293
+ if cfg.get("label") == source:
294
+ cfg["label"] = target
295
+ for setting in _output_settings(node, cur["output"]):
296
+ setting["type"] = cur["output_type"]
297
+
298
+ return True, "converted %s -> %s" % (source, target)
299
+
300
+
301
+ def rebind_output(node: dict, variable_id: str) -> tuple[bool, str]:
302
+ """Point a SQL node's Output at a different flow variable, in both layers, in place.
303
+
304
+ The runtime layer holds a positional `<%N%>` slot plus the variable id; the designer layer holds
305
+ the bare variable id. A node whose Output was never bound gets a fresh slot placed past every
306
+ `@param` bind index, because the engine resolves those slots positionally and a collision hands
307
+ the query the wrong value. Returns (changed, message).
308
+ """
309
+ family, legacy = family_of(node)
310
+ if legacy:
311
+ return False, ("node is on a deprecated template (%s) - run sql-parameterize first"
312
+ % node.get("templateId"))
313
+ pid = _CURRENT[family]["output"]
314
+
315
+ param = next((p for p in node.get("parameters") or [] if p.get("tabPropertyId") == pid), None)
316
+ if param is None:
317
+ return False, "no Output parameter (%s) found on the node" % pid
318
+
319
+ bound = param.get("variable") or []
320
+ if bound and bound[0].get("variableId") == variable_id:
321
+ return False, "Output is already bound to %s" % variable_id
322
+
323
+ if bound:
324
+ bound[0]["variableId"] = variable_id
325
+ bound[0]["attribute"] = None
326
+ else:
327
+ slot = _next_slot(node)
328
+ param["variable"] = [{"id": slot, "variableId": variable_id, "attribute": None}]
329
+ param["value"] = "<%%%d%%>" % slot
330
+
331
+ for setting in _output_settings(node, pid):
332
+ setting["value"] = variable_id
333
+
334
+ return True, "Output rebound to %s" % variable_id
335
+
336
+
337
+ def _next_slot(node: dict) -> int:
338
+ """The first positional `<%N%>` index no parameter on this node already claims."""
339
+ used = {-1}
340
+ for prm in node.get("parameters") or []:
341
+ for ve in prm.get("variable") or []:
342
+ if isinstance(ve.get("id"), int):
343
+ used.add(ve["id"])
344
+ value = prm.get("value")
345
+ if isinstance(value, str):
346
+ used.update(int(m) for m in _PLACEHOLDER.findall(value))
347
+ elif isinstance(value, list):
348
+ for row in value:
349
+ if isinstance(row, dict) and isinstance(row.get("id"), int):
350
+ used.add(row["id"])
351
+ return max(used) + 1
352
+
353
+
354
+ def _migrate_to_current(node: dict, query_param: dict, family: str, legacy: dict) -> None:
355
+ """Move a node off a deprecated SQL template onto its family's current one, in place.
356
+
357
+ Purely a ROLE-BASED id remap driven by _LEGACY / _CURRENT: each legacy property id is looked up by
358
+ the role it plays (credentials, side-pannel, sql, timeout, output) and rewritten to the current
359
+ template's id for that same role, in both the runtime `parameters[]` and the designer customData.
360
+ A required Time Out the legacy template never had is seeded from `timeout_default`, so the
361
+ migration cannot hand the designer an empty required field.
362
+ """
363
+ cur = _CURRENT[family]
364
+ remap = {legacy[role]: cur[role] for role in legacy if role in cur}
365
+ node["actionTemplateName"] = family
366
+ node["templateId"] = cur["templateId"]
367
+
368
+ for prm in node.get("parameters") or []:
369
+ pid = prm.get("tabPropertyId")
370
+ if pid in remap:
371
+ prm["tabPropertyId"] = remap[pid]
372
+ # the SQL param is authoritative even if the table missed it (unknown legacy layout)
373
+ query_param["tabPropertyId"] = cur["sql"]
374
+
375
+ for cfg in (node.get("customData") or {}).get("configuration") or []:
376
+ for setting in cfg.get("settings") or []:
377
+ if setting.get("id") in remap:
378
+ setting["id"] = remap[setting["id"]]
379
+ _relabel(setting, cur)
380
+ if isinstance(setting.get("value"), list):
381
+ for sub in setting["value"]:
382
+ if isinstance(sub, dict):
383
+ if sub.get("id") in remap:
384
+ sub["id"] = remap[sub["id"]]
385
+ _relabel(sub, cur)
386
+
387
+ default = cur.get("timeout_default")
388
+ if default and cur.get("timeout"):
389
+ _ensure_setting(node, cur["timeout"], cur["sidepanel"], "Time Out", "number", default)
390
+
391
+
392
+ def _relabel(setting: dict, cur: dict) -> None:
393
+ """Give a remapped setting the CURRENT template's wording; a stale label on a property that now
394
+ belongs to a different template is how the next reader concludes the migration did not happen."""
395
+ label = (cur.get("labels") or {}).get(setting.get("id"))
396
+ if label:
397
+ setting["label"] = label
398
+
399
+
400
+ def _ensure_setting(node: dict, pid: str, sidepanel_pid: str, label: str, stype: str, value) -> None:
401
+ """Add a required property the legacy template did not carry, to BOTH layers, if it is absent."""
402
+ params = node.setdefault("parameters", [])
403
+ if not any(p.get("tabPropertyId") == pid for p in params):
404
+ params.append({"tabPropertyId": pid, "variable": [], "value": value})
405
+ for cfg in (node.get("customData") or {}).get("configuration") or []:
406
+ for setting in cfg.get("settings") or []:
407
+ if setting.get("id") == sidepanel_pid and isinstance(setting.get("value"), list):
408
+ if not any(isinstance(s, dict) and s.get("id") == pid for s in setting["value"]):
409
+ setting["value"].append({"id": pid, "dataTypeId": None, "label": label,
410
+ "type": stype, "value": value})
@@ -0,0 +1,50 @@
1
+ """Which form-code-key a call uses: one per PROCESIO installation.
2
+
3
+ A form's "Switch to code" CSS and JavaScript (`Data.code`) is AES-encrypted with a
4
+ passphrase the installation's web app holds. The platform team confirmed (2026-10-01)
5
+ that there is one key per INSTALLATION: identical on every workspace of it, and not
6
+ guaranteed to match on another. In this tool an installation is an environment
7
+ (environments.py), so the key is stored per environment:
8
+
9
+ agents-and-tools:procesio:form-code-key@<environment> e.g. form-code-key@Internal-QA
10
+
11
+ The bare `form-code-key` predates that and keeps working for the DEFAULT environment,
12
+ the same rule an unbound credential profile follows (environments.resolve). It is never
13
+ used for any other environment: a blob encrypted with another installation's key is one
14
+ that installation's renderer cannot open, and the form goes blank
15
+ (FORM-DEV-GUIDE/08-PITFALLS.md). A missing key is an error naming the exact secret to
16
+ store, never a silent fallback.
17
+ """
18
+ from __future__ import annotations
19
+
20
+ from tools.procesio.errors import UsageError
21
+
22
+ TOOL = "procesio"
23
+ LEGACY = "form-code-key"
24
+
25
+
26
+ def secret_name(env_name: str) -> str:
27
+ """The Credential Manager secret holding `env_name`'s key."""
28
+ return f"{LEGACY}@{env_name}"
29
+
30
+
31
+ def key_for(env_name: str | None) -> str:
32
+ """The form-code-key for `env_name` (None means the default environment)."""
33
+ from tools._lib import creds # lazy: avoid the keyring import unless needed
34
+ from tools.procesio import environments
35
+
36
+ default = environments.get_default()
37
+ env = (environments.canonical_name(env_name) or env_name) if env_name else default
38
+ key = creds.get_optional(TOOL, secret_name(env))
39
+ if key:
40
+ return key
41
+ if env == default:
42
+ key = creds.get_optional(TOOL, LEGACY)
43
+ if key:
44
+ return key
45
+ other = (f" The bare {LEGACY} is the default environment's key ({default}) and is "
46
+ f"never used for another installation." if env != default else "")
47
+ raise UsageError(
48
+ f"no form-code-key stored for environment {env}: the AES passphrase that "
49
+ f"installation uses for a form's Data.code. Store it with: python "
50
+ f"scripts/set-credential.py {TOOL} {secret_name(env)}.{other}")