Topology

Topology Is Runtime Truth

Sigil topology is the canonical, compiler-visible declaration of a project's external runtime dependencies.

Topology is not config.

Topology answers:

  • what external things this project depends on
  • what those logical dependencies are called
  • which environment names exist

Config answers:

  • how one named environment constructs the runtime world for those dependencies

Why Sigil Splits Topology from Config

Without this split, runtime truth gets blurred together:

  • architecture and credentials live in one file
  • app code falls back to process.env
  • tools reconstruct the system from strings

Sigil prefers one explicit model:

  • src/topology.lib.sigil declares dependency handles and environment names
  • config/.lib.sigil exports the selected environment's world
  • application code uses typed handles from •topology
  • only config modules may read process.env

Canonical Project Shape

Topology-aware projects define:

src/topology.lib.sigil
config/local.lib.sigil
config/test.lib.sigil
config/production.lib.sigil

Environment names are flexible, but the file path is canonical:

  • if Sigil is run with --env test, the project needs config/test.lib.sigil
  • if Sigil is run with --env production, the project needs config/production.lib.sigil

Canonical Topology Module

src/topology.lib.sigil declares only dependency handles and environment names:

c local=(§topology.environment("local"):§topology.Environment)

c mailerApi=(§topology.httpService("mailerApi"):§topology.HttpServiceDependency)

c prod=(§topology.environment("prod"):§topology.Environment)

c test=(§topology.environment("test"):§topology.Environment)

No URLs. No ports. No usernames. No passwords. No env-var names.

Those belong in config.

Canonical Config Modules

Each declared environment gets one config module exporting world:

c world=(†runtime.world(†clock.systemClock(),†fs.real(),[†http.proxy("http://127.0.0.1:45110",•topology.mailerApi)],†log.capture(),†process.deny(),†random.seeded(1337),[],†timer.virtual()):†runtime.World)

Production-style config can read env vars, but only there:

e process

c world=(†runtime.world(†clock.systemClock(),†fs.real(),[†http.proxy((process.env.mailerApiUrl:String),•topology.mailerApi)],†log.stdout(),†process.real(),†random.real(),[],†timer.real()):†runtime.World)

Application Code Uses Handles, Not Endpoints

Canonical HTTP usage:

λmain()=>!Http String match §httpClient.get(•topology.mailerApi,§httpClient.emptyHeaders(),"/health"){
  Ok(response)=>response.body|
  Err(error)=>error.message
}

Canonical TCP usage:

λmain()=>!Tcp String match §tcpClient.send(•topology.eventStream,"ping"){
  Ok(response)=>response.message|
  Err(error)=>error.message
}

Forbidden patterns:

§httpClient.get("http://127.0.0.1:45110",headers,"/health")
§tcpClient.send("127.0.0.1","ping",45120)
process.env.mailerApiUrl

--env Is Required

Sigil does not guess a default environment for topology-aware work.

Use:

sigil validate projects/topology-http --env test
sigil run projects/topology-http/src/getClient.sigil --env test
sigil test projects/topology-http/tests --env test

If topology is present and --env is missing, Sigil rejects the command.

What Sigil Enforces

Compile-time:

  • topology constructors only in src/topology.lib.sigil
  • world HTTP/TCP entry constructors only in config/*.lib.sigil and test-local world { ... }
  • topology-aware HTTP/TCP APIs require dependency handles
  • raw endpoint usage is rejected
  • process.env is only allowed in config/*.lib.sigil

Validate-time:

  • the selected environment must be declared in topology
  • config/.lib.sigil must exist
  • the config module must export world
  • world must include every primitive effect entry
  • every declared HTTP/TCP dependency must appear exactly once in world
  • no undeclared dependency handles are allowed in world

Tests Are Environments

Tests are just another environment:

  • same logical dependency identity
  • different baseline world
  • optional per-test world { ... } derivation

That keeps one runtime model for:

  • app code
  • local development
  • integration tests
  • production