380 lines
18 KiB
Markdown
380 lines
18 KiB
Markdown
<!--
|
|
Sync Impact Report:
|
|
Version: 1.11.0 → 1.12.0 (MINOR: Moved Google authentication config to global JSON objects)
|
|
Modified Principles:
|
|
- Section I.V: Added google-scopes.json to dynamic JSON objects examples
|
|
- Removed google.* configuration from config/default.json
|
|
- proxy.js Section 1 now reads ONLY from globalThis['service-account-key'] and globalThis['google-scopes']
|
|
- config/default.json now contains ONLY infrastructure (server, logging)
|
|
- proxy.js authentication is now 100% global-object-based with zero config dependency
|
|
Modified Files:
|
|
- Created global/google-scopes.json with scopes array setting
|
|
- Removed entire google section from config/default.json
|
|
- Updated proxy.js Section 1 (initializeServiceAccount) to use only global objects
|
|
- Updated server.js validateConfig() to validate new global objects
|
|
Breaking Changes:
|
|
- config.google.serviceAccountEmail removed (credentials are in global/service-account-key.json)
|
|
- config.google.serviceAccountKeyPath removed (always global/service-account-key.json)
|
|
- config.google.scopes removed (now in global/google-scopes.json)
|
|
- All Google authentication config now exclusively in global/ directory
|
|
Modified Sections:
|
|
- Section I.V: Updated examples list to include google-scopes
|
|
- Section I.IV: Clarified config/default.json contains ONLY infrastructure
|
|
Templates Status:
|
|
⚠ plan-template.md - Document global/ for ALL authentication and behavioral config
|
|
⚠ tasks-template.md - Never put auth, secrets, or behavioral config in config/default.json
|
|
✅ spec-template.md - No changes required
|
|
Follow-up TODOs:
|
|
- Update tests to mock globalThis['service-account-key'] and globalThis['google-scopes']
|
|
- Document scopes format in google-scopes.json.example
|
|
- Verify all config references removed from proxy.js Section 1
|
|
-->
|
|
|
|
# Proxy Scripts Constitution
|
|
|
|
## Core Principles
|
|
|
|
### 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:
|
|
- HTTP server setup
|
|
- Configuration loading
|
|
- Global console replacement with custom logger
|
|
- Request delegation to `proxy.handleRequest()`
|
|
|
|
**Rationale**: Monolithic architecture enables simple packaging as a single IVA Studio proxy script and prevents fragmentation of business logic across multiple files. ALL functionality must be in one place.
|
|
|
|
### I. Zero External Imports from `proxy.js` (NON-NEGOTIABLE)
|
|
|
|
`proxy.js` MUST have **ZERO import statements**. All dependencies MUST be provided as global objects by server.js.
|
|
|
|
**File system access** from `proxy.js` is **ABSOLUTELY PROHIBITED** under any circumstances. The `fs` module MUST NOT be imported into proxy.js.
|
|
|
|
**External libraries** (axios, jwt, googleapis, etc.) MUST NOT be imported. Use globals provided by server.js instead.
|
|
|
|
**Rationale**: Monolithic architecture requires ALL I/O operations and dependency injection to be centralized in server.js, ensuring proxy.js contains ONLY pure business logic.
|
|
|
|
**For data files that proxy.js needs** (service account keys, certificates, secrets):
|
|
1. Place JSON files in `global/` directory
|
|
2. server.js automatically loads them as global objects using the filename as the object name
|
|
3. proxy.js accesses them via `globalThis[objectName]`
|
|
|
|
**Example**:
|
|
- File: `global/service-account-key.json`
|
|
- Global: `globalThis['service-account-key']`
|
|
- Access in proxy.js: `const credentials = globalThis['service-account-key']`
|
|
|
|
**Enforcement**:
|
|
- proxy.js MUST have NO `import` statements (file should start with comments, then code)
|
|
- During code review, verify first line of code is NOT an import
|
|
- Any `import` statement in proxy.js MUST be rejected immediately
|
|
- All file operations MUST be in server.js, which then provides data via globals
|
|
- All external libraries MUST be provided as globals by server.js
|
|
|
|
|
|
#### I.I What MUST Be in proxy.js
|
|
|
|
The following MUST be implemented as inline functions within `proxy.js`:
|
|
|
|
1. **Authentication**: Service Account JWT, OAuth flows, token management
|
|
2. **Business Logic**: All request handling, routing, and processing
|
|
3. **Data Transformation**: Document parsing, XML generation, data mapping
|
|
4. **API Integration**: Drive API queries, error mapping, response handling
|
|
5. **Request Queue**: FIFO queue for sequential processing
|
|
6. **Utility Functions**: Request ID generation, validation, XML escaping, date formatting
|
|
7. **Error Handling**: All error mapping and HTTP status code logic
|
|
|
|
**NO EXCEPTIONS** - Even complex authentication (OAuth 2.0, JWT) must be inline.
|
|
|
|
#### I.II What Can Be Separate Files
|
|
|
|
ONLY the following infrastructure modules may exist outside `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)
|
|
3. **config/**: JSON configuration files (data files, not code)
|
|
|
|
**Test files are exempt** - Test utilities may exist solely for test compatibility if needed, but MUST NOT be imported by production code.
|
|
|
|
#### 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`
|
|
- Exceptions require explicit constitutional justification with measurable trade-offs
|
|
- When in doubt, inline it in `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 `global/` 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
|
|
|
|
#### I.V Global Objects Provided by server.js
|
|
|
|
The `server.js` file MUST make the following objects available globally for use by `proxy.js`:
|
|
|
|
**Core Infrastructure Globals:**
|
|
|
|
1. **console** - Custom logger from `logger.js`
|
|
- Purpose: Structured JSON logging
|
|
- Usage: `console.info()`, `console.debug()`, `console.error()`
|
|
- Replaces: Built-in console object
|
|
|
|
2. **crypto** - Node.js crypto module
|
|
- Purpose: UUID generation, cryptographic operations
|
|
- Usage: `crypto.randomUUID()`, etc.
|
|
- Note: Cannot use name 'crypto' due to Web Crypto API conflict
|
|
- Replaces: `import crypto from 'node:crypto'` in proxy.js
|
|
|
|
3. **config** - Configuration object
|
|
- Purpose: Infrastructure settings ONLY (server host/port, logging level)
|
|
- Usage: `global.config.server.port`, `global.config.logging.level`
|
|
- Loaded: From `config/default.json` merged with ENV vars
|
|
- **DOES NOT contain**: Authentication, secrets, API keys, behavioral config (use global/ instead)
|
|
|
|
4. **axios** - HTTP client library
|
|
- Purpose: Making HTTP requests to external APIs
|
|
- Usage: `axios.get(url)`, `axios.post(url, data)`
|
|
- Package: `axios`
|
|
- Replaces: `import axios from 'axios'` in proxy.js
|
|
|
|
5. **uuidv4** - UUID v4 generator
|
|
- Purpose: Generate RFC4122 compliant UUIDs
|
|
- Usage: `uuidv4()` returns string like "110ec58a-a0f2-4ac4-8393-c866d813b8d1"
|
|
- Package: `uuid` (v4 function only)
|
|
- Replaces: `import { v4 as uuidv4 } from 'uuid'` in proxy.js
|
|
|
|
6. **jwt** - JSON Web Token library
|
|
- Purpose: Creating and verifying JWTs for authentication
|
|
- Usage: `jwt.sign(payload, secret)`, `jwt.verify(token, secret)`
|
|
- Package: `jsonwebtoken`
|
|
- Replaces: `import jwt from 'jsonwebtoken'` in proxy.js
|
|
|
|
7. **xmlBuilder** - XML builder/generator
|
|
- Purpose: Constructing XML documents programmatically
|
|
- Usage: `xmlBuilder({ root: { child: 'value' } })`
|
|
- Package: `xmlbuilder2` (create function)
|
|
- Replaces: `import { create } from 'xmlbuilder2'` in proxy.js
|
|
|
|
**Dynamic Data Globals:**
|
|
|
|
8. **Dynamic JSON objects from global/ directory**
|
|
- Purpose: Authentication credentials, secrets, API keys, and behavioral configuration
|
|
- Pattern: Each `global/filename.json` → `globalThis['filename']`
|
|
- Examples:
|
|
- `global/service-account-key.json` → `globalThis['service-account-key']` (Service Account credentials with client_email and private_key)
|
|
- `global/google-scopes.json` → `globalThis['google-scopes']` (OAuth2 scopes array for Google APIs)
|
|
- `global/sitemap-config.json` → `globalThis['sitemap-config']` (Sitemap settings like maxUrls)
|
|
- `global/drive-query.json` → `globalThis['drive-query']` (Drive API query filter)
|
|
- `global/api-keys.json` → `globalThis['api-keys']` (API keys and secrets)
|
|
- Usage in proxy.js: `const creds = globalThis['service-account-key']`, `const scopes = globalThis['google-scopes']`
|
|
- Loaded: Automatically by server.js at startup using `loadGlobalObjects()`
|
|
- **Note**: ALL authentication, secrets, and behavioral configuration MUST be in global/, NEVER in config/default.json
|
|
|
|
**Rationale**: Centralizing global setup and ALL file I/O in server.js achieves:
|
|
- **ZERO imports in proxy.js** - complete dependency injection pattern
|
|
- Consistent environment setup and library versions
|
|
- Easy testing (mock globals instead of mocking module imports)
|
|
- Clear separation: server.js = infrastructure & dependencies, proxy.js = pure business logic
|
|
- Single source of truth for dependency injection
|
|
- Direct REST API calls instead of heavyweight SDK wrappers
|
|
|
|
#### 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.11.0 | **Ratified**: 2026-03-05 | **Last Amended**: 2026-03-07
|