9.1 KiB
Project Memory
Git Preferences
-
Default branch: Always use
maininstead ofmaster- When initializing repos:
git init -b main - When creating first commit, use
mainbranch - When pushing:
git push -u origin main
- When initializing repos:
-
Standardized Git Identity: All HiveOps repositories use consistent git configuration
- User name:
directlx - User email:
directlx.dev@gmail.com - Set in each repository:
git config user.name "directlx" && git config user.email "directlx.dev@gmail.com" - Verify before committing:
git config user.name && git config user.email - All 12 HiveOps repositories have been standardized (as of 2026-02-15)
- User name:
Documentation Organization
-
Markdown files location: Always place documentation
.mdfiles in thedocs/directory- Exception:
README.mdstays in repository root - All other
.mdfiles go indocs/ - Update references in
README.mdto point todocs/paths - Keep documentation organized and centralized
- Exception:
-
Deployment Documentation: Comprehensive guides for microservice deployment
docs/DEPLOYMENT-GUIDE.md- Complete deployment procedures, troubleshooting, rollbackdocs/DEPLOYMENT-QUICKSTART.md- Fast reference for quick deployments- Both guides include standardized git configuration verification steps
- Deployment workflow: Build → Push → SSH to production → Pull → Deploy → Verify
Browser-Only Access Restriction
Context: HiveOps Incident Management is restricted to only work through HiveOps Browser application, not direct web browser access.
Implementation Pattern (Dual-Layer Security)
-
Nginx Layer (
instances/services/nginx/conf.d/default.conf):- API/Agent endpoints (
^/(api|atm|actuator)/): NO browser check - agents don't have browser headers - Frontend (
/): Browser check required - serves blocked page if unauthorized - Location:
/blocked.htmlservesinstances/services/nginx/conf.d/blocked.html - IMPORTANT: Agents run on ATMs without HiveOps Browser headers - nginx must allow
/api/,/atm/,/actuator/paths through without browser checks
- API/Agent endpoints (
-
Backend Layer (Java Spring Boot):
BrowserOnlyFilter.java- Servlet filter that checks headers, allows/api/**,/atm/**,/actuator/**- Registered in
SecurityConfig.javavia.addFilterBefore() - Spring Security handles authentication:
/api/**- requires JWT authentication (hasRole("USER"))/atm/**- allows unauthenticated access (permitAll) for agent communication/actuator/health,/actuator/info- public endpoints
HiveOps Browser Header Injection
File: hiveops-browser/src/main/main.js — attached to incidentView.webContents.session
Injects X-HiveOps-Browser, X-HiveOps-Browser-Version, User-Agent suffix, and Authorization: Bearer <token> (from authManager.getToken()). See "Browser JWT Injection" section below for full details.
Critical Nginx Configuration Pattern
Always use DNS resolver + variables for proxy_pass:
# Docker DNS resolver (prevents "host not found" errors at startup)
resolver 127.0.0.11 valid=30s;
location / {
set $backend "service-name:port";
proxy_pass http://$backend/;
# ... proxy headers
}
Why: Nginx resolves hostnames in proxy_pass at config load time. If services aren't ready, nginx fails to start. Using variables defers DNS resolution to request time.
Files Modified for Browser Restriction
hiveops-openmetal/instances/services/nginx/conf.d/default.conf- nginx config with browser checkshiveops-openmetal/instances/services/nginx/conf.d/blocked.html- blocked access pagehiveops-incident/backend/.../filter/BrowserOnlyFilter.java- backend filterhiveops-incident/backend/.../config/SecurityConfig.java- filter registrationhiveops-browser/src/main/main.js- header injection
Spring Security 6.x Authentication Issue (RESOLVED 2026-02-16)
Problem: AnonymousAuthenticationFilter overwrites custom authentication, causing 403 errors even when authentication is successfully set.
Solution: Disable anonymous authentication in SecurityConfig:
http.anonymous(anonymous -> anonymous.disable())
Use hasRole("USER") instead of .authenticated() for authorization rules.
Nginx Proxy Path Issue (RESOLVED 2026-02-16)
Problem: Simple proxy_pass http://$backend/; with location /incident/ doesn't correctly forward paths with HTTP/2 - all requests arrive as GET /.
Solution: Use regex location to capture and forward the full path:
location ~ ^/incident/(.*)$ {
set $backend "hiveops-incident:8081";
set $incident_path /$1;
proxy_pass http://$backend$incident_path$is_args$args;
proxy_pass_request_headers on;
}
Agent 405 Errors - Nginx Method/Browser Check Issue (RESOLVED 2026-02-16)
Problem: Agents getting 405 Method Not Allowed errors when calling:
/api/atms/config/sync(POST)/atm/fm/modules/{country}/{atm}(POST)
Root Causes:
- Global CORS headers restricted all methods to
GET, OPTIONSonincident.bcos.cloud - Nginx was enforcing HiveOps Browser header check on API/agent endpoints
Solution:
- Remove global CORS method restrictions from server block
- Create separate location blocks:
^/(api|atm|actuator)/→ NO browser check (agents don't have headers), allow all methods/→ Browser check required (frontend only), restrictive CORS
- Backend Spring Security handles authentication (JWT for
/api/**, permitAll for/atm/**)
JWT Session Expiry Bug (RESOLVED 2026-02-26)
Problem: Users see 403 on incident page approximately every 4 hours.
Root cause:
auth-manager.js:getToken()returned expired tokens without checking expirymain.jsinjected expiredAuthorization: Bearer <token>into all incident view requests- Backend's
JwtAuthenticationFilterrejected invalid token → no authentication set - Spring Security with
anonymous.disable()returned 403 instead of 401
Fix 1 — hiveops-browser/src/main/auth-manager.js:
getToken() {
if (!this.isAuthenticated()) { return null; } // ← added expiry check
const auth = this.getAuth();
return auth && auth.token ? auth.token : null;
}
Fix 2 — hiveops-incident/backend/.../config/SecurityConfig.java:
.exceptionHandling(ex -> ex
.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))
)
Unauthenticated requests now return 401 (not 403) so clients can distinguish session expiry from access denied.
Note: 4-hour session expiry is hardcoded in auth-manager.js:storeAuth(). Background validator checks every 15 minutes and forces re-login on expiry.
Browser JWT Injection
File: hiveops-browser/src/main/main.js — incidentView.webContents.session.webRequest.onBeforeSendHeaders
Injects into the incident view (not all requests):
X-HiveOps-Browser: trueX-HiveOps-Browser-Version: <version>User-Agent: ... HiveOps/<version>Authorization: Bearer <token>(fromauthManager.getToken())
Browser Release Workflow
# Run from /source/hiveops-src/hiveops-browser/
./build-all.sh
# Auto-bumps patch version, builds all platforms (Linux + Windows via Wine),
# copies installers to ../hiveops-openmetal/hiveops/instances/browser/downloads/
# SCP installers to CDN server
scp "downloads/HiveOps Browser Setup X.X.XX.exe" \
"downloads/HiveOps Browser-X.X.XX.AppImage" \
"downloads/hiveops-browser_X.X.XX_amd64.deb" \
hiveops@173.231.252.43:~/hiveops/hiveops-openmetal/instances/browser/downloads/
# Run release script on CDN server
ssh hiveops@173.231.252.43
cd ~/hiveops/hiveops-openmetal/instances/browser
./scripts/release-browser.sh X.X.XX \
"HiveOps Browser Setup X.X.XX.exe" \
"HiveOps Browser-X.X.XX.AppImage" \
"hiveops-browser_X.X.XX_amd64.deb"
# Commit version bump in hiveops-browser, commit downloads + CLAUDE.md in hiveops-openmetal
Latest released version: 2.0.47
Deployment
# SSH user for production servers
ssh hiveops@173.231.252.40
# Instance 1 (Services) deployment path — same on both local and production
~/hiveops/hiveops-openmetal/instances/services/
# After nginx config changes, always copy from local:
scp /source/hiveops-src/hiveops-openmetal/hiveops/instances/services/nginx/conf.d/default.conf \
hiveops@173.231.252.40:~/hiveops/hiveops-openmetal/instances/services/nginx/conf.d/
# Restart services
cd ~/hiveops/hiveops-openmetal/instances/services
docker compose restart nginx
docker compose up -d hiveops-incident
Server IPs
- Services (
incident.bcos.cloud,api.bcos.cloud, etc.) →173.231.252.40 - CDN (
cdn.bcos.cloud,bcos.cloud) →173.231.252.43 - Database →
173.231.252.45
For CDN work: ssh hiveops@173.231.252.43 and cd ~/hiveops/hiveops-openmetal/instances/browser
Reorganized Structure (2026-02-20)
hiveops/instances/services/— wasinstances/services/hiveops/instances/browser/— wasinstances/browser/shared/database/— wasinstances/database/hiveops/docker-compose*.yml— was rootdocker-compose*.ymlhiveops/.env— was root.envsmartjournal/— NEW, SmartJournal skeleton