Αρχιτεκτονική
Επισκόπηση
Ενότητα με τίτλο «Επισκόπηση»Το Control Center ακολουθεί Καθαρή Αρχιτεκτονική με προτεραιότητα στα χαρακτηριστικά και μοτίβο θυρών και προσαρμογέων. Η βάση κώδικα είναι οργανωμένη γύρω από επιχειρηματικούς τομείς (χαρακτηριστικά), με αυστηρούς κανόνες εξαρτήσεων που επιβάλλονται από ένα αυτοματοποιημένο τεστ αρχιτεκτονικής.
Ένας λεπτός πελάτης πάνω από έναν headless διακομιστή
Ενότητα με τίτλο «Ένας λεπτός πελάτης πάνω από έναν headless διακομιστή»Το Control Center είναι αρχιτεκτονική λεπτού πελάτη. Κανένας πελάτης δεν ανοίγει τη βάση δεδομένων — μια headless διεργασία cc_server κατέχει τα δεδομένα (μια μικρή global.db συν ένα αρχείο SQLite ανά χώρο εργασίας, που ανοίγει με καθυστέρηση) και τα σερβίρει μέσω WebSocket RPC. Η εφαρμογή για υπολογιστή, η έκδοση για web και ο σύντροφος για το τηλέφωνο είναι όλα στρώματα απόδοσης πάνω από αυτή τη μία σύνδεση RPC.
Η επιτραπέζια εφαρμογή επιλέγει πώς φτάνει στον διακομιστή της κατά την πρώτη εκκίνηση: τοπικά (εκκινεί ένα cc_server σε αυτό το μηχάνημα και συνομιλεί μέσω loopback — η προεπιλογή) ή απομακρυσμένα (καλεί ένα cc_server αλλού μέσω ασφαλούς WebSocket). Ο πελάτης web είναι πάντα απομακρυσμένος. Ο επιλυτής εκκίνησης (bootstrap/server_backend.dart) επιλέγει τη διαδρομή προτού υπάρξει το Riverpod και έπειτα αντικαθιστά το rpcClientProvider με τον συνδεδεμένο πελάτη — έτσι κάθε χαρακτηριστικό διαβάζει και γράφει μέσω του διακομιστή και όχι μέσω τοπικής βάσης δεδομένων.
Το ίδιο το επίπεδο RPC είναι χωρίς κατάσταση: μια συνεδρία ταυτοποιείται, αλλά δεν δεσμεύεται σε κάποιον χώρο εργασίας. Κάθε κλήση με εμβέλεια χώρου εργασίας φέρει το δικό της workspace_id στα ορίσματά της και ο διανομέας αρνείται μια τέτοια κλήση χωρίς αυτό. Αυτό επιτρέπει σε δύο πελάτες σε έναν διακομιστή να κρατούν διαφορετικούς ενεργούς χώρους εργασίας χωρίς έναν «τρέχοντα χώρο εργασίας» που θα κρατούσε ο διακομιστής και για τον οποίο θα διαφωνούσαν — και σημαίνει ότι η απομόνωση επιβάλλεται ανά κλήση και όχι ανά σύνδεση.
Πρόκειται για ένα Dart workspace με ένα ενιαίο επιλυμένο lockfile και είκοσι ένα μέλη — δεκαπέντε πακέτα και έξι εφαρμογές — με ρίζα του workspace την εφαρμογή για υπολογιστή και web (control_center). Οι έξι εφαρμογές είναι το headless δυαδικό του διακομιστή (cc_server), ο headless εκτελεστής στόλου (cc_worker), η PWA για το τηλέφωνο (cc_remote), ο διαμεσολαβητής αναμετάδοσης WebSocket (cc_signaling_server), η γκαλερί Widgetbook (cc_gallery) και ο δημόσιος κεντρικός υπολογιστής επίδειξης (cc_demo_server). Τα δεκαπέντε πακέτα είναι τα cc_ui (σύστημα σχεδίασης), cc_domain (κοινός πυρήνας σε καθαρή Dart: οντότητες, αντικείμενα τιμής, θύρες, συμβάντα και το επίπεδο τομέα κάθε χαρακτηριστικού), cc_harness (ο ενσωματωμένος πυρήνας πρακτόρων: βρόχος πράκτορα σε καθαρή Dart — μηνύματα, θύρα παρόχου, εργαλεία, συμπύκνωση, καθοδήγηση, άγκιστρα, υποπράκτορες — χωρίς dart:io και χωρίς άλλη εξάρτηση cc_*), cc_harness_runtime (ο ενσωματωμένος προσαρμογέας χρόνου εκτέλεσης του μηχανισμού: πάροχοι ροής μόνο για VM, μεσιτεία διαπιστευτηρίων OAuth/PKCE, χώροι αποθήκευσης διαπιστευτηρίων και το γενικό σύνολο εργαλείων — εκτελεί πράκτορες χωρίς εγκατεστημένο εξωτερικό CLI), cc_rpc (μεταφορές πελάτη), cc_host (πυρήνας διακομιστή), cc_data (απομακρυσμένα αποθετήρια), cc_persistence (βάση δεδομένων πλευράς διακομιστή), cc_server_core (σύνθεση εφαρμογής και διακομιστή + χρόνος εκτέλεσης ταυτότητας/παρουσίας/στόλου/αξιολογήσεων), cc_infra (προσαρμογείς μόνο για VM), cc_mcp (εργαλεία MCP), cc_mcp_client (πελάτης για εξωτερικούς διακομιστές MCP, που γεφυρώνει τα εργαλεία τους στο τοπικό μητρώο), cc_markdown (μηχανή markdown εντός του αποθετηρίου), cc_natives (φύλλο FFI) και system_audio_capture. Δείτε το Ανάπτυξη και πελάτες για τον πλήρη πίνακα πελατών και το τι εκτελείται πού.
Κανόνας εξαρτήσεων
Ενότητα με τίτλο «Κανόνας εξαρτήσεων»Presentation → Application/Providers → Domain ← Infrastructure- Επίπεδο τομέα: οντότητες καθαρής Dart, αντικείμενα τιμής, διεπαφές αποθετηρίων, θύρες και υπηρεσίες τομέα. Μηδενικές εισαγωγές από την υποδομή (χωρίς dio, drift ή μοντέλα δικτύου).
- Επίπεδο παρουσίασης: οθόνες, widgets, notifiers. Καμία άμεση πρόσβαση σε drift/DAO/επίπεδο δεδομένων· τα πάντα περνούν από παρόχους Riverpod → αποθετήρια.
- Επίπεδο υποδομής: συγκεκριμένες υλοποιήσεις των θυρών τομέα και των διεπαφών αποθετηρίων. Εξαρτάται από τον τομέα, ποτέ το αντίστροφο.
Δομή χαρακτηριστικών
Ενότητα με τίτλο «Δομή χαρακτηριστικών»Η πλήρης μορφή ενός χαρακτηριστικού είναι:
feature_name/├── data/ # Repository implementations, data sources, services, DTOs, mappers├── domain/ # Entities, repository interfaces, ports, use cases├── presentation/ # Screens, widgets, notifiers└── providers/ # Riverpod providersΕλάχιστα χαρακτηριστικά κάτω από το lib/features/ φέρουν στην πραγματικότητα και τα τέσσερα, και τα κενά είναι διδακτικά και όχι τυχαία. Ο κοινός πυρήνας απορρόφησε το domain/ κάθε χαρακτηριστικού στο cc_domain και ο λεπτός πελάτης δεν διατηρεί υλοποιήσεις αποθετηρίων, οπότε τα περισσότερα χαρακτηριστικά κάτω από το lib/ είναι presentation/ συν providers/ και τίποτα άλλο. Ένας κατάλογος data/ ή domain/ που επιβιώνει στον πελάτη σηματοδοτεί κάτι που είναι πραγματικά πλευράς πελάτη.
Δύο ονομαστικές εξαιρέσεις αξίζει να τις γνωρίζετε:
- Το
mcpέχει μόνο παρόχους. Η διεπαφή ρυθμίσεων και κατάστασής του βρίσκεται κάτω από τοsettings/και η ίδια η επιφάνεια εργαλείων είναι πακέτο (cc_mcp), όχι φάκελος χαρακτηριστικού. - Το
orchestrationκαι τοplan_studioφέρουν μόνοpresentation/καιproviders/.
Το χαρακτηριστικό guardrails τοποθετεί το επίπεδο τομέα του στο cc_domain/features/guardrails/ και όχι στη ρίζα της εφαρμογής, επειδή το επιβάλλει ο διακομιστής: ένας κανόνας αντιστοιχίζει μια ActionClass (ή ένα commandPrefix κελύφους) σε μια απόφαση — allow, prompt ή deny — σε κάποια εμβέλεια, οι κανόνες αποθηκεύονται ανά χώρο εργασίας και κάθε ελεγχόμενη ενέργεια πράκτορα επιλύεται μέσω της αλυσίδας πολιτικής πριν εκτελεστεί. Η επίλυση διατρέχει space > agent > workspace > mode preset > built-in default και αποφασίζει η πρώτη εμβέλεια που έχει κανόνα που ταιριάζει· το πιο περιοριστικό λειτουργεί μόνο ως κριτήριο ισοπαλίας εντός μίας εμβέλειας και για τον συνδυασμό των κλάσεων που δηλώνει μία ενέργεια. Η επιφάνεια για τον χειριστή είναι Ρυθμίσεις → Χώρος εργασίας → Δικαιώματα πρακτόρων, στη διαδρομή /workspaces/<id>/settings/workspace/permissions. Δείτε τους Περιορισμούς για το μοντέλο.
Κοινός πυρήνας
Ενότητα με τίτλο «Κοινός πυρήνας»Το packages/cc_domain/lib/core/domain/ περιέχει οντότητες και αποθετήρια κοινά σε 3+ χαρακτηριστικά. Είναι καθαρή Dart με μηδενικές εξαρτήσεις υποδομής, και αυτό επιτρέπει τόσο στον πελάτη Flutter όσο και στο δυαδικό του διακομιστή χωρίς Flutter να εισάγουν τους ίδιους ορισμούς:
- Βασικές οντότητες:
Agent,AgentRunLog,Workspace,Repo,ReviewSpaceAssociation - Ταυτότητα και συνεργασία:
User,Principal(sealedUserPrincipal|AgentPrincipal),WorkspaceMember,WorkspaceRole - Οντότητες μνήμης:
MemoryFact,MemoryPolicy,AgentWorkingMemory,MemoryAccessGrant - Κοινά αντικείμενα τιμής:
AgentSkills,AgentRole,Mode,SandboxBackend,SandboxSpec,RunCost - Κοινές θύρες:
SandboxPort,CredentialBrokerPort,WorkspaceFilesystemPort,GitRepoInspectorPort,EmbeddingPort - Υπηρεσίες τομέα:
MemoryAccessPolicy,ActivityLogger,MentionResolver,RunLivenessClassifier DomainEventBus+ τύποι συμβάντων (χώρου εργασίας/πράκτορα, PR/κριτικής, μηνυμάτων, εισιτηρίων, pipeline, ενορχήστρωσης, μνήμης, ημερολογίου/συσκέψεων, ταυτότητας και ιδιότητας μέλους, παρατηρησιμότητας)
Ταυτότητα και συνεργασία
Ενότητα με τίτλο «Ταυτότητα και συνεργασία»Το Control Center είναι πολυχρηστικό: άνθρωποι και πράκτορες είναι ισότιμοι δρώντες που ενοποιούνται από ένα Principal. Ένα μέλος χώρου εργασίας είναι ένας User δεσμευμένος σε ένα Workspace με κάποιον WorkspaceRole (owner/admin/member/viewer/guest). Η ιδιότητα μέλους είναι το όριο πρόσβασης — όχι ένα κλειδί σύζευξης — και οι εκχωρήσεις ανά αποθετήριο εμποδίζουν την ιδιότητα μέλους χώρου εργασίας να υπερβαίνει σε προνόμια το forge. Ο πρώτος χρήστης που δημιουργείται σε έναν νέο διακομιστή κατέχει την εγκατάσταση· οι υπόλοιποι συμμετέχουν με πρόσκληση ή μέσω OIDC. Η δημιουργία ενός χώρου εργασίας σημαδεύει αυτόν τον χρήστη ως owner.
Η συνεργασία σε πραγματικό χρόνο βασίζεται σε διακομιστή ως πηγή αυθεντίας + last-writer-wins (LWW) ανά πεδίο και όχι σε CRDT. Η παρουσία (ποιος είναι εδώ, πού βρίσκεται, δείκτες, πληκτρολόγηση, η ζωντανή κατάσταση ενός πράκτορα και το τρέχον κόστος του) είναι ένα ξεχωριστό εφήμερο κανάλι που δεν αποθηκεύεται ποτέ· η διαρκής κατάσταση κινείται σε έναν κορμό αισιόδοξων μεταβολών + επαναφοράς από τον διακομιστή + LWW. Άνθρωποι και πράκτορες μοιράζονται έναν κατάλογο. Με έναν μόνο ανθρώπινο χειριστή το κανάλι παρουσίας μένει αδρανές και δεν εμφανίζεται κανένα στοιχείο καταλόγου — η συνεργασία δεν κοστίζει τίποτα στον μοναχικό χρήστη.
Θύρες και προσαρμογείς
Ενότητα με τίτλο «Θύρες και προσαρμογείς»Οι θύρες είναι αφηρημένες διεπαφές στο επίπεδο τομέα. Οι προσαρμογείς είναι συγκεκριμένες υλοποιήσεις στην υποδομή. Επειδή ο headless διακομιστής κατέχει τα δεδομένα και πρέπει να χτίζεται χωρίς Flutter, σχεδόν κάθε προσαρμογέας είναι μόνο για VM και βρίσκεται στο packages/cc_infra/lib/src/, οργανωμένος ανά μέλημα:
| Θύρα | Θέση προσαρμογέα |
|---|---|
SandboxPort |
cc_infra/lib/src/sandboxing/ (native_sandbox_adapter.dart) |
CredentialBrokerPort |
cc_infra/lib/src/sandboxing/ (env_credential_broker.dart, github_fine_grained_broker.dart) |
GitRepoInspectorPort |
cc_infra/lib/src/git/ (git_repo_inspector.dart) |
EmbeddingPort |
cc_infra/lib/src/embedding/ (embedding_service.dart) |
NotificationPort |
lib/core/notifications/ (πλευράς πελάτη: αποδίδει τοπικά τα συμβάντα του διακομιστή) |
AgentBackend |
cc_infra/lib/src/dispatch/backends/ (acp_backend.dart, harness_backend.dart, cli_backends.dart) |
TicketProviderPort |
cc_infra/lib/src/tickets/linear/ (LinearTicketAdapter). Τα Jira, ClickUp και GitHub Issues είναι προσαρμογείς συγχρονισμού εισιτηρίων στο cc_infra/lib/src/tickets/sync/; τα τοπικά εισιτήρια ζουν στη βάση δεδομένων του χώρου εργασίας χωρίς TicketProviderPort. |
PipelineEnginePort |
cc_domain features/pipelines/domain/services/ (υπηρεσία τομέα σε καθαρή Dart — δεν χρειάζεται υποδομή) |
Η ρίζα σύνθεσης της εφαρμογής (di/providers.dart) δεσμεύει τις θύρες της πλευράς πελάτη με υλοποιήσεις μέσω παρόχων Riverpod· ο διακομιστής συνθέτει τους προσαρμογείς του στο cc_server_core.
Διαχείριση κατάστασης
Ενότητα με τίτλο «Διαχείριση κατάστασης»Riverpod για όλη την κατάσταση του πελάτη:
Notifier<T>καιAsyncNotifier<T>για μεταβλητή κατάστασηFutureProvider<T>για ασύγχρονα δεδομένα- Οι λίστες και οι ζωντανές γραμμές φτάνουν μέσω συνδρομών RPC ως
AsyncValue<List<T>>— ο διακομιστής χρησιμοποιεί εσωτερικά το.watch()του Drift· κανένας πελάτης δεν ανοίγει το Drift - Τα εργαλεία MCP λαμβάνουν τις εξαρτήσεις τους ως τυποποιημένες παραμέτρους κατασκευαστή, ποτέ ως
Ref
Βάση δεδομένων
Ενότητα με τίτλο «Βάση δεδομένων»Drift (SQLite), χωρισμένο σε δύο βάσεις δεδομένων, και οι δύο στο cc_persistence:
GlobalDatabase(<dataDir>/global.db) — ένας σύντομος κατάλογος πινάκων που αφορούν πραγματικά ολόκληρο τον διακομιστή: το μητρώο χώρων εργασίας, χρήστες/προτιμήσεις/συζευγμένες συσκευές, συνδέσεις SSO, ρυθμίσεις διακομιστή για όλη την εγκατάσταση, διαχειριζόμενες πολιτικές ενεργειών (ένα όριο για όλη την εγκατάσταση που μπορεί μόνο να σφίξει τους περιορισμούς του χώρου εργασίας), τη ροή ειδήσεων ανά χρήστη, την ουρά του στόλου (εργάτες/εργασίες/αρχείο τοποθέτησης), το ευρετήριοworkspace_routesπριν από την ταυτοποίηση και τα μεταδεδομένα της εγκατάστασης. Η εκκίνηση ανοίγει μόνο αυτό το αρχείο, οπότε το κόστος εκκίνησης μένει σταθερό ανεξάρτητα από το πόσο ιστορικό συσσωρεύουν οι χώροι εργασίας. Η προσθήκη πίνακα εδώ είναι απόφαση απομόνωσης για την οποία ένα τεστ καστάνιας σας αναγκάζει να επιχειρηματολογήσετε.WorkspaceDatabase(<dataDir>/<workspaceId>/workspace.db) — ένας κατάλογος ανά χώρο εργασίας, που περιέχει ένα αρχείο SQLite και ό,τι άλλο ανήκει μόνο σε αυτόν τον χώρο εργασίας, ώστε τα worktrees μιας συνομιλίας και τα αρχεία των πρακτόρων να βρίσκονται δίπλα στη βάση δεδομένων και να διαγράφονται μαζί της. Σχεδόν τα πάντα ζουν εδώ: πράκτορες, χώροι, εισιτήρια, μνήμη, pipelines, συσκέψεις, το γράφημα κώδικα, κριτικές, αποθετήρια. Τα αρχεία ανοίγουν με καθυστέρηση την πρώτη φορά που τα αγγίζει κανείς, μέσω τουWorkspaceDatabaseManager.of(workspaceId), και πληρώνουν τότε το δικό τουςquick_check, την εγκατάσταση FTS/trigger και τοvector_init.
Και τα δύο μισά ξεκίνησαν από μια ενοποιημένη αφετηρία v1 — το onCreate χτίζει το τρέχον σχήμα — με βήματα μετανάστευσης να προσαρτώνται μόνο όταν κάποια αναπτυγμένη βάση δεδομένων πρέπει να μεταφερθεί προς τα εμπρός.
Επειδή ένας χώρος εργασίας είναι ένα αρχείο, η εξαγωγή ενός χώρου εργασίας είναι μία μόνο δήλωση VACUUM INTO (workspace.export) και όχι εξαγωγή πίνακα προς πίνακα· το workspace.import υιοθετεί ένα τέτοιο αρχείο και χρησιμοποιεί το ενσωματωμένο workspace_meta για να ξεχωρίσει το δικό του αρχείο που υιοθετείται ξανά από ένα που προήλθε από άλλη εγκατάσταση.
Και οι δύο βάσεις δεδομένων ανήκουν στο cc_persistence και ανοίγουν μόνο από το cc_server· κανένας πελάτης δεν ανοίγει βάση δεδομένων — κάθε πελάτης διαβάζει/γράφει μέσω RPC. Οι πίνακες ορίζονται στο packages/cc_persistence/lib/database/tables/, τα DAO στο .../daos/· οι οντότητες τομέα είναι καθαρή Dart, ξεχωριστές από τις κλάσεις πινάκων του Drift, με αντιστοίχιση στα επίπεδα δεδομένων. Το FTS5 χειρίζεται την αναζήτηση πλήρους κειμένου και τα embeddings sqlite_vector, και τα δύο μόνο στον διακομιστή· και οι δύο βάσεις εκτελούν PRAGMA foreign_keys=ON σε λειτουργία ημερολογίου WAL.
Δρομολόγηση
Ενότητα με τίτλο «Δρομολόγηση»go_router, με ένα γεγονός που διέπει όλα τα υπόλοιπα: κάθε προορισμός εντός της εφαρμογής έχει πρόθεμα χώρου εργασίας, με τη μορφή /workspaces/:workspaceId/…. Το αναγνωριστικό του χώρου εργασίας στο URL είναι η μοναδική πηγή αλήθειας για τον ενεργό χώρο εργασίας — το activeWorkspaceIdProvider οδηγείται από τη διαδρομή και όχι το αντίστροφο — και γι’ αυτό η ανάγνωση δεδομένων με εμβέλεια χώρου εργασίας έξω από μια διαδρομή με πρόθεμα δεν έχει από πού να πάρει το αναγνωριστικό της.
- Συναρτήσεις κατασκευής διαδρομών στο
router/routes.dart, καθεμία με το αναγνωριστικό του χώρου εργασίας ως πρώτο όρισμα, όχι σταθερές συμβολοσειρών - Τέσσερις διαδρομές πριν από το πλαίσιο δεν έχουν πρόθεμα:
/splash,/onboarding,/signed-outκαι/workspaces(ο επιλογέας) - Το
ShellRouteπεριβάλλει το κέλυφος της εφαρμογής· αυτές οι τέσσερις επιφάνειες αποδίδονται σε πλήρη οθόνη έξω από αυτό - Φύλακας ταυτοποίησης: η ημιτελής ρύθμιση οδηγεί στο
/onboarding· μια ολοκληρωμένη ρύθμιση της οποίας το διαπιστευτήριο forge έχει χαθεί οδηγεί στο/signed-out. Ολοκληρωμένη σημαίνει ότι τουλάχιστον ένα forge είναι συνδεδεμένο για τον συνδεδεμένο χρήστη και υπάρχει τουλάχιστον ένας χώρος εργασίας — όχι συγκεκριμένα το GitHub — και το CLIghδεν είναι μέθοδος ταυτοποίησης - Πύλη εισαγωγής στο
features/auth/providers/
Δικτύωση (πλευράς διακομιστή)
Ενότητα με τίτλο «Δικτύωση (πλευράς διακομιστή)»Όλο το εξωτερικό HTTP ζει στον διακομιστή. Οι πελάτες δεν καλούν ποτέ απευθείας το GitHub, τη Linear ή την Google — καλούν λειτουργίες RPC του διακομιστή, και ακόμη και τα απομακρυσμένα πολυμέσα ανακτώνται μέσω του σημείου πρόσβασης /proxy/media του διακομιστή και όχι από την αρχική πηγή.
- Πελάτες dio στο
packages/cc_infra/lib/src/:GitHubApiClient,GitHubPrClient,GitHubContentClient,GitHubGraphQLClient,GitLabApiClient,BitbucketApiClient,LinearGraphQlClientκαιGoogleCalendarApiClient - Έγχυση token ταυτοποίησης μέσω interceptors, συμπεριλαμβανομένου ενός interceptor Google OAuth ανά λογαριασμό στο
cc_server_coreπου ανανεώνει τα token στο 401 - Όλα τα σφάλματα αντιστοιχίζονται μέσω του
packages/cc_infra/lib/src/network/error_mapper.dart→ τυποποιημένες υποκλάσειςAppExceptionπου ορίζονται στοcc_domain
Ασφάλεια
Ενότητα με τίτλο «Ασφάλεια»Ο διακομιστής κρατά τα διαπιστευτήρια που μετράνε: τα token του GitHub και των εισιτηρίων για εκκινήσεις πρακτόρων, τα κλειδιά των παρόχων LLM και τα token OAuth ζουν όλα κάτω από τον κατάλογο δεδομένων του διακομιστή ή στο περιβάλλον του. Αυτό που εξακολουθεί να κρατά το keychain του πελάτη είναι το δικό του διαπιστευτήριο συσκευής και το κλειδί σύζευξης για έναν απομακρυσμένο διακομιστή.
- Μυστικά στο
flutter_secure_storage(keychain του macOS, credential manager των Windows, libsecret του Linux) — το διαπιστευτήριο συσκευής του πελάτη και τα κλειδιά απομακρυσμένης σύζευξης, όχι τα token των παρόχων shared_preferencesμόνο για μη ευαίσθητες προτιμήσεις (θέμα, γραμματοσειρά, διάταξη)- Τα υπολείμματα μυστικών παρόχων από παλαιότερες εγκαταστάσεις παραδίδονται μία φορά στον διακομιστή από το
features/auth/providers/credential_migration.dartκαι έπειτα διαγράφονται από το keychain του πελάτη
Επιβολή της αρχιτεκτονικής
Ενότητα με τίτλο «Επιβολή της αρχιτεκτονικής»Οι περιορισμοί της αρχιτεκτονικής επικυρώνονται από το test/core/architecture_constraints_test.dart, το οποίο αποτυγχάνει αν παραβιαστούν οι κανόνες εξαρτήσεων.
Σχετικές έννοιες
Ενότητα με τίτλο «Σχετικές έννοιες»- Χώροι εργασίας και απομόνωση: πώς επιβάλλεται η απομόνωση
- Κύκλος ζωής αποστολής πράκτορα: η ροή της αποστολής
- Γεγονότα τομέα: επικοινωνία μεταξύ χαρακτηριστικών
- Ανάπτυξη και πελάτες: το μοντέλο του λεπτού πελάτη πάνω από διακομιστή και ο πίνακας πελατών