Files
kme_content_adapter/.github/copilot-instructions.md
Peter.Morton 50b87297d2 feat(002): add sitemap generation feature
- Refactor kmeContentSourceAdapter.js into getValidToken(), oidcAuthFlow(),
  and sitemapFlow(); add sitemap generation using hydra:member response structure
- Add searchApiBaseUrl, tenant, proxyBaseUrl fields to kme_CSA_settings.json
  and kme_CSA_settings.json.example
- Add 17 unit tests for sitemap flow and non-sitemap routing regression
- Add 5 contract tests for sitemap endpoint (proxy-http.test.js)
- Add [Unreleased] sitemap entry to CHANGELOG.md
- Add full specs/002-sitemap-generation/ artifact directory
  (spec, plan, tasks, data-model, contracts, research, quickstart, checklist)
- Update constitution.md: add redis as permitted global, refresh
  kme_CSA_settings references
- Update copilot-instructions.md SPECKIT marker to sitemap plan
2026-04-22 22:08:08 -05:00

111 lines
4.8 KiB
Markdown

<!-- SPECKIT START -->
For additional context about technologies to be used, project structure,
shell commands, and other important information, read the current plan at
`specs/002-sitemap-generation/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.