fix: isolate runtime install lifecycle state - #131
Conversation
|
🦞👀 Pull request received. I will update this pull request when review starts. |
|
Codex review: found issues before merge. Reviewed September 2, 2026, 10:47 AM ET / 14:47 UTC. ClawSweeper reviewWhat this changesThis PR gives npm runtime-install lifecycle work a disposable OpenClaw home and state path so installing a runtime cannot mutate the caller’s OpenClaw database or config. Regression provenancePossible regression — probable (reproduction; reviewed change). No predecessor PR is attributed. Merge readinessKeep this PR open: it demonstrates the caller-state isolation fix, but the prior P1 compatibility blocker remains because npm itself now runs with a replacement home directory and cannot discover an operator’s user-level npm transport configuration. Priority: P1 Review scores
Verification
How this fits togetherOCM installs OpenClaw runtimes through npm, whose package lifecycle scripts inherit the install process environment. Those scripts can otherwise resolve caller-owned OpenClaw paths before OCM records the installed runtime. flowchart LR
A[OCM runtime install] --> B[npm install process]
B --> C[Isolated lifecycle environment]
C --> D[Package lifecycle script]
D --> E[Disposable OpenClaw state]
B --> F[Managed runtime files]
Decision needed
Why: Preserving a user-level npm configuration can restore private-registry compatibility but can also expose credentials to package lifecycle code; strict isolation avoids that exposure but changes existing operator behavior. Before merge
Findings
Agent review detailsSecurityNone. Review metrics
Merge-risk optionsMaintainer options:
Technical reviewBest possible solution: Retain caller-state isolation, then define and test an explicit npm transport-configuration boundary that does not expose caller-owned OpenClaw data or credentials to package lifecycle code. Do we have a high-confidence way to reproduce the issue? Yes—source-reproducible with high confidence: the supplied clean-room run demonstrates the legacy mutation and the added production-path regression covers host and managed npm, while current main still lacks this isolation boundary. Is this the best way to solve the issue? No—the state-isolation mechanism is appropriate, but applying a replacement HOME to npm itself leaves an unresolved compatibility and credential-exposure contract for user-level npm transport configuration. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: not found in the target repository. Codex review notes: model internal, reasoning high; reviewed against e04c10166d6b. LabelsLabel justifications:
EvidenceWhat I checked:
Likely related people:
Rank-up movesOptional improvements that raise the rating; they are not merge blockers.
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (3 earlier review cycles)
|
|
@steipete ClawSweeper accepted the supplied behavior proof but raised a P1 compatibility decision: the current isolation boundary changes npm's HOME, so npm no longer discovers an operator's home-level Could you confirm the intended contract for this PR?
I lean toward option 1, but forwarding the original user-config path wholesale could also expose authentication material to package lifecycle scripts, so I do not want to assume that security/compatibility tradeoff without maintainer direction. Once confirmed, I can align the implementation and add focused regression coverage. ClawSweeper finding: #131 (comment) |
|
@steipete A quick follow-up on the npm configuration question above: could you confirm the preferred approach for preserving supported npm transport settings while keeping caller-owned OpenClaw state isolated? I'm ready to update the implementation and add focused compatibility coverage once the direction is clear. If another maintainer owns this decision, happy to follow up with them. Thanks! |
Summary
Fixes #98.
Relation to the requested reproduction
This directly answers Peter's follow-up on #98. PR #110 had already proved that known external plugin records are rejected safely, but it did not identify the original schema-migration path. Peter therefore asked for a credential-free reproduction that preserved the relevant config path fields, plugin install records, symlink targets, environment-variable names, and exact commands while omitting credentials and database contents.
The reproduction added here keeps those requested structural inputs and compares the same published OpenClaw beta installation across OCM v0.2.32, the fixed current build, and an explicit-path control. It identifies
ocm runtime install's inherited npm lifecycle environment as the first write boundary: the legacy lane resolves the caller's default OpenClaw state and migrates its database, while the fixed lane leaves the source state and config unchanged.Root cause
ocm runtime installlaunched npm with the caller's environment. When an OpenClaw package postinstall resolved its default paths, inheritedHOMEled it back to$HOME/.openclaw/state/openclaw.sqlite. Installing[email protected]could therefore migrate the source database from schema 7 to 8 before the runtime was recorded.PR #110 correctly contains known external plugin records during adoption, but it does not own this runtime-package child-process boundary.
Fix
The runtime package installer now gives npm lifecycle scripts a disposable root under the staged install:
HOMEandUSERPROFILEOPENCLAW_HOMEOPENCLAW_STATE_DIROPENCLAW_CONFIG_PATHIt also removes
OCM_ACTIVE_ENV,OCM_ACTIVE_ENV_ROOT, andOPENCLAW_PROFILE. The same helper covers direct npm, managed Node/npm, local builds that use the package installer, and local companion installs.Regression proof
The integration test runs the official runtime-install flow with both host npm and managed Node/npm. Its fake lifecycle script uses OpenClaw's path-resolution order and attempts to mutate caller-owned state/config.
The credential-free published-package reproduction in the fixed run also proves:
The fixture preserves the requested redacted config path fields,
plugins.installsrecords, symlink target, environment-variable names, and exact commands without uploading credentials or database contents.Validation
cargo fmt --checkcargo check --workspace --all-targets --lockedcargo test --lockedAll passed in run 33441331742.
Scope
Agent Transcript
Redacted Codex session transcript
This is a scoped, sanitized record of the work that produced this PR. System/developer prompts, internal reasoning, raw tool output, credentials, authentication details, local user paths, and unrelated conversation were omitted.
User: Asked whether an OCM release-validation isolation failure matched an earlier report.
Assistant: Matched the incident to OCM issue #98: an adopted disposable environment's beta runtime installation migrated the caller-owned OpenClaw state database from schema 7 to 8.
User: Shared Patrick's explicit approval to investigate and open an OCM PR.
Assistant: Rechecked issue #98 and Peter's follow-up. PR #110 covered known external plugin records, but Peter still needed a credential-free reproduction preserving config path shapes, plugin install records, symlink targets, environment-variable names, and exact commands without credentials or database contents.
Assistant: Reconstructed the original command order and narrowed the first source-state write to
ocm runtime install, before the candidate gateway was started. To avoid touching real gateway state, moved the proof to a synthetic fixture and secrets-free GitHub Actions workflow.Assistant: Built a three-lane reproduction using the published OpenClaw beta package. OCM v0.2.32 changed the synthetic source database from schema 7 to 8; an explicit-path control left it unchanged. This identified npm lifecycle path resolution through the inherited caller environment as the owner boundary.
User: Approved implementing the OCM repair and regression test.
Assistant: Added a production-path regression covering both host npm and managed Node/npm. Before the fix, the test failed because the lifecycle probe changed caller-owned OpenClaw state.
Assistant: Updated runtime installation so npm lifecycle children receive disposable OpenClaw home, state, and config paths, while active OCM/OpenClaw profile context is removed. Applied the same boundary to companion-package installation and cleaned the disposable state after npm exits.
Assistant: Reran the focused regression, full Rust test suite, formatting/checks, release builds, and credential-free clean-room reproduction. The fixed lane remained schema 7 with source database and config unchanged. Opened PR #131 with the red/green runs and evidence matrix.
Assistant: After PR creation, ClawSweeper accepted the supplied behavior proof and raised a separate compatibility decision: replacing npm's home also hides user-level
.npmrctransport configuration. That choice was left visible for maintainer decision rather than silently assumed.