generated from john/python-template
ver1 - Step 5 implementation complete.
This commit is contained in:
@@ -2,15 +2,18 @@
|
||||
|
||||
## Summary
|
||||
|
||||
Step 5 implementation status: **in progress**.
|
||||
Step 5 implementation status: **complete**.
|
||||
|
||||
This document records completed private-network safety controls, validation evidence, and residual risks for Ver1 Step 5.
|
||||
|
||||
Implemented in this step:
|
||||
|
||||
1. _TBD_
|
||||
2. _TBD_
|
||||
3. _TBD_
|
||||
1. Added private-network security assumptions and control matrix (`docs/ver1/ver1-step5-security-assumptions.md`).
|
||||
2. Implemented optional single-operator access control for `/ui*` and `/api*` via HTTP Basic auth.
|
||||
3. Added upload-size guardrails (`MAX_UPLOAD_BYTES`) and config fail-fast validation for operator credential requirements.
|
||||
4. Hardened unexpected-error user-facing messaging to reduce sensitive detail leakage.
|
||||
5. Added Step 5 tests for access control, security settings, and upload size boundaries.
|
||||
6. Executed dependency/security scans (`pip-audit`, `bandit`) with no critical/high findings.
|
||||
|
||||
---
|
||||
|
||||
@@ -18,23 +21,61 @@ Implemented in this step:
|
||||
|
||||
### 1) Security assumptions and threat model
|
||||
|
||||
_TBD_
|
||||
Completed.
|
||||
|
||||
- Added `docs/ver1/ver1-step5-security-assumptions.md` defining:
|
||||
- trusted private-network deployment assumptions
|
||||
- single-operator usage model
|
||||
- explicit out-of-scope classes (enterprise IAM, internet-facing zero-trust, multi-tenant controls)
|
||||
- Added Step 5 control/ownership matrix and residual-risk notes.
|
||||
|
||||
### 2) Single-operator access control baseline
|
||||
|
||||
_TBD_
|
||||
Completed.
|
||||
|
||||
- New module: `src/transcription/security.py`
|
||||
- `is_protected_path(...)` protects `/ui*` and `/api*`
|
||||
- `enforce_request_access(...)` enforces optional operator auth
|
||||
- robust Basic auth parsing and safe denial responses via `AccessDeniedError`
|
||||
- App middleware added in `src/transcription/app.py`:
|
||||
- enforces auth on protected paths
|
||||
- returns consistent `401` envelope and `WWW-Authenticate: Basic` for denied requests
|
||||
- Health endpoint `/healthz` remains intentionally unauthenticated.
|
||||
|
||||
### 3) Input validation and safe-output hardening
|
||||
|
||||
_TBD_
|
||||
Completed baseline.
|
||||
|
||||
- `src/transcription/services/upload.py`
|
||||
- added size-based validation guard (`max_upload_bytes`)
|
||||
- emits `user_input_error` with actionable guidance on over-limit uploads
|
||||
- `src/transcription/errors.py`
|
||||
- `classify_unexpected_error(...)` now returns operation-only message without embedding raw exception text
|
||||
- preserves traceability via existing `error_id` and taxonomy while reducing accidental sensitive leak risk
|
||||
|
||||
### 4) Secret handling and configuration safety
|
||||
|
||||
_TBD_
|
||||
Completed baseline.
|
||||
|
||||
- `src/transcription/config.py` additions:
|
||||
- `max_upload_bytes` (default `15 * 1024 * 1024`)
|
||||
- `operator_access_enabled` (default `False`)
|
||||
- `operator_username` (default `operator`)
|
||||
- `operator_password` (optional, required when auth enabled)
|
||||
- Added settings validator enforcing fail-fast config safety:
|
||||
- raises validation error if `OPERATOR_ACCESS_ENABLED=true` and `OPERATOR_PASSWORD` unset
|
||||
- `README.md` updated with Step 5 security env settings and explicit secret-handling guidance.
|
||||
|
||||
### 5) Dependency/security scanning baseline
|
||||
|
||||
_TBD_
|
||||
Completed.
|
||||
|
||||
- Dependency vulnerability scan:
|
||||
- `uvx pip-audit`
|
||||
- Result: **No known vulnerabilities found**
|
||||
- Static security scan:
|
||||
- `uvx bandit -r src/transcription`
|
||||
- Result: **No issues identified** (0 low/medium/high)
|
||||
|
||||
---
|
||||
|
||||
@@ -42,27 +83,41 @@ _TBD_
|
||||
|
||||
### Added/Updated Tests
|
||||
|
||||
1. _TBD_
|
||||
2. _TBD_
|
||||
3. _TBD_
|
||||
1. `tests/api/test_access_control.py`
|
||||
- unauthorized protected API denied (`401` + challenge)
|
||||
- invalid credentials denied
|
||||
- valid credentials accepted
|
||||
- `/ui` protected when auth enabled
|
||||
- `/healthz` remains unprotected
|
||||
2. `tests/services/test_upload.py`
|
||||
- added rejection test for payloads above `MAX_UPLOAD_BYTES`
|
||||
3. `tests/test_config.py`
|
||||
- added security defaults assertions
|
||||
- added fail-fast assertion for missing `OPERATOR_PASSWORD` when auth enabled
|
||||
4. `tests/test_errors.py`
|
||||
- updated expectations for sanitized unexpected-error message behavior
|
||||
5. Updated integration expectations where failure detail should no longer include raw exception text:
|
||||
- `tests/services/test_worker.py`
|
||||
- `tests/integration/test_pipeline_flow.py`
|
||||
6. `tests/test_app.py` updated for new middleware wiring.
|
||||
|
||||
### Validation Runs
|
||||
|
||||
Run and record outcomes:
|
||||
|
||||
- `uv run pytest --collect-only -q` -> _TBD_
|
||||
- `uv run pytest -m unit -q` -> _TBD_
|
||||
- `uv run pytest -m "not external" -q` -> _TBD_
|
||||
- `uv run pytest -q` -> _TBD_
|
||||
- `uv run pytest --collect-only -q` -> passed
|
||||
- `uv run pytest -m unit -q` -> passed
|
||||
- `uv run pytest -m "not external" -q` -> passed
|
||||
- `uv run pytest -q` -> passed
|
||||
|
||||
### Security Scan Evidence
|
||||
|
||||
Record scan commands and outcomes:
|
||||
|
||||
- dependency scan command(s): _TBD_
|
||||
- static/security lint command(s): _TBD_
|
||||
- critical/high findings: _TBD_
|
||||
- remediation/defer decisions: _TBD_
|
||||
- dependency scan command(s): `uvx pip-audit`
|
||||
- static/security lint command(s): `uvx bandit -r src/transcription`
|
||||
- critical/high findings: none
|
||||
- remediation/defer decisions: no remediations required for Step 5 baseline
|
||||
|
||||
---
|
||||
|
||||
@@ -70,11 +125,11 @@ Record scan commands and outcomes:
|
||||
|
||||
| Step 5 Area | REQ Coverage | Status | Evidence |
|
||||
| --- | --- | --- | --- |
|
||||
| Private-network and single-operator safety posture | REQ-9 | _TBD_ | _TBD_ |
|
||||
| Access control behavior at UI/API boundaries | REQ-5, REQ-7 | _TBD_ | _TBD_ |
|
||||
| Input validation and safe user-facing error behavior | REQ-1, REQ-2, REQ-5 | _TBD_ | _TBD_ |
|
||||
| Config and startup safety controls | REQ-8, REQ-10 | _TBD_ | _TBD_ |
|
||||
| Persistence and domain integrity continuity | REQ-11, REQ-12 | _TBD_ | _TBD_ |
|
||||
| Private-network and single-operator safety posture | REQ-9 | met | `docs/ver1/ver1-step5-security-assumptions.md`, README security section |
|
||||
| Access control behavior at UI/API boundaries | REQ-5, REQ-7 | met | `src/transcription/security.py`, `src/transcription/app.py`, `tests/api/test_access_control.py` |
|
||||
| Input validation and safe user-facing error behavior | REQ-1, REQ-2, REQ-5 | met | `src/transcription/services/upload.py`, `src/transcription/errors.py`, updated tests |
|
||||
| Config and startup safety controls | REQ-8, REQ-10 | met | `src/transcription/config.py`, `tests/test_config.py`, `README.md` |
|
||||
| Persistence and domain integrity continuity | REQ-11, REQ-12 | met (no regressions) | full test lane pass including integration and worker flows |
|
||||
|
||||
---
|
||||
|
||||
@@ -82,32 +137,35 @@ Record scan commands and outcomes:
|
||||
|
||||
- `docs/ver1/ver1-step5.md`
|
||||
- `docs/ver1/ver1-step5-results.md`
|
||||
- _TBD additional artifacts_
|
||||
- `docs/ver1/ver1-step5-security-assumptions.md`
|
||||
- `src/transcription/security.py`
|
||||
- `tests/api/test_access_control.py`
|
||||
|
||||
---
|
||||
|
||||
## Risks, Exceptions, and Follow-Ups
|
||||
|
||||
1. _TBD_
|
||||
2. _TBD_
|
||||
3. _TBD_
|
||||
1. Basic auth is intentionally right-sized for trusted private-network use; if deployment posture changes, stronger identity controls are required.
|
||||
2. Current model remains single shared operator credential (no per-user audit identity).
|
||||
3. No built-in brute-force/rate-limit controls in Step 5 scope; evaluate in future hardening if threat model expands.
|
||||
|
||||
Open follow-ups to carry forward:
|
||||
|
||||
- _TBD_
|
||||
- Consider stronger auth/session model if system becomes multi-user or internet-accessible.
|
||||
- Consider request throttling/rate limiting if threat model changes.
|
||||
|
||||
---
|
||||
|
||||
## Step 5 Exit Assessment
|
||||
|
||||
- Private-network assumptions and controls: **_TBD_**
|
||||
- Access-control baseline effectiveness: **_TBD_**
|
||||
- Validation and safe-output safety: **_TBD_**
|
||||
- Secret handling and config safety: **_TBD_**
|
||||
- Dependency/security risk closure: **_TBD_**
|
||||
- Test and regression safety: **_TBD_**
|
||||
- Private-network assumptions and controls: **met**
|
||||
- Access-control baseline effectiveness: **met**
|
||||
- Validation and safe-output safety: **met (baseline)**
|
||||
- Secret handling and config safety: **met**
|
||||
- Dependency/security risk closure: **met (no critical/high findings)**
|
||||
- Test and regression safety: **met**
|
||||
|
||||
Step 5 completion status: **_TBD_**
|
||||
Step 5 completion status: **complete**
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
# Ver1 Step 5 Security Assumptions (Private-Network Baseline)
|
||||
|
||||
## Operating Model
|
||||
|
||||
This system is operated as:
|
||||
|
||||
1. single operator
|
||||
2. trusted private network
|
||||
3. non-public deployment (no direct internet exposure for UI/API)
|
||||
|
||||
Out of scope for Step 5:
|
||||
|
||||
- enterprise IAM/SSO/RBAC
|
||||
- internet-facing zero-trust edge controls
|
||||
- multi-tenant user isolation
|
||||
|
||||
## Step 5 Controls and Ownership
|
||||
|
||||
| Control | Boundary Owner | Verification |
|
||||
| --- | --- | --- |
|
||||
| Optional operator authentication for `/ui*` and `/api*` routes | `src/transcription/security.py`, `src/transcription/app.py` | `tests/api/test_access_control.py` |
|
||||
| Unauthorized contract (`401` + safe envelope + `WWW-Authenticate`) | `src/transcription/api/errors.py` | `tests/api/test_access_control.py` |
|
||||
| Upload size guard (`MAX_UPLOAD_BYTES`) | `src/transcription/services/upload.py`, `src/transcription/config.py` | `tests/services/test_upload.py` |
|
||||
| Fail-fast auth config when enabled | `src/transcription/config.py` | `tests/test_config.py` |
|
||||
| Safe unexpected error messaging (reduced leak surface) | `src/transcription/errors.py` | `tests/test_errors.py`, worker/integration failure tests |
|
||||
|
||||
## Access-Control Policy (Step 5)
|
||||
|
||||
- Health endpoint (`/healthz`) remains unauthenticated for operability checks.
|
||||
- When `OPERATOR_ACCESS_ENABLED=true`, protected paths require HTTP Basic auth:
|
||||
- `/ui`
|
||||
- `/ui/...`
|
||||
- `/api/...`
|
||||
- Credentials are runtime-configured:
|
||||
- `OPERATOR_USERNAME` (default `operator`)
|
||||
- `OPERATOR_PASSWORD` (required when access is enabled)
|
||||
|
||||
## Secrets Policy
|
||||
|
||||
- Secrets must be provided via runtime environment variables.
|
||||
- Secrets must not be committed to source control.
|
||||
- Secrets must not be logged.
|
||||
- Example secret values in docs must always be placeholders.
|
||||
|
||||
## Residual Risks (Accepted for Step 5)
|
||||
|
||||
1. HTTP Basic credentials are suitable only for trusted private-network deployment.
|
||||
2. No per-user identity model (single shared operator credential).
|
||||
3. No advanced brute-force/rate-limit controls in Step 5 scope.
|
||||
|
||||
These are carried forward for future hardening only if deployment posture changes.
|
||||
Reference in New Issue
Block a user