Repository navigation
forgeyard javascript typescript 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.
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.
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.
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.
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
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/
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,
}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,
}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.
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,
}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)
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.
First-class Bun support:
bun runtime
bun package manager
bundler/test features where used
platform/architecture
Bun identity is locked separately from Node.
pub enum JsRuntimeMode {
LockedManaged,
PlatformProvided,
AuditedHost,
}Preferred for CI:
LockedManaged
pub enum JsRuntimeTrust {
Unverified,
DigestVerified,
VendorVerified,
OrganizationApproved,
Revoked,
}Package manager version participates in derivation identity.
Examples:
npm
pnpm
Yarn
Bun
Do not assume package manager behavior is stable across versions.
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.
If package.json declares:
"packageManager": "pnpm@..."
Forgeyard resolves and locks it.
Release build uses the locked package manager.
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
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.
If repository contains:
package-lock.json
pnpm-lock.yaml
yarn.lock
Forgeyard should warn/error rather than guess.
Explicit project config decides.
Forgeyard records relevant semantics:
dependencies
devDependencies
peerDependencies
optionalDependencies
engines
packageManager
workspaces
scripts
type
exports
imports
main/module/browser fields
Example:
javascript: (
runtime: (
kind: Node,
version: "locked",
digest: "blake3:...",
),
package_manager: (
kind: Pnpm,
version: "locked",
digest: "blake3:...",
),
dependency_graph: "blake3:...",
)Strict model:
resolve
↓
fetch package tarballs/metadata
↓
verify integrity
↓
store immutably
↓
install/build offline
The build does not depend on live npm registry state.
Configure:
approved public registries
private registries
organization mirrors
direct Git dependencies
HTTP tarballs
Production can require internal mirrors only.
Credentials belong only to fetch/resolution.
Package content is stored immutably.
Credentials never enter artifact identity or package bundle.
Where lockfile provides integrity metadata, verify it.
Forgeyard additionally hashes fetched package content into its own immutable store.
Resolve:
repository
requested ref
commit
content digest
Production build never tracks moving branch state.
Examples:
file:
workspace:
link:
resolve to immutable source/workspace identities.
Do not depend on arbitrary runner filesystem content.
Support:
npm workspaces
pnpm workspaces
Yarn workspaces
Bun workspaces
and monorepo tools layered above them.
workspace packages
↓
internal dependency edges
↓
external dependency closure
↓
build/test targets
Forgeyard should preserve package-manager workspace semantics.
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.
Each workspace package:
pub struct JsWorkspacePackage {
pub name: PackageName,
pub path: VirtualPath,
pub package_json_digest: Digest,
pub source_digest: Digest,
}Install phase is explicit.
Strict release:
lock verified
package closure fetched
network denied
deterministic install
Prefer lock-preserving commands such as:
npm ci
for CI rather than mutable resolution.
Use frozen-lockfile/offline equivalents according to supported pnpm behavior.
Forgeyard controls store path.
Use immutable/frozen lock behavior according to Yarn generation/version.
Forgeyard must distinguish Yarn Classic from modern Yarn.
Use locked/frozen dependency behavior supported by the resolved Bun version.
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.
pnpm's store is mutable acceleration.
Forgeyard can map package blobs into a Forgeyard-controlled cache/store while preserving pnpm semantics.
For Plug'n'Play projects:
.pnp.*
Yarn version
cache artifacts
are explicit build inputs.
Forgeyard must not force node_modules mode.
If repository commits Yarn cache or similar artifacts, they are source inputs.
Forgeyard still verifies consistency with lock/package-manager policy.
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.
pub enum LifecycleScriptPolicy {
Allow,
AllowListed,
Deny,
Audit,
}Enterprise/release default can use allowlist or audit-enforce migration.
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.
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.
Forgeyard supplies:
Python if required by toolchain
C/C++ compiler
make/ninja/MSBuild as needed
Node headers
SDK/sysroot
all explicitly.
Shared-library dependencies of .node binaries are validated through Forgeyard C/C++ linkage subsystem.
TypeScript is first-class.
Toolchain identity includes:
typescript package/compiler version
tsconfig
extends chain
plugins
transformers where used
pub struct TypeScriptSpec {
pub compiler: LockedToolRef,
pub tsconfig: StoreObjectId,
pub project_references: Vec<TsProjectRef>,
pub incremental: TsIncrementalPolicy,
}Forgeyard resolves:
extends
references
compilerOptions
include/exclude/files
paths
baseUrl
module/moduleResolution
target
jsx
declaration
source maps
All effective config must be inspectable.
External/package-based extends are locked dependencies.
Local paths resolve inside source snapshot.
TypeScript project references form a build graph.
Forgeyard can use them for:
incremental build planning
cache keys
affected package analysis
.tsbuildinfo is mutable acceleration.
Key it by:
TypeScript compiler identity
tsconfig identity
source graph
target
Never trust arbitrary developer .tsbuildinfo.
Forgeyard explicitly models:
ESM
CommonJS
Mixed
because runtime/build behavior differs.
package.json "type" affects module interpretation.
It participates in package/build identity.
Package export maps are source semantics and part of library package validation.
Forgeyard uses bundler adapters rather than one generic "frontend" command.
Supported first-class candidates:
Vite
Rollup
esbuild
Webpack
SWC
#[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>;
}Forgeyard tracks:
Vite version
config file
plugins
mode
environment variables
target
Rollup configuration underneath
Track:
Rollup version
plugins
input graph
output format
treeshaking options
chunk naming
sourcemap policy
Track:
esbuild version/binary
platform
target
format
external packages
defines
minification
sourcemap policy
esbuild may use native binary packages, so platform identity matters.
Track:
Webpack version
config
loaders
plugins
mode
target
optimization
chunk/content hashing behavior
Track:
SWC core/native binary identity
config
target
module mode
minification
plugins
Native binary identity matters.
Optional adapter can lock:
@babel/core
presets
plugins
config chain
targets
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.
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
Track:
postcss version
config
plugins
plugin versions
Track:
Tailwind version
config
content/source scanning inputs
plugins
Generated CSS is content-addressed output.
If using native/Dart Sass packages, lock implementation and platform-specific binary/package identity.
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.
Do not bake secrets into frontend bundles.
Forgeyard policy should reject known secret references in client-build environment.
Example:
PUBLIC_API_ORIGIN
VITE_PUBLIC_*
NEXT_PUBLIC_*
if they affect artifact bytes, they are explicit build inputs.
Prefer:
one immutable frontend/server artifact
+
runtime/environment config
where framework permits.
Avoid rebuilding per deployment environment unnecessarily.
SSR applications have two artifact classes:
server runtime artifact
client/static artifact
Forgeyard should model them separately.
Static-site build output is an immutable directory tree.
Canonicalize:
paths
metadata
archive packaging
and hash tree content.
Source maps are separate or bundled outputs according to policy.
They may contain source paths/content.
Apply path normalization and security policy.
Minifier version/config is build identity.
Do not assume minified output stability across versions.
Use content-derived stable chunk naming where supported.
Avoid random or timestamp-derived filenames in reproducible release mode.
Content-hashed asset filenames are naturally compatible with Forgeyard CAS.
First-class:
Node test runner
Vitest
Jest
Playwright
Cypress adapter
framework-specific test runners
pub struct JsTestPlan {
pub runner: JsTestRunner,
pub projects: Vec<TestProject>,
pub shards: u32,
pub coverage: CoveragePolicy,
pub timeout: Duration,
}Use locked Node runtime.
Test flags/config are explicit.
Track:
Vitest version
Vite version
config
environment (node/jsdom/happy-dom/etc.)
Track:
Jest version
transformers
test environment
config
coverage provider
Playwright/Cypress require browser binaries/runtime packages.
These are toolchain inputs.
Model:
Chromium
Firefox
WebKit where supported
browser revision
OS dependencies
headless/display environment
Browser downloads happen in resolver/fetch stage, not strict test realization.
Use immutable browser objects.
Treat Cypress binary/runtime identity as locked tool input.
Tests can shard across:
files
projects
browsers
according to framework semantics.
Framework caches are acceleration only.
Release validation can force fresh test execution.
First-class candidates:
ESLint
Biome
oxlint
framework linters
Tool versions/configs are locked.
Support verification:
Prettier
Biome
dprint adapter
CI should report diffs, not silently rewrite source.
TypeScript type-check job is separate from bundling where appropriate.
tsc --noEmit
or project-specific equivalent.
Potential:
ESLint
Biome
TypeScript compiler diagnostics
security-focused analyzers
dependency-policy scanners
Lock graph is scanned for:
known vulnerabilities
license policy
deprecated packages
untrusted registry/source
unexpected lifecycle scripts
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.
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.
Forgeyard records packages containing lifecycle scripts.
Policy can deny scripts for selected scopes.
Strict install sees:
locked package manager
lockfile
package source objects
workspace source
controlled cache/store
No public network.
Synthetic HOME prevents:
.npmrc
.yarnrc
.pnpm config
user certificates
global packages
from silently affecting build.
Forgeyard synthesizes approved registry/cache behavior.
Project-local config files are explicit source inputs.
User-global config is ignored in strict mode.
Project .npmrc can affect resolution/install.
Parse and policy-check it.
Secrets/tokens are not allowed as committed plaintext inputs.
Forgeyard controls:
PATH
HOME
NODE_ENV
CI
npm_config_*
PNPM_*
YARN_*
BUN_*
TZ
LANG
TMPDIR
plus project build variables.
Strict builds do not use globally installed npm packages.
All executables come from:
locked package manager/runtime
workspace dependencies
explicit Forgeyard tool inputs
Uncontrolled npx may fetch packages.
Strict policy:
npx may execute only already-locked/local tools
No implicit network install.
Resolve executables from controlled dependency graph.
Do not fall back to arbitrary host PATH.
Examples:
GraphQL codegen
OpenAPI generators
protobuf
ORM clients
route generation
framework codegen
Generators are locked tools.
locked generator
↓
source/schema inputs
↓
generated tree
↓
compare or consume
If generated source is committed:
regenerate
↓
diff
↓
fail if stale
Some JS tooling uses native binaries:
esbuild
SWC
sharp
sqlite bindings
canvas
bcrypt variants
Platform-specific package/native binary identity must be locked.
Platform-specific optional dependency selection participates in derivation identity.
pub struct JsPlatform {
pub os: JsOs,
pub arch: JsArch,
pub libc: Option<LibcKind>,
}For Linux native dependencies, glibc/musl may matter.
Frontend target includes:
browser target policy
module format
bundler
minification
CSS pipeline
Backend target includes:
Node/Bun runtime
platform
architecture
module mode
native addon closure
Treat runtimes such as worker/edge environments as explicit platform contracts where supported.
Do not assume Node API compatibility.
Pure frontend bundles can build on many runner platforms.
Backend packages with native addons require target-compatible/native-cross toolchains.
Same derivation:
Runner A -> output X
Runner B -> output Y
Compare:
bundle tree
server output
static assets
archives
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.
For static/build directory:
sort paths
normalize metadata
hash file contents
Do not rewrite semantic JS/CSS content arbitrarily.
Normalize source roots/paths.
Physical runner path must not leak.
If framework supports configurable build ID, derive it deterministically from release/source identity.
Do not use wall-clock/random IDs.
Release policy can require a separate runner.
Mismatch quarantines artifact.
Possible layers:
bundler cache
TypeScript incremental cache
framework cache
package-manager cache
Forgeyard action cache
Forgeyard CAS
Each has distinct validity rules.
Include:
runtime ID
package-manager ID
lock graph ID
platform
tool versions
config digests
environment affecting bytes
Examples:
.next/cache
.vite cache
webpack cache
turbo cache
Nx cache
Treat as disposable acceleration.
Forgeyard may import/export framework cache artifacts but validates action identity.
Third-party remote cache is optional.
Use workspace graph:
changed package
↓
reverse workspace dependencies
↓
affected build/test set
Fallback to safe superset if uncertainty exists.
Forgeyard may consume:
task graph
package graph
cache hints
but Forgeyard scheduler remains authoritative for distributed execution.
Same principle:
consume graph metadata
do not make Nx database authoritative over Forgeyard artifact identity
Good candidates:
workspace build tasks
test shards
browser test shards
lint/type-check shards
static frontend builds
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,
}Filter:
runtime
platform
browser requirement
native addon toolchain
OS-specific framework requirement
trust tier
memory
Score:
dependency closure locality
runtime locality
browser locality
cache warmth
queue delay
resource headroom
Prefetch:
Node/Bun runtime
package manager
common dependency blobs
browser binaries
native addon toolchains
Browser tests can use specialized pools with:
display/headless support
browser set
GPU where required
mobile emulation capabilities
Large Webpack/Next builds can be RAM-heavy.
Scheduler uses historical memory data rather than only CPU count.
Avoid oversubscribing:
many workspace builds
+
bundler worker pools
+
test worker pools
Forgeyard resource governor coordinates global concurrency.
Shard by:
test file
workspace package
browser
project
according to runner semantics.
On failures store:
screenshots
video
trace
console logs
network logs
as CAS artifacts.
Optional:
bundle size
Lighthouse adapter
asset size budgets
route payload budgets
Use dedicated evidence, not package identity.
Track:
total JS
initial route JS
CSS
largest chunks
against baseline.
Optional diagnostics can compare:
unexpected package inclusion
bundle graph growth
Show:
workspace packages
external packages
version
source
integrity
native/lifecycle flags
Show:
workspace tasks
TypeScript projects
bundles
SSR/client split
tests
browser matrix
Display:
Node/Bun version
runtime digest
platform
trust
ABI
Display:
manager
version
lockfile
frozen mode
cache state
registry policy
Display:
tsc version
tsconfig chain
project references
type-check status
incremental cache status
Display:
addon package
Node-API/ABI
C/C++ toolchain
runtime linkage
platform artifact
Display:
primary digest
reproducer digest
bundle tree match
runtime
package manager
lock graph
environment inputs
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
Shows:
runtime
package manager
lockfile
workspace graph
TypeScript compiler
bundler
build target
native addons
build env
cache state
Examples:
pnpm-lock.yaml changed
TypeScript version changed
Vite config changed
PUBLIC_API_ORIGIN changed
Node runtime changed
native addon toolchain changed
pub enum JsFailure {
DetectionFailure,
RuntimeFailure,
PackageManagerFailure,
LockFailure,
DependencyFetchFailure,
InstallFailure,
LifecycleScriptFailure,
TypeCheckFailure,
BuildFailure,
TestFailure,
BrowserTestFailure,
AnalysisFailure,
NativeAddonFailure,
PackagingFailure,
ReproducibilityFailure,
}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.
Dependency installation failed
package:
example-native-addon
reason:
postinstall attempted network access
policy:
build/install network denied
Lifecycle script denied
package:
suspicious-package
script:
postinstall
policy:
AllowListed
Native addon hermeticity violation
attempted library:
/usr/local/lib/libfoo.so
reason:
outside declared native closure
forgeyard js dev
provides:
runtime
package manager
workspace dependencies
TypeScript
bundler
test/lint tools
matching CI identities.
Export:
Node/Bun runtime path
TypeScript SDK
workspace metadata
tsconfig
package-manager metadata
for editors/IDEs.
Standalone Forgeyard can:
resolve/fetch packages
materialize dependencies
build
test
bundle
package
with local CAS/store.
daemon
↓
workspace task
↓
remote JS/TS runner
↓
runtime + dependency closure
↓
build/test
↓
CAS outputs
Adds:
private registry mirror
approved package mirror
signed lock policy
OIDC/RBAC
browser farms
independent reproducers
multi-region CAS
air-gap support
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.
SBOM includes:
workspace packages
external packages
versions
sources
integrity hashes
native addon dependencies
runtime package
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
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
For publishable libraries:
package.json
compiled JS
declaration files
source maps if configured
license/readme
Validate package contents before publishing.
Validate:
main
module
types
exports
imports
files
bin
point to actual package contents.
Create package artifact deterministically.
Inspect package manifest/tree before publication.
Publishing is separate from build.
immutable package tarball
↓
policy/approval
↓
registry publish
Do not rebuild during publish.
Static output can publish to:
object storage
CDN origin
static hosting
OCI
Forgeyard release site
same digest promoted across environments where configuration model permits.
Package:
server output
runtime closure or runtime requirement
production dependencies where needed
SBOM
provenance
For Node server deployments, determine production runtime dependency closure.
Do not blindly copy full dev node_modules.
Frameworks that produce self-contained server output can use that as preferred deployment closure, if validated.
Base images referenced by digest.
Do not rebuild application binary/bundle inside environment-specific OCI stages.
Prefer:
build immutable app artifact
↓
assemble deterministic image
source
↓
artifact X
↓
test X
↓
reproduce X
↓
stage X
↓
production X
pub struct JsReleaseManifest {
pub version: Version,
pub artifacts: BTreeMap<JsReleaseTarget, PackageDigest>,
pub sbom: Digest,
pub provenance: Digest,
}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
May allow:
warm local caches
dirty source
broader lifecycle script audit mode
framework dev server
incremental TS/bundler cache
with visible impurity status.
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
detect
↓
lock/install integrity
↓
format check
↓
lint
↓
typecheck
↓
unit tests
↓
build
install
↓
lint
↓
typecheck
↓
Vitest/Jest
↓
Vite/Webpack build
↓
bundle-size check
build app
↓
start controlled server
↓
Playwright/Cypress shards
↓
collect screenshots/traces
full workspace tests
browser matrix
dependency/security scan
extended static analysis
bundle-size trend
reproducibility sampling
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
Implement:
JsProjectSpec
runtime/package-manager detection
lockfile detection
workspace detection
TypeScript detection
bundler detection
Exit:
Forgeyard correctly describes common JS/TS repos.
Implement:
Node runtime store
Bun runtime store
npm/pnpm/Yarn/Bun manager locking
Corepack policy
Implement:
lock graph
registry fetch
private registry auth
offline install
synthetic HOME
cache isolation
Exit:
project installs and builds without network after fetch.
Implement:
tsconfig resolution
TypeScript compiler identity
project references
typecheck
incremental cache
Implement:
Vite
Rollup
esbuild
Webpack
SWC
with common bundle-result model.
Implement:
Node test
Vitest
Jest
ESLint
Biome
format checks
Implement:
Playwright
browser toolchains
test sharding
artifact collection
Integrate:
node-gyp
C/C++ toolchain
Node-API/ABI
runtime linkage validation
Implement:
stable paths
deterministic env
content-tree comparison
framework-specific diagnostics
independent rebuild
Implement:
npm package
static bundle
server package
OCI
release manifests
promotion
Implement:
workspace graph
affected-task calculation
remote task execution
Turborepo/Nx graph adapters
Implement:
approved registry mirror
script policy
signed lock approval
dependency trust
air-gap mirror
multi-region CAS
- 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.
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
- 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.
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
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.
(
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,
),
),
)(
runtime: (
kind: Node,
version: "locked",
digest: "blake3:...",
),
package_manager: (
kind: Pnpm,
version: "locked",
digest: "blake3:...",
),
workspace: (
lockfile: "blake3:...",
graph: "blake3:...",
),
dependency_closure: "blake3:...",
)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,
),
)| 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 |
Forgeyard CI/CD & Build Platform · Wiki Index · GitHub Repository · Architecture Specifications
All architecture specifications are released under project governance guidelines.
Core Foundations & Source Domain
Storage, CAS & Data Plane
- Storage & Metadata
- CAS & Artifact Data Plane
- Cache Architecture, Build Acceleration, Remote Cache & Cache Correctness
- Data Lifecycle, Retention, Archival, Deletion, Legal Hold & Privacy Governance
- Artifact Registry, Package Repository, OCI Distribution & Internal Software Distribution
- Database Schema Migration, Online Backfill, Data Transformation & Zero-Downtime Change Orchestration
Pipeline Engine, IR, State Machine & Scheduling
- Pipeline IR, Parsing, Normalization & Planning
- Run / Job State Machine
- Scheduler
- Events, Event Delivery & Reconciliation
- Pipeline Triggers, Schedules, Manual Dispatch & Event-Driven Execution
- Workflow Concurrency, Distributed Locks, Idempotency Keys, Reservations & Exclusive Resource Coordination
- Job Checkpointing, Suspend/Resume, Preemption, Graceful Cancellation & Spot/Interruptible Runner Recovery
Runners, Sandboxing, Transport & Fleet Orchestration
- Runner / Agent
- Sandbox & Executor
- Transport, QUIC & Internal Protocol
- Device Lab
- Runner Fleet Autoscaling, Capacity Provisioning & Infrastructure Provider
- Runner Image Factory, Golden Image, Patch Management & Fleet Baseline Attestation
- Network Connectivity, Private Resource Access, Egress Control, Tunneling & Zero-Trust Service Connectivity
Security, Policy, Secrets & Supply Chain
Packaging, Releases, Deployment & Delivery
- Packaging
- Release
- Deployment
- Release Distribution, Update Delivery, Installer, Channel & Client Update
- Environment Promotion, Progressive Delivery, Feature Rollout, Canary Analysis & Automated Rollback Governance
- Artifact Promotion Policy, Release Train, Environment Channel & Lifecycle Governance
- Hermetic Build, Functional Packaging & Reproducible Distribution
Observability, Diagnostics, Testing & Quality
- Observability, Health & Doctor
- Search, Indexing, Query & Operational Analytics
- Test Results, Quality Gates, Coverage & Flaky-Test Intelligence
- Benchmarking, Performance Regression, Load-Test & Capacity Intelligence
- Static Analysis, Code Quality, Security Scanning & Findings Management
- Failure Diagnosis, Debugging, Reproduction, Bisect & Root-Cause Intelligence
- Reliability Engineering, SLO, Error Budget, Availability & Resilience Governance
- Test Data, Fixtures, Ephemeral Databases, Service Virtualization & Integration-Test Environment
- Incident Management, On-Call, Escalation, Response Coordination & Postmortem
API, UI, DevEx & Service Portal
- API / Axum
- Dioxus UI / GUI
- Developer Experience, Local Dev Environment, CLI Workflows & Reproducible Workstation
- Workflow Templates, Reusable Pipelines, Organization Standards & Golden Paths
- Service Catalog, Component Ownership, Environment Inventory & Developer Portal
- API/ABI/Schema/Protocol Compatibility, Contract Evolution & Breaking-Change Governance
- Remote Development Environments, Cloud Workspaces, Codespaces-Style Sessions & Developer Workspace Orchestration
Distributed Coordination, Federation & Operations
- SCM Provider Integrations
- High Availability, Coordination & Raft
- Remote Build Execution (RBE) Interoperability
- Plugin & Extension
- Operations, Backup, Upgrade & Disaster Recovery
- Self-Hosting, Bootstrap & Release-of-Forgeyard
- Notifications, Alerting & Human Workflow
- Entitlements, Licensing, Subscription & Commercial Access-Control
- Monorepo Intelligence, Dependency Graph, Affected-Change & Incremental Execution
- Dependency, Package Registry, Artifact Mirror & Software-Source Governance
- Configuration, Feature Flags, Runtime Settings & Dynamic Configuration Governance
- Cost Accounting, FinOps, Chargeback/Showback & Resource Economics
- CI/CD Migration, Import, Compatibility & Legacy-System Interoperability
- Multi-Region Federation, Edge Sites, Disconnected Operation & Cross-Site Replication
- Infrastructure-as-Code, Environment Provisioning, Preview Environments & Drift Reconciliation
- Merge Queue, Speculative Integration, Batch Validation & Protected Target Submission
- AI-Assisted CI Optimization, Engineering Copilot & Autonomous Recommendation Governance
- Build Graph Replay, Historical Reproducibility, Time-Travel CI & Evidence Reconstruction
- Change Risk Assessment, Preflight Simulation, Policy Preview & What-If Analysis
- Configuration Drift Detection, Desired-State Convergence, Runtime Reconciliation & Environment Consistency
- Dependency Update Automation, Version Maintenance, Vulnerability Remediation & Upgrade Campaign