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>
837 lines
22 KiB
JSON
837 lines
22 KiB
JSON
{
|
|
"nodes": {
|
|
"site_nxji43wtm3aiv7th": {
|
|
"object": "node",
|
|
"id": "site_nxji43wtm3aiv7th",
|
|
"type": "site",
|
|
"parentId": null,
|
|
"visible": true,
|
|
"metadata": {},
|
|
"polygon": {
|
|
"type": "polygon",
|
|
"points": [[-15, -15], [15, -15], [15, 15], [-15, 15]]
|
|
},
|
|
"children": [
|
|
{
|
|
"object": "node",
|
|
"id": "building_16mw8oy88f952is9",
|
|
"type": "building",
|
|
"parentId": null,
|
|
"visible": true,
|
|
"metadata": {},
|
|
"children": ["level_3jbpcuma0wfwclex"],
|
|
"position": [0, 0, 0],
|
|
"rotation": [0, 0, 0]
|
|
}
|
|
]
|
|
},
|
|
"building_16mw8oy88f952is9": {
|
|
"object": "node",
|
|
"id": "building_16mw8oy88f952is9",
|
|
"type": "building",
|
|
"parentId": null,
|
|
"visible": true,
|
|
"metadata": {},
|
|
"children": ["level_3jbpcuma0wfwclex"],
|
|
"position": [0, 0, 0],
|
|
"rotation": [0, 0, 0]
|
|
},
|
|
"level_3jbpcuma0wfwclex": {
|
|
"object": "node",
|
|
"id": "level_3jbpcuma0wfwclex",
|
|
"type": "level",
|
|
"parentId": null,
|
|
"visible": true,
|
|
"metadata": {},
|
|
"children": [
|
|
"wall_j3ymyd8zrn1tm3vw",
|
|
"wall_ch18gs2ztca3ev6w",
|
|
"wall_5vkgxbr2yy7g73ne",
|
|
"wall_kgzojan8e7v59e98",
|
|
"wall_3jnpbahwg9lxy986",
|
|
"wall_ovunx8saqwfu1v4v",
|
|
"wall_zutd5kdbx2arrg9h",
|
|
"wall_x0pcifb7x4glmarr",
|
|
"wall_f7kmekmgvmfsrm7o",
|
|
"zone_o7ke6p48ne5vca23",
|
|
"zone_xqv8a3g282kfsqni",
|
|
"zone_9cbw5gy7huqn00kn",
|
|
"zone_4x1y6af3q099sequ",
|
|
"zone_dftxlw40a4iwnqpt",
|
|
"zone_2qu75mqpfvty8d1q",
|
|
"zone_92x5t8808vyw1ik0",
|
|
"zone_lnki9rxnoyq72rwi",
|
|
"slab_rfyzzvcxlkbgif1w",
|
|
"fence_rj9vb67pvbkxj291",
|
|
"fence_4yf9yt0x8i27l8ol",
|
|
"fence_b8d9n2j3987egkq4",
|
|
"fence_7v9k8hfa4gejy8mb",
|
|
"fence_6mosl7txfxj0wxyq",
|
|
"zone_6l4ls8mr4rtfvsye"
|
|
],
|
|
"level": 0
|
|
},
|
|
"wall_j3ymyd8zrn1tm3vw": {
|
|
"object": "node",
|
|
"id": "wall_j3ymyd8zrn1tm3vw",
|
|
"type": "wall",
|
|
"parentId": "level_3jbpcuma0wfwclex",
|
|
"visible": true,
|
|
"metadata": {},
|
|
"children": [
|
|
"door_u3esm5o28gjglczx",
|
|
"door_d83emijui1hbi4ai",
|
|
"window_j75zxpkawiriwu3n",
|
|
"window_3ow9tht3fymvnasw"
|
|
],
|
|
"thickness": 0.2,
|
|
"height": 2.7,
|
|
"start": [-8, 4],
|
|
"end": [4, 4],
|
|
"frontSide": "unknown",
|
|
"backSide": "unknown"
|
|
},
|
|
"wall_ch18gs2ztca3ev6w": {
|
|
"object": "node",
|
|
"id": "wall_ch18gs2ztca3ev6w",
|
|
"type": "wall",
|
|
"parentId": "level_3jbpcuma0wfwclex",
|
|
"visible": true,
|
|
"metadata": {},
|
|
"children": ["door_hf6glt3wf2yrtbez", "window_ge40ad7xouig550s"],
|
|
"thickness": 0.2,
|
|
"height": 2.7,
|
|
"start": [-8, -4],
|
|
"end": [4, -4],
|
|
"frontSide": "unknown",
|
|
"backSide": "unknown"
|
|
},
|
|
"wall_5vkgxbr2yy7g73ne": {
|
|
"object": "node",
|
|
"id": "wall_5vkgxbr2yy7g73ne",
|
|
"type": "wall",
|
|
"parentId": "level_3jbpcuma0wfwclex",
|
|
"visible": true,
|
|
"metadata": {},
|
|
"children": ["window_5cp5kjonpq0pf741"],
|
|
"thickness": 0.2,
|
|
"height": 2.7,
|
|
"start": [-8, -4],
|
|
"end": [-8, 4],
|
|
"frontSide": "unknown",
|
|
"backSide": "unknown"
|
|
},
|
|
"wall_kgzojan8e7v59e98": {
|
|
"object": "node",
|
|
"id": "wall_kgzojan8e7v59e98",
|
|
"type": "wall",
|
|
"parentId": "level_3jbpcuma0wfwclex",
|
|
"visible": true,
|
|
"metadata": {},
|
|
"children": ["window_rma26zrn7dkanen3", "window_sp6a94rwh54afdnj"],
|
|
"thickness": 0.2,
|
|
"height": 2.7,
|
|
"start": [4, -4],
|
|
"end": [4, 4],
|
|
"frontSide": "unknown",
|
|
"backSide": "unknown"
|
|
},
|
|
"wall_3jnpbahwg9lxy986": {
|
|
"object": "node",
|
|
"id": "wall_3jnpbahwg9lxy986",
|
|
"type": "wall",
|
|
"parentId": "level_3jbpcuma0wfwclex",
|
|
"visible": true,
|
|
"metadata": {},
|
|
"children": [],
|
|
"thickness": 0.2,
|
|
"height": 2.7,
|
|
"start": [-1, 0],
|
|
"end": [-1, 4],
|
|
"frontSide": "unknown",
|
|
"backSide": "unknown"
|
|
},
|
|
"wall_ovunx8saqwfu1v4v": {
|
|
"object": "node",
|
|
"id": "wall_ovunx8saqwfu1v4v",
|
|
"type": "wall",
|
|
"parentId": "level_3jbpcuma0wfwclex",
|
|
"visible": true,
|
|
"metadata": {},
|
|
"children": ["door_ysujgio81ptoofe7"],
|
|
"thickness": 0.2,
|
|
"height": 2.7,
|
|
"start": [-1, -4],
|
|
"end": [-1, 0],
|
|
"frontSide": "unknown",
|
|
"backSide": "unknown"
|
|
},
|
|
"wall_zutd5kdbx2arrg9h": {
|
|
"object": "node",
|
|
"id": "wall_zutd5kdbx2arrg9h",
|
|
"type": "wall",
|
|
"parentId": "level_3jbpcuma0wfwclex",
|
|
"visible": true,
|
|
"metadata": {},
|
|
"children": ["door_dwn4l10ctn9uqibm"],
|
|
"thickness": 0.2,
|
|
"height": 2.7,
|
|
"start": [-4, -4],
|
|
"end": [-4, 0],
|
|
"frontSide": "unknown",
|
|
"backSide": "unknown"
|
|
},
|
|
"wall_x0pcifb7x4glmarr": {
|
|
"object": "node",
|
|
"id": "wall_x0pcifb7x4glmarr",
|
|
"type": "wall",
|
|
"parentId": "level_3jbpcuma0wfwclex",
|
|
"visible": true,
|
|
"metadata": {},
|
|
"children": [],
|
|
"thickness": 0.2,
|
|
"height": 2.7,
|
|
"start": [-4, -1],
|
|
"end": [-1, -1],
|
|
"frontSide": "unknown",
|
|
"backSide": "unknown"
|
|
},
|
|
"wall_f7kmekmgvmfsrm7o": {
|
|
"object": "node",
|
|
"id": "wall_f7kmekmgvmfsrm7o",
|
|
"type": "wall",
|
|
"parentId": "level_3jbpcuma0wfwclex",
|
|
"visible": true,
|
|
"metadata": {},
|
|
"children": ["door_gclhf676wdn8643p"],
|
|
"thickness": 0.2,
|
|
"height": 2.7,
|
|
"start": [-4, -2],
|
|
"end": [-1, -2],
|
|
"frontSide": "unknown",
|
|
"backSide": "unknown"
|
|
},
|
|
"zone_o7ke6p48ne5vca23": {
|
|
"object": "node",
|
|
"id": "zone_o7ke6p48ne5vca23",
|
|
"type": "zone",
|
|
"name": "living-dining",
|
|
"parentId": "level_3jbpcuma0wfwclex",
|
|
"visible": true,
|
|
"metadata": {},
|
|
"polygon": [[-8, 0], [-1, 0], [-1, 4], [-8, 4]],
|
|
"color": "#3b82f6"
|
|
},
|
|
"zone_xqv8a3g282kfsqni": {
|
|
"object": "node",
|
|
"id": "zone_xqv8a3g282kfsqni",
|
|
"type": "zone",
|
|
"name": "kitchen",
|
|
"parentId": "level_3jbpcuma0wfwclex",
|
|
"visible": true,
|
|
"metadata": {},
|
|
"polygon": [[-1, 0], [4, 0], [4, 4], [-1, 4]],
|
|
"color": "#3b82f6"
|
|
},
|
|
"zone_9cbw5gy7huqn00kn": {
|
|
"object": "node",
|
|
"id": "zone_9cbw5gy7huqn00kn",
|
|
"type": "zone",
|
|
"name": "bedroom-2",
|
|
"parentId": "level_3jbpcuma0wfwclex",
|
|
"visible": true,
|
|
"metadata": {},
|
|
"polygon": [[-8, -4], [-4, -4], [-4, 0], [-8, 0]],
|
|
"color": "#3b82f6"
|
|
},
|
|
"zone_4x1y6af3q099sequ": {
|
|
"object": "node",
|
|
"id": "zone_4x1y6af3q099sequ",
|
|
"type": "zone",
|
|
"name": "hallway",
|
|
"parentId": "level_3jbpcuma0wfwclex",
|
|
"visible": true,
|
|
"metadata": {},
|
|
"polygon": [[-4, -2], [-1, -2], [-1, -1], [-4, -1]],
|
|
"color": "#3b82f6"
|
|
},
|
|
"zone_dftxlw40a4iwnqpt": {
|
|
"object": "node",
|
|
"id": "zone_dftxlw40a4iwnqpt",
|
|
"type": "zone",
|
|
"name": "bathroom-2",
|
|
"parentId": "level_3jbpcuma0wfwclex",
|
|
"visible": true,
|
|
"metadata": {},
|
|
"polygon": [[-4, -4], [-1, -4], [-1, -2], [-4, -2]],
|
|
"color": "#3b82f6"
|
|
},
|
|
"zone_2qu75mqpfvty8d1q": {
|
|
"object": "node",
|
|
"id": "zone_2qu75mqpfvty8d1q",
|
|
"type": "zone",
|
|
"name": "bathroom-1",
|
|
"parentId": "level_3jbpcuma0wfwclex",
|
|
"visible": true,
|
|
"metadata": {},
|
|
"polygon": [[-4, -1], [-1, -1], [-1, 0], [-4, 0]],
|
|
"color": "#3b82f6"
|
|
},
|
|
"zone_92x5t8808vyw1ik0": {
|
|
"object": "node",
|
|
"id": "zone_92x5t8808vyw1ik0",
|
|
"type": "zone",
|
|
"name": "master-bedroom",
|
|
"parentId": "level_3jbpcuma0wfwclex",
|
|
"visible": true,
|
|
"metadata": {},
|
|
"polygon": [[-1, -4], [4, -4], [4, 0], [-1, 0]],
|
|
"color": "#3b82f6"
|
|
},
|
|
"door_u3esm5o28gjglczx": {
|
|
"object": "node",
|
|
"id": "door_u3esm5o28gjglczx",
|
|
"type": "door",
|
|
"parentId": "wall_j3ymyd8zrn1tm3vw",
|
|
"visible": true,
|
|
"metadata": {},
|
|
"position": [0.2, 1.05, 0],
|
|
"rotation": [0, 0, 0],
|
|
"wallId": "wall_j3ymyd8zrn1tm3vw",
|
|
"width": 0.9,
|
|
"height": 2.1,
|
|
"frameThickness": 0.05,
|
|
"frameDepth": 0.07,
|
|
"threshold": true,
|
|
"thresholdHeight": 0.02,
|
|
"hingesSide": "left",
|
|
"swingDirection": "inward",
|
|
"segments": [
|
|
{
|
|
"type": "panel",
|
|
"heightRatio": 0.4,
|
|
"columnRatios": [1],
|
|
"dividerThickness": 0.03,
|
|
"panelDepth": 0.01,
|
|
"panelInset": 0.04
|
|
},
|
|
{
|
|
"type": "panel",
|
|
"heightRatio": 0.6,
|
|
"columnRatios": [1],
|
|
"dividerThickness": 0.03,
|
|
"panelDepth": 0.01,
|
|
"panelInset": 0.04
|
|
}
|
|
],
|
|
"handle": true,
|
|
"handleHeight": 1.05,
|
|
"handleSide": "right",
|
|
"contentPadding": [0.04, 0.04],
|
|
"doorCloser": false,
|
|
"panicBar": false,
|
|
"panicBarHeight": 1
|
|
},
|
|
"door_d83emijui1hbi4ai": {
|
|
"object": "node",
|
|
"id": "door_d83emijui1hbi4ai",
|
|
"type": "door",
|
|
"parentId": "wall_j3ymyd8zrn1tm3vw",
|
|
"visible": true,
|
|
"metadata": {},
|
|
"position": [0.75, 1.05, 0],
|
|
"rotation": [0, 0, 0],
|
|
"wallId": "wall_j3ymyd8zrn1tm3vw",
|
|
"width": 2.2,
|
|
"height": 2.1,
|
|
"frameThickness": 0.05,
|
|
"frameDepth": 0.07,
|
|
"threshold": true,
|
|
"thresholdHeight": 0.02,
|
|
"hingesSide": "left",
|
|
"swingDirection": "inward",
|
|
"segments": [
|
|
{
|
|
"type": "panel",
|
|
"heightRatio": 0.4,
|
|
"columnRatios": [1],
|
|
"dividerThickness": 0.03,
|
|
"panelDepth": 0.01,
|
|
"panelInset": 0.04
|
|
},
|
|
{
|
|
"type": "panel",
|
|
"heightRatio": 0.6,
|
|
"columnRatios": [1],
|
|
"dividerThickness": 0.03,
|
|
"panelDepth": 0.01,
|
|
"panelInset": 0.04
|
|
}
|
|
],
|
|
"handle": true,
|
|
"handleHeight": 1.05,
|
|
"handleSide": "right",
|
|
"contentPadding": [0.04, 0.04],
|
|
"doorCloser": false,
|
|
"panicBar": false,
|
|
"panicBarHeight": 1
|
|
},
|
|
"door_hf6glt3wf2yrtbez": {
|
|
"object": "node",
|
|
"id": "door_hf6glt3wf2yrtbez",
|
|
"type": "door",
|
|
"parentId": "wall_ch18gs2ztca3ev6w",
|
|
"visible": true,
|
|
"metadata": {},
|
|
"position": [0.65, 1.05, 0],
|
|
"rotation": [0, 0, 0],
|
|
"wallId": "wall_ch18gs2ztca3ev6w",
|
|
"width": 0.9,
|
|
"height": 2.1,
|
|
"frameThickness": 0.05,
|
|
"frameDepth": 0.07,
|
|
"threshold": true,
|
|
"thresholdHeight": 0.02,
|
|
"hingesSide": "left",
|
|
"swingDirection": "inward",
|
|
"segments": [
|
|
{
|
|
"type": "panel",
|
|
"heightRatio": 0.4,
|
|
"columnRatios": [1],
|
|
"dividerThickness": 0.03,
|
|
"panelDepth": 0.01,
|
|
"panelInset": 0.04
|
|
},
|
|
{
|
|
"type": "panel",
|
|
"heightRatio": 0.6,
|
|
"columnRatios": [1],
|
|
"dividerThickness": 0.03,
|
|
"panelDepth": 0.01,
|
|
"panelInset": 0.04
|
|
}
|
|
],
|
|
"handle": true,
|
|
"handleHeight": 1.05,
|
|
"handleSide": "right",
|
|
"contentPadding": [0.04, 0.04],
|
|
"doorCloser": false,
|
|
"panicBar": false,
|
|
"panicBarHeight": 1
|
|
},
|
|
"door_ysujgio81ptoofe7": {
|
|
"object": "node",
|
|
"id": "door_ysujgio81ptoofe7",
|
|
"type": "door",
|
|
"parentId": "wall_ovunx8saqwfu1v4v",
|
|
"visible": true,
|
|
"metadata": {},
|
|
"position": [0.3, 1.05, 0],
|
|
"rotation": [0, 0, 0],
|
|
"wallId": "wall_ovunx8saqwfu1v4v",
|
|
"width": 0.8,
|
|
"height": 2.1,
|
|
"frameThickness": 0.05,
|
|
"frameDepth": 0.07,
|
|
"threshold": true,
|
|
"thresholdHeight": 0.02,
|
|
"hingesSide": "left",
|
|
"swingDirection": "inward",
|
|
"segments": [
|
|
{
|
|
"type": "panel",
|
|
"heightRatio": 0.4,
|
|
"columnRatios": [1],
|
|
"dividerThickness": 0.03,
|
|
"panelDepth": 0.01,
|
|
"panelInset": 0.04
|
|
},
|
|
{
|
|
"type": "panel",
|
|
"heightRatio": 0.6,
|
|
"columnRatios": [1],
|
|
"dividerThickness": 0.03,
|
|
"panelDepth": 0.01,
|
|
"panelInset": 0.04
|
|
}
|
|
],
|
|
"handle": true,
|
|
"handleHeight": 1.05,
|
|
"handleSide": "right",
|
|
"contentPadding": [0.04, 0.04],
|
|
"doorCloser": false,
|
|
"panicBar": false,
|
|
"panicBarHeight": 1
|
|
},
|
|
"door_dwn4l10ctn9uqibm": {
|
|
"object": "node",
|
|
"id": "door_dwn4l10ctn9uqibm",
|
|
"type": "door",
|
|
"parentId": "wall_zutd5kdbx2arrg9h",
|
|
"visible": true,
|
|
"metadata": {},
|
|
"position": [0.5, 1.05, 0],
|
|
"rotation": [0, 0, 0],
|
|
"wallId": "wall_zutd5kdbx2arrg9h",
|
|
"width": 0.8,
|
|
"height": 2.1,
|
|
"frameThickness": 0.05,
|
|
"frameDepth": 0.07,
|
|
"threshold": true,
|
|
"thresholdHeight": 0.02,
|
|
"hingesSide": "left",
|
|
"swingDirection": "inward",
|
|
"segments": [
|
|
{
|
|
"type": "panel",
|
|
"heightRatio": 0.4,
|
|
"columnRatios": [1],
|
|
"dividerThickness": 0.03,
|
|
"panelDepth": 0.01,
|
|
"panelInset": 0.04
|
|
},
|
|
{
|
|
"type": "panel",
|
|
"heightRatio": 0.6,
|
|
"columnRatios": [1],
|
|
"dividerThickness": 0.03,
|
|
"panelDepth": 0.01,
|
|
"panelInset": 0.04
|
|
}
|
|
],
|
|
"handle": true,
|
|
"handleHeight": 1.05,
|
|
"handleSide": "right",
|
|
"contentPadding": [0.04, 0.04],
|
|
"doorCloser": false,
|
|
"panicBar": false,
|
|
"panicBarHeight": 1
|
|
},
|
|
"door_gclhf676wdn8643p": {
|
|
"object": "node",
|
|
"id": "door_gclhf676wdn8643p",
|
|
"type": "door",
|
|
"parentId": "wall_f7kmekmgvmfsrm7o",
|
|
"visible": true,
|
|
"metadata": {},
|
|
"position": [0.5, 1, 0],
|
|
"rotation": [0, 0, 0],
|
|
"wallId": "wall_f7kmekmgvmfsrm7o",
|
|
"width": 0.7,
|
|
"height": 2,
|
|
"frameThickness": 0.05,
|
|
"frameDepth": 0.07,
|
|
"threshold": true,
|
|
"thresholdHeight": 0.02,
|
|
"hingesSide": "left",
|
|
"swingDirection": "inward",
|
|
"segments": [
|
|
{
|
|
"type": "panel",
|
|
"heightRatio": 0.4,
|
|
"columnRatios": [1],
|
|
"dividerThickness": 0.03,
|
|
"panelDepth": 0.01,
|
|
"panelInset": 0.04
|
|
},
|
|
{
|
|
"type": "panel",
|
|
"heightRatio": 0.6,
|
|
"columnRatios": [1],
|
|
"dividerThickness": 0.03,
|
|
"panelDepth": 0.01,
|
|
"panelInset": 0.04
|
|
}
|
|
],
|
|
"handle": true,
|
|
"handleHeight": 1.05,
|
|
"handleSide": "right",
|
|
"contentPadding": [0.04, 0.04],
|
|
"doorCloser": false,
|
|
"panicBar": false,
|
|
"panicBarHeight": 1
|
|
},
|
|
"window_j75zxpkawiriwu3n": {
|
|
"object": "node",
|
|
"id": "window_j75zxpkawiriwu3n",
|
|
"type": "window",
|
|
"parentId": "wall_j3ymyd8zrn1tm3vw",
|
|
"visible": true,
|
|
"metadata": {},
|
|
"position": [0.3, 0.7, 0],
|
|
"rotation": [0, 0, 0],
|
|
"wallId": "wall_j3ymyd8zrn1tm3vw",
|
|
"width": 2,
|
|
"height": 1.4,
|
|
"frameThickness": 0.05,
|
|
"frameDepth": 0.07,
|
|
"columnRatios": [1],
|
|
"rowRatios": [1],
|
|
"columnDividerThickness": 0.03,
|
|
"rowDividerThickness": 0.03,
|
|
"sill": true,
|
|
"sillDepth": 0.08,
|
|
"sillThickness": 0.03
|
|
},
|
|
"window_3ow9tht3fymvnasw": {
|
|
"object": "node",
|
|
"id": "window_3ow9tht3fymvnasw",
|
|
"type": "window",
|
|
"parentId": "wall_j3ymyd8zrn1tm3vw",
|
|
"visible": true,
|
|
"metadata": {},
|
|
"position": [0.45, 0.7, 0],
|
|
"rotation": [0, 0, 0],
|
|
"wallId": "wall_j3ymyd8zrn1tm3vw",
|
|
"width": 1.4,
|
|
"height": 1.4,
|
|
"frameThickness": 0.05,
|
|
"frameDepth": 0.07,
|
|
"columnRatios": [1],
|
|
"rowRatios": [1],
|
|
"columnDividerThickness": 0.03,
|
|
"rowDividerThickness": 0.03,
|
|
"sill": true,
|
|
"sillDepth": 0.08,
|
|
"sillThickness": 0.03
|
|
},
|
|
"window_5cp5kjonpq0pf741": {
|
|
"object": "node",
|
|
"id": "window_5cp5kjonpq0pf741",
|
|
"type": "window",
|
|
"parentId": "wall_5vkgxbr2yy7g73ne",
|
|
"visible": true,
|
|
"metadata": {},
|
|
"position": [0.25, 0.55, 0],
|
|
"rotation": [0, 0, 0],
|
|
"wallId": "wall_5vkgxbr2yy7g73ne",
|
|
"width": 1,
|
|
"height": 1.1,
|
|
"frameThickness": 0.05,
|
|
"frameDepth": 0.07,
|
|
"columnRatios": [1],
|
|
"rowRatios": [1],
|
|
"columnDividerThickness": 0.03,
|
|
"rowDividerThickness": 0.03,
|
|
"sill": true,
|
|
"sillDepth": 0.08,
|
|
"sillThickness": 0.03
|
|
},
|
|
"window_rma26zrn7dkanen3": {
|
|
"object": "node",
|
|
"id": "window_rma26zrn7dkanen3",
|
|
"type": "window",
|
|
"parentId": "wall_kgzojan8e7v59e98",
|
|
"visible": true,
|
|
"metadata": {},
|
|
"position": [0.25, 0.7, 0],
|
|
"rotation": [0, 0, 0],
|
|
"wallId": "wall_kgzojan8e7v59e98",
|
|
"width": 1.4,
|
|
"height": 1.4,
|
|
"frameThickness": 0.05,
|
|
"frameDepth": 0.07,
|
|
"columnRatios": [1],
|
|
"rowRatios": [1],
|
|
"columnDividerThickness": 0.03,
|
|
"rowDividerThickness": 0.03,
|
|
"sill": true,
|
|
"sillDepth": 0.08,
|
|
"sillThickness": 0.03
|
|
},
|
|
"window_sp6a94rwh54afdnj": {
|
|
"object": "node",
|
|
"id": "window_sp6a94rwh54afdnj",
|
|
"type": "window",
|
|
"parentId": "wall_kgzojan8e7v59e98",
|
|
"visible": true,
|
|
"metadata": {},
|
|
"position": [0.75, 0.7, 0],
|
|
"rotation": [0, 0, 0],
|
|
"wallId": "wall_kgzojan8e7v59e98",
|
|
"width": 1.4,
|
|
"height": 1.4,
|
|
"frameThickness": 0.05,
|
|
"frameDepth": 0.07,
|
|
"columnRatios": [1],
|
|
"rowRatios": [1],
|
|
"columnDividerThickness": 0.03,
|
|
"rowDividerThickness": 0.03,
|
|
"sill": true,
|
|
"sillDepth": 0.08,
|
|
"sillThickness": 0.03
|
|
},
|
|
"window_ge40ad7xouig550s": {
|
|
"object": "node",
|
|
"id": "window_ge40ad7xouig550s",
|
|
"type": "window",
|
|
"parentId": "wall_ch18gs2ztca3ev6w",
|
|
"visible": true,
|
|
"metadata": {},
|
|
"position": [0.3, 0.3, 0],
|
|
"rotation": [0, 0, 0],
|
|
"wallId": "wall_ch18gs2ztca3ev6w",
|
|
"width": 0.8,
|
|
"height": 0.6,
|
|
"frameThickness": 0.05,
|
|
"frameDepth": 0.07,
|
|
"columnRatios": [1],
|
|
"rowRatios": [1],
|
|
"columnDividerThickness": 0.03,
|
|
"rowDividerThickness": 0.03,
|
|
"sill": true,
|
|
"sillDepth": 0.08,
|
|
"sillThickness": 0.03
|
|
},
|
|
"zone_lnki9rxnoyq72rwi": {
|
|
"object": "node",
|
|
"id": "zone_lnki9rxnoyq72rwi",
|
|
"type": "zone",
|
|
"name": "pool",
|
|
"parentId": "level_3jbpcuma0wfwclex",
|
|
"visible": true,
|
|
"metadata": {
|
|
"kind": "pool",
|
|
"depthM": 1.8,
|
|
"finish": "tile"
|
|
},
|
|
"polygon": [[5, -1.5], [10, -1.5], [10, 1.5], [5, 1.5]],
|
|
"color": "#3b82f6"
|
|
},
|
|
"slab_rfyzzvcxlkbgif1w": {
|
|
"object": "node",
|
|
"id": "slab_rfyzzvcxlkbgif1w",
|
|
"type": "slab",
|
|
"parentId": "level_3jbpcuma0wfwclex",
|
|
"visible": true,
|
|
"metadata": {},
|
|
"polygon": [[5, -1.5], [10, -1.5], [10, 1.5], [5, 1.5]],
|
|
"holes": [],
|
|
"holeMetadata": [],
|
|
"elevation": -1.8,
|
|
"autoFromWalls": false
|
|
},
|
|
"fence_rj9vb67pvbkxj291": {
|
|
"object": "node",
|
|
"id": "fence_rj9vb67pvbkxj291",
|
|
"type": "fence",
|
|
"parentId": "level_3jbpcuma0wfwclex",
|
|
"visible": true,
|
|
"metadata": {},
|
|
"start": [-10, 7.5],
|
|
"end": [-1, 7.5],
|
|
"height": 1.8,
|
|
"thickness": 0.08,
|
|
"baseHeight": 0.22,
|
|
"postSpacing": 2,
|
|
"postSize": 0.1,
|
|
"topRailHeight": 0.04,
|
|
"groundClearance": 0,
|
|
"edgeInset": 0.015,
|
|
"baseStyle": "grounded",
|
|
"color": "#ffffff",
|
|
"style": "privacy"
|
|
},
|
|
"fence_4yf9yt0x8i27l8ol": {
|
|
"object": "node",
|
|
"id": "fence_4yf9yt0x8i27l8ol",
|
|
"type": "fence",
|
|
"parentId": "level_3jbpcuma0wfwclex",
|
|
"visible": true,
|
|
"metadata": {},
|
|
"start": [1, 7.5],
|
|
"end": [10, 7.5],
|
|
"height": 1.8,
|
|
"thickness": 0.08,
|
|
"baseHeight": 0.22,
|
|
"postSpacing": 2,
|
|
"postSize": 0.1,
|
|
"topRailHeight": 0.04,
|
|
"groundClearance": 0,
|
|
"edgeInset": 0.015,
|
|
"baseStyle": "grounded",
|
|
"color": "#ffffff",
|
|
"style": "privacy"
|
|
},
|
|
"fence_b8d9n2j3987egkq4": {
|
|
"object": "node",
|
|
"id": "fence_b8d9n2j3987egkq4",
|
|
"type": "fence",
|
|
"parentId": "level_3jbpcuma0wfwclex",
|
|
"visible": true,
|
|
"metadata": {},
|
|
"start": [10, 7.5],
|
|
"end": [10, -7.5],
|
|
"height": 1.8,
|
|
"thickness": 0.08,
|
|
"baseHeight": 0.22,
|
|
"postSpacing": 2,
|
|
"postSize": 0.1,
|
|
"topRailHeight": 0.04,
|
|
"groundClearance": 0,
|
|
"edgeInset": 0.015,
|
|
"baseStyle": "grounded",
|
|
"color": "#ffffff",
|
|
"style": "privacy"
|
|
},
|
|
"fence_7v9k8hfa4gejy8mb": {
|
|
"object": "node",
|
|
"id": "fence_7v9k8hfa4gejy8mb",
|
|
"type": "fence",
|
|
"parentId": "level_3jbpcuma0wfwclex",
|
|
"visible": true,
|
|
"metadata": {},
|
|
"start": [10, -7.5],
|
|
"end": [-10, -7.5],
|
|
"height": 1.8,
|
|
"thickness": 0.08,
|
|
"baseHeight": 0.22,
|
|
"postSpacing": 2,
|
|
"postSize": 0.1,
|
|
"topRailHeight": 0.04,
|
|
"groundClearance": 0,
|
|
"edgeInset": 0.015,
|
|
"baseStyle": "grounded",
|
|
"color": "#ffffff",
|
|
"style": "privacy"
|
|
},
|
|
"fence_6mosl7txfxj0wxyq": {
|
|
"object": "node",
|
|
"id": "fence_6mosl7txfxj0wxyq",
|
|
"type": "fence",
|
|
"parentId": "level_3jbpcuma0wfwclex",
|
|
"visible": true,
|
|
"metadata": {},
|
|
"start": [-10, -7.5],
|
|
"end": [-10, 7.5],
|
|
"height": 1.8,
|
|
"thickness": 0.08,
|
|
"baseHeight": 0.22,
|
|
"postSpacing": 2,
|
|
"postSize": 0.1,
|
|
"topRailHeight": 0.04,
|
|
"groundClearance": 0,
|
|
"edgeInset": 0.015,
|
|
"baseStyle": "grounded",
|
|
"color": "#ffffff",
|
|
"style": "privacy"
|
|
},
|
|
"zone_6l4ls8mr4rtfvsye": {
|
|
"object": "node",
|
|
"id": "zone_6l4ls8mr4rtfvsye",
|
|
"type": "zone",
|
|
"name": "garden",
|
|
"parentId": "level_3jbpcuma0wfwclex",
|
|
"visible": true,
|
|
"metadata": {
|
|
"kind": "garden"
|
|
},
|
|
"polygon": [[-10, -7.5], [10, -7.5], [10, 7.5], [-10, 7.5]],
|
|
"color": "#3b82f6"
|
|
}
|
|
},
|
|
"rootNodeIds": ["site_nxji43wtm3aiv7th"],
|
|
"collections": {}
|
|
}
|