Skip to content

feat: before_install → POST /install-scan (terminal, fail-closed)#13

Merged
olivrg merged 1 commit into
mainfrom
feat/before-install
Jun 18, 2026
Merged

feat: before_install → POST /install-scan (terminal, fail-closed)#13
olivrg merged 1 commit into
mainfrom
feat/before-install

Conversation

@olivrg

@olivrg olivrg commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Implements before_installPOST /install-scan — the last unimplemented adapter hook (issue #11, Part B). Maps the OpenClaw install event to the scan endpoint and enforces the decision, fail-closed.

Behavior

  • allow{} (proceed)
  • deny{ block: true, blockReason: feedback.message ?? reason ?? 'Blocked by Helio' }
  • client { ok: false } (unreachable / timeout / 5xx / malformed) → fail closed (block)
  • Terminal: no /audit follow-up, no correlation/evaluation_id threading.

Request-body mapping (per plan §B.2)

Field Source
package.source normalized request.kind (npm/git/archive/file/dir/skill) — not targetType (kind ≠ provenance; supply-chain rules match on origin)
package.name plugin?.packageName ?? targetName (true package identity, universal fallback)
package.version plugin?.version (omitted when absent)
package.spec request.requestedSpecifier (omitted when absent)
metadata mode, target_type, builtin_scan { critical, warn, info } (OpenClaw's own scan summary, forwarded as context)

Optional fields are conditionally spread, not set to undefined (exactOptionalPropertyTypes).

Notes

  • A default switch arm with a never binding turns any future decision-enum drift into a compile error, while staying fail-closed at runtime.
  • Re-exports PluginInstallRequestKind from the SDK types barrel.
  • Independently reviewed against the contract and plan §B.2 — no blocking findings; both non-blocking suggestions (exhaustiveness guard + edge-case tests) applied.

Verification

pnpm verify green: format ✓, lint ✓, typecheck (0 errors) ✓, 185 tests pass, build ✓. 14 new unit tests cover the happy path, all six kind→source mappings, packageName fallback, deny via feedback/reason/default, update-mode + errored-scan metadata forwarding, and fail-closed unavailability.

Implement the last unimplemented adapter hook. before_install maps the
OpenClaw install event to POST /install-scan and enforces the decision:

- allow → {} (proceed)
- deny  → { block: true, blockReason: feedback.message ?? reason ?? fallback }
- client { ok: false } (unreachable/timeout/5xx/malformed) → fail closed (block)

Terminal call — no /audit follow-up, no correlation threading.

Request-body mapping:
- package.source ← normalized request.kind (npm/git/archive/file/dir/skill),
  NOT targetType (kind ≠ provenance; supply-chain rules match on origin)
- package.name  ← plugin.packageName ?? targetName (true package identity)
- package.version ← plugin.version; package.spec ← request.requestedSpecifier
  (omitted, not undefined, under exactOptionalPropertyTypes)
- metadata: mode, target_type, builtin_scan { critical, warn, info }
  (OpenClaw's own static-scan summary, forwarded as context)

A default switch arm with a `never` binding makes future decision-enum
drift a compile error while staying fail-closed at runtime.

Re-exports PluginInstallRequestKind from the SDK types barrel.
@olivrg olivrg merged commit db6a4b5 into main Jun 18, 2026
1 check passed
@olivrg olivrg deleted the feat/before-install branch June 18, 2026 11:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant