seunggabi opened a new issue, #44512:
URL: https://github.com/apache/superset/issues/44512
## [SIP] Proposal for an optional download reason on data exports
### Motivation
Superset's Action Log (`logs.json`) already records *who* exported *which*
chart or query result and *when*. It does not record *why*.
For some deployments the "why" is a compliance requirement, not a
nice-to-have. Korea's PIPA safeguards standard (개인정보의 안전성 확보조치 기준, Art. 8)
requires that when access logs show personal data was downloaded, the
controller checks and records the reason for that download. GDPR and HIPAA
style audits ask the same "purpose of processing" question. Today that answer
lives outside Superset: a spreadsheet next to the log, or a security team
chasing people after the monthly log review ("you exported 30k rows of the
customer table on the 12th, what was that for?").
Examples of what the log should be able to say:
- `FIN-1123 churn deck for finance` on a CSV export of a customer-segment
chart
- `checking a suspected dup in orders, will delete after` on a SQL Lab
result download
- `Scheduled report: Weekly KPI (id=42)` on an xlsx pulled by Alerts &
Reports, so report-driven downloads are separable from human ones
A side effect operators have asked for: the prompt itself discourages casual
"download everything".
### Proposed Change
Implemented in #44499, opt-in behind a feature flag
`REQUIRE_DOWNLOAD_REASON` (default `False`).
When the flag is on:
- **Frontend**: before a CSV/XLSX export from Explore, a dashboard chart
menu, the dashboard-wide Excel export, or SQL Lab (regular and streaming), a
small dialog asks "Why are you downloading this data?". Cancel aborts the
export. The trimmed reason (max 255 chars) is sent as the `download_reason`
query parameter. JSON / image / PDF exports are not affected.
- **Backend**: the CSV/XLSX export endpoints reject requests without a
non-blank `download_reason` with a SIP-40 `400` error. Nothing new is
persisted: the event logger already merges query-string and form fields into
the `logs.json` payload, so the reason shows up in Security → Action Log next
to the existing export event.
- **Alerts & Reports**: scheduled CSV/XLSX reports supply `Scheduled report:
<name> (id=<id>)` automatically, so they keep working with the flag on.
When the flag is off nothing changes: no dialog, no extra parameter, no new
400, and the flag-off export paths stay fully synchronous.
### New or Changed Public Interfaces
- New feature flag `REQUIRE_DOWNLOAD_REASON`.
- New optional query parameter `download_reason` on `GET/POST
/api/v1/chart/data`, `GET /api/v1/sqllab/export/<client_id>/`, `POST
/api/v1/sqllab/export_streaming/`, `POST /api/v1/dashboard/<pk>/export_xlsx/`.
Required (400 otherwise) only when the flag is on. Documented in the OpenAPI
spec and `UPDATING.md`.
- No new models, tables, or React public components. One new util module on
each side (`superset/utils/download_reason.py`, `src/utils/downloadReason.tsx`).
### New dependencies
None.
### Migration Plan and Compatibility
No database migration. No stored URL changes. API clients that call the
export endpoints must pass `download_reason` once an operator enables the flag;
this is called out in `UPDATING.md`.
### Rejected Alternatives
- **A config key instead of a feature flag.** The frontend has to know
whether to show the prompt. Feature flags already reach the browser through the
bootstrap payload with a typed `FeatureFlag` enum; a config key would need the
same boolean plumbed through common bootstrap data plus a frontend type.
`GRANULAR_EXPORT_CONTROLS` is existing precedent for gating export behaviour
with a flag. Open to switching if the community prefers a config key.
- **A dedicated `download_reasons` table.** Adds a model, migration, DAO and
API for data the event logger already captures. The Action Log is where
operators look for export events, so the reason belongs next to them.
- **Making the reason always required.** Most deployments do not need it,
and it adds friction to every export. Opt-in only.
- **Logging rejected (no-reason) attempts.** A rejected request downloads
nothing, and the UI always sends a reason when the flag is on, so a 400 only
comes from an API client that was not updated. Left as-is; if wanted, that is a
change to `log_context` itself, not to this feature.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]