// Path prefixes whose /api/* requests are handled locally even when an
// x-node-id header targets a remote node. These endpoints are gateway-level
// concerns (auth, node registry, licensing, fleet aggregation, webhooks,
// meta) that must never be proxied to a remote Sencho instance.
//
// Consumed by:
//   - middleware/jsonParser.ts  → skip JSON parsing only for non-exempt remote proxy requests
//   - middleware/nodeContext.ts → skip node resolution for exempt paths
export const PROXY_EXEMPT_PREFIXES: readonly string[] = [
  '/api/auth/',
  '/api/nodes',
  '/api/license',
  '/api/fleet/',
  '/api/webhooks',
  '/api/meta',
];

/** Returns true when the path should bypass the remote proxy (handled locally). */
export function isProxyExemptPath(path: string): boolean {
  for (const prefix of PROXY_EXEMPT_PREFIXES) {
    if (path.startsWith(prefix)) return true;
  }
  return false;
}

// Path prefixes that are hub-only: they must be served on the instance you are
// signed into and never proxied to a remote node. This covers state owned by
// the local hub (centralized audit, fleet schedules, notification routing
// rules, the admin-only aggregated logs feed and its stream counters), SSO
// configuration and authentication mode (control-plane identity state), and
// private registry credentials, which are stored and managed per instance.
// Blueprints and node labels are hub-owned too: the hub is the only instance
// that holds the desired-state definitions and the label set its placement
// selectors resolve against, so a proxied request would read or write a remote
// node's unrelated copy instead of the fleet's actual intent.
// Routed to the local hub when nodeId resolves to local, but rejected when
// nodeId resolves to a remote node so a script/curl call cannot trick the proxy
// into forwarding the request across a node boundary. This matters for the logs
// feed (its admin gate lives in the local route handler, which the proxy would
// skip when forwarding a remote nodeId) and for registries and Fleet Secrets (a
// proxied request would otherwise carry a plaintext secret to, or read stored
// secret values from, the remote; the secrets routes' admin gate also lives in
// the local route handler, which the proxy would skip).
//
// Entries are stored with a trailing slash; the matcher accepts the exact
// collection path (without the trailing slash) AND any sub-path under it,
// so e.g. `/api/scheduled-tasks` and `/api/scheduled-tasks/42` both match.
// A bare startsWith() would let the collection path silently fall through
// and be forwarded by the remote proxy.
//
// Frontend nav surfaces are gated separately via `HUB_ONLY_VIEWS` in
// useViewNavigationState.ts; this list is the backend defense-in-depth.
//
// Consumed by:
//   - middleware/hubOnlyGuard.ts → 403 when nodeId is remote
export const HUB_ONLY_PREFIXES: readonly string[] = [
  '/api/scheduled-tasks/',
  '/api/audit-log/',
  '/api/notification-routes/',
  '/api/notification-suppression-rules/',
  '/api/logs/global/',
  '/api/system/log-stream-metrics/',
  '/api/registries/',
  '/api/secrets/',
  '/api/blueprints/',
  '/api/node-labels/',
  '/api/registry-delivery/',
  '/api/sso/',
];

/** Returns true when the path is hub-only and must not be proxied to a remote node. */
export function isHubOnlyPath(path: string): boolean {
  const normalized = path.toLowerCase();
  for (const prefix of HUB_ONLY_PREFIXES) {
    const normalizedPrefix = prefix.toLowerCase();
    if (normalized.startsWith(normalizedPrefix)) return true;
    if (normalized === normalizedPrefix.slice(0, -1)) return true;
  }
  return false;
}
