# FILE: blueprints/ai-tax-agent-bootstrap.yaml
# Authentik Bootstrap (v2025.x): users, groups, scope mappings, OIDC providers, applications

version: 1

metadata:
  name: AI Tax Agent — Bootstrap + OIDC Providers

entries:
  # --- Groups first (so the admin user can reference them) -------------------
  - model: authentik_core.group
    state: present
    identifiers:
      name: "Administrators"
    attrs:
      is_superuser: true

  - model: authentik_core.group
    state: present
    identifiers:
      name: "Tax Reviewers"
    attrs:
      is_superuser: false

  - model: authentik_core.group
    state: present
    identifiers:
      name: "Accountants"
    attrs:
      is_superuser: false

  - model: authentik_core.group
    state: present
    identifiers:
      name: "Clients"
    attrs:
      is_superuser: false

  # --- Admin user ------------------------------------------------------------
  - model: authentik_core.user
    state: present
    identifiers:
      username: admin
    attrs:
      name: "System Administrator"
      email: admin@local.lan
      is_active: true
      is_staff: true
      is_superuser: true
      groups:
        - !Find [authentik_core.group, [name, "Administrators"]]

  # --- E2E Test User ---------------------------------------------------------
  - model: authentik_core.user
    state: present
    identifiers:
      username: e2e_tester
    attrs:
      name: "E2E Tester"
      email: e2e@example.com
      is_active: true
      password: "password123"
      groups:
        - !Find [authentik_core.group, [name, "Tax Reviewers"]]
        - !Find [authentik_core.group, [name, "Administrators"]]

  # Helper finders

  # ========= OIDC Providers + Applications ==================================

  # --- UI Review (Proxy Provider for ForwardAuth) ---------------------------
  - model: authentik_providers_proxy.proxyprovider
    state: present
    identifiers:
      name: "UI Review Proxy"
    attrs:
      external_host: "https://review.local.lan"
      internal_host: "http://ui-review:3030"
      authorization_flow:
        !Find [authentik_flows.flow, [slug, "default-authentication-flow"]]
      invalidation_flow:
        !Find [authentik_flows.flow, [slug, "default-invalidation-flow"]]
      mode: "forward_single"
      cookie_domain: "local.lan"

  - model: authentik_core.application
    state: present
    identifiers:
      slug: "ui-review"
    attrs:
      name: "UI Review"
      provider:
        !Find [
          authentik_providers_proxy.proxyprovider,
          [name, "UI Review Proxy"],
        ]
      meta_launch_url: "https://review.local.lan"
      meta_description: "Tax Agent Platform - Review UI"
      meta_publisher: "AI Tax Agent"
      policy_engine_mode: "any"

  # --- Vault OIDC Provider --------------------------------------------------
  - model: authentik_providers_oauth2.oauth2provider
    state: present
    identifiers:
      name: "Vault OIDC"
    attrs:
      client_id: "vault"
      client_secret: !Env [AUTHENTIK_VAULT_CLIENT_SECRET, "changeme"]
      client_type: "confidential"
      redirect_uris:
        - matching_mode: strict
          url: "https://vault.local.lan/ui/vault/auth/oidc/oidc/callback"
        - matching_mode: strict
          url: "https://vault.local.lan/oidc/callback"
        - matching_mode: strict
          url: "http://localhost:8250/oidc/callback"
      sub_mode: "hashed_user_id"
      include_claims_in_id_token: true
      issuer_mode: "per_provider"
      signing_key:
        !Find [
          authentik_crypto.certificatekeypair,
          [name, "authentik Self-signed Certificate"],
        ]
      property_mappings:
        - !Find [
            authentik_providers_oauth2.scopemapping,
            [scope_name, "openid"],
          ]
        - !Find [authentik_providers_oauth2.scopemapping, [scope_name, "email"]]
        - !Find [
            authentik_providers_oauth2.scopemapping,
            [scope_name, "profile"],
          ]
      authorization_flow:
        !Find [authentik_flows.flow, [slug, "default-authentication-flow"]]
      invalidation_flow:
        !Find [authentik_flows.flow, [slug, "default-invalidation-flow"]]

  - model: authentik_core.application
    state: present
    identifiers:
      slug: "vault-oidc"
    attrs:
      name: "Vault OIDC"
      provider:
        !Find [authentik_providers_oauth2.oauth2provider, [name, "Vault OIDC"]]
      meta_launch_url: "https://vault.local.lan"
      meta_description: "Vault OIDC Authentication"
      meta_publisher: "AI Tax Agent"
      policy_engine_mode: "any"

  # --- MinIO OIDC Provider --------------------------------------------------

  # Scope Mapping for MinIO Policy
  - model: authentik_providers_oauth2.scopemapping
    state: present
    identifiers:
      name: "MinIO Policy Mapping"
    attrs:
      name: "MinIO Policy Mapping"
      description: "Maps Authentik users to MinIO policies"
      scope_name: "minio"
      expression: |
        # Default to readwrite for all authenticated users
        # You can customize this based on groups
        return {
            "policy": "readwrite"
        }

  - model: authentik_providers_oauth2.oauth2provider
    state: present
    identifiers:
      name: "MinIO OIDC"
    attrs:
      client_id: "minio"
      client_secret: !Env [AUTHENTIK_MINIO_CLIENT_SECRET, "changeme"]
      client_type: "confidential"
      redirect_uris:
        - matching_mode: strict
          url: "https://minio.local.lan/oauth_callback"
      sub_mode: "hashed_user_id"
      include_claims_in_id_token: true
      issuer_mode: "per_provider"
      signing_key:
        !Find [
          authentik_crypto.certificatekeypair,
          [name, "authentik Self-signed Certificate"],
        ]
      property_mappings:
        - !Find [
            authentik_providers_oauth2.scopemapping,
            [scope_name, "openid"],
          ]
        - !Find [authentik_providers_oauth2.scopemapping, [scope_name, "email"]]
        - !Find [
            authentik_providers_oauth2.scopemapping,
            [scope_name, "profile"],
          ]
        - !Find [
            authentik_providers_oauth2.scopemapping,
            [name, "MinIO Policy Mapping"],
          ]
      authorization_flow:
        !Find [authentik_flows.flow, [slug, "default-authentication-flow"]]
      invalidation_flow:
        !Find [authentik_flows.flow, [slug, "default-invalidation-flow"]]

  - model: authentik_core.application
    state: present
    identifiers:
      slug: "minio-oidc"
    attrs:
      name: "MinIO OIDC"
      provider:
        !Find [authentik_providers_oauth2.oauth2provider, [name, "MinIO OIDC"]]
      meta_launch_url: "https://minio.local.lan"
      meta_description: "MinIO Object Storage OIDC"
      meta_publisher: "AI Tax Agent"
      policy_engine_mode: "any"

  # --- Grafana SSO Configuration -------------------------------------------

  # Custom Role Mapping for Grafana
  - model: authentik_providers_oauth2.scopemapping
    state: present
    identifiers:
      name: "Grafana Role Mapping"
    attrs:
      name: "Grafana Role Mapping"
      description: "Maps Authentik groups to Grafana roles"
      scope_name: "role"
      expression: |
        # Map Authentik groups to Grafana roles
        user_groups = [group.name for group in request.user.ak_groups.all()]

        # Admin role mapping
        if "authentik Admins" in user_groups or "Administrators" in user_groups:
            return "Admin"

        # Editor role mapping
        if "Tax Reviewers" in user_groups or "Accountants" in user_groups:
            return "Editor"

        # Default to Viewer role
        return "Viewer"

  # Grafana OAuth2 Provider
  - model: authentik_providers_oauth2.oauth2provider
    state: present
    identifiers:
      name: "Grafana"
    attrs:
      client_id: !Env [GRAFANA_OAUTH_CLIENT_ID, "grafana"]
      client_secret: !Env [GRAFANA_OAUTH_CLIENT_SECRET, "changeme"]
      client_type: "confidential"
      redirect_uris:
        - matching_mode: strict
          url: "https://grafana.local.lan/login/generic_oauth"
      sub_mode: "hashed_user_id"
      include_claims_in_id_token: true
      issuer_mode: "per_provider"
      signing_key:
        !Find [
          authentik_crypto.certificatekeypair,
          [name, "authentik Self-signed Certificate"],
        ]
      property_mappings:
        - !Find [
            authentik_providers_oauth2.scopemapping,
            [scope_name, "openid"],
          ]
        - !Find [authentik_providers_oauth2.scopemapping, [scope_name, "email"]]
        - !Find [
            authentik_providers_oauth2.scopemapping,
            [scope_name, "profile"],
          ]

        - !Find [
            authentik_providers_oauth2.scopemapping,
            [name, "Grafana Role Mapping"],
          ]
      authorization_flow:
        !Find [authentik_flows.flow, [slug, "default-authentication-flow"]]
      invalidation_flow:
        !Find [authentik_flows.flow, [slug, "default-invalidation-flow"]]

  # Grafana Application
  - model: authentik_core.application
    state: present
    identifiers:
      slug: "grafana"
    attrs:
      name: "Grafana"
      provider:
        !Find [authentik_providers_oauth2.oauth2provider, [name, "Grafana"]]
      meta_launch_url: "https://grafana.local.lan"
      meta_description: "Grafana monitoring and observability platform"
      meta_publisher: "Grafana Labs"
      policy_engine_mode: "any"

  # --- Traefik Dashboard (Proxy Provider for ForwardAuth) -------------------
  - model: authentik_providers_proxy.proxyprovider
    state: present
    identifiers:
      name: "Traefik Dashboard Proxy"
    attrs:
      external_host: "https://traefik.local.lan"
      internal_host: "http://apa-traefik:8080"
      authorization_flow:
        !Find [authentik_flows.flow, [slug, "default-authentication-flow"]]
      invalidation_flow:
        !Find [authentik_flows.flow, [slug, "default-invalidation-flow"]]
      mode: "forward_single"
      cookie_domain: "local.lan"

  - model: authentik_core.application
    state: present
    identifiers:
      slug: "traefik-dashboard"
    attrs:
      name: "Traefik Dashboard"
      provider:
        !Find [
          authentik_providers_proxy.proxyprovider,
          [name, "Traefik Dashboard Proxy"],
        ]
      meta_launch_url: "https://traefik.local.lan"
      meta_description: "Traefik Edge Router Dashboard"
      meta_publisher: "AI Tax Agent"
      policy_engine_mode: "any"

  # --- NATS Monitoring (Proxy Provider for ForwardAuth) --------------------
  - model: authentik_providers_proxy.proxyprovider
    state: present
    identifiers:
      name: "NATS Monitoring Proxy"
    attrs:
      external_host: "https://nats.local.lan"
      internal_host: "http://apa-nats:8222"
      authorization_flow:
        !Find [authentik_flows.flow, [slug, "default-authentication-flow"]]
      invalidation_flow:
        !Find [authentik_flows.flow, [slug, "default-invalidation-flow"]]
      mode: "forward_single"
      cookie_domain: "local.lan"

  - model: authentik_core.application
    state: present
    identifiers:
      slug: "nats-monitoring"
    attrs:
      name: "NATS Monitoring"
      provider:
        !Find [
          authentik_providers_proxy.proxyprovider,
          [name, "NATS Monitoring Proxy"],
        ]
      meta_launch_url: "https://nats.local.lan"
      meta_description: "NATS Messaging System Monitoring"
      meta_publisher: "AI Tax Agent"
      policy_engine_mode: "any"

  # --- AI Tax Agent API (Proxy Provider for ForwardAuth) --------------------
  - model: authentik_providers_proxy.proxyprovider
    state: present
    identifiers:
      name: "AI Tax Agent API Proxy"
    attrs:
      external_host: "https://api.local.lan"
      internal_host: "http://apa-traefik:8080"
      authorization_flow:
        !Find [authentik_flows.flow, [slug, "default-authentication-flow"]]
      invalidation_flow:
        !Find [authentik_flows.flow, [slug, "default-invalidation-flow"]]
      mode: "forward_single"
      cookie_domain: "local.lan"

  - model: authentik_core.application
    state: present
    identifiers:
      slug: "ai-tax-agent-api-gateway"
    attrs:
      name: "AI Tax Agent API Gateway"
      provider:
        !Find [
          authentik_providers_proxy.proxyprovider,
          [name, "AI Tax Agent API Proxy"],
        ]
      meta_launch_url: "https://api.local.lan"
      meta_description: "AI Tax Agent API Gateway"
      meta_publisher: "AI Tax Agent"
      policy_engine_mode: "any"

  # --- Outpost Configuration ------------------------------------------------
  - model: authentik_outposts.outpost
    state: present
    identifiers:
      name: "authentik Embedded Outpost"
    attrs:
      token: !Env [AUTHENTIK_OUTPOST_TOKEN, "changeme"]
      providers:
        - !Find [
            authentik_providers_proxy.proxyprovider,
            [name, "Traefik Dashboard Proxy"],
          ]
        - !Find [
            authentik_providers_proxy.proxyprovider,
            [name, "UI Review Proxy"],
          ]
        - !Find [
            authentik_providers_proxy.proxyprovider,
            [name, "AI Tax Agent API Proxy"],
          ]
        - !Find [
            authentik_providers_proxy.proxyprovider,
            [name, "NATS Monitoring Proxy"],
          ]
