Changes: Accept ADR 0001 for the bounded React/TypeScript/Vite and Node/npm choice; record independent security findings and update S00-002 handoff. Preserve browser interaction and release/interoperability limits. Validation: Fresh-cache npm ci and strict npm run build passed on Node 24.21.0/npm 11.19.0; lock and artifact SHA256 matched executor evidence. Verified exact pins, 67 locked license/integrity entries and installed runtime license notices. HTTP preview matched built HTML/JS; make check passed 72 tooling tests; scoped diff and whitespace checked. No DOM interaction, vulnerability/provenance or product readiness acceptance is claimed. Task: S00-002 Agent: auto-security-bd73f4f80779 Role: security Action: review Status: done Task title: Выбрать framework и build runtime
82 lines
12 KiB
Markdown
82 lines
12 KiB
Markdown
# ADR 0001: Framework and build runtime for Luma Web
|
|
|
|
- Status: accepted — independent security review of S00-002; evidence: `state/evidence/S00-002-review.md`.
|
|
- Task / requirement: S00-002 / NFR-007.
|
|
- Date: 2026-10-15.
|
|
- Decision owner: auto-orchestrator-68a05c587e33 (orchestrator).
|
|
- Reviewer: auto-security-bd73f4f80779 (security), 2026-10-15.
|
|
|
|
## Context and required capabilities
|
|
|
|
Input: immutable NFR-007, accepted ADR 0000, architecture/contract registry and reviewed S00-011 registry remediation. Output: this bounded stack decision and one isolated rendering spike in `experiments/0001-stack`. Acceptance is exact versions, lockfile, actual clean install/build and documented license/runtime/browser limits. This selects browser UI and its build tooling, without selecting XMPP/OMEMO/media libraries, backend providers, routing/state libraries or shared schemas.
|
|
|
|
Luma needs a client-rendered UI, typed application/adapter boundaries, static deployment and eventual browser workers. An SSR application server is unnecessary for this experiment: secrets and OMEMO remain in their separately defined client boundaries. A UI library does not validate those boundaries or guarantee encrypted interoperability. S01 still owns exact contracts; S00-003…010 retain their existing decisions.
|
|
|
|
## Candidates and primary sources
|
|
|
|
Primary documentation and public registry metadata read on 2026-10-15. Versions below were retrieved with `npm view`; only the selected stack was installed/built. No performance comparison is claimed.
|
|
|
|
| Criterion | React + TypeScript + Vite | Vue + TypeScript + Vite |
|
|
| --- | --- | --- |
|
|
| Candidate UI | React / React DOM 19.3.1, MIT | Vue 3.5.44, MIT |
|
|
| Typed UI | TSX, `react-jsx`, native TypeScript JSX checking; React types 19.3.0 | Composition API / SFC; official Vite plugin 6.0.10 and vue-tsc 3.3.13, both MIT |
|
|
| Build / language | Vite 8.3.4, TypeScript 7.0.2 | Same Vite/TypeScript candidates; plugin peer range includes Vite 8 and Vue 3.5 |
|
|
| Application model | Explicit state updates and render functions; suitable for future typed commands/view models | Reactive refs and templates; also compatible with the architecture |
|
|
| Tooling tradeoff | One TypeScript checker for `.ts` and `.tsx`; plain Vite can build this spike without a React plugin | SFC compilation and template checking add separate tooling; Vue can also use render functions |
|
|
| Static hosting | Client bundle, no runtime Node server required | Client bundle, no runtime Node server required |
|
|
| Browser limits | Modern ESM browser target inherited from Vite; API support needs feature checks | Vue 3 targets modern browsers and excludes IE11; Vite limits also apply |
|
|
| Actual experiment | Clean install and strict typecheck/production build completed | Documentation/metadata comparison only; not installed or benchmarked |
|
|
|
|
Sources:
|
|
|
|
- [React's from-scratch setup](https://react.dev/learn/build-a-react-app-from-scratch) documents Vite as a build option and the additional application responsibilities of that approach. [createRoot](https://react.dev/reference/react-dom/client/createRoot) defines the DOM mounting API used here.
|
|
- [Vue quick start](https://vuejs.org/guide/quick-start.html) documents a Vite-based SPA, SFCs and optional TypeScript. [Vue FAQ](https://vuejs.org/about/faq.html) covers MIT licensing and modern-browser constraints. [Vue TypeScript tooling](https://vuejs.org/guide/typescript/overview.html) describes vue-tsc/template checking.
|
|
- [TypeScript JSX](https://www.typescriptlang.org/docs/handbook/jsx.html) defines TSX and automatic JSX runtime/type checking.
|
|
- [Vite getting started](https://vite.dev/guide/) documents framework templates and Node requirements. [Production build](https://vite.dev/guide/build.html) documents static output, browser targets and absence of automatic API polyfills.
|
|
- [Node release lifecycle](https://nodejs.org/en/about/previous-releases) identifies Node 24 as LTS and Node 26 as Current on this date. [Official Node 24.21.0 distribution](https://nodejs.org/dist/v24.21.0/) supplies runtime and checksums.
|
|
- [npm ci](https://docs.npmjs.com/cli/v11/commands/npm-ci/) defines lockfile-based clean installation, mismatch failure and removal of existing node_modules.
|
|
- Exact primary registry records: [React](https://registry.npmjs.org/react/19.3.1), [React DOM](https://registry.npmjs.org/react-dom/19.3.1), [Vue](https://registry.npmjs.org/vue/3.5.44), [Vite](https://registry.npmjs.org/vite/8.3.4), [TypeScript](https://registry.npmjs.org/typescript/7.0.2), [npm](https://registry.npmjs.org/npm/11.19.0), [Vue plugin](https://registry.npmjs.org/@vitejs%2fplugin-vue/6.0.10), [vue-tsc](https://registry.npmjs.org/vue-tsc/3.3.13). React type packages are pinned and their licenses recorded in the inventory.
|
|
|
|
## Decision
|
|
|
|
Select React 19.3.1 / React DOM 19.3.1, TypeScript 7.0.2 and Vite 8.3.4, built with Node 24.21.0 LTS and its bundled npm 11.19.0. Use `.ts` for non-UI typed modules and `.tsx` for React UI; ESM imports and strict TypeScript checking. This is a project engineering choice, not a requirement imposed by the product specification. TSX keeps ordinary typed module imports and UI checks on the same compiler path, fitting the existing domain/application/ports boundaries. Vue is viable; no claim of React performance/security superiority is made.
|
|
|
|
The six direct dependencies have exact versions, with no range operators. `package-lock.json` version 3 locks transitive/optional platform packages with registry URLs and integrity. `.nvmrc`, exact engines, packageManager and the build runtime guard establish tool pins; `.npmrc` requires strict engines and verified HTTPS. Node and npm are build tools; they are not a browser runtime or a selected push gateway stack. Lockfile updates require explicit review, not automatic floating upgrades.
|
|
|
|
No React Compiler, Babel, React refresh plugin, router, state store, service worker or polyfill is introduced. Vite's built-in TSX transform is sufficient for this spike, as verified by the build. Production development tooling and CI are subsequent scoped tasks; adding plugins requires license/API/browser checks. TypeScript 7 installs a platform compiler package; unsupported build-host platforms need a separate verified runtime/tooling decision.
|
|
|
|
## Focused experiment and actual result
|
|
|
|
The spike mounts a heading, an explicit local-experiment notice, an Increment button and a live counter through createRoot/useState. It contains no account fixture or transport and has no external runtime asset/CDN requests. See its README for exact reproduction and manual browser procedure.
|
|
|
|
Verified on macOS ARM64 using the official Node tarball downloaded over normal HTTPS and matched against SHASUMS256.txt. The tarball SHA-256 is `bed7eea5325e1108f32ce5228ddd6a5f0f08a499ee42aa7442aea583702f6057`. This is checksum verification against the same vendor HTTPS origin, not detached-signature verification. Node was unpacked only under `/private/tmp`; system tools/configuration were unchanged.
|
|
|
|
- `npm install --ignore-scripts --no-audit --no-fund` generated the lockfile (24 installed packages).
|
|
- `npm ci --ignore-scripts --no-audit --no-fund` with a new empty cache performed the actual clean install; exit 0, 24 packages. Existing node_modules was replaced by npm ci. Optional native packages supplied prebuilt binaries; lifecycle scripts stayed disabled.
|
|
- `npm run build` with the exact pinned tools performed strict `tsc --noEmit` and Vite production build; exit 0 before and after clean install. Output: 14 transformed modules; index HTML 0.29 kB, JavaScript 219.87 kB (68.75 kB gzip). These sizes describe this spike, not a product budget.
|
|
- The two build outputs and lockfile had identical SHA-256 hashes on this host. This demonstrates a local repeated build, not cross-OS bit-for-bit reproducibility.
|
|
- Loopback `npm run preview` served HTML and the byte-matching JavaScript artifact with HTTP 200; this was an HTTP smoke check, not browser execution. The preview process was stopped.
|
|
- `make check`: exit 0, 276 tasks / 22 stages / 221 requirements / 211 Web requirements; 66 tooling tests passed. It verifies the foundation, not the application.
|
|
|
|
No browser was available: in-app browser creation returned unavailable and browser inventory was empty. Interactive DOM rendering/click behavior is therefore an external check, not reported as passed. The card's mandatory clean install/build checks passed; release browser functionality still needs actual browser evidence in its assigned tasks. No XMPP/crypto/media/provider interoperability is implied.
|
|
|
|
## License / security / browser constraints
|
|
|
|
React, React DOM, their type packages and Vite use MIT; TypeScript uses Apache-2.0; Node uses MIT with bundled third-party notices; npm uses Artistic-2.0 with its own dependency licenses. React DOM requires React ^19.3.1; the selected exact version satisfies it. Vite 8.3.4 requires Node ^20.19.0 or >=22.12.0, TypeScript requires >=16.20.0, and npm 11.19.0 requires ^20.17.0 or >=22.9.0. Node 24.21.0 meets all selected requirements; do not choose EOL Node 20 merely because an engine range permits it.
|
|
|
|
The full locked inventory is in `experiments/0001-stack/LICENSE_INVENTORY.md`, including uninstalled optional platforms. Transitives include ISC, BSD-3-Clause, Apache-2.0 and MPL-2.0 (Lightning CSS build-time binaries). Build tools are not browser runtime dependencies; modified MPL-covered files would require their applicable source obligations on distribution. Browser-bundled React/React DOM/Scheduler copyright/license texts are preserved in `THIRD_PARTY_NOTICES.md`. Runtime distributions retain their original Node/npm notices. Future release packaging must collect notices for its actual full dependency graph; this inventory is not a license approval for future libraries.
|
|
|
|
The explicit syntax target is Chrome/Edge 111, Firefox 114, Safari 16.4, matching the documented Vite 8 baseline. These are compiler floors, not the accepted product test matrix (S00-006). There are no API polyfills: ESM/dynamic import/import.meta, DOM and appropriate JS built-ins must be available. WebCrypto/IndexedDB/WebRTC/notifications/permissions/storage quota must be checked independently; HTTPS/WSS and secure contexts remain mandatory in deployed use. Neither UI library makes closed-tab sockets or continuous media possible.
|
|
|
|
The loopback HTTP dev/preview server serves only this synthetic local UI. It does not connect to production endpoints and is not a workaround for TLS, certificates, crypto or CORS. No unsafe HTML insertion, secrets, environment credentials, analytics or real conversation data is present. Lock integrity does not prove provenance or absence of vulnerabilities; dependency monitoring/advisory review remains a continuing release responsibility.
|
|
|
|
## Consequences and migration triggers
|
|
|
|
After separate acceptance, downstream tasks may create stack-specific `.ts`/`.tsx` modules within their own cards, establish application CI/build and implement reviewed S01 contracts. No other module, plan definition, requirement snapshot or shared contract is changed here. The reviewed registry-access probe is retained unchanged.
|
|
|
|
A need for validated older browsers, unavailable native build-host packages, an incompatible required crypto/protocol dependency, or unacceptable measured UI behavior triggers a new bounded ADR/plan change and experiment. Do not replace this stack or introduce plaintext/stub fallbacks silently. A future revision may select Vue after real evidence; the unbuilt candidate is not represented as tested. Reviewer should verify exact pins/lock integrity/license notices, reproduce clean install/build, assess stated limits and record acceptance before consumers treat this ADR as accepted.
|
|
|
|
## Independent acceptance
|
|
|
|
Security reviewer auto-security-bd73f4f80779 repeated fresh-cache npm ci and strict typecheck/build on Node 24.21.0/npm 11.19.0, verified manifest/lock pins, all 67 locked license/integrity entries and runtime notice texts, and matched executor artifact hashes. Loopback preview served identical HTML/JS; make check passed 72 tooling tests. The bounded stack decision is accepted. DOM interaction was not executed in this review; product browser matrix, interoperability, vulnerability/provenance assessment and release readiness remain outside this acceptance. Review evidence records commands and limits; coordinator owns the review commit.
|