Publication note. The application captures in this article contain demonstration and test data, not real customer, member, patient, claim, provider, user, or production-record information. Environment, host, database, and server identifiers were removed where present.

The Architectural Problem

Long-running enterprise work rarely fits a single status column. A claim can be received, reviewed, adjudicated, paid, appealed, reopened, and archived. Some of those facts describe the present; others describe a durable milestone. Several tracks can advance independently. What a user may do next depends on a combination of facts rather than one enumerated state name.

An enumerative state machine attempts to name every valid combination. With n independent Boolean statuses, however, the potential state space contains 2n combinations. Even a modest catalogue quickly makes a hand-authored graph incomplete, repetitive, and difficult to govern.

The I.T.S. Framework takes the opposite approach:

  1. Define a finite catalogue of meaningful statuses.
  2. Represent an entity's current state as the subset of those statuses currently true.
  3. Define actions as transformations that assert some statuses and retract others.
  4. Define applicability as predicates over the current state and relevant related states.
  5. Store the declarations as data and let the framework compile and execute them.

The engine does not know what Approved, Archived, or Carrier Paid means. It knows how to evaluate sets, guards, and transformations. Business meaning remains in configuration.

Current state a set of flags — one BIGINT Which actions apply? applicability rules decide required / forbidden flags Execute one action the transition flags added / removed New state loop
Figure 1. The conceptual loop. Everything after §1 is the mechanism that makes this loop fast and configurable without code.

Operating Context and Architectural Boundary

The production I.T.S. Framework desktop runtime and its desktop modules target .NET 10 for Windows. The stack includes Windows Forms, ADO.NET, DataSet/DataRow, and SQL Server 2025. The database is the authoritative contract; the WinForms interface binds directly to relational runtime objects and obtains workflow configuration through the shared data runtime.

Deployments can run on premises, in a private cloud, or on AWS or Azure. SQL Server can be local, hosted on a cloud virtual machine, or supplied through a managed cloud database service when its latency, integration, security, operational, and feature-compatibility characteristics fit the deployment.

In the principal operating model, application servers remain close to SQL Server and users connect through RDP or RDS. The remote client receives pixels. The internal desktop architecture therefore does not require an HTTP/JSON boundary between every WinForms module and the database.

This boundary is deliberate. The model described here is not a blanket recommendation for public browser applications, offline clients, untrusted networks, or systems that require an independently versioned public API or domain contract. Those environments introduce different trust, latency, distribution, and compatibility requirements.

The Formal State Space

Fix one workflow W. Let its status universe be the finite set

UW = {u0, u1, …, un-1},   0 ≤ n ≤ 63.

A workflow state is a subset of that universe:

S(W) = ℘(UW) ≅ {0,1}n.

The set reading and the vector reading describe the same object. In the set reading, a status is either a member of the current state or it is not. In the vector reading, the statuses are the multiple Boolean dimensions of the state space, and each individual status supplies one coordinate:

s = (b0, b1, …, bn-1),   bi ∈ {0,1}.

A status is therefore not an enumerated name for the entire state. It is one independent dimension along which that state can vary. The complete state is the multidimensional Boolean vector formed by all status coordinates in the selected typed universe.

ReadingFormal objectFramework representation
SetsUWThe named statuses currently true
Vectors ∈ {0,1}nThe individual bits of flg
Scalar encodingφW(s)One nonnegative BIGINT

The potential state space contains 2n combinations. That is not the same as saying every combination is reachable. Initial conditions, mutual-exclusion rules, guards, and the configured action catalogue determine a reachable subset RWS(W). This distinction matters: the algebra defines what can be represented; configuration defines what the deployed process can actually produce.

Definition: current state. In the runtime log, flg represents the statuses currently true. It is not the complete historical record. The append-only log and the monotonic acc_flg field preserve history separately.
n = 3 : the state space is a cube; each corner is one state vector (0,0,0) (1,0,0) (0,0,1) (1,0,1) (0,1,0) (1,1,0) (0,1,1) (1,1,1) T₍a,r₎ an operator moves the entity from one corner to another at n = 63 this cube has 2⁶³ corners
Figure 2. The state space as a hypercube. Transitions are not edges in a hand-drawn graph — they are operators that may cross the cube in any direction.

Encoding State as One Integer

Assign each status ui a stable bit index i. The encoding is

φW(s) = Σi=0n-1 χs(ui) · 2i,
with φW : ℘(UW) → {0,1,…,2n-1}.

Here χs is the indicator function: it returns 1 when the status belongs to the state and 0 otherwise. The codomain is the interval of representable masks, not all integers. Within that interval, the encoding is bijective: every subset has exactly one mask and every valid mask decodes to exactly one subset.

More precisely, φW is an isomorphism between the Boolean algebra of subsets and the algebra of n-bit masks under bitwise operations:

Set operationMask operationMeaning
sts | tStatuses present in either set
sts & tStatuses present in both sets
s \ ts & ~tStatuses in s but not t
ms(s & m) = mThe state contains every required bit
sm ≠ ∅(s & m) > 0The state contains at least one selected bit

The cost of each mask expression is bounded by a small, fixed number of scalar operations; it does not grow with the number of set bits inside the mask. That does not make an entire SQL query constant-time. Row count, joins, memory, I/O, cardinality estimation, and access paths still determine query cost.

The complement requires a universe

Set complement is always relative to UW. A SQL Server BIGINT has 64 physical bits, while a valid workflow uses only indices 0 through 62. Therefore ~m by itself flips bits outside the workflow universe and may produce a negative integer. Expressions such as s & ~r remain safe because s contains only valid state bits; a standalone complement must be intersected with the workflow's universe mask.

Index and value are different contracts

ValuePurposeExample
ixReadable, stable bit position used while authoring39
flgComputed value used by the runtime549755813888
CASE
    WHEN [ix] > 62 THEN -1
    ELSE POWER(CONVERT(BIGINT, 2), [ix])
END

ITS_MLWFFlg.flg is computed from ix, so the authoring index and runtime value cannot drift independently.

flg = 1546 011 010 19 08 07 06 05 04 13 02 11 00 Archived Approved Reviewed bit index
Figure 3. One integer carries the whole set. An entity whose value is 1546 has bits 1, 3 and 9 raised: it has been reviewed, approved and archived.

Actions as Guarded State Operators

An action declares two sets: statuses to assert, a, and statuses to retract, r. Its state operator is

T(a,r)(s) = (s \ r) ∪ a

(s & ~r) | a.

An action is therefore an assert/retract status operator over a typed state universe. Its masks identify the status dimensions to make true and the dimensions to make false; they do not replace the state with one enumerated label.

The operator T(a,r) is a total function on the representable state space. The business transition is not necessarily total, because the action may be legal only when a guard holds. With guard g, the configured transition is the partial function

τ(a,r,g)(s) = T(a,r)(s)   when   g(s)=true;
τ(a,r,g)(s) is undefined otherwise.

This separation is fundamental. The operator answers what would the state become? The guard answers may this operator be applied here? Confusing effect with restriction is one of the most dangerous configuration errors in a workflow engine.

Current state s
      |
      v
Evaluate guard g(s) ---- false ----> refuse the action
      |
     true
      |
      v
Apply T(a,r) ----> new current state

Algebraic Properties and Their Limits

The closed form makes several properties provable rather than anecdotal.

Idempotence of the state transformation.

T(T(s)) = (((s \ r) ∪ a) \ r) ∪ a
= (s \ r) ∪ (a \ r) ∪ a
= (s \ r) ∪ a = T(s).

No condition ar = ∅ is required. If the same bit appears in both masks, the final assertion wins and repeated application still reaches the same state.

This proves that repeating the pure state calculation makes no further state change. It does not prove that replaying an entire business action is harmless. Audit inserts, notifications, external calls, financial postings, and other side effects require their own transaction and idempotency controls.

Assertion dominates retraction. Within one operator, union is applied after difference. Therefore a bit present in both masks remains set:

a ∩ r ≠ ∅   ⇒   assertion wins on the overlap.

This permits the useful form “clear every status in this exclusive group, then assert this one.” A canonical representation can normalize the retraction set to r \ a without changing the function.

Closure under composition. Applying T1 and then T2 still produces an operator from the same family:

T(a2,r2) ∘ T(a1,r1)
= T(a',r'),
a'=(a1 \ r2) ∪ a2,   r'=r1 ∪ r2.

A sequence can therefore be summarized by another assert/retract pair. Derived effects such as snflg can be folded into the retraction mask before execution without creating a richer operator type.

General non-commutativity, not universal non-commutativity. Some operators commute, but conflicting operators generally do not:

T2 ∘ T1 ≠ T1 ∘ T2   in general.

If one action asserts a bit that another retracts, the last action normally determines that bit. Independent actions over disjoint status sets do commute. Because order can matter, the runtime preserves the transition sequence in an append-only log.

Monotonicity with respect to input state. For a fixed action, if st, then T(s) ⊆ T(t). Retraction and assertion do not reverse the subset order. A sequence can still appear to move “backward” in business terms because its configured retraction set can remove a progress status.

The Four Canonical Guard Polarities

The engine's guard grammar combines four quantified relationships between current state s and a configured mask m:

ClauseSet formMask formReads as
Require allms(s & m) = mMust have every selected status
Require anysm ≠ ∅(s & m) > 0Must have at least one
Forbid anysm = ∅(s & m) = 0Must have none
Forbid allms(s & m) ≠ mMust be missing at least one
IF (@sflg   <> 0 AND (@flg & @sflg)   <> @sflg)  RETURN 0; -- require all
IF (@soflg  <> 0 AND (@flg & @soflg)   = 0)      RETURN 0; -- require any
IF (@snflg  <> 0 AND (@flg & @snflg)  <> 0)      RETURN 0; -- forbid any
IF (@sonflg <> 0 AND (@flg & @sonflg) = @sonflg) RETURN 0; -- forbid all

The four clauses arise from two quantifiers—all and any—crossed with two polarities—require and forbid. A guard row can combine the clauses by conjunction.

The empty mask disables an optional clause

The empty set is not naturally true for every primitive. “Require any element of the empty set” is false. The engine therefore guards each optional branch with m <> 0. In the configuration language, zero means this clause is absent, so the enclosing guard treats it as neutral.

A precise expressiveness boundary

These clauses are complete for the engine's chosen four-polarity mask grammar. They are not functionally complete for every Boolean predicate over n bits. A condition such as “at least two of these three statuses,” exclusive-or, or an arbitrary disjunction of conjunctions cannot always be represented by one row containing four masks. Such requirements need multiple configured expressions, a composed group, a checklist, or a specialized validator.

Rigor matters here. Calling the four clauses “all possible bitmask predicates” would overstate the model. Their value is that they cover a large, understandable, efficiently evaluated class of workflow preconditions while preserving a clear escape boundary for requirements outside that class.

Typed Workflows, Status Dimensions, and Threads

Each workflow owns a separate status universe. Reusing bit index 8 in two workflows does not make the statuses equivalent. The integer alone is therefore not the complete type of a state; the meaningful value is the pair (workflow_id, flg). The workflow_id selects the universe in which the mask must be interpreted.

Universes contain thread-specific spaces

Within one workflow universe UW, each thread j selects a set of status dimensions DW,jUW. Those dimensions induce the thread's own Boolean state space:

S(W,j) = ℘(DW,j) ≅ {0,1}|DW,j|.

The hierarchy is therefore explicit: the workflow identifies a typed universe; statuses supply its Boolean dimensions; and threads organize selected dimensions into distinct business spaces. Different workflow universes can contain different status catalogues and different collections of thread spaces.

When the configured threads form independent, disjoint tracks, their dimensions partition the workflow universe:

UW = DW,1 ⊎ DW,2 ⊎ … ⊎ DW,m,
S(W) ≅ S(W,1) × S(W,2) × … × S(W,m).

If a deployment uses threads as overlapping classifications instead, each thread still identifies a valid subspace, but the product expression is no longer an independent decomposition. The configuration determines which interpretation applies.

Across independent workflows, the total application state is another typed Cartesian product:

Stotal = S(W1) × S(W2) × … × S(Wk).

For finite Boolean spaces, direct-sum and product constructions are isomorphic, but “product of typed states” expresses the implementation more accurately: every universe retains its own catalogue, thread spaces, encoding, and identity. The framework defines no business comparison between equal numeric masks from different universes.

Threads provide a local progress coordinate

A thread can impose a configured step order over the status dimensions assigned to its space. The runtime may then derive a progress summary for thread DW,j:

pW,j(s) = max { step(i) : ui ∈ DW,j and ui ∈ s }.

This is an ordinal summary function, not a linear projection in the strict algebraic sense. Across several threads, progress becomes the tuple

pW(s) = (pW,1(s), pW,2(s), …, pW,m(s)).

Two entities can therefore be ahead on different tracks without either being globally “farther along.” That partial ordering is the formal reason the framework does not force all workflow progress into one scalar.

Workflow “Claim Processing” — a 3-dimensional universe Review Received Screened Approved Closed Financial Priced Invoiced Paid Settled Compliance Screened Audited Cleared position = (Review: Approved, Financial: Invoiced, Compliance: Screened)
Figure 5. Three independent axes. The entity is simultaneously somewhere on every one. Filled markers are the furthest point reached per dimension; hollow markers are positions not yet reached.

The Schema as an Authoring Language

The physical engine is driven by two principal catalogues and a normalized authoring surface.

ITS_MLWFFlg: the status catalogue

ColumnRole
workflow_idSelects the typed status universe.
ixStable bit index from 0 through 62.
flgComputed value 2ix.
stepOptional ordinal position within a configured thread.
step_threadIdentifies the track to which the status belongs.
nflgStatuses automatically retracted whenever this status is asserted.
pplcbl*Predicates that govern asserting this status.
rmvpplcbl*Predicates that govern retracting this status.

ITS_MLWFActn: the operator catalogue

A row represents a reusable expression. Historical naming calls it an action, but its configured masks can be consumed as an effect, a guard, or a filter according to context.

ColumnMeaningRole
flgStatuses explicitly assertedEffect
nflgStatuses explicitly retractedEffect
snflgRetractions derived from asserted statusesDerived effect
npflgNegative propagation to related entitiesEffect
pplcblflgRequire all selected statusesApplicability
pplcblorflgRequire at least one selected statusApplicability
pplcblnflgForbid every selected status individuallyApplicability
pplcblprvflgRequire statuses on a related or previous entityApplicability
pplcblprvnflgForbid statuses on a related or previous entityApplicability
chkflgRequire checklist itemsApplicability
chknflgForbid blocking checklist itemsApplicability
oflgFilter rows that have all selected statusesQuery
onflgFilter rows that have none of the selected statusesQuery

ITS_MLWFActnFlg: the normalized declaration

Administrators do not need to calculate decimal masks or decide which of thirteen columns receives a bit. They author normalized statements:

(actn_id, flg_ix, mode_id)

Example:
(Approve, Approved, Assert)
(Approve, Reviewed, Require all)
(Approve, Archived, Forbid any)

The action-flag compiler validates the declaration, routes it to the correct semantic role, and recomputes the denormalized masks used by the execution path. The wide mask row is therefore a compiled projection; the normalized rows are the authoring contract.

SOURCE — authored ITS_MLWFActnFlg (actn 7201, ix 3, mode 1) (actn 7201, ix 8, mode 2) (actn 7201, ix 1, mode 3) (actn 7201, ix 9, mode 4) mode_id → ITS_MLFlgMode (11 named roles) Save validate + derive DERIVED — engine-maintained ITS_MLWFActn flg = 8 nflg = 256 snflg = (from ITS_MLWFFlg.nflg) pplcblflg = 2 pplcblnflg = 512 oflg, onflg, npflg, chk… (13 total) never written by hand Read in the right order The mask columns are the compiled artefact. Diagnosing configuration by reading them is reading the output of the build.
Figure 4. Source and projection. An editor declares (action, bit, role); the action-flag compiler validates the statement, routes it to the right column, and recomputes the derived masks — including snflg (§9).
Complete I.T.S. Entity Management workspace showing workflow actions, status flags, action-status flag modes, and action threads
The authoring surface. Actions, status flags, semantic modes, groups, security groups, ranks, and threads are maintained together. The administrator works with named declarations; the runtime consumes compiled masks.

This distinction is what makes a collection of visually indistinguishable BIGINT columns governable. A naked integer has no semantic role. The normalized row supplies that role before compilation.

Three Roles for the Same Mask Vocabulary

The stem flg means “a set of statuses.” Prefixes describe how that set is interpreted. The same compact vocabulary participates in three different operations.

ContextPositive maskNegative maskResult
EffectBits to assertBits to retractA new state
ApplicabilityStatuses requiredStatuses forbiddenAllowed or refused
FilterRows must have theseRows must not have theseA selected work set

Role 1: effect

new_flg = (old_flg & res_nflg) | actn_flg

res_nflg = ~(snflg | nflg)

actn_flg asserts statuses. snflg | nflg identifies statuses to retract. The engine inverts that retraction set into the preservation mask res_nflg, so one expression clears and sets bits.

Role 2: applicability

The pplcbl* columns feed the guard grammar. A positive mask can require all or any; a negative mask can forbid any or all. These expressions decide whether an operator is offered and whether execution is valid.

Role 3: filter

oflg and onflg select entities for a work queue. The predicate is mathematically the same kind of relation used by a guard; its result is lifted from one Boolean decision to a set of matching rows.

Complete I.T.S. Operational Dashboard showing a configured workqueue status filter and demonstration claim data
A guard grammar reused as a query. The Workqueue selector exposes named status combinations to users while the engine evaluates the compiled masks over scoped current-state rows.

A mask has no complete meaning without its role. The value 256 can mean “assert Denied,” “retract Denied,” “require Denied,” or “exclude Denied.” Establish the consumer before interpreting the number.

ROLE 1 — Effect what a transition does flg → bits to add nflg → bits to remove mutates the entity ROLE 2 — Applicability when it is allowed pplcblflg → required pplcblnflg → forbidden refuses, never mutates ROLE 3 — Filter which entities to show flg → must have all nflg → must have none a saved query Same columns. The consuming context decides the meaning — establish the role before reading any value.
Figure 6. Three readings of one schema.

Groups as Binding Points

An action group is not merely a folder. It is a binding point that mounts reusable expressions on a particular surface. The consuming surface determines how the expression is read.

Mounted onExpression is consumed as
Command list or dropdownA transition: apply assert and retract masks
Work queue or saved filterA predicate: select matching entity states
Classifier or status displayA named interpretation of a state pattern
Composite groupA reusable part of a larger surface

Security subscriptions intersect with group membership. An expression can exist, be valid for the current state, and still remain invisible because the effective security group does not grant access to the surface on which it is mounted.

Complete I.T.S. Operational Dashboard showing a configured action dropdown and demonstration claim data
The same catalogue at execution time. The Action dropdown presents configured transitions appropriate to the current module, user, group, and entity state.
I.T.S. File Management view showing an Accounting process action group with configured actions
A group in another solution context. File Management consumes an Accounting process group without the workflow engine learning what invoices, orders, or insurance approvals mean.

This reuse is sometimes described as polymorphism. It is not language-level subtype polymorphism; it is controlled semantic reuse. A configured row supplies masks, and a typed consumer selects the operation those masks participate in.

Bound to the group configuration User may use it security Applies to this entity the pplcbl* rules (§10) appears on screen
Figure 7. Three independent filters, each configured separately. A missing option is therefore always one of three questions: is it bound here, may I use it, does it apply to this entity?

Derived Effects and Status-Level Invariants

ITS_MLWFActn contains both nflg and snflg, but they have different ownership.

  • nflg is authored: the action explicitly retracts the selected statuses.
  • snflg is derived: the statuses being asserted contribute their own configured retractions.

Suppose Approved and Rejected are mutually exclusive. The invariant belongs to the status catalogue, not to every action that might assert one of those statuses. If Approved.nflg contains Rejected, then every current or future action that asserts Approved automatically inherits the retraction.

snflg(action) = ⋃ { nflg(u) : u ∈ asserted(action) }.

The union symbol here means bitwise aggregation. The save procedure recomputes that union when declarations change. Action authors do not edit snflg directly.

Why the invariant belongs to the protected status

If every action had to repeat the exclusion rule, correctness would depend on remembering all existing actions and every future action. Attaching the invariant to the status that owns it changes the maintenance problem from “update every consumer” to “declare the rule once.”

Approved.nflg includes Rejected
            |
            +-- Approve action -----------+
            +-- Supervisor Approve -------+-- derive the same retraction
            +-- Batch Approve ------------+
            +-- actions added years later +

Effect is not restriction

Configuration trap. A status-level nflg is an effect. It means “when this status is asserted, retract those statuses.” It does not mean “refuse this status when those statuses are present.” Refusal belongs in an applicability mask or another validator. Confusing the two can remove data instead of producing an error.

Evaluate real deltas

Status-level rules should be evaluated only for bits that actually change:

set_bits = a_flg  & ~flg; -- off before, on after
rmv_bits = a_nflg &  flg; -- on before, off after

Testing every bit named by a broad action would revalidate statuses that are already true or already absent. Delta evaluation aligns validation with the idempotent state operator: when a repeated operator changes no bit, there is no new status transition for a status-level rule to approve.

One declaration Approved.nflg = Rejected on the status that owns the invariant engine action “Approve” action “Auto-approve” action “Bulk approve” action “Reinstate” …and any written later all covered automatically, via snflg
Figure 8. Derivation inverts the cost. The conflict is declared once, on the status that owns it, and every action — past, present and future — is covered.

State, History, and Audit

The runtime preserves three related but distinct facts:

ValueMeaningBehavior
flgStatuses currently trueCan assert and retract bits
acc_flgStatuses that have ever been trueMonotonic; bits never clear
Log rowsOrdered transition historyAppend-only sequence with actor, time, action, and resulting state

The current state is calculated once inside the persistence statement:

INSERT INTO dbo.WorkflowEntityLog
    (..., ltst, flg, acc_flg, actn_flg, actn_nflg, ...)
SELECT
     ...
    ,1
    ,E.flg
    ,E.flg | ISNULL(L.acc_flg, 0)
    ,A.flg
    ,A.res_nflg
    ,...
FROM ...
CROSS APPLY
(
    SELECT (ISNULL(L.flg, 0) & A.res_nflg) | A.flg AS flg
) E;

ITS_ActnGet supplies the preservation mask already derived from explicit and status-level retractions. The persistence procedure therefore cannot accidentally apply nflg while omitting snflg.

The latest log row is marked with ltst = 1. The prior latest row is retired in the same transactional operation. Recording actn_flg and the effective preservation or retraction information allows an auditor to distinguish two transitions that happen to produce the same final mask.

flg answers “where is the entity now?” acc_flg answers “which milestones has it ever reached?” The log answers “in what order, by whom, and through which configured actions did it move?”

WorkflowEntityLog — one row per execution ltst = 0 flg = 2 history ltst = 1 flg = 258 previous state (LEFT JOIN) (old & res_nflg) | actn_flg ltst = 1 flg = 262 acc_flg = 262 new row — now the current state the old row is flipped to ltst = 0
Figure 9. Append-only state. The ltst = 1 row is the present; every other row is the audit trail.

This short excerpt shows the Action Log inside a complete application built with the I.T.S. Framework. The user-facing workspace remains visible while the log exposes the ordered actions beneath it, connecting configured operators to the append-only history described above.

Complete I.T.S. Framework application with the workflow Action Log displayed beneath the active workspace
Configured state history inside the operational workspace. The excerpt shows the runtime log as part of the complete application rather than as an isolated diagnostic window. Each displayed row records an action in time order and preserves the context from which the status vector progressed.

What to watch: Action Log selected at 00:00 · ordered history visible at 00:03 · configured action catalogue at 00:06 · return to the complete log at 00:09. All displayed values are demonstration and test data.

Work Queues, Filtering, and Query Performance

A configured work queue reads an expression as a predicate rather than an effect:

SELECT TOP (1)
       @sflg  = flg,
       @snflg = nflg,
       @soflg = oflg,
       @sonflg = onflg
FROM dbo.ITS_MLWFActn
WHERE id = @workqueue_id;

SELECT L.*
FROM dbo.WorkflowEntityLog AS L
WHERE L.ltst = 1
  AND L.env = @env
  AND (@sflg  = 0 OR (L.flg & @sflg)  = @sflg)
  AND (@snflg = 0 OR (L.flg & @snflg) = 0)
  AND (@soflg = 0 OR (L.flg & @soflg) > 0)
  AND (@sonflg = 0 OR (L.flg & @sonflg) <> @sonflg);

The predicate should be applied after selective relational conditions such as current-row marker, environment, tenant, owner, date range, or entity key. A dynamic expression such as (flg & @mask) = @mask is not normally seekable through an ordinary B-tree index on flg; SQL Server must evaluate it for each candidate row that reaches that stage.

Preferred execution shapeRisky execution shape
Seek or narrow by tenant, environment, current-row marker, owner, and dateBegin with a dynamic bitwise test across the entire log
Evaluate masks over the already-scoped rowsAssume the compact expression automatically makes the query selective
Use computed indexed columns only for stable, high-value fixed predicatesCreate many speculative indexes for arbitrary runtime masks

An index on flg can still serve exact-equality workloads, and an indexed computed column can serve a fixed mask expression when justified. The limitation is specifically the expectation that one ordinary index can seek efficiently for arbitrary masks supplied at runtime.

A bitmask is a cheap test on a row already in scope. It is an expensive way to discover candidate rows without another selective predicate.

1 — Narrow ltst = 1 env = @env INDEX SEEK millions of rows 2 — Materialise INTO #V + CREATE INDEX working set 3 — Scan EvalFlgFltr bitmask, unavoidable result Reversing steps 1 and 3 scans the whole table to answer the same question.
Figure 10. Narrow, materialise, then scan. The bitmask is always a scan; the design question is only how many rows reach it.

The -1 Sentinel and Practical Hazards

-1 means all physical bits, not a valid workflow state

In two's-complement BIGINT, -1 has every physical bit set. The engine uses it as an “all bits” sentinel in helpers and optional mask parameters. It lies outside the valid nonnegative state encoding, which uses bit positions 0 through 62.

  • An index above 62 produces the sentinel rather than overflowing into the sign bit.
  • Rendering helpers can interpret -1 as “all configured statuses.”
  • An optional check mask can default to -1, making chk_flg & flg preserve every valid state bit.

The sentinel must never be persisted as an entity's current state. Treating it as an ordinary state would collapse the distinction between every configured status, unused physical bits, and the reserved sign position.

Never add or sum masks

Set union is bitwise OR, not arithmetic addition. If two masks overlap, addition carries into another bit. For example, 12 and 24 both contain bit 8; 12 + 24 = 36 clears the shared bit through carry and asserts a bit nobody declared. Use | or aggregate normalized single-bit rows through a union-safe method.

Cast large literals explicitly

Large integer-looking constants do not always enter a T-SQL expression as BIGINT. Cast high-bit values explicitly before bitwise operations:

CAST(549755813888 AS BIGINT)

Use parentheses even when precedence is defined

In T-SQL, bitwise AND/OR have higher precedence than comparison operators, and comparisons have higher precedence than logical AND. Therefore flg & m = m evaluates the bitwise expression before equality. Parentheses such as (flg & m) = m should still be used because they make the intended grouping explicit. The ordering is documented in Microsoft Learn's T-SQL operator-precedence reference.

Do not assume a dense catalogue

Bit index i need not have a configured status row. Helpers that walk the physical bit range must tolerate sparse catalogues. A missing catalogue row should not silently eliminate an entity from a result.

Do not edit compiled masks directly

The masks on ITS_MLWFActn are projections maintained from ITS_MLWFActnFlg. Direct updates bypass validation, semantic typing, derivation, and audit. The next legitimate save can overwrite the manual change because the normalized declarations remain authoritative.

Where the Framework Ends

The framework owns the algebra, catalogues, normalized authoring contract, compilation procedures, operator execution, guard grammar, rendering helpers, group composition, and security-aware presentation. Those objects can be deployed without knowing any specific claim, invoice, order, document, or approval process.

A solution owns its workflow catalogue, status names, transitions, applicability rules, group bindings, security subscriptions, checklists, and the entity log that carries state. Those are solution data, even when the framework supplies the tables and procedures that govern them.

The database half and client half are both necessary. SQL Server validates declarations, derives masks, applies state transitions, and preserves audit history. WinForms turns named groups into usable surfaces, hides actions the user may not execute, resolves work queues, and displays status names instead of opaque integers.

  • Solutions do not fork the engine. A new business restriction normally becomes a configured predicate or validator.
  • The engine does not learn business statuses. Literal masks with domain meaning belong in catalogue rows, never framework code.
  • Escape boundaries remain explicit. Cardinality rules, cross-aggregate constraints, external approvals, and distributed side effects may require validators or orchestration beyond the four-polarity grammar.
A deliberate architecture is not a universal architecture. The design is strongest where SQL Server is authoritative, the application runtime is trusted and close to the database, workflows are centrally configured, and the WinForms client is delivered through controlled application-server sessions.

Object Map

The following objects form the conceptual engine. CRUD procedures, audit triggers, and solution-specific tables are intentionally omitted.

ObjectKindResponsibility
ITS_MLWorkFlowTableWorkflow definition and typed isolation boundary
ITS_MLWFFlgTableStatus catalogue, bit index, thread, effects, and status-level rules
ITS_MLWFActnTableCompiled operator and predicate masks
ITS_MLWFThreadTableNamed workflow tracks
ITS_MLWFActnThreadTableAction-to-thread assignment
ITS_MLWFActnGrpTableBinding surface for transitions, filters, and classifications
ITS_MLWFActnGrpActnTableExpression-to-group binding
ITS_MLWFActnGrpGrpTableComposition of groups from other groups
ITS_MLWFActnGrpThreadTableGroup scope by thread or stage
ITS_MLWFSGrpAGrpSubscriptionTableSecurity-group access to an action surface
ITS_MLWFActnFlgTableNormalized (action, bit, mode) authoring contract
ITS_MLFlgModeTableSemantic type catalogue for flag declarations
Action-flag compilerDatabase contractValidates declarations and recompiles masks; implementation name intentionally omitted
ITS_ActnGetTVFReads an expression as an effect and derives res_nflg
ITSWF_GetFlgActnGrpTVFReads grouped expressions as predicates
ITSWF_GetActnGrpsTVFResolves the surfaces on which an expression is mounted
ITS_FnWFEvalFlgFltrTVFSet-based evaluation of the guard grammar
ITS_FnWFEvalFlgFltrScalarFunctionProcedural evaluation of the same grammar
ITSWF_EvalFlgApplicabilityTVFStatus-level validation; one row per violation
ITSWF_FlgApplicabilityMsgTVFRenders violations as human-readable messages
ITSWF_GetStatusTVFConverts masks to status names
ITSWF_GetStatusStepTVFDerives the furthest configured step per thread
ITSWF_GetFlgStrTVFRenders present and absent status names
ITS_GetTallyFlgTVFSupplies the physical bit index/value sequence

Inline table-valued functions are preferred where their relational definitions can be incorporated into the calling plan. Validators return a set of violations: zero rows means success. That convention composes naturally with EXISTS, NOT EXISTS, and APPLY.

Software Engineering Views of the Engine

The algebra describes the engine precisely, but no single diagram can expose every engineering concern. The following views apply complementary notations to the same implementation: orthogonal state regions for concurrency, a data model for authoring and compilation, a sequence diagram for execution order, a Petri net for open intervals, a marker projection for temporal queries, a data-flow pipeline for performance, and a component diagram for authority and trust.

The diagrams preserve the structure of the implemented engine while normalizing solution-specific database, table, trigger, and procedure names. They document the architecture without identifying a client or exposing a solution-specific persistence contract.

Which diagrams apply, and which do not

Most standard state-machine notations break down on this engine for one specific reason: the state is not a label; it is a 63-bit vector. A diagram that assumes one state at a time cannot describe it. The notation must match the question being asked.

NotationVerdictWhy
Harel statechart with orthogonal regionsUseEach bit is an independent concurrent region. This notation expresses simultaneity honestly.
Entity model of the metadata tablesUseThe authoring surface and the derived projection are separate tables; the distinction is invisible without a structural view.
Sequence diagramUseA single save crosses validation, insertion, marker maintenance, and dependent operations. Ordering is the point.
Petri netUseTransitions consume and produce facts. Tokens model pending cycles better than arrows between named states.
Data-flow or query pipelineUsePerformance is governed by predicate order, which is a flow property rather than a structural one.
Component and trust boundaryUseThe engine spans database and client; authority must be drawn explicitly.
Flat finite-state machine, one bubble per stateRejectSixty-three independent bits allow up to 263 representable combinations. A flat graph is not merely large; it represents the model incorrectly.
UML class diagram of workflow domain objectsRejectThere is no parallel workflow domain-class model. Behavior lives in metadata rows and relational runtime contracts.
Use-case diagramRejectIt adds no structural information that the configured action catalogue and authorization model do not already carry.

Orthogonal State Regions

This is the central software-engineering view. An entity does not sit in one named state; it occupies one Boolean sub-state in every applicable region at once. The composite state is the product of those regions, encoded as one BIGINT.

Workflow entity — composite state (63 orthogonal regions) ix 2 · Pending External Response clear (0) set (1) mask 4 ix 17 · Response Acknowledged clear (0) set (1) mask 131072 ix 18 · Response Requested clear (0) set (1) mask 262144 ix 39 · Network Message Sent clear (0) set (1) mask 549755813888 … 59 further independent regions … composite stateflg = Σ (region · 2^ix) → one BIGINT column Regions are independent: an entity can be simultaneously “Response Requested” and “Pending External Response” and not yet “Response Acknowledged.” A flat state machine requires a separate label for every combination. Representable composite states: up to 2^63 — which is why the flat finite-state graph is rejected.
Engineering View 1. Each named status is a two-state orthogonal region. The engine stores the complete product state in a single integer.

Domain and Data Model

The important structural fact is that the normalized authoring surface and the executable form are different tables. Editors write typed rows; the compilation procedure derives the bitmask columns. Hand-editing the derived side corrupts the contract because the source declaration and executable projection no longer agree.

ITS_MLWFFlg workflow_id, ix, name pplcblflg / pplcblnflg … status and bit dictionary status-level applicability masks ITS_MLFlgMode id, name named semantic roles: assert, retract, require, forbid, filter, and others ITS_MLWFActnFlg actn_id, flg_ix, mode_id AUTHORING SURFACE typed, normalized, no mask columns one row per (action, bit, role) ITS_MLWFActn id, name flg, nflg, snflg, oflg, onflg, … (BIGINT masks) DERIVED PROJECTION never hand-edit WorkflowEntityLog entity_id, workflow_id, env flg, actn_flg, actn_id, ts ltst, stts_ltst, ack_ltst, actn_ltst, decision_ltst, event_ltst append-only history flg_ix mode_id (FK) validated compilationderives masks applied on save
Engineering View 2. Metadata topology. The action table's executable mask columns are computed output, not authoring input.
Operational rule. Updating workflow-status or action-status metadata invokes the compilation path, which reads audit identity and time-zone values from SESSION_CONTEXT. An administrative script must establish the required session context before making changes or the update must fail.

State-Advance Sequence

One user action crosses six participants. Ordering is explicit: validation occurs before the insert, and latest-marker projections are recomputed after the append by the database-maintained projection path.

WinForms Client WorkflowLogSave TransitionValidator GuardEvaluator Entity Log Marker Projector invoke action a on entity validate(entity, action) (flg, actn_flg, preservation mask) message — NULL means allowed blocked → abort with catalogue message alternative · blocked: write nothing; return the reason to the client INSERT flg = (previous.flg & preservation_mask) | assert_mask, ltst = 1 AFTER INSERT recompute latest, status, acknowledgement, action, decision, and event markers then update related references, chain state, and the entity digest return refreshed row
Engineering View 3. A single state advance. The guard runs first; database-maintained projections update after the append, never at the caller's discretion.
-- the state operator inside the normalized workflow save path
CROSS APPLY
(
    SELECT (ISNULL(previous_row.flg, 0) & action.res_nflg)
           | action.flg AS flg
) AS next_state;

-- retract first, then assert: T(s) = (s \ r) ∪ a

Petri Net: The External-Response Cycle

A pending condition is not one state name. It is an open interval between two status events. A Petri net expresses that directly: a token resides in the pending place until the acknowledging transition fires.

not yetrequested PENDINGrequest bit set, acknowledgement bit clear acknowledgedclosed Response Requested sets the request bitrecords ts = t₀ Response Acknowledged configured acknowledgement actionsassert the acknowledgement bitsets ack_ltst = 1, ts = t₁ time pending = t₁ − t₀ if the token has not moved: DATEDIFF(DAY, t₀, SYSDATETIMEOFFSET())
Engineering View 4. Pending duration is the token's residence time. In the observed design, the closing event is materialized while the opening event must be recovered from history.
Measured asymmetry. The runtime materializes the closing acknowledgement event through a latest-marker column, but it has no equivalent marker for the opening request event. Deriving t0 therefore requires locating the earlier row whose actn_flg asserted the request bit. That bitmask scan is non-sargable, which makes the query pipeline below essential.

Latest-Marker Projection

Each marker applies the same windowed idiom to a different predicate: select the highest log identity within an entity partition that satisfies a condition. Placing the markers side by side explains how an append-only history can answer several current-state questions with narrow indexed access.

WorkflowEntityLog — one partition, ordered by identity id 101import id 118request id 130status change id 147acknowledgement id 152decision id 168latest row ltst = 1MAX(id) overall ack_ltst = 1MAX(id) where acknowledgement bit was asserted stts_ltst = 1MAX(id) where status changed decision_ltst = 1MAX(id) where decision recorded opening request eventnot materialized — must be located All latest markers are maintained together by the database projection path in one windowed update,and values are written only when their computed marker changes.
Engineering View 5. Every *_ltst column is a materialized argmax over the partition. The opening side of the pending cycle has no equivalent marker.

Query Pipeline: Narrow, Materialize, Scan

The index topology determines the mandatory evaluation order. Current-row, environment, entity, workflow, owner, and date predicates are sargable. A runtime test against an arbitrary bitmask is not. The correct plan narrows through indexed relational columns, materializes the candidate set when useful, and evaluates the mask only over that smaller relation.

1 · NARROWsargable predicates onlyenv, entity_id,workflow_id, ltst = 1 2 · MATERIALIZESELECT … INTO #Candidatesexplicit column listoptional temp-table index 3 · SCANbitmask evaluationconfigured guard functionnon-sargable, small set 4 · JOINmatchesresult set large history →small candidate setcheap at this size Anti-pattern: putting the dynamic bitmask predicate first.Without a matching fixed computed-column strategy, a leading arbitrary mask test scans the complete candidate source.
Engineering View 6. The mandatory order: indexed predicates narrow first; arbitrary bitmask evaluation is deferred until the candidate set is small.
Generic filtered-index rolePredicate
Current row by entity, workflow, and environmentWHERE ltst = 1
Latest status change by entity and scopeWHERE stts_ltst = 1
Latest action by entity and scopeWHERE actn_ltst = 1

Component and Trust Boundary

The engine is neither the database alone nor the client alone. Both halves participate, but only one side is authoritative. The client improves usability; the database preserves correctness regardless of the caller.

Client — WinForms · renders status and action groups as surfaces· hides operators the user may not apply· sends action and entity selection· posts normalized metadata changesConvenience only — never the guarantee.An incomplete client payload cannot define correctness. Authoritative SQL Server Database · evaluates applicability rules· applies the state operator· maintains derived markers· emits catalogue messagesAuthoritative. Rules hold hereregardless of the caller. trust boundary action request allow or refuse + message Observed boundary risk: any solution-specific save path that bypasses transition validation also bypasses its guards.
Engineering View 7. Any execution path that bypasses the validating persistence boundary bypasses the workflow rules with it.
Known integration risk. One implementation review identified a solution-specific persistence path that did not invoke the standard transition validator. Its client and procedure names are intentionally omitted. The architectural lesson is general: UI filtering is not enforcement, and every write path must converge on the authoritative guard boundary.
Reading order. Engineering View 1 explains what a state is; View 2 shows where behavior is authored and compiled; View 3 shows how a transition executes; Views 4 and 5 explain how durations and current projections emerge from history; View 6 shows how to query that history at scale; and View 7 establishes where correctness is enforced.

Final Principle

The engine is the implementation of a small, explicit algebra:

  • A workflow state is a subset of a finite, typed status universe.
  • Statuses are the Boolean dimensions of that state space.
  • A mask is a lossless scalar encoding of that subset.
  • An action is an assert/retract status operator.
  • A legal transition is that operator restricted by a configured guard.
  • A work queue applies related predicates across a scoped relation of current states.
  • A thread selects status dimensions within its universe, defines a business state space, and yields a derived ordinal progress summary.
  • The append-only log preserves ordering, while acc_flg preserves milestone reachability.

The mathematical structure does not replace the enterprise details. It gives those details a stable language. Statuses, actions, rules, groups, permissions, and work queues can change without changing the mechanism that evaluates them.

Configure the business vocabulary. Compile it into masks. Execute one rigorously defined engine.

Author's Preface

My training in telecommunications engineering began close to the machine: bits, registers, Boolean algebra, logical expressions, circuit simplification, applied algebra, microcontrollers, and digital systems. These concepts shaped not only what I learned, but also how I learned to analyze complex systems.

At its core, a digital telephone exchange is a large, specialized real-time computer. Moving from telecommunications into software development—and later studying programming theory and high-level languages in greater depth—did not replace that foundation. It added new layers of abstraction to it. I continued to approach software with the same tools and habits I had acquired while programming microcontrollers and designing digital circuits: representing state precisely, reducing expressions, separating control from behavior, and searching for the simplest structure capable of producing the required result.

The engine described in this article emerged from that way of thinking. Its use of bits, masks, Boolean expressions, and state transformations is not merely an implementation technique. It reflects a broader principle: even highly complex business workflows can often be reduced to a small, rigorous set of logical operations and then rebuilt as flexible, configurable systems.

This article therefore brings together several disciplines that have influenced my work: the abstraction and generalization of complex systems, process engineering, software engineering, low-level programming, and applied algebra.

The challenge is not only to design and implement such a system, but also to explain it. Complex architectures are often difficult to simplify and present clearly without losing the reasoning that makes them work. This article is an attempt to describe that reasoning as directly and precisely as possible.

— Jorge Cruz