Skip to content

Roadmap

Items below are not implemented in the current build. Each entry states the gap, the constraint, and the intended approach.

SCIM group membership

Gap. Reach reports name SCIM groups but cannot enumerate their members. The simulator must take SCIM group IDs as an input rather than resolving them from a user identity.

Constraint. The ZPA management API does not expose user-to-group membership. The ZPA SCIM API does, but requires a per-IdP static bearer token that must be issued and rotated separately for each IdP, which does not scale operationally.

Approach. Direct integration with the upstream IdP (Microsoft Graph for Entra ID, Okta API for Okta). One adapter per IdP, configured via env vars, exposing LookupUserGroups(userID) []scimGroupID.

Proactive cache refresh

Current behavior. The fetcher caches each ZPA resource with a TTL (5 minutes for volatile resources, 1 hour for stable ones). When the TTL expires, the next request triggers a refetch and the index is rebuilt from the new data. On fetch failure, the cache returns the last-good data along with the error. Cache.Get (internal/fetcher/cache.go:62) rechecks freshness after acquiring the write lock so concurrent callers after expiry collapse to a single fetch. SCIM attribute values are loaded lazily per (idpID, headerID) pair on first access rather than eagerly enumerated at index build.

Gap 1 — reactive only. Refresh fires only when a request arrives after expiry. The first request after each expiry pays the full SDK round-trip latency (seconds, sometimes tens of seconds on a busy tenant). A daemon would warm the cache in the background so user requests never pay that latency.

Gap 2 — no eager warmup at startup. The first request after process start hits an empty cache. Container restarts impose the same cold-start cost on whichever request lands first.

Gap 3 — no manual refresh trigger. When a change in ZPA needs immediate visibility, the only options are “wait up to TTL” or restart the process.

Approach. A background goroutine refreshes each cached resource slightly before its TTL expires. An optional POST /api/v1/refresh invalidates the cache on demand. Eager warmup at startup populates every cache before the listener accepts connections.

Browser-to-backend request correlation

Gap. Frontend telemetry events do not include the X-Request-Id of the associated backend call. Correlation across logs is by route + time only.

Approach. The browser fetch wrapper records X-Request-Id from the response and attaches it to subsequent telemetry events fired from that component tree.

Per-route ACLs

Gap. Authelia decides whether a user may reach the application at all. Once authenticated, every endpoint is open to every user.

Approach. Extend Authelia’s policy file to add per-path rules. Add forward-auth blocks per route group in the Caddyfile. No backend change required.

Wildcard collisions in domain overlap report

Gap. The domain overlap report lists literal duplicate domain entries only. Implicit collisions where one segment declares *.example.com and another declares db.example.com are not surfaced.

Approach. Augment the overlap pass with a wildcard-walk over every domain entry across segments, emitting one DomainOverlapDetail per implicit collision.