first
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
# ADR-0001 — Monorepo Structure for ASF
|
||||
|
||||
- **Status:** Accepted
|
||||
- **Date:** 2026-09-07
|
||||
- **Deciders:** ASF Architecture Team
|
||||
|
||||
## Context
|
||||
|
||||
Azurian Software Factory comprises several logical components:
|
||||
a shared domain model, an event schema package, connectors, multiple backend services
|
||||
(core, context, ai, worker) and a Next.js web frontend.
|
||||
|
||||
We must choose a repository organization that balances:
|
||||
- Strong cohesion for shared types / contracts
|
||||
- Independent deployability of services
|
||||
- Local developer ergonomics
|
||||
- Clear service boundaries
|
||||
|
||||
## Decision
|
||||
|
||||
Use a **single monorepo** with the following top-level layout:
|
||||
|
||||
```
|
||||
ASF/
|
||||
├── frontend/asf-web/ # Next.js SaaS UI
|
||||
├── services/ # Deployable Python services
|
||||
│ ├── asf-core/
|
||||
│ ├── asf-context/
|
||||
│ ├── asf-ai/
|
||||
│ └── asf-worker/
|
||||
├── packages/ # Shared installable Python packages
|
||||
│ ├── asf-domain/
|
||||
│ ├── asf-events/
|
||||
│ └── asf-connectors/
|
||||
├── docs/ # Architecture, ADRs, API docs
|
||||
├── infrastructure/ # Dockerfiles, scripts
|
||||
└── tests/ # Cross-service integration tests
|
||||
```
|
||||
|
||||
Shared packages are installed in editable mode (`pip install -e`) when
|
||||
developing locally.
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- Shared domain models and event schemas live in one place — no drift.
|
||||
- Refactors that cross service boundaries are done atomically in one PR.
|
||||
- Local `docker-compose` up brings up the whole stack trivially.
|
||||
- Search / navigation works across the whole product.
|
||||
|
||||
### Negative
|
||||
- CI pipelines must be careful to only rebuild what changed.
|
||||
- Service release tagging must be explicit (single git log, many artefacts).
|
||||
|
||||
### Risks / Mitigations
|
||||
- Accidental tight coupling between services → mitigated by code review,
|
||||
AGENT.md rules, and keeping services import only from `packages/*`, never
|
||||
from each other.
|
||||
@@ -0,0 +1,63 @@
|
||||
# ADR-0002 — MongoDB as Primary Persistence
|
||||
|
||||
- **Status:** Accepted
|
||||
- **Date:** 2026-09-07
|
||||
- **Deciders:** ASF Architecture Team
|
||||
|
||||
## Context
|
||||
|
||||
ASF requires a primary store for Organizations, Projects, Artifacts,
|
||||
ArtifactRelationships, Jobs, AuditEvents and similar tenant-scoped records.
|
||||
|
||||
Key properties required:
|
||||
- Flexible schema: the generic `Artifact` model needs extensible `metadata`.
|
||||
- Document-level locality: an Artifact document bundles relationships list,
|
||||
metadata and version.
|
||||
- Horizontal scaling and multi-tenancy (every query is scoped by `tenant_id`).
|
||||
- Async/await Python driver support.
|
||||
|
||||
## Decision
|
||||
|
||||
Adopt **MongoDB 7.x** as the only primary operational database.
|
||||
|
||||
Use compound indexes prefixed with `tenant_id` for all tenant-owned
|
||||
collections. Collections are intentionally few:
|
||||
- `organizations`
|
||||
- `users`
|
||||
- `teams`
|
||||
- `projects`
|
||||
- `artifacts`
|
||||
- `artifact_relationships`
|
||||
- `integrations`
|
||||
- `jobs`
|
||||
- `ai_executions`
|
||||
- `audit_events`
|
||||
|
||||
**We do NOT** create a collection per artifact type. Every artifact type
|
||||
(requirement, task, commit, test, deployment…) lives in the single
|
||||
`artifacts` collection discriminated by `type`.
|
||||
|
||||
MinIO holds large binaries / reports; MongoDB stores the object reference
|
||||
and metadata.
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- Flexible `metadata` on Artifacts matches the "Everything is an Artifact"
|
||||
principle without schema migrations for every new artifact subtype.
|
||||
- Compound `(tenant_id, project_id, …)` indexes give fast tenant-scoped
|
||||
reads and guarantee isolation at query time.
|
||||
- Native async driver (`motor`) integrates naturally with FastAPI.
|
||||
|
||||
### Negative
|
||||
- No foreign-key constraints across collections — referential integrity is
|
||||
an application responsibility (mitigated via service-layer validations
|
||||
and tests).
|
||||
- Relationship graph traversal requires multiple queries or the
|
||||
`$graphLookup` aggregation stage. The schema is intentionally designed
|
||||
so that a future graph-database projection is possible without rewriting
|
||||
domain logic.
|
||||
|
||||
### Follow-up
|
||||
- ADR for graph-database introduction once traversal patterns stabilize.
|
||||
- ADR for vector / embedding store (Semantic Context Engine phase).
|
||||
@@ -0,0 +1,61 @@
|
||||
# ADR-0003 — RabbitMQ as Event and Job Backbone
|
||||
|
||||
- **Status:** Accepted
|
||||
- **Date:** 2026-09-07
|
||||
- **Deciders:** ASF Architecture Team
|
||||
|
||||
## Context
|
||||
|
||||
ASF has two asynchronous messaging needs:
|
||||
1. **Domain events** (facts that happened — `artifact.created`,
|
||||
`deployment.completed`, …) used for decoupled side effects.
|
||||
2. **Asynchronous jobs** (AI inference, indexing, code analysis, testing)
|
||||
that need separate queues with priorities and horizontal workers.
|
||||
|
||||
A single backbone that handles both patterns is preferred to reduce
|
||||
infrastructure surface.
|
||||
|
||||
## Decision
|
||||
|
||||
Adopt **RabbitMQ 3.13+** as the sole event/job backbone.
|
||||
|
||||
### Logical queues
|
||||
|
||||
| Queue | Purpose | Priority |
|
||||
|------------------------|----------------------------------------|----------|
|
||||
| `asf.ai.interactive` | Latency-sensitive user-facing AI work | High |
|
||||
| `asf.ai.background` | Batch / low-priority AI work | Normal |
|
||||
| `asf.indexing` | Repository / document indexing | Low |
|
||||
| `asf.code_analysis` | Static analysis tasks | Normal |
|
||||
| `asf.testing` | Test execution requests | Normal |
|
||||
| `asf.devops` | Deployment / CI orchestration | Normal |
|
||||
| `asf.notifications` | Emails / webhooks / in-app notif. | Normal |
|
||||
|
||||
### Source of truth
|
||||
RabbitMQ delivers work. **Persistent job state** (status, timestamps,
|
||||
usage, error, correlation) lives in MongoDB `jobs` collection. Workers
|
||||
update Mongo as they progress through `queued → running → completed|failed`.
|
||||
|
||||
RabbitMQ is **never** the permanent system of record for job state.
|
||||
|
||||
### Event format
|
||||
Every event message contains:
|
||||
```
|
||||
event_id, event_type, timestamp, tenant_id, project_id?,
|
||||
correlation_id, causation_id?, payload
|
||||
```
|
||||
|
||||
Large payloads / binaries go to MinIO; the message carries only a
|
||||
reference.
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- One broker, well-understood routing / priority / TTL / DLX semantics.
|
||||
- Workers are stateless, horizontally scalable processes.
|
||||
- At-least-once delivery matches domain; idempotency keys on workers
|
||||
prevent duplicate side-effects.
|
||||
|
||||
### Negative
|
||||
- Exactly-once is not provided — consumers must be idempotent.
|
||||
- Operational complexity of a broker (mitigated by managed services in prod).
|
||||
@@ -0,0 +1,65 @@
|
||||
# ADR-0004 — AI Gateway Abstraction Layer
|
||||
|
||||
- **Status:** Accepted
|
||||
- **Date:** 2026-09-07
|
||||
- **Deciders:** ASF Architecture Team
|
||||
|
||||
## Context
|
||||
|
||||
ASF requires LLM capabilities for:
|
||||
- Code analysis
|
||||
- Requirement decomposition
|
||||
- Test generation
|
||||
- Context-aware chat ("Ask ASF")
|
||||
- Incident analysis
|
||||
|
||||
Target inference backends include on-prem DGX Spark, OpenAI-compatible
|
||||
local APIs, commercial providers, and customer-hosted endpoints.
|
||||
|
||||
Tenants may have different AI policies (allowed models, budgets,
|
||||
geographic restrictions).
|
||||
|
||||
## Decision
|
||||
|
||||
Introduce an **ASF AI Gateway** service (`services/asf-ai/`) with a
|
||||
stable Python interface.
|
||||
|
||||
### Interface
|
||||
|
||||
Business code requests **capabilities**, never models:
|
||||
|
||||
```python
|
||||
class AIGateway(Protocol):
|
||||
async def analyze_code(self, request: CodeAnalysisRequest) -> AnalysisResult: ...
|
||||
async def generate_tests(self, request: TestGenerationRequest) -> GeneratedTests: ...
|
||||
async def chat(self, request: ChatRequest, ctx: AIContext) -> ChatResponse: ...
|
||||
async def decompose_requirement(self, req: RequirementDecomposeRequest) -> Decomposition: ...
|
||||
```
|
||||
|
||||
Provider adapters implement the gateway. Model selection, routing,
|
||||
priority queuing, usage metering, cost tracking and tenant AI policy
|
||||
live inside the gateway — not in callers.
|
||||
|
||||
### Bootstrap
|
||||
|
||||
The first implementation ships with a `MockProvider` that returns
|
||||
deterministic canned responses with realistic latencies. Real providers
|
||||
(OpenAI-compatible, NVIDIA, etc.) are added as adapters later without
|
||||
touching domain/business code.
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- No LLM provider lock-in — swap / add adapters freely.
|
||||
- Usage and cost tracking centralized.
|
||||
- Tenant-level policy enforceable at one boundary.
|
||||
- Tests for business logic run fast against the mock — no external API
|
||||
calls, no flakiness.
|
||||
|
||||
### Negative
|
||||
- One more abstraction — the initial API surface must be designed
|
||||
carefully so future providers truly fit.
|
||||
|
||||
### Mitigation
|
||||
- Provider adapters are written early for at least two real providers,
|
||||
to validate the abstraction before domain code depends heavily on it.
|
||||
@@ -0,0 +1,113 @@
|
||||
# ASF Architecture Overview
|
||||
|
||||
> Metafora "**Ufficio Postale di ASF**":
|
||||
>
|
||||
> Ogni informazione che entra o esce da ASF è una **busta (Artifact)**.
|
||||
> Le **Relazioni** sono gli indirizzi che legano una busta all'altra.
|
||||
> RabbitMQ è il **carteggio** (posta interna), MongoDB l'**archivio**,
|
||||
> l'AI Gateway è l'**ufficio analisti** che legge le buste e risponde,
|
||||
> il Context Engine è l'**impiegato che raccoglie il fascicolo completo**
|
||||
> prima di passarlo a un analista.
|
||||
|
||||
## Logical Diagram (ASCII)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ asf-web (Next.js) │
|
||||
│ Shell · Overview · Context Explorer · │
|
||||
│ Traceability (React Flow) · Ask ASF chat │
|
||||
└────────────────────┬────────────────────────┘
|
||||
│ HTTPS /api/v1
|
||||
┌────────────────────▼────────────────────────┐
|
||||
│ asf-core (FastAPI REST API) │
|
||||
│ Orgs · Projects · Artifacts · Relations · │
|
||||
│ Jobs CRUD · Audit · Auth boundary │
|
||||
└──────┬───────────────┬───────────┬───────────┘
|
||||
│ │ │
|
||||
(writes/reads)│ (events) │ (queries)│
|
||||
▼ ▼ ▼
|
||||
┌─────────────┐ ┌────────────┐ ┌───────────────┐
|
||||
│ MongoDB │ │ RabbitMQ │ │ asf-context │
|
||||
│ (archivio) │ │ (carteggio)│ │ (fascicolatore)│
|
||||
└─────────────┘ └──────┬─────┘ └───────┬───────┘
|
||||
│ │
|
||||
(jobs) │ │ assemble context
|
||||
▼ │
|
||||
┌───────────────────┐ │
|
||||
│ asf-worker │ │
|
||||
│ (addetti alle poste)│ │
|
||||
│ consumers: │ │
|
||||
│ ai.*, indexing, │ │
|
||||
│ testing, devops │ │
|
||||
└─────────┬─────────┘ │
|
||||
│ │
|
||||
(inference reqs) │
|
||||
▼ │
|
||||
┌───────────────────┐ │
|
||||
│ asf-ai │◄──────┘
|
||||
│ AI Gateway │
|
||||
│ (ufficio analisti)│
|
||||
│ ├─ MockProvider │
|
||||
│ ├─ model routing │
|
||||
│ └─ usage/cost │
|
||||
└─────────┬─────────┘
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────┐
|
||||
│ Provider adapters (future): │
|
||||
│ · NVIDIA DGX / OpenAI compat │
|
||||
│ · External providers │
|
||||
└───────────────────────────────┘
|
||||
|
||||
┌────────────────────────────────────────────────────────────────┐
|
||||
│ Shared packages (imported by all services): │
|
||||
│ · asf-domain → Pydantic models (Artifact, Job, Org, ...) │
|
||||
│ · asf-events → Event schemas (RabbitMQ payload contracts) │
|
||||
│ · asf-connectors → Integration interfaces (GitHub, Jira, ...) │
|
||||
└────────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌─────────────────────────────┐
|
||||
│ Supporting infrastructure │
|
||||
│ · Redis (cache / locks) │
|
||||
│ · MinIO (large blobs) │
|
||||
└─────────────────────────────┘
|
||||
```
|
||||
|
||||
## Data Flow — end-to-end (Example: "Crea un Requirement")
|
||||
|
||||
1. User POST `/api/v1/projects/{p_id}/artifacts` (type=`requirement`)
|
||||
via **asf-web** → **asf-core**.
|
||||
2. **asf-core** validates tenant context, writes to MongoDB `artifacts`,
|
||||
emits `artifact.created` event to RabbitMQ, returns `201`.
|
||||
3. **asf-worker** picks up `artifact.created` from the events exchange.
|
||||
4. Worker optionally submits `ai.inference.requested` for "enrich
|
||||
requirement" to `asf.ai.background` queue.
|
||||
5. Another worker calls **asf-ai** gateway → provider → returns
|
||||
enrichment. Updates `artifact.metadata.enriched = true`, writes an
|
||||
`artifact.updated` event, records an `AIExecution` in MongoDB.
|
||||
6. UI polls / SSE receives update; Context Explorer now shows both the
|
||||
Artifact AND its enrichment trace.
|
||||
|
||||
## Tenancy Boundary
|
||||
|
||||
```
|
||||
Organization (tenant_id == organization_id in bootstrap)
|
||||
│
|
||||
├── Team[]
|
||||
└── Project[]
|
||||
└── Artifact[] + ArtifactRelationship[] + Job[]
|
||||
```
|
||||
|
||||
**Rule:** Ogni query su dati tenant-owned è filtrata da `tenant_id`.
|
||||
Il `tenant_id` non viene mai accettato dal client direttamente ma
|
||||
deriva dal contesto di autenticazione validato.
|
||||
|
||||
## Extensibility Points
|
||||
|
||||
| Concern | Where | Future Hook |
|
||||
|-----------------------|----------------------------|--------------------------------|
|
||||
| Semantic search / RAG | asf-context | Vector DB (pgvector / Qdrant) |
|
||||
| Graph traversal | asf-context (Mongo $lookup)| Graph DB projection |
|
||||
| Auth / SSO | asf-core middleware | OIDC / SAML adapters |
|
||||
| Billing / metering | asf-core + asf-ai usage | Subscription service |
|
||||
| External providers | asf-connectors + AI Gateway| Per-system adapter |
|
||||
Reference in New Issue
Block a user