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.
- imbi_common-0.1.0/.github/workflows/docs.yml +53 -0
- imbi_common-0.1.0/.github/workflows/publish.yml +45 -0
- imbi_common-0.1.0/.github/workflows/test.yml +54 -0
- imbi_common-0.1.0/.gitignore +10 -0
- imbi_common-0.1.0/.pre-commit-config.yaml +36 -0
- imbi_common-0.1.0/CLAUDE.md +75 -0
- imbi_common-0.1.0/LICENSE +28 -0
- imbi_common-0.1.0/PKG-INFO +104 -0
- imbi_common-0.1.0/PROGRESS.md +126 -0
- imbi_common-0.1.0/README.md +69 -0
- imbi_common-0.1.0/compose.yaml +32 -0
- imbi_common-0.1.0/docs/adr/0001-imbi-common-library-extraction.md +218 -0
- imbi_common-0.1.0/docs/adr/0002-lifespan-composition.md +170 -0
- imbi_common-0.1.0/docs/api/auth.md +68 -0
- imbi_common-0.1.0/docs/api/blueprints.md +70 -0
- imbi_common-0.1.0/docs/api/clickhouse.md +76 -0
- imbi_common-0.1.0/docs/api/graph.md +95 -0
- imbi_common-0.1.0/docs/api/lifespan.md +68 -0
- imbi_common-0.1.0/docs/api/logging.md +63 -0
- imbi_common-0.1.0/docs/api/models.md +73 -0
- imbi_common-0.1.0/docs/api/plugins.md +92 -0
- imbi_common-0.1.0/docs/api/settings.md +40 -0
- imbi_common-0.1.0/docs/api/valkey.md +53 -0
- imbi_common-0.1.0/docs/code-review-2026-04-22.md +235 -0
- imbi_common-0.1.0/docs/configuration.md +177 -0
- imbi_common-0.1.0/docs/guides/authentication.md +155 -0
- imbi_common-0.1.0/docs/guides/database-setup.md +274 -0
- imbi_common-0.1.0/docs/guides/deployment.md +150 -0
- imbi_common-0.1.0/docs/guides/lifespan-di.md +273 -0
- imbi_common-0.1.0/docs/guides/plugins.md +337 -0
- imbi_common-0.1.0/docs/guides/testing.md +383 -0
- imbi_common-0.1.0/docs/index.md +89 -0
- imbi_common-0.1.0/docs/installation.md +127 -0
- imbi_common-0.1.0/docs/quickstart.md +157 -0
- imbi_common-0.1.0/justfile +86 -0
- imbi_common-0.1.0/mkdocs.yml +88 -0
- imbi_common-0.1.0/pyproject.toml +166 -0
- imbi_common-0.1.0/src/imbi_common/__init__.py +38 -0
- imbi_common-0.1.0/src/imbi_common/auth/__init__.py +0 -0
- imbi_common-0.1.0/src/imbi_common/auth/core.py +133 -0
- imbi_common-0.1.0/src/imbi_common/auth/encryption.py +213 -0
- imbi_common-0.1.0/src/imbi_common/blueprints.py +308 -0
- imbi_common-0.1.0/src/imbi_common/clickhouse/__init__.py +163 -0
- imbi_common-0.1.0/src/imbi_common/clickhouse/client.py +257 -0
- imbi_common-0.1.0/src/imbi_common/clickhouse/privacy.py +171 -0
- imbi_common-0.1.0/src/imbi_common/clickhouse/schemata.toml +89 -0
- imbi_common-0.1.0/src/imbi_common/graph/__init__.py +61 -0
- imbi_common-0.1.0/src/imbi_common/graph/chunk.py +73 -0
- imbi_common-0.1.0/src/imbi_common/graph/client.py +781 -0
- imbi_common-0.1.0/src/imbi_common/graph/cypher.py +302 -0
- imbi_common-0.1.0/src/imbi_common/graph/embeddings.py +131 -0
- imbi_common-0.1.0/src/imbi_common/graph/initializer.py +259 -0
- imbi_common-0.1.0/src/imbi_common/graph/schemata.toml +283 -0
- imbi_common-0.1.0/src/imbi_common/helpers.py +13 -0
- imbi_common-0.1.0/src/imbi_common/lifespan.py +215 -0
- imbi_common-0.1.0/src/imbi_common/log-config.toml +21 -0
- imbi_common-0.1.0/src/imbi_common/logging.py +52 -0
- imbi_common-0.1.0/src/imbi_common/models.py +594 -0
- imbi_common-0.1.0/src/imbi_common/plugins/__init__.py +90 -0
- imbi_common-0.1.0/src/imbi_common/plugins/base.py +347 -0
- imbi_common-0.1.0/src/imbi_common/plugins/errors.py +27 -0
- imbi_common-0.1.0/src/imbi_common/plugins/registry.py +182 -0
- imbi_common-0.1.0/src/imbi_common/plugins/schemas.py +209 -0
- imbi_common-0.1.0/src/imbi_common/plugins/templates.py +44 -0
- imbi_common-0.1.0/src/imbi_common/py.typed +0 -0
- imbi_common-0.1.0/src/imbi_common/scoring/__init__.py +20 -0
- imbi_common-0.1.0/src/imbi_common/scoring/attribute.py +55 -0
- imbi_common-0.1.0/src/imbi_common/scoring/engine.py +54 -0
- imbi_common-0.1.0/src/imbi_common/scoring/history.py +74 -0
- imbi_common-0.1.0/src/imbi_common/scoring/models.py +112 -0
- imbi_common-0.1.0/src/imbi_common/scoring/policies.py +59 -0
- imbi_common-0.1.0/src/imbi_common/server.py +183 -0
- imbi_common-0.1.0/src/imbi_common/settings.py +319 -0
- imbi_common-0.1.0/src/imbi_common/valkey.py +44 -0
- imbi_common-0.1.0/src/imbi_common/versioning.py +87 -0
- imbi_common-0.1.0/tests/__init__.py +0 -0
- imbi_common-0.1.0/tests/auth/__init__.py +1 -0
- imbi_common-0.1.0/tests/auth/test_core.py +101 -0
- imbi_common-0.1.0/tests/auth/test_encryption.py +85 -0
- imbi_common-0.1.0/tests/auth/test_encryption_class.py +215 -0
- imbi_common-0.1.0/tests/clickhouse/__init__.py +1 -0
- imbi_common-0.1.0/tests/clickhouse/test_client.py +670 -0
- imbi_common-0.1.0/tests/clickhouse/test_init.py +411 -0
- imbi_common-0.1.0/tests/clickhouse/test_privacy.py +359 -0
- imbi_common-0.1.0/tests/conftest.py +11 -0
- imbi_common-0.1.0/tests/test_blueprints.py +1008 -0
- imbi_common-0.1.0/tests/test_chunk.py +89 -0
- imbi_common-0.1.0/tests/test_cypher.py +490 -0
- imbi_common-0.1.0/tests/test_embeddings.py +135 -0
- imbi_common-0.1.0/tests/test_graph.py +600 -0
- imbi_common-0.1.0/tests/test_helpers.py +25 -0
- imbi_common-0.1.0/tests/test_lifespan.py +224 -0
- imbi_common-0.1.0/tests/test_logging.py +82 -0
- imbi_common-0.1.0/tests/test_models.py +883 -0
- imbi_common-0.1.0/tests/test_plugins/__init__.py +0 -0
- imbi_common-0.1.0/tests/test_plugins/test_base.py +179 -0
- imbi_common-0.1.0/tests/test_plugins/test_errors.py +46 -0
- imbi_common-0.1.0/tests/test_plugins/test_registry.py +301 -0
- imbi_common-0.1.0/tests/test_plugins/test_schemas.py +206 -0
- imbi_common-0.1.0/tests/test_plugins/test_templates.py +60 -0
- imbi_common-0.1.0/tests/test_scoring/__init__.py +0 -0
- imbi_common-0.1.0/tests/test_scoring/test_attribute.py +124 -0
- imbi_common-0.1.0/tests/test_scoring/test_engine.py +135 -0
- imbi_common-0.1.0/tests/test_scoring/test_history.py +70 -0
- imbi_common-0.1.0/tests/test_scoring/test_models.py +118 -0
- imbi_common-0.1.0/tests/test_scoring/test_policies.py +193 -0
- imbi_common-0.1.0/tests/test_server.py +193 -0
- imbi_common-0.1.0/tests/test_settings.py +242 -0
- imbi_common-0.1.0/tests/test_valkey.py +42 -0
- imbi_common-0.1.0/tests/test_versioning.py +133 -0
- 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,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
|