Architecture¶
Overall architecture¶
Central is a single-process Go HTTP service that:
- Serves the AcuGIS portal HTML/JS under
/(optionalBASE_PATHprefix) - Issues and validates platform authentication (cookie sessions and PATs)
- Stores portal cards and shared identity/ACL tables in PostgreSQL
- Aggregates downstream discovery feeds into
GET /api/catalog - Stores uploaded card thumbnails on the local filesystem
Apache (evidenced in the parent repository) terminates TLS and reverse-proxies Central at the site root while mounting other services under their own prefixes.
flowchart TB
U[Browser / acugis CLI / API clients] --> A[Apache TLS proxy]
A -->|/ login logout selected /api| C[Central :8888]
A -->|/dashboard /qgis-publish-service /tileserver /jasper-report-services /geovault ...| S[Downstream services]
C --> PG[(PostgreSQL<br/>cards · users · sessions · PATs · ACLs)]
C --> TH[Filesystem thumbnails]
C --> MEM[In-memory catalog cache]
C -->|same-origin discovery + session cookie| S
Major components¶
| Component | Location | Responsibility |
|---|---|---|
| HTTP mux / portal pages | main.go |
Route registration, HTML pages, health/catalog/portal handlers |
| Admin auth API | admin_auth.go |
Users, groups, resources, permission rows |
| ACL editor API | admin_resource_acl.go |
Overview + replace matrix |
| PAT / account | user_tokens.go |
Account page and token CRUD for current user |
| Portal store | internal/portal/store.go |
Schema ensure, cards, pool lifecycle |
| Auth adapters | internal/portal/auth.go, pat_store.go, auth_admin.go, authz_store.go, acl_admin.go |
shared/auth providers and admin SQL |
| Discovery | internal/portal/discovery.go |
Static service registry + normalize discovery payloads |
| Catalog aggregator | internal/portal/catalog.go |
TTL cache + bucketed catalog response |
| Thumbnails | internal/portal/thumbnails.go |
Validate and write image uploads |
| Base path helpers | internal/web/basepath.go |
BASE_PATH, forwarded prefix/proto |
| Shared auth | ../shared/auth |
Sessions, PATs, password hashing, middleware helpers |
| Shared UI | ../shared/ui |
Federation shell assets at /shared/ui/ |
| Web UI | web/ |
Templates and browser JS |
Directory layout¶
central/
main.go
admin_auth.go
admin_resource_acl.go
user_tokens.go
build.sh / build.ps1
go.mod / go.sum
internal/
portal/
web/
web/
deploy/
systemd/
sql/
docs/
Request flow¶
sequenceDiagram
participant C as Client
participant P as Proxy
participant H as Central handler chain
participant A as shared/auth AttachUser
participant D as Handler + Postgres/cache
C->>P: HTTPS request
P->>H: HTTP + X-Forwarded-*
H->>H: ApplyForwardedProto
H->>A: AttachUser (if DB configured)
A->>A: Cookie acugis_session then Bearer PAT
A->>D: Handler with optional user context
D-->>C: JSON / HTML / redirect / static file
Middleware order:
proxyHeadersappliesX-Forwarded-Proto- When auth is configured:
authService.AttachUser - Exact method+path registrations on
http.ServeMux - Catch-all
mount("/")portal handler for HTML/static files
Admin API handlers call requireAdmin (session/PAT + IsAdmin). Authenticated account/PAT handlers call requireAuthenticatedUser.
Authentication flow¶
sequenceDiagram
participant B as Browser
participant C as Central
participant DB as PostgreSQL
B->>C: POST /login (username, password, next)
C->>DB: Load dashboard_users by username
C->>C: Verify PBKDF2 password
C->>DB: Insert hashed session into dashboard_sessions
C-->>B: 303 + Set-Cookie acugis_session
B->>C: Subsequent APIs with cookie
C->>DB: Lookup session hash + enabled user + groups
PAT path:
- Authenticated user creates token via
POST /api/me/tokens - Plaintext
agp_...returned once - Later requests send
Authorization: Bearer agp_... - Central hashes and looks up
personal_access_tokens
Cookie takes precedence; invalid/expired cookies fall through to bearer validation.
Database interactions¶
- Pool:
pgxpool.Newwith DSN; no explicit pool sizing in Central - Schema:
EnsureSchemaat startup (unversionedCREATE TABLE IF NOT EXISTS/ additive ALTERs) - Transactions: card reorder, replace user groups, replace resource ACL
- Auth schema bootstrap also seeds default groups and platform service resources
Details: Database.
Background workers¶
None verified. There are:
- No goroutine workers
- No cron/systemd timers owned by Central
- No queue consumers
Related one-shot startup work (not recurring):
- Delete expired sessions during empty-admin bootstrap
- Ensure schema, seed groups, ensure platform service resources
- Create thumbnails directory
Caching¶
| Cache | Scope | TTL | Key |
|---|---|---|---|
| Catalog discovery | Process memory | CENTRAL_CATALOG_CACHE_TTL (default 45s) |
service_key + "|" + full Cookie header |
No Redis/Memcached. Cache is lost on restart. There is no global size bound or proactive eviction beyond overwrite on fetch.
File storage¶
| Asset | Location | Persistence |
|---|---|---|
| Templates/static UI | CENTRAL_WEB_ROOT (web/) |
Deployed with binary |
| Thumbnails | CENTRAL_THUMBNAILS_DIR |
Local disk; URL stored in portal_cards.image_url |
| Shared UI | FEDERATION_SHARED_UI_ROOT / discovered shared/ui |
Read-only assets |
Thumbnail rules: max 5 MiB; JPEG/PNG/WebP/GIF; random hex filename. No garbage collection when cards are deleted.
External integrations¶
Hard-coded same-origin discovery endpoints (internal/portal/discovery.go):
| Service key | Display name | Discovery path |
|---|---|---|
dashboard-service |
Dashboards | /dashboard/api/discovery |
qgis-publish-service |
QGIS Maps | /qgis-publish-service/api/discovery |
acugis-tileserver |
Tileserver | /tileserver/api/discovery |
jasper-report-service |
Reports | /jasper-report-services/api/discovery/index.php |
geovault |
GeoVault | /geovault/api/discovery |
Behavior:
- Origin built from
X-Forwarded-Proto/ TLS andX-Forwarded-Host/Host - Current
acugis_sessioncookie is forwarded - Failures become catalog
warnings(catalog still returns HTTP 200) - Stub endpoints
GET /api/maps|reports|forms|datasetsare not wired to these services yet
Resource-sync admin page derives sync URLs by replacing /api/discovery with /api/resource-sync (Jasper uses /api/resource-sync/index.php).
Logging¶
- Standard library
logto stdout/stderr - systemd: journald with
SyslogIdentifier=central - No structured logging, request IDs, metrics, or tracing subsystem was found