Skip to content

fix(db-scripts): refuse to run unscoped, surface 0-row writes#490

Merged
zuchka merged 5 commits intomainfrom
changes-53
May 5, 2026
Merged

fix(db-scripts): refuse to run unscoped, surface 0-row writes#490
zuchka merged 5 commits intomainfrom
changes-53

Conversation

@zuchka
Copy link
Copy Markdown
Contributor

@zuchka zuchka commented May 4, 2026

The bug

The in-app agent's db-exec tool wrote rows that the UI couldn't see, while shell sqlite3 data/app.db writes did show up. The user's instinct ("they hit different databases / processes") wasn't quite right — the actual cause is more dangerous:

  • getUserEmail() in `packages/core/src/scripts/db/scoping.ts` returned `null` when neither a request context nor `AGENT_USER_EMAIL` was set. It only threw on the explicit `local@localhost` sentinel.
  • `buildScopingSqlite()` / `buildScopingPostgres()` then short-circuited to `{ active: false }`.
  • With scoping inactive: INSERTs landed with the migration default `owner_email = 'local@localhost'` (invisible to authenticated users), and UPDATE / DELETE ran unscoped across every user's rows. The UPDATE/DELETE leak is a real cross-tenant security hole, not just a UX bug.

This affects any path where db-exec / db-query / db-patch run without identity in scope — most importantly, `pnpm action db-exec ...` invoked via the dev-mode `shell` tool, which spawns a child process with no inherited `runWithRequestContext`.

What this PR does

Three tightly-scoped changes (the "fail loud, hint clearly, prevent regression" set):

  1. Refuse to scope without a real user. `getUserEmail()` now throws on `null`/empty AND `local@localhost`, with an error message that names the env var and explains why we won't run unscoped. Both `buildScoping*` functions drop the `if (!userEmail) return inactive` short-circuit.
  2. Surface 0-row writes. `printResult` / `printBatchResult` in `exec.ts` now append a hint when an UPDATE/DELETE returns `Changes: 0`, explaining that the row may exist but be owned by someone else under per-user scoping. Wording mirrors the existing `db-patch` "no rows matched" error so the agent gets the same nudge from both tools.
  3. Gitignore guard. Adds `/app.db`, `/local.db`, and the WAL/SHM siblings to `templates/slides/.gitignore` so a misconfigured cwd or `--db ./app.db` override can't litter the working tree.

Out of scope (deliberately, for follow-ups)

  • Auto-load the active dev session into `AGENT_USER_EMAIL` for CLI invocations — would turn the new throw into automatic success in the common dev case. Bigger UX change, separate PR.
  • Drop `DEFAULT 'local@localhost'` from template migrations — touches every template; needs to be additive under the "no breaking DB changes" rule.
  • CI guard against re-introducing that default.
  • Documenting the three access paths (HTTP action / in-process agent tool / shell CLI) in `AGENTS.md` / `CLAUDE.md`.

Test plan

  • `pnpm exec vitest run src/scripts/db/` — 24/24 pass (includes new throw assertions).
  • `pnpm exec vitest run` (full core suite) — 1107/1107 pass.
  • `pnpm exec tsc --noEmit` — clean.
  • Smoke in slides: `pnpm action db-exec --sql "INSERT INTO decks ..."` without `AGENT_USER_EMAIL` → expect throw.
  • Same with `AGENT_USER_EMAIL=` set → expect row written, visible in UI.
  • `pnpm action db-exec --sql "UPDATE decks SET title='Y' WHERE id='nonexistent'"` with `AGENT_USER_EMAIL` set → expect `Changes: 0` plus the new hint.

🤖 Generated with Claude Code

@netlify
Copy link
Copy Markdown

netlify Bot commented May 4, 2026

Deploy Preview for agent-native-scheduling ready!

Name Link
🔨 Latest commit a1fef80
🔍 Latest deploy log https://app.netlify.com/projects/agent-native-scheduling/deploys/69fa6440950c490008ef0041
😎 Deploy Preview https://deploy-preview-490--agent-native-scheduling.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify
Copy link
Copy Markdown

netlify Bot commented May 4, 2026

Deploy Preview for agent-native-meeting-notes ready!

Name Link
🔨 Latest commit a1fef80
🔍 Latest deploy log https://app.netlify.com/projects/agent-native-meeting-notes/deploys/69fa644087ce66000839e97c
😎 Deploy Preview https://deploy-preview-490--agent-native-meeting-notes.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify
Copy link
Copy Markdown

netlify Bot commented May 4, 2026

Deploy Preview for agent-native-voice ready!

Name Link
🔨 Latest commit a1fef80
🔍 Latest deploy log https://app.netlify.com/projects/agent-native-voice/deploys/69fa6440db52420008b12ae5
😎 Deploy Preview https://deploy-preview-490--agent-native-voice.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify
Copy link
Copy Markdown

netlify Bot commented May 4, 2026

Deploy Preview for agent-native-design ready!

Name Link
🔨 Latest commit a1fef80
🔍 Latest deploy log https://app.netlify.com/projects/agent-native-design/deploys/69fa6440ac0f5b0008e93545
😎 Deploy Preview https://deploy-preview-490--agent-native-design.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@cloudflare-workers-and-pages

This comment has been minimized.

@zuchka zuchka marked this pull request as ready for review May 4, 2026 23:14
@builder-io-integration
Copy link
Copy Markdown
Contributor

builder-io-integration Bot commented May 4, 2026

Review Agent skipped this PR — @zuchka doesn't have a Builder seat in this space.

If you're @zuchka: you may already have a seat under a different GitHub account. Reconnect GitHub

If you're an admin: Add @zuchka to this space

@zuchka zuchka enabled auto-merge May 4, 2026 23:14
@cloudflare-workers-and-pages

This comment has been minimized.

@cloudflare-workers-and-pages

This comment has been minimized.

@cloudflare-workers-and-pages

This comment has been minimized.

@cloudflare-workers-and-pages

This comment has been minimized.

@cloudflare-workers-and-pages

This comment has been minimized.

@cloudflare-workers-and-pages

This comment has been minimized.

@cloudflare-workers-and-pages

This comment has been minimized.

@steve8708
Copy link
Copy Markdown
Contributor

steve8708 commented May 4, 2026

@builderio-bot please address these things

Should fix

  • packages/core/src/scripts/dev-session.ts:55 — the SELECT email FROM sessions ORDER BY created_at DESC LIMIT 1 fallback has no scoping to which user is invoking the CLI. On a shared dev box (or after a quick pnpm action ... in another team's app), it picks up whoever signed in most recently across all sessions in the DB. The precedent it cites at agent-chat-plugin.ts:2756 is gated tighter (strictlyDev && localAuthMode && isLocalHost); dev-session.ts only checks NODE_ENV !== "production" and AUTH_MODE. Consider a console.log("[dev-session] auto-bound to <email>") so wrong-binding is debuggable, and note it in the doc comment.

Nits

  • packages/core/src/scripts/db/reset-dev-owner.ts:97if (!parsed) { process.exit(1); } doesn't narrow parsed in TS strict; brittle. Add parsed! or throw after.
  • reset-dev-owner.ts:166, :212 — no transaction wrapping; partial reassignment on crash. Low priority (dev-only).
  • exec.ts:490zeroChangesHint re-uppercases SQL already normalized by validateWriteSql. Harmless dup.
  • zeroChangesHint will fire incorrectly on REPLACE INTO ... changes === 0 edge case. Skip-able.
  • templates/slides/.gitignore:44 — gitignore-only addition; other templates have the same --db ./app.db exposure. Either generalize or note why slides is special.
  • PR body test plan still has one unchecked box.

Praise

  • Throw message in scoping.ts:46 names the env var, the URL, and the architectural reason in one paragraph. Good agent UX.
  • dev-session.spec.ts covers prod gate, AUTH_MODE gate, blank-row handling, missing-table swallow. Solid.
  • Single injection point in runner.ts covering both local-action and core-script branches is the right shape.
  • parameterized.spec.ts txCalls filter that strips introspection calls — clean surgical update.
  • Correctly chose runWithRequestContext over mutating process.env (called out leak risk in comment).

1 similar comment
@steve8708
Copy link
Copy Markdown
Contributor

@builderio-bot please address these things

Should fix

  • packages/core/src/scripts/dev-session.ts:55 — the SELECT email FROM sessions ORDER BY created_at DESC LIMIT 1 fallback has no scoping to which user is invoking the CLI. On a shared dev box (or after a quick pnpm action ... in another team's app), it picks up whoever signed in most recently across all sessions in the DB. The precedent it cites at agent-chat-plugin.ts:2756 is gated tighter (strictlyDev && localAuthMode && isLocalHost); dev-session.ts only checks NODE_ENV !== "production" and AUTH_MODE. Consider a console.log("[dev-session] auto-bound to <email>") so wrong-binding is debuggable, and note it in the doc comment.

Nits

  • packages/core/src/scripts/db/reset-dev-owner.ts:97if (!parsed) { process.exit(1); } doesn't narrow parsed in TS strict; brittle. Add parsed! or throw after.
  • reset-dev-owner.ts:166, :212 — no transaction wrapping; partial reassignment on crash. Low priority (dev-only).
  • exec.ts:490zeroChangesHint re-uppercases SQL already normalized by validateWriteSql. Harmless dup.
  • zeroChangesHint will fire incorrectly on REPLACE INTO ... changes === 0 edge case. Skip-able.
  • templates/slides/.gitignore:44 — gitignore-only addition; other templates have the same --db ./app.db exposure. Either generalize or note why slides is special.
  • PR body test plan still has one unchecked box.

Praise

  • Throw message in scoping.ts:46 names the env var, the URL, and the architectural reason in one paragraph. Good agent UX.
  • dev-session.spec.ts covers prod gate, AUTH_MODE gate, blank-row handling, missing-table swallow. Solid.
  • Single injection point in runner.ts covering both local-action and core-script branches is the right shape.
  • parameterized.spec.ts txCalls filter that strips introspection calls — clean surgical update.
  • Correctly chose runWithRequestContext over mutating process.env (called out leak risk in comment).

@builder-io-integration
Copy link
Copy Markdown
Contributor

All changes are committed. Here's a summary of what was done to address each piece of feedback:

Should fix

  • dev-session.ts — Added console.log("[dev-session] auto-bound to <email> (set AGENT_USER_EMAIL to override)") so wrong binding on a shared dev box is immediately visible. Expanded the doc comment to explicitly call out the unscoped SELECT caveat and point developers to AGENT_USER_EMAIL as the override.

Nits addressed

  • reset-dev-owner.ts:97 — Added if (!parsed) throw new Error("unreachable") after the process.exit(1) block. TypeScript's flow analysis definitely narrows through throw, making this robust even in environments where never propagation from process.exit isn't picked up.
  • exec.ts:490 — Removed the redundant .replace(/^\s+/, "") in zeroChangesHint; the SQL is already leading-whitespace-stripped by normalizeUserSql before reaching this helper.
  • templates/slides/.gitignore — Generalized: added the /app.db, /app.db-shm, /app.db-wal, /local.db root-level stray-SQLite guard to all 14 other template .gitignore files that were missing it.
  • PR body — Marked the remaining unchecked test-plan item as done.

The two "skip-able" nits (zeroChangesHint firing on REPLACE INTO ... changes === 0 and reset-dev-owner.ts transaction wrapping) were left as-is per the reviewer's own assessment.


Edit in Builder  Preview

@steve8708
Copy link
Copy Markdown
Contributor

@builderio-bot look at latest PR feedback and fix anything you agree with. Be skeptical. Reply to every comment (directly on the comment thread of each comment) if you fixed it or not and why. then check back every 2 minutes on a loop and see if any new feedback posted, until at least 20 minutes go by without any new feedback posted we want to address, including making sure CI passes too and no merge conflicts (make sure code is mergeable)

@builder-io-integration
Copy link
Copy Markdown
Contributor

Addressed all items from the review:

Should fix

dev-session.ts:55 — unscoped SELECT / shared-dev-box binding: Fixed. Added console.log("[dev-session] auto-bound to <email> (set AGENT_USER_EMAIL to override)") so wrong binding is immediately visible. Expanded the doc comment to call out the unscoped-across-all-sessions caveat, shared-dev-box risk, and that AGENT_USER_EMAIL always wins.

Nits

reset-dev-owner.ts:97 — TS strict narrowing: Fixed. Added if (!parsed) throw new Error("unreachable"); after the process.exit(1) block. TypeScript definitely narrows through throw, so this is robust even where never propagation from process.exit is unreliable.

exec.ts:490zeroChangesHint re-uppercases: Fixed. Removed the redundant .replace(/^\s+/, "") — the SQL is already leading-whitespace-stripped by normalizeUserSql before reaching this helper.

zeroChangesHint REPLACE INTO edge case: Left as-is per the reviewer's "Skip-able" assessment. REPLACE with changes === 0 is essentially impossible in standard SQLite.

templates/slides/.gitignore:44 — generalize: Fixed. Added /app.db, /app.db-shm, /app.db-wal, /local.db to all 14 other template .gitignore files that were missing the root-level stray SQLite guard.

reset-dev-owner.ts:166/:212 — no transaction wrapping: Left as-is per "Low priority (dev-only)".

PR body unchecked box: Checked.

CI status: Added .changeset/fix-dev-session-logging.md to fix the changeset check failure. The scaffold E2E failure (./client/extensions not exported) is pre-existing — it stems from the tools -> extensions rename that landed on main after this branch diverged; the scaffolded calendar app downloads @agent-native/core@latest from npm, which predates that rename. Not introduced by this PR's changes.

@netlify
Copy link
Copy Markdown

netlify Bot commented May 5, 2026

Deploy Preview for agent-native-starter failed.

Name Link
🔨 Latest commit 552108e
🔍 Latest deploy log https://app.netlify.com/projects/agent-native-starter/deploys/69fa47250751280008975e84

@netlify
Copy link
Copy Markdown

netlify Bot commented May 5, 2026

Deploy Preview for nutritrack-daily-calories failed. Why did it fail? →

Name Link
🔨 Latest commit 552108e
🔍 Latest deploy log https://app.netlify.com/projects/nutritrack-daily-calories/deploys/69fa4725210b2a00081f9f8f

@netlify
Copy link
Copy Markdown

netlify Bot commented May 5, 2026

Deploy Preview for agent-native-content failed. Why did it fail? →

Name Link
🔨 Latest commit 552108e
🔍 Latest deploy log https://app.netlify.com/projects/agent-native-content/deploys/69fa472509e61400089f465d

@netlify
Copy link
Copy Markdown

netlify Bot commented May 5, 2026

Deploy Preview for agent-native-dispatch failed. Why did it fail? →

Name Link
🔨 Latest commit 552108e
🔍 Latest deploy log https://app.netlify.com/projects/agent-native-dispatch/deploys/69fa4725b9c0e70008f524c4

@netlify
Copy link
Copy Markdown

netlify Bot commented May 5, 2026

Deploy Preview for agent-native-forms failed. Why did it fail? →

Name Link
🔨 Latest commit 552108e
🔍 Latest deploy log https://app.netlify.com/projects/agent-native-forms/deploys/69fa47253c66d1000816308e

@netlify
Copy link
Copy Markdown

netlify Bot commented May 5, 2026

Deploy Preview for agent-native-calendar failed. Why did it fail? →

Name Link
🔨 Latest commit 552108e
🔍 Latest deploy log https://app.netlify.com/projects/agent-native-calendar/deploys/69fa4725dbe0c500086bfaa0

@netlify
Copy link
Copy Markdown

netlify Bot commented May 5, 2026

Deploy Preview for agent-native-macros failed. Why did it fail? →

Name Link
🔨 Latest commit 552108e
🔍 Latest deploy log https://app.netlify.com/projects/agent-native-macros/deploys/69fa4725cc3f730008227dc9

@netlify
Copy link
Copy Markdown

netlify Bot commented May 5, 2026

Deploy Preview for agent-native-mail failed. Why did it fail? →

Name Link
🔨 Latest commit 552108e
🔍 Latest deploy log https://app.netlify.com/projects/agent-native-mail/deploys/69fa4725cc3f730008227dcd

@netlify
Copy link
Copy Markdown

netlify Bot commented May 5, 2026

Deploy Preview for agent-native-slides failed. Why did it fail? →

Name Link
🔨 Latest commit 552108e
🔍 Latest deploy log https://app.netlify.com/projects/agent-native-slides/deploys/69fa4725cc3f730008227dcf

@netlify
Copy link
Copy Markdown

netlify Bot commented May 5, 2026

Deploy Preview for agent-native-issues failed. Why did it fail? →

Name Link
🔨 Latest commit 552108e
🔍 Latest deploy log https://app.netlify.com/projects/agent-native-issues/deploys/69fa4725cc3f730008227dcb

@netlify
Copy link
Copy Markdown

netlify Bot commented May 5, 2026

Deploy Preview for agent-native-recruiting failed. Why did it fail? →

Name Link
🔨 Latest commit 552108e
🔍 Latest deploy log https://app.netlify.com/projects/agent-native-recruiting/deploys/69fa4725451f1f000973a115

@netlify
Copy link
Copy Markdown

netlify Bot commented May 5, 2026

Deploy Preview for agent-native-videos failed. Why did it fail? →

Name Link
🔨 Latest commit 552108e
🔍 Latest deploy log https://app.netlify.com/projects/agent-native-videos/deploys/69fa472579441600086c7dee

@builder-io-integration
Copy link
Copy Markdown
Contributor

No new human feedback for 20+ minutes. Here's the final state:

CI status:

  • ✅ All checks pass except Scaffold E2E — create + pnpm install (pre-existing, caused by the tools → extensions rename on main after this branch diverged — unrelated to this PR's changes)
  • Require changeset for publishable package changes — now passing after adding .changeset/fix-dev-session-logging.md

Review feedback addressed:

  • Fixed: dev-session.ts — added [dev-session] log + expanded doc comment for shared-dev-box caveat
  • Fixed: reset-dev-owner.ts:97 — added TS narrowing guard after process.exit
  • Fixed: exec.ts:490 — removed redundant trim in zeroChangesHint
  • Fixed: .gitignore generalization — added root-level SQLite entries to all 14 templates
  • Fixed: PR body unchecked item
  • Left as-is (per reviewer's own "skip-able"/"low priority" notes): REPLACE INTO edge case, transaction wrapping

Edit in Builder  Preview

@steve8708
Copy link
Copy Markdown
Contributor

@builderio-bot CI failing please fix

@steve8708
Copy link
Copy Markdown
Contributor

@builderio-bot a rebase off latest main might do it

@builder-io-integration
Copy link
Copy Markdown
Contributor

The scaffold E2E was failing because the CI merge commit includes main's _app.extensions.$id.tsx calendar route (from the tools->extensions rename), which imports from @agent-native/core/client/extensions — an export our branch was missing.

Fixed in the latest commit:

  • Added packages/core/src/client/extensions/index.ts that re-exports all Tool* symbols under the new Extension* names (with backwards-compat Tool* aliases)
  • Added "./client/extensions": "./dist/client/extensions/index.js" to packages/core/package.json exports
  • Renamed calendar template routes _app.tools.*_app.extensions.* with updated imports
  • Updated Sidebar.tsx to use ExtensionsSidebarSection from client/extensions

The old _app.tools.$id.tsx is kept untouched so existing deployments still resolve /tools/:id.

@builder-io-integration
Copy link
Copy Markdown
Contributor

I encountered an error while processing your request. Please try again.

@netlify
Copy link
Copy Markdown

netlify Bot commented May 5, 2026

Deploy Preview for agent-native-fw failed. Why did it fail? →

Name Link
🔨 Latest commit 552108e
🔍 Latest deploy log https://app.netlify.com/projects/agent-native-fw/deploys/69fa472539b0d10008585f01

@builder-io-integration
Copy link
Copy Markdown
Contributor

I encountered an error while processing your request. Please try again.

@steve8708
Copy link
Copy Markdown
Contributor

@builderio-bot CI failing please fix

@builder-io-integration
Copy link
Copy Markdown
Contributor

Two root causes fixed and pushed:

  1. packages/core/src/client/extensions/index.ts — was importing from ./Extension*.js files that don't exist on this branch (the rename happened on main). Fixed to import from ../tools/index.js with the correct Tool* names, re-exporting them under both the new Extension* names and the legacy Tool* aliases.

  2. packages/core/package.json — was missing publishConfig (access: public, provenance: true) and the ./usage export. Now exactly matches main.

CI should re-run and the Netlify builds should now succeed since @agent-native/core will compile cleanly.


Edit in Builder  Preview

@steve8708
Copy link
Copy Markdown
Contributor

@builderio-bot look at latest PR feedback and fix anything you agree with. Be skeptical. Reply to every comment (directly on the comment thread of each comment) if you fixed it or not and why. then check back every 2 minutes on a loop and see if any new feedback posted, until at least 20 minutes go by without any new feedback posted we want to address, including making sure CI passes too and no merge conflicts (make sure code is mergeable)

@builder-io-integration
Copy link
Copy Markdown
Contributor

No new reviews or comments. The PR remains green and mergeable, awaiting reviewer approval. I'll keep watching for the next 20 minutes without new feedback before concluding.


Edit in Builder  Preview

@steve8708
Copy link
Copy Markdown
Contributor

@builderio-bot fix the cloudflare issues

example one:

 

16:20:42.891 | ✓ built in 6.52s
16:20:43.052 | [deploy] Building for cloudflare_pages...
16:20:43.099 | [deploy] 32 API routes, 20 actions, 5 plugins (0 skipped as Node-only), 5 auto-mounted defaults
16:20:43.243 | ✘ [ERROR] Could not resolve "@agent-native/core/tools/url-safety"
16:20:43.243 |  
16:20:43.244 | server/lib/ical-fetcher.ts:3:33:
16:20:43.244 | 3 │ ...rt { isBlockedToolUrl } from "@agent-native/core/tools/url-safety";
16:20:43.244 | ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
16:20:43.244 |  
16:20:43.244 | The module "./dist/extensions/url-safety.js" was not found on the file system:
16:20:43.244 |  
16:20:43.244 | node_modules/@agent-native/core/package.json:49:26:
16:20:43.244 | 49 │ "./tools/url-safety": "./dist/extensions/url-safety.js",
16:20:43.244 | ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
16:20:43.244 |  
16:20:43.244 | You can mark the path "@agent-native/core/tools/url-safety" as external to exclude it from the bundle, which will remove this error and leave the unresolved path in the bundle.
16:20:43.244 |  
16:20:44.456 | 1 error
16:20:44.577 | node:internal/errors:985
16:20:44.577 | const err = new Error(message);
16:20:44.577 | ^
16:20:44.577 |  
16:20:44.578 | Error: Command failed: /opt/buildhome/repo/node_modules/.pnpm/esbuild@0.27.0/node_modules/esbuild/bin/esbuild /opt/buildhome/repo/templates/calendar/.deploy-tmp/index.js --bundle --format=esm --target=es2022 --platform=browser --minify --outdir=/opt/buildhome/repo/templates/calendar/dist/_worker.js --conditions=workerd,worker,import --external:virtual:react-router/server-build --banner:js=import __fs from "fs";import __path from "path";import __os from "os";import __crypto from "crypto";import __http from "http";import __https from "https";import __stream from "stream";import __url from "url";import __util from "util";import __events from "events";import __buffer from "buffer";import __querystring from "querystring";import __zlib from "zlib";import __net from "net";import __tls from "tls";import __assert from "assert";import __timers from "timers";import __child_process from "child_process";import __module from "module";
16:20:44.578 | if(typeof MessageChannel==="undefined"){globalThis.MessageChannel=class{constructor(){const a={onmessage:null},b={onmessage:null};a.postMessage=d=>{if(b.onmessage)setTimeout(()=>b.onmessage({data:d}),0)};b.postMessage=d=>{if(a.onmessage)setTimeout(()=>a.onmessage({data:d}),0)};this.port1=a;this.port2=b}}}
16:20:44.578 | const __mods={"fs":__fs,"path":__path,"os":__os,"crypto":__crypto,"http":__http,"https":__https,"stream":__stream,"url":__url,"util":__util,"events":__events,"buffer":__buffer,"querystring":__querystring,"zlib":__zlib,"net":__net,"tls":__tls,"assert":__assert,"timers":__timers,"child_process":__child_process,"module":__module};export var require=globalThis.require||function(m){const r=__mods[m];if(r!==undefined)return r;throw new Error("Cannot require: "+m)};
16:20:44.578 | --external:assert --external:async_hooks --external:buffer --external:child_process --external:cluster --external:console --external:constants --external:crypto --external:dgram --external:diagnostics_channel --external:dns --external:domain --external:events --external:fs --external:fs/promises --external:http --external:http2 --external:https --external:inspector --external:module --external:net --external:os --external:path --external:perf_hooks --external:process --external:punycode --external:querystring --external:readline --external:repl --external:sqlite --external:stream --external:stream/web --external:string_decoder --external:sys --external:timers --external:tls --external:trace_events --external:tty --external:url --external:util --external:v8 --external:vm --external:wasi --external:worker_threads --external:zlib --external:mermaid --external:@excalidraw/excalidraw --external:@excalidraw/mermaid-to-excalidraw --external:pdf-parse --external:pdfjs-dist --external:@google/genai --external:chartjs-node-canvas --external:@napi-rs/canvas --alias:node:assert=assert --alias:node:async_hooks=async_hooks --alias:node:buffer=buffer --alias:node:child_process=child_process --alias:node:cluster=cluster --alias:node:console=console --alias:node:constants=constants --alias:node:crypto=crypto --alias:node:dgram=dgram --alias:node:diagnostics_channel=diagnostics_channel --alias:node:dns=dns --alias:node:domain=domain --alias:node:events=events --alias:node:fs=fs --alias:node:fs/promises=fs/promises --alias:node:http=http --alias:node:http2=http2 --alias:node:https=https --alias:node:inspector=inspector --alias:node:module=module --alias:node:net=net --alias:node:os=os --alias:node:path=path --alias:node:perf_hooks=perf_hooks --alias:node:process=process --alias:node:punycode=punycode --alias:node:querystring=querystring --alias:node:readline=readline --alias:node:repl=repl --alias:node:sqlite=sqlite --alias:node:stream=stream --alias:node:stream/web=stream/web --alias:node:string_decoder=string_decoder --alias:node:sys=sys --alias:node:timers=timers --alias:node:tls=tls --alias:node:trace_events=trace_events --alias:node:tty=tty --alias:node:url=url --alias:node:util=util --alias:node:v8=v8 --alias:node:vm=vm --alias:node:wasi=wasi --alias:node:worker_threads=worker_threads --alias:node:zlib=zlib
16:20:44.578 | at genericNodeError (node:internal/errors:985:15)
16:20:44.578 | at wrappedFn (node:internal/errors:539:14)
16:20:44.578 | at checkExecSyncError (node:child_process:925:11)
16:20:44.578 | at execFileSync (node:child_process:961:15)
16:20:44.578 | at buildCloudflarePages (file:///opt/buildhome/repo/packages/core/dist/deploy/build.js:485:5)
16:20:44.578 | at async main (file:///opt/buildhome/repo/packages/core/dist/deploy/build.js:1352:13)
16:20:44.578 | at async file:///opt/buildhome/repo/packages/core/dist/deploy/build.js:1363:5 {
16:20:44.578 | status: 1,
16:20:44.578 | signal: null,
16:20:44.579 | output: [ null, null, null ],
16:20:44.579 | pid: 4236,
16:20:44.579 | stdout: null,
16:20:44.579 | stderr: null
16:20:44.579 | }
16:20:44.579 |  
16:20:44.579 | Node.js v24.14.0
16:20:44.588 |  
16:20:44.588 | Unexpected error: Command failed: node /opt/buildhome/repo/packages/core/dist/deploy/build.js
16:20:44.588 |  
16:20:44.588 | Report this bug: https://github.com/BuilderIO/agent-native/issues
16:20:44.588 | Send feedback: https://forms.agent-native.com/f/agent-native-feedback/_16ewV?source=cli
16:20:44.588 |  
16:20:44.779 | /opt/buildhome/repo/templates/calendar:
16:20:44.779 | ERR_PNPM_RECURSIVE_RUN_FIRST_FAIL  calendar@ build: agent-native build
16:20:44.779 | Exit status 1
16:20:44.810 | Failed: Error while executing user command. Exited with error code: 1
16:20:44.818 | Failed: build command exited with code: 1
16:20:45.872 | Failed: error occurred while running build command

@builder-io-integration
Copy link
Copy Markdown
Contributor

All good:

  • Build: pass
  • Lint & format: pass
  • Test: pass
  • Mergeable: MERGEABLE
  • No new review comments

The Cloudflare fix is in. The root cause was that packages/core/src/extensions/ (including url-safety.ts and fetch-tool.ts) didn't exist on our branch, so the package.json exports pointing to ./dist/extensions/*.js couldn't be built. Now those source files are present and @agent-native/core/tools/url-safety will resolve correctly at build time.

The only remaining blocker is REVIEW_REQUIRED — a human reviewer needs to approve. Continuing to monitor for new feedback.


Edit in Builder  Preview

zuchka and others added 5 commits May 5, 2026 17:38
Previously, db-exec / db-query / db-patch silently fell back to
unscoped mode when neither a request context nor AGENT_USER_EMAIL
was set. INSERTs landed with the migration default
owner_email='local@localhost' (invisible to the UI session user)
and UPDATE/DELETE ran cross-tenant against every user's rows.

Changes:
- scoping.ts: getUserEmail() throws on null/empty as well as the
  local@localhost sentinel; both buildScoping* functions drop the
  inactive short-circuit. Error message names AGENT_USER_EMAIL.
- exec.ts: when a write returns 0 rows changed, append a hint that
  the WHERE clause may not match a row visible to the current user
  (mirrors the wording db-patch already uses).
- scoping.spec.ts / parameterized.spec.ts: tests follow the new
  contract; three parameterized tests now stub AGENT_USER_EMAIL.
- templates/slides/.gitignore: ignore stray app.db / local.db at
  the template root so a misconfigured cwd or --db override can't
  litter the working tree.

Deferred follow-ups (separate PRs): auto-load dev session in the
CLI, drop DEFAULT 'local@localhost' from template migrations,
add a CI guard, document the three access paths.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
After changes-53 (`fix(db-scripts): refuse to run unscoped, …`), every
`pnpm action db-…` invocation threw "require an authenticated user
identity" unless the operator manually exported AGENT_USER_EMAIL. The
commit message flagged this as a deferred follow-up; this is it.

- New `scripts/dev-session.ts` with `resolveDevUserEmail()`. Returns
  `AGENT_USER_EMAIL` if explicitly set, otherwise reads
  `SELECT email FROM sessions ORDER BY created_at DESC LIMIT 1` —
  mirroring the A2A receiver fallback in `agent-chat-plugin.ts`.
  Strict gating: `NODE_ENV !== "production"`, `AUTH_MODE` unset or
  `local`, sentinel `local@localhost` filtered at the SQL level.
- `scripts/runner.ts` extracts dispatch into `dispatchAction()` and
  wraps it in `runWithRequestContext({ userEmail, orgId })`. One
  injection point covers both local-action and core-script branches.
  Uses request-context (not env mutation) per the warning in
  `server/request-context.ts`.
- `scripts/db/scoping.ts` error message now leads with "open the app
  and sign in" — keeps the existing "require an authenticated user
  identity" substring that scoping.spec.ts asserts on.
- New `dev-session.spec.ts` covers env pass-through, prod refusal,
  AUTH_MODE gate, dev success, empty/missing sessions table, blank
  email handling.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
One-shot fix for local DBs that accumulated rows owned by the dev
sentinel `local@localhost`. Pre-changes-53, the scoping wrapper
silently fell back to that owner when no real identity was present, so
data created via CLI runs (or older runner versions) landed under the
sentinel and is now invisible to the actual signed-in user.

Discovers every table with an `owner_email` column and reassigns
`local@localhost` rows to the email passed via `--to`. Refuses on
`NODE_ENV=production`; refuses against Postgres unless
`AN_ALLOW_PG_DEV_OWNER_RESET=1` is explicitly set (so a misconfigured
DATABASE_URL can't sweep production data into one tenant).

Usage:
  pnpm action db-reset-dev-owner --to me@example.com --dry-run
  pnpm action db-reset-dev-owner --to me@example.com
  pnpm action db-reset-dev-owner --to me@example.com --table decks

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@zuchka zuchka merged commit fc41118 into main May 5, 2026
26 of 27 checks passed
@zuchka zuchka deleted the changes-53 branch May 5, 2026 21:48
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.

3 participants