From f8a1968859510be8a5399a38cae0c7dbe3d1635d Mon Sep 17 00:00:00 2001 From: Kris Zyp Date: Sun, 26 Apr 2026 17:47:02 -0600 Subject: [PATCH 1/3] Expand VM module loader section in v5 migration guide Add comprehensive documentation for the new applications configuration options: lockdown modes, allowedDirectory, allowedBuiltinModules, dependencyLoader, and how to disable the VM loader for legacy compatibility. Also fix missing closing backtick on harper-pro install command. Co-Authored-By: Claude Sonnet 4.6 --- release-notes/v5-lincoln/v5-migration.md | 70 +++++++++++++++++++++++- 1 file changed, 68 insertions(+), 2 deletions(-) diff --git a/release-notes/v5-lincoln/v5-migration.md b/release-notes/v5-lincoln/v5-migration.md index 0332d829..3bd3dcd4 100644 --- a/release-notes/v5-lincoln/v5-migration.md +++ b/release-notes/v5-lincoln/v5-migration.md @@ -6,7 +6,7 @@ HarperDB now uses the name Harper, not HarperDB. And this change is reflected in The open source edition can be run with: `npm i -g harper` And the pro edition can be run with: -`npm i -g @harperfast/harper-pro +`npm i -g @harperfast/harper-pro` Application code should import from the `harper` package instead of `harperdb`: @@ -114,7 +114,73 @@ Harper has expanded support for using standard Response-like objects in the API. ## VM Module Loader -In Harper version 5, Harper now uses a VM module loader to load modules. This allows Harper to load modules with more controlled access and security, and provide application specific functionality, such as custom/configurable logging for each application. Configuration for the module loading is available in the `applications` section of the configuration, and can be disabled in the VM module loader is causing problems for legacy code. +Harper v5 loads application modules through Node.js's VM module API, giving each application its own module cache and execution context. This provides per-application context: the `logger` global/export is automatically tagged with the application name, and `config` reflects that application's own configuration. Each application's module graph is isolated from other applications and from Harper internals. + +All module loading behavior is controlled by the `applications` section in `harperdb-config.yaml`: + +```yaml +applications: + lockdown: freeze-after-load # default; see below + moduleLoader: vm # vm (default) | native | compartment + dependencyLoader: auto # auto (default) | app | native + allowedDirectory: app # app (default) | any + allowedSpawnCommands: # see "Spawning new processes" above + - npm + - node + # allowedBuiltinModules: [] # if omitted, all Node.js built-ins are allowed +``` + +### Intrinsic Lockdown + +The default lockdown mode (`freeze-after-load`) freezes JavaScript intrinsics (`Object`, `Array`, `Promise`, `Map`, `Set`, and others) after all application code has loaded. This prevents prototype pollution attacks. If application code or a dependency modifies intrinsic prototypes at runtime (after startup), it will throw a TypeError. + +Available lockdown modes: +- `freeze-after-load` — freeze intrinsics after all components have loaded (default) +- `freeze` — freeze intrinsics before loading any application code +- `ses` — full SES lockdown via the `ses` package (strictest; most likely to break packages that mutate built-ins) +- `none` — no lockdown + +If a dependency modifies intrinsic prototypes and you need a temporary workaround, set `lockdown: none`. + +### Allowed Directory + +In production, applications can only load modules from within their own directory tree (`allowedDirectory: app`). Attempting to load a module from outside that directory will throw. Dev mode installs default to `allowedDirectory: any`, so local development is typically unaffected. + +If your application legitimately needs to load files from outside its own directory in production, set: + +```yaml +applications: + allowedDirectory: any +``` + +### Allowed Built-in Modules + +By default all Node.js built-in modules are accessible. To restrict which built-ins applications may import, set an explicit allowlist: + +```yaml +applications: + allowedBuiltinModules: + - fs + - path + - http +``` + +### Dependency Loading + +By default (`dependencyLoader: auto`), npm packages that do not declare `harper` as a dependency are loaded with the native Node.js loader. Packages that do depend on `harper` are loaded through the VM loader so they receive application context. Set `dependencyLoader: app` to always use the VM loader for dependencies, or `native` to always use the native loader for packages. + +### Disabling the VM Loader + +If the VM loader is causing compatibility issues with existing code, it can be disabled entirely: + +```yaml +applications: + moduleLoader: native +``` + +This restores pre-v5 behavior where modules are loaded with a standard `import()`. Application-specific context (tagged logging, per-app `config`) will not be available in native mode. + +If the goal is only to fix package compatibility while keeping application context for first-party code, `dependencyLoader: native` is a narrower option—it uses native loading only for npm packages while keeping the VM loader for application source files. # Recommend Changes From 06d6e1e984bef3bd37f5179654e23d5a5a3e2dec Mon Sep 17 00:00:00 2001 From: Kris Zyp Date: Mon, 27 Apr 2026 22:04:53 -0600 Subject: [PATCH 2/3] Update release-notes/v5-lincoln/v5-migration.md Co-authored-by: Ethan Arrowood --- release-notes/v5-lincoln/v5-migration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release-notes/v5-lincoln/v5-migration.md b/release-notes/v5-lincoln/v5-migration.md index 3bd3dcd4..8547ead8 100644 --- a/release-notes/v5-lincoln/v5-migration.md +++ b/release-notes/v5-lincoln/v5-migration.md @@ -180,7 +180,7 @@ applications: This restores pre-v5 behavior where modules are loaded with a standard `import()`. Application-specific context (tagged logging, per-app `config`) will not be available in native mode. -If the goal is only to fix package compatibility while keeping application context for first-party code, `dependencyLoader: native` is a narrower option—it uses native loading only for npm packages while keeping the VM loader for application source files. +If the goal is only to fix package compatibility while keeping application context for first-party code, `dependencyLoader: native` is a narrower option. It uses native loading only for npm packages while keeping the VM loader for application source files. # Recommend Changes From 2854cccc665f214f91b2cb4d39f77ef4503301cd Mon Sep 17 00:00:00 2001 From: Kris Zyp Date: Tue, 28 Apr 2026 04:40:27 -0600 Subject: [PATCH 3/3] Format --- release-notes/v5-lincoln/v5-migration.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/release-notes/v5-lincoln/v5-migration.md b/release-notes/v5-lincoln/v5-migration.md index 8547ead8..330212db 100644 --- a/release-notes/v5-lincoln/v5-migration.md +++ b/release-notes/v5-lincoln/v5-migration.md @@ -120,11 +120,11 @@ All module loading behavior is controlled by the `applications` section in `harp ```yaml applications: - lockdown: freeze-after-load # default; see below - moduleLoader: vm # vm (default) | native | compartment - dependencyLoader: auto # auto (default) | app | native - allowedDirectory: app # app (default) | any - allowedSpawnCommands: # see "Spawning new processes" above + lockdown: freeze-after-load # default; see below + moduleLoader: vm # vm (default) | native | compartment + dependencyLoader: auto # auto (default) | app | native + allowedDirectory: app # app (default) | any + allowedSpawnCommands: # see "Spawning new processes" above - npm - node # allowedBuiltinModules: [] # if omitted, all Node.js built-ins are allowed @@ -135,6 +135,7 @@ applications: The default lockdown mode (`freeze-after-load`) freezes JavaScript intrinsics (`Object`, `Array`, `Promise`, `Map`, `Set`, and others) after all application code has loaded. This prevents prototype pollution attacks. If application code or a dependency modifies intrinsic prototypes at runtime (after startup), it will throw a TypeError. Available lockdown modes: + - `freeze-after-load` — freeze intrinsics after all components have loaded (default) - `freeze` — freeze intrinsics before loading any application code - `ses` — full SES lockdown via the `ses` package (strictest; most likely to break packages that mutate built-ins)