supython 0.1.10__tar.gz → 0.1.11__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 (260) hide show
  1. {supython-0.1.10 → supython-0.1.11}/.gitignore +9 -1
  2. {supython-0.1.10 → supython-0.1.11}/CHANGELOG.md +44 -2
  3. {supython-0.1.10 → supython-0.1.11}/PKG-INFO +45 -152
  4. {supython-0.1.10 → supython-0.1.11}/README.md +44 -151
  5. {supython-0.1.10 → supython-0.1.11}/pyproject.toml +1 -1
  6. {supython-0.1.10 → supython-0.1.11}/src/supython/cli.py +30 -12
  7. supython-0.1.11/src/supython/extensions.py +68 -0
  8. supython-0.1.11/src/supython/scaffold/init_project.py +217 -0
  9. supython-0.1.11/src/supython/scaffold/templates/README.md.tmpl +32 -0
  10. supython-0.1.10/src/supython/scaffold/templates/apps_hooks.py.tmpl → supython-0.1.11/src/supython/scaffold/templates/apps_hooks_welcome.py.tmpl +1 -1
  11. supython-0.1.10/src/supython/scaffold/templates/apps_jobs.py.tmpl → supython-0.1.11/src/supython/scaffold/templates/apps_jobs_example.py.tmpl +1 -1
  12. supython-0.1.11/src/supython/scaffold/templates/package_hooks_init.py.tmpl +8 -0
  13. supython-0.1.11/src/supython/scaffold/templates/package_jobs_init.py.tmpl +8 -0
  14. supython-0.1.11/src/supython/scaffold/templates/pyproject.toml.tmpl +15 -0
  15. {supython-0.1.10 → supython-0.1.11}/src/supython/scaffold/templates/settings.py.tmpl +5 -1
  16. supython-0.1.10/src/supython/migrations/0003_demo_todos.sql → supython-0.1.11/src/supython/scaffold/templates/static/0001_create_todos.sql +10 -3
  17. supython-0.1.11/src/supython/scaffold/templates/static/functions_hello.py +13 -0
  18. supython-0.1.10/src/supython/extensions.py +0 -36
  19. supython-0.1.10/src/supython/scaffold/init_project.py +0 -144
  20. supython-0.1.10/src/supython/scaffold/templates/README.md.tmpl +0 -22
  21. supython-0.1.10/src/supython/scaffold/templates/migrations/.gitkeep +0 -0
  22. {supython-0.1.10 → supython-0.1.11}/LICENSE +0 -0
  23. {supython-0.1.10 → supython-0.1.11}/SECURITY.md +0 -0
  24. {supython-0.1.10 → supython-0.1.11}/src/supython/__init__.py +0 -0
  25. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/__init__.py +0 -0
  26. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/api/__init__.py +0 -0
  27. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/api/auth.py +0 -0
  28. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/api/auth_templates.py +0 -0
  29. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/api/auth_users.py +0 -0
  30. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/api/db.py +0 -0
  31. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/api/functions.py +0 -0
  32. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/api/jobs.py +0 -0
  33. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/api/ops.py +0 -0
  34. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/api/realtime.py +0 -0
  35. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/api/service_auth.py +0 -0
  36. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/api/service_auth_templates.py +0 -0
  37. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/api/service_auth_users.py +0 -0
  38. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/api/service_db.py +0 -0
  39. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/api/service_functions.py +0 -0
  40. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/api/service_jobs.py +0 -0
  41. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/api/service_ops.py +0 -0
  42. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/api/service_realtime.py +0 -0
  43. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/api/service_storage.py +0 -0
  44. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/api/storage.py +0 -0
  45. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/api/system.py +0 -0
  46. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/audit.py +0 -0
  47. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/deps.py +0 -0
  48. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/errors.py +0 -0
  49. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/schemas.py +0 -0
  50. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/session.py +0 -0
  51. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/spa.py +0 -0
  52. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Alert-dluGVkos.js +0 -0
  53. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Alert-dluGVkos.js.map +0 -0
  54. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Audit-Njung3HI.js +0 -0
  55. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Audit-Njung3HI.js.map +0 -0
  56. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Backups-DzPlFgrm.js +0 -0
  57. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Backups-DzPlFgrm.js.map +0 -0
  58. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Buckets-ByacGkU1.js +0 -0
  59. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Buckets-ByacGkU1.js.map +0 -0
  60. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Channels-BoIuTtam.js +0 -0
  61. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Channels-BoIuTtam.js.map +0 -0
  62. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/ChevronRight-CtQH1EQ1.js +0 -0
  63. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/ChevronRight-CtQH1EQ1.js.map +0 -0
  64. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/CodeViewer-Bqy7-wvH.js +0 -0
  65. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/CodeViewer-Bqy7-wvH.js.map +0 -0
  66. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Crons-B67vc39F.js +0 -0
  67. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Crons-B67vc39F.js.map +0 -0
  68. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/DashboardView-CUTFVL6k.js +0 -0
  69. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/DashboardView-CUTFVL6k.js.map +0 -0
  70. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/DataTable-COAAWEft.js +0 -0
  71. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/DataTable-COAAWEft.js.map +0 -0
  72. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/DescriptionsItem-P8JUDaBs.js +0 -0
  73. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/DescriptionsItem-P8JUDaBs.js.map +0 -0
  74. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/DrawerContent-TpYTFgF1.js +0 -0
  75. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/DrawerContent-TpYTFgF1.js.map +0 -0
  76. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Empty-cr2r7e2u.js +0 -0
  77. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Empty-cr2r7e2u.js.map +0 -0
  78. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/EmptyState-DeDck-OL.js +0 -0
  79. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/EmptyState-DeDck-OL.js.map +0 -0
  80. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Grid-hFkp9F4P.js +0 -0
  81. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Grid-hFkp9F4P.js.map +0 -0
  82. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Input-DppYTq9C.js +0 -0
  83. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Input-DppYTq9C.js.map +0 -0
  84. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Invoke-DW3Nveeh.js +0 -0
  85. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Invoke-DW3Nveeh.js.map +0 -0
  86. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/JsonField-DibyJgun.js +0 -0
  87. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/JsonField-DibyJgun.js.map +0 -0
  88. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/LoginView-BjLyE3Ds.css +0 -0
  89. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/LoginView-CoOjECT_.js +0 -0
  90. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/LoginView-CoOjECT_.js.map +0 -0
  91. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Logs-D9WYrnIT.js +0 -0
  92. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Logs-D9WYrnIT.js.map +0 -0
  93. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Logs-DS1XPa0h.css +0 -0
  94. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Migrations-DOSC2ddQ.js +0 -0
  95. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Migrations-DOSC2ddQ.js.map +0 -0
  96. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/ObjectBrowser-_5w8vOX8.js +0 -0
  97. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/ObjectBrowser-_5w8vOX8.js.map +0 -0
  98. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Queue-CywZs6vI.js +0 -0
  99. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Queue-CywZs6vI.js.map +0 -0
  100. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/RefreshTokens-Ccjr53jg.js +0 -0
  101. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/RefreshTokens-Ccjr53jg.js.map +0 -0
  102. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/RlsEditor-BSlH9vSc.js +0 -0
  103. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/RlsEditor-BSlH9vSc.js.map +0 -0
  104. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Routes-BiLXE49D.js +0 -0
  105. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Routes-BiLXE49D.js.map +0 -0
  106. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Routes-C-ianIGD.css +0 -0
  107. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/SchemaBrowser-DKy2_KQi.css +0 -0
  108. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/SchemaBrowser-XFvFbtDB.js +0 -0
  109. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/SchemaBrowser-XFvFbtDB.js.map +0 -0
  110. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Select-DIzZyRZb.js +0 -0
  111. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Select-DIzZyRZb.js.map +0 -0
  112. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Space-n5-XcguU.js +0 -0
  113. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Space-n5-XcguU.js.map +0 -0
  114. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/SqlEditor-b8pTsILY.js +0 -0
  115. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/SqlEditor-b8pTsILY.js.map +0 -0
  116. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/SqlWorkspace-BUS7IntH.js +0 -0
  117. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/SqlWorkspace-BUS7IntH.js.map +0 -0
  118. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/TableData-CQIagLKn.js +0 -0
  119. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/TableData-CQIagLKn.js.map +0 -0
  120. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Tag-D1fOKpTH.js +0 -0
  121. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Tag-D1fOKpTH.js.map +0 -0
  122. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Templates-BS-ugkdq.js +0 -0
  123. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Templates-BS-ugkdq.js.map +0 -0
  124. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Thing-CEAniuMg.js +0 -0
  125. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Thing-CEAniuMg.js.map +0 -0
  126. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Users-wzwajhlh.js +0 -0
  127. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/Users-wzwajhlh.js.map +0 -0
  128. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/_plugin-vue_export-helper-DGA9ry_j.js +0 -0
  129. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/dist-VXIJLCYq.js +0 -0
  130. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/dist-VXIJLCYq.js.map +0 -0
  131. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/format-length-CGCY1rMh.js +0 -0
  132. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/format-length-CGCY1rMh.js.map +0 -0
  133. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/get-Ca6unauB.js +0 -0
  134. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/get-Ca6unauB.js.map +0 -0
  135. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/index-CeE6v959.js +0 -0
  136. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/index-CeE6v959.js.map +0 -0
  137. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/pinia-COXwfrOX.js +0 -0
  138. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/pinia-COXwfrOX.js.map +0 -0
  139. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/resources-Bt6thQCD.js +0 -0
  140. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/resources-Bt6thQCD.js.map +0 -0
  141. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/use-locale-mtgM0a3a.js +0 -0
  142. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/use-locale-mtgM0a3a.js.map +0 -0
  143. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/use-merged-state-BvhkaHNX.js +0 -0
  144. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/use-merged-state-BvhkaHNX.js.map +0 -0
  145. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/useConfirm-tMjvBFXR.js +0 -0
  146. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/useConfirm-tMjvBFXR.js.map +0 -0
  147. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/useResource-C_rJCY8C.js +0 -0
  148. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/useResource-C_rJCY8C.js.map +0 -0
  149. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/useTable-CnZc5zhi.js +0 -0
  150. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/useTable-CnZc5zhi.js.map +0 -0
  151. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/useTable-Dg0XlRlq.css +0 -0
  152. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/useToast-DsZKx0IX.js +0 -0
  153. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/useToast-DsZKx0IX.js.map +0 -0
  154. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/utils-sbXoq7Ir.js +0 -0
  155. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/assets/utils-sbXoq7Ir.js.map +0 -0
  156. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/favicon.svg +0 -0
  157. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/icons.svg +0 -0
  158. {supython-0.1.10 → supython-0.1.11}/src/supython/admin/static/index.html +0 -0
  159. {supython-0.1.10 → supython-0.1.11}/src/supython/app.py +0 -0
  160. {supython-0.1.10 → supython-0.1.11}/src/supython/auth/__init__.py +0 -0
  161. {supython-0.1.10 → supython-0.1.11}/src/supython/auth/_email_job.py +0 -0
  162. {supython-0.1.10 → supython-0.1.11}/src/supython/auth/claims.py +0 -0
  163. {supython-0.1.10 → supython-0.1.11}/src/supython/auth/deps.py +0 -0
  164. {supython-0.1.10 → supython-0.1.11}/src/supython/auth/providers/__init__.py +0 -0
  165. {supython-0.1.10 → supython-0.1.11}/src/supython/auth/providers/github.py +0 -0
  166. {supython-0.1.10 → supython-0.1.11}/src/supython/auth/providers/google.py +0 -0
  167. {supython-0.1.10 → supython-0.1.11}/src/supython/auth/providers/oauth.py +0 -0
  168. {supython-0.1.10 → supython-0.1.11}/src/supython/auth/providers/registry.py +0 -0
  169. {supython-0.1.10 → supython-0.1.11}/src/supython/auth/ratelimit.py +0 -0
  170. {supython-0.1.10 → supython-0.1.11}/src/supython/auth/router.py +0 -0
  171. {supython-0.1.10 → supython-0.1.11}/src/supython/auth/schemas.py +0 -0
  172. {supython-0.1.10 → supython-0.1.11}/src/supython/auth/service.py +0 -0
  173. {supython-0.1.10 → supython-0.1.11}/src/supython/backups/__init__.py +0 -0
  174. {supython-0.1.10 → supython-0.1.11}/src/supython/backups/_backup_job.py +0 -0
  175. {supython-0.1.10 → supython-0.1.11}/src/supython/backups/schemas.py +0 -0
  176. {supython-0.1.10 → supython-0.1.11}/src/supython/backups/service.py +0 -0
  177. {supython-0.1.10 → supython-0.1.11}/src/supython/body_size.py +0 -0
  178. {supython-0.1.10 → supython-0.1.11}/src/supython/client/__init__.py +0 -0
  179. {supython-0.1.10 → supython-0.1.11}/src/supython/client/_auth.py +0 -0
  180. {supython-0.1.10 → supython-0.1.11}/src/supython/client/_client.py +0 -0
  181. {supython-0.1.10 → supython-0.1.11}/src/supython/client/_config.py +0 -0
  182. {supython-0.1.10 → supython-0.1.11}/src/supython/client/_functions.py +0 -0
  183. {supython-0.1.10 → supython-0.1.11}/src/supython/client/_storage.py +0 -0
  184. {supython-0.1.10 → supython-0.1.11}/src/supython/client/py.typed +0 -0
  185. {supython-0.1.10 → supython-0.1.11}/src/supython/db.py +0 -0
  186. {supython-0.1.10 → supython-0.1.11}/src/supython/db_admin.py +0 -0
  187. {supython-0.1.10 → supython-0.1.11}/src/supython/functions/__init__.py +0 -0
  188. {supython-0.1.10 → supython-0.1.11}/src/supython/functions/context.py +0 -0
  189. {supython-0.1.10 → supython-0.1.11}/src/supython/functions/loader.py +0 -0
  190. {supython-0.1.10 → supython-0.1.11}/src/supython/functions/router.py +0 -0
  191. {supython-0.1.10 → supython-0.1.11}/src/supython/functions/schemas.py +0 -0
  192. {supython-0.1.10 → supython-0.1.11}/src/supython/gen/__init__.py +0 -0
  193. {supython-0.1.10 → supython-0.1.11}/src/supython/gen/_introspect.py +0 -0
  194. {supython-0.1.10 → supython-0.1.11}/src/supython/gen/types_py.py +0 -0
  195. {supython-0.1.10 → supython-0.1.11}/src/supython/gen/types_ts.py +0 -0
  196. {supython-0.1.10 → supython-0.1.11}/src/supython/health.py +0 -0
  197. {supython-0.1.10 → supython-0.1.11}/src/supython/hooks.py +0 -0
  198. {supython-0.1.10 → supython-0.1.11}/src/supython/jobs/__init__.py +0 -0
  199. {supython-0.1.10 → supython-0.1.11}/src/supython/jobs/backends.py +0 -0
  200. {supython-0.1.10 → supython-0.1.11}/src/supython/jobs/context.py +0 -0
  201. {supython-0.1.10 → supython-0.1.11}/src/supython/jobs/cron.py +0 -0
  202. {supython-0.1.10 → supython-0.1.11}/src/supython/jobs/cron_inproc.py +0 -0
  203. {supython-0.1.10 → supython-0.1.11}/src/supython/jobs/decorators.py +0 -0
  204. {supython-0.1.10 → supython-0.1.11}/src/supython/jobs/registry.py +0 -0
  205. {supython-0.1.10 → supython-0.1.11}/src/supython/jobs/router.py +0 -0
  206. {supython-0.1.10 → supython-0.1.11}/src/supython/jobs/schemas.py +0 -0
  207. {supython-0.1.10 → supython-0.1.11}/src/supython/jobs/service.py +0 -0
  208. {supython-0.1.10 → supython-0.1.11}/src/supython/jobs/worker.py +0 -0
  209. {supython-0.1.10 → supython-0.1.11}/src/supython/jwks.py +0 -0
  210. {supython-0.1.10 → supython-0.1.11}/src/supython/keyset.py +0 -0
  211. {supython-0.1.10 → supython-0.1.11}/src/supython/logging_config.py +0 -0
  212. {supython-0.1.10 → supython-0.1.11}/src/supython/mail.py +0 -0
  213. {supython-0.1.10 → supython-0.1.11}/src/supython/mailer.py +0 -0
  214. {supython-0.1.10 → supython-0.1.11}/src/supython/migrate.py +0 -0
  215. {supython-0.1.10 → supython-0.1.11}/src/supython/migrations/0001_extensions_and_roles.sql +0 -0
  216. {supython-0.1.10 → supython-0.1.11}/src/supython/migrations/0002_auth_schema.sql +0 -0
  217. {supython-0.1.10 → supython-0.1.11}/src/supython/migrations/0004_auth_v0_2.sql +0 -0
  218. {supython-0.1.10 → supython-0.1.11}/src/supython/migrations/0005_storage_schema.sql +0 -0
  219. {supython-0.1.10 → supython-0.1.11}/src/supython/migrations/0006_realtime_schema.sql +0 -0
  220. {supython-0.1.10 → supython-0.1.11}/src/supython/migrations/0007_jobs_schema.sql +0 -0
  221. {supython-0.1.10 → supython-0.1.11}/src/supython/migrations/0008_jobs_last_error.sql +0 -0
  222. {supython-0.1.10 → supython-0.1.11}/src/supython/migrations/0009_auth_rate_limits.sql +0 -0
  223. {supython-0.1.10 → supython-0.1.11}/src/supython/migrations/0010_worker_heartbeat.sql +0 -0
  224. {supython-0.1.10 → supython-0.1.11}/src/supython/migrations/0011_admin_schema.sql +0 -0
  225. {supython-0.1.10 → supython-0.1.11}/src/supython/migrations/0012_auth_banned_until.sql +0 -0
  226. {supython-0.1.10 → supython-0.1.11}/src/supython/migrations/0013_email_templates.sql +0 -0
  227. {supython-0.1.10 → supython-0.1.11}/src/supython/migrations/0014_realtime_payload_warning.sql +0 -0
  228. {supython-0.1.10 → supython-0.1.11}/src/supython/migrations/0015_backups_schema.sql +0 -0
  229. {supython-0.1.10 → supython-0.1.11}/src/supython/passwords.py +0 -0
  230. {supython-0.1.10 → supython-0.1.11}/src/supython/realtime/__init__.py +0 -0
  231. {supython-0.1.10 → supython-0.1.11}/src/supython/realtime/broker.py +0 -0
  232. {supython-0.1.10 → supython-0.1.11}/src/supython/realtime/protocol.py +0 -0
  233. {supython-0.1.10 → supython-0.1.11}/src/supython/realtime/router.py +0 -0
  234. {supython-0.1.10 → supython-0.1.11}/src/supython/realtime/schemas.py +0 -0
  235. {supython-0.1.10 → supython-0.1.11}/src/supython/realtime/service.py +0 -0
  236. {supython-0.1.10 → supython-0.1.11}/src/supython/realtime/topics.py +0 -0
  237. {supython-0.1.10 → supython-0.1.11}/src/supython/realtime/websocket.py +0 -0
  238. {supython-0.1.10 → supython-0.1.11}/src/supython/scaffold/__init__.py +0 -0
  239. {supython-0.1.10 → supython-0.1.11}/src/supython/scaffold/templates/Caddyfile.tmpl +0 -0
  240. {supython-0.1.10 → supython-0.1.11}/src/supython/scaffold/templates/asgi.py.tmpl +0 -0
  241. {supython-0.1.10 → supython-0.1.11}/src/supython/scaffold/templates/docker-compose.prod.yml.tmpl +0 -0
  242. {supython-0.1.10 → supython-0.1.11}/src/supython/scaffold/templates/docker-compose.yml.tmpl +0 -0
  243. {supython-0.1.10 → supython-0.1.11}/src/supython/scaffold/templates/docker_postgres_Dockerfile.tmpl +0 -0
  244. {supython-0.1.10 → supython-0.1.11}/src/supython/scaffold/templates/docker_postgres_postgresql.conf.tmpl +0 -0
  245. {supython-0.1.10 → supython-0.1.11}/src/supython/scaffold/templates/env.example.tmpl +0 -0
  246. {supython-0.1.10 → supython-0.1.11}/src/supython/scaffold/templates/functions_README.md.tmpl +0 -0
  247. {supython-0.1.10 → supython-0.1.11}/src/supython/scaffold/templates/gitignore.tmpl +0 -0
  248. {supython-0.1.10 → supython-0.1.11}/src/supython/scaffold/templates/manage.py.tmpl +0 -0
  249. {supython-0.1.10 → supython-0.1.11}/src/supython/scaffold/templates/package_init.py.tmpl +0 -0
  250. {supython-0.1.10 → supython-0.1.11}/src/supython/secretset.py +0 -0
  251. {supython-0.1.10 → supython-0.1.11}/src/supython/security_headers.py +0 -0
  252. {supython-0.1.10 → supython-0.1.11}/src/supython/settings.py +0 -0
  253. {supython-0.1.10 → supython-0.1.11}/src/supython/settings_module.py +0 -0
  254. {supython-0.1.10 → supython-0.1.11}/src/supython/storage/__init__.py +0 -0
  255. {supython-0.1.10 → supython-0.1.11}/src/supython/storage/backends.py +0 -0
  256. {supython-0.1.10 → supython-0.1.11}/src/supython/storage/router.py +0 -0
  257. {supython-0.1.10 → supython-0.1.11}/src/supython/storage/schemas.py +0 -0
  258. {supython-0.1.10 → supython-0.1.11}/src/supython/storage/service.py +0 -0
  259. {supython-0.1.10 → supython-0.1.11}/src/supython/storage/signing.py +0 -0
  260. {supython-0.1.10 → supython-0.1.11}/src/supython/tokens.py +0 -0
@@ -29,7 +29,8 @@ dev-app/backups/
29
29
  dev-app/__pycache__/
30
30
  dev-app/functions/__pycache__/
31
31
  dev-app/.tmp/
32
-
32
+ dev-app/
33
+ examples/
33
34
  .references/
34
35
  .references/*.md
35
36
  .claude/
@@ -43,3 +44,10 @@ ts-sdk/*.log
43
44
  .tmp/
44
45
 
45
46
  admin-ui/node_modules/
47
+
48
+ /.supython/secrets/
49
+ /.supython/secrets.json
50
+ /.supython/jwt_private.pem
51
+ /.supython/keys/
52
+ /.supython/keyset.json
53
+ /.supython/jwks.json
@@ -2,8 +2,7 @@
2
2
 
3
3
  All notable changes to supython are recorded here. The format follows
4
4
  [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the
5
- project uses **ZeroVer** (`0.x.y`) see `docs/PROJECT.md` §14.0 for
6
- what counts as a breaking change. There is no scheduled `1.0.0`; treat
5
+ project uses **ZeroVer** (`0.x.y`). There is no scheduled `1.0.0`; treat
7
6
  every `MINOR` as a potential breaking release.
8
7
 
9
8
  Categories used per release:
@@ -31,6 +30,48 @@ Each entry links the relevant `PROJECT.md` section and decision-log row
31
30
 
32
31
  ---
33
32
 
33
+ ## [0.1.11] — 2026-06-13
34
+
35
+ Project-initialization ergonomics. `supython init` now produces a project that
36
+ boots with no manual setup.
37
+
38
+ ### Breaking
39
+
40
+ - `supython init` arguments changed. The first argument is now the **importable
41
+ package name** (still required); the optional second argument is the **target
42
+ directory** (Django-style — `.` for the current directory), defaulting to
43
+ `./<name>`. The `--here` flag is **removed**: `supython init myapp --here`
44
+ becomes `supython init myapp .`.
45
+ - The scaffolded `jobs.py` and `hooks.py` single-file seeds are replaced by
46
+ auto-discovered **packages** `<name>/jobs/` and `<name>/hooks/`. Every module
47
+ inside each package is imported at boot, so jobs and hooks can be split across
48
+ files. `EXTENSIONS` in `settings.py` now points at the packages (`<name>.jobs`,
49
+ `<name>.hooks`) rather than the old modules.
50
+
51
+ ### Added
52
+
53
+ - `supython init` generates a ready-to-run, gitignored `.env` (from the example
54
+ template) so the stack boots without a manual `cp .env.example .env` step.
55
+ - `supython init` generates a `pyproject.toml` that declares the project and
56
+ pins the installed supython version; install the scaffold with `pip install -e .`.
57
+ - The scaffold seeds an example edge function (`functions/hello.py`) and an
58
+ example application migration (`migrations/0001_create_todos.sql`).
59
+
60
+ ### Changed
61
+
62
+ - Re-running `supython init` is now a safe top-up: existing files are skipped,
63
+ not overwritten, unless `--force` is passed.
64
+ - The generated JWT keypair and signing secrets under `.supython/` are **never**
65
+ overwritten — not even with `--force` — to avoid silently rotating keys and
66
+ invalidating live tokens, sessions, and signed URLs. Rotation has dedicated
67
+ homes: `supython keygen` and `supython secret rotate`.
68
+ - The scaffolded `todos` table moved out of supython's framework migrations into
69
+ the project's own `migrations/`. `supython migrate` applies only supython's
70
+ framework schemas (auth, storage, realtime, jobs); apply your application
71
+ migrations with a tool of your choice (dbmate recommended).
72
+
73
+ ---
74
+
34
75
  ## [0.1.10] — 2026-06-12
35
76
 
36
77
  ### Added
@@ -257,6 +298,7 @@ v0.1–v0.7 plus a v1.1.x admin track; see §19 decision log
257
298
  ---
258
299
 
259
300
 
301
+ [0.1.11]: https://github.com/Tkeby/supython/releases/tag/v0.1.11
260
302
  [0.1.10]: https://github.com/Tkeby/supython/releases/tag/v0.1.10
261
303
  [0.1.9]: https://github.com/Tkeby/supython/releases/tag/v0.1.9
262
304
  [0.1.0]: https://github.com/Tkeby/supython/releases/tag/v0.1.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: supython
3
- Version: 0.1.10
3
+ Version: 0.1.11
4
4
  Summary: A lightweight Postgres-first BaaS framework for Python
5
5
  Project-URL: Homepage, https://github.com/Tkeby/supython
6
6
  Project-URL: Repository, https://github.com/Tkeby/supython
@@ -153,20 +153,25 @@ python -m venv .venv && source .venv/bin/activate
153
153
  pip install supython
154
154
 
155
155
  # 2. scaffold a new project
156
+ # `myapp` is the importable package name. An optional second argument
157
+ # sets the target dir (`.` = current dir); it defaults to ./myapp.
156
158
  supython init myapp
157
159
  cd myapp
158
- cp .env.example .env
159
- # Review .env — at minimum confirm AUTHENTICATOR_PASSWORD matches
160
- # the value PostgREST will use (docker-compose.yml injects it via env).
160
+ # install the project (and supython, pinned in the generated pyproject.toml)
161
+ pip install -e .
161
162
  #
162
- # The scaffold creates:
163
- # manage.py Optional CLI entrypoint (sets SUPYTHON_SETTINGS_MODULE)
163
+ # The scaffold generates a ready-to-run, gitignored .env plus a JWT keypair
164
+ # and signing secrets under .supython/ no manual edits needed to boot.
165
+ # It also creates:
166
+ # pyproject.toml — declares this project, pins the supython version
164
167
  # myapp/settings.py — declare EXTENSIONS, EXTRA_ROUTERS, EXTRA_MIDDLEWARE
165
- # myapp/jobs.py example @job seed (register your background jobs here)
166
- # myapp/hooks.py example @on("signup") seed (lifecycle hooks)
168
+ # myapp/jobs/ package of @job / @cron modules (all auto-imported)
169
+ # myapp/hooks/ package of @on(...) lifecycle hooks (all auto-imported)
167
170
  # myapp/asgi.py — optional entrypoint for uvicorn/gunicorn
171
+ # functions/hello.py — example edge function (GET /functions/hello)
172
+ # migrations/0001_create_todos.sql — example app migration (apply with dbmate)
168
173
 
169
- # 3. boot Postgres + PostgREST and run migrations (one command)
174
+ # 3. boot Postgres + PostgREST and apply supython's framework migrations
170
175
  supython up
171
176
 
172
177
  # 4. run the auth/API service (separate terminal)
@@ -191,6 +196,10 @@ You should now have:
191
196
 
192
197
  ## End-to-end smoke test
193
198
 
199
+ This uses the scaffolded `todos` table, so first apply the example app migration
200
+ (`migrations/0001_create_todos.sql`) with [dbmate](https://github.com/amacneil/dbmate)
201
+ or your migration tool of choice — `supython migrate` only handles framework schemas.
202
+
194
203
  ```bash
195
204
  # sign up
196
205
  curl -sS -X POST http://localhost:8000/auth/v1/signup \
@@ -532,128 +541,31 @@ need to edit SQL.
532
541
 
533
542
  ```
534
543
  supython/
535
- ├── manage.py # optional cli entrypoint (sets SUPYTHON_SETTINGS_MODULE)
536
- ├── docker-compose.yml # Postgres + PostgREST (dev stack)
537
- ├── docker-compose.prod.yml # hardened single-host production stack
538
- ├── docker-compose.test.yml # dedicated test Postgres on port 54323
539
- ├── Caddyfile # reverse-proxy TLS for prod
540
- ├── <name>/ # your Python package
541
- │ ├── __init__.py
542
- │ ├── settings.py # project settings (EXTENSIONS, EXTRA_ROUTERS, …)
543
- │ ├── asgi.py # optional ASGI entrypoint (uvicorn <name>.asgi:app)
544
- │ ├── jobs.py # example @job seed
545
- └── hooks.py # example @on("signup") seed
546
- ├── migrations/
547
- │ ├── 0001_extensions_and_roles.sql # anon/authenticated/service_role/authenticator
548
- │ ├── 0002_auth_schema.sql # auth.users, auth.refresh_tokens, auth.uid()
549
- │ ├── 0003_demo_todos.sql # the demo table + RLS policies
550
- │ ├── 0004_auth_v0_2.sql # identities, one_time_tokens, audit_log
551
- │ ├── 0005_storage_schema.sql # storage.buckets + storage.objects
552
- ├── 0006_realtime_schema.sql # realtime schema, trigger, enable() helper
553
- ├── 0007_jobs_schema.sql # jobs queue, cron_schedules, enqueue/claim_next
554
- ├── 0008_jobs_last_error.sql # last_error column on jobs.jobs
555
- ├── 0009_auth_rate_limits.sql # auth fixed-window rate-limit counters
556
- ├── 0010_worker_heartbeat.sql # worker heartbeat for /readyz
557
- ├── 0011_admin_schema.sql # admin.admin_users, sessions, audit
558
- ├── 0012_auth_banned_until.sql # banned_until on auth.users
559
- │ ├── 0013_email_templates.sql # auth.email_templates
560
- │ ├── 0014_realtime_payload_warning.sql # >8KB payload warning counter
561
- │ └── 0015_backups_schema.sql # backups metadata
562
- ├── examples/
563
- │ ├── todos.http # HTTP smoke tests (auth + PostgREST)
564
- │ ├── storage.http # storage upload / signed URL examples
565
- │ ├── functions.http # edge-function call examples
566
- │ └── chat.html # two-browser realtime demo (vanilla JS, zero deps)
567
- ├── docs/
568
- │ ├── PROJECT.md # architecture + roadmap (single source of truth)
569
- │ ├── Installation.md # full install guide (dev, prod, managed Postgres)
570
- │ └── admin-ui/
571
- │ ├── admin-surface-plan.md # admin implementation plan + phase status
572
- │ └── admin-surface.md # admin architecture + contracts
573
- ├── tests/
574
- │ ├── conftest.py # cross-tree fixtures (keys, capturing mailer)
575
- │ ├── _keys.py # JWT-forging helpers
576
- │ ├── fixtures/ # test function modules, etc.
577
- │ ├── unit/ # pure-Python tests (~6s, no Docker)
578
- │ │ ├── test_admin_session.py
579
- │ │ ├── test_admin_service_db.py
580
- │ │ └── ...
581
- │ └── integration/ # full ASGI + Postgres on port 54323
582
- │ ├── conftest.py # pool, app, client, autouse DB cleaners
583
- │ ├── test_auth_signup_login.py
584
- │ ├── test_admin_auth.py
585
- │ ├── test_admin_auth_users.py
586
- │ ├── test_admin_db_rows.py
587
- │ ├── test_admin_jobs.py
588
- │ ├── test_admin_ops_backups.py
589
- │ ├── test_admin_storage.py
590
- │ ├── test_postgrest_rls.py
591
- │ ├── test_realtime_ws.py
592
- │ └── ...
593
- ├── admin-ui/ # Vue 3 + Vite SPA (built → src/supython/admin/static/)
594
- │ └── src/
595
- │ ├── api/ # single fetch seam
596
- │ ├── components/ # shell, data, editors, feedback
597
- │ ├── composables/ # useResource, useTable, useConfirm, useImpersonate, …
598
- │ ├── stores/ # auth, ui
599
- │ ├── views/ # Dashboard, db/, auth/, storage/, functions/, …
600
- │ └── router/
601
- └── src/supython/
602
- ├── __init__.py # single version string
603
- ├── settings.py # pydantic-settings, .env-driven
604
- ├── db.py # asyncpg pool + lifespan + as_role() / as_service_role()
605
- ├── mailer.py # ConsoleBackend / SmtpBackend
606
- ├── tokens.py # RS256/ES256 JWT + JWKS
607
- ├── passwords.py # argon2id
608
- ├── migrate.py # ~50-line SQL migration runner
609
- ├── app.py # FastAPI factory
610
- ├── cli.py # typer: up, dev, keygen, admin, worker, test, …
611
- ├── extensions.py # eager-import dotted module paths at boot
612
- ├── settings_module.py # user settings (EXTENSIONS, EXTRA_ROUTERS, …)
613
- ├── health.py # /livez, /readyz, /health endpoints
614
- ├── logging_config.py # structured JSON log setup
615
- ├── security_headers.py # HSTS, CSP, etc.
616
- ├── body_size.py # request body size guards
617
- ├── jwks.py # JWKS generation + rotation helpers
618
- ├── keyset.py # asymmetric key rotation manifest
619
- ├── secretset.py # symmetric secret rotation manifest
620
- ├── hooks.py # generic hook system: on() / fire()
621
- ├── mail.py # email send with job-retry fallback
622
- ├── auth/
623
- │ ├── schemas.py
624
- │ ├── service.py # full auth layer: signup / OAuth / OTP / recover …
625
- │ ├── router.py # all /auth/v1/* routes
626
- │ └── providers/ # Google, GitHub, OAuth2 helpers
627
- ├── storage/
628
- │ ├── backends.py # LocalBackend, S3Backend
629
- │ ├── service.py
630
- │ └── router.py # /storage/v1/*
631
- ├── functions/
632
- │ ├── loader.py # filesystem discovery + hot reload
633
- │ └── router.py # /functions/v1/*
634
- ├── realtime/
635
- │ ├── protocol.py # Phoenix Channels encode/decode
636
- │ ├── broker.py # fan-out engine with RLS filtering
637
- │ ├── websocket.py # WS route with JWT auth
638
- │ └── router.py # /realtime/v1/*
639
- ├── jobs/
640
- │ ├── registry.py # @job / @cron decorator store
641
- │ ├── service.py # enqueue, claim_next, mark_*
642
- │ ├── worker.py # long-running poll/dispatch/drain loop
643
- │ ├── cron.py # pg_cron sync + InProcScheduler
644
- │ └── router.py # /jobs/v1/*
645
- ├── admin/
646
- │ ├── session.py # admin cookie session (SHA-256 hashed, 8h TTL)
647
- │ ├── deps.py # require_admin dependency
648
- │ ├── spa.py # static SPA mount + index.html fallback
649
- │ ├── schemas.py # shared Pydantic models
650
- │ ├── audit.py # admin audit log writer
651
- │ ├── static/ # pre-built Vue 3 SPA bundle (committed)
652
- │ └── api/ # /admin/api/v1/* route handlers
653
- ├── backups/ # pg_dump wrapper + restore
654
- ├── gen/ # supython gen types --lang py|ts
655
- ├── scaffold/ # supython init templates
656
- └── client/ # Python SDK (optional [client] extra)
544
+ ├── src/supython/ # the FastAPI service + CLI (the published package)
545
+ ├── app.py # FastAPI factory
546
+ ├── cli.py # typer CLI: init, up, dev, worker, migrate, gen, …
547
+ ├── db.py # asyncpg pool + as_role() / as_service_role()
548
+ ├── settings.py # pydantic-settings, .env-driven
549
+ ├── tokens.py # RS256/ES256 JWT + JWKS
550
+ │ ├── migrate.py # ~50-line SQL migration runner
551
+ │ ├── migrations/ # framework schema (auth, storage, realtime, jobs, …)
552
+ │ ├── auth/ # /auth/v1/* — signup, OAuth, OTP, recovery
553
+ │ ├── storage/ # /storage/v1/* — local + S3 backends
554
+ ├── functions/ # /functions/v1/* — filesystem-discovered handlers
555
+ ├── realtime/ # /realtime/v1/* — Phoenix Channels over LISTEN/NOTIFY
556
+ │ ├── jobs/ # /jobs/v1/* — queue, worker, pg_cron scheduling
557
+ │ ├── admin/ # /admin/api/v1/* + the built Vue SPA (static/)
558
+ │ ├── backups/ # pg_dump wrapper + restore
559
+ │ ├── gen/ # `supython gen types --lang py|ts`
560
+ │ ├── scaffold/ # `supython init` templates
561
+ └── client/ # optional Python SDK ([client] extra)
562
+ ├── admin-ui/ # Vue 3 + Vite SPA, built → src/supython/admin/static/
563
+ ├── ts-sdk/ # @supython/sdk TypeScript SDK
564
+ ├── dev-app/ # scaffolded sample project for local development
565
+ ├── examples/ # .http smoke tests + chat.html realtime demo
566
+ ├── tests/ # unit/ (no Docker) + integration/ (Postgres :54323)
567
+ ├── Dockerfile
568
+ └── pyproject.toml
657
569
  ```
658
570
 
659
571
  ## Plugins & extensions
@@ -693,10 +605,10 @@ supython down # stop the stack (keeps data)
693
605
  supython down --prod # stop the prod stack
694
606
  supython reset # stop the stack and DELETE the volume (destructive)
695
607
  supython reset --prod # stop prod stack and DELETE volumes
696
- supython migrate # apply pending SQL migrations
608
+ supython migrate # apply supython's framework migrations (auth, storage, …)
697
609
  supython info # print resolved settings
698
610
  supython doctor # diagnose roles, extensions, JWKS, grants, migration drift
699
- supython init <name> # scaffold a new supython project
611
+ supython init <pkg> [dir] # scaffold a project (pkg = package name; dir defaults to ./<pkg>)
700
612
  supython gen types --lang py --out db_schema.py # emit typed dataclasses + TypedDicts
701
613
  supython gen types --lang ts --out types.ts # emit TypeScript Database interface
702
614
 
@@ -819,25 +731,6 @@ unit tests always run in isolation.
819
731
  **CI:** runners with Docker run `supython test up && supython test run`;
820
732
  runners without Docker run `pytest tests/unit` for a meaningful subset.
821
733
 
822
- ## Roadmap
823
-
824
- - ✅ Email/password auth, PostgREST contract, RLS demo
825
- - ✅ OAuth, password reset, magic link, OTP, reuse detection, email backend, test suite
826
- - ✅ Storage (S3/local) with RLS-on-metadata, edge-style functions from a `functions/` directory; `db.as_role(role, claims)` helper; `supython init` scaffold; `supython gen types --lang py`
827
- - ✅ Realtime over `LISTEN/NOTIFY` with RLS-aware fan-out; Phoenix Channels wire format; broadcast + presence; `examples/chat.html` demo
828
- - ✅ Job queue worker + `pg_cron` scheduling + hooks + CLI management commands
829
- - ✅ Grooming + security foundation: unified versioning, CORS closed by default, RS256 JWT, rate limiting, `supython doctor`, pool sizing, statement timeout
830
- - ✅ Production observable: structured JSON logs, `/livez`/`/readyz`/`/health`, security headers, input size guards, audit log completeness, OAuth PKCE, secret rotation runbooks
831
- - ✅ (partial) Multi-arch Docker images, admin control plane (Vue 3 SPA — database, auth, storage, functions, realtime, jobs, backups, log tail), CI buildx workflow; benchmarks + security audit pass + dependency budget CI remaining
832
- - *(deferred)* — Realtime v2 over logical replication
833
- - ✅ **TypeScript SDK** — `@supython/sdk` wrapping `@supabase/postgrest-js` + `@supabase/realtime-js`
834
-
835
- ### Future
836
-
837
- - **Admin control plane** polish (tests + remaining DoD items)
838
- - **Realtime v2** — logical replication (demand-driven; swap when trigger overhead or >8KB payload data warrants it)
839
- - **Prometheus `/metrics`** + **OpenTelemetry** — optional extras
840
-
841
734
  ## License
842
735
 
843
736
  MIT
@@ -94,20 +94,25 @@ python -m venv .venv && source .venv/bin/activate
94
94
  pip install supython
95
95
 
96
96
  # 2. scaffold a new project
97
+ # `myapp` is the importable package name. An optional second argument
98
+ # sets the target dir (`.` = current dir); it defaults to ./myapp.
97
99
  supython init myapp
98
100
  cd myapp
99
- cp .env.example .env
100
- # Review .env — at minimum confirm AUTHENTICATOR_PASSWORD matches
101
- # the value PostgREST will use (docker-compose.yml injects it via env).
101
+ # install the project (and supython, pinned in the generated pyproject.toml)
102
+ pip install -e .
102
103
  #
103
- # The scaffold creates:
104
- # manage.py Optional CLI entrypoint (sets SUPYTHON_SETTINGS_MODULE)
104
+ # The scaffold generates a ready-to-run, gitignored .env plus a JWT keypair
105
+ # and signing secrets under .supython/ no manual edits needed to boot.
106
+ # It also creates:
107
+ # pyproject.toml — declares this project, pins the supython version
105
108
  # myapp/settings.py — declare EXTENSIONS, EXTRA_ROUTERS, EXTRA_MIDDLEWARE
106
- # myapp/jobs.py example @job seed (register your background jobs here)
107
- # myapp/hooks.py example @on("signup") seed (lifecycle hooks)
109
+ # myapp/jobs/ package of @job / @cron modules (all auto-imported)
110
+ # myapp/hooks/ package of @on(...) lifecycle hooks (all auto-imported)
108
111
  # myapp/asgi.py — optional entrypoint for uvicorn/gunicorn
112
+ # functions/hello.py — example edge function (GET /functions/hello)
113
+ # migrations/0001_create_todos.sql — example app migration (apply with dbmate)
109
114
 
110
- # 3. boot Postgres + PostgREST and run migrations (one command)
115
+ # 3. boot Postgres + PostgREST and apply supython's framework migrations
111
116
  supython up
112
117
 
113
118
  # 4. run the auth/API service (separate terminal)
@@ -132,6 +137,10 @@ You should now have:
132
137
 
133
138
  ## End-to-end smoke test
134
139
 
140
+ This uses the scaffolded `todos` table, so first apply the example app migration
141
+ (`migrations/0001_create_todos.sql`) with [dbmate](https://github.com/amacneil/dbmate)
142
+ or your migration tool of choice — `supython migrate` only handles framework schemas.
143
+
135
144
  ```bash
136
145
  # sign up
137
146
  curl -sS -X POST http://localhost:8000/auth/v1/signup \
@@ -473,128 +482,31 @@ need to edit SQL.
473
482
 
474
483
  ```
475
484
  supython/
476
- ├── manage.py # optional cli entrypoint (sets SUPYTHON_SETTINGS_MODULE)
477
- ├── docker-compose.yml # Postgres + PostgREST (dev stack)
478
- ├── docker-compose.prod.yml # hardened single-host production stack
479
- ├── docker-compose.test.yml # dedicated test Postgres on port 54323
480
- ├── Caddyfile # reverse-proxy TLS for prod
481
- ├── <name>/ # your Python package
482
- │ ├── __init__.py
483
- │ ├── settings.py # project settings (EXTENSIONS, EXTRA_ROUTERS, …)
484
- │ ├── asgi.py # optional ASGI entrypoint (uvicorn <name>.asgi:app)
485
- │ ├── jobs.py # example @job seed
486
- └── hooks.py # example @on("signup") seed
487
- ├── migrations/
488
- │ ├── 0001_extensions_and_roles.sql # anon/authenticated/service_role/authenticator
489
- │ ├── 0002_auth_schema.sql # auth.users, auth.refresh_tokens, auth.uid()
490
- │ ├── 0003_demo_todos.sql # the demo table + RLS policies
491
- │ ├── 0004_auth_v0_2.sql # identities, one_time_tokens, audit_log
492
- │ ├── 0005_storage_schema.sql # storage.buckets + storage.objects
493
- ├── 0006_realtime_schema.sql # realtime schema, trigger, enable() helper
494
- ├── 0007_jobs_schema.sql # jobs queue, cron_schedules, enqueue/claim_next
495
- ├── 0008_jobs_last_error.sql # last_error column on jobs.jobs
496
- ├── 0009_auth_rate_limits.sql # auth fixed-window rate-limit counters
497
- ├── 0010_worker_heartbeat.sql # worker heartbeat for /readyz
498
- ├── 0011_admin_schema.sql # admin.admin_users, sessions, audit
499
- ├── 0012_auth_banned_until.sql # banned_until on auth.users
500
- │ ├── 0013_email_templates.sql # auth.email_templates
501
- │ ├── 0014_realtime_payload_warning.sql # >8KB payload warning counter
502
- │ └── 0015_backups_schema.sql # backups metadata
503
- ├── examples/
504
- │ ├── todos.http # HTTP smoke tests (auth + PostgREST)
505
- │ ├── storage.http # storage upload / signed URL examples
506
- │ ├── functions.http # edge-function call examples
507
- │ └── chat.html # two-browser realtime demo (vanilla JS, zero deps)
508
- ├── docs/
509
- │ ├── PROJECT.md # architecture + roadmap (single source of truth)
510
- │ ├── Installation.md # full install guide (dev, prod, managed Postgres)
511
- │ └── admin-ui/
512
- │ ├── admin-surface-plan.md # admin implementation plan + phase status
513
- │ └── admin-surface.md # admin architecture + contracts
514
- ├── tests/
515
- │ ├── conftest.py # cross-tree fixtures (keys, capturing mailer)
516
- │ ├── _keys.py # JWT-forging helpers
517
- │ ├── fixtures/ # test function modules, etc.
518
- │ ├── unit/ # pure-Python tests (~6s, no Docker)
519
- │ │ ├── test_admin_session.py
520
- │ │ ├── test_admin_service_db.py
521
- │ │ └── ...
522
- │ └── integration/ # full ASGI + Postgres on port 54323
523
- │ ├── conftest.py # pool, app, client, autouse DB cleaners
524
- │ ├── test_auth_signup_login.py
525
- │ ├── test_admin_auth.py
526
- │ ├── test_admin_auth_users.py
527
- │ ├── test_admin_db_rows.py
528
- │ ├── test_admin_jobs.py
529
- │ ├── test_admin_ops_backups.py
530
- │ ├── test_admin_storage.py
531
- │ ├── test_postgrest_rls.py
532
- │ ├── test_realtime_ws.py
533
- │ └── ...
534
- ├── admin-ui/ # Vue 3 + Vite SPA (built → src/supython/admin/static/)
535
- │ └── src/
536
- │ ├── api/ # single fetch seam
537
- │ ├── components/ # shell, data, editors, feedback
538
- │ ├── composables/ # useResource, useTable, useConfirm, useImpersonate, …
539
- │ ├── stores/ # auth, ui
540
- │ ├── views/ # Dashboard, db/, auth/, storage/, functions/, …
541
- │ └── router/
542
- └── src/supython/
543
- ├── __init__.py # single version string
544
- ├── settings.py # pydantic-settings, .env-driven
545
- ├── db.py # asyncpg pool + lifespan + as_role() / as_service_role()
546
- ├── mailer.py # ConsoleBackend / SmtpBackend
547
- ├── tokens.py # RS256/ES256 JWT + JWKS
548
- ├── passwords.py # argon2id
549
- ├── migrate.py # ~50-line SQL migration runner
550
- ├── app.py # FastAPI factory
551
- ├── cli.py # typer: up, dev, keygen, admin, worker, test, …
552
- ├── extensions.py # eager-import dotted module paths at boot
553
- ├── settings_module.py # user settings (EXTENSIONS, EXTRA_ROUTERS, …)
554
- ├── health.py # /livez, /readyz, /health endpoints
555
- ├── logging_config.py # structured JSON log setup
556
- ├── security_headers.py # HSTS, CSP, etc.
557
- ├── body_size.py # request body size guards
558
- ├── jwks.py # JWKS generation + rotation helpers
559
- ├── keyset.py # asymmetric key rotation manifest
560
- ├── secretset.py # symmetric secret rotation manifest
561
- ├── hooks.py # generic hook system: on() / fire()
562
- ├── mail.py # email send with job-retry fallback
563
- ├── auth/
564
- │ ├── schemas.py
565
- │ ├── service.py # full auth layer: signup / OAuth / OTP / recover …
566
- │ ├── router.py # all /auth/v1/* routes
567
- │ └── providers/ # Google, GitHub, OAuth2 helpers
568
- ├── storage/
569
- │ ├── backends.py # LocalBackend, S3Backend
570
- │ ├── service.py
571
- │ └── router.py # /storage/v1/*
572
- ├── functions/
573
- │ ├── loader.py # filesystem discovery + hot reload
574
- │ └── router.py # /functions/v1/*
575
- ├── realtime/
576
- │ ├── protocol.py # Phoenix Channels encode/decode
577
- │ ├── broker.py # fan-out engine with RLS filtering
578
- │ ├── websocket.py # WS route with JWT auth
579
- │ └── router.py # /realtime/v1/*
580
- ├── jobs/
581
- │ ├── registry.py # @job / @cron decorator store
582
- │ ├── service.py # enqueue, claim_next, mark_*
583
- │ ├── worker.py # long-running poll/dispatch/drain loop
584
- │ ├── cron.py # pg_cron sync + InProcScheduler
585
- │ └── router.py # /jobs/v1/*
586
- ├── admin/
587
- │ ├── session.py # admin cookie session (SHA-256 hashed, 8h TTL)
588
- │ ├── deps.py # require_admin dependency
589
- │ ├── spa.py # static SPA mount + index.html fallback
590
- │ ├── schemas.py # shared Pydantic models
591
- │ ├── audit.py # admin audit log writer
592
- │ ├── static/ # pre-built Vue 3 SPA bundle (committed)
593
- │ └── api/ # /admin/api/v1/* route handlers
594
- ├── backups/ # pg_dump wrapper + restore
595
- ├── gen/ # supython gen types --lang py|ts
596
- ├── scaffold/ # supython init templates
597
- └── client/ # Python SDK (optional [client] extra)
485
+ ├── src/supython/ # the FastAPI service + CLI (the published package)
486
+ ├── app.py # FastAPI factory
487
+ ├── cli.py # typer CLI: init, up, dev, worker, migrate, gen, …
488
+ ├── db.py # asyncpg pool + as_role() / as_service_role()
489
+ ├── settings.py # pydantic-settings, .env-driven
490
+ ├── tokens.py # RS256/ES256 JWT + JWKS
491
+ │ ├── migrate.py # ~50-line SQL migration runner
492
+ │ ├── migrations/ # framework schema (auth, storage, realtime, jobs, …)
493
+ │ ├── auth/ # /auth/v1/* — signup, OAuth, OTP, recovery
494
+ │ ├── storage/ # /storage/v1/* — local + S3 backends
495
+ ├── functions/ # /functions/v1/* — filesystem-discovered handlers
496
+ ├── realtime/ # /realtime/v1/* — Phoenix Channels over LISTEN/NOTIFY
497
+ │ ├── jobs/ # /jobs/v1/* — queue, worker, pg_cron scheduling
498
+ │ ├── admin/ # /admin/api/v1/* + the built Vue SPA (static/)
499
+ │ ├── backups/ # pg_dump wrapper + restore
500
+ │ ├── gen/ # `supython gen types --lang py|ts`
501
+ │ ├── scaffold/ # `supython init` templates
502
+ └── client/ # optional Python SDK ([client] extra)
503
+ ├── admin-ui/ # Vue 3 + Vite SPA, built → src/supython/admin/static/
504
+ ├── ts-sdk/ # @supython/sdk TypeScript SDK
505
+ ├── dev-app/ # scaffolded sample project for local development
506
+ ├── examples/ # .http smoke tests + chat.html realtime demo
507
+ ├── tests/ # unit/ (no Docker) + integration/ (Postgres :54323)
508
+ ├── Dockerfile
509
+ └── pyproject.toml
598
510
  ```
599
511
 
600
512
  ## Plugins & extensions
@@ -634,10 +546,10 @@ supython down # stop the stack (keeps data)
634
546
  supython down --prod # stop the prod stack
635
547
  supython reset # stop the stack and DELETE the volume (destructive)
636
548
  supython reset --prod # stop prod stack and DELETE volumes
637
- supython migrate # apply pending SQL migrations
549
+ supython migrate # apply supython's framework migrations (auth, storage, …)
638
550
  supython info # print resolved settings
639
551
  supython doctor # diagnose roles, extensions, JWKS, grants, migration drift
640
- supython init <name> # scaffold a new supython project
552
+ supython init <pkg> [dir] # scaffold a project (pkg = package name; dir defaults to ./<pkg>)
641
553
  supython gen types --lang py --out db_schema.py # emit typed dataclasses + TypedDicts
642
554
  supython gen types --lang ts --out types.ts # emit TypeScript Database interface
643
555
 
@@ -760,25 +672,6 @@ unit tests always run in isolation.
760
672
  **CI:** runners with Docker run `supython test up && supython test run`;
761
673
  runners without Docker run `pytest tests/unit` for a meaningful subset.
762
674
 
763
- ## Roadmap
764
-
765
- - ✅ Email/password auth, PostgREST contract, RLS demo
766
- - ✅ OAuth, password reset, magic link, OTP, reuse detection, email backend, test suite
767
- - ✅ Storage (S3/local) with RLS-on-metadata, edge-style functions from a `functions/` directory; `db.as_role(role, claims)` helper; `supython init` scaffold; `supython gen types --lang py`
768
- - ✅ Realtime over `LISTEN/NOTIFY` with RLS-aware fan-out; Phoenix Channels wire format; broadcast + presence; `examples/chat.html` demo
769
- - ✅ Job queue worker + `pg_cron` scheduling + hooks + CLI management commands
770
- - ✅ Grooming + security foundation: unified versioning, CORS closed by default, RS256 JWT, rate limiting, `supython doctor`, pool sizing, statement timeout
771
- - ✅ Production observable: structured JSON logs, `/livez`/`/readyz`/`/health`, security headers, input size guards, audit log completeness, OAuth PKCE, secret rotation runbooks
772
- - ✅ (partial) Multi-arch Docker images, admin control plane (Vue 3 SPA — database, auth, storage, functions, realtime, jobs, backups, log tail), CI buildx workflow; benchmarks + security audit pass + dependency budget CI remaining
773
- - *(deferred)* — Realtime v2 over logical replication
774
- - ✅ **TypeScript SDK** — `@supython/sdk` wrapping `@supabase/postgrest-js` + `@supabase/realtime-js`
775
-
776
- ### Future
777
-
778
- - **Admin control plane** polish (tests + remaining DoD items)
779
- - **Realtime v2** — logical replication (demand-driven; swap when trigger overhead or >8KB payload data warrants it)
780
- - **Prometheus `/metrics`** + **OpenTelemetry** — optional extras
781
-
782
675
  ## License
783
676
 
784
677
  MIT
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "supython"
7
- version = "0.1.10"
7
+ version = "0.1.11"
8
8
  description = "A lightweight Postgres-first BaaS framework for Python"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"