10xscale-agentflow-cli 0.4.0__tar.gz → 0.5.0__tar.gz

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 (201) hide show
  1. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/10xscale_agentflow_cli.egg-info/PKG-INFO +2 -2
  2. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/10xscale_agentflow_cli.egg-info/SOURCES.txt +17 -0
  3. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/10xscale_agentflow_cli.egg-info/requires.txt +1 -1
  4. 10xscale_agentflow_cli-0.5.0/AGENTFLOW_JSON.md +273 -0
  5. 10xscale_agentflow_cli-0.5.0/AUTHORIZATION_PLAN.md +101 -0
  6. 10xscale_agentflow_cli-0.5.0/AUTHORIZATION_PLAN_PHASE2.md +34 -0
  7. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/CLAUDE.md +25 -5
  8. 10xscale_agentflow_cli-0.5.0/CUSTOM_AUTH.md +216 -0
  9. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/PKG-INFO +2 -2
  10. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow.json +1 -0
  11. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/commands/build.py +51 -0
  12. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/commands/init.py +19 -3
  13. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/main.py +10 -1
  14. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/defaults.py +193 -1
  15. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/prod/agentflow.json +9 -3
  16. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/prod/auth/agent_auth.py +1 -4
  17. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/agent-skills/references/api-configuration.md +1 -1
  18. 10xscale_agentflow_cli-0.5.0/agentflow_cli/cli/templates/skills/agent-skills/references/auth-and-authorization.md +149 -0
  19. 10xscale_agentflow_cli-0.5.0/agentflow_cli/src/app/core/auth/authorization.py +369 -0
  20. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/core/auth/jwt_auth.py +1 -0
  21. 10xscale_agentflow_cli-0.5.0/agentflow_cli/src/app/core/auth/ownership_resolver.py +147 -0
  22. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/core/auth/permissions.py +70 -3
  23. 10xscale_agentflow_cli-0.5.0/agentflow_cli/src/app/core/auth/route_guard.py +79 -0
  24. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/core/config/graph_config.py +57 -7
  25. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/core/config/media_settings.py +20 -2
  26. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/core/config/settings.py +9 -0
  27. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/core/config/setup_middleware.py +159 -2
  28. 10xscale_agentflow_cli-0.5.0/agentflow_cli/src/app/core/middleware/rate_limit/keying.py +82 -0
  29. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/core/middleware/request_limits.py +18 -1
  30. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/loader.py +149 -14
  31. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/main.py +59 -3
  32. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/routers/checkpointer/router.py +19 -2
  33. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/routers/checkpointer/services/checkpointer_service.py +29 -0
  34. 10xscale_agentflow_cli-0.5.0/agentflow_cli/src/app/routers/evals/__init__.py +6 -0
  35. 10xscale_agentflow_cli-0.5.0/agentflow_cli/src/app/routers/evals/router.py +38 -0
  36. 10xscale_agentflow_cli-0.5.0/agentflow_cli/src/app/routers/evals/services/__init__.py +1 -0
  37. 10xscale_agentflow_cli-0.5.0/agentflow_cli/src/app/routers/evals/services/eval_report_service.py +354 -0
  38. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/routers/graph/router.py +214 -2
  39. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/routers/graph/schemas/graph_schemas.py +100 -0
  40. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/routers/graph/services/graph_service.py +528 -20
  41. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/routers/graph/services/multimodal_preprocessor.py +5 -0
  42. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/routers/media/__init__.py +62 -4
  43. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/routers/media/router.py +49 -6
  44. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/routers/setup_router.py +2 -0
  45. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/routers/store/router.py +32 -27
  46. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/routers/store/services/store_service.py +3 -1
  47. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/utils/__init__.py +2 -2
  48. 10xscale_agentflow_cli-0.5.0/agentflow_cli/src/app/utils/telemetry_store.py +123 -0
  49. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/utils/thread_name_generator.py +5 -5
  50. 10xscale_agentflow_cli-0.5.0/graph/__init__.py +1 -0
  51. 10xscale_agentflow_cli-0.5.0/graph/dummy_store.py +215 -0
  52. 10xscale_agentflow_cli-0.5.0/graph/fake_realtime_client.py +129 -0
  53. 10xscale_agentflow_cli-0.5.0/graph/live.py +79 -0
  54. 10xscale_agentflow_cli-0.5.0/graph/react.py +221 -0
  55. 10xscale_agentflow_cli-0.5.0/graph/thread_name_generator.py +18 -0
  56. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/pyproject.toml +3 -3
  57. 10xscale_agentflow_cli-0.4.0/agentflow_cli/cli/templates/skills/agent-skills/references/auth-and-authorization.md +0 -87
  58. 10xscale_agentflow_cli-0.4.0/agentflow_cli/src/app/core/auth/authorization.py +0 -90
  59. 10xscale_agentflow_cli-0.4.0/agentflow_cli/src/app/core/middleware/rate_limit/keying.py +0 -24
  60. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/10xscale_agentflow_cli.egg-info/dependency_links.txt +0 -0
  61. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/10xscale_agentflow_cli.egg-info/entry_points.txt +0 -0
  62. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/10xscale_agentflow_cli.egg-info/not-zip-safe +0 -0
  63. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/10xscale_agentflow_cli.egg-info/top_level.txt +0 -0
  64. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/LICENSE +0 -0
  65. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/MANIFEST.in +0 -0
  66. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/README.md +0 -0
  67. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/__init__.py +0 -0
  68. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/__init__.py +0 -0
  69. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/commands/__init__.py +0 -0
  70. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/commands/api.py +0 -0
  71. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/commands/eval.py +0 -0
  72. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/commands/skills.py +0 -0
  73. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/commands/test.py +0 -0
  74. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/commands/version.py +0 -0
  75. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/constants.py +0 -0
  76. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/core/__init__.py +0 -0
  77. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/core/config.py +0 -0
  78. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/core/output.py +0 -0
  79. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/core/validation.py +0 -0
  80. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/exceptions.py +0 -0
  81. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/logger.py +0 -0
  82. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/__init__.py +0 -0
  83. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/dev/agentflow.json +0 -0
  84. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/dev/graph/__init__.py +0 -0
  85. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/dev/graph/agent.py +0 -0
  86. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/prod/.pre-commot-config.yaml +0 -0
  87. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/prod/auth/__init__.py +0 -0
  88. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/prod/evals/__init__.py +0 -0
  89. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/prod/evals/user_simulator_eval.py +0 -0
  90. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/prod/evals/weather_agents_eval.py +0 -0
  91. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/prod/graph/__init__.py +0 -0
  92. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/prod/graph/agent.py +0 -0
  93. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/prod/graph/state.py +0 -0
  94. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/prod/graph/thread_name_generator.py +0 -0
  95. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/prod/graph/tools/__init__.py +0 -0
  96. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/prod/graph/tools/weather_tool.py +0 -0
  97. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/prod/graph/validators/__init__.py +0 -0
  98. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/prod/graph/validators/lifecyle.py +0 -0
  99. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/prod/graph/validators/manager.py +0 -0
  100. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/prod/graph/validators/validators.py +0 -0
  101. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/prod/tests/__init__.py +0 -0
  102. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/prod/tests/conftest.py +0 -0
  103. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/prod/tests/test_agent_eval.py +0 -0
  104. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/prod/tests/test_catalog_tools.py +0 -0
  105. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/prod/tests/test_graph_nodes.py +0 -0
  106. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/agent-skills/references/agents-and-tools.md +0 -0
  107. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/agent-skills/references/api-client.md +0 -0
  108. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/agent-skills/references/api-settings-and-middleware.md +0 -0
  109. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/agent-skills/references/architecture.md +0 -0
  110. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/agent-skills/references/callbacks-and-command.md +0 -0
  111. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/agent-skills/references/checkpointing-and-threads.md +0 -0
  112. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/agent-skills/references/cli-commands.md +0 -0
  113. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/agent-skills/references/client-auth-and-errors.md +0 -0
  114. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/agent-skills/references/client-messages-invoke-stream.md +0 -0
  115. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/agent-skills/references/client-threads-memory-files.md +0 -0
  116. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/agent-skills/references/context-id-background.md +0 -0
  117. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/agent-skills/references/dependency-injection.md +0 -0
  118. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/agent-skills/references/evaluation.md +0 -0
  119. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/agent-skills/references/id-and-thread-name-generators.md +0 -0
  120. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/agent-skills/references/media-and-files.md +0 -0
  121. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/agent-skills/references/memory-and-store.md +0 -0
  122. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/agent-skills/references/prebuilt-agents-and-tools.md +0 -0
  123. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/agent-skills/references/production-runtime.md +0 -0
  124. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/agent-skills/references/providers-and-adapters.md +0 -0
  125. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/agent-skills/references/publishers-and-runtime-protocols.md +0 -0
  126. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/agent-skills/references/rate-limiting.md +0 -0
  127. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/agent-skills/references/realtime.md +0 -0
  128. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/agent-skills/references/remote-tools.md +0 -0
  129. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/agent-skills/references/rest-api-and-errors.md +0 -0
  130. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/agent-skills/references/security-and-validators.md +0 -0
  131. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/agent-skills/references/state-and-messages.md +0 -0
  132. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/agent-skills/references/state-graph.md +0 -0
  133. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/agent-skills/references/stream-emitter.md +0 -0
  134. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/agent-skills/references/streaming.md +0 -0
  135. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/agent-skills/references/testing-and-evaluation.md +0 -0
  136. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/agent-skills/references/unit-testing.md +0 -0
  137. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/claude/SKILL.md +0 -0
  138. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/codex/SKILL.md +0 -0
  139. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/copilot/SKILL.md +0 -0
  140. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/cli/templates/skills/copilot/agentflow.instructions.md +0 -0
  141. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/__init__.py +0 -0
  142. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/__init__.py +0 -0
  143. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/core/__init__.py +0 -0
  144. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/core/auth/__init__.py +0 -0
  145. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/core/auth/auth_backend.py +0 -0
  146. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/core/auth/base_auth.py +0 -0
  147. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/core/config/__init__.py +0 -0
  148. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/core/config/sentry_config.py +0 -0
  149. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/core/config/setup_logs.py +0 -0
  150. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/core/config/worker_middleware.py +0 -0
  151. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/core/exceptions/__init__.py +0 -0
  152. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/core/exceptions/general_exception.py +0 -0
  153. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/core/exceptions/handle_errors.py +0 -0
  154. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/core/exceptions/resources_exceptions.py +0 -0
  155. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/core/exceptions/user_exception.py +0 -0
  156. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/core/middleware/__init__.py +0 -0
  157. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/core/middleware/rate_limit/__init__.py +0 -0
  158. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/core/middleware/rate_limit/base.py +0 -0
  159. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/core/middleware/rate_limit/factory.py +0 -0
  160. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/core/middleware/rate_limit/memory.py +0 -0
  161. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/core/middleware/rate_limit/middleware.py +0 -0
  162. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/core/middleware/rate_limit/redis.py +0 -0
  163. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/core/middleware/security_headers.py +0 -0
  164. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/core/utils/__init__.py +0 -0
  165. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/core/utils/log_sanitizer.py +0 -0
  166. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/routers/__init__.py +0 -0
  167. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/routers/a2a.py +0 -0
  168. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/routers/a2ui.py +0 -0
  169. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/routers/checkpointer/__init__.py +0 -0
  170. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/routers/checkpointer/schemas/__init__.py +0 -0
  171. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/routers/checkpointer/schemas/checkpointer_schemas.py +0 -0
  172. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/routers/checkpointer/services/__init__.py +0 -0
  173. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/routers/graph/__init__.py +0 -0
  174. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/routers/graph/realtime_guard.py +0 -0
  175. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/routers/graph/schemas/__init__.py +0 -0
  176. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/routers/graph/services/__init__.py +0 -0
  177. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/routers/media/schemas.py +0 -0
  178. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/routers/ping/__init__.py +0 -0
  179. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/routers/ping/router.py +0 -0
  180. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/routers/store/__init__.py +0 -0
  181. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/routers/store/schemas/__init__.py +0 -0
  182. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/routers/store/schemas/store_schemas.py +0 -0
  183. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/routers/store/services/__init__.py +0 -0
  184. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/tasks/__init__.py +0 -0
  185. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/tasks/user_tasks.py +0 -0
  186. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/utils/callable_helper.py +0 -0
  187. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/utils/media/__init__.py +0 -0
  188. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/utils/media/extractor.py +0 -0
  189. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/utils/media/pipeline.py +0 -0
  190. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/utils/parse_output.py +0 -0
  191. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/utils/response_helper.py +0 -0
  192. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/utils/schemas/__init__.py +0 -0
  193. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/utils/schemas/output_schemas.py +0 -0
  194. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/utils/schemas/user_schemas.py +0 -0
  195. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/utils/snowflake_id_generator.py +0 -0
  196. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/utils/swagger_helper.py +0 -0
  197. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/agentflow_cli/src/app/worker.py +0 -0
  198. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/setup.cfg +0 -0
  199. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/tests/test_multimodal_sprint2_extraction.py +0 -0
  200. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/tests/test_sprint4_media_api.py +0 -0
  201. {10xscale_agentflow_cli-0.4.0 → 10xscale_agentflow_cli-0.5.0}/tests/test_utils_parse_and_callable.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: 10xscale-agentflow-cli
3
- Version: 0.4.0
3
+ Version: 0.5.0
4
4
  Summary: CLI and API for 10xscale AgentFlow
5
5
  Author-email: 10xscale <contact@10xscale.ai>
6
6
  Maintainer-email: Shudipto Trafder <shudiptotrafder@gmail.com>
@@ -22,7 +22,7 @@ Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
22
22
  Requires-Python: >=3.12
23
23
  Description-Content-Type: text/markdown
24
24
  License-File: LICENSE
25
- Requires-Dist: 10xscale-agentflow>=0.8.0
25
+ Requires-Dist: 10xscale-agentflow>=0.9.0
26
26
  Requires-Dist: fastapi
27
27
  Requires-Dist: gunicorn
28
28
  Requires-Dist: orjson
@@ -1,4 +1,8 @@
1
+ AGENTFLOW_JSON.md
2
+ AUTHORIZATION_PLAN.md
3
+ AUTHORIZATION_PLAN_PHASE2.md
1
4
  CLAUDE.md
5
+ CUSTOM_AUTH.md
2
6
  LICENSE
3
7
  MANIFEST.in
4
8
  README.md
@@ -104,7 +108,9 @@ agentflow_cli/src/app/core/auth/auth_backend.py
104
108
  agentflow_cli/src/app/core/auth/authorization.py
105
109
  agentflow_cli/src/app/core/auth/base_auth.py
106
110
  agentflow_cli/src/app/core/auth/jwt_auth.py
111
+ agentflow_cli/src/app/core/auth/ownership_resolver.py
107
112
  agentflow_cli/src/app/core/auth/permissions.py
113
+ agentflow_cli/src/app/core/auth/route_guard.py
108
114
  agentflow_cli/src/app/core/config/__init__.py
109
115
  agentflow_cli/src/app/core/config/graph_config.py
110
116
  agentflow_cli/src/app/core/config/media_settings.py
@@ -140,6 +146,10 @@ agentflow_cli/src/app/routers/checkpointer/schemas/__init__.py
140
146
  agentflow_cli/src/app/routers/checkpointer/schemas/checkpointer_schemas.py
141
147
  agentflow_cli/src/app/routers/checkpointer/services/__init__.py
142
148
  agentflow_cli/src/app/routers/checkpointer/services/checkpointer_service.py
149
+ agentflow_cli/src/app/routers/evals/__init__.py
150
+ agentflow_cli/src/app/routers/evals/router.py
151
+ agentflow_cli/src/app/routers/evals/services/__init__.py
152
+ agentflow_cli/src/app/routers/evals/services/eval_report_service.py
143
153
  agentflow_cli/src/app/routers/graph/__init__.py
144
154
  agentflow_cli/src/app/routers/graph/realtime_guard.py
145
155
  agentflow_cli/src/app/routers/graph/router.py
@@ -167,6 +177,7 @@ agentflow_cli/src/app/utils/parse_output.py
167
177
  agentflow_cli/src/app/utils/response_helper.py
168
178
  agentflow_cli/src/app/utils/snowflake_id_generator.py
169
179
  agentflow_cli/src/app/utils/swagger_helper.py
180
+ agentflow_cli/src/app/utils/telemetry_store.py
170
181
  agentflow_cli/src/app/utils/thread_name_generator.py
171
182
  agentflow_cli/src/app/utils/media/__init__.py
172
183
  agentflow_cli/src/app/utils/media/extractor.py
@@ -174,6 +185,12 @@ agentflow_cli/src/app/utils/media/pipeline.py
174
185
  agentflow_cli/src/app/utils/schemas/__init__.py
175
186
  agentflow_cli/src/app/utils/schemas/output_schemas.py
176
187
  agentflow_cli/src/app/utils/schemas/user_schemas.py
188
+ graph/__init__.py
189
+ graph/dummy_store.py
190
+ graph/fake_realtime_client.py
191
+ graph/live.py
192
+ graph/react.py
193
+ graph/thread_name_generator.py
177
194
  tests/test_multimodal_sprint2_extraction.py
178
195
  tests/test_sprint4_media_api.py
179
196
  tests/test_utils_parse_and_callable.py
@@ -1,4 +1,4 @@
1
- 10xscale-agentflow>=0.8.0
1
+ 10xscale-agentflow>=0.9.0
2
2
  fastapi
3
3
  gunicorn
4
4
  orjson
@@ -0,0 +1,273 @@
1
+ # `agentflow.json` — Configuration Reference
2
+
3
+ This is the only file you write to turn your compiled graph into a running API server.
4
+ `agentflow api` reads it, resolves each key, and boots FastAPI + WebSocket around your graph.
5
+
6
+ Every key except `agent` is optional. Secrets never live here — they stay in the environment
7
+ (loaded from the file named by `env`).
8
+
9
+ ---
10
+
11
+ ## Minimal (development)
12
+
13
+ ```json
14
+ {
15
+ "agent": "graph.react:app"
16
+ }
17
+ ```
18
+
19
+ `agent` points at a compiled graph; everything else defaults. No auth, in-memory everything,
20
+ allow-all authorization. Enough to run locally.
21
+
22
+ ---
23
+
24
+ ## Full shape
25
+
26
+ ```json
27
+ {
28
+ "agent": "graph.react:app",
29
+ "env": ".env",
30
+
31
+ "auth": null,
32
+ "authorization": null,
33
+
34
+ "checkpointer": null,
35
+ "store": null,
36
+ "redis": null,
37
+
38
+ "injectq": null,
39
+ "thread_name_generator": null,
40
+
41
+ "rate_limit": {},
42
+ "websocket": {},
43
+ "observability": null
44
+ }
45
+ ```
46
+
47
+ ---
48
+
49
+ ## Keys
50
+
51
+ ### `agent` (required)
52
+ `"module:attribute"` resolving to a `CompiledGraph`. The loader accepts a `CompiledGraph`
53
+ object, or a sync/async factory that returns one.
54
+
55
+ ```json
56
+ "agent": "graph.react:app"
57
+ ```
58
+
59
+ ### `env`
60
+ Path to a `.env` file, loaded at config-load time. Put all secrets here (JWT key, DB URLs,
61
+ API keys). Never inline secrets in this JSON.
62
+
63
+ ```json
64
+ "env": ".env"
65
+ ```
66
+
67
+ ### `auth` — who is the caller? (authentication)
68
+ Produces a `user` dict with at least `user_id`. Three forms:
69
+
70
+ | Value | Meaning |
71
+ |---|---|
72
+ | `null` | No authentication. All endpoints run unauthenticated (dev). |
73
+ | `"jwt"` | Built-in JWT bearer auth. Requires `JWT_SECRET_KEY` + `JWT_ALGORITHM` in env (fails at boot if missing). Token must carry `user_id` and `exp`. |
74
+ | `{"method": "custom", "path": "auth.backend:MyAuth"}` | Your own `BaseAuth` subclass (`from agentflow_cli import BaseAuth`). |
75
+
76
+ ```json
77
+ "auth": "jwt"
78
+ ```
79
+
80
+ ### `authorization` — what may the caller do? (authorization)
81
+ Separate from `auth`. Controls object-level access (thread ownership), per-endpoint scopes,
82
+ and storage isolation. Four forms:
83
+
84
+ | Value | Meaning |
85
+ |---|---|
86
+ | `null` | **Mode-based default**: `ownership` in production, `allow_all` in development. |
87
+ | `"ownership"` | Owner-only: a thread is readable/runnable only by the user who created it. Enforced on every thread-touching endpoint (invoke/stream/stop/fix + all checkpointer ops). |
88
+ | `"allow_all"` (aliases `"default"`, `"none"`) | Any authenticated user may do anything. |
89
+ | `"auth.backend:MyBackend"` | Your own `AuthorizationBackend` subclass. |
90
+ | `{...}` (object) | RBAC — see below. |
91
+
92
+ Plain owner-only:
93
+ ```json
94
+ "authorization": "ownership"
95
+ ```
96
+
97
+ RBAC (roles → scopes, on top of owner-only isolation):
98
+ ```json
99
+ "authorization": {
100
+ "backend": "rbac",
101
+ "roles": {
102
+ "admin": ["*"],
103
+ "member": ["graph:invoke", "graph:stream", "graph:read", "checkpointer:read"]
104
+ },
105
+ "default_scopes": ["graph:read"],
106
+ "isolation": "owner"
107
+ }
108
+ ```
109
+
110
+ - `roles` — map each role (from the user's `roles`/`role` claim) to the scopes it grants.
111
+ `"*"` grants every scope.
112
+ - `default_scopes` — granted to everyone, even a user with no role.
113
+ - `isolation` — `"owner"` (owner-only storage, default) or `"none"` (any authenticated user
114
+ sees all rows).
115
+
116
+ Available scopes (`"<resource>:<action>"`):
117
+
118
+ | Resource | Scopes |
119
+ |---|---|
120
+ | graph | `graph:invoke`, `graph:stream`, `graph:stop`, `graph:fix`, `graph:setup`, `graph:read` |
121
+ | checkpointer | `checkpointer:read`, `checkpointer:write`, `checkpointer:delete` |
122
+ | memory (store) | `memory:read`, `memory:write`, `memory:delete` |
123
+ | files | `files:read`, `files:upload` |
124
+ | config | `config:read` |
125
+
126
+ Scopes are only enforced once an identity actually carries scopes (an RBAC role, or a JWT
127
+ `scopes` claim). Without them the server stays permissive — nothing breaks until you issue
128
+ scopes.
129
+
130
+ ### `checkpointer` — durable thread state
131
+ `"module:attr"` resolving to a `BaseCheckpointer`. Omit for in-memory (state lost on restart).
132
+ Ownership-based authorization requires a checkpointer that can resolve thread owners
133
+ (Postgres/SQLite/in-memory all do; a bare base does not).
134
+
135
+ ```json
136
+ "checkpointer": "graph.infra:checkpointer"
137
+ ```
138
+
139
+ ### `store` — long-term memory (vector store)
140
+ `"module:attr"` resolving to a `BaseStore` (Qdrant, Mem0, ...). Powers `/v1/store/*`. Scoped
141
+ per-user according to the active authorization isolation policy.
142
+
143
+ ```json
144
+ "store": "graph.infra:store"
145
+ ```
146
+
147
+ ### `redis`
148
+ Redis URL. Shared by the rate-limiter (redis backend) and the ownership-cache L2 tier (so
149
+ ownership lookups are shared across workers instead of per-process).
150
+
151
+ ```json
152
+ "redis": "redis://localhost:6379/0"
153
+ ```
154
+
155
+ ### `injectq`
156
+ `"module:attr"` resolving to an InjectQ container, if you want to pre-bind dependencies
157
+ (db handles, config, `user_id`) for injection into your tools.
158
+
159
+ ### `thread_name_generator`
160
+ `"module:attr"` resolving to a `ThreadNameGenerator` — auto-names new threads.
161
+
162
+ ### `rate_limit`
163
+ Object. Omit or `{"enabled": false}` to disable.
164
+
165
+ ```json
166
+ "rate_limit": {
167
+ "enabled": true,
168
+ "backend": "redis",
169
+ "requests": 100,
170
+ "window": 60,
171
+ "by": "ip",
172
+ "trusted_proxy_headers": true,
173
+ "trusted_proxy_hops": 1,
174
+ "exclude_paths": ["/ping"],
175
+ "fail_open": true,
176
+ "redis": { "url": "redis://localhost:6379/0", "prefix": "agentflow:rate-limit" }
177
+ }
178
+ ```
179
+
180
+ | Field | Default | Notes |
181
+ |---|---|---|
182
+ | `enabled` | `true` | |
183
+ | `backend` | `"memory"` | `memory` \| `redis` \| `custom`. **`memory` counts per process — use `redis` for multi-worker.** For `custom`, bind a `BaseRateLimitBackend` in InjectQ. |
184
+ | `requests` | `100` | Allowed requests per window. |
185
+ | `window` | `60` | Window length in seconds. |
186
+ | `by` | `"ip"` | `ip` \| `user` \| `global`. |
187
+ | `trusted_proxy_headers` | `false` | Honour `X-Forwarded-For` only when `true` (i.e. behind a proxy you control). |
188
+ | `trusted_proxy_hops` | `1` | How many proxies you control appended to `X-Forwarded-For`; entries left of these are forgeable. |
189
+ | `exclude_paths` | `[]` | Paths exempt from limiting. |
190
+ | `fail_open` | `true` | On backend error: `true` = allow, `false` = deny. |
191
+
192
+ ### `websocket`
193
+ Per-process cap on concurrent WebSocket connections (`/v1/graph/ws`, `/v1/graph/live`).
194
+ `null`/`0` = unlimited.
195
+
196
+ ```json
197
+ "websocket": { "max_connections": 100 }
198
+ ```
199
+
200
+ ### `observability`
201
+ Declarative Logfire / LangSmith wiring. Tokens (`LOGFIRE_TOKEN`, `LANGSMITH_API_KEY`) stay in
202
+ the environment.
203
+
204
+ ```json
205
+ "observability": {
206
+ "level": "standard",
207
+ "logfire": { "enabled": true, "service_name": "my-agent" },
208
+ "langsmith": { "enabled": true, "project": "my-agent", "endpoint": null }
209
+ }
210
+ ```
211
+
212
+ ---
213
+
214
+ ## Production example
215
+
216
+ ```json
217
+ {
218
+ "agent": "graph.react:app",
219
+ "env": ".env",
220
+
221
+ "auth": "jwt",
222
+ "authorization": {
223
+ "backend": "rbac",
224
+ "roles": {
225
+ "admin": ["*"],
226
+ "member": ["graph:invoke", "graph:stream", "graph:read", "checkpointer:read", "memory:read", "memory:write"]
227
+ },
228
+ "default_scopes": [],
229
+ "isolation": "owner"
230
+ },
231
+
232
+ "checkpointer": "graph.infra:checkpointer",
233
+ "store": "graph.infra:store",
234
+ "redis": "redis://redis:6379/0",
235
+
236
+ "rate_limit": {
237
+ "enabled": true,
238
+ "backend": "redis",
239
+ "requests": 100,
240
+ "window": 60,
241
+ "by": "user",
242
+ "trusted_proxy_headers": true,
243
+ "redis": { "url": "redis://redis:6379/0" }
244
+ },
245
+
246
+ "websocket": { "max_connections": 500 }
247
+ }
248
+ ```
249
+
250
+ Required env for this example (in `.env`):
251
+
252
+ ```
253
+ MODE=production
254
+ IS_DEBUG=false
255
+ ORIGINS=https://app.example.com
256
+ JWT_SECRET_KEY=<32+ char secret>
257
+ JWT_ALGORITHM=HS256
258
+ ```
259
+
260
+ ---
261
+
262
+ ## Defaults at a glance
263
+
264
+ | If you omit... | You get |
265
+ |---|---|
266
+ | `auth` | No authentication. |
267
+ | `authorization` | `ownership` in production, `allow_all` in development. |
268
+ | `checkpointer` | In-memory (lost on restart). |
269
+ | `store` | No memory API. |
270
+ | `redis` | Ownership cache is L1-only (per-process); redis rate-limit backend unavailable. |
271
+ | `rate_limit` | No rate limiting. |
272
+ | `websocket` | Unlimited connections. |
273
+ | `observability` | None. |
@@ -0,0 +1,101 @@
1
+ # Scalable Object-Level Authorization — Design & Plan
2
+
3
+ Status: DONE (all steps implemented, tested, documented)
4
+ Scope: `agentflow-api` (auth layer) + `agentflow` core (`aget_thread_owner` source-of-truth lookup)
5
+
6
+ ## Goal
7
+
8
+ Owner-only access to threads, enforced on **every** thread-touching step (invoke, stream,
9
+ stop, fix, and all checkpointer read/write/delete), **on by default in production** when the
10
+ developer enables auth, fully overridable, and **scalable** — no database round-trip per
11
+ request.
12
+
13
+ ## Design principles
14
+
15
+ 1. **Ownership is immutable.** A thread's owner is set at creation and never changes; only
16
+ deletion removes it. Therefore the owner is safe to cache aggressively (cache-forever)
17
+ and we essentially never re-hit the DB for a known thread.
18
+ 2. **Single decision point.** One `AuthorizationBackend`, invoked before every handler. No
19
+ per-endpoint bespoke checks.
20
+ 3. **Secure by construction.** No route can ship unprotected (enforced at boot).
21
+ 4. **Graceful degradation.** No checkpointer / a checkpointer that can't resolve ownership →
22
+ warn + allow (nothing persisted to protect). Redis is optional.
23
+
24
+ ## Components
25
+
26
+ ### 1. Source of truth: `aget_thread_owner` (core) — DONE
27
+
28
+ `BaseCheckpointer.aget_thread_owner(thread_id) -> user_id | None`:
29
+ - base: raises `NotImplementedError` (so a backend can't silently report "no owner", which
30
+ would defeat owner-based authorization).
31
+ - `PgCheckpointer`: `SELECT user_id FROM threads WHERE thread_id = $1`.
32
+ - `InMemoryCheckpointer`, `SqliteCheckpointer`: read the stored thread record's `user_id`.
33
+
34
+ This is the DB-level lookup the cache sits in front of. Already implemented + unit tested.
35
+
36
+ ### 2. `ThreadOwnershipResolver` (the scalable cache) — NEW (`agentflow-api`)
37
+
38
+ - **L1**: in-process LRU, bounded (default 10_000), immutable owners cached with **no TTL**.
39
+ - **L2**: Redis, reusing the app's existing Redis client when configured; key
40
+ `af:authz:owner:{thread_id}`. Gracefully L1-only when Redis is absent.
41
+ - `owner_of(thread_id) -> str | None`: L1 → L2 (fill L1) → DB `aget_thread_owner` (fill L2+L1).
42
+ **Only positive results are cached; `None` is never cached** — a nonexistent thread can
43
+ become owned by the very next request, so caching `None` would open a TOCTOU hole.
44
+ - `evict(thread_id)`: clears L1+L2. Called when a thread is deleted.
45
+ - Cost: first touch of a thread = 1 lookup; every subsequent request = in-process hit.
46
+
47
+ ### 3. `OwnershipAuthorizationBackend` — rewire to use the resolver
48
+
49
+ Decision table (cached; no raw DB call):
50
+ - no `user_id` → deny
51
+ - non-thread resource (`store`, `files`) → allow (they self-scope)
52
+ - no `resource_id` → allow (list/create endpoints)
53
+ - `owner = resolver.owner_of(resource_id)`:
54
+ - `None` → allow (brand-new session / empty read)
55
+ - `owner == user_id` → allow
56
+ - `owner != user_id` → **deny, for every action including invoke/stream**
57
+ - resolver reports unsupported backend → warn + allow; resolver error → fail closed (deny).
58
+
59
+ ### 4. Secure-by-construction enforcement (fail-closed at boot)
60
+
61
+ `assert_all_routes_protected(app)` runs at startup: walk every route; any non-public route
62
+ (allowlist: `/ping`) whose dependency tree lacks `RequirePermission` makes the server
63
+ **refuse to start** with a clear error. Keeps precise per-handler `(resource, action)`, adds
64
+ zero per-request overhead, and turns a forgotten guard into a deploy-time failure instead of
65
+ a silently-open production endpoint. (Delivers the "authorization on every step" guarantee
66
+ more robustly than a literal router dependency, which cannot cleanly derive each route's
67
+ action.)
68
+
69
+ ### 5. Invalidation
70
+
71
+ `CheckpointerService.delete_thread` (and the `aclean_thread` path) calls
72
+ `resolver.evict(thread_id)`.
73
+
74
+ ### 6. Config surface (unchanged)
75
+
76
+ `"authorization"`: `"ownership"` | `"allow_all"`/`"default"`/`"none"` | `"module:attr"` |
77
+ unset → `ownership` in production, `allow_all` in development. Developer choice always wins.
78
+
79
+ ## Test plan
80
+
81
+ - Resolver: L1 hit, L2 promote-to-L1, DB fill, negative-not-cached, evict, LRU bound.
82
+ - Backend: full decision table over the cached path.
83
+ - Startup invariant: a route missing `RequirePermission` → boot raises; allowlist passes.
84
+ - Integration: non-owner invoke/stream/read/delete → 403; owner → ok; second call served from
85
+ cache (asserted with a call-counting fake checkpointer — no second DB hit).
86
+ - Core: `aget_thread_owner` for in-memory/sqlite (done).
87
+
88
+ ## Docs
89
+
90
+ Update `docs/how-to/api-cli/add-auth.md` and `agentflow-api/CLAUDE.md`: caching model,
91
+ immutability, Redis opt-in, boot-time guarantee.
92
+
93
+ ## Execution order
94
+
95
+ 1. ThreadOwnershipResolver + unit tests.
96
+ 2. Rewire OwnershipAuthorizationBackend onto the resolver + update tests.
97
+ 3. Wire resolver into DI (loader) and evict on delete_thread.
98
+ 4. Startup invariant `assert_all_routes_protected` + boot wiring + tests.
99
+ 5. Integration tests (owner-only + cache-hit assertion).
100
+ 6. Docs.
101
+ 7. Full suite (api + core) green with coverage.
@@ -0,0 +1,34 @@
1
+ # Phase 2 — Policy-driven isolation (single source of truth, non-hijackable)
2
+
3
+ Problem: `user_id` scoping in the checkpointer is just data partitioning on a supplied id.
4
+ It's not authorization, and `allow_all` (authz) can contradict the data layer. Fix: one
5
+ **trusted policy**, set only by the server from auth, drives both.
6
+
7
+ ## The idea (short)
8
+
9
+ 1. **Trusted policy in config, server-only.** The API injects `config["policy"] = {"scope": ...}`
10
+ built from the active authorization backend. It **overwrites/strips** any client-sent
11
+ `policy` (and already overwrites `user_id`), so the frontend can send whatever it wants —
12
+ ignored. Not hijackable.
13
+ - `OwnershipAuthorizationBackend.isolation_scope()` -> `"owner"`
14
+ - `DefaultAuthorizationBackend` / others -> `"none"`
15
+
16
+ 2. **Checkpointer honors the policy.**
17
+ - `scope == "owner"` -> filter state/messages/threads by `user_id`.
18
+ - `scope == "none"` -> no filtering (allow_all genuinely returns everything).
19
+ - policy absent (direct core-lib call, no API) -> fall back to the checkpointer's own
20
+ `enforce_user_isolation` default (backward compatible).
21
+ Applies to pg (already scopes; make it read policy), **InMemory + sqlite (add scoping)**.
22
+
23
+ 3. **Coherent.** allow_all -> no 403 + no data scope. ownership -> 403 + data scope. Same
24
+ policy drives both decisions. Kills the dev/InMemory leak because scoping no longer depends
25
+ on which checkpointer happens to filter.
26
+
27
+ ## Steps
28
+ 1. `AuthorizationBackend.isolation_scope()` (base `"none"`, ownership `"owner"`).
29
+ 2. API config builders set trusted `config["policy"]` (checkpointer_service `_config`;
30
+ graph_service invoke/stream/stop/fix where `user_id` is set). Strip client `policy`.
31
+ 3. Checkpointer scoping reads `config["policy"]["scope"]` (pg/inmemory/sqlite), fallback to
32
+ `enforce_user_isolation`.
33
+ 4. Tests (non-owner blocked on InMemory too; allow_all returns everything; client-sent policy
34
+ ignored) + docs.
@@ -5,13 +5,16 @@ core framework see `agentflow/CLAUDE.md`; for the TS client, docs, or playground
5
5
  for the monorepo overview see the workspace-root `CLAUDE.md`.
6
6
 
7
7
  - Package name (PyPI): `10xscale-agentflow-cli`
8
- - Version: `0.3.2.9` (`pyproject.toml`). `CLI_VERSION` and `agentflow_cli.__version__` are
8
+ - Version: `0.4.0` (`pyproject.toml`). `CLI_VERSION` and `agentflow_cli.__version__` are
9
9
  single-sourced from the installed distribution metadata (falling back to `pyproject.toml`), so
10
- `agentflow version` reports `0.3.2.9` consistently. The previous `1.0.0` hardcode is gone.
10
+ `agentflow version` reports `0.4.0` consistently. The previous `1.0.0` hardcode is gone.
11
11
  - Requires: Python >= 3.12 · Status: `4 - Beta`
12
12
  - Console entry point: `agentflow = agentflow_cli.cli.main:main`
13
13
  - Depends on the core framework: `10xscale-agentflow>=0.7.0`.
14
14
 
15
+ - Depends on the core framework: `10xscale-agentflow>=0.9.0` (0.9.0 is the first release that
16
+ ships `agentflow.core.authz`, which the RBAC/scope code imports).
17
+
15
18
  ## What this package is
16
19
 
17
20
  It turns an Agentflow `CompiledGraph` into a production FastAPI service, plus a Typer CLI to
@@ -76,8 +79,25 @@ and for redis backend a `redis` sub-object `{ "url", "prefix" }` (or shorthand U
76
79
  load if missing). JWT logic lives in `core/auth/jwt_auth.py`.
77
80
  - `"auth": {"method": "custom", "path": "module:attr"}` loads your `BaseAuth` subclass
78
81
  (`from agentflow_cli import BaseAuth`).
79
- - Authorization (RBAC, per-tool) is separate: `core/auth/authorization.py`
80
- (`AuthorizationBackend` / `DefaultAuthorizationBackend`), wired via the `authorization` key.
82
+ - Authorization (RBAC / object-level) is separate: `core/auth/authorization.py`
83
+ (`AuthorizationBackend` / `DefaultAuthorizationBackend` / `OwnershipAuthorizationBackend`),
84
+ wired via the `authorization` key. That key accepts `"module:attr"` (custom), a built-in
85
+ name (`"ownership"` = owner-only thread access; `"allow_all"`/`"default"`/`"none"`), or
86
+ `null`. When unset it defaults **by mode**: `ownership` in production (secure by default),
87
+ `allow_all` in development. Selection lives in `loader._resolve_authorization_backend`;
88
+ `RequirePermission` passes `resource_id` (thread_id from path or body) to `authorize`.
89
+ - **Ownership is object-level and enforced on every thread-touching step** (invoke/stream/
90
+ stop/fix + all checkpointer read/write/delete): a thread is accessible only to its owner;
91
+ a foreign `invoke`/`stream` is rejected up front (403), never reaching the graph.
92
+ - **Scalable, not a DB call per request.** Ownership is immutable, so it is cached by
93
+ `core/auth/ownership_resolver.py::ThreadOwnershipResolver`: in-process LRU (L1) + optional
94
+ shared Redis (L2, reuses `config.redis`/`settings.REDIS_URL`). The backing lookup is
95
+ `BaseCheckpointer.aget_thread_owner` (implemented in pg/in-memory/sqlite; base raises
96
+ `NotImplementedError`). Cache is evicted on thread delete (`CheckpointerService.delete_thread`);
97
+ the L2 client is closed in the lifespan shutdown.
98
+ - **Secure by construction:** `core/auth/route_guard.py::assert_all_routes_protected` runs at
99
+ boot (`main.py` after `init_routes`) and refuses to start if any non-public route lacks a
100
+ `RequirePermission` guard (`/ping` is the only public path).
81
101
 
82
102
  ## HTTP + WebSocket surface (all under `/v1` except ping)
83
103
 
@@ -134,7 +154,7 @@ ruff check . && ruff format .
134
154
 
135
155
  - **Version is now single-sourced.** `CLI_VERSION` (and `agentflow_cli.__version__`, which aliases
136
156
  it) resolve from installed distribution metadata, falling back to `pyproject.toml`. `agentflow
137
- version` reports `0.3.2.9` for both the CLI and package lines. (The old hardcoded `1.0.0` drift is
157
+ version` reports `0.4.0` for both the CLI and package lines. (The old hardcoded `1.0.0` drift is
138
158
  resolved.)
139
159
  - **README shows `agentflow init --prod`** — that flag does not exist. `init` is interactive and
140
160
  only accepts `--path` / `--force`.