Start

Application Loop

Build one installed multi-module Topaz package into source-free native and Python products.

This guide takes one package from a clean Topaz installation through creation, authoring, static gates, documentation, and direct offline execution. It uses the current product identity Topaz 5.6.5 with language mode topaz-5.6; the patch changes the tool workflow, not the v5.6 grammar.

Prerequisites

Install Topaz and confirm the exact product and language identity:

BASH
curl -fsSL https://topaz.ooo/install.sh | sh
topaz version --verbose

Native builds require a Rust toolchain. Python products require Python 3.11 or newer at runtime. Neither toolchain is needed merely to author, check, format, test, or document the package.

Create the package

Start from an empty working directory and let the installed CLI create the final application root:

BASH
topaz init --root release-inventory

Running the command again refuses to overwrite the scaffold. The completed example has this layout:

release-inventory/
  topaz.toml
  src/main.tpz
  src/policy.tpz
  src/report.tpz
  data/releases.csv
  data/policy.toml
  out/report.txt
registry/
  report_slug/1.0.0/topaz.toml
  report_slug/1.0.0/src/lib.tpz

Create the directories that are not part of the initial scaffold before writing the files below:

BASH
mkdir -p release-inventory/src release-inventory/data release-inventory/out
mkdir -p registry/report_slug/1.0.0/src

Replace the scaffold manifest with the following package declaration. The filesystem capabilities allow reads only under data and writes only under out; ordinary path traversal and symlink escapes are rejected.

TOML
[package]
name = "release_inventory"
version = "0.1.0"
language = "5.6"
entry = "src/main.tpz"

[build]
target = "native"
deterministic = true

[dependencies]
std = "5.6"
report_slug = "1.0.0"

[capabilities.fs]
read = ["data"]
write = ["out"]

The entry selects sample and negative-test modes, reads structured input, and writes the report:

TOPAZ
import src.report { buildReport }
import std.fs

const SAMPLE_CSV = "name,status,score\nCore API,ready,91\nDraft Tool,draft,99\nCLI Pack,ready,84"
const SAMPLE_POLICY = "[policy]\nrequired_status = \"ready\"\nminimum_score = 85"

function renderSample(csv: string) -> Result<int, string> {
  let report = buildReport(csv, SAMPLE_POLICY)?
  print(report)
  Ok(0)
}

function hasArg(args: Array<string>, expected: string) -> bool {
  match args.indexOf(expected) {
    case Some(_) => true
    case None => false
  }
}

export function main(args: Array<string>, stdin: string) -> Result<int, string> {
  if hasArg(args, "--sample") {
    return renderSample(SAMPLE_CSV)
  }
  if hasArg(args, "--bad-sample") {
    return renderSample("name,status,score\nBroken Row,ready,nope")
  }
  if hasArg(args, "--probe-denied") {
    let secret = fs.readText("secret.txt")?
    print(secret)
    return Ok(0)
  }
  if hasArg(args, "--probe-symlink") {
    let secret = fs.readText("data/escape-link")?
    print(secret)
    return Ok(0)
  }

  let inventory = fs.readText("data/releases.csv")?
  let policy = fs.readText("data/policy.toml")?
  let report = buildReport(inventory, policy)?
  fs.writeText("out/report.txt", "{report}\n")?
  print(report)
  Ok(0)
}

src/policy.tpz validates the TOML policy:

TOPAZ
export type Policy = { requiredStatus: string, minimumScore: int }

function field(obj: JSONValue, name: string) -> Result<JSONValue, string> {
  match obj.get(name) {
    case Some(value) => Ok(value)
    case None => Err("missing policy.{name}")
  }
}

export function parsePolicy(text: string) -> Result<Policy, string> {
  let document = TOML.toJson(TOML.parse(text)?)
  let policy = field(document, "policy")?
  let requiredValue = field(policy, "required_status")?
  let minimumValue = field(policy, "minimum_score")?
  let required = requiredValue.asString() ?? ""
  let minimum = minimumValue.asInt() ?? -1
  if required.byteLength() == 0 {
    return Err("policy.required_status must not be empty")
  }
  if minimum < 0 {
    return Err("policy.minimum_score must be a non-negative int")
  }
  Ok({ requiredStatus: required, minimumScore: minimum })
}

src/report.tpz combines the local module, collections, CSV input, deterministic errors, and the package dependency:

TOPAZ
import report_slug { slug }
import src.policy { Policy, parsePolicy }

function cell(row: Map<string, string>, name: string) -> Result<string, string> {
  match row.get(name) {
    case Some(value) => Ok(value)
    case None => Err("missing CSV column {name}")
  }
}

function acceptedLine(row: Map<string, string>, policy: Policy) -> Result<Option<string>, string> {
  let name = cell(row, "name")?
  let status = cell(row, "status")?
  let scoreText = cell(row, "score")?
  let score = match toInt(scoreText) {
    case Some(value) => value
    case None => return Err("invalid score `{scoreText}` for `{name}`")
  }
  if status != policy.requiredStatus || score < policy.minimumScore {
    return Ok(None)
  }
  Ok(Some("{slug(name)?}:{score}"))
}

export function buildReport(csvText: string, policyText: string) -> Result<string, string> {
  let policy = parsePolicy(policyText)?
  let rows = CSV.parseWithHeader(csvText)?
  let mut accepted: Array<string> = []
  for row in rows {
    match acceptedLine(row, policy)? {
      case Some(line) => accepted.push(line)
      case None => ()
    }
  }
  let lines = accepted.sorted()
  Ok("accepted={lines.length}\n{lines.join("\n")}")
}

Create the local registry dependency with this manifest and src/lib.tpz:

TOML
[package]
name = "report_slug"
version = "1.0.0"
language = "5.6"
entry = "src/lib.tpz"

[build]
target = "native"
deterministic = true

[dependencies]
std = "5.6"

[exports]
module = "src/lib.tpz"
TOPAZ
export function slug(name: string) -> Result<string, string> {
  let spaces = Regex.compile(" +")?
  Ok(spaces.replaceAll(name.trim(), "-"))
}

Finally, write the runtime inputs and create the output directory:

# data/releases.csv
name,status,score
Core API,ready,91
CLI Pack,ready,84
Python Host,ready,88
Draft Tool,draft,99

# data/policy.toml
[policy]
required_status = "ready"
minimum_score = 85

Lock, vendor, and run authoring gates

Vendor the dependency, then remove the registry to prove subsequent package operations use only the lockfile and vendored bytes:

BASH
topaz vendor --root release-inventory --from registry
rm -rf registry
topaz check --root release-inventory --locked
topaz fmt --check --root release-inventory
topaz test --root release-inventory --locked -- --sample
topaz doc --root release-inventory --locked --out-dir docs-out

fmt --check invokes the same formatter as fmt and writes nothing. An editor can start topaz lsp --root release-inventory; saved package diagnostics resolve the vendored module, while an invalid unsaved edit is diagnosed from the overlay without changing the file on disk.

Run the checked package and its deterministic malformed-input case:

BASH
topaz run --root release-inventory --locked
topaz run --root release-inventory --locked -- --bad-sample

The successful report is:

accepted=2
Core-API:91
Python-Host:88

Build both products

Native and Python products use distinct commands:

BASH
topaz build --release --root release-inventory --locked --out-dir native-out
topaz build --target python --root release-inventory --locked --out-dir python-out

The native runtime deliverable is native-out/target/release/program (program.exe on Windows). The Python runtime deliverables are python-out/program.py and python-out/topaz_py_rt.py. Each build also writes topaz-artifact.json, which records the 5.6.5 toolchain, topaz-5.6 language mode, target, runtime requirements, and managed-file hashes.

Copy only those runtime deliverables plus data/ and an empty writable out/ into separate runtime directories. Then delete the application source, the registry, generated documentation, and both build directories:

BASH
mkdir -p native-runtime/data native-runtime/out
mkdir -p python-runtime/data python-runtime/out
cp native-out/target/release/program native-runtime/program
cp python-out/program.py python-out/topaz_py_rt.py python-runtime/
cp release-inventory/data/* native-runtime/data/
cp release-inventory/data/* python-runtime/data/
rm -rf release-inventory registry docs-out native-out python-out

With network and proxies disabled, run each product from its own runtime directory so its declared relative data/ and out/ roots remain valid:

BASH
(cd native-runtime && env HTTP_PROXY=http://127.0.0.1:9 HTTPS_PROXY=http://127.0.0.1:9 ALL_PROXY=http://127.0.0.1:9 NO_PROXY= CARGO_NET_OFFLINE=true ./program)
(cd python-runtime && env HTTP_PROXY=http://127.0.0.1:9 HTTPS_PROXY=http://127.0.0.1:9 ALL_PROXY=http://127.0.0.1:9 NO_PROXY= CARGO_NET_OFFLINE=true python3 program.py)

Both products produce the same report and output file without the Topaz checkout, application source, registry, Cargo build tree, or network. The native product needs only its executable and declared runtime data; the Python product additionally needs topaz_py_rt.py and Python 3.11+.