Forgeyard JavaScript / TypeScript CI/CD System & Architecture
Document type: Dedicated language ecosystem System & Architecture
Project: Forgeyard CI/CD
Subsystem: First-class JavaScript and TypeScript build, test, analysis, packaging, monorepo, frontend, backend, reproducibility, distribution, and release integration
Implementation direction: Rust-first Forgeyard core with native integration to Node.js/Bun and mainstream JS/TS tooling
Status: Target production architecture
Relationship to Forgeyard: This document defines the dedicated JavaScript/TypeScript subsystem that integrates with Forgeyard’s pipeline IR, hermetic build system, scheduler, runners, CAS, functional store, provenance, packaging, distribution, and deployment architecture.
1. Purpose
JavaScript and TypeScript require a dedicated Forgeyard architecture because the ecosystem has unusually large and mutable dependency graphs, multiple package managers, multiple runtimes, multiple module systems, and many build tools.
A JS/TS build can depend on:
- Node.js or Bun version;
- npm, pnpm, Yarn, or Bun package-manager version;
package.json;- lockfile contents;
- workspace/monorepo topology;
- npm registry state;
- private registries;
- transitive package tarballs;
- lifecycle scripts;
- native addons;
- Node-API/ABI;
- TypeScript compiler version;
tsconfig.json;- package
exports; - ESM/CJS semantics;
- bundler version;
- Babel/SWC/esbuild configuration;
- browserslist data;
- PostCSS/Tailwind/Sass tooling;
- environment variables;
- generated source;
- filesystem paths;
- timestamps;
- build-time network access;
- dev/prod dependency selection;
- optional dependencies;
- platform-specific dependency resolution;
- browser/runtime target;
- SSR framework behavior;
- mutable
node_modules; - package-manager global caches.
Forgeyard therefore needs a subsystem whose central rule is:
A JavaScript/TypeScript build is defined by source + runtime + package manager + lock graph + workspace graph + compiler/transpiler/bundler configuration + platform target + controlled environment.
2. Architectural Objectives
Forgeyard JS/TS MUST:
- support JavaScript and TypeScript as first-class ecosystems;
- support Node.js as the primary runtime;
- support Bun as an additional first-class runtime;
- support npm;
- support pnpm;
- support Yarn;
- support Bun package management;
- support package-lock, pnpm-lock, Yarn locks, and Bun lockfiles;
- support workspaces and monorepos;
- support TypeScript compilation;
- support ESM and CommonJS;
- support frontend, backend, CLI, library, SSR, and static-site builds;
- support Vite, Rollup, esbuild, SWC, Webpack, and configurable tools;
- support Jest, Vitest, Node test runner, Playwright/Cypress adapters;
- support linting and formatting;
- support native addons through Forgeyard C/C++ integration;
- support deterministic dependency installation;
- support fully offline builds after resolution/fetch;
- prevent arbitrary lifecycle-script impurity;
- support build cache and remote cache safely;
- support reproducible frontend/server bundles;
- support SBOM/provenance;
- support deterministic packaging and OCI;
- explain dependency/build graph changes;
- support local-first and enterprise distributed modes.
3. Non-Goals
Forgeyard does not replace:
- Node.js;
- Bun;
- npm;
- pnpm;
- Yarn;
- TypeScript;
- Vite;
- Rollup;
- Webpack;
- esbuild;
- SWC;
- framework build tools.
Forgeyard resolves, locks, isolates, verifies, caches, packages, and orchestrates them.
4. High-Level Architecture
flowchart TB
Src["JS/TS Source Tree"]
Detect["JS/TS Detector"]
Model["JsProjectSpec"]
Runtime["Runtime Resolver"]
PM["Package Manager Resolver"]
Deps["Dependency Resolver"]
WS["Workspace Resolver"]
Lock["JS/TS Lock Graph"]
Graph["Build/Test Graph"]
Sched["Forgeyard Scheduler"]
Runner["JS/TS Runner"]
Sand["Hermetic Sandbox"]
Build["Compiler / Bundler Adapter"]
Test["Test / Lint / Browser Test"]
CAS["Forgeyard CAS + Functional Store"]
Repro["Reproducibility Verifier"]
Pack["Package / OCI / Static Bundle"]
Prov["SBOM / Provenance / Signing"]
Dist["Promotion / Distribution"]
Src --> Detect
Detect --> Model
Model --> Runtime
Model --> PM
Model --> Deps
Model --> WS
Runtime --> Lock
PM --> Lock
Deps --> Lock
WS --> Lock
Lock --> Graph
Graph --> Sched
Sched --> Runner
Runner --> Sand
Sand --> Build
Build --> Test
Build --> CAS
Test --> CAS
CAS --> Repro
Repro --> Pack
Pack --> Prov
Prov --> Dist
5. Suggested Forgeyard Workspace
crates/
├── forgeyard-js/
├── forgeyard-js-model/
├── forgeyard-js-detect/
├── forgeyard-js-runtime/
├── forgeyard-js-node/
├── forgeyard-js-bun/
├── forgeyard-js-package-manager/
├── forgeyard-js-lock/
├── forgeyard-js-workspace/
├── forgeyard-js-install/
├── forgeyard-js-typescript/
├── forgeyard-js-bundler/
├── forgeyard-js-vite/
├── forgeyard-js-rollup/
├── forgeyard-js-esbuild/
├── forgeyard-js-webpack/
├── forgeyard-js-swc/
├── forgeyard-js-test/
├── forgeyard-js-browser-test/
├── forgeyard-js-analysis/
├── forgeyard-js-native-addon/
├── forgeyard-js-cache/
├── forgeyard-js-package/
└── forgeyard-js-provenance/
6. Core Domain Model
#![allow(unused)]
fn main() {
pub struct JsProjectSpec {
pub source: SourceRef,
pub runtime: JsRuntimeRequest,
pub package_manager: PackageManagerRequest,
pub workspace: JsWorkspaceSpec,
pub dependencies: JsDependencyPolicy,
pub module_system: ModuleSystemPolicy,
pub typescript: Option<TypeScriptSpec>,
pub build_target: JsBuildTarget,
pub build: JsBuildPolicy,
pub testing: JsTestPolicy,
pub analysis: JsAnalysisPolicy,
pub reproducibility: ReproducibilityPolicy,
}
}
7. Strong Types
#![allow(unused)]
fn main() {
pub enum JsRuntimeKind {
Node,
Bun,
}
pub enum JsPackageManagerKind {
Npm,
Pnpm,
Yarn,
Bun,
}
pub enum JsModuleSystem {
Esm,
CommonJs,
Mixed,
}
pub enum JsBuildKind {
Backend,
Frontend,
Library,
Cli,
Ssr,
StaticSite,
Worker,
}
}
8. Project Detection
Detect:
package.json
package-lock.json
pnpm-lock.yaml
yarn.lock
bun.lock / bun.lockb
tsconfig.json
jsconfig.json
vite.config.*
rollup.config.*
webpack.config.*
next.config.*
nuxt.config.*
svelte.config.*
astro.config.*
turbo.json
nx.json
lerna.json
Detection is advisory; explicit Forgeyard config wins.
9. Detection Result
#![allow(unused)]
fn main() {
pub struct JsDetection {
pub runtime_hints: Vec<JsRuntimeKind>,
pub package_managers: Vec<DetectedPackageManager>,
pub workspaces: Vec<DetectedWorkspace>,
pub typescript: bool,
pub bundlers: Vec<DetectedBundler>,
pub frameworks: Vec<DetectedFramework>,
pub native_addon_risk: DetectionState,
}
}
10. Runtime Identity
Node/Bun version strings are not sufficient identity.
Runtime identity should include:
runtime binary
bundled libraries/runtime resources
platform
architecture
runtime distribution identity
Logical:
JsRuntimeId = H(runtime closure)
11. Node.js Integration
First-class Node support:
node
npm if bundled
corepack if used
Node ABI / Node-API metadata
platform/architecture
Node installation should be Forgeyard-managed or explicitly platform-provided.
12. Bun Integration
First-class Bun support:
bun runtime
bun package manager
bundler/test features where used
platform/architecture
Bun identity is locked separately from Node.
13. Runtime Modes
#![allow(unused)]
fn main() {
pub enum JsRuntimeMode {
LockedManaged,
PlatformProvided,
AuditedHost,
}
}
Preferred for CI:
LockedManaged
14. Runtime Trust
#![allow(unused)]
fn main() {
pub enum JsRuntimeTrust {
Unverified,
DigestVerified,
VendorVerified,
OrganizationApproved,
Revoked,
}
}
15. Package Manager Identity
Package manager version participates in derivation identity.
Examples:
npm
pnpm
Yarn
Bun
Do not assume package manager behavior is stable across versions.
16. Corepack
If Corepack is used:
Corepack version
selected package-manager version
activation metadata
must be controlled.
Strict CI must not silently download a newer package manager during build.
17. packageManager Field
If package.json declares:
"packageManager": "pnpm@..."
Forgeyard resolves and locks it.
Release build uses the locked package manager.
18. Dependency Lock Strategy
Forgeyard treats ecosystem lockfiles as primary dependency resolution inputs and adds an outer Forgeyard identity layer.
package.json
+
ecosystem lockfile
+
package manager identity
+
registry/source policy
+
fetched package content identities
=
JsDependencyGraphId
19. Lockfiles
Supported:
package-lock.json
pnpm-lock.yaml
yarn.lock
Bun lockfile
Strict release requires exactly one authoritative package-manager mode per workspace unless explicitly configured otherwise.
20. Mixed Lockfile Detection
If repository contains:
package-lock.json
pnpm-lock.yaml
yarn.lock
Forgeyard should warn/error rather than guess.
Explicit project config decides.
21. package.json
Forgeyard records relevant semantics:
dependencies
devDependencies
peerDependencies
optionalDependencies
engines
packageManager
workspaces
scripts
type
exports
imports
main/module/browser fields
22. Outer Forgeyard Lock
Example:
javascript: (
runtime: (
kind: Node,
version: "locked",
digest: "blake3:...",
),
package_manager: (
kind: Pnpm,
version: "locked",
digest: "blake3:...",
),
dependency_graph: "blake3:...",
)
23. Registry Fetch Architecture
Strict model:
resolve
↓
fetch package tarballs/metadata
↓
verify integrity
↓
store immutably
↓
install/build offline
The build does not depend on live npm registry state.
24. Registry Policy
Configure:
approved public registries
private registries
organization mirrors
direct Git dependencies
HTTP tarballs
Production can require internal mirrors only.
25. Private Registries
Credentials belong only to fetch/resolution.
Package content is stored immutably.
Credentials never enter artifact identity or package bundle.
26. Package Integrity
Where lockfile provides integrity metadata, verify it.
Forgeyard additionally hashes fetched package content into its own immutable store.
27. Git Dependencies
Resolve:
repository
requested ref
commit
content digest
Production build never tracks moving branch state.
28. Local Dependencies
Examples:
file:
workspace:
link:
resolve to immutable source/workspace identities.
Do not depend on arbitrary runner filesystem content.
29. Workspaces
Support:
npm workspaces
pnpm workspaces
Yarn workspaces
Bun workspaces
and monorepo tools layered above them.
30. Workspace Graph
workspace packages
↓
internal dependency edges
↓
external dependency closure
↓
build/test targets
Forgeyard should preserve package-manager workspace semantics.
31. Monorepo Detection
Optional integrations:
Turborepo
Nx
Lerna
Rush
These are optimizers/orchestrators, not the source of dependency truth.
Forgeyard may consume their graph metadata but retains its own pipeline semantics.
32. Workspace Package Identity
Each workspace package:
#![allow(unused)]
fn main() {
pub struct JsWorkspacePackage {
pub name: PackageName,
pub path: VirtualPath,
pub package_json_digest: Digest,
pub source_digest: Digest,
}
}
33. Dependency Installation
Install phase is explicit.
Strict release:
lock verified
package closure fetched
network denied
deterministic install
34. npm Install Mode
Prefer lock-preserving commands such as:
npm ci
for CI rather than mutable resolution.
35. pnpm Install Mode
Use frozen-lockfile/offline equivalents according to supported pnpm behavior.
Forgeyard controls store path.
36. Yarn Install Mode
Use immutable/frozen lock behavior according to Yarn generation/version.
Forgeyard must distinguish Yarn Classic from modern Yarn.
37. Bun Install Mode
Use locked/frozen dependency behavior supported by the resolved Bun version.
38. node_modules
node_modules is a realization artifact, not a source-of-truth dependency database.
Forgeyard may:
materialize it
cache it
discard it
but dependency identity comes from lock graph + package contents + manager/runtime semantics.
39. pnpm Store
pnpm’s store is mutable acceleration.
Forgeyard can map package blobs into a Forgeyard-controlled cache/store while preserving pnpm semantics.
40. Yarn PnP
For Plug’n’Play projects:
.pnp.*
Yarn version
cache artifacts
are explicit build inputs.
Forgeyard must not force node_modules mode.
41. Zero-Install Repositories
If repository commits Yarn cache or similar artifacts, they are source inputs.
Forgeyard still verifies consistency with lock/package-manager policy.
42. Lifecycle Scripts
High-risk:
preinstall
install
postinstall
prepare
prepack
postpack
They can execute arbitrary code.
Forgeyard must execute them only inside hermetic sandbox and according to policy.
43. Lifecycle Script Policy
#![allow(unused)]
fn main() {
pub enum LifecycleScriptPolicy {
Allow,
AllowListed,
Deny,
Audit,
}
}
Enterprise/release default can use allowlist or audit-enforce migration.
44. Native Addons
Packages using:
node-gyp
node-pre-gyp
cmake-js
N-API native code
Rust native extensions
need explicit native toolchains.
Forgeyard integrates with C/C++ and Rust subsystems as needed.
45. Node-API / ABI
Native addon identity must include:
Node runtime ABI / Node-API target
platform
architecture
native compiler toolchain
native dependencies
Do not reuse binary addons across incompatible runtime ABI blindly.
46. node-gyp
Forgeyard supplies:
Python if required by toolchain
C/C++ compiler
make/ninja/MSBuild as needed
Node headers
SDK/sysroot
all explicitly.
47. Native Addon Runtime Validation
Shared-library dependencies of .node binaries are validated through Forgeyard C/C++ linkage subsystem.
48. TypeScript
TypeScript is first-class.
Toolchain identity includes:
typescript package/compiler version
tsconfig
extends chain
plugins
transformers where used
49. TypeScript Project Model
#![allow(unused)]
fn main() {
pub struct TypeScriptSpec {
pub compiler: LockedToolRef,
pub tsconfig: StoreObjectId,
pub project_references: Vec<TsProjectRef>,
pub incremental: TsIncrementalPolicy,
}
}
50. tsconfig.json
Forgeyard resolves:
extends
references
compilerOptions
include/exclude/files
paths
baseUrl
module/moduleResolution
target
jsx
declaration
source maps
All effective config must be inspectable.
51. tsconfig Extends
External/package-based extends are locked dependencies.
Local paths resolve inside source snapshot.
52. Project References
TypeScript project references form a build graph.
Forgeyard can use them for:
incremental build planning
cache keys
affected package analysis
53. TypeScript Incremental Cache
.tsbuildinfo is mutable acceleration.
Key it by:
TypeScript compiler identity
tsconfig identity
source graph
target
Never trust arbitrary developer .tsbuildinfo.
54. JavaScript Module Systems
Forgeyard explicitly models:
ESM
CommonJS
Mixed
because runtime/build behavior differs.
55. type Field
package.json "type" affects module interpretation.
It participates in package/build identity.
56. exports / imports
Package export maps are source semantics and part of library package validation.
57. Bundler Architecture
Forgeyard uses bundler adapters rather than one generic “frontend” command.
Supported first-class candidates:
Vite
Rollup
esbuild
Webpack
SWC
58. Bundler Trait
#![allow(unused)]
fn main() {
#[async_trait]
pub trait JsBundlerAdapter {
async fn detect(&self, source: &SourceTree) -> Result<Detection>;
async fn resolve_config(&self, project: &JsProjectSpec) -> Result<ResolvedBundlerConfig>;
async fn build(&self, ctx: BundlerContext) -> Result<BundleResult>;
}
}
59. Vite
Forgeyard tracks:
Vite version
config file
plugins
mode
environment variables
target
Rollup configuration underneath
60. Rollup
Track:
Rollup version
plugins
input graph
output format
treeshaking options
chunk naming
sourcemap policy
61. esbuild
Track:
esbuild version/binary
platform
target
format
external packages
defines
minification
sourcemap policy
esbuild may use native binary packages, so platform identity matters.
62. Webpack
Track:
Webpack version
config
loaders
plugins
mode
target
optimization
chunk/content hashing behavior
63. SWC
Track:
SWC core/native binary identity
config
target
module mode
minification
plugins
Native binary identity matters.
64. Babel
Optional adapter can lock:
@babel/core
presets
plugins
config chain
targets
65. Browserslist
Frontend target resolution can depend on Browserslist configuration and database.
Forgeyard should make:
browserslist config
caniuse data/dependency versions
part of the locked dependency graph.
66. CSS / HTML Integration
HTML/CSS are handled in this JS/TS subsystem because modern frontend builds commonly depend on JS toolchains.
Support:
plain HTML/CSS
PostCSS
Tailwind
Sass/SCSS
Less
CSS Modules
CSS-in-JS build tooling
67. PostCSS
Track:
postcss version
config
plugins
plugin versions
68. Tailwind
Track:
Tailwind version
config
content/source scanning inputs
plugins
Generated CSS is content-addressed output.
69. Sass
If using native/Dart Sass packages, lock implementation and platform-specific binary/package identity.
70. Frontend Environment Variables
Frameworks often bake env values into static assets.
Therefore distinguish:
build-time public environment
runtime server environment
secrets
Build-time environment affecting bytes is part of derivation identity.
71. Secret Rule
Do not bake secrets into frontend bundles.
Forgeyard policy should reject known secret references in client-build environment.
72. Public Build Variables
Example:
PUBLIC_API_ORIGIN
VITE_PUBLIC_*
NEXT_PUBLIC_*
if they affect artifact bytes, they are explicit build inputs.
73. Runtime Config Separation
Prefer:
one immutable frontend/server artifact
+
runtime/environment config
where framework permits.
Avoid rebuilding per deployment environment unnecessarily.
74. SSR
SSR applications have two artifact classes:
server runtime artifact
client/static artifact
Forgeyard should model them separately.
75. Static Site
Static-site build output is an immutable directory tree.
Canonicalize:
paths
metadata
archive packaging
and hash tree content.
76. Source Maps
Source maps are separate or bundled outputs according to policy.
They may contain source paths/content.
Apply path normalization and security policy.
77. Minification
Minifier version/config is build identity.
Do not assume minified output stability across versions.
78. Chunk Naming
Use content-derived stable chunk naming where supported.
Avoid random or timestamp-derived filenames in reproducible release mode.
79. Asset Fingerprinting
Content-hashed asset filenames are naturally compatible with Forgeyard CAS.
80. Testing
First-class:
Node test runner
Vitest
Jest
Playwright
Cypress adapter
framework-specific test runners
81. Unit Test Model
#![allow(unused)]
fn main() {
pub struct JsTestPlan {
pub runner: JsTestRunner,
pub projects: Vec<TestProject>,
pub shards: u32,
pub coverage: CoveragePolicy,
pub timeout: Duration,
}
}
82. Node Test Runner
Use locked Node runtime.
Test flags/config are explicit.
83. Vitest
Track:
Vitest version
Vite version
config
environment (node/jsdom/happy-dom/etc.)
84. Jest
Track:
Jest version
transformers
test environment
config
coverage provider
85. Browser Testing
Playwright/Cypress require browser binaries/runtime packages.
These are toolchain inputs.
86. Browser Toolchain
Model:
Chromium
Firefox
WebKit where supported
browser revision
OS dependencies
headless/display environment
87. Playwright
Browser downloads happen in resolver/fetch stage, not strict test realization.
Use immutable browser objects.
88. Cypress
Treat Cypress binary/runtime identity as locked tool input.
89. Browser Test Sharding
Tests can shard across:
files
projects
browsers
according to framework semantics.
90. Test Cache
Framework caches are acceleration only.
Release validation can force fresh test execution.
91. Linting
First-class candidates:
ESLint
Biome
oxlint
framework linters
Tool versions/configs are locked.
92. Formatting
Support verification:
Prettier
Biome
dprint adapter
CI should report diffs, not silently rewrite source.
93. Type Checking
TypeScript type-check job is separate from bundling where appropriate.
tsc --noEmit
or project-specific equivalent.
94. Static Analysis
Potential:
ESLint
Biome
TypeScript compiler diagnostics
security-focused analyzers
dependency-policy scanners
95. Dependency Security
Lock graph is scanned for:
known vulnerabilities
license policy
deprecated packages
untrusted registry/source
unexpected lifecycle scripts
96. Typosquatting / Dependency Confusion
Forgeyard should flag:
new package
unexpected registry
private/public name collision
source change
publisher/source change where metadata exists
Lock diff becomes a security review artifact.
97. Lock Diff
Example:
react 19.x -> 20.x
12 transitive packages changed
1 new lifecycle script
1 package source changed
2 licenses changed
Better than raw lockfile review alone.
98. Install Script Audit
Forgeyard records packages containing lifecycle scripts.
Policy can deny scripts for selected scopes.
99. Hermetic Install
Strict install sees:
locked package manager
lockfile
package source objects
workspace source
controlled cache/store
No public network.
100. HOME Isolation
Synthetic HOME prevents:
.npmrc
.yarnrc
.pnpm config
user certificates
global packages
from silently affecting build.
101. Package Manager Config
Forgeyard synthesizes approved registry/cache behavior.
Project-local config files are explicit source inputs.
User-global config is ignored in strict mode.
102. .npmrc
Project .npmrc can affect resolution/install.
Parse and policy-check it.
Secrets/tokens are not allowed as committed plaintext inputs.
103. Environment Isolation
Forgeyard controls:
PATH
HOME
NODE_ENV
CI
npm_config_*
PNPM_*
YARN_*
BUN_*
TZ
LANG
TMPDIR
plus project build variables.
104. Global Packages
Strict builds do not use globally installed npm packages.
All executables come from:
locked package manager/runtime
workspace dependencies
explicit Forgeyard tool inputs
105. npx
Uncontrolled npx may fetch packages.
Strict policy:
npx may execute only already-locked/local tools
No implicit network install.
106. Package Binary Resolution
Resolve executables from controlled dependency graph.
Do not fall back to arbitrary host PATH.
107. Generated Code
Examples:
GraphQL codegen
OpenAPI generators
protobuf
ORM clients
route generation
framework codegen
Generators are locked tools.
108. Codegen Stage
locked generator
↓
source/schema inputs
↓
generated tree
↓
compare or consume
109. Generated-Code Verification
If generated source is committed:
regenerate
↓
diff
↓
fail if stale
110. Native Tool Extensions
Some JS tooling uses native binaries:
esbuild
SWC
sharp
sqlite bindings
canvas
bcrypt variants
Platform-specific package/native binary identity must be locked.
111. Optional Dependencies
Platform-specific optional dependency selection participates in derivation identity.
112. Platform Model
#![allow(unused)]
fn main() {
pub struct JsPlatform {
pub os: JsOs,
pub arch: JsArch,
pub libc: Option<LibcKind>,
}
}
For Linux native dependencies, glibc/musl may matter.
113. Frontend Target
Frontend target includes:
browser target policy
module format
bundler
minification
CSS pipeline
114. Backend Target
Backend target includes:
Node/Bun runtime
platform
architecture
module mode
native addon closure
115. Edge/Worker Target
Treat runtimes such as worker/edge environments as explicit platform contracts where supported.
Do not assume Node API compatibility.
116. Cross-Building
Pure frontend bundles can build on many runner platforms.
Backend packages with native addons require target-compatible/native-cross toolchains.
117. Reproducibility
Same derivation:
Runner A -> output X
Runner B -> output Y
Compare:
bundle tree
server output
static assets
archives
118. Common Nondeterminism Sources
timestamps
random chunk IDs
absolute paths
unordered object traversal
build machine paths
generated UUIDs
native addon linker metadata
framework build IDs
environment-derived values
Forgeyard adapters should identify known framework-specific sources where possible.
119. Output Tree Canonicalization
For static/build directory:
sort paths
normalize metadata
hash file contents
Do not rewrite semantic JS/CSS content arbitrarily.
120. Source Map Reproducibility
Normalize source roots/paths.
Physical runner path must not leak.
121. Framework Build IDs
If framework supports configurable build ID, derive it deterministically from release/source identity.
Do not use wall-clock/random IDs.
122. Reproducer
Release policy can require a separate runner.
Mismatch quarantines artifact.
123. Build Cache
Possible layers:
bundler cache
TypeScript incremental cache
framework cache
package-manager cache
Forgeyard action cache
Forgeyard CAS
Each has distinct validity rules.
124. Cache Namespace
Include:
runtime ID
package-manager ID
lock graph ID
platform
tool versions
config digests
environment affecting bytes
125. Framework Cache
Examples:
.next/cache
.vite cache
webpack cache
turbo cache
Nx cache
Treat as disposable acceleration.
126. Remote Cache
Forgeyard may import/export framework cache artifacts but validates action identity.
Third-party remote cache is optional.
127. Monorepo Change Analysis
Use workspace graph:
changed package
↓
reverse workspace dependencies
↓
affected build/test set
Fallback to safe superset if uncertainty exists.
128. Turborepo Integration
Forgeyard may consume:
task graph
package graph
cache hints
but Forgeyard scheduler remains authoritative for distributed execution.
129. Nx Integration
Same principle:
consume graph metadata
do not make Nx database authoritative over Forgeyard artifact identity
130. Remote Execution
Good candidates:
workspace build tasks
test shards
browser test shards
lint/type-check shards
static frontend builds
131. Scheduler Capabilities
#![allow(unused)]
fn main() {
pub struct JsRunnerCapabilities {
pub runtimes: Vec<JsRuntimeId>,
pub package_managers: Vec<PackageManagerId>,
pub platforms: Vec<JsPlatform>,
pub browsers: Vec<BrowserToolchainId>,
pub native_toolchains: Vec<CppToolchainId>,
pub sandbox: SandboxCapabilities,
}
}
132. Scheduler Hard Constraints
Filter:
runtime
platform
browser requirement
native addon toolchain
OS-specific framework requirement
trust tier
memory
133. Scheduler Scoring
Score:
dependency closure locality
runtime locality
browser locality
cache warmth
queue delay
resource headroom
134. Runner Prewarming
Prefetch:
Node/Bun runtime
package manager
common dependency blobs
browser binaries
native addon toolchains
135. Browser Runner Pool
Browser tests can use specialized pools with:
display/headless support
browser set
GPU where required
mobile emulation capabilities
136. Frontend Build Resource Class
Large Webpack/Next builds can be RAM-heavy.
Scheduler uses historical memory data rather than only CPU count.
137. Adaptive Parallelism
Avoid oversubscribing:
many workspace builds
+
bundler worker pools
+
test worker pools
Forgeyard resource governor coordinates global concurrency.
138. Test Sharding
Shard by:
test file
workspace package
browser
project
according to runner semantics.
139. Browser Artifact Capture
On failures store:
screenshots
video
trace
console logs
network logs
as CAS artifacts.
140. Frontend Performance Tests
Optional:
bundle size
Lighthouse adapter
asset size budgets
route payload budgets
Use dedicated evidence, not package identity.
141. Bundle Size Gate
Track:
total JS
initial route JS
CSS
largest chunks
against baseline.
142. Tree-Shaking Validation
Optional diagnostics can compare:
unexpected package inclusion
bundle graph growth
143. Dependency Graph UI
Show:
workspace packages
external packages
version
source
integrity
native/lifecycle flags
144. Build Graph UI
Show:
workspace tasks
TypeScript projects
bundles
SSR/client split
tests
browser matrix
145. Runtime UI
Display:
Node/Bun version
runtime digest
platform
trust
ABI
146. Package Manager UI
Display:
manager
version
lockfile
frozen mode
cache state
registry policy
147. TypeScript UI
Display:
tsc version
tsconfig chain
project references
type-check status
incremental cache status
148. Native Addon UI
Display:
addon package
Node-API/ABI
C/C++ toolchain
runtime linkage
platform artifact
149. Reproducibility UI
Display:
primary digest
reproducer digest
bundle tree match
runtime
package manager
lock graph
environment inputs
150. CLI
Recommended:
forgeyard js detect
forgeyard js lock
forgeyard js fetch
forgeyard js install
forgeyard js graph
forgeyard js build
forgeyard js typecheck
forgeyard js test
forgeyard js browser-test
forgeyard js lint
forgeyard js format-check
forgeyard js analyze
forgeyard js reproduce
forgeyard js package
forgeyard js explain
forgeyard js explain-rebuild
forgeyard js runtime
forgeyard js deps
forgeyard js workspace
151. forgeyard js explain
Shows:
runtime
package manager
lockfile
workspace graph
TypeScript compiler
bundler
build target
native addons
build env
cache state
152. Explain Rebuild
Examples:
pnpm-lock.yaml changed
TypeScript version changed
Vite config changed
PUBLIC_API_ORIGIN changed
Node runtime changed
native addon toolchain changed
153. Failure Classification
#![allow(unused)]
fn main() {
pub enum JsFailure {
DetectionFailure,
RuntimeFailure,
PackageManagerFailure,
LockFailure,
DependencyFetchFailure,
InstallFailure,
LifecycleScriptFailure,
TypeCheckFailure,
BuildFailure,
TestFailure,
BrowserTestFailure,
AnalysisFailure,
NativeAddonFailure,
PackagingFailure,
ReproducibilityFailure,
}
}
154. Diagnostics
#![allow(unused)]
fn main() {
pub struct JsDiagnostic {
pub severity: Severity,
pub tool: ToolIdentity,
pub package: Option<PackageName>,
pub file: Option<VirtualPath>,
pub line: Option<u32>,
pub column: Option<u32>,
pub message: String,
}
}
Preserve raw logs too.
155. Install Failure Example
Dependency installation failed
package:
example-native-addon
reason:
postinstall attempted network access
policy:
build/install network denied
156. Lifecycle Script Violation
Lifecycle script denied
package:
suspicious-package
script:
postinstall
policy:
AllowListed
157. Native Addon Violation
Native addon hermeticity violation
attempted library:
/usr/local/lib/libfoo.so
reason:
outside declared native closure
158. Development Environment
forgeyard js dev
provides:
runtime
package manager
workspace dependencies
TypeScript
bundler
test/lint tools
matching CI identities.
159. IDE Integration
Export:
Node/Bun runtime path
TypeScript SDK
workspace metadata
tsconfig
package-manager metadata
for editors/IDEs.
160. Local Mode
Standalone Forgeyard can:
resolve/fetch packages
materialize dependencies
build
test
bundle
package
with local CAS/store.
161. Distributed Mode
daemon
↓
workspace task
↓
remote JS/TS runner
↓
runtime + dependency closure
↓
build/test
↓
CAS outputs
162. Enterprise Mode
Adds:
private registry mirror
approved package mirror
signed lock policy
OIDC/RBAC
browser farms
independent reproducers
multi-region CAS
air-gap support
163. Air-Gapped Build
Bundle:
source
runtime
package manager
package tarball closure
workspace lock graph
native addon toolchains
browser toolchains if tests require them
Strict build/test can then run offline.
164. SBOM
SBOM includes:
workspace packages
external packages
versions
sources
integrity hashes
native addon dependencies
runtime package
165. Provenance
Record:
source digest
package.json digest
lockfile digest
runtime ID
package-manager ID
workspace graph
TypeScript ID
bundler ID
build target
build-time public env
native addon closure
output digest
runner
sandbox policy
166. Packaging
Potential outputs:
static site bundle
server directory
single-file/compiled runtime output where tooling supports it
npm package tarball
zip/tar.zst
OCI image
Forgeyard native bundle
167. npm Library Package
For publishable libraries:
package.json
compiled JS
declaration files
source maps if configured
license/readme
Validate package contents before publishing.
168. Package Export Validation
Validate:
main
module
types
exports
imports
files
bin
point to actual package contents.
169. npm Pack Verification
Create package artifact deterministically.
Inspect package manifest/tree before publication.
170. Registry Publishing
Publishing is separate from build.
immutable package tarball
↓
policy/approval
↓
registry publish
Do not rebuild during publish.
171. Frontend Distribution
Static output can publish to:
object storage
CDN origin
static hosting
OCI
Forgeyard release site
same digest promoted across environments where configuration model permits.
172. Backend Distribution
Package:
server output
runtime closure or runtime requirement
production dependencies where needed
SBOM
provenance
173. Dependency Pruning
For Node server deployments, determine production runtime dependency closure.
Do not blindly copy full dev node_modules.
174. Standalone Output
Frameworks that produce self-contained server output can use that as preferred deployment closure, if validated.
175. OCI
Base images referenced by digest.
Do not rebuild application binary/bundle inside environment-specific OCI stages.
Prefer:
build immutable app artifact
↓
assemble deterministic image
176. Build Once, Promote Many
source
↓
artifact X
↓
test X
↓
reproduce X
↓
stage X
↓
production X
177. Release Manifest
#![allow(unused)]
fn main() {
pub struct JsReleaseManifest {
pub version: Version,
pub artifacts: BTreeMap<JsReleaseTarget, PackageDigest>,
pub sbom: Digest,
pub provenance: Digest,
}
}
178. Production Defaults
Recommended:
locked runtime
locked package manager
single authoritative lockfile
frozen dependency install
offline build after fetch
synthetic HOME
no global packages
controlled lifecycle scripts
explicit build-time environment
locked TypeScript/bundler
native addons locked
independent reproduction
179. Development Defaults
May allow:
warm local caches
dirty source
broader lifecycle script audit mode
framework dev server
incremental TS/bundler cache
with visible impurity status.
180. Error-Prone Behaviors to Prevent
Forgeyard should detect/reject:
package manager mismatch
lockfile ignored
multiple conflicting lockfiles
runtime auto-upgrade
Corepack auto-download during build
ambient npmrc/yarn config
global package dependency
network install during release build
unlocked Git dependency
local file dependency outside source snapshot
lifecycle script hidden network/tool usage
native addon using host compiler
native addon using host library
build secret baked into client bundle
random/timestamped build IDs
physical runner paths in source maps
181. Reference PR Pipeline
detect
↓
lock/install integrity
↓
format check
↓
lint
↓
typecheck
↓
unit tests
↓
build
182. Reference Frontend PR
install
↓
lint
↓
typecheck
↓
Vitest/Jest
↓
Vite/Webpack build
↓
bundle-size check
183. Reference Browser Pipeline
build app
↓
start controlled server
↓
Playwright/Cypress shards
↓
collect screenshots/traces
184. Reference Nightly
full workspace tests
browser matrix
dependency/security scan
extended static analysis
bundle-size trend
reproducibility sampling
185. Reference Release
clean source
↓
lock verification
↓
offline hermetic install
↓
typecheck/lint/tests
↓
hermetic build
↓
native addon linkage check
↓
independent reproduction
↓
deterministic package
↓
SBOM/provenance
↓
sign
↓
promote identical artifact
186. Implementation Phase 1 — Domain and Detection
Implement:
JsProjectSpec
runtime/package-manager detection
lockfile detection
workspace detection
TypeScript detection
bundler detection
Exit:
Forgeyard correctly describes common JS/TS repos.
187. Phase 2 — Runtime and Package Manager Locking
Implement:
Node runtime store
Bun runtime store
npm/pnpm/Yarn/Bun manager locking
Corepack policy
188. Phase 3 — Dependency Fetch/Install
Implement:
lock graph
registry fetch
private registry auth
offline install
synthetic HOME
cache isolation
Exit:
project installs and builds without network after fetch.
189. Phase 4 — TypeScript
Implement:
tsconfig resolution
TypeScript compiler identity
project references
typecheck
incremental cache
190. Phase 5 — Bundlers
Implement:
Vite
Rollup
esbuild
Webpack
SWC
with common bundle-result model.
191. Phase 6 — Testing/Analysis
Implement:
Node test
Vitest
Jest
ESLint
Biome
format checks
192. Phase 7 — Browser Tests
Implement:
Playwright
browser toolchains
test sharding
artifact collection
193. Phase 8 — Native Addons
Integrate:
node-gyp
C/C++ toolchain
Node-API/ABI
runtime linkage validation
194. Phase 9 — Reproducibility
Implement:
stable paths
deterministic env
content-tree comparison
framework-specific diagnostics
independent rebuild
195. Phase 10 — Packaging/Distribution
Implement:
npm package
static bundle
server package
OCI
release manifests
promotion
196. Phase 11 — Monorepo Optimization
Implement:
workspace graph
affected-task calculation
remote task execution
Turborepo/Nx graph adapters
197. Phase 12 — Enterprise Supply Chain
Implement:
approved registry mirror
script policy
signed lock approval
dependency trust
air-gap mirror
multi-region CAS
198. Acceptance Tests
- Remove host Node/Bun: locked runtime build still succeeds.
- Change global npm/pnpm/Yarn config: strict build unchanged.
- Change global package installation: strict build unchanged.
- Disable network after fetch: install/build still succeeds.
- Change package-manager version: derivation changes.
- Change lockfile: dependency graph changes.
- Add conflicting lockfile: Forgeyard errors unless explicitly configured.
- Change public build variable: derivation changes.
- Change runtime-only secret: artifact does not rebuild.
- Lifecycle script attempts network: strict policy blocks it.
- Native addon uses
/usr/local/lib: strict build rejects. - TypeScript version changes: typecheck/build identity changes.
- Bundler config changes: output derivation changes.
- Physical build path changes: source maps/output remain reproducible where supported.
- Independent runner produces same bundle tree.
- Reproducer mismatch quarantines release.
- npm package exports reference missing file: package validation fails.
- Promotion preserves exact artifact digest.
199. Production Readiness Gates
Do not call JS/TS support production-ready until:
runtime locking is stable
package-manager locking is stable
lockfile semantics are correct
offline installs work
private registries work securely
HOME/global config leakage is prevented
lifecycle scripts are controlled
TypeScript config resolution is accurate
bundler adapters are tested
browser test toolchains are reproducible enough for CI
native addons integrate with C/C++
source-map/build-path normalization works
reproducibility verification detects mismatches
package validation works
200. Architectural Invariants
- Runtime version string alone is not runtime identity.
- Package-manager version is explicit.
- Strict CI uses one authoritative dependency lock mode.
- Package installation does not resolve mutable dependency versions during release build.
- Strict install/build is offline after fetch.
- Host HOME/global package-manager config is not trusted.
- Global npm packages are not build inputs.
- Lifecycle scripts execute only under Forgeyard sandbox/policy.
- Native addons introduce explicit native toolchain identity.
- TypeScript compiler/config is explicit.
- Bundler/minifier versions are explicit.
- Build-time public environment affecting bytes is explicit.
- Secrets are not permitted in frontend build output.
- Source maps do not expose physical runner paths in strict release mode.
- Workspaces are modeled explicitly.
- Framework caches are acceleration only.
- Monorepo affected-task optimization must fail safe to broader execution.
- Reproducibility compares actual bundle/package content.
- Registry credentials never enter artifact identity.
- Promotion never rebuilds a release artifact.
201. Final Target Architecture
JavaScript / TypeScript Project
│
▼
Forgeyard JS Detector
│
▼
JsProjectSpec
│
┌────────────────────┼────────────────────┐
▼ ▼ ▼
Runtime Resolver Package Manager Workspace/Deps
Resolver Resolver
│ │ │
└────────────────────┼────────────────────┘
▼
Immutable JS/TS Lock
│
▼
Workspace/Task Graph
│
▼
Forgeyard Scheduler
│
▼
Hermetic JS Runner
│
┌────────────────┼────────────────┐
▼ ▼ ▼
TypeScript Bundler Tests
│ │ │
└────────────────┼────────────────┘
▼
Native Addon Validation
when applicable
│
▼
Content-Addressed Output
│
▼
Independent Reproducer
│
▼
Deterministic Packaging
│
▼
SBOM / Provenance / Signing
│
▼
Forgeyard Distribution
202. Final Architectural Position
For JS/TS, a dependable build identity is:
Source snapshot
+
Node/Bun runtime
+
package-manager identity
+
package.json
+
lockfile
+
workspace graph
+
dependency package contents
+
TypeScript/compiler configuration
+
bundler/transpiler/minifier configuration
+
platform/runtime target
+
build-time public environment
+
controlled lifecycle-script policy
+
hermetic sandbox
=
JS/TS derivation
When native addons exist:
JS/TS derivation
+
Node-API/ABI
+
C/C++ toolchain
+
native sysroot
+
native dependency closure
=
native JS/TS derivation
And a trustworthy release requires:
Derivation
↓
offline hermetic install/build
↓
typecheck / lint / tests / browser tests
↓
native linkage validation when required
↓
actual output digest
↓
independent reproduction
↓
deterministic package
↓
SBOM + provenance
↓
signature
↓
promotion of identical bytes
This gives Forgeyard first-class JavaScript/TypeScript support without inheriting the ecosystem’s usual mutable node_modules, global configuration, runtime drift, registry drift, lifecycle-script ambiguity, or hidden native-addon dependencies.
Appendix A — Recommended JS/TS Release Policy
(
javascript_release_policy: (
source: (
dirty_tree: Denied,
),
runtime: (
locked: Required,
),
package_manager: (
locked: Required,
single_authoritative_lock: Required,
),
dependencies: (
frozen: Required,
build_network: Denied,
private_registry_credentials: FetchOnly,
),
lifecycle_scripts: (
policy: AllowListed,
),
environment: (
host_home: Denied,
global_packages: Denied,
secrets_in_client_bundle: Denied,
),
native_addons: (
native_toolchain_locked: RequiredWhenPresent,
runtime_linkage_validation: RequiredWhenPresent,
),
reproducibility: (
independent_rebuilds: 1,
distinct_host: true,
comparison: NormalizedTree,
),
release: (
sbom: Required,
provenance: Required,
signing: Required,
rebuild_on_promotion: Denied,
),
),
)
Appendix B — Example Node + pnpm Lock
(
runtime: (
kind: Node,
version: "locked",
digest: "blake3:...",
),
package_manager: (
kind: Pnpm,
version: "locked",
digest: "blake3:...",
),
workspace: (
lockfile: "blake3:...",
graph: "blake3:...",
),
dependency_closure: "blake3:...",
)
Appendix C — Example TypeScript Frontend Configuration
javascript: (
runtime: LockedNode("node-stable"),
package_manager: LockedPnpm("pnpm"),
workspace: Auto,
typescript: (
compiler: Locked("typescript"),
project: "tsconfig.json",
),
build: (
kind: Frontend,
bundler: Vite(
config: "vite.config.ts",
),
),
environment: {
"PUBLIC_API_ORIGIN": BuildInput("https://api.example.invalid"),
},
reproducibility: (
network: Denied,
independent_rebuilds: 1,
),
)
Appendix D — First-Class Tooling Matrix
| Area | First-class |
|---|---|
| Runtime | Node.js, Bun |
| Package managers | npm, pnpm, Yarn, Bun |
| Dependency model | lockfiles, workspaces, private registries |
| TypeScript | tsc, project references, incremental cache |
| Bundling | Vite, Rollup, esbuild, Webpack, SWC |
| Testing | Node test, Vitest, Jest |
| Browser testing | Playwright, Cypress adapter |
| Analysis | ESLint, Biome, TypeScript diagnostics |
| Formatting | Prettier, Biome |
| Monorepo | native workspaces, Turborepo/Nx adapters |
| Native extensions | node-gyp/N-API via Forgeyard C/C++ |
| Frontend | HTML/CSS/PostCSS/Tailwind/Sass pipelines |
| Distribution | npm packages, static bundles, server bundles, OCI |
| Reproducibility | offline hermetic install/build + independent reproduction |