Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ serde = { version = "=1.0.229", features = ["derive"] }
serde_json = "=1.0.151"
stack-compiler = { git = "https://github.com/stack-sh/compiler.git", rev = "3d2379483da1edaeb24a26d43743587a4f5bd645" }
stack-formatter = { path = "crates/stack-formatter" }
stack-theme = { git = "https://github.com/stack-sh/theme.git", rev = "ed6c500762fc9ccffc8777172ac672a716dcd916" }
stack-theme = { git = "https://github.com/stack-sh/theme.git", rev = "d25b883884420adcc124e4c9c786ad92925eae60" }
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ cargo doc --workspace --no-deps

`stack-engine` exposes byte-oriented `format`, `check`, and `render` methods through an engine bound to the embedded or a caller-provided validated catalog. Every normal output carries engine, authored language, theme catalog version, and theme catalog revision metadata. User-source failures stay in ordered portable diagnostics. Invalid provided catalogs and violated normalized pipeline invariants use a separate operational-error channel. Checks and renders resolve the requested theme, validate deterministic integer geometry, and route ordered edges outside node interiors. Missing themes and icons produce source-mapped `STK6001` and `STK5001` warnings while a fallback SVG remains available. An unsatisfied authored order hint produces `STK4001` at its source-map range; a satisfied hint does not.

The renderer emits fixed-dimension standalone SVG with embedded catalog icons, local marker references, escaped authored text, accessible title and description metadata, and no script, event handler, external URL, host font measurement, or runtime I/O. Canonical SVG snapshots are byte-stable and parsed by `scripts/validate-svg.py`; set `UPDATE_STACK_SNAPSHOTS=1` only when intentionally regenerating them. CI also executes one exact numeric geometry fixture in both the native suite and a WASI build.
The renderer emits fixed-dimension standalone SVG with embedded catalog icons, local marker references, escaped authored text, accessible title and description metadata, and no script, event handler, external URL, host font measurement, or runtime I/O. The bundled catalog provides the first-party explicit icon identifiers `api`, `web`, `mobile`, `desktop`, `server`, `container`, `cluster`, `cloud`, `scheduler`, `webhook`, `identity`, and `observability` in every core theme. Canonical SVG snapshots are byte-stable and parsed by `scripts/validate-svg.py`; set `UPDATE_STACK_SNAPSHOTS=1` only when intentionally regenerating them. CI also executes one exact numeric geometry fixture in both the native suite and a WASI build.

The npm package exports synchronous `format`, `check`, and `render` functions after asynchronous module initialization. Each operation accepts `string | Uint8Array` and returns a specific typed result with camel-case metadata and portable diagnostics. Diagnostics preserve the compiler's primary range, ordered `expected` values, corrective help, and related source locations. Invalid UTF-8 remains a normal `STK1001` result. Unsupported JavaScript input types and internal operational failures throw at the adapter boundary. Shared fixtures compare complete native and WebAssembly results, including formatted source, diagnostics, SVG, and metadata. Artifact validation audits WebAssembly imports and package contents; browser consumers retain responsibility for loading the module and performing any DOM, filesystem, network, or clock work.

Expand Down
6 changes: 3 additions & 3 deletions THIRD_PARTY_LICENSES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

| Component | Revision | License | Source | Notes |
| --- | --- | --- | --- | --- |
| `stack-compiler` | `17a0abe9c35e641761ff08fdf59b29a42828d9fd` | Apache-2.0 | <https://github.com/stack-sh/compiler> | Unmodified Rust dependency; its license and notice obligations apply to distributions that include it. |
| `stack-theme` | `ed6c500762fc9ccffc8777172ac672a716dcd916` | Apache-2.0 | <https://github.com/stack-sh/theme> | Unmodified Rust dependency with repository-authored core SVG assets and deterministic metrics; its license and notice obligations apply to distributions that include it. |
| `stack-compiler` | `3d2379483da1edaeb24a26d43743587a4f5bd645` | Apache-2.0 | <https://github.com/stack-sh/compiler> | Unmodified Rust dependency; its license and notice obligations apply to distributions that include it. |
| `stack-theme` | `d25b883884420adcc124e4c9c786ad92925eae60` | Apache-2.0 | <https://github.com/stack-sh/theme> | Unmodified Rust dependency with repository-authored fallback and explicit core SVG assets and deterministic metrics; its license and notice obligations apply to distributions that include it. |
| `serde` / `serde_core` | `1.0.229` | MIT OR Apache-2.0 | <https://github.com/serde-rs/serde> | Runtime catalog data types through `stack-theme`. |
| `serde_json` | `1.0.151` | MIT OR Apache-2.0 | <https://github.com/serde-rs/json> | Runtime embedded-catalog decoding through `stack-theme`; also used by formatter conformance tests. |
| `itoa` | `1.0.18` | MIT OR Apache-2.0 | <https://github.com/dtolnay/itoa> | Transitive runtime dependency of `serde_json`. |
Expand All @@ -32,6 +32,6 @@
| `wasm-bindgen-cli` | `0.2.127` | MIT OR Apache-2.0 | <https://github.com/wasm-bindgen/wasm-bindgen> | Version-matched build tool; not shipped in the npm package. |
| `typescript` | `7.0.2` | Apache-2.0 | <https://github.com/microsoft/TypeScript> | Type-check tool; not shipped in the npm package. |

No third-party visual asset is bundled in a Stack Engine distribution. The npm package includes this inventory and the Apache-2.0, MIT, and Unicode-3.0 license texts required by its compiled dependency choices.
No third-party visual asset is bundled in a Stack Engine distribution. The bundled fallback and 12 explicit icons are Stack-authored Apache-2.0 assets from `stack-theme`. The npm package includes this inventory and the Apache-2.0, MIT, and Unicode-3.0 license texts required by its compiled dependency choices.

Before publishing a native library, binary-derived artifact, or WASM package, this inventory must list the shipped dependencies and assets, their pinned versions, exact licenses, required license texts, attribution, modifications, and redistribution conditions. Build-only dependencies that are not shipped should be distinguished from distributed code.
2 changes: 1 addition & 1 deletion crates/stack-engine-wasm/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "stack-engine-wasm"
version = "0.2.0"
version = "0.3.0"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion crates/stack-engine/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "stack-engine"
version = "0.2.0"
version = "0.3.0"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
Expand Down
52 changes: 51 additions & 1 deletion crates/stack-engine/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,7 @@ mod tests {
output.metadata.language_version,
Some(LanguageVersion { major: 1, minor: 0 })
);
assert_eq!(output.metadata.theme_catalog_version, "0.1.0");
assert_eq!(output.metadata.theme_catalog_version, "0.2.0");
assert_eq!(
output.metadata.theme_catalog_revision,
stack_theme::CATALOG_REVISION
Expand All @@ -530,6 +530,56 @@ mod tests {
}
}

#[test]
fn bundled_catalog_resolves_explicit_core_icons() -> Result<(), Box<dyn Error>> {
let expected_icons = [
("api", "Application programming interface"),
("web", "Web application"),
("mobile", "Mobile application"),
("desktop", "Desktop application"),
("server", "Server host"),
("container", "Application container"),
("cluster", "Compute cluster"),
("cloud", "Cloud environment"),
("scheduler", "Scheduled execution"),
("webhook", "Webhook endpoint"),
("identity", "Identity and access"),
("observability", "Observability system"),
];
let catalog = stack_theme::catalog();
assert_eq!(catalog.catalog_version, "0.2.0");
assert_eq!(
stack_theme::CATALOG_REVISION,
"sha256:d3a8a5a9d2100e496af3fd7adf389788f4a77508bf749a108183a2abf8f681e1"
);
for theme in &catalog.themes {
for (identifier, subject) in expected_icons {
let icon = theme
.icons
.iter()
.find(|icon| icon.id == identifier)
.ok_or("core icon is unavailable in a bundled theme")?;
assert_eq!(icon.subject, subject);
assert_eq!(icon.asset.path, format!("assets/core/{identifier}.svg"));
}
}

let source = b"stack 1.0 diagram \"Core icon\" { theme dark node gateway \"Gateway\" { kind service detail \"Public API\" icon \"api\" } }";
let checked = Engine::bundled().check(source)?;
let rendered = Engine::bundled().render(source)?;
assert!(checked.diagnostics.is_empty());
assert!(rendered.diagnostics.is_empty());
assert_eq!(rendered.metadata.theme_catalog_version, "0.2.0");
assert_eq!(
rendered.metadata.theme_catalog_revision,
stack_theme::CATALOG_REVISION
);
let svg = rendered.svg.ok_or("explicit icon render produced no SVG")?;
assert!(svg.contains("data-icon-id=\"api\""));
assert!(!svg.contains("data-icon-id=\"kind-external\""));
Ok(())
}

#[test]
fn format_preserves_semantic_diagnostics_but_not_syntax_failures() {
let engine = Engine::bundled();
Expand Down
11 changes: 11 additions & 0 deletions crates/stack-engine/tests/fixtures/explicit-core-icon.stack
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
stack 1.0

diagram "Core icon" {
theme dark

node gateway "Gateway" {
kind service
detail "Public API"
icon "api"
}
}
22 changes: 22 additions & 0 deletions crates/stack-engine/tests/render_snapshots.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,28 @@ fn canonical_valid_fixtures_match_standalone_svg_snapshots() -> Result<(), Box<d
Ok(())
}

#[test]
fn explicit_core_icon_matches_standalone_svg_snapshot() -> Result<(), Box<dyn Error>> {
let source = include_bytes!("fixtures/explicit-core-icon.stack");
let output = Engine::bundled().render(source)?;
assert!(output.diagnostics.is_empty());
assert_eq!(output.metadata.theme_catalog_version, "0.2.0");
assert_eq!(
output.metadata.theme_catalog_revision,
stack_theme::CATALOG_REVISION
);
let svg = output.svg.ok_or("explicit icon fixture produced no SVG")?;
assert!(svg.contains("data-icon-id=\"api\""));
let snapshot =
Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/snapshots/render/explicit-core-icon.svg");
if std::env::var_os("UPDATE_STACK_SNAPSHOTS").is_some() {
std::fs::write(&snapshot, &svg)?;
} else {
assert_eq!(svg, std::fs::read_to_string(&snapshot)?);
}
Ok(())
}

fn specification_root() -> Result<PathBuf, Box<dyn Error>> {
let configured = std::env::var_os("STACK_SPECIFICATION_DIR")
.ok_or("STACK_SPECIFICATION_DIR must point to stack-sh/specification")?;
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 28 additions & 0 deletions crates/stack-engine/tests/snapshots/render/explicit-core-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions docs/dependency-audit.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# Dependency and host-I/O audit

Audit date: 2026-09-03
Audit date: 2026-09-04

## Runtime graph

`stack-engine` has three direct dependencies:

- `stack-compiler` at `17a0abe9c35e641761ff08fdf59b29a42828d9fd` for byte decoding, parsing, validation, normalized IR, source maps, and compiler diagnostics;
- `stack-compiler` at `3d2379483da1edaeb24a26d43743587a4f5bd645` for byte decoding, parsing, validation, normalized IR, source maps, and compiler diagnostics;
- the workspace-local `stack-formatter` for canonical source output;
- `stack-theme` at `ed6c500762fc9ccffc8777172ac672a716dcd916` for the embedded core catalog, SVG bytes, deterministic font metrics, catalog version, and catalog revision.
- `stack-theme` at `d25b883884420adcc124e4c9c786ad92925eae60` for the `0.2.0` embedded core catalog, 12 provider-neutral explicit icons, SVG bytes, deterministic font metrics, catalog version, and catalog revision.

`stack-engine-wasm` adds `serde` for its serializable native parity model and, only on `wasm32`, version-matched `wasm-bindgen` and `js-sys` for the JavaScript ABI, typed-array input, and plain object construction. It does not use `web-sys` or a WASI target.

Expand Down
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "stack-engine-workspace",
"private": true,
"version": "0.2.0",
"version": "0.3.0",
"workspaces": [
"packages/engine"
],
Expand Down
4 changes: 3 additions & 1 deletion packages/engine/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ await init();

const formatted = format('stack 1.0 diagram "API" { node api "API" }');
const checked = check(new TextEncoder().encode('stack 1.0 diagram "API" { node api "API" }'));
const rendered = render('stack 1.0 diagram "API" { node api "API" }');
const rendered = render('stack 1.0 diagram "API" { node api "API" { icon "api" } }');
```

Each operation is synchronous after module initialization and accepts either a JavaScript string or `Uint8Array`. Invalid Stack source, including invalid UTF-8 bytes, returns normal portable diagnostics. Diagnostics include the primary range, ordered `expected` values, corrective help, and related source locations. A JavaScript value of any other type throws `TypeError` at the package boundary.

The package does not read files, contact a network service, inspect the DOM, observe a clock, or measure host fonts. Consumers own module loading and all host I/O.

The bundled catalog resolves `api`, `web`, `mobile`, `desktop`, `server`, `container`, `cluster`, `cloud`, `scheduler`, `webhook`, `identity`, and `observability` as first-party explicit icons in the `default`, `light`, and `dark` themes. Missing authored icon identifiers still produce `STK5001` and render the theme's fallback icon.
Loading