[CHAIN] feat(ui): add fail-closed Registry access boundaries - #12499
Conversation
- Renew in-memory server-issued eligibility leases with bounded freshness - Hide navigation and unmount protected state on access loss - Deny direct Registry routes before any Registry data read
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Review — findings that survived an adversarial passFour candidate findings were each handed to a fresh reviewer whose only job was to disprove them. Three were narrowed, one was redirected, none survived as a merge blocker. Reporting only what held up, with the severity the counter-evidence supports. Scope note first, because it reframes everything below: 1.
|
| const expiresAt = useRef(Date.now() + initialLeaseDurationMs); | ||
| const [now, setNow] = useState(Date.now()); |
There was a problem hiding this comment.
I may be missing some context about the requirements, but i see a lot of timing check if the user can access the registry, why is so crucial to be aware this fast? Should not be enought on each user token refresh and get the current permissions there?
| useEffect(() => { | ||
| const refreshVisible = () => { | ||
| if (document.visibilityState === "visible") void refresh(true); | ||
| }; | ||
| const refreshOnline = () => void refresh(true); | ||
| window.addEventListener("focus", refreshVisible); | ||
| window.addEventListener("online", refreshOnline); | ||
| document.addEventListener("visibilitychange", refreshVisible); | ||
| return () => { | ||
| window.removeEventListener("focus", refreshVisible); | ||
| window.removeEventListener("online", refreshOnline); | ||
| document.removeEventListener("visibilitychange", refreshVisible); | ||
| }; | ||
| }, []); |
There was a problem hiding this comment.
Following my previous comment/concern, also not in a "React way" implemented i would say
|
Review routing note: do not test the client access-boundary or eligibility-provider snapshot in this PR. Those components are removed by #12520's lease-free, server-authoritative access model. Review only the retained proxy, navigation, and server access contracts here, then validate final Registry behavior in #12524 and #12590. |
🔗 Part of Chained PRs
feat/prowler-2414-registry-uifeat/prowler-2414-registry-ui-02-access-authorityChain Overview
Scope
/registrypage.Autonomy
Context
A fresh server permission check is not enough for a long-lived browser session. Registry navigation and protected content must disappear within a bounded interval after permission or flag rollback, while direct requests must independently fail closed before reading Registry data.
This slice adds that access boundary without introducing any Registry API or credential behavior.
Description
/registryindependently in both the proxy and dynamic server page, redirecting denial to/profilebefore any Registry read.No npm dependency, Registry endpoint call, backend change, migration, deployment change, or complete explorer UI is introduced.
Steps to review
registry-eligibility-provider.tsxfor unknown initialization, 15/30-second bounds, invalidate-before-refresh events, and stale-generation suppression.registry-access-boundary.tsxunmounts children when eligibility is not current.ui/proxy.tsandui/app/(prowler)/registry/page.tsxindependently evaluate fresh access and redirect to/profilebefore Registry reads.cd ui && pnpm exec vitest run --project unit proxy.test.ts lib/registry/access.server.test.ts components/layout/main-layout/main-layout.test.tsx components/layout/app-sidebar/navigation-config.test.ts components/layout/app-sidebar/app-sidebar-content.test.tsx; the recorded result is 5 files / 29 tests.cd ui && pnpm exec vitest run --project integration components/registry/registry-eligibility-provider.integration.test.tsx components/registry/registry-access-boundary.integration.test.tsx; the recorded result is 2 files / 3 tests.cd ui && pnpm run test:unit && pnpm run test:integration; the recorded results are 3,074 unit and 111 integration tests passing.PREK_NO_CONCURRENCY=1 uv run --directory . prek run; Prettier, ESLint, TypeScript, related tests, and root hooks are recorded as passing.Checklist
Community Checklist
SDK/CLI
UI
no-changelog, and the user-visible slice will add the feature fragment.API
MCP Server
License
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.