Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
4ca722c
Add startup-phase lifecycle and runtime path helpers
kriszyp May 16, 2026
954c720
Convert CJS .js source modules to ESM .ts
kriszyp May 16, 2026
f984865
Wire type-strip entry point and defer module-load side effects
kriszyp May 16, 2026
fb39a47
Fix subcommand module resolution for CJS dist mode
kriszyp May 16, 2026
5539f00
Address claude/review feedback and unit-test regression
kriszyp May 17, 2026
c6d8e45
Fix remaining typestrip require()s and lazy-init ErrorResource
kriszyp May 17, 2026
01fedfc
Preserve module-scope variable names for rewire-using unit tests
kriszyp May 17, 2026
8082f52
Fix unit-test regressions from CJS-to-ESM conversion
kriszyp May 17, 2026
4df3131
Alias remaining imports for rewire-using tests (PropertiesReader, ins…
kriszyp May 17, 2026
6c9bd4b
Lazy-access harperBridge in dataLayer; fix __dirname use in jobRunner
kriszyp May 17, 2026
6fed391
Convert remaining top-level require() calls in LMDB/launch files to i…
kriszyp May 17, 2026
c7400ec
Drop unused JSDoc type require() in lmdbSearchByConditions
kriszyp May 17, 2026
258a370
Expose alaSQLExtension members as named exports
kriszyp May 17, 2026
b40822c
Convert remaining ESM-file require() calls flagged by claude/review
kriszyp May 17, 2026
97693f6
Drain startup hooks before HTTP-test server start
kriszyp May 17, 2026
4649f69
Stop subcommand env init and config-load resilience
kriszyp May 17, 2026
54fc5a5
Wait for whenComponentsLoaded before api-test requests
kriszyp May 17, 2026
b2fa0d8
Remove whenComponentsLoaded await in api-test setup
kriszyp May 17, 2026
532d028
Restore initSync() at top of databases.ts
kriszyp May 17, 2026
08cc6d1
Drain startup before server.getUser override in api-test setup
kriszyp May 17, 2026
cd4d92d
Make onSocket sync to preserve mTLS test compatibility
kriszyp May 17, 2026
f5d45e1
Restore initSync() module-load calls (cycle-tolerant)
kriszyp May 17, 2026
c549be5
Graceful worker shutdown in create.test.js to avoid rocksdb-js segfault
kriszyp May 17, 2026
7a4053b
Lazy dataLoader logger + lazy componentLoader in operations.ts
kriszyp May 17, 2026
7e73f28
Move startup-hook drain into run.ts main() after initialize()
kriszyp May 17, 2026
e798364
Lazy-Proxy CertificateVerificationSource for stub-friendly construction
kriszyp May 17, 2026
e382ff6
Resolve apitests/CRL conflict on startServers awaiting
kriszyp May 17, 2026
b24809a
Lazy-Proxy CertificateRevocationListSource (matches CertificateVerifi…
kriszyp May 17, 2026
625f569
Skip DEFAULT_CONFIG fallback for non-root components with empty config
kriszyp May 18, 2026
a337cdf
Fix all 187 TypeScript build errors (clean tsc emit)
kriszyp May 25, 2026
e1342fb
Fix @ts-expect-error + eslint-disable ordering for legacy globals
kriszyp May 26, 2026
c529ce0
Restore rewire-compat aliases for itc.ts and serverHandlers.ts
kriszyp May 26, 2026
dafaeb4
Fix prettier formatting in databases.ts and test JSON file
kriszyp May 26, 2026
61dae1e
Remove accidentally committed test artifact file
kriszyp May 26, 2026
c3ed37b
Fix JSON import attribute error in Node 24 typestrip mode
kriszyp May 29, 2026
4afaf8d
Fix mount_hdb rewire test after JSON import refactor
kriszyp May 29, 2026
9565667
Fix missed process.exit(1) → realExit(1) in worker startup error path
kriszyp May 30, 2026
5c4de25
Fix .js import extensions → .ts for typestrip mode
kriszyp Jun 1, 2026
68a07fd
Restore accidentally-deleted security/certificateVerification files
kriszyp Jun 1, 2026
28c73fd
Fix regression in server/operationsServer.ts and related files
kriszyp Jun 1, 2026
3a06d7f
Replace require() calls in common_utils.ts with ESM import
kriszyp Jun 1, 2026
077c2d8
Fix circular import breaking restart listener in CJS dist
kriszyp Jun 1, 2026
40e2d22
Fix require-in-ESM via databasesRef registry instead of circular top-…
kriszyp Jun 1, 2026
6fdafc4
Fix validate.js default-export unwrapping in ESM typestrip mode
kriszyp Jun 1, 2026
06f9685
Fix typestrip drift + open review blockers
kriszyp Jun 14, 2026
827a0a4
Fix ESM require() calls and componentLoader duplicate block
kriszyp Jun 14, 2026
3fe68b6
Fix harper_logger.ts ESM export and segfault handler; remove lock file
kriszyp Jun 14, 2026
593ae65
Fix harper_logger.ts ESM export missing start/startOnMainThread; fix …
kriszyp Jun 14, 2026
626779c
Fix worker SHUTDOWN handler updating wrong restartNumber binding
kriszyp Jul 14, 2026
572db8e
Preserve current runtime behavior in TypeStrip mode
kriszyp Oct 5, 2026
1b886fc
Clarify TypeStrip startup and dispatch comments
kriszyp Oct 5, 2026
6652aae
Skip nonexistent eval entries during worker startup
kriszyp Oct 5, 2026
14d769c
Preserve compiled runtime paths through symlinks
kriszyp Oct 5, 2026
32dad74
Keep worker fixtures out of server test discovery
kriszyp Oct 5, 2026
b59aa3c
Refresh cached configuration before runtime startup
kriszyp Oct 5, 2026
23a8a86
Keep CLI imports safe in evaluated workers
kriszyp Oct 5, 2026
2ce64a2
Preserve cold SQL loading and startup logging in both runtimes
kriszyp Oct 5, 2026
f6b1251
Preserve TypeStrip startup and public runtime boundaries
kriszyp Oct 5, 2026
f6fcaf5
Preserve main startup behavior and CSV source loading
kriszyp Oct 5, 2026
e9e8a16
Preserve configured codecs and terminal startup behavior
kriszyp Oct 5, 2026
3389d14
Keep response compression and shutdown continuations direct
kriszyp Oct 5, 2026
3cf6b64
fix: initialize fresh-install configuration at startup
kriszyp Oct 5, 2026
1dcc9f9
Fix main-thread inspector configuration overrides
kriszyp Oct 5, 2026
e0b4440
Keep framing coverage for the renamed backup loader
kriszyp Oct 5, 2026
4e6e3ea
Preserve TypeStrip startup across current main changes
kriszyp Oct 13, 2026
5746329
Merge current main and preserve native loader bindings
kriszyp Oct 13, 2026
5c03d24
Normalize formatting after the TypeStrip rebase
kriszyp Oct 13, 2026
f6eb005
Fix embedded core runtime paths and schema emission
kriszyp Oct 13, 2026
7c896a4
Resolve lazy core plugins independently of product imports
kriszyp Oct 13, 2026
6a76511
Run source-compatible unit tests without a build (#3199)
kriszyp Oct 23, 2026
767abb0
Merge main while preserving TypeStrip runtime compatibility
kriszyp Oct 23, 2026
3a42122
Merge main's RocksDB registry API migration
kriszyp Oct 23, 2026
3845722
Adapt incoming transport and Fastify fixtures to TypeStrip
kriszyp Oct 23, 2026
86c2b46
Defer model persistence until core initialization completes
kriszyp Oct 23, 2026
7f2aa39
Keep mutable logger export fixture in the compiled lane
kriszyp Oct 23, 2026
386f55f
Preserve protected core names through cold startup
kriszyp Oct 23, 2026
87e01ad
Fix main's red eviction test: build its version-reusing write from an…
kriszyp Oct 23, 2026
5ea289d
Make TypeStrip runtime fixtures portable to Windows
kriszyp Oct 23, 2026
9337df6
Merge current main while preserving TypeStrip initialization
kriszyp Oct 23, 2026
b5c8283
Guard source imports and merged login body handling
kriszyp Oct 23, 2026
2669b93
Isolate certificate reload fixtures and await settled MQTT wills
kriszyp Oct 23, 2026
d1691e3
Keep mutable worker-pool logger tests in the compiled lane
kriszyp Oct 23, 2026
f3f3d9a
Keep mutable residency logger tests in the compiled lane
kriszyp Oct 23, 2026
e9dd83f
Merge current LMDB close and replication fixes from main
kriszyp Oct 23, 2026
f5abb4e
Merge status logging while preserving TypeStrip runtime adapters
kriszyp Oct 23, 2026
578fd25
Pin admission fixtures to an indexed IPv4 listener
kriszyp Oct 23, 2026
2f957f2
Allocate available loopback ports for uWS test listeners
kriszyp Oct 23, 2026
a0b2544
Partition compiled core CI into bounded directory suites
kriszyp Oct 24, 2026
fbcb11d
Import the Mocha constructor portably in the shutdown fixture
kriszyp Oct 24, 2026
d349dbf
Merge main through 808d5f543 into the TypeStrip branch
kriszyp Oct 24, 2026
a38064e
Recheck shutdown after the failed-closed scan at startup
kriszyp Oct 24, 2026
b7fe1e3
Load fixture workers' runtime modules through #src so the source lane…
kriszyp Oct 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
4 changes: 4 additions & 0 deletions .github/DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ Pushes to `main` and release branches run the same staging path, copying into a

Write a fixture's rows in one transaction and await a write only before the step that reads it. Empty a table with `Table.clear()`, or with every delete in one transaction where the table has a full-text index (`clear()` refuses it) or the suite reads the deletes from the audit log (`clear()` writes none). Where a test checks write order (calibration discovery scans decisions by time), keep those writes serial and let the independent ones commit alongside them. Before raising the cap, compare each suite's time in the `lmdb` step with the same suite in `resources (core)`/`resources (indexes)` of the same job, and fix the suite whose LMDB time grew.

## Core CI partitions directories without dropping runtime coverage (`workflows/unit-test.yml`)

The compiled core gate runs `test:unit:main:core`, `test:unit:main:components` and `test:unit:main:server` as separately bounded steps. Components and server each select their directory's `**/*test.*js`; core delegates the unchanged canonical `test:unit:main` with those two directories excluded. The three selections are disjoint and exhaustive, including `.mjs` runtime probes. New files land in their directory's shard, and the full canonical command remains available locally. Cold source/compiled subprocess probes belong in the server step rather than spending the rest of core's failure-reporting window. Each step retains the eight-minute bound; the job backstop exceeds their executable cap sum.

## A release cherry-pick skips a change its branch already has (`workflows/cherry-pick-patch.yml`, `scripts/change-landed.sh`)

Before picking, the cherry-pick job asks `scripts/change-landed.sh` whether picking the PR onto the release branch could land anything new. The script replays the picked commits onto the release in order with `git merge-tree`, resolving each conflict toward the commit, and the result must be the release's own tree. A conflict then means only that a commit met content a later commit of the PR already wrote. It also merges the PR's net change, `MERGE_BASE..HEAD_SHA` (`MERGE_SHA^1..MERGE_SHA` for a merge-commit merge), into the release, and that must leave the tree unchanged; this covers merge resolutions that no commit carries. Only that answer skips the PR, with no branch and no PR. A change whose file content is partly present, reverted, absorbed by main from another PR, or undone by a later commit of its own picks as before. So does a conflicting change, and so does a check that cannot run. "Unchanged" is decided by Git's merge rules, the same rules the picks themselves run under: a gitlink the release already moved past, or a configured merge driver that keeps the release's side, counts as present for both. Replaying a landed PR one commit at a time re-applies each intermediate commit against its own final content, which conflicts instead of coming out empty. harper#3067 was the second run of a `demilestoned`/`milestoned` pair re-picking harper#3038 onto the v5.3 the first run had just landed it on.
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/review-coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ jobs:
dataLayer/backupRepository.ts
dataLayer/harperBridge/ResourceBridge.ts
dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbGetBackup.js
dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbGetBackup.ts
dataLayer/restoreMarker.ts
dataLayer/rocksdbBackup.ts
dataLayer/schemaDescribe.ts
Expand Down
56 changes: 53 additions & 3 deletions .github/workflows/unit-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ jobs:
runs-on: ubuntu-latest
# A job that hits this cap is reported as `cancelled`, not `failure`, so it reads as non-red
# on a required check. Every step below is capped in its own right and this sits above their
# sum (55 on the longest leg), so a stall surfaces as a step failure and this stays a backstop.
timeout-minutes: 56
# sum (72 on Node 22/24, 69 on Node 26), so a stall surfaces as a step failure and this stays a backstop.
timeout-minutes: 73
strategy:
fail-fast: false
matrix:
Expand Down Expand Up @@ -120,7 +120,17 @@ jobs:
- name: 'Unit tests: main'
if: "!cancelled() && steps.setup-harper.outcome == 'success'"
timeout-minutes: 8
run: npm run test:unit:main
run: npm run test:unit:main:core

- name: 'Unit tests: components'
if: "!cancelled() && steps.setup-harper.outcome == 'success'"
timeout-minutes: 8
run: npm run test:unit:main:components

- name: 'Unit tests: server'
if: "!cancelled() && steps.setup-harper.outcome == 'success'"
timeout-minutes: 8
run: npm run test:unit:main:server

- name: 'Unit tests: apitests'
if: "!cancelled() && steps.setup-harper.outcome == 'success'"
Expand All @@ -142,6 +152,46 @@ jobs:
timeout-minutes: 6
run: npm run test:unit:lmdb

unit-test-source:
name: Native Unit Test (Node.js v${{ matrix.node-version }})
runs-on: ubuntu-latest
timeout-minutes: 39
strategy:
fail-fast: false
matrix:
node-version: ${{ (github.event.inputs.node-version == 'all' || github.event.inputs.node-version == '') && fromJSON('["22.18.0", "24.0.0", 22, 24, 26]') || fromJSON(format('[{0}]', github.event.inputs.node-version)) }}
steps:
- name: Checkout code
timeout-minutes: 3
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Setup Node.js
timeout-minutes: 5
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: ${{ matrix.node-version }}
package-manager-cache: false
check-latest: ${{ matrix.node-version == 26 }}
- name: Install dependencies
timeout-minutes: 6
run: npm ci --ignore-scripts
- name: Verify no compiled distribution
timeout-minutes: 1
run: test ! -d dist
- name: Check unit harness types
timeout-minutes: 2
run: npm run test:types:unit
- name: Native core units
timeout-minutes: 8
run: npm run test:unit:typestrip
- name: Native resource units (core)
if: '!cancelled()'
timeout-minutes: 8
run: npm run test:unit:typestrip:resources:core
- name: Native resource units (indexes)
if: '!cancelled()'
timeout-minutes: 5
run: npm run test:unit:typestrip:resources:indexes

# Windows had no unit-level coverage at all before this job: every job above pins
# ubuntu-latest, and integration-tests.yml was the only workflow touching Windows.
# Platform-gated code and the tests written to prove it therefore never executed.
Expand Down
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Run a single test file directly:
npx mocha unitTests/resources/mytest.js
```

TypeScript is stripped at runtime via `--conditions=typestrip` (Node.js native type stripping) — no compilation required for development. Use `npm run test:unit:typestrip` to run tests with this mode.
TypeScript is stripped at runtime via `--conditions=typestrip` (Node.js native type stripping). `npm run test:unit:typestrip` runs the source-compatible core subset without compilation; export-rewriting and compiled-artifact fixtures retain `#js`. Run `npm run build` followed by `npm run test:unit:typestrip:main` for the complete core selection in separate source and compiled processes.

**Unit-test isolation:** every mocha run gets its own per-PID root under `unitTests/envDir/<pid>` — config file, log, keys, and every database including `system` (`unitTests/mocha.init.js` builds it before any test loads; `setupTestDBPath()` re-asserts the paths). A suite that needs the system tables to exist seeds them with `ensureSystemTables()` from `unitTests/testUtils.js` (system tables, a super_user role with an `admin` user, self-signed certs — what an install would create). After each test file, `unitTests/perFileDatabaseTeardown.js` drops every database that file created, and on RocksDB also removes one it closed but left on disk (the module header says why). So a test file must not depend on a database another file created, and must not create one in a root-level hook or test (outside any `describe`); `system`, configured databases and databases that existed before the file started are kept. Unit runs therefore stay out of an installed Harper root, can run while a local Harper is running, and work on a machine with no Harper install at all. Known carve-outs: `test:unit:apitests` still stops a running Harper first, for port reasons only (a wildcard-bound instance holds `*:9925/9926/1883`, starving the loopback-address pool); and the few test files that clear mocha.init.js's `ROOTPATH` export to exercise boot-props resolution fall back to the installed root's resolution inside their scope.

Expand Down
24 changes: 22 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,29 @@ Build the project using `npm run build` or `npm run build:watch` to automaticall

Run integration tests using `npm run test:integration:all`. For targeted runs or additional options, use `npm run test:integration -- <pattern>`. Make sure to read the [integration test instructions](./integrationTests/README.md) for setup requirements (particularly the loopback address configuration).

Run unit tests using `npm run test:unit <unit-test-file>` or `npm run test:unit:all`, but make sure to build the project first since unit tests depend on the built source files.
Run a source-compatible test directly, without building Harper:

> Unit tests currently use [Mocha](https://mochajs.org/) as the test runner, but since they are implemented in TypeScript and are sometimes executing TypeScript source code, it also uses [TSX](https://tsx.is/) for compilation and execution. The npm script `test:unit` sets the appropriate env vars and mocha configuration file. Make sure that the `TSX_TSCONFIG_PATH` environment variable points to the correct `tsconfig.json` file for the unit tests (i.e. `./unitTests/tsconfig.json`) and not the root-level `tsconfig.json`.
```bash
npm run test:unit:typestrip -- unitTests/components/deploymentRecorder.test.js
```

`#src` selects the source tree in this lane; retained JavaScript sources use explicit mappings or a `.js` suffix. `npm run test:unit:typestrip` runs the source-compatible part of the core gate. Native resource tests use `npm run test:unit:typestrip:resources`. Source conditions are inherited by workers and spawned fixtures.

Legacy tests that rewire exports, replace module namespaces or manipulate their export cache retain `#js` and need compiled CommonJS. Build after changing the code they test, then run them with ordinary Mocha:

```bash
npm run build
npm run test:unit -- unitTests/config/configUtils.test.js
npm run test:unit:typestrip:main
```

The combined `:typestrip:main` command covers the same selection as `test:unit:main` in two sequential processes. Each has its own isolated configuration and databases. `--list` on `node unitTests/runTypeStripTests.mts` shows the partition. `:typestrip:all` selects all `*test.*js` suites, including the API and legacy storage suites; stop a conflicting server before API tests as for the ordinary API gate.

Use the project-installed Mocha through the npm scripts or `npx`; completion tracking patches that copy.

A source process denies `#js`, and the harness fails a source run that loaded this checkout's compiled core, checking at file boundaries and final completion. Route an existing mutable-export suite to the compiled lane instead of mixing trees. The combined launcher rejects a globally enabled `typestrip` condition; let it choose each lane. Ordinary compiled CI still runs all tests, while native CI never builds `dist`.

The launcher runs each lane in one process, so use ordinary Mocha for watch or parallel mode. Custom configurations must require `unitTests/mocha.init.js` for completion tracking. Mixed selections with global `--file` setup run compiled to preserve ordering. File reporters and external reporters must run separately per lane to avoid overwriting output. Ctrl-C removes the launcher's temporary configuration; a force-killed process can leave that directory and its isolated database root. The existing stale-root sweep reclaims only the database root. `.mocharc.json` sets Mocha's per-test timeout to zero (no limit). CI bounds each step; use `--timeout` for local per-test limits. The full selection needs a current build for legacy and artifact checks.

## Code Formatting & Linting

Expand Down
Loading
Loading