Wire case-level access control into gather, investigations, monitoring, reports routers #67
Labels
No labels
agentic-osint
audit
blocked:commit-ready-failed
blocked:gate-fetch
blocked:gate-fetch
blocked:gate-lint
blocked:gate-plan
blocked:gate-research
blocked:needs-decision
blocked:needs-human
blocked:no-changes
blocked:preflight
blocked:verify-failed
bug
chore
deferred
enhancement
feature-request
in-progress
lint-baseline
lint-cleanup
needs-decompose
needs-triage
performance
quickfix
security/medium
triage-approved
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Mark/osint-hub#67
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Parent Issue: #36 (Case-level access control) / #53
Scope
Wire
require_case_accessdependency into gather, investigations, monitoring, and reports routers.Background
These are the operational routers that trigger actions within a case context. They receive
case_idvia request body or path param.Acceptance Criteria
POST /gather/— requireseditorcase access (case_id in request body)POST /investigations/— requireseditorcase access (case_id in request body)GET /investigations/{id}— requiresviewercase access (resolve case_id from investigation)GET /monitoring/?case_id=X— requiresviewercase accessPOST /monitoring/— requireseditorcase access (case_id in body)DELETE /monitoring/{id}— requireseditorcase accessGET /reports/{case_id}— requiresviewercase accessPOST /reports/{case_id}— requireseditorcase accessDependencies
Implementation Notes
require_case_accessusage⏸ Needs Decision
Blocking factors:
Scope: medium Risk: low Spec: aligned Type: enhancement
Summary: Wire the existing require_case_access dependency into 4 routers (gather, investigations, monitoring, reports) to enforce viewer/editor case-level authorization on ~15 endpoints.
Suggestion: Three patterns needed: (1) path-param case_id (reports, investigations/case/{case_id}) → Depends(require_case_access(...)) directly; (2) body-based case_id (gather POST, investigations create, parse-evidence) → inline CaseAccessService.can_access() call after body extraction; (3) entity-resolved case_id (investigations/{run_id}, monitoring/jobs/{job_id}) → DB-lookup first then inline can_access() check. Monitoring's GET /jobs with optional case_id needs a conditional check. The AC mentions POST /reports/{case_id} but that endpoint doesn't exist yet — may need creation or the AC groups existing report endpoints under a shorthand.
Rationale: Medium scope because 4 router files and ~15 endpoints are touched, including 3 distinct patterns for case_id resolution (path param, request body, entity lookup). Risk is low: this is purely additive — no existing routes, schemas, or behaviors change, the require_case_access dependency and CaseAccessService are already implemented and tested, admin bypass is built in, and only new 403 errors can emerge. Aligned with parent issues #36/#53.
Action: Review each blocking factor above. Remove
blocked:needs-decisionlabel to route back to triage.GSD VERIFY phase failed after 3 attempts.
═══ Gate: verify-passed (osint-hub#67) ═══
Mode: Tier 1 (functional only)
GATE OK: All gates up to 'implement' pass
── Tier 1: Functional ────────────────────────────────
Running tests...
❌ Tests failed (exit 4)
configfile: pyproject.toml
plugins: anyio-4.13.0, httpx-0.36.2, timeout-2.4.0, xdist-3.8.0, cov-7.1.0, split-0.11.0, asyncio-1.4.0
timeout: 60.0s
timeout method: signal
timeout func_only: False
asyncio: mode=Mode.STRICT, debug=False, asyncio_default_fixture_loop_scope=None, asyncio_default_test_loop_scope=function
collected 0 items
============================ no tests ran in 0.00s =============================
ERROR: file or directory not found: tests/
============================= test session starts ==============================
platform linux -- Python 3.11.14, pytest-9.0.3, pluggy-1.6.0
rootdir: /home/b/Projects/osint-hub
configfile: pyproject.toml
plugins: anyio-4.13.0, httpx-0.36.2, timeout-2.4.0, xdist-3.8.0, cov-7.1.0, split-0.11.0, asyncio-1.4.0
asyncio: mode=Mode.STRICT, debug=False, asyncio_default_fixture_loop_scope=None, asyncio_default_test_loop_scope=function
collected 0 items
============================ no tests ran in 0.00s =============================
Running linter...
✅ Lint clean
Running type checker...
✅ Types check clean
Previous test count: unknown
❌ GATE FAIL: verify-passed
- Tests failed with exit code 4
GATE FAIL: verify — blocked at 2026-05-26T23:13:51Z
Class: test-failure
Evidence: Verification failed: 1 failures
Git tag: osint-hub#67-gate-verify-fail-ac0f77c0bf7b (use gate-retry after fixing)