Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

14KB

WSC-MVC — Technical and Product Specification

Version: 0.1 (development specification)
Status: Proposed; implementation behavior must be verified on the target Windows/IIS host.

1. Mission

Build a small, maintainable, WSC-first MVC framework for Classic ASP. IIS receives HTTP traffic; a single ASP bootstrap dispatches requests to VBScript Windows Script Components registered as COM objects. Application behavior lives in WSC files; presentation lives in separate HTML templates. Ship verified increments rather than an elaborate untested framework.

2. Fixed decisions

  • Runtime: Windows, IIS, Classic ASP, VBScript; no ASP.NET, PHP, Node.js, or JScript runtime dependency.
  • Object architecture: registered .wsc COM components; stable ProgIDs and CLSIDs.
  • Presentation: separate .html templates, served only through the rendering layer when containing placeholders or private content.
  • Entry point: one Default.asp, plus IIS rewrite configuration and optional Global.asa only if justified.
  • IIS is a hard runtime requirement for HTTP integration; WSH-based component smoke tests are a separate concern.
  • Prefer built-in Windows/IIS capabilities and ADODB; no third-party framework required.
  • Business logic must not reference ASP Request, Response, Server, or Session.
  • All behavior dependent on WSC/COM/IIS quirks must be tested on Windows and documented; do not infer support from ordinary VBScript class behavior.

3. Non-goals for v0.1

No ORM, controller auto-discovery, automatic reflection, hot reload, plugin system, migrations, authentication, session-backed COM instances, application-scoped WSC instances, database-backed example, complex DI, or production-ready HTML parser. Do not implement these speculatively.

4. Initial execution path

GET /hello -> IIS URL Rewrite -> /Default.asp -> Server.CreateObject("WscMvc.Application") -> Application.Run(...) -> WscMvc.HomeController -> string/response contract -> HTTP 200, text/html; charset=utf-8, body Hello from WSC-MVC!.

Prefer a bootstrap with Option Explicit, no business logic, no includes, no embedded HTML, and only request-host wiring. Define and verify a precise ownership rule for HTTP status, headers, and writing: do not write a partially successful response before dispatch can fail. Test whether COM calls can accept the proposed ASP built-in objects; if passing an object fails, use a tested host adapter or pass only primitive request data. Do not silently assume an ASP object is serializable or universally callable from WSC.

5. Target project structure

Revised 2026-09-19 (explicit user direction, superseding the original v0.1 tree): IIS's site physical path is a public/ folder only — never the project root. Every other project directory is a sibling of the folder actually served, entirely outside the served tree — not reachable by IIS regardless of web.config, which is a stronger guarantee than request-filtering rules over a shared directory. Default.asp reaches sibling directories (e.g. logs/) via a parent-relative Server.MapPath, which requires enableParentPaths=true for the site. See docs/DECISIONS.md for the full rationale and docs/ARCHITECTURE.md for how it's wired up.

Further revised 2026-09-19 (same day, same direction): the diagnostics/test harness (GET /self-test) is its own separate IIS site/app (test-app/), not a route on the production site. Both sites share the exact same Framework//Controllers/ COM components (registered once, globally) — nothing about the framework or business logic is duplicated, only the thin per-site Default.asp+web.config wiring exists twice (and Default.asp is intentionally byte-identical in both places; see docs/DECISIONS.md).

WSC-MVC/
  public/                      # production site's IIS physical path
    Default.asp
    web.config
  test-app/
    public/                    # test-app site's IIS physical path (separate site/port)
      Default.asp              # intentionally identical to public/Default.asp
      web.config                # only routes /self-test
    logs/
      app.log                  # this site's own log, separate from the production one
  Framework/
    Application.wsc
    Router.wsc                 # phase 3
    RequestContext.wsc
    ResponseResult.wsc         # phase 2; optional if simpler contract works
    ViewRenderer.wsc           # phase 4
  Controllers/
    HomeController.wsc
    SelfTestController.wsc
  Views/
    Home.html                  # phase 4
    Layout.html                # phase 4
  logs/
    app.log                    # production site's log
  tests/
    Test-Components.vbs
    Test-Http.ps1
    run-self-test.sh
  tools/
    Register-Components.ps1
    Unregister-Components.ps1
    Setup-Site.ps1
  docs/
    ARCHITECTURE.md
    DECISIONS.md
    TEST-RESULTS.md
  SPEC.md
  IMPLEMENTATION_PLAN.md
  AGENTS.md
  CLAUDE.md
  README.md

The tree is a target, not an instruction to create placeholder classes before their phase.

6. Component contract

  • Each .wsc represents one named, cohesive component. The .wsc XML <registration> establishes COM identity; <public> explicitly lists callable methods/properties; <script language="VBScript"> contains implementation.
  • Do not assume a VBScript Class ... End Class placed inside a WSC becomes its exposed COM object. Use and validate the WSC script/public syntax on the target host.
  • Use PascalCase for file names and public members, WscMvc.ComponentName ProgIDs, and a unique, stable GUID per component (never recycle across unrelated components).
  • A component has a minimal documented public API. Unexposed functions remain internal. Initialize(...) is a framework convention, not an automatic WSC constructor.
  • Use explicit parameter and return contracts, including whether values are objects (Set) or scalars, and how missing/Null/Empty values are handled.
  • Use composition; do not invent inheritance, decorators, interfaces, or reflection that VBScript/WSC cannot provide.
  • Limit cross-component COM calls inside hot loops; keep interface calls coarse enough to measure.
  • Do not store ASP host objects or mutable request data in persistent scopes.

7. HTTP and routing contract (phase 3)

  • Support GET and POST initially; distinguish unsupported methods with a deliberate HTTP status.
  • Normalize path consistently; preserve an explicit original path; match literal routes before parameterized routes.
  • URL-decode exactly once where appropriate; validate route values and reject ambiguous or malformed paths rather than guessing.
  • Static assets bypass the rewrite. WSC, config, source, tests, logs, and private templates must not be served publicly.
  • Return deliberate 404 for unmatched routes, 405 for disallowed methods (with Allow where possible), 400 for malformed requests, 500 for unexpected failures.
  • Don't use unvalidated request values as filesystem paths, ProgIDs, method names, SQL identifiers, or template names.
  • Do not implement arbitrary controller/method activation from a URL; use an explicit allowlisted route map.

8. View contract (phase 4)

  • Templates live separately from code and are not directly browser-accessible if they contain private information or placeholders.
  • Default-encode data for HTML text; define separate, explicit handling for attributes, URLs, JS contexts, and raw HTML. Avoid unsafe universal substitution.
  • Never execute VBScript or arbitrary expression code supplied by a template. Prefer a minimal documented placeholder syntax.
  • Use a deliberate layout convention and report missing templates as server errors without exposing local filesystem paths.

9. Database contract (later phase)

  • ADODB with provider-specific adapters only when needed; parameterized commands for values, never string-concatenate untrusted SQL data.
  • Parameterize with correct order/type/size for the provider; identifier selection must use an allowlist.
  • Connection, recordset, command, and transaction ownership must be explicit. Release objects and close resources on success and failure.
  • Services/repositories do not depend on ASP host objects. Transactions have a clear owner and rollback path.

10. Security and operations

  • Default deny direct HTTP access to .wsc, .vbs, .ps1, .md, .config where appropriate, source/private directories, test output, logs, and templates. IIS configuration must be tested, including direct-extension and path variations.
  • Avoid printing debug stacks, COM registration details, connection strings, paths, secrets, or raw exception text to clients.
  • Record request correlation ID, route, elapsed time, outcome, and safe diagnostic information without sensitive payloads.
  • No broad filesystem write privileges. Register WSCs from an elevated, controlled deployment step; do not let a web request register COM classes.
  • Validate application pool identity, architecture (32/64-bit), DCOM/COM permissions where applicable, and IIS/ASP feature installation.
  • Do not cache COM objects in Session/Application. Favor short-lived request-owned instances and document threading implications.
  • Changes to COM registration must be idempotent, reversible, and explicit about privilege and architecture.
  • web.config is not a substitute for NTFS permissions or placing private source outside webroot; verify both where practical.

11. Error-handling contract

  • Local On Error Resume Next only around an operation whose Err.Number is immediately checked and cleared; otherwise use On Error GoTo 0.
  • Handle errors at the nearest layer that can add useful context or recover. Central HTTP boundary emits a safe 500 response if headers/body are not committed.
  • Define a testable strategy for already-committed responses. Never pretend an exception can undo a sent body.
  • Distinguish an expected not-found/validation result from a programmer/COM failure.

12. Definition of done for each component

  1. Contract and source file exist; XML is well-formed.
  2. Public declarations match implemented functions/procedures and documented names.
  3. ProgID/CLSID identities are recorded and stable.
  4. Registration/unregistration is tested on Windows at the required bitness.
  5. WSH smoke test instantiates it where applicable; IIS HTTP integration runs when host objects are required.
  6. Failure path and cleanup are tested; no unmanaged mutable shared request state.
  7. Security review covers direct HTTP exposure and untrusted input.
  8. README or architecture docs reflect actual implementation, not intentions.
  9. Tests are reported as PASS, FAIL, or NOT RUN with commands, host details, and evidence.

13. Milestone sequence and gates

M0: Inspect repository/environment; record OS/IIS/ASP/bitness/permissions and missing tools. No claim of execution on Linux/macOS. M1: Application.wsc and HomeController.wsc register and instantiate; /hello returns expected 200/body; isolated WSH test where possible; registration is reversible. M2: Request/response context, central error mapping, per-request object lifetime; concurrent request smoke test. M3: Static route table, GET/POST method dispatch, 400/404/405 tests, safe URL handling. M4: Separate HTML templates and encoding tests; layout only after basic rendering passes. M5: ADODB connection lifecycle, parameterized queries, transactions, repository tests against an explicitly configured test DB. M6: Security, session/auth architecture, logging, deployment and concurrency hardening. M7: Scaffolding, repeatable tests, documentation, agent-guided quality improvements. Each milestone needs passing evidence before the next. Explicitly document any blocked milestone.

14. Acceptance tests for M1

  • cscript //nologo tests\Test-Components.vbs reports successful creation and expected method result (if the component's public API is host-independent).
  • powershell -File tests\Test-Http.ps1 -BaseUrl http://localhost:<port> verifies status, content type, and exact body for /hello.
  • Direct requests to WSC files and private directories are denied.
  • Missing ProgID or broken registration produces a safe 500; no filesystem path or raw internal exception is exposed.
  • Unregistration removes the project registrations only and is reversible by re-registration.
  • Test at least two concurrent HTTP requests; no cross-request leakage.
  • No tests are described as passed without actual output.

15. Open questions to resolve experimentally

  • Can the proposed WSC Application COM method receive ASP intrinsic objects across this specific IIS/COM boundary reliably? If not, use a small ASP-host adapter and primitive arguments.
  • What exact registration tool and script-component XML forms work on the deployment OS and the relevant 32/64-bit host?
  • What is the safe reload/deployment procedure for an updated WSC under load? Do not promise hot reload before measuring it.
  • Which response contract best preserves error handling before bytes are sent? Record experiments, chosen behavior, tradeoffs, and evidence in docs/DECISIONS.md.

16. Reference reading

Powered by TurnKey Linux.