duallity is a pure computation library. It parses no untrusted formats, opens no sockets, spawns
no processes, and deserializes nothing: it computes weighted edit-distance paths over a query string
$`q`$ and an in-memory dictionary $`D`$ that the host supplies, and returns ranked
corrections. Consequently its attack surface is narrow and is dominated by a single class of concern —
algorithmic resource exhaustion (denial of service).
These pages state that surface precisely, bound the one realistic risk with concrete knobs, and document the exact dictionary-node key together with the residual hash-table considerations around it.
| Document | Covers |
|---|---|
| Threat model | The inputs and trust boundary, the (small) attack surface, and how to bound resource use with concrete numeric limits. |
| Hashing and collisions | The exact DictionaryNodeKey, why ordinary hash-table collisions cannot alias two dictionary nodes, and future hardening options. |
STRIDE (Kohnfelder & Garg, Microsoft, 1999) is a mnemonic for six threat categories: Spoofing, Tampering, Repudiation, Information disclosure, Denial of service, and Elevation of privilege. It is a system-level framework; applied to a self-contained, side-effect-free compute library, five of its six categories are structurally not applicable because the mechanisms they describe (identities, persisted or transmitted artifacts, audit logs, secret channels, privilege boundaries) simply do not exist inside duallity. The sixth — denial of service — is the whole of the practical surface.
| STRIDE category | Applies to duallity? | Rationale |
|---|---|---|
| Spoofing (falsifying identity) | N/A | duallity authenticates nothing and holds no principals, sessions, tokens, or credentials. There is no identity to spoof. |
| Tampering (violating integrity) | N/A in the library | With no persistence, no I/O, and no deserialization there is no on-disk or on-wire artifact whose integrity duallity could fail to protect. The one logical integrity question — could two distinct dictionary nodes be conflated? — is closed by the exact key (hashing-and-collisions). In-memory tampering is the host's memory-safety domain, and duallity adds no unsafe (engineering/safety-and-panics). |
| Repudiation (denying an action) | N/A | duallity keeps no logs or transactions to repudiate; it is a deterministic pure function of $`(q, D, \text{config})`$. Its determinism actively aids the host's own auditing and issue reproduction. |
| Information disclosure (leaking data) | N/A | duallity processes strings, not secrets, and opens no channel over which to leak. It is not constant-time, but its running time is a function of public inputs only (the query, the dictionary, and $`k`$); it branches on no secret, so timing reveals nothing sensitive. |
| Denial of service (exhausting resources) | Yes — the one real risk | An adversary who controls the query (and possibly influences the dictionary) can try to inflate the explored product-state band. This is the subject of threat-model §3–§4 and is bounded by max_distance, query length, and CachePolicy::Lru. |
| Elevation of privilege (gaining rights) | N/A | No privilege boundary is crossed: no unsafe, no FFI into privileged code, no process or shell invocation, and no dynamic code loading. duallity runs entirely within the host's existing privileges. |
The single live row — denial of service — is not left as an abstract worry: every vector is tied
to a concrete, enforceable bound in the threat model's per-vector mitigation table
and, beneath those tunable knobs, to the crate's hard structural ceilings (the u32 StateId and
VocabId spaces, which fail closed rather than overflow).
- No I/O, no network, no deserialization. duallity only computes over a query string and an in-memory dictionary you supply; there is no parsing-of-untrusted-bytes, SSRF, path-traversal, or deserialization-gadget surface of its own.
- No
unsafe(engineering/safety-and-panics) — the crate introduces no memory-safety surface of its own making, and every fallible step reports throughResult/Optionrather than a wrapping overflow. - The realistic concern is algorithmic resource use at large
$`k`$/ large dictionaries. Bound it with a smallmax_distance, a query-length cap at the host boundary, andCachePolicy::Lru(see threat-model). - Dictionary nodes use a compact exact
DictionaryNodeKey. Ordinary hash-table collisions do not alias nodes; the packing and its non-aliasing proof are in hashing-and-collisions.
- threat-model — inputs, attack surface, and resource bounds.
- hashing-and-collisions — the exact node key and its collision behavior.
- engineering/safety-and-panics — the zero-
unsafestory and the complete panic inventory. - guides/05 · Performance and tuning — the same knobs, framed for performance.