[Spec Kit] Implementation progress
This commit is contained in:
110
.github/copilot-instructions.md
vendored
110
.github/copilot-instructions.md
vendored
@@ -0,0 +1,110 @@
|
||||
<!-- SPECKIT START -->
|
||||
For additional context about technologies to be used, project structure,
|
||||
shell commands, and other important information, read the current plan at
|
||||
`specs/001-oidc-proxy-script/plan.md`
|
||||
<!-- SPECKIT END -->
|
||||
|
||||
## Project Overview
|
||||
|
||||
`kme-content-adapter` is an HTTP proxy adapter (Node.js ≥18, ESM) that searches and exports documents from KME via a single proxy script executed in a VM sandbox.
|
||||
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
npm run dev # Start with --watch (auto-restart on file changes)
|
||||
npm start # Start, piping logs through jq for pretty-printing
|
||||
npm test # Run all tests
|
||||
npm run test:unit # Unit tests only
|
||||
npm run test:integration # Integration tests only
|
||||
npm run test:contract # Contract tests only
|
||||
|
||||
# Run a single test file
|
||||
node --test tests/unit/my.test.js
|
||||
```
|
||||
|
||||
Tests use the Node.js built-in test runner (`node:test`). No test framework is installed.
|
||||
|
||||
Environment overrides: `PORT`, `HOST`, `LOG_LEVEL`.
|
||||
|
||||
## Architecture
|
||||
|
||||
The server loads `src/proxyScripts/proxy.js` once at startup using `vm.Script`, then executes it in a **fresh isolated VM context per request** via `vm.createContext`. This mirrors the target deployment environment (IVA Studio proxy script).
|
||||
|
||||
```
|
||||
src/
|
||||
├── proxyScripts/
|
||||
│ └── proxy.js # ALL business logic lives here
|
||||
├── globalVariables/
|
||||
│ ├── *.json # Runtime data injected into VM context
|
||||
│ └── adapterHelper.js # Pure utility functions (optional)
|
||||
├── logger.js # Structured JSON logger
|
||||
└── server.js # HTTP server bootstrap only
|
||||
config/
|
||||
└── default.json # Infrastructure settings (port, host, log level)
|
||||
```
|
||||
|
||||
**Context injection** — `server.js` injects these globals into every request context:
|
||||
|
||||
| Variable | Source |
|
||||
|---|---|
|
||||
| `console` | Custom structured logger (`logger.js`) |
|
||||
| `crypto` | Node.js Web Crypto API |
|
||||
| `axios` | HTTP client |
|
||||
| `jwt` | `jsonwebtoken` |
|
||||
| `uuidv4` | UUID v4 generator |
|
||||
| `xmlBuilder` | `xmlbuilder2` `create` function |
|
||||
| `URLSearchParams`, `URL` | Node.js globals |
|
||||
| `adapterHelper` | Loaded from `src/globalVariables/adapterHelper.js` (if present) |
|
||||
| `<name>` | Each JSON/JS file in `src/globalVariables/` (filename → variable name) |
|
||||
| `req`, `res` | Node.js HTTP request/response |
|
||||
|
||||
Routing metadata (`workspaceId`, `branch`, `route`) is attached by `server.js` to `req.params` before invoking the proxy — `proxy.js` must read these from `req.params`, never from `config`.
|
||||
|
||||
## Key Conventions
|
||||
|
||||
### `src/proxyScripts/proxy.js` — The Only Place for Business Logic
|
||||
|
||||
- **ZERO `import`/`export` statements** — the file runs in a VM with no module system access.
|
||||
- **ZERO access to `config`, `global.config`, or `process.env`** — these are server concerns.
|
||||
- All dependencies arrive via the injected VM context (see table above).
|
||||
- Access injected variables directly: `adapter_settings.key`, not `globalThis["adapter_settings"]`.
|
||||
|
||||
### `src/globalVariables/adapterHelper.js` — Literal Function Body Pattern
|
||||
|
||||
This file contains the **literal body of a function**, not valid standalone JavaScript. `server.js` wraps it at load time:
|
||||
|
||||
```javascript
|
||||
// server.js wraps the file contents like this:
|
||||
const wrappedCode = `(function() {\n${code}\n})()`;
|
||||
```
|
||||
|
||||
So `adapterHelper.js` must end with a bare `return { ... }` that exports the helpers object. It must have zero imports/exports and contain only pure utilities (validators, formatters, XML helpers, error mappers). Authentication, API calls, and state must stay in `proxy.js`.
|
||||
|
||||
### `src/globalVariables/` — Filename Is the Variable Name
|
||||
|
||||
Every file loaded from this directory is injected into the VM context using its filename (without extension) as the key:
|
||||
|
||||
- `adapter_settings.json` → available as `adapter_settings` in `proxy.js`
|
||||
- `adapterHelper.js` → available as `adapterHelper` in `proxy.js`
|
||||
- Files matching `*.example.*` are skipped.
|
||||
- JSON files are loaded before JS files (so JS modules can reference JSON data).
|
||||
|
||||
### Config vs. Secrets
|
||||
|
||||
- `config/default.json` — infrastructure only: `server.port`, `server.host`, `logging.level`, `proxy.*`
|
||||
- Credentials, API keys, and behavioral config → JSON files in `src/globalVariables/`
|
||||
|
||||
### Logging
|
||||
|
||||
Use the `logger` from `src/logger.js` in server-side code. It accepts either a string or a structured object:
|
||||
|
||||
```javascript
|
||||
logger.info("Simple message");
|
||||
logger.info({ message: "Structured", requestId: "abc", status: 200 });
|
||||
```
|
||||
|
||||
In `proxy.js`, use the injected `console` object (same API).
|
||||
|
||||
### Challenging New Files
|
||||
|
||||
Before adding any file to `src/`, verify it belongs to one of the five allowed categories (server.js, logger.js, proxyScripts/proxy.js, globalVariables/*.json, globalVariables/adapterHelper.js). New files require explicit justification against the monolithic architecture constraint.
|
||||
|
||||
Reference in New Issue
Block a user