Repository navigation
Conversation
…errides - Stage storage.engine in installer.ts before mountHdb() using the same precedence createConfigFile() persists (HARPER_SET_CONFIG > HARPER_CONFIG > CLI/prompt/HDB_CONFIG > HARPER_DEFAULT_CONFIG), then force-reload the persisted config in createConfigFile() so the temporary install-time override is retired once harper-config.yaml owns storage.engine. - Guard setProperty(propName, undefined) in environmentManager.ts so it does not record an undefined override in appliedOverrides (and clears any prior override for that key), preventing undefined from overriding the persisted config after initSync() or across worker threads. - Skip updateConfigValue() in bin/run.ts when initialize() itself just ran install() on first boot so lower-precedence CLI/env args do not overwrite the newly created harper-config.yaml. Dispatch-Task: harper-install-env-storage-engine Co-Authored-By: Gemini <noreply@google.com>
…tion - Re-apply environment and HARPER_SET_CONFIG overrides during install before reading storage_engine - Ensure resolveInstallStorageEngine initializes default config when uninitialized - Preserve existing YAML content and unmapped component blocks when HDB_CONFIG is used during install - Restore temporary install storage_engine override after createConfigFile instead of clearing pre-existing overrides - Make unitTests/install/installer.test.js self-contained by restoring storage_engine and databases in afterEach Dispatch-Task: harper-install-env-storage-engine Co-Authored-By: Gemini <noreply@google.com>
- Avoid recording setProperty override in stageStorageEngine before createConfigFile - Delete flatConfigObj entry when updateConfigObject is called with undefined - Strip runtime env-var keys case-insensitively and for legacy aliases in filterArgsAgainstRuntimeConfig - Preserve undefined values in HARPER_DEFAULT_CONFIG when reading resolveStorageEngineFromEnvAndFile - Keep bin/run.ts focused on install storage.engine resolution - Add environmentManager, configUtils, harperConfigEnvVars, and installer unit tests Dispatch-Task: harper-install-env-storage-engine Co-Authored-By: Gemini <noreply@google.com>
…rArgsAgainstRuntimeConfig Dispatch-Task: harper-install-env-storage-engine Co-Authored-By: Gemini <noreply@google.com>
…ARPER_CONFIG Avoid spreading lossy flattenConfig output from HDB_CONFIG into createConfigFile args so operationsApi.network, node.hostname, and comments in HDB_CONFIG are preserved intact. Track CLI/individual env var storage args distinctly from HDB_CONFIG user paths at install time so CLI overrides beat HARPER_CONFIG while HARPER_CONFIG still overrides HDB_CONFIG. Dispatch-Task: harper-install-env-storage-engine Co-Authored-By: Gemini <noreply@google.com>
…ommit Dispatch-Task: harper-install-env-storage-engine Co-Authored-By: Gemini <noreply@google.com>
…i source decay, and design docs Dispatch-Task: harper-install-env-storage-engine Co-Authored-By: Gemini <noreply@google.com>
…precedence - Extract composeInstallConfig and stageInstallConfig in configUtils.ts so install-time config is composed once before mountHdb() and passed directly to createConfigFile(), ensuring storage.engine, compression, path, and caching settings never drift between mountHdb() and harper-config.yaml - Align install-time and runtime config precedence on HARPER_DEFAULT_CONFIG < HDB_CONFIG / CLI / user < HARPER_CONFIG < HARPER_SET_CONFIG so system DB engine and subsequent runtime boots cannot disagree - Guard post-install updateConfigValue loop in bin/run.ts when auto-install already composed CLI args during initialize() - Validate configDoc before touching target file in createConfigFile() and add writeFileSync fallback when restoring pre-seeded root HDB_CONFIG on rollback - Add unit tests for RocksDB zstd compression, default kNoCompression, STORAGE_COMPRESSION=false coercion during mountHdb, and ENOSPC rollback Dispatch-Task: harper-install-env-storage-engine Co-Authored-By: Gemini <noreply@google.com>
…sion before mountHdb - Validate staged install config after mountHdb creates the default storage directory and before createTables() opens databases, refreshing flatConfigObj and initPaths so custom storage.path and nonexistent storage.path fail cleanly. - Call resetRocksCompression() and initPaths.resetPaths() when staging install config and in test setup/teardown, and assert compression= in RocksDB OPTIONS-*. - Track un-authored DEV_MODE_CONFIG keys via defaultedArgKeys so HARPER_DEFAULT_CONFIG overrides un-authored dev mode defaults while yielding to explicit CLI/env args. - Preserve pre-seeded root HDB_CONFIG via sibling backup-aside on rollback. Dispatch-Task: harper-install-env-storage-engine Co-Authored-By: Gemini <noreply@google.com>
…n rollback Dispatch-Task: harper-install-env-storage-engine Co-Authored-By: Gemini <noreply@google.com>
…taller tests - Restore pre-seeded HDB_CONFIG inside rootPath on rollback via .install-backup rename or writeFileSync fallback, retaining backup if restore fails - Gate deleteBootPropertiesFile on shouldWriteBootProps so rollback does not delete a pre-existing ~/.harperdb boot properties directory - Resolve CLI/env keys and legacy CONFIG_PARAM_MAP aliases in filterArgsAgainstRuntimeConfig before matching HARPER_CONFIG/HARPER_SET_CONFIG paths - Skip isObject entries in assignCmdEnvVariables instead of coercing object config entries to '[object Object]' - Wrap backfilled YAML defaults and synced env objects in YAMLMap nodes while preserving inline comments on overridden scalars - Refresh rootPath from configUtils.getConfigValue(ROOTPATH) in createCertificates before joining HDB_KEYS_DIR_NAME - Isolate installer.test.js system database and analytics from sibling suites Dispatch-Task: harper-install-env-storage-engine Co-Authored-By: Gemini <noreply@google.com>
… install config staging - Snapshot pre-existing top-level entries in hdbRoot before install so rollback only removes entries created by the failed install even when HDB_CONFIG points outside hdbRoot - Remove test-only resetRocksCompression() and setProperty(..., undefined) calls from production stageInstallConfig() - Expand numeric threads shorthand and clear scalar ancestor nodes before setIn in composeInstallConfig - Reject dead args/baseConfigPath/defaultedArgKeys arguments when staged is passed to createConfigFile and update JSDoc - Export initialize() from bin/run.ts and test subsequent-boot HARPER_CONFIG filtering and auto-install installedDuringInit skip Dispatch-Task: harper-install-env-storage-engine Co-Authored-By: Gemini <noreply@google.com>
…and clean pre-existing storage dirs on rollback - Share clearScalarAncestors(configDoc, splitParam) across composeInstallConfig and updateConfigValue (guarded by typeof configDoc.deleteIn === 'function' for stub docs) so setting nested keys under boolean/scalar parents (e.g. http_mtls_required under http.mtls: false) expands the ancestor map instead of failing in setIn - Snapshot pre-existing entries in existing storage directories and candidate system DB paths before mountHdb so rollback removes install-created system DB artifacts inside pre-existing empty database mounts while preserving pre-existing directories - Keep addUnhandleRejectionListener() gated only by !skipListeners in bin/run.ts initialize() - Remove duplicate unreachable threads_ block in composeInstallConfig and test both THREADS_COUNT and THREADS_DEBUG in configUtils.test.js Dispatch-Task: harper-install-env-storage-engine Co-Authored-By: Gemini <noreply@google.com>
…hten rollback sweep
…ult empty template maps
There was a problem hiding this comment.
Code Review
This pull request introduces a staged configuration flow during installation, allowing the full install configuration to be composed, validated, and staged in-memory before the database is mounted and written to disk. It adds support for backfilling missing defaults from defaultConfig.yaml when a user-supplied HDB_CONFIG template is provided, while tracking user-authored paths to preserve the precedence ladder (HARPER_DEFAULT_CONFIG < user/HDB_CONFIG/CLI < HARPER_CONFIG < HARPER_SET_CONFIG). Additionally, it enhances argument filtering to include HARPER_CONFIG alongside HARPER_SET_CONFIG, improves the robustness of the installation rollback process to preserve pre-existing operator files and restore pre-seeded configurations, and updates setProperty to clear overrides when passed undefined. As there are no review comments, I have no feedback to provide.
|
Thanks for taking this on. The staged install config looks like the right shape. One acceptance case worth adding explicitly, since the PR text frames the bug as engine and compression and does not mention Case: first-boot Test shape, for both RocksDB and LMDB, with
By my read of Possible gap, for after merge. A pre-seeded — Claude Sonnet 5.5 |
⊙ Problem
During first-time install, the installer created the
systemdatabase before composingharper-config.yaml. It resolved only the CLI and legacySTORAGE_ENGINEoverride in memory, while workers later read the config file from disk. Setting the storage engine or RocksDB compression viaHARPER_DEFAULT_CONFIG,HARPER_SET_CONFIG,STORAGE_*environment variables, or anHDB_CONFIGtemplate could leavesystemon RocksDB while workers opened LMDB.HDB_CONFIGinstalls also skipped applying CLI and environment overrides to the file.🤔 Should
HDB_CONFIGtemplates also receive environment, CLI, and default backfills during install?Yes. Operators pass partial
HDB_CONFIGtemplates alongside CLI flags orHARPER_SET_CONFIGoverrides, and expect the installer and workers to share one complete config. Backfilling missing defaults and applying layered overrides keepsHDB_CONFIGconsistent with standard installs. Restoring the pre-install file on rollback makes it reversible.💡 Solution
HARPER_DEFAULT_CONFIG,HDB_CONFIGtemplate, CLI flags,STORAGE_*env vars, andHARPER_SET_CONFIG) in memory beforemountHdb(), and validate the staged configuration before creatingsystemtables.HDB_CONFIGfile on failure.⚖️ Alternatives
createConfigFile()storage settings intoenvManagerbeforecreateTables()— leavesHDB_CONFIGtemplate installs broken becausemainskippedcreateConfigFile()whenHDB_CONFIGexisted, so CLI and env overrides never reached disk.harper-config.yamlbeside an existingHDB_CONFIGinstead of updatingHDB_CONFIGin place — diverges fromkeys.updateConfigCert()onmain, which already rewritesHDB_CONFIGin place, and changes which fileharper-boot.jsonpoints to.🤔 Should install update a pre-existing
HDB_CONFIGfile in place or write a separateharper-config.yaml?We update
HDB_CONFIGin place and restore its original bytes on rollback to matchkeys.updateConfigCert()onmainand keepharper-boot.jsonpointed at the operator's path. Writing a siblingharper-config.yamlinstead is a local change ininstaller.tsif we prefer treatingHDB_CONFIGas read-only.🔧 Changes
config/configUtils.ts: ExtractscomposeInstallConfig(),stageInstallConfig(),validateStagedInstallConfig(), andwriteStagedInstallConfig(), backfills missing defaults intoHDB_CONFIGtemplates and tracks authored template leaf paths viabackfillMissingDefaults()andcollectLeafDotPaths()while keepingcreateConfigFile(args, skipFsValidation)compatible with existing callers.config/harperConfigEnvVars.ts: ExtendsfilterArgsAgainstRuntimeConfig()to filter individual env vars and legacy aliases againstHARPER_CONFIG, checks ancestor and descendant path sources inhasRespectedSource(), and acceptsuserPathsinprepareRuntimeEnvConfig()to seed'user'sources from anHDB_CONFIGtemplate.utility/install/installer.ts: Stages the composed install config beforemountHdb(), validates it viabeforeCreateTablesbefore creatingsystemtables, and backs up and writes the staged config toHDB_CONFIGorharper-config.yaml;rollbackInstall()uses pre-install snapshots of root entries, storage directories, and candidatesystemdatabase paths so rollback removes only artifacts created during the failed install and restores any pre-existingHDB_CONFIG.utility/environment/environmentManager.ts: UpdatessetProperty()so passingundefineddeletes the key fromappliedOverridesand clears the property instead of leaving a stale worker override.security/keys.ts: Updates the comment inupdateConfigCert()to note thatfilterArgsAgainstRuntimeConfig()filters bothHARPER_CONFIGandHARPER_SET_CONFIGkeys.bin/run.tsandutility/mount_hdb.ts: TracksinstalledDuringInitinbin/run.tsso first-time boot skips callingupdateConfigValue(false)a second time afterinstall()already persisted the config, and adds an optionalbeforeCreateTablescallback inutility/mount_hdb.tsthat runs after directory creation and beforecreateTables().DESIGN.md,config/DESIGN.md, andresources/DESIGN.md: Documents the staged install configuration pipeline andstageInstallConfig()ordering inDESIGN.md,config/DESIGN.md, andresources/DESIGN.md.🤔 How should empty maps in an
HDB_CONFIGtemplate interact withHARPER_DEFAULT_CONFIG?An empty map where
defaultConfig.yamldefines a non-empty section (such ashttp: {}) is backfilled from defaults. It stays overridable byHARPER_DEFAULT_CONFIG. Any other empty map (such asmyComponent: {}oroperationsApi.tls: {}) is recorded as'user'-authored and preserved. AllowingHARPER_DEFAULT_CONFIGto populate all empty maps is a two-line change incollectLeafDotPaths().✅ Verification
npx mocha unitTests/install/installer.test.js unitTests/config/configUtils.test.js unitTests/config/harperConfigEnvVars-config.test.js unitTests/config/harperConfigEnvVars-filter.test.js unitTests/utility/environment/environmentManager.test.js(180 passing), verifying realinstall()runs across RocksDB and LMDB,HDB_CONFIGtemplates,HARPER_DEFAULT_CONFIG/HARPER_SET_CONFIG/STORAGE_*layers, pre-table validation failures, and snapshot-scoped rollback.npm run lintandnpm run check:design-docswith zero warnings or errors.Added unit test coverage by file
unitTests/install/installer.test.js: End-to-endinstall()tests across RocksDB and LMDB for every config env layer,HDB_CONFIGtemplates, boot-flowinitialize(), pre-table validation failure, and snapshot-scoped rollback.unitTests/config/configUtils.test.js: Unit tests forstageInstallConfig(),validateStagedInstallConfig(),writeStagedInstallConfig(),HDB_CONFIGdefault backfilling, and empty-section source attribution (http: {},myComponent: {},operationsApi.tls: {}).unitTests/config/harperConfigEnvVars-config.test.jsandunitTests/config/harperConfigEnvVars-filter.test.js: Tests forfilterArgsAgainstRuntimeConfig()withHARPER_CONFIGand legacy aliases,prepareRuntimeEnvConfig()withuserPaths, and ancestor/descendant source precedence acrossHARPER_DEFAULT_CONFIG,HDB_CONFIG, andHARPER_SET_CONFIG.unitTests/utility/environment/environmentManager.test.js: Tests thatsetProperty(key, undefined)clears the property and removes its entry fromgetConfigOverrides().🤖 Generated by Google Gemini; posted via @kriszyp.
Release target: main — 134 changed lines predate this shallow clone's history, so who introduced them is unknown
Related PRs: #3078 overlaps (both touch install() and rollbackInstall() in utility/install/installer.ts)
Complexity: complicated
Deferred findings
53553ea78c754adaminor data-integrity —utility/install/installer.ts— Rollback removes all of ~/.harperdb (pre-existing keys/stale props) whenever this run wrote the props file — filed Installer rollback removes entire ~/.harperdb directory instead of only newly created boot properties #32300374edb02dca6a99minor documentation —config/harperConfigEnvVars.ts— HARPER_CONFIG now beats individual env vars for every key at install and runtime; breaking precedence change — filed docs(config): document HDB_CONFIG template backfill and HARPER_CONFIG precedence in external docs #32319b856519c7f02598minor data-integrity —config/harperConfigEnvVars.ts— Env-owned storage.engine is deleted when the env var is removed; next boot uses the default engine against the existing system DB — filed stageRocksCompression leaves temporary storage compression overrides in envManager after install #321853cb954cf387c47cnit documentation —config/configUtils.ts— Template backfill pins every current default into the operator's HDB_CONFIG, rewritten in place — filed docs(config): document HDB_CONFIG template backfill and HARPER_CONFIG precedence in external docs #3231Review-Coverage: authored=gemini; ran=muse,claude,cursor-composer,cursor-muse; adjudicated=domain; declined=cursor-grok,cursor-kimi; rounds=16; full=4 @ eb2bcdc
Review-Attention: study ~14m (sensitive: keys.ts; decisions: do-less-alternative, hdb-config-in-place-rewrite, snapshot-scoped-rollback, empty-template-section-semantics, setproperty-undefined-clears) @ eb2bcdc