Phase (c) of docs/DESIGN.md §5. Stacked on #6 → #5, and it needs QRun-IO/qqq#1170.
views/<slug>.<csv|xlsx|json>. The saved view's filter, columns and order are exported as the user via POST /table/{t}/export, streamed with invokeForStream.
reports/<slug>.<fmt>.renderSavedReport runs as the user, and the file is then streamed from GET /download/{file}. reports/ is listed only when the instance has a report storage table.
No disk. A generated read channel serves the stream through a bounded in-memory read-ahead window (downloadReadAheadMb). A backward seek past the window fails with "download sequentially".
Limits.maxGeneratedFileMb and the account's daily download cap are counted as the bytes flow, and an overrun logs LIMIT.
Audit. DOWNLOAD transfer-log rows record the object kind, id, format, bytes and duration.
Masking. Downloads carry exactly what /qqq/v1 returns for the user. The test uses a FieldSecurityLock DENY field and byte-compares the SFTP file with a direct same-user export. The secured-data tiers plug into the same core path.
Spec note. Core's RenderSavedReportExecuteStep stages the rendered report in a JVM temp file and deletes it in try-with-resources. That is the bounded temp area the owner rule allows, so the k8s temp emptyDir is now 512Mi in-memory.
Tests: 77, covering:
CSV, XLSX and JSON;
column order;
the masking parity;
no access without read permission;
a saved report run as the user;
a 50k-row streaming export under the no-disk guard;
the read-window unit tests;
the quotas;
audit rows.
JaCoCo is at 92.6% instructions and 97.2% classes.
Phase (c) of `docs/DESIGN.md` §5. **Stacked on #6 → #5**, and it needs QRun-IO/qqq#1170.
- **`views/<slug>.<csv|xlsx|json>`.** The saved view's filter, columns and order are exported **as the user** via `POST /table/{t}/export`, streamed with `invokeForStream`.
- **`reports/<slug>.<fmt>`.** `renderSavedReport` runs as the user, and the file is then streamed from `GET /download/{file}`. `reports/` is listed only when the instance has a report storage table.
- **No disk.** A generated read channel serves the stream through a bounded in-memory read-ahead window (`downloadReadAheadMb`). A backward seek past the window fails with "download sequentially".
- **Limits.** `maxGeneratedFileMb` and the account's daily download cap are counted as the bytes flow, and an overrun logs `LIMIT`.
- **Audit.** DOWNLOAD transfer-log rows record the object kind, id, format, bytes and duration.
- **Masking.** Downloads carry exactly what `/qqq/v1` returns for the user. The test uses a `FieldSecurityLock` DENY field and byte-compares the SFTP file with a direct same-user export. The secured-data tiers plug into the same core path.
- **Spec note.** Core's `RenderSavedReportExecuteStep` stages the rendered report in a JVM temp file and deletes it in try-with-resources. That is the bounded temp area the owner rule allows, so the k8s temp `emptyDir` is now 512Mi in-memory.
**Tests:** 77, covering:
- CSV, XLSX and JSON;
- column order;
- the masking parity;
- no access without read permission;
- a saved report run as the user;
- a 50k-row streaming export under the no-disk guard;
- the read-window unit tests;
- the quotas;
- audit rows.
JaCoCo is at 92.6% instructions and 97.2% classes.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Phase (c) of
docs/DESIGN.md§5. Stacked on #6 → #5, and it needs QRun-IO/qqq#1170.views/<slug>.<csv|xlsx|json>. The saved view's filter, columns and order are exported as the user viaPOST /table/{t}/export, streamed withinvokeForStream.reports/<slug>.<fmt>.renderSavedReportruns as the user, and the file is then streamed fromGET /download/{file}.reports/is listed only when the instance has a report storage table.downloadReadAheadMb). A backward seek past the window fails with "download sequentially".maxGeneratedFileMband the account's daily download cap are counted as the bytes flow, and an overrun logsLIMIT./qqq/v1returns for the user. The test uses aFieldSecurityLockDENY field and byte-compares the SFTP file with a direct same-user export. The secured-data tiers plug into the same core path.RenderSavedReportExecuteStepstages the rendered report in a JVM temp file and deletes it in try-with-resources. That is the bounded temp area the owner rule allows, so the k8s tempemptyDiris now 512Mi in-memory.Tests: 77, covering:
JaCoCo is at 92.6% instructions and 97.2% classes.
🤖 Generated with Claude Code