Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
122 commits
Select commit Hold shift + click to select a range
ab09786
fix: stop repo gitignore hiding discovered source
Jun 21, 2026
e73124b
fix: prevent stdlib submodule spoof taints
Jun 21, 2026
c0de30c
fix: reject MCP doctor caller filigree URLs
Jun 21, 2026
7d16b55
fix: harden rekey snapshot provenance
Jun 21, 2026
b1a9de3
fix: preserve rust command shadow rebinds
Jun 21, 2026
0a30f62
fix: drop untrusted MCP sibling URLs
Jun 21, 2026
d7ecb90
fix: bound delta caller seed expansion
Jun 21, 2026
09eae7a
fix: preserve explicit sibling loopback pins
Jun 21, 2026
cddc421
Add `yaml.unsafe_load` and `yaml.full_load` to serialization sinks
google-labs-jules[bot] Jun 21, 2026
c4cf7c8
chore(deps): bump pypa/gh-action-pypi-publish
dependabot[bot] Jun 21, 2026
4ad7776
chore(deps): bump actions/configure-pages from 5 to 6
dependabot[bot] Jun 21, 2026
36c2ea3
chore(deps): bump actions/deploy-pages from 4 to 5
dependabot[bot] Jun 21, 2026
646ff0f
chore(deps): bump actions/checkout from 4 to 7
dependabot[bot] Jun 21, 2026
4e8e107
chore(deps): bump astral-sh/setup-uv from 7.6.0 to 8.2.0
dependabot[bot] Jun 21, 2026
cbd287d
fix: gate waiver_add entity_symbol resolve under MCP network policy
Jun 22, 2026
6d9172c
fix: eliminate cubic candidate-set merge blowup (scan DoS)
Jun 22, 2026
504cf87
docs: consolidate Wardline release materials
Jun 22, 2026
b5bdb7d
docs: consolidate Wardline release materials
Jun 23, 2026
073ec2f
Fix git core.fsmonitor local execution vulnerabilities
google-labs-jules[bot] Jun 23, 2026
8418c77
Fix git core.fsmonitor local execution vulnerabilities
google-labs-jules[bot] Jun 23, 2026
f6cf5e7
fix(doctor): preserve filigree probe provenance
Jun 23, 2026
bc96534
fix(filigree): soft-fail unsafe mint token reads
Jun 23, 2026
eff7c7c
fix(scanner): bound l2 taint analysis work
Jun 23, 2026
5113b44
fix(filigree): avoid response body amplification
Jun 24, 2026
42e2bab
fix(site): pin site-kit fetch in pages build
Jun 24, 2026
e27ed1b
fix(mcp): advertise scan integration effects
Jun 24, 2026
de1509d
fix(mcp): gate rekey cache-dir writes
Jun 24, 2026
9747831
fix(rust): isolate mount overlay prepass failures
Jun 24, 2026
751af16
fix(fingerprint): bind singleton suppressions to source body
Jun 24, 2026
3e1db6b
fix(rust): surface invalid trust markers
Jun 24, 2026
5b30a2f
fix(fingerprint): include full call spans
Jun 24, 2026
e4e4b20
fix(gitignore): track wardline suppression state
Jun 24, 2026
27ec91e
fix(doctor): preserve resolved url provenance
Jun 24, 2026
eca642c
fix(scan): guard explicit output paths
Jun 24, 2026
f42875d
fix(scan): preserve raw hashes for CRLF files
Jun 24, 2026
1e3e0d6
fix(filigree): require confirmed legacy identity
Jun 24, 2026
a0d28f6
fix(rust): tolerate invalid UTF-8 manifests
Jun 24, 2026
edf852d
fix(install): repair mismatched filigree loopback urls
Jun 24, 2026
8f603b3
fix(rust): track args and captured format taint
Jun 24, 2026
31e03a4
fix(rust): normalize nested cfg predicates
Jun 24, 2026
4fbe585
fix(rust): avoid recursive inline module indexing
Jun 24, 2026
84f01cf
fix(discovery): keep nested Rust target modules
Jun 24, 2026
9638114
fix(install): avoid quadratic foreign fence scan
Jun 24, 2026
5924d7f
fix(filigree): redact diagnostic URLs
Jun 24, 2026
22a21ca
Merge branch 'fix/candidate-set-merge-dos' into release/consolidation…
Jun 24, 2026
e511f0c
Merge branch 'origin/release/consolidation-2026-06-23' into release/c…
Jun 24, 2026
9fd2ac0
Merge branch 'origin/dependabot/github_actions/actions/checkout-7' in…
Jun 24, 2026
8b2a534
Merge branch 'origin/dependabot/github_actions/actions/configure-page…
Jun 24, 2026
312151d
Merge branch 'origin/dependabot/github_actions/actions/deploy-pages-5…
Jun 24, 2026
c415619
Merge branch 'origin/dependabot/github_actions/actions-minor-patch-8d…
Jun 24, 2026
fa3a292
Merge branch 'origin/dependabot/github_actions/astral-sh/setup-uv-8.2…
Jun 24, 2026
4e5ba38
Merge branch 'origin/sentinel-git-fsmonitor-fix-12815921081369848082'…
Jun 24, 2026
05f956a
Merge branch 'origin/sentinel/yaml-serialization-sinks-17995805523521…
Jun 24, 2026
8def1a4
docs: spec for project-root-anchored scan artifacts + doctor hygiene
Jun 25, 2026
e55501c
docs: revise project-root-anchored artifacts spec per panel review
Jun 25, 2026
5b2146f
docs: capture _ensure_weft_config ordering hazard in artifacts spec
Jun 25, 2026
0670360
docs: resolve MCP doctor delete posture to 'MCP can delete too'
Jun 25, 2026
9096ff0
docs: TDD implementation plan for project-root-anchored artifacts
Jun 25, 2026
f2b1833
docs: revise plan per plan-review (advisory DoctorCheck status contract)
Jun 25, 2026
86759ac
feat(paths): project_root_for + artifacts_dir helpers (own DEFAULT_AR…
Jun 25, 2026
125a9de
feat(artifacts): anchor default scan artifacts to the weft-project root
Jun 25, 2026
998c367
fix(run): drop stale 'output defaults under the subdirectory' clause …
Jun 25, 2026
41e6ced
test(scan): pin project-root artifact anchoring end-to-end
Jun 25, 2026
a4018e8
refactor(discovery): expose WALK_SKIP_DIRS for the doctor sweep
Jun 25, 2026
bcc0a91
feat(doctor): DoctorCheck carries removed/review payload lists
Jun 25, 2026
eeec30f
feat(doctor): _check_gitignore — advisory, idempotent, CRLF-safe mana…
Jun 25, 2026
822f0d4
feat(doctor): _sweep_stray_artifacts — confined, no-follow, nested-ro…
Jun 25, 2026
ce1cd43
feat(doctor): wire gitignore+sweep into doctor; anchor to project_roo…
Jun 25, 2026
e8926c4
fix(artifacts): restore dir-level symlink guard lost in the project-r…
Jun 25, 2026
2cf95ef
feat(mcp): doctor repair:true deletes strays; advertise destructiveHi…
Jun 25, 2026
134dbd3
docs: project-root-anchored artifacts + doctor hygiene (CHANGELOG + g…
Jun 25, 2026
3a57bf4
fix(doctor): always protect default .wardline; align symlink exit cod…
Jun 25, 2026
b3db52a
Merge feat/project-root-anchored-artifacts into release/consolidation…
Jun 25, 2026
0a8b8d4
docs(weft): weft-seam conformance program plan + reusable kit spec
Jun 25, 2026
aff3761
feat(conformance): P0 enforceable weft seam registry + fail-closed gate
Jun 25, 2026
5b0dcf2
refactor(federation): extract shared WeftHttp transport (wardline-184…
Jun 25, 2026
9f0c4d1
refactor(federation): single-source the federation-status envelope (w…
Jun 25, 2026
861e6cf
feat(conformance): SEI(loomweave->wardline) reaches at_bar via consum…
Jun 25, 2026
cf248a5
feat(conformance): qualname parity reaches at_bar (live oracle + both…
Jun 25, 2026
4b9561d
feat(conformance): 3 consumer seams reach at_bar + harden the keyston…
Jun 25, 2026
461e25f
feat(conformance): MCP B1/B2 reaches at_bar via one-sided golden-sche…
Jun 25, 2026
dd82307
feat(conformance): suppression-filter seam reaches at_bar (wardline-a…
Jun 25, 2026
54c6582
feat(conformance): scan-results emission/intake reaches at_bar (cross…
Jun 25, 2026
00f1f83
feat(conformance): finding-identity wire reaches at_bar (cross-repo)
Jun 25, 2026
b714296
feat(conformance): taint-fact store wire reaches at_bar (cross-repo, …
Jun 25, 2026
5903b45
feat(conformance): vocabulary-descriptor wire reaches at_bar (cross-r…
Jun 25, 2026
78bd22e
feat(conformance): G1 wardline->legis scan-artifact wire reaches at_b…
Jun 25, 2026
5de9e23
feat(conformance): peer_conformant verdict + dispose the 7 legis peer…
Jun 25, 2026
0729a86
fix(conformance): downgrade SEI-wire-transport peer_conformant -> gap…
Jun 25, 2026
808e497
Merge weft-seam-conformance into release/consolidation-2026-06-26
Jun 25, 2026
d172f73
site: member-specific deconfliction-not-security disclaimer + Charter…
Jun 26, 2026
df0a79f
docs(seam): adjudicate legis→warpline preflight seam — legis conforms…
Jun 26, 2026
9f5924b
feat(delta): declare scope_source + warpline producer_generated_at in…
Jun 26, 2026
dffa092
feat(attest): bump to wardline-attest-2 with per-boundary content_has…
Jun 26, 2026
ab0754f
test(contract): publish wardline.delta_scope.v1 + strengthen worklist…
Jun 26, 2026
7b4afcd
fix(attest): correct content_hash granularity label — entity-body, no…
Jun 26, 2026
33d5d5f
feat(delta): mirror warpline impact_completeness as producer_complete…
Jun 26, 2026
b1a97d5
docs(contract): publish wardline-attest-2 consumer prompt (warpline R…
Jun 27, 2026
c32563d
style: apply ruff format to satisfy the Lint+Format CI gate
Jun 27, 2026
29170e5
feat(doctor): detect & clear stale sibling ephemeral.port files
Jun 27, 2026
595e953
fix(doctor): preserve probe provenance and gate stale probes
Jun 27, 2026
d5efdd0
product: rotate Now → weft-seam-conformance (crash recovery); PDR-0002
Jun 27, 2026
c661286
feat(doctor): repo_binding store-read check — let the seam say "I can…
Jun 27, 2026
6508c07
product: doctor.repo_binding seam leg landed (Now bet execution); PDR…
Jun 27, 2026
c7fa458
product: ACCEPT PRD-0001 (Codex P1 close-out — bet paid off); PDR-0004
Jun 27, 2026
8fe09d6
feat(ci): fail-closed source-drift job; arm sei_drift/worklist_drift …
Jun 27, 2026
a1f121f
docs(plan): mark crit-3b T3 done + CI-verified (run 28301178826)
Jun 27, 2026
b6704c0
fix(fingerprint): make entity_source_fingerprint interpreter-stable (…
Jun 27, 2026
e4668ab
product: ACCEPT crit-3 (source-drift CI fail-closed) + fingerprint cr…
Jun 27, 2026
7e99147
docs: add 2026-06-28 architecture analysis
Jun 28, 2026
b5abe39
fix: harden baseline and delta contracts
Jun 28, 2026
cfe546e
refactor(core): break the broad core/ layering residual + enforce it
Jun 28, 2026
b3d0a81
feat(scan): surface INERT taint gate — Python enforcement-posture vis…
Jun 28, 2026
72bc9eb
feat(grammar): pack-bridge for elspeth's @trust_boundary vocabulary
Jun 28, 2026
f40b3d5
product: elspeth dogfood detour — ship inert-gate visibility + pack-b…
Jun 28, 2026
9886280
refactor(grammar): de-elspeth the pack-bridge — generic third-party t…
Jun 28, 2026
652d3bf
feat(doctor): engine self-test + configured-but-missing loomweave dep…
Jun 28, 2026
b5170e2
feat(scan): FastAPI/starlette request-type taint source coverage
Jun 28, 2026
53a1424
fix(docs): re-sync glossary line-anchors after the Part A summary-blo…
Jun 28, 2026
8004fa2
product: Q4 resolved — hold 'silent until opted in', instrument inert…
Jun 28, 2026
adb42a0
release: v1.1.0 — curated CHANGELOG + version bump
Jun 28, 2026
3540145
fix(release): ruff-format install/doctor.py + make version test minor…
Jun 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 73 additions & 17 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,31 +21,32 @@ jobs:
runs-on: ubuntu-latest
if: github.event_name != 'schedule'
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
with:
enable-cache: true
python-version: "3.13"
- run: uv sync --all-extras --group dev
- run: uv run ruff check src tests
- run: uv run ruff format --check src tests
- name: Layering contracts (import-linter, report-only)
# Report-only: `|| true` keeps this non-blocking. Encodes intended core/ layering
# (taint engine must not import the attestation layer). BROKEN today; the layering
# agent moves the code (wardline-9ec283d168). Surfaces drift without gating CI.
run: uv run lint-imports || true
- name: Layering contracts (import-linter, enforcing)
# Gating: the engine and policy tiers must not import up into orchestration,
# output, or federation (engine-purity + policy-purity, both KEPT). See
# [tool.importlinter] in pyproject.toml for the tier model; intra-tier cycles
# are guarded by tests/conformance/test_import_layering.py.
run: uv run lint-imports

typecheck:
name: Types (mypy strict)
runs-on: ubuntu-latest
if: github.event_name != 'schedule'
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
with:
enable-cache: true
python-version: "3.13"
Expand All @@ -60,10 +61,10 @@ jobs:
matrix:
python-version: ["3.12", "3.13"]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
with:
enable-cache: true
python-version: ${{ matrix.python-version }}
Expand All @@ -76,10 +77,10 @@ jobs:
needs: test
if: github.event_name != 'schedule'
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
with:
enable-cache: true
python-version: "3.13"
Expand Down Expand Up @@ -120,10 +121,10 @@ jobs:
runs-on: ubuntu-latest
if: github.event_name == 'schedule'
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
with:
enable-cache: true
python-version: "3.13"
Expand Down Expand Up @@ -163,10 +164,10 @@ jobs:
- name: Warpline
marker: warpline_e2e
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
with:
enable-cache: true
python-version: "3.13"
Expand All @@ -188,3 +189,58 @@ jobs:
echo "- Trigger: \`${{ github.event_name }}\`"
echo "- Missing local services, secrets, or capabilities fail this required oracle run."
} >> "$GITHUB_STEP_SUMMARY"

# Producer-source drift: byte-compares wardline's vendored fixtures against the
# authoritative sibling SOURCE on origin/main (loomweave SEI oracle, warpline
# reverify-worklist wire). The default PR suite already fail-closes on a vendored-copy
# EDIT via the Layer-1 blob-pins; this job closes the other half — a silent divergence
# between the vendored copy and the upstream HEAD — which no PR-time test can see without
# the sibling source. Weekly/dispatch only (a sibling change must never block a wardline
# PR); needs WARDLINE_SIBLING_SOURCE_TOKEN (read-only) to check out the private siblings.
# crit-3b: wardline-79ba05f464 (SEI) / wardline-c0563eee74 (warpline worklist).
source-drift:
name: Sibling-source drift (weekly/manual, fail-closed)
runs-on: ubuntu-latest
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
- name: Check out loomweave source (read-only)
uses: actions/checkout@v7
with:
repository: foundryside-dev/loomweave
token: ${{ secrets.WARDLINE_SIBLING_SOURCE_TOKEN }}
path: _siblings/loomweave
persist-credentials: false
- name: Check out warpline source (read-only)
uses: actions/checkout@v7
with:
repository: foundryside-dev/warpline
token: ${{ secrets.WARDLINE_SIBLING_SOURCE_TOKEN }}
path: _siblings/warpline
persist-credentials: false
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
with:
enable-cache: true
python-version: "3.13"
- run: uv sync --all-extras --group dev
- name: Source-byte drift vs sibling origin/main (fail-closed)
# WARDLINE_LIVE_ORACLE_REQUIRED=1 turns a missing-source SKIP into a FAILURE
# (sei_drift/worklist_drift are in LIVE_ORACLE_MARKERS), so a broken checkout fails
# the required run instead of passing green. A genuine drift (a sibling shipped a new
# contract) reds this until wardline re-vendors per each module's RE-VENDOR PROCEDURE.
run: uv run pytest tests/conformance -m "sei_drift or worklist_drift" -v
env:
WARDLINE_LIVE_ORACLE_REQUIRED: "1"
WARDLINE_LOOMWEAVE_REPO: ${{ github.workspace }}/_siblings/loomweave
WARDLINE_WARPLINE_REPO: ${{ github.workspace }}/_siblings/warpline
- name: Summarize source-drift
if: always()
run: |
{
echo "### Sibling-source drift"
echo "- Markers: \`sei_drift\`, \`worklist_drift\` (byte-compare vs loomweave + warpline origin/main)"
echo "- Trigger: \`${{ github.event_name }}\`"
echo "- A vendored-fixture drift, or a failed sibling checkout, fails this required run."
} >> "$GITHUB_STEP_SUMMARY"
13 changes: 9 additions & 4 deletions .github/workflows/deploy-site.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# copied verbatim into the build output). It consumes the shared @weft/site-kit,
# which lives in a SUBDIRECTORY of a DIFFERENT repo (foundryside-dev/weft).
# npm cannot install a git subdirectory as a file: dep directly, so the build
# sparse-fetches packages/site-kit into site/vendor/site-kit first
# sparse-fetches a pinned packages/site-kit commit into site/vendor/site-kit first
# (scripts/fetch-site-kit.mjs), then `npm install` resolves the file: dep and
# `astro build` compiles it. The fetch also runs as a preinstall hook, but the
# explicit step keeps the order legible.
Expand All @@ -29,6 +29,11 @@ concurrency:
group: pages
cancel-in-progress: false

env:
# Privileged Pages builds must consume an immutable site-kit revision. Update
# this SHA deliberately when promoting a new foundryside-dev/weft site kit.
WEFT_SITE_KIT_REF: a8f9a6a77458d2ec697cfbc1f71dd88a51962cb7

jobs:
build:
runs-on: ubuntu-latest
Expand All @@ -37,13 +42,13 @@ jobs:
working-directory: site
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v7

- name: Configure Pages
# Pin the Pages source to GitHub Actions (build_type=workflow); enables
# Pages if needed. Without this, deploy-pages fails when the repo is
# still set to "Deploy from a branch".
uses: actions/configure-pages@v5
uses: actions/configure-pages@v6
with:
enablement: true

Expand Down Expand Up @@ -78,4 +83,4 @@ jobs:
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
uses: actions/deploy-pages@v5
6 changes: 3 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ jobs:
name: Build distributions
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7
- uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
with:
enable-cache: true
python-version: "3.13"
Expand Down Expand Up @@ -59,4 +59,4 @@ jobs:
# twine reject it ("Unknown distribution format") and blocks the release.
# Verification above already consumed it.
run: rm -f dist/SHA256SUMS
- uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
- uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ output/
# port (a live, never-committed runtime artifact, not tracked state).
.weft/*/ephemeral.port

# Local sibling tool stores are runtime/tooling state for this checkout. Keep
# wardline's own .weft/wardline/ suppression state visible and auditable.
.weft/filigree/
.weft/loomweave/
.weft/warpline/

# Filigree issue tracker
.filigree/
.env
Expand All @@ -56,7 +62,6 @@ coverage.json
loomweave.yaml

# Filigree issue tracker
.weft/
.filigree.conf
.agents/skills/loomweave-workflow/.fingerprint
.agents/skills/loomweave-workflow/SKILL.md
Expand Down
9 changes: 9 additions & 0 deletions .jules/sentinel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
## 2025-02-14 - Prevent Git Config Code Execution
**Vulnerability:** Invoking `git` via `subprocess` against untrusted directories without overriding config can allow malicious repositories to execute code via `.git/config` hooks like `core.fsmonitor`.
**Learning:** `git` uses configurations from the `.git/config` file in the current working directory or `cwd` argument, which could be controlled by an attacker when analyzing untrusted codebases.
**Prevention:** Explicitly pass `("-c", "core.fsmonitor=false")` as `_SAFE_GIT_CONFIG` to all `git` subprocess commands in the codebase.

## 2026-06-21 - [Add Unsafe PyYAML Loaders to Taint Tracking]
**Vulnerability:** The static analyzer was missing `yaml.unsafe_load` and `yaml.full_load` in its `_SERIALISATION_SINKS` mapping, potentially leading to false negatives when tracking untrusted data flowing into these dangerous deserialization functions.
**Learning:** Even if functions are listed in rule specifications (like `_SINK_SPECS`), they also need to be properly categorized in the core taint propagation logic (`_SERIALISATION_SINKS`) to ensure the analyzer correctly sheds validation provenance (converting output to `UNKNOWN_RAW`).
**Prevention:** When adding new sinks to rule definitions, always verify if they need to be added to core propagation mappings like `_SERIALISATION_SINKS` or `_PROPAGATING_BUILTINS`.
91 changes: 91 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,96 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [1.1.0] - 2026-06-29

### Changed
- **BREAKING (unreleased contract):** attest bundle schema bumped `wardline-attest-1` → `wardline-attest-2`; each boundary now carries `content_hash` (entity-body span blake3 binding key, null when unresolved). `wardline-attest-1` bundles no longer verify.
- Default scan artifacts now anchor to the weft-project root (the `weft.toml` directory)
rather than the scan cwd, so a subdirectory scan writes to `<project-root>/.wardline/`.
Retention is therefore project-root-wide across heterogeneous subdir/root scans sharing
one `.wardline/`. **Migration:** the artifact moves to the project root; `wardline doctor
--repair` sweeps now-stale per-subdir `.wardline/` dirs — update any CI/automation reading
a hardcoded `<subdir>/.wardline/*-findings.jsonl` path.

### Added
- **FastAPI / Starlette request-type taint source coverage.** `wardline` now seeds
untrusted taint from the raw request accessors on `fastapi.Request` /
`starlette.requests.Request` receivers — the `query_params` / `path_params` /
`headers` / `cookies` properties and the `json` / `body` / `form` / `stream`
methods — so request data flowing into a declared `@trusted` sink is flagged
without hand-annotating every access. Type-aware: a non-request attribute on the
same receiver (e.g. `req.app.state.db`) does not fire. Still annotation-driven —
it lights up on top of your declared trusted core, not on an unannotated app.
- **Inert-gate visibility (enforcement-posture honesty).** Scan output now always
carries a `resolution.inert` posture field (agent-summary + MCP). An armed gate
(`--fail-on`) that passes while the scan recognized **zero** trust boundaries
prints a reliance-gated stderr banner — closing the "green while checking nothing"
false-assurance gap on annotation-driven scans. Calibrated to stay silent on bare/
advisory scans and on legitimately boundary-free pure-logic code.
- **Third-party trust-vocabulary pack-bridge.** A wardline pack can now map another
project's own trust-boundary decorator vocabulary onto a wardline `BoundaryType`,
so a team with existing trust annotations in a different grammar gets enforcement
by referencing one pack under `[wardline] packs` in `weft.toml` (or `--trust-pack`)
— no re-annotation.
- **`wardline doctor` engine self-test + loomweave-dep flag.** New `engine.selftest`
check runs the analyzer on a built-in trusted source→sink and asserts the taint
rule fires ("taint analysis fires correctly"); new `loomweave.dep` check flags a
configured-but-missing `[loomweave]` extra.
- **`wardline doctor` repo-binding store-read check.** A present-but-unreadable
baseline store now reports a machine-readable reason and `binding_ok=false` — the
seam can say "I can't read my store" instead of returning a confident empty.
- Delta-scan scope block now declares its `scope_source` and echoes warpline's unverified `producer_completeness` (warpline's `data.impact_completeness` — combined completeness+staleness object) across CLI/SARIF/MCP; MCP scope schema is key-parity-tested against `DeltaScopeReport`. Replaces the removed `producer_generated_at` (which read a phantom `data.generated_at` key warpline never emitted).
- `wardline doctor --repair` gitignores the artifacts dir and sweeps stray managed
artifacts; deletion is available on both the CLI and the MCP `doctor` tool (`repair:true`,
advertised `destructiveHint: true`), bounded to managed (timestamped) files inside
non-standard `.wardline/` dirs under the project root; emptied dirs are removed
best-effort (non-empty dirs are left in place).
- **`wardline doctor` detects and clears stale sibling `ephemeral.port` files** (new
`stale_sibling_ports` check, CLI + MCP `doctor` tool). A sibling's
`.weft/<sibling>/ephemeral.port` advertises a live `serve` instance; when that process
has exited or wedged, the file lingers and every scan dials a dead/hung origin —
stalling the agent gate up to the federation 30s `urlopen` timeout per round-trip on a
purely advisory emission (the reported `wardline scan` hang). The check probes each
advertised port (filigree, loomweave) at the host the scan dials, with a short 2s
deadline (not 30s): an unreachable port — connection refused **or** no HTTP reply within
the deadline (a wedged server) — is stale, and `--repair`/`fix:true` deletes the file so
the scan stops dialing it. A live server (any HTTP status) is never touched; the delete
is regular-file / no-follow confined (a symlinked `ephemeral.port` is never followed).
Advisory like the stray-artifact sweep — a stale port never flips the aggregate doctor
verdict.

### Security
- **Cross-interpreter fingerprint determinism (3.12 == 3.13).** `entity_source_fingerprint`
previously hashed `ast.dump`, whose output changed in CPython 3.13
(`show_empty=False` omits empty-list fields), making the cross-tool JOIN KEY
(baseline / waiver / judged stores + the Filigree wire) interpreter-dependent — a
silent-drop-on-join hazard where a finding suppressed under one interpreter could
reappear under another. The fingerprint now uses a structural, version-stable
canonical dump; the join key is byte-identical across 3.12 / 3.13, proven by the CI
matrix. **No scheme bump** — 3.13 reference values are unchanged.
- **Agent-surface hardening batch.** Closed a set of MCP / federation policy-bypass
and resource-exhaustion holes: MCP network-policy gates on `waiver_add` entity
resolution and `rekey` cache-dir writes; rejection of untrusted MCP sibling and
doctor-caller URLs; rekey snapshot-provenance hardening; stdlib-submodule
spoof-taint prevention; Filigree diagnostic-URL redaction, response-body-amplification
bound, and unsafe-mint-token soft-fail; a quadratic foreign-fence scan bound (and,
under Fixed, the cubic candidate-set scan-DoS). Enforced by the soundness oracle +
the security regression suite; a new fail-open hole is treated as a P0.

### Fixed
- **Candidate-set merge no longer scales cubically (scan DoS).** The Level-2
branch-join merges for lambda bindings (`_merge_branch_bindings`) and
receiver-type candidates (`_merge_branch_types`) deduplicated with a nested
linear scan of the growing candidate list — O(bucket²) per merge, O(N³)
across a chain of `N` one-armed branches rebinding the same name. An
attacker-authored file (~1100 such branches) could drive a default-gate scan
to ~15s and exhaust CPU on every local and CI run. Both merges now dedup via
an identity/equality set (O(bucket) per merge, O(N²) cumulative), preserving
the exact candidate set and insertion order; the demonstrated 1100-branch case
drops from seconds to milliseconds. No analysis behavior changes — the
candidate sets are identical, so no false negative is introduced.
Reviewed regression source: `eff4eed2` (wardline-c797baf28b).

## [1.0.7] - 2026-06-24

### Fixed
Expand Down Expand Up @@ -1353,6 +1443,7 @@ for Python — enterprise-class trust-boundary analysis at small-team weight.
- **Packaging** — MIT-licensed; optional extras `scanner` (config + CLI) and
`weft` (HTTP integrations).

[Unreleased]: https://github.com/foundryside-dev/wardline/compare/v1.0.6...HEAD
[1.0.6]: https://github.com/foundryside-dev/wardline/compare/v1.0.5...v1.0.6
[1.0.5]: https://github.com/foundryside-dev/wardline/compare/v1.0.4...v1.0.5
[1.0.4]: https://github.com/foundryside-dev/wardline/compare/v1.0.3...v1.0.4
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ see `CLAUDE.md`).

- **TDD.** Write the failing test first.
- Keep PRs focused — one logical change per PR.
- New behavior needs tests. New `wardline.yaml` keys need a `config_schema.py` update.
- New behavior needs tests. New `[wardline]` keys in `weft.toml` need a `config_schema.py` update.
- No back-compat shims for unreleased specs — make clean changes.
- Wardline scans its own source as a CI gate; keep the tree finding-clean (or baselined).

Expand Down
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ help: ## Show this help message
install: ## Install all extras + dev tooling
uv sync --all-extras --group dev

lint: ## Run linter + format check
lint: ## Run linter + format check + layering contracts
uv run ruff check src tests
uv run ruff format --check src tests
uv run lint-imports

format: ## Auto-format and fix lint
uv run ruff format src tests
Expand Down
Loading