Status: Proposed
Version: 1.0
Date: 2025-12-28
Supersedes: N/A
Related ADRs: ADR-033 (Kernel-Shell Architecture), ADR-030 (VibesPro™ Foundation)
Related PRDs: PRD-023
With the Kernel-Shell architecture (ADR-033), SEA™ contains multiple bounded contexts in a single Nx workspace:
libs/sea/*)libs/vibespro/*)libs/shared/*)Without enforcement, developers will inevitably create cross-boundary imports:
Symptom observed in similar projects: After 1-2 months, bounded contexts become entangled, and the architecture diagram no longer matches reality.
We adopt Nx module boundary enforcement using tags and dependency rules, validated in CI.
1
2
scope:{context} - Which bounded context owns the lib
type:{layer} - What architectural layer the lib belongs to
| Tag Category | Values | Purpose |
|---|---|---|
scope:sea |
SEA™ kernel libraries | Core domain ownership |
scope:vibespro |
VibesPro™ libraries | VibesPro™ domain ownership |
scope:shared |
Cross-cutting utilities | Shared by all contexts |
type:domain |
Pure domain logic | No I/O, no dependencies |
type:app |
Use-cases/orchestration | Business workflows |
type:ports |
Interfaces/protocols | Abstraction boundaries |
type:adapters |
Infrastructure implementations | I/O, DB, HTTP, queues |
type:public |
Public API facades | Only cross-context entry point |
type:shell |
Application composition | Config + wiring only |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
{
"@nx/enforce-module-boundaries": [
"error",
{
"depConstraints": [
{
"sourceTag": "scope:sea",
"onlyDependOnLibsWithTags": [
"scope:sea",
"scope:shared",
"type:public"
]
},
{
"sourceTag": "scope:vibespro",
"onlyDependOnLibsWithTags": ["scope:vibespro", "scope:shared"]
},
{
"sourceTag": "type:domain",
"onlyDependOnLibsWithTags": ["type:domain", "scope:shared"]
},
{
"sourceTag": "type:app",
"onlyDependOnLibsWithTags": [
"type:domain",
"type:ports",
"scope:shared"
]
},
{
"sourceTag": "type:ports",
"onlyDependOnLibsWithTags": ["type:domain", "scope:shared"]
},
{
"sourceTag": "type:adapters",
"onlyDependOnLibsWithTags": [
"type:domain",
"type:app",
"type:ports",
"scope:shared"
]
},
{
"sourceTag": "type:shell",
"onlyDependOnLibsWithTags": [
"type:app",
"type:adapters",
"type:public",
"scope:shared"
]
}
]
}
]
}
| Rule | Meaning | Prevents |
|---|---|---|
scope:sea → scope:vibespro only via type:public |
SEA™ integrates with VibesPro™ through public facade only | Tight coupling to VibesPro™ internals |
type:domain → never type:adapters |
Domain has no infrastructure dependencies | I/O leaking into business logic |
type:adapters → inward only |
Adapters implement ports, depend on domain | Adapter logic in domain |
| Shells cannot import domain directly | Shells compose via app layer | Domain logic in composition |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// libs/sea/domain/project.json
{
"tags": ["scope:sea", "type:domain"]
}
// libs/vibespro/public-api/project.json
{
"tags": ["scope:vibespro", "type:public"]
}
// libs/sea/adapters/postgres/project.json
{
"tags": ["scope:sea", "type:adapters"]
}
// apps/sea-api/project.json
{
"tags": ["scope:sea", "type:shell"]
}
nx graph shows actual dependenciesscope: and one type:@nx/enforce-module-boundaries in eslint.config.jsnx lint --all)nx graph monthly for unexpected edges// eslint-disable to bypass boundary rulestype:domain to have any external runtime dependencies| Spec Concept | Nx Representation | Verification |
|---|---|---|
| Bounded Context | scope:* tag |
Graph shows isolated clusters |
| Domain Layer | type:domain |
Zero adapter imports |
| Ports | type:ports |
interface-only files |
| Adapters | type:adapters |
Implementation files |
| Public Contract | type:public |
Only cross-scope entry |
| INV-ID | Invariant | Type | Enforcement |
|---|---|---|---|
| INV-034 | All libs have scope + type tags | Structural | CI lint check |
| INV-035 | Domain never imports adapters | Structural | Nx boundary rule |
| INV-036 | Cross-scope only via public | Structural | Nx boundary rule |
| INV-037 | Graph remains acyclic | Structural | nx graph validation |
| Attribute | Target | Rationale |
|---|---|---|
| Build Isolation | Each lib builds independently | Parallel CI |
| Testability | Domain testable without infra | Fast unit tests |
| Maintainability | Clear ownership per scope | Team autonomy |
| Evolvability | Can split BC to separate repo | Future microservices |
All bounded contexts and libraries in the workspace.
nx lint --all passes with zero boundary violationsnx graph shows clear clusters matching bounded contextslibs/vibespro/domain from libs/sea/app