Reorganize project structure: relocate proxy.js and global directory

- Move src/proxy.js → src/proxyScripts/proxy.js
- Move global/ → src/globalVariables/
- Update constitution.md to reflect new file locations
- Update all documentation references to new paths
- Consolidate all source code under src/ directory

Constitution version: 1.15.0 → 1.16.0

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
2026-03-07 10:35:03 -06:00
parent c2ecc72775
commit f6710203c7
3 changed files with 123 additions and 40 deletions

View File

@@ -1,5 +1,49 @@
<!--
Sync Impact Report:
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)
@@ -33,59 +77,59 @@ Follow-up TODOs:
### I. Monolithic Architecture (NON-NEGOTIABLE)
**ALL business logic, data processing, authentication, and request handling MUST exist within the `proxy.js` file.** The `server.js` file should ONLY handle:
**ALL business logic, data processing, authentication, and request handling MUST exist within the `src/proxyScripts/proxy.js` file.** The `server.js` file should ONLY handle:
- HTTP server setup
- Configuration loading
- Global object injection into isolated context
- Loading proxy.js via `vm.Script` and `vm.createContext`
- Loading src/proxyScripts/proxy.js via `vm.Script` and `vm.createContext`
- Per-request context creation with all necessary globals
**Implementation via vm.Script**:
`proxy.js` MUST be loaded using Node.js `vm.Script` and executed in isolated contexts created per-request with `vm.createContext`. This ensures:
`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 `proxy.js` to access Node.js module system or file system, ensuring ALL functionality exists in one isolated, dependency-injected file.
**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.
### I. Zero External Imports or Exports from `proxy.js` (NON-NEGOTIABLE)
### I. Zero External Imports or Exports from `src/proxyScripts/proxy.js` (NON-NEGOTIABLE)
`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 import statements**. All dependencies MUST be provided through `vm.createContext` by server.js.
`proxy.js` MUST have **ZERO export statements**. The file MUST be pure JavaScript code executed in an isolated VM context.
`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 `proxy.js` is **ABSOLUTELY PROHIBITED** under any circumstances. The `fs` module MUST NOT be accessible.
**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. 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 proxy.js contains ONLY pure business logic with zero capability for I/O operations.
**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 proxy.js needs** (service account keys, certificates, secrets):
1. Place JSON files in `global/` directory
**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. proxy.js accesses them as simple variables in context (e.g., `google_drive_settings`)
4. src/proxyScripts/proxy.js accesses them as simple variables in context (e.g., `google_drive_settings`)
**Example**:
- File: `global/google_drive_settings.json`
- 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 proxy.js: Direct variable access `google_drive_settings.serviceAccount`
- Access in src/proxyScripts/proxy.js: Direct variable access `google_drive_settings.serviceAccount`
**Enforcement**:
- proxy.js MUST have NO `import` statements (file should start with comments, then code)
- proxy.js MUST have NO `export` statements (no module.exports, no export keyword)
- Any `import` or `export` in proxy.js MUST be rejected immediately
- server.js MUST load proxy.js using `vm.Script` constructor
- 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 proxy.js
#### I.I What MUST Be in src/proxyScripts/proxy.js
The following MUST be implemented as inline functions within `proxy.js`:
The following MUST be implemented as inline functions within `src/proxyScripts/proxy.js`:
1. **Authentication**: Service Account JWT, OAuth flows, token management
2. **Business Logic**: All request handling, routing, and processing
@@ -99,21 +143,37 @@ The following MUST be implemented as inline functions within `proxy.js`:
#### I.II What Can Be Separate Files
ONLY the following infrastructure modules may exist outside `proxy.js`:
ONLY the following infrastructure modules may exist outside `src/proxyScripts/proxy.js`:
1. **logger.js**: Structured logging with console replacement (ONLY logging, no business logic)
2. **server.js**: HTTP server bootstrap and configuration (ONLY server setup, no business logic)
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 loaded at startup (credentials, settings)
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 (monolithic)
├── globalVariables/
│ └── *.json # Data files for VM context
├── logger.js # Structured logging
└── server.js # HTTP server bootstrap
config/
└── default.json # Infrastructure settings
```
#### I.III Enforcement
During code review and planning:
- ANY file in `src/` besides `proxy.js`, `logger.js`, `server.js` MUST be challenged
- Authentication, even if complex, MUST be inline in `proxy.js`
- ANY file in `src/proxyScripts/` besides `proxy.js` MUST be challenged
- ANY file in `src/` besides `proxyScripts/`, `logger.js`, `server.js` MUST be challenged
- Authentication, even if complex, MUST be inline in `src/proxyScripts/proxy.js`
- Exceptions require explicit constitutional justification with measurable trade-offs
- When in doubt, inline it in `proxy.js`
- When in doubt, inline it in `src/proxyScripts/proxy.js`
**RED FLAGS to reject immediately:**
- Separate files for: auth, database, utilities, helpers, services, controllers, models
@@ -125,13 +185,13 @@ During code review and planning:
- 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 `global/` directory as JSON files
- 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 `global/` directory
- 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 `proxy.js`:
The `server.js` file MUST inject the following objects into VM context for use by `src/proxyScripts/proxy.js`:
**VM Context Injection Pattern:**
@@ -149,7 +209,7 @@ const globalVMContext = {
xmlBuilder,
};
// Load dynamic data from global/ directory into globalVariableContext
// Load dynamic data from src/globalVariables/ directory into globalVariableContext
let globalVariableContext = {}; // Populated by loadGlobalObjects()
// Per-request: Create fresh context with all dependencies
@@ -162,7 +222,7 @@ const context = vm.createContext({
script.runInContext(context);
```
**Note:** 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.
**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:**
@@ -216,17 +276,17 @@ script.runInContext(context);
**Dynamic Data Context Variables:**
9. **Dynamic JSON objects from global/ directory**
9. **Dynamic JSON objects from src/globalVariables/ directory**
- Purpose: Authentication credentials, secrets, API keys, and behavioral configuration
- Pattern: Each `global/filename.json` loaded by server.js → added to `globalVariableContext` → spread into VM context
- Pattern: Each `src/globalVariables/filename.json` loaded by server.js → added to `globalVariableContext` → spread into VM context
- Examples:
- `global/google_drive_settings.json` → context variable `google_drive_settings` (consolidated service account, scopes, drive query, sitemap config)
- `global/api-keys.json` → context variable `api_keys` (API keys and secrets)
- `global/custom-config.json` → context variable `custom_config` (behavioral settings)
- Usage in proxy.js: Direct variable access `const settings = google_drive_settings;`
- `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 global/, NEVER in config/default.json
- **Note**: ALL authentication, secrets, and behavioral configuration MUST be in src/globalVariables/, NEVER in config/default.json
**Request/Response Objects:**
@@ -239,13 +299,13 @@ script.runInContext(context);
- Injected fresh: Per-request from `http.createServer((req, res) => ...)`
**Rationale**: Using `vm.createContext` with spread operator pattern for dependency injection achieves:
- **Runtime-enforced isolation** - proxy.js physically cannot access Node.js module system or file system
- **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 proxy.js uses
- **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

View File

@@ -0,0 +1,23 @@
{
"serviceAccount": {
"type": "service_account",
"project_id": "black-portfolio-486723-f2",
"private_key_id": "01d829a7ef4b4a85506ad31718bb4331c8618183",
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQChyph2XLEiFtmN\nvnetGXI4xXwwH1rxd9ieDD9jMfBGvTjAcbhLILO4BBa+bWMyHzjyK7AKp4a4Bs5w\ny3dYHCFlCF/46kf2j+wcCDmnBTHcjS61E+ycSy9Jznz7myZac3bzf4QT3z4po02S\n+okJdH1CKGFepWfQysmATCQ8+nQQCovjydQI6WX+q5LlUpGv3WLjHJsX0YNpy1fS\nHglMw57iY5s7qprdFJNlQqgVy9TQGxzcIZtRFW6YriMhZty7Nxdr5hvLWgqtSNuw\ntFzqeWcJyuCbROlDTWGmKtlwa8lRmtNXWSrIPNKvDaicr7HLUoMh3phfMMtxi1OC\nfZhXvd0BAgMBAAECggEAAURGka5/uh1ejvfPzy6ILKzSUEcOPB5zhx0VOeHSMInt\nWII0wUeoaTi6I/EpGK4CcQYcajXwmyQzADKInNC3ZneJ1vyga1F/cE1Ubw6ZFYcT\nB5AIOdrzwU69KeQM4/exgF4rhsi4T2+aeoZ3gD1jLcDGuTdqGYTH7iHSerooLS1h\nGwG5wSy0fn5vpRNfMZLZ9ZdPQi+PQujiVDkuABYdax018kHyqFTxCzaxX6uuSKMH\nDFh3k6q/WUxgEmQfs6cvJKVbcXs8vPU4ROaz2shId3NV/jev1orrRpFOl5ptKBxh\nbtOykl21r96gGTN2zs32KgleDYFDpscDk3Ik2FqXkQKBgQDTJ6iSCvjUflWl6HQz\nuuDuXMElK842vr3SLAgUskB4hY6Hy4kZskfIth+KvAM+wxS6JPUXx2p6VaL8P4Av\nJklwQdXHEfSRrgBncUtfFcrcvvykOioaL17fS2EPsbjjdsBt9oZCiahRDSwoIhrE\nwKqwHlrmVWC7EluNRxxzPKFuEQKBgQDEJxPVSWQUIWtCHwa1NnU1oxvUTdSSkGRJ\n3AG9zAu3r0mwqA2BvAVDbfDQmvWgXALvmaLcIkKJOEcTv7MuH9o5TyEoBBJ4DtKY\nQWDcPn0rBCvX7GQ3b5r9DhbiubtCotyJQnL6LIpwZpJC+sDTq5x6nI3TrOrFmyGA\n4XlNL+5P8QKBgD7479wGK6lrt+1Pwv/+dsB/pxaH1usavY+llA9gDbwj0JsNB2lD\ncwcX0ZZVdf5Mvay6AuJBla7ARWhHI9pr57Dz4WaKI08i/nnbHuhPnn1w8/WiZxYC\nFKAxYdQFY6dqrf7da7MCTNFHRWj+qs8MyprVorRYuA1ybx1WHNT9OwORAoGABJ/L\nNucBBfx3s9pZZSJAhyAuQsYG8eGXi6o1HE1YJV9rhE+h6eIN2bYYzEIq8jnZE97y\nWPAx01xRSKTnS3oSwfEcnf3ilZP74P0BlI+gkcgKZI+9GRV3eOnBHl00jfCa9F1t\nqnosVVQFtLCGpTbRfI5+RXQ5IKl0k749BtXPb3ECgYBLO3S+EBTcsS9fYzq9dNSk\n5WG2DEqezgciJ46ZPtLqLs4IhDNVozhorY9lfg9LfQpY5gAJR88eLtdAv0quDbYn\npxxMglR09qNmcX/nPvRfCvua45n2VaTRuUdyEzjKUtUlp5oVWo4XmKLqPTOeJkuh\nT85FN2oAmw0ZGJ0eLiU7tQ==\n-----END PRIVATE KEY-----\n",
"client_email": "n8n-service@black-portfolio-486723-f2.iam.gserviceaccount.com",
"client_id": "108246676308214231920",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/n8n-service%40black-portfolio-486723-f2.iam.gserviceaccount.com",
"universe_domain": "googleapis.com"
},
"scopes": [
"https://www.googleapis.com/auth/drive.readonly"
],
"driveQuery": "trashed = false",
"proxyScriptEndPoint": "http://localhost:3000",
"sitemap": {
"maxUrls": 50000
}
}