Topology Specification
Purpose
Sigil topology defines the canonical representation of named runtime boundaries for topology-aware projects.
Topology is declaration only. Concrete environment worlds live in config modules.
Outside projects, Sigil uses the same topology and world constructors directly in a single file with ordinary local names and a local top-level c world.
Canonical Files
A topology-aware project uses:
src/topology.lib.sigil
config/.lib.sigil
src/topology.lib.sigil is the canonical source of truth for:
- declared boundary handles
- declared environment names
config/ is the canonical source of truth for:
- one selected environment's runtime world
- selected env declarations exposed to application code through
•config.
src/policies.lib.sigil is the canonical source of truth for:
- boundary rules over labelled data
- trusted transforms referenced by
Through(...)
Topology Surface
§topology defines:
t Environment=Environment(String)
t FsRoot=FsRoot(String)
t HttpServiceDependency=HttpServiceDependency(String)
t LogSink=LogSink(String)
t ProcessHandle=ProcessHandle(String)
t PtyHandle=PtyHandle(String)
t SqlHandle=SqlHandle(String)
t TcpServiceDependency=TcpServiceDependency(String)
t WebSocketHandle=WebSocketHandle(String)
λenvironment(name:String)=>Environment
λfsRoot(name:String)=>FsRoot
λhttpService(name:String)=>HttpServiceDependency
λlogSink(name:String)=>LogSink
λprocessHandle(name:String)=>ProcessHandle
λptyHandle(name:String)=>PtyHandle
λsqlHandle(name:String)=>SqlHandle
λtcpService(name:String)=>TcpServiceDependency
λwebsocketHandle(name:String)=>WebSocketHandle
†runtime and world entry roots define the canonical env surface:
t World={clock:†clock.ClockEntry,fs:†fs.FsEntry,fsRoots:[†fs.FsRootEntry],fsWatch:†fsWatch.FsWatchEntry,fsWatchRoots:[†fsWatch.FsWatchRootEntry],http:[†http.HttpEntry],log:†log.LogEntry,logSinks:[†log.LogSinkEntry],process:†process.ProcessEntry,processHandles:[†process.ProcessHandleEntry],pty:†pty.PtyEntry,ptyHandles:[†pty.PtyHandleEntry],random:†random.RandomEntry,sql:†sql.SqlEntry,sqlHandles:[†sql.SqlHandleEntry],stream:†stream.StreamEntry,tcp:[†tcp.TcpEntry],timer:†timer.TimerEntry,websocket:†websocket.WebSocketEntry,websocketHandles:[†websocket.WebSocketHandleEntry]}
λworld(clock:†clock.ClockEntry,fs:†fs.FsEntry,fsWatch:†fsWatch.FsWatchEntry,http:[†http.HttpEntry],log:†log.LogEntry,process:†process.ProcessEntry,pty:†pty.PtyEntry,random:†random.RandomEntry,sql:†sql.SqlEntry,stream:†stream.StreamEntry,tcp:[†tcp.TcpEntry],timer:†timer.TimerEntry,websocket:†websocket.WebSocketEntry)=>World
λwithFsRoots(fsRoots:[†fs.FsRootEntry],world:World)=>World
λwithFsWatchRoots(fsWatchRoots:[†fsWatch.FsWatchRootEntry],world:World)=>World
λwithLogSinks(logSinks:[†log.LogSinkEntry],world:World)=>World
λwithProcessHandles(processHandles:[†process.ProcessHandleEntry],world:World)=>World
λwithPtyHandles(ptyHandles:[†pty.PtyHandleEntry],world:World)=>World
λwithSqlHandles(sqlHandles:[†sql.SqlHandleEntry],world:World)=>World
λwithWebSocketHandles(websocketHandles:[†websocket.WebSocketHandleEntry],world:World)=>World
Compile-Time Rules
Topology declaration location
In project mode, calls to these constructors are only valid in src/topology.lib.sigil:
§topology.fsRoot§topology.httpService§topology.logSink§topology.processHandle§topology.ptyHandle§topology.sqlHandle§topology.tcpService§topology.websocketHandle§topology.environment
World entry location
In project mode, calls to †http., †fs.Root, †fsWatch., †fsWatch.Root, †log.Sink, †process., †pty., †sql., and †websocket.* world-entry constructors are only valid in:
config/*.lib.sigil- test-local
world { ... }clauses
Ambient env access
In project mode, process.env access is only valid in config/*.lib.sigil.
In standalone mode, process.env may be read directly because there is no separate config module.
It is invalid in:
src/topology.lib.sigil- ordinary application modules
- tests
- any other project source file
Dependency-aware API usage
Topology-aware HTTP/TCP APIs require dependency handles:
§httpClient.*requiresHttpServiceDependency§tcpClient.*requiresTcpServiceDependency
The compiler rejects:
- raw URLs passed to topology-aware HTTP client APIs
- raw host/port values passed to topology-aware TCP client APIs
- dependency kind mismatches
Label-aware boundary rules operate on exact named boundaries:
§file.*AtrequiresFsRoot§fsWatch.watchAtrequiresFsRoot§log.writerequiresLogSink§process.runAt/§process.startAtrequireProcessHandle§pty.spawnAt/§pty.spawnManagedAtrequirePtyHandle§sql.all/§sql.one/§sql.exec.../§sql.raw...requireSqlHandle§websocket.route/§websocket.connectionsrequireWebSocketHandle§httpServer.websocketRoute/§httpServer.websocketConnectionsrequireWebSocketHandle
Validate-Time Rules
Validation is environment-specific.
For selected environment :
src/topology.lib.sigilmust existmust be declared in topologyconfig/must exist.lib.sigil config/must export.lib.sigil worldworldmust provide all primitive effect entries- every declared
FsRootmust appear in bothfsRootsandfsWatchRoots - every declared
SqlHandlemust appear insqlHandles - every other declared named boundary must appear in the matching
worldentry collection - no undeclared boundaries may appear in
world - boundary names must be unique in topology
- non-
worldtop-level declarations in that config module are exposed through
the selected config root •config.
Execution Model
Topology-aware commands require an explicit environment:
sigil validate --env
sigil run --env
sigil test --env
Sigil does not provide an implicit default environment for topology-aware projects or for code that reads •config..
Standalone files with a local top-level c world do not require --env.
Test-World Observation
Topology-aware tests assert exact named-boundary outcomes through the active test world. Canonical examples include:
※check::file.existsAt(path,•topology.exportsDir)※check::fsWatch.watchingAt(path,•topology.exportsDir)※check::log.containsAt(message,•topology.auditLog)※observe::fsWatch.watchesAt(•topology.exportsDir)※observe::process.commandsAt(•topology.govBrCli)※observe::pty.writesAt(•topology.assistantShell)※check::pty.spawnedOnceAt(•topology.assistantShell)※observe::sql...is intentionally absent in v1; SQL tests currently assert results through ordinary program output and fixture setup※observe::websocket.receivedAt(•topology.liveUpdates)※check::websocket.connectedOnceAt(•topology.liveUpdates)
Diagnostics
Topology diagnostics use SIGIL-TOPO-*.
Current codes include:
SIGIL-TOPO-MISSING-MODULESIGIL-TOPO-MISSING-CONFIG-MODULESIGIL-TOPO-INVALID-CONFIG-MODULESIGIL-TOPO-ENV-REQUIREDSIGIL-TOPO-ENV-NOT-FOUNDSIGIL-TOPO-ENV-ACCESS-LOCATIONSIGIL-TOPO-CONSTRUCTOR-LOCATIONSIGIL-TOPO-RAW-ENDPOINT-FORBIDDENSIGIL-TOPO-DEPENDENCY-KIND-MISMATCHSIGIL-TOPO-INVALID-HANDLESIGIL-TOPO-DUPLICATE-DEPENDENCYSIGIL-TOPO-DUPLICATE-BINDINGSIGIL-TOPO-MISSING-BINDINGSIGIL-TOPO-BINDING-KIND-MISMATCH