stkit 17.0.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.
- stkit-17.0.0/.gitignore +33 -0
- stkit-17.0.0/CHANGELOG.md +253 -0
- stkit-17.0.0/LICENSE +21 -0
- stkit-17.0.0/PKG-INFO +135 -0
- stkit-17.0.0/README.md +88 -0
- stkit-17.0.0/SECURITY.md +24 -0
- stkit-17.0.0/examples/minimal/.env-sample +78 -0
- stkit-17.0.0/examples/minimal/.gitignore +8 -0
- stkit-17.0.0/examples/minimal/README.md +16 -0
- stkit-17.0.0/examples/minimal/minimal/__init__.py +1 -0
- stkit-17.0.0/examples/minimal/minimal/app.py +9 -0
- stkit-17.0.0/examples/minimal/minimal/migrations/364232ae77d5_add_note.py +37 -0
- stkit-17.0.0/examples/minimal/minimal/note/__init__.py +15 -0
- stkit-17.0.0/examples/minimal/minimal/note/models.py +40 -0
- stkit-17.0.0/examples/minimal/minimal/note/templates/note/index.html +186 -0
- stkit-17.0.0/examples/minimal/minimal/note/views.py +113 -0
- stkit-17.0.0/examples/minimal/minimal/settings.py +7 -0
- stkit-17.0.0/examples/minimal/minimal/templates/layout.html +3 -0
- stkit-17.0.0/examples/minimal/pyproject.toml +26 -0
- stkit-17.0.0/examples/minimal/tests/__init__.py +0 -0
- stkit-17.0.0/examples/minimal/tests/test_app.py +23 -0
- stkit-17.0.0/examples/minimal/uv.lock +2039 -0
- stkit-17.0.0/pyproject.toml +107 -0
- stkit-17.0.0/stk/__init__.py +19 -0
- stkit-17.0.0/stk/__main__.py +6 -0
- stkit-17.0.0/stk/agent_login.py +78 -0
- stkit-17.0.0/stk/app.py +323 -0
- stkit-17.0.0/stk/checks.py +634 -0
- stkit-17.0.0/stk/cli/__init__.py +49 -0
- stkit-17.0.0/stk/cli/agent.py +267 -0
- stkit-17.0.0/stk/cli/base.py +79 -0
- stkit-17.0.0/stk/cli/database.py +199 -0
- stkit-17.0.0/stk/cli/develop.py +63 -0
- stkit-17.0.0/stk/cli/doctor.py +262 -0
- stkit-17.0.0/stk/cli/main.py +101 -0
- stkit-17.0.0/stk/cli/reports.py +296 -0
- stkit-17.0.0/stk/cli/smoke.py +399 -0
- stkit-17.0.0/stk/cli/users.py +259 -0
- stkit-17.0.0/stk/cli/watch.py +68 -0
- stkit-17.0.0/stk/extensions.py +29 -0
- stkit-17.0.0/stk/migrations/__init__.py +130 -0
- stkit-17.0.0/stk/migrations/env.py +58 -0
- stkit-17.0.0/stk/migrations/script.py.mako +17 -0
- stkit-17.0.0/stk/migrations/versions/stk_0001_initial_schema.py +213 -0
- stkit-17.0.0/stk/portal/views.py +34 -0
- stkit-17.0.0/stk/public/__init__.py +0 -0
- stkit-17.0.0/stk/public/models.py +0 -0
- stkit-17.0.0/stk/public/views.py +344 -0
- stkit-17.0.0/stk/scaffold/__init__.py +1 -0
- stkit-17.0.0/stk/scaffold/app/CLAUDE.md +65 -0
- stkit-17.0.0/stk/scaffold/app/Dockerfile +41 -0
- stkit-17.0.0/stk/scaffold/app/README.md +16 -0
- stkit-17.0.0/stk/scaffold/app/__app__/__init__.py +1 -0
- stkit-17.0.0/stk/scaffold/app/__app__/app.py +8 -0
- stkit-17.0.0/stk/scaffold/app/__app__/settings.py +7 -0
- stkit-17.0.0/stk/scaffold/app/claude/skills/stk-api/SKILL.md +52 -0
- stkit-17.0.0/stk/scaffold/app/claude/skills/stk-blueprint/SKILL.md +48 -0
- stkit-17.0.0/stk/scaffold/app/claude/skills/stk-deploy/SKILL.md +61 -0
- stkit-17.0.0/stk/scaffold/app/claude/skills/stk-lessons/SKILL.md +58 -0
- stkit-17.0.0/stk/scaffold/app/claude/skills/stk-migrate/SKILL.md +96 -0
- stkit-17.0.0/stk/scaffold/app/docker-compose.yml +88 -0
- stkit-17.0.0/stk/scaffold/app/dockerignore +13 -0
- stkit-17.0.0/stk/scaffold/app/env-sample +78 -0
- stkit-17.0.0/stk/scaffold/app/gitignore +8 -0
- stkit-17.0.0/stk/scaffold/app/nginx/nginx.conf +46 -0
- stkit-17.0.0/stk/scaffold/app/nginx/stk.conf +36 -0
- stkit-17.0.0/stk/scaffold/app/postgres/init-db.sh +8 -0
- stkit-17.0.0/stk/scaffold/app/pyproject.toml +23 -0
- stkit-17.0.0/stk/scaffold/app/tests/__init__.py +0 -0
- stkit-17.0.0/stk/scaffold/app/tests/test_app.py +23 -0
- stkit-17.0.0/stk/scaffold/generator.py +209 -0
- stkit-17.0.0/stk/scaffold/templates.py +437 -0
- stkit-17.0.0/stk/security.py +145 -0
- stkit-17.0.0/stk/settings.py +147 -0
- stkit-17.0.0/stk/shell.py +284 -0
- stkit-17.0.0/stk/static/VERSIONS.txt +4 -0
- stkit-17.0.0/stk/static/css/app.css +229 -0
- stkit-17.0.0/stk/static/css/layout.css +330 -0
- stkit-17.0.0/stk/static/css/vuetify.min.css +6 -0
- stkit-17.0.0/stk/static/icons/fonts/tabler-icons.woff2 +0 -0
- stkit-17.0.0/stk/static/icons/tabler-icons.min.css +4 -0
- stkit-17.0.0/stk/static/img/auth-bg.webp +0 -0
- stkit-17.0.0/stk/static/img/favicon.ico +0 -0
- stkit-17.0.0/stk/static/img/stk.svg +1664 -0
- stkit-17.0.0/stk/static/js/axios.min.js +5 -0
- stkit-17.0.0/stk/static/js/components/NotificationDropdown.js +156 -0
- stkit-17.0.0/stk/static/js/components/ThemeSwitcher.js +68 -0
- stkit-17.0.0/stk/static/js/components/TransitionExpand.js +64 -0
- stkit-17.0.0/stk/static/js/components/VerticalNavGroup.js +119 -0
- stkit-17.0.0/stk/static/js/components/VerticalNavLink.js +36 -0
- stkit-17.0.0/stk/static/js/components/VerticalNavSectionTitle.js +21 -0
- stkit-17.0.0/stk/static/js/components/index.js +47 -0
- stkit-17.0.0/stk/static/js/config.js +150 -0
- stkit-17.0.0/stk/static/js/vue.min.js +13 -0
- stkit-17.0.0/stk/static/js/vuetify.min.js +3148 -0
- stkit-17.0.0/stk/static/robots.txt +1 -0
- stkit-17.0.0/stk/tasks/__init__.py +78 -0
- stkit-17.0.0/stk/templates/401.html +14 -0
- stkit-17.0.0/stk/templates/404.html +12 -0
- stkit-17.0.0/stk/templates/500.html +13 -0
- stkit-17.0.0/stk/templates/_brand.html +1 -0
- stkit-17.0.0/stk/templates/auth_layout.html +26 -0
- stkit-17.0.0/stk/templates/cms/activities.html +135 -0
- stkit-17.0.0/stk/templates/cms/roles.html +215 -0
- stkit-17.0.0/stk/templates/cms/users.html +312 -0
- stkit-17.0.0/stk/templates/dashboard.html +132 -0
- stkit-17.0.0/stk/templates/index.html +52 -0
- stkit-17.0.0/stk/templates/layout.html +328 -0
- stkit-17.0.0/stk/templates/login-layout.html +54 -0
- stkit-17.0.0/stk/templates/security/_macros.html +39 -0
- stkit-17.0.0/stk/templates/security/_messages.html +12 -0
- stkit-17.0.0/stk/templates/security/change_password.html +100 -0
- stkit-17.0.0/stk/templates/security/confirm_email.html +44 -0
- stkit-17.0.0/stk/templates/security/email/change_notice.html +4 -0
- stkit-17.0.0/stk/templates/security/email/change_notice.txt +5 -0
- stkit-17.0.0/stk/templates/security/email/confirmation_instructions.html +3 -0
- stkit-17.0.0/stk/templates/security/email/confirmation_instructions.txt +3 -0
- stkit-17.0.0/stk/templates/security/email/login_instructions.html +5 -0
- stkit-17.0.0/stk/templates/security/email/login_instructions.txt +5 -0
- stkit-17.0.0/stk/templates/security/email/reset_instructions.html +1 -0
- stkit-17.0.0/stk/templates/security/email/reset_instructions.txt +3 -0
- stkit-17.0.0/stk/templates/security/email/reset_notice.html +1 -0
- stkit-17.0.0/stk/templates/security/email/reset_notice.txt +1 -0
- stkit-17.0.0/stk/templates/security/email/welcome.html +7 -0
- stkit-17.0.0/stk/templates/security/email/welcome.txt +7 -0
- stkit-17.0.0/stk/templates/security/forgot_password.html +63 -0
- stkit-17.0.0/stk/templates/security/login_user.html +206 -0
- stkit-17.0.0/stk/templates/security/mf_recovery.html +67 -0
- stkit-17.0.0/stk/templates/security/mf_recovery_codes.html +119 -0
- stkit-17.0.0/stk/templates/security/register_user.html +263 -0
- stkit-17.0.0/stk/templates/security/reset_password.html +53 -0
- stkit-17.0.0/stk/templates/security/send_confirmation.html +48 -0
- stkit-17.0.0/stk/templates/security/send_login.html +39 -0
- stkit-17.0.0/stk/templates/security/two_factor_select.html +78 -0
- stkit-17.0.0/stk/templates/security/two_factor_setup.html +166 -0
- stkit-17.0.0/stk/templates/security/two_factor_verify_code.html +71 -0
- stkit-17.0.0/stk/templates/security/wan_register.html +179 -0
- stkit-17.0.0/stk/templates/security/wan_signin.html +123 -0
- stkit-17.0.0/stk/templates/security/wan_verify.html +109 -0
- stkit-17.0.0/stk/user/__init__.py +0 -0
- stkit-17.0.0/stk/user/forms.py +10 -0
- stkit-17.0.0/stk/user/models.py +308 -0
- stkit-17.0.0/stk/user/views.py +339 -0
- stkit-17.0.0/stk/utils/email.py +32 -0
- stkit-17.0.0/stk/utils/ratelimit.py +67 -0
- stkit-17.0.0/stk/websocket.py +133 -0
- stkit-17.0.0/tests/test_agent_operability.py +318 -0
- stkit-17.0.0/tests/test_branding.py +29 -0
- stkit-17.0.0/tests/test_builder_ux.py +114 -0
- stkit-17.0.0/tests/test_cli.py +63 -0
- stkit-17.0.0/tests/test_composition.py +122 -0
- stkit-17.0.0/tests/test_csrf_exempt.py +51 -0
- stkit-17.0.0/tests/test_error_handler.py +21 -0
- stkit-17.0.0/tests/test_migration_drift.py +50 -0
- stkit-17.0.0/tests/test_production_security.py +683 -0
- stkit-17.0.0/tests/test_scaffolder.py +352 -0
- stkit-17.0.0/tests/test_security_compatibility.py +122 -0
- stkit-17.0.0/tests/test_shell.py +87 -0
- stkit-17.0.0/tests/test_smoke_pages.py +92 -0
- stkit-17.0.0/tests/test_static_versioning.py +27 -0
stkit-17.0.0/.gitignore
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
*.pyc
|
|
2
|
+
.webassets-cache
|
|
3
|
+
.idea
|
|
4
|
+
celerybeat-schedule
|
|
5
|
+
env
|
|
6
|
+
.env
|
|
7
|
+
.env.backup*
|
|
8
|
+
local_settings.py
|
|
9
|
+
node_modules/
|
|
10
|
+
.DS_Store
|
|
11
|
+
.sass-cache
|
|
12
|
+
.vscode/
|
|
13
|
+
.cache/
|
|
14
|
+
.parcel-cache
|
|
15
|
+
stk.sqlite3
|
|
16
|
+
instance/
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
__pycache__/
|
|
20
|
+
|
|
21
|
+
# Claude Code
|
|
22
|
+
.claude/settings.local.json
|
|
23
|
+
*.skill
|
|
24
|
+
.quartenv
|
|
25
|
+
|
|
26
|
+
# Private planning docs and security reviews (never publish; checks.py fails if tracked)
|
|
27
|
+
security-review*
|
|
28
|
+
docs/plans/
|
|
29
|
+
docs/stk-report.html
|
|
30
|
+
docs/superpowers/
|
|
31
|
+
|
|
32
|
+
# Browser smoke artifacts
|
|
33
|
+
.stk/smoke/
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## v17.0.0 (unreleased)
|
|
4
|
+
|
|
5
|
+
stk becomes an installed, versioned package. An app is a separate, thin package that composes it and never edits a framework file, so upgrading stk is a version bump plus whatever its release note says.
|
|
6
|
+
|
|
7
|
+
### Breaking
|
|
8
|
+
|
|
9
|
+
- An app is no longer a fork of stk. `stk init <name>` writes an app package: `myapp/app.py` builds `Stk(__name__, config=Config, extensions=[...])`, settings are `class Config(stk.Config)` in `myapp/settings.py`, and the app depends on `stkit>=17,<18`: stk is published on PyPI as `stkit`, still imported as `stk` and run as `stk`. Commands find the app from `[tool.stk] app` in the nearest `pyproject.toml`, or from `STK_APP`.
|
|
10
|
+
- `create_app(Config)` is replaced by `Stk(import_name, config=..., extensions=[...])`. Each extension is a package with `init_app(app)`; its `models` module is imported before it is called. `run.py` is gone: uvicorn serves the `[tool.stk] app` value (`myapp.app:app`).
|
|
11
|
+
- Templates and static files resolve app first, then each extension's, then stk's. Core templates are reachable as `stk/<name>`. `layout.html` gains `title` and `navigation` blocks.
|
|
12
|
+
- The sidebar is data: `stk/static/js/navigation.js` is removed. Extensions add pages with `app.navigation.append({...})`; they appear under Dashboard in extension order.
|
|
13
|
+
- stk's migrations ship inside the package (`stk/migrations/`) as one squashed revision, `stk_0001`, with the branch label `stk`. An app keeps its own lineage in `myapp/migrations/`, and each app revision depends on stk's head. `stk db upgrade` runs `upgrade heads`. `alembic.ini` and the `alembic/` directory are gone. A database created by stk 16 is not upgraded.
|
|
14
|
+
- `stk new <module>` writes an extension into the app package and adds it to the app's `extensions` list; it no longer patches `stk/app.py` or `navigation.js`.
|
|
15
|
+
- `stk run` serves through uvicorn with a 3 second graceful shutdown, so Ctrl+C no longer hangs on open tabs. Its options are `--host`, `--port`, and `--reload/--no-reload`.
|
|
16
|
+
- Importing stk needs no environment: missing `SECRET_KEY` or `SECURITY_PASSWORD_SALT` fails when the app is built. `.env` is read from the working directory. `Config.APP_DIR` and `Config.PROJECT_ROOT` are removed; the default SQLite database is `instance/stk.db` beside the app package.
|
|
17
|
+
- `Dockerfile`, `docker-compose.yml`, `nginx/`, `postgres/`, and `.env-sample` move into the app template that `stk init` writes. Nginx and Caddy pass `/static/` to the app instead of reading `stk/static` from disk. `deploy.sh` requires `REPO`, your app's repository. `.gitattributes` and the merge-based upgrade guide are removed.
|
|
18
|
+
- `checks.py` moves to `stk/checks.py` and runs against the app. Its docs checks run only inside the stk repository.
|
|
19
|
+
|
|
20
|
+
### Also
|
|
21
|
+
|
|
22
|
+
- `stk db check` and `stk smoke` use a throwaway database of the configured dialect, so Postgres apps are checked on Postgres (the role needs CREATEDB). Autogenerate never offers to drop PostGIS's `spatial_ref_sys`. `stk.migrations.portable_tables()` returns the tables SQLite can build.
|
|
23
|
+
- Autogenerated revisions import what their column types need, and pass ruff without per-file exceptions.
|
|
24
|
+
- `stk doctor` reports the app it loaded and understands two lineages.
|
|
25
|
+
|
|
26
|
+
### Upgrade considerations
|
|
27
|
+
|
|
28
|
+
There is nothing to upgrade from: 17.0.0 starts the new design. To move an app built on stk 16, start a fresh app with `stk init`, move each module into the app package with an `init_app`, move its settings into the app's `Config`, turn template and navigation edits into overrides and `app.navigation` entries, and replace its migration history with one fresh app revision. Paste-ready prompt for a coding agent:
|
|
29
|
+
|
|
30
|
+
```text
|
|
31
|
+
Move this app off its stk 16 fork onto stk 17. Run `uvx --from stkit stk init <name>` next to it. For each module the app added under stk/: move it to <name>/<module>/, give its __init__.py an init_app(app) that registers its blueprint and appends its sidebar entries to app.navigation, and add it to `extensions` in <name>/app.py. Move app settings into <name>/settings.py (class Config(stk.Config)). Replace edited stk templates with files at the same path in <name>/templates/ that extend "stk/<name>" and override blocks. Delete the old migrations, then run `uv run stk db upgrade` and `uv run stk db revision -m "initial"`. Done when `uv run stk verify` and `uv run stk smoke` pass and no file under stk is edited.
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## v16.4.1 (2026-10-25)
|
|
35
|
+
|
|
36
|
+
No migration required.
|
|
37
|
+
|
|
38
|
+
- Apps built on stk upgrade by merging stk release tags: see Deployment, "Upgrading an app built on stk". `.gitattributes` keeps an app's README, CHANGELOG, lockfile, and brand files on merge once `git config merge.ours.driver true` is set. An app copied without stk's history records its starting commit once with `git merge -s ours --allow-unrelated-histories <commit>`.
|
|
39
|
+
- `stk smoke` skips every WebSocket route, not only `/ws`, and any path listed in the new `STK_SMOKE_SKIP` app config value.
|
|
40
|
+
- The Vue brace check in `stk verify` ignores `<script>` bodies, where JS template literals are valid.
|
|
41
|
+
|
|
42
|
+
## v16.4.0 (2026-10-25)
|
|
43
|
+
|
|
44
|
+
No migration required.
|
|
45
|
+
|
|
46
|
+
- New `stk-lessons` skill. When a failure the docs did not warn about costs an agent time, it logs one line in `.stk/lessons.md` and continues. On request, it triages the log: drops covered or one-off lessons, confirms the rest in code, and proposes each at the strongest home that holds (code default, `stk verify` check, `stk doctor` hint, docs line, skill step). Nothing applies without approval. Apps built on stk get framework lessons in generic terms to send upstream.
|
|
47
|
+
|
|
48
|
+
## v16.3.0 (2026-10-25)
|
|
49
|
+
|
|
50
|
+
No migration required.
|
|
51
|
+
|
|
52
|
+
- Static JS and CSS in the layouts load through `url_for('static', ...)`, which adds a content hash (`?v=...`). The app, `nginx/stk.conf`, and the Caddy config from `deploy.sh` cache versioned files forever and revalidate the rest. Servers set up by an earlier `deploy.sh` cached every static file for a year: re-run it or apply the new `handle_path /static/*` block to the Caddyfile.
|
|
53
|
+
- `alembic.ini` no longer names a database, so `uv run alembic` targets the app's database like `stk db` does.
|
|
54
|
+
- `Base` sets `eager_defaults`, so `server_default` and SQL `onupdate` columns are readable after a flush instead of raising `MissingGreenlet`.
|
|
55
|
+
- `TestingConfig` in `stk/settings.py` pins the database, sessions, mail, OAuth, rate limits, breach check, and agent login. Subclass it in tests instead of `Config` so `.env` never reaches them.
|
|
56
|
+
- `stk verify` fails on `{` inside a Vue `${ }` interpolation, which blanks the page.
|
|
57
|
+
|
|
58
|
+
## v16.2.1 (2026-10-23)
|
|
59
|
+
|
|
60
|
+
No migration required.
|
|
61
|
+
|
|
62
|
+
- `stk verify` fails on a migration whose `upgrade()` drops or renames a table or column, retypes a column, or adds a NOT NULL column without a `server_default`. Mark a deliberate step with a `# destructive: <reason>` comment inside `upgrade()`.
|
|
63
|
+
- `stk verify` fails when `CLAUDE.md` grows past 8KB or a skill past 4KB, so the agent index stays an index.
|
|
64
|
+
|
|
65
|
+
## v16.2.0 (2026-10-23)
|
|
66
|
+
|
|
67
|
+
No migration required.
|
|
68
|
+
|
|
69
|
+
- The docs in `docs/src/content/docs/` are the single source for humans and agents. `.stk/context/` and the `stk-dev` skill are removed; their content moved into the Frontend, Models, JSON APIs, Background Work, Build Loop, and Deployment pages. `AGENTS.md` is now an index of those pages plus the rules that fail silently. Apps that referenced `.stk/context/*.md` should point at the docs pages instead.
|
|
70
|
+
- `stk inspect commands` reports every command and option, as text, `--json`, or `--markdown`. The docs CLI reference is generated from it.
|
|
71
|
+
- `stk verify` fails when the CLI reference is stale, when `stk/settings.py` reads an environment variable the Configuration page does not list, when `AGENTS.md` misses a docs page, or when docs, skills, or the README point at a file that does not exist.
|
|
72
|
+
- New docs pages: Configuration, CLI Reference, Renaming Your App, and WebSockets in Background Work. The docs site uses the stk logo.
|
|
73
|
+
|
|
74
|
+
## v16.1.0 (2026-10-19)
|
|
75
|
+
|
|
76
|
+
No migration required. Existing databases keep their constraint names and show no drift.
|
|
77
|
+
|
|
78
|
+
- `APP_NAME`, `APP_TAGLINE` and `APP_DESCRIPTION` settings brand titles and auth pages. The logo lives in one partial, `stk/templates/_brand.html`. The placeholder Terms of Service and Privacy Policy line is removed from login and registration.
|
|
79
|
+
- `stk.security.csrf_exempt` lets a signed third-party webhook skip the CSRF token check. Host, API body and pagination checks still apply, and the view must authenticate the caller itself.
|
|
80
|
+
- `stk smoke` also visits every parameterless GET page, skipping auth flows, APIs and webhooks, and fails on uncaught page errors.
|
|
81
|
+
- Unhandled database errors return 500 and are logged instead of using the SQLAlchemy error code as the status.
|
|
82
|
+
- `stk db downgrade -1` accepts relative targets.
|
|
83
|
+
- `stk install` and `stk create` reject email addresses the login form would refuse.
|
|
84
|
+
- New constraints are named by a convention on `Base.metadata`, so SQLite batch migrations can add foreign keys.
|
|
85
|
+
- The navigation drawer starts closed on phones.
|
|
86
|
+
- `stk --version` reports the framework version when an app renames its package, and `setup.sh` runs without a terminal.
|
|
87
|
+
|
|
88
|
+
## v16.0.0 (2026-10-06)
|
|
89
|
+
|
|
90
|
+
Requires quart-security 2.0.1. Run `uv run stk db upgrade` and `uv run stk protect-mfa` before upgrading an existing deployment. Preserve the MFA encryption keys.
|
|
91
|
+
|
|
92
|
+
- Require CSRF tokens for application mutations and send them from Axios.
|
|
93
|
+
- Use single-use OAuth state, PKCE, signed Google ID tokens, and verified GitHub email. Disable automatic email linking and enforce local MFA and account lockout.
|
|
94
|
+
- Rotate Redis session IDs on authentication changes and keep tracking records aligned with revoked sessions.
|
|
95
|
+
- Use atomic SQL authentication limits across workers. Apply migration `20261006_0002` before starting the app.
|
|
96
|
+
- Bound WebSocket connections, queues, messages, and lifetime. Require same-origin connections and explicit broadcast recipients. Remove automatic audit broadcasts.
|
|
97
|
+
- Enforce admin password policy and bound API pagination. Use Argon2id for new passwords; existing hashes still verify.
|
|
98
|
+
- Encrypt enrolled and pending MFA seeds. `stk protect-mfa` encrypts dormant accounts and supports key rotation.
|
|
99
|
+
- Disable public password registration by default. Set `SECURITY_REGISTERABLE=True` only when required.
|
|
100
|
+
- Require unique database and Redis secrets plus TLS certificates in Docker Compose. Keep data services and the app port private.
|
|
101
|
+
- Update vulnerable runtime packages and add PostgreSQL and Redis security checks to CI.
|
|
102
|
+
|
|
103
|
+
See `SECURITY.md` for deployment requirements and review limits.
|
|
104
|
+
|
|
105
|
+
## v15.0.0 (2026-10-06)
|
|
106
|
+
|
|
107
|
+
Requires quart-security 2.0.0 and a database migration before startup.
|
|
108
|
+
Run `uv run stk db upgrade` to add the shared authentication-state table.
|
|
109
|
+
Existing login cookies are invalidated.
|
|
110
|
+
|
|
111
|
+
- Share database sessions between authentication and application routes.
|
|
112
|
+
- Revoke authentication state on logout, password resets, and single-session login.
|
|
113
|
+
- Preserve local HTTP cookie configuration and default to secure cookies.
|
|
114
|
+
- Pass application settings to password hashing in account commands.
|
|
115
|
+
- Add regression checks for startup, copied cookies, session revocation, and TOTP replay.
|
|
116
|
+
|
|
117
|
+
## v14.1.0 (2026-07-25)
|
|
118
|
+
|
|
119
|
+
### Added
|
|
120
|
+
- `stk doctor`: env, secrets, database, migration state, admin user, vendored
|
|
121
|
+
assets, agent-login exposure, browser, and REPL, each problem with the command
|
|
122
|
+
that fixes it. `--json` for tooling.
|
|
123
|
+
- `stk verify --watch`: re-runs only the checks a changed file can break (models
|
|
124
|
+
touch migration drift, templates do not) and prints the remedy under a failure.
|
|
125
|
+
- Every verify check now carries its remedy, in the text output and in the JSON.
|
|
126
|
+
- `stk new <name>` generates and applies the migration, then prints the URL of the
|
|
127
|
+
page it created. `--no-migrate` opts out.
|
|
128
|
+
- Docs: `build-loop.mdx` and `shell.mdx`, both example-first.
|
|
129
|
+
|
|
130
|
+
### Changed
|
|
131
|
+
- Alembic failures report one line plus a next step instead of a traceback.
|
|
132
|
+
- CI actions bumped off Node 20 (checkout v7, setup-uv v9, upload-artifact v7).
|
|
133
|
+
- `alembic.ini` sets `path_separator`, silencing the deprecation warning.
|
|
134
|
+
|
|
135
|
+
### Removed
|
|
136
|
+
- `stk migrate` and `stk migration-status`, pure aliases for `stk db upgrade` and
|
|
137
|
+
`stk db current`.
|
|
138
|
+
|
|
139
|
+
## v14.0.0 (2026-07-25)
|
|
140
|
+
|
|
141
|
+
Bundles the unreleased 13.4.x work (hardened auth via quart-security 1.4.1) with a
|
|
142
|
+
new CLI, a frontend upgrade, and three gates that catch failures the old gate could
|
|
143
|
+
not see.
|
|
144
|
+
|
|
145
|
+
### Added
|
|
146
|
+
- `stk` command as the single entry point: grouped `--help`, app factory baked in
|
|
147
|
+
(no `QUART_APP`), `python -m stk` and `uv run stk` both work. `quart <command>`
|
|
148
|
+
keeps working.
|
|
149
|
+
- `stk shell`: async REPL with the app, a live `db` session, every model, query
|
|
150
|
+
helpers, and top-level `await`. Uses ptpython (dev extra) for highlighting,
|
|
151
|
+
fuzzy completion, and fish-style suggestions; falls back to the stdlib console.
|
|
152
|
+
`stk shell -c "await count(User)"` for one-shot queries and scripts.
|
|
153
|
+
- `stk db check`: fails when models have drifted from migrations, measured by
|
|
154
|
+
running migrations onto a throwaway database. Part of `stk verify`, so CI enforces it.
|
|
155
|
+
- `stk smoke` now visits `/`, measures WCAG contrast on every button, chip, and
|
|
156
|
+
alert, and fails on text that is invisible against its background.
|
|
157
|
+
- `checks.py` asserts every route the report calls guarded actually rejects
|
|
158
|
+
anonymous access.
|
|
159
|
+
- `vendor.sh` refreshes pinned frontend assets; versions recorded in
|
|
160
|
+
`stk/static/VERSIONS.txt`.
|
|
161
|
+
|
|
162
|
+
### Changed
|
|
163
|
+
- **Vuetify 3.7.8 to 4.1.6.** Material Design 2 type classes are gone; 67 usages
|
|
164
|
+
renamed to the MD3 names (`text-h5` to `text-headline-small`, and so on). Forks
|
|
165
|
+
with custom templates must do the same rename. Mapping table in
|
|
166
|
+
`.stk/context/frontend.md`.
|
|
167
|
+
- Vue 3.3.4 to 3.5.40, now the production build (was shipping the dev build).
|
|
168
|
+
Axios to 1.18.1. Tabler Icons 3.45.0 self-hosted instead of an unpinned CDN.
|
|
169
|
+
- `stk/commands.py` (918 lines) split into `stk/cli/`: `agent`, `database`,
|
|
170
|
+
`users`, `reports`, `smoke`, `base`.
|
|
171
|
+
- Route auth in `stk inspect routes` is read from the actual guard chain instead
|
|
172
|
+
of guessed from path prefixes.
|
|
173
|
+
- `stk verify` prints the tail of a failing check instead of a bare cross.
|
|
174
|
+
|
|
175
|
+
### Fixed
|
|
176
|
+
- Seven security routes (`/change`, `/tf-setup`, `/wan-register`, and others) were
|
|
177
|
+
reported as public while actually requiring auth.
|
|
178
|
+
- `GET /mf-recovery` returned 500 to anonymous users: the template used
|
|
179
|
+
`mf_recovery_form` while quart-security passes `recovery_form`.
|
|
180
|
+
- Nav filtering mutated state inside a computed, which hung the dashboard under
|
|
181
|
+
Vue 3.5's production reactivity (the dev build only warned).
|
|
182
|
+
- Buttons rendered as anchors took the link colour, so a primary button on a
|
|
183
|
+
primary background was invisible. Vuetify 4 ships in CSS cascade layers, which
|
|
184
|
+
let unlayered app CSS win.
|
|
185
|
+
- Smoke output redacted the agent-login token by list position, leaking it when a
|
|
186
|
+
page was added.
|
|
187
|
+
|
|
188
|
+
### Removed
|
|
189
|
+
- 5.1MB of unused Material Design Icons (referenced nowhere).
|
|
190
|
+
- `register_shellcontext`, replaced by `stk shell`.
|
|
191
|
+
- Empty `stk/core/` and app packages left over from a killed branch.
|
|
192
|
+
|
|
193
|
+
## v11.3.0 (2025-12-02)
|
|
194
|
+
|
|
195
|
+
### Added
|
|
196
|
+
- Lite mode: Zero-config startup with `uv sync && flask run` — no Redis required
|
|
197
|
+
- Full mode: Optional Redis + Celery via `uv sync --extra full`
|
|
198
|
+
- SQLAlchemy-based sessions as default (Redis sessions optional)
|
|
199
|
+
- AI-assisted development with AGENTS.md for Claude Code and Cursor
|
|
200
|
+
|
|
201
|
+
### Changed
|
|
202
|
+
- Redis and Celery moved to optional dependencies
|
|
203
|
+
- SQLite database path now uses absolute path in `instance/stk.db`
|
|
204
|
+
- Updated documentation for lite/full mode workflow
|
|
205
|
+
- Simplified README with clearer positioning
|
|
206
|
+
|
|
207
|
+
## v11.2.0 (2025-04-24)
|
|
208
|
+
|
|
209
|
+
### Added
|
|
210
|
+
- Production-ready Docker configuration with multi-stage builds
|
|
211
|
+
- PostgreSQL service in Docker Compose setup
|
|
212
|
+
- Improved environment variable handling for Docker
|
|
213
|
+
- Support for user-specific Docker UID configuration
|
|
214
|
+
- Enhanced setup.sh script with Docker configuration option
|
|
215
|
+
|
|
216
|
+
### Changed
|
|
217
|
+
- Optimized Dockerfile with multi-stage build for smaller, more secure images
|
|
218
|
+
- Fixed Redis connectivity by using correct environment variables
|
|
219
|
+
- Improved nginx configuration with proper retry settings
|
|
220
|
+
- Enhanced tmpfs configuration for better performance
|
|
221
|
+
- Added proper health checks for all Docker services
|
|
222
|
+
|
|
223
|
+
## v11.1.0 (2025-03-30)
|
|
224
|
+
|
|
225
|
+
### Added
|
|
226
|
+
- Migrated from pip/venv to uv for package management
|
|
227
|
+
- Faster installation and dependency resolution
|
|
228
|
+
- Better Python environment isolation
|
|
229
|
+
|
|
230
|
+
### Changed
|
|
231
|
+
- Updated setup.sh script to use uv instead of venv
|
|
232
|
+
- Modified Dockerfile to use uv for package installation
|
|
233
|
+
- Updated documentation to reference uv
|
|
234
|
+
|
|
235
|
+
## v11.0 (2023-03-27)
|
|
236
|
+
|
|
237
|
+
### Added
|
|
238
|
+
- New activity model to track user actions like creating and editing users/roles
|
|
239
|
+
- Cursor Rules for improved code generation and assistance
|
|
240
|
+
- Comprehensive documentation for Cursor Rules approach
|
|
241
|
+
|
|
242
|
+
### Changed
|
|
243
|
+
- Improved user and roles tables design in both frontend and backend
|
|
244
|
+
- Transitioned from OpenAI integration to Cursor Rules for code generation
|
|
245
|
+
- Enhanced admin user creation with better console output
|
|
246
|
+
|
|
247
|
+
### Removed
|
|
248
|
+
- Removed flask-openai dependency and related code generation commands
|
|
249
|
+
- Removed OpenAI API key requirements
|
|
250
|
+
|
|
251
|
+
### Fixed
|
|
252
|
+
- Various UI and UX improvements
|
|
253
|
+
- Code cleanup and bug fixes
|
stkit-17.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020 Nidal Alhariri
|
|
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.
|
stkit-17.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: stkit
|
|
3
|
+
Version: 17.0.0
|
|
4
|
+
Summary: An async Quart framework optimized for AI-assisted development workflows
|
|
5
|
+
Author-email: Level09 <hello@level09.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Python: >=3.11
|
|
9
|
+
Requires-Dist: aiosmtplib>=5.0.0
|
|
10
|
+
Requires-Dist: aiosqlite>=0.20.0
|
|
11
|
+
Requires-Dist: alembic>=1.16.0
|
|
12
|
+
Requires-Dist: authlib<2,>=1.9.1
|
|
13
|
+
Requires-Dist: bcrypt>=4.3.0
|
|
14
|
+
Requires-Dist: blinker>=1.9.0
|
|
15
|
+
Requires-Dist: click>=8.3.1
|
|
16
|
+
Requires-Dist: cryptography>=45.0.5
|
|
17
|
+
Requires-Dist: email-validator>=2.2.0
|
|
18
|
+
Requires-Dist: httpx2>=2.16.0
|
|
19
|
+
Requires-Dist: httpx>=0.27.0
|
|
20
|
+
Requires-Dist: jinja2>=3.1.6
|
|
21
|
+
Requires-Dist: joserfc<2,>=1.7.1
|
|
22
|
+
Requires-Dist: libpass>=1.9.0
|
|
23
|
+
Requires-Dist: orjson>=3.10.18
|
|
24
|
+
Requires-Dist: pillow>=13.0.0
|
|
25
|
+
Requires-Dist: psycopg2-binary>=2.9.10
|
|
26
|
+
Requires-Dist: python-dotenv>=1.1.1
|
|
27
|
+
Requires-Dist: qrcode>=8.2
|
|
28
|
+
Requires-Dist: quart-security<3,>=2.0.1
|
|
29
|
+
Requires-Dist: quart-session>=3.0.0
|
|
30
|
+
Requires-Dist: quart>=0.20.0
|
|
31
|
+
Requires-Dist: rich>=14.0.0
|
|
32
|
+
Requires-Dist: sqlalchemy[asyncio]>=2.0.41
|
|
33
|
+
Requires-Dist: uvicorn>=0.40.0
|
|
34
|
+
Requires-Dist: webauthn>=2.6.0
|
|
35
|
+
Requires-Dist: wtforms>=3.2.1
|
|
36
|
+
Provides-Extra: asgi
|
|
37
|
+
Requires-Dist: hypercorn>=0.17.0; extra == 'asgi'
|
|
38
|
+
Provides-Extra: dev
|
|
39
|
+
Requires-Dist: playwright; extra == 'dev'
|
|
40
|
+
Requires-Dist: pre-commit; extra == 'dev'
|
|
41
|
+
Requires-Dist: ptpython>=3.0.30; extra == 'dev'
|
|
42
|
+
Requires-Dist: ruff; extra == 'dev'
|
|
43
|
+
Provides-Extra: full
|
|
44
|
+
Requires-Dist: asyncpg>=0.30.0; extra == 'full'
|
|
45
|
+
Requires-Dist: redis>=7.1.0; extra == 'full'
|
|
46
|
+
Description-Content-Type: text/markdown
|
|
47
|
+
|
|
48
|
+
<p align="center">
|
|
49
|
+
<picture>
|
|
50
|
+
<source media="(prefers-color-scheme: dark)" srcset="docs/src/assets/logo-dark.webp">
|
|
51
|
+
<img src="docs/src/assets/logo-light.webp" alt="stk" width="360">
|
|
52
|
+
</picture>
|
|
53
|
+
</p>
|
|
54
|
+
|
|
55
|
+
<h1 align="center">stk</h1>
|
|
56
|
+
|
|
57
|
+
<p align="center">
|
|
58
|
+
<strong>Async Python framework with batteries you actually need.</strong><br>
|
|
59
|
+
Auth, 2FA, WebAuthn, OAuth, WebSockets, admin dashboard, Vue 3 frontend. No build step, no third-party auth services. One codebase, you own everything.
|
|
60
|
+
STK makes SaaS apps legible, changeable, testable, and operable by agents.
|
|
61
|
+
</p>
|
|
62
|
+
|
|
63
|
+
<p align="center">
|
|
64
|
+
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT"></a>
|
|
65
|
+
<a href="https://www.python.org/"><img src="https://img.shields.io/badge/python-3.11%2B-blue.svg" alt="Python 3.11+"></a>
|
|
66
|
+
<a href="https://docs.astral.sh/uv/"><img src="https://img.shields.io/badge/uv-package%20manager-blueviolet.svg" alt="uv"></a>
|
|
67
|
+
</p>
|
|
68
|
+
|
|
69
|
+
<p align="center">
|
|
70
|
+
<a href="https://docs.stk.dev">Docs</a> ·
|
|
71
|
+
<a href="https://docs.stk.dev/llms.txt">llms.txt</a> ·
|
|
72
|
+
<a href="https://github.com/level09/stk/wiki">Tutorials</a>
|
|
73
|
+
</p>
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
uvx --from stkit stk init myapp && cd myapp
|
|
79
|
+
uv run stk db upgrade # database via Alembic
|
|
80
|
+
uv run stk install # admin user
|
|
81
|
+
uv run stk run # localhost:5000
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Your app is its own package that composes stk, not a fork of it. Upgrading stk is a version bump.
|
|
85
|
+
|
|
86
|
+
## Why stk
|
|
87
|
+
|
|
88
|
+
Most frameworks give you routing and leave the rest as homework. Auth alone eats weeks. Then you bolt on Clerk or Auth0, hand your users' credentials to a third party, and pay per-MAU for the privilege.
|
|
89
|
+
|
|
90
|
+
stk ships what actually matters:
|
|
91
|
+
|
|
92
|
+
**You own your auth.** Login, session management, TOTP 2FA (Google Authenticator, Authy, 1Password), WebAuthn passkeys (Touch ID, YubiKey), recovery codes, OAuth (Google, GitHub). Production code, not a tutorial. Your users' data stays on your server.
|
|
93
|
+
|
|
94
|
+
**Async all the way down.** Quart + async SQLAlchemy + aiosmtplib + native WebSockets. Not async bolted onto a sync framework. Real concurrency without threads, workers, or callback hell.
|
|
95
|
+
|
|
96
|
+
**No JS build step.** Vue 3 + Vuetify 4 loaded directly in the browser. No webpack, no vite, no node_modules, no npm. Delete your frontend toolchain. Still get a polished admin dashboard with data tables, dark mode, collapsible sidebar, 5000+ icons.
|
|
97
|
+
|
|
98
|
+
**SQLite by default.** Deploy anywhere. No managed database required. PostgreSQL when you need it, not when the framework demands it.
|
|
99
|
+
|
|
100
|
+
**No Celery, no Redis (unless you want them).** Background tasks run on asyncio. Session store works with cookies or Redis. Complexity is opt-in.
|
|
101
|
+
|
|
102
|
+
**Built to be operated by agents.** `stk inspect` reports routes, auth guards, models, and commands as JSON. `stk verify` and `stk smoke` are a real gate: lint, migration drift, and a real browser that fails on console errors and invisible text. The docs ship in the repo and the gate fails when they drift from the code.
|
|
103
|
+
|
|
104
|
+
> **Want payments?** [ReadyKit](https://readykit.dev) adds Stripe, multi-tenancy, and teams on top of stk.
|
|
105
|
+
|
|
106
|
+
## What's included
|
|
107
|
+
|
|
108
|
+
- **Auth and security:** Argon2id passwords (12 char minimum), TOTP 2FA, passkeys as first or second factor, recovery codes, Google and GitHub OAuth with PKCE and verified emails, session tracking by IP and device, account lockout, per-IP rate limits shared across workers, CSRF on every mutation. Public sign-up is off by default.
|
|
109
|
+
- **Admin dashboard:** users, roles, and an activity audit log, with server-paginated tables and JSON APIs.
|
|
110
|
+
- **Real-time:** authenticated, origin-checked WebSockets that push to a named user and close when the session ends.
|
|
111
|
+
- **Frontend:** Vue 3 and Vuetify 4 with no build step, dark mode, collapsible sidebar, notifications, Tabler Icons.
|
|
112
|
+
- **Tooling:** one CLI, `stk`: run, shell, new, db, doctor, verify, smoke, inspect, report, and user management.
|
|
113
|
+
- **Deploy:** a one-command VPS script (Caddy, systemd, hardened OS) or Docker Compose with PostgreSQL, Redis, and Nginx.
|
|
114
|
+
|
|
115
|
+
## Stack
|
|
116
|
+
|
|
117
|
+
| Layer | Tech |
|
|
118
|
+
|-------|------|
|
|
119
|
+
| Runtime | Python 3.11+, [uv](https://docs.astral.sh/uv/) |
|
|
120
|
+
| Web | [Quart](https://quart.palletsprojects.com/) (async Flask) |
|
|
121
|
+
| ORM | SQLAlchemy 2.0+ async |
|
|
122
|
+
| Database | SQLite (default), PostgreSQL (optional) |
|
|
123
|
+
| Migrations | Alembic |
|
|
124
|
+
| Auth | [quart-security](https://quart-security.readthedocs.io/) (2FA, WebAuthn, OAuth) |
|
|
125
|
+
| Frontend | Vue 3, Vuetify 4, Axios |
|
|
126
|
+
| Server | Uvicorn (ASGI) behind Caddy or Nginx |
|
|
127
|
+
|
|
128
|
+
## Documentation
|
|
129
|
+
|
|
130
|
+
Everything else lives at [docs.stk.dev](https://docs.stk.dev), and in this repo at `docs/src/content/docs/`:
|
|
131
|
+
[quick start](https://docs.stk.dev/getting-started/), [build loop](https://docs.stk.dev/build-loop/), [models](https://docs.stk.dev/models/), [frontend](https://docs.stk.dev/frontend/), [authentication](https://docs.stk.dev/authentication/), [configuration](https://docs.stk.dev/configuration/), [CLI reference](https://docs.stk.dev/cli/), [deployment](https://docs.stk.dev/deployment/), and [working with agents](https://docs.stk.dev/ai-coding/). Upgrade notes are in `CHANGELOG.md`; the production security contract is `SECURITY.md`.
|
|
132
|
+
|
|
133
|
+
## License
|
|
134
|
+
|
|
135
|
+
MIT
|
stkit-17.0.0/README.md
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<picture>
|
|
3
|
+
<source media="(prefers-color-scheme: dark)" srcset="docs/src/assets/logo-dark.webp">
|
|
4
|
+
<img src="docs/src/assets/logo-light.webp" alt="stk" width="360">
|
|
5
|
+
</picture>
|
|
6
|
+
</p>
|
|
7
|
+
|
|
8
|
+
<h1 align="center">stk</h1>
|
|
9
|
+
|
|
10
|
+
<p align="center">
|
|
11
|
+
<strong>Async Python framework with batteries you actually need.</strong><br>
|
|
12
|
+
Auth, 2FA, WebAuthn, OAuth, WebSockets, admin dashboard, Vue 3 frontend. No build step, no third-party auth services. One codebase, you own everything.
|
|
13
|
+
STK makes SaaS apps legible, changeable, testable, and operable by agents.
|
|
14
|
+
</p>
|
|
15
|
+
|
|
16
|
+
<p align="center">
|
|
17
|
+
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT"></a>
|
|
18
|
+
<a href="https://www.python.org/"><img src="https://img.shields.io/badge/python-3.11%2B-blue.svg" alt="Python 3.11+"></a>
|
|
19
|
+
<a href="https://docs.astral.sh/uv/"><img src="https://img.shields.io/badge/uv-package%20manager-blueviolet.svg" alt="uv"></a>
|
|
20
|
+
</p>
|
|
21
|
+
|
|
22
|
+
<p align="center">
|
|
23
|
+
<a href="https://docs.stk.dev">Docs</a> ·
|
|
24
|
+
<a href="https://docs.stk.dev/llms.txt">llms.txt</a> ·
|
|
25
|
+
<a href="https://github.com/level09/stk/wiki">Tutorials</a>
|
|
26
|
+
</p>
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
uvx --from stkit stk init myapp && cd myapp
|
|
32
|
+
uv run stk db upgrade # database via Alembic
|
|
33
|
+
uv run stk install # admin user
|
|
34
|
+
uv run stk run # localhost:5000
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Your app is its own package that composes stk, not a fork of it. Upgrading stk is a version bump.
|
|
38
|
+
|
|
39
|
+
## Why stk
|
|
40
|
+
|
|
41
|
+
Most frameworks give you routing and leave the rest as homework. Auth alone eats weeks. Then you bolt on Clerk or Auth0, hand your users' credentials to a third party, and pay per-MAU for the privilege.
|
|
42
|
+
|
|
43
|
+
stk ships what actually matters:
|
|
44
|
+
|
|
45
|
+
**You own your auth.** Login, session management, TOTP 2FA (Google Authenticator, Authy, 1Password), WebAuthn passkeys (Touch ID, YubiKey), recovery codes, OAuth (Google, GitHub). Production code, not a tutorial. Your users' data stays on your server.
|
|
46
|
+
|
|
47
|
+
**Async all the way down.** Quart + async SQLAlchemy + aiosmtplib + native WebSockets. Not async bolted onto a sync framework. Real concurrency without threads, workers, or callback hell.
|
|
48
|
+
|
|
49
|
+
**No JS build step.** Vue 3 + Vuetify 4 loaded directly in the browser. No webpack, no vite, no node_modules, no npm. Delete your frontend toolchain. Still get a polished admin dashboard with data tables, dark mode, collapsible sidebar, 5000+ icons.
|
|
50
|
+
|
|
51
|
+
**SQLite by default.** Deploy anywhere. No managed database required. PostgreSQL when you need it, not when the framework demands it.
|
|
52
|
+
|
|
53
|
+
**No Celery, no Redis (unless you want them).** Background tasks run on asyncio. Session store works with cookies or Redis. Complexity is opt-in.
|
|
54
|
+
|
|
55
|
+
**Built to be operated by agents.** `stk inspect` reports routes, auth guards, models, and commands as JSON. `stk verify` and `stk smoke` are a real gate: lint, migration drift, and a real browser that fails on console errors and invisible text. The docs ship in the repo and the gate fails when they drift from the code.
|
|
56
|
+
|
|
57
|
+
> **Want payments?** [ReadyKit](https://readykit.dev) adds Stripe, multi-tenancy, and teams on top of stk.
|
|
58
|
+
|
|
59
|
+
## What's included
|
|
60
|
+
|
|
61
|
+
- **Auth and security:** Argon2id passwords (12 char minimum), TOTP 2FA, passkeys as first or second factor, recovery codes, Google and GitHub OAuth with PKCE and verified emails, session tracking by IP and device, account lockout, per-IP rate limits shared across workers, CSRF on every mutation. Public sign-up is off by default.
|
|
62
|
+
- **Admin dashboard:** users, roles, and an activity audit log, with server-paginated tables and JSON APIs.
|
|
63
|
+
- **Real-time:** authenticated, origin-checked WebSockets that push to a named user and close when the session ends.
|
|
64
|
+
- **Frontend:** Vue 3 and Vuetify 4 with no build step, dark mode, collapsible sidebar, notifications, Tabler Icons.
|
|
65
|
+
- **Tooling:** one CLI, `stk`: run, shell, new, db, doctor, verify, smoke, inspect, report, and user management.
|
|
66
|
+
- **Deploy:** a one-command VPS script (Caddy, systemd, hardened OS) or Docker Compose with PostgreSQL, Redis, and Nginx.
|
|
67
|
+
|
|
68
|
+
## Stack
|
|
69
|
+
|
|
70
|
+
| Layer | Tech |
|
|
71
|
+
|-------|------|
|
|
72
|
+
| Runtime | Python 3.11+, [uv](https://docs.astral.sh/uv/) |
|
|
73
|
+
| Web | [Quart](https://quart.palletsprojects.com/) (async Flask) |
|
|
74
|
+
| ORM | SQLAlchemy 2.0+ async |
|
|
75
|
+
| Database | SQLite (default), PostgreSQL (optional) |
|
|
76
|
+
| Migrations | Alembic |
|
|
77
|
+
| Auth | [quart-security](https://quart-security.readthedocs.io/) (2FA, WebAuthn, OAuth) |
|
|
78
|
+
| Frontend | Vue 3, Vuetify 4, Axios |
|
|
79
|
+
| Server | Uvicorn (ASGI) behind Caddy or Nginx |
|
|
80
|
+
|
|
81
|
+
## Documentation
|
|
82
|
+
|
|
83
|
+
Everything else lives at [docs.stk.dev](https://docs.stk.dev), and in this repo at `docs/src/content/docs/`:
|
|
84
|
+
[quick start](https://docs.stk.dev/getting-started/), [build loop](https://docs.stk.dev/build-loop/), [models](https://docs.stk.dev/models/), [frontend](https://docs.stk.dev/frontend/), [authentication](https://docs.stk.dev/authentication/), [configuration](https://docs.stk.dev/configuration/), [CLI reference](https://docs.stk.dev/cli/), [deployment](https://docs.stk.dev/deployment/), and [working with agents](https://docs.stk.dev/ai-coding/). Upgrade notes are in `CHANGELOG.md`; the production security contract is `SECURITY.md`.
|
|
85
|
+
|
|
86
|
+
## License
|
|
87
|
+
|
|
88
|
+
MIT
|
stkit-17.0.0/SECURITY.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Security and production deployment
|
|
2
|
+
|
|
3
|
+
Use the locked dependencies with `uv sync --frozen --extra full`. Apply `uv run stk db upgrade` and `uv run stk protect-mfa` before starting an existing deployment. Version 16 adds `rate_limit_window`; version 15 added `quart_security_state`. Both tables are required. Docker Compose runs the migrations before the app starts.
|
|
4
|
+
|
|
5
|
+
Use a unique generated `SECRET_KEY` and `SECURITY_PASSWORD_SALT`. Set `STK_ENV=production`, `QUART_DEBUG=0`, and `SESSION_COOKIE_SECURE=True`. Set `STK_PUBLIC_URL` to the HTTPS origin of the app. Set `SECURITY_WAN_RP_ID` to its DNS name and `SECURITY_WAN_EXPECTED_ORIGIN` to that HTTPS origin. The public URL restricts request hosts and fixes OAuth callback URLs. Trust proxy headers only from your proxy. The Compose app port is private and Uvicorn trusts the internal proxy network.
|
|
6
|
+
|
|
7
|
+
The production Compose stack requires `DB_ADMIN_PASSWORD`, `DB_PASSWORD`, `REDIS_PASSWORD`, `STK_HOST`, `TLS_CERTIFICATE`, and `TLS_PRIVATE_KEY`. Passwords must be unique and URL-safe because they appear in connection URLs. Certificate paths must be absolute, valid for the public host, and readable by the configured container UID. Renew certificates and reload Nginx before expiry. New PostgreSQL volumes use a separate non-superuser app role. Existing volumes need an operator privilege review because initialization scripts do not run again. Only ports 80 and 443 are published. Port 80 redirects to HTTPS. Keep container images patched and restrict access to the Docker host and network.
|
|
8
|
+
|
|
9
|
+
Public password registration is disabled by default. Enable it only for an app that needs public registration. OAuth providers remain opt-in. OAuth creates accounts only from verified provider identities; it does not attach a provider to an existing email. Existing users must use their current sign-in method. Review provider links created before version 16 because this update cannot establish how those links were originally authorized. Provider access tokens are no longer stored for login. Remove stored legacy provider tokens through your approved data maintenance process.
|
|
10
|
+
|
|
11
|
+
All POST, PUT, PATCH, and DELETE routes require the session CSRF token in a form or the `X-CSRFToken` header. The shared layout configures Axios. Custom API clients must fetch a rendered page and include its token. These APIs use session authentication. Do not disable CSRF for production. Webhooks from third parties that have no session can opt out per view with `stk.security.csrf_exempt` placed below the route decorator; an exempt view must authenticate the caller itself, for example by verifying an HMAC signature, and still gets the host, API body, and pagination checks.
|
|
12
|
+
|
|
13
|
+
Authentication limits use atomic fixed-minute SQL windows shared across workers. Defaults are 120 authentication requests and 10 authentication attempts per IP per minute, shared across auth endpoints. `STK_AUTH_REQUEST_LIMIT` and `STK_AUTH_ATTEMPT_LIMIT` are application config values. Fixed windows permit a burst at a boundary. An edge proxy should apply total connection and traffic limits. Limits rely on a trusted client IP; behind a proxy, configure forwarded-header trust explicitly. A proxy error must not make the whole site use one IP or accept client-supplied IP headers.
|
|
14
|
+
|
|
15
|
+
WebSocket defaults allow 5 connections per user and 1000 per worker, a queue of 32 messages, and 60 incoming messages per minute with a 64 KiB message limit. Sessions are checked before each outgoing message and every 5 seconds. Logout, account deactivation, expiry, and session revocation close the connection. These checks bound the revocation delay. `STK_WS_*` application config values can tune these limits. Connections must use the same origin, or an explicit `STK_WS_ALLOWED_ORIGINS` list. Broadcasts require a user ID. Audit entries are stored in the database and remain accessible through the admin API. In-memory delivery is local to one worker; use a separate authorized message transport if the app needs cross-worker delivery.
|
|
16
|
+
|
|
17
|
+
New passwords use Argon2id. Legacy hashes verify and upgrade on login. Password creation and reset routes check minimum length and the breach service. The authentication dependency permits a password if that external service is unavailable; monitoring should detect these failures. Admin password hashes are generated off the event loop. MFA, OAuth, Redis, and shared state controls have regression tests. CI also checks PostgreSQL migrations, real Redis session behavior, and runtime dependency advisories.
|
|
18
|
+
|
|
19
|
+
The 2026-10-06 review covers framework routes and local test fixtures. It is not a certification of a deployed application. Validate live OAuth provider settings, real authenticator/passkey enrollment, proxy behavior, certificate renewal, backup restoration, monitoring, and traffic capacity in your staging environment before production. A dependency scan only checks published advisories. See `security-review-2026-10-06.md` for the original findings and remediation evidence.
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
TOTP seeds and pending setup secrets are encrypted by quart-security 2.0.1. Legacy seeds remain readable and upgrade on login or authenticated requests. `uv run stk protect-mfa` encrypts all dormant seeds and rotates existing encrypted seeds to the current key. The command prints only a count and commits the data changes as one transaction. Run it in a maintenance window after taking a protected backup.
|
|
23
|
+
|
|
24
|
+
The default MFA encryption key is derived from `SECRET_KEY` for backward-compatible setup. Keep it stable. For independent key rotation, set `SECURITY_TOTP_ENCRYPTION_KEYS` to a comma-separated list of Fernet keys. The first key writes new data; all listed keys read existing data. Generate a key with `uv run python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"`. Protect keys separately from database backups. To move from the default to an independent keyring, include the old default key from `derive_totp_encryption_key(old_secret_key)` in the keyring until existing seeds have been rotated and pending setup states have expired. Retain keys needed for recovery of required backups. Do not change `SECRET_KEY` while using its derived MFA key unless you preserve the old MFA key. Invalid ciphertext or a wrong key fails closed.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# ============================================
|
|
2
|
+
# STK CONFIGURATION
|
|
3
|
+
# ============================================
|
|
4
|
+
# Lite mode: uv sync && uv run stk run (just works)
|
|
5
|
+
# Full mode: uv sync --extra full (Redis + asyncpg)
|
|
6
|
+
# ============================================
|
|
7
|
+
|
|
8
|
+
# === CORE (Required) ===
|
|
9
|
+
SECRET_KEY=
|
|
10
|
+
QUART_DEBUG=1
|
|
11
|
+
STK_ENV=development
|
|
12
|
+
SECURITY_REGISTERABLE=False
|
|
13
|
+
SECURITY_PASSWORD_SALT=
|
|
14
|
+
|
|
15
|
+
# === BRANDING ===
|
|
16
|
+
#APP_NAME=stk
|
|
17
|
+
#APP_TAGLINE=Secure. Scalable. Swift.
|
|
18
|
+
#APP_DESCRIPTION=
|
|
19
|
+
|
|
20
|
+
# === DATABASE ===
|
|
21
|
+
# SQLite used by default (instance/stk.db) - no config needed
|
|
22
|
+
# Schema changes are tracked with Alembic migrations
|
|
23
|
+
# PostgreSQL (uncomment for production)
|
|
24
|
+
#SQLALCHEMY_DATABASE_URI=postgresql+asyncpg://postgres:pass@localhost/dbname
|
|
25
|
+
|
|
26
|
+
# === FULL MODE - Redis + asyncpg (optional) ===
|
|
27
|
+
# Uncomment after: uv sync --extra full
|
|
28
|
+
#REDIS_URL=redis://localhost:6379/1
|
|
29
|
+
|
|
30
|
+
# === OAUTH (optional) ===
|
|
31
|
+
GOOGLE_AUTH_ENABLED=False
|
|
32
|
+
GOOGLE_OAUTH_CLIENT_ID=your_google_client_id
|
|
33
|
+
GOOGLE_OAUTH_CLIENT_SECRET=your_google_client_secret
|
|
34
|
+
|
|
35
|
+
GITHUB_AUTH_ENABLED=False
|
|
36
|
+
GITHUB_OAUTH_CLIENT_ID=your_github_client_id
|
|
37
|
+
GITHUB_OAUTH_CLIENT_SECRET=your_github_client_secret
|
|
38
|
+
|
|
39
|
+
# For local development only (remove in production)
|
|
40
|
+
OAUTHLIB_INSECURE_TRANSPORT=1
|
|
41
|
+
|
|
42
|
+
# === MAIL (optional) ===
|
|
43
|
+
MAIL_SERVER=smtp.sendgrid.net
|
|
44
|
+
MAIL_USERNAME=sendgrid
|
|
45
|
+
MAIL_PASSWORD=sendgrid_secure_password
|
|
46
|
+
SECURITY_EMAIL_SENDER=info@domain.com
|
|
47
|
+
|
|
48
|
+
# === SESSION & COOKIES ===
|
|
49
|
+
# Local HTTP only. Use True with HTTPS in production.
|
|
50
|
+
SESSION_COOKIE_SECURE=False
|
|
51
|
+
SESSION_COOKIE_HTTPONLY=True
|
|
52
|
+
SESSION_COOKIE_SAMESITE=Lax
|
|
53
|
+
# Set to True to logout other sessions on login (single session per user)
|
|
54
|
+
DISABLE_MULTIPLE_SESSIONS=False
|
|
55
|
+
|
|
56
|
+
# ============================================
|
|
57
|
+
# DOCKER CONFIGURATION (docker compose up)
|
|
58
|
+
# ============================================
|
|
59
|
+
#COMPOSE_PROJECT_NAME=minimal
|
|
60
|
+
#PYTHONUNBUFFERED=true
|
|
61
|
+
#DOCKER_UID=1000
|
|
62
|
+
#DB_ADMIN_PASSWORD=generate-a-separate-admin-secret
|
|
63
|
+
#DB_PASSWORD=generate-a-unique-secret
|
|
64
|
+
#REDIS_PASSWORD=generate-a-unique-secret
|
|
65
|
+
#SQLALCHEMY_DATABASE_URI=postgresql+asyncpg://stk:${DB_PASSWORD}@postgres/stk
|
|
66
|
+
#REDIS_URL=redis://:${REDIS_PASSWORD}@redis:6379/1
|
|
67
|
+
|
|
68
|
+
# Required by the production Docker stack. Use readable certificate files.
|
|
69
|
+
#STK_HOST=app.example.com
|
|
70
|
+
#TLS_CERTIFICATE=/absolute/path/fullchain.pem
|
|
71
|
+
#TLS_PRIVATE_KEY=/absolute/path/key.pem
|
|
72
|
+
#STK_PUBLIC_URL=https://app.example.com
|
|
73
|
+
#SECURITY_WAN_RP_ID=app.example.com
|
|
74
|
+
#SECURITY_WAN_EXPECTED_ORIGIN=https://app.example.com
|
|
75
|
+
|
|
76
|
+
# Optional independent MFA encryption keyring, newest key first.
|
|
77
|
+
# Generate Fernet keys and retain old keys during rotation. See SECURITY.md.
|
|
78
|
+
#SECURITY_TOTP_ENCRYPTION_KEYS=new-fernet-key,old-fernet-key
|