treadstone 0.1.1__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.
- treadstone-0.1.1/.agents/skills/database-migration/SKILL.md +211 -0
- treadstone-0.1.1/.agents/skills/dev-lifecycle/SKILL.md +113 -0
- treadstone-0.1.1/.agents/skills/dev-setup/SKILL.md +102 -0
- treadstone-0.1.1/.agents/skills/neon-postgres/SKILL.md +186 -0
- treadstone-0.1.1/.env.example +36 -0
- treadstone-0.1.1/.githooks/pre-commit +22 -0
- treadstone-0.1.1/.githooks/pre-push +17 -0
- treadstone-0.1.1/.github/workflows/cd.yml +57 -0
- treadstone-0.1.1/.github/workflows/ci.yml +59 -0
- treadstone-0.1.1/.github/workflows/project.yml +16 -0
- treadstone-0.1.1/.github/workflows/release.yml +226 -0
- treadstone-0.1.1/.gitignore +34 -0
- treadstone-0.1.1/.python-version +1 -0
- treadstone-0.1.1/AGENTS.md +128 -0
- treadstone-0.1.1/Dockerfile +16 -0
- treadstone-0.1.1/LICENSE +199 -0
- treadstone-0.1.1/Makefile +166 -0
- treadstone-0.1.1/PKG-INFO +199 -0
- treadstone-0.1.1/README.md +178 -0
- treadstone-0.1.1/alembic/README +1 -0
- treadstone-0.1.1/alembic/env.py +74 -0
- treadstone-0.1.1/alembic/script.py.mako +28 -0
- treadstone-0.1.1/alembic/versions/0049d56201ad_add_k8s_claim_name_and_make_image_.py +40 -0
- treadstone-0.1.1/alembic/versions/7d32ba24d363_add_sandbox_table.py +60 -0
- treadstone-0.1.1/alembic/versions/a30f8dfeb16e_add_user_oauth_account_invitation_api_.py +93 -0
- treadstone-0.1.1/alembic/versions/a54ae0733978_rename_k8s_claim_name_to_k8s_sandbox_.py +32 -0
- treadstone-0.1.1/alembic/versions/bc37bfeef9ac_add_provision_mode_persist_storage_size_.py +36 -0
- treadstone-0.1.1/alembic.ini +149 -0
- treadstone-0.1.1/deploy/README.md +251 -0
- treadstone-0.1.1/deploy/agent-sandbox/Chart.yaml +6 -0
- treadstone-0.1.1/deploy/agent-sandbox/README.md +39 -0
- treadstone-0.1.1/deploy/agent-sandbox/templates/_helpers.tpl +16 -0
- treadstone-0.1.1/deploy/agent-sandbox/templates/upstream-resources.yaml +15 -0
- treadstone-0.1.1/deploy/agent-sandbox/upstream/VERSION +1 -0
- treadstone-0.1.1/deploy/agent-sandbox/upstream/extensions.yaml +4305 -0
- treadstone-0.1.1/deploy/agent-sandbox/upstream/manifest.yaml +4147 -0
- treadstone-0.1.1/deploy/agent-sandbox/values-demo.yaml +13 -0
- treadstone-0.1.1/deploy/agent-sandbox/values-local.yaml +13 -0
- treadstone-0.1.1/deploy/agent-sandbox/values-prod.yaml +13 -0
- treadstone-0.1.1/deploy/agent-sandbox/values.yaml +13 -0
- treadstone-0.1.1/deploy/kind/kind-config.yaml +20 -0
- treadstone-0.1.1/deploy/sandbox-runtime/Chart.yaml +6 -0
- treadstone-0.1.1/deploy/sandbox-runtime/templates/_helpers.tpl +14 -0
- treadstone-0.1.1/deploy/sandbox-runtime/templates/sandbox-templates.yaml +39 -0
- treadstone-0.1.1/deploy/sandbox-runtime/templates/sandbox-warmpool.yaml +16 -0
- treadstone-0.1.1/deploy/sandbox-runtime/values-demo.yaml +38 -0
- treadstone-0.1.1/deploy/sandbox-runtime/values-local.yaml +38 -0
- treadstone-0.1.1/deploy/sandbox-runtime/values-prod.yaml +38 -0
- treadstone-0.1.1/deploy/sandbox-runtime/values.yaml +38 -0
- treadstone-0.1.1/deploy/treadstone/Chart.yaml +6 -0
- treadstone-0.1.1/deploy/treadstone/templates/_helpers.tpl +28 -0
- treadstone-0.1.1/deploy/treadstone/templates/clusterrole.yaml +57 -0
- treadstone-0.1.1/deploy/treadstone/templates/clusterrolebinding.yaml +16 -0
- treadstone-0.1.1/deploy/treadstone/templates/deployment.yaml +40 -0
- treadstone-0.1.1/deploy/treadstone/templates/ingress.yaml +36 -0
- treadstone-0.1.1/deploy/treadstone/templates/migration-job.yaml +31 -0
- treadstone-0.1.1/deploy/treadstone/templates/service.yaml +16 -0
- treadstone-0.1.1/deploy/treadstone/templates/serviceaccount.yaml +9 -0
- treadstone-0.1.1/deploy/treadstone/values-demo.yaml +32 -0
- treadstone-0.1.1/deploy/treadstone/values-local.yaml +31 -0
- treadstone-0.1.1/deploy/treadstone/values-prod.yaml +39 -0
- treadstone-0.1.1/deploy/treadstone/values.yaml +44 -0
- treadstone-0.1.1/docs/zh-CN/design/2026-03-17-phase0-scaffolding.md +605 -0
- treadstone-0.1.1/docs/zh-CN/design/2026-03-17-phase1-auth.md +1130 -0
- treadstone-0.1.1/docs/zh-CN/design/2026-03-17-phase2-sandbox-orchestration.md +799 -0
- treadstone-0.1.1/docs/zh-CN/design/2026-03-17-phase3-billing.md +78 -0
- treadstone-0.1.1/docs/zh-CN/design/2026-03-17-phase4-marketplace.md +105 -0
- treadstone-0.1.1/docs/zh-CN/design/2026-03-17-treadstone-design.md +80 -0
- treadstone-0.1.1/docs/zh-CN/design/2026-03-17-treadstone-roadmap.md +77 -0
- treadstone-0.1.1/docs/zh-CN/design/2026-03-18-deployment-strategy-design.md +224 -0
- treadstone-0.1.1/docs/zh-CN/design/2026-03-18-testing-ci-and-make-ship.md +544 -0
- treadstone-0.1.1/docs/zh-CN/design/2026-03-19-phase2-sandbox-api-implementation.md +609 -0
- treadstone-0.1.1/docs/zh-CN/design/2026-03-21-dual-path-sandbox-design.md +147 -0
- treadstone-0.1.1/docs/zh-CN/design/2026-03-21-sandbox-templates-design.md +223 -0
- treadstone-0.1.1/docs/zh-CN/design/2026-03-22-phase3-sdk-cli.md +418 -0
- treadstone-0.1.1/docs/zh-CN/plans/2026-03-21-sandbox-templates-implementation.md +566 -0
- treadstone-0.1.1/docs/zh-CN/plans/2026-03-22-phase3-sdk-cli-implementation.md +207 -0
- treadstone-0.1.1/openapi-client-config.yaml +5 -0
- treadstone-0.1.1/pyproject.toml +60 -0
- treadstone-0.1.1/sandbox.md +769 -0
- treadstone-0.1.1/scripts/down.sh +18 -0
- treadstone-0.1.1/scripts/e2e-test.sh +57 -0
- treadstone-0.1.1/scripts/export_openapi.py +29 -0
- treadstone-0.1.1/scripts/kind-setup.sh +83 -0
- treadstone-0.1.1/scripts/up.sh +29 -0
- treadstone-0.1.1/sdk/python/.gitignore +23 -0
- treadstone-0.1.1/sdk/python/README.md +124 -0
- treadstone-0.1.1/sdk/python/pyproject.toml +26 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/__init__.py +8 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/api/__init__.py +1 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/api/auth/__init__.py +1 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/api/auth/auth_change_password.py +186 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/api/auth/auth_create_api_key.py +186 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/api/auth/auth_delete_api_key.py +179 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/api/auth/auth_delete_user.py +179 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/api/auth/auth_get_user.py +165 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/api/auth/auth_invite.py +186 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/api/auth/auth_list_api_keys.py +165 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/api/auth/auth_list_users.py +195 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/api/auth/auth_login.py +174 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/api/auth/auth_logout.py +131 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/api/auth/auth_register.py +166 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/api/config/__init__.py +1 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/api/config/config_get_config.py +123 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/api/sandbox_templates/__init__.py +1 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/api/sandbox_templates/sandbox_templates_list_sandbox_templates.py +165 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/api/sandboxes/__init__.py +1 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/api/sandboxes/sandboxes_create_sandbox.py +186 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/api/sandboxes/sandboxes_create_sandbox_token_endpoint.py +202 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/api/sandboxes/sandboxes_delete_sandbox.py +179 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/api/sandboxes/sandboxes_get_sandbox.py +181 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/api/sandboxes/sandboxes_list_sandboxes.py +214 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/api/sandboxes/sandboxes_start_sandbox.py +181 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/api/sandboxes/sandboxes_stop_sandbox.py +181 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/api/system/__init__.py +1 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/api/system/system_health.py +123 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/client.py +268 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/errors.py +16 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/__init__.py +79 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/api_key_list_response.py +75 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/api_key_response.py +119 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/api_key_summary.py +119 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/auth_0_config.py +69 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/auth_config.py +175 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/authing_config.py +69 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/change_password_request.py +69 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/config_response.py +67 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/create_api_key_request.py +81 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/create_sandbox_request.py +143 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/create_sandbox_request_labels.py +46 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/create_sandbox_token_request.py +61 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/health_response.py +61 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/http_validation_error.py +79 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/invite_request.py +72 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/invite_response.py +79 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/login_request.py +69 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/login_response.py +61 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/logto_config.py +69 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/message_response.py +61 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/register_request.py +91 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/register_response.py +77 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/resource_spec.py +69 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/sandbox_detail_response.py +274 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/sandbox_detail_response_labels.py +46 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/sandbox_list_response.py +83 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/sandbox_response.py +145 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/sandbox_response_labels.py +46 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/sandbox_template_list_response.py +75 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/sandbox_template_response.py +99 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/sandbox_token_response.py +79 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/sandbox_urls.py +83 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/user_detail_response.py +107 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/user_list_response.py +83 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/user_response.py +77 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/validation_error.py +123 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/models/validation_error_context.py +46 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/py.typed +1 -0
- treadstone-0.1.1/sdk/python/treadstone_sdk/types.py +54 -0
- treadstone-0.1.1/skills-lock.json +10 -0
- treadstone-0.1.1/tests/__init__.py +0 -0
- treadstone-0.1.1/tests/api/__init__.py +0 -0
- treadstone-0.1.1/tests/api/test_api_key_api.py +83 -0
- treadstone-0.1.1/tests/api/test_auth_api.py +93 -0
- treadstone-0.1.1/tests/api/test_config_api.py +23 -0
- treadstone-0.1.1/tests/api/test_deps.py +18 -0
- treadstone-0.1.1/tests/api/test_health.py +10 -0
- treadstone-0.1.1/tests/api/test_sandbox_proxy_api.py +131 -0
- treadstone-0.1.1/tests/api/test_sandbox_subdomain_api.py +143 -0
- treadstone-0.1.1/tests/api/test_sandbox_templates_api.py +76 -0
- treadstone-0.1.1/tests/api/test_sandbox_token_api.py +128 -0
- treadstone-0.1.1/tests/api/test_sandboxes_api.py +166 -0
- treadstone-0.1.1/tests/conftest.py +19 -0
- treadstone-0.1.1/tests/e2e/01-auth-flow.hurl +47 -0
- treadstone-0.1.1/tests/e2e/02-api-key.hurl +57 -0
- treadstone-0.1.1/tests/e2e/03-sandbox-crud.hurl +91 -0
- treadstone-0.1.1/tests/e2e/04-password-change.hurl +46 -0
- treadstone-0.1.1/tests/e2e/05-sandbox-dual-path.hurl +129 -0
- treadstone-0.1.1/tests/integration/.env.test.example +5 -0
- treadstone-0.1.1/tests/integration/README.md +58 -0
- treadstone-0.1.1/tests/integration/__init__.py +0 -0
- treadstone-0.1.1/tests/integration/conftest.py +37 -0
- treadstone-0.1.1/tests/integration/test_auth_integration.py +152 -0
- treadstone-0.1.1/tests/integration/test_db.py +32 -0
- treadstone-0.1.1/tests/unit/__init__.py +0 -0
- treadstone-0.1.1/tests/unit/test_api_key_model.py +14 -0
- treadstone-0.1.1/tests/unit/test_config.py +33 -0
- treadstone-0.1.1/tests/unit/test_errors.py +50 -0
- treadstone-0.1.1/tests/unit/test_k8s_client.py +163 -0
- treadstone-0.1.1/tests/unit/test_k8s_sync.py +177 -0
- treadstone-0.1.1/tests/unit/test_oidc_verifier.py +24 -0
- treadstone-0.1.1/tests/unit/test_sandbox_model.py +81 -0
- treadstone-0.1.1/tests/unit/test_sandbox_proxy.py +132 -0
- treadstone-0.1.1/tests/unit/test_sandbox_service.py +327 -0
- treadstone-0.1.1/tests/unit/test_sandbox_subdomain.py +32 -0
- treadstone-0.1.1/tests/unit/test_sandbox_token.py +42 -0
- treadstone-0.1.1/tests/unit/test_user_manager.py +29 -0
- treadstone-0.1.1/tests/unit/test_user_model.py +55 -0
- treadstone-0.1.1/treadstone/__init__.py +0 -0
- treadstone-0.1.1/treadstone/api/__init__.py +0 -0
- treadstone-0.1.1/treadstone/api/auth.py +281 -0
- treadstone-0.1.1/treadstone/api/config.py +27 -0
- treadstone-0.1.1/treadstone/api/deps.py +100 -0
- treadstone-0.1.1/treadstone/api/sandbox_proxy.py +94 -0
- treadstone-0.1.1/treadstone/api/sandbox_templates.py +18 -0
- treadstone-0.1.1/treadstone/api/sandboxes.py +183 -0
- treadstone-0.1.1/treadstone/api/schemas.py +222 -0
- treadstone-0.1.1/treadstone/auth/__init__.py +27 -0
- treadstone-0.1.1/treadstone/cli/__init__.py +0 -0
- treadstone-0.1.1/treadstone/cli/__main__.py +6 -0
- treadstone-0.1.1/treadstone/cli/_client.py +56 -0
- treadstone-0.1.1/treadstone/cli/_output.py +52 -0
- treadstone-0.1.1/treadstone/cli/api_keys.py +61 -0
- treadstone-0.1.1/treadstone/cli/auth.py +138 -0
- treadstone-0.1.1/treadstone/cli/config_cmd.py +27 -0
- treadstone-0.1.1/treadstone/cli/main.py +58 -0
- treadstone-0.1.1/treadstone/cli/sandboxes.py +143 -0
- treadstone-0.1.1/treadstone/cli/templates.py +32 -0
- treadstone-0.1.1/treadstone/config.py +43 -0
- treadstone-0.1.1/treadstone/core/__init__.py +0 -0
- treadstone-0.1.1/treadstone/core/database.py +31 -0
- treadstone-0.1.1/treadstone/core/errors.py +120 -0
- treadstone-0.1.1/treadstone/core/users.py +96 -0
- treadstone-0.1.1/treadstone/main.py +120 -0
- treadstone-0.1.1/treadstone/middleware/__init__.py +0 -0
- treadstone-0.1.1/treadstone/middleware/sandbox_subdomain.py +142 -0
- treadstone-0.1.1/treadstone/models/__init__.py +5 -0
- treadstone-0.1.1/treadstone/models/api_key.py +24 -0
- treadstone-0.1.1/treadstone/models/sandbox.py +73 -0
- treadstone-0.1.1/treadstone/models/user.py +67 -0
- treadstone-0.1.1/treadstone/services/__init__.py +0 -0
- treadstone-0.1.1/treadstone/services/k8s_client.py +433 -0
- treadstone-0.1.1/treadstone/services/k8s_sync.py +254 -0
- treadstone-0.1.1/treadstone/services/sandbox_proxy.py +195 -0
- treadstone-0.1.1/treadstone/services/sandbox_service.py +272 -0
- treadstone-0.1.1/treadstone/services/sandbox_token.py +38 -0
- treadstone-0.1.1/uv.lock +2244 -0
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: database-migration
|
|
3
|
+
description: Database model design and Alembic migration workflow for Treadstone. Use whenever adding or modifying SQLAlchemy models, generating Alembic migrations, or applying schema changes to Neon. Also use when the user mentions "migration", "add table", "add column", "schema change", "database model", or any task involving treadstone/models/.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Database Model & Migration Workflow
|
|
7
|
+
|
|
8
|
+
All schema changes flow through this pipeline — never modify a production database by hand:
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
SQLAlchemy model → Alembic autogenerate → review migration → apply to test branch → verify → apply to production
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Quick reference:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
make migration MSG="add example table" # Generate migration
|
|
18
|
+
make migrate # Apply to DB
|
|
19
|
+
make downgrade # Rollback last migration
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Step 1: Design the Model
|
|
25
|
+
|
|
26
|
+
Create or modify files in `treadstone/models/`.
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
treadstone/models/
|
|
30
|
+
├── __init__.py # Re-exports all models (critical for Alembic)
|
|
31
|
+
├── user.py # User, OAuthAccount, Invitation
|
|
32
|
+
├── api_key.py # ApiKey
|
|
33
|
+
└── <new_model>.py # Your new model
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Model Template
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
from datetime import datetime
|
|
40
|
+
|
|
41
|
+
from sqlalchemy import DateTime, ForeignKey, String
|
|
42
|
+
from sqlalchemy.orm import Mapped, mapped_column
|
|
43
|
+
|
|
44
|
+
from treadstone.core.database import Base
|
|
45
|
+
from treadstone.models.user import random_id, utc_now
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class Example(Base):
|
|
49
|
+
__tablename__ = "example"
|
|
50
|
+
|
|
51
|
+
id: Mapped[str] = mapped_column(
|
|
52
|
+
String(24), primary_key=True, default=lambda: "ex" + random_id()
|
|
53
|
+
)
|
|
54
|
+
name: Mapped[str] = mapped_column(String(256), nullable=False)
|
|
55
|
+
owner_id: Mapped[str] = mapped_column(
|
|
56
|
+
String(24), ForeignKey("user.id", ondelete="cascade"), nullable=False
|
|
57
|
+
)
|
|
58
|
+
gmt_created: Mapped[datetime] = mapped_column(
|
|
59
|
+
DateTime(timezone=True), default=utc_now, nullable=False
|
|
60
|
+
)
|
|
61
|
+
gmt_deleted: Mapped[datetime | None] = mapped_column(
|
|
62
|
+
DateTime(timezone=True), nullable=True
|
|
63
|
+
)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Conventions
|
|
67
|
+
|
|
68
|
+
| Convention | Rationale |
|
|
69
|
+
|-----------|-----------|
|
|
70
|
+
| `String(24)` PK with prefix (`"user"`, `"key"`, `"ex"`) | Human-readable IDs, no UUID overhead |
|
|
71
|
+
| `gmt_created` / `gmt_updated` / `gmt_deleted` timestamps | Consistent audit trail, soft-delete support |
|
|
72
|
+
| `ForeignKey(..., ondelete="cascade")` | Prevent orphan rows |
|
|
73
|
+
| `DateTime(timezone=True)` | Always store timezone-aware timestamps |
|
|
74
|
+
| `Mapped[...]` + `mapped_column()` | Modern SQLAlchemy 2.0 style with type safety |
|
|
75
|
+
| `StrEnum` (not `str, Enum`) | Python 3.12+ idiomatic, passes ruff UP042 |
|
|
76
|
+
| Soft-delete via `gmt_deleted` | Prefer soft-delete over hard-delete for important data |
|
|
77
|
+
|
|
78
|
+
### Joined Eager Loading Gotcha
|
|
79
|
+
|
|
80
|
+
Models with `relationship(..., lazy="joined")` (e.g. `User.oauth_accounts`) require `.unique()` before extracting results, otherwise SQLAlchemy raises `InvalidRequestError`:
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
result = await session.execute(select(User))
|
|
84
|
+
users = result.unique().scalars().all() # .unique() required!
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Step 2: Register the Model
|
|
90
|
+
|
|
91
|
+
Every new model **must** be imported in `treadstone/models/__init__.py`. Alembic autogenerate only detects models registered with `Base.metadata` at import time.
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
# treadstone/models/__init__.py
|
|
95
|
+
from treadstone.models.api_key import ApiKey
|
|
96
|
+
from treadstone.models.example import Example # <-- add
|
|
97
|
+
from treadstone.models.user import Invitation, OAuthAccount, Role, User
|
|
98
|
+
|
|
99
|
+
__all__ = ["User", "OAuthAccount", "Invitation", "Role", "ApiKey", "Example"]
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
If you skip this, `alembic revision --autogenerate` generates an empty migration.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Step 3: Write a Test for the Model
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
# tests/unit/test_example_model.py
|
|
110
|
+
from treadstone.models.example import Example
|
|
111
|
+
|
|
112
|
+
def test_example_fields_exist():
|
|
113
|
+
e = Example()
|
|
114
|
+
assert hasattr(e, "id")
|
|
115
|
+
assert hasattr(e, "name")
|
|
116
|
+
assert hasattr(e, "owner_id")
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
make test
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Step 4: Generate and Review the Migration
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
make migration MSG="add example table"
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Open the generated file in `alembic/versions/` and verify:
|
|
132
|
+
|
|
133
|
+
- Correct table name and columns
|
|
134
|
+
- Foreign keys point to the right tables
|
|
135
|
+
- Indexes on frequently queried columns
|
|
136
|
+
- `nullable` settings match intent
|
|
137
|
+
- `downgrade()` correctly reverses changes
|
|
138
|
+
- No unintended changes to existing tables
|
|
139
|
+
|
|
140
|
+
### Common Pitfalls
|
|
141
|
+
|
|
142
|
+
| Pitfall | Symptom | Fix |
|
|
143
|
+
|---------|---------|-----|
|
|
144
|
+
| Model not in `__init__.py` | Empty migration | Add import to `treadstone/models/__init__.py` |
|
|
145
|
+
| Pooled connection string | Intermittent migration errors | Use direct (non-pooled) connection for Alembic |
|
|
146
|
+
| `+asyncpg` in Alembic URL | `RuntimeError: cannot use async engine` | `env.py` strips it automatically — don't add it back |
|
|
147
|
+
| Enum value changes | Alembic doesn't detect them | Handle enum migrations manually |
|
|
148
|
+
| Column rename | Autogenerate sees drop + add | Write manual migration with `op.alter_column()` |
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Step 5: Apply to Neon Test Branch First
|
|
153
|
+
|
|
154
|
+
Never migrate production directly. Neon branches are instant, copy-on-write clones — use one as a staging environment.
|
|
155
|
+
|
|
156
|
+
```
|
|
157
|
+
Production (main branch)
|
|
158
|
+
└── Test branch (fork, apply migration here first)
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
1. Create a test branch via Neon Console or CLI (if not already existing)
|
|
162
|
+
2. Apply migration to the test branch:
|
|
163
|
+
```bash
|
|
164
|
+
TREADSTONE_DATABASE_URL="<test-branch-url>" make migrate
|
|
165
|
+
```
|
|
166
|
+
3. Run integration tests:
|
|
167
|
+
```bash
|
|
168
|
+
make test-all
|
|
169
|
+
```
|
|
170
|
+
4. If tests pass, apply to production:
|
|
171
|
+
```bash
|
|
172
|
+
make migrate # with .env pointing to production
|
|
173
|
+
```
|
|
174
|
+
5. If tests fail, fix and retry. Use `make downgrade` or reset the branch via Neon Console.
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Step 6: Commit
|
|
179
|
+
|
|
180
|
+
Commit the model, migration file, and tests together as one logical unit:
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
git add treadstone/models/ alembic/versions/ tests/
|
|
184
|
+
git commit -m "feat: add example model and migration"
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Rollback
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
make downgrade # Rollback last migration
|
|
193
|
+
uv run alembic downgrade -2 # Rollback 2 steps
|
|
194
|
+
uv run alembic downgrade base # Rollback to empty
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
To reset a Neon test branch entirely, use the Neon Console "Reset from parent" feature.
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## Checklist
|
|
202
|
+
|
|
203
|
+
- [ ] Model defined in `treadstone/models/<name>.py` with type hints
|
|
204
|
+
- [ ] Model imported in `treadstone/models/__init__.py`
|
|
205
|
+
- [ ] Unit test written and passing
|
|
206
|
+
- [ ] Migration generated with `make migration MSG="..."`
|
|
207
|
+
- [ ] Migration file reviewed manually
|
|
208
|
+
- [ ] Migration applied to Neon test branch
|
|
209
|
+
- [ ] Integration tests passing (`make test-all`)
|
|
210
|
+
- [ ] Migration applied to production
|
|
211
|
+
- [ ] Committed together: model + migration + tests
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dev-lifecycle
|
|
3
|
+
description: Treadstone daily development lifecycle — the step-by-step loop from creating a branch to merging a PR. Use this skill every time you develop a new feature, fix a bug, refactor code, or make any code change that will be shipped. Covers branching, TDD cycle, shipping, PR creation, CI monitoring, and merging. If the user says "add feature X", "fix bug Y", "implement Z", or anything that implies writing and shipping code, this skill applies.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Development Lifecycle
|
|
7
|
+
|
|
8
|
+
Never push directly to main. All code merges go through Pull Requests — this includes AI Agents.
|
|
9
|
+
|
|
10
|
+
## The Loop
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
branch → TDD (write test → fail → implement → pass → refactor) → ship → PR → CI → merge
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Step 1: Create a Feature Branch
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
git checkout main && git pull
|
|
20
|
+
git checkout -b feat/descriptive-name
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Branch naming: `feat/`, `fix/`, `chore/`, `refactor/`, `docs/`, `test/`.
|
|
24
|
+
|
|
25
|
+
## Step 2: TDD Cycle
|
|
26
|
+
|
|
27
|
+
Repeat per unit of work — keep iterations small.
|
|
28
|
+
|
|
29
|
+
1. **Write a failing test** in the appropriate directory (`tests/unit/`, `tests/api/`, or `tests/integration/`). See the Testing section in `AGENTS.md` for which directory to use.
|
|
30
|
+
|
|
31
|
+
2. **Confirm it fails:**
|
|
32
|
+
```bash
|
|
33
|
+
make test
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
3. **Write the minimal implementation** to make the test pass — nothing more.
|
|
37
|
+
|
|
38
|
+
4. **Confirm it passes:**
|
|
39
|
+
```bash
|
|
40
|
+
make test
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
5. **Refactor** if needed, re-run `make test` to confirm nothing broke.
|
|
44
|
+
|
|
45
|
+
## Step 3: Ship to Feature Branch
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
make ship MSG="feat: add user registration endpoint"
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
This runs `git add -A && git commit && git push` on the current feature branch.
|
|
52
|
+
|
|
53
|
+
Verify you are NOT on main before shipping: `git branch --show-current`.
|
|
54
|
+
|
|
55
|
+
Commit messages follow Conventional Commits format (`feat:`, `fix:`, `test:`, `refactor:`, `chore:`, `docs:`). Keep commits small — one logical unit each. See `AGENTS.md` Git Workflow section for full conventions.
|
|
56
|
+
|
|
57
|
+
All GitHub-visible content (commit messages, PR titles/bodies, review comments) must be in English.
|
|
58
|
+
|
|
59
|
+
## Step 4: Create a Pull Request
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
gh pr create --title "feat: add user registration" --body "$(cat <<'EOF'
|
|
63
|
+
## Summary
|
|
64
|
+
- Implement user registration and login
|
|
65
|
+
- Support email/password + Cookie session
|
|
66
|
+
|
|
67
|
+
## Test Plan
|
|
68
|
+
- [x] make test
|
|
69
|
+
- [x] make lint
|
|
70
|
+
EOF
|
|
71
|
+
)"
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Use HEREDOC for the body to avoid quote escaping issues.
|
|
75
|
+
|
|
76
|
+
## Step 5: Monitor CI
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
gh run watch
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
If CI fails:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
gh run view <run-id> --log-failed # inspect failure
|
|
86
|
+
make test # reproduce locally
|
|
87
|
+
make lint # check formatting
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Fix, then `make ship MSG="fix: ..."` to push the fix.
|
|
91
|
+
|
|
92
|
+
## Step 6: Merge
|
|
93
|
+
|
|
94
|
+
Once CI is green:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
gh pr merge --squash
|
|
98
|
+
git checkout main && git pull
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## K8s Verification (When Needed)
|
|
102
|
+
|
|
103
|
+
If the change affects sandbox orchestration or deployment, verify on a local Kind cluster before merging. Follow `deploy/README.md` for the full workflow:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
make up # build + deploy to Kind
|
|
107
|
+
make test-e2e # run E2E tests against the cluster
|
|
108
|
+
make down # tear down when done
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Quick Reference
|
|
112
|
+
|
|
113
|
+
Run `make help` for the full command list.
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dev-setup
|
|
3
|
+
description: First-time Treadstone local development environment setup. Run once after cloning the repo and before starting any development. Covers system dependency installation, Python environment, Neon database connection, migrations, and environment verification. Use this skill when the user/agent just entered the project, needs to rebuild the environment, or encounters setup-related issues like missing dependencies, broken .env, or failed migrations.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# First-Time Dev Environment Setup
|
|
7
|
+
|
|
8
|
+
Run this once. After completion, switch to the `dev-lifecycle` skill for daily development.
|
|
9
|
+
|
|
10
|
+
## 1. System Dependencies
|
|
11
|
+
|
|
12
|
+
Verify these tools are installed:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
python3 --version # 3.12+
|
|
16
|
+
uv --version # Python package manager
|
|
17
|
+
gh --version # GitHub CLI (optional, for PR/issue ops)
|
|
18
|
+
docker --version # Container builds + Kind cluster
|
|
19
|
+
kind --version # Local K8s cluster (sandbox dev only)
|
|
20
|
+
kubectl version --client # K8s CLI
|
|
21
|
+
helm version --short # Helm chart deployment
|
|
22
|
+
hurl --version # E2E testing (HTTP request runner)
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Install missing tools (macOS):
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
29
|
+
brew install kind kubectl helm hurl
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## 2. Install Python Dependencies
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
make install
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
This runs `uv sync` (creates `.venv`, installs all deps) and configures git hooks.
|
|
39
|
+
|
|
40
|
+
## 3. Configure Database (Neon)
|
|
41
|
+
|
|
42
|
+
The project uses [Neon](https://neon.tech) Serverless PostgreSQL — no local Postgres needed.
|
|
43
|
+
|
|
44
|
+
Get the connection string from https://console.neon.tech, then:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
cp .env.example .env
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Edit `.env` and set the connection string in asyncpg format:
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
TREADSTONE_DATABASE_URL=postgresql+asyncpg://neondb_owner:xxx@ep-xxx.ap-southeast-1.aws.neon.tech/neondb?sslmode=require
|
|
54
|
+
TREADSTONE_DEBUG=true
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
The URL scheme must be `postgresql+asyncpg://` (not `postgresql://`). Keep `?sslmode=require`.
|
|
58
|
+
|
|
59
|
+
## 4. Apply Database Migrations
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
make migrate
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Expected: `INFO [alembic.runtime.migration] Context impl PostgresqlImpl.` with migration details listed.
|
|
66
|
+
|
|
67
|
+
## 5. Verify Environment
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
make test
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Expected: all tests pass (integration tests are excluded by default). If tests pass, the environment is ready.
|
|
74
|
+
|
|
75
|
+
## 6. Local K8s Cluster (Sandbox Development)
|
|
76
|
+
|
|
77
|
+
For sandbox-related features that require a real Kubernetes cluster, follow `deploy/README.md` — it covers Kind cluster creation, image building, Helm deployment, and smoke testing end-to-end.
|
|
78
|
+
|
|
79
|
+
Quick start:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
make up # One-command: Kind cluster + build + deploy
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Pure API development (`make dev`) does not require a K8s cluster.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Troubleshooting
|
|
90
|
+
|
|
91
|
+
**`uv sync` fails:**
|
|
92
|
+
- Confirm Python 3.12+: `python3 --version`
|
|
93
|
+
- Try: `uv python install 3.12`
|
|
94
|
+
|
|
95
|
+
**Database connection fails (`could not connect`):**
|
|
96
|
+
- Check the connection string in `.env`
|
|
97
|
+
- Confirm the URL uses `postgresql+asyncpg://` not `postgresql://`
|
|
98
|
+
- Neon free-tier projects auto-suspend; first connection may be slow (~1s cold start)
|
|
99
|
+
|
|
100
|
+
**`alembic upgrade head` reports `authentication failed`:**
|
|
101
|
+
- Confirm `.env` exists in the project root
|
|
102
|
+
- URL-encode special characters in the password
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: neon-postgres
|
|
3
|
+
description: Guides and best practices for working with Neon Serverless Postgres. Covers getting started, local development with Neon, choosing a connection method, Neon features, authentication (@neondatabase/auth), PostgREST-style data API (@neondatabase/neon-js), Neon CLI, and Neon's Platform API/SDKs. Use for any Neon-related questions.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Neon Serverless Postgres
|
|
7
|
+
|
|
8
|
+
Neon is a serverless Postgres platform that separates compute and storage to offer autoscaling, branching, instant restore, and scale-to-zero. It's fully compatible with Postgres and works with any language, framework, or ORM that supports Postgres.
|
|
9
|
+
|
|
10
|
+
## Neon Documentation
|
|
11
|
+
|
|
12
|
+
The Neon documentation is the source of truth for all Neon-related information. Always verify claims against the official docs before responding. Neon features and APIs evolve, so prefer fetching current docs over relying on training data.
|
|
13
|
+
|
|
14
|
+
### Fetching Docs as Markdown
|
|
15
|
+
|
|
16
|
+
Any Neon doc page can be fetched as markdown in two ways:
|
|
17
|
+
|
|
18
|
+
1. **Append `.md` to the URL** (simplest): https://neon.com/docs/introduction/branching.md
|
|
19
|
+
2. **Request `text/markdown`** on the standard URL: `curl -H "Accept: text/markdown" https://neon.com/docs/introduction/branching`
|
|
20
|
+
|
|
21
|
+
Both return the same markdown content. Use whichever method your tools support.
|
|
22
|
+
|
|
23
|
+
### Finding the Right Page
|
|
24
|
+
|
|
25
|
+
The docs index lists every available page with its URL and a short description:
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
https://neon.com/docs/llms.txt
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Common doc URLs are organized in the topic links below. If you need a page not listed here, search the docs index: https://neon.com/docs/llms.txt — don't guess URLs.
|
|
32
|
+
|
|
33
|
+
## What Is Neon
|
|
34
|
+
|
|
35
|
+
Use this for architecture explanations and terminology (organizations, projects, branches, endpoints) before giving implementation advice.
|
|
36
|
+
|
|
37
|
+
Link: https://neon.com/docs/ai/skills/neon-postgres/references/what-is-neon.md
|
|
38
|
+
|
|
39
|
+
## Getting Started
|
|
40
|
+
|
|
41
|
+
Use this for first-time setup: org/project selection, connection strings, driver installation, optional auth, and initial schema setup.
|
|
42
|
+
|
|
43
|
+
Link: https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md
|
|
44
|
+
|
|
45
|
+
## Connection Methods & Drivers
|
|
46
|
+
|
|
47
|
+
Use this when you need to pick the correct transport and driver based on runtime constraints (TCP, HTTP, WebSocket, edge, serverless, long-running).
|
|
48
|
+
|
|
49
|
+
Link: https://neon.com/docs/ai/skills/neon-postgres/references/connection-methods.md
|
|
50
|
+
|
|
51
|
+
### Serverless Driver
|
|
52
|
+
|
|
53
|
+
Use this for `@neondatabase/serverless` patterns, including HTTP queries, WebSocket transactions, and runtime-specific optimizations.
|
|
54
|
+
|
|
55
|
+
Link: https://neon.com/docs/ai/skills/neon-postgres/references/neon-serverless.md
|
|
56
|
+
|
|
57
|
+
### Neon JS SDK
|
|
58
|
+
|
|
59
|
+
Use this for combined Neon Auth + Data API workflows with PostgREST-style querying and typed client setup.
|
|
60
|
+
|
|
61
|
+
Link: https://neon.com/docs/ai/skills/neon-postgres/references/neon-js.md
|
|
62
|
+
|
|
63
|
+
## Developer Tools
|
|
64
|
+
|
|
65
|
+
Use this for local development enablement with `npx neonctl@latest init`, VSCode extension setup, and Neon MCP server configuration.
|
|
66
|
+
|
|
67
|
+
Link: https://neon.com/docs/ai/skills/neon-postgres/references/devtools.md
|
|
68
|
+
|
|
69
|
+
### Neon CLI
|
|
70
|
+
|
|
71
|
+
Use this for terminal-first workflows, scripts, and CI/CD automation with `neonctl`.
|
|
72
|
+
|
|
73
|
+
Link: https://neon.com/docs/ai/skills/neon-postgres/references/neon-cli.md
|
|
74
|
+
|
|
75
|
+
## Neon Admin API
|
|
76
|
+
|
|
77
|
+
The Neon Admin API can be used to manage Neon resources programmatically. It is used behind the scenes by the Neon CLI and MCP server, but can also be used directly for more complex automation workflows or when embedding Neon in other applications.
|
|
78
|
+
|
|
79
|
+
### Neon REST API
|
|
80
|
+
|
|
81
|
+
Use this for direct HTTP automation, endpoint-level control, API key auth, rate-limit handling, and operation polling.
|
|
82
|
+
|
|
83
|
+
Link: https://neon.com/docs/ai/skills/neon-postgres/references/neon-rest-api.md
|
|
84
|
+
|
|
85
|
+
### Neon TypeScript SDK
|
|
86
|
+
|
|
87
|
+
Use this when implementing typed programmatic control of Neon resources in TypeScript via `@neondatabase/api-client`.
|
|
88
|
+
|
|
89
|
+
Link: https://neon.com/docs/ai/skills/neon-postgres/references/neon-typescript-sdk.md
|
|
90
|
+
|
|
91
|
+
### Neon Python SDK
|
|
92
|
+
|
|
93
|
+
Use this when implementing programmatic Neon management in Python with the `neon-api` package.
|
|
94
|
+
|
|
95
|
+
Link: https://neon.com/docs/ai/skills/neon-postgres/references/neon-python-sdk.md
|
|
96
|
+
|
|
97
|
+
## Neon Auth
|
|
98
|
+
|
|
99
|
+
Use this for managed user authentication setup, UI components, auth methods, and Neon Auth integration pitfalls in Next.js and React apps.
|
|
100
|
+
|
|
101
|
+
Link: https://neon.com/docs/ai/skills/neon-postgres/references/neon-auth.md
|
|
102
|
+
|
|
103
|
+
Neon Auth is also embedded in the Neon JS SDK - so depending on your use case, you may want to use the Neon JS SDK instead of Neon Auth. See https://neon.com/docs/ai/skills/neon-postgres/references/connection-methods.md for more details.
|
|
104
|
+
|
|
105
|
+
## Branching
|
|
106
|
+
|
|
107
|
+
Use this when the user is planning isolated environments, schema migration testing, preview deployments, or branch lifecycle automation.
|
|
108
|
+
|
|
109
|
+
Key points:
|
|
110
|
+
|
|
111
|
+
- Branches are instant, copy-on-write clones (no full data copy).
|
|
112
|
+
- Each branch has its own compute endpoint.
|
|
113
|
+
- Use the neonctl CLI or MCP server to create, inspect, and compare branches.
|
|
114
|
+
|
|
115
|
+
Link: https://neon.com/docs/ai/skills/neon-postgres/references/branching.md
|
|
116
|
+
|
|
117
|
+
## Autoscaling
|
|
118
|
+
|
|
119
|
+
Use this when the user needs compute to scale automatically with workload and wants guidance on CU sizing and runtime behavior.
|
|
120
|
+
|
|
121
|
+
Link: https://neon.com/docs/introduction/autoscaling.md
|
|
122
|
+
|
|
123
|
+
## Scale to Zero
|
|
124
|
+
|
|
125
|
+
Use this when optimizing idle costs and discussing suspend/resume behavior, including cold-start trade-offs.
|
|
126
|
+
|
|
127
|
+
Key points:
|
|
128
|
+
|
|
129
|
+
- Idle computes suspend automatically (default 5 minutes, configurable) (unless disabled - launch & scale plan only)
|
|
130
|
+
- First query after suspend typically has a cold-start penalty (around hundreds of ms)
|
|
131
|
+
- Storage remains active while compute is suspended.
|
|
132
|
+
|
|
133
|
+
Link: https://neon.com/docs/introduction/scale-to-zero.md
|
|
134
|
+
|
|
135
|
+
## Instant Restore
|
|
136
|
+
|
|
137
|
+
Use this when the user needs point-in-time recovery or wants to restore data state without traditional backup restore workflows.
|
|
138
|
+
|
|
139
|
+
Key points:
|
|
140
|
+
|
|
141
|
+
- Restore windows depend on plan limits.
|
|
142
|
+
- Users can create branches from historical points-in-time.
|
|
143
|
+
- Time Travel queries can be used for historical inspection workflows.
|
|
144
|
+
|
|
145
|
+
Link: https://neon.com/docs/introduction/branch-restore.md
|
|
146
|
+
|
|
147
|
+
## Read Replicas
|
|
148
|
+
|
|
149
|
+
Use this for read-heavy workloads where the user needs dedicated read-only compute without duplicating storage.
|
|
150
|
+
|
|
151
|
+
Key points:
|
|
152
|
+
|
|
153
|
+
- Replicas are read-only compute endpoints sharing the same storage.
|
|
154
|
+
- Creation is fast and scaling is independent from primary compute.
|
|
155
|
+
- Typical use cases: analytics, reporting, and read-heavy APIs.
|
|
156
|
+
|
|
157
|
+
Link: https://neon.com/docs/introduction/read-replicas.md
|
|
158
|
+
|
|
159
|
+
## Connection Pooling
|
|
160
|
+
|
|
161
|
+
Use this when the user is in serverless or high-concurrency environments and needs safe, scalable Postgres connection management.
|
|
162
|
+
|
|
163
|
+
Key points:
|
|
164
|
+
|
|
165
|
+
- Neon pooling uses PgBouncer.
|
|
166
|
+
- Add `-pooler` to endpoint hostnames to use pooled connections.
|
|
167
|
+
- Pooling is especially important in serverless runtimes with bursty concurrency.
|
|
168
|
+
|
|
169
|
+
Link: https://neon.com/docs/connect/connection-pooling.md
|
|
170
|
+
|
|
171
|
+
## IP Allow Lists
|
|
172
|
+
|
|
173
|
+
Use this when the user needs to restrict database access by trusted networks, IPs, or CIDR ranges.
|
|
174
|
+
|
|
175
|
+
Link: https://neon.com/docs/introduction/ip-allow.md
|
|
176
|
+
|
|
177
|
+
## Logical Replication
|
|
178
|
+
|
|
179
|
+
Use this when integrating CDC pipelines, external Postgres sync, or replication-based data movement.
|
|
180
|
+
|
|
181
|
+
Key points:
|
|
182
|
+
|
|
183
|
+
- Neon supports native logical replication workflows.
|
|
184
|
+
- Useful for replicating to/from external Postgres systems.
|
|
185
|
+
|
|
186
|
+
Link: https://neon.com/docs/guides/logical-replication-guide.md
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# === Database ===
|
|
2
|
+
# Get connection string from Neon Console: https://console.neon.tech
|
|
3
|
+
TREADSTONE_DATABASE_URL=postgresql+asyncpg://user:password@ep-xxx.region.aws.neon.tech/neondb?sslmode=require
|
|
4
|
+
|
|
5
|
+
# === App ===
|
|
6
|
+
TREADSTONE_DEBUG=false
|
|
7
|
+
TREADSTONE_AUTH_TYPE=cookie
|
|
8
|
+
TREADSTONE_REGISTER_MODE=unlimited
|
|
9
|
+
|
|
10
|
+
# === Auth Secrets ===
|
|
11
|
+
TREADSTONE_JWT_SECRET=CHANGE_ME_IN_PROD
|
|
12
|
+
TREADSTONE_OAUTH_REDIRECT_URL=http://localhost:3000/auth/callback
|
|
13
|
+
|
|
14
|
+
# === OAuth Social (leave empty to disable) ===
|
|
15
|
+
TREADSTONE_GOOGLE_OAUTH_CLIENT_ID=
|
|
16
|
+
TREADSTONE_GOOGLE_OAUTH_CLIENT_SECRET=
|
|
17
|
+
TREADSTONE_GITHUB_OAUTH_CLIENT_ID=
|
|
18
|
+
TREADSTONE_GITHUB_OAUTH_CLIENT_SECRET=
|
|
19
|
+
|
|
20
|
+
# === Auth0 / Authing / Logto (leave empty to disable) ===
|
|
21
|
+
TREADSTONE_AUTH0_DOMAIN=
|
|
22
|
+
TREADSTONE_AUTH0_CLIENT_ID=
|
|
23
|
+
TREADSTONE_AUTHING_DOMAIN=
|
|
24
|
+
TREADSTONE_AUTHING_APP_ID=
|
|
25
|
+
TREADSTONE_LOGTO_DOMAIN=
|
|
26
|
+
TREADSTONE_LOGTO_APP_ID=
|
|
27
|
+
|
|
28
|
+
# === Sandbox ===
|
|
29
|
+
# Subdomain-based sandbox routing (for browser Web UI access)
|
|
30
|
+
# Dev: "sandbox.localhost" -> {sandbox_id}.sandbox.localhost:8000
|
|
31
|
+
# Prod: "sandbox.example.com" -> {sandbox_id}.sandbox.example.com
|
|
32
|
+
# Empty string disables subdomain routing.
|
|
33
|
+
TREADSTONE_SANDBOX_DOMAIN=
|
|
34
|
+
TREADSTONE_SANDBOX_NAMESPACE=treadstone
|
|
35
|
+
TREADSTONE_SANDBOX_PORT=8080
|
|
36
|
+
TREADSTONE_SANDBOX_PROXY_TIMEOUT=180.0
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
echo "=== pre-commit: format + lint ==="
|
|
5
|
+
|
|
6
|
+
uv run ruff check --fix treadstone/ tests/
|
|
7
|
+
uv run ruff format treadstone/ tests/
|
|
8
|
+
|
|
9
|
+
# Re-stage files that were auto-formatted
|
|
10
|
+
git diff --name-only | xargs -r git add
|
|
11
|
+
|
|
12
|
+
if ! uv run ruff check treadstone/ tests/; then
|
|
13
|
+
echo "ERROR: Lint check failed. Fix issues above, then commit again."
|
|
14
|
+
exit 1
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
if ! uv run ruff format --check treadstone/ tests/; then
|
|
18
|
+
echo "ERROR: Format check failed."
|
|
19
|
+
exit 1
|
|
20
|
+
fi
|
|
21
|
+
|
|
22
|
+
echo "pre-commit checks passed."
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# Prevent direct pushes to the remote `main` branch.
|
|
4
|
+
# All branch updates to main must go through Pull Requests.
|
|
5
|
+
#
|
|
6
|
+
# Tag pushes (e.g. git push origin v0.1.1) are allowed from any local branch.
|
|
7
|
+
|
|
8
|
+
while read -r local_ref local_sha remote_ref remote_sha; do
|
|
9
|
+
[ -z "$remote_ref" ] && continue
|
|
10
|
+
if [[ "$remote_ref" == "refs/heads/main" ]]; then
|
|
11
|
+
echo ""
|
|
12
|
+
echo "ERROR: Direct push to remote 'main' is not allowed."
|
|
13
|
+
echo " Please create a feature branch and open a Pull Request."
|
|
14
|
+
echo ""
|
|
15
|
+
exit 1
|
|
16
|
+
fi
|
|
17
|
+
done
|