Skip to content

fix: check and verify for plans#1634

Merged
sidmohanty11 merged 9 commits into
BuilderIO:mainfrom
sidmohanty11:check-and-verify
Jun 29, 2026
Merged

fix: check and verify for plans#1634
sidmohanty11 merged 9 commits into
BuilderIO:mainfrom
sidmohanty11:check-and-verify

Conversation

@sidmohanty11

@sidmohanty11 sidmohanty11 commented Jun 28, 2026

Copy link
Copy Markdown
Contributor
  • verify POSTs the MDX folder to the Plan app's new, public, no-DB validate-local-plan-source action, which runs the renderer's own parsePlanMdxFolder + planContentSchema. Its verdict gates verify's ok, and rejected plans surface the renderer's exact schema-path issue (e.g. blocks[1].data.tabs[0].blocks[0].data.items[0].id). When the endpoint is unavailable (older/unreachable Plan app), verify degrades to the transport checks and warns that content was not validated, rather than hard-failing.
  • check now recurses into nested tabs block arrays so the common nested-checklist / question-form / missing-id case is caught offline, and it no longer reports validation: "passed". It reports a clearly-scoped lint-passed with a note pointing to verify for authoritative validation.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@github-actions

github-actions Bot commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

Visual recap — skipped

The visual recap job did not run for this pull request. This is informational only and does not block the PR.

Recap skipped for b9a89b0: external fork PR requires a maintainer to apply the recap label to the current head SHA.

@builder-io-integration

builder-io-integration Bot commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

⚠️ Review Agent ran into a problem and couldn't finish reviewing the latest commit.

We've been automatically notified and are looking into it. Push a new commit to re-trigger the review, or contact support@builder.io if this keeps happening.

Error ID: 1e213be6191e475ba59570dff4ae9a9a

builder-io-integration[bot]

This comment was marked as outdated.

@builder-io-integration builder-io-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Builder reviewed your changes and found 2 potential issues 🟡

Review Details

This incremental pass fixes the three issues from the prior review: the public validator now has top-level requiresAuth: false, the offline fallback no longer rejects the renderer-supported <Columns columns={[...]}/> form outright, and the validator size cap has been raised to cover the CLI’s packaged payload budget. I verified those fixes and resolved the stale review threads before continuing.

Risk assessment: High. This PR still adds a new public unauthenticated validation action and changes the plan local verify fallback semantics, so parity gaps between the offline lint and the renderer remain important.

The overall approach is still sound: verify now reaches the renderer’s real parser/schema when available, and the nested checklist/question-form checks added here do close a meaningful false-green case. Targeted specs also pass on the updated head (packages/core/src/cli/plan-local.spec.ts and templates/plan/actions/validate-local-plan-source.spec.ts).

New findings:

  • 🟡 The offline fallback still does not recurse into top-level <Columns columns={[...]}/> blocks, so nested invalid content there can still false-green.
  • 🟡 Nested visual-questions blocks are still skipped by the new recursive fallback lint even though top-level VisualQuestions are validated.

🧪 Browser testing: Skipped — PR only modifies CLI/server/docs/tests, no UI impact.

// recursing through nested containers. This is still a subset of the renderer
// schema (which is why `verify` is the authority), but it closes the common
// nested checklist / question-form / missing-id case offline.
const NESTED_CONTAINER_TAGS: ReadonlyArray<{ tag: string; attr: string }> = [

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Fallback lint still skips nested blocks inside top-level Columns JSON syntax

The new recursive fallback only scans TabsBlock/Tabs, so a top-level <Columns columns={[{ id, label, blocks: [...] }]} /> block still never gets its nested checklist/question blocks walked. When renderer validation is unavailable, verify can therefore still false-green invalid nested content in the renderer-supported Columns JSON form.

Additional Info
`NESTED_CONTAINER_TAGS` only includes TabsBlock/Tabs here, while top-level Columns JSON syntax is supported elsewhere in this PR and by the renderer round-trip tests.

Fix in Builder

Comment thread packages/core/src/cli/plan-local.ts Outdated
}
return;
}
if (type === "question-form") {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Nested visual-questions blocks are not validated by the recursive fallback lint

This recursive path only validates nested blocks with type === "question-form", but the top-level lint already treats VisualQuestions as equivalent question content. If renderer validation is unavailable, nested type: "visual-questions" blocks can still pass offline even when required question fields like id or mode are missing.

Additional Info
Top-level lint uses `/(QuestionForm|VisualQuestions)\b/` in `lintQuestionFormShape`, but the nested traversal only checks `type === "question-form"` here.

Fix in Builder

@builder-io-integration builder-io-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Builder reviewed your changes and found 1 potential issue 🔴

Review Details

This incremental pass re-checks the latest PR head after the follow-up fixes. I verified the previously discussed auth and fallback changes are in place, and I reran the targeted specs for packages/core/src/cli/plan-local.spec.ts and templates/plan/actions/validate-local-plan-source.spec.ts; both still pass.

Risk assessment: High. The PR continues to expose a new unauthenticated validation endpoint and uses it to change plan local verify semantics, so request-boundary protections matter as much as schema correctness.

I also re-checked the two already-open fallback-lint parity comments. They still appear to be unresolved, so I did not repost them.

New finding:

  • 🔴 The public validate-local-plan-source endpoint enforces its byte cap only inside the action body, after the action router has already parsed the full JSON request. That means an anonymous caller can still force large-body allocation/parse work on this new public route before the 16 MiB guard runs.

The renderer-backed verification direction is still good overall, but this request-size enforcement gap should be closed before treating the new public validator as safe to ship.

🧪 Browser testing: Skipped — PR only modifies CLI/server/docs/tests, no UI impact.

"The plan MDX folder: plan.mdx plus optional canvas.mdx, prototype.mdx, .plan-state.json, and assets/.",
),
}),
http: { method: "POST" },

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Public validator enforces payload size only after the body is fully parsed

This unauthenticated POST only checks MAX_MDX_BYTES inside run(), but the core action router parses the full JSON body first via webReq.json() / readBody(event). A large anonymous request can therefore still force memory/CPU work on this public route before the 16 MiB guard runs, so the size limit needs to be enforced at the HTTP body-read boundary too.

Additional Info
Confirmed against packages/core/src/server/action-routes.ts lines 304-312; `readBodyWithSizeLimit` exists in packages/core/src/server/h3-helpers.ts but is not used by the generic action POST path.

Fix in Builder

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good thing to add, let me scope a maxBodySize for this action and maybe in the future other actions can reuse it

@sidmohanty11 sidmohanty11 merged commit 995dd3b into BuilderIO:main Jun 29, 2026
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants