Render plan and fractal scene derive directories from Assembly.Location; the in-memory load emptied it.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Exception messages carry raw paths and every console write escapes them once (Printable iterates runes: astral format characters and lone surrogates). AquariumHost reports startup refusals escaped. IOException from link resolution becomes InvalidOperationException. Managed assemblies load from memory so the temp dir can be deleted on Windows. The newline-in-file-name test is skipped on Windows.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Review (Heimdall): a path outside the pinned root (as resolved or as given) is refused by
string comparison before File.Exists or any link is followed; the trusted-root setting is
its own small type that takes the environment variable once, caches it and refuses blank
values; Printable also escapes backslash, format characters (bidi, zero-width) and the
line and paragraph separators; dev-watch matches the host ack by the unique slot leaf with
doubled backslashes; dev-reload prunes live-slots and rejects stale reopen state up front.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Review (Heimdall): dev scripts keep slots and live-slots under artifacts/dev-reload/assemblies
and pass that as the root, not the whole dev root; --client-trusted-root refuses an empty or
missing value and the environment variable is cleared on every path; the UNC/fully-qualified
string rule runs before File.Exists on a pointer target; control characters are escaped in
every logged path.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Review (Heimdall): the root is resolved once at construction and a volume root
is refused and the effective root logged; the loader loads and records the
resolved final path (so a pointer naming a link does not reload every poll);
dependency and native-library resolution go through the same check; the
AQUARIUM_CLIENT_TRUSTED_ROOT variable is cleared after reading. Tests: UNC in any
separator mix, volume root, pinned root, resolved-path storage, junction and
symlink tests that report an explicit skip instead of passing silently.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
dev-watch writes the reload pointer under artifacts/dev-reload/live-slots, a
sibling of slots; a slot-directory root refused every watch reload and the
reopen path. Test: a sibling directory loads inside an explicit root, not under
the default root, and an outside assembly is still refused.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The reload pointer, and the initial --client-assembly, named any path and ran
whatever it held in the engine process. Reload now refuses relative and UNC
paths and anything that, links followed, lies outside the trusted root
(--client-trusted-root or AQUARIUM_CLIENT_TRUSTED_ROOT; default: the directory
of the initial assembly). dev-reload passes its slot directory as the root.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>