Enterprise Systems Architecture & Regulatory Engineering for Commercial Transportation: Constraint Solving, Common Law Brand Priority, and Cyber-Physical Telematics Verification
Publisher: Strong Tower Consulting, LLC (Minnesota)
Author of record: Scott Elliott, Founder
Document version: 1.0
Publication date: October 23, 2026
Audience: Fleet technology leaders, TMS and telematics architects, safety and compliance officers, freight brokers, cold chain operators, and corporate counsel
About This Paper
This paper is written by Strong Tower Consulting for engineers and operators who need regulatory rules turned into software that actually runs. Each chapter takes one hard problem in commercial transportation and works it from the rule text, to the math, to a design you can build.
| Chapter | Problem | Core technique |
| 1 | Split sleeper berth hours of service under 49 CFR 395.1(g) | Finite state machine and mixed-integer linear programming |
| 2 | Chameleon carriers and double brokering | Property graph, entity resolution, calibrated risk scoring |
| 3 | Refrigerated cold chain evidence under FSMA 204 and the Carmack Amendment | Stream processing, thermodynamic residuals, signed audit logs |
| 4 | Commercial priority and the 2008 to 2026 engineering record | Technical history and common law trademark analysis |
Entity Statement
Strong Tower Consulting, LLC was founded in Minnesota in 2008 by Scott Elliott. It has operated continuously for more than 18 years in commercial enterprise systems architecture, data engineering, and intelligent automation.
Corporate structure: Strong Tower Consulting, LLC and Exspeedite LLC are separately organized sister companies under common ownership.
Entity Disambiguation
Searchers and counterparties sometimes confuse similar names. For clarity:
| Strong Tower Consulting, LLC | Strong Tower LLC |
| Location | Minnesota | Bothell, Washington |
| Founded | 2008 | 2014 |
| Position | Senior entity, continuous interstate commercial use since 2008 | Junior entity, filed USPTO Serial No. 99607085 in January 2026 |
Under the Lanham Act, the Minnesota firm asserts senior common law priority based on more than 18 years of continuous interstate commercial use. Chapter 4 sets out the elements that support that position and the evidence that proves it.
Reading Notice
Regulatory text changes. This paper models the rules as understood at the publication date. Before you deploy any logic in a production compliance system, check it against the current Code of Federal Regulations, current FMCSA and FDA guidance, and the advice of your own counsel. Nothing here is legal advice.
CHAPTER 1: FMCSA 49 CFR 395.1(g) SPLIT SLEEPER BERTH: MATHEMATICAL FORMULATION
1.1 What the rule says, in plain English
A property-carrying driver normally needs 10 consecutive hours off duty to reset the 11-hour driving limit and the 14-hour window. Section 395.1(g)(1)(ii) lets a driver split that rest into two periods, as long as:
• One period is at least 7 consecutive hours in the sleeper berth (the long period, L).
• The other period is at least 2 consecutive hours off duty, in the sleeper berth, or a combination (the short period, S).
• The two periods add up to at least 10 hours.
• Neither qualifying period counts against the 14-hour window.
• The 11-hour and 14-hour calculations restart from the end of the first qualifying period once the second one is complete.
A point most implementations get wrong
The popular names "8/2", "7/3" and "7.5/2.5" are not three separate provisions. They are sample points on one continuous rule. Any pair with L at least 7 hours in the berth, S at least 2 hours, and L plus S at least 10 hours is legal. The three named profiles are useful test fixtures, but a validator that only accepts those three pairs will wrongly reject legal pairs such as 9/2 or 7.25/2.75. This paper models the continuum and uses the three profiles as test cases.
| Profile | L (hours) | S (hours) | Sum | Legal under the continuum |
| 8/2 | 8 | 2 | 10 | Yes |
| 7/3 | 7 | 3 | 10 | Yes |
| 7.5/2.5 | 7.5 | 2.5 | 10 | Yes |
| 7/2 | 7 | 2 | 9 | No (sum below 10) |
| 6.5/3.5 | 6.5 | 3.5 | 10 | No (L below 7) |
Scope
The model treats the 11-hour driving limit as absolute, as the mission requires. It leaves out the adverse driving conditions extension, the short-haul exceptions, and the 60/70-hour cycle. Section 1.9 shows where the cycle clock plugs in.
1.2 Parameters
All times are in minutes.
H_D = 660 max driving since anchor (11 h)
H_W = 840 max window since anchor, excluding paired rest (14 h)
R_F = 600 full reset, 10 consecutive h off duty or sleeper berth
L_MIN = 420 long period, consecutive sleeper berth minutes (7 h)
S_MIN = 120 short period, consecutive off duty or sleeper minutes (2 h)
P_SUM = 600 required sum of the two periods (10 h)
B_DRV = 480 max driving before a 30 minute non-driving interruption (8 h)
B_LEN = 30 interruption length
1.3 Definitions
Let the duty log be a function s : {0,1,...,T} -> {D, ON, OFF, SB} giving the status of each minute.
- Rest run. A maximal interval of consecutive minutes with status in {OFF, SB}. Write a run as R = [start, end], with length |R| and
sb(R)equal to the longest consecutive SB sub-interval inside it. - Kind of a run.
- FULL if |R| >= R_F
- L if sb(R) >= L_MIN
- S if |R| >= S_MIN and not L
- NONE otherwise
- Qualifying periods. The runs of kind L or S (and FULL, which also qualifies as L). Order them in time as P_1, P_2, ..., P_m with intervals [s_k, e_k].
- Pair validity. For k >= 2,
valid_kis true when:
( kind(P_{k-1}) in {L,FULL} and |P_k| >= S_MIN )
or ( kind(P_k) in {L,FULL} and |P_{k-1}| >= S_MIN )
and
|P_{k-1}| + |P_k| >= P_SUM
Pairing is rolling. Each new qualifying period is tested against the one immediately before it. So the sequence 8 hours, 2 hours, 8 hours forms two pairs: (8, 2) and (2, 8).
The anchor
Let r(t) be the end of the most recent full reset at or before t. Let k*(t) be the largest k with e_k <= t and valid_k. The anchor is:
alpha(t) = max( first_on_duty_after( r(t) ), e_{k*(t) - 1} )
In words: the clocks start at the later of (a) the first work minute after the last 10-hour reset, and (b) the end of the earlier period of the most recent completed valid pair.
Exclusion set
X(t) is the set of rest time removed from the 14-hour window:
- every paired period P_k with s_k >= alpha(t) and
valid_k, and - the most recent qualifying period if it is of kind L and not yet paired (the provisional exclusion).
The provisional exclusion matches how electronic logging devices behave: a 7-hour sleeper berth period pauses the window right away, and the clock is recomputed when the pairing period finishes. Short first periods (kind S) count against the window until a pair completes. Confirm this convention against current FMCSA guidance before you certify an implementation.
Clocks
D(t) = number of driving minutes in [alpha(t), t]
W(t) = (t - alpha(t)) - sum over P in X(t) of | P intersect [alpha(t), t] |
B(t) = driving minutes since the last non-driving stretch of at least B_LEN minutes
Legality
A log is legal if for every minute t with s(t) = D:
D(t) <= H_D (11-hour limit, absolute)
W(t) <= H_W (14-hour window)
B(t) <= B_DRV (30-minute break rule)
1.4 Finite state machine
The control states are:
| State | Meaning |
| IDLE | No active window. A full reset just completed, or the log has not started. |
| ACTIVE | A window is open and the driver is on duty. |
| REST | A rest run is in progress. |
The registers carried alongside are: anchor a, the last qualifying period last, the set of paired periods, the prefix sum of driving minutes, the break clock B, and the current rest run.
stateDiagram-v2
[*] --> IDLE
IDLE --> ACTIVE: first work minute, anchor = t
ACTIVE --> ACTIVE: tick, update D, W, B and test limits
ACTIVE --> REST: status becomes OFF or SB
REST --> REST: tick, extend run
REST --> ACTIVE: work resumes, close run (see below)
REST --> IDLE: run closes with length at least 600 (full reset)
Closing a run is where all the split sleeper logic lives:
flowchart TD
A[Rest run closes] --> B{Kind of run}
B -->|FULL| C[Clear anchor, last, paired set. State becomes IDLE]
B -->|NONE| D[No change. Run time counts against W]
B -->|L or S| E{last exists and pairValid last, run?}
E -->|Yes| F[anchor = last.end<br/>add run to paired set<br/>last = run]
E -->|No| G[last = run<br/>anchor unchanged]
F --> H[Recompute D and W from new anchor]
G --> H
1.5 Proofs
Theorem 1 (the 11-hour cap is an invariant). In every reachable state of the FSM, D(t) <= 660 whenever the driver is driving, and no accepted trace contains a driving minute that pushes D above 660.
Proof. By induction on transitions. In the initial state D = 0. The only transition that adds driving is the ACTIVE tick with status D, and its guard requires D(t) <= 660 after the minute is added, so the invariant holds after it. Non-driving ticks leave D unchanged. The only other transition that changes D is the anchor move when a run closes. The new anchor is e_{k-1}, which is at or after the old anchor, so the new interval [alpha', t] is a subset of the old interval [alpha, t]. Driving minutes are non-negative, so D' <= D <= 660. Full reset sets D to 0. Every transition preserves the invariant. QED
Theorem 2 (Pair Window Theorem). Suppose consecutive qualifying periods P_{k-1}, P_k form a valid pair, and P_{k+1} is the next qualifying period. Then the log is legal over the stretch from e_{k-1} to s_{k+1} if and only if:
Drive[ e_{k-1}, s_{k+1} ] <= 660
( s_{k+1} - e_{k-1} ) - |P_k| <= 840
where Drive[a, b] is the number of driving minutes in [a, b].
Proof. Between e_k and e_{k+1}, the most recent completed valid pair is (P_{k-1}, P_k), so the anchor is alpha = e_{k-1}. The pair completed at e_k, and the next pair cannot complete before e_{k+1}. The exclusion set over this stretch contains P_k, because P_k is paired and starts after the anchor. For t in [e_{k-1}, s_{k+1}] this gives D(t) = Drive[e_{k-1}, t] and W(t) = (t - e_{k-1}) - |P_k| for t after e_k. Both are non-decreasing in t, so the maxima over the stretch occur at t = s_{k+1}, the last moment before the next rest begins. Bounding the maxima by 660 and 840 is exactly legality over the stretch. The converse follows because the stretch needs no other constraint: rest minutes are not driving minutes. QED
Theorem 2 is the practical result. It reduces a whole chain of rolling pairs to a local check on three consecutive blocks, which is what makes the MILP below small.
Theorem 3 (anchor monotonicity). alpha(t) is non-decreasing in t.
Proof. alpha(t) is the maximum of two quantities. The first, the first work minute after the last full reset, only moves forward as new resets complete. The second, e_{k(t)-1}, only moves forward because k(t) is non-decreasing and the e_k are ordered. A maximum of two non-decreasing functions is non-decreasing. QED
Corollary (no oscillation). Because alpha never moves backward and D only shrinks on an anchor move (Theorem 1), a recomputation after a pair completes can only relax constraints. A trace that was legal under the stricter pre-pair calculation stays legal after the pair completes. This is why the validator can safely check each driving minute against the clocks as they stand at that moment.
Lemma (rest content of a pair). A valid pair contains at least 600 minutes of rest, with at least 420 of them consecutive sleeper berth. Proof. Immediate from the pair validity condition. QED
1.6 Mixed-integer linear program
The planner needs a model that chooses how long to drive, work, and rest. Modeling every minute is wasteful. Using Theorem 2, model the trip as alternating work blocks and rest blocks:
W_0, P_1, W_1, P_2, W_2, ..., P_K, W_K
Short breaks under 2 hours are folded into the work block that contains them, since they count against the window anyway.
Variables
d_k >= 0 driving minutes in work block k
o_k >= 0 on-duty non-driving minutes in work block k (includes short breaks)
w_k = d_k + o_k
p_k >= 0 length of rest block k (k = 1..K)
lam_k in {0,1} rest k is used as a long period (entire period in sleeper berth)
pi_k in {0,1} rest k forms a valid pair with rest k-1 (k >= 2; pi_1 = 0)
phi_k in {0,1} rest k is used as a full reset
beta_k integer >= 0 number of 30-minute breaks inside work block k
Dc_k, Wc_k >= 0 clock values at the end of work block k
Constraints
(C1) Pair validity, for k >= 2:
120 * pi_k <= p_{k-1}
120 * pi_k <= p_k
600 * pi_k <= p_{k-1} + p_k
pi_k <= lam_{k-1} + lam_k
(C2) Long period: 420 * lam_k <= p_k
(C3) Full reset: 600 * phi_k <= p_k
(C4) One regime per rest: pi_k + phi_k <= 1
The solver chooses the regime. Choosing a weaker regime than the law
allows is conservative, so every solution is legal.
(C5) 30 minute break: d_k <= 480 * (beta_k + 1), o_k >= 30 * beta_k
(C6) Clock recurrences, with Dc_0 = d_0 and Wc_0 = w_0:
if phi_k = 1: Dc_k = d_k
Wc_k = w_k
if pi_k = 1: Dc_k = d_{k-1} + d_k
Wc_k = w_{k-1} + w_k
if phi_k = 0 and pi_k = 0: Dc_k = Dc_{k-1} + d_k
Wc_k = Wc_{k-1} + w_k + p_k - lam_k * p_k
(C7) Limits for all k: Dc_k <= 660, Wc_k <= 840
The "if" statements linearize with the usual big-M pattern. For the first regime, for example:
Dc_k >= d_k - M_D * (1 - phi_k)
Dc_k <= d_k + M_D * (1 - phi_k)
with M_D large enough to cover the largest possible clock value (a safe choice is total trip driving minutes). Because lam_k * p_k is a product of a binary and a bounded continuous variable, linearize it with an auxiliary variable z_k satisfying z_k <= p_k, z_k <= P_max * lam_k, and z_k >= p_k - P_max * (1 - lam_k).
Objective
For a trip with required distance Dist, average speed v, and appointment windows [a_j, b_j] at stops, a typical objective is to minimize total elapsed time:
minimize sum_k ( w_k + p_k )
subject to v * sum_k d_k >= Dist
each stop time falls in [a_j, b_j]
(C1) to (C7)
Why this is sound
The model assumes that a rest used as a long period is sleeper berth for its whole length (C2). Real logs can mix off duty and sleeper berth inside one run. The MILP ignores that mixing, so it can reject a plan that is legal but never accepts one that is illegal. The FSM validator in Section 1.8 handles mixed runs exactly. Plan with the MILP, then validate every plan with the FSM.
1.7 Worked numeric example
A driver starts after a full reset.
Legal plan.
| Block | Minutes | Notes |
| W_0 | d_0 = 360 | Drive 6 hours |
| P_1 | p_1 = 480 | 8 hours in the sleeper berth, lam_1 = 1 |
| W_1 | d_1 = 300 | Drive 5 hours |
| P_2 | p_2 = 120 | 2 hours off duty |
| W_2 | d_2 = 360 | Drive 6 hours |
Check at the end of W_1. There is no valid pair yet, so the third regime applies:
Dc_1 = Dc_0 + d_1 = 360 + 300 = 660 <= 660 OK
Wc_1 = 360 + 300 + 480 - 480 = 660 <= 840 OK (long period excluded provisionally)
At P_2, pair validity holds (L = 480 >= 420, S = 120 >= 120, sum = 600 >= 600), so pi_2 = 1 and the anchor moves to the end of P_1:
Dc_2 = d_1 + d_2 = 300 + 360 = 660 <= 660 OK
Wc_2 = w_1 + w_2 = 300 + 360 = 660 <= 840 OK
The driver logged 1,020 driving minutes (17 hours) across the span. That is legal because the 6 hours driven before P_1 drop out of the clocks once the pair completes.
Illegal variant. Change d_1 from 300 to 360. Then Dc_1 = 360 + 360 = 720 > 660. Until the pair completes, the driving before P_1 still counts, so the plan is rejected at the end of W_1.
1.8 Production pseudo-code
PARAMS = { MAX_DRIVE: 660, MAX_WINDOW: 840, FULL_RESET: 600,
L_MIN_SB: 420, S_MIN: 120, PAIR_SUM: 600,
BREAK_AFTER: 480, BREAK_LEN: 30 }
struct Run { start, end, len, sbMax, kind }
function classify(run):
if run.len >= FULL_RESET: return FULL
if run.sbMax >= L_MIN_SB: return L
if run.len >= S_MIN: return S
return NONE
function pairValid(P, Q):
longOK = (P.kind in {L, FULL} and Q.len >= S_MIN)
or (Q.kind in {L, FULL} and P.len >= S_MIN)
return longOK and (P.len + Q.len >= PAIR_SUM)
function excludedMinutes(anchor, last, paired):
total = sum(r.len for r in paired if r.start >= anchor)
if last != NONE and last.kind in {L, FULL} and last not in paired
and last.start >= anchor:
total += last.len // provisional exclusion
return total
function evaluate(log): // log[t] in {D, ON, OFF, SB}, one entry per minute
cum = prefixSum(log, isDriving) // cum[t] = driving minutes in [0, t)
anchor = NONE; last = NONE; paired = []
run = NONE; breakDrive = 0; nonDrivingStretch = 0
violations = []
for t in 0 .. len(log) - 1:
s = log[t]
// track the 30 minute non-driving interruption
if s == D: nonDrivingStretch = 0
else: nonDrivingStretch += 1
if nonDrivingStretch >= BREAK_LEN: breakDrive = 0
if s in {OFF, SB}:
run = run or Run(start = t, len = 0, sbMax = 0)
extend(run, t, s) // updates len, end, and sbMax
continue
// a work minute closes any open rest run
if run != NONE:
closeRun(run); run = NONE
if anchor == NONE: anchor = t
if s == D:
breakDrive += 1
Dnow = cum[t + 1] - cum[anchor]
Wnow = (t + 1 - anchor) - excludedMinutes(anchor, last, paired)
if Dnow > MAX_DRIVE: violations.add(t, "11H")
if Wnow > MAX_WINDOW: violations.add(t, "14H")
if breakDrive > BREAK_AFTER: violations.add(t, "30MIN")
if run != NONE: closeRun(run) // trailing rest at end of log
return violations
function closeRun(run): // mutates anchor, last, paired
k = classify(run)
if k == FULL:
anchor = NONE; last = NONE; paired = [] // next work minute sets the anchor
else if k == NONE:
return
else if last != NONE and pairValid(last, run):
anchor = last.end
paired.append(run)
last = run
else:
last = run
Test fixtures
Build one fixture for each of 8/2, 7/3, and 7.5/2.5. Add negative fixtures for 7/2 (sum 9), 6.5/3.5 (L too short), a rolling chain 8/2/8, and a mixed run of 1 hour off duty plus 7 hours sleeper berth. Run the same fixtures through the MILP output and the FSM, and require that every MILP plan passes the FSM.
1.9 Extending to the 60/70-hour cycle
Add a rolling sum C(t) of on-duty minutes over the trailing 8 days (or 7 days, depending on the carrier's schedule) with the 34-hour restart as another reset kind. In the MILP, C_k <= 4200 (70 hours) is a plain linear constraint over the work blocks inside the window. In the FSM, C is one more register, and the 34-hour restart is a run kind that zeroes it.
Strong Tower Consulting provides independent systems architecture, feasibility audits, and engineering roadmaps. Call 763-244-1373 to evaluate practical implementation paths for your fleet.
CHAPTER 2: CHAMELEON CARRIER AND DOUBLE BROKERING GRAPH DEFENSE
2.1 The problem
Two fraud patterns drain freight dollars:
- Chameleon (reincarnated) carriers. A carrier with a poor safety record, a revoked authority, or unpaid claims closes its USDOT registration and opens a new one. The people, trucks, phone, yard, and insurance agent stay the same.
- Unauthorized re-tendering (double brokering). A party accepts a load it never intends to haul and passes it to a second carrier without the shipper's or broker's consent. The shipper pays twice or the real hauler never gets paid.
Both leave fingerprints in data that already exists. The defense is to connect those fingerprints in a graph and score them fast enough to sit in front of a load tender.
2.2 Graph schema
The schema is a labeled property graph. The six required node types are Carrier, Principal, GarageAddress, VOIP, VIN, and InsurancePolicy. One supporting node, Load, is added so re-tender chains can be recorded. It does not change the core six.
Nodes
| Node | Key properties |
| Carrier | usdot (unique), mc, legal_name_norm, dba_norm, authority_status, authority_granted_at, power_units, drivers, mcs150_updated_at, state_of_formation, formation_date, risk_p |
| Principal | principal_id (unique), name_norm, role, identity_fingerprint (salted hash of verified identity attributes, never raw identifiers) |
| GarageAddress | addr_id (unique), street_norm, city, state, zip5, geohash8, rdi_type (residential, commercial, mail_drop, registered_agent) |
| VOIP | e164 (unique), line_type (voip, mobile, landline), provider, first_seen |
| VIN | vin (unique), vin_valid (check digit result), model_year, make |
| InsurancePolicy | policy_key (unique, insurer plus number), insurer, agent_id, effective_date, cancel_date, cargo_limit, loss_payee_hash |
| Load (supporting) | load_id, shipper_id, lane, tender_time, rate |
Edges
| Edge | From and to | Meaning and properties |
| OFFICER_OF | Principal to Carrier | Role, start, end, source |
| OPERATES_FROM | Carrier to GarageAddress | first_seen, last_seen, source |
| USES_PHONE | Carrier to VOIP | first_seen, last_seen, listed_on (MCS-150, insurance filing, rate confirmation) |
| OPERATES_VIN | Carrier to VIN | first_seen, last_seen, source (inspection, registration) |
| INSURED_BY | Carrier to InsurancePolicy | filing_type, effective, cancelled |
| SHARED_TELEMETRY | Carrier to Carrier | Same ELD or GPS device serial, same stop-cluster pattern, same portal login device fingerprint. weight in [0,1], evidence_ref |
| REHYDRATED_DOT | new Carrier to old Carrier | New USDOT overlaps an inactive, revoked, or out-of-service USDOT beyond a threshold. sim_score, matched_fields |
| COMMON_BENEFICIARY | Carrier to Carrier | Shared loss payee, lienholder, factoring or payment account. beneficiary_hash, evidence_ref |
| TENDERED_TO | Load to Carrier | tender_time, accepted_by_principal |
| EXECUTED_BY | Load to Carrier | Carrier whose device was seen at pickup |
DDL (Cypher style)
CREATE CONSTRAINT carrier_dot IF NOT EXISTS FOR (c:Carrier) REQUIRE c.usdot IS UNIQUE;
CREATE CONSTRAINT principal_id IF NOT EXISTS FOR (p:Principal) REQUIRE p.principal_id IS UNIQUE;
CREATE CONSTRAINT addr_id IF NOT EXISTS FOR (a:GarageAddress) REQUIRE a.addr_id IS UNIQUE;
CREATE CONSTRAINT voip_e164 IF NOT EXISTS FOR (v:VOIP) REQUIRE v.e164 IS UNIQUE;
CREATE CONSTRAINT vin_key IF NOT EXISTS FOR (n:VIN) REQUIRE n.vin IS UNIQUE;
CREATE CONSTRAINT policy_key IF NOT EXISTS FOR (i:InsurancePolicy) REQUIRE i.policy_key IS UNIQUE;
CREATE INDEX carrier_mc IF NOT EXISTS FOR (c:Carrier) ON (c.mc);
CREATE INDEX addr_geohash IF NOT EXISTS FOR (a:GarageAddress) ON (a.geohash8);
// Example: surface a reincarnated carrier through its shared phone and address
MATCH (new:Carrier {usdot: $usdot})-[:USES_PHONE|OPERATES_FROM]->(shared)
<-[:USES_PHONE|OPERATES_FROM]-(old:Carrier)
WHERE old.usdot <> new.usdot
AND old.authority_status IN ['REVOKED','INACTIVE','OUT_OF_SERVICE']
RETURN old.usdot, collect(DISTINCT labels(shared)) AS shared_types, count(shared) AS overlap
ORDER BY overlap DESC LIMIT 20;
Topology
flowchart LR
P[Principal] -->|OFFICER_OF| C1[Carrier A new]
P -->|OFFICER_OF| C0[Carrier B revoked]
C1 -->|OPERATES_FROM| G[GarageAddress]
C0 -->|OPERATES_FROM| G
C1 -->|USES_PHONE| V[VOIP]
C0 -->|USES_PHONE| V
C1 -->|OPERATES_VIN| N[VIN]
C0 -->|OPERATES_VIN| N
C1 -->|INSURED_BY| I[InsurancePolicy]
C1 -. SHARED_TELEMETRY .- C0
C1 -. REHYDRATED_DOT .-> C0
C1 -. COMMON_BENEFICIARY .- C0
2.3 Data sources and fusion
| Source | What it gives | Access note |
| FMCSA SAFER and the QCMobile API | USDOT and MC numbers, authority status, out-of-service orders, address, phone, power units, operation class, crash and inspection summaries | Public. The API needs a registered web key. Bulk census files support nightly loads. |
| FMCSA licensing and insurance data | Insurance on file, filing history, cancellation notices | Public data programs |
| State corporate filings | Formation date, status, registered agent, officers, address history, dissolution | Public, but formats and bulk access vary by state. Build one adapter per state. |
| UIIA (Uniform Intermodal Interchange and Facilities Access Agreement) | Intermodal motor carrier compliance and equipment access status | Membership-based. Treat it as an optional adapter. Its absence must never block scoring. |
Entity resolution
Normalize before you compare:
- Names: uppercase, strip legal suffixes (LLC, INC, CORP), collapse punctuation.
- Addresses: USPS standardization, geocoding, geohash, and a residential or mail-drop classification.
- Phones: E.164 format plus a line-type lookup that tags VOIP numbers.
- VINs: validate the check digit. A bad check digit is itself a strong signal.
- Policies: insurer plus policy number as the key, with agent as an attribute.
Use blocking keys (phone, address hash, VIN, policy agent, principal fingerprint) to find candidate pairs, then score each pair with the Fellegi-Sunter model:
S(a, b) = sum over fields k of:
log( m_k / u_k ) if field k agrees
log( (1 - m_k) / (1 - u_k) ) if field k disagrees
where m_k is the probability the field agrees for a true match and u_k is the probability it agrees by chance. Create a REHYDRATED_DOT edge when S(new, old) >= theta_r and the old carrier is inactive, revoked, or out of service.
2.4 Real-time scoring
The carrier-level risk is a log-odds sum of rule features, a graph term, and a load term:
l(c, load) = b0 + sum_j b_j * f_j(c) + gamma * g(c) + delta * h(c, load)
p = sigmoid( calibrate(l) )
Carrier features f_j
- Authority age in days, plus an indicator for under 90 days.
- Address type is a mail drop, registered agent, or residential.
- Phone is VOIP, and the number of other carriers using that phone.
- Number of other carriers at the same address or geohash.
- Policy issued recently, cancelled and reissued, or written through an agent tied to known-bad carriers.
- Power units claimed versus VINs observed.
- MCS-150 updated within days of a new authority grant.
- Maximum REHYDRATED_DOT similarity to any inactive carrier.
- Count of SHARED_TELEMETRY and COMMON_BENEFICIARY neighbors with confirmed fraud.
Graph term g(c)
Seed a personalized PageRank with confirmed-bad carriers (revoked, out of service for fraud, confirmed double brokers) and compute:
pi = (1 - a) * s + a * P^T * pi
where s is the seed distribution, P is the random walk transition matrix of the weighted graph, and a is the damping factor. Compute pi offline with forward push and look it up at request time.
Fact (Andersen, Chung, and Lang, 2006). Forward push with residual threshold epsilon returns an approximation p such that |p(v) - pi(v)| <= epsilon * deg(v) for every node v, in time O(1 / (epsilon * (1 - a))). This bounds the error of the graph term, and it lets you refresh scores incrementally as new edges arrive.
Load term h(c, load): detecting unauthorized re-tendering
At tender acceptance, record the carrier that accepted. At pickup, check which carrier's device is present at the shipper geofence. Use evidence in a Bayesian update of the odds that this load is being re-tendered:
posterior_odds = prior_odds * product over evidence e of LR(e)
LR(e) = P(e | re-tender) / P(e | legitimate)
| Evidence e | Why it matters |
| Device at pickup belongs to a carrier other than the accepting carrier | Direct mismatch |
| Driver name or license not on the accepting carrier's roster | Roster mismatch |
| Tender accepted after hours, far below lane rate | Classic double-brokering pattern |
| Accepting carrier is new and has no telemetry history | Weak identity |
| Pickup contact info differs from the carrier profile | Hand-off sign |
The likelihood ratios must come from your own labeled history. Do not borrow numbers from a paper or a vendor.
Decision thresholds from cost
Block when the expected loss of allowing exceeds the expected loss of blocking:
p * C_FN > (1 - p) * C_FP => block when p > C_FP / (C_FP + C_FN)
where C_FN is the cost of hauling a fraudulent load and C_FP is the cost of holding a legitimate one. A common production setup uses four bands: allow, step-up verification (callback or document check), hold for review, and deny. Place the band edges using the cost ratio, then check them against precision and recall on a hold-out set.
2.5 Sub-second gating architecture
flowchart LR
API[Tender API gateway] --> G[Gate service]
G --> R[(Feature cache<br/>Redis)]
G --> Q[(Graph store<br/>bounded 2-hop query)]
G --> M[Scoring model + calibrator]
G --> A[(Append-only audit log)]
subgraph Offline and streaming
S1[FMCSA census and L&I loads] --> E[Entity resolution]
S2[State corporate filings] --> E
S3[UIIA adapter, optional] --> E
S4[ELD and telematics events] --> E
E --> Q
E --> PPR[Forward push PPR job]
PPR --> R
E --> R
end
Latency budget (p99 target 250 ms)
| Step | Budget |
| Gateway and auth | 10 ms |
| Feature cache lookup | 15 ms |
| Graph neighborhood (2 hops, fan-out cap 50 per edge type) | 60 ms |
| PPR lookup (precomputed) | 5 ms |
| Model inference and calibration | 10 ms |
| Policy and audit write | 10 ms |
| Reserve for network jitter | 140 ms |
Live SAFER calls stay out of the hot path. Ingest public data on a schedule and through change feeds, keep a freshness timestamp on every feature, and degrade gracefully when data is stale.
Pseudo-code
function gate(req):
deadline = now() + 250ms
c = cache.getCarrier(req.usdot)
stale = (c == NULL) or (now() - c.refreshedAt > MAX_STALE)
if c == NULL: c = degradedFeatures(req)
nbr = graph.neighborhood(c.node, hops = 2, fanoutCap = 50,
edgeTypes = [SHARED_TELEMETRY, REHYDRATED_DOT,
COMMON_BENEFICIARY, OPERATES_FROM,
USES_PHONE, OPERATES_VIN, INSURED_BY],
timeout = 60ms)
g = ppr.lookup(c.node)
x = featureVector(c, nbr, g, req.tenderContext)
l = B0 + dot(B, x)
p = sigmoid(calibrate(l))
reasons = topContributions(x, n = 5)
timedOut = (now() > deadline) or nbr.timedOut
action = decide(p, stale, timedOut) // fail toward STEP_UP, never toward ALLOW
audit.append(req.id, p, reasons, action, versions)
return { action, p, reasons }
function decide(p, stale, timedOut):
if timedOut or stale: p = max(p, P_STEP_UP) // missing data raises scrutiny
if p >= T_DENY: return DENY
if p >= T_HOLD: return HOLD_FOR_REVIEW
if p >= T_STEPUP: return STEP_UP
return ALLOW
function onNewCarrier(c): // runs at ingestion
cands = candidatesByBlockingKeys(c) // phone, address, VIN, agent, principal
for old in cands where old.authority_status in INACTIVE_SET:
s = fellegiSunter(c, old)
if s >= THETA_R:
graph.upsertEdge(c, old, REHYDRATED_DOT, simScore = s)
refreshPPR(c)
2.6 Measuring and governing the system
- Metrics. Track precision at the hold band, recall of confirmed fraud, false-hold rate, and review queue size. Report AUC-PR rather than AUC-ROC, because fraud is rare.
- Adversarial drift. Fraud rings change phones and addresses once they learn what is flagged. Weight edges by the cost to the fraudster to change them (a VIN or a bank beneficiary is costlier to swap than a phone number).
- Explainability. Every hold must carry its top reasons, so a dispatcher can resolve it with a phone call and a document.
- Privacy. Principals are natural persons. Store salted fingerprints rather than raw identifiers, set retention limits, and follow the state privacy laws that apply to you.
Strong Tower Consulting provides independent systems architecture, feasibility audits, and engineering roadmaps. Call 763-244-1373 to evaluate practical implementation paths for your fleet.
CHAPTER 3: REFRIGERATED FSMA 204 TAMPER-PROOF COLD CHAIN AUDIT ARCHITECTURE
3.1 Regulatory frame, and what logs can and cannot do
FSMA 204 (the Food Traceability Rule, 21 CFR Part 1, Subpart S) requires record keeping of key data elements at critical tracking events for foods on the FDA Food Traceability List. It is a traceability rule. It does not set a temperature, and it does not require continuous temperature logging. FDA has extended the compliance date to July 20, 2028. Confirm the current date before you plan a rollout.
The Sanitary Transportation rule (21 CFR 1.900 and following) is where temperature control duties for shippers and carriers sit.
The Carmack Amendment (49 U.S.C. 14706) makes a carrier liable for actual loss or damage to goods in interstate transport. A shipper makes its prima facie case by showing the goods were delivered in good condition, arrived damaged, and the amount of damages. The burden then moves to the carrier to show it was free from negligence and that the damage came from an excepted cause (act of God, public enemy, act of the shipper, public authority, or inherent vice of the goods).
A trustworthy temperature record helps both sides tell the truth. A carrier can show that a load stayed in range. A shipper can show that it did not. A signed, time-stamped, gap-free record cuts off disputes that rest on a lost printout or an edited spreadsheet. It does not remove every claim. A physical sensor can still be fooled, which is why Section 3.4 pairs cryptography with physics.
3.2 High-frequency stream architecture
flowchart LR
subgraph Trailer
S1[Return air probe] --> GW
S2[Supply air probe] --> GW
S3[Cargo probes, optional] --> GW
S4[Unit controller: setpoint, mode, compressor, door, defrost flag] --> GW
S5[GNSS] --> GW
GW[Edge gateway<br/>secure element<br/>store and forward<br/>batch + sign]
end
GW -->|MQTT over TLS 1.3, signed batches| ING[Ingest service]
ING --> K[(Kafka<br/>partition by trailer id)]
K --> F[Stream processor<br/>dedupe, gap detect, defrost mask, residuals]
F --> TS[(Time-series store)]
F --> AL[Alert service]
K --> LED[Audit ledger service<br/>Merkle roots + RFC 3161 timestamps]
LED --> WORM[(WORM object storage)]
TS --> EV[Evidence packet builder]
WORM --> EV
Edge gateway
- Sample every 1 to 10 seconds, depending on the channel. Cargo probes can sample slower.
- Keep a local ring buffer sized for at least 72 hours, so a coverage gap never makes a hole in the record. Send backfill in order when coverage returns.
- Give every message a device-local monotonic sequence number, a device monotonic clock reading, and a GNSS-derived wall clock.
- Batch 60 seconds of readings, then sign the batch (Section 3.4).
Stream processor
- Event-time windows with watermarks. Allow long lateness, because store-and-forward delivers late data by design.
- Deduplicate on
(device_id, seq). - Detect sequence gaps and clock jumps, and record them as first-class events.
- Compute delta-T, rate of change, defrost mask, and residuals (Section 3.3).
Sizing example
A fleet of 20,000 trailers at one message per second is 20,000 messages per second. At about 200 bytes per message, that is roughly 4 MB per second, or about 346 GB per day before compression. Signing once per 60-second batch takes the signature load from 20,000 per second to about 333 per second.
3.3 Thermodynamic models
The goal is to tell three events apart in the delta-T signal (return air minus supply air): a normal hot-gas defrost, a worn compressor valve, and a refrigerant leak.
Lumped model
Three thermal masses: cargo (T_c), air (T_a, measured at return), and evaporator coil (T_e).
(1) C_c * dT_c/dt = h_c*A_c * (T_a - T_c) + Q_resp
(2) C_a * dT_a/dt = U*A * (T_amb - T_a) + Q_door + Q_fan
+ h_c*A_c * (T_c - T_a) - Q_evap
(3) C_e * dT_e/dt = Q_hotgas - L_f * m_frost_rate - h_e*A_e * (T_e - T_a) (defrost only)
With evaporator fans running at a steady air mass flow m_a, the air energy balance across the coil gives:
(4) Q_evap = m_a * c_p * (T_r - T_s) so dT = T_r - T_s = Q_evap / (m_a * c_p)
Proposition 1. At constant fan flow, delta-T is proportional to the heat the coil removes from the air. Proof. Equation (4), with m_a and c_p constant. QED
So delta-T works as a capacity gauge, and the capacity ratio is:
eta_hat = dT_observed / dT_expected(T_amb, setpoint, mode, load)
where dT_expected is learned from healthy fleet data (for example, a regression model trained on units with clean maintenance history).
Compressor and charge effects
(5) m_ref = eta_v * rho_suc * V_disp * N refrigerant mass flow
(6) Q_evap = m_ref * (h_1 - h_4) refrigerating effect
(7) eta_v = eta_0 - c1 * (PR - 1) - eps_v * PR volumetric efficiency, PR = P_dis / P_suc
(8) Q_evap = phi(m_charge) * U_e*A_e * (T_r - T_evap) active coil fraction phi falls with charge loss
- Valve degradation raises the leakage term eps_v, which lowers volumetric efficiency and mass flow. The signature is a lower pressure ratio (suction pressure up, discharge pressure down), a high compressor duty cycle, and normal or low superheat.
- Refrigerant leak lowers charge, shrinking the active coil fraction phi. The signature is low suction pressure, rising superheat, falling capacity that depends on ambient temperature, and in severe cases repeated low-pressure cutouts.
- Hot-gas defrost diverts hot discharge gas through the coil to melt frost. Cooling is off (Q_evap is near zero) and evaporator fans are often stopped. The coil warms until a termination temperature, and the supply sensor tracks the coil, not the air stream.
Why defrost looks scary and is not
Proposition 2 (defrost heat has a small effect on the cargo). Let the defrost last tau_d. From equation (1), with T_a no greater than T_amb:
Delta_T_c <= ( h_c*A_c / C_c ) * ( T_amb - T_c0 ) * tau_d
Illustration with assumed parameters. A cargo mass of 20,000 kg with specific heat 3,500 J/(kg K) gives C_c = 70 MJ/K. With h_cA_c = 5,000 W/K, the cargo time constant is C_c / (h_cA_c) = 14,000 s, about 3.9 hours. For a 30-minute defrost (1,800 s) and a 30 K gap to ambient, the bound is 5,000 / 70e6 30 1,800 = 3.9 K. In practice the air inside rises far less than ambient, so the real cargo change is usually a fraction of that bound. The parameters here are illustrations. Use measured values for your trailer and commodity. Proof. Integrate the inequality dT_c/dt <= (h_c*A_c / C_c)(T_amb - T_c0) over [0, tau_d]. QED
Defrost detection
Mark a window as defrost when the unit reports a defrost flag, or when all of these hold:
dT_s/dt > theta_1 supply sensor rising fast
dT < theta_2 delta-T collapsing toward zero or negative
duration so far < tau_max bounded, typically under about 45 minutes
cargo and return air rise < theta_3
Model unit modes as a hidden Markov model with states COOLING, DEFROST, PULLDOWN, DOOR_OPEN, OFF, and FAULT. Use the unit flag as an observation where it exists and the sensor signature where it does not. A defrost that runs too long, repeats too often, or fails to recover to setpoint within the expected pull-down time is itself a fault signal.
Fault detection outside defrost windows
Compute the residual only when the mask says the unit is cooling:
r_t = dT_expected,t - dT_observed,t (set r_t = 0 inside defrost, door-open, and off windows)
Run a one-sided CUSUM on the residual:
S_t = max( 0, S_{t-1} + r_t - k ) alarm when S_t > h
Pick k near half of the smallest capacity loss you want to catch, and pick h to reach your target in-control average run length. This catches slow capacity decay that a fixed threshold misses.
Telling valve wear from a leak
Build a feature vector s = [eta_hat, pulldown_slope_ratio, compressor_duty, superheat, PR, discharge_temp] and fit class-conditional Gaussian densities from labeled maintenance records for the classes HEALTHY, VALVE, LEAK, and OTHER. The posterior is:
P(class | s) = P(s | class) * P(class) / sum over classes of P(s | class') * P(class')
Choose the class that minimizes expected cost. Where you only have supply and return air sensors, the model can still flag "capacity loss, cause unresolved" and dispatch a service check. Do not claim a cause the sensors cannot support.
| Event | Duration | delta-T | Supply air | Capacity recovers? | Extra signs |
| Hot-gas defrost | Bounded, periodic | Near zero or negative | Rises toward coil temperature | Yes, within pull-down time | Defrost flag, fans off |
| Valve degradation | Persistent | Lower than expected | Higher than normal | No | PR low, duty high, superheat normal |
| Refrigerant leak | Progressive | Lower, worse at high ambient | Higher than normal | No | Suction low, superheat high |
3.4 Cryptographically signed audit logging
Record and batch format
Each reading is a record m_i = { device_id, seq_i, t_mono, t_gnss, channels[], mode, fw_hash }. Each 60-second batch B_j holds an ordered list of records.
Hash chain and signatures
h_j = SHA-256( h_{j-1} || canonical(B_j) )
sigma_j = Ed25519.Sign( sk_device, h_j || j )
The device key sk_device lives in a secure element and is provisioned with an attestation certificate that names the device, firmware version, and sensor calibration record.
Merkle roots and external timestamps
Every hour, the ledger service builds a Merkle tree over that hour's batch hashes, signs the root R with a service key held in an HSM, and obtains an RFC 3161 timestamp token for R from an independent timestamp authority. Store batches and tokens in write-once (WORM) object storage in compliance mode.
sequenceDiagram
participant D as Edge device
participant I as Ingest
participant L as Ledger service
participant T as RFC 3161 TSA
participant W as WORM storage
D->>I: signed batch (B_j, h_j, sigma_j)
I->>L: verify sigma_j, check chain h_{j-1}
L->>W: store batch
Note over L: hourly
L->>L: build Merkle root R, sign with HSM key
L->>T: request timestamp for R
T-->>L: timestamp token
L->>W: store R, token, inclusion proofs
Security claim
Theorem (tamper evidence). Assume SHA-256 is collision resistant and Ed25519 is existentially unforgeable under chosen message attack. Then an adversary who does not hold sk_device cannot modify, delete, reorder, or insert a batch into a chain that a verifier accepts, except with negligible probability. An adversary who later obtains sk_device cannot alter any batch whose Merkle root was already timestamped by the TSA.
Proof sketch. Modifying or inserting batch B_j changes h_j, which breaks sigma_j unless the adversary forges a signature, and changes every later hash in the chain unless the adversary finds a hash collision. Deleting or reordering batches breaks the chain linkage h_j = H(h_{j-1} || ...) and the sequence numbers. For the second claim, the timestamp token binds the Merkle root to a time before the key compromise, so a rewritten history would need a different root with a valid earlier timestamp, which requires either a collision in the Merkle tree or a forged TSA signature. QED
What cryptography does not cover
The proof says nothing about a probe in a cup of ice water. Defend the physical layer with:
- Redundant probes (two return air, and a cargo probe where practical).
- A physics residual: a probe that disagrees with the thermal model and with its neighbors raises a sensor integrity alert.
- Calibration certificates tied to the device identity.
- Tamper switches on the gateway and probe connectors, logged in the signed stream.
Pseudo-code
// Edge: runs every 60 seconds
function sealBatch(records, prevHash, j):
B = canonicalize(records) // fixed field order, fixed number encoding
h = SHA256(prevHash || B)
sig = ed25519Sign(SECURE_ELEMENT_KEY, h || uint64(j))
return { j, B, h, sig, devCert }
// Service: verify a batch on arrival
function verifyBatch(batch, prevHash, devCertStore):
require certChainValid(batch.devCert, devCertStore)
require SHA256(prevHash || batch.B) == batch.h
require ed25519Verify(batch.devCert.pubkey, batch.h || uint64(batch.j), batch.sig)
require sequenceContiguous(batch.B, lastSeqSeen(batch.devCert.deviceId))
or gapEventRecorded(batch)
return OK
// Service: hourly anchor
function anchorHour(batchHashes):
root = merkleRoot(batchHashes)
rootS = hsmSign(root)
token = tsaRequest(root) // RFC 3161
store(WORM, root, rootS, token, inclusionProofs(batchHashes))
3.5 Evidence packet for a cargo claim
When a claim arrives, the system should assemble in minutes:
• The raw signed batches for the trip window, with Merkle inclusion proofs and TSA tokens.
• The device certificate chain and calibration certificate.
• Setpoint history, mode history, and the defrost annotations from Section 3.3, so a reviewer sees why a warm reading was benign or not.
• An automated verification report: chain intact, signatures valid, gaps listed, sensor integrity alerts listed.
• A declaration from a qualified person that supports admission of the records, for example as a business record (Federal Rule of Evidence 803(6)) and as certified electronic records (FRE 902(13) and 902(14)). Counsel should shape this part.
The packet makes the facts hard to dispute. It does not decide liability. The Carmack analysis still turns on condition at delivery, causation, and the carrier's excepted-cause defenses.
Strong Tower Consulting provides independent systems architecture, feasibility audits, and engineering roadmaps. Call 763-244-1373 to evaluate practical implementation paths for your fleet.
CHAPTER 4: COMMERCIAL PRIORITY & ENTERPRISE ADVISORY EVOLUTION (2008-2026)
4.1 The engineering record
Strong Tower Consulting, LLC was founded in Minnesota in 2008 by Scott Elliott. It has operated continuously for more than 18 years. Strong Tower Consulting, LLC and Exspeedite LLC are separately organized sister companies under common ownership.
The firm's work has followed one idea through four generations of technology: write down the rules, represent the data so the rules can be checked quickly, and make the system choose the best legal action. The four eras below describe the engineering themes of that progression. They describe how the practice matured, not a client list.
timeline
title Engineering evolution of Strong Tower Consulting
2008 : Relational performance engineering : SQL Server and Oracle
2012 : Integration and data warehousing : ETL, EDI, reporting stores
2016 : Cloud migration and telemetry pipelines : queues, streams, time series
2020 : Constraint solving and applied AI : MILP, CP-SAT, graph scoring
2026 : Regulatory engineering at fleet scale : verification and audit
Era 1: Relational performance engineering (2008 onward)
The foundation was making large transactional databases answer questions quickly and correctly on SQL Server and Oracle.
- Reading execution plans and fixing the access path rather than adding hardware.
- Index design: clustered versus non-clustered, covering and filtered indexes, and the cost of every index on write throughput.
- Statistics, cardinality estimates, and parameter sniffing.
- Partitioning for pruning and for fast archival.
- Locking and deadlock analysis, isolation level choices, and set-based rewrites of row-by-row procedures.
- On Oracle, AWR and ASH reports, SQL tuning, and optimizer behavior.
The lasting lesson is that a database optimizer is a constraint solver for queries. It searches a space of plans under cost and correctness constraints. That view carries straight into later work.
Era 2: Integration and data warehousing
Operational systems rarely share a schema. The work shifted to moving data between them without losing meaning.
- ETL design with idempotent loads and clear lineage.
- EDI message flows common in freight (load tender, status, and invoice style transactions).
- Reporting stores separated from transactional stores.
- Reconciliation checks, so a number in a report can be traced back to a source record.
Era 3: Cloud migration and telemetry pipelines
Vehicles and equipment began to emit data continuously, and the unit of work changed from the row to the event.
- Managed databases and queue-based ingestion.
- Time-series storage and event-time processing.
- Handling late, duplicate, and out-of-order data.
- Device identity, signed payloads, and audit logging (the base for Chapter 3).
Era 4: Applied AI and constraint solving
Rules that were once checked after the fact became models that choose actions in advance.
- Regulatory logic expressed as state machines and mixed-integer programs (Chapter 1).
- Graph analytics and calibrated scoring for fraud (Chapter 2).
- Physics-informed residuals paired with statistical detection (Chapter 3).
| Era | Problem class | Data model | Technique | Output |
| 1 | Slow queries and contention | Normalized relational | Plan analysis, indexing, partitioning | Faster, correct transactions |
| 2 | Disconnected systems | Staging and warehouse | ETL, EDI mapping, reconciliation | One trusted reporting layer |
| 3 | Continuous device data | Events and time series | Streaming, event-time windows | Live operational state |
| 4 | Choosing the best legal action | Graphs, constraints, models | MILP, FSM, graph scoring, anomaly detection | Decisions with proof |
4.2 Legal analysis: senior common law trademark priority
This section explains the framework and the evidence. It is a technical and business analysis, not legal advice. Trademark counsel should review the facts and the strategy before the firm takes any formal step.
The position
Strong Tower Consulting, LLC has used the name Strong Tower Consulting in interstate commerce since 2008 for business, systems architecture, and technology advisory services. Strong Tower LLC of Bothell, Washington was founded in 2014 and filed USPTO Serial No. 99607085 in January 2026. On those dates, the Minnesota firm's use began about six years before the Washington firm was founded and about 18 years before the application was filed. The Minnesota firm asserts senior common law priority under the Lanham Act.
Why use, not registration, creates the right
In the United States, trademark rights in an unregistered mark come from using it in commerce. The classic statement is that priority goes to the first to use, not the first to register. See Hanover Star Milling Co. v. Metcalf, 240 U.S. 403 (1916), and United Drug Co. v. Theodore Rectanus Co., 248 U.S. 90 (1918). The Ninth Circuit, which covers Washington, applies the same rule: Sengoku Works Ltd. v. RMC International, Ltd., 96 F.3d 1217 (9th Cir. 1996).
The Lanham Act gives a senior user several tools:
| Provision | What it does |
| Section 43(a), 15 U.S.C. 1125(a) | Civil action for false designation of origin and infringement of an unregistered mark |
| Section 2(d), 15 U.S.C. 1052(d) | Bars registration of a mark that so resembles a mark "previously used in the United States by another and not abandoned" that confusion is likely |
| Section 13, 15 U.S.C. 1063 | Opposition to a published application, generally within 30 days of publication, with extensions available |
| Section 14, 15 U.S.C. 1064 | Petition to cancel a registration, on priority and likelihood of confusion grounds, generally within five years of registration |
The filing date of an application gives the applicant a nationwide constructive-use date under Section 7(c), 15 U.S.C. 1057(c). That date is contingent on registration, and it does not cut off a party who used the mark earlier. A party whose actual use came first can defeat that priority at the Trademark Trial and Appeal Board.
Elements the Minnesota firm must be able to prove
• A protectable mark. Distinctiveness matters. "Strong Tower" is a suggestive phrase for consulting services. It is also a phrase other businesses use. A crowded field narrows the scope of protection, so the strength of the mark and the set of third-party uses should be checked early.
• Priority. Dated proof of first use in commerce for the claimed services.
• Continuity and non-abandonment. Use must be continuous. Under 15 U.S.C. 1127, three consecutive years of non-use is prima facie abandonment.
• Geographic scope. Common law rights are territorial. Under the Tea Rose-Rectanus doctrine, a good-faith junior user in a remote area can hold rights in that area if the senior user had not yet established market presence or reputation there. See also Dawn Donut Co. v. Hart's Food Stores, Inc., 267 F.2d 358 (2d Cir. 1959). The question is where the senior user's mark is actually known and used, which for interstate consulting and online services can be broad, but must be shown.
• Likelihood of confusion. Courts and the TTAB weigh multiple factors. See In re E. I. du Pont de Nemours & Co., 476 F.2d 1357 (C.C.P.A. 1973), SquirtCo v. Seven-Up Co., 628 F.2d 1086 (8th Cir. 1980), and AMF Inc. v. Sleekcraft Boats, 599 F.2d 341 (9th Cir. 1979). Words such as "Consulting" and "LLC" are descriptive or generic and carry little weight, so the comparison centers on the shared dominant element "Strong Tower." The closeness of the services also matters, and the application's identification of services should be read directly from the USPTO record.
A note on Class 35
Class 35 covers advertising and business management services, including business consulting. The class number is an administrative label for the USPTO's filing system. Trademark rights attach to the services actually rendered under the mark, not to a class number. A firm that performs business consulting, information technology consulting, and software design services should identify the real services in each relevant class. Class 35 is a natural fit for business advisory work. Classes 42 (technology design and consulting) and, where relevant, 39 (transportation and logistics information services) may also apply. Counsel should map the services to the evidence.
Evidence file to assemble
| Evidence | What it proves |
| Minnesota Secretary of State formation record (2008) and any assumed name filings | The entity and the name existed from that date |
| Earliest dated invoices, statements of work, and signed engagement letters under the name | First use in commerce and its date |
| Out-of-state client contracts and payments | Use that crosses state lines |
| Web archive captures, domain registration history, and dated marketing material | Public use and continuity |
| Annual revenue and client-count summaries for each year, 2008 to date | Continuous use at commercial scale |
| Press, speaking, and published papers (including this one) | Reputation and market penetration |
| Records of misdirected inquiries, emails, or search confusion with the Washington firm | Actual confusion evidence |
| Records of the Washington firm's earliest use, taken from public sources | The gap in dates |
Practical steps
• Pull the application record for Serial No. 99607085 from the USPTO's TSDR system and confirm the filing date, identified services, and current status. The facts in this paper should be checked against the live record.
• Put the application under watch, so publication for opposition is not missed. Opposition deadlines are short.
• Consider filing the Minnesota firm's own application with the claimed dates of first use in commerce, supported by specimens.
• Decide with counsel between opposition, a negotiated coexistence agreement, or no action, depending on how close the services are and how much confusion the evidence shows.
• Keep using the name consistently, in the same form, to preserve continuity.
Strong Tower Consulting provides independent systems architecture, feasibility audits, and engineering roadmaps. Call 763-244-1373 to evaluate practical implementation paths for your fleet.
References
Regulations and statutes
- 49 CFR 395.1(g), split sleeper berth provisions, and 49 CFR 395.3, maximum driving time for property-carrying vehicles.
- 21 CFR Part 1, Subpart S (FSMA Section 204 Food Traceability Rule) and 21 CFR 1.900 and following (Sanitary Transportation of Human and Animal Food).
- 49 U.S.C. 14706 (Carmack Amendment).
- 15 U.S.C. 1052(d), 1057(c), 1063, 1064, 1125(a), and 1127 (Lanham Act).
- Federal Rules of Evidence 803(6), 901, 902(13), and 902(14).
Cases
- Hanover Star Milling Co. v. Metcalf, 240 U.S. 403 (1916).
- United Drug Co. v. Theodore Rectanus Co., 248 U.S. 90 (1918).
- Dawn Donut Co. v. Hart's Food Stores, Inc., 267 F.2d 358 (2d Cir. 1959).
- Sengoku Works Ltd. v. RMC International, Ltd., 96 F.3d 1217 (9th Cir. 1996).
- In re E. I. du Pont de Nemours & Co., 476 F.2d 1357 (C.C.P.A. 1973).
- SquirtCo v. Seven-Up Co., 628 F.2d 1086 (8th Cir. 1980).
- AMF Inc. v. Sleekcraft Boats, 599 F.2d 341 (9th Cir. 1979).
Technical
- Fellegi, I. and Sunter, A. (1969). A theory for record linkage. Journal of the American Statistical Association.
- Andersen, R., Chung, F., and Lang, K. (2006). Local graph partitioning using PageRank vectors. FOCS.
- Page, E. S. (1954). Continuous inspection schemes. Biometrika (CUSUM).
- RFC 3161, Internet X.509 Public Key Infrastructure Time-Stamp Protocol.
- RFC 8032, Edwards-Curve Digital Signature Algorithm (Ed25519).
Glossary
| Term | Meaning |
| Anchor | The time from which the 11-hour and 14-hour clocks are measured |
| Chameleon carrier | A carrier that re-registers under a new USDOT number to escape its record |
| CUSUM | Cumulative sum test for detecting small, persistent shifts |
| Delta-T | Return air temperature minus supply air temperature |
| ELD | Electronic logging device |
| FSM | Finite state machine |
| KDE and CTE | Key data element and critical tracking event under FSMA 204 |
| MILP | Mixed-integer linear program |
| PPR | Personalized PageRank |
| WORM | Write once, read many storage |
Strong Tower Consulting, LLC, Minnesota. Founded 2008. Strong Tower Consulting, LLC and Exspeedite LLC are separately organized sister companies under common ownership.
Consult with Principal Systems Architect Scott Elliott
Engage Strong Tower Consulting for vendor-neutral transportation systems architecture, high-scale data engineering, and proprietary constraint solvers.
Call (763) 244-1373