chattice 0.1.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 (372) hide show
  1. chattice-0.1.0/.gitignore +24 -0
  2. chattice-0.1.0/.python-version +2 -0
  3. chattice-0.1.0/CHANGELOG.md +29 -0
  4. chattice-0.1.0/CODE_OF_CONDUCT.md +6 -0
  5. chattice-0.1.0/CONTRIBUTING.md +73 -0
  6. chattice-0.1.0/LICENSE +21 -0
  7. chattice-0.1.0/PKG-INFO +210 -0
  8. chattice-0.1.0/PUBLIC_API.md +28 -0
  9. chattice-0.1.0/README.md +173 -0
  10. chattice-0.1.0/SECURITY.md +29 -0
  11. chattice-0.1.0/THIRD_PARTY_NOTICES.md +64 -0
  12. chattice-0.1.0/docs/adr/ADR-001-event-domain-model.md +50 -0
  13. chattice-0.1.0/docs/adr/ADR-002-dispatcher-router.md +53 -0
  14. chattice-0.1.0/docs/adr/ADR-003-raw-google-models.md +46 -0
  15. chattice-0.1.0/docs/adr/ADR-004-transport-abstraction.md +42 -0
  16. chattice-0.1.0/docs/adr/ADR-005-authentication-abstraction.md +46 -0
  17. chattice-0.1.0/docs/adr/ADR-006-fsm-key-strategy.md +45 -0
  18. chattice-0.1.0/docs/adr/ADR-007-cards-builder.md +45 -0
  19. chattice-0.1.0/docs/adr/ADR-008-sync-async-responses.md +50 -0
  20. chattice-0.1.0/docs/adr/ADR-009-google-interaction-normalization.md +55 -0
  21. chattice-0.1.0/docs/adr/ADR-010-project-identity.md +22 -0
  22. chattice-0.1.0/docs/adr/ADR-011-versioning-policy.md +25 -0
  23. chattice-0.1.0/docs/adr/index.md +21 -0
  24. chattice-0.1.0/docs/adr/template.md +26 -0
  25. chattice-0.1.0/docs/aiogram-comparison.md +237 -0
  26. chattice-0.1.0/docs/api.md +71 -0
  27. chattice-0.1.0/docs/architecture/authentication.md +126 -0
  28. chattice-0.1.0/docs/architecture/bot-api-client.md +129 -0
  29. chattice-0.1.0/docs/architecture/capabilities.md +166 -0
  30. chattice-0.1.0/docs/architecture/cards.md +115 -0
  31. chattice-0.1.0/docs/architecture/dependency-injection.md +43 -0
  32. chattice-0.1.0/docs/architecture/dialogs-app-home.md +179 -0
  33. chattice-0.1.0/docs/architecture/dispatcher-router.md +77 -0
  34. chattice-0.1.0/docs/architecture/event-model.md +102 -0
  35. chattice-0.1.0/docs/architecture/forms-vs-fsm-vs-scenes.md +123 -0
  36. chattice-0.1.0/docs/architecture/fsm.md +191 -0
  37. chattice-0.1.0/docs/architecture/google-interaction-adapter.md +124 -0
  38. chattice-0.1.0/docs/architecture/http-transport.md +50 -0
  39. chattice-0.1.0/docs/architecture/middleware.md +62 -0
  40. chattice-0.1.0/docs/architecture/observability.md +143 -0
  41. chattice-0.1.0/docs/architecture/overview.md +102 -0
  42. chattice-0.1.0/docs/architecture/pubsub.md +85 -0
  43. chattice-0.1.0/docs/architecture/reliability.md +191 -0
  44. chattice-0.1.0/docs/architecture/security.md +165 -0
  45. chattice-0.1.0/docs/architecture/testing.md +184 -0
  46. chattice-0.1.0/docs/architecture/transports.md +70 -0
  47. chattice-0.1.0/docs/architecture/workspace-events.md +134 -0
  48. chattice-0.1.0/docs/assets/brand/chattice-logo.png +0 -0
  49. chattice-0.1.0/docs/assets/brand/chattice-mark-black.png +0 -0
  50. chattice-0.1.0/docs/assets/brand/chattice-mark-white.png +0 -0
  51. chattice-0.1.0/docs/assets/brand/chattice-mark.png +0 -0
  52. chattice-0.1.0/docs/assets/brand/favicon.png +0 -0
  53. chattice-0.1.0/docs/assets/brand/github-avatar.png +0 -0
  54. chattice-0.1.0/docs/common-mistakes.md +57 -0
  55. chattice-0.1.0/docs/concepts/mental-model.md +87 -0
  56. chattice-0.1.0/docs/cookbook/recipes.md +211 -0
  57. chattice-0.1.0/docs/examples.md +42 -0
  58. chattice-0.1.0/docs/getting-started/authentication.md +122 -0
  59. chattice-0.1.0/docs/getting-started/first-deployment.md +56 -0
  60. chattice-0.1.0/docs/getting-started/google-chat-setup.md +95 -0
  61. chattice-0.1.0/docs/getting-started/installation.md +48 -0
  62. chattice-0.1.0/docs/getting-started/project-structure.md +27 -0
  63. chattice-0.1.0/docs/getting-started/quickstart.md +161 -0
  64. chattice-0.1.0/docs/guides/advanced-apis.md +56 -0
  65. chattice-0.1.0/docs/guides/auth-capabilities.md +130 -0
  66. chattice-0.1.0/docs/guides/cards-forms-dialogs.md +190 -0
  67. chattice-0.1.0/docs/guides/commands.md +73 -0
  68. chattice-0.1.0/docs/guides/deployment.md +230 -0
  69. chattice-0.1.0/docs/guides/enterprise.md +83 -0
  70. chattice-0.1.0/docs/guides/files-media.md +444 -0
  71. chattice-0.1.0/docs/guides/memberships-spaces.md +118 -0
  72. chattice-0.1.0/docs/guides/messages.md +131 -0
  73. chattice-0.1.0/docs/guides/routing-state.md +153 -0
  74. chattice-0.1.0/docs/guides/transports.md +95 -0
  75. chattice-0.1.0/docs/guides/workspace-events.md +77 -0
  76. chattice-0.1.0/docs/index.md +59 -0
  77. chattice-0.1.0/docs/llms.txt +53 -0
  78. chattice-0.1.0/docs/public-api.md +409 -0
  79. chattice-0.1.0/docs/reference/compatibility.md +29 -0
  80. chattice-0.1.0/docs/reference/google-api-mapping.md +42 -0
  81. chattice-0.1.0/docs/release/sbom-chattice.spdx.json +1712 -0
  82. chattice-0.1.0/docs/stability.md +52 -0
  83. chattice-0.1.0/docs/troubleshooting.md +169 -0
  84. chattice-0.1.0/examples/README.md +34 -0
  85. chattice-0.1.0/examples/__init__.py +1 -0
  86. chattice-0.1.0/examples/bots/__init__.py +11 -0
  87. chattice-0.1.0/examples/bots/buttons_bot.py +87 -0
  88. chattice-0.1.0/examples/bots/command_bot.py +74 -0
  89. chattice-0.1.0/examples/bots/dialog_bot.py +78 -0
  90. chattice-0.1.0/examples/bots/echo_bot.py +38 -0
  91. chattice-0.1.0/examples/bots/fastapi_bot.py +48 -0
  92. chattice-0.1.0/examples/bots/form_bot.py +78 -0
  93. chattice-0.1.0/examples/bots/fsm_bot.py +85 -0
  94. chattice-0.1.0/examples/bots/http_echo_bot.py +52 -0
  95. chattice-0.1.0/examples/bots/pubsub_bot.py +60 -0
  96. chattice-0.1.0/examples/bots/pubsub_pull_echo_bot.py +54 -0
  97. chattice-0.1.0/examples/bots/workspace_events_bot.py +50 -0
  98. chattice-0.1.0/examples/docs/__init__.py +1 -0
  99. chattice-0.1.0/examples/docs/from_zero.py +310 -0
  100. chattice-0.1.0/examples/docs/quickstart_app.py +29 -0
  101. chattice-0.1.0/examples/production/crm_workflow/__init__.py +1 -0
  102. chattice-0.1.0/examples/production/crm_workflow/main.py +252 -0
  103. chattice-0.1.0/examples/production/multi_space_notification.py +75 -0
  104. chattice-0.1.0/examples/scenarios/__init__.py +5 -0
  105. chattice-0.1.0/examples/scenarios/apphome_dashboard.py +66 -0
  106. chattice-0.1.0/examples/scenarios/buttons_menu.py +96 -0
  107. chattice-0.1.0/examples/scenarios/dynamic_employee_picker.py +51 -0
  108. chattice-0.1.0/examples/scenarios/link_preview.py +58 -0
  109. chattice-0.1.0/examples/scenarios/private_dialog_to_public_card.py +107 -0
  110. chattice-0.1.0/examples/scenarios/registration_dialog.py +112 -0
  111. chattice-0.1.0/examples/scenarios/registration_fsm.py +116 -0
  112. chattice-0.1.0/examples/scenarios/request_form.py +103 -0
  113. chattice-0.1.0/examples/scenarios/request_form_plus_fsm.py +161 -0
  114. chattice-0.1.0/examples/scenarios/text_triggers.py +64 -0
  115. chattice-0.1.0/llms.txt +53 -0
  116. chattice-0.1.0/mkdocs.yml +73 -0
  117. chattice-0.1.0/pyproject.toml +134 -0
  118. chattice-0.1.0/scripts/gen_llms_txt.py +64 -0
  119. chattice-0.1.0/scripts/gen_sbom.py +85 -0
  120. chattice-0.1.0/scripts/serve_smoke.sh +36 -0
  121. chattice-0.1.0/scripts/verify_package.sh +71 -0
  122. chattice-0.1.0/src/chattice/__init__.py +8 -0
  123. chattice-0.1.0/src/chattice/_json_snapshot.py +35 -0
  124. chattice-0.1.0/src/chattice/actions.py +223 -0
  125. chattice-0.1.0/src/chattice/adapters/__init__.py +1 -0
  126. chattice-0.1.0/src/chattice/adapters/google_chat/__init__.py +19 -0
  127. chattice-0.1.0/src/chattice/adapters/google_chat/envelope.py +80 -0
  128. chattice-0.1.0/src/chattice/adapters/google_chat/exceptions.py +25 -0
  129. chattice-0.1.0/src/chattice/adapters/google_chat/inputs.py +107 -0
  130. chattice-0.1.0/src/chattice/adapters/google_chat/interaction.py +20 -0
  131. chattice-0.1.0/src/chattice/adapters/google_chat/models.py +97 -0
  132. chattice-0.1.0/src/chattice/adapters/google_chat/parser.py +369 -0
  133. chattice-0.1.0/src/chattice/assets.py +23 -0
  134. chattice-0.1.0/src/chattice/auth/__init__.py +21 -0
  135. chattice-0.1.0/src/chattice/auth/providers.py +190 -0
  136. chattice-0.1.0/src/chattice/capabilities/__init__.py +25 -0
  137. chattice-0.1.0/src/chattice/capabilities/matrix.py +460 -0
  138. chattice-0.1.0/src/chattice/cards/__init__.py +46 -0
  139. chattice-0.1.0/src/chattice/cards/_assets.py +130 -0
  140. chattice-0.1.0/src/chattice/cards/accessory.py +40 -0
  141. chattice-0.1.0/src/chattice/cards/actions.py +67 -0
  142. chattice-0.1.0/src/chattice/cards/card.py +387 -0
  143. chattice-0.1.0/src/chattice/cards/dialog.py +54 -0
  144. chattice-0.1.0/src/chattice/cards/raw.py +55 -0
  145. chattice-0.1.0/src/chattice/cards/serialization.py +26 -0
  146. chattice-0.1.0/src/chattice/cards/status.py +42 -0
  147. chattice-0.1.0/src/chattice/cards/validation.py +48 -0
  148. chattice-0.1.0/src/chattice/cards/widgets.py +453 -0
  149. chattice-0.1.0/src/chattice/client/__init__.py +28 -0
  150. chattice-0.1.0/src/chattice/client/bot.py +1163 -0
  151. chattice-0.1.0/src/chattice/client/credentials.py +8 -0
  152. chattice-0.1.0/src/chattice/client/errors.py +119 -0
  153. chattice-0.1.0/src/chattice/dispatcher/__init__.py +8 -0
  154. chattice-0.1.0/src/chattice/dispatcher/dependency.py +189 -0
  155. chattice-0.1.0/src/chattice/dispatcher/dispatcher.py +302 -0
  156. chattice-0.1.0/src/chattice/dispatcher/handler.py +28 -0
  157. chattice-0.1.0/src/chattice/dispatcher/lifespan.py +87 -0
  158. chattice-0.1.0/src/chattice/dispatcher/middleware.py +57 -0
  159. chattice-0.1.0/src/chattice/dispatcher/observer.py +83 -0
  160. chattice-0.1.0/src/chattice/dispatcher/router.py +92 -0
  161. chattice-0.1.0/src/chattice/events/__init__.py +52 -0
  162. chattice-0.1.0/src/chattice/events/action.py +48 -0
  163. chattice-0.1.0/src/chattice/events/app_home.py +33 -0
  164. chattice-0.1.0/src/chattice/events/base.py +24 -0
  165. chattice-0.1.0/src/chattice/events/command.py +65 -0
  166. chattice-0.1.0/src/chattice/events/common.py +33 -0
  167. chattice-0.1.0/src/chattice/events/error.py +16 -0
  168. chattice-0.1.0/src/chattice/events/form.py +82 -0
  169. chattice-0.1.0/src/chattice/events/message.py +170 -0
  170. chattice-0.1.0/src/chattice/events/references.py +204 -0
  171. chattice-0.1.0/src/chattice/events/space.py +24 -0
  172. chattice-0.1.0/src/chattice/events/unknown.py +15 -0
  173. chattice-0.1.0/src/chattice/events/widget.py +26 -0
  174. chattice-0.1.0/src/chattice/exceptions/__init__.py +72 -0
  175. chattice-0.1.0/src/chattice/experimental/__init__.py +5 -0
  176. chattice-0.1.0/src/chattice/experimental/ai/__init__.py +35 -0
  177. chattice-0.1.0/src/chattice/experimental/ai/google.py +248 -0
  178. chattice-0.1.0/src/chattice/experimental/ai/models.py +168 -0
  179. chattice-0.1.0/src/chattice/filters/__init__.py +14 -0
  180. chattice-0.1.0/src/chattice/filters/base.py +65 -0
  181. chattice-0.1.0/src/chattice/filters/magic.py +237 -0
  182. chattice-0.1.0/src/chattice/forms.py +164 -0
  183. chattice-0.1.0/src/chattice/fsm/__init__.py +50 -0
  184. chattice-0.1.0/src/chattice/fsm/context.py +55 -0
  185. chattice-0.1.0/src/chattice/fsm/filter.py +39 -0
  186. chattice-0.1.0/src/chattice/fsm/record.py +405 -0
  187. chattice-0.1.0/src/chattice/fsm/redis.py +134 -0
  188. chattice-0.1.0/src/chattice/fsm/states.py +60 -0
  189. chattice-0.1.0/src/chattice/fsm/storage.py +132 -0
  190. chattice-0.1.0/src/chattice/idempotency.py +318 -0
  191. chattice-0.1.0/src/chattice/integrations/__init__.py +1 -0
  192. chattice-0.1.0/src/chattice/integrations/fastapi/__init__.py +13 -0
  193. chattice-0.1.0/src/chattice/integrations/fastapi/router.py +567 -0
  194. chattice-0.1.0/src/chattice/integrations/gcs/__init__.py +126 -0
  195. chattice-0.1.0/src/chattice/media/__init__.py +380 -0
  196. chattice-0.1.0/src/chattice/media/_rest.py +130 -0
  197. chattice-0.1.0/src/chattice/middleware.py +40 -0
  198. chattice-0.1.0/src/chattice/observability.py +25 -0
  199. chattice-0.1.0/src/chattice/py.typed +1 -0
  200. chattice-0.1.0/src/chattice/testing/__init__.py +16 -0
  201. chattice-0.1.0/src/chattice/testing/assertions.py +46 -0
  202. chattice-0.1.0/src/chattice/testing/event_factory.py +203 -0
  203. chattice-0.1.0/src/chattice/testing/fake_transport.py +308 -0
  204. chattice-0.1.0/src/chattice/testing/fsm.py +13 -0
  205. chattice-0.1.0/src/chattice/testing/mock_bot.py +185 -0
  206. chattice-0.1.0/src/chattice/transports/__init__.py +1 -0
  207. chattice-0.1.0/src/chattice/transports/http/__init__.py +29 -0
  208. chattice-0.1.0/src/chattice/transports/http/adapter.py +51 -0
  209. chattice-0.1.0/src/chattice/transports/http/errors.py +18 -0
  210. chattice-0.1.0/src/chattice/transports/http/request.py +46 -0
  211. chattice-0.1.0/src/chattice/transports/http/response.py +83 -0
  212. chattice-0.1.0/src/chattice/transports/http/verifier.py +154 -0
  213. chattice-0.1.0/src/chattice/transports/pubsub.py +159 -0
  214. chattice-0.1.0/src/chattice/transports/pubsub_runner.py +479 -0
  215. chattice-0.1.0/src/chattice/workspace_events/__init__.py +20 -0
  216. chattice-0.1.0/src/chattice/workspace_events/envelope.py +35 -0
  217. chattice-0.1.0/src/chattice/workspace_events/parser.py +246 -0
  218. chattice-0.1.0/src/chattice/workspace_events/runtime.py +340 -0
  219. chattice-0.1.0/tests/__init__.py +0 -0
  220. chattice-0.1.0/tests/auth/__init__.py +0 -0
  221. chattice-0.1.0/tests/auth/test_bot_auth.py +161 -0
  222. chattice-0.1.0/tests/auth/test_experimental_namespace.py +30 -0
  223. chattice-0.1.0/tests/auth/test_providers.py +111 -0
  224. chattice-0.1.0/tests/capabilities/__init__.py +0 -0
  225. chattice-0.1.0/tests/capabilities/test_gate.py +52 -0
  226. chattice-0.1.0/tests/capabilities/test_matrix.py +143 -0
  227. chattice-0.1.0/tests/capabilities/test_scope_hardening.py +183 -0
  228. chattice-0.1.0/tests/cards/__init__.py +0 -0
  229. chattice-0.1.0/tests/cards/test_actions.py +30 -0
  230. chattice-0.1.0/tests/cards/test_asset_publishing.py +290 -0
  231. chattice-0.1.0/tests/cards/test_card.py +126 -0
  232. chattice-0.1.0/tests/cards/test_dialog.py +26 -0
  233. chattice-0.1.0/tests/cards/test_dialog_observers.py +90 -0
  234. chattice-0.1.0/tests/cards/test_form_roundtrip.py +65 -0
  235. chattice-0.1.0/tests/cards/test_form_widgets.py +68 -0
  236. chattice-0.1.0/tests/cards/test_gate.py +76 -0
  237. chattice-0.1.0/tests/cards/test_gate_apphome.py +66 -0
  238. chattice-0.1.0/tests/cards/test_gate_dialog.py +105 -0
  239. chattice-0.1.0/tests/cards/test_image.py +66 -0
  240. chattice-0.1.0/tests/cards/test_roundtrip.py +91 -0
  241. chattice-0.1.0/tests/cards/test_serialization.py +34 -0
  242. chattice-0.1.0/tests/cards/test_snapshots.py +56 -0
  243. chattice-0.1.0/tests/cards/test_status.py +27 -0
  244. chattice-0.1.0/tests/cards/test_validation.py +22 -0
  245. chattice-0.1.0/tests/cards/test_widgets.py +112 -0
  246. chattice-0.1.0/tests/client/__init__.py +0 -0
  247. chattice-0.1.0/tests/client/_fake_transport.py +5 -0
  248. chattice-0.1.0/tests/client/test_bot_close.py +121 -0
  249. chattice-0.1.0/tests/client/test_bot_crud.py +99 -0
  250. chattice-0.1.0/tests/client/test_bot_errors.py +67 -0
  251. chattice-0.1.0/tests/client/test_bot_lazy.py +57 -0
  252. chattice-0.1.0/tests/client/test_bot_lifecycle.py +158 -0
  253. chattice-0.1.0/tests/client/test_bot_memberships.py +254 -0
  254. chattice-0.1.0/tests/client/test_bot_privacy.py +167 -0
  255. chattice-0.1.0/tests/client/test_bot_send.py +123 -0
  256. chattice-0.1.0/tests/client/test_credentials.py +18 -0
  257. chattice-0.1.0/tests/client/test_errors.py +85 -0
  258. chattice-0.1.0/tests/client/test_fake_transport.py +49 -0
  259. chattice-0.1.0/tests/client/test_integration.py +74 -0
  260. chattice-0.1.0/tests/client/test_resource_names_f13.py +50 -0
  261. chattice-0.1.0/tests/fixtures/google_chat/conformance/README.md +23 -0
  262. chattice-0.1.0/tests/fixtures/google_chat/conformance/dm_card_click.json +29 -0
  263. chattice-0.1.0/tests/fixtures/google_chat/conformance/private_card_button.json +30 -0
  264. chattice-0.1.0/tests/fixtures/google_chat/conformance/private_card_form.json +37 -0
  265. chattice-0.1.0/tests/fixtures/google_chat/conformance/private_command.json +21 -0
  266. chattice-0.1.0/tests/fixtures/google_chat/conformance/shared_thread_card_click_user_a.json +30 -0
  267. chattice-0.1.0/tests/fixtures/google_chat/conformance/shared_thread_card_click_user_b.json +30 -0
  268. chattice-0.1.0/tests/fixtures/google_chat/interactions/README.md +44 -0
  269. chattice-0.1.0/tests/fixtures/google_chat/interactions/added_to_space.json +5 -0
  270. chattice-0.1.0/tests/fixtures/google_chat/interactions/app_command.json +8 -0
  271. chattice-0.1.0/tests/fixtures/google_chat/interactions/app_home.json +7 -0
  272. chattice-0.1.0/tests/fixtures/google_chat/interactions/app_home_card_clicked.json +10 -0
  273. chattice-0.1.0/tests/fixtures/google_chat/interactions/card_clicked.json +16 -0
  274. chattice-0.1.0/tests/fixtures/google_chat/interactions/card_clicked_cancel_dialog.json +6 -0
  275. chattice-0.1.0/tests/fixtures/google_chat/interactions/card_clicked_form.json +14 -0
  276. chattice-0.1.0/tests/fixtures/google_chat/interactions/card_clicked_human_message.json +37 -0
  277. chattice-0.1.0/tests/fixtures/google_chat/interactions/card_clicked_request_dialog.json +6 -0
  278. chattice-0.1.0/tests/fixtures/google_chat/interactions/card_clicked_submit_dialog.json +9 -0
  279. chattice-0.1.0/tests/fixtures/google_chat/interactions/malformed_conflict.json +1 -0
  280. chattice-0.1.0/tests/fixtures/google_chat/interactions/malformed_missing_type.json +1 -0
  281. chattice-0.1.0/tests/fixtures/google_chat/interactions/malformed_timestamp.json +1 -0
  282. chattice-0.1.0/tests/fixtures/google_chat/interactions/malformed_type.json +1 -0
  283. chattice-0.1.0/tests/fixtures/google_chat/interactions/message.json +12 -0
  284. chattice-0.1.0/tests/fixtures/google_chat/interactions/message_action.json +15 -0
  285. chattice-0.1.0/tests/fixtures/google_chat/interactions/message_matched_url.json +21 -0
  286. chattice-0.1.0/tests/fixtures/google_chat/interactions/removed_from_space.json +5 -0
  287. chattice-0.1.0/tests/fixtures/google_chat/interactions/slash_command.json +22 -0
  288. chattice-0.1.0/tests/fixtures/google_chat/interactions/submit_form.json +12 -0
  289. chattice-0.1.0/tests/fixtures/google_chat/interactions/unknown_event.json +5 -0
  290. chattice-0.1.0/tests/fixtures/google_chat/interactions/widget_updated.json +8 -0
  291. chattice-0.1.0/tests/fsm/__init__.py +0 -0
  292. chattice-0.1.0/tests/fsm/test_context.py +52 -0
  293. chattice-0.1.0/tests/fsm/test_dispatcher_integration.py +84 -0
  294. chattice-0.1.0/tests/fsm/test_filter.py +54 -0
  295. chattice-0.1.0/tests/fsm/test_gate.py +91 -0
  296. chattice-0.1.0/tests/fsm/test_memory_storage.py +58 -0
  297. chattice-0.1.0/tests/fsm/test_record.py +256 -0
  298. chattice-0.1.0/tests/fsm/test_redis_storage.py +80 -0
  299. chattice-0.1.0/tests/fsm/test_states.py +36 -0
  300. chattice-0.1.0/tests/fsm/test_storage_key.py +63 -0
  301. chattice-0.1.0/tests/integration/__init__.py +0 -0
  302. chattice-0.1.0/tests/integration/live/README.md +79 -0
  303. chattice-0.1.0/tests/integration/live/__init__.py +0 -0
  304. chattice-0.1.0/tests/integration/live/test_smoke.py +165 -0
  305. chattice-0.1.0/tests/integration/test_personal_shared_conformance.py +466 -0
  306. chattice-0.1.0/tests/integrations/test_gcs_assets.py +223 -0
  307. chattice-0.1.0/tests/media/__init__.py +0 -0
  308. chattice-0.1.0/tests/media/test_attachment_identity.py +350 -0
  309. chattice-0.1.0/tests/media/test_attachment_ref.py +103 -0
  310. chattice-0.1.0/tests/media/test_bot_media.py +440 -0
  311. chattice-0.1.0/tests/media/test_inputfile.py +200 -0
  312. chattice-0.1.0/tests/media/test_media_rest.py +202 -0
  313. chattice-0.1.0/tests/media/test_message_attachment_refs.py +39 -0
  314. chattice-0.1.0/tests/reliability/__init__.py +0 -0
  315. chattice-0.1.0/tests/reliability/test_gate.py +206 -0
  316. chattice-0.1.0/tests/reliability/test_idempotency.py +134 -0
  317. chattice-0.1.0/tests/reliability/test_observability.py +79 -0
  318. chattice-0.1.0/tests/reliability/test_redaction.py +176 -0
  319. chattice-0.1.0/tests/reliability/test_redis_lifecycle_f09.py +119 -0
  320. chattice-0.1.0/tests/reliability/test_timeout_cancellation.py +64 -0
  321. chattice-0.1.0/tests/test_accessory_widgets.py +110 -0
  322. chattice-0.1.0/tests/test_actions.py +198 -0
  323. chattice-0.1.0/tests/test_ai.py +296 -0
  324. chattice-0.1.0/tests/test_ai_gemini_hardening.py +170 -0
  325. chattice-0.1.0/tests/test_apphome_integration.py +118 -0
  326. chattice-0.1.0/tests/test_architecture.py +236 -0
  327. chattice-0.1.0/tests/test_cards_integration.py +243 -0
  328. chattice-0.1.0/tests/test_codec_form_card_f11.py +154 -0
  329. chattice-0.1.0/tests/test_command_routing.py +122 -0
  330. chattice-0.1.0/tests/test_dependency.py +135 -0
  331. chattice-0.1.0/tests/test_dialog_envelope_truth_table.py +223 -0
  332. chattice-0.1.0/tests/test_dialog_integration.py +158 -0
  333. chattice-0.1.0/tests/test_dispatcher.py +192 -0
  334. chattice-0.1.0/tests/test_documentation_examples.py +45 -0
  335. chattice-0.1.0/tests/test_dx_enrichment.py +249 -0
  336. chattice-0.1.0/tests/test_events.py +55 -0
  337. chattice-0.1.0/tests/test_examples.py +121 -0
  338. chattice-0.1.0/tests/test_fastapi_integration.py +282 -0
  339. chattice-0.1.0/tests/test_filters.py +279 -0
  340. chattice-0.1.0/tests/test_forms.py +127 -0
  341. chattice-0.1.0/tests/test_gap_hardening.py +148 -0
  342. chattice-0.1.0/tests/test_google_interactions.py +445 -0
  343. chattice-0.1.0/tests/test_immutable_facades_f10.py +82 -0
  344. chattice-0.1.0/tests/test_lifespan.py +77 -0
  345. chattice-0.1.0/tests/test_log_redaction.py +140 -0
  346. chattice-0.1.0/tests/test_middleware.py +176 -0
  347. chattice-0.1.0/tests/test_persistent_actions.py +104 -0
  348. chattice-0.1.0/tests/test_pubsub_workspace_integration.py +423 -0
  349. chattice-0.1.0/tests/test_raw_and_validation.py +140 -0
  350. chattice-0.1.0/tests/test_regexp_filters.py +72 -0
  351. chattice-0.1.0/tests/test_router.py +198 -0
  352. chattice-0.1.0/tests/testing/__init__.py +0 -0
  353. chattice-0.1.0/tests/testing/test_assertions_fsm.py +56 -0
  354. chattice-0.1.0/tests/testing/test_event_factory.py +70 -0
  355. chattice-0.1.0/tests/testing/test_gate.py +23 -0
  356. chattice-0.1.0/tests/testing/test_mock_bot.py +75 -0
  357. chattice-0.1.0/tests/transports/__init__.py +0 -0
  358. chattice-0.1.0/tests/transports/http/__init__.py +0 -0
  359. chattice-0.1.0/tests/transports/http/_test_tokens.py +91 -0
  360. chattice-0.1.0/tests/transports/http/test_adapter.py +58 -0
  361. chattice-0.1.0/tests/transports/http/test_errors.py +22 -0
  362. chattice-0.1.0/tests/transports/http/test_pubsub.py +68 -0
  363. chattice-0.1.0/tests/transports/http/test_request.py +46 -0
  364. chattice-0.1.0/tests/transports/http/test_response.py +38 -0
  365. chattice-0.1.0/tests/transports/http/test_verifier.py +325 -0
  366. chattice-0.1.0/tests/transports/test_pubsub_runner.py +487 -0
  367. chattice-0.1.0/tests/transports/test_pubsub_verifier.py +97 -0
  368. chattice-0.1.0/tests/workspace_events/__init__.py +0 -0
  369. chattice-0.1.0/tests/workspace_events/test_gate.py +86 -0
  370. chattice-0.1.0/tests/workspace_events/test_observer.py +71 -0
  371. chattice-0.1.0/tests/workspace_events/test_parser.py +393 -0
  372. chattice-0.1.0/uv.lock +2458 -0
@@ -0,0 +1,24 @@
1
+ .venv/
2
+ .coverage
3
+ .mypy_cache/
4
+ .pytest_cache/
5
+ .ruff_cache/
6
+ __pycache__/
7
+ *.py[cod]
8
+ build/
9
+ dist/
10
+ site/
11
+ *.egg-info/
12
+ .DS_Store
13
+
14
+ .coverage*
15
+
16
+ .secrets/
17
+ token.json
18
+ oauth-client.json
19
+ service-account*.json
20
+
21
+ # macOS synchronization duplicates.
22
+ * [0-9]
23
+ * [0-9].*
24
+ .env
@@ -0,0 +1,2 @@
1
+ 3.11
2
+
@@ -0,0 +1,29 @@
1
+ # Changelog
2
+
3
+ All notable changes are documented here. The project follows Semantic
4
+ Versioning. Before 1.0, incompatible changes may be released in a minor
5
+ version and will include migration notes.
6
+
7
+ ## [0.1.0] — Initial public release
8
+
9
+ ### Added
10
+
11
+ - Async dispatcher, routers, middleware, dependency injection, filters, and
12
+ typed Google Chat interaction events.
13
+ - HTTP, Pub/Sub, streaming-pull, and Google Workspace Events integrations.
14
+ - Async Google Chat API client with app and delegated-user authentication.
15
+ - Typed Cards v2 builders, dialogs, forms, App Home responses, card updates,
16
+ attachments, and optional Card image publishing.
17
+ - Finite-state storage, idempotency storage, Redis integrations, lifecycle
18
+ resources, and observability hooks.
19
+ - FastAPI integration, testing helpers, runnable examples, API reference, and
20
+ deployment guidance.
21
+ - Raw Google payload and client escape hatches for forward compatibility.
22
+ - Automated dependency, Google Chat schema, Cards SDK, and release-note
23
+ monitoring.
24
+
25
+ ### Compatibility
26
+
27
+ - Python 3.11, 3.12, and 3.13.
28
+ - Google Chat API v1 and Cards v2.
29
+ - The package distribution and Python import are both named `chattice`.
@@ -0,0 +1,6 @@
1
+ # Code of Conduct
2
+
3
+ Be respectful, constructive, and honest. No harassment, discrimination,
4
+ or hostile behavior. Maintainers may remove contributions or
5
+ participation that violates this. If you experience or witness a
6
+ problem, contact the maintainers privately.
@@ -0,0 +1,73 @@
1
+ # Contributing to Chattice
2
+
3
+ Chattice is an async Python framework for Google Chat apps. Contributions
4
+ that are naturally additive are the most welcome:
5
+
6
+ - new Google UI support (widgets, cards)
7
+ - Google API wrappers behind the raw escape hatch pattern
8
+ - tests, examples, docs, bug fixes
9
+
10
+ ## Workflow
11
+
12
+ 1. Open an issue describing the problem or idea (no PR-first for
13
+ architectural changes — see the RFC rule below).
14
+ 2. Branch off `main`; implement with tests.
15
+ 3. Run the full gate suite:
16
+
17
+ ```bash
18
+ uv sync --all-groups
19
+ uv run pytest -q
20
+ uv run mypy src tests
21
+ uv run ruff check . && uv run ruff format --check .
22
+ uv run mkdocs build --strict
23
+ bash scripts/verify_package.sh
24
+ ```
25
+
26
+ 4. Open a PR. The description must state: the problem, public API
27
+ impact, compatibility impact, tests/docs added, risk level, and
28
+ whether core changed.
29
+
30
+ ## Rules
31
+
32
+ - New examples must expose a `main()` executed from
33
+ `tests/test_examples.py` (docs can never drift).
34
+ - Fixtures must be official payload shapes with provenance recorded in
35
+ `tests/fixtures/google_chat/interactions/README.md`.
36
+ - Public API changes require the public-API rule (charter §7): typing,
37
+ tests, docs, deliberate export, compatibility review.
38
+ - Architectural changes (Dispatcher/Router/FSM contracts, new workflow
39
+ engines, package splits, breaking API) require a lightweight design
40
+ proposal first: Problem · Current behavior · Proposed API · Why the
41
+ current API is insufficient · Alternatives · Compatibility ·
42
+ Migration · Maintenance cost · Simpler solutions rejected.
43
+
44
+ ## License
45
+
46
+ MIT. By contributing you agree your contributions are licensed
47
+ under it. No CLA required.
48
+
49
+ ## Upstream Google changes
50
+
51
+ Google updates the wire layer (`google-apps-chat`, `google-apps-card`)
52
+ and ships Developer Preview features continuously. The documented public
53
+ surface changes deliberately, so every upstream change follows one protocol:
54
+
55
+ 1. An update PR arrives from dependabot (weekly, `google-sdks` group)
56
+ or from the weekly `upstream-check` workflow's `upstream` issue.
57
+ 2. CI runs the full suite, mypy/ruff, and the golden fixtures.
58
+ 3. Wire analysis of the SDK diff:
59
+ - a new event FIELD → keep it lossless (`raw`), add a round-trip
60
+ test; no public API change;
61
+ - a new event TYPE → decide: typed support (adapter + capability)
62
+ or explicit `UnknownEvent`; update the Google API mapping and the
63
+ capabilities matrix;
64
+ - a breaking change → P0 issue, a Chattice semver decision (rare).
65
+ 4. Update fixtures (reviewed), docs (mapping/capabilities), and the
66
+ compatibility revision.
67
+ 5. Pre-release: run every example (the `examples/docs/from_zero.py`
68
+ journey plus the bots/scenarios).
69
+
70
+ Principles: Google updates are additive INSIDE the adapters; the public
71
+ Chattice surface changes only by Chattice's own semver decision. The
72
+ lossless paths (`UnknownEvent`, `RawWidget`, `Bot.raw_client`) absorb
73
+ new Google types — a new type must never crash existing bots.
chattice-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Chattice contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,210 @@
1
+ Metadata-Version: 2.5
2
+ Name: chattice
3
+ Version: 0.1.0
4
+ Summary: Async typed event framework for Google Chat apps
5
+ Project-URL: Documentation, https://whiteysage.github.io/chattice/
6
+ Project-URL: Source, https://github.com/WhiteySage/chattice
7
+ Project-URL: Issues, https://github.com/WhiteySage/chattice/issues
8
+ Project-URL: Changelog, https://github.com/WhiteySage/chattice/blob/main/CHANGELOG.md
9
+ Author: WhiteySage
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Framework :: AsyncIO
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Typing :: Typed
20
+ Requires-Python: >=3.11
21
+ Requires-Dist: google-apps-chat<1.0.0,>=0.10.4
22
+ Requires-Dist: google-auth<3,>=2.30
23
+ Requires-Dist: pydantic<3.0,>=2.10
24
+ Provides-Extra: fastapi
25
+ Requires-Dist: fastapi<1,>=0.115; extra == 'fastapi'
26
+ Provides-Extra: gcs
27
+ Requires-Dist: google-cloud-storage<4,>=3; extra == 'gcs'
28
+ Provides-Extra: gemini
29
+ Requires-Dist: google-genai<3,>=1; extra == 'gemini'
30
+ Provides-Extra: media
31
+ Requires-Dist: google-api-python-client<3,>=2.198; extra == 'media'
32
+ Provides-Extra: pubsub
33
+ Requires-Dist: google-cloud-pubsub<3,>=2.21; extra == 'pubsub'
34
+ Provides-Extra: redis
35
+ Requires-Dist: redis<7,>=5; extra == 'redis'
36
+ Description-Content-Type: text/markdown
37
+
38
+ <img src="https://raw.githubusercontent.com/WhiteySage/chattice/main/docs/assets/brand/chattice-logo.png"
39
+ alt="Chattice" width="320" />
40
+
41
+ # Chattice
42
+
43
+ Async, typed event framework for Google Chat apps — aiogram-quality DX, Google-native semantics.
44
+
45
+ [![Python](https://img.shields.io/badge/python-3.11%20%7C%203.12%20%7C%203.13-blue)](https://pypi.org/project/chattice/)
46
+ [![License](https://img.shields.io/badge/license-MIT-green)](LICENSE)
47
+ [![Status](https://img.shields.io/badge/status-pre--1.0-orange)](#status)
48
+ [![Discussions](https://img.shields.io/badge/discussions-questions%20%26%20help-blue)](https://github.com/WhiteySage/chattice/discussions)
49
+
50
+ ```python
51
+ from chattice import Dispatcher, F, Router
52
+ from chattice.events import MessageEvent
53
+
54
+ router = Router()
55
+
56
+
57
+ @router.message(F.text == "ping")
58
+ async def ping(message: MessageEvent) -> str:
59
+ return "pong" # synchronous interaction response (no auth, 30 s deadline)
60
+
61
+
62
+ dispatcher = Dispatcher()
63
+ dispatcher.include_router(router)
64
+ ```
65
+
66
+ ## What this is
67
+
68
+ - **Google Chat-native.** Space, Thread, Message, Command, Action, Card,
69
+ Dialog, App Home, Workspace Events are first-class typed objects. No
70
+ Telegram concepts leak into the domain model.
71
+ - **aiogram ergonomics.** Routers, magic filters (`F`), middleware,
72
+ dependency injection, FSM — the DX you know, without Telegram
73
+ semantics.
74
+ - **Explicit response model.** A handler RETURN is the synchronous
75
+ interaction response (30 s deadline); outbound `Bot` calls are
76
+ separate authenticated operations. Contextual `message.reply()` /
77
+ `thread.send()` / `space.send()` methods are zero-fetch adapters over
78
+ that same Bot, never a hidden second channel.
79
+ - **Secure by default.** Incoming verification is fail-closed, push
80
+ endpoints require a verifier, outbound privacy gates (private
81
+ messages, notifications, preview features) fail closed before any
82
+ network call.
83
+ - **Core is small.** Core abstracts Google Chat platform primitives and
84
+ technical boilerplate ONLY. Business scenarios (polls, approvals,
85
+ tickets) are assembled from the primitives in your
86
+ application code — never added to core.
87
+
88
+ ## What this is not
89
+
90
+ - **Not a Telegram framework.** No `chat_id`, no `CallbackQuery`, no
91
+ `Update` hierarchy, no Telegram-style long polling (see the
92
+ [aiogram comparison](https://whiteysage.github.io/chattice/aiogram-comparison/)).
93
+ - **Not a Google product.** Independent open-source project, not
94
+ endorsed by Google.
95
+
96
+ ## Two ways to run
97
+
98
+ Chattice has two honest startup models (see the
99
+ [aiogram side-by-side](docs/aiogram-comparison.md)):
100
+
101
+ ```python
102
+ # HTTP — Google calls your HTTPS endpoint; the handler RETURN is the
103
+ # synchronous response (Dialogs and App Home work here).
104
+ app.include_router(create_chat_router(dispatcher, GoogleTokenVerifier(audience=...)))
105
+ # python -m uvicorn app:app
106
+
107
+ # Pub/Sub streaming pull — a persistent subscriber process, visually
108
+ # like aiogram's start_polling, but it is NOT Telegram polling.
109
+ # No domain/TLS needed; no Dialogs, no App Home — answers go outbound
110
+ # through the authenticated Bot.
111
+ await dispatcher.run_pubsub(subscription, bot=bot)
112
+ # python app.py
113
+ ```
114
+
115
+ ## Capabilities
116
+
117
+ | Area | Support |
118
+ | --- | --- |
119
+ | Events | MESSAGE, CARD_CLICKED, APP_COMMAND (slash/quick/message actions), ADDED/REMOVED_FROM_SPACE, APP_HOME, SUBMIT_FORM, WIDGET_UPDATED |
120
+ | Routing | Routers, observer-wide filters, magic filters, middleware, DI |
121
+ | Cards | Typed facades, public/non-sensitive PNG/JPEG publication through an optional AssetPublisher, sync updates |
122
+ | Memberships | APP-auth add/get/list/remove for internal human users; caller-member Space listing |
123
+ | Dialogs | OPEN_DIALOG, submit/cancel observers, action status; capability-gated per transport |
124
+ | FSM | State/StatesGroup, Memory + Redis record storage (compare-and-set) |
125
+ | Ingress | HTTP (verified), Pub/Sub push (verified), Pub/Sub streaming pull, Workspace Events CloudEvents |
126
+ | Media | Local-file attachments sent with USER auth end to end (`media.upload` → `messages.create`, sender = HUMAN); download USER/APP; metadata APP; 200 MB local preflight |
127
+ | Auth | App (service account), user (OAuth refresh), incoming verification |
128
+ | Testing | MockBot, EventFactory, assertions, fake transport |
129
+
130
+ ## Install
131
+
132
+ Python 3.11+ (3.11–3.13 tested). MIT-licensed.
133
+
134
+ ```bash
135
+ pip install "chattice[fastapi,pubsub,redis]" # core + all integrations
136
+
137
+ # or pick only what you need:
138
+ # pip install chattice core
139
+ # pip install "chattice[fastapi]" FastAPI integration
140
+ # pip install "chattice[redis]" Redis FSM/idempotency storage
141
+ # pip install "chattice[pubsub]" Pub/Sub push + streaming pull
142
+ # pip install "chattice[gcs]" Local Card image publication through GCS
143
+
144
+ # using uv
145
+ uv add "chattice[fastapi,pubsub,redis]"
146
+ ```
147
+
148
+ ## Quickstart
149
+
150
+ 1. Parse a documented interaction payload:
151
+
152
+ ```python
153
+ from chattice.adapters.google_chat import parse_interaction
154
+
155
+ event = parse_interaction(payload)
156
+ result = await dispatcher.feed_update(event)
157
+ ```
158
+
159
+ 2. Serve HTTP interactions (FastAPI):
160
+
161
+ ```python
162
+ from fastapi import FastAPI
163
+ from chattice.integrations.fastapi import create_chat_router
164
+ from chattice.transports.http import GoogleTokenVerifier
165
+
166
+ app = FastAPI()
167
+ app.include_router(create_chat_router(dispatcher, GoogleTokenVerifier(audience="...")))
168
+ ```
169
+
170
+ 3. Send messages:
171
+
172
+ ```python
173
+ from chattice.client import Bot
174
+
175
+ bot = Bot(credentials=...)
176
+ await bot.send_message("spaces/AAA", text="hello")
177
+ ```
178
+
179
+ Inside an interaction handler, configure the same Bot once and use the known
180
+ Google context without extra fetches:
181
+
182
+ ```python
183
+ dispatcher = Dispatcher(bot=bot)
184
+
185
+
186
+ @router.message()
187
+ async def reply(message: MessageEvent) -> None:
188
+ await message.reply("hello in this thread")
189
+ ```
190
+
191
+ ## Docs
192
+
193
+ Start with [Installation](https://whiteysage.github.io/chattice/getting-started/installation/), the
194
+ [5-minute Quickstart](https://whiteysage.github.io/chattice/getting-started/quickstart/), and the
195
+ [Space → Thread → Message mental model](https://whiteysage.github.io/chattice/concepts/mental-model/). The
196
+ [public API reference](https://whiteysage.github.io/chattice/public-api/), [Google mapping](https://whiteysage.github.io/chattice/reference/google-api-mapping/),
197
+ and [aiogram comparison](https://whiteysage.github.io/chattice/aiogram-comparison/) are linked from the docs site.
198
+ Runnable examples live in [`examples/`](https://github.com/WhiteySage/chattice/tree/main/examples); machine-readable documentation is available in
199
+ [`llms.txt`](https://whiteysage.github.io/chattice/llms.txt).
200
+
201
+ ## Status
202
+
203
+ Pre-1.0 **public release** (current version 0.1.0) — see
204
+ [CHANGELOG](CHANGELOG.md). The documented public
205
+ surface is the compatibility baseline: pre-1.0 work may add APIs but does not incompatibly
206
+ rename, remove, or change existing contracts. `chattice.experimental`
207
+ has no compatibility promise. `Bot.raw_client` and raw event payloads
208
+ follow Google's SDK and wire schema rather than the stable facade
209
+ promise. **Not an official Google product** — independent open-source
210
+ software, not endorsed by Google. MIT License, see [LICENSE](https://github.com/WhiteySage/chattice/blob/main/LICENSE).
@@ -0,0 +1,28 @@
1
+ # PUBLIC_API — machine-readable index
2
+
3
+ This file is the compact machine-readable index. The full
4
+ human reference: `docs/public-api.md`; rendered signatures:
5
+ `docs/api.md`. Architecture test `tests/test_architecture.py::test_every_public_export_is_importable` pins every package's `__all__`; the canonical entry-point rule lives in `docs/public-api.md`.
6
+
7
+ - chattice: Dispatcher · Router · F · __version__
8
+ - chattice.actions: ActionData (`function=` discriminator binding) · ActionDataDecodeError · ActionDataFilter
9
+ - chattice.assets: AssetPublisher
10
+ - chattice.auth: AuthMode · CredentialsProvider · ServiceAccountCredentialsProvider · UserCredentialsProvider · CHAT_BOT_SCOPE · CHAT_APP_MEMBERSHIPS_SCOPE
11
+ - chattice.capabilities: ResponseCapabilities · ResponseCapability · OutboundCapabilities · OutboundCapability · PreviewCapabilities · PreviewFeature · PREVIEW_APP_COMMAND_TYPES · CapabilityNotSupported
12
+ - chattice.cards: Card · CardHeader · Section · Button (string or ActionData binding) · ButtonList · TextParagraph · Divider · Image (`from_url`/`from_path`/`from_bytes`) · TextInput · SelectionInput · DateTimePicker · Action · OpenLink · Dialog · ActionStatus · ActionStatusCode · Validation · TextInputType · AccessoryWidget · RawWidget
13
+ - chattice.client: Bot (message/media/Card asset/membership/Space operations) · MessageReplyOption · ChatAPIError + wrapped error classes · wrap_api_error · CredentialsProvider (compat re-export)
14
+ - chattice.dispatcher: Dispatcher (`bot=` contextual binding) · Router · EventObserver · Lifespan · LifespanResource
15
+ - chattice.events: Event · MessageEvent (`reply`, lossless read metadata) · CommandEvent · CommandKind · ActionEvent · ActionSource · AddedToSpaceEvent · RemovedFromSpaceEvent · UnknownEvent · ErrorEvent · AppHomeEvent · FormSubmitEvent · WidgetUpdatedEvent · SpaceRef.send · ThreadRef.send · refs · form input values · DialogEventType · TimeZone
16
+ - chattice.filters: F · MagicExpression · MagicField · Filter · BaseFilter · FilterLike · FilterValue
17
+ - chattice.forms: FormModel · FormDecodeError · FormFilter
18
+ - chattice.fsm: State · StatesGroup · FSMContext · FSMStrategy · StorageKey · BaseStorage · MemoryStorage · RedisStorage (lazy) · StateFilter · FSMError · FSMRecord · FSMRecordConflict · FSMRecordStorage · MemoryFSMRecordStorage · RedisFSMRecordStorage (lazy) · BaseStorageFromRecord
19
+ - chattice.idempotency: IdempotencyStorage · MemoryIdempotencyStorage · RedisIdempotencyStorage · ClaimResult · new_owner
20
+ - chattice.integrations.fastapi: create_chat_router · create_pubsub_router · create_workspace_events_router
21
+ - chattice.integrations.gcs: GCSAssetPublisher
22
+ - chattice.middleware: Middleware · BaseMiddleware · MiddlewareLike · NextHandler
23
+ - chattice.observability: ObservabilityHooks
24
+ - chattice.testing: MockBot · EventFactory · FakeChatTransport · assert_card_has_button · assert_card_header · set_state_for
25
+ - chattice.transports.http: SYNC_RESPONSE_DEADLINE · HTTPInteractionAdapter · InteractionContext · IncomingRequest · IncomingRequestVerifier · GoogleTokenVerifier · MockVerifier · InteractionResponse · ResponseState · WidgetAutocomplete · RawInteractionResponse · VerificationError · DoubleResponseError
26
+ - chattice.transports.pubsub: PubSubPushAdapter · PubSubEnvelopeError · decode_message_data · PubSubPushVerifier · GooglePubSubVerifier · MockPubSubVerifier
27
+ - chattice.workspace_events: EventsDispatcher · EventsRouter · WorkspaceEvent · WorkspaceEventType · WorkspaceEventError · parse_workspace_event · parse_workspace_envelope
28
+ - chattice.experimental: marker has no direct exports; chattice.experimental.ai is distributed but explicitly unstable and outside the stable API
@@ -0,0 +1,173 @@
1
+ <img src="https://raw.githubusercontent.com/WhiteySage/chattice/main/docs/assets/brand/chattice-logo.png"
2
+ alt="Chattice" width="320" />
3
+
4
+ # Chattice
5
+
6
+ Async, typed event framework for Google Chat apps — aiogram-quality DX, Google-native semantics.
7
+
8
+ [![Python](https://img.shields.io/badge/python-3.11%20%7C%203.12%20%7C%203.13-blue)](https://pypi.org/project/chattice/)
9
+ [![License](https://img.shields.io/badge/license-MIT-green)](LICENSE)
10
+ [![Status](https://img.shields.io/badge/status-pre--1.0-orange)](#status)
11
+ [![Discussions](https://img.shields.io/badge/discussions-questions%20%26%20help-blue)](https://github.com/WhiteySage/chattice/discussions)
12
+
13
+ ```python
14
+ from chattice import Dispatcher, F, Router
15
+ from chattice.events import MessageEvent
16
+
17
+ router = Router()
18
+
19
+
20
+ @router.message(F.text == "ping")
21
+ async def ping(message: MessageEvent) -> str:
22
+ return "pong" # synchronous interaction response (no auth, 30 s deadline)
23
+
24
+
25
+ dispatcher = Dispatcher()
26
+ dispatcher.include_router(router)
27
+ ```
28
+
29
+ ## What this is
30
+
31
+ - **Google Chat-native.** Space, Thread, Message, Command, Action, Card,
32
+ Dialog, App Home, Workspace Events are first-class typed objects. No
33
+ Telegram concepts leak into the domain model.
34
+ - **aiogram ergonomics.** Routers, magic filters (`F`), middleware,
35
+ dependency injection, FSM — the DX you know, without Telegram
36
+ semantics.
37
+ - **Explicit response model.** A handler RETURN is the synchronous
38
+ interaction response (30 s deadline); outbound `Bot` calls are
39
+ separate authenticated operations. Contextual `message.reply()` /
40
+ `thread.send()` / `space.send()` methods are zero-fetch adapters over
41
+ that same Bot, never a hidden second channel.
42
+ - **Secure by default.** Incoming verification is fail-closed, push
43
+ endpoints require a verifier, outbound privacy gates (private
44
+ messages, notifications, preview features) fail closed before any
45
+ network call.
46
+ - **Core is small.** Core abstracts Google Chat platform primitives and
47
+ technical boilerplate ONLY. Business scenarios (polls, approvals,
48
+ tickets) are assembled from the primitives in your
49
+ application code — never added to core.
50
+
51
+ ## What this is not
52
+
53
+ - **Not a Telegram framework.** No `chat_id`, no `CallbackQuery`, no
54
+ `Update` hierarchy, no Telegram-style long polling (see the
55
+ [aiogram comparison](https://whiteysage.github.io/chattice/aiogram-comparison/)).
56
+ - **Not a Google product.** Independent open-source project, not
57
+ endorsed by Google.
58
+
59
+ ## Two ways to run
60
+
61
+ Chattice has two honest startup models (see the
62
+ [aiogram side-by-side](docs/aiogram-comparison.md)):
63
+
64
+ ```python
65
+ # HTTP — Google calls your HTTPS endpoint; the handler RETURN is the
66
+ # synchronous response (Dialogs and App Home work here).
67
+ app.include_router(create_chat_router(dispatcher, GoogleTokenVerifier(audience=...)))
68
+ # python -m uvicorn app:app
69
+
70
+ # Pub/Sub streaming pull — a persistent subscriber process, visually
71
+ # like aiogram's start_polling, but it is NOT Telegram polling.
72
+ # No domain/TLS needed; no Dialogs, no App Home — answers go outbound
73
+ # through the authenticated Bot.
74
+ await dispatcher.run_pubsub(subscription, bot=bot)
75
+ # python app.py
76
+ ```
77
+
78
+ ## Capabilities
79
+
80
+ | Area | Support |
81
+ | --- | --- |
82
+ | Events | MESSAGE, CARD_CLICKED, APP_COMMAND (slash/quick/message actions), ADDED/REMOVED_FROM_SPACE, APP_HOME, SUBMIT_FORM, WIDGET_UPDATED |
83
+ | Routing | Routers, observer-wide filters, magic filters, middleware, DI |
84
+ | Cards | Typed facades, public/non-sensitive PNG/JPEG publication through an optional AssetPublisher, sync updates |
85
+ | Memberships | APP-auth add/get/list/remove for internal human users; caller-member Space listing |
86
+ | Dialogs | OPEN_DIALOG, submit/cancel observers, action status; capability-gated per transport |
87
+ | FSM | State/StatesGroup, Memory + Redis record storage (compare-and-set) |
88
+ | Ingress | HTTP (verified), Pub/Sub push (verified), Pub/Sub streaming pull, Workspace Events CloudEvents |
89
+ | Media | Local-file attachments sent with USER auth end to end (`media.upload` → `messages.create`, sender = HUMAN); download USER/APP; metadata APP; 200 MB local preflight |
90
+ | Auth | App (service account), user (OAuth refresh), incoming verification |
91
+ | Testing | MockBot, EventFactory, assertions, fake transport |
92
+
93
+ ## Install
94
+
95
+ Python 3.11+ (3.11–3.13 tested). MIT-licensed.
96
+
97
+ ```bash
98
+ pip install "chattice[fastapi,pubsub,redis]" # core + all integrations
99
+
100
+ # or pick only what you need:
101
+ # pip install chattice core
102
+ # pip install "chattice[fastapi]" FastAPI integration
103
+ # pip install "chattice[redis]" Redis FSM/idempotency storage
104
+ # pip install "chattice[pubsub]" Pub/Sub push + streaming pull
105
+ # pip install "chattice[gcs]" Local Card image publication through GCS
106
+
107
+ # using uv
108
+ uv add "chattice[fastapi,pubsub,redis]"
109
+ ```
110
+
111
+ ## Quickstart
112
+
113
+ 1. Parse a documented interaction payload:
114
+
115
+ ```python
116
+ from chattice.adapters.google_chat import parse_interaction
117
+
118
+ event = parse_interaction(payload)
119
+ result = await dispatcher.feed_update(event)
120
+ ```
121
+
122
+ 2. Serve HTTP interactions (FastAPI):
123
+
124
+ ```python
125
+ from fastapi import FastAPI
126
+ from chattice.integrations.fastapi import create_chat_router
127
+ from chattice.transports.http import GoogleTokenVerifier
128
+
129
+ app = FastAPI()
130
+ app.include_router(create_chat_router(dispatcher, GoogleTokenVerifier(audience="...")))
131
+ ```
132
+
133
+ 3. Send messages:
134
+
135
+ ```python
136
+ from chattice.client import Bot
137
+
138
+ bot = Bot(credentials=...)
139
+ await bot.send_message("spaces/AAA", text="hello")
140
+ ```
141
+
142
+ Inside an interaction handler, configure the same Bot once and use the known
143
+ Google context without extra fetches:
144
+
145
+ ```python
146
+ dispatcher = Dispatcher(bot=bot)
147
+
148
+
149
+ @router.message()
150
+ async def reply(message: MessageEvent) -> None:
151
+ await message.reply("hello in this thread")
152
+ ```
153
+
154
+ ## Docs
155
+
156
+ Start with [Installation](https://whiteysage.github.io/chattice/getting-started/installation/), the
157
+ [5-minute Quickstart](https://whiteysage.github.io/chattice/getting-started/quickstart/), and the
158
+ [Space → Thread → Message mental model](https://whiteysage.github.io/chattice/concepts/mental-model/). The
159
+ [public API reference](https://whiteysage.github.io/chattice/public-api/), [Google mapping](https://whiteysage.github.io/chattice/reference/google-api-mapping/),
160
+ and [aiogram comparison](https://whiteysage.github.io/chattice/aiogram-comparison/) are linked from the docs site.
161
+ Runnable examples live in [`examples/`](https://github.com/WhiteySage/chattice/tree/main/examples); machine-readable documentation is available in
162
+ [`llms.txt`](https://whiteysage.github.io/chattice/llms.txt).
163
+
164
+ ## Status
165
+
166
+ Pre-1.0 **public release** (current version 0.1.0) — see
167
+ [CHANGELOG](CHANGELOG.md). The documented public
168
+ surface is the compatibility baseline: pre-1.0 work may add APIs but does not incompatibly
169
+ rename, remove, or change existing contracts. `chattice.experimental`
170
+ has no compatibility promise. `Bot.raw_client` and raw event payloads
171
+ follow Google's SDK and wire schema rather than the stable facade
172
+ promise. **Not an official Google product** — independent open-source
173
+ software, not endorsed by Google. MIT License, see [LICENSE](https://github.com/WhiteySage/chattice/blob/main/LICENSE).
@@ -0,0 +1,29 @@
1
+ # Security Policy
2
+
3
+ ## Reporting
4
+
5
+ Report suspected security vulnerabilities through **GitHub private
6
+ vulnerability reporting** (Security Advisories) on the public
7
+ repository — enable the feature before the first public release.
8
+ Until the repository is public, contact the project owner directly.
9
+ Do not open a public issue for vulnerabilities.
10
+
11
+ ## Supported versions
12
+
13
+ For pre-1.0 releases, only the latest release receives security fixes.
14
+ The policy will be expanded before 1.0.
15
+
16
+ ## Security model
17
+
18
+ Chattice ships transport verification and capability guards:
19
+
20
+ - Incoming HTTP interactions: `GoogleTokenVerifier` (Google-issued
21
+ bearer tokens, audience + issuer checks) → 401 on failure.
22
+ - Pub/Sub push: `GooglePubSubVerifier` (signature, audience, REQUIRED
23
+ service-account email, email_verified) — secure by default; an
24
+ explicit `allow_unverified=True` opt-in exists for local use only.
25
+ - Push dedupe is an owner-safe state machine; handlers must stay
26
+ idempotent (push has no exactly-once guarantee).
27
+ - Secrets are never logged: the redaction source-scan test pins this.
28
+
29
+ If you find a bypass, please report it per the section above.
@@ -0,0 +1,64 @@
1
+ # Third-party notices
2
+
3
+ Chattice is licensed under the MIT License. This file lists the direct
4
+ third-party dependencies of the project and their licenses, based on the
5
+ locked dependency inventory. It is an engineering compliance record, not legal
6
+ advice. Versions are the locked versions in `uv.lock`.
7
+
8
+ All declared direct dependencies carry permissive licenses compatible
9
+ with the MIT License (Apache-2.0, MIT, BSD-2/3-Clause, ISC). No
10
+ GPL/AGPL/SSPL dependency is declared.
11
+
12
+ ## Runtime dependencies
13
+
14
+ | Package | Version | License |
15
+ | --- | --- | --- |
16
+ | [google-apps-chat](https://github.com/googleapis/google-cloud-python/tree/main/packages/google-apps-chat) | 0.10.4 | Apache-2.0 |
17
+ | [google-auth](https://github.com/googleapis/google-auth-library-python) | 2.56.3 | Apache-2.0 |
18
+ | [pydantic](https://github.com/pydantic/pydantic) | 2.13.4 | MIT |
19
+
20
+ ## Optional extras
21
+
22
+ | Package | Version | License | Extra |
23
+ | --- | --- | --- | --- |
24
+ | [fastapi](https://github.com/fastapi/fastapi) | 0.141.1 | MIT | `fastapi` |
25
+ | [redis](https://github.com/redis/redis-py) | 6.4.0 | MIT | `redis` |
26
+ | [google-genai](https://github.com/googleapis/python-genai) | 2.18.1 | Apache-2.0 | `gemini` |
27
+ | [google-cloud-pubsub](https://github.com/googleapis/python-pubsub) | 2.39.1 | Apache-2.0 | `pubsub` |
28
+
29
+ ## Development, documentation and build dependencies
30
+
31
+ | Package | Version | License |
32
+ | --- | --- | --- |
33
+ | [cryptography](https://github.com/pyca/cryptography) | 45.0.7 | Apache-2.0 OR BSD-3-Clause |
34
+ | [fakeredis](https://github.com/cunla/fakeredis-py) | 2.37.0 | BSD-3-Clause |
35
+ | [httpx](https://github.com/encode/httpx) | 0.28.1 | BSD-3-Clause |
36
+ | [mkdocs](https://github.com/mkdocs/mkdocs) | 1.6.1 | BSD-2-Clause |
37
+ | [mkdocs-material](https://github.com/squidfunk/mkdocs-material) | 9.7.7 | MIT |
38
+ | [mkdocstrings[python]](https://github.com/mkdocstrings/mkdocstrings) | 1.0.6 | ISC |
39
+ | [mypy](https://github.com/python/mypy) | 1.20.2 | MIT (with identified PSF-licensed portions) |
40
+ | [pyjwt](https://github.com/jpadilla/pyjwt) | 2.13.0 | MIT |
41
+ | [pytest](https://github.com/pytest-dev/pytest) | 8.4.2 | MIT |
42
+ | [pytest-asyncio](https://github.com/pytest-dev/pytest-asyncio) | 1.4.0 | Apache-2.0 |
43
+ | [pytest-cov](https://github.com/pytest-dev/pytest-cov) | 7.1.0 | MIT |
44
+ | [ruff](https://github.com/astral-sh/ruff) | 0.16.3 | MIT |
45
+ | [uvicorn](https://github.com/encode/uvicorn) | 0.52.3 | BSD-3-Clause |
46
+ | [hatchling](https://github.com/pypa/hatch) | >=1.27 (build backend) | MIT |
47
+
48
+ ## What is and is not distributed
49
+
50
+ The wheel packages `src/chattice` and project licensing/typing
51
+ metadata; it does NOT embed dependency source trees. Declaring
52
+ dependencies in wheel metadata causes installers to fetch their
53
+ independently licensed distributions; it does not relicense or copy
54
+ them into Chattice.
55
+
56
+ An exact-artifact SBOM for the locked dependency set is generated from
57
+ `uv.lock` with `scripts/gen_sbom.py` (SPDX 2.3 JSON, written to
58
+ `docs/release/`). Run it after every lock change and commit the result.
59
+
60
+ ## Chattice license
61
+
62
+ MIT License — see [LICENSE](LICENSE). This project is independent
63
+ open-source software: not official Google software and not endorsed by
64
+ Google.