# Phase 3: Project Context Awareness - Architecture Diagram --- ## System Architecture Overview ``` ┌───────────────────────────────────────────────────────────────────────┐ │ PHASE 3 ARCHITECTURE │ └───────────────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────────────────┐ │ FRONTEND LAYER │ ├─────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ Navbar │ │ Rule Manager │ │ Project │ │ │ │ │ │ │ │ Manager │ │ │ │ ┌──────────┐ │ │ • View Rules │ │ • List │ │ │ │ │ Project │ │ │ • Rendered │ │ • Create │ │ │ │ │ Selector │ │ │ Text │ │ • Edit │ │ │ │ │ Dropdown │ │ │ • Template │ │ • Delete │ │ │ │ └────┬─────┘ │ │ • Variables │ │ │ │ │ └──────┼────────┘ └──────┬───────┘ └──────┬───────┘ │ │ │ │ │ │ │ └──────────────────┴─────────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────┐ │ │ │ API Request │ │ │ │ with projectId │ │ │ └────────┬────────┘ │ └─────────────────────────────┼───────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ BACKEND LAYER │ ├─────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │ │ │ Projects │ │ Variables │ │ Rules (Enh.) │ │ │ │ Controller │ │ Controller │ │ Controller │ │ │ ├──────────────────┤ ├──────────────────┤ ├──────────────────┤ │ │ │ GET /projects │ │ GET /vars │ │ GET /rules │ │ │ │ POST /projects │ │ POST /vars │ │ ?project=... │ │ │ │ PUT /projects │ │ PUT /vars │ │ │ │ │ │ DELETE /projects │ │ DELETE /vars │ │ Returns: │ │ │ └────────┬─────────┘ └────────┬─────────┘ │ • text │ │ │ │ │ │ • renderedText │ │ │ │ │ │ • variables │ │ │ │ │ └────────┬─────────┘ │ │ │ │ │ │ │ ▼ ▼ ▼ │ │ ┌─────────────────────────────────────────────────────────────┐ │ │ │ VARIABLE SUBSTITUTION SERVICE │ │ │ ├─────────────────────────────────────────────────────────────┤ │ │ │ │ │ │ │ substituteVariables(ruleText, projectId) │ │ │ │ ┌───────────────────────────────────────────────────┐ │ │ │ │ │ 1. Extract ${VAR} from text │ │ │ │ │ │ 2. Query VariableValue for projectId │ │ │ │ │ │ 3. Build substitution map: {VAR: value} │ │ │ │ │ │ 4. Replace ${VAR} with actual value │ │ │ │ │ │ 5. Return renderedText + metadata │ │ │ │ │ └───────────────────────────────────────────────────┘ │ │ │ │ │ │ │ │ extractVariables(text) → ['VAR1', 'VAR2'] │ │ │ │ getAllVariables() → [{name, usageCount}] │ │ │ │ validateProjectVariables(projectId) → {missing} │ │ │ │ │ │ │ └─────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────┬───────────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────────┐ │ DATABASE LAYER (MongoDB) │ ├─────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │ │ │ projects │ │ variableValues │ │ governanceRules │ │ │ ├──────────────────┤ ├──────────────────┤ ├──────────────────┤ │ │ │ id (PK) │ │ projectId (FK) │ │ id │ │ │ │ name │ │ variableName │ │ text (template) │ │ │ │ description │ │ value │ │ scope │ │ │ │ techStack │ │ description │ │ variables[] │ │ │ │ active │ │ category │ │ applicableProjs │ │ │ └──────────────────┘ └──────────────────┘ └──────────────────┘ │ │ │ │ Index: (id) Index: (projectId, variableName) │ │ │ └─────────────────────────────────────────────────────────────────────────┘ ``` --- ## Data Flow: Variable Substitution ``` ┌─────────────────────────────────────────────────────────────────────────┐ │ VARIABLE SUBSTITUTION FLOW │ └─────────────────────────────────────────────────────────────────────────┘ STEP 1: User Selects Project ┌────────────────┐ │ User clicks │ │ "Tractatus" in │ │ project picker │ └───────┬────────┘ │ ▼ ┌────────────────────────────────┐ │ localStorage.setItem( │ │ 'currentProject', │ │ 'tractatus' │ │ ) │ └───────┬────────────────────────┘ │ ▼ STEP 2: Frontend Requests Rules with Context ┌────────────────────────────────┐ │ GET /api/admin/rules? │ │ project=tractatus │ └───────┬────────────────────────┘ │ ▼ STEP 3: Backend Filters Applicable Rules ┌─────────────────────────────────────────────────┐ │ Query: │ │ { │ │ $or: [ │ │ { scope: 'UNIVERSAL' }, │ │ { applicableProjects: 'tractatus' } │ │ ], │ │ active: true │ │ } │ └───────┬─────────────────────────────────────────┘ │ ▼ STEP 4: For Each Rule, Extract Variables ┌─────────────────────────────────────────────────┐ │ Rule Text: │ │ "MongoDB database MUST be named ${DB_NAME} │ │ in ${ENVIRONMENT}." │ │ │ │ Extracted Variables: │ │ ['DB_NAME', 'ENVIRONMENT'] │ └───────┬─────────────────────────────────────────┘ │ ▼ STEP 5: Lookup Variable Values for Project ┌─────────────────────────────────────────────────┐ │ Query variableValues: │ │ { │ │ projectId: 'tractatus', │ │ variableName: { │ │ $in: ['DB_NAME', 'ENVIRONMENT'] │ │ } │ │ } │ │ │ │ Results: │ │ [ │ │ {variableName: 'DB_NAME', value: 'tractatus_dev'}, │ │ {variableName: 'ENVIRONMENT', value: 'development'} │ │ ] │ └───────┬─────────────────────────────────────────┘ │ ▼ STEP 6: Build Substitution Map ┌─────────────────────────────────────────────────┐ │ Substitution Map: │ │ { │ │ 'DB_NAME': 'tractatus_dev', │ │ 'ENVIRONMENT': 'development' │ │ } │ └───────┬─────────────────────────────────────────┘ │ ▼ STEP 7: Replace Placeholders ┌─────────────────────────────────────────────────┐ │ Original: │ │ "MongoDB database MUST be named ${DB_NAME} │ │ in ${ENVIRONMENT}." │ │ │ │ Regex: /\$\{([A-Z_]+)\}/g │ │ │ │ Rendered: │ │ "MongoDB database MUST be named tractatus_dev │ │ in development." │ └───────┬─────────────────────────────────────────┘ │ ▼ STEP 8: Return Enriched Response ┌─────────────────────────────────────────────────┐ │ { │ │ "id": "inst_019", │ │ "text": "...${DB_NAME}...${ENVIRONMENT}...", │ │ "renderedText": "...tractatus_dev...development...", │ │ "variables": [ │ │ {"name": "DB_NAME", "value": "tractatus_dev"}, │ │ {"name": "ENVIRONMENT", "value": "development"} │ │ ], │ │ "scope": "UNIVERSAL" │ │ } │ └───────┬─────────────────────────────────────────┘ │ ▼ STEP 9: Frontend Displays ┌─────────────────────────────────────────────────┐ │ ┌─────────────────────────────────────────────┐ │ │ │ inst_019 | SYSTEM | HIGH │ │ │ │ │ │ │ │ Rendered (for Tractatus): │ │ │ │ MongoDB database MUST be named tractatus_dev│ │ │ │ in development. │ │ │ │ │ │ │ │ Template: ...${DB_NAME}...${ENVIRONMENT}... │ │ │ │ Variables: DB_NAME=tractatus_dev, │ │ │ │ ENVIRONMENT=development │ │ │ └─────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────┘ ``` --- ## UI Component Hierarchy ``` ┌─────────────────────────────────────────────────────────────────────────┐ │ ADMIN INTERFACE │ └─────────────────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────────────────┐ │ Navbar (All Pages) │ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ Tractatus Admin [Project: Tractatus ▼] Dashboard Rules [Logout]│ │ │ └─────────────────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────────┘ │ ┌───────────────┼───────────────┐ │ │ │ ▼ ▼ ▼ ┌────────────────┐ ┌───────────────┐ ┌─────────────┐ │ Rule Manager │ │ Project │ │ Dashboard │ │ │ │ Manager │ │ │ ├────────────────┤ ├───────────────┤ └─────────────┘ │ • List Rules │ │ • List Projs │ │ • Rendered │ │ • Add Project │ │ Text │ │ • Edit Proj │ │ • Template │ │ │ │ • Variables │ │ ┌─────────┐ │ │ • Edit Rule │ │ │ Project │ │ │ │ │ │ Editor │ │ │ ┌──────────┐ │ │ ├─────────┤ │ │ │ Variable │ │ │ │ • Meta │ │ │ │ Editor │ │ │ │ • Vars │ │ │ │ Modal │ │ │ │ │ │ │ └──────────┘ │ │ │ ┌─────┐ │ │ └────────────────┘ │ │ │ Var │ │ │ │ │ │ Edit│ │ │ │ │ └─────┘ │ │ │ └─────────┘ │ └───────────────┘ ``` --- ## Component Interaction Diagram ``` ┌─────────────────────────────────────────────────────────────────────────┐ │ COMPONENT INTERACTIONS │ └─────────────────────────────────────────────────────────────────────────┘ Event Flow: User Changes Project Selection ┌─────────────────┐ │ ProjectSelector │ (1) User clicks project dropdown └────────┬────────┘ │ │ (2) Emits 'projectChanged' event │ { projectId: 'tractatus' } │ ├──────────────────────┬───────────────────┐ │ │ │ ▼ ▼ ▼ ┌────────────────┐ ┌──────────────────┐ ┌─────────────┐ │ Rule Manager │ │ Project Manager │ │ Dashboard │ └────────┬───────┘ └────────┬─────────┘ └──────┬──────┘ │ │ │ │ (3) Listens │ (3) Listens │ (3) Listens │ to event │ to event │ to event │ │ │ │ (4) Reloads │ (4) Updates │ (4) Updates │ rules with │ current │ stats for │ new context │ selection │ project │ │ │ ▼ ▼ ▼ ┌─────────────────────────────────────────────────────────┐ │ localStorage.setItem('currentProject', id) │ └─────────────────────────────────────────────────────────┘ ``` --- ## Database Relationships ``` ┌─────────────────────────────────────────────────────────────────────────┐ │ DATABASE RELATIONSHIPS │ └─────────────────────────────────────────────────────────────────────────┘ ┌──────────────────┐ │ projects │ │ │ │ id (PK) ─────────┼──────────┐ │ name │ │ │ techStack │ │ 1:N │ active │ │ └──────────────────┘ │ │ ▼ ┌──────────────────┐ │ variableValues │ │ │ │ projectId (FK) ──┼─── References projects.id │ variableName │ │ value │ │ │ │ UNIQUE(projectId,│ │ variableName) │ └──────────────────┘ │ │ Referenced by │ (through variables[] field) │ ▼ ┌──────────────────┐ │ governanceRules │ │ │ │ id │ │ text (template) │ │ variables[] ─────┼─── e.g., ['DB_NAME', 'DB_PORT'] │ scope │ │ applicableProj[] ┼─── e.g., ['tractatus', 'family-history'] └──────────────────┘ Example Query Flow: 1. Get rules for project "tractatus" 2. Find rules where scope=UNIVERSAL OR 'tractatus' in applicableProjects 3. For each rule, extract variables[] field 4. Query variableValues where projectId='tractatus' AND variableName IN variables[] 5. Substitute ${VAR} with values 6. Return enriched rules ``` --- ## API Endpoints Overview ``` ┌─────────────────────────────────────────────────────────────────────────┐ │ API ENDPOINTS (Phase 3) │ └─────────────────────────────────────────────────────────────────────────┘ PROJECTS API ├─ GET /api/admin/projects → List all projects ├─ GET /api/admin/projects/:id → Get project + variables ├─ POST /api/admin/projects → Create project ├─ PUT /api/admin/projects/:id → Update project └─ DELETE /api/admin/projects/:id → Soft delete project VARIABLES API ├─ GET /api/admin/projects/:id/variables → Get all vars for project ├─ POST /api/admin/projects/:id/variables → Create/update variable ├─ PUT /api/admin/projects/:id/variables/:var → Update variable value ├─ DELETE /api/admin/projects/:id/variables/:var → Delete variable └─ GET /api/admin/variables/global → All unique variable names RULES API (Enhanced) └─ GET /api/admin/rules?project=:id → Get rules with substitution (Enhanced existing endpoint) ``` --- ## Substitution Algorithm Pseudocode ```javascript function substituteVariables(ruleText, projectId) { // Step 1: Extract variable placeholders const regex = /\$\{([A-Z_]+)\}/g; const variableNames = [...new Set( [...ruleText.matchAll(regex)].map(m => m[1]) )]; if (variableNames.length === 0) { return { renderedText: ruleText, variables: [] }; } // Step 2: Query database for values const values = await VariableValue.find({ projectId: projectId, variableName: { $in: variableNames } }); // Step 3: Build substitution map const substitutionMap = {}; values.forEach(v => { substitutionMap[v.variableName] = v.value; }); // Step 4: Replace placeholders const renderedText = ruleText.replace( regex, (match, varName) => substitutionMap[varName] || match ); // Step 5: Build metadata const variables = variableNames.map(name => ({ name: name, value: substitutionMap[name] || null, missing: !substitutionMap[name] })); return { renderedText, variables, hasAllValues: variables.every(v => !v.missing) }; } ``` --- **Architecture Complexity**: Medium **Integration Points**: 3 (Models, Services, Controllers) **New Collections**: 2 (projects, variableValues) **Enhanced Collections**: 1 (governanceRules - query logic only) --- **Diagram Created**: 2025-10-11 **For**: Phase 3 Implementation **Status**: Ready for Development