ADR 0010: First-class device-interlock bypass — permission-gated, time-boxed, annunciated, edge-enforced¶
Status: Accepted Date: 2026-06-16 Issue: #575 Related: ADR 0007 (parent — device-level interlocks), ADR 0005 (permission vocabulary)
Context¶
ADR 0007 shipped device-level interlocks on the DO/AO output blocks:
while the wired ILCK input or the interlockAddress device-read signal
trips, the block forces its safeValue instead of the commanded IN. Its
"bypass stance (v1)" was documented-only: overriding the source block of a
wired ILCK through the runtime's normal audited tag-write path suppresses
the trip, and the write lands in the audit trail. That is a bypass in effect,
but it has none of the controls a process plant expects of one:
- Not gated. Anyone with the
operatepermission (every operator) can write a tag; nothing distinguishes "command this output" from "disable a protection." - Not marked. The audit record reads as an ordinary tag write, not an interlock bypass — invisible to a reviewer scanning for protection overrides.
- Not time-boxed. A suppressed trip stays suppressed until someone remembers to undo it. Forgotten bypasses are a classic incident precursor.
- Not annunciated. Nothing on the faceplate says "this interlock is currently bypassed."
- Doesn't cover
interlockAddress. The tag-write trick only reaches a wiredILCKsource; a device-read trip can't be bypassed at all.
Traditional DCS practice (DeltaV, and PLC practice generally) treats bypass as a first-class state: gated behind a supervisory/engineering permission, time-boxed with automatic expiry, and continuously annunciated while active. Pharma customers will expect Management-of-Change-grade bypass handling, and 21 CFR Part 11 expects the override and its justification in the record.
The hard constraint is the same one that motivated ADR 0007: the device interlock is enforced in the FB scan on the edge node precisely so it keeps protecting through a control-plane partition. A bypass — and especially its expiry — must therefore also be enforced on the edge. If the control plane owned the bypass timer, a partition could strand an output unprotected past its intended window, which is the exact failure ADR 0007 set out to prevent.
Decision¶
Device-interlock bypass becomes a first-class, edge-enforced runtime state
on the DO/AO blocks, set only through a permission-gated gateway API and
recorded in the audit trail.
- Edge-owned, time-boxed, auto-expiring. The bypass deadline lives on the block's interlock and is evaluated every FB scan against the runtime clock. When the deadline passes, the bypass clears and the interlock re-arms — on the edge, with no control-plane involvement, so it survives a partition. The bypass is never persisted: a runtime restart or network hot-swap re-arms the interlock (the safe direction).
- Suppresses the entire trip. A bypass suppresses both the wired
ILCKinput and theinterlockAddressdevice-read source. A bypass that left a device-read trip still forcing the output would be useless to the engineer who asked to command it. While bypassed the block writes itsINvalue even when tripped. - Annunciated. A new
ILCK_BYPASSEDboolean output onDO/AOis true while a bypass is in effect;ILCK_ACTIVE(the interlock is forcing the safe value) is correspondingly false while bypassed. Faceplates surface the state as anARMED/TRIPPED/BYPASSEDbadge per output block, and an AlarmDefinition can be wired toILCK_BYPASSEDas the audit companion. - Permission-gated. A new
interlock:bypasspermission is added to the ADR 0005 vocabulary. It is not part of the cumulative read→admin tier ladder: it is granted by default to engineer and admin only — not to supervisor. Bypassing a device interlock requires engineering knowledge of the protection being disabled, not supervisory sign-off. Deployments may re-assign it through their roles file like any other permission. - Audited (set and clear). The gateway records an
AuditRecord(action: Command,category: interlock-bypass) on every set and every clear, carrying the acting user, a required reason, the target block, and — on set — the computed expiry timestamp.
Auto-expiry in the audit trail (decision: bounded grant, not a discrete event)¶
Auto-expiry happens autonomously on the edge, where AuditRecords are not
originated (they route through the gateway with the authenticated identity).
Rather than build an edge→audit event bridge, the set record bounds the
authorized window: it states the exact expiry timestamp, so an auditor reading
it knows the protection was suppressed for exactly [t₀, t₀+d]. This is the
Management-of-Change permit model — one authorizing action grants a window; the
permit lapsing at its end is the absence of an extension, not a new signed
event. The ILCK_BYPASSED → false transition at expiry is independently
observable (faceplate, and any AlarmDefinition wired to it). A discrete,
machine-emitted "expired" record from the edge is deferred; it would require
the edge to originate audit records and buys little over the bounded grant.
BPCS, not SIS¶
Unchanged from ADR 0007: none of this is a safety instrumented function. A bypassable BPCS interlock is appropriate for process protection; safety- critical trips remain hardwired or in a certified safety PLC and are not bypassable through this path.
Framing reconciled by ADR 0011
The "safety-critical trips remain hardwired or in a certified safety PLC" phrasing here predates ADR 0011. The decision in this ADR is unchanged. The accurate framing is that a CNDCS interlock is a BPCS-layer protection function that can be credited as an independent protection layer (IEC 61511 Clause 9.2); whether a hazard also requires an independent SIS is a per-process PHA/LOPA decision. The point preserved here is narrower and still holds: where a function is assigned to an SIS, that SIS is not reachable through this bypass path.
Alternatives Considered¶
- Leave the v1 documented-only stance. Rejected — it fails every
expectation above; the tag-write "bypass" is unmarked, ungated, unbounded,
and can't touch
interlockAddress. - Gateway- (control-plane-) owned bypass timer. A bypass flag and expiry held in the control plane, pushed to the edge. Rejected: it re-introduces the partition gap ADR 0007 closed — a partition during a bypass could leave the output unprotected past its window because the expiring authority is unreachable. The timer must be where the interlock is.
- Grant
interlock:bypassto supervisor (cumulative tier). Rejected for the default: a bypass is an engineering judgement about a specific protection, not a sign-off; cumulativeness would also hand it to admin-above but is wrong at the supervisor rung. Deployments that staff differently set it in their roles file. - A discrete edge-emitted "expired" AuditRecord via MQTT bridge. Deferred — see above. Adds a new edge→audit surface for marginal gain over the bounded grant record.
- Persist the bypass across runtime restart/hot-swap. Rejected: re-arming a protection on restart is the safe direction; a bypass surviving a restart could silently outlive the conditions that justified it.
Consequences¶
- Code:
pkg/fbruntime/{types,runtime}.go(theBypassableinterface,FBContext.Nowclock,Runtime.BypassInterlock/ClearInterlockBypass);pkg/fbruntime/blocks/{interlock,qx,ao}.go(bypass state +ILCK_BYPASSEDoutput);pkg/blockcatalog/catalog.go(the new output);internal/adapter(NetworkManager passthrough + runtime HTTP…/blocks/{block}/bypass);internal/gateway(theinterlock:bypasspermission, the CM-scoped set/clear routes, audit);pkg/auth/authz.go(vocabulary + default grant); gateway UI (bypass dialog + per-block badge in the ControlModule detail). No CRD shape change. - API: two new routes under
/api/v1/sites/{site}/controlmodules/{cm}/interlock/bypass(POSTset,DELETEclear), documented indocs/api-reference.mdper ADR 0003. - Compliance: strengthens 21 CFR Part 11 (an interlock override is now a
distinct, reason-bearing, attributable record, not an anonymous tag write)
and IEC 62443 SR 1.1/SR 2.1 (a sensitive capability gated by a dedicated,
least-privilege permission).
docs/compliance/{iec62443,21-cfr-11}.mdnote the capability. - Operations: a bypassed interlock is visible as
BYPASSEDon the ControlModule faceplate and (where wired) as an alarm; it auto-expires, and an engineer/admin can clear it early. - Reversibility: high — the block output and the permission are additive; with no bypass set, behavior is identical to ADR 0007. Removing the permission from the vocabulary would be a breaking config change (ADR 0005 deprecation discipline) only after deployments write roles files against it.