# HiveOps Portal UI Implementation Plan
## Overview
Add a Thymeleaf portal UI accessible at `mgmt.directlx.dev/portal` for managing:
- **Customers** (separate from Users/admins)
- **Product Key Licenses** linked to customers
- **API Keys** for hiveops-agent (with configurable scopes)
- **Global Configuration**
## Design Decisions
- **Auth**: Session-based for portal (separate from JWT API)
- **UI**: Bootstrap 5 (via CDN)
- **Customer Model**: Separate entity (Users are admins, Customers get licenses)
- **API Key Scope**: Full agent operations with configurable permissions
---
## Implementation Phases
### Phase 1: Dependencies & Database
**1.1 Update pom.xml** - Add dependencies:
```xml
org.springframework.boot
spring-boot-starter-thymeleaf
org.thymeleaf.extras
thymeleaf-extras-springsecurity6
```
**1.2 Create migration** `V3__add_customer_and_apikey_tables.sql`:
- `customers` table (name, email, company, phone, status, metadata)
- `api_keys` table (name, key_prefix, key_hash, scopes, customer_id, status, expires_at)
- Add `customer_id` FK to `licenses` table
### Phase 2: Entities & Repositories
**2.1 Create entities:**
- `Customer.java` - name, email, company, phone, address, notes, status (ACTIVE/SUSPENDED/ARCHIVED)
- `ApiKey.java` - name, keyPrefix, keyHash, scopes (JSON), status, expiresAt, lastUsedAt
**2.2 Update `License.java`** - Add `@ManyToOne Customer customer`
**2.3 Create repositories:**
- `CustomerRepository.java` - findByUuid, findByEmail, search()
- `ApiKeyRepository.java` - findByKeyPrefix, findActiveByKeyPrefix
### Phase 3: Services
**3.1 Create services:**
- `CustomerService.java` - CRUD, search, suspend/activate
- `ApiKeyService.java` - generate (returns raw key once), validate, revoke
- `PortalLicenseService.java` - create license for customer, generate key
- `DashboardService.java` - statistics aggregation
**API Key format**: `hiveops_{8-char-prefix}_{32-char-random}`
- Only SHA-256 hash stored; raw key shown once at creation
### Phase 4: Security Configuration
**4.1 Create `ApiKeyAuthenticationFilter.java`**
- Process `X-API-Key` header for agent requests
- Validate against hashed keys in DB
**4.2 Update `SecurityConfig.java`** - Dual filter chains:
```java
// Order 1: API chain (JWT, stateless)
@Bean @Order(1)
SecurityFilterChain apiFilterChain() { ... }
// Order 2: Portal chain (session-based)
@Bean @Order(2)
SecurityFilterChain portalFilterChain() {
// Form login at /portal/login
// Session management
// CSRF enabled
}
```
### Phase 5: Portal Controllers
Create in `com.hiveops.mgmt.controller.portal`:
| Controller | Routes | Function |
|------------|--------|----------|
| `PortalDashboardController` | `/portal/`, `/portal/dashboard`, `/portal/login` | Dashboard, login |
| `PortalCustomerController` | `/portal/customers/**` | Customer CRUD |
| `PortalLicenseController` | `/portal/licenses/**` | License management |
| `PortalApiKeyController` | `/portal/api-keys/**` | API key management |
| `PortalSettingsController` | `/portal/settings/**` | Global settings (admin only) |
### Phase 6: Templates & Static Resources
**Directory structure:**
```
src/main/resources/
├── templates/portal/
│ ├── layout/base.html
│ ├── fragments/ (header, sidebar, footer, alerts, pagination)
│ ├── login.html
│ ├── dashboard.html
│ ├── customers/ (list, form, view)
│ ├── licenses/ (list, form, view)
│ ├── api-keys/ (list, form, created)
│ ├── settings/list.html
│ └── error/ (403, 404, 500)
└── static/portal/
├── css/styles.css
├── js/portal.js
└── images/logo.svg
```
### Phase 7: Configuration Updates
**Update `application.yml`:**
```yaml
server:
servlet:
context-path: / # Changed from /api
session:
timeout: 30m
spring:
thymeleaf:
prefix: classpath:/templates/
suffix: .html
cache: false
```
---
## Key Files to Modify
| File | Changes |
|------|---------|
| `pom.xml` | Add Thymeleaf dependencies |
| `application.yml` | Add Thymeleaf config, change context-path |
| `SecurityConfig.java` | Dual filter chains for API + Portal |
| `License.java` | Add customer relationship |
## New Files to Create
| Category | Count | Files |
|----------|-------|-------|
| Migration | 1 | V3__add_customer_and_apikey_tables.sql |
| Entities | 2 | Customer.java, ApiKey.java |
| Repositories | 2 | CustomerRepository.java, ApiKeyRepository.java |
| Services | 4 | CustomerService, ApiKeyService, PortalLicenseService, DashboardService |
| Security | 2 | ApiKeyAuthenticationFilter, ApiKeyAuthentication |
| Controllers | 5 | Portal controllers |
| DTOs | 8 | Request/Response DTOs |
| Templates | ~20 | Thymeleaf HTML templates |
| Static | 3 | CSS, JS, images |
---
## Verification
1. **Build**: `./mvnw clean compile` - verify no compilation errors
2. **Database**: Run migrations, verify tables created
3. **Login**: Access `/portal/login`, authenticate as admin@hiveops.com
4. **Customer CRUD**: Create, view, edit, suspend customers
5. **License Generation**: Create license linked to customer, verify key format
6. **API Key Generation**: Create API key, verify raw key shown once, test validation
7. **Settings**: Edit global settings (admin only)
8. **Existing API**: Verify `/api/v1/auth/login` still works with JWT