stkit 17.0.1__tar.gz → 17.0.2__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 (162) hide show
  1. {stkit-17.0.1 → stkit-17.0.2}/CHANGELOG.md +8 -0
  2. {stkit-17.0.1 → stkit-17.0.2}/PKG-INFO +1 -1
  3. {stkit-17.0.1 → stkit-17.0.2}/pyproject.toml +1 -1
  4. {stkit-17.0.1 → stkit-17.0.2}/stk/__init__.py +1 -1
  5. {stkit-17.0.1 → stkit-17.0.2}/stk/checks.py +3 -2
  6. {stkit-17.0.1 → stkit-17.0.2}/stk/cli/main.py +13 -2
  7. stkit-17.0.2/tests/test_app_index.py +43 -0
  8. {stkit-17.0.1 → stkit-17.0.2}/.gitignore +0 -0
  9. {stkit-17.0.1 → stkit-17.0.2}/LICENSE +0 -0
  10. {stkit-17.0.1 → stkit-17.0.2}/README.md +0 -0
  11. {stkit-17.0.1 → stkit-17.0.2}/SECURITY.md +0 -0
  12. {stkit-17.0.1 → stkit-17.0.2}/examples/minimal/.env-sample +0 -0
  13. {stkit-17.0.1 → stkit-17.0.2}/examples/minimal/.gitignore +0 -0
  14. {stkit-17.0.1 → stkit-17.0.2}/examples/minimal/README.md +0 -0
  15. {stkit-17.0.1 → stkit-17.0.2}/examples/minimal/minimal/__init__.py +0 -0
  16. {stkit-17.0.1 → stkit-17.0.2}/examples/minimal/minimal/app.py +0 -0
  17. {stkit-17.0.1 → stkit-17.0.2}/examples/minimal/minimal/migrations/364232ae77d5_add_note.py +0 -0
  18. {stkit-17.0.1 → stkit-17.0.2}/examples/minimal/minimal/note/__init__.py +0 -0
  19. {stkit-17.0.1 → stkit-17.0.2}/examples/minimal/minimal/note/models.py +0 -0
  20. {stkit-17.0.1 → stkit-17.0.2}/examples/minimal/minimal/note/templates/note/index.html +0 -0
  21. {stkit-17.0.1 → stkit-17.0.2}/examples/minimal/minimal/note/views.py +0 -0
  22. {stkit-17.0.1 → stkit-17.0.2}/examples/minimal/minimal/settings.py +0 -0
  23. {stkit-17.0.1 → stkit-17.0.2}/examples/minimal/minimal/templates/layout.html +0 -0
  24. {stkit-17.0.1 → stkit-17.0.2}/examples/minimal/pyproject.toml +0 -0
  25. {stkit-17.0.1 → stkit-17.0.2}/examples/minimal/tests/__init__.py +0 -0
  26. {stkit-17.0.1 → stkit-17.0.2}/examples/minimal/tests/test_app.py +0 -0
  27. {stkit-17.0.1 → stkit-17.0.2}/examples/minimal/uv.lock +0 -0
  28. {stkit-17.0.1 → stkit-17.0.2}/stk/__main__.py +0 -0
  29. {stkit-17.0.1 → stkit-17.0.2}/stk/agent_login.py +0 -0
  30. {stkit-17.0.1 → stkit-17.0.2}/stk/app.py +0 -0
  31. {stkit-17.0.1 → stkit-17.0.2}/stk/cli/__init__.py +0 -0
  32. {stkit-17.0.1 → stkit-17.0.2}/stk/cli/agent.py +0 -0
  33. {stkit-17.0.1 → stkit-17.0.2}/stk/cli/base.py +0 -0
  34. {stkit-17.0.1 → stkit-17.0.2}/stk/cli/database.py +0 -0
  35. {stkit-17.0.1 → stkit-17.0.2}/stk/cli/develop.py +0 -0
  36. {stkit-17.0.1 → stkit-17.0.2}/stk/cli/doctor.py +0 -0
  37. {stkit-17.0.1 → stkit-17.0.2}/stk/cli/reports.py +0 -0
  38. {stkit-17.0.1 → stkit-17.0.2}/stk/cli/smoke.py +0 -0
  39. {stkit-17.0.1 → stkit-17.0.2}/stk/cli/users.py +0 -0
  40. {stkit-17.0.1 → stkit-17.0.2}/stk/cli/watch.py +0 -0
  41. {stkit-17.0.1 → stkit-17.0.2}/stk/extensions.py +0 -0
  42. {stkit-17.0.1 → stkit-17.0.2}/stk/migrations/__init__.py +0 -0
  43. {stkit-17.0.1 → stkit-17.0.2}/stk/migrations/env.py +0 -0
  44. {stkit-17.0.1 → stkit-17.0.2}/stk/migrations/script.py.mako +0 -0
  45. {stkit-17.0.1 → stkit-17.0.2}/stk/migrations/versions/stk_0001_initial_schema.py +0 -0
  46. {stkit-17.0.1 → stkit-17.0.2}/stk/portal/views.py +0 -0
  47. {stkit-17.0.1 → stkit-17.0.2}/stk/public/__init__.py +0 -0
  48. {stkit-17.0.1 → stkit-17.0.2}/stk/public/models.py +0 -0
  49. {stkit-17.0.1 → stkit-17.0.2}/stk/public/views.py +0 -0
  50. {stkit-17.0.1 → stkit-17.0.2}/stk/scaffold/__init__.py +0 -0
  51. {stkit-17.0.1 → stkit-17.0.2}/stk/scaffold/app/CLAUDE.md +0 -0
  52. {stkit-17.0.1 → stkit-17.0.2}/stk/scaffold/app/Dockerfile +0 -0
  53. {stkit-17.0.1 → stkit-17.0.2}/stk/scaffold/app/README.md +0 -0
  54. {stkit-17.0.1 → stkit-17.0.2}/stk/scaffold/app/__app__/__init__.py +0 -0
  55. {stkit-17.0.1 → stkit-17.0.2}/stk/scaffold/app/__app__/app.py +0 -0
  56. {stkit-17.0.1 → stkit-17.0.2}/stk/scaffold/app/__app__/settings.py +0 -0
  57. {stkit-17.0.1 → stkit-17.0.2}/stk/scaffold/app/claude/skills/stk-api/SKILL.md +0 -0
  58. {stkit-17.0.1 → stkit-17.0.2}/stk/scaffold/app/claude/skills/stk-blueprint/SKILL.md +0 -0
  59. {stkit-17.0.1 → stkit-17.0.2}/stk/scaffold/app/claude/skills/stk-deploy/SKILL.md +0 -0
  60. {stkit-17.0.1 → stkit-17.0.2}/stk/scaffold/app/claude/skills/stk-lessons/SKILL.md +0 -0
  61. {stkit-17.0.1 → stkit-17.0.2}/stk/scaffold/app/claude/skills/stk-migrate/SKILL.md +0 -0
  62. {stkit-17.0.1 → stkit-17.0.2}/stk/scaffold/app/docker-compose.yml +0 -0
  63. {stkit-17.0.1 → stkit-17.0.2}/stk/scaffold/app/dockerignore +0 -0
  64. {stkit-17.0.1 → stkit-17.0.2}/stk/scaffold/app/env-sample +0 -0
  65. {stkit-17.0.1 → stkit-17.0.2}/stk/scaffold/app/github/workflows/checks.yml +0 -0
  66. {stkit-17.0.1 → stkit-17.0.2}/stk/scaffold/app/gitignore +0 -0
  67. {stkit-17.0.1 → stkit-17.0.2}/stk/scaffold/app/nginx/nginx.conf +0 -0
  68. {stkit-17.0.1 → stkit-17.0.2}/stk/scaffold/app/nginx/stk.conf +0 -0
  69. {stkit-17.0.1 → stkit-17.0.2}/stk/scaffold/app/postgres/init-db.sh +0 -0
  70. {stkit-17.0.1 → stkit-17.0.2}/stk/scaffold/app/pyproject.toml +0 -0
  71. {stkit-17.0.1 → stkit-17.0.2}/stk/scaffold/app/tests/__init__.py +0 -0
  72. {stkit-17.0.1 → stkit-17.0.2}/stk/scaffold/app/tests/test_app.py +0 -0
  73. {stkit-17.0.1 → stkit-17.0.2}/stk/scaffold/generator.py +0 -0
  74. {stkit-17.0.1 → stkit-17.0.2}/stk/scaffold/templates.py +0 -0
  75. {stkit-17.0.1 → stkit-17.0.2}/stk/security.py +0 -0
  76. {stkit-17.0.1 → stkit-17.0.2}/stk/settings.py +0 -0
  77. {stkit-17.0.1 → stkit-17.0.2}/stk/shell.py +0 -0
  78. {stkit-17.0.1 → stkit-17.0.2}/stk/static/VERSIONS.txt +0 -0
  79. {stkit-17.0.1 → stkit-17.0.2}/stk/static/css/app.css +0 -0
  80. {stkit-17.0.1 → stkit-17.0.2}/stk/static/css/layout.css +0 -0
  81. {stkit-17.0.1 → stkit-17.0.2}/stk/static/css/vuetify.min.css +0 -0
  82. {stkit-17.0.1 → stkit-17.0.2}/stk/static/icons/fonts/tabler-icons.woff2 +0 -0
  83. {stkit-17.0.1 → stkit-17.0.2}/stk/static/icons/tabler-icons.min.css +0 -0
  84. {stkit-17.0.1 → stkit-17.0.2}/stk/static/img/auth-bg.webp +0 -0
  85. {stkit-17.0.1 → stkit-17.0.2}/stk/static/img/favicon.ico +0 -0
  86. {stkit-17.0.1 → stkit-17.0.2}/stk/static/img/stk.svg +0 -0
  87. {stkit-17.0.1 → stkit-17.0.2}/stk/static/js/axios.min.js +0 -0
  88. {stkit-17.0.1 → stkit-17.0.2}/stk/static/js/components/NotificationDropdown.js +0 -0
  89. {stkit-17.0.1 → stkit-17.0.2}/stk/static/js/components/ThemeSwitcher.js +0 -0
  90. {stkit-17.0.1 → stkit-17.0.2}/stk/static/js/components/TransitionExpand.js +0 -0
  91. {stkit-17.0.1 → stkit-17.0.2}/stk/static/js/components/VerticalNavGroup.js +0 -0
  92. {stkit-17.0.1 → stkit-17.0.2}/stk/static/js/components/VerticalNavLink.js +0 -0
  93. {stkit-17.0.1 → stkit-17.0.2}/stk/static/js/components/VerticalNavSectionTitle.js +0 -0
  94. {stkit-17.0.1 → stkit-17.0.2}/stk/static/js/components/index.js +0 -0
  95. {stkit-17.0.1 → stkit-17.0.2}/stk/static/js/config.js +0 -0
  96. {stkit-17.0.1 → stkit-17.0.2}/stk/static/js/vue.min.js +0 -0
  97. {stkit-17.0.1 → stkit-17.0.2}/stk/static/js/vuetify.min.js +0 -0
  98. {stkit-17.0.1 → stkit-17.0.2}/stk/static/robots.txt +0 -0
  99. {stkit-17.0.1 → stkit-17.0.2}/stk/tasks/__init__.py +0 -0
  100. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/401.html +0 -0
  101. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/404.html +0 -0
  102. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/500.html +0 -0
  103. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/_brand.html +0 -0
  104. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/auth_layout.html +0 -0
  105. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/cms/activities.html +0 -0
  106. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/cms/roles.html +0 -0
  107. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/cms/users.html +0 -0
  108. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/dashboard.html +0 -0
  109. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/index.html +0 -0
  110. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/layout.html +0 -0
  111. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/login-layout.html +0 -0
  112. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/security/_macros.html +0 -0
  113. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/security/_messages.html +0 -0
  114. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/security/change_password.html +0 -0
  115. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/security/confirm_email.html +0 -0
  116. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/security/email/change_notice.html +0 -0
  117. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/security/email/change_notice.txt +0 -0
  118. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/security/email/confirmation_instructions.html +0 -0
  119. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/security/email/confirmation_instructions.txt +0 -0
  120. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/security/email/login_instructions.html +0 -0
  121. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/security/email/login_instructions.txt +0 -0
  122. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/security/email/reset_instructions.html +0 -0
  123. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/security/email/reset_instructions.txt +0 -0
  124. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/security/email/reset_notice.html +0 -0
  125. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/security/email/reset_notice.txt +0 -0
  126. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/security/email/welcome.html +0 -0
  127. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/security/email/welcome.txt +0 -0
  128. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/security/forgot_password.html +0 -0
  129. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/security/login_user.html +0 -0
  130. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/security/mf_recovery.html +0 -0
  131. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/security/mf_recovery_codes.html +0 -0
  132. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/security/register_user.html +0 -0
  133. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/security/reset_password.html +0 -0
  134. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/security/send_confirmation.html +0 -0
  135. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/security/send_login.html +0 -0
  136. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/security/two_factor_select.html +0 -0
  137. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/security/two_factor_setup.html +0 -0
  138. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/security/two_factor_verify_code.html +0 -0
  139. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/security/wan_register.html +0 -0
  140. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/security/wan_signin.html +0 -0
  141. {stkit-17.0.1 → stkit-17.0.2}/stk/templates/security/wan_verify.html +0 -0
  142. {stkit-17.0.1 → stkit-17.0.2}/stk/user/__init__.py +0 -0
  143. {stkit-17.0.1 → stkit-17.0.2}/stk/user/forms.py +0 -0
  144. {stkit-17.0.1 → stkit-17.0.2}/stk/user/models.py +0 -0
  145. {stkit-17.0.1 → stkit-17.0.2}/stk/user/views.py +0 -0
  146. {stkit-17.0.1 → stkit-17.0.2}/stk/utils/email.py +0 -0
  147. {stkit-17.0.1 → stkit-17.0.2}/stk/utils/ratelimit.py +0 -0
  148. {stkit-17.0.1 → stkit-17.0.2}/stk/websocket.py +0 -0
  149. {stkit-17.0.1 → stkit-17.0.2}/tests/test_agent_operability.py +0 -0
  150. {stkit-17.0.1 → stkit-17.0.2}/tests/test_branding.py +0 -0
  151. {stkit-17.0.1 → stkit-17.0.2}/tests/test_builder_ux.py +0 -0
  152. {stkit-17.0.1 → stkit-17.0.2}/tests/test_cli.py +0 -0
  153. {stkit-17.0.1 → stkit-17.0.2}/tests/test_composition.py +0 -0
  154. {stkit-17.0.1 → stkit-17.0.2}/tests/test_csrf_exempt.py +0 -0
  155. {stkit-17.0.1 → stkit-17.0.2}/tests/test_error_handler.py +0 -0
  156. {stkit-17.0.1 → stkit-17.0.2}/tests/test_migration_drift.py +0 -0
  157. {stkit-17.0.1 → stkit-17.0.2}/tests/test_production_security.py +0 -0
  158. {stkit-17.0.1 → stkit-17.0.2}/tests/test_scaffolder.py +0 -0
  159. {stkit-17.0.1 → stkit-17.0.2}/tests/test_security_compatibility.py +0 -0
  160. {stkit-17.0.1 → stkit-17.0.2}/tests/test_shell.py +0 -0
  161. {stkit-17.0.1 → stkit-17.0.2}/tests/test_smoke_pages.py +0 -0
  162. {stkit-17.0.1 → stkit-17.0.2}/tests/test_static_versioning.py +0 -0
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## v17.0.2 (2026-10-25)
4
+
5
+ No migration required.
6
+
7
+ - `stk verify` follows redirects from `/` and checks that the page it lands on answers 200, so an app whose `/` sends people to sign-in or to its own home passes. A redirect to a broken page still fails.
8
+ - Replacing stk's landing view is documented: `app.view_functions["public.index"] = home` in an extension's `init_app` (Architecture, Public).
9
+ - `STK_CLI_SECTIONS` groups an app's own commands in `stk --help`, after stk's sections, instead of listing them all under Other.
10
+
3
11
  ## v17.0.1 (2026-10-25)
4
12
 
5
13
  No migration required.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: stkit
3
- Version: 17.0.1
3
+ Version: 17.0.2
4
4
  Summary: An async Quart framework optimized for AI-assisted development workflows
5
5
  Author-email: Level09 <hello@level09.com>
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "stkit"
3
- version = "17.0.1"
3
+ version = "17.0.2"
4
4
  description = "An async Quart framework optimized for AI-assisted development workflows"
5
5
  authors = [
6
6
  {name = "Level09", email = "hello@level09.com"}
@@ -3,7 +3,7 @@ stk Framework
3
3
  A modern Python web framework optimized for AI-assisted development.
4
4
  """
5
5
 
6
- __version__ = "17.0.1"
6
+ __version__ = "17.0.2"
7
7
 
8
8
 
9
9
  def __getattr__(name):
@@ -286,10 +286,11 @@ def check_admin_reset_route(app):
286
286
  )
287
287
 
288
288
 
289
- @check("GET / returns 200")
289
+ @check("GET / answers 200, after any redirects")
290
290
  async def check_http_index(app):
291
+ # An app may send / to its sign-in or home page; what it lands on must work.
291
292
  client = app.test_client()
292
- response = await client.get("/")
293
+ response = await client.get("/", follow_redirects=True)
293
294
  assert response.status_code == 200, f"Expected 200, got {response.status_code}"
294
295
 
295
296
 
@@ -10,7 +10,7 @@ import inspect
10
10
  from importlib.metadata import version
11
11
 
12
12
  import click
13
- from quart.cli import QuartGroup
13
+ from quart.cli import NoAppException, QuartGroup, ScriptInfo
14
14
 
15
15
  import stk.cli as cli
16
16
  from stk.cli.base import load_app
@@ -44,7 +44,7 @@ class StkGroup(QuartGroup):
44
44
  if command is not None and not command.hidden:
45
45
  commands[name] = command
46
46
 
47
- for title, names in SECTIONS:
47
+ for title, names in [*SECTIONS, *_app_sections(ctx)]:
48
48
  rows = [
49
49
  (name, commands.pop(name).get_short_help_str(limit=60))
50
50
  for name in names
@@ -64,6 +64,17 @@ class StkGroup(QuartGroup):
64
64
  )
65
65
 
66
66
 
67
+ def _app_sections(ctx):
68
+ """The app's own help sections, `STK_CLI_SECTIONS`; none outside an app."""
69
+ try:
70
+ app = ctx.ensure_object(ScriptInfo).load_app()
71
+ except NoAppException:
72
+ return []
73
+ return [
74
+ (title, list(names)) for title, names in app.config.get("STK_CLI_SECTIONS", ())
75
+ ]
76
+
77
+
67
78
  def _create_app(**_kwargs):
68
79
  return load_app()
69
80
 
@@ -0,0 +1,43 @@
1
+ """An app may replace stk's landing page, and verify judges where / lands."""
2
+
3
+ import unittest
4
+ from types import SimpleNamespace
5
+
6
+ from quart import redirect
7
+
8
+ from stk.app import Stk
9
+ from stk.checks import check_http_index
10
+ from stk.cli.main import _app_sections
11
+ from stk.settings import TestingConfig
12
+
13
+
14
+ class AppIndexTest(unittest.IsolatedAsyncioTestCase):
15
+ async def test_index_can_be_replaced_and_a_redirect_passes_the_check(self):
16
+ app = Stk(__name__, config=TestingConfig)
17
+
18
+ async def home():
19
+ return redirect("/login")
20
+
21
+ app.view_functions["public.index"] = home
22
+ response = await app.test_client().get("/")
23
+ self.assertEqual(response.status_code, 302)
24
+ self.assertTrue(await check_http_index(app))
25
+
26
+ async def test_a_redirect_to_a_broken_page_fails_the_check(self):
27
+ app = Stk(__name__, config=TestingConfig)
28
+
29
+ async def home():
30
+ return redirect("/nowhere")
31
+
32
+ app.view_functions["public.index"] = home
33
+ self.assertFalse(await check_http_index(app))
34
+
35
+
36
+ class AppHelpSectionsTest(unittest.TestCase):
37
+ def test_app_sections_come_from_config(self):
38
+ app = Stk(__name__, config=TestingConfig)
39
+ app.config["STK_CLI_SECTIONS"] = [("Runs", ("worker", "enrich"))]
40
+ ctx = SimpleNamespace(
41
+ ensure_object=lambda _: SimpleNamespace(load_app=lambda: app)
42
+ )
43
+ self.assertEqual(_app_sections(ctx), [("Runs", ["worker", "enrich"])])
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes