Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .agent-loop/CURRENT_STATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ authority; these records do not grant or withhold it.
| [WS-CI-002](initiatives/WS-CI-002-deterministic-agent-gates/STATUS.md) | `WS-CI-002-01` complete through PR #311; Agent Gates is deterministic per PR head | Preserve protected-branch review as the independent approval authority |
| [WS-CI-003](initiatives/WS-CI-003-atomic-chunk-state/STATUS.md) | `WS-CI-003-01` complete | Require every chunk PR to land its final contract and initiative state atomically |
| [WS-DB-001](initiatives/WS-DB-001-v01-schema-baseline/STATUS.md) | v0.1 schema baseline complete through PRs #316 and #317 | Extend `0001_v01_baseline` only through future bounded migrations |
| [WS-SEC-001](initiatives/WS-SEC-001-dependency-alert-remediation/STATUS.md) | `WS-SEC-001-01` complete on merge with patched runtime and tooling dependencies | Handle future security alerts through fresh bounded dependency changes |
| [WS-DOCS-001](initiatives/WS-DOCS-001-current-v01-documentation/STATUS.md) | Current v0.1 entry documentation complete | Keep current pages synchronized with merged capability changes |
| [WS-DOCS-002](initiatives/WS-DOCS-002-workstream-definition/STATUS.md) | Canonical Workstream definition complete | Preserve terminology across current documentation and generated artifacts |
| [WS-XINT-001](initiatives/WS-XINT-001-lifecycle-boundary-reconciliation/STATUS.md) | Planning reconciliation complete and closed | Owner initiatives implement the resulting boundaries |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Chunk Map: WS-SEC-001 Dependency Alert Remediation

| Chunk | Goal | Risk | State |
|---|---|---:|---|
| `WS-SEC-001-01` | Upgrade six Dependabot-alerted runtime and tooling dependency records without changing product behavior | L1 | Complete |
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Status: WS-SEC-001 Dependency Alert Remediation

- Initiative state: complete on merge of `WS-SEC-001-01`
- Runtime dependency outcome: `cryptography` and `pypdf` use patched versions.
- Tooling dependency outcome: backend manifests use patched `pytest` and
`pytest-asyncio`; mutation-tool manifests use patched `pytest` and `uv`
versions.
- Product behavior changed: no

Future dependency alerts use fresh bounded changes against current `main`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# WS-SEC-001-01: Patch Dependency Alerts

## Intent

Close the six open Dependabot alerts by moving direct and transitive runtime
dependencies and retained development tooling to patched versions.

## Allowed files

- `backend/pyproject.toml`
- `backend/uv.lock`
- `backend/config/guide_extractor_dependencies.json`
- `scripts/mutation-requirements.in`
- `scripts/mutation-requirements.txt`
- focused dependency tests or documentation if compatibility requires them
- `.agent-loop/CURRENT_STATE.md`
- `.agent-loop/initiatives/WS-SEC-001-dependency-alert-remediation/**`

## Not allowed

- Product behavior, API, persistence, migration, authorization, or workflow changes
- Disabling or dismissing alerts without a patched dependency
- Weakening dependency hashes, parser isolation, tests, coverage, or CI gates
- Unrelated dependency upgrades

## Acceptance criteria

- `cryptography` resolves to at least 50.0.0.
- `pypdf` is exactly 6.15.0 in the direct hash pin, approval manifest, and lock.
- Backend pytest resolves to at least 9.0.3 after compatibility validation.
- `pytest-asyncio` resolves to the tested pytest-9-compatible 1.4.x line.
- Retained mutation tooling pins pytest at least 9.0.3 and uv at least 0.11.15 with hashes.
- Guide dependency integrity and focused parser, auth, and mutation-policy tests pass.
- No Workstream product behavior changes.

## Risk and review

Risk: L1 security/dependency integrity. Required review: security, CI integrity,
test delta, and senior engineering.

## Verification

```bash
set -euo pipefail
cd backend
uv lock --check
uv run python scripts/check_guide_extractor_dependencies.py
uv pip install --dry-run --require-hashes \
-r ../scripts/mutation-requirements.txt
uv run pytest -q tests/test_guide_extractor_dependencies.py tests/test_guide_pdf.py tests/test_mutation_policy.py
WORKSTREAM_TEST_ADMIN_DATABASE_URL=postgresql+asyncpg://workstream:workstream@localhost:5433/postgres \
uv run python scripts/run_isolated_tests.py \
--metadata-json /tmp/ws-sec-001-auth-test.json \
--timeout-seconds 600 -- uv run pytest -q tests/test_auth.py
cd ..
python3 scripts/check_markdown_links.py
python3 scripts/check_chunk_state_sync.py --base-ref origin/main
git diff --check
Comment thread
coderabbitai[bot] marked this conversation as resolved.
```

## Merge state

- Outcome on merge: `complete`
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# External Review Response: WS-SEC-001-01

## Comments Addressed

- Raised the backend `pytest-asyncio` lower bound to the tested 1.4 line so the
declared range cannot select an earlier release that excludes pytest 9.
- Made the recorded verification sequence fail fast and added a hash-locked
dry run for the retained mutation-tool requirements.
- Named the backend `pytest`/`pytest-asyncio` pair and mutation `pytest`/`uv`
pair explicitly in the initiative outcome.
- Reverified that the direct pin, approval manifest, lock, and normative
specification agree on `pypdf` 6.15.0. No additional change was required for
that already-satisfied thread.
- Expanded the GitHub PR description to the repository trust-bundle structure.

## Comments Deferred

None.

## Human Decisions Needed

None beyond normal review and explicit merge approval.

## Commands Rerun

```bash
cd backend
uv lock --check
uv run python scripts/check_guide_extractor_dependencies.py
uv pip install --dry-run --require-hashes \
-r ../scripts/mutation-requirements.txt
uv run pytest -q tests/test_guide_extractor_dependencies.py \
tests/test_guide_pdf.py tests/test_mutation_policy.py
cd ..
python3 scripts/check_markdown_links.py
python3 scripts/check_chunk_state_sync.py --base-ref origin/main
git diff --check
```

## Remaining Risks

The full semantic-lane and coverage suite remains the exact-head GitHub
Backend workflow's responsibility.
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# PR Trust Bundle: WS-SEC-001-01

## Chunk

`WS-SEC-001-01` - Patch dependency alerts

## Goal And Context

Patch the six open Dependabot findings without changing Workstream product
behavior. The bounded contract is
[`WS-SEC-001-01-patch-dependency-alerts.md`](../chunks/WS-SEC-001-01-patch-dependency-alerts.md).

## What Changed And Why

- Upgraded `cryptography` and the approved `pypdf` artifact to patched lines.
- Upgraded backend pytest/pytest-asyncio and retained mutation pytest/uv
tooling to mutually compatible patched lines.
- Preserved exact artifact and mutation-manifest hashes.
- Synchronized the parser approval manifest, normative specification, and
durable initiative state.

## Scope Control

Only dependency declarations, generated locks, dependency approval records,
the matching normative version declarations, and WS-SEC-001 loop evidence
changed. No product behavior, API, persistence, migration, authorization,
workflow, test, coverage, or CI gate changed.

## Acceptance Proof

- Backend lock resolves `cryptography` 50.0.0, `pypdf` 6.15.0, pytest 9.1.1,
and pytest-asyncio 1.4.0.
- Mutation requirements hash-install pytest 9.0.3 and uv 0.11.15.
- The direct PDF pin, approval manifest, lock, and normative specification
agree on the approved version and artifact identity.
- Focused dependency/parser/mutation tests and real-PostgreSQL authorization
tests passed before publication; the exact-head GitHub workflow supplies the
complete semantic-lane and coverage proof.

## Reviewer Results

| Reviewer | Result | Blocking findings | Notes |
|---|---:|---|---|
| Security | PASS WITH LOW RISKS | None | Stale normative pypdf references fixed |
| CI integrity | PASS WITH LOW RISKS | None | No CI files or gates changed |
| Test delta | PASS WITH LOW RISKS | None | No tests or thresholds changed |
| Senior engineering | PASS WITH LOW RISKS | None | Resolver-marker churn noted as non-blocking |
| CodeRabbit | Addressed | None open after fixes | Three threads triaged; valid findings fixed |

## CI Integrity And Remaining Risks

No workflow, test, lint, coverage, or package-script gate was weakened. Backend
dev ranges may resolve later compatible minor releases in future fresh pip
installs; the exact PR head must pass GitHub Backend before merge.

## Human Review And Merge Ownership

Review the dependency versions, exact hashes, synchronized pypdf records, and
green exact-head checks. Only the user may approve and merge this PR.
12 changes: 6 additions & 6 deletions backend/config/guide_extractor_dependencies.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"advisory_snapshot": {
"checked_at": "2026-07-30",
"checked_at": "2026-08-12",
"provider": "OSV",
"query_url": "https://api.osv.dev/v1/query"
},
Expand All @@ -9,9 +9,9 @@
"advisories": [],
"approved_artifacts": [
{
"filename": "pypdf-6.14.2-py3-none-any.whl",
"sha256": "3f07891af76dc002657e04993ab9b4de81de29f9013b9761d0b7968bff12e946",
"url": "https://files.pythonhosted.org/packages/49/e6/136aa8993a2ae7214e0b0ef2edaa0d2e08d1d4e4982635b08a835ff31ec8/pypdf-6.14.2-py3-none-any.whl"
"filename": "pypdf-6.15.0-py3-none-any.whl",
"sha256": "14e001d6504822cb1ca9c7ed9a69bccb320f59b320730f55af804361abe4d5ee",
"url": "https://files.pythonhosted.org/packages/af/72/ce3067ac31e214a66388159f8462ddb8c13dd00170f24d555a1f1ae8ee91/pypdf-6.15.0-py3-none-any.whl"
}
],
"cancellation_timeout_implications": "Pure-Python parsing remains confined to the existing killable extraction child; cancellation never relies on cooperative parser shutdown.",
Expand All @@ -25,7 +25,7 @@
"license": "BSD-3-Clause",
"maintenance": {
"assessment": "active",
"release_uploaded_at": "2026-06-23T14:18:28.867545Z",
"release_uploaded_at": "2026-08-06T13:06:47.709049Z",
"source_url": "https://github.com/py-pdf/pypdf"
},
"malformed_input_history": "A mature untrusted-PDF parser with recurring malformed-input and denial-of-service hardening; ART still rejects active features and enforces page, byte, CPU, memory, and wall-clock limits outside the library.",
Expand All @@ -34,7 +34,7 @@
"network_behavior": "No network access is required for approved PDF text extraction; the extraction child remains no-network.",
"source_index": "https://pypi.org/simple",
"transitive_dependencies": [],
"version": "6.14.2"
"version": "6.15.0"
},
{
"advisories": [],
Expand Down
6 changes: 3 additions & 3 deletions backend/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ dependencies = [
"Pillow @ https://files.pythonhosted.org/packages/84/21/a35af28dcc61f37ed850a2d64c65c701321dfbf25085e469d5559360cbbf/pillow-12.3.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl#sha256=78cb2c6865a35ab8ff8b75fd122f6033b92a62c82801110e48ddd6c936a45d91 ; python_version == \"3.12\" and sys_platform == \"linux\" and platform_machine == \"x86_64\" and platform_python_implementation == \"CPython\"",
"PyJWT[crypto]>=2.13,<3.0",
"pydantic-settings>=2.6,<3.0",
"pypdf @ https://files.pythonhosted.org/packages/49/e6/136aa8993a2ae7214e0b0ef2edaa0d2e08d1d4e4982635b08a835ff31ec8/pypdf-6.14.2-py3-none-any.whl#sha256=3f07891af76dc002657e04993ab9b4de81de29f9013b9761d0b7968bff12e946",
"pypdf @ https://files.pythonhosted.org/packages/af/72/ce3067ac31e214a66388159f8462ddb8c13dd00170f24d555a1f1ae8ee91/pypdf-6.15.0-py3-none-any.whl#sha256=14e001d6504822cb1ca9c7ed9a69bccb320f59b320730f55af804361abe4d5ee",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

url='https://files.pythonhosted.org/packages/af/72/ce3067ac31e214a66388159f8462ddb8c13dd00170f24d555a1f1ae8ee91/pypdf-6.15.0-py3-none-any.whl'
sha256='14e001d6504822cb1ca9c7ed9a69bccb320f59b320730f55af804361abe4d5ee'

for file in \
  backend/pyproject.toml \
  backend/config/guide_extractor_dependencies.json \
  docs/spec_artifact_storage_service.md
do
  test -f "$file"
  rg -n -F "$url" "$file"
  rg -n -F "$sha256" "$file"
done

Repository: Flow-Research/workstream

Length of output: 862


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- candidate dependency and lock files ---'
git ls-files | rg '(^|/)(pyproject\.toml|.*(lock|dependencies|artifact_storage).*)$' || true

printf '%s\n' '--- all pypdf references ---'
rg -n -i -C 2 'pypdf|14e001d6504822cb1ca9c7ed9a69bccb320f59b320730f55af804361abe4d5ee|pypdf-6\.15\.0' . --glob '!*.pyc' || true

printf '%s\n' '--- relevant tracked-file excerpts ---'
for file in backend/pyproject.toml backend/config/guide_extractor_dependencies.json docs/spec_artifact_storage_service.md; do
  if test -f "$file"; then
    echo "### $file"
    rg -n -i -C 4 'pypdf|pdf|dependency|lock' "$file" || true
  else
    echo "### $file (missing)"
  fi
done

Repository: Flow-Research/workstream

Length of output: 50382


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

python3 - <<'PY'
import json
import re
import tomllib
from pathlib import Path

expected = {
    "version": "6.15.0",
    "filename": "pypdf-6.15.0-py3-none-any.whl",
    "url": "https://files.pythonhosted.org/packages/af/72/ce3067ac31e214a66388159f8462ddb8c13dd00170f24d555a1f1ae8ee91/pypdf-6.15.0-py3-none-any.whl",
    "sha256": "14e001d6504822cb1ca9c7ed9a69bccb320f59b320730f55af804361abe4d5ee",
}

pyproject = tomllib.loads(Path("backend/pyproject.toml").read_text())
requirements = pyproject["project"]["dependencies"]
pinned = [r for r in requirements if r.startswith("pypdf @ ")]
print("pyproject:", pinned)
assert len(pinned) == 1
assert expected["url"] in pinned[0]
assert f"`#sha256`={expected['sha256']}" in pinned[0]

manifest = json.loads(Path("backend/config/guide_extractor_dependencies.json").read_text())
entry = next(d for d in manifest["dependencies"] if d["name"] == "pypdf")
artifact = entry["approved_artifacts"][0]
print("manifest:", entry["version"], artifact)
assert entry["version"] == expected["version"]
assert artifact["filename"] == expected["filename"]
assert artifact["url"] == expected["url"]
assert artifact["sha256"] == expected["sha256"]

lock = Path("backend/uv.lock").read_text()
package = re.search(
    r'(?ms)^\[\[package\]\]\n(?:(?!^\[\[package\]\]).)*?^name = "pypdf"\n(?:(?!^\[\[package\]\]).)*?^version = "([^"]+)".*?^source = \{ url = "([^"]+)" \}.*?^wheels = \[\n\s+\{ url = "([^"]+)", hash = "sha256:([^"]+)" \ },\n\]',
    lock,
)
assert package, "pypdf package record not found in backend/uv.lock"
print("uv.lock:", package.groups())
assert package.group(1) == expected["version"]
assert package.group(2) == expected["url"]
assert package.group(3) == expected["url"]
assert package.group(4) == expected["sha256"]

docs = Path("docs/spec_artifact_storage_service.md").read_text()
versions = re.findall(r"`pypdf==([^`]+)`", docs)
print("docs pypdf version declarations:", versions)
assert versions and all(v == expected["version"] for v in versions)
print("all authoritative records agree")
PY

printf '%s\n' '--- dependency synchronization checks ---'
rg -n -C 3 'guide_extractor_dependencies|uv\.lock|pyproject\.toml|approved_artifacts|canonical allowlist|exact wheel URLs and hashes' \
  backend/scripts/check_guide_extractor_dependencies.py \
  backend/tests/test_guide_extractor_dependencies.py \
  docs/spec_artifact_storage_service.md | head -200

Repository: Flow-Research/workstream

Length of output: 282


Keep the pinned pypdf records synchronized.

backend/pyproject.toml, backend/config/guide_extractor_dependencies.json, and backend/uv.lock must use pypdf 6.15.0 with the same wheel URL and SHA-256 hash. docs/spec_artifact_storage_service.md needs only the approved version declaration.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/pyproject.toml` at line 21, Synchronize the pypdf dependency records
in pyproject.toml, guide_extractor_dependencies.json, and uv.lock to version
6.15.0 using the identical wheel URL and SHA-256 hash shown in the diff. Update
docs/spec_artifact_storage_service.md only to declare the approved pypdf
version.

"sqlalchemy[asyncio]>=2.0,<3.0",
"uvicorn[standard]>=0.30,<1.0",
]
Expand All @@ -38,8 +38,8 @@ agents = [
dev = [
"docstr-coverage>=2.3,<3.0",
"jsonschema==4.26.0",
"pytest>=8.0,<9.0",
"pytest-asyncio>=0.24,<1.0",
"pytest>=9.0.3,<10.0",
"pytest-asyncio>=1.4,<2.0",
"pytest-cov==7.1.0",
"ruff>=0.8,<0.16",
]
Expand Down
Loading
Loading