Skip to content

[AAASM-4137] 🔒 (node-sdk): Fail-closed adapters and reconcile postinstall resolution#235

Merged
Chisanan232 merged 2 commits into
masterfrom
v0.0.1/AAASM-4137/adapter_failclosed_postinstall
Jul 5, 2026
Merged

[AAASM-4137] 🔒 (node-sdk): Fail-closed adapters and reconcile postinstall resolution#235
Chisanan232 merged 2 commits into
masterfrom
v0.0.1/AAASM-4137/adapter_failclosed_postinstall

Conversation

@Chisanan232

Copy link
Copy Markdown
Contributor

Target

Close a LOW-severity hardening batch (sweep AAASM-4120): make the ai-sdk / openai-agents framework adapters fail closed on governance faults like the other wrappers, and stop the postinstall script resolving native package names that were never published.

  • Task summary:

    Two independent node-sdk gaps, both verified in source at HEAD:

    1. Adapters swallowed check/approval faults (fail-open). src/hooks/ai-sdk.ts and src/hooks/openai-agents.ts wrapped the pre-execution gateway check and approval wait in try { … } catch { return executeOriginal() }. A caller-supplied config.gatewayClient (honored in init-assembly.ts) that throws on a transport error was therefore silently treated as ALLOW, while with-assembly.ts / wrap-tool-with-assembly.ts (no catch → propagate) would DENY — an inconsistent posture. Removed the swallowing catches so faults propagate (reject/deny under enforce), matching the other wrappers and enforceGovernance.
    2. postinstall resolved unpublished package names (inert). scripts/postinstall.mjs resolved @agent-assembly/<platformKey> binary packages that are neither declared nor published (the declared @agent-assembly/runtime-* optionalDeps ship the aasm CLI, not a .node), so runPostinstall always threw → caught → warned → no-opped, masking a real binary-provisioning regression. The napi .node binaries actually ship in-package under native/aa-ffi-node/ and are resolved by index.cjs at load time. Reconciled the script to verify that bundled binding is present for the current platform, so a missing binary fails loudly at install rather than only at first native load. No dependency-confusion introduced — all names stay under the org-owned @agent-assembly scope.
  • Task tickets:

    • Task ID: AAASM-4137.
    • Relative task IDs:
      • AAASM-4120 (sweep parent).
    • Relative PRs:
      • N/A.
  • Key point change:

    • ai-sdk / openai-agents adapter faults now fail closed (propagate/deny) instead of executing the original tool.
    • postinstall now verifies the in-package native binding instead of copying from a phantom per-platform npm package.

Effecting Scope

  • Action Types:
    • 🔧 Fixing bug
    • 🍀 Improving something (security posture consistency)
  • Scopes:
    • 🤖 Framework hooks
    • 🧪 Unit testing
    • 🚀 Building → 📦 Project configurations (postinstall)
  • Additional description:
    Fail-open removal is only observable with a caller-supplied gatewayClient that throws; the built-in native client catches internally and never throws, so no behavior change for the default path. Under enforce this is a hardening, not a breaking change.

Description

  • 🔒 (hooks): Remove the swallowing try/catch around check / approval in the ai-sdk and openai-agents adapters; update the four contradicted tests to assert the fault propagates and the original tool does not run.
  • 🐛 (postinstall): Verify the bundled native/aa-ffi-node/ binding for the current platform (mirroring index.cjs resolution) instead of resolving unpublished @agent-assembly/<platformKey> packages; update the .d.mts and tests.

How to verify: pnpm typecheck && pnpm lint && pnpm test — full suite green (358 passed, 2 skipped). New/updated tests: a throwing gatewayClient under enforce now blocks the tool in both adapters; postinstall confirms/loud-fails on the in-package binding.

Closes AAASM-4137

🤖 Generated with Claude Code

The ai-sdk and openai-agents adapters wrapped the pre-execution gateway
check and approval wait in try { … } catch { return executeOriginal() },
so a caller-supplied gatewayClient that throws on a transport error was
silently treated as ALLOW. The with-assembly / wrap-tool wrappers have no
such catch: an un-caught check() rejects and blocks the tool. Drop the
swallowing catches so all wrappers share one fail-closed posture; faults
now propagate (reject) under enforce. Existing tests updated to assert the
fault propagates and the original tool does not run.

refs AAASM-4137
postinstall resolved @agent-assembly/<platformKey> binary packages that
were never declared nor published (the declared @agent-assembly/runtime-*
optionalDeps ship the aasm CLI, not a .node), so runPostinstall always
threw, got caught, warned, and no-opped — masking a real binary-provisioning
regression. The napi .node binaries actually ship in-package under
native/aa-ffi-node/ and are resolved by index.cjs at load time. Verify that
bundled binding is present for the current platform (mirroring index.cjs
resolution) so a missing binary fails loudly at install rather than only at
first native load. All names stay under the org-owned @agent-assembly scope.

refs AAASM-4137
@codecov

codecov Bot commented Jul 4, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@sonarqubecloud

sonarqubecloud Bot commented Jul 4, 2026

Copy link
Copy Markdown

@Chisanan232

Chisanan232 commented Jul 5, 2026

Copy link
Copy Markdown
Contributor Author

Review — AAASM-4137 fail-closed adapters + postinstall reconcile

Verdict: Approve-ready (comment only, no approval per review protocol). All four dimensions green.

1. CI — 25/25 checks passing, 0 failed. No fix needed.

2. Scope vs ticket — Matches AAASM-4137 exactly (both sub-items of the LOW hardening batch under sweep AAASM-4120): (a) remove the fail-open try/catch in the ai-sdk and openai-agents adapters, (b) reconcile postinstall from phantom @agent-assembly/<platformKey> packages to verifying the in-package native/aa-ffi-node/ binding. Four contradicted adapter tests were flipped to assert propagation; postinstall tests updated.

3. Side effects — Verified:

  • Catch removal is only observable with a caller-supplied gatewayClient that throws. The built-in native client's check catches internally ({ denied: failClosed }, never throws), so the default happy path is unchanged — allowed tools still run. Under enforce, a throwing caller client now blocks instead of silently allowing (new tests assert originalExecute/originalRunTool not called + the fault message propagates), matching with-assembly / wrap-tool-with-assembly.
  • postinstall now mirrors index.cjs resolution (index.node, else first index.<triple>.node) against the bundled native/aa-ffi-node/ dir; imports (fs, path, pathToFileURL) intact; runPostinstall warns (returns false) only when the binding is genuinely absent for a supported platform, instead of the old always-throw that masked real state. No dependency-confusion — all names stay under the org-owned @agent-assembly scope.

4. FE — N/A.

Local validation (worktree, pnpm install && typecheck && lint && test): typecheck clean, ESLint no issues, 358 passed / 2 skipped (52 files passed / 1 skipped). No packaging-lock flake tripped this run.

Touches src/hooks/*.ts, scripts/postinstall.*, and their tests — no overlap with #234; the two are independently mergeable.

— Claude Code

@Chisanan232 Chisanan232 merged commit 456223f into master Jul 5, 2026
25 checks passed
@Chisanan232 Chisanan232 deleted the v0.0.1/AAASM-4137/adapter_failclosed_postinstall branch July 5, 2026 00:44
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