Adds Framework/ViewRenderer.wsc (WscMvc.ViewRenderer), loading separate
.html templates and substituting {{Key}} placeholders with HTML-encoded
values from a Scripting.Dictionary. Wires /hello through the new pipeline
(HomeController -> Application -> ViewRenderer -> Views/Home.html) while
preserving the exact pre-M4 response body, so the M1 acceptance test
doubles as a live regression check for the render pipeline.
Views/ is unreachable over HTTP by the same physical-separation guarantee
already used for Framework/ and Controllers/ (sibling of public/, never
inside it) - verified directly, not assumed.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
At Daniel's explicit direction: /self-test moves off the production site
entirely, onto a second, separate IIS site/app.
- test-app/public/: own site (WscMvcTests, *:8091), own web.config (routes
only /self-test), own logs/ - genuinely isolated from production traffic
- Default.asp duplicated into test-app/public/ (intentionally byte-
identical - the bootstrap is fully generic, IIS just requires each site
to have its own physical files; documented 'keep in sync' in both copies)
- No framework/business-logic duplication: both sites share the exact same
registered Framework/Controllers COM components. Application.wsc's
/self-test route case is unchanged; only removed the production site's
web.config rewrite rule that used to expose it there
- production public/web.config: dropped /self-test rewrite rule; GET
/self-test on production now plain 404 (nothing routes there)
- tools/Setup-Site.ps1: now automates the logs/ IIS_IUSRS ACL grant
(previously a manual one-off command), scoped per-site; also hardened
with ='Stop' + a PhysicalPath pre-check after
finding it silently continued past a real New-Website failure
- tests/Test-Http.ps1: production-only now (checks /hello + confirms
/self-test is genuinely unreachable there); tests/run-self-test.sh
points at the new WscMvcTests site
- Verified both sites end-to-end: correct routes, correct 404s for
cross-site/Framework access, separate log files, idempotent Setup-Site.ps1
reruns for both sites
- SPEC.md, docs/ARCHITECTURE.md, docs/DECISIONS.md, docs/TEST-RESULTS.md,
README.md updated to match; README also brought current after being
stale since M1
At Daniel's explicit direction (overrides SPEC.md $5's originally fixed
tree, updated in place per AGENTS.md precedence rules):
- Default.asp + web.config moved into public/; Framework/Controllers/
tests/tools/docs/logs are now siblings entirely outside the served root
- physical separation, not a web.config rule, is what protects them now
- IIS site physicalPath changed to C:\Projects\wsc-mvc\public
- enableParentPaths enabled, scoped to just this site via
`appcmd ... /commit:apphost` (writes a <location> block in
applicationHost.config, not a machine-wide unlock of the locked
system.webServer/asp section)
- Default.asp now uses Server.MapPath("../logs") to reach logs/
- tools/Setup-Site.ps1 automates and reconciles all of the above,
verified idempotent (safe to re-run)
- Verified enableParentPaths does not open a client-side traversal hole:
direct/encoded/double-encoded ../ URL attempts all correctly 404/403
- Full regression re-run (WSH, HTTP, curl+JSON self-test) all pass
unchanged from the client's point of view
- SPEC.md, docs/ARCHITECTURE.md, docs/DECISIONS.md, docs/TEST-RESULTS.md
updated to reflect the new structure as current, not left stale