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,200 @@
1
+ """Auth: cookie-session login, header construction, caching, expiry."""
2
+ from __future__ import annotations
3
+
4
+ import time
5
+
6
+ import pytest
7
+
8
+ from tools.procesio import auth, profiles
9
+ from tools.procesio.errors import AuthError, ProcesioAPIError
10
+ from tools.procesio.tests.conftest import FakeResp, FakeSession
11
+
12
+ _COOKIES = {auth.ACCESS_COOKIE: "AAA", auth.REFRESH_COOKIE: "RRR"}
13
+
14
+
15
+ # -- login (form POST + cookies) --------------------------------------------
16
+
17
+ def test_login_form_post_shape_and_cookies():
18
+ profile = {"type": "userpass", "username": "u@example.com", "password": "p"}
19
+ sess = FakeSession(queue=[FakeResp(200, {"message": "Authentication successful"},
20
+ cookies=_COOKIES,
21
+ headers={"x-session-expires-at": "1893456000"})])
22
+ tok = auth.login(profile, sess)
23
+ assert tok["cookies"][auth.ACCESS_COOKIE] == "AAA"
24
+ assert tok["expires_at"] == 1893456000.0
25
+ call = sess.calls[0]
26
+ assert call["url"] == "https://webapi.procesio.app/api/authentication"
27
+ assert call["data"] == {"username": "u@example.com", "password": "p",
28
+ "client_id": "procesio-ui"} # form body, not json
29
+ assert call["json"] is None
30
+ assert call["headers"]["x-requested-by"] == "playground-v1"
31
+ assert call["headers"]["Content-Type"] == "application/x-www-form-urlencoded"
32
+
33
+
34
+ def test_login_non_2xx_raises():
35
+ profile = {"type": "userpass", "username": "u", "password": "p"}
36
+ sess = FakeSession(queue=[FakeResp(407, {}, "Unauthorized")])
37
+ with pytest.raises(ProcesioAPIError) as ei:
38
+ auth.login(profile, sess)
39
+ assert ei.value.status == 407
40
+
41
+
42
+ def test_login_2xx_without_access_cookie_raises():
43
+ profile = {"type": "userpass", "username": "u", "password": "p"}
44
+ sess = FakeSession(queue=[FakeResp(200, {"message": "ok"}, cookies={})])
45
+ with pytest.raises(AuthError):
46
+ auth.login(profile, sess)
47
+
48
+
49
+ def test_parse_expiry_iso_and_epoch():
50
+ assert auth._parse_expiry("1893456000") == 1893456000.0
51
+ assert auth._parse_expiry(None) is None
52
+ iso = auth._parse_expiry("2030-01-01T00:00:00Z")
53
+ assert iso and iso > time.time()
54
+
55
+
56
+ # -- auth_headers: apikey ---------------------------------------------------
57
+
58
+ def test_apikey_headers_include_workspaceid(store):
59
+ profiles.save_profile("k", {"type": "apikey", "key": "N", "value": "V",
60
+ "workspace_id": "WS"})
61
+ h = auth.auth_headers("k", profiles.get_profile("k"), FakeSession())
62
+ assert h == {"key": "N", "value": "V", "workspaceid": "WS"}
63
+
64
+
65
+ def test_apikey_headers_without_workspaceid(store):
66
+ profiles.save_profile("k", {"type": "apikey", "key": "N", "value": "V"})
67
+ h = auth.auth_headers("k", profiles.get_profile("k"), FakeSession())
68
+ assert h == {"key": "N", "value": "V"}
69
+
70
+
71
+ # -- auth_headers: userpass (cookie) ----------------------------------------
72
+
73
+ def test_userpass_uses_cached_cookies(store):
74
+ profiles.save_profile("u", {"type": "userpass", "username": "u", "password": "p"})
75
+ profiles.set_token_cache("u", {"cookies": _COOKIES, "expires_at": time.time() + 9999})
76
+ sess = FakeSession() # must NOT be called - session is fresh
77
+ h = auth.auth_headers("u", profiles.get_profile("u"), sess)
78
+ assert h["x-requested-by"] == "playground-v1"
79
+ assert auth.ACCESS_COOKIE in h["Cookie"] and "AAA" in h["Cookie"]
80
+ assert sess.calls == []
81
+
82
+
83
+ def test_userpass_logs_in_when_no_cache(store):
84
+ profiles.save_profile("u", {"type": "userpass", "username": "u", "password": "p"})
85
+ sess = FakeSession(queue=[FakeResp(200, {"message": "ok"}, cookies=_COOKIES,
86
+ headers={"x-session-expires-at": "1893456000"})])
87
+ h = auth.auth_headers("u", profiles.get_profile("u"), sess)
88
+ assert "AAA" in h["Cookie"]
89
+ assert profiles.get_token_cache("u")["cookies"][auth.ACCESS_COOKIE] == "AAA"
90
+
91
+
92
+ def test_userpass_relogs_in_when_expired(store):
93
+ profiles.save_profile("u", {"type": "userpass", "username": "u", "password": "p"})
94
+ profiles.set_token_cache("u", {"cookies": {auth.ACCESS_COOKIE: "OLD"},
95
+ "expires_at": time.time() - 10}) # expired
96
+ sess = FakeSession(queue=[FakeResp(200, {"message": "ok"},
97
+ cookies={auth.ACCESS_COOKIE: "NEW"})])
98
+ h = auth.auth_headers("u", profiles.get_profile("u"), sess)
99
+ assert "NEW" in h["Cookie"] and "OLD" not in h["Cookie"]
100
+
101
+
102
+ # -- session renewal: refresh before re-sending the password ------------------
103
+
104
+ def _refresh_resp(access="NEW", refresh="RNEW"):
105
+ return FakeResp(200, {"message": "Token refreshed successfully"},
106
+ cookies={auth.ACCESS_COOKIE: access, auth.REFRESH_COOKIE: refresh})
107
+
108
+
109
+ def test_persist_caches_both_cookies(store):
110
+ """The refresh cookie is the whole point of caching - dropping it forces a
111
+ full username/password login every ~30 min (the access JWT's lifetime)."""
112
+ profiles.save_profile("u", {"type": "userpass", "username": "u", "password": "p"})
113
+ auth._persist_cookies("u", {"cookies": _COOKIES, "expires_at": 123.0})
114
+ assert profiles.get_token_cache("u")["cookies"][auth.ACCESS_COOKIE] == "AAA"
115
+ assert profiles.get_refresh_cookie("u") == "RRR"
116
+
117
+
118
+ def test_expired_access_refreshes_instead_of_logging_in(store):
119
+ profiles.save_profile("u", {"type": "userpass", "username": "u", "password": "p"})
120
+ profiles.set_token_cache("u", {"cookies": _COOKIES, "expires_at": time.time() - 10})
121
+ sess = FakeSession(queue=[_refresh_resp()])
122
+ h = auth.auth_headers("u", profiles.get_profile("u"), sess)
123
+ assert "NEW" in h["Cookie"]
124
+ assert len(sess.calls) == 1
125
+ assert sess.calls[0]["url"].endswith(auth.REFRESH_PATH)
126
+ # the password was never sent
127
+ assert "password" not in (sess.calls[0].get("data") or {})
128
+ assert sess.calls[0]["data"]["refresh_token"] == "RRR"
129
+ # and the renewed pair replaced the cache (access + its own refresh entry)
130
+ assert profiles.get_token_cache("u")["cookies"][auth.ACCESS_COOKIE] == "NEW"
131
+ assert profiles.get_refresh_cookie("u") == "RNEW"
132
+
133
+
134
+ def test_refresh_failure_falls_back_to_full_login(store):
135
+ profiles.save_profile("u", {"type": "userpass", "username": "u", "password": "p"})
136
+ profiles.set_token_cache("u", {"cookies": _COOKIES, "expires_at": time.time() - 10})
137
+ sess = FakeSession(queue=[
138
+ FakeResp(400, {"error": "invalid_grant"}), # refresh
139
+ FakeResp(200, {"message": "ok"}, cookies={auth.ACCESS_COOKIE: "LOGGEDIN"}),
140
+ ])
141
+ h = auth.auth_headers("u", profiles.get_profile("u"), sess)
142
+ assert "LOGGEDIN" in h["Cookie"]
143
+ assert sess.calls[0]["url"].endswith(auth.REFRESH_PATH)
144
+ assert sess.calls[1]["url"].endswith(auth.LOGIN_PATH)
145
+
146
+
147
+ def test_no_refresh_cookie_goes_straight_to_login(store):
148
+ profiles.save_profile("u", {"type": "userpass", "username": "u", "password": "p"})
149
+ profiles.set_token_cache("u", {"cookies": {auth.ACCESS_COOKIE: "OLD"},
150
+ "expires_at": time.time() - 10})
151
+ sess = FakeSession(queue=[FakeResp(200, {"message": "ok"},
152
+ cookies={auth.ACCESS_COOKIE: "NEW"})])
153
+ h = auth.auth_headers("u", profiles.get_profile("u"), sess)
154
+ assert "NEW" in h["Cookie"]
155
+ assert len(sess.calls) == 1 and sess.calls[0]["url"].endswith(auth.LOGIN_PATH)
156
+
157
+
158
+ def test_dead_refresh_token_is_not_spent_on_a_round_trip(store):
159
+ """A refresh JWT that is already past its own exp buys nothing."""
160
+ dead = auth._usable_refresh_token(
161
+ "u", {"cookies": {auth.REFRESH_COOKIE: _jwt_with_exp(time.time() - 500)}})
162
+ assert dead is None
163
+ live = auth._usable_refresh_token(
164
+ "u", {"cookies": {auth.REFRESH_COOKIE: _jwt_with_exp(time.time() + 5000)}})
165
+ assert live is not None
166
+
167
+
168
+ def test_refresh_cookie_persists_in_its_own_entry(store):
169
+ """Credential Manager caps a blob at ~1280 CHARS (2560 bytes UTF-16LE), so the
170
+ two ~1700-char JWTs cannot share one entry - the refresh cookie gets its own."""
171
+ profiles.save_profile("u", {"type": "userpass", "username": "u", "password": "p"})
172
+ auth._persist_cookies("u", {"cookies": _COOKIES, "expires_at": 123.0})
173
+ assert profiles.get_token_cache("u")["cookies"] == {auth.ACCESS_COOKIE: "AAA"}
174
+ assert profiles.get_refresh_cookie("u") == "RRR"
175
+ # and it is reachable when only the persistent store has it
176
+ auth._MEM_COOKIES.clear()
177
+ assert auth._usable_refresh_token("u") == "RRR"
178
+
179
+
180
+ def test_clearing_a_session_drops_the_refresh_cookie_too(store):
181
+ profiles.save_profile("u", {"type": "userpass", "username": "u", "password": "p"})
182
+ auth._persist_cookies("u", {"cookies": _COOKIES, "expires_at": 123.0})
183
+ auth.clear_cookies("u")
184
+ assert profiles.get_refresh_cookie("u") is None
185
+
186
+
187
+ def test_reauthenticate_prefers_refresh(store):
188
+ profiles.save_profile("u", {"type": "userpass", "username": "u", "password": "p"})
189
+ profiles.set_token_cache("u", {"cookies": _COOKIES, "expires_at": time.time() + 9999})
190
+ sess = FakeSession(queue=[_refresh_resp(access="REAUTH")])
191
+ cookies = auth.reauthenticate("u", profiles.get_profile("u"), sess)
192
+ assert cookies[auth.ACCESS_COOKIE] == "REAUTH"
193
+ assert sess.calls[0]["url"].endswith(auth.REFRESH_PATH)
194
+
195
+
196
+ def _jwt_with_exp(exp: float) -> str:
197
+ import base64, json as _json
198
+ def seg(d):
199
+ return base64.urlsafe_b64encode(_json.dumps(d).encode()).decode().rstrip("=")
200
+ return f"{seg({'alg': 'HS256'})}.{seg({'exp': int(exp)})}.sig"
@@ -0,0 +1,78 @@
1
+ """Spec-driven actions: naming, full coverage, path/query/body handling, dry-run."""
2
+ from __future__ import annotations
3
+
4
+ from tools.procesio import autogen, main, swagger
5
+ from tools.procesio.client import ProcesioClient
6
+ from tools.procesio.tests.conftest import FakeResp, FakeSession
7
+
8
+
9
+ def _builder(profile, session):
10
+ return lambda prof: ProcesioClient(profile=profile, name="t", session=session)
11
+
12
+
13
+ def test_action_name_mappings():
14
+ assert autogen.action_name("GET", "/api/Projects") == "get-projects"
15
+ assert autogen.action_name("POST", "/api/Projects/{id}/run") == "post-projects-by-id-run"
16
+ assert (autogen.action_name("GET", "/api/Projects/instances/{id}/status")
17
+ == "get-projects-instances-by-id-status")
18
+ assert (autogen.action_name("DELETE", "/api/DataTypes/attribute/{rootDataTypeId}/{attributeId}")
19
+ == "delete-datatypes-attribute-by-rootdatatypeid-by-attributeid")
20
+
21
+
22
+ def test_one_action_per_endpoint():
23
+ gen = autogen.build_actions()
24
+ assert len(gen) == len(swagger.all_endpoints())
25
+
26
+
27
+ def test_every_endpoint_is_reachable():
28
+ """Each spec endpoint must map to an action in the merged dispatcher."""
29
+ names = set(main.ACTIONS)
30
+ missing = [(ep["method"], ep["path"])
31
+ for ep in swagger.all_endpoints()
32
+ if autogen.action_name(ep["method"], ep["path"]) not in names]
33
+ assert not missing, f"endpoints without an action: {missing[:5]}"
34
+
35
+
36
+ def test_generated_get_substitutes_path():
37
+ sess = FakeSession(queue=[FakeResp(200, {"ok": 1})])
38
+ out = main.dispatch("get-projects-by-id-payload", ["--id", "PID"],
39
+ client_builder=_builder({"type": "apikey", "key": "N", "value": "V"}, sess))
40
+ assert out["result"] == {"ok": 1}
41
+ assert sess.calls[0]["url"] == "https://webapi.procesio.app/api/Projects/PID/payload"
42
+
43
+
44
+ def test_generated_post_passes_query_and_body():
45
+ sess = FakeSession(queue=[FakeResp(200, {"id": "x"})])
46
+ main.dispatch(
47
+ "post-projects-by-id-run",
48
+ ["--id", "PID", "--runSynchronous", "true",
49
+ "--body", '{"payload":{},"connectionid":null}'],
50
+ client_builder=_builder({"type": "apikey", "key": "N", "value": "V"}, sess),
51
+ )
52
+ c = sess.calls[0]
53
+ assert c["url"] == "https://webapi.procesio.app/api/Projects/PID/run"
54
+ assert c["params"] == {"runSynchronous": "true"}
55
+ assert c["json"] == {"payload": {}, "connectionid": None}
56
+
57
+
58
+ def test_generated_dry_run_does_not_send():
59
+ sess = FakeSession(queue=[])
60
+ out = main.dispatch("delete-projects-by-id", ["--id", "PID", "--dry-run"],
61
+ client_builder=_builder({"type": "apikey", "key": "N", "value": "V"}, sess))
62
+ assert out["dry_run"] is True
63
+ assert out["method"] == "DELETE" and out["path"] == "/api/Projects/PID"
64
+ assert sess.calls == []
65
+
66
+
67
+ def test_path_param_id_not_duplicated_as_query():
68
+ """/api/Projects/instances/{id}/status lists 'id' among params; it must be a
69
+ single required path arg, not also a query arg."""
70
+ gen = autogen.build_actions()
71
+ defn = gen["get-projects-instances-by-id-status"]
72
+ import argparse
73
+ p = argparse.ArgumentParser()
74
+ defn.add_args(p)
75
+ opts = [o[2:] for a in p._actions for o in a.option_strings
76
+ if o.startswith("--") and o != "--help"]
77
+ assert opts.count("id") == 1
78
+ assert "flowTemplateId" in opts # the real query params remain
@@ -0,0 +1,180 @@
1
+ """Two builder gaps that only surface when a process is actually SAVED.
2
+
3
+ 1. **Attribute paths were never resolved.** `{"var": "row", "path": ["ToEmail"]}` is documented and
4
+ accepted, but `attr_index` was never populated, so the attribute NAME was written straight into
5
+ `attribute.attributeId` — a field the API parses as a Guid. Every model-typed attribute binding
6
+ was rejected at save time with `Error converting value "ToEmail" to type 'System.Guid'`.
7
+
8
+ 2. **A SQL node was built without its `Parameters config tab`.** The builder emits only the
9
+ properties the caller named; the designer renders that property from the TEMPLATE, finds no
10
+ value, and blocks the save with "Please make sure that the action is defined/configured
11
+ properly". So no `process-create` config containing an Execute Query / Execute Command could be
12
+ saved at all, whether or not it bound any parameter.
13
+ """
14
+ from __future__ import annotations
15
+
16
+ import pytest
17
+
18
+ from tools.procesio.dto.process import builder
19
+ from tools.procesio.errors import UsageError
20
+ from tools.procesio.flowmodel import sqlparam
21
+
22
+
23
+ MODEL_ID = "11111111-1111-1111-1111-111111111111"
24
+ CHILD_ID = "22222222-2222-2222-2222-222222222222"
25
+ TO_EMAIL_ID = "aaaaaaaa-0000-0000-0000-000000000001"
26
+ CLIENT_ID = "aaaaaaaa-0000-0000-0000-000000000002"
27
+ CITY_ID = "bbbbbbbb-0000-0000-0000-000000000001"
28
+
29
+
30
+ def _ctx_with_model() -> dict:
31
+ """A ctx whose model_attrs is what prepare_ctx builds from GET /api/DataTypes/{id}."""
32
+ return {
33
+ "var_ids": {"row": "var-row"},
34
+ "var_models": {"row": MODEL_ID},
35
+ "model_attrs": {
36
+ MODEL_ID: {
37
+ "toemail": {"id": TO_EMAIL_ID, "name": "ToEmail", "dataTypeId": None},
38
+ "client": {"id": CLIENT_ID, "name": "Client", "dataTypeId": CHILD_ID},
39
+ },
40
+ CHILD_ID: {
41
+ "city": {"id": CITY_ID, "name": "City", "dataTypeId": None},
42
+ },
43
+ },
44
+ }
45
+
46
+
47
+ # ------------------------------------------------------------------ attribute paths
48
+
49
+ def test_an_attribute_name_resolves_to_its_guid():
50
+ p = builder._make_parameter("prop-1", {"var": "row", "path": ["ToEmail"]},
51
+ _ctx_with_model(), [0])
52
+ assert p["Variable"][0]["attribute"] == {"attributeId": TO_EMAIL_ID, "nextAttribute": None}
53
+
54
+
55
+ def test_attribute_names_are_matched_case_insensitively():
56
+ p = builder._make_parameter("prop-1", {"var": "row", "path": ["toemail"]},
57
+ _ctx_with_model(), [0])
58
+ assert p["Variable"][0]["attribute"]["attributeId"] == TO_EMAIL_ID
59
+
60
+
61
+ def test_a_nested_path_descends_through_the_child_model():
62
+ p = builder._make_parameter("prop-1", {"var": "row", "path": ["Client", "City"]},
63
+ _ctx_with_model(), [0])
64
+ assert p["Variable"][0]["attribute"] == {
65
+ "attributeId": CLIENT_ID,
66
+ "nextAttribute": {"attributeId": CITY_ID, "nextAttribute": None},
67
+ }
68
+
69
+
70
+ def test_a_guid_passed_directly_is_left_alone():
71
+ """A caller who already knows the attribute id must not need the model resolved."""
72
+ p = builder._make_parameter("prop-1", {"var": "row", "path": [TO_EMAIL_ID]},
73
+ _ctx_with_model(), [0])
74
+ assert p["Variable"][0]["attribute"]["attributeId"] == TO_EMAIL_ID
75
+
76
+
77
+ def test_an_unknown_attribute_fails_loudly_instead_of_writing_a_name_the_api_rejects():
78
+ with pytest.raises(UsageError) as e:
79
+ builder._make_parameter("prop-1", {"var": "row", "path": ["Nope"]},
80
+ _ctx_with_model(), [0])
81
+ msg = str(e.value)
82
+ assert "Nope" in msg
83
+ assert "ToEmail" in msg, "the error must name the attributes that DO exist"
84
+
85
+
86
+ def test_a_template_binding_resolves_attribute_paths_the_same_way():
87
+ p = builder._make_parameter(
88
+ "prop-1",
89
+ {"template": "EXEC p @a='<%0%>', @b='<%1%>'",
90
+ "vars": [{"var": "row", "path": ["ToEmail"]}, {"var": "row", "path": ["Client", "City"]}]},
91
+ _ctx_with_model(), [0])
92
+ assert p["Variable"][0]["attribute"]["attributeId"] == TO_EMAIL_ID
93
+ assert p["Variable"][1]["attribute"]["nextAttribute"]["attributeId"] == CITY_ID
94
+
95
+
96
+ def test_no_path_still_means_no_attribute():
97
+ p = builder._make_parameter("prop-1", {"var": "row"}, _ctx_with_model(), [0])
98
+ assert p["Variable"][0]["attribute"] is None
99
+
100
+
101
+ def test_a_variable_with_no_known_model_passes_the_path_through_unchanged():
102
+ """Offline or for an untyped variable, the old pass-through behaviour is the safe fallback."""
103
+ ctx = {"var_ids": {"row": "var-row"}}
104
+ p = builder._make_parameter("prop-1", {"var": "row", "path": ["ToEmail"]}, ctx, [0])
105
+ assert p["Variable"][0]["attribute"]["attributeId"] == "ToEmail"
106
+
107
+
108
+ # ------------------------------------------------------------------ SQL bind property
109
+
110
+ @pytest.mark.parametrize("template_name,bind_pid", [
111
+ ("Execute Query", sqlparam.PID_BIND),
112
+ ("Execute Command", sqlparam.EC_PID_BIND),
113
+ ])
114
+ def test_a_sql_node_always_carries_its_parameters_config_tab(template_name, bind_pid):
115
+ params = [{"TabPropertyId": "some-other-prop", "Variable": [], "Value": "x"}]
116
+ out = builder._ensure_sql_bind_property({"name": template_name}, params)
117
+ bind = [p for p in out if p["TabPropertyId"] == bind_pid]
118
+ assert len(bind) == 1
119
+ assert bind[0]["Value"] == [], "an unbound SQL node still needs the property, just empty"
120
+
121
+
122
+ def test_an_existing_binding_is_not_overwritten():
123
+ existing = [{"TabPropertyId": sqlparam.PID_BIND, "Variable": [], "Value": [{"id": 0}]}]
124
+ out = builder._ensure_sql_bind_property({"name": "Execute Query"}, existing)
125
+ assert out == existing
126
+
127
+
128
+ def test_a_non_sql_action_is_left_alone():
129
+ params = [{"TabPropertyId": "p", "Variable": [], "Value": "x"}]
130
+ assert builder._ensure_sql_bind_property({"name": "Node"}, params) == params
131
+
132
+
133
+ def test_the_command_family_gets_its_own_bind_id_not_the_query_one():
134
+ out = builder._ensure_sql_bind_property({"name": "Execute Command"}, [])
135
+ pids = {p["TabPropertyId"] for p in out}
136
+ assert sqlparam.EC_PID_BIND in pids
137
+ assert sqlparam.PID_BIND not in pids, (
138
+ "the Query bind id on a Command node leaves every @param unbound at runtime")
139
+
140
+
141
+ # ------------------------------------------------------------------ engine-state properties
142
+
143
+ def _foreach_template() -> dict:
144
+ """The For Each template as the live catalog serves it: two `ignore` properties carrying the
145
+ engine's loop state, with their seed values already on the template."""
146
+ return {"name": "For Each", "configuration": [{"settings": [
147
+ {"id": "in-list", "label": "In List", "type": "any", "value": None},
148
+ {"id": "timeout", "label": "Action timeout", "type": "number", "value": None},
149
+ {"id": "idx", "label": "Zero based list index", "type": "ignore", "value": "-1"},
150
+ {"id": "started", "label": "Action start time", "type": "ignore",
151
+ "value": "2010-01-01T00:00:00.0000000Z"},
152
+ {"id": "item", "label": "For Each Item", "type": "any", "value": None},
153
+ ]}]}
154
+
155
+
156
+ def test_engine_state_properties_are_seeded_from_the_template():
157
+ """A For Each whose start time is missing times out on its FIRST iteration: the engine compares
158
+ against a default far in the past, so the elapsed time is always over any cap."""
159
+ params = [{"TabPropertyId": "in-list", "Variable": [], "Value": "<%0%>"}]
160
+
161
+ out = builder._ensure_engine_state_properties(_foreach_template(), params)
162
+
163
+ by_pid = {p["TabPropertyId"]: p["Value"] for p in out}
164
+ assert by_pid["idx"] == "-1"
165
+ assert by_pid["started"] == "2010-01-01T00:00:00.0000000Z"
166
+ assert by_pid["in-list"] == "<%0%>", "the caller's own parameters are untouched"
167
+
168
+
169
+ def test_a_seeded_state_property_is_not_duplicated():
170
+ params = [{"TabPropertyId": "idx", "Variable": [], "Value": "7"}]
171
+ out = builder._ensure_engine_state_properties(_foreach_template(), params)
172
+ idx = [p for p in out if p["TabPropertyId"] == "idx"]
173
+ assert len(idx) == 1 and idx[0]["Value"] == "7"
174
+
175
+
176
+ def test_an_action_with_no_ignore_properties_is_unchanged():
177
+ tpl = {"name": "Node", "configuration": [{"settings": [
178
+ {"id": "code", "label": "Code", "type": "code-editor", "value": None}]}]}
179
+ params = [{"TabPropertyId": "code", "Variable": [], "Value": "x"}]
180
+ assert builder._ensure_engine_state_properties(tpl, params) == params
@@ -0,0 +1,72 @@
1
+ """prepare_ctx must surface a workspace's custom (connector) actions into the
2
+ action catalog GENERICALLY - any installed custom action resolvable by name or
3
+ actionId, with no per-action code - and must do so even when the full live
4
+ catalog fetch (`GET /api/Actions?getFullAction=true`) is slow or fails.
5
+
6
+ The full-catalog endpoint is occasionally pathologically slow, so the build
7
+ falls back to the bundled, built-in-only catalog. Before the fix that fallback
8
+ silently dropped every connector, so a process that used one failed with
9
+ "unknown action ... not in the action catalog". The fix fetches the workspace's
10
+ custom actions separately via the narrow, fast
11
+ `GET /api/Actions/node?getFullAction=true&isCustom=true` (the same endpoint
12
+ `customaction-list` uses) and merges them in unconditionally.
13
+ """
14
+ import tools.procesio.dto.process.builder as pb
15
+
16
+
17
+ CUSTOM = {
18
+ "actionId": "517cf512-6a26-4bb7-b0c6-c6f8116e12a4",
19
+ "name": "HTML to Word (.docx)",
20
+ "isProcesioAction": False,
21
+ "configuration": [],
22
+ }
23
+
24
+
25
+ class _Client:
26
+ """Minimal fake: the full-catalog fetch is the failure path, the scoped
27
+ custom-action fetch is the fast path that carries the connector."""
28
+
29
+ def __init__(self, full_fails=True, full_actions=None):
30
+ self.full_fails = full_fails
31
+ self.full_actions = full_actions or []
32
+ self.calls = []
33
+
34
+ def get(self, path, params=None, **kw):
35
+ # accepts read_timeout=/deadline= (the client's real knobs), like ProcesioClient.get
36
+ self.calls.append((path, params))
37
+ if path == "/api/Actions":
38
+ if self.full_fails:
39
+ raise RuntimeError("full catalog pathologically slow")
40
+ return {"actions": self.full_actions}
41
+ if path == "/api/Actions/node":
42
+ assert params == {"getFullAction": "true", "isCustom": "true"}
43
+ return {"actions": [CUSTOM]}
44
+ raise AssertionError(f"unexpected GET {path}")
45
+
46
+
47
+ def test_custom_action_resolves_when_full_catalog_fetch_fails():
48
+ c = _Client(full_fails=True)
49
+ ctx = pb.prepare_ctx(c, {"title": "t", "variables": [], "actions": []})
50
+ idx = ctx["catalog"]
51
+ # resolvable by name (lowercased) AND by actionId
52
+ assert idx.get("html to word (.docx)") is CUSTOM
53
+ assert idx.get(CUSTOM["actionId"]) is CUSTOM
54
+ # and a built-in is still present from the bundled catalog
55
+ assert idx.get("generate guid"), "bundled built-ins must remain available"
56
+ # the scoped custom-action endpoint was actually consulted
57
+ assert any(p == "/api/Actions/node" for p, _ in c.calls)
58
+
59
+
60
+ def test_resolve_template_finds_custom_action_by_name_and_id():
61
+ c = _Client(full_fails=True)
62
+ ctx = pb.prepare_ctx(c, {"title": "t", "variables": [], "actions": []})
63
+ assert pb._resolve_template("HTML to Word (.docx)", ctx) is CUSTOM
64
+ assert pb._resolve_template(CUSTOM["actionId"], ctx) is CUSTOM
65
+
66
+
67
+ def test_custom_action_merged_even_when_full_catalog_omits_it():
68
+ # Full fetch succeeds but returns only built-ins (connectors absent); the
69
+ # scoped fetch must still add the custom action.
70
+ c = _Client(full_fails=False, full_actions=[])
71
+ ctx = pb.prepare_ctx(c, {"title": "t", "variables": [], "actions": []})
72
+ assert ctx["catalog"].get(CUSTOM["actionId"]) is CUSTOM
@@ -0,0 +1,114 @@
1
+ """ProcesioClient: URL building, header injection, error mapping, 401 retry."""
2
+ from __future__ import annotations
3
+
4
+ import pytest
5
+
6
+ from tools.procesio import profiles
7
+ from tools.procesio.client import ProcesioClient
8
+ from tools.procesio.errors import ProcesioAPIError
9
+ from tools.procesio.tests.conftest import FakeResp, FakeSession
10
+
11
+
12
+ def _client(profile, session):
13
+ return ProcesioClient(profile=profile, name="t", session=session)
14
+
15
+
16
+ def test_get_builds_url_and_injects_apikey_headers():
17
+ sess = FakeSession(queue=[FakeResp(200, {"ok": True})])
18
+ c = _client({"type": "apikey", "key": "N", "value": "V", "workspace_id": "WS"}, sess)
19
+ out = c.get("/api/Workspaces")
20
+ assert out == {"ok": True}
21
+ call = sess.calls[0]
22
+ assert call["url"] == "https://webapi.procesio.app/api/Workspaces"
23
+ assert call["headers"]["key"] == "N"
24
+ assert call["headers"]["value"] == "V"
25
+ assert call["headers"]["workspaceid"] == "WS"
26
+
27
+
28
+ def test_query_drops_none_values():
29
+ sess = FakeSession(queue=[FakeResp(200, [])])
30
+ c = _client({"type": "apikey", "key": "N", "value": "V"}, sess)
31
+ c.get("/api/Projects", {"pageNumber": 1, "searchName": None})
32
+ assert sess.calls[0]["params"] == {"pageNumber": 1}
33
+
34
+
35
+ def test_non_2xx_raises_apierror_with_status():
36
+ sess = FakeSession(queue=[FakeResp(403, {"message": "nope"})])
37
+ c = _client({"type": "apikey", "key": "N", "value": "V"}, sess)
38
+ with pytest.raises(ProcesioAPIError) as ei:
39
+ c.get("/api/Projects")
40
+ assert ei.value.status == 403
41
+ assert ei.value.details["message"] == "nope"
42
+
43
+
44
+ def test_userpass_401_triggers_relogin_retry(store):
45
+ from tools.procesio import auth
46
+ profiles.save_profile("u", {"type": "userpass", "username": "u", "password": "p"})
47
+ # Far-future expiry -> treated as fresh and used (an unknown/None expiry is now
48
+ # distrusted, forcing a pre-emptive re-login). This exercises the 401-retry path:
49
+ # the cached token IS sent, the GET 401s, then the client re-logins and retries.
50
+ profiles.set_token_cache("u", {"cookies": {auth.ACCESS_COOKIE: "STALE"},
51
+ "expires_at": 9999999999})
52
+ # 1st GET -> 401 ; client clears cache, re-logs-in, retries -> 200
53
+ sess = FakeSession(queue=[
54
+ FakeResp(401, {"message": "expired"}), # the GET
55
+ FakeResp(200, {"message": "ok"}, cookies={auth.ACCESS_COOKIE: "FRESH"}), # re-login
56
+ FakeResp(200, {"ok": 1}), # retried GET
57
+ ])
58
+ c = ProcesioClient(profile=profiles.get_profile("u"), name="u", session=sess)
59
+ out = c.get("/api/Workspaces")
60
+ assert out == {"ok": 1}
61
+ # final retried GET carried the FRESH session cookie
62
+ assert "FRESH" in sess.calls[-1]["headers"]["Cookie"]
63
+
64
+
65
+ def test_post_sets_content_type_and_body():
66
+ sess = FakeSession(queue=[FakeResp(200, {"id": "x"})])
67
+ c = _client({"type": "apikey", "key": "N", "value": "V"}, sess)
68
+ c.post("/api/Projects/abc/run", {"payload": {}, "connectionid": None})
69
+ call = sess.calls[0]
70
+ assert call["json"] == {"payload": {}, "connectionid": None}
71
+ assert call["headers"]["Content-Type"] == "application/json"
72
+
73
+
74
+ def test_userpass_403_also_triggers_reauth_retry(store):
75
+ """A REJECTED session comes back 403, not 401 (measured against the prod
76
+ gateway). Treating 403 as final surfaced a stale session as an unactionable
77
+ permission error."""
78
+ from tools.procesio import auth
79
+ profiles.save_profile("u", {"type": "userpass", "username": "u", "password": "p"})
80
+ profiles.set_token_cache("u", {"cookies": {auth.ACCESS_COOKIE: "STALE"},
81
+ "expires_at": 9999999999})
82
+ sess = FakeSession(queue=[
83
+ FakeResp(403, {"message": "rejected"}), # the GET
84
+ FakeResp(200, {"message": "ok"}, cookies={auth.ACCESS_COOKIE: "FRESH"}), # re-login
85
+ FakeResp(200, {"ok": 1}), # retried GET
86
+ ])
87
+ c = ProcesioClient(profile=profiles.get_profile("u"), name="u", session=sess)
88
+ assert c.get("/api/Workspaces") == {"ok": 1}
89
+ assert "FRESH" in sess.calls[-1]["headers"]["Cookie"]
90
+
91
+
92
+ def test_reauth_is_one_shot_so_a_real_permission_denial_still_raises(store):
93
+ from tools.procesio import auth
94
+ profiles.save_profile("u", {"type": "userpass", "username": "u", "password": "p"})
95
+ profiles.set_token_cache("u", {"cookies": {auth.ACCESS_COOKIE: "OK"},
96
+ "expires_at": 9999999999})
97
+ sess = FakeSession(queue=[
98
+ FakeResp(403, {"message": "denied"}),
99
+ FakeResp(200, {"message": "ok"}, cookies={auth.ACCESS_COOKIE: "FRESH"}),
100
+ FakeResp(403, {"message": "denied"}), # still denied -> genuine
101
+ ])
102
+ c = ProcesioClient(profile=profiles.get_profile("u"), name="u", session=sess)
103
+ with pytest.raises(ProcesioAPIError) as e:
104
+ c.get("/api/Workspaces")
105
+ assert e.value.status == 403
106
+
107
+
108
+ def test_apikey_403_is_never_retried(store):
109
+ """Only a userpass SESSION can go stale; an API key that is denied is denied."""
110
+ sess = FakeSession(queue=[FakeResp(403, {"message": "denied"})])
111
+ c = _client({"type": "apikey", "key": "N", "value": "V"}, sess)
112
+ with pytest.raises(ProcesioAPIError):
113
+ c.get("/api/Workspaces")
114
+ assert len(sess.calls) == 1