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.
Files changed (64) hide show
  1. z3rno_server-0.1.0/.env.example +46 -0
  2. z3rno_server-0.1.0/.github/workflows/ci.yml +77 -0
  3. z3rno_server-0.1.0/.github/workflows/release.yml +39 -0
  4. z3rno_server-0.1.0/.gitignore +74 -0
  5. z3rno_server-0.1.0/.pre-commit-config.yaml +100 -0
  6. z3rno_server-0.1.0/CLAUDE.md +71 -0
  7. z3rno_server-0.1.0/CONTRIBUTING.md +97 -0
  8. z3rno_server-0.1.0/Dockerfile +62 -0
  9. z3rno_server-0.1.0/LICENSE +201 -0
  10. z3rno_server-0.1.0/Makefile +128 -0
  11. z3rno_server-0.1.0/PKG-INFO +119 -0
  12. z3rno_server-0.1.0/README.md +95 -0
  13. z3rno_server-0.1.0/SECURITY.md +29 -0
  14. z3rno_server-0.1.0/docker-compose.dev.yml +158 -0
  15. z3rno_server-0.1.0/docker-compose.monitoring.yml +61 -0
  16. z3rno_server-0.1.0/docker-compose.prod.yml +250 -0
  17. z3rno_server-0.1.0/monitoring/grafana/provisioning/dashboards/dashboards.yml +12 -0
  18. z3rno_server-0.1.0/monitoring/grafana/provisioning/dashboards/z3rno-overview.json +128 -0
  19. z3rno_server-0.1.0/monitoring/grafana/provisioning/datasources/prometheus.yml +9 -0
  20. z3rno_server-0.1.0/monitoring/prometheus/prometheus.yml +11 -0
  21. z3rno_server-0.1.0/pyproject.toml +113 -0
  22. z3rno_server-0.1.0/scripts/healthcheck.sh +173 -0
  23. z3rno_server-0.1.0/src/z3rno_server/__init__.py +1 -0
  24. z3rno_server-0.1.0/src/z3rno_server/api/__init__.py +1 -0
  25. z3rno_server-0.1.0/src/z3rno_server/api/api_keys.py +208 -0
  26. z3rno_server-0.1.0/src/z3rno_server/api/audit.py +80 -0
  27. z3rno_server-0.1.0/src/z3rno_server/api/health.py +22 -0
  28. z3rno_server-0.1.0/src/z3rno_server/api/memories.py +435 -0
  29. z3rno_server-0.1.0/src/z3rno_server/api/sessions.py +172 -0
  30. z3rno_server-0.1.0/src/z3rno_server/api/worker.py +39 -0
  31. z3rno_server-0.1.0/src/z3rno_server/config.py +70 -0
  32. z3rno_server-0.1.0/src/z3rno_server/dependencies.py +78 -0
  33. z3rno_server-0.1.0/src/z3rno_server/main.py +66 -0
  34. z3rno_server-0.1.0/src/z3rno_server/middleware/__init__.py +1 -0
  35. z3rno_server-0.1.0/src/z3rno_server/middleware/auth.py +322 -0
  36. z3rno_server-0.1.0/src/z3rno_server/middleware/body_limit.py +57 -0
  37. z3rno_server-0.1.0/src/z3rno_server/middleware/logging.py +62 -0
  38. z3rno_server-0.1.0/src/z3rno_server/middleware/org_context.py +23 -0
  39. z3rno_server-0.1.0/src/z3rno_server/middleware/rate_limit.py +199 -0
  40. z3rno_server-0.1.0/src/z3rno_server/middleware/rbac.py +45 -0
  41. z3rno_server-0.1.0/src/z3rno_server/middleware/request_id.py +20 -0
  42. z3rno_server-0.1.0/src/z3rno_server/schemas/__init__.py +36 -0
  43. z3rno_server-0.1.0/src/z3rno_server/schemas/audit.py +47 -0
  44. z3rno_server-0.1.0/src/z3rno_server/schemas/memories.py +158 -0
  45. z3rno_server-0.1.0/src/z3rno_server/schemas/shared.py +22 -0
  46. z3rno_server-0.1.0/src/z3rno_server/workers/__init__.py +1 -0
  47. z3rno_server-0.1.0/src/z3rno_server/workers/celery_app.py +32 -0
  48. z3rno_server-0.1.0/src/z3rno_server/workers/embeddings.py +81 -0
  49. z3rno_server-0.1.0/src/z3rno_server/workers/healthcheck.py +21 -0
  50. z3rno_server-0.1.0/src/z3rno_server/workers/lifecycle.py +170 -0
  51. z3rno_server-0.1.0/tests/__init__.py +0 -0
  52. z3rno_server-0.1.0/tests/conftest.py +20 -0
  53. z3rno_server-0.1.0/tests/load/README.md +60 -0
  54. z3rno_server-0.1.0/tests/load/__init__.py +0 -0
  55. z3rno_server-0.1.0/tests/load/locustfile.py +132 -0
  56. z3rno_server-0.1.0/tests/test_api_memories.py +78 -0
  57. z3rno_server-0.1.0/tests/test_config.py +63 -0
  58. z3rno_server-0.1.0/tests/test_e2e.py +212 -0
  59. z3rno_server-0.1.0/tests/test_health.py +30 -0
  60. z3rno_server-0.1.0/tests/test_middleware_auth.py +249 -0
  61. z3rno_server-0.1.0/tests/test_middleware_request_id.py +43 -0
  62. z3rno_server-0.1.0/tests/test_schemas.py +174 -0
  63. z3rno_server-0.1.0/tests/test_security.py +321 -0
  64. 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"]