chore: archive legacy implementation and document rebuild

This commit is contained in:
hungtran24 2026-09-25 09:54:57 +07:00
parent 1f0b95edd8
commit 81c3de8087
237 changed files with 5081 additions and 625 deletions

33
.dockerignore Normal file
View File

@ -0,0 +1,33 @@
# Never send the archived codebase or local configuration to a build context.
old_repo/
.env
.env.*
# Local Python environments and generated files.
.venv/
venv/
__pycache__/
*.py[cod]
.pytest_cache/
.ruff_cache/
.pyright/
.coverage*
htmlcov/
# Local web dependencies and build output.
node_modules/
**/node_modules/
.bun/
**/.bun/
.svelte-kit/
**/.svelte-kit/
playwright-report/
test-results/
# Repository metadata and unrelated local artifacts.
.git/
.claude/
.codex/
.scratch/
vault/
rewrite_architect.md

15
.editorconfig Normal file
View File

@ -0,0 +1,15 @@
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
[*.{yml,yaml,json,toml,ini,md}]
indent_size = 2
[Makefile]
indent_style = tab

View File

@ -1,19 +1,28 @@
# Local development only. Replace all credentials in deployed environments.
ENVIRONMENT=development
DATABASE_URL=postgresql+asyncpg://postgres:postgres@localhost:5433/lead_scoring
AIHUB_BASE_URL=http://localhost:8080
DEBUG=false
# Example values for local development only. Do not use these credentials in staging/production.
# .env is ignored by Git. .env.test is local-only and must point to ai_platform_test.
# Compose interpolates this file; only explicitly listed environment entries reach containers.
# JSON arrays consumed by pydantic-settings. These values work with the Dev Console example.
SERVICE_CALLERS=[{"caller_id":"dev-console","token":"local-dev-token","allowed_apps":["dev-console"],"allowed_features":["lead-scoring"],"allowed_tenants":["omni-account-42","omni-test-tenant-42"]}]
TENANT_ALLOWLIST=["omni-account-42","omni-test-tenant-42"]
SCORING_CONFIGS=[{"version":"1.0.0","confidence":0.8,"confidence_threshold":0.7,"hitl_policy_version":"1.0.0","effort_profile":"medium","fallback_policy":"rules_only_review","ai_model":"openai/gpt-4o-mini"}]
# Docker Compose PostgreSQL (local only)
POSTGRES_USER=ai_platform
POSTGRES_PASSWORD=local-change-this-password
POSTGRES_DB=ai_platform
POSTGRES_PORT=55432
BACKEND_PORT=8000
WEB_PORT=3000
WORKER_LEASE_SECONDS=30
WORKER_RECOVERY_INTERVAL_SECONDS=5
KILL_SWITCH_ENABLED=false
# Backend: read by ai_platform.infrastructure.config.settings.Settings (AI_PLATFORM_ prefix)
AI_PLATFORM_ENVIRONMENT=development
AI_PLATFORM_DATABASE_URL=postgresql+asyncpg://ai_platform:local-change-this-password@127.0.0.1:55432/ai_platform
# Required for backend provisioning endpoint; generate a fresh random secret for local use.
AI_PLATFORM_TENANT_PROVISIONING_SECRET=local-provisioner-replace-before-use
AI_PLATFORM_ADMIN_COOKIE_SECURE=false
AI_PLATFORM_SESSION_TTL_SECONDS=28800
# Optional, required together when sending webhook to a local Omni receiver.
# AI_PLATFORM_WEBHOOK_URL=http://localhost:8080/api/v1/internal/lead-scoring/events
# AI_PLATFORM_WEBHOOK_SIGNING_SECRET=local-replace-before-use
# Optional; no global V-Key: Omni sends X-Tenant-VKey per scoring request.
# AI_PLATFORM_AIHUB_BASE_URL=http://localhost:8080
# Enable webhook delivery by setting both values.
# WEBHOOK_SUBSCRIBER_URL=http://localhost:8080/api/v1/internal/lead-scoring/events
# WEBHOOK_SIGNING_SECRET=replace-with-local-signing-secret
WEBHOOK_SIGNING_KEY_ID=pilot-2026-01
# Compose web origin only; native SvelteKit dev reads apps/web/.env.
WEB_ORIGIN=http://localhost:3000
# Do not place tenant keys, V-Keys, admin sessions or backend URLs in PUBLIC_* variables.

96
.gitignore vendored
View File

@ -1,76 +1,42 @@
# Python & Virtual Environments
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
.venv/
venv/
ENV/
env/
.uv/
# Linters, Type Checkers & Test Caches
.ruff_cache/
.pytest_cache/
.mypy_cache/
.pyre/
.pytype/
.pyright/
.coverage
.coverage.*
htmlcov/
nosetests.xml
coverage.xml
*.cover
*.py,cover
# Node / Bun / Frontend
node_modules/
node_modules
apps/dev-console/node_modules
.bun/
dist-ssr/
*.local
.svelte-kit/
# Playwright & Testing Reports
playwright-report/
test-results/
blob-report/
# Environment Variables & Local Secrets
# Local configuration and private data
.env
.env.*
!.env.example
# Project-local
vault/
.scratch/
.codex/
docs/agents/
.claude/
.codex/
CLAUDE.LOCAL.md
# Generated artifacts
/openapi.json
# IDE, OS & Editor Artifacts
# Python
.venv/
venv/
__pycache__/
*.py[cod]
*.egg-info/
.pytest_cache/
.ruff_cache/
.pyright/
.mypy_cache/
.coverage*
htmlcov/
build/
dist/
# Web and generated output
node_modules/
.bun/
.svelte-kit/
.playwright/
playwright-report/
test-results/
*.local
# Generated contracts: versioned Contract Pack is tracked separately
/openapi.json
/apps/web/src/lib/generated/
# OS and editor
.DS_Store
Thumbs.db
*.swp
*.swo
*~

23
.importlinter Normal file
View File

@ -0,0 +1,23 @@
[importlinter]
root_package = ai_platform
[importlinter:contract:domain]
name = Lead Scoring domain stays independent of effects and HTTP
type = forbidden
source_modules =
ai_platform.lead_scoring.domain
forbidden_modules =
ai_platform.infrastructure
ai_platform.presentation
ai_platform.bootstrap
ai_platform.platform
[importlinter:contract:application]
name = Lead Scoring application does not import adapters or HTTP
type = forbidden
source_modules =
ai_platform.lead_scoring.application
forbidden_modules =
ai_platform.infrastructure
ai_platform.presentation
ai_platform.bootstrap

17
.pre-commit-config.yaml Normal file
View File

@ -0,0 +1,17 @@
exclude: ^old_repo/
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.12.11
hooks:
- id: ruff
- id: ruff-format
args: [--check]
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: check-yaml
- id: check-toml
- id: check-merge-conflict
- id: detect-private-key

178
AGENTS.md
View File

@ -1,172 +1,12 @@
# AGENTS.md
# Repository workflow
This file provides guidance to Codex (Codex.ai/code) when working with this repository.
This repository is the rebuilt AI Platform. `old_repo/` is historical and excluded from builds. The approved rebuild plan authorizes implementation; `docs/specs/ai-platform-lead-scoring.md` is review-ready for cross-service acceptance, so unverified Omni/AIHub wire details are not release claims.
## Purpose and status
1. Before changing Lead Scoring behavior, read `docs/specs/ai-platform-lead-scoring.md`, `CONTEXT.md`, and `ARCHITECTURE.md`. Read `stack.md` when choosing a runtime or dependency. Generated OpenAPI and small Omni fixtures own exact wire shapes.
2. Put tenant/admin authentication, configuration and shared DB setup in `platform`; put deterministic rules/metrics and run lifecycle in `lead_scoring/domain`; orchestration in `application`, I/O in `infrastructure`, HTTP mapping in `presentation`, and wiring in `bootstrap`. Churn follows the same layout only when a specification exists.
3. Omni owns rules/weights/HITL/CRM; AI Platform owns AI profile and technical run status. V-Key is request-scoped RAM only. One tenant key per tenant authenticates the platform; Admin Web uses a distinct session. Terminal webhook triggers Omni GET.
4. **Kiểm tra tính nhất quán trước khi tối ưu một phần:** đối chiếu API với fixture Omni, tên env với `Settings`/Compose/CI, lệnh build với package/lockfile và UI với design system ở `ARCHITECTURE.md`. Web dùng Tailwind CSS v4 cho semantic tokens, shadcn-svelte cho component cần thiết, Bits UI cho tương tác phức tạp; dùng HTML native cho form/bảng đơn giản, không tự tái tạo primitives. Xem `rewrite_architect.md` để hiểu lý do chọn stack, không dùng nó làm contract song song.
5. File trên 200 dòng là tín hiệu review: kiểm tra trách nhiệm trộn lẫn, tách tại boundary có nghĩa. Giữ một OpenAPI generated và vài Omni fixtures thật, không tạo hệ schema thứ hai.
6. Trước bàn giao, chạy Ruff/Pyright/Import Linter/pytest, Svelte checks/build/tests, migration và contract generation có liên quan. Báo chính xác pass/fail; hook opt-in, CI là gate. Không stage `.env`, `.env.test`, ignored assets hoặc secrets.
This repository is the Python-first AI Platform workspace. Lead Scoring is the first service; related systems are `DotB-Omni`, `lead-scoring-agent`, and `aihub` under `/home/hung/code/dotb_workspace/`.
The repository contains specifications, project documentation, and the initialized baseline for the Lead Scoring service (`src/lead_scoring/`).
Before implementing or changing Lead Scoring Customer Pilot behavior, read:
- `docs/specs/lead-scoring-customer-pilot.md`: authoritative product behavior, scope, invariants, acceptance boundaries, and cross-service ownership.
- `stack.md`: technology decisions, candidates, evidence, and unresolved stack questions. It does not override the approved specification.
The DotB Vault RFC, initial brief, Grill Brief, legacy reports, drafts, and agent messages are historical/supporting context rather than implementation authority. Exact wire formats become authoritative through released Pydantic models, generated OpenAPI/JSON Schemas, and shared fixtures.
## Communication
- Keep responses short, specific, and decision-oriented.
- Put the decision or conclusion first, followed by only the evidence and next action needed.
- Keep the main context high-signal. Put raw logs, scratch data, and long intermediate reports in `/tmp/` or the appropriate durable document.
- Use lists and compact structure when they make the result easier to scan.
- State assumptions, unresolved decisions, and verification status explicitly.
## Writing
- Write directly and precisely. Avoid buzzwords, filler, and repeated explanations.
- Comments explain intent, invariants, trade-offs, or non-obvious constraints, not syntax or line-by-line behavior.
- Do not add speculative documentation, abstractions, or metadata that the repository does not need.
- Do not use emoji or em dashes in new prose, comments, or reports. Preserve emoji and punctuation that are part of existing paths or quoted source text.
## Delegation
- Prioritize standard subagents over teammates to minimize token overhead. Spawn multiple subagents when parallel execution is genuinely needed.
- Pick the agent type matching the task from available configured agents (e.g., `explorer`, `implementer`, `tester`, `researcher`, `adversarial-reviewer`, `general`, `codebase-memory`).
- Delegate context-heavy or tool-heavy work with a clear scope, completion criteria, and evidence requirements.
- Require condensed handoffs containing conclusions, changed paths, verification, and uncertainty. Do not paste raw logs into the main context.
- The main context retains final decisions and integration responsibility. Agent messages are evidence, not user approval.
## Agent skills
### Issue tracker
Local Markdown issues are stored under `.scratch/<feature-slug>/`. See `docs/agents/issue-tracker.md`.
### Domain docs
The repository uses a single-context domain layout. See `docs/agents/domain.md`.
## Project knowledge
- `AGENTS.md` is the project map for conventions, verified commands, boundaries, and gotchas.
- `docs/specs/lead-scoring-customer-pilot.md` is the approved source of truth for Lead Scoring Customer Pilot product behavior and build boundaries.
- `stack.md` is the primary record for technology decisions and unresolved stack questions; it cannot override the approved spec.
- `docs/` contains shared project knowledge intended for version control.
- `/tmp/` is for scratch data, raw logs, and temporary handoffs.
- Released Pydantic models, generated OpenAPI/JSON Schemas, tests, and shared fixtures become the exact executable contract when they exist.
## Documentation
- Put temporary reports, raw logs, and scratch material in `/tmp/`.
- Put durable team knowledge in `docs/` and include it in version control.
- Use `vault/` only for durable project-local knowledge that must not be committed.
- New durable Markdown documents under `docs/` or `vault/` use minimal YAML frontmatter:
```yaml
---
title: Document title
description: A short description of what the document contains and when it is useful.
status: draft
tags: []
---
```
- `title` and `description` are required. For governed specs, `status` may be `draft`, `review_ready`, `approved`, or `deprecated`; other existing document schemas keep their established status vocabulary. `tags` is optional.
- Do not add metadata that Git, the filesystem, or existing tooling can derive.
- Preserve the format and metadata schema of existing documents. Do not add frontmatter, reformat, move, or normalize existing files unless the task explicitly requests migration.
- `AGENTS.md`, README files, and files with an existing schema keep their established format.
## Repository structure
- `src/lead_scoring/`: Lead Scoring production service package and CLI tools.
- `alembic/`: database migrations for PostgreSQL.
- `tests/`: test suite including health check, OpenAPI CLI, and migration lifecycle.
- `docs/specs/lead-scoring-customer-pilot.md`: approved Lead Scoring Customer Pilot specification.
- `docs/`: durable shared project documentation.
- `.scratch/`: local untracked draft specs and issue tickets used by agent skills.
- `stack.md`: technology decisions and unresolved stack questions.
- `.codex/settings.json`: project hook configuration.
- `.codex/hooks/post-edit-check.py`: Python-only PostToolUse feedback hook.
## Product and frontend boundary
The frontend boundary is approved for Customer Pilot: DotB-Omni owns all customer-facing Lead Scoring configuration and HITL UI. AI Platform may provide only an internal Dev Console for fixtures, contract testing, failure testing, and allowlisted integration verification; it must not duplicate Omni business UI.
When the internal Dev Console is implemented:
- Use Svelte 5 and TypeScript with Bun, Vite, and Vitest. Add SvelteKit only when routing, SSR, or deployment requires it.
- Generate types from backend OpenAPI and consume them through `openapi-fetch`.
- Keep shared transport concerns such as authentication and error handling outside generated code.
- Use the official Svelte tooling, including `@sveltejs/mcp` autofixer feedback and `svelte-check`.
- Use Playwright only for important end-to-end user flows.
TypeScript 7 native compiler and language server are pilot candidates, not the adopted project default. Test them project-locally before changing global runtimes or the shared `mcpls` configuration.
## Engineering principles
- Follow YAGNI. Implement only what the current requirement needs; do not add speculative abstractions, extension points, compatibility layers, or infrastructure.
- Prefer the simplest design that preserves clear boundaries and can be changed safely.
- Reuse the standard library and established, actively maintained packages when they reduce code and operational burden. Avoid dependencies for trivial behavior.
- Keep code explicit. Use precise names, short control flow, and direct data transformations. Avoid cleverness, hidden side effects, global mutable state, and premature optimization.
- Prefer composition over inheritance and functions over classes. Introduce a class only when state, lifecycle, or a framework contract genuinely requires one.
- Keep a functional core with side effects at the boundaries. Isolate I/O, persistence, network calls, clocks, and environment access.
- Organize modules by capability or domain responsibility, not by arbitrary technical layers.
- Avoid wrappers that only rename another API. Every abstraction must remove meaningful complexity or enforce a real boundary.
- Preserve one clear source of truth for contracts, configuration, and domain rules.
## AI-native code
Write code that humans and coding agents can understand with minimal hidden context:
- Make dependencies, inputs, outputs, errors, and side effects explicit.
- Use typed, stable contracts at module and service boundaries.
- Keep related implementation and tests easy to locate.
- Prefer deterministic behavior and small composable functions.
- Document decisions and non-obvious constraints, not syntax or line-by-line behavior.
- Match existing conventions before introducing a new pattern.
- Make the smallest coherent change and remove superseded code instead of leaving parallel implementations.
## Verified commands
- `uv sync`: sync workspace dependencies and environment.
- `uv run pytest`: run pytest test suite against Python 3.13.
- `uv run ruff check src tests`: run lint checks across source and tests.
- `uv run ruff format --check src tests`: check code formatting.
- `uv run pyright`: run Pyright static type checker.
- `uv run ty check`: run project-local ty type checker.
- `uv run generate-openapi`: deterministically generate root `openapi.json`.
- `uv run generate-openapi --check`: verify that `openapi.json` is present and matches the current backend contract.
- `uv run generate-webhook-contract`: deterministically generate terminal webhook contract pack.
- `uv run generate-webhook-contract --check`: verify that webhook contract pack is present and matches current models.
- `uv run generate-polling-contract`: deterministically generate scoring run polling contract pack.
- `uv run generate-polling-contract --check`: verify that polling contract pack is present and matches current models.
- `uv run generate-contract-pack`: deterministically generate the versioned shared Contract Pack.
- `uv run generate-contract-pack --validate-fixtures`: validate provider and consumer fixture expectations.
- `uv run generate-contract-pack --check`: verify the versioned Contract Pack and checksums are present and current.
- `uv run alembic upgrade head`: apply database migrations up to head.
- `uv run alembic downgrade base`: revert all database migrations.
## Deterministic generation
- When a verified project generator exists, use it instead of manually editing derived files.
- Treat OpenAPI output and generated frontend types as derived artifacts. Regenerate them from the backend contract and require the authoritative verification command to detect drift.
- Do not edit generated files manually unless the project workflow explicitly requires it.
## Safety and scope
- Inspect a path before overwriting or deleting it. Preserve existing configuration, documentation, code, and data unless the task explicitly authorizes removal or migration.
- Do not expose secrets in logs, reports, handoffs, or generated artifacts.
- Do not install packages, modify system configuration, or create permissions and background services without explicit approval.
- Bootstrap production code only after the relevant product and implementation decision. Customer-facing Lead Scoring UI remains owned by DotB-Omni.
## Tooling and verification gotchas
- Root `openapi.json` and frontend build output remain covered by the ignore policy; the versioned Contract Pack OpenAPI artifact is generated and committed, and must not be edited manually.
- The project PostToolUse hook is configured in `.codex/settings.json` for `Write` and `Edit`. It handles Python files via `ruff` (safe fix and format). Full type-checking (`pyright`, `ty`) and test suites belong to explicit verification steps. Preserve the working-tree modification to `.codex/hooks/post-edit-check.py` unless explicitly asked to change or reset it.
- Do not modify `/etc`, package-manager state, system services, drivers, kernel settings, global Node/TypeScript versions, or the shared `mcpls` configuration as part of repository work unless explicitly approved.
## Quality of life
Pyright LSP is available for semantic navigation. Use it for definitions, references, hover types, document and workspace symbols, and call hierarchy; then read the relevant implementation to understand business rules and side effects.
Use `README.md` for current local commands; `stack.md` for decisions and deferred production hosting/TLS/secret/backup/alerts. Preserve the user's existing ignored files unless explicitly authorized to replace them. No global tool installs or system configuration changes during repo work.

60
ARCHITECTURE.md Normal file
View File

@ -0,0 +1,60 @@
# Architecture
## Status and scope
This document describes the intended architecture for the rebuilt AI Platform, not a verified description of working code. The root Lead Scoring provider specification is `docs/specs/ai-platform-lead-scoring.md`; it remains `draft/review_ready` pending review. Its ownership boundary is authoritative only after approval. The archived code and documents under `old_repo/` are historical evidence, not the new architecture or implementation.
AI Platform is a provider service: it executes bounded rule scoring and a selected AI profile, maintains scoring-run lifecycle, and exposes result retrieval. DotB-Omni owns customer-configured rules/weights, HITL and customer actions, snapshot construction, user authorization, and CRM writeback. Omni is notified of terminal outcome through an agreed signed HMAC webhook and then calls the authenticated GET endpoint for run details. DotB EMS remains the CRM system of record. There is no customer-facing settings or review UI in this service scope.
## Intended backend boundaries
The proposed modular monolith has one runtime and one deployable backend. These names describe target ownership, not files already present.
- **Bootstrap/composition:** loads validated settings and composes framework, database, provider client, and application workflows. Resource lifetime is established here.
- **Platform:** tenant-key verification and tenant isolation, shared persistence/runtime concerns, and operational interfaces. It does not own Omni customer configuration or user permissions.
- **Lead Scoring domain:** rule execution, scoring-run state/invariants, and profile semantics. Deterministic scoring rules should be pure functions; run identity and lifecycle belong in an entity/value model where useful.
- **Lead Scoring application:** admission, idempotency, execution coordination, result retrieval, and notification workflow. Use cases own transaction meaning; infrastructure supplies mechanisms. AI profile contains model, prompts and timeout; app-provided rules and weights arrive in each run body.
- **Infrastructure:** database mappings/repositories, AIHub HTTP client, HMAC signing, and delivery adapters. Provider details stop at these boundaries.
- **Presentation:** HTTP request/response mapping, tenant-auth dependency at the edge, health/readiness, and API error mapping. Transport schemas do not become domain objects by accident.
Dependency direction is inward: presentation and infrastructure may depend on application/domain contracts; domain does not depend on frameworks, persistence, network, environment, or application orchestration. Bootstrap is the composition root. Avoid generic base services, empty ports, service locators, and multiple deployment processes unless evidence requires them.
## Lifecycle and data invariants
1. Authenticate and establish the tenant boundary before accessing a run.
2. Validate bounded request input and calculate a stable canonical-body fingerprint.
3. Scope client-supplied UUID idempotency to the tenant. Same UUID/same canonical body resolves to the existing run; same UUID/different body conflicts. The service generates a distinct run UUID.
4. Commit admitted run before acknowledging acceptance. Execution holds raw V-Key only in current process memory; it is never persisted.
5. Rules-only requires no AIHub or V-Key; medium bounded two-pass is the default when AI is requested. Light/heavy are deferred until verified demand, not placeholders.
6. Persist terminal outcome independently from notification delivery. Signed webhook informs Omni, which performs authenticated GET for the authoritative result.
7. One-process recovery terminalizes work that cannot resume after interruption. It does not restore the lost V-Key or promise an automatic retry.
8. Delete/redact sensitive run material at 90 days under an approved policy; tenant offboarding and backup treatment need operational decisions.
These are target constraints, not statements that the code currently enforces them. See the spec for unresolved contract and review gates.
## Transaction and effect boundaries
- Application use cases define atomic boundaries, including run transition and any durable notification intent where selected. Persistence adapters implement transactions.
- AIHub requests are network effects with explicit timeout and bounded policy once AIHub behavior has been verified. Never add speculative provider retries.
- HMAC delivery is an effect with bounded retry and observable terminal delivery state. Exact signing and replay rules are contract decisions with Omni.
- Clock, UUID generation, provider client, and persistence are explicit inputs at the application boundary when deterministic testing or lifecycle behavior requires them.
- Domain functions are deterministic and I/O-free. Stateful objects are justified by identity, invariant, or lifecycle rather than used as namespaces.
## Admin Web design system
Admin Web dùng SvelteKit 5, Tailwind CSS v4 semantic tokens, shadcn-svelte component source cho button/input/card/badge/table khi UI cần, Bits UI cho dialog/dropdown/popover hoặc tương tác phức tạp, và một icon family Lucide nếu cần icon. Chỉ thêm component đang dùng, không scaffold cả catalog. `src/lib/components/ui/` chỉ chứa primitives không biết domain; route giữ thành phần chỉ dùng tại route. HTML native là lựa chọn đúng cho form, label và bảng đơn giản khi không cần behavior phức tạp. Style tokens có một nguồn trong `apps/web/src/app.css`; UI phải kiểm tra focus, keyboard, validation, responsive và contrast. Browser chỉ gọi SvelteKit; backend auth/credentials và `BACKEND_INTERNAL_URL` thuộc `$lib/server/`. Không tạo frontend Clean Architecture giả lập.
## Verification structure (target)
- Unit: domain calculations, validation and transitions without network/database.
- Integration: persistence/migrations on the selected production database and AIHub HTTP adapter with controlled transport.
- Functional: HTTP request through application/persistence and back, including tenant isolation and idempotency.
- Architecture: import direction, framework isolation, and composition-root rules.
- Contract: shared provider/Omni fixtures for requests, replay conflicts, result GET, HMAC delivery, acknowledgements, and errors.
- Operational: process interruption, recovery terminality, 90-day redaction, secret-leak sentinels, and deployment restore drills.
Actual test commands, directories, and enforcement must follow checked-in tooling once present; do not describe this target taxonomy as an existing test suite.
## Deferred decisions
Production hosting/orchestrator, network and TLS topology, secret manager and rotation ownership, database backup/restore and deletion guarantees, alerting/observability destination, load/SLO targets, exact contract publication/versioning, and AIHub protocol/model/timeouts remain deferred. Resolve them with accountable owners before the corresponding implementation or deployment. No production-readiness claim is warranted while these remain open.

160
CLAUDE.md
View File

@ -1,159 +1 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with this repository.
## Purpose and status
This repository is the Python-first AI Platform workspace. Lead Scoring is the first service; related systems are `DotB-Omni`, `lead-scoring-agent`, and `aihub` under `/home/hung/code/dotb_workspace/`.
The repository contains specifications, project documentation, and the initialized baseline for the Lead Scoring service (`src/lead_scoring/`).
Before implementing or changing Lead Scoring Customer Pilot behavior, read:
- `docs/specs/lead-scoring-customer-pilot.md`: authoritative product behavior, scope, invariants, acceptance boundaries, and cross-service ownership.
- `stack.md`: technology decisions, candidates, evidence, and unresolved stack questions. It does not override the approved specification.
The DotB Vault RFC, initial brief, Grill Brief, legacy reports, drafts, and agent messages are historical/supporting context rather than implementation authority. Exact wire formats become authoritative through released Pydantic models, generated OpenAPI/JSON Schemas, and shared fixtures.
## Communication
- Keep responses short, specific, and decision-oriented.
- Put the decision or conclusion first, followed by only the evidence and next action needed.
- Keep the main context high-signal. Put raw logs, scratch data, and long intermediate reports in `/tmp/` or the appropriate durable document.
- Use lists and compact structure when they make the result easier to scan.
- State assumptions, unresolved decisions, and verification status explicitly.
## Writing
- Write directly and precisely. Avoid buzzwords, filler, and repeated explanations.
- Comments explain intent, invariants, trade-offs, or non-obvious constraints, not syntax or line-by-line behavior.
- Do not add speculative documentation, abstractions, or metadata that the repository does not need.
- Do not use emoji or em dashes in new prose, comments, or reports. Preserve emoji and punctuation that are part of existing paths or quoted source text.
## Delegation
- Use the configured `researcher` agent for read-only exploration and research.
- Use the configured `primary-engineer` agent for implementation, debugging, and multi-step engineering work. If it is unavailable, use the narrowest suitable implementation agent.
- Implementation agents own TDD tests; use the `tester` agent for independent verification before completion.
- Delegate context-heavy or tool-heavy work with a clear scope, completion criteria, and evidence requirements.
- Require condensed handoffs containing conclusions, changed paths, verification, and uncertainty. Do not paste raw logs into the main context.
- The main context retains final decisions and integration responsibility. Agent messages are evidence, not user approval.
## Project knowledge
- `CLAUDE.md` is the project map for conventions, verified commands, boundaries, and gotchas.
- `docs/specs/lead-scoring-customer-pilot.md` is the approved source of truth for Lead Scoring Customer Pilot product behavior and build boundaries.
- `stack.md` is the primary record for technology decisions and unresolved stack questions; it cannot override the approved spec.
- `docs/` contains shared project knowledge intended for version control.
- `/tmp/` is for scratch data, raw logs, and temporary handoffs.
- Released Pydantic models, generated OpenAPI/JSON Schemas, tests, and shared fixtures become the exact executable contract when they exist.
## Documentation
- Put temporary reports, raw logs, and scratch material in `/tmp/`.
- Put durable team knowledge in `docs/` and include it in version control.
- Use `vault/` only for durable project-local knowledge that must not be committed.
- New durable Markdown documents under `docs/` or `vault/` use minimal YAML frontmatter:
```yaml
---
title: Document title
description: A short description of what the document contains and when it is useful.
status: draft
tags: []
---
```
- `title` and `description` are required. For governed specs, `status` may be `draft`, `review_ready`, `approved`, or `deprecated`; other existing document schemas keep their established status vocabulary. `tags` is optional.
- Do not add metadata that Git, the filesystem, or existing tooling can derive.
- Preserve the format and metadata schema of existing documents. Do not add frontmatter, reformat, move, or normalize existing files unless the task explicitly requests migration.
- `CLAUDE.md`, README files, and files with an existing schema keep their established format.
## Repository structure
- `src/lead_scoring/`: Lead Scoring production service package and CLI tools.
- `alembic/`: database migrations for PostgreSQL.
- `tests/`: test suite including health check, OpenAPI CLI, and migration lifecycle.
- `docs/specs/lead-scoring-customer-pilot.md`: approved Lead Scoring Customer Pilot specification.
- `docs/`: durable shared project documentation.
- `stack.md`: technology decisions and unresolved stack questions.
- `.claude/settings.json`: project hook configuration.
- `.claude/hooks/post-edit-check.py`: Python-only PostToolUse feedback hook.
## Product and frontend boundary
The frontend boundary is approved for Customer Pilot: DotB-Omni owns all customer-facing Lead Scoring configuration and HITL UI. AI Platform may provide only an internal Dev Console for fixtures, contract testing, failure testing, and allowlisted integration verification; it must not duplicate Omni business UI.
When the internal Dev Console is implemented:
- Use Svelte 5 and TypeScript with Bun, Vite, and Vitest. Add SvelteKit only when routing, SSR, or deployment requires it.
- Generate types from backend OpenAPI and consume them through `openapi-fetch`.
- Keep shared transport concerns such as authentication and error handling outside generated code.
- Use the official Svelte tooling, including `@sveltejs/mcp` autofixer feedback and `svelte-check`.
- Use Playwright only for important end-to-end user flows.
TypeScript 7 native compiler and language server are pilot candidates, not the adopted project default. Test them project-locally before changing global runtimes or the shared `mcpls` configuration.
## Engineering principles
- Follow YAGNI. Implement only what the current requirement needs; do not add speculative abstractions, extension points, compatibility layers, or infrastructure.
- Prefer the simplest design that preserves clear boundaries and can be changed safely.
- Reuse the standard library and established, actively maintained packages when they reduce code and operational burden. Avoid dependencies for trivial behavior.
- Keep code explicit. Use precise names, short control flow, and direct data transformations. Avoid cleverness, hidden side effects, global mutable state, and premature optimization.
- Prefer composition over inheritance and functions over classes. Introduce a class only when state, lifecycle, or a framework contract genuinely requires one.
- Keep a functional core with side effects at the boundaries. Isolate I/O, persistence, network calls, clocks, and environment access.
- Organize modules by capability or domain responsibility, not by arbitrary technical layers.
- Avoid wrappers that only rename another API. Every abstraction must remove meaningful complexity or enforce a real boundary.
- Preserve one clear source of truth for contracts, configuration, and domain rules.
## AI-native code
Write code that humans and coding agents can understand with minimal hidden context:
- Make dependencies, inputs, outputs, errors, and side effects explicit.
- Use typed, stable contracts at module and service boundaries.
- Keep related implementation and tests easy to locate.
- Prefer deterministic behavior and small composable functions.
- Document decisions and non-obvious constraints, not syntax or line-by-line behavior.
- Match existing conventions before introducing a new pattern.
- Make the smallest coherent change and remove superseded code instead of leaving parallel implementations.
## Verified commands
- `uv sync`: sync workspace dependencies and environment.
- `uv run pytest`: run pytest test suite against Python 3.13.
- `uv run ruff check src tests`: run lint checks across source and tests.
- `uv run ruff format --check src tests`: check code formatting.
- `uv run pyright`: run Pyright static type checker.
- `uv run ty check`: run project-local ty type checker.
- `uv run generate-openapi`: deterministically generate root `openapi.json`.
- `uv run generate-openapi --check`: verify that `openapi.json` is present and matches the current backend contract.
- `uv run generate-webhook-contract`: deterministically generate terminal webhook contract pack.
- `uv run generate-webhook-contract --check`: verify that webhook contract pack is present and matches current models.
- `uv run generate-polling-contract`: deterministically generate scoring run polling contract pack.
- `uv run generate-polling-contract --check`: verify that polling contract pack is present and matches current models.
- `uv run alembic upgrade head`: apply database migrations up to head.
- `uv run alembic downgrade base`: revert all database migrations.
## Deterministic generation
- When a verified project generator exists, use it instead of manually editing derived files.
- Treat OpenAPI output and generated frontend types as derived artifacts. Regenerate them from the backend contract and require the authoritative verification command to detect drift.
- Do not edit generated files manually unless the project workflow explicitly requires it.
## Safety and scope
- Inspect a path before overwriting or deleting it. Preserve existing configuration, documentation, code, and data unless the task explicitly authorizes removal or migration.
- Do not expose secrets in logs, reports, handoffs, or generated artifacts.
- Do not install packages, modify system configuration, or create permissions and background services without explicit approval.
- Bootstrap production code only after the relevant product and implementation decision. Customer-facing Lead Scoring UI remains owned by DotB-Omni.
## Tooling and verification gotchas
- Generated OpenAPI and frontend build output must remain covered by the existing ignore policy and should not be edited manually.
- The project PostToolUse hook is configured in `.claude/settings.json` for `Write` and `Edit`. It currently handles Python files only and invokes the existing `ruff` and `ty` tools. Preserve the pre-existing working-tree modification to `.claude/hooks/post-edit-check.py` unless explicitly asked to change or reset it.
- Do not modify `/etc`, package-manager state, system services, drivers, kernel settings, global Node/TypeScript versions, or the shared `mcpls` configuration as part of repository work unless explicitly approved.
## Quality of life
Pyright LSP is available for semantic navigation. Use it for definitions, references, hover types, document and workspace symbols, and call hierarchy; then read the relevant implementation to understand business rules and side effects.
Follow `AGENTS.md` for repository-wide instructions and workflow.

34
CONTEXT.md Normal file
View File

@ -0,0 +1,34 @@
# Context
Canonical language for the AI Platform Lead Scoring provider. The implementation described here is planned, not verified as working. The provider specification `docs/specs/ai-platform-lead-scoring.md` is a `draft/review_ready`, pending approval.
## Systems and ownership
- **AI Platform:** provider service for bounded AI profiles, rule execution, scoring-run lifecycle, result retrieval, and terminal notification.
- **DotB-Omni / Omni:** customer-facing authority for configured rules and weights, HITL policy and actions, caller-side authorization, lead identity/snapshot construction, and CRM writeback. Omni reads details from the provider after a signed notification.
- **DotB EMS:** CRM system of record for leads.
- **AIHub:** external AI gateway expected to validate/use V-Key and own model access, quota, and provider behavior. Its protocol and integration have not yet been independently verified; never infer endpoints, headers, or payloads.
## Domain terms
- **Tenant:** customer/account boundary used to scope credentials, idempotency keys, and run access. A run lookup must remain inside its authenticated tenant.
- **Tenant key:** service credential used to authenticate a tenant/caller at the provider boundary, subject to final agreed provisioning contract. It is distinct from the raw **V-Key** used for AIHub access. Do not treat the terms as interchangeable.
- **V-Key:** sensitive AIHub credential material. Target rule: keep raw value in memory only for the active execution attempt; never persist, log, trace, or send it to the browser. Source and exact forwarding protocol are unresolved.
- **Canonical snapshot:** bounded input assembled by Omni from the lead and permitted evidence. It is an input snapshot, not an AI Platform-owned CRM record.
- **Scoring configuration:** customer-authored rule/weight and HITL configuration owned by Omni. The provider may consume an immutable version with the request for reproducibility; it does not become the customer configuration authority.
- **AI profile:** provider execution choice `light`, `medium`, or `heavy`. These are three bounded orchestration modes, not confirmed AIHub-native offerings. Concrete models, passes, limits, and timeouts are unresolved.
- **Scoring run:** one provider execution for one tenant, request UUID, subject, snapshot, configuration version, and AI profile. The server-generated run UUID identifies the persisted run.
- **Request UUID / idempotency identity:** client-provided UUID included in the request body, scoped to a tenant. Same UUID and same canonical body replays the existing run; same UUID and different body conflicts. A new scoring attempt uses a new UUID. Exact fingerprint normalization remains contract work.
- **Result GET:** tenant-authenticated read of the authoritative run result. Omni calls it after receiving a signed terminal notification.
- **HITL (human-in-the-loop):** human review workflow and customer actions owned by Omni. The provider does not authorize end users or own the review interface.
- **Terminal notification:** provider-to-Omni signed HMAC webhook indicating a run outcome. It is a notification, not the result source of truth; Omni GETs the run. HMAC envelope, replay window, and retry protocol are unresolved.
- **Recovery:** after interruption of the single-process runtime, terminalize work that cannot continue because its volatile task/V-Key was lost. Recovery is not resumption and does not imply automatic re-execution.
- **Retention:** proposed deletion/redaction of sensitive run material after 90 days. Backup deletion, audit retention, and tenant offboarding behavior need explicit approval.
## Disambiguation
- **Rules and weights** are customer policy owned by Omni; **rule execution** is provider behavior owned by AI Platform.
- **Customer action** means Omni-authorized configuration/review/initiation behavior; an API caller's identity does not establish end-user permission.
- **Webhook delivery state** is separate from scoring-run state. A notification failure does not by itself rewrite a completed scoring result.
- **Idempotency** prevents duplicate admission for a body UUID; it does not guarantee exactly-once AIHub invocation or webhook delivery.
- **Draft/review_ready** means prepared for stakeholder review only. It does not mean approved, released, or implemented.

152
README.md
View File

@ -1,133 +1,71 @@
# AI Platform - Lead Scoring Service
# AI Platform
Lead Scoring service and internal Dev Console for the AI Platform.
New AI Platform repository scaffold. The backend and SvelteKit implementation are being developed concurrently; this document records the intended local workflow, not a claim that every command already works.
## What runs locally
## Runtime layout
| Component | Purpose | Default address |
| --- | --- | --- |
| PostgreSQL 16 | Stores scoring runs and migrations | `localhost:5433` |
| Lead Scoring API | REST API, async scoring worker, OpenAPI | `http://localhost:8000` |
| Dev Console | Internal fixture and contract-testing UI | `http://localhost:5173` |
| AIHub | Optional external AI inference dependency | `http://localhost:8080` |
- Python 3.13 backend package: `src/ai_platform`, served as `ai_platform.main:app`.
- PostgreSQL 16 with a new, project-specific Compose volume named `ai_platform_pgdata`.
- Alembic schema changes are applied as a one-shot Compose service before the backend starts.
- SvelteKit is a separate web image under `apps/web`.
- `old_repo/` is archived source only and is excluded from Docker build contexts and local checks.
The service still runs if local AIHub is unavailable: the default config uses `rules_only_review` fallback. A reachable AIHub and a valid tenant VKey are required for live AI scoring.
The local Compose stack runs one backend process. It is for development only; default credentials and loopback port mappings are not deployment settings. Keep production secrets outside `.env` and inject them through the deployment environment or a secrets manager.
## Requirements
## Local setup
Install before starting:
Copy the backend/Compose template and the separate SvelteKit server-only template. Both `.env` files are ignored by Git; the previous root `.env` is preserved under `old_repo/.env` as historical local data, not loaded by the rebuilt service.
- Git
- Python 3.13 or newer
- [uv](https://docs.astral.sh/uv/)
- [Bun](https://bun.sh/)
- Docker with Docker Compose plugin
## Start from a fresh clone
```bash
git clone https://github.com/HungTran24/dotb_ai-platform.git
cd dotb_ai-platform
```sh
cp .env.example .env
cp apps/dev-console/.env.example apps/dev-console/.env
cp apps/web/.env.example apps/web/.env
make install
```
The copied `.env` files are local only and ignored by Git. Their example values are intentionally for development only.
Start the database and run the backend and web servers in separate terminals:
### 1. Start PostgreSQL
```bash
docker compose up -d postgres
docker compose ps
```sh
make db-up
make migrate
make backend-dev
make web-dev
```
The included Compose service exposes PostgreSQL on port `5433` to avoid conflicting with other local projects. If port `5433` is occupied, choose another port and update both values before migration:
The local web server should call the backend through server-only configuration. Do not expose `BACKEND_INTERNAL_URL`, database credentials, or provider keys as browser-visible `PUBLIC_*` variables.
```bash
POSTGRES_PORT=15432 docker compose up -d postgres
# Then set DATABASE_URL=postgresql+asyncpg://postgres:postgres@localhost:15432/lead_scoring in .env
Compose can instead build and start all services, including the one-shot migration step:
```sh
docker compose up --build
```
### 2. Install backend dependencies and migrate the database
The database is reachable from the host at `127.0.0.1:55432`, backend at `127.0.0.1:8000`, and web at `127.0.0.1:3000` by default. To discard only this new database and its data, run `docker compose down -v`; this does not target archived or unrelated volumes.
```bash
uv sync
uv run alembic upgrade head
The local database starts with only the development database. To run tests safely, create a separate database in that same new PostgreSQL instance, then pass its URL explicitly:
```sh
docker compose exec postgres createdb -U ai_platform ai_platform_test
AI_PLATFORM_DATABASE_URL=postgresql+asyncpg://ai_platform:local-change-this-password@127.0.0.1:55432/ai_platform_test make test
```
### 3. Start the Lead Scoring API
`make test` rejects a database URL that does not contain `ai_platform_test`. CI provisions its own isolated PostgreSQL 16 test database.
Run in a separate terminal from the repository root:
## Quality checks
```bash
uv run uvicorn lead_scoring.main:app --reload --host 0.0.0.0 --port 8000
The opt-in pre-commit runner is installed by `make install` as a project-local development dependency. Run:
```sh
make check-fast
make check
```
Check the API:
`make check-fast` runs the pinned Ruff and pre-commit-hooks rules. `make check` additionally runs Python type/import checks and tests; tests must use a separate test database, never a developer or production database. CI uses the same fast hooks and the Makefile test/check commands with an isolated PostgreSQL 16 service.
```bash
curl http://localhost:8000/health
```
## Operations notes
OpenAPI UI: `http://localhost:8000/docs`
- Apply migrations as a release step; application startup must not migrate the database.
- `/health/live` is liveness; `/health/ready` checks readiness and PostgreSQL. The Compose backend health check waits for readiness.
- Avoid logging credentials, request payloads containing personal data, or provider responses with sensitive content.
- The Compose PostgreSQL volume is disposable development data. Backup, restore, retention, secrets, TLS, and alerting must be defined for the eventual deployment target.
### 4. Start the Dev Console
Run in a second terminal:
```bash
cd apps/dev-console
bun install --frozen-lockfile
bun run dev
```
Open `http://localhost:5173`.
## Local configuration
Root `.env` configures the backend. `apps/dev-console/.env` configures the Vite development server.
| Variable | Default | Purpose |
| --- | --- | --- |
| `DATABASE_URL` | PostgreSQL at `localhost:5433` | Backend database connection |
| `AIHUB_BASE_URL` | `http://localhost:8080` | Optional AIHub endpoint |
| `DEV_CONSOLE_API_URL` | `http://localhost:8000` | Dev Console API proxy target |
| `DEV_CONSOLE_PORT` | `5173` | Dev Console development port |
| `DEV_CONSOLE_PREVIEW_PORT` | `4173` | Dev Console preview port |
| `DEV_CONSOLE_SERVICE_TOKEN` | `local-dev-token` | Must match the local backend `SERVICE_CALLERS` entry |
| `DEV_CONSOLE_TEST_VKEY` | `local-test-vkey` | Forwarded only to AIHub calls; replace for real AIHub use |
The local backend template includes an allowlisted `dev-console` caller and baseline scoring config version `1.0.0`, so the Dev Console can open immediately after startup.
## Stop local services
```bash
docker compose down
```
To remove the local database data too:
```bash
docker compose down -v
```
## Verification
Backend:
```bash
uv run pytest
uv run ruff check src tests
uv run ruff format --check src tests
uv run pyright
uv run ty check
```
Frontend:
```bash
cd apps/dev-console
bun run check
bun run test
bun run build
```
The web container currently assumes `package.json`, `bun.lock`, a production SvelteKit build at `build/index.js`, and Bun compatibility with the selected SvelteKit adapter. Confirm those assumptions with the web implementation before treating the image as verified.

View File

@ -0,0 +1,43 @@
---
title: AI Platform Lead Scoring v2
description: Hành vi nhà cung cấp Lead Scoring và ranh giới với DotB-Omni trong bản rebuild.
status: review_ready
---
# Lead Scoring v2
Đặc tả này thay thế hành vi Pilot trong `old_repo/`. API còn phải được DotB-Omni kiểm tra bằng vài fixture chung trước khi coi là hợp đồng tích hợp đã phát hành. Các quyết định dưới đây đã được chốt trong kế hoạch rebuild; các giới hạn hạ tầng/AIHub chưa xác minh được ghi riêng ở cuối.
## Sở hữu
- DotB-Omni tạo snapshot, định nghĩa rules/points và rule/AI weights, score bands, HITL/review/override, quyền người dùng và hành động CRM. Omni gửi tenant key và V-Key từ backend của mình, không từ browser.
- AI Platform xác thực tenant, thực thi rules của Omni, gọi AIHub khi cần, tính rule_score/ai_score/final_score, lưu run và gửi thông báo kết thúc. Admin Web nội bộ chỉ quản lý AI profile và xem/chạy fixtures; không quản lý customer rules/review.
- DotB EMS là nguồn sự thật CRM. Omni nhận webhook terminal rồi GET chi tiết run trước khi ghi EMS. Webhook không chứa snapshot, V-Key hay AI evidence.
## Admission và idempotency
`POST /v1/lead-scoring/runs` nhận `Authorization: Bearer <tenant_key>`, `Idempotency-Key: <UUID>` và `X-Tenant-VKey` tùy chọn. Body chứa `request_id` cùng UUID, `subject_ref`, snapshot, app-defined scoring configuration (`version`, rules/points, `rule_weight`, `ai_weight`) và AI profile. Tenant được suy ra từ key xác thực, không từ body. `GET /v1/lead-scoring/runs/{run_id}` chỉ trả dữ liệu của tenant đó.
- Fingerprint SHA-256 của canonical **body Omni**; không bao gồm tenant key, V-Key hoặc AI profile do server chọn. Lookup `(tenant, request_id)` trước khi chọn profile. Cùng key/body trả run cũ mà không schedule AI; cùng key/body khác trả 409. PostgreSQL unique constraint giải quyết concurrent requests; retry admission đã commit nhưng mất response dùng cùng UUID/body.
- Run mới đóng băng AI profile đang active, INSERT + COMMIT trước khi schedule và trả 202; `Location` trỏ đến GET. Nếu không schedule được, run thành failed và response phản ánh trạng thái thực, không để pending giả. Chấm lại hoặc thử profile mới dùng UUID mới. Không reuse UUID quá 90 ngày: run và fingerprint bị xóa, không có tombstone.
- Validate chặt loại rule/operator/value, tổng weights bằng 1, score/points và dữ liệu snapshot; đầu vào sai trả 422. Snapshot tối đa 10 conversations, 50 messages, 20.000 ký tự nội dung và 90 ngày evidence; giữ thứ tự deterministic. Kích thước toàn body có hard cap. Không hard-code rule giáo dục hay category/action/review state.
## Kết quả và lỗi
- `ai_weight=0`: `rules_only`, `degraded=false`, `ai_score=null`, không gọi AIHub và không cần V-Key.
- `ai_weight>0` nhưng thiếu V-Key hoặc AIHub lỗi: `rules_only_fallback`, `degraded=true`, `ai_score/ai_confidence=null`, `final_score=rule_score`, `error_code` đã chuẩn hóa. Không tự AI retry.
- AI thành công: `hybrid`, `degraded=false`, `final_score=clamp(round(rule_score*rule_weight + ai_score*ai_weight), 0, 100)`; trả breakdown, reasoning/evidence/confidence được giới hạn. Cùng raw signals có thể ảnh hưởng cả rules lẫn AI; không gửi app rules/points vào AI prompt để hạn chế chấm hai lần.
- Bug/code/DB failure thành `failed`, không giả là AI fallback. AI profile gồm versioned model, prompts và timeout/token limits, không sở hữu app rules hoặc weights. Medium two-pass là mặc định; Light/Heavy chỉ bổ sung khi có nhu cầu và được xác minh với AIHub.
## Key, session và delivery
- Platform có một active tenant key/tenant dùng chung cho LS và feature sau này: provisioner secret server-side cấp qua `POST /v1/platform/tenant-keys`, raw trả một lần, DB chỉ có verifier/digest; cấp trùng 409. Nếu response mất sau commit, admin CLI rotate cũ/thay mới atomically; không tự rotate khi POST bị replay.
- `X-Tenant-VKey` chỉ giữ trong RAM của current scoring task và forward `Authorization: Bearer` tới AIHub. Không persist/log/trace/error/browser. V-Key không phải platform authentication. Admin session độc lập, password hash, CSRF cho mutation, cookie bảo vệ, logout/expiry và audit thay đổi config/key không kèm secrets.
- Một backend process + asyncio tasks. Startup trước readiness terminalize pending/running cũ thành `failed/worker_interrupted`; task exception cũng terminalize. V-Key không durable nên không resume AI sau crash; caller muốn làm lại dùng UUID mới.
- Terminal transition và PostgreSQL outbox event commit cùng transaction. Dispatcher gửi HMAC-signed webhook tới một Omni URL cố định với event ID/timestamp, bounded retry và dead-letter. Omni xác minh chữ ký/chống replay/dedupe, GET chi tiết và áp dụng writeback theo run mới nhất của `(tenant, subject)`; delivery replay không chấm AI lại. Không broker, dynamic subscription, polling scheduler tại Omni.
## Privacy và nghiệm thu
- Scheduled retention xóa run, snapshot, fingerprint, evidence và outbox liên quan sau 90 ngày; test xóa thật. Không lưu thông tin nhạy cảm trong payload webhook/log. Chính sách xóa tenant/offboarding và vòng đời backup phải chốt trước production; xóa DB không có nghĩa xóa ngay backup.
- Fixture chung tối thiểu: admission/replay và 409, rules-only/hybrid/fallback, failed run, webhook HMAC và Omni GET/writeback. Generated OpenAPI là nguồn schema; không lặp lại bộ schema cho từng projection không có consumer.
- Cần xác minh bằng sandbox AIHub về endpoint, strict structured output, model, timeout, quota và lỗi; Omni phải xác nhận fixture, signature/replay và writeback. Hosting, TLS, secret injection, backup/restore và alert destination chốt theo nơi deploy. Chưa khẳng định production-ready khi các điều đó chưa được kiểm chứng.

19
old_repo/.env.example Normal file
View File

@ -0,0 +1,19 @@
# Local development only. Replace all credentials in deployed environments.
ENVIRONMENT=development
DATABASE_URL=postgresql+asyncpg://postgres:postgres@localhost:5433/lead_scoring
AIHUB_BASE_URL=http://localhost:8080
DEBUG=false
# JSON arrays consumed by pydantic-settings. These values work with the Dev Console example.
SERVICE_CALLERS=[{"caller_id":"dev-console","token":"local-dev-token","allowed_apps":["dev-console"],"allowed_features":["lead-scoring"],"allowed_tenants":["omni-account-42","omni-test-tenant-42"]}]
TENANT_ALLOWLIST=["omni-account-42","omni-test-tenant-42"]
SCORING_CONFIGS=[{"version":"1.0.0","confidence":0.8,"confidence_threshold":0.7,"hitl_policy_version":"1.0.0","effort_profile":"medium","fallback_policy":"rules_only_review","ai_model":"openai/gpt-4o-mini"}]
WORKER_LEASE_SECONDS=30
WORKER_RECOVERY_INTERVAL_SECONDS=5
KILL_SWITCH_ENABLED=false
# Enable webhook delivery by setting both values.
# WEBHOOK_SUBSCRIBER_URL=http://localhost:8080/api/v1/internal/lead-scoring/events
# WEBHOOK_SIGNING_SECRET=replace-with-local-signing-secret
WEBHOOK_SIGNING_KEY_ID=pilot-2026-01

76
old_repo/.gitignore vendored Normal file
View File

@ -0,0 +1,76 @@
# Python & Virtual Environments
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
.venv/
venv/
ENV/
env/
.uv/
# Linters, Type Checkers & Test Caches
.ruff_cache/
.pytest_cache/
.mypy_cache/
.pyre/
.pytype/
.pyright/
.coverage
.coverage.*
htmlcov/
nosetests.xml
coverage.xml
*.cover
*.py,cover
# Node / Bun / Frontend
node_modules/
node_modules
apps/dev-console/node_modules
.bun/
dist-ssr/
*.local
.svelte-kit/
# Playwright & Testing Reports
playwright-report/
test-results/
blob-report/
# Environment Variables & Local Secrets
.env
.env.*
!.env.example
# Project-local
vault/
.scratch/
.codex/
docs/agents/
.claude/
CLAUDE.LOCAL.md
# Generated artifacts
/openapi.json
# IDE, OS & Editor Artifacts
.DS_Store
Thumbs.db
*.swp
*.swo
*~

1
old_repo/.python-version Normal file
View File

@ -0,0 +1 @@
3.13

172
old_repo/AGENTS.md Normal file
View File

@ -0,0 +1,172 @@
# AGENTS.md
This file provides guidance to Codex (Codex.ai/code) when working with this repository.
## Purpose and status
This repository is the Python-first AI Platform workspace. Lead Scoring is the first service; related systems are `DotB-Omni`, `lead-scoring-agent`, and `aihub` under `/home/hung/code/dotb_workspace/`.
The repository contains specifications, project documentation, and the initialized baseline for the Lead Scoring service (`src/lead_scoring/`).
Before implementing or changing Lead Scoring Customer Pilot behavior, read:
- `docs/specs/lead-scoring-customer-pilot.md`: authoritative product behavior, scope, invariants, acceptance boundaries, and cross-service ownership.
- `stack.md`: technology decisions, candidates, evidence, and unresolved stack questions. It does not override the approved specification.
The DotB Vault RFC, initial brief, Grill Brief, legacy reports, drafts, and agent messages are historical/supporting context rather than implementation authority. Exact wire formats become authoritative through released Pydantic models, generated OpenAPI/JSON Schemas, and shared fixtures.
## Communication
- Keep responses short, specific, and decision-oriented.
- Put the decision or conclusion first, followed by only the evidence and next action needed.
- Keep the main context high-signal. Put raw logs, scratch data, and long intermediate reports in `/tmp/` or the appropriate durable document.
- Use lists and compact structure when they make the result easier to scan.
- State assumptions, unresolved decisions, and verification status explicitly.
## Writing
- Write directly and precisely. Avoid buzzwords, filler, and repeated explanations.
- Comments explain intent, invariants, trade-offs, or non-obvious constraints, not syntax or line-by-line behavior.
- Do not add speculative documentation, abstractions, or metadata that the repository does not need.
- Do not use emoji or em dashes in new prose, comments, or reports. Preserve emoji and punctuation that are part of existing paths or quoted source text.
## Delegation
- Prioritize standard subagents over teammates to minimize token overhead. Spawn multiple subagents when parallel execution is genuinely needed.
- Pick the agent type matching the task from available configured agents (e.g., `explorer`, `implementer`, `tester`, `researcher`, `adversarial-reviewer`, `general`, `codebase-memory`).
- Delegate context-heavy or tool-heavy work with a clear scope, completion criteria, and evidence requirements.
- Require condensed handoffs containing conclusions, changed paths, verification, and uncertainty. Do not paste raw logs into the main context.
- The main context retains final decisions and integration responsibility. Agent messages are evidence, not user approval.
## Agent skills
### Issue tracker
Local Markdown issues are stored under `.scratch/<feature-slug>/`. See `docs/agents/issue-tracker.md`.
### Domain docs
The repository uses a single-context domain layout. See `docs/agents/domain.md`.
## Project knowledge
- `AGENTS.md` is the project map for conventions, verified commands, boundaries, and gotchas.
- `docs/specs/lead-scoring-customer-pilot.md` is the approved source of truth for Lead Scoring Customer Pilot product behavior and build boundaries.
- `stack.md` is the primary record for technology decisions and unresolved stack questions; it cannot override the approved spec.
- `docs/` contains shared project knowledge intended for version control.
- `/tmp/` is for scratch data, raw logs, and temporary handoffs.
- Released Pydantic models, generated OpenAPI/JSON Schemas, tests, and shared fixtures become the exact executable contract when they exist.
## Documentation
- Put temporary reports, raw logs, and scratch material in `/tmp/`.
- Put durable team knowledge in `docs/` and include it in version control.
- Use `vault/` only for durable project-local knowledge that must not be committed.
- New durable Markdown documents under `docs/` or `vault/` use minimal YAML frontmatter:
```yaml
---
title: Document title
description: A short description of what the document contains and when it is useful.
status: draft
tags: []
---
```
- `title` and `description` are required. For governed specs, `status` may be `draft`, `review_ready`, `approved`, or `deprecated`; other existing document schemas keep their established status vocabulary. `tags` is optional.
- Do not add metadata that Git, the filesystem, or existing tooling can derive.
- Preserve the format and metadata schema of existing documents. Do not add frontmatter, reformat, move, or normalize existing files unless the task explicitly requests migration.
- `AGENTS.md`, README files, and files with an existing schema keep their established format.
## Repository structure
- `src/lead_scoring/`: Lead Scoring production service package and CLI tools.
- `alembic/`: database migrations for PostgreSQL.
- `tests/`: test suite including health check, OpenAPI CLI, and migration lifecycle.
- `docs/specs/lead-scoring-customer-pilot.md`: approved Lead Scoring Customer Pilot specification.
- `docs/`: durable shared project documentation.
- `.scratch/`: local untracked draft specs and issue tickets used by agent skills.
- `stack.md`: technology decisions and unresolved stack questions.
- `.codex/settings.json`: project hook configuration.
- `.codex/hooks/post-edit-check.py`: Python-only PostToolUse feedback hook.
## Product and frontend boundary
The frontend boundary is approved for Customer Pilot: DotB-Omni owns all customer-facing Lead Scoring configuration and HITL UI. AI Platform may provide only an internal Dev Console for fixtures, contract testing, failure testing, and allowlisted integration verification; it must not duplicate Omni business UI.
When the internal Dev Console is implemented:
- Use Svelte 5 and TypeScript with Bun, Vite, and Vitest. Add SvelteKit only when routing, SSR, or deployment requires it.
- Generate types from backend OpenAPI and consume them through `openapi-fetch`.
- Keep shared transport concerns such as authentication and error handling outside generated code.
- Use the official Svelte tooling, including `@sveltejs/mcp` autofixer feedback and `svelte-check`.
- Use Playwright only for important end-to-end user flows.
TypeScript 7 native compiler and language server are pilot candidates, not the adopted project default. Test them project-locally before changing global runtimes or the shared `mcpls` configuration.
## Engineering principles
- Follow YAGNI. Implement only what the current requirement needs; do not add speculative abstractions, extension points, compatibility layers, or infrastructure.
- Prefer the simplest design that preserves clear boundaries and can be changed safely.
- Reuse the standard library and established, actively maintained packages when they reduce code and operational burden. Avoid dependencies for trivial behavior.
- Keep code explicit. Use precise names, short control flow, and direct data transformations. Avoid cleverness, hidden side effects, global mutable state, and premature optimization.
- Prefer composition over inheritance and functions over classes. Introduce a class only when state, lifecycle, or a framework contract genuinely requires one.
- Keep a functional core with side effects at the boundaries. Isolate I/O, persistence, network calls, clocks, and environment access.
- Organize modules by capability or domain responsibility, not by arbitrary technical layers.
- Avoid wrappers that only rename another API. Every abstraction must remove meaningful complexity or enforce a real boundary.
- Preserve one clear source of truth for contracts, configuration, and domain rules.
## AI-native code
Write code that humans and coding agents can understand with minimal hidden context:
- Make dependencies, inputs, outputs, errors, and side effects explicit.
- Use typed, stable contracts at module and service boundaries.
- Keep related implementation and tests easy to locate.
- Prefer deterministic behavior and small composable functions.
- Document decisions and non-obvious constraints, not syntax or line-by-line behavior.
- Match existing conventions before introducing a new pattern.
- Make the smallest coherent change and remove superseded code instead of leaving parallel implementations.
## Verified commands
- `uv sync`: sync workspace dependencies and environment.
- `uv run pytest`: run pytest test suite against Python 3.13.
- `uv run ruff check src tests`: run lint checks across source and tests.
- `uv run ruff format --check src tests`: check code formatting.
- `uv run pyright`: run Pyright static type checker.
- `uv run ty check`: run project-local ty type checker.
- `uv run generate-openapi`: deterministically generate root `openapi.json`.
- `uv run generate-openapi --check`: verify that `openapi.json` is present and matches the current backend contract.
- `uv run generate-webhook-contract`: deterministically generate terminal webhook contract pack.
- `uv run generate-webhook-contract --check`: verify that webhook contract pack is present and matches current models.
- `uv run generate-polling-contract`: deterministically generate scoring run polling contract pack.
- `uv run generate-polling-contract --check`: verify that polling contract pack is present and matches current models.
- `uv run generate-contract-pack`: deterministically generate the versioned shared Contract Pack.
- `uv run generate-contract-pack --validate-fixtures`: validate provider and consumer fixture expectations.
- `uv run generate-contract-pack --check`: verify the versioned Contract Pack and checksums are present and current.
- `uv run alembic upgrade head`: apply database migrations up to head.
- `uv run alembic downgrade base`: revert all database migrations.
## Deterministic generation
- When a verified project generator exists, use it instead of manually editing derived files.
- Treat OpenAPI output and generated frontend types as derived artifacts. Regenerate them from the backend contract and require the authoritative verification command to detect drift.
- Do not edit generated files manually unless the project workflow explicitly requires it.
## Safety and scope
- Inspect a path before overwriting or deleting it. Preserve existing configuration, documentation, code, and data unless the task explicitly authorizes removal or migration.
- Do not expose secrets in logs, reports, handoffs, or generated artifacts.
- Do not install packages, modify system configuration, or create permissions and background services without explicit approval.
- Bootstrap production code only after the relevant product and implementation decision. Customer-facing Lead Scoring UI remains owned by DotB-Omni.
## Tooling and verification gotchas
- Root `openapi.json` and frontend build output remain covered by the ignore policy; the versioned Contract Pack OpenAPI artifact is generated and committed, and must not be edited manually.
- The project PostToolUse hook is configured in `.codex/settings.json` for `Write` and `Edit`. It handles Python files via `ruff` (safe fix and format). Full type-checking (`pyright`, `ty`) and test suites belong to explicit verification steps. Preserve the working-tree modification to `.codex/hooks/post-edit-check.py` unless explicitly asked to change or reset it.
- Do not modify `/etc`, package-manager state, system services, drivers, kernel settings, global Node/TypeScript versions, or the shared `mcpls` configuration as part of repository work unless explicitly approved.
## Quality of life
Pyright LSP is available for semantic navigation. Use it for definitions, references, hover types, document and workspace symbols, and call hierarchy; then read the relevant implementation to understand business rules and side effects.

159
old_repo/CLAUDE.md Normal file
View File

@ -0,0 +1,159 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with this repository.
## Purpose and status
This repository is the Python-first AI Platform workspace. Lead Scoring is the first service; related systems are `DotB-Omni`, `lead-scoring-agent`, and `aihub` under `/home/hung/code/dotb_workspace/`.
The repository contains specifications, project documentation, and the initialized baseline for the Lead Scoring service (`src/lead_scoring/`).
Before implementing or changing Lead Scoring Customer Pilot behavior, read:
- `docs/specs/lead-scoring-customer-pilot.md`: authoritative product behavior, scope, invariants, acceptance boundaries, and cross-service ownership.
- `stack.md`: technology decisions, candidates, evidence, and unresolved stack questions. It does not override the approved specification.
The DotB Vault RFC, initial brief, Grill Brief, legacy reports, drafts, and agent messages are historical/supporting context rather than implementation authority. Exact wire formats become authoritative through released Pydantic models, generated OpenAPI/JSON Schemas, and shared fixtures.
## Communication
- Keep responses short, specific, and decision-oriented.
- Put the decision or conclusion first, followed by only the evidence and next action needed.
- Keep the main context high-signal. Put raw logs, scratch data, and long intermediate reports in `/tmp/` or the appropriate durable document.
- Use lists and compact structure when they make the result easier to scan.
- State assumptions, unresolved decisions, and verification status explicitly.
## Writing
- Write directly and precisely. Avoid buzzwords, filler, and repeated explanations.
- Comments explain intent, invariants, trade-offs, or non-obvious constraints, not syntax or line-by-line behavior.
- Do not add speculative documentation, abstractions, or metadata that the repository does not need.
- Do not use emoji or em dashes in new prose, comments, or reports. Preserve emoji and punctuation that are part of existing paths or quoted source text.
## Delegation
- Use the configured `researcher` agent for read-only exploration and research.
- Use the configured `primary-engineer` agent for implementation, debugging, and multi-step engineering work. If it is unavailable, use the narrowest suitable implementation agent.
- Implementation agents own TDD tests; use the `tester` agent for independent verification before completion.
- Delegate context-heavy or tool-heavy work with a clear scope, completion criteria, and evidence requirements.
- Require condensed handoffs containing conclusions, changed paths, verification, and uncertainty. Do not paste raw logs into the main context.
- The main context retains final decisions and integration responsibility. Agent messages are evidence, not user approval.
## Project knowledge
- `CLAUDE.md` is the project map for conventions, verified commands, boundaries, and gotchas.
- `docs/specs/lead-scoring-customer-pilot.md` is the approved source of truth for Lead Scoring Customer Pilot product behavior and build boundaries.
- `stack.md` is the primary record for technology decisions and unresolved stack questions; it cannot override the approved spec.
- `docs/` contains shared project knowledge intended for version control.
- `/tmp/` is for scratch data, raw logs, and temporary handoffs.
- Released Pydantic models, generated OpenAPI/JSON Schemas, tests, and shared fixtures become the exact executable contract when they exist.
## Documentation
- Put temporary reports, raw logs, and scratch material in `/tmp/`.
- Put durable team knowledge in `docs/` and include it in version control.
- Use `vault/` only for durable project-local knowledge that must not be committed.
- New durable Markdown documents under `docs/` or `vault/` use minimal YAML frontmatter:
```yaml
---
title: Document title
description: A short description of what the document contains and when it is useful.
status: draft
tags: []
---
```
- `title` and `description` are required. For governed specs, `status` may be `draft`, `review_ready`, `approved`, or `deprecated`; other existing document schemas keep their established status vocabulary. `tags` is optional.
- Do not add metadata that Git, the filesystem, or existing tooling can derive.
- Preserve the format and metadata schema of existing documents. Do not add frontmatter, reformat, move, or normalize existing files unless the task explicitly requests migration.
- `CLAUDE.md`, README files, and files with an existing schema keep their established format.
## Repository structure
- `src/lead_scoring/`: Lead Scoring production service package and CLI tools.
- `alembic/`: database migrations for PostgreSQL.
- `tests/`: test suite including health check, OpenAPI CLI, and migration lifecycle.
- `docs/specs/lead-scoring-customer-pilot.md`: approved Lead Scoring Customer Pilot specification.
- `docs/`: durable shared project documentation.
- `stack.md`: technology decisions and unresolved stack questions.
- `.claude/settings.json`: project hook configuration.
- `.claude/hooks/post-edit-check.py`: Python-only PostToolUse feedback hook.
## Product and frontend boundary
The frontend boundary is approved for Customer Pilot: DotB-Omni owns all customer-facing Lead Scoring configuration and HITL UI. AI Platform may provide only an internal Dev Console for fixtures, contract testing, failure testing, and allowlisted integration verification; it must not duplicate Omni business UI.
When the internal Dev Console is implemented:
- Use Svelte 5 and TypeScript with Bun, Vite, and Vitest. Add SvelteKit only when routing, SSR, or deployment requires it.
- Generate types from backend OpenAPI and consume them through `openapi-fetch`.
- Keep shared transport concerns such as authentication and error handling outside generated code.
- Use the official Svelte tooling, including `@sveltejs/mcp` autofixer feedback and `svelte-check`.
- Use Playwright only for important end-to-end user flows.
TypeScript 7 native compiler and language server are pilot candidates, not the adopted project default. Test them project-locally before changing global runtimes or the shared `mcpls` configuration.
## Engineering principles
- Follow YAGNI. Implement only what the current requirement needs; do not add speculative abstractions, extension points, compatibility layers, or infrastructure.
- Prefer the simplest design that preserves clear boundaries and can be changed safely.
- Reuse the standard library and established, actively maintained packages when they reduce code and operational burden. Avoid dependencies for trivial behavior.
- Keep code explicit. Use precise names, short control flow, and direct data transformations. Avoid cleverness, hidden side effects, global mutable state, and premature optimization.
- Prefer composition over inheritance and functions over classes. Introduce a class only when state, lifecycle, or a framework contract genuinely requires one.
- Keep a functional core with side effects at the boundaries. Isolate I/O, persistence, network calls, clocks, and environment access.
- Organize modules by capability or domain responsibility, not by arbitrary technical layers.
- Avoid wrappers that only rename another API. Every abstraction must remove meaningful complexity or enforce a real boundary.
- Preserve one clear source of truth for contracts, configuration, and domain rules.
## AI-native code
Write code that humans and coding agents can understand with minimal hidden context:
- Make dependencies, inputs, outputs, errors, and side effects explicit.
- Use typed, stable contracts at module and service boundaries.
- Keep related implementation and tests easy to locate.
- Prefer deterministic behavior and small composable functions.
- Document decisions and non-obvious constraints, not syntax or line-by-line behavior.
- Match existing conventions before introducing a new pattern.
- Make the smallest coherent change and remove superseded code instead of leaving parallel implementations.
## Verified commands
- `uv sync`: sync workspace dependencies and environment.
- `uv run pytest`: run pytest test suite against Python 3.13.
- `uv run ruff check src tests`: run lint checks across source and tests.
- `uv run ruff format --check src tests`: check code formatting.
- `uv run pyright`: run Pyright static type checker.
- `uv run ty check`: run project-local ty type checker.
- `uv run generate-openapi`: deterministically generate root `openapi.json`.
- `uv run generate-openapi --check`: verify that `openapi.json` is present and matches the current backend contract.
- `uv run generate-webhook-contract`: deterministically generate terminal webhook contract pack.
- `uv run generate-webhook-contract --check`: verify that webhook contract pack is present and matches current models.
- `uv run generate-polling-contract`: deterministically generate scoring run polling contract pack.
- `uv run generate-polling-contract --check`: verify that polling contract pack is present and matches current models.
- `uv run alembic upgrade head`: apply database migrations up to head.
- `uv run alembic downgrade base`: revert all database migrations.
## Deterministic generation
- When a verified project generator exists, use it instead of manually editing derived files.
- Treat OpenAPI output and generated frontend types as derived artifacts. Regenerate them from the backend contract and require the authoritative verification command to detect drift.
- Do not edit generated files manually unless the project workflow explicitly requires it.
## Safety and scope
- Inspect a path before overwriting or deleting it. Preserve existing configuration, documentation, code, and data unless the task explicitly authorizes removal or migration.
- Do not expose secrets in logs, reports, handoffs, or generated artifacts.
- Do not install packages, modify system configuration, or create permissions and background services without explicit approval.
- Bootstrap production code only after the relevant product and implementation decision. Customer-facing Lead Scoring UI remains owned by DotB-Omni.
## Tooling and verification gotchas
- Generated OpenAPI and frontend build output must remain covered by the existing ignore policy and should not be edited manually.
- The project PostToolUse hook is configured in `.claude/settings.json` for `Write` and `Edit`. It currently handles Python files only and invokes the existing `ruff` and `ty` tools. Preserve the pre-existing working-tree modification to `.claude/hooks/post-edit-check.py` unless explicitly asked to change or reset it.
- Do not modify `/etc`, package-manager state, system services, drivers, kernel settings, global Node/TypeScript versions, or the shared `mcpls` configuration as part of repository work unless explicitly approved.
## Quality of life
Pyright LSP is available for semantic navigation. Use it for definitions, references, hover types, document and workspace symbols, and call hierarchy; then read the relevant implementation to understand business rules and side effects.

133
old_repo/README.md Normal file
View File

@ -0,0 +1,133 @@
# AI Platform - Lead Scoring Service
Lead Scoring service and internal Dev Console for the AI Platform.
## What runs locally
| Component | Purpose | Default address |
| --- | --- | --- |
| PostgreSQL 16 | Stores scoring runs and migrations | `localhost:5433` |
| Lead Scoring API | REST API, async scoring worker, OpenAPI | `http://localhost:8000` |
| Dev Console | Internal fixture and contract-testing UI | `http://localhost:5173` |
| AIHub | Optional external AI inference dependency | `http://localhost:8080` |
The service still runs if local AIHub is unavailable: the default config uses `rules_only_review` fallback. A reachable AIHub and a valid tenant VKey are required for live AI scoring.
## Requirements
Install before starting:
- Git
- Python 3.13 or newer
- [uv](https://docs.astral.sh/uv/)
- [Bun](https://bun.sh/)
- Docker with Docker Compose plugin
## Start from a fresh clone
```bash
git clone https://github.com/HungTran24/dotb_ai-platform.git
cd dotb_ai-platform
cp .env.example .env
cp apps/dev-console/.env.example apps/dev-console/.env
```
The copied `.env` files are local only and ignored by Git. Their example values are intentionally for development only.
### 1. Start PostgreSQL
```bash
docker compose up -d postgres
docker compose ps
```
The included Compose service exposes PostgreSQL on port `5433` to avoid conflicting with other local projects. If port `5433` is occupied, choose another port and update both values before migration:
```bash
POSTGRES_PORT=15432 docker compose up -d postgres
# Then set DATABASE_URL=postgresql+asyncpg://postgres:postgres@localhost:15432/lead_scoring in .env
```
### 2. Install backend dependencies and migrate the database
```bash
uv sync
uv run alembic upgrade head
```
### 3. Start the Lead Scoring API
Run in a separate terminal from the repository root:
```bash
uv run uvicorn lead_scoring.main:app --reload --host 0.0.0.0 --port 8000
```
Check the API:
```bash
curl http://localhost:8000/health
```
OpenAPI UI: `http://localhost:8000/docs`
### 4. Start the Dev Console
Run in a second terminal:
```bash
cd apps/dev-console
bun install --frozen-lockfile
bun run dev
```
Open `http://localhost:5173`.
## Local configuration
Root `.env` configures the backend. `apps/dev-console/.env` configures the Vite development server.
| Variable | Default | Purpose |
| --- | --- | --- |
| `DATABASE_URL` | PostgreSQL at `localhost:5433` | Backend database connection |
| `AIHUB_BASE_URL` | `http://localhost:8080` | Optional AIHub endpoint |
| `DEV_CONSOLE_API_URL` | `http://localhost:8000` | Dev Console API proxy target |
| `DEV_CONSOLE_PORT` | `5173` | Dev Console development port |
| `DEV_CONSOLE_PREVIEW_PORT` | `4173` | Dev Console preview port |
| `DEV_CONSOLE_SERVICE_TOKEN` | `local-dev-token` | Must match the local backend `SERVICE_CALLERS` entry |
| `DEV_CONSOLE_TEST_VKEY` | `local-test-vkey` | Forwarded only to AIHub calls; replace for real AIHub use |
The local backend template includes an allowlisted `dev-console` caller and baseline scoring config version `1.0.0`, so the Dev Console can open immediately after startup.
## Stop local services
```bash
docker compose down
```
To remove the local database data too:
```bash
docker compose down -v
```
## Verification
Backend:
```bash
uv run pytest
uv run ruff check src tests
uv run ruff format --check src tests
uv run pyright
uv run ty check
```
Frontend:
```bash
cd apps/dev-console
bun run check
bun run test
bun run build
```

79
old_repo/alembic.ini Normal file
View File

@ -0,0 +1,79 @@
# A generic, single database configuration.
[alembic]
# path to migration scripts
script_location = %(here)s/alembic
# template used to generate migration file names; The default value is %%(rev)s_%%(slug)s
# file_template = %%(rev)s_%%(slug)s
# sys.path path, will be prepended to sys.path if present.
prepend_sys_path = %(here)s
path_separator = os
# timezone to use when rendering the date within the migration file
# as well as the filename.
# string value is passed to dateutil.tz.gettz()
# leave blank for localtime
# timezone =
# max length of characters to apply to the
# "slug" field
# truncate_slug_length = 40
# set to 'true' to run the environment during
# the 'revision' command, regardless of autogenerate
# revision_environment = false
# set to 'true' to allow .pyc and .pyo files without
# a source .py file to be detected as revisions in the
# versions/ directory
# sourceless = false
# version location specification; This defaults
# to alembic/versions. When using multiple version
# directories, initial revisions must be specified with --version-path.
# The path separator used here should be the separator specified by "version_path_separator"
# version_locations = %(here)s/bar:%(here)s/bat:alembic/versions
# version path separator
version_path_separator = os
# the output encoding used when revision files
# are written from script.py.mako
# output_encoding = utf-8
# Logging configuration
[loggers]
keys = root,sqlalchemy,alembic
[handlers]
keys = console
[formatters]
keys = generic
[logger_root]
level = WARN
handlers = console
qualname =
[logger_sqlalchemy]
level = WARN
handlers =
qualname = sqlalchemy.engine
[logger_alembic]
level = INFO
handlers =
qualname = alembic
[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic
[formatter_generic]
format = %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %H:%M:%S

View File

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

View File

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

View File

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

Before

Width:  |  Height:  |  Size: 125 KiB

After

Width:  |  Height:  |  Size: 125 KiB

View File

Before

Width:  |  Height:  |  Size: 98 KiB

After

Width:  |  Height:  |  Size: 98 KiB

View File

Before

Width:  |  Height:  |  Size: 155 KiB

After

Width:  |  Height:  |  Size: 155 KiB

View File

Before

Width:  |  Height:  |  Size: 108 KiB

After

Width:  |  Height:  |  Size: 108 KiB

14
old_repo/compose.yaml Normal file
View File

@ -0,0 +1,14 @@
services:
postgres:
image: postgres:16-alpine
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: lead_scoring
ports:
- "${POSTGRES_PORT:-5433}:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d lead_scoring"]
interval: 5s
timeout: 5s
retries: 10

Some files were not shown because too many files have changed in this diff Show More