Aller au contenu

Composition root

La composition root assemble toutes les dépendances d’arka-deck en un graphe vivant. Elle instancie les adapters, les use-cases, les addons, et les câble via injection de dépendances manuelle.

Source de vérité : composition/core-container.ts, composition/web-container.ts.


ContainerRôle
createCoreContainer(deps)Instancie le cœur : event bus, adapters outbound (stores, clients), use-cases inbound, addons first-party
createWebContainer(coreContainer, deps)Instancie la couche serveur web : Fastify, routes, état UI courant (workspace + projet)

Le coreContainer est utilisable sans serveur web (par exemple en CLI ou en tests). Le webContainer ajoute la couche transport HTTP.


1. Adapters infrastructure
├── Clock (FsClock)
├── IdGenerator (UuidIdGenerator)
├── Filesystem (FsFilesystem avec allowlist)
├── ArkaHome (~/.arka-deck/ ou ARKA_DECK_HOME)
└── SecretCipher (AesSecretCipher)
2. Event bus
└── InMemoryEventBus
3. Stores prod
├── FsProjectStore, FsProjectIndexStore, FsWorkspaceStore
├── SqliteChatSessionStore
├── SqliteArkadocStore, SqliteArkadocManifestStore
└── SqliteConnectorInstallationStore, etc.
4. Clients HTTP Cortex
├── HttpCatalogueClient, HttpCatalogueBlocsClient
├── HttpArkadocCortexClient, HttpAtomsClient
└── HttpCortexLiteRuntimeContextClient
5. Provider hub
└── HttpProviderHub (registre + lifecycle providers LLM)
6. Use-cases inbound
├── buildForProjects, buildForWorkspaces
├── buildForChat, buildForCatalogue
├── buildForArkadoc, buildForSquads, buildForMissionGuardian
└── ... (tous les for-*.ts implémentés)
7. Addons first-party
├── registerCortexActionsAddon
├── registerCortexLiteAddon
├── registerMemoryLocalAddon
├── registerGouvernanceLiteAddon
├── registerSquadLeaderAddon
├── registerSquadOrchestrationAddon
└── registerNotionConnectAddon
8. Materializers
├── ClaudeAgentWorkspaceMaterializer
├── HookWorkspaceMaterializer
└── SkillWorkspaceMaterializer

composition/ est le seul dossier autorisé à importer simultanément depuis :

  • core/ (ports, use-cases, domain)
  • adapters/ (outbound + inbound)
  • addons/ (registers)
  • providers/ (runtimes)

Les autres dossiers respectent strictement les frontières (cf. ADR 0001).


Le pattern type pour câbler un addon dans la composition :

// composition/core-container.ts (extrait simplifié)
import { registerCortexActionsAddon } from '../addons/cortex-actions/src/index.js';
export async function createCoreContainer(deps): Promise<CoreContainer> {
// ... infrastructure, event bus, stores
const cortexActionsRuntime = registerCortexActionsAddon({
clock,
filesystem,
eventBus,
idGenerator,
resolveSession: (sessionId) =>
chatSessionStore.getSession(sessionId).then((s) => s?.projectPath ?? null),
cortexBaseUrl: process.env.ARKA_DECK_CORTEX_URL,
});
// Enregistrer le runtime dans le registre d'addons
addonRegistry.registerRuntime('cortex-actions', cortexActionsRuntime);
return { /* ... */ };
}

Si l’addon expose des routes HTTP, leur câblage vit dans composition/addons/<name>-routes.ts et est appelé depuis web-container.ts.


PhaseAction
BootcreateCoreContainer instancie le graphe, démarre les abonnements bus
RunLes routes consomment les use-cases via le container
ShutdowncoreContainer.dispose() appelle les unsubscribe() des addons et ferme les ressources (SQLite, sidecars)