# DECNET โ€” Technical Debt Register > Last updated: 2026-04-09 โ€” All addressable debt cleared. > Severity: ๐Ÿ”ด Critical ยท ๐ŸŸ  High ยท ๐ŸŸก Medium ยท ๐ŸŸข Low --- ## ๐Ÿ”ด Critical ### ~~DEBT-001 โ€” Hardcoded JWT fallback secret~~ โœ… RESOLVED ~~**File:** `decnet/env.py:15`~~ Fixed in commit `b6b046c`. `DECNET_JWT_SECRET` is now required; startup raises `ValueError` if unset or set to a known-bad value. ### ~~DEBT-002 โ€” Default admin credentials in code~~ โœ… CLOSED (by design) `DECNET_ADMIN_PASSWORD` defaults to `"admin"` intentionally โ€” the web dashboard enforces a password change on first login (`must_change_password=1`). Startup enforcement removed as it broke tooling without adding meaningful security. ### ~~DEBT-003 โ€” Hardcoded LDAP password placeholder~~ โœ… CLOSED (false positive) `templates/ldap/server.py:73` โ€” `""` is a log label for SASL auth attempts, not an operational credential. The LDAP template is a honeypot; it has no bind password of its own. ### ~~DEBT-004 โ€” Wildcard CORS with no origin restriction~~ โœ… RESOLVED ~~**File:** `decnet/web/api.py:48-54`~~ Fixed in commit `b6b046c`. `allow_origins` now uses `DECNET_CORS_ORIGINS` (env var, defaults to `http://localhost:8080`). `allow_methods` and `allow_headers` tightened to explicit allowlists. --- ## ๐ŸŸ  High ### ~~DEBT-005 โ€” Auth module has zero test coverage~~ โœ… RESOLVED ~~**File:** `decnet/web/auth.py`~~ Comprehensive test suite added in `tests/api/` covering login, password change, token validation, and JWT edge cases. ### ~~DEBT-006 โ€” Database layer has zero test coverage~~ โœ… RESOLVED ~~**File:** `decnet/web/sqlite_repository.py`~~ `tests/api/test_repository.py` added โ€” covers log insertion, bounty CRUD, histogram queries, stats summary, and fuzz testing of all query paths. In-memory SQLite with `StaticPool` ensures full isolation. ### ~~DEBT-007 โ€” Web API routes mostly untested~~ โœ… RESOLVED ~~**Files:** `decnet/web/router/` (all sub-modules)~~ Full coverage added across `tests/api/` โ€” fleet, logs, bounty, stream, auth all have dedicated test modules with both functional and fuzz test cases. ### ~~DEBT-008 โ€” Auth token accepted via query string~~ โœ… RESOLVED ~~**File:** `decnet/web/dependencies.py:33-34`~~ Query-string token fallback removed. `get_current_user` now accepts only `Authorization: Bearer ` header. Tokens no longer appear in access logs or browser history. ### ~~DEBT-009 โ€” Inconsistent and unstructured logging across templates~~ โœ… CLOSED (false positive) All service templates already import from `decnet_logging` and use `syslog_line()` for structured output. The `print(line, flush=True)` present in some templates is the intentional Docker stdout channel for container log forwarding โ€” not unstructured debug output. ### ~~DEBT-010 โ€” `decnet_logging.py` duplicated across all 19 service templates~~ โœ… RESOLVED ~~**Files:** `templates/*/decnet_logging.py`~~ All 22 per-directory copies deleted. Canonical source lives at `templates/decnet_logging.py`. `deployer.py` now calls `_sync_logging_helper()` before `docker compose up` โ€” it copies the canonical file into each active template build context automatically. --- ## ๐ŸŸก Medium ### DEBT-011 โ€” No database migration system **File:** `decnet/web/db/sqlite/repository.py` Schema is created during startup via `SQLModel.metadata.create_all`. There is no Alembic or equivalent migration layer. Schema changes across deployments require manual intervention or silently break existing databases. **Status:** Architectural. Deferred โ€” requires Alembic integration and migration history bootstrapping. ### ~~DEBT-012 โ€” No environment variable validation schema~~ โœ… RESOLVED ~~**File:** `decnet/env.py`~~ `DECNET_API_PORT` and `DECNET_WEB_PORT` now validated via `_port()` โ€” enforces integer type and 1โ€“65535 range, raises `ValueError` with a clear message on bad input. ### ~~DEBT-013 โ€” Unvalidated input on `decky_name` route parameter~~ โœ… RESOLVED ~~**File:** `decnet/web/router/fleet/api_mutate_decky.py:10`~~ `decky_name` now declared as `Path(..., pattern=r"^[a-z0-9\-]{1,64}$")` โ€” FastAPI rejects non-matching values with 422 before any downstream processing. ### ~~DEBT-014 โ€” Streaming endpoint has no error handling~~ โœ… RESOLVED ~~**File:** `decnet/web/router/stream/api_stream_events.py`~~ `event_generator()` now wrapped in `try/except`. `asyncio.CancelledError` is handled silently (clean disconnect). All other exceptions log server-side via `log.exception()` and yield an `event: error` SSE frame to the client. ### ~~DEBT-015 โ€” Broad exception detail leaked to API clients~~ โœ… RESOLVED ~~**File:** `decnet/web/router/fleet/api_deploy_deckies.py:78`~~ Raw exception message no longer returned to client. Full exception now logged server-side via `log.exception()`. Client receives generic `"Deployment failed. Check server logs for details."`. ### ~~DEBT-016 โ€” Unvalidated log query parameters~~ โœ… RESOLVED ~~**File:** `decnet/web/router/logs/api_get_logs.py:12-19`~~ `search` capped at `max_length=512`. `start_time` and `end_time` validated against `^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}$` regex pattern. FastAPI rejects invalid input with 422. ### ~~DEBT-017 โ€” Silent DB lock retry during startup~~ โœ… RESOLVED ~~**File:** `decnet/web/api.py:20-26`~~ Each retry attempt now emits `log.warning("DB init attempt %d/5 failed: %s", attempt, exc)`. After all retries exhausted, `log.error()` is emitted so degraded startup is always visible in logs. ### ~~DEBT-018 โ€” No Docker HEALTHCHECK in any template~~ โœ… RESOLVED ~~**Files:** All 20 `templates/*/Dockerfile`~~ All 24 Dockerfiles updated with: ```dockerfile HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ CMD kill -0 1 || exit 1 ``` ### ~~DEBT-019 โ€” Most template containers run as root~~ โœ… RESOLVED ~~**Files:** All `templates/*/Dockerfile` except Cowrie~~ All 24 Dockerfiles now create a `decnet` system user, use `setcap cap_net_bind_service+eip` on the Python binary (allows binding ports < 1024 without root), and drop to `USER decnet` before `ENTRYPOINT`. ### ~~DEBT-020 โ€” Swagger/OpenAPI disabled in production~~ โœ… RESOLVED ~~**File:** `decnet/web/api.py:43-45`~~ All route decorators now declare `responses={401: {"description": "Not authenticated"}, 422: {"description": "Validation error"}}`. OpenAPI schema is complete for all endpoints. ### ~~DEBT-021 โ€” `sqlite_repository.py` is a god module~~ โœ… RESOLVED ~~**File:** `decnet/web/sqlite_repository.py` (~400 lines)~~ Fully refactored to `decnet/web/db/` modular layout: `models.py` (SQLModel schema), `repository.py` (abstract base), `sqlite/repository.py` (SQLite implementation), `sqlite/database.py` (engine/session factory). Commit `de84cc6`. ### DEBT-026 โ€” IMAP/POP3 bait emails not configurable via service config **Files:** `templates/imap/server.py`, `templates/pop3/server.py`, `decnet/services/imap.py`, `decnet/services/pop3.py` Bait emails are hardcoded. A stub env var `IMAP_EMAIL_SEED` is read but currently ignored. Full implementation requires: 1. `IMAP_EMAIL_SEED` points to a JSON file with a list of `{from_, to, subject, date, body}` dicts. 2. `templates/imap/server.py` loads and merges/replaces `_BAIT_EMAILS` from that file at startup. 3. `decnet/services/imap.py` `compose_fragment()` reads `service_cfg["email_seed"]` and injects `IMAP_EMAIL_SEED` + a bind-mount for the seed file into the compose fragment. 4. Same pattern for POP3 (`POP3_EMAIL_SEED`). **Status:** Stub in place โ€” full wiring deferred to next session. --- ### DEBT-027 โ€” Dynamic Bait Store **Files:** `templates/redis/server.py`, `templates/ftp/server.py` The bait store and honeypot files are hardcoded. A dynamic injection framework should be created to populate this payload across different honeypots. **Status:** Deferred โ€” out of current scope. --- ## ๐ŸŸข Low ### ~~DEBT-022 โ€” Debug `print()` in correlation engine~~ โœ… CLOSED (false positive) `decnet/correlation/engine.py:20` โ€” The `print()` call is inside the module docstring as a usage example, not in executable code. No production code path affected. ### DEBT-023 โ€” Unpinned base Docker images **Files:** All `templates/*/Dockerfile` `debian:bookworm-slim` and similar tags are used without digest pinning. Image contents can silently change on `docker pull`, breaking reproducibility and supply-chain integrity. **Status:** Deferred โ€” requires `docker pull` access to resolve current digests for each base image. ### ~~DEBT-024 โ€” Stale service version hardcoded in Redis template~~ โœ… RESOLVED ~~**File:** `templates/redis/server.py:15`~~ `REDIS_VERSION` updated from `"7.0.12"` to `"7.2.7"` (current stable). ### ~~DEBT-025 โ€” No lock file for Python dependencies~~ โœ… RESOLVED ~~**Files:** Project root~~ `requirements.lock` generated via `pip freeze`. Reproducible installs now available via `pip install -r requirements.lock`. --- ## Summary | ID | Severity | Area | Status | |----|----------|------|--------| | ~~DEBT-001~~ | โœ… | Security / Auth | resolved `b6b046c` | | ~~DEBT-002~~ | โœ… | Security / Auth | closed (by design) | | ~~DEBT-003~~ | โœ… | Security / Infra | closed (false positive) | | ~~DEBT-004~~ | โœ… | Security / API | resolved `b6b046c` | | ~~DEBT-005~~ | โœ… | Testing | resolved | | ~~DEBT-006~~ | โœ… | Testing | resolved | | ~~DEBT-007~~ | โœ… | Testing | resolved | | ~~DEBT-008~~ | โœ… | Security / Auth | resolved | | ~~DEBT-009~~ | โœ… | Observability | closed (false positive) | | ~~DEBT-010~~ | โœ… | Code Duplication | resolved | | DEBT-011 | ๐ŸŸก Medium | DB / Migrations | deferred (Alembic scope) | | ~~DEBT-012~~ | โœ… | Config | resolved | | ~~DEBT-013~~ | โœ… | Security / Input | resolved | | ~~DEBT-014~~ | โœ… | Reliability | resolved | | ~~DEBT-015~~ | โœ… | Security / API | resolved | | ~~DEBT-016~~ | โœ… | Security / API | resolved | | ~~DEBT-017~~ | โœ… | Reliability | resolved | | ~~DEBT-018~~ | โœ… | Infra | resolved | | ~~DEBT-019~~ | โœ… | Security / Infra | resolved | | ~~DEBT-020~~ | โœ… | Docs | resolved | | ~~DEBT-021~~ | โœ… | Architecture | resolved `de84cc6` | | ~~DEBT-022~~ | โœ… | Code Quality | closed (false positive) | | DEBT-023 | ๐ŸŸข Low | Infra | deferred (needs docker pull) | | ~~DEBT-024~~ | โœ… | Infra | resolved | | ~~DEBT-025~~ | โœ… | Build | resolved | | DEBT-026 | ๐ŸŸก Medium | Features | deferred (out of scope) | | DEBT-027 | ๐ŸŸก Medium | Features | deferred (out of scope) | **Remaining open:** DEBT-011 (Alembic), DEBT-023 (image pinning), DEBT-026 (modular mailboxes), DEBT-027 (Dynamic bait store) **Estimated remaining effort:** ~10 hours