quorum-ai 0.1.5__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 (113) hide show
  1. quorum_ai-0.1.5/.dockerignore +91 -0
  2. quorum_ai-0.1.5/.dockerignore.bak3 +93 -0
  3. quorum_ai-0.1.5/.env.example +21 -0
  4. quorum_ai-0.1.5/.firebase/hosting.bGFuZGluZw.cache +4 -0
  5. quorum_ai-0.1.5/.gitignore +16 -0
  6. quorum_ai-0.1.5/CHANGELOG.md +78 -0
  7. quorum_ai-0.1.5/Dockerfile +100 -0
  8. quorum_ai-0.1.5/Dockerfile.bak +97 -0
  9. quorum_ai-0.1.5/Dockerfile.bak2 +96 -0
  10. quorum_ai-0.1.5/Dockerfile.bak4 +97 -0
  11. quorum_ai-0.1.5/PKG-INFO +257 -0
  12. quorum_ai-0.1.5/README.md +203 -0
  13. quorum_ai-0.1.5/complex_test.py +26 -0
  14. quorum_ai-0.1.5/deploy/cloudrun.yaml +141 -0
  15. quorum_ai-0.1.5/docs/AUDIT_FINDINGS_v0.1.2.md +239 -0
  16. quorum_ai-0.1.5/docs/AUDIT_FINDINGS_v0.1.4.md +73 -0
  17. quorum_ai-0.1.5/docs/AUDIT_FINDINGS_v0.1.5.md +89 -0
  18. quorum_ai-0.1.5/docs/CONTEXT_PROFILES.md +121 -0
  19. quorum_ai-0.1.5/docs/POSTMORTEM_v0.1.0_deploy.md +100 -0
  20. quorum_ai-0.1.5/docs/SELF_EVAL_2026-06-17.json +242 -0
  21. quorum_ai-0.1.5/landing/README.md +112 -0
  22. quorum_ai-0.1.5/landing/index.html +303 -0
  23. quorum_ai-0.1.5/landing/node.png +0 -0
  24. quorum_ai-0.1.5/landing/risk.png +0 -0
  25. quorum_ai-0.1.5/pyproject.toml +68 -0
  26. quorum_ai-0.1.5/quorum_overnight_topics.txt +136 -0
  27. quorum_ai-0.1.5/scripts/README.md +37 -0
  28. quorum_ai-0.1.5/scripts/quorum-research-mode/README.md +89 -0
  29. quorum_ai-0.1.5/scripts/quorum-research-mode/genetic_prompts.py +266 -0
  30. quorum_ai-0.1.5/scripts/quorum-research-mode/lora_finetune_setup.py +200 -0
  31. quorum_ai-0.1.5/scripts/quorum-self-modify/self_modify.py +800 -0
  32. quorum_ai-0.1.5/scripts/smoke_test_docker.sh +187 -0
  33. quorum_ai-0.1.5/src/quorum/__init__.py +15 -0
  34. quorum_ai-0.1.5/src/quorum/_local_mode.py +50 -0
  35. quorum_ai-0.1.5/src/quorum/agents/__init__.py +26 -0
  36. quorum_ai-0.1.5/src/quorum/agents/autopilot.py +126 -0
  37. quorum_ai-0.1.5/src/quorum/agents/drafts.py +350 -0
  38. quorum_ai-0.1.5/src/quorum/agents/reframe.py +139 -0
  39. quorum_ai-0.1.5/src/quorum/agents/tools/__init__.py +164 -0
  40. quorum_ai-0.1.5/src/quorum/agents/tools/linkedin.py +204 -0
  41. quorum_ai-0.1.5/src/quorum/agents/tools/mcp.py +116 -0
  42. quorum_ai-0.1.5/src/quorum/agents/tools/metrics_store.py +193 -0
  43. quorum_ai-0.1.5/src/quorum/agents/tools/twitter.py +127 -0
  44. quorum_ai-0.1.5/src/quorum/billing/__init__.py +13 -0
  45. quorum_ai-0.1.5/src/quorum/billing/email_sender.py +316 -0
  46. quorum_ai-0.1.5/src/quorum/billing/stripe_billing.py +1224 -0
  47. quorum_ai-0.1.5/src/quorum/cli.py +802 -0
  48. quorum_ai-0.1.5/src/quorum/context.py +105 -0
  49. quorum_ai-0.1.5/src/quorum/core/__init__.py +1 -0
  50. quorum_ai-0.1.5/src/quorum/core/consensus.py +765 -0
  51. quorum_ai-0.1.5/src/quorum/core/embeddings.py +716 -0
  52. quorum_ai-0.1.5/src/quorum/core/memory.py +654 -0
  53. quorum_ai-0.1.5/src/quorum/customer_keys.py +220 -0
  54. quorum_ai-0.1.5/src/quorum/doctor.py +418 -0
  55. quorum_ai-0.1.5/src/quorum/evolution/__init__.py +0 -0
  56. quorum_ai-0.1.5/src/quorum/evolution/ab_testing.py +1135 -0
  57. quorum_ai-0.1.5/src/quorum/evolution/adversarial.py +1457 -0
  58. quorum_ai-0.1.5/src/quorum/evolution/architecture_search.py +908 -0
  59. quorum_ai-0.1.5/src/quorum/evolution/competition.py +1227 -0
  60. quorum_ai-0.1.5/src/quorum/evolution/distillation.py +758 -0
  61. quorum_ai-0.1.5/src/quorum/evolution/federated.py +597 -0
  62. quorum_ai-0.1.5/src/quorum/evolution/hebbian.py +936 -0
  63. quorum_ai-0.1.5/src/quorum/evolution/memory_loop.py +585 -0
  64. quorum_ai-0.1.5/src/quorum/evolution/meta.py +783 -0
  65. quorum_ai-0.1.5/src/quorum/evolution/overnight.py +150 -0
  66. quorum_ai-0.1.5/src/quorum/evolution/rlhf.py +1021 -0
  67. quorum_ai-0.1.5/src/quorum/evolution/router.py +897 -0
  68. quorum_ai-0.1.5/src/quorum/evolution/self_prompt.py +1173 -0
  69. quorum_ai-0.1.5/src/quorum/evolution/swarm.py +127 -0
  70. quorum_ai-0.1.5/src/quorum/evolution/synthetic_data.py +975 -0
  71. quorum_ai-0.1.5/src/quorum/evolution/web_learner.py +313 -0
  72. quorum_ai-0.1.5/src/quorum/firestore_stores.py +351 -0
  73. quorum_ai-0.1.5/src/quorum/hsp/__init__.py +5 -0
  74. quorum_ai-0.1.5/src/quorum/hsp/ai_act_cert.py +518 -0
  75. quorum_ai-0.1.5/src/quorum/hsp/gate.py +162 -0
  76. quorum_ai-0.1.5/src/quorum/hsp/webhook.py +478 -0
  77. quorum_ai-0.1.5/src/quorum/providers/__init__.py +1 -0
  78. quorum_ai-0.1.5/src/quorum/providers/anthropic.py +92 -0
  79. quorum_ai-0.1.5/src/quorum/providers/base.py +43 -0
  80. quorum_ai-0.1.5/src/quorum/providers/claude_cli.py +85 -0
  81. quorum_ai-0.1.5/src/quorum/providers/cohere.py +85 -0
  82. quorum_ai-0.1.5/src/quorum/providers/deepseek.py +78 -0
  83. quorum_ai-0.1.5/src/quorum/providers/gemini.py +82 -0
  84. quorum_ai-0.1.5/src/quorum/providers/grok.py +77 -0
  85. quorum_ai-0.1.5/src/quorum/providers/mistral.py +83 -0
  86. quorum_ai-0.1.5/src/quorum/providers/moonshot.py +107 -0
  87. quorum_ai-0.1.5/src/quorum/providers/nvidia.py +98 -0
  88. quorum_ai-0.1.5/src/quorum/providers/ollama.py +52 -0
  89. quorum_ai-0.1.5/src/quorum/providers/openai.py +93 -0
  90. quorum_ai-0.1.5/src/quorum/providers/qwen.py +148 -0
  91. quorum_ai-0.1.5/src/quorum/providers/registry.py +185 -0
  92. quorum_ai-0.1.5/src/quorum/providers/replicate.py +112 -0
  93. quorum_ai-0.1.5/src/quorum/providers/zhipu.py +105 -0
  94. quorum_ai-0.1.5/src/quorum/server/__init__.py +23 -0
  95. quorum_ai-0.1.5/src/quorum/server/main.py +2017 -0
  96. quorum_ai-0.1.5/src/quorum/web/__init__.py +5 -0
  97. quorum_ai-0.1.5/src/quorum/web/multi_source.py +187 -0
  98. quorum_ai-0.1.5/src/quorum/web/search.py +109 -0
  99. quorum_ai-0.1.5/tests/__init__.py +0 -0
  100. quorum_ai-0.1.5/tests/evolution/__init__.py +0 -0
  101. quorum_ai-0.1.5/tests/evolution/test_ab_testing.py +350 -0
  102. quorum_ai-0.1.5/tests/evolution/test_adversarial.py +226 -0
  103. quorum_ai-0.1.5/tests/evolution/test_competition.py +250 -0
  104. quorum_ai-0.1.5/tests/evolution/test_hebbian.py +239 -0
  105. quorum_ai-0.1.5/tests/evolution/test_meta.py +147 -0
  106. quorum_ai-0.1.5/tests/evolution/test_self_prompt.py +286 -0
  107. quorum_ai-0.1.5/tests/evolution/test_synthetic_data.py +243 -0
  108. quorum_ai-0.1.5/tests/providers/__init__.py +0 -0
  109. quorum_ai-0.1.5/tests/providers/test_cohere.py +68 -0
  110. quorum_ai-0.1.5/tests/providers/test_grok.py +54 -0
  111. quorum_ai-0.1.5/tests/providers/test_mistral.py +175 -0
  112. quorum_ai-0.1.5/tests/test_consensus.py +51 -0
  113. quorum_ai-0.1.5/uv.lock +2349 -0
@@ -0,0 +1,91 @@
1
+ # ============================================================================
2
+ # .dockerignore — keep the build context small and secret-free
3
+ # ============================================================================
4
+
5
+ # --- Tests & dev tooling --------------------------------------------------
6
+ tests/
7
+ test/
8
+ **/tests/
9
+ **/test_*.py
10
+ **/*_test.py
11
+ .pytest_cache/
12
+ .coverage
13
+ .coverage.*
14
+ htmlcov/
15
+ .tox/
16
+ .nox/
17
+ .mypy_cache/
18
+ .ruff_cache/
19
+ .hypothesis/
20
+
21
+ # --- Python build / cache -------------------------------------------------
22
+ __pycache__/
23
+ **/__pycache__/
24
+ *.py[cod]
25
+ *$py.class
26
+ *.so
27
+ *.egg
28
+ *.egg-info/
29
+ build/
30
+ dist/
31
+ .eggs/
32
+ pip-wheel-metadata/
33
+
34
+ # --- Virtualenvs ----------------------------------------------------------
35
+ .venv/
36
+ venv/
37
+ env/
38
+ .env/
39
+ ENV/
40
+
41
+ # --- VCS ------------------------------------------------------------------
42
+ .git/
43
+ .gitignore
44
+ .gitattributes
45
+ .github/
46
+ .gitlab-ci.yml
47
+
48
+ # --- Local data / databases ----------------------------------------------
49
+ *.db
50
+ *.sqlite
51
+ *.sqlite3
52
+ *.db-journal
53
+ data/
54
+ local_data/
55
+
56
+ # --- Secrets / environment files -----------------------------------------
57
+ .env
58
+ .env.*
59
+ !.env.example
60
+ *.pem
61
+ *.key
62
+ *.crt
63
+ secrets/
64
+ .secrets/
65
+
66
+ # --- Editor / OS noise ----------------------------------------------------
67
+ .vscode/
68
+ .idea/
69
+ *.swp
70
+ *.swo
71
+ *~
72
+ .DS_Store
73
+ Thumbs.db
74
+
75
+ # --- Docker / CI artifacts -----------------------------------------------
76
+ Dockerfile*
77
+ !Dockerfile
78
+ docker-compose*.yml
79
+ .dockerignore
80
+
81
+ # --- Docs / misc not needed in image -------------------------------------
82
+ CHANGELOG.md
83
+ CONTRIBUTING.md
84
+ LICENSE
85
+ docs/
86
+ landing/
87
+ !src/**/*.md
88
+
89
+ # --- Logs -----------------------------------------------------------------
90
+ *.log
91
+ logs/
@@ -0,0 +1,93 @@
1
+ # ============================================================================
2
+ # .dockerignore — keep the build context small and secret-free
3
+ # ============================================================================
4
+
5
+ # --- Tests & dev tooling --------------------------------------------------
6
+ tests/
7
+ test/
8
+ **/tests/
9
+ **/test_*.py
10
+ **/*_test.py
11
+ .pytest_cache/
12
+ .coverage
13
+ .coverage.*
14
+ htmlcov/
15
+ .tox/
16
+ .nox/
17
+ .mypy_cache/
18
+ .ruff_cache/
19
+ .hypothesis/
20
+
21
+ # --- Python build / cache -------------------------------------------------
22
+ __pycache__/
23
+ **/__pycache__/
24
+ *.py[cod]
25
+ *$py.class
26
+ *.so
27
+ *.egg
28
+ *.egg-info/
29
+ build/
30
+ dist/
31
+ .eggs/
32
+ pip-wheel-metadata/
33
+
34
+ # --- Virtualenvs ----------------------------------------------------------
35
+ .venv/
36
+ venv/
37
+ env/
38
+ .env/
39
+ ENV/
40
+
41
+ # --- VCS ------------------------------------------------------------------
42
+ .git/
43
+ .gitignore
44
+ .gitattributes
45
+ .github/
46
+ .gitlab-ci.yml
47
+
48
+ # --- Local data / databases ----------------------------------------------
49
+ *.db
50
+ *.sqlite
51
+ *.sqlite3
52
+ *.db-journal
53
+ data/
54
+ local_data/
55
+
56
+ # --- Secrets / environment files -----------------------------------------
57
+ .env
58
+ .env.*
59
+ !.env.example
60
+ *.pem
61
+ *.key
62
+ *.crt
63
+ secrets/
64
+ .secrets/
65
+
66
+ # --- Editor / OS noise ----------------------------------------------------
67
+ .vscode/
68
+ .idea/
69
+ *.swp
70
+ *.swo
71
+ *~
72
+ .DS_Store
73
+ Thumbs.db
74
+
75
+ # --- Docker / CI artifacts -----------------------------------------------
76
+ Dockerfile*
77
+ !Dockerfile
78
+ docker-compose*.yml
79
+ .dockerignore
80
+
81
+ # --- Docs / misc not needed in image -------------------------------------
82
+ README.md
83
+ CHANGELOG.md
84
+ CONTRIBUTING.md
85
+ LICENSE
86
+ docs/
87
+ landing/
88
+ *.md
89
+ !src/**/*.md
90
+
91
+ # --- Logs -----------------------------------------------------------------
92
+ *.log
93
+ logs/
@@ -0,0 +1,21 @@
1
+ # Bring Your Own Keys (BYOK) — Quorum never stores or proxies your API keys.
2
+ # All keys are read at runtime by the provider you actually use.
3
+
4
+ # Paid providers (you bring your account)
5
+ ANTHROPIC_API_KEY=sk-ant-...
6
+ OPENAI_API_KEY=sk-...
7
+ GOOGLE_AI_STUDIO_KEY=AQ...
8
+ XAI_API_KEY=xai-...
9
+
10
+ # Open-source models via Replicate (one key, many models)
11
+ REPLICATE_API_TOKEN=r8_...
12
+
13
+ # Local Llama via Ollama (free, runs on your machine)
14
+ OLLAMA_HOST=http://localhost:11434
15
+
16
+ # HSP integration (commercial users only)
17
+ HSP_PROTOCOL_KEY=
18
+ HSP_GATE_WEBHOOK=
19
+
20
+ # Optional: embedding model for semantic consensus
21
+ QUORUM_EMBED_PROVIDER=gemini # gemini | openai | local
@@ -0,0 +1,4 @@
1
+ README.md,1781574398026,744fde70922291a99a47ce695c74c75d7c3593911d35c90533ba42cd21ae3ae8
2
+ index.html,1781773507666,5b983a5323d553e3edeeacb05e5fcc7dfdd2cdccac9fe69643e0cb2ad18921b9
3
+ risk.png,1781773493192,489e1f4f91a1630ab03a11695eebb21bc4621ed4ddb28089cadeb9eb407a7b7f
4
+ node.png,1781773493970,ef8d24f596115951ad4452d55a6685be9d1ad674dc83b1bf014084150a5540a4
@@ -0,0 +1,16 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ .venv/
5
+ venv/
6
+ .env
7
+ .env.local
8
+ .pytest_cache/
9
+ .ruff_cache/
10
+ .coverage
11
+ dist/
12
+ build/
13
+ .DS_Store
14
+ *.log
15
+ .idea/
16
+ .vscode/
@@ -0,0 +1,78 @@
1
+ # Changelog
2
+
3
+ All notable changes to Quorum are documented here. Format loosely follows Keep-a-Changelog; versioning follows SemVer.
4
+
5
+ ## [0.1.0] — 2026-06-16
6
+
7
+ The "real product" release: 13 self-evolution loops, vector memory, HSP gate, FastAPI server, Stripe billing, and EU AI Act per-query PDF certificate. All modules ship with in-memory fallbacks so tests pass without external keys.
8
+
9
+ ### Added — core
10
+
11
+ - `src/quorum/core/embeddings.py` — async embedding client (OpenAI / Cohere / local) with cosine + euclidean similarity helpers; replaces the v0.0.1 Jaccard placeholder for semantic consensus
12
+ - `src/quorum/core/memory.py` — vector memory store backed by aiosqlite (with pure-Python in-memory fallback); recall-by-prompt for the memory loop
13
+
14
+ ### Added — 13 self-evolution loops (`src/quorum/evolution/`)
15
+
16
+ - `rlhf.py` — explicit thumbs/correction-driven weight updates
17
+ - `hebbian.py` — co-correctness correlation between model pairs
18
+ - `distillation.py` — cheap models learn from consensus answers
19
+ - `router.py` — per-domain model weighting (code, vision, biomed, …)
20
+ - `memory_loop.py` — retrieval-augmented consensus on similar past prompts
21
+ - `meta.py` — meta-learning audit of which loops are improving accuracy
22
+ - `competition.py` — pairwise model duels, ELO-style ranking
23
+ - `ab_testing.py` — two prompt variants per call, win-rate tracking
24
+ - `synthetic_data.py` — high-confidence consensus → training data export
25
+ - `federated.py` — cross-tenant signal aggregation without raw data leak
26
+ - `self_prompt.py` — Quorum rewrites ambiguous prompts before fan-out
27
+ - `adversarial.py` — red-team prompts; models that fall for them lose weight
28
+ - `architecture_search.py` — trial new model combos / topologies; promote winners
29
+
30
+ ### Added — HSP gate & compliance (`src/quorum/hsp/`)
31
+
32
+ - `ai_act_cert.py` — per-query PDF certificate (reportlab) satisfying EU AI Act Art. 12 + Art. 13; SHA-256 hash-chain across tenant; required for the 2026-08-02 enforcement window
33
+ - `webhook.py` — signed HSP gate decision callback handler (patent PCT/US26/11908)
34
+
35
+ ### Added — billing (`src/quorum/billing/`)
36
+
37
+ - `stripe_billing.py` — Stripe-backed metered billing for Free / Pro / Team / Enterprise tiers + Compliance add-on; signature-verified webhook handler; in-memory fallback when `STRIPE_API_KEY` is unset so CI passes without secrets
38
+
39
+ ### Added — server (`src/quorum/server/`)
40
+
41
+ - `main.py` — FastAPI app with slowapi rate limiting, Bearer/BYOK auth, endpoints: `/v1/consensus`, `/v1/consensus/stream` (SSE), `/v1/models`, `/v1/feedback`, `/v1/cert/{id}`, `/v1/billing/checkout`, `/v1/billing/webhook`, `/v1/hsp/webhook`, `/v1/usage`, `/healthz`, `/metrics`; entry point `quorum-server`
42
+
43
+ ### Changed
44
+
45
+ - `pyproject.toml` — version bump 0.0.1 → 0.1.0; status Alpha → Beta; new deps: reportlab, stripe, fastapi, uvicorn[standard], slowapi; aiosqlite as optional `storage` extra; mypy added to `dev`; new script `quorum-server`
46
+ - `README.md` — full rewrite covering the 13 loops, billing tiers, hosted API endpoints, EU AI Act certification, and an ASCII architecture diagram
47
+ - `src/quorum/core/consensus.py` — replaced Jaccard placeholder with semantic-similarity path through `core/embeddings.py`; surfaces `evolution_signals` from the 13 loops
48
+
49
+ ### Notes
50
+
51
+ - Every external service (Stripe, Supabase, HSP webhook signing) has a graceful in-memory or stub fallback when env vars are missing — `pytest` runs green on a clean machine
52
+ - All evolution loops are async write-backs; they never block the request path
53
+ - HSP-gated modules carry the dual Apache 2.0 + HSP commercial-restriction header
54
+
55
+ ## [0.0.1] — 2026-06-16
56
+
57
+ Initial public cut. Minimal but real: five providers, async fan-out, lexical placeholder for consensus scoring, CLI.
58
+
59
+ ### Added
60
+
61
+ - `README.md`, `LICENSE` (Apache 2.0), `LICENSE-HSP` (PCT/US26/11908 commercial restrictions)
62
+ - `quorum/pyproject.toml` — package config, Python 3.10+, BYOK extras
63
+ - `quorum/src/quorum/__init__.py` — public `consensus` re-export
64
+ - `quorum/src/quorum/cli.py` — typer-based `quorum` CLI
65
+ - `quorum/src/quorum/core/consensus.py` — async orchestrator, Jaccard placeholder scoring
66
+ - `quorum/src/quorum/providers/base.py` — provider ABC
67
+ - `quorum/src/quorum/providers/registry.py` — provider discovery + ordering
68
+ - `quorum/src/quorum/providers/anthropic.py` — Claude client (BYOK)
69
+ - `quorum/src/quorum/providers/gemini.py` — Gemini client (BYOK)
70
+ - `quorum/src/quorum/providers/openai.py` — GPT client (BYOK)
71
+ - `quorum/src/quorum/providers/ollama.py` — local Ollama client
72
+ - `quorum/src/quorum/providers/replicate.py` — Replicate-hosted Llama/Mistral
73
+ - `quorum/src/quorum/hsp/__init__.py`, `hsp/gate.py` — decorator stub for HSP-gated calls
74
+ - `quorum/tests/test_consensus.py` — async smoke test, no external keys required
75
+ - `quorum/.env.example`, `quorum/.gitignore`
76
+
77
+ [0.1.0]: https://github.com/jaquelinejaque/sovereignchain/releases/tag/v0.1.0
78
+ [0.0.1]: https://github.com/jaquelinejaque/sovereignchain/releases/tag/v0.0.1
@@ -0,0 +1,100 @@
1
+ # syntax=docker/dockerfile:1.7
2
+ # ============================================================================
3
+ # Quorum API — Multi-stage Dockerfile for Cloud Run
4
+ # Stage 1: builder — installs deps with uv into a virtualenv
5
+ # Stage 2: runner — slim runtime, non-root user, copies only the venv + src
6
+ # ============================================================================
7
+
8
+ # ----------------------------------------------------------------------------
9
+ # Stage 1 — builder
10
+ # ----------------------------------------------------------------------------
11
+ FROM python:3.12-slim AS builder
12
+
13
+ ENV PYTHONDONTWRITEBYTECODE=1 \
14
+ PYTHONUNBUFFERED=1 \
15
+ PIP_DISABLE_PIP_VERSION_CHECK=1 \
16
+ PIP_NO_CACHE_DIR=1 \
17
+ UV_LINK_MODE=copy \
18
+ UV_COMPILE_BYTECODE=1 \
19
+ VIRTUAL_ENV=/opt/venv \
20
+ PATH="/opt/venv/bin:${PATH}"
21
+
22
+ # Build-time OS deps (kept minimal; purged in runner stage by not copying)
23
+ RUN apt-get update \
24
+ && apt-get install -y --no-install-recommends \
25
+ build-essential \
26
+ curl \
27
+ ca-certificates \
28
+ && rm -rf /var/lib/apt/lists/*
29
+
30
+ # Install uv (fast resolver/installer from Astral)
31
+ RUN pip install --no-cache-dir "uv>=0.4.0"
32
+
33
+ # Create isolated virtualenv we will copy into the runner
34
+ RUN uv venv "${VIRTUAL_ENV}"
35
+
36
+ WORKDIR /build
37
+
38
+ # Copy dependency manifest first to maximize Docker layer cache
39
+ COPY pyproject.toml ./
40
+ # Optional lock file — copy if present (graceful: ignored if missing on context)
41
+
42
+ # Install project dependencies into the venv
43
+ # --system would target /usr; we explicitly target the venv via VIRTUAL_ENV.
44
+ RUN uv pip install --no-cache --requirement pyproject.toml
45
+
46
+ # Copy the actual source and install the project itself (editable=False)
47
+ COPY README.md ./
48
+ COPY src ./src
49
+ RUN uv pip install --no-cache --no-deps .
50
+
51
+ # ----------------------------------------------------------------------------
52
+ # Stage 2 — runner (slim, non-root)
53
+ # ----------------------------------------------------------------------------
54
+ FROM python:3.12-slim AS runner
55
+
56
+ ENV PYTHONDONTWRITEBYTECODE=1 \
57
+ PYTHONUNBUFFERED=1 \
58
+ PIP_DISABLE_PIP_VERSION_CHECK=1 \
59
+ VIRTUAL_ENV=/opt/venv \
60
+ PATH="/opt/venv/bin:${PATH}" \
61
+ PORT=8080 \
62
+ HOST=0.0.0.0
63
+
64
+ # Runtime OS deps only — curl is needed for HEALTHCHECK
65
+ RUN apt-get update \
66
+ && apt-get install -y --no-install-recommends \
67
+ curl \
68
+ ca-certificates \
69
+ tini \
70
+ && rm -rf /var/lib/apt/lists/* \
71
+ && groupadd --system --gid 1001 quorum \
72
+ && useradd --system --uid 1001 --gid quorum --home-dir /app --shell /usr/sbin/nologin quorum
73
+
74
+ WORKDIR /app
75
+
76
+ # Copy the prepared virtualenv from builder
77
+ COPY --from=builder --chown=quorum:quorum /opt/venv /opt/venv
78
+
79
+ # Copy project files needed at runtime
80
+ COPY --chown=quorum:quorum pyproject.toml ./
81
+ COPY --chown=quorum:quorum src ./src
82
+
83
+ # Drop privileges
84
+ # Pre-create writable data dir for SQLite stores (api_keys, usage, memory, etc).
85
+ # /app is otherwise read-only for non-root, so api_key_store/memory/etc would fail.
86
+ RUN mkdir -p /app/.quorum && chown -R quorum:quorum /app/.quorum
87
+ USER quorum:quorum
88
+
89
+ EXPOSE 8080
90
+
91
+ # Cloud Run probes /healthz; local docker run uses this HEALTHCHECK too.
92
+ HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
93
+ CMD curl -fsS "http://127.0.0.1:${PORT:-8080}/healthz" || exit 1
94
+
95
+ # tini = proper PID 1 (reaps zombies, forwards signals to uvicorn)
96
+ ENTRYPOINT ["/usr/bin/tini", "--"]
97
+
98
+ # Cloud Run injects $PORT (default 8080); host must be 0.0.0.0
99
+ # Use sh -c so ${PORT:-8080} expansion happens at runtime, not build time.
100
+ CMD ["sh", "-c", "exec uvicorn quorum.server.main:app --host 0.0.0.0 --port ${PORT:-8080} --proxy-headers --forwarded-allow-ips='*'"]
@@ -0,0 +1,97 @@
1
+ # syntax=docker/dockerfile:1.7
2
+ # ============================================================================
3
+ # Quorum API — Multi-stage Dockerfile for Cloud Run
4
+ # Stage 1: builder — installs deps with uv into a virtualenv
5
+ # Stage 2: runner — slim runtime, non-root user, copies only the venv + src
6
+ # ============================================================================
7
+
8
+ # ----------------------------------------------------------------------------
9
+ # Stage 1 — builder
10
+ # ----------------------------------------------------------------------------
11
+ FROM python:3.12-slim AS builder
12
+
13
+ ENV PYTHONDONTWRITEBYTECODE=1 \
14
+ PYTHONUNBUFFERED=1 \
15
+ PIP_DISABLE_PIP_VERSION_CHECK=1 \
16
+ PIP_NO_CACHE_DIR=1 \
17
+ UV_LINK_MODE=copy \
18
+ UV_COMPILE_BYTECODE=1 \
19
+ VIRTUAL_ENV=/opt/venv \
20
+ PATH="/opt/venv/bin:${PATH}"
21
+
22
+ # Build-time OS deps (kept minimal; purged in runner stage by not copying)
23
+ RUN apt-get update \
24
+ && apt-get install -y --no-install-recommends \
25
+ build-essential \
26
+ curl \
27
+ ca-certificates \
28
+ && rm -rf /var/lib/apt/lists/*
29
+
30
+ # Install uv (fast resolver/installer from Astral)
31
+ RUN pip install --no-cache-dir "uv>=0.4.0"
32
+
33
+ # Create isolated virtualenv we will copy into the runner
34
+ RUN uv venv "${VIRTUAL_ENV}"
35
+
36
+ WORKDIR /build
37
+
38
+ # Copy dependency manifest first to maximize Docker layer cache
39
+ COPY pyproject.toml ./
40
+ # Optional lock file — copy if present (graceful: ignored if missing on context)
41
+ COPY uv.loc[k] ./
42
+
43
+ # Install project dependencies into the venv
44
+ # --system would target /usr; we explicitly target the venv via VIRTUAL_ENV.
45
+ RUN uv pip install --no-cache --requirement pyproject.toml
46
+
47
+ # Copy the actual source and install the project itself (editable=False)
48
+ COPY src ./src
49
+ RUN uv pip install --no-cache --no-deps .
50
+
51
+ # ----------------------------------------------------------------------------
52
+ # Stage 2 — runner (slim, non-root)
53
+ # ----------------------------------------------------------------------------
54
+ FROM python:3.12-slim AS runner
55
+
56
+ ENV PYTHONDONTWRITEBYTECODE=1 \
57
+ PYTHONUNBUFFERED=1 \
58
+ PIP_DISABLE_PIP_VERSION_CHECK=1 \
59
+ VIRTUAL_ENV=/opt/venv \
60
+ PATH="/opt/venv/bin:${PATH}" \
61
+ PORT=8080 \
62
+ HOST=0.0.0.0
63
+
64
+ # Runtime OS deps only — curl is needed for HEALTHCHECK
65
+ RUN apt-get update \
66
+ && apt-get install -y --no-install-recommends \
67
+ curl \
68
+ ca-certificates \
69
+ tini \
70
+ && rm -rf /var/lib/apt/lists/* \
71
+ && groupadd --system --gid 1001 quorum \
72
+ && useradd --system --uid 1001 --gid quorum --home-dir /app --shell /usr/sbin/nologin quorum
73
+
74
+ WORKDIR /app
75
+
76
+ # Copy the prepared virtualenv from builder
77
+ COPY --from=builder --chown=quorum:quorum /opt/venv /opt/venv
78
+
79
+ # Copy project files needed at runtime
80
+ COPY --chown=quorum:quorum pyproject.toml ./
81
+ COPY --chown=quorum:quorum src ./src
82
+
83
+ # Drop privileges
84
+ USER quorum:quorum
85
+
86
+ EXPOSE 8080
87
+
88
+ # Cloud Run probes /healthz; local docker run uses this HEALTHCHECK too.
89
+ HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
90
+ CMD curl -fsS "http://127.0.0.1:${PORT:-8080}/healthz" || exit 1
91
+
92
+ # tini = proper PID 1 (reaps zombies, forwards signals to uvicorn)
93
+ ENTRYPOINT ["/usr/bin/tini", "--"]
94
+
95
+ # Cloud Run injects $PORT (default 8080); host must be 0.0.0.0
96
+ # Use sh -c so ${PORT:-8080} expansion happens at runtime, not build time.
97
+ CMD ["sh", "-c", "exec uvicorn quorum.server.main:app --host 0.0.0.0 --port ${PORT:-8080} --proxy-headers --forwarded-allow-ips='*'"]
@@ -0,0 +1,96 @@
1
+ # syntax=docker/dockerfile:1.7
2
+ # ============================================================================
3
+ # Quorum API — Multi-stage Dockerfile for Cloud Run
4
+ # Stage 1: builder — installs deps with uv into a virtualenv
5
+ # Stage 2: runner — slim runtime, non-root user, copies only the venv + src
6
+ # ============================================================================
7
+
8
+ # ----------------------------------------------------------------------------
9
+ # Stage 1 — builder
10
+ # ----------------------------------------------------------------------------
11
+ FROM python:3.12-slim AS builder
12
+
13
+ ENV PYTHONDONTWRITEBYTECODE=1 \
14
+ PYTHONUNBUFFERED=1 \
15
+ PIP_DISABLE_PIP_VERSION_CHECK=1 \
16
+ PIP_NO_CACHE_DIR=1 \
17
+ UV_LINK_MODE=copy \
18
+ UV_COMPILE_BYTECODE=1 \
19
+ VIRTUAL_ENV=/opt/venv \
20
+ PATH="/opt/venv/bin:${PATH}"
21
+
22
+ # Build-time OS deps (kept minimal; purged in runner stage by not copying)
23
+ RUN apt-get update \
24
+ && apt-get install -y --no-install-recommends \
25
+ build-essential \
26
+ curl \
27
+ ca-certificates \
28
+ && rm -rf /var/lib/apt/lists/*
29
+
30
+ # Install uv (fast resolver/installer from Astral)
31
+ RUN pip install --no-cache-dir "uv>=0.4.0"
32
+
33
+ # Create isolated virtualenv we will copy into the runner
34
+ RUN uv venv "${VIRTUAL_ENV}"
35
+
36
+ WORKDIR /build
37
+
38
+ # Copy dependency manifest first to maximize Docker layer cache
39
+ COPY pyproject.toml ./
40
+ # Optional lock file — copy if present (graceful: ignored if missing on context)
41
+
42
+ # Install project dependencies into the venv
43
+ # --system would target /usr; we explicitly target the venv via VIRTUAL_ENV.
44
+ RUN uv pip install --no-cache --requirement pyproject.toml
45
+
46
+ # Copy the actual source and install the project itself (editable=False)
47
+ COPY src ./src
48
+ RUN uv pip install --no-cache --no-deps .
49
+
50
+ # ----------------------------------------------------------------------------
51
+ # Stage 2 — runner (slim, non-root)
52
+ # ----------------------------------------------------------------------------
53
+ FROM python:3.12-slim AS runner
54
+
55
+ ENV PYTHONDONTWRITEBYTECODE=1 \
56
+ PYTHONUNBUFFERED=1 \
57
+ PIP_DISABLE_PIP_VERSION_CHECK=1 \
58
+ VIRTUAL_ENV=/opt/venv \
59
+ PATH="/opt/venv/bin:${PATH}" \
60
+ PORT=8080 \
61
+ HOST=0.0.0.0
62
+
63
+ # Runtime OS deps only — curl is needed for HEALTHCHECK
64
+ RUN apt-get update \
65
+ && apt-get install -y --no-install-recommends \
66
+ curl \
67
+ ca-certificates \
68
+ tini \
69
+ && rm -rf /var/lib/apt/lists/* \
70
+ && groupadd --system --gid 1001 quorum \
71
+ && useradd --system --uid 1001 --gid quorum --home-dir /app --shell /usr/sbin/nologin quorum
72
+
73
+ WORKDIR /app
74
+
75
+ # Copy the prepared virtualenv from builder
76
+ COPY --from=builder --chown=quorum:quorum /opt/venv /opt/venv
77
+
78
+ # Copy project files needed at runtime
79
+ COPY --chown=quorum:quorum pyproject.toml ./
80
+ COPY --chown=quorum:quorum src ./src
81
+
82
+ # Drop privileges
83
+ USER quorum:quorum
84
+
85
+ EXPOSE 8080
86
+
87
+ # Cloud Run probes /healthz; local docker run uses this HEALTHCHECK too.
88
+ HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
89
+ CMD curl -fsS "http://127.0.0.1:${PORT:-8080}/healthz" || exit 1
90
+
91
+ # tini = proper PID 1 (reaps zombies, forwards signals to uvicorn)
92
+ ENTRYPOINT ["/usr/bin/tini", "--"]
93
+
94
+ # Cloud Run injects $PORT (default 8080); host must be 0.0.0.0
95
+ # Use sh -c so ${PORT:-8080} expansion happens at runtime, not build time.
96
+ CMD ["sh", "-c", "exec uvicorn quorum.server.main:app --host 0.0.0.0 --port ${PORT:-8080} --proxy-headers --forwarded-allow-ips='*'"]