Adds Framework/Database.wsc (WscMvc.Database): explicit, request-scoped
ADODB connection/transaction/command lifecycle, parameterized commands
via ADO positional placeholders (never string-concatenated SQL), and
Null-safe value handling. Proven via tests/Test-Components.vbs against a
real database, including a single-quote-containing value round-tripped
through a parameterized INSERT/SELECT to demonstrate no injection risk.
LocalDB was tried first (zero-install) but failed under the real IIS
ApplicationPoolIdentity ("SQL Server Network Interfaces" - LocalDB isn't
supported for IIS-hosted use per Microsoft's own guidance, confirmed
experimentally via a dedicated SelfTestController check, not assumed).
Pivoted to a real network-reachable SQL Server with SQL auth, which has
no dependency on the caller's Windows identity and was verified to work
under the real app-pool identity via the same check.
The live connection string lives only in an untracked db.connectionstring
file (.gitignore'd before it was ever written to disk) and is threaded
through Application.Run exactly like the existing logDir/viewsDir
pattern - Database.wsc itself never touches the filesystem or ASP
intrinsics. No new production route/view was added, per SPEC's
"database-backed example" non-goal - proven the same way M1-M4 proved
their components, via direct component tests plus one diagnostic-only
self-test check.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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