imbi-common 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 (111) hide show
  1. imbi_common-0.1.0/.github/workflows/docs.yml +53 -0
  2. imbi_common-0.1.0/.github/workflows/publish.yml +45 -0
  3. imbi_common-0.1.0/.github/workflows/test.yml +54 -0
  4. imbi_common-0.1.0/.gitignore +10 -0
  5. imbi_common-0.1.0/.pre-commit-config.yaml +36 -0
  6. imbi_common-0.1.0/CLAUDE.md +75 -0
  7. imbi_common-0.1.0/LICENSE +28 -0
  8. imbi_common-0.1.0/PKG-INFO +104 -0
  9. imbi_common-0.1.0/PROGRESS.md +126 -0
  10. imbi_common-0.1.0/README.md +69 -0
  11. imbi_common-0.1.0/compose.yaml +32 -0
  12. imbi_common-0.1.0/docs/adr/0001-imbi-common-library-extraction.md +218 -0
  13. imbi_common-0.1.0/docs/adr/0002-lifespan-composition.md +170 -0
  14. imbi_common-0.1.0/docs/api/auth.md +68 -0
  15. imbi_common-0.1.0/docs/api/blueprints.md +70 -0
  16. imbi_common-0.1.0/docs/api/clickhouse.md +76 -0
  17. imbi_common-0.1.0/docs/api/graph.md +95 -0
  18. imbi_common-0.1.0/docs/api/lifespan.md +68 -0
  19. imbi_common-0.1.0/docs/api/logging.md +63 -0
  20. imbi_common-0.1.0/docs/api/models.md +73 -0
  21. imbi_common-0.1.0/docs/api/plugins.md +92 -0
  22. imbi_common-0.1.0/docs/api/settings.md +40 -0
  23. imbi_common-0.1.0/docs/api/valkey.md +53 -0
  24. imbi_common-0.1.0/docs/code-review-2026-04-22.md +235 -0
  25. imbi_common-0.1.0/docs/configuration.md +177 -0
  26. imbi_common-0.1.0/docs/guides/authentication.md +155 -0
  27. imbi_common-0.1.0/docs/guides/database-setup.md +274 -0
  28. imbi_common-0.1.0/docs/guides/deployment.md +150 -0
  29. imbi_common-0.1.0/docs/guides/lifespan-di.md +273 -0
  30. imbi_common-0.1.0/docs/guides/plugins.md +337 -0
  31. imbi_common-0.1.0/docs/guides/testing.md +383 -0
  32. imbi_common-0.1.0/docs/index.md +89 -0
  33. imbi_common-0.1.0/docs/installation.md +127 -0
  34. imbi_common-0.1.0/docs/quickstart.md +157 -0
  35. imbi_common-0.1.0/justfile +86 -0
  36. imbi_common-0.1.0/mkdocs.yml +88 -0
  37. imbi_common-0.1.0/pyproject.toml +166 -0
  38. imbi_common-0.1.0/src/imbi_common/__init__.py +38 -0
  39. imbi_common-0.1.0/src/imbi_common/auth/__init__.py +0 -0
  40. imbi_common-0.1.0/src/imbi_common/auth/core.py +133 -0
  41. imbi_common-0.1.0/src/imbi_common/auth/encryption.py +213 -0
  42. imbi_common-0.1.0/src/imbi_common/blueprints.py +308 -0
  43. imbi_common-0.1.0/src/imbi_common/clickhouse/__init__.py +163 -0
  44. imbi_common-0.1.0/src/imbi_common/clickhouse/client.py +257 -0
  45. imbi_common-0.1.0/src/imbi_common/clickhouse/privacy.py +171 -0
  46. imbi_common-0.1.0/src/imbi_common/clickhouse/schemata.toml +89 -0
  47. imbi_common-0.1.0/src/imbi_common/graph/__init__.py +61 -0
  48. imbi_common-0.1.0/src/imbi_common/graph/chunk.py +73 -0
  49. imbi_common-0.1.0/src/imbi_common/graph/client.py +781 -0
  50. imbi_common-0.1.0/src/imbi_common/graph/cypher.py +302 -0
  51. imbi_common-0.1.0/src/imbi_common/graph/embeddings.py +131 -0
  52. imbi_common-0.1.0/src/imbi_common/graph/initializer.py +259 -0
  53. imbi_common-0.1.0/src/imbi_common/graph/schemata.toml +283 -0
  54. imbi_common-0.1.0/src/imbi_common/helpers.py +13 -0
  55. imbi_common-0.1.0/src/imbi_common/lifespan.py +215 -0
  56. imbi_common-0.1.0/src/imbi_common/log-config.toml +21 -0
  57. imbi_common-0.1.0/src/imbi_common/logging.py +52 -0
  58. imbi_common-0.1.0/src/imbi_common/models.py +594 -0
  59. imbi_common-0.1.0/src/imbi_common/plugins/__init__.py +90 -0
  60. imbi_common-0.1.0/src/imbi_common/plugins/base.py +347 -0
  61. imbi_common-0.1.0/src/imbi_common/plugins/errors.py +27 -0
  62. imbi_common-0.1.0/src/imbi_common/plugins/registry.py +182 -0
  63. imbi_common-0.1.0/src/imbi_common/plugins/schemas.py +209 -0
  64. imbi_common-0.1.0/src/imbi_common/plugins/templates.py +44 -0
  65. imbi_common-0.1.0/src/imbi_common/py.typed +0 -0
  66. imbi_common-0.1.0/src/imbi_common/scoring/__init__.py +20 -0
  67. imbi_common-0.1.0/src/imbi_common/scoring/attribute.py +55 -0
  68. imbi_common-0.1.0/src/imbi_common/scoring/engine.py +54 -0
  69. imbi_common-0.1.0/src/imbi_common/scoring/history.py +74 -0
  70. imbi_common-0.1.0/src/imbi_common/scoring/models.py +112 -0
  71. imbi_common-0.1.0/src/imbi_common/scoring/policies.py +59 -0
  72. imbi_common-0.1.0/src/imbi_common/server.py +183 -0
  73. imbi_common-0.1.0/src/imbi_common/settings.py +319 -0
  74. imbi_common-0.1.0/src/imbi_common/valkey.py +44 -0
  75. imbi_common-0.1.0/src/imbi_common/versioning.py +87 -0
  76. imbi_common-0.1.0/tests/__init__.py +0 -0
  77. imbi_common-0.1.0/tests/auth/__init__.py +1 -0
  78. imbi_common-0.1.0/tests/auth/test_core.py +101 -0
  79. imbi_common-0.1.0/tests/auth/test_encryption.py +85 -0
  80. imbi_common-0.1.0/tests/auth/test_encryption_class.py +215 -0
  81. imbi_common-0.1.0/tests/clickhouse/__init__.py +1 -0
  82. imbi_common-0.1.0/tests/clickhouse/test_client.py +670 -0
  83. imbi_common-0.1.0/tests/clickhouse/test_init.py +411 -0
  84. imbi_common-0.1.0/tests/clickhouse/test_privacy.py +359 -0
  85. imbi_common-0.1.0/tests/conftest.py +11 -0
  86. imbi_common-0.1.0/tests/test_blueprints.py +1008 -0
  87. imbi_common-0.1.0/tests/test_chunk.py +89 -0
  88. imbi_common-0.1.0/tests/test_cypher.py +490 -0
  89. imbi_common-0.1.0/tests/test_embeddings.py +135 -0
  90. imbi_common-0.1.0/tests/test_graph.py +600 -0
  91. imbi_common-0.1.0/tests/test_helpers.py +25 -0
  92. imbi_common-0.1.0/tests/test_lifespan.py +224 -0
  93. imbi_common-0.1.0/tests/test_logging.py +82 -0
  94. imbi_common-0.1.0/tests/test_models.py +883 -0
  95. imbi_common-0.1.0/tests/test_plugins/__init__.py +0 -0
  96. imbi_common-0.1.0/tests/test_plugins/test_base.py +179 -0
  97. imbi_common-0.1.0/tests/test_plugins/test_errors.py +46 -0
  98. imbi_common-0.1.0/tests/test_plugins/test_registry.py +301 -0
  99. imbi_common-0.1.0/tests/test_plugins/test_schemas.py +206 -0
  100. imbi_common-0.1.0/tests/test_plugins/test_templates.py +60 -0
  101. imbi_common-0.1.0/tests/test_scoring/__init__.py +0 -0
  102. imbi_common-0.1.0/tests/test_scoring/test_attribute.py +124 -0
  103. imbi_common-0.1.0/tests/test_scoring/test_engine.py +135 -0
  104. imbi_common-0.1.0/tests/test_scoring/test_history.py +70 -0
  105. imbi_common-0.1.0/tests/test_scoring/test_models.py +118 -0
  106. imbi_common-0.1.0/tests/test_scoring/test_policies.py +193 -0
  107. imbi_common-0.1.0/tests/test_server.py +193 -0
  108. imbi_common-0.1.0/tests/test_settings.py +242 -0
  109. imbi_common-0.1.0/tests/test_valkey.py +42 -0
  110. imbi_common-0.1.0/tests/test_versioning.py +133 -0
  111. imbi_common-0.1.0/uv.lock +2390 -0
@@ -0,0 +1,53 @@
1
+ name: Deploy Documentation
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ paths:
8
+ - 'docs/**'
9
+ - 'justfile'
10
+ - 'mkdocs.yml'
11
+ - 'pyproject.toml'
12
+ - '.github/workflows/docs.yml'
13
+ workflow_dispatch:
14
+
15
+ permissions:
16
+ contents: read
17
+ pages: write
18
+ id-token: write
19
+
20
+ concurrency:
21
+ group: "pages"
22
+ cancel-in-progress: false
23
+
24
+ jobs:
25
+ build:
26
+ runs-on: ubuntu-latest
27
+ steps:
28
+ - name: Checkout repository
29
+ uses: actions/checkout@v5
30
+ - name: Install just
31
+ uses: extractions/setup-just@v2
32
+ - name: Install uv
33
+ uses: astral-sh/setup-uv@v7
34
+ with:
35
+ python-version: 3.14
36
+ enable-cache: true
37
+ - name: Build documentation
38
+ run: just docs
39
+ - name: Upload artifact
40
+ uses: actions/upload-pages-artifact@v3
41
+ with:
42
+ path: ./site
43
+
44
+ deploy:
45
+ environment:
46
+ name: github-pages
47
+ url: ${{ steps.deployment.outputs.page_url }}
48
+ runs-on: ubuntu-latest
49
+ needs: build
50
+ steps:
51
+ - name: Deploy to GitHub Pages
52
+ id: deployment
53
+ uses: actions/deploy-pages@v4
@@ -0,0 +1,45 @@
1
+ name: Publish to PyPI
2
+ on:
3
+ release:
4
+ types: [published]
5
+
6
+ permissions:
7
+ id-token: write
8
+
9
+ jobs:
10
+ build:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - name: Checkout repository
14
+ uses: actions/checkout@v6
15
+ with:
16
+ fetch-depth: 0
17
+
18
+ - name: Install uv
19
+ uses: astral-sh/setup-uv@v5
20
+
21
+ - name: Set up Python
22
+ run: uv python install 3.14
23
+
24
+ - name: Build
25
+ run: uv build
26
+
27
+ - name: Upload dist
28
+ uses: actions/upload-artifact@v4
29
+ with:
30
+ name: dist
31
+ path: dist/
32
+
33
+ publish:
34
+ needs: build
35
+ runs-on: ubuntu-latest
36
+ environment: pypi
37
+ steps:
38
+ - name: Download dist
39
+ uses: actions/download-artifact@v4
40
+ with:
41
+ name: dist
42
+ path: dist/
43
+
44
+ - name: Publish package
45
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,54 @@
1
+ name: Testing
2
+ on:
3
+ pull_request:
4
+ push:
5
+ branches: [ "main" ]
6
+ paths-ignore:
7
+ - 'docs/**'
8
+ - '*.md'
9
+ tags-ignore: [ "*" ]
10
+
11
+ jobs:
12
+ lint:
13
+ name: "Static Analysis"
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - name: Checkout repository
17
+ uses: actions/checkout@v5
18
+ - name: Install just
19
+ uses: extractions/setup-just@v2
20
+ with:
21
+ just-version: '1.47.1'
22
+ - name: Install uv
23
+ uses: astral-sh/setup-uv@v7
24
+ with:
25
+ enable-cache: true
26
+ - name: Run linters
27
+ run: just lint
28
+
29
+ test:
30
+ name: "Automated Tests"
31
+ runs-on: ubuntu-latest
32
+ strategy:
33
+ fail-fast: false
34
+ matrix:
35
+ python: [ "3.14" ]
36
+ steps:
37
+ - name: Checkout repository
38
+ uses: actions/checkout@v5
39
+ - name: Install just
40
+ uses: extractions/setup-just@v2
41
+ with:
42
+ just-version: '1.47.1'
43
+ - name: Install uv
44
+ uses: astral-sh/setup-uv@v7
45
+ with:
46
+ python-version: "${{ matrix.python }}"
47
+ enable-cache: true
48
+ - name: Test with python ${{ matrix.python }}
49
+ run: just test
50
+ - name: Upload Coverage
51
+ uses: codecov/codecov-action@v5
52
+ with:
53
+ files: ./build/coverage.xml
54
+ flags: unittests
@@ -0,0 +1,10 @@
1
+ .*
2
+ /build
3
+ /dist
4
+ /docs/superpowers
5
+ /public
6
+ /site
7
+ VERSION
8
+ !/.github
9
+ !/.gitignore
10
+ !/.pre-commit-config.yaml
@@ -0,0 +1,36 @@
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v5.0.0
4
+ hooks:
5
+ - id: trailing-whitespace
6
+ - id: end-of-file-fixer
7
+ - id: check-yaml
8
+ - id: check-added-large-files
9
+ - id: check-merge-conflict
10
+ - id: check-toml
11
+ - id: debug-statements
12
+
13
+ - repo: https://github.com/astral-sh/ruff-pre-commit
14
+ rev: v0.14.6
15
+ hooks:
16
+ - id: ruff-check
17
+ args: [--fix]
18
+ - id: ruff-format
19
+
20
+ - repo: https://github.com/tombi-toml/tombi-pre-commit
21
+ rev: v0.7.25
22
+ hooks:
23
+ - id: tombi-format
24
+
25
+ - repo: local
26
+ hooks:
27
+ - id: mypy
28
+ name: mypy
29
+ language: system
30
+ types: [python]
31
+ pass_filenames: false
32
+ entry: uv
33
+ args:
34
+ - run
35
+ - mypy
36
+ - src
@@ -0,0 +1,75 @@
1
+ # AGENTS.md
2
+
3
+ This file provides guidance to Agents (eg, Claude Code) when working with code in this repository.
4
+
5
+ ## Commands
6
+
7
+ This project uses `just` as a task runner and `uv` for Python package management.
8
+
9
+ ```bash
10
+ just setup # Install dependencies and pre-commit hooks
11
+ just docker # Bootstrap the docker environment and setup database schema
12
+ just test # Run full test suite with coverage (requires Docker)
13
+ just test <file> # Run specific test file(s) without coverage
14
+ just lint # Run all linters via pre-commit
15
+ just format # Reformat code (ruff + tombi)
16
+ just docs # Generate documentation into `site`
17
+ just clean # Tear down Docker, remove .env and build artifacts
18
+ just real-clean # Remove .venv and all caches (prompts for confirmation)
19
+ ```
20
+
21
+ The `just test` target automatically starts Docker services (PostgreSQL with AGE + ClickHouse), creates a `.env` file with connection URLs, and runs coverage. When running specific files, the `.env` must already exist or env vars must be set.
22
+
23
+ Running individual tests (e.g., during iteration):
24
+
25
+ ```bash
26
+ just test tests/path/to/test_file.py
27
+ just test tests/path/to/test_file.py::TestClass::test_method
28
+ ```
29
+
30
+ ## Architecture
31
+
32
+ `imbi-common` is a shared library consumed by `imbi-api`, `imbi-gateway`, and `imbi-mcp`. Source lives in `src/imbi_common/`, tests in `tests/`.
33
+
34
+ ### Module map
35
+
36
+ | Module | Purpose |
37
+ | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
38
+ | `graph/` | Apache AGE subpackage — re-exports `Graph`, `Pool`, `SearchResult`, `parse_agtype`, `graph_lifespan` from `__init__.py` |
39
+ | `graph/client.py` | `Graph` class with psycopg v3 pool and high-level methods (`create`, `delete`, `match`, `merge`, `execute`) |
40
+ | `graph/cypher.py` | Cypher query generation from Pydantic models — `create`, `delete`, `match`, `merge` return `Statement` named tuples with templates and parameters |
41
+ | `graph/embeddings.py`| fastembed `TextEmbedding` wrapper for generating vector embeddings |
42
+ | `graph/chunk.py` | Text chunking utilities for embedding pipelines |
43
+ | `graph/initializer.py`| Graph database initialization from `schemata.toml` — creates extensions, graphs, vlabels, indexes, embeddings table, and functions |
44
+ | `clickhouse/` | ClickHouse async client singleton with `query()` / `insert()`, schema setup via `schemata.toml`, and privacy utilities |
45
+ | `valkey.py` | Valkey async client integration — exposes `valkey_lifespan` and `Client` (FastAPI DI alias) wrapping `valkey.asyncio.Valkey` |
46
+ | `models.py` | Pydantic domain models (`Project`, `Team`, `Environment`, `Organization`, `ProjectType`, `Blueprint`) with `Edge` dataclass metadata for graph relationships |
47
+ | `blueprints.py` | Runtime schema extension system — loads `Blueprint` nodes from the graph and uses `pydantic.create_model` to dynamically add fields to existing models |
48
+ | `settings.py` | Pydantic Settings classes (`Postgres`, `Clickhouse`, `Valkey`, `Auth`) plus `Configuration` for TOML file loading. Settings pick up env vars with prefixes `POSTGRES_`, `CLICKHOUSE_`, `VALKEY_`, `IMBI_AUTH_` |
49
+ | `auth/core.py` | JWT creation (`create_access_token`, `create_refresh_token`) and verification (`verify_token`) |
50
+ | `auth/encryption.py` | Fernet symmetric encryption for sensitive tokens via `TokenEncryption` singleton; module-level `encrypt_token`/`decrypt_token` helpers |
51
+ | `server.py` | Typer/uvicorn `serve()` command and `bind_entrypoint()` helper for building service CLIs |
52
+ | `logging.py` | Logging configuration loader using `log-config.toml` |
53
+ | `helpers.py` | Small utility functions |
54
+
55
+ ### Key patterns
56
+
57
+ **Singletons**: `Clickhouse.get_instance()`, `TokenEncryption.get_instance()`, and `settings.get_auth_settings()` all use class-level singletons. Tests that need clean state must reset them explicitly (e.g., `TokenEncryption.reset_instance()`). `Graph` is instantiated directly (no singleton).
58
+
59
+ **Graph + edges**: Models use `typing.Annotated` with `models.Edge(rel_type=..., direction=...)` metadata to declare graph relationships. `graph/client.py` tries `model_validate()` first when deserializing raw node data; if that raises `ValidationError` (e.g. due to missing edge fields stored as separate relationships), it falls back to `model_construct()`.
60
+
61
+ **Blueprint system**: `blueprints.get_model(database, MyModel)` accepts a `Graph` instance and a model class, fetches `Blueprint` nodes from the graph whose `type` matches the model class name, then calls `pydantic.create_model` to return a dynamically extended subclass.
62
+
63
+ **Settings loading order**: Each `BaseSettings` subclass reads from `.env` file and environment variables with its prefix. `Configuration` additionally supports `config.toml` checked in order: `./config.toml` → `~/.config/imbi/config.toml` → `/etc/imbi/config.toml`.
64
+
65
+ **ClickHouse schema**: DDL is defined in `src/imbi_common/clickhouse/schemata.toml` and executed via `Clickhouse.setup_schema()` (called explicitly during setup, not on every startup).
66
+
67
+ **PostgreSQL schema**: Database init scripts live in `schema/postgres/` and are mounted into the Docker container's `/docker-entrypoint-initdb.d/`.
68
+
69
+ ## Code style
70
+
71
+ - Line length: 79 characters
72
+ - Quote style: single quotes
73
+ - Type checking: strict (basedpyright + mypy)
74
+ - Test coverage minimum: 90%
75
+ - `ruff` rules include bandit (`S`), but `S` rules are disabled in test files
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2026, AWeber
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,104 @@
1
+ Metadata-Version: 2.4
2
+ Name: imbi-common
3
+ Version: 0.1.0
4
+ Summary: Shared library for the Imbi ecosystem providing core data access, authentication primitives, and domain models
5
+ Author-email: "Gavin M. Roy" <gavinr@aweber.com>, Dave Shawley <daves@aweber.com>
6
+ License-Expression: BSD-3-Clause
7
+ License-File: LICENSE
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Natural Language :: English
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.14
14
+ Requires-Python: >=3.14
15
+ Requires-Dist: cryptography>=42.0.4
16
+ Requires-Dist: jsonschema-models
17
+ Requires-Dist: markdown-it-py>=3.0
18
+ Requires-Dist: nanoid>=2.0.0
19
+ Requires-Dist: orjson
20
+ Requires-Dist: pydantic-settings
21
+ Requires-Dist: pydantic[email]>=2.0
22
+ Requires-Dist: pyjwt>=2.10.1
23
+ Requires-Dist: python-slugify
24
+ Requires-Dist: typer>=0.21.1
25
+ Provides-Extra: databases
26
+ Requires-Dist: clickhouse-connect[async]==0.12rc1; extra == 'databases'
27
+ Requires-Dist: fastembed>=0.6; extra == 'databases'
28
+ Requires-Dist: pgvector>=0.3; extra == 'databases'
29
+ Requires-Dist: psycopg[binary,pool]>=3.3; extra == 'databases'
30
+ Requires-Dist: valkey>=6; extra == 'databases'
31
+ Provides-Extra: server
32
+ Requires-Dist: fastapi>=0.115.0; extra == 'server'
33
+ Requires-Dist: uvicorn[standard]>=0.40.0; extra == 'server'
34
+ Description-Content-Type: text/markdown
35
+
36
+ # Imbi Common Library
37
+
38
+ Shared library for the Imbi ecosystem providing core data access, authentication primitives, and domain models.
39
+
40
+ ## Overview
41
+
42
+ `imbi-common` is a Python library that provides common functionality for all Imbi services including:
43
+
44
+ - **Database Clients**: Apache AGE/PostgreSQL (graph database) and ClickHouse (analytics database) with connection management
45
+ - **Domain Models**: Pydantic models for Projects, Organizations, Teams, Environments, ProjectTypes, and more
46
+ - **Authentication**: JWT token creation/verification, token encryption
47
+ - **Configuration**: Pydantic Settings-based configuration management with TOML file support
48
+ - **Blueprint System**: Dynamic schema extension system for runtime model customization
49
+ - **Logging**: Consistent logging configuration across all services
50
+
51
+ ## Services Using imbi-common
52
+
53
+ - **imbi-api**: Main API service for service management
54
+ - **imbi-gateway**: Webhook processing service
55
+ - **imbi-mcp**: Model Context Protocol server for Claude integration
56
+
57
+ ## Documentation
58
+
59
+ Full documentation is available at: [https://aweber-imbi.github.io/imbi-common/](https://aweber-imbi.github.io/imbi-common/)
60
+
61
+ ## Development
62
+
63
+ ### Prerequisites
64
+
65
+ - [just](https://just.systems/man/en/packages.html) — task runner
66
+ - [uv](https://docs.astral.sh/uv/getting-started/installation/) — Python package manager
67
+
68
+ ### Setup
69
+
70
+ ```bash
71
+ # Clone the repository
72
+ git clone https://github.com/AWeber-Imbi/imbi-common.git
73
+ cd imbi-common
74
+
75
+ # Install dependencies and pre-commit hooks
76
+ just setup
77
+ ```
78
+
79
+ ### Running Tests
80
+
81
+ ```bash
82
+ just test # Full test suite with coverage (requires Docker)
83
+ just test <file> # Run specific test file(s)
84
+ ```
85
+
86
+ ### Code Quality
87
+
88
+ ```bash
89
+ just lint # Run all linters
90
+ just format # Reformat code
91
+ ```
92
+
93
+ ## License
94
+
95
+ BSD-3-Clause - See [LICENSE](LICENSE) file for details.
96
+
97
+ ## Authors
98
+
99
+ - Dave Shawley <daves@aweber.com>
100
+ - Gavin M. Roy <gavinr@aweber.com>
101
+
102
+ ## Contributing
103
+
104
+ Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
@@ -0,0 +1,126 @@
1
+ # imbi-common Creation Progress
2
+
3
+ ## Completed Tasks ✅
4
+
5
+ ### 1. Repository Structure
6
+ - ✅ Created `src/imbi_common/` package structure (simple package with underscore)
7
+ - ✅ Created subdirectories: `neo4j/`, `clickhouse/`, `auth/`
8
+ - ✅ Created test structure: `tests/` with matching subdirectories
9
+ - ✅ Created docs structure: `docs/api/`, `docs/guides/`, `docs/adr/`
10
+ - ✅ Created `.github/workflows/` for CI/CD
11
+
12
+ ### 2. Configuration Files
13
+ - ✅ `pyproject.toml` - Hatchling build system matching imbi-api patterns
14
+ - ✅ `.gitignore` - Copied from imbi-api
15
+ - ✅ `.pre-commit-config.yaml` - Ruff, mypy configuration
16
+ - ✅ `LICENSE` - BSD-3-Clause
17
+ - ✅ `README.md` - Comprehensive project overview
18
+
19
+ ### 3. Extracted Modules
20
+ - ✅ `settings.py` - Complete configuration management (standalone)
21
+ - ✅ `neo4j/` - Client, constants, public API (imports updated to imbi_common)
22
+ - ✅ `clickhouse/` - Client, privacy utilities, base schemas (imports updated)
23
+ - ✅ `models.py` - All core domain and auth models (imports updated)
24
+ - ✅ `blueprints.py` - Blueprint system (imports updated)
25
+ - ✅ `auth/core.py` - Password hashing, JWT (imports updated)
26
+ - ✅ `auth/encryption.py` - Token encryption (imports updated)
27
+ - ✅ `logging.py` - Log configuration with dictConfig support (new module)
28
+ - ✅ `log-config.toml` - Logging configuration
29
+
30
+ ### 4. Base Schemas
31
+ - ✅ Created minimal `clickhouse/schemata.toml` with only shared tables:
32
+ - `session_activity` - Used by API and MCP
33
+ - `mfa_events` - MFA tracking
34
+ - ✅ API-specific schemas (api_key_usage, rate_limit_events, email_audit) remain in imbi-api
35
+
36
+ ### 5. Code Quality
37
+ - ✅ All imports updated from `imbi` to `imbi_common`
38
+ - ✅ Fixed version import in neo4j client
39
+ - ✅ All ruff checks passing (no linting errors)
40
+ - ✅ Line length issues fixed (79 character limit)
41
+ - ✅ Proper module imports following project conventions
42
+
43
+ ### 6. Public API
44
+ - ✅ Created `__init__.py` with proper exports
45
+ - ✅ Version string: `0.1.0`
46
+ - ✅ Exposes all main modules: settings, models, neo4j, clickhouse, auth, blueprints, logging
47
+
48
+ ## Next Steps 📋
49
+
50
+ ### Documentation
51
+ - [ ] Set up MkDocs with mkdocs.yml
52
+ - [ ] Write docs/index.md (home page)
53
+ - [ ] Write docs/installation.md
54
+ - [ ] Write docs/quickstart.md
55
+ - [ ] Write docs/configuration.md
56
+ - [ ] Write API reference docs (docs/api/*.md)
57
+ - [ ] Write guides (docs/guides/*.md)
58
+ - [ ] Create ADR 0001 documenting all decisions
59
+
60
+ ### Testing
61
+ - [ ] Create unittest test structure
62
+ - [ ] Write unit tests for settings module
63
+ - [ ] Write unit tests for auth module
64
+ - [ ] Write unit tests for logging module
65
+ - [ ] Write integration tests for neo4j (with Docker)
66
+ - [ ] Write integration tests for clickhouse (with Docker)
67
+ - [ ] Create test base classes (Neo4jTestCase, ClickHouseTestCase)
68
+
69
+ ### CI/CD
70
+ - [ ] Create .github/workflows/test.yml (test, lint, type check)
71
+ - [ ] Create .github/workflows/docs.yml (build and deploy to GitHub Pages)
72
+ - [ ] Create .github/workflows/publish.yml (publish to PyPI on release)
73
+
74
+ ### Final Steps
75
+ - [ ] Install dependencies with uv
76
+ - [ ] Run full test suite
77
+ - [ ] Build package: `python -m build`
78
+ - [ ] Test installation
79
+ - [ ] Publish v0.1.0
80
+
81
+ ## File Structure Summary
82
+
83
+ ```
84
+ imbi-common/
85
+ ├── src/imbi_common/
86
+ │ ├── __init__.py ✅ Public API
87
+ │ ├── py.typed ✅ Type hints marker
88
+ │ ├── settings.py ✅ Configuration
89
+ │ ├── models.py ✅ Domain models
90
+ │ ├── blueprints.py ✅ Blueprint system
91
+ │ ├── logging.py ✅ Log configuration
92
+ │ ├── log-config.toml ✅ Logging config
93
+ │ ├── neo4j/
94
+ │ │ ├── __init__.py ✅ Public API
95
+ │ │ ├── client.py ✅ Neo4j client
96
+ │ │ └── constants.py ✅ Indexes/constraints
97
+ │ ├── clickhouse/
98
+ │ │ ├── __init__.py ✅ Public API
99
+ │ │ ├── client.py ✅ ClickHouse client
100
+ │ │ ├── privacy.py ✅ GDPR utilities
101
+ │ │ └── schemata.toml ✅ Base schemas
102
+ │ └── auth/
103
+ │ ├── __init__.py ✅ Auth package
104
+ │ ├── core.py ✅ Password/JWT
105
+ │ └── encryption.py ✅ Token encryption
106
+ ├── tests/ ✅ Test structure created
107
+ ├── docs/ ✅ Docs structure created
108
+ ├── pyproject.toml ✅ Build configuration
109
+ ├── README.md ✅ Project overview
110
+ ├── LICENSE ✅ BSD-3-Clause
111
+ ├── .gitignore ✅ From imbi-api
112
+ └── .pre-commit-config.yaml ✅ From imbi-api
113
+ ```
114
+
115
+ ## Import Pattern
116
+
117
+ All imports updated to use `imbi_common`:
118
+
119
+ ```python
120
+ from imbi_common import settings, models, neo4j, clickhouse, auth, blueprints, logging
121
+ from imbi_common.auth import core, encryption
122
+ ```
123
+
124
+ ## Status: ~40% Complete
125
+
126
+ Core extraction is done. Documentation and testing remain.
@@ -0,0 +1,69 @@
1
+ # Imbi Common Library
2
+
3
+ Shared library for the Imbi ecosystem providing core data access, authentication primitives, and domain models.
4
+
5
+ ## Overview
6
+
7
+ `imbi-common` is a Python library that provides common functionality for all Imbi services including:
8
+
9
+ - **Database Clients**: Apache AGE/PostgreSQL (graph database) and ClickHouse (analytics database) with connection management
10
+ - **Domain Models**: Pydantic models for Projects, Organizations, Teams, Environments, ProjectTypes, and more
11
+ - **Authentication**: JWT token creation/verification, token encryption
12
+ - **Configuration**: Pydantic Settings-based configuration management with TOML file support
13
+ - **Blueprint System**: Dynamic schema extension system for runtime model customization
14
+ - **Logging**: Consistent logging configuration across all services
15
+
16
+ ## Services Using imbi-common
17
+
18
+ - **imbi-api**: Main API service for service management
19
+ - **imbi-gateway**: Webhook processing service
20
+ - **imbi-mcp**: Model Context Protocol server for Claude integration
21
+
22
+ ## Documentation
23
+
24
+ Full documentation is available at: [https://aweber-imbi.github.io/imbi-common/](https://aweber-imbi.github.io/imbi-common/)
25
+
26
+ ## Development
27
+
28
+ ### Prerequisites
29
+
30
+ - [just](https://just.systems/man/en/packages.html) — task runner
31
+ - [uv](https://docs.astral.sh/uv/getting-started/installation/) — Python package manager
32
+
33
+ ### Setup
34
+
35
+ ```bash
36
+ # Clone the repository
37
+ git clone https://github.com/AWeber-Imbi/imbi-common.git
38
+ cd imbi-common
39
+
40
+ # Install dependencies and pre-commit hooks
41
+ just setup
42
+ ```
43
+
44
+ ### Running Tests
45
+
46
+ ```bash
47
+ just test # Full test suite with coverage (requires Docker)
48
+ just test <file> # Run specific test file(s)
49
+ ```
50
+
51
+ ### Code Quality
52
+
53
+ ```bash
54
+ just lint # Run all linters
55
+ just format # Reformat code
56
+ ```
57
+
58
+ ## License
59
+
60
+ BSD-3-Clause - See [LICENSE](LICENSE) file for details.
61
+
62
+ ## Authors
63
+
64
+ - Dave Shawley <daves@aweber.com>
65
+ - Gavin M. Roy <gavinr@aweber.com>
66
+
67
+ ## Contributing
68
+
69
+ Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
@@ -0,0 +1,32 @@
1
+ services:
2
+ clickhouse:
3
+ image: clickhouse/clickhouse-server:latest
4
+ ports:
5
+ - "8123"
6
+ - "9000"
7
+ environment:
8
+ - CLICKHOUSE_DB=default
9
+ - CLICKHOUSE_USER=default
10
+ - CLICKHOUSE_PASSWORD=password
11
+ healthcheck:
12
+ test: ["CMD-SHELL", "wget -qO- http://localhost:8123/ping | grep -q 'Ok'"]
13
+
14
+ postgres:
15
+ image: ghcr.io/aweber-imbi/postgres:latest
16
+ ports:
17
+ - "5432"
18
+ environment:
19
+ POSTGRES_PASSWORD: secret
20
+ POSTGRES_DB: imbi
21
+ healthcheck:
22
+ test: ["CMD-SHELL", "pg_isready -U postgres"]
23
+
24
+ valkey:
25
+ image: valkey/valkey:8-alpine
26
+ ports:
27
+ - "6379"
28
+ healthcheck:
29
+ test: ["CMD-SHELL", "valkey-cli ping"]
30
+ interval: 5s
31
+ timeout: 5s
32
+ retries: 10