feat: reveal, break-glass and the secured-data UI API extension (phase c) #8

Merged
KofTwentyTwo merged 1 commits from feature/reveal-and-break-glass into develop 2026-10-14 12:15:52 +00:00
KofTwentyTwo commented 2026-10-14 01:47:50 +00:00 (Migrated from github.com)

Summary

Phase (c) of secured data (spec: QRun-IO/qqq docs/SECURED-DATA.md §7.2, §7.3).

  • Reveal (RevealService):
    • The record is read as the user, so table permissions and record locks apply. The field must be REVEALABLE.
    • The reason comes from the policy's list or is free text (allowed or required per the policy), up to 500 characters.
    • The daily cap is enforced. Over it, the reveal is logged as CAPPED and raises an alert.
    • On success it writes a grant and a REVEAL log row, and returns the value with its expiry. The value is read as the system only after every check passes.
    • Refused on the assistant channel.
    • isRevealActive unmasks only that record and field until expiry: a 5-second cache with an exact expiry check.
  • Break-glass:
    • "Start break-glass" table action: reason of at least 20 characters, duration up to 8 h, optional table scope and classification ceiling. It raises a HIGH alert and notifies admins.
    • "End break-glass" record action, using the standard Review/Result.
    • A one-minute expiry job, plus expiry checked at read time.
    • StatusService reports the caller's state.
  • UI API extension secured-data 1.0.0: POST /qbit/secured-data/reveal, GET /qbit/secured-data/reveal/options and GET /qbit/secured-data/status, with the fragment committed and a contract test. RC.5 has no extension point, so these compile under the uiapi profile, marked STAND-IN(core=QRun-IO/qqq#1128, removeBy=RC.6).
  • Contingent field picker for classification rows: field_name lists the chosen table's fields, following the qbit-quick-search resolveTable(otherValues) template. dependsOn("table_name") is a TODO until the core RC has it.

Tests

  • RC.5 (CI): 56 tests, 52 passed, 4 skipped (the core and UI API integration tests).
  • Locally against the core branch with -Duiapi=true: 59 tests, 58 passed, 1 skipped. This run covers the HTTP operations, unmasking after a reveal through core, and the extension contract.
  • Checkstyle and coverage gates pass.

Notes

  • Bell delivery to admins uses the alerts notify SPI (#1125) when the host has it.
  • On multi-replica deployments, atomic caps and the single-active-session rule need shared coordination (documented in the README).

🤖 Generated with Claude Code

## Summary Phase (c) of secured data (spec: QRun-IO/qqq `docs/SECURED-DATA.md` §7.2, §7.3). - **Reveal** (`RevealService`): - The record is read as the user, so table permissions and record locks apply. The field must be REVEALABLE. - The reason comes from the policy's list or is free text (allowed or required per the policy), up to 500 characters. - The daily cap is enforced. Over it, the reveal is logged as CAPPED and raises an alert. - On success it writes a grant and a REVEAL log row, and returns the value with its expiry. The value is read as the system only after every check passes. - Refused on the assistant channel. - `isRevealActive` unmasks only that record and field until expiry: a 5-second cache with an exact expiry check. - **Break-glass:** - "Start break-glass" table action: reason of at least 20 characters, duration up to 8 h, optional table scope and classification ceiling. It raises a HIGH alert and notifies admins. - "End break-glass" record action, using the standard Review/Result. - A one-minute expiry job, plus expiry checked at read time. - `StatusService` reports the caller's state. - **UI API extension `secured-data` 1.0.0:** `POST /qbit/secured-data/reveal`, `GET /qbit/secured-data/reveal/options` and `GET /qbit/secured-data/status`, with the fragment committed and a contract test. RC.5 has no extension point, so these compile under the `uiapi` profile, marked `STAND-IN(core=QRun-IO/qqq#1128, removeBy=RC.6)`. - **Contingent field picker** for classification rows: `field_name` lists the chosen table's fields, following the qbit-quick-search `resolveTable(otherValues)` template. `dependsOn("table_name")` is a TODO until the core RC has it. ## Tests - RC.5 (CI): 56 tests, 52 passed, 4 skipped (the core and UI API integration tests). - Locally against the core branch with `-Duiapi=true`: 59 tests, 58 passed, 1 skipped. This run covers the HTTP operations, unmasking after a reveal through core, and the extension contract. - Checkstyle and coverage gates pass. ## Notes - Bell delivery to admins uses the alerts notify SPI (#1125) when the host has it. - On multi-replica deployments, atomic caps and the single-active-session rule need shared coordination (documented in the README). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.