feat(fresh-ui): safe render_ui renderer#565
Conversation
|
[PHASE: IMPL] [VERDICT: READY_FOR_A1_REVIEW] Slice FB5 landed in commit Scope
Guard Regressions
Raw Gate Evidence
Deferred / Not Certified
|
|
[PHASE: A1 SLICE REVIEW] [Tier-A supervisor — FAIL_FIX, fix dispatched to generator] Substantive review of the Blocking finding — nested-array depth-guard bypass (reachable DoS)
if (Array.isArray(node)) {
return node.map((child, index) => (<span …>{renderNode(child, depth, context)}</span>));
}So the Verdict: FAIL_FIX. One-line fix (recurse the array branch at Verified clean (no rework needed)
Merge held behind the fix + re-review + IMPL-EVAL (separate OpenHands session) + the #258 close-gate. This bypass is the kind of defect the B→D lane-override adversarial mitigation existed to catch. |
|
[PHASE: IMPL] [VERDICT: READY_FOR_A1_REVIEW] A1 FAIL_FIX for the nested-array depth guard bypass is pushed. Scope:
Commit: Raw gate evidence:
Lock hygiene: Guard regressions green:
|
|
[PHASE: A1 SLICE REVIEW] [Tier-A supervisor sign-off — PASS] Re-review after the FAIL_FIX fix ( Fix verified
Still verified (unchanged by the fix)
A1 PASS. Proceeding to IMPL-EVAL (separate OpenHands session, security-hardened re-attack of the depth + whitelist guards). Merge held behind IMPL-EVAL PASS + the #258 close-gate. The adversarial mitigation the B→D lane override called for was performed at A1 (this bypass was caught and fixed before any eval cycle was spent). |
|
@openhands-agent model=openrouter/qwen/qwen3.7-max output=pr-comment iterations=1500 use harness IMPL-EVAL — FB5
|
OpenHands Agent — CompletedOPENHANDS_VERDICT: PASS Model: IMPL-EVAL Summary: FB5 render_ui generative-UI renderer (#258, PR #565)SummaryIndependent IMPL-EVAL security re-attack of the Fresh UI Changes
ValidationDecisive Checks (all PASS)
Adversarial Depth TraceConstructed 50-level array nesting in
Responses to Review CommentsN/A (fresh evaluation session). Remaining Risks
OPENHANDS_VERDICT: PASS Run: https://github.com/rickylabs/netscript/actions/runs/28856577359 |
|
[PHASE: IMPL-EVAL] [VERDICT: PASS] IMPL-EVAL: FB5 render_ui generative-UI renderer (#258)Independent security re-attack complete. All decisive checks pass. Decisive Checks Summary
Adversarial Depth TraceConstructed 50-level array nesting in
Security Boundary AssessmentThe renderer correctly self-bounds against AI-tool-controlled payloads:
PR Body Close-Gate
VerdictPASS — Merge-safe. The renderer is a robust security boundary for generative-UI payloads. OPENHANDS_VERDICT: PASS |
Independent security re-attack confirms: - Depth guard complete on all 3 recursive descent paths - Type whitelist closed, no raw HTML path - Contract seam correct (consumes E4 input, existing registry) - All gates green: tests, doc-lint, publish dry-run, arch:check, lock hygiene - A1 fix verified (pre-fix bypass confirmed, post-fix guard confirmed) Co-authored-by: openhands <openhands@all-hands.dev>
Summary
Adds the Fresh UI consumer renderer for
render_uitool payloads: a bounded recursive renderer with a curatedlayout/viz/datavocabulary, depth fallback, and unknown-type fallback. The renderer is exposed through@netscript/fresh-ui/ai/render-uiand registered in the existingaiFresh UI collection.Scope
scaffold.runtimegenerated-project E2E (gate:e2e) and end-to-endui:add aiinstall verification remain open on [AI-stack FB5] fresh-ui: generative-ui-renderer (recursive JSON tree -> curated DS vocabulary) #258. Issue test(cli-e2e): scaffold.runtime coverage for fresh-ui ai generative-ui renderer #564 tracks that deferred work; [AI-stack FB5] fresh-ui: generative-ui-renderer (recursive JSON tree -> curated DS vocabulary) #258 stays open until test(cli-e2e): scaffold.runtime coverage for fresh-ui ai generative-ui renderer #564 lands.scaffold.runtimegenerated-project E2E coverage; [AI-stack FB5] fresh-ui: generative-ui-renderer (recursive JSON tree -> curated DS vocabulary) #258's remaining acceptance is completed there, not in this PR.Slices
Definition of Done
RenderUiToolInputfrom@netscript/ai/tools; do not redefine the E4 input contract.layout,viz, anddatacategories.aiFresh UI collection.gate:e2efullscaffold.runtimegenerated-project coverage. Deferred to test(cli-e2e): scaffold.runtime coverage for fresh-ui ai generative-ui renderer #564; do not check this box for [AI-stack FB5] fresh-ui: generative-ui-renderer (recursive JSON tree -> curated DS vocabulary) #258.fe05c814array-branch depth fix.)Validation
deno doc --filter RenderUiToolInput packages/ai/tools.ts— exit 0; E4 input is{ component, props?, title? }.deno doc --filter renderUiTool packages/ai/tools.ts— exit 0;render_uiis client-deferred.deno check --unstable-kv packages/fresh-ui/src/ai/render-ui.tsx packages/fresh-ui/tests/ai/render-ui.test.tsx— exit 0.deno test --allow-read --unstable-kv packages/fresh-ui/tests/ai/render-ui.test.tsx— exit 0; 4 passed / 0 failed (incl. nested-array depth regression).deno run --allow-read --allow-run .llm/tools/run-deno-check.ts --root packages/fresh-ui --ext ts,tsx— exit 0; filesSelected=128, failedBatches=0, totalOccurrences=0.deno run --allow-read --allow-run .llm/tools/run-deno-lint.ts --root packages/fresh-ui --ext ts,tsx— exit 0; totalOccurrences=0.deno run --allow-read --allow-run .llm/tools/run-deno-fmt.ts --root packages/fresh-ui --ext ts,tsx --ignore-line-endings— exit 0; failedBatches=0.deno test --allow-all packages/fresh-ui/tests/— exit 0; 132 passed / 0 failed.rtk proxy deno task arch:check— exit 0; warnings only, no FAIL rows.deno run --allow-read --allow-run .llm/tools/run-deno-doc-lint.ts --root packages/fresh-ui --entrypoints ./src/ai/render-ui.tsx --pretty— exit 0; totalErrors=0.deno task doc:lint --root packages/fresh-ui --pretty— exit 0 wrapper; existinginteractive.tsdoc-lint debt remains, new renderer entrypoint total=0.deno publish --dry-run --allow-dirtyfrompackages/fresh-ui— exit 0; no--allow-slow-types; dry run complete.deno run -A packages/cli/bin/netscript-dev.ts ui:add ai --project-root .llm/tmp/fresh-ui-render-ui-smoke --registry-root packages/fresh-ui --force— exit 0; installed 25 items, copied 47 files, renderer copied tolib/ai/render-ui.tsx.Harness
.llm/runs/beta6-nondash--supervisor/worklog-258.md,context-pack-258.md,drift-258.mdDrift / Debt
interactive.tsdebt; touched renderer entrypoint is clean.@netscript/ai@^0.0.1-beta.5;ui:add aicopy itself succeeds.gate:e2edeferred to test(cli-e2e): scaffold.runtime coverage for fresh-ui ai generative-ui renderer #564; per owner decision (2026-07-07) this PR references [AI-stack FB5] fresh-ui: generative-ui-renderer (recursive JSON tree -> curated DS vocabulary) #258 without a closing keyword so [AI-stack FB5] fresh-ui: generative-ui-renderer (recursive JSON tree -> curated DS vocabulary) #258 stays open until test(cli-e2e): scaffold.runtime coverage for fresh-ui ai generative-ui renderer #564's E2E lands.