# Design Decisions Key architectural choices and their rationale for the Headlamp Polaris Plugin. ## 1. Service Proxy vs. Direct Access **Decision:** Use Kubernetes service proxy, not direct ClusterIP access **Context:** - Plugin needs to access Polaris dashboard API - Two options: Direct ClusterIP access or Kubernetes service proxy -Headlamp already has K8s API credentials **Decision:** Use service proxy path: `/api/v1/namespaces/polaris/services/polaris-dashboard:80/proxy/results.json` **Rationale:** - Headlamp already has K8s API credentials (service account or user token) - Service proxy leverages existing RBAC (no new credentials needed) - Works with Headlamp's token auth and OIDC - Simpler deployment (no additional network policies for plugin) - Consistent with Headlamp's architecture (all API calls go through K8s API) **Trade-offs:** - ✅ **Pros:** Simpler RBAC, works with user tokens, no new credentials - ❌ **Cons:** Longer URL path, requires `services/proxy` permission **Alternatives Considered:** - Direct ClusterIP access → Rejected (requires new credentials, network policies) - External Polaris URL → Supported as optional feature (custom URL setting) ## 2. React Context vs. Redux/Zustand **Decision:** Use React Context for state management **Context:** - Plugin needs to share Polaris audit data across multiple views - Options: React Context, Redux, Zustand, or component props **Decision:** Use React Context with `PolarisDataProvider` **Rationale:** 1. **Simple state:** Single AuditData object, no complex mutations 2. **Read-only:** No transactions, undo/redo, or optimistic updates 3. **Headlamp constraints:** Cannot add external dependencies (Redux not bundled) 4. **Performance:** Data changes infrequently (5-30 minute refresh interval) **Trade-offs:** - ✅ **Pros:** No dependencies, simple API, built-in React feature - ❌ **Cons:** All consumers re-render on data change (acceptable for infrequent updates) **Alternatives Considered:** - Redux → Rejected (not available in plugin environment) - Zustand → Rejected (requires external dependency) - Component props → Rejected (prop drilling, duplicate fetches) ## 3. Drawer Navigation vs. Dedicated Routes **Decision:** Use drawer for namespace detail, not dedicated route **Context:** - Namespaces list needs drill-down to per-namespace detail - Options: Dedicated route (`/polaris/ns/:namespace`) or drawer overlay **Decision:** Use drawer with URL hash (`/polaris/namespaces#kube-system`) **Rationale:** - **Better UX:** Drawer overlays table, preserves scroll position and context - **URL hash:** Preserves navigation state, supports browser back/forward - **Keyboard shortcuts:** Escape key to close drawer - **Sidebar limitation:** Headlamp sidebar doesn't support 3-level nesting **Trade-offs:** - ✅ **Pros:** Better UX, preserves context, keyboard navigation - ❌ **Cons:** Hash-based routing (not "true" route), drawer accessibility considerations **Alternatives Considered:** - Dedicated route → Rejected (loses table context, requires back navigation) - Modal → Rejected (less natural for drill-down, no URL state) ## 4. No MUI Direct Imports **Decision:** Never import from `@mui/material` or `@mui/icons-material` **Context:** - Plugin needs UI components (buttons, icons, etc.) - Headlamp uses MUI but doesn't expose full library to plugins **Decision:** Use only Headlamp CommonComponents or HTML elements with inline styles **Rationale:** - Importing MUI causes `createSvgIcon undefined` runtime error - Headlamp plugin environment provides limited MUI exports - CommonComponents cover 90% of use cases **Implementation:** - Use `StatusLabel`, `SectionBox`, `SimpleTable` from CommonComponents - Use standard HTML elements (`