z3rno-server 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- z3rno_server-0.1.0/.env.example +46 -0
- z3rno_server-0.1.0/.github/workflows/ci.yml +77 -0
- z3rno_server-0.1.0/.github/workflows/release.yml +39 -0
- z3rno_server-0.1.0/.gitignore +74 -0
- z3rno_server-0.1.0/.pre-commit-config.yaml +100 -0
- z3rno_server-0.1.0/CLAUDE.md +71 -0
- z3rno_server-0.1.0/CONTRIBUTING.md +97 -0
- z3rno_server-0.1.0/Dockerfile +62 -0
- z3rno_server-0.1.0/LICENSE +201 -0
- z3rno_server-0.1.0/Makefile +128 -0
- z3rno_server-0.1.0/PKG-INFO +119 -0
- z3rno_server-0.1.0/README.md +95 -0
- z3rno_server-0.1.0/SECURITY.md +29 -0
- z3rno_server-0.1.0/docker-compose.dev.yml +158 -0
- z3rno_server-0.1.0/docker-compose.monitoring.yml +61 -0
- z3rno_server-0.1.0/docker-compose.prod.yml +250 -0
- z3rno_server-0.1.0/monitoring/grafana/provisioning/dashboards/dashboards.yml +12 -0
- z3rno_server-0.1.0/monitoring/grafana/provisioning/dashboards/z3rno-overview.json +128 -0
- z3rno_server-0.1.0/monitoring/grafana/provisioning/datasources/prometheus.yml +9 -0
- z3rno_server-0.1.0/monitoring/prometheus/prometheus.yml +11 -0
- z3rno_server-0.1.0/pyproject.toml +113 -0
- z3rno_server-0.1.0/scripts/healthcheck.sh +173 -0
- z3rno_server-0.1.0/src/z3rno_server/__init__.py +1 -0
- z3rno_server-0.1.0/src/z3rno_server/api/__init__.py +1 -0
- z3rno_server-0.1.0/src/z3rno_server/api/api_keys.py +208 -0
- z3rno_server-0.1.0/src/z3rno_server/api/audit.py +80 -0
- z3rno_server-0.1.0/src/z3rno_server/api/health.py +22 -0
- z3rno_server-0.1.0/src/z3rno_server/api/memories.py +435 -0
- z3rno_server-0.1.0/src/z3rno_server/api/sessions.py +172 -0
- z3rno_server-0.1.0/src/z3rno_server/api/worker.py +39 -0
- z3rno_server-0.1.0/src/z3rno_server/config.py +70 -0
- z3rno_server-0.1.0/src/z3rno_server/dependencies.py +78 -0
- z3rno_server-0.1.0/src/z3rno_server/main.py +66 -0
- z3rno_server-0.1.0/src/z3rno_server/middleware/__init__.py +1 -0
- z3rno_server-0.1.0/src/z3rno_server/middleware/auth.py +322 -0
- z3rno_server-0.1.0/src/z3rno_server/middleware/body_limit.py +57 -0
- z3rno_server-0.1.0/src/z3rno_server/middleware/logging.py +62 -0
- z3rno_server-0.1.0/src/z3rno_server/middleware/org_context.py +23 -0
- z3rno_server-0.1.0/src/z3rno_server/middleware/rate_limit.py +199 -0
- z3rno_server-0.1.0/src/z3rno_server/middleware/rbac.py +45 -0
- z3rno_server-0.1.0/src/z3rno_server/middleware/request_id.py +20 -0
- z3rno_server-0.1.0/src/z3rno_server/schemas/__init__.py +36 -0
- z3rno_server-0.1.0/src/z3rno_server/schemas/audit.py +47 -0
- z3rno_server-0.1.0/src/z3rno_server/schemas/memories.py +158 -0
- z3rno_server-0.1.0/src/z3rno_server/schemas/shared.py +22 -0
- z3rno_server-0.1.0/src/z3rno_server/workers/__init__.py +1 -0
- z3rno_server-0.1.0/src/z3rno_server/workers/celery_app.py +32 -0
- z3rno_server-0.1.0/src/z3rno_server/workers/embeddings.py +81 -0
- z3rno_server-0.1.0/src/z3rno_server/workers/healthcheck.py +21 -0
- z3rno_server-0.1.0/src/z3rno_server/workers/lifecycle.py +170 -0
- z3rno_server-0.1.0/tests/__init__.py +0 -0
- z3rno_server-0.1.0/tests/conftest.py +20 -0
- z3rno_server-0.1.0/tests/load/README.md +60 -0
- z3rno_server-0.1.0/tests/load/__init__.py +0 -0
- z3rno_server-0.1.0/tests/load/locustfile.py +132 -0
- z3rno_server-0.1.0/tests/test_api_memories.py +78 -0
- z3rno_server-0.1.0/tests/test_config.py +63 -0
- z3rno_server-0.1.0/tests/test_e2e.py +212 -0
- z3rno_server-0.1.0/tests/test_health.py +30 -0
- z3rno_server-0.1.0/tests/test_middleware_auth.py +249 -0
- z3rno_server-0.1.0/tests/test_middleware_request_id.py +43 -0
- z3rno_server-0.1.0/tests/test_schemas.py +174 -0
- z3rno_server-0.1.0/tests/test_security.py +321 -0
- z3rno_server-0.1.0/uv.lock +4073 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# z3rno-server local dev environment
|
|
2
|
+
#
|
|
3
|
+
# Copy this file to `.env` and adjust values as needed:
|
|
4
|
+
# cp .env.example .env
|
|
5
|
+
#
|
|
6
|
+
# Docker Compose automatically picks up .env when running `docker compose up`.
|
|
7
|
+
# Do NOT commit your real .env — it's already in .gitignore.
|
|
8
|
+
|
|
9
|
+
# -----------------------------------------------------------------------------
|
|
10
|
+
# PostgreSQL (z3rno-postgres:17 with all extensions pre-installed)
|
|
11
|
+
# -----------------------------------------------------------------------------
|
|
12
|
+
POSTGRES_DB=z3rno
|
|
13
|
+
POSTGRES_USER=z3rno
|
|
14
|
+
POSTGRES_PASSWORD=z3rno_dev_password
|
|
15
|
+
POSTGRES_HOST_PORT=5432
|
|
16
|
+
|
|
17
|
+
# -----------------------------------------------------------------------------
|
|
18
|
+
# Valkey (used for cache, session state, rate-limit counters, Celery broker)
|
|
19
|
+
# -----------------------------------------------------------------------------
|
|
20
|
+
VALKEY_HOST_PORT=6379
|
|
21
|
+
|
|
22
|
+
# -----------------------------------------------------------------------------
|
|
23
|
+
# z3rno-server (FastAPI)
|
|
24
|
+
# -----------------------------------------------------------------------------
|
|
25
|
+
SERVER_HOST_PORT=8000
|
|
26
|
+
LOG_LEVEL=INFO
|
|
27
|
+
CORS_ORIGINS=http://localhost:3000,http://localhost:8000
|
|
28
|
+
|
|
29
|
+
# API key for local dev. The real z3rno-server will look up org_id via this.
|
|
30
|
+
# In production, API keys are stored hashed in the api_keys table. For local
|
|
31
|
+
# dev, any non-empty string works and maps to a bootstrap dev tenant.
|
|
32
|
+
Z3RNO_API_KEY=z3rno_sk_test_localdev
|
|
33
|
+
|
|
34
|
+
# -----------------------------------------------------------------------------
|
|
35
|
+
# Embedding provider (LiteLLM)
|
|
36
|
+
# -----------------------------------------------------------------------------
|
|
37
|
+
# MVP default is OpenAI text-embedding-3-small (1536 dims).
|
|
38
|
+
# Leave OPENAI_API_KEY empty for schema work that doesn't need real embeddings;
|
|
39
|
+
# the server will use a random-vector stub for development.
|
|
40
|
+
EMBEDDING_MODEL=text-embedding-3-small
|
|
41
|
+
OPENAI_API_KEY=
|
|
42
|
+
|
|
43
|
+
# -----------------------------------------------------------------------------
|
|
44
|
+
# Celery worker
|
|
45
|
+
# -----------------------------------------------------------------------------
|
|
46
|
+
CELERY_WORKER_CONCURRENCY=4
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
push:
|
|
6
|
+
branches: [main]
|
|
7
|
+
|
|
8
|
+
concurrency:
|
|
9
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
10
|
+
cancel-in-progress: true
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
python:
|
|
14
|
+
name: Python ${{ matrix.python-version }}
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
strategy:
|
|
17
|
+
fail-fast: false
|
|
18
|
+
matrix:
|
|
19
|
+
python-version: ['3.11', '3.12']
|
|
20
|
+
|
|
21
|
+
services:
|
|
22
|
+
postgres:
|
|
23
|
+
image: pgvector/pgvector:pg17
|
|
24
|
+
env:
|
|
25
|
+
POSTGRES_USER: z3rno
|
|
26
|
+
POSTGRES_PASSWORD: z3rno_dev_password
|
|
27
|
+
POSTGRES_DB: z3rno
|
|
28
|
+
ports:
|
|
29
|
+
- 5432:5432
|
|
30
|
+
options: >-
|
|
31
|
+
--health-cmd "pg_isready -U z3rno -d z3rno"
|
|
32
|
+
--health-interval 10s
|
|
33
|
+
--health-timeout 5s
|
|
34
|
+
--health-retries 5
|
|
35
|
+
|
|
36
|
+
valkey:
|
|
37
|
+
image: valkey/valkey:8
|
|
38
|
+
ports:
|
|
39
|
+
- 6379:6379
|
|
40
|
+
options: >-
|
|
41
|
+
--health-cmd "valkey-cli ping"
|
|
42
|
+
--health-interval 10s
|
|
43
|
+
--health-timeout 5s
|
|
44
|
+
--health-retries 5
|
|
45
|
+
|
|
46
|
+
env:
|
|
47
|
+
DATABASE_URL: postgresql+asyncpg://z3rno:z3rno_dev_password@localhost:5432/z3rno
|
|
48
|
+
REDIS_URL: redis://localhost:6379/0
|
|
49
|
+
|
|
50
|
+
steps:
|
|
51
|
+
- name: Checkout
|
|
52
|
+
uses: actions/checkout@v4
|
|
53
|
+
|
|
54
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
55
|
+
uses: actions/setup-python@v5
|
|
56
|
+
with:
|
|
57
|
+
python-version: ${{ matrix.python-version }}
|
|
58
|
+
|
|
59
|
+
- name: Install uv
|
|
60
|
+
uses: astral-sh/setup-uv@v3
|
|
61
|
+
with:
|
|
62
|
+
enable-cache: true
|
|
63
|
+
|
|
64
|
+
- name: Install dependencies
|
|
65
|
+
run: uv sync --all-extras --dev
|
|
66
|
+
|
|
67
|
+
- name: Ruff — lint
|
|
68
|
+
run: uv run ruff check .
|
|
69
|
+
|
|
70
|
+
- name: Ruff — format check
|
|
71
|
+
run: uv run ruff format --check .
|
|
72
|
+
|
|
73
|
+
- name: mypy — type check
|
|
74
|
+
run: uv run mypy .
|
|
75
|
+
|
|
76
|
+
- name: pytest — unit tests
|
|
77
|
+
run: uv run pytest -v --cov --cov-report=term-missing --cov-report=xml
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v*.*.*'
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
publish:
|
|
10
|
+
name: Publish to PyPI
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
environment: release
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
id-token: write
|
|
16
|
+
steps:
|
|
17
|
+
- name: Checkout
|
|
18
|
+
uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Set up Python
|
|
21
|
+
uses: actions/setup-python@v5
|
|
22
|
+
with:
|
|
23
|
+
python-version: '3.12'
|
|
24
|
+
|
|
25
|
+
- name: Install uv
|
|
26
|
+
uses: astral-sh/setup-uv@v3
|
|
27
|
+
with:
|
|
28
|
+
enable-cache: true
|
|
29
|
+
|
|
30
|
+
- name: Build distributions
|
|
31
|
+
run: uv build
|
|
32
|
+
|
|
33
|
+
- name: Check distributions
|
|
34
|
+
run: ls -la dist/
|
|
35
|
+
|
|
36
|
+
- name: Publish to PyPI
|
|
37
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
38
|
+
with:
|
|
39
|
+
password: ${{ secrets.PYPI_API_TOKEN }}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# macOS
|
|
2
|
+
.DS_Store
|
|
3
|
+
Thumbs.db
|
|
4
|
+
|
|
5
|
+
# Python
|
|
6
|
+
__pycache__/
|
|
7
|
+
*.py[cod]
|
|
8
|
+
*$py.class
|
|
9
|
+
*.so
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# Virtual envs
|
|
30
|
+
.env
|
|
31
|
+
.venv
|
|
32
|
+
env/
|
|
33
|
+
venv/
|
|
34
|
+
ENV/
|
|
35
|
+
env.bak/
|
|
36
|
+
venv.bak/
|
|
37
|
+
|
|
38
|
+
# Testing / coverage
|
|
39
|
+
.pytest_cache/
|
|
40
|
+
.coverage
|
|
41
|
+
.coverage.*
|
|
42
|
+
htmlcov/
|
|
43
|
+
.tox/
|
|
44
|
+
.nox/
|
|
45
|
+
coverage.xml
|
|
46
|
+
*.cover
|
|
47
|
+
.hypothesis/
|
|
48
|
+
|
|
49
|
+
# Type checkers / linters
|
|
50
|
+
.mypy_cache/
|
|
51
|
+
.dmypy.json
|
|
52
|
+
dmypy.json
|
|
53
|
+
.ruff_cache/
|
|
54
|
+
.pyre/
|
|
55
|
+
.pytype/
|
|
56
|
+
|
|
57
|
+
# Editors / IDEs
|
|
58
|
+
.idea/
|
|
59
|
+
.vscode/
|
|
60
|
+
*.swp
|
|
61
|
+
*.swo
|
|
62
|
+
*~
|
|
63
|
+
|
|
64
|
+
# Local state
|
|
65
|
+
*.log
|
|
66
|
+
*.sqlite
|
|
67
|
+
*.db
|
|
68
|
+
.env.local
|
|
69
|
+
.env.*.local
|
|
70
|
+
|
|
71
|
+
# Secrets — never commit
|
|
72
|
+
secrets/
|
|
73
|
+
*.key
|
|
74
|
+
*.pem
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Pre-commit hooks for Python repos (z3rno-core, z3rno-server, z3rno-sdk-python)
|
|
2
|
+
#
|
|
3
|
+
# Install:
|
|
4
|
+
# pip install pre-commit # or: brew install pre-commit
|
|
5
|
+
# pre-commit install # wires into .git/hooks/pre-commit
|
|
6
|
+
#
|
|
7
|
+
# Run manually:
|
|
8
|
+
# pre-commit run --all-files
|
|
9
|
+
#
|
|
10
|
+
# Skip a hook for one commit:
|
|
11
|
+
# SKIP=ruff git commit -m "..."
|
|
12
|
+
#
|
|
13
|
+
# Update pinned versions:
|
|
14
|
+
# pre-commit autoupdate
|
|
15
|
+
|
|
16
|
+
default_language_version:
|
|
17
|
+
python: python3.12
|
|
18
|
+
|
|
19
|
+
default_install_hook_types:
|
|
20
|
+
- pre-commit
|
|
21
|
+
- commit-msg
|
|
22
|
+
|
|
23
|
+
repos:
|
|
24
|
+
# ---------------------------------------------------------------------------
|
|
25
|
+
# Generic hygiene — applies to every repo
|
|
26
|
+
# ---------------------------------------------------------------------------
|
|
27
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
28
|
+
rev: v5.0.0
|
|
29
|
+
hooks:
|
|
30
|
+
- id: trailing-whitespace
|
|
31
|
+
args: [--markdown-linebreak-ext=md]
|
|
32
|
+
- id: end-of-file-fixer
|
|
33
|
+
- id: check-yaml
|
|
34
|
+
args: [--allow-multiple-documents]
|
|
35
|
+
- id: check-toml
|
|
36
|
+
- id: check-json
|
|
37
|
+
- id: check-merge-conflict
|
|
38
|
+
- id: check-case-conflict
|
|
39
|
+
- id: check-added-large-files
|
|
40
|
+
args: [--maxkb=500]
|
|
41
|
+
- id: check-symlinks
|
|
42
|
+
- id: destroyed-symlinks
|
|
43
|
+
- id: mixed-line-ending
|
|
44
|
+
args: [--fix=lf]
|
|
45
|
+
- id: detect-private-key
|
|
46
|
+
|
|
47
|
+
# ---------------------------------------------------------------------------
|
|
48
|
+
# Ruff — linter + formatter (replaces black, isort, flake8, pyupgrade)
|
|
49
|
+
# ---------------------------------------------------------------------------
|
|
50
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
51
|
+
rev: v0.8.6
|
|
52
|
+
hooks:
|
|
53
|
+
- id: ruff
|
|
54
|
+
args: [--fix, --exit-non-zero-on-fix]
|
|
55
|
+
- id: ruff-format
|
|
56
|
+
|
|
57
|
+
# ---------------------------------------------------------------------------
|
|
58
|
+
# mypy — strict static type checking (skeleton-mode tolerant)
|
|
59
|
+
# ---------------------------------------------------------------------------
|
|
60
|
+
- repo: https://github.com/pre-commit/mirrors-mypy
|
|
61
|
+
rev: v1.13.0
|
|
62
|
+
hooks:
|
|
63
|
+
- id: mypy
|
|
64
|
+
# Skip cleanly if no pyproject.toml exists yet (skeleton mode).
|
|
65
|
+
entry: bash -c 'if [ -f pyproject.toml ]; then mypy "$@"; else echo "skeleton mode: no pyproject.toml — skipping mypy"; fi' --
|
|
66
|
+
additional_dependencies:
|
|
67
|
+
- pydantic>=2.10
|
|
68
|
+
- sqlalchemy[mypy]>=2.0.36
|
|
69
|
+
- types-redis
|
|
70
|
+
- types-requests
|
|
71
|
+
|
|
72
|
+
# ---------------------------------------------------------------------------
|
|
73
|
+
# sqlfluff — SQL linter + formatter (PostgreSQL dialect)
|
|
74
|
+
# ---------------------------------------------------------------------------
|
|
75
|
+
- repo: https://github.com/sqlfluff/sqlfluff
|
|
76
|
+
rev: 3.3.0
|
|
77
|
+
hooks:
|
|
78
|
+
- id: sqlfluff-lint
|
|
79
|
+
args: [--dialect=postgres]
|
|
80
|
+
- id: sqlfluff-fix
|
|
81
|
+
args: [--dialect=postgres]
|
|
82
|
+
|
|
83
|
+
# ---------------------------------------------------------------------------
|
|
84
|
+
# commit message format (conventional commits, soft enforcement)
|
|
85
|
+
# ---------------------------------------------------------------------------
|
|
86
|
+
- repo: https://github.com/compilerla/conventional-pre-commit
|
|
87
|
+
rev: v3.6.0
|
|
88
|
+
hooks:
|
|
89
|
+
- id: conventional-pre-commit
|
|
90
|
+
stages: [commit-msg]
|
|
91
|
+
args: [feat, fix, build, chore, ci, docs, perf, refactor, revert, style, test]
|
|
92
|
+
|
|
93
|
+
ci:
|
|
94
|
+
# If you ever flip the repo to use pre-commit.ci (a free SaaS that runs
|
|
95
|
+
# pre-commit on every PR and auto-fixes), this controls its behaviour.
|
|
96
|
+
# Until then it's harmless metadata.
|
|
97
|
+
autofix_prs: true
|
|
98
|
+
autoupdate_schedule: monthly
|
|
99
|
+
skip: []
|
|
100
|
+
submodules: false
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
## Project
|
|
4
|
+
|
|
5
|
+
z3rno-server is the FastAPI REST API server for Z3rno. It wraps z3rno-core engine functions as HTTP endpoints, handles authentication, rate limiting, and manages Celery workers for background tasks. SDKs and external clients only talk to this server.
|
|
6
|
+
|
|
7
|
+
## Quick Reference
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
uv sync --dev # Install dependencies
|
|
11
|
+
uv run ruff check . # Lint
|
|
12
|
+
uv run ruff format . # Format
|
|
13
|
+
uv run mypy . # Type check
|
|
14
|
+
uv run pytest # Run tests
|
|
15
|
+
make dev-up # Start docker compose stack
|
|
16
|
+
make dev-down # Stop stack
|
|
17
|
+
make dev-psql # Connect to postgres shell
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Architecture
|
|
21
|
+
|
|
22
|
+
- `src/z3rno_server/main.py` — FastAPI app factory, middleware registration, router includes
|
|
23
|
+
- `src/z3rno_server/api/` — Route handlers: memories.py (store/recall/forget), audit.py, sessions.py, health.py, worker.py
|
|
24
|
+
- `src/z3rno_server/middleware/` — auth.py, rate_limit.py, logging.py, request_id.py, org_context.py
|
|
25
|
+
- `src/z3rno_server/schemas/` — Pydantic request/response models (the API contract for SDKs)
|
|
26
|
+
- `src/z3rno_server/workers/` — Celery tasks: lifecycle.py, embeddings.py, healthcheck.py, celery_app.py
|
|
27
|
+
- `src/z3rno_server/config.py` — pydantic-settings (DATABASE_URL, REDIS_URL, etc.)
|
|
28
|
+
- `src/z3rno_server/dependencies.py` — FastAPI DI: database session with RLS context
|
|
29
|
+
|
|
30
|
+
## API Endpoints
|
|
31
|
+
|
|
32
|
+
- `POST /v1/memories` — Store memory (calls z3rno_core.engine.store)
|
|
33
|
+
- `POST /v1/memories/recall` — Recall by query (calls z3rno_core.engine.recall)
|
|
34
|
+
- `POST /v1/memories/forget` — Forget/delete (calls z3rno_core.engine.forget)
|
|
35
|
+
- `GET /v1/audit` — Query audit log (calls z3rno_core.engine.audit)
|
|
36
|
+
- `POST /v1/sessions` — Start session (Redis-only)
|
|
37
|
+
- `POST /v1/sessions/{id}/end` — End session
|
|
38
|
+
- `GET /v1/health` — Liveness probe
|
|
39
|
+
- `GET /v1/ready` — Readiness probe
|
|
40
|
+
- `GET /v1/worker/health` — Celery worker healthcheck (public, no auth)
|
|
41
|
+
- `GET /metrics` — Prometheus metrics (public, no auth)
|
|
42
|
+
|
|
43
|
+
## Middleware Chain (order matters)
|
|
44
|
+
|
|
45
|
+
RequestId -> Logging -> Auth -> RateLimit -> Route Handler
|
|
46
|
+
|
|
47
|
+
## Key Conventions
|
|
48
|
+
|
|
49
|
+
- Python 3.11+, src/ layout, hatchling build
|
|
50
|
+
- z3rno-core is a git dependency (switches to PyPI version when published)
|
|
51
|
+
- Ruff + mypy for code quality
|
|
52
|
+
- API key auth via Authorization: Bearer or X-API-Key header
|
|
53
|
+
- Public paths skip auth: /v1/health, /v1/ready, /docs, /redoc, /openapi.json, /metrics, /v1/worker/health
|
|
54
|
+
- Sessions are Redis-only (no relational sessions table)
|
|
55
|
+
- Celery workers use Valkey as broker and result backend
|
|
56
|
+
- Conventional commits
|
|
57
|
+
|
|
58
|
+
## Environment Variables
|
|
59
|
+
|
|
60
|
+
- `DATABASE_URL` — PostgreSQL connection (asyncpg driver)
|
|
61
|
+
- `REDIS_URL` — Valkey connection
|
|
62
|
+
- `EMBEDDING_MODEL` — LiteLLM model name (default: text-embedding-3-small)
|
|
63
|
+
- `OPENAI_API_KEY` — For embedding generation
|
|
64
|
+
- `CORS_ORIGINS` — Comma-separated allowed origins
|
|
65
|
+
- `LOG_LEVEL` — Structlog level (default: INFO)
|
|
66
|
+
|
|
67
|
+
## Docker Compose
|
|
68
|
+
|
|
69
|
+
`docker-compose.dev.yml` runs 4 services: postgres (z3rno-postgres:17), valkey, server, worker. All on the `z3rno` network. Postgres uses platform: linux/amd64 for Apple Silicon compatibility.
|
|
70
|
+
|
|
71
|
+
`docker-compose.prod.yml` runs the same services plus Traefik for TLS termination. Uses required env vars, resource limits, health checks, password-protected Valkey, and real Celery worker command.
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Contributing to z3rno-server
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing to Z3rno. This guide covers the development workflow for `z3rno-server`.
|
|
4
|
+
|
|
5
|
+
## Getting Started
|
|
6
|
+
|
|
7
|
+
1. Fork and clone the repository.
|
|
8
|
+
2. Install Python 3.11+ and [uv](https://docs.astral.sh/uv/).
|
|
9
|
+
3. Install dependencies:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
uv sync --dev
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
4. Start the local development stack:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
docker compose -f docker-compose.dev.yml up
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
This brings up PostgreSQL (with pgvector, Apache AGE), Valkey, the server, and a Celery worker.
|
|
22
|
+
|
|
23
|
+
5. Run the checks:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
uv run ruff check .
|
|
27
|
+
uv run mypy .
|
|
28
|
+
uv run pytest
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Development Workflow
|
|
32
|
+
|
|
33
|
+
1. Create a feature branch from `main`:
|
|
34
|
+
```bash
|
|
35
|
+
git checkout -b feat/your-feature
|
|
36
|
+
```
|
|
37
|
+
2. Write your code with tests.
|
|
38
|
+
3. Run linting, type checking, and tests (see above).
|
|
39
|
+
4. Commit using conventional commit messages.
|
|
40
|
+
5. Open a pull request against `main`.
|
|
41
|
+
|
|
42
|
+
## Code Style
|
|
43
|
+
|
|
44
|
+
This project uses **ruff** for linting and formatting. Configuration lives in `pyproject.toml`.
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# Lint
|
|
48
|
+
uv run ruff check .
|
|
49
|
+
|
|
50
|
+
# Format
|
|
51
|
+
uv run ruff format .
|
|
52
|
+
|
|
53
|
+
# Type check
|
|
54
|
+
uv run mypy .
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Testing
|
|
58
|
+
|
|
59
|
+
Tests use `pytest` with `pytest-asyncio` and `httpx` for endpoint testing. Integration tests require running services and are marked with `@pytest.mark.integration`.
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
# All tests
|
|
63
|
+
uv run pytest
|
|
64
|
+
|
|
65
|
+
# Unit tests only
|
|
66
|
+
uv run pytest -m "not integration"
|
|
67
|
+
|
|
68
|
+
# With coverage
|
|
69
|
+
uv run pytest --cov=src/z3rno_server
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Commit Messages
|
|
73
|
+
|
|
74
|
+
Follow [Conventional Commits](https://www.conventionalcommits.org/):
|
|
75
|
+
|
|
76
|
+
- `feat:` new feature
|
|
77
|
+
- `fix:` bug fix
|
|
78
|
+
- `docs:` documentation only
|
|
79
|
+
- `test:` adding or updating tests
|
|
80
|
+
- `refactor:` code change that neither fixes a bug nor adds a feature
|
|
81
|
+
- `chore:` maintenance (deps, CI, tooling)
|
|
82
|
+
|
|
83
|
+
Examples:
|
|
84
|
+
- `feat: add session timeout endpoint`
|
|
85
|
+
- `fix: rate limiter not respecting Retry-After header`
|
|
86
|
+
|
|
87
|
+
## Pull Request Process
|
|
88
|
+
|
|
89
|
+
1. Ensure all checks pass (`ruff check`, `mypy`, `pytest`).
|
|
90
|
+
2. Keep PRs focused -- one logical change per PR.
|
|
91
|
+
3. Update or add tests for any changed behavior.
|
|
92
|
+
4. Fill out the PR template description.
|
|
93
|
+
5. A maintainer will review and merge.
|
|
94
|
+
|
|
95
|
+
## Questions?
|
|
96
|
+
|
|
97
|
+
Open a [GitHub Discussion](https://github.com/the-ai-project-co/z3rno-server/discussions) or reach out at engineering@z3rno.dev.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# syntax=docker/dockerfile:1.7
|
|
2
|
+
#
|
|
3
|
+
# z3rno-server — FastAPI REST server for Z3rno
|
|
4
|
+
# Multi-stage build: builder installs deps, runtime copies only what's needed.
|
|
5
|
+
|
|
6
|
+
# ---------------------------------------------------------------------------
|
|
7
|
+
# Stage 1: builder — install dependencies with uv
|
|
8
|
+
# ---------------------------------------------------------------------------
|
|
9
|
+
FROM python:3.12-slim-bookworm AS builder
|
|
10
|
+
|
|
11
|
+
ENV PYTHONDONTWRITEBYTECODE=1 \
|
|
12
|
+
PYTHONUNBUFFERED=1 \
|
|
13
|
+
PIP_DISABLE_PIP_VERSION_CHECK=1 \
|
|
14
|
+
PIP_NO_CACHE_DIR=1
|
|
15
|
+
|
|
16
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
17
|
+
git ca-certificates \
|
|
18
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
19
|
+
|
|
20
|
+
# Install uv for fast dependency resolution
|
|
21
|
+
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
|
|
22
|
+
|
|
23
|
+
WORKDIR /app
|
|
24
|
+
|
|
25
|
+
# Copy project files
|
|
26
|
+
COPY pyproject.toml ./
|
|
27
|
+
COPY src/ src/
|
|
28
|
+
|
|
29
|
+
# Install dependencies into the system site-packages
|
|
30
|
+
RUN uv pip install --system -e ".[worker]"
|
|
31
|
+
|
|
32
|
+
# ---------------------------------------------------------------------------
|
|
33
|
+
# Stage 2: runtime — lean image with only installed packages and source
|
|
34
|
+
# ---------------------------------------------------------------------------
|
|
35
|
+
FROM python:3.12-slim-bookworm AS runtime
|
|
36
|
+
|
|
37
|
+
LABEL org.opencontainers.image.title="z3rno-server" \
|
|
38
|
+
org.opencontainers.image.source="https://github.com/the-ai-project-co/z3rno-server" \
|
|
39
|
+
org.opencontainers.image.licenses="Apache-2.0"
|
|
40
|
+
|
|
41
|
+
ENV PYTHONDONTWRITEBYTECODE=1 \
|
|
42
|
+
PYTHONUNBUFFERED=1
|
|
43
|
+
|
|
44
|
+
RUN groupadd --system z3rno && useradd --system --gid z3rno --create-home z3rno
|
|
45
|
+
|
|
46
|
+
WORKDIR /app
|
|
47
|
+
|
|
48
|
+
# Copy installed Python packages from builder
|
|
49
|
+
COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
|
|
50
|
+
COPY --from=builder /usr/local/bin /usr/local/bin
|
|
51
|
+
|
|
52
|
+
# Copy application source
|
|
53
|
+
COPY --chown=z3rno:z3rno src/ src/
|
|
54
|
+
|
|
55
|
+
USER z3rno
|
|
56
|
+
|
|
57
|
+
EXPOSE 8000
|
|
58
|
+
|
|
59
|
+
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
|
|
60
|
+
CMD ["python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/v1/health')"]
|
|
61
|
+
|
|
62
|
+
CMD ["uvicorn", "z3rno_server.main:app", "--host", "0.0.0.0", "--port", "8000"]
|