HARBOR
Harbor
Harbor is the server-local dynamic app platform for app.peisongxiao.com.
Current v1 scope:
- Go runtime
- docked-app landing page at
/ - app reverse proxying by slug
- shared theme CSS derived from Lighthouse tokens, served by Harbor at
/_harbor/static/theme.css - embedded local OIDC flow for e2e testing
- Postgres-backed mutable platform state for users, direct permissions, theme/timezone preferences, and maintenance state
- centralized guest vs authenticated permission injection
- principal resolution by:
- Harbor API key bearer token
- Harbor session cookie
- guest fallback
- downstream identity headers for docked apps:
X-Harbor-User-IdX-Harbor-SubjectX-Harbor-UsernameX-Harbor-Display-UsernameX-Harbor-GuestX-Harbor-RolesX-Harbor-PermissionsX-Harbor-TimezoneX-Harbor-ThemeX-Harbor-Auth-MethodX-Harbor-API-Key-Idwhen the request is authenticated by API key
- management socket contract for app lifecycle
- global maintenance mode with drain/resume signaling
- built-in authenticated account surface at
/myself/ - built-in account APIs under
/_harbor/api/me* - DB-backed Harbor API keys
- docked app source resolution from exactly one of:
SOURCE_DIRCLONE_URL+BRANCH
Harbor is operated through lighthouse-cli:
lighthouse validate --target harborlighthouse build --target harborlighthouse apply --target harborlighthouse clean --target harborlighthouse harbor locallighthouse harbor statuslighthouse harbor add-userlighthouse harbor set-passwordlighthouse harbor list-permissionslighthouse harbor list-all-permissionslighthouse harbor add-permissionslighthouse harbor delete-permissionslighthouse harbor delete-userlighthouse harbor migrate-dblighthouse harbor maintenance on|off
User storage model:
HARBOR.OIDC.EMBEDDED_USERSare bootstrap-only seed users- mutable Harbor users and platform state live in Harbor’s Postgres schema
- after
lighthouse harbor migrate-db, Harbor reads steady-state auth, preferences, and maintenance state from Postgres - once the Harbor database is initialized, it is safe to remove
EMBEDDED_USERSfrom Harbor config - Harbor reloads DB-backed user and platform state while serving requests, so permission and preference changes take effect without a restart
- canonical usernames are normalized to lowercase and restricted to
a-z,0-9,_, and- - display usernames stay separate and human-facing
- the
adminpermission is a wildcard and satisfies all app permission checks
Built-in account surface:
/myself/is a Harbor-owned page, not a docked app- it is only shown to authenticated browser sessions
- guests do not see the
Myselfentry - account APIs are same-origin and session-auth only for mutation:
GET /_harbor/api/meGET /_harbor/api/me/permissionsGET /_harbor/api/me/api-keysPATCH /_harbor/api/me/preferencesPATCH /_harbor/api/me/profilePOST /_harbor/api/me/passwordPOST /_harbor/api/me/api-keysDELETE /_harbor/api/me/api-keys/:id
Harbor API keys:
- stored in Harbor’s Postgres schema
- token format:
hpk_1_<public_id>_<secret>
- Harbor stores only the hashed secret
- keys are bound to the Harbor user, not to a username slug
- API keys participate in principal resolution and can authenticate docked app requests or Harbor admin routes when the user has the required permissions
Proxy authorization notes:
GUEST_CAN_VIEW=falseblocks unauthenticated guests at the Harbor proxy edge- when an app declares
READ_PERMISSIONS, authenticated users must satisfy at least one of them unless they haveadmin WRITE_PERMISSIONSremain metadata in Harbor v1; app-local write enforcement still lives inside the docked app- app slug
myselfis reserved for Harbor’s built-in account surface
The runtime binary itself is built from this directory.
Current production direction:
- Harbor itself is deployed from this repo
harbor-scheduleis the first production-facing docked appharbor-todoremains an e2e/testing app rather than a production app