[Spec Kit] Implementation progress
This commit is contained in:
33
CHANGELOG.md
Normal file
33
CHANGELOG.md
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
|
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## [0.1.0] - 2026-04-23
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- `src/proxyScripts/kmeContentSourceAdapter.js` — OIDC authentication proxy script running in a Node.js VM sandbox (zero imports/exports)
|
||||||
|
- `src/globalVariables/kme_CSA_settings.json` — OIDC credentials and token endpoint configuration (gitignored)
|
||||||
|
- `src/globalVariables/kme_CSA_settings.json.example` — placeholder settings file for version control
|
||||||
|
- Redis-backed token cache (`authorization` hash, fields `token` and `expiry`) — token persists across adapter restarts
|
||||||
|
- Token stampede guard via in-process `_pendingFetch` promise — only one token fetch in-flight at a time
|
||||||
|
- Absolute Unix epoch expiry check (`Date.now() / 1000 < expiry`)
|
||||||
|
- `200 OK / Authorized` response on successful authentication
|
||||||
|
- `401 Unauthorized` response with descriptive message on auth failure (bad credentials, timeout, unreachable service)
|
||||||
|
- 5-second timeout on OIDC token POST requests
|
||||||
|
- Structured logging throughout proxy script using `console.debug`, `console.info`, and `console.error`
|
||||||
|
- `redis` dependency wired into VM context via `createClient().connect()` in `server.js`
|
||||||
|
- Unit tests (`tests/unit/proxy.test.js`) — 12 tests covering US1, US2, US3, and stampede guard
|
||||||
|
- Contract tests (`tests/contract/proxy-http.test.js`) — 2 tests covering HTTP 200/401 response shape
|
||||||
|
|
||||||
|
[Unreleased]: https://github.com/your-org/kme-content-adapter/compare/v0.1.0...HEAD
|
||||||
|
[0.1.0]: https://github.com/your-org/kme-content-adapter/releases/tag/v0.1.0
|
||||||
112
README.md
112
README.md
@@ -0,0 +1,112 @@
|
|||||||
|
# kme-content-adapter
|
||||||
|
|
||||||
|
An HTTP proxy adapter that authenticates against KME and proxies content requests through an isolated VM sandbox, mirroring the IVA Studio proxy script execution environment.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- Node.js ≥ 18
|
||||||
|
- Redis (used for token caching)
|
||||||
|
- `jq` (optional — used by `npm start` for log pretty-printing)
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
cp src/globalVariables/kme_CSA_settings.json.example src/globalVariables/kme_CSA_settings.json
|
||||||
|
# Edit kme_CSA_settings.json with real credentials
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### `src/globalVariables/kme_CSA_settings.json`
|
||||||
|
|
||||||
|
Credentials and OIDC settings — **never commit this file**.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"tokenUrl": "https://<host>/oidc-token-service/<env>/token",
|
||||||
|
"username": "<username>",
|
||||||
|
"password": "<password>",
|
||||||
|
"clientId": "default",
|
||||||
|
"scope": "openid tags content_entitlements"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `config/default.json`
|
||||||
|
|
||||||
|
Infrastructure settings (port, host, log level). Override with environment variables:
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
|---|---|---|
|
||||||
|
| `PORT` | `3000` | HTTP server port |
|
||||||
|
| `HOST` | `0.0.0.0` | Bind address |
|
||||||
|
| `LOG_LEVEL` | `debug` | Log level: `DEBUG`, `INFO`, `WARN`, `ERROR` |
|
||||||
|
|
||||||
|
## Running
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dev # Development — auto-restart on file changes
|
||||||
|
npm start # Production — logs piped through jq
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm test # All tests
|
||||||
|
npm run test:unit # Unit tests only
|
||||||
|
npm run test:integration # Integration tests only
|
||||||
|
npm run test:contract # Contract tests only
|
||||||
|
|
||||||
|
# Single test file
|
||||||
|
node --test tests/unit/proxy.test.js
|
||||||
|
```
|
||||||
|
|
||||||
|
Tests use the Node.js built-in `node:test` runner. No external test framework.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
The server loads `src/proxyScripts/kmeContentSourceAdapter.js` once at startup via `vm.Script`, then executes it in a **fresh isolated VM context per request** via `vm.createContext`.
|
||||||
|
|
||||||
|
```
|
||||||
|
src/
|
||||||
|
├── proxyScripts/
|
||||||
|
│ └── kmeContentSourceAdapter.js # All business logic (zero imports/exports)
|
||||||
|
├── globalVariables/
|
||||||
|
│ ├── kme_CSA_settings.json # OIDC credentials (gitignored)
|
||||||
|
│ └── adapterHelper.js # Pure utilities (optional)
|
||||||
|
├── logger.js # Structured JSON logger
|
||||||
|
└── server.js # HTTP server bootstrap only
|
||||||
|
config/
|
||||||
|
└── default.json # Infrastructure settings
|
||||||
|
```
|
||||||
|
|
||||||
|
### VM Context Globals
|
||||||
|
|
||||||
|
All dependencies are injected into each request's sandbox:
|
||||||
|
|
||||||
|
| Variable | Source |
|
||||||
|
|---|---|
|
||||||
|
| `console` | Structured logger |
|
||||||
|
| `crypto` | Node.js Web Crypto API |
|
||||||
|
| `axios` | HTTP client |
|
||||||
|
| `jwt` | `jsonwebtoken` |
|
||||||
|
| `uuidv4` | UUID v4 generator |
|
||||||
|
| `xmlBuilder` | `xmlbuilder2` `create` |
|
||||||
|
| `redis` | Connected Redis client |
|
||||||
|
| `URLSearchParams`, `URL` | Node.js globals |
|
||||||
|
| `kme_CSA_settings` | Loaded from `src/globalVariables/kme_CSA_settings.json` |
|
||||||
|
| `req`, `res` | Node.js HTTP request/response |
|
||||||
|
|
||||||
|
### Key Constraints for `kmeContentSourceAdapter.js`
|
||||||
|
|
||||||
|
- **Zero `import`/`export`** — runs in a VM with no module system
|
||||||
|
- **No `config`, `global.config`, or `process.env`** — use injected globals only
|
||||||
|
- Routing metadata is available via `req.params` (set by `server.js`)
|
||||||
|
|
||||||
|
## Token Caching
|
||||||
|
|
||||||
|
OIDC tokens are cached in Redis under the hash key `authorization` (fields `token` and `expiry`). The cache survives adapter restarts. Token expiry is stored as an absolute Unix epoch timestamp.
|
||||||
|
|
||||||
|
## Changelog
|
||||||
|
|
||||||
|
See [CHANGELOG.md](CHANGELOG.md).
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "kme-content-adapter",
|
"name": "kme-content-adapter",
|
||||||
"version": "1.0.0",
|
"version": "0.1.0",
|
||||||
"description": "HTTP proxy adapter to search and export documents from KME",
|
"description": "HTTP proxy adapter to search and export documents from KME",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/server.js",
|
"main": "src/server.js",
|
||||||
|
|||||||
Reference in New Issue
Block a user