Metadata-Version: 2.4
Name: lattice-meetbot-admin
Version: 0.2.0
Summary: Mountable FastAPI admin router for lattice-meetbot captures. Constructor-DI, MeetbotAdminRepo protocol, SQLite reference impl.
Author: CodeWarrior4Life
License: Apache-2.0
Project-URL: Homepage, https://github.com/CodeWarrior4Life/lattice-meetbot-admin
Project-URL: Issues, https://github.com/CodeWarrior4Life/lattice-meetbot-admin/issues
Keywords: lattice,meeting,admin,transcription,diarization,personas
Classifier: Development Status :: 4 - Beta
Classifier: Framework :: FastAPI
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
Classifier: Topic :: Office/Business :: Groupware
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: fastapi>=0.110
Requires-Dist: pydantic>=2.0
Requires-Dist: pydantic-settings>=2.0
Requires-Dist: httpx>=0.27
Requires-Dist: python-multipart>=0.0.9
Requires-Dist: sqlalchemy>=2.0
Requires-Dist: alembic>=1.13
Requires-Dist: typer>=0.12
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
Requires-Dist: pytest-cov>=4.0; extra == "dev"
Requires-Dist: ruff>=0.1.0; extra == "dev"
Requires-Dist: mypy>=1.5; extra == "dev"
Requires-Dist: uvicorn>=0.27; extra == "dev"
Requires-Dist: httpx>=0.27; extra == "dev"
Requires-Dist: fakeredis>=2.21; extra == "dev"
Provides-Extra: server
Requires-Dist: uvicorn[standard]>=0.27; extra == "server"
Provides-Extra: queue
Requires-Dist: rq>=1.16; extra == "queue"
Requires-Dist: redis>=5.0; extra == "queue"
Provides-Extra: chat
Requires-Dist: anthropic>=0.40; extra == "chat"
Dynamic: license-file

# lattice-meetbot-admin

Mountable FastAPI admin router for [lattice-meetbot](https://github.com/CodeWarrior4Life/lattice-meetbot) captures.

## Installation

```bash
pip install lattice-meetbot-admin
```

With dev server support:

```bash
pip install 'lattice-meetbot-admin[server]'
```

Optional extras for v0.2 features:

```bash
# Background workers (rq + redis) -- required for /webhooks/capture-complete + worker CLI
pip install 'lattice-meetbot-admin[queue]'

# Chat surface (anthropic SDK) -- required if you wire a real BrainClient that proxies to Claude
pip install 'lattice-meetbot-admin[chat]'

# All-in-one
pip install 'lattice-meetbot-admin[server,queue,chat]'
```

## Quick Start

### Mount into a FastAPI host

```python
from fastapi import FastAPI
from lattice_meetbot_admin import create_router, MeetbotAdminConfig

config = MeetbotAdminConfig(
    db_url="sqlite:///./meetbot_admin.db",
    # auth_dependency=require_admin_auth,  # optional: your FastAPI auth callable
)

app = FastAPI()
app.include_router(create_router(config), prefix="/api/meetbot-admin")
```

Then hit `http://localhost:8000/api/meetbot-admin/health` to confirm it's live.

### Dev server (standalone)

```bash
lattice-meetbot-admin dev-server --db-url sqlite:///./meetbot_admin.db
# API at http://127.0.0.1:5557/api/meetbot-admin/docs
```

## Architecture

`lattice-meetbot-admin` is a **constructor-DI** package -- no global state. Pass your config once at mount time:

- `MeetbotAdminConfig` -- Pydantic v2 settings model (env-var overrides via `MEETBOT_ADMIN_*` prefix)
- `MeetbotAdminRepo` -- `typing.Protocol`; implement against your storage backend or use the bundled `SqliteMeetbotAdminRepo`
- `create_router(config, repo=...)` -- returns an `APIRouter`; mount under any prefix
- `create_admin_app(config, repo=...)` -- returns a `FastAPI` sub-application for `app.mount()`

## REST API

### Core (v0.1)

| Method | Path | Description |
|--------|------|-------------|
| GET | `/health` | Health check (returns version + 5 feature flags) |
| GET | `/meetings` | List meetings (paginated, filterable) |
| GET | `/meetings/{id}` | Meeting detail (segments + speakers) |
| GET | `/meetings/{id}/segments` | Transcript segments |
| GET | `/meetings/{id}/speakers` | Per-speaker stats |
| GET | `/personas` | List personas |
| GET | `/personas/autocomplete?q=` | Ranked autocomplete |
| GET | `/personas/{name}` | Persona detail |
| PATCH | `/personas/{name}` | Update persona fields |
| GET | `/voicenotes` | List voicenote profiles |
| GET | `/voicenotes/{persona_name}` | Voicenote profile |
| PUT | `/voicenotes/{persona_name}` | Upsert voicenote (idempotent) |

### v0.2 (Phase 1)

All v0.2 routes are gated behind feature flags + auth (same `auth_dependency`
as core routes). A route returns `503` when its feature flag is off or its
required collaborator (BrainClient, TaskQueue, ffmpeg) is missing.

| Method | Path | Description | 503 gate |
|--------|------|-------------|----------|
| POST | `/chat` | BrainClient proxy (retrieval + Q&A) | `enable_chat=False` OR `brain_client is None` |
| POST | `/search` | FTS5 segment search (Sqlite) / linear scan (InMemory) | `enable_search=False` |
| POST | `/clips` | Enqueue ffmpeg clip job | `enable_clip_export=False` OR `ffmpeg` not on PATH |
| GET | `/clips/{id}/download` | Stream rendered clip (`FileResponse`) | `enable_clip_export=False` |
| POST | `/webhooks/capture-complete` | Record + enqueue post-capture job | `enable_webhooks=False` OR rq queue unreachable |

Multi-tenant scope: every list/search/chat/webhook surface accepts
`owner_user_id` and threads it into repo filters, `BrainClient.retrieve`
scope, and TaskQueue job kwargs.

## Configuration (v0.2)

`MeetbotAdminConfig` adds the following fields on top of v0.1:

| Field | Type | Default | Notes |
|-------|------|---------|-------|
| `enable_chat` | `bool` | `False` | Gates `/chat`. |
| `enable_search` | `bool` | `False` | Gates `/search`. |
| `enable_clip_export` | `bool` | `False` | Gates `/clips` + `/clips/{id}/download`. |
| `enable_webhooks` | `bool` | `False` | Gates `/webhooks/capture-complete`. |
| `anthropic_api_key` | `SecretStr \| None` | `None` | Excluded from model dump; never appears in `/health`. |
| `clip_storage_dir` | `Path \| None` | `None` | Where rendered clips land. |
| `brain_client` | `BrainClient \| None` | `None` | Host-injected. Excluded from dump. |
| `task_queue` | `TaskQueue \| None` | `None` | Host-injected. Excluded from dump. |
| `redis_url` | `str \| None` | `None` | Used by `RqTaskQueue` + worker CLI. |

Env-var loading uses the `MEETBOT_ADMIN_*` prefix (e.g. `MEETBOT_ADMIN_ENABLE_CHAT=true`).

## Worker CLI (v0.2)

Background jobs (post-capture pipeline, clip render, etc.) run via `rq`.
Start a worker with:

```bash
lattice-meetbot-admin worker --redis-url redis://localhost:6379/0 --queue meetbot
```

Optional `--owner-user-id` scopes the worker to a single tenant (useful for
per-tenant capacity isolation).

## Migrations

```bash
lattice-meetbot-admin migrate --db-url sqlite:///./meetbot_admin.db
```

Alembic `0002` (shipped in v0.2) adds the FTS5 `segments_fts` shadow table,
`capture_events`, and the `voicenotes.owner_user_id` column.

## Deferred (v0.3+)

- Worker-side `owner_user_id` enforcement (v0.2 carries the id end-to-end; worker filtering is not yet wired).

## License

Apache-2.0. Author: CodeWarrior4Life.
