fix(research): extend single-label host reject to Tier-1 derivation (§1.7 backward-sweep follow-up to #857) - #860
Merged
Conversation
…§1.7 backward-sweep)
The §1.7 backward-sweep of this umbrella's Tier-2 guard (loadAckFile single-label
reject) found the SAME single-label gap on the parallel host-derivation surface:
tier1For's candidateFields filter rejected IP-literal / punycode / multi-tenant
hosts but NOT bare TLDs. Proved live: homepage "https://com" (or repository
"https://io") derives a Tier-1 host "com", scope-locked to that package, which
hostMatches would then treat as authorizing every *.com for that package's
research. Non-escalating (requires the package to be an installed direct dep —
npm already ran its lifecycle code, a strictly larger grant), but a real,
avoidable widening in the same class as the IP-literal/punycode rejects sitting
beside it — the exact inconsistency the Tier-2 guard closed.
Fix: add `if (!host.includes('.')) continue;` to the candidateFields loop, right
after the isIpLiteral reject — so Tier-1 package-metadata hosts and Tier-2 ack
hosts reject bare TLDs consistently. Paired-negative tier1.test.ts S2-N8
(homepage "com" AND repository "io" → tier1For yields no host; RED without the
guard per the live derivation proof, GREEN with it). Bundle regenerated (tier1For
is bundled) — drift check green. §5 item 4 records the both-surfaces coverage.
This is the recursive-self-application (invariant #2) the backward-check exists to
force: apply the new guard's logic to its sibling artefacts, not just the one the
finding started on.
§1.7: forward-check — complies with no-paid-llm-in-ci.md (guard + S2-N8 are deterministic vitest, zero API, allowlist-resolver.ts:200); doc-authority-hierarchy.md §2-§3 (research-source-trust.md header untouched, principle 09 green); build-first-reuse-default.md (in-file guard + test, no new dep; REFERENCE prior-art-evaluations.md#186-#188); ai-laziness-traps.md §2 T15 (recursive self-application — the guard is swept onto its Tier-1 sibling, not left one-surface). backward-check — the sweep itself: enumerated every host-derivation surface (Tier-0 curated const — not human/attacker-writable; Tier-1 candidateFields — GAP found + closed here; Tier-2 loadAckFile — closed in the prior commit), tier1.test.ts:205 positive control still authorizes a legitimate two-label host; no surface left inconsistent.
Prior-art: skipped — in-file guard + paired-negative test extending an existing capability (the Tier-1 resolver) onto its sibling surface; no new dependency or code-module.
artyhoo
enabled auto-merge (squash)
July 2, 2026 22:44
Merged
8 tasks
artyhoo
pushed a commit
that referenced
this pull request
Jul 3, 2026
…SSOT #195) Reconcile the parallel-evolution collision with staging (moved to c07563d during the D1 run) and unblock the merge, per maintainer 'go' 2026-07-03: 1. Cosmetic conflict in allowlist-resolver.ts — #860 independently added the byte-identical bare-TLD Tier-1 guard D1 also has (WF restore cc90b3a + S2-N8); resolved keeping D1's Diagnostic|null-migrated version (guard identical). 2. #861 shipped agents/backward-sweep-auditor.md with no Prior-art trailer/SSOT -> staging audit-self was RED on principle 11 F1. Closed as an SSOT DATA fix: new entry #195 (BUILD verdict, cold PR-blind sibling-surface enumerator, no upstream analog) supplies the F1 match. No code change to #861's agent; the underlying gap is #861's, fixed here under explicit maintainer authorization to land the chain. Bundle regenerated (--check green). Full packages/core suite 1893 passed | 12 skipped; principle 11 8/8; typecheck clean post-merge. Prior-art: skipped — merge reconciliation + an SSOT data-entry (#195) closing an inherited pre-existing F1 gap; no new capability introduced by this merge
4 tasks
artyhoo
added a commit
that referenced
this pull request
Jul 3, 2026
…ging (#879) Kickoff was authored locally on fix/trust-tiers-s5-readjudication (whose own work is already merged via #857/#860) and never committed. Per kickoff-staging-placement.md, a kickoff only on a feature branch is invisible to /pipeline and aif dispatch — land it on staging before any dispatch. Prior-art: skipped — docs-only kickoff authoring, no new capability Co-authored-by: t <t@t.co>
2 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
Follow-up to the merged #857. #857's §1.7 backward-sweep (done properly after an operator challenge) surfaced a parallel gap — but the fix landed on the branch after #857 was already squash-merged, so it did not reach
staging. This PR carries just that one delta.The gap (still open in
staging): the single-label-host reject #857 added to Tier-2 (loadAckFile) had an identical sibling hole in Tier-1 derivation.tier1For'scandidateFieldsfilter rejected IP-literal / punycode / multi-tenant hosts but not bare TLDs — so a direct dependency withhomepage: "https://com"(orrepository: "https://io") derives a trusted Tier-1 hostcom, scope-locked to that package, whichhostMatchesthen treats as authorizing every*.comfor that package's research.Reachability: non-escalating — the package must be an installed direct dependency (npm already ran its lifecycle code, a strictly larger grant). But it is a real, avoidable widening in the same class as the IP-literal / punycode rejects sitting beside it — the exact inconsistency #857 closed on the Tier-2 surface. Proved live:
homepage:"https://com"→ derived hostcom.Fix:
if (!host.includes('.')) continue;in thecandidateFieldsloop, right after theisIpLiteralreject — so Tier-1 package-metadata hosts and Tier-2 ack hosts reject bare TLDs consistently. Paired-negativetier1.test.tsS2-N8 (comhomepage +iorepository →tier1Foryields no host). Bundle regenerated (tier1Foris bundled) — drift check green.research-source-trust.md§5 item 4 already records the both-surfaces coverage (came in via #857 commit 1's doc; this PR's source change makes it true).This is the recursive-self-application (invariant #2) the backward-check exists to force: apply a new guard's logic to its sibling artefacts, not only the surface the finding started on.
Verification (on the current
stagingbase)tier1.test.tsS2-N8 green (RED without the guard, proven by the live derivation ofcom/io); positive control still authorizes a legitimate two-label hostloadAckFile+ Tier-1candidateFields)build:synth-bundle:check— cherry-picked bundle matches a fresh build on thestagingbasetsc --noEmitclean; markdownlint clean§1.7 Forward-check applied
Existing disciplines checked: no-paid-llm-in-ci.md — the guard + S2-N8 are deterministic vitest, zero API-billed calls (
allowlist-resolver.ts:200). doc-authority-hierarchy.md §2-§3 —research-source-trust.md's Class-A + Authoritative-for header untouched; principle 09 green. build-first-reuse-default.md — in-file guard + test, no new dependency/module; REFERENCEprior-art-evaluations.md#186-#188. ai-laziness-traps.md §2 T15 — recursive self-application: the guard is swept onto its Tier-1 sibling, not left one-surface.§1.7 Backward-check applied
The sweep (this PR is itself the sweep result): #857's Tier-2 guard rejects single-label hosts, so I enumerated every host-derivation surface for the same class of gap: Tier-0 (
ALLOWED_SOURCEScurated const) — hand-curated, not human/attacker-writable, no single-label hosts, no gap; Tier-1 (tier1ForcandidateFields) — GAP FOUND (homepage:"https://com"→ trustedcom), closed here atallowlist-resolver.ts:200+ paired-negativetier1.test.ts:205(S2-N8); Tier-2 (loadAckFile) — closed in #857. The positive control attier1.test.ts:227still authorizes a legitimate two-label host, and the shared-apex slice stays pinned by30-research-source-trust.test.ts:139. No host-derivation surface is left inconsistent; §5 structure + Class-A header preserved; principle 09/30 green.