Skip to content

Part 5: Relationships & Multiple Sources

In Part 4, you enriched a single file with architecture and enrichment tags. Now you will connect multiple files into a live dependency graph.

5.1 Add relationship tags to user-service.ts

Section titled “5.1 Add relationship tags to user-service.ts”

Add these tags to user-service.ts:

* @libar-docs-used-by AuthHandler
* @libar-docs-uses EventStore
* @libar-docs-depends-on EventStore
* @libar-docs-see-also AuthHandler, EventStore

These reference patterns that do not exist yet — that is intentional. The system will track these as pending references until you create the matching files.

Relationship tags:

TagExamplePurpose
@libar-docs-usesEventStoreDirect dependency (solid arrow --> in diagrams)
@libar-docs-used-byAuthHandlerReverse dependency
@libar-docs-depends-onEventStoreRoadmap sequencing (dashed arrow -.->)
@libar-docs-enablesUserServiceReverse sequencing
@libar-docs-see-alsoAuthHandler, EventStoreCross-reference without dependency

After all the additions from Parts 3-5, your file should look like this:

/** @libar-docs */
/**
* @libar-docs-pattern UserService
* @libar-docs-status active
* @libar-docs-core
* @libar-docs-arch-role service
* @libar-docs-arch-context identity
* @libar-docs-arch-layer application
* @libar-docs-used-by AuthHandler
* @libar-docs-uses EventStore
* @libar-docs-extract-shapes UserRecord
* @libar-docs-phase 1
* @libar-docs-release v0.1.0
* @libar-docs-brief Core user lifecycle management service
* @libar-docs-usecase "Register a new user account via the signup form"
* @libar-docs-usecase "Look up a user by ID for profile display"
* @libar-docs-usecase "Deactivate a compromised user account"
* @libar-docs-quarter Q1-2026
* @libar-docs-depends-on EventStore
* @libar-docs-see-also AuthHandler, EventStore
*
* ## UserService - User Lifecycle Management
*
* Manages user lifecycle — registration, lookup, and deactivation.
*
* ### When to Use
*
* - When registering new users
* - When looking up user information
* - When deactivating user accounts
*/
/** @libar-docs-shape reference-sample */
export interface UserRecord {
id: string;
email: string;
active: boolean;
}
export class UserService {
private users = new Map<string, UserRecord>();
register(email: string): string {
const id = crypto.randomUUID();
this.users.set(id, { id, email, active: true });
return id;
}
findById(id: string): UserRecord | null {
return this.users.get(id) ?? null;
}
deactivate(id: string): boolean {
const user = this.users.get(id);
if (!user) return false;
user.active = false;
return true;
}
}

Create src/sample-sources/auth-handler.ts:

/** @libar-docs */
/**
* @libar-docs-pattern AuthHandler
* @libar-docs-status roadmap
* @libar-docs-api
* @libar-docs-arch-role service
* @libar-docs-arch-context identity
* @libar-docs-arch-layer application
* @libar-docs-uses UserService
* @libar-docs-extract-shapes AuthResult
* @libar-docs-phase 2
* @libar-docs-release vNEXT
* @libar-docs-brief Authentication and session management handler
* @libar-docs-usecase "Authenticate a user with email and password"
* @libar-docs-usecase "Validate an active session token"
* @libar-docs-depends-on UserService
* @libar-docs-quarter Q1-2026
* @libar-docs-see-also UserService
*
* ## AuthHandler - Authentication & Sessions
*
* Handles authentication and session management.
*
* ### When to Use
*
* - When authenticating user credentials
* - When creating or validating sessions
*/
/** @libar-docs-shape reference-sample */
export interface AuthResult {
success: boolean;
sessionId?: string;
error?: string;
}
export class AuthHandler {
authenticate(email: string, password: string): AuthResult {
if (email.length === 0 || password.length < 8) {
return { success: false, error: "Invalid credentials" };
}
return { success: true, sessionId: `session-${Date.now()}` };
}
createSession(userId: string): string {
return `session-${userId}-${Date.now()}`;
}
}

Create src/sample-sources/event-store.ts:

/** @libar-docs */
/**
* @libar-docs-pattern EventStore
* @libar-docs-status deferred
* @libar-docs-infra
* @libar-docs-arch-role infrastructure
* @libar-docs-arch-context persistence
* @libar-docs-arch-layer infrastructure
* @libar-docs-used-by UserService
* @libar-docs-extract-shapes DomainEvent
* @libar-docs-phase 3
* @libar-docs-release vNEXT
* @libar-docs-brief Append-only event store for domain event persistence
* @libar-docs-usecase "Persist a domain event after a user action"
* @libar-docs-usecase "Replay events for audit trail or debugging"
* @libar-docs-quarter Q2-2026
* @libar-docs-enables UserService
* @libar-docs-see-also UserService
*
* ## EventStore - Append-Only Event Storage
*
* Append-only event store for domain events.
* Deferred pending infrastructure decisions.
*
* ### When to Use
*
* - When persisting domain events
* - When replaying event history
*/
/** @libar-docs-shape reference-sample */
export interface DomainEvent {
type: string;
payload: unknown;
timestamp: number;
}
export class EventStore {
private events: DomainEvent[] = [];
append(type: string, payload: unknown): void {
this.events.push({ type, payload, timestamp: Date.now() });
}
getAll(): DomainEvent[] {
return [...this.events];
}
getByType(type: string): DomainEvent[] {
return this.events.filter((e) => e.type === type);
}
}

These files use the same tag patterns you learned: identity + architecture + enrichment + shapes + relationships. AuthHandler uses UserService, while EventStore is used by UserService and has status deferred.

Terminal window
npm run process:overview
=== PROGRESS ===
6 patterns (0 completed, 1 active, 5 planned) = 0%
=== ACTIVE PHASES ===
Phase 1: Inception (1 active)
=== BLOCKING ===
UserService blocked by: EventStore
AuthHandler blocked by: UserService

What just happened: The system automatically computed the dependency chain: AuthHandler depends on UserService, which depends on EventStore. The blocking report surfaces this — no manual tracking needed.

Explore the full dependency tree:

Terminal window
npm run process:query -- dep-tree AuthHandler
EventStore (3, deferred)
-> UserService (1, active)
-> AuthHandler (2, roadmap) <- YOU ARE HERE

This shows the chain from root dependency (EventStore) through UserService to AuthHandler, with phase numbers and statuses at each level.

List all bounded contexts:

Terminal window
npm run process:query -- arch context
{
"success": true,
"data": [
{
"context": "identity",
"count": 2,
"patterns": ["UserService", "AuthHandler"]
},
{
"context": "persistence",
"count": 1,
"patterns": ["EventStore"]
}
]
}

Note: The identity context has count 2 (UserService and AuthHandler) — not 3 as you might expect. The shape patterns (UserRecord, AuthResult, DomainEvent) do not have arch-context tags, so they are not counted in bounded context groupings. Only patterns with explicit @libar-docs-arch-context tags appear here.

Terminal window
npm run process:query -- list --status roadmap
{
"success": true,
"data": [
{
"patternName": "AuthHandler",
"category": "api",
"file": "src/sample-sources/auth-handler.ts",
"source": "typescript",
"status": "roadmap",
"phase": 2
}
]
}

Only AuthHandler has status roadmap at this point. EventStore is deferred, not roadmap — the list --status roadmap filter correctly excludes it.

Before moving on, verify:

  • npm run process:sources shows 3 TypeScript files
  • npm run process:overview shows 6 patterns (3 main + 3 shapes)
  • npm run process:query -- arch context shows identity and persistence
  • npm run process:query -- dep-tree AuthHandler shows a dependency chain
  • Multiple sources with @libar-docs-uses and @libar-docs-depends-on create a live dependency graph
  • The process:overview blocking report surfaces dependency chains automatically
  • dep-tree shows recursive dependencies for any pattern
  • Pattern names in relationship tags must match exactly (case-sensitive)