hypothesis
Everything exported by guardlink/hypothesis, from the .d.ts files published in guardlink@2.2.0. See the entry points for the other subpaths, and use guardlink as a library for worked examples.
Interfaces
Section titled “Interfaces”BoundaryClaimClassification
Section titled “BoundaryClaimClassification”Properties
Section titled “Properties”| Property | Type |
|---|---|
ledger |
HypothesesStatus |
records |
BoundaryClaimRecord[] |
summary |
BoundaryClaimSummary |
BoundaryClaimRecord
Section titled “BoundaryClaimRecord”Properties
Section titled “Properties”| Property | Type | Description |
|---|---|---|
asset_a |
string |
- |
asset_b |
string |
- |
claim |
string |
- |
description |
string |
- |
directed |
boolean |
Written from <outer> to <inner>: asset_a is the outer side. |
entry |
BoundaryEntry | null |
- |
expired |
boolean |
The entry no longer applies because the code beneath the boundary changed. |
file |
string |
- |
id |
string |
The boundary’s #id, without the #; ‘’ when it has none. |
key |
string |
- |
line |
number |
- |
location |
SourceLocation |
- |
previous |
HypothesisOutcomeRecord<BoundaryOutcome> | null |
- |
state |
BoundaryClaimState |
- |
BoundaryClaimSummary
Section titled “BoundaryClaimSummary”Properties
Section titled “Properties”| Property | Type |
|---|---|
contradicted |
number |
retest |
number |
supported |
number |
unverified |
number |
HypothesesLedger
Section titled “HypothesesLedger”Properties
Section titled “Properties”| Property | Type |
|---|---|
anchor_hash_version |
number |
entries |
LedgerEntry[] |
schema |
"guardlink.hypotheses/v1" |
HypothesesRead
Section titled “HypothesesRead”Properties
Section titled “Properties”| Property | Type |
|---|---|
error? |
string |
ledger |
HypothesesLedger | null |
status |
HypothesesStatus |
HypothesisAnchor
Section titled “HypothesisAnchor”Properties
Section titled “Properties”| Property | Type |
|---|---|
hash |
string |
scope |
AnchorScope |
symbol |
string | null |
HypothesisClassification
Section titled “HypothesisClassification”Properties
Section titled “Properties”| Property | Type |
|---|---|
ledger |
HypothesesStatus |
records |
HypothesisRecord[] |
summary |
HypothesisSummary |
HypothesisEntry
Section titled “HypothesisEntry”Extends
Section titled “Extends”Type Parameters
Section titled “Type Parameters”| Type Parameter | Default type |
|---|---|
O extends LedgerOutcome |
HypothesisOutcome |
Properties
Section titled “Properties”| Property | Type | Description | Inherited from |
|---|---|---|---|
anchor |
HypothesisAnchor | null |
The claim’s anchor when the outcome was recorded; null when the claim had none. | HypothesisOutcomeRecord.anchor |
at |
string |
ISO 8601, UTC. | HypothesisOutcomeRecord.at |
by |
string |
human:<name> or cxg:<template>. |
HypothesisOutcomeRecord.by |
claim |
string |
Display only; never matched on. | - |
evidence |
string |
- | HypothesisOutcomeRecord.evidence |
file |
string |
- | - |
history |
HypothesisOutcomeRecord<O>[] |
Earlier outcomes for the same key, newest first. | - |
key |
string |
Stable claim key from relationRecords. |
- |
line |
number |
- | - |
outcome |
O |
- | HypothesisOutcomeRecord.outcome |
source |
HypothesisSource |
- | HypothesisOutcomeRecord.source |
HypothesisOutcomeRecord
Section titled “HypothesisOutcomeRecord”Extended by
Section titled “Extended by”Type Parameters
Section titled “Type Parameters”| Type Parameter | Default type |
|---|---|
O extends LedgerOutcome |
HypothesisOutcome |
Properties
Section titled “Properties”| Property | Type | Description |
|---|---|---|
anchor |
HypothesisAnchor | null |
The claim’s anchor when the outcome was recorded; null when the claim had none. |
at |
string |
ISO 8601, UTC. |
by |
string |
human:<name> or cxg:<template>. |
evidence |
string |
- |
outcome |
O |
- |
source |
HypothesisSource |
- |
HypothesisRecord
Section titled “HypothesisRecord”Extended by
Section titled “Extended by”Properties
Section titled “Properties”| Property | Type | Description |
|---|---|---|
asset |
string |
- |
claim |
string |
- |
entry |
HypothesisEntry<HypothesisOutcome> | null |
- |
expired |
boolean |
The entry no longer applies because the code beneath the claim changed. |
file |
string |
- |
key |
string |
- |
line |
number |
- |
location |
SourceLocation |
- |
previous |
HypothesisOutcomeRecord<HypothesisOutcome> | null |
The lapsed outcome, when expired. |
refs |
string[] |
The exposure’s external references (cwe:, owasp:), for the offered Confirmed line. |
severity |
string |
- |
state |
HypothesisState |
- |
threat |
string |
- |
verb |
"exposes" | "confirmed" |
- |
HypothesisSummary
Section titled “HypothesisSummary”Properties
Section titled “Properties”| Property | Type |
|---|---|
confirmed |
number |
refuted |
number |
retest |
number |
untested |
number |
ImportResult
Section titled “ImportResult”Properties
Section titled “Properties”| Property | Type | Description |
|---|---|---|
ambiguous |
object[] |
- |
boundaries |
object[] |
Outcomes recorded against a declared boundary’s claim key. Never written into source. |
confirmed |
object[] |
- |
malformed |
object[] |
A stamp arrived under one of our names that is not a claim key. Reported, never joined: it says nothing about which claim was tested, so guessing from the coarse tiers would be a confirmation resting on a value we rejected. |
scanId |
string |
- |
stale |
object[] |
The finding’s claim key names no claim in the model: the claim it was tested against is gone. No candidates are offered — whatever the coarse tiers would have matched is a different claim, and recording this evidence against it by hand is the exact confirmation the key just refused. |
unmatched |
ScanFinding[] |
- |
OutcomeInput
Section titled “OutcomeInput”Properties
Section titled “Properties”| Property | Type | Description |
|---|---|---|
at |
string |
ISO 8601. The caller supplies it so the ledger stays deterministic under test. |
by |
string |
- |
evidence |
string |
- |
source? |
HypothesisSource |
- |
RankedHypothesis
Section titled “RankedHypothesis”Extends
Section titled “Extends”Properties
Section titled “Properties”| Property | Type | Description | Inherited from |
|---|---|---|---|
asset |
string |
- | HypothesisRecord.asset |
claim |
string |
- | HypothesisRecord.claim |
entry |
HypothesisEntry<HypothesisOutcome> | null |
- | HypothesisRecord.entry |
expired |
boolean |
The entry no longer applies because the code beneath the claim changed. | HypothesisRecord.expired |
file |
string |
- | HypothesisRecord.file |
key |
string |
- | HypothesisRecord.key |
line |
number |
- | HypothesisRecord.line |
location |
SourceLocation |
- | HypothesisRecord.location |
onPath |
boolean |
The asset sits on an undefended source-to-sink path. | - |
previous |
HypothesisOutcomeRecord<HypothesisOutcome> | null |
The lapsed outcome, when expired. |
HypothesisRecord.previous |
rank |
number |
- | - |
refs |
string[] |
The exposure’s external references (cwe:, owasp:), for the offered Confirmed line. | HypothesisRecord.refs |
severity |
string |
- | HypothesisRecord.severity |
state |
HypothesisState |
- | HypothesisRecord.state |
threat |
string |
- | HypothesisRecord.threat |
unowned |
boolean |
No Owns names the asset. | - |
verb |
"exposes" | "confirmed" |
- | HypothesisRecord.verb |
ScanFinding
Section titled “ScanFinding”Properties
Section titled “Properties”| Property | Type | Description |
|---|---|---|
annotation |
{ file: string; line: number; } | null |
- |
asset |
string | null |
- |
boundary_claim_key |
string | null |
The claim key of a declared boundary this finding tested, read under every name in BOUNDARY_CLAIM_KEY_NAMES at the finding’s top level, in its annotation, or in either one’s properties. A probe can test a boundary and an exposure at once, so this sits beside claim_key rather than replacing it. Null when absent, and when every value found is unshaped (boundary_malformed). |
boundary_malformed |
ScanStamp | null |
- |
boundary_outcome |
BoundaryOutcome |
What the probe found about the boundary: contradicted unless the finding says supported. |
claim_key |
string | null |
The claim key the export stamped onto the finding, when it carries one, read under every name in CLAIM_KEY_NAMES and from every container a consumer puts it in — see findingStamp. A stamp guardlink fails to recognise is worse than no stamp: it takes the weaker join, and the report that carried the discriminator gets told to start sending one. Null when the finding carried no stamp AND when EVERY stamp it carried is unshaped — the latter lands in malformed_stamp instead, so the two are never confused for each other. |
confidence |
string | number | null |
- |
cwe_ids |
string[] |
- |
evidence |
object |
- |
evidence.data |
Record<string, unknown> |
- |
evidence.matched_patterns |
string[] |
- |
evidence.request |
string | null |
- |
evidence.response |
string | null |
- |
id |
string |
- |
junk_stamps |
ScanStamp[] |
Unshaped candidates found ALONGSIDE a valid key, which was used. Reported as a note and nothing more: selecting the good key must not silently hide that something is emitting garbage under a guardlink name, but it is not grounds to refuse a join the report identified precisely. |
malformed_stamp |
ScanStamp | null |
Candidates were present under our names and NONE was shaped like a claim key. Its own state: a producer emitting something else under our name is neither “unstamped” nor “the claim is gone”, and folding it into either loses the one thing worth knowing about it. |
rival_stamps |
ScanStamp[] |
Well-formed keys that DISAGREE with the one selected — the report claiming two different exposures at once. Deterministic precedence still picks the winner, because a widening must not change what an already-accepted report resolves to; what changes is that the disagreement is no longer discarded. A conflicting VALID extra is likelier to be trusted than an obviously malformed one, so hiding it is worse than hiding junk, not equally bad. |
severity |
string |
- |
template_id |
string |
- |
threat |
string | null |
- |
title |
string |
- |
Type Aliases
Section titled “Type Aliases”BoundaryClaimState
Section titled “BoundaryClaimState”BoundaryClaimState =
"unverified"|"supported"|"contradicted"|"retest"
BoundaryEntry
Section titled “BoundaryEntry”BoundaryEntry =
HypothesisEntry<BoundaryOutcome>
An outcome recorded against a declared boundary’s claim key.
BoundaryOutcome
Section titled “BoundaryOutcome”BoundaryOutcome =
"supported"|"contradicted"
What testing a declared boundary found: the line held, or it did not.
HypothesesStatus
Section titled “HypothesesStatus”HypothesesStatus =
"present"|"absent"|"corrupt"
HypothesisOutcome
Section titled “HypothesisOutcome”HypothesisOutcome =
"confirmed"|"refuted"
HypothesisSource
Section titled “HypothesisSource”HypothesisSource = {
kind:"manual"; } | {confidence:number|string|null;joined_by?:JoinedBy;kind:"scan";scan_id:string;template_id:string; }
Union Members
Section titled “Union Members”Type Literal
Section titled “Type Literal”{ kind: "manual"; }
Type Literal
Section titled “Type Literal”{ confidence: number | string | null; joined_by?: JoinedBy; kind: "scan"; scan_id: string; template_id: string; }
joined_by is absent on entries written before it existed; treat that as unknown, not as verified.
HypothesisState
Section titled “HypothesisState”HypothesisState =
"untested"|"confirmed"|"refuted"|"retest"
JoinedBy
Section titled “JoinedBy”JoinedBy =
"claim-key"|"claim-key-contested"|"location"|"asset-threat"|"cwe"
Which identity joined a scan finding to its claim. claim-key is the only one
that names the claim itself; location, asset-threat and cwe match
something the claim merely sits at or near, so a claim that moved onto the
tested line satisfies them. Recorded so a reader can tell a key-verified
confirmation from one taken on the weaker match — an unmarked pair of those is
the failure GAP-58 describes.
claim-key-contested is a key-verified join whose report carried MORE THAN
ONE well-formed key, naming different claims: the winner came from a
deterministic precedence tiebreak, not from agreement. It is its own value
rather than a flag beside claim-key because “key-verified” is a claim about
what happened, and a tiebreak establishes less than an uncontested stamp. A
label that overstates the verification actually performed is the same species
as every other false claim this subsystem exists to prevent.
LedgerEntry
Section titled “LedgerEntry”LedgerEntry =
HypothesisEntry|BoundaryEntry
LedgerOutcome
Section titled “LedgerOutcome”LedgerOutcome =
HypothesisOutcome|BoundaryOutcome
Variables
Section titled “Variables”BOUNDARY_CLAIM_KEY_NAMES
Section titled “BOUNDARY_CLAIM_KEY_NAMES”
constBOUNDARY_CLAIM_KEY_NAMES: readonlystring[]
Every name a scan report may carry a boundary’s claim key under. Separate from
CLAIM_KEY_NAMES because a finding stamped with both is reporting on two
claims, an exposure and the boundary in front of it, not contradicting itself.
HYPOTHESES_FILE
Section titled “HYPOTHESES_FILE”
constHYPOTHESES_FILE:".guardlink/hypotheses.json"=".guardlink/hypotheses.json"
GuardLink Hypotheses — barrel.
Comment
Section titled “Comment”– “The tested state of every exposure and declared boundary: a ledger of outcomes with evidence, expiry by code hash, and a ranked queue”
HYPOTHESES_SCHEMA
Section titled “HYPOTHESES_SCHEMA”
constHYPOTHESES_SCHEMA:"guardlink.hypotheses/v1"="guardlink.hypotheses/v1"
GuardLink Hypotheses — barrel.
Comment
Section titled “Comment”– “The tested state of every exposure and declared boundary: a ledger of outcomes with evidence, expiry by code hash, and a ranked queue”
Functions
Section titled “Functions”attachHypotheses()
Section titled “attachHypotheses()”attachHypotheses(
model,c):void
Stamp the state onto each exposure so surfaces that only see the model can read it.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
model |
ThreatModel |
c |
HypothesisClassification |
Returns
Section titled “Returns”void
classifyBoundaryClaims()
Section titled “classifyBoundaryClaims()”classifyBoundaryClaims(
model,read):BoundaryClaimClassification
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
model |
ThreatModel |
read |
HypothesesRead |
Returns
Section titled “Returns”classifyHypotheses()
Section titled “classifyHypotheses()”classifyHypotheses(
model,read):HypothesisClassification
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
model |
ThreatModel |
read |
HypothesesRead |
Returns
Section titled “Returns”confirmedLine()
Section titled “confirmedLine()”confirmedLine(
record,entry):string
The @confirmed annotation that reflects a confirmation, ready to paste.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
record |
HypothesisRecord |
entry |
HypothesisEntry |
Returns
Section titled “Returns”string
emptyHypotheses()
Section titled “emptyHypotheses()”emptyHypotheses():
HypothesesLedger
GuardLink Hypotheses — barrel.
Returns
Section titled “Returns”Comment
Section titled “Comment”– “The tested state of every exposure and declared boundary: a ledger of outcomes with evidence, expiry by code hash, and a ranked queue”
formatBoundaryList()
Section titled “formatBoundaryList()”formatBoundaryList(
c,state?):string
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
c |
BoundaryClaimClassification |
state? |
string |
Returns
Section titled “Returns”string
formatBoundaryOutcome()
Section titled “formatBoundaryOutcome()”formatBoundaryOutcome(
record,entry):string
One boundary outcome, as a block. Like formatOutcome, it names the claim, not a position.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
record |
BoundaryClaimRecord |
entry |
BoundaryEntry |
Returns
Section titled “Returns”string
formatHypothesisList()
Section titled “formatHypothesisList()”formatHypothesisList(
c,state?):string
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
c |
HypothesisClassification |
state? |
string |
Returns
Section titled “Returns”string
formatImport()
Section titled “formatImport()”formatImport(
r):string
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
r |
ImportResult |
Returns
Section titled “Returns”string
formatIntake()
Section titled “formatIntake()”formatIntake(
q,project,total):string
The queue as a brief bugb intake can take. total is the queue length
BEFORE -n bounded it.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
q |
RankedHypothesis[] |
project |
string |
total |
number |
Returns
Section titled “Returns”string
Comment
Section titled “Comment”– “A bounded brief that does not say it is bounded is a misleading brief. This one closes by telling an operator to hand it to bugb intake, so a 10-item page of a 142-claim queue reads as the whole of what there is to test and the 132 it never names read as nothing left to do. Both numbers are stated above the list and again on that closing line, since either can be the one an operator reads, along with the flag that asks for the rest. An untruncated brief is unchanged, down to the byte. The notice COUNTS the remainder and deliberately names no state for it: rankUntested queues untested and retest together, so a state noun here can misdescribe what is hidden — calling a claim that was confirmed, and whose code has since moved, untested, in the very line an operator hands to bugb intake. Membership is decided by that filter and is free to change without anyone reading this string; a line that only counts cannot fall out of step with what it counts, and the per-item labels below keep the composition legible where it belongs. The remainder clause agrees in number, because a remainder of exactly one is an ordinary count and The other 1 are is the kind of seam that tells a reader the sentence was never run at that value. The page size stays a numeral even when it is one: a bounded notice has to name both numbers, so it is not dropped for grammar. total is REQUIRED here for the same reason as in formatQueue — a default would return the permissive answer to a caller who forgot it, in the one renderer an operator hands to bugb intake”
formatOutcome()
Section titled “formatOutcome()”formatOutcome(
record,entry,offered?):string
One outcome, as a block.
The header names the CLAIM and not a position. record.line is a pre-write
coordinate — this runs before --write splices anything — and the authoritative
post-write positions are the wrote and already confirmed lines the CLI prints
once the writes have landed. Printing a second coordinate for the same thing asks
the reader to hold two and pick correctly, and the two WILL disagree in the run
that moves one of them; the asset, threat and key identify the claim without one.
offered is the exception and is safe: it is shown only when nothing is being
written, so no insertion can move it.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
record |
HypothesisRecord |
entry |
HypothesisEntry |
offered? |
string |
Returns
Section titled “Returns”string
formatQueue()
Section titled “formatQueue()”formatQueue(
q,total):string
The queue as a table. total is the queue length BEFORE -n bounded it.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
q |
RankedHypothesis[] |
total |
number |
Returns
Section titled “Returns”string
Comment
Section titled “Comment”– “The header counted the rows it was handed, so once -n bounded every renderer a 142-claim queue printed 10 to test: not a smaller answer to the same question but a wrong answer to it, because that line is the only place the table says how much there is. It names both numbers when the page is short of the queue, and reads exactly as it always did when it is not — a run that hides nothing must not grow a notice about hiding. total is REQUIRED and deliberately carries no default: defaulting it to q.length hands a caller who forgets it the permissive answer — truncated false, and a 10-of-142 page reporting 10 to test — which is the wrong number this renderer exists to stop, reinstalled as a silent default. Required, an omission is a build failure instead of a confident wrong answer”
Comment
Section titled “Comment”– “total decides EVERY branch here, the empty page included. The early return is the one sentence in this function that names a state rather than counting — it says every exposure has an outcome that still holds — so it is owed to total === 0 and not to an empty page: formatQueue([], 142) asked the queue for nothing and got nothing back, which says where the page ended, never that there is nothing outstanding. That branch was the last place in this file where a required total was accepted and then not read, and an empty page over a non-empty queue now falls through to the ordinary header and renders 0 of 142 to test, which counts and claims nothing”
importScan()
Section titled “importScan()”importScan(
root,model,scanPath,input):ImportResult
Join each finding to a claim and record the confirmed ones.
A claim key RESOLVES the join; it does not narrow one. A finding that carries a key is looked up against the whole record set, and that lookup is the whole answer: it hits exactly one claim (keys are unique within a model) or it hits none, in which case the claim it named is gone and the finding is stale. The coarse tiers — annotation location, then asset and threat, then CWE — run ONLY for a finding that carries no key, and a finding that fits more than one of them is reported as ambiguous, never guessed.
The order matters and is not an optimisation. Were the tiers to run first, the location tier would pick whatever claim now sits on the tested line and the key would only get to veto it — so a claim that merely DRIFTED (its file edited above it, moving its line) would be reported stale while it is alive and holding the stamped key, and a finding carrying nothing but a key — the most precise identifier in the system — would be reported unmatched. A wrong location match must never beat a correct key.
The key is the one the ledger already keys an entry on: a digest of the claim’s own words, so it survives every edit that is not the claim — a line move, and an edit to the code beneath it. That is what separates a finding from a sibling claim that landed on the line it was tested at: same file, same line, same asset, same threat, therefore the same threat id, and nothing else on the finding tells them apart.
The bound: two BYTE-IDENTICAL claims in one file — same verb, asset, threat,
external refs and description — share a digest and are told apart only by an
ordinal in document order. Delete the earlier one and the survivor inherits
…:0, the deleted claim’s exact key, so a finding stamped against the first
joins to the second. That is the shape this function exists to refuse,
surviving at a strictly narrower population. Separately, rewording a claim’s
own description re-keys it, so a stamp from before the rewording is refused.
Every confirmation records WHICH identity joined it (joined_by), because a
key-verified confirmation and one taken on the coarse tiers must not be
indistinguishable after the fact.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
root |
string |
model |
ThreatModel |
scanPath |
string |
input |
{ at: string; by: string; } |
input.at |
string |
input.by |
string |
Returns
Section titled “Returns”rankUntested()
Section titled “rankUntested()”rankUntested(
records,model,pathAssets?):RankedHypothesis[]
What to test next. retest first (a confirmed finding whose code changed),
then untested; within each: severity, then on an undefended path, then
unowned, then file and line. pathAssets is the set of asset refs on
unmitigated paths (findUnmitigatedPaths(...).assetsOnPath), in any form.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
records |
HypothesisRecord[] |
model |
ThreatModel |
pathAssets? |
Set<string> |
Returns
Section titled “Returns”readHypotheses()
Section titled “readHypotheses()”readHypotheses(
root):HypothesesRead
GuardLink Hypotheses — barrel.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
root |
string |
Returns
Section titled “Returns”Comment
Section titled “Comment”– “The tested state of every exposure and declared boundary: a ledger of outcomes with evidence, expiry by code hash, and a ranked queue”
recordBoundaryOutcome()
Section titled “recordBoundaryOutcome()”recordBoundaryOutcome(
root,model,target,outcome,input):object
Record one outcome for the boundary target names: its claim key, #id, or file:line.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
root |
string |
model |
ThreatModel |
target |
string |
outcome |
BoundaryOutcome |
input |
OutcomeInput |
Returns
Section titled “Returns”object
entry:
BoundaryEntry
record
Section titled “record”record:
BoundaryClaimRecord
recordOutcome()
Section titled “recordOutcome()”recordOutcome(
root,model,target,outcome,input):object
Record one outcome for the exposure at target (file:line).
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
root |
string |
model |
ThreatModel |
target |
string |
outcome |
HypothesisOutcome |
input |
OutcomeInput |
Returns
Section titled “Returns”object
entry:
HypothesisEntry
record
Section titled “record”record:
HypothesisRecord
resolveBoundaryTarget()
Section titled “resolveBoundaryTarget()”resolveBoundaryTarget(
model,target):BoundaryClaimRecord
The boundary a target names: its claim key, its #id, or the file:line of
its @boundary. Refuses anything that does not name exactly one.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
model |
ThreatModel |
target |
string |
Returns
Section titled “Returns”resolveTarget()
Section titled “resolveTarget()”resolveTarget(
model,target):HypothesisRecord
The exposure at file:line, or an error that says what is there instead.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
model |
ThreatModel |
target |
string |
Returns
Section titled “Returns”scanEvidence()
Section titled “scanEvidence()”scanEvidence(
scanId,f):string
Evidence text for the ledger: what the template sent and what came back, redacted, plus the scan id.
EVERY value here comes out of a scan report, and this string can be written
into someone’s source as an @confirmed description. So all of them go
through one() — the single boundary they can enter through — rather than
each interpolation remembering. A per-field helper is exactly how
template_id, title and matched_patterns came to be interpolated raw
while only request and response were collapsed, and a newline in any of
them ends our line and puts report-controlled text on the next one, in the
syntax the threat model is parsed from.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
scanId |
string |
f |
ScanFinding |
Returns
Section titled “Returns”string
serializeHypotheses()
Section titled “serializeHypotheses()”serializeHypotheses(
ledger):string
Deterministic serialisation: entries by file, line, key.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
ledger |
HypothesesLedger |
Returns
Section titled “Returns”string
writeConfirmedLine()
Section titled “writeConfirmedLine()”writeConfirmedLine(
root,record,line):ConfirmedWrite
Insert the line directly beneath the @exposes, with the same comment
prefix. Reports already-present when a
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
root |
string |
record |
HypothesisRecord |
line |
string |
Returns
Section titled “Returns”ConfirmedWrite
Confirmed
Section titled “Confirmed”for the pair already sits
there, and refuses a line that does not parse back as one @confirmed.
The re-parse is the structural half of the same guard confirmedLine’s
collapse gives: the description is assembled from a scan report, and a value
that broke out of its quotes or its line would land in source as something
the next parse reads differently from what we thought we wrote. Checking here
rather than in the caller means no caller can skip it. Same reason, and the
same pairing, as buildAcceptLines in src/review/index.ts.
record.line is resolved from a model parsed BEFORE this call, and this call
splices a line into the file — so applying several of these to one file must
go in DESCENDING line order. Ascending, each insertion shifts every later
target down by one, and where the shifted line is itself an @exposes every
guard below passes and the confirmation lands against a claim that was never
tested. Re-resolving between writes would work too; the ordering is cheaper
and cannot be forgotten halfway.
writeHypotheses()
Section titled “writeHypotheses()”writeHypotheses(
root,ledger):void
GuardLink Hypotheses — barrel.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
root |
string |
ledger |
HypothesesLedger |
Returns
Section titled “Returns”void
Comment
Section titled “Comment”– “The tested state of every exposure and declared boundary: a ledger of outcomes with evidence, expiry by code hash, and a ranked queue”

