Version: 1.17.0 → 1.18.0 (MINOR: Function loading pattern documentation)
Changes:
- Document loadGlobalVariableFunctions() generic pattern
- Update VM context injection code example
- Update helpers.js loading documentation
- Document tempContext with full globalVMContext + globalVariableContext
- Fix duplicate req entry and renumber to 11 and 12
Key Documentation Updates:
1. Section I.II - helpers.js Pattern:
- Loaded by loadGlobalVariableFunctions() which scans ALL .js files
- Filename determines key: helpers.js → globalVariableContext.helpers
- Executed in tempContext with full VM globals access
2. Section I.V - VM Context Injection Pattern:
- Replaced specific helpers loading code with generic pattern
- Documents loadGlobalVariableFunctions() scanning all .js files
- Shows tempContext creation with {...globalVMContext, ...globalVariableContext}
- Documents 4-step loading process with filename-to-key mapping
3. Section I.V - Helper Functions Module:
- Added Generic Loading Pattern section
- Documents full access to VM globals (axios, jwt, crypto, etc.)
- Documents access to previously loaded JSON data and functions
- Added note about extensibility (utils.js, validators.js, etc.)
Architecture Notes:
- Generic pattern: any .js file in globalVariables/ auto-loaded
- tempContext includes all dependencies from both contexts
- Function modules can access same globals as proxy.js
- Supports multiple function modules without code changes
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
633 lines
33 KiB
Markdown
633 lines
33 KiB
Markdown
<!--
|
|
Sync Impact Report:
|
|
Version: 1.17.0 → 1.18.0 (MINOR: Updated function loading pattern documentation)
|
|
Modified Principles:
|
|
- Section I.V: Updated VM context injection pattern to reflect loadGlobalVariableFunctions
|
|
- Section I.V: Documented generic .js file loading from globalVariables/
|
|
- Section I.V: Updated tempContext to use full globalVMContext + globalVariableContext
|
|
- Section I.II: Updated helpers.js documentation to reflect generic pattern
|
|
Architecture Changes:
|
|
- Renamed loadHelpers() → loadGlobalVariableFunctions()
|
|
- Generic pattern: loads ALL .js files from globalVariables/ (not just helpers.js)
|
|
- Filename determines key: helpers.js → globalVariableContext.helpers
|
|
- tempContext now includes full VM globals and previously loaded data
|
|
- Function modules can access all dependencies (axios, jwt, etc.)
|
|
Code Changes:
|
|
- server.js: loadGlobalVariableFunctions() loads all .js files generically
|
|
- server.js: tempContext uses {...globalVMContext, ...globalVariableContext}
|
|
- Pattern matches loadGlobalObjects() structure for consistency
|
|
Modified Sections:
|
|
- Section I.II: Updated file structure and helpers.js pattern documentation
|
|
- Section I.V: Complete rewrite of function module loading documentation
|
|
- Section I.V: Updated context injection pattern code example
|
|
Rationale:
|
|
- Generic pattern supports multiple function modules without code changes
|
|
- Consistent with loadGlobalObjects() pattern (JSON files)
|
|
- Function modules can depend on full set of VM globals
|
|
- Enables complex function modules that need access to libraries
|
|
Templates Status:
|
|
✅ All templates - No changes needed (implementation detail)
|
|
Previous Version:
|
|
Version: 1.16.0 → 1.17.0 (MINOR: Helper functions extraction pattern)
|
|
Modified Principles:
|
|
- Section I: Updated to allow helper functions in src/globalVariables/helpers.js
|
|
- Section I.II: Added helpers.js to allowed files list
|
|
- Section I.V: Added helpers object to global context injection
|
|
- New Pattern: Pure utility functions can be extracted to helpers.js and loaded via vm.Script
|
|
Architecture Changes:
|
|
- Created src/globalVariables/helpers.js (315 lines)
|
|
- Extracted 11 helper functions from proxy.js
|
|
- Reduced proxy.js from 752 to 493 lines (35% reduction)
|
|
- Helper functions loaded via vm.Script and injected as 'helpers' global object
|
|
- proxy.js now uses helpers.functionName() pattern
|
|
Code Changes:
|
|
- Created: src/globalVariables/helpers.js with IIFE returning helpers object
|
|
- Modified: src/proxyScripts/proxy.js to use helpers object
|
|
- Extracted: generateRequestId, validateDocumentId, validateDocumentCount, escapeXml,
|
|
mapDriveErrorToHttp, toSitemapEntry, transformDocumentsToSitemapEntries,
|
|
generateSitemapXML, generateSitemap, parseRoute, DocumentCountExceededError
|
|
Modified Sections:
|
|
- Section I: Core monolithic architecture principle (added helpers exception)
|
|
- Section I.I: What must be in proxy.js (clarified helpers can be external)
|
|
- Section I.II: What can be separate files (added helpers.js)
|
|
- Section I.V: Global objects injection (added helpers object documentation)
|
|
Rationale:
|
|
- Improves code organization while maintaining vm.Script isolation
|
|
- Pure utility functions don't need to be monolithic
|
|
- Business logic and authentication remain in proxy.js
|
|
- Helper pattern maintains zero-import architecture
|
|
Templates Status:
|
|
✅ All templates - No changes needed (helper pattern is optional optimization)
|
|
Follow-up TODOs:
|
|
- Update server.js to load helpers.js via vm.Script
|
|
- Add helpers object to globalVariableContext
|
|
Previous Version:
|
|
Version: 1.15.0 → 1.16.0 (PATCH: Directory relocation and documentation update)
|
|
Modified Principles:
|
|
- Section I: Updated all references to global/ directory to src/globalVariables/
|
|
- Section I.II: Updated file structure to reflect global/ → src/globalVariables/
|
|
- Section I.IV: Updated configuration section to reference src/globalVariables/
|
|
- Section I.V: Updated global objects documentation to reference src/globalVariables/
|
|
Documentation Changes:
|
|
- Updated all references to global/ directory to src/globalVariables/
|
|
- Clarified that src/globalVariables/ contains JSON data files loaded at startup
|
|
- Updated file structure documentation to show correct hierarchy
|
|
Code Changes:
|
|
- Relocated: global/ → src/globalVariables/
|
|
- No logic changes to any files
|
|
Modified Sections:
|
|
- Section I: Multiple references to global directory location
|
|
- Section I.II: File structure documentation
|
|
- Section I.IV: Configuration section
|
|
- Section I.V: Global objects injection section
|
|
Templates Status:
|
|
✅ All templates - No changes needed (directory relocation only)
|
|
Follow-up TODOs:
|
|
- Update server.js to load global objects from new location (src/globalVariables/)
|
|
Previous Version:
|
|
Version: 1.14.0 → 1.15.0 (PATCH: File relocation and documentation update)
|
|
Modified Principles:
|
|
- Section I.II: Updated file structure to reflect proxy.js relocation to src/proxyScripts/
|
|
- Section I.III: Updated enforcement rules to reflect new proxy.js location
|
|
Documentation Changes:
|
|
- Updated all references to proxy.js to reflect new location at src/proxyScripts/proxy.js
|
|
- Clarified that src/proxyScripts/ contains the main proxy script (singular, not plural scripts)
|
|
- Updated file structure documentation to show correct hierarchy
|
|
Code Changes:
|
|
- Relocated: src/proxy.js → src/proxyScripts/proxy.js
|
|
- Created directory: src/proxyScripts/
|
|
- No logic changes to proxy.js itself
|
|
Modified Sections:
|
|
- Section I.II: File structure documentation
|
|
- Section I.III: Enforcement rules
|
|
- All references to proxy.js location throughout document
|
|
Templates Status:
|
|
✅ All templates - No changes needed (file relocation only)
|
|
Follow-up TODOs:
|
|
- Update server.js to load proxy.js from new location (src/proxyScripts/proxy.js)
|
|
Previous Version:
|
|
Version: 1.13.0 → 1.14.0 (PATCH: Documentation corrections to match actual implementation)
|
|
Modified Principles:
|
|
- Section I.V: Removed config from context injection (proxy.js doesn't need infrastructure settings)
|
|
- Section I.V: Documented spread operator pattern (globalVMContext and globalVariableContext)
|
|
- Section I.V: Clarified direct variable access pattern for proxy.js
|
|
- Section I.V: Updated injection pattern to show actual loadGlobalObjects() → globalVariableContext flow
|
|
- Section I.V: Renumbered items after removing config (was 12 items, now 11)
|
|
- Section I.V: Enhanced rationale to explain spread operator benefits
|
|
Documentation Changes:
|
|
- Removed config: global.config from context injection example (not actually injected)
|
|
- Added explicit code example showing globalVMContext and globalVariableContext definitions
|
|
- Clarified that proxy.js uses direct variable access: `const x = google_drive_settings;`
|
|
- Documented spread operator pattern: `{ ...globalVMContext, ...globalVariableContext, req, res }`
|
|
- Added note about URL availability (not in globalVMContext but available via Node.js)
|
|
No Code Changes:
|
|
- This is purely a documentation update to match existing implementation
|
|
- No JavaScript files modified
|
|
- Constitution now accurately reflects server.js and proxy.js patterns
|
|
Modified Sections:
|
|
- Section I.V: Complete rewrite of VM Context Injection Pattern section
|
|
- Section I.V: Rationale updated to explain spread operator benefits
|
|
Templates Status:
|
|
✅ All templates - No changes needed (documentation-only update)
|
|
Follow-up TODOs:
|
|
- Consider updating proxy.js to use direct variable access instead of globalThis["name"]
|
|
-->
|
|
|
|
# Proxy Scripts Constitution
|
|
|
|
## Core Principles
|
|
|
|
### I. Monolithic Architecture (NON-NEGOTIABLE)
|
|
|
|
**ALL business logic, data processing, authentication, and request handling MUST exist within the `src/proxyScripts/proxy.js` file.** Pure utility/helper functions MAY be extracted to `src/globalVariables/helpers.js` if they improve code organization. The `server.js` file should ONLY handle:
|
|
- HTTP server setup
|
|
- Configuration loading
|
|
- Global object injection into isolated context
|
|
- Loading src/proxyScripts/proxy.js via `vm.Script` and `vm.createContext`
|
|
- Loading src/globalVariables/helpers.js via `vm.Script` (optional)
|
|
- Per-request context creation with all necessary globals
|
|
|
|
**Implementation via vm.Script**:
|
|
`src/proxyScripts/proxy.js` MUST be loaded using Node.js `vm.Script` and executed in isolated contexts created per-request with `vm.createContext`. This ensures:
|
|
- Complete isolation from server.js module system
|
|
- All dependencies provided explicitly through context objects
|
|
- Zero ability to import/export modules
|
|
- Pure functional execution with injected dependencies
|
|
|
|
**Rationale**: Monolithic architecture enables simple packaging as a single IVA Studio proxy script and prevents fragmentation of business logic across multiple files. Using `vm.Script` enforces architectural boundaries at runtime, making it impossible for `src/proxyScripts/proxy.js` to access Node.js module system or file system, ensuring ALL functionality exists in one isolated, dependency-injected file.
|
|
|
|
**Helper Functions Pattern**: Pure utility functions (XML escaping, validation, formatting, routing) MAY be extracted to `src/globalVariables/helpers.js` to improve readability and maintainability. The helpers module:
|
|
- MUST be loaded via `vm.Script` (same isolation as proxy.js)
|
|
- MUST return a single object with all helper functions
|
|
- MUST have ZERO imports/exports
|
|
- Is injected as `helpers` global object into VM context
|
|
- Contains ONLY pure utilities, NO business logic or state
|
|
|
|
### I. Zero External Imports or Exports from `src/proxyScripts/proxy.js` (NON-NEGOTIABLE)
|
|
|
|
`src/proxyScripts/proxy.js` MUST have **ZERO import statements**. All dependencies MUST be provided through `vm.createContext` by server.js.
|
|
|
|
`src/proxyScripts/proxy.js` MUST have **ZERO export statements**. The file MUST be pure JavaScript code executed in an isolated VM context.
|
|
|
|
**File system access** from `src/proxyScripts/proxy.js` is **ABSOLUTELY PROHIBITED** under any circumstances. The `fs` module MUST NOT be accessible.
|
|
|
|
**External libraries** (axios, jwt, googleapis, etc.) MUST NOT be imported. Dependencies are injected through VM context by server.js.
|
|
|
|
**Rationale**: Using `vm.Script` and `vm.createContext` enforces architectural boundaries at the VM level. src/proxyScripts/proxy.js runs in an isolated context with NO access to Node.js module system, file system, or process globals. ALL dependencies must be explicitly injected per-request through the context object, ensuring src/proxyScripts/proxy.js contains ONLY pure business logic with zero capability for I/O operations.
|
|
|
|
**For data files that src/proxyScripts/proxy.js needs** (service account keys, certificates, secrets):
|
|
1. Place JSON files in `src/globalVariables/` directory
|
|
2. server.js loads them at startup using `loadGlobalObjects()`
|
|
3. server.js injects them into VM context per-request via `vm.createContext`
|
|
4. src/proxyScripts/proxy.js accesses them as simple variables in context (e.g., `google_drive_settings`)
|
|
|
|
**Example**:
|
|
- File: `src/globalVariables/google_drive_settings.json`
|
|
- Loading: server.js reads and assigns to `globalVariableContext.google_drive_settings`
|
|
- Injection: server.js adds `google_drive_settings: globalVariableContext.google_drive_settings` to context
|
|
- Access in src/proxyScripts/proxy.js: Direct variable access `google_drive_settings.serviceAccount`
|
|
|
|
**Enforcement**:
|
|
- src/proxyScripts/proxy.js MUST have NO `import` statements (file should start with comments, then code)
|
|
- src/proxyScripts/proxy.js MUST have NO `export` statements (no module.exports, no export keyword)
|
|
- Any `import` or `export` in src/proxyScripts/proxy.js MUST be rejected immediately
|
|
- server.js MUST load src/proxyScripts/proxy.js using `vm.Script` constructor
|
|
- server.js MUST execute via `script.runInContext(context)` with fresh context per request
|
|
- All dependencies injected through `vm.createContext({ ... })` context object
|
|
- VM isolation prevents access to require(), import(), fs, process, and Node.js globals
|
|
|
|
|
|
#### I.I What MUST Be in src/proxyScripts/proxy.js
|
|
|
|
The following MUST be implemented in `src/proxyScripts/proxy.js` (or extracted to helpers.js if pure utilities):
|
|
|
|
1. **Authentication**: Service Account JWT, OAuth flows, token management (MUST be in proxy.js)
|
|
2. **Business Logic**: All request handling, routing, and processing (MUST be in proxy.js)
|
|
3. **Data Transformation**: Document parsing, XML generation, data mapping (MUST be in proxy.js or helpers.js)
|
|
4. **API Integration**: Drive API queries, error mapping, response handling (MUST be in proxy.js)
|
|
5. **Request Queue**: FIFO queue for sequential processing (MUST be in proxy.js)
|
|
6. **Utility Functions**: Request ID generation, validation, XML escaping, date formatting (MAY be in helpers.js)
|
|
7. **Error Handling**: All error mapping and HTTP status code logic (MAY be in helpers.js)
|
|
|
|
**Helper Extraction Guidelines**:
|
|
- ✅ **CAN extract**: Pure functions, validators, formatters, XML utilities, error mappers, route parsers
|
|
- ❌ **MUST NOT extract**: Authentication, API calls, request queue, cached state, business decisions
|
|
|
|
**NO EXCEPTIONS for business logic** - Even complex authentication (OAuth 2.0, JWT) must be in proxy.js.
|
|
|
|
#### I.II What Can Be Separate Files
|
|
|
|
ONLY the following infrastructure modules may exist outside `src/proxyScripts/proxy.js`:
|
|
|
|
1. **src/logger.js**: Structured logging with console replacement (ONLY logging, no business logic)
|
|
2. **src/server.js**: HTTP server bootstrap and configuration (ONLY server setup, no business logic)
|
|
3. **config/**: JSON configuration files (data files, not code)
|
|
4. **src/globalVariables/**: JSON data files AND helpers.js module
|
|
- `*.json`: Runtime data loaded at startup (credentials, settings)
|
|
- `helpers.js`: Pure utility functions loaded via vm.Script (OPTIONAL)
|
|
5. **src/proxyScripts/**: Directory containing the main proxy script (proxy.js)
|
|
|
|
**Test files are exempt** - Test utilities may exist solely for test compatibility if needed, but MUST NOT be imported by production code.
|
|
|
|
**File Structure**:
|
|
```
|
|
src/
|
|
├── proxyScripts/
|
|
│ └── proxy.js # Main business logic (authentication, API, queue)
|
|
├── globalVariables/
|
|
│ ├── *.json # Data files for VM context
|
|
│ └── helpers.js # Pure utility functions (OPTIONAL)
|
|
├── logger.js # Structured logging
|
|
└── server.js # HTTP server bootstrap
|
|
config/
|
|
└── default.json # Infrastructure settings
|
|
```
|
|
|
|
**helpers.js Pattern**:
|
|
- MUST be loaded using `vm.Script` (same isolation as proxy.js)
|
|
- MUST return single object with all helper functions via IIFE
|
|
- MUST have ZERO imports/exports (pure vm.Script execution)
|
|
- Loaded by `loadGlobalVariableFunctions()` which scans for ALL .js files
|
|
- Filename determines global key: `helpers.js` → `globalVariableContext.helpers`
|
|
- Injected as `helpers` global object into VM context
|
|
- Contains ONLY pure utilities: validators, formatters, XML, error mappers
|
|
- MUST NOT contain: authentication, API calls, state, business decisions
|
|
- Executed in tempContext with full access to globalVMContext and globalVariableContext
|
|
|
|
#### I.III Enforcement
|
|
|
|
During code review and planning:
|
|
- ANY file in `src/proxyScripts/` besides `proxy.js` MUST be challenged
|
|
- ANY file in `src/globalVariables/` besides `helpers.js` and `*.json` MUST be challenged
|
|
- ANY file in `src/` besides `proxyScripts/`, `globalVariables/`, `logger.js`, `server.js` MUST be challenged
|
|
- Authentication, even if complex, MUST be in `src/proxyScripts/proxy.js` (never in helpers.js)
|
|
- Business logic MUST be in `src/proxyScripts/proxy.js` (never in helpers.js)
|
|
- Exceptions require explicit constitutional justification with measurable trade-offs
|
|
- When in doubt about helpers extraction, keep it in `src/proxyScripts/proxy.js`
|
|
|
|
**RED FLAGS to reject immediately:**
|
|
- Separate files for: auth, database, utilities, helpers, services, controllers, models
|
|
- Any file containing business logic or domain knowledge
|
|
- Multiple files "organizing" the codebase
|
|
|
|
#### I.IV Configuration
|
|
|
|
- Configuration for the Node.js web server infrastructure should be stored as JSON in `config/default.json`.
|
|
- `config/default.json` MUST contain ONLY infrastructure settings: server (host, port), logging level
|
|
- `config/default.json` MUST NOT contain authentication credentials, secrets, API keys, or behavioral configuration
|
|
- Authentication credentials, secrets, and ALL behavioral configuration MUST be stored in `src/globalVariables/` directory as JSON files
|
|
- Global JSON files are automatically loaded by server.js and made available as global objects
|
|
- server.js should validate both configuration from `config/default.json` AND global objects from `src/globalVariables/` directory
|
|
|
|
#### I.V Global Objects Provided by server.js
|
|
|
|
The `server.js` file MUST inject the following objects into VM context for use by `src/proxyScripts/proxy.js`:
|
|
|
|
**VM Context Injection Pattern:**
|
|
|
|
server.js uses a spread operator pattern for cleaner context creation:
|
|
|
|
```javascript
|
|
// Define static VM context (libraries and built-ins)
|
|
const globalVMContext = {
|
|
URLSearchParams,
|
|
URL,
|
|
console: logger,
|
|
crypto,
|
|
axios,
|
|
uuidv4,
|
|
jwt,
|
|
xmlBuilder,
|
|
};
|
|
|
|
// Load dynamic data from src/globalVariables/ directory
|
|
let globalVariableContext = {}; // Populated by loadGlobalObjects() and loadGlobalVariableFunctions()
|
|
|
|
// Load JSON data files at startup
|
|
loadGlobalObjects(); // Loads *.json files
|
|
|
|
// Load function modules (.js files) at startup
|
|
loadGlobalVariableFunctions(); // Loads *.js files
|
|
// Pattern for loading .js files:
|
|
// 1. Scan globalVariables/ for all *.js files (excluding *.example.js)
|
|
// 2. For each file, create tempContext with {...globalVMContext, ...globalVariableContext}
|
|
// 3. Execute file via vm.Script in tempContext
|
|
// 4. Store returned object in globalVariableContext using filename as key
|
|
// Example: helpers.js returns object → globalVariableContext.helpers = object
|
|
|
|
// Per-request: Create fresh context with all dependencies
|
|
const context = vm.createContext({
|
|
...globalVMContext, // Spread static dependencies
|
|
...globalVariableContext, // Spread dynamic data (JSON + function modules)
|
|
req, // Fresh request object
|
|
res // Fresh response object
|
|
});
|
|
script.runInContext(context);
|
|
```
|
|
|
|
**Note:** src/proxyScripts/proxy.js accesses these as direct variables (e.g., `google_drive_settings`, not `globalThis["google_drive_settings"]`). The VM context makes all properties available as top-level variables.
|
|
|
|
**Core Infrastructure Context Variables:**
|
|
|
|
1. **console** - Custom logger from `logger.js`
|
|
- Purpose: Structured JSON logging
|
|
- Usage: `console.info()`, `console.debug()`, `console.error()`
|
|
- Injected from: `globalVMContext.console` (set to `logger`)
|
|
|
|
2. **crypto** - Web Crypto API (built-in)
|
|
- Purpose: UUID generation, cryptographic operations
|
|
- Usage: `crypto.randomUUID()`, etc.
|
|
- Injected from: `globalVMContext.crypto`
|
|
- Note: Web Crypto API available by default in Node.js
|
|
|
|
3. **axios** - HTTP client library
|
|
- Purpose: Making HTTP requests to external APIs
|
|
- Usage: `axios.get(url)`, `axios.post(url, data)`
|
|
- Package: `axios`
|
|
- Injected from: `globalVMContext.axios`
|
|
|
|
4. **uuidv4** - UUID v4 generator
|
|
- Purpose: Generate RFC4122 compliant UUIDs
|
|
- Usage: `uuidv4()` returns string like "110ec58a-a0f2-4ac4-8393-c866d813b8d1"
|
|
- Package: `uuid` (v4 function only)
|
|
- Injected from: `globalVMContext.uuidv4`
|
|
|
|
5. **jwt** - JSON Web Token library
|
|
- Purpose: Creating and verifying JWTs for authentication
|
|
- Usage: `jwt.sign(payload, secret)`, `jwt.verify(token, secret)`
|
|
- Package: `jsonwebtoken`
|
|
- Injected from: `globalVMContext.jwt`
|
|
|
|
6. **xmlBuilder** - XML builder/generator
|
|
- Purpose: Constructing XML documents programmatically
|
|
- Usage: `xmlBuilder({ root: { child: 'value' } })`
|
|
- Package: `xmlbuilder2` (create function)
|
|
- Injected from: `globalVMContext.xmlBuilder`
|
|
|
|
**Built-in Web APIs:**
|
|
|
|
7. **URLSearchParams** - URL query string parser (built-in)
|
|
- Purpose: Parse and manipulate URL query strings
|
|
- Usage: `new URLSearchParams(queryString)`
|
|
- Injected from: `globalVMContext.URLSearchParams`
|
|
|
|
8. **URL** - URL parser (built-in)
|
|
- Purpose: Parse and manipulate URLs
|
|
- Usage: `new URL(urlString)`
|
|
- Injected from: `globalVMContext.URL`
|
|
- Note: Currently not included in globalVMContext but available in Node.js by default
|
|
|
|
**Dynamic Data Context Variables:**
|
|
|
|
9. **Dynamic JSON objects from src/globalVariables/ directory**
|
|
- Purpose: Authentication credentials, secrets, API keys, and behavioral configuration
|
|
- Pattern: Each `src/globalVariables/filename.json` loaded by server.js → added to `globalVariableContext` → spread into VM context
|
|
- Examples:
|
|
- `src/globalVariables/google_drive_settings.json` → context variable `google_drive_settings` (consolidated service account, scopes, drive query, sitemap config)
|
|
- `src/globalVariables/api-keys.json` → context variable `api_keys` (API keys and secrets)
|
|
- `src/globalVariables/custom-config.json` → context variable `custom_config` (behavioral settings)
|
|
- Usage in src/proxyScripts/proxy.js: Direct variable access `const settings = google_drive_settings;`
|
|
- Loading: By server.js at startup using `loadGlobalObjects()` function
|
|
- Injection: Via spread operator `...globalVariableContext` in `vm.createContext()`
|
|
- **Note**: ALL authentication, secrets, and behavioral configuration MUST be in src/globalVariables/, NEVER in config/default.json
|
|
|
|
**Helper Functions Module:**
|
|
|
|
10. **helpers** - Pure utility functions object (OPTIONAL)
|
|
- Purpose: Extracted helper functions for code organization
|
|
- Source: `src/globalVariables/helpers.js` loaded via `vm.Script`
|
|
- Pattern: IIFE returning object with all helper functions
|
|
- Loading: server.js loads via `loadGlobalVariableFunctions()` at startup
|
|
- Generic Loading Pattern:
|
|
- All .js files in globalVariables/ are loaded automatically
|
|
- Filename determines key: `helpers.js` → `globalVariableContext.helpers`
|
|
- Executed in tempContext with `{...globalVMContext, ...globalVariableContext}`
|
|
- Can access all VM globals: axios, jwt, crypto, console, etc.
|
|
- Can access previously loaded JSON data and function modules
|
|
- Injection: Spread into VM context via `...globalVariableContext`
|
|
- Usage in src/proxyScripts/proxy.js: `helpers.functionName()` (e.g., `helpers.generateRequestId()`)
|
|
- Contains: Pure utilities only (validators, formatters, XML, error mappers, route parsers)
|
|
- MUST NOT contain: Authentication, API calls, state, business logic
|
|
- Example functions:
|
|
- `helpers.generateRequestId()` - UUID generation
|
|
- `helpers.validateDocumentId(id)` - Document ID validation
|
|
- `helpers.escapeXml(str)` - XML character escaping
|
|
- `helpers.generateSitemap(docs, baseUrl)` - Sitemap generation
|
|
- `helpers.mapDriveErrorToHttp(error)` - Error mapping
|
|
- `helpers.parseRoute(method, url)` - Route parsing
|
|
- `helpers.DocumentCountExceededError` - Custom error class
|
|
- Generic Pattern Note: You can add more .js files (e.g., `utils.js`, `validators.js`)
|
|
and they will be automatically loaded as `globalVariableContext.utils`, etc.
|
|
|
|
**Request/Response Objects:**
|
|
|
|
11. **req** - HTTP IncomingMessage
|
|
- Purpose: Access request data (URL, method, headers, body)
|
|
- Injected fresh: Per-request from `http.createServer((req, res) => ...)`
|
|
|
|
12. **res** - HTTP ServerResponse
|
|
- Purpose: Send response to client
|
|
- Injected fresh: Per-request from `http.createServer((req, res) => ...)`
|
|
|
|
**Rationale**: Using `vm.createContext` with spread operator pattern for dependency injection achieves:
|
|
- **Runtime-enforced isolation** - src/proxyScripts/proxy.js physically cannot access Node.js module system or file system
|
|
- **Zero imports possible** - VM context has no `require()` or `import()` capability
|
|
- **Explicit dependencies** - All available objects must be explicitly listed in globalVMContext or globalVariableContext
|
|
- **Clean organization** - Static dependencies (globalVMContext) separated from dynamic data (globalVariableContext)
|
|
- **Per-request isolation** - Fresh context per request prevents cross-request state leakage
|
|
- **Testing simplicity** - Mock entire context object instead of individual module imports
|
|
- **Clear contracts** - Context spread pattern documents every dependency src/proxyScripts/proxy.js uses
|
|
- **Security boundaries** - VM sandbox prevents escape to underlying system
|
|
- **DRY principle** - Spread operators eliminate repetitive property declarations
|
|
|
|
|
|
#### I.VI Logging
|
|
|
|
Modify server.js to replace the global `console` object with the `logger` export from `logger.js`. This will make all console.log, console.info, console.error calls throughout the application use the custom logger.
|
|
|
|
Logging should use `logger.js` module that has the following functions:
|
|
|
|
- log - which defaults to the 'info' function
|
|
- info - which writes to stdout
|
|
- debug - which prefixes the output with "[DEBUG]" written in red font and writes to stdout
|
|
- error - which prefixes the output with "[ERROR]" written in red font and writes to stderr
|
|
|
|
### II. API-First Design
|
|
|
|
Every feature MUST expose a clear, documented API before implementation begins. APIs MUST follow RESTful principles where applicable, use consistent naming conventions, and include comprehensive error handling with meaningful status codes and messages.
|
|
|
|
**Rationale**: API-first design ensures contracts are stable, enables parallel front-end/back-end work, facilitates integration testing, and produces naturally documented systems.
|
|
|
|
### III. Test-First Development (NON-NEGOTIABLE)
|
|
|
|
Test-Driven Development is MANDATORY for all production code. The cycle MUST be:
|
|
|
|
1. Write failing tests
|
|
2. Obtain user approval of test scenarios
|
|
3. Implement minimum code to pass tests
|
|
4. Refactor while maintaining green tests
|
|
|
|
Unit tests MUST achieve minimum 80% code coverage. Integration tests MUST cover all API contracts and critical user flows.
|
|
|
|
**Rationale**: TDD catches defects early, documents expected behavior, enables confident refactoring, and ensures all code paths are exercised.
|
|
|
|
### IV. Security & Privacy by Default
|
|
|
|
All user data MUST be treated as sensitive. OAuth tokens, credentials, and personal information MUST be encrypted at rest and in transit. The principle of least privilege MUST govern all access controls. Audit logging MUST track all data access and modifications.
|
|
|
|
**Rationale**: Privacy violations damage trust and carry legal liability. Security must be foundational, not retrofitted.
|
|
|
|
### V. Observability & Debuggability
|
|
|
|
All operations MUST emit structured logs with appropriate severity levels (DEBUG, INFO, WARN, ERROR). Errors MUST include context (request IDs, user IDs, operation names) sufficient for diagnosis. Performance-critical paths MUST expose metrics (latency, throughput, error rates).
|
|
|
|
**Rationale**: Production issues are inevitable. Observable systems reduce mean time to resolution and enable proactive problem detection.
|
|
|
|
### VI. Semantic Versioning & Change Management
|
|
|
|
All public APIs MUST follow semantic versioning (MAJOR.MINOR.PATCH):
|
|
|
|
- MAJOR: Breaking changes that require consumer updates
|
|
- MINOR: Backward-compatible feature additions
|
|
- PATCH: Backward-compatible bug fixes
|
|
|
|
Breaking changes MUST include migration guides and deprecation notices for at least one MINOR version before removal.
|
|
|
|
**Rationale**: Clear versioning communicates impact, enables safe upgrades, and respects downstream consumers' need for stability.
|
|
|
|
### VII. Simplicity, Minimal Dependencies & YAGNI
|
|
|
|
Implement only features with demonstrated need. Choose the simplest solution that satisfies current requirements. Reject premature optimization and speculative features. Complexity MUST be explicitly justified with measurable benefits.
|
|
|
|
**Dependency Minimization**: Prefer Node.js built-in modules over external npm packages. Each external dependency MUST be justified by:
|
|
|
|
- Significant functionality that would take >2 days to implement correctly
|
|
- Active maintenance and security track record
|
|
- Clear, documented benefit that outweighs maintenance risk
|
|
|
|
Prohibited without explicit approval:
|
|
|
|
- Utility libraries for functionality Node.js provides natively (fs, path, crypto, http, etc.)
|
|
- Heavy framework dependencies when lightweight alternatives exist
|
|
- Multiple packages solving the same problem
|
|
|
|
**Rationale**: External dependencies introduce supply chain risk, increase bundle size, complicate auditing, and create maintenance burden. Node.js built-ins are stable, well-tested, and maintained by the platform.
|
|
|
|
## API Design Standards
|
|
|
|
All external APIs MUST:
|
|
|
|
- Accept and return JSON for structured data
|
|
- Use standard HTTP methods (GET, POST, PUT, DELETE, PATCH) semantically
|
|
- Return appropriate HTTP status codes (2xx success, 4xx client errors, 5xx server errors)
|
|
- Include rate limiting headers where applicable
|
|
- Version endpoints explicitly (e.g., /v1/, /v2/)
|
|
- Document all parameters, responses, and error codes using OpenAPI/Swagger
|
|
|
|
Response formats MUST be consistent and include:
|
|
|
|
- Timestamp of response generation
|
|
- Request correlation ID for tracing
|
|
- Pagination metadata for list operations
|
|
- Clear error messages with actionable guidance
|
|
|
|
## Security & Data Protection
|
|
|
|
Authentication & Authorization MUST:
|
|
|
|
- Never log or expose credentials, tokens, or API keys
|
|
- Validate all input to prevent injection attacks
|
|
- Apply rate limiting to prevent abuse
|
|
|
|
Data Handling MUST:
|
|
|
|
- Minimize data retention—delete temporary files promptly
|
|
- Encrypt sensitive data using industry-standard algorithms (AES-256 or equivalent)
|
|
- Sanitize all user-supplied content before processing
|
|
- Implement CSRF protection for web interfaces
|
|
|
|
## Development Workflow
|
|
|
|
Code Reviews MUST:
|
|
|
|
- Verify alignment with all constitutional principles
|
|
- Check test coverage meets minimum thresholds
|
|
- Validate API contracts match documentation
|
|
- Confirm security best practices are followed
|
|
|
|
Quality Gates (ALL must pass before merge):
|
|
|
|
- All tests pass (unit, integration, end-to-end)
|
|
- Code coverage ≥ 80%
|
|
- No critical security vulnerabilities (use automated scanning)
|
|
- Documentation updated for API/behavior changes
|
|
- Performance regression checks pass
|
|
|
|
Deployment MUST:
|
|
|
|
- Use automated CI/CD pipelines
|
|
- Include smoke tests post-deployment
|
|
- Support rollback within 5 minutes
|
|
- Include release notes documenting all changes
|
|
|
|
## Technology Stack
|
|
|
|
**Platform**: Node.js (LTS version or later)
|
|
|
|
**Mandatory Baseline**:
|
|
|
|
- Use Node.js built-in modules as first choice (fs, path, crypto, http, https, stream, util, url, querystring, etc.)
|
|
- **DO NOT use 'events' EventEmitter** - implement simple patterns directly (e.g., Promise-based queues)
|
|
- Plain JavaScript (ES2022+) without TypeScript
|
|
- JSDoc comments for type documentation where needed
|
|
- JavaScript tooling (ESLint, Prettier) does not count against dependency budget
|
|
- Native test runner (node:test) or minimal test framework
|
|
|
|
**Dependency Approval Process**:
|
|
Any external npm package (excluding JavaScript tooling like ESLint and Prettier) MUST be justified in the feature specification with:
|
|
|
|
1. **Functionality gap**: What Node.js built-ins cannot do
|
|
2. **Implementation cost**: Estimated effort to build vs. maintain dependency
|
|
3. **Risk assessment**: Package security, maintenance history, download stats
|
|
4. **Alternatives considered**: Why alternatives were rejected
|
|
|
|
**Examples of acceptable dependencies** (when justified):
|
|
|
|
- xmlbuilder2
|
|
- axios
|
|
- uuid
|
|
|
|
**Examples of prohibited dependencies** (use Node.js built-ins or inline implementations instead):
|
|
|
|
- lodash/underscore (use native Array/Object methods)
|
|
- moment/date-fns (use native Date, Intl.DateTimeFormat)
|
|
- rimraf (use fs.rm with recursive: true)
|
|
- mkdirp (use fs.mkdir with recursive: true)
|
|
- **EventEmitter from 'events'** (implement simple queue classes directly - no need for event system)
|
|
- express/fastify (use native http/https for simple servers
|
|
|
|
**Node.js built-in modules to prefer:**
|
|
- Use 'node:' prefix for clarity: `import crypto from 'node:crypto'`
|
|
- Acceptable built-ins: fs, path, crypto, http, https, stream, util, url, querystring, etc.
|
|
- NOT acceptable: 'events' EventEmitter - implement patterns directly without event system
|
|
|
|
IMPORTANT : All dependencies that are not acceptable must be approved when running plan and task agents
|
|
|
|
## Governance
|
|
|
|
This constitution supersedes all other development practices and guidelines. When conflicts arise between this document and team conventions, the constitution takes precedence.
|
|
|
|
Amendments to this constitution require:
|
|
|
|
1. Documented justification explaining the need for change
|
|
2. Impact analysis of affected systems and workflows
|
|
3. Approval from project maintainers
|
|
4. Migration plan for any breaking changes
|
|
5. Update of version number following semantic versioning rules
|
|
|
|
All pull requests, code reviews, and design discussions MUST verify compliance with constitutional principles. Exceptions MUST be rare, explicitly justified with measurable trade-offs, and documented in the relevant specification or plan.
|
|
|
|
For runtime development guidance, refer to `.github/prompts/` and `.github/agents/` files which operationalize these principles into agent workflows.
|
|
|
|
**Version**: 1.14.0 | **Ratified**: 2026-03-05 | **Last Amended**: 2026-03-07
|