Documentation · design
Importers and connectors
Design document. The core of Archipelago depends on neither; it depends on the facts they produce.
Importer
interface Importer {
id: string // 'niagara-station', 'jci-caf', ...
formats: FormatSniffer[] // magic bytes and structure, never extension alone
import(bytes, options): ImportResult
}
ImportResult = { artifact, assertions[], bindingHints[], questions[], coverage, redactions[], warnings[] }Pure: no sockets, no second file, no database, run in a worker with memory and time limits. Archive handling is hardened: caps on entry count, entry size, inflated size and ratio; entries read by name into memory and never written to disk; XML parsed by a reader that resolves no entities. The result reports coverage (typed, attached, unknown) so an import is honest about what it did not understand.
Connector
interface Connector {
id: string
describe(): { capabilities: { discover, read, subscribe, history, alarms, write: false }, configSchema, nativeRefSchema }
open(config, context): Promise<Session>
}
interface Session {
discover(scope?): AsyncIterable<DiscoveredNode>
read(refs): Promise<Reading[]>
subscribe(refs, opts?): AsyncIterable<Reading>
history?(ref, range, cursor?): AsyncIterable<HistoryBatch>
alarms?(cursor?): AsyncIterable<AlarmEvent>
health(): Health
close(): Promise<void>
}Every reading carries its source, so the model records it as observed with the connector as provenance. Cursors make histories and alarms resumable across restarts. Backpressure is the connector's job. A connector runs in the edge process by default and can be moved to a child process over the same interface when isolation matters.
Write capability
A separate interface, WritableSession, with write(ref, value, priority, reason) and release. No early connector implements it. When it arrives: enabling it per connector is an admin action, each write needs a role that grants it, carries a reason, and is audited. Read-only by default is a type, not a setting.
Binding hints
A point carries zero or more bindings: a connector id and a native reference, with provenance. Importers emit binding hints when a file holds a native address. A station backup's BACnet proxy extensions hold device instance, object type and object instance for every proxied point, so the BACnet/IP connector can read those controllers directly, with no station software in the loop. A controller file holds the same object list. A register map is itself a set of bindings.
Planned implementations
See Integrations for every source with its status and what it cannot see.