Commit Graph
482 Commits
Author SHA1 Message Date
Aymeric Rabot 3d5c87a651 feat(mcp): add guided construction workflows 2026-04-27 14:31:04 -04:00
Sudhir YadavandGitHub bc93f09304 Merge branch 'main' into feat/2d-editor 2026-04-27 18:07:28 +05:30
sudhir d00ba42b9f Enable drag after duplicating roofs and stairs 2026-04-27 13:32:31 +05:30
sudhir 3ae8d6d0fa Extract floorplan placement and hit-testing helpers 2026-04-27 12:18:27 +05:30
sudhir a796c0fd0a Move item dimensions into local item overlays 2026-04-27 10:57:50 +05:30
sudhir e4f42e0ee5 Use bbox anchors for item dimension measurements 2026-04-27 10:49:20 +05:30
sudhir 59779c5bf2 Use mesh bounds for item placement and floorplan 2026-04-27 09:57:05 +05:30
sudhir 45f0867a74 Extract floorplan render logic into editor 2D modules 2026-04-26 23:02:03 +05:30
Aymeric Rabot b3d1f663f6 fix(mcp): use local sqlite scene storage 2026-04-24 13:32:04 -07:00
sudhir 275a42cc7f Simplify paint material compatibility logic 2026-04-25 00:15:29 +05:30
sudhir cb268509ea Invalidate viewer on hover style updates 2026-04-25 00:06:31 +05:30
sudhir d36441fa47 Add hover highlights to paint interactions 2026-04-24 23:29:34 +05:30
sudhir 2b656bcf8b Remove editor hover styles from viewer defaults 2026-04-24 23:05:14 +05:30
sudhir 325f2e4603 Refactor viewer hover styles and remove preview state 2026-04-24 22:49:04 +05:30
sudhir 7297c76204 Use paint icon for material mode 2026-04-24 12:50:05 +05:30
sudhir 83e1c9d1fd Align floorplan drawing with local build coordinates 2026-04-24 12:39:36 +05:30
sudhir a5448a0053 Make material categories horizontally scrollable 2026-04-24 10:43:38 +05:30
sudhir 2876f39876 Refactor paint materials to use category-based compatibility 2026-04-23 12:48:50 +05:30
sudhir 88b2f095f1 Merge branch 'feat/color-picker-tool' of github.com:sudhir9297/editor into feat/color-picker-tool 2026-04-23 10:26:54 +05:30
sudhir 4483957a0d Remove material pickers from side panels 2026-04-23 10:21:33 +05:30
sudhir fb3de8debc Refactor material paint preview handling 2026-04-22 18:16:20 +05:30
Sudhir YadavandGitHub 8fde99e7c9 Merge branch 'main' into feat/color-picker-tool 2026-04-22 17:57:26 +05:30
sudhir 1492e5bd0c Add roof drag controls to the 2D floorplan 2026-04-22 17:24:58 +05:30
sudhir a69591670d Refactor floorplan wall visuals and shared plan helpers 2026-04-22 15:34:22 +05:30
sudhir 87dfdf1b38 Add paint hover previews to viewer 2026-04-22 10:52:35 +05:30
Pascal 4b5c3beadc release: v0.6.0
Bump @pascal-app/core, @pascal-app/viewer, and @pascal-app/editor to 0.6.0.
Update cross-package peer/dev dependency versions.
2026-04-21 20:52:02 +00:00
sudhir 65399731f7 Enable material paint for fence slab and ceiling nodes 2026-04-21 15:19:46 +05:30
sudhir b925cf1e7a Show paint cursor on incompatible clicks 2026-04-21 15:11:46 +05:30
sudhir 5d75e29bc5 Add material paint mode with scrollable palette 2026-04-21 15:00:09 +05:30
sudhir ec393b0c91 Use live snap settings in polygon editor and slab actions 2026-04-21 11:46:57 +05:30
sudhir 53720d664f Align roof and slab dragging to snap targets 2026-04-21 11:41:31 +05:30
sudhir 8ae217502c Add curved fence support 2026-04-21 11:26:49 +05:30
sudhir 5b5b80be61 Support fence endpoint moves and drafting snap 2026-04-21 11:18:54 +05:30
sudhir ffa78f1344 Fix realtime undo updates for wall and fence moves 2026-04-21 11:12:04 +05:30
sudhir 8cf2df1483 Unify material target selection across wall stair and roof 2026-04-20 22:45:56 +05:30
sudhir dd5b6e5e83 Fix slab material reload and wall curve step 2026-04-20 14:13:47 +05:30
sudhir b715e96038 Fix fence UV generation before geometry merge 2026-04-20 13:12:20 +05:30
sudhir dfdeca4aae Refine roof edit selection behavior and panel actions 2026-04-20 13:08:45 +05:30
sudhir bbc351d3a4 Add roof material targets and UV mapping 2026-04-20 12:57:06 +05:30
sudhir 05002a7865 Allow stair side clicks to target side materials 2026-04-20 12:04:43 +05:30
sudhir 4f9b822e54 Add click-targeted stair materials and UV mapping 2026-04-20 12:01:23 +05:30
sudhir df9c4e499f Restrict ground occluder to recessed slabs 2026-04-20 11:25:36 +05:30
sudhir 71ddb7052b Add two-sided wall material targeting 2026-04-20 11:18:20 +05:30
Adrian PerezandClaude Opus 4.7 06d00566f0 docs(mcp): fix residual stale-number references in PR description
Two lines still cited the pre-A2 state (294 tests / 40 files,
"known gaps remain at save_scene / POST boundary"). Corrected
against the actual 302/41 and the Phase 10 A2 closure of those
boundaries via the shared apiGraphSchema.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 21:03:44 +02:00
Adrian PerezandClaude Opus 4.7 7ed34f5b4f docs(mcp): update PR description with post-A2 state (302 tests, 20 commits)
A5 wrote the initial PR description before the A2 security fixes
landed, so it cited 294 tests / 9 commits and listed several now-fixed
items as follow-ups. Updated:

- 294 -> 302 tests (8 new SSRF guard tests in safe-fetch.test.ts)
- 40 -> 41 test files
- 9 -> 20 commits with the actual Phase 5-10 series listed
- Security-notes section: document safeFetch + shared apiGraphSchema
  wiring on both POST and PUT; remove "tracked follow-up" for
  save_scene URL validation (done); add "tracked follow-up" keeps
  same-id write race + auth layer
- Checklist: flip two items from [ ] to [x] for URL validation and
  SSRF protection

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 21:02:39 +02:00
Adrian PerezandClaude Opus 4.7 6ace4bf7c8 docs(mcp): add Phase 10 pre-push audit reports (5 agents)
Five parallel audit agents reviewed the branch before open-sourcing
the PR to pascalorg/editor:

- a1-secrets.md: SAFE TO PUSH. Scanned 176 files / 40,768 diff lines.
  Zero secrets, tokens, API keys, PEM blocks, JWTs, or cookies.
  Only MEDIUM finding: absolute /Users/adrian paths in test-report
  scripts (cosmetic, not security).

- a2-security.md: FOUND 2 HIGH-severity issues, both FIXED in
  commit 8757de0:
  * PUT /api/scenes/[id] still had the loose graphSchema that POST
    got fixed in Phase 8 P4. Shared schema extracted to
    apps/editor/lib/graph-schema.ts so both routes re-validate.
  * photo_to_scene + analyze_floorplan_image + analyze_room_photo
    all did raw fetch(url) on user-supplied URLs - a textbook SSRF
    to 169.254.169.254 cloud metadata. Added safe-fetch.ts with
    private-IP / link-local / .local-hostname denylists, manual
    redirect revalidation, size cap, timeout, env-allowlist.

- a3-code-quality.md: READY FOR REVIEW. Zero production `any`, all
  tools Zod-validated in+out, uniform error handling,
  conventional-commits. Two non-blocking follow-ups: client editor
  components (SceneLoader, SaveButton) have no tests; document
  check_collisions n^2 scaling.

- a4-performance.md: SHIP WITH NOTES. MCP dist 904 KB, Supabase
  lazy-imported (zero editor bundle impact), v0.1 hot paths
  sub-200ms. Flagged: FilesystemSceneStore.index.json O(n) per
  write (fine <1k scenes), concurrency races (documented in P8),
  client render at 5k nodes unverified.

- a5-pr-description.md: polished final PR description that
  corrected stale test counts (294 not 142), disclosed all 5
  cross-cutting surfaces, named the known failures honestly,
  split the checklist, expanded the scope to the real Phase 7
  deliverables.

Overall verdict: READY TO PUSH after the A2 fixes landed. No
blockers remain.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 21:00:02 +02:00
Adrian PerezandClaude Opus 4.7 8757de0c36 fix(mcp,editor): close PUT-route URL bypass + vision-tool SSRF (Phase 10 A2)
Pre-push audit agent A2 flagged two HIGH-severity security issues that
would have shipped in the PR had we not checked:

1. PUT /api/scenes/[id] URL-validation bypass. Phase 8 P4 fixed
   the POST /api/scenes route by replacing a loose z.unknown() graph
   schema with AnyNode superRefine. The fix never made it to the PUT
   handler - an attacker could resubmit the same javascript:/file:///
   payloads via PUT. Fixed by extracting the tight validator into
   apps/editor/lib/graph-schema.ts and sharing it across both routes.

2. SSRF in photo_to_scene / analyze_floorplan_image /
   analyze_room_photo. All three tools called raw fetch(image) on
   user-supplied URLs with no validation - a direct
   http://169.254.169.254/latest/meta-data/ exfil primitive on any
   cloud host. Added packages/mcp/src/lib/safe-fetch.ts that:
   - Blocks loopback (127.0.0.0/8, ::1)
   - Blocks link-local incl. cloud metadata (169.254.0.0/16)
   - Blocks private ranges (10/8, 172.16/12, 192.168/16, fc00::/7)
   - Blocks .local/.internal/.corp hostnames + localhost variants
   - Blocks v4-mapped IPv6 loopback (::ffff:127.0.0.1)
   - Manual redirects (max 3), revalidating the allowlist per hop
   - 20 MB response-size cap (streamed, enforced per-chunk)
   - 10s timeout
   - Optional PASCAL_ALLOWED_ASSET_ORIGINS env allowlist

Tests: 8 new SSRF guard tests, all vision tests still pass, full
suite 302/302.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 20:59:26 +02:00
Adrian PerezandClaude Opus 4.7 08e7b6db71 test(mcp): add populate-gallery script for post-ship demo
Seeds the shared scene store with Casa del Sol + 3 templates + 3 Villa
Azul variants so /scenes can be browsed end-to-end after a fresh
`bun dev` + `pascal-mcp --http` restart.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 20:52:55 +02:00
Adrian PerezandClaude Opus 4.7 f230d9a401 test(mcp): Villa Azul + 10-agent deep verification
Builds a larger, richer house than Casa del Sol via MCP save_scene
(no injection hack), then dispatches 10 parallel verifiers across
schema, geometry, dimensions, openings, HTTP, page render,
parentage, round-trip, spatial, visual.

Villa Azul — 56 nodes, validate_scene=true, 44KB on disk:
- 15x10m building envelope (vs Casa del Sol's 12x8)
- 9 interior zones (master bed/bath, bed 2/3, shared bath,
  living/dining, kitchen, entry hall, corridor)
- 10 doors + 12 windows (all cut successfully)
- 4 exterior zones (pool 8x4 + basin slab at -2m, outdoor kitchen,
  driveway, back patio)
- 5 rail-style fences (vs Casa del Sol's privacy) with 2m entrance gap

Verification: 108 checks, 104 PASS, 4 findings:
- V1 schema: 56/56
- V2 geometry: 7/7 (perimeter closes, interior T-junctions, no
  zone overlaps, fence gap verified)
- V3 dimensions: 13/13 zone areas exact (1 spec mismatch on site
  polygon default, not a build bug)
- V4 openings: 22/22 dimensional fit, surfaced a tool gap in
  cut_opening (no adjacency check) + my build packed too tightly
- V5 HTTP: 10/10 (GET/PUT/PATCH/DELETE/HEAD, If-Match conflicts)
- V6 page: 14/14 (/scene/:id 81KB, /scenes 20KB, 404 fallback)
- V7 parentage: surfaced CROSS_CUTTING §2 site->building->level
  parentId=null (pre-existing in core's loadScene)
- V8 round-trip: 10/10 byte-equal, duplicate_level -> 110 nodes
- V9 spatial: 12/12 (find_nodes, measure, constraints resource)
- V10 visual: HTML fallback (Chrome extension disconnected during
  run); API layer intact

Follow-up tracked: `cut_opening` should check opening-adjacency on
the same wall (minimum gap) to catch tight packing during patch
construction. Currently returns success and relies on the UI to
visualise the overlap.

Live at http://localhost:3002/scene/a6e7919eacbe.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 20:39:08 +02:00
Adrian PerezandClaude Opus 4.7 0b84e7b7b1 fix(mcp,editor): close URL-validation bypasses surfaced by Phase 8 P4
Phase 8 parallel validation flagged two boundaries where malicious URLs
(javascript:, file:, external http:, data:text/html, ...) could be
persisted despite the AssetUrl allowlist added in Phase 7 A7:

1. `save_scene({ includeCurrentScene: false, graph })` — the graph arg
   was treated as opaque (`z.record(z.string(), z.unknown())`) and
   written to the store without re-running AnyNode.safeParse.

2. `POST /api/scenes { graph }` in the editor API — same issue; the
   Zod `graphSchema` accepted anything object-shaped.

Fixes:
- `save-scene.ts`: when `includeCurrentScene === false`, iterate every
  node and run `AnyNode.safeParse`; collect issues and throw
  `McpError(InvalidParams, 'graph_invalid', { errors })` on any
  failure.
- `app/api/scenes/route.ts`: replace `graphSchema` with a structured
  `z.object({ nodes, rootNodeIds, collections? })` + `superRefine`
  that runs `AnyNode.safeParse` on every node. Invalid → 400 with
  detailed issue paths.

Tests:
- Added `save_scene` regression test for the P4 attack
  (item.asset.src = 'javascript:alert(1)') — expected error.
- Fixed the existing `includeCurrentScene=false` test to use a
  schema-compliant site node id (the prior `id: 'root'` now fails
  the AnyNode parse, which is the desired strict behaviour).
- Full suite: 294 pass / 0 fail.

Also adds Phase 8 test-reports/phase8/** (10 agents, ~15 scripts +
markdown reports) documenting the validation run, plus minor biome
cleanups to the Phase 5/7 test artefacts (removed stale
`// biome-ignore` suppression comments that now resolve to the
already-off `noConsole` rule).

Phase 8 result summary (10 parallel agents, stdio MCP transport with
isolated data dirs):
- P1 templates: 18/18 PASS
- P2 variants: 6/7 mutations + determinism + save + combined + error
- P3 locking: 12/12 PASS (MCP + editor HTTP If-Match)
- P4 URL hardening: fixed 2 bypasses (see above)
- P5 photo-to-scene: 6/6 PASS
- P6 Casa del Sol via save_scene: 13/13 PASS
- P7 editor HTTP API: 18/18 PASS
- P8 concurrency: 4/5 PASS, flagged 2 real filesystem-store races
  (expectedVersion CAS gap + .index.json drift under parallel writes)
- P9 edge cases: 13/13 PASS (size cap, slug safety, bad inputs)
- P10 full sweep: 37/37 PASS (30 tools + 4 resources + 3 prompts)

Known follow-ups:
- FilesystemSceneStore needs a proper lockfile / atomic CAS to fix
  the P8 concurrency bugs (low priority: single-writer MCP is the
  typical case).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 20:26:26 +02:00