143 lines
9.7 KiB
Markdown
143 lines
9.7 KiB
Markdown
# Report Inventory
|
|
|
|
This inventory records the current report surface before moving report reads
|
|
or writes into SQLite. Generated paths are rooted at `REPORT_DIR` (normally
|
|
`reports/`). The SQLite tables listed below already exist in schema v1 unless
|
|
noted otherwise.
|
|
|
|
## Artifacts
|
|
|
|
| Area | Producer and formats | Current role and consumers | Classification |
|
|
| --- | --- | --- | --- |
|
|
| `copyparty/` | `Analyzer.write_report()` creates timestamped `.txt`; `write_data()` creates per-IP CSV/JSON, denied-path CSV, flagged/banned IP TXT, `requests.csv`, `authed_users.json`, and `mikrotik-block.rsc`. | Reports API serves top-level text reports. `requests.csv` is imported by `app.db.backfill`; per-run data supports inspection and legacy workflows. Retention prunes generated files. | Request rows and per-scan IP stats are canonical in `requests` and `ip_stats`; rendered summaries and exports are derived. |
|
|
| `npm/` | Same analyzer outputs, plus user-agent and host summary CSV files. | Same consumers as copyparty. `requests.csv` is a legacy backfill input; retention prunes generated files. | Request rows and per-scan IP stats are canonical in `requests` and `ip_stats`; summaries and exports are derived. |
|
|
| `app/data/` | Consolidated scan writes `blocklist_ipv4.txt` and `blocklist_ipv6.txt`. | Blocklist UI/API reads these files; scan history reconstruction and firewall sync use them as current/compatibility inputs. Retention explicitly protects them. | Operational compatibility exports. Canonical blocked targets and events belong in `blocklist_entries` and `blocklist_events`; keep files until every consumer uses the DB and git-history contract is replaced. |
|
|
| `app/` timestamped JSON | `write_blocklist_report()` emits scan/firewall change reports when the router is reachable. | Human-readable audit trail containing run delta, cumulative targets, router changes, dry-run state, and errors; retained under report retention. | Derived audit artifact. Preserve structured fields and source scan association in the DB before considering file retirement. |
|
|
| `mikrotik/` | `MikrotikFirewall.save_state_report()` writes timestamped JSON snapshots and report data; latest state is also written to `data/mikrotik/*.json`. | Firewall UI/API displays current state and snapshot history. `app.db.backfill` currently imports only the latest `data/mikrotik` snapshot; runtime snapshot persistence uses `firewall_snapshots`, `firewall_address_list_entries`, and `firewall_rule_entries`. | Firewall rows and snapshots are canonical in the DB once persisted. Keep JSON exports during migration and retain any git-diff inputs required by deployment/audit. |
|
|
|
|
## Consumers
|
|
|
|
- `GET /api/reports/<source>` lists top-level files in the selected report
|
|
directory; `GET /api/reports/<source>/<path>` reads a file below it.
|
|
- The reports page consumes those endpoints. Scan status and dashboard helpers
|
|
select the newest source and MikroTik report files for display.
|
|
- `/api/blocklist` reads the consolidated IPv4/IPv6 text files. Scan history
|
|
reconstruction and firewall sync also consume those files alongside the
|
|
SQLite ledger and git history.
|
|
- RouterOS `.rsc` exports and firewall synchronization consume generated
|
|
targets; these are operational outputs, not disposable presentation files.
|
|
- `app.db.backfill` imports per-source `requests.csv`, blocklist history, and
|
|
the latest common MikroTik JSON snapshot. It does not currently import all
|
|
timestamped reports or all historical MikroTik snapshots.
|
|
- Report retention removes old generated artifacts after consolidated scans,
|
|
subject to configured age/file-count limits; the consolidated blocklist
|
|
files are protected.
|
|
|
|
## Restructuring Implications
|
|
|
|
- Keep `requests`, `ip_stats`, blocklist tables, and firewall snapshot tables
|
|
as the queryable source of truth for facts they already represent. Avoid
|
|
copying those facts into a generic report blob.
|
|
- A future report-artifact record should store metadata and structured fields
|
|
that have no canonical home yet. Rendered text/CSV/JSON should be generated
|
|
from those records or remain an explicit export.
|
|
- Preserve source paths, generated timestamps, scan IDs, and hashes during
|
|
import so DB records can be traced back to original files.
|
|
- Do not retire blocklist exports, RouterOS scripts, or source logs until
|
|
their consumers and audit requirements have explicit replacements.
|
|
|
|
## Database and API Design
|
|
|
|
### Canonical Data
|
|
|
|
Continue treating normalized domain tables as canonical for facts they
|
|
already represent:
|
|
|
|
- `requests` for parsed request events.
|
|
- `ip_stats` for per-IP/per-scan aggregates.
|
|
- `scans` and `scans_sources` for run status, parameters, and source counts.
|
|
- `blocklist_entries`, `blocklist_reasons`, and `blocklist_events` for block
|
|
decisions and history.
|
|
- `firewall_snapshots`, `firewall_address_list_entries`, and
|
|
`firewall_rule_entries` for router state.
|
|
|
|
Add a `report_artifacts` table only for report-specific summaries that cannot
|
|
be reconstructed from those canonical rows. Proposed columns:
|
|
|
|
| Column | Purpose |
|
|
| --- | --- |
|
|
| `id` | Integer primary key. |
|
|
| `source` | `copyparty`, `npm`, `app`, or `mikrotik`. Keep as text because `log_sources` currently covers only request sources. |
|
|
| `scan_id` | Nullable link to the generating scan; legacy imports may not have a known scan. |
|
|
| `report_type` | Stable type such as `analyzer_summary`, `blocklist_change`, or `firewall_snapshot_summary`. |
|
|
| `generated_at` | Original generation timestamp when known; otherwise import time plus an explicit unknown/original-time flag in metadata. |
|
|
| `schema_version` | Version of the structured payload shape. |
|
|
| `payload_json` | Structured report-specific summary, not a duplicate of requests or raw logs. |
|
|
| `original_path` | Relative source path for provenance and legacy lookup. |
|
|
| `content_sha256` | Hash of imported source content for integrity and idempotent import. |
|
|
| `created_at` | Database import/creation timestamp. |
|
|
|
|
Use a unique index on `(original_path, content_sha256)` for idempotent file
|
|
imports. Keep payload schemas type-specific and versioned. Do not copy
|
|
`requests.csv`, `ips.json`, firewall rows, or blocklists wholesale into
|
|
`payload_json`; query their canonical tables and generate exports from those
|
|
tables. If a rendered text report is retained as a database artifact, store
|
|
its report-specific structured inputs and render text on demand rather than
|
|
using opaque text as the only source of truth.
|
|
|
|
### API Transition Contract
|
|
|
|
- Add `GET /api/reports` with optional `source`, `type`, `since`, `until`,
|
|
`limit`, and opaque `cursor` filters. Return a stable list of artifact
|
|
metadata: `id`, `source`, `scan_id`, `type`, `generated_at`, and available
|
|
export formats. Enforce a bounded default and maximum page size.
|
|
- Add `GET /api/report-artifacts/<artifact_id>` for the structured payload and
|
|
provenance metadata. Use a distinct path because `/api/reports/<source>`
|
|
already owns the one-segment route shape.
|
|
- Add `GET /api/report-artifacts/<artifact_id>/export` for supported report types and formats
|
|
(initially JSON and, where useful, CSV/TXT). Generate exports from canonical
|
|
tables and versioned artifact payloads; do not accept filesystem paths from
|
|
a database-backed export request.
|
|
- Preserve the current source/path routes as a read-only compatibility
|
|
fallback while files remain. The reports page should consume DB metadata
|
|
first, then offer legacy files when no imported artifact exists. Return
|
|
stable JSON errors for unknown IDs, unsupported formats, and unavailable
|
|
DB state.
|
|
- Keep ordering deterministic (`generated_at DESC`, then `id DESC`), validate
|
|
filter values, and use cursor pagination for large histories. Do not expose
|
|
absolute server paths in list responses.
|
|
|
|
### Sensitive and Large Content
|
|
|
|
Do not include raw request lines or full request histories in report payloads;
|
|
those belong in the dedicated log-storage design and require separate access
|
|
and retention controls. Keep high-volume CSV exports generated on demand. Treat
|
|
IP addresses, paths/query strings, user names, user agents, and firewall state
|
|
as sensitive operational data: the existing web server must remain
|
|
localhost-only, payloads should include only fields needed by the report, and
|
|
new endpoints must not expose raw log data by default. Backups and exported
|
|
files inherit the same access and retention requirements as the database.
|
|
|
|
## Migration Implementation Status
|
|
|
|
- Schema v2 adds `report_artifacts` with source, scan link, report type,
|
|
generation time, payload version, original relative path, and SHA-256 hash.
|
|
- `python -m app.db.backfill --dry-run --reports-only` inventories supported
|
|
report files by source and format. The importer is idempotent, preserves
|
|
malformed JSON as text with a parse error, reports unreadable/oversized
|
|
files, and never modifies source files. It skips exports owned by canonical
|
|
tables (for example `requests.csv` and current blocklists).
|
|
- New analyzer text summaries and consolidated blocklist change reports are
|
|
written to SQLite and their existing files. Firewall snapshots continue to
|
|
be persisted in the normalized firewall tables.
|
|
- The Reports page lists database artifacts first, supports cursor pagination
|
|
and JSON/CSV/TXT downloads, and retains the existing file-backed routes as a
|
|
fallback for unmigrated files.
|
|
- Validation covers idempotency, malformed/oversized inputs, source/format
|
|
counts, backup/restore, dual-write payloads, and API fallback. A workspace
|
|
dry-run found 76 files: 60 eligible, 16 canonical exports skipped, and none
|
|
unmappable at the time of the check.
|
|
- No report files have been retired. Keep this gate closed until every listed
|
|
consumer has moved or has an explicit compatibility requirement, and a
|
|
production backup/restore and parity review has been approved.
|