# Prod operator OIDC application + dezky-platform-admins access policy.
# Mirrors infrastructure/docker-compose/configs/authentik/blueprints/
# operator-application.yaml, with .local → .eu URLs. Applied by the
# authentik-worker (mounts /blueprints/custom; reads OPERATOR_OIDC_* from env).
#
# Provider/app are state:created (never clobber a hand-made live provider);
# group/policy/binding are state:present (reconcile + enforce on every env).
version: 1
metadata:
  name: dezky-operator-application
  labels:
    blueprints.goauthentik.io/instantiate: "true"

entries:
  - model: authentik_core.group
    state: present
    identifiers:
      name: dezky-platform-admins
    attrs:
      name: dezky-platform-admins

  - id: operator-oauth2-provider
    model: authentik_providers_oauth2.oauth2provider
    state: created
    identifiers:
      client_id: !Env [OPERATOR_OIDC_CLIENT_ID, dezky-operator]
    attrs:
      name: dezky-operator
      client_type: confidential
      client_id: !Env [OPERATOR_OIDC_CLIENT_ID, dezky-operator]
      client_secret: !Env OPERATOR_OIDC_CLIENT_SECRET
      authorization_flow:
        !Find [authentik_flows.flow, [slug, default-provider-authorization-implicit-consent]]
      invalidation_flow:
        !Find [authentik_flows.flow, [slug, default-provider-invalidation-flow]]
      signing_key:
        !Find [authentik_crypto.certificatekeypair, [name, "authentik Self-signed Certificate"]]
      redirect_uris:
        - matching_mode: strict
          url: https://operator.dezky.eu/auth/oidc/callback
      property_mappings:
        - !Find [authentik_providers_oauth2.scopemapping, [managed, "goauthentik.io/providers/oauth2/scope-openid"]]
        - !Find [authentik_providers_oauth2.scopemapping, [managed, "goauthentik.io/providers/oauth2/scope-email"]]
        - !Find [authentik_providers_oauth2.scopemapping, [managed, "goauthentik.io/providers/oauth2/scope-profile"]]
      sub_mode: hashed_user_id
      issuer_mode: per_provider
      # Authentik 2026.5+ enforces a per-provider grant_types allowlist; an empty
      # list rejects every authorize request ("Invalid grant_type for provider").
      # authorization_code = login; refresh_token = offline_access silent refresh.
      grant_types:
        - authorization_code
        - refresh_token

  - id: operator-application
    model: authentik_core.application
    state: created
    identifiers:
      slug: dezky-operator
    attrs:
      name: Dezky Operator
      slug: dezky-operator
      provider: !KeyOf operator-oauth2-provider
      meta_launch_url: https://operator.dezky.eu
      meta_description: Internal Dezky operator control plane. Platform admins only.

  - id: operator-require-platform-admin
    model: authentik_policies_expression.expressionpolicy
    state: present
    identifiers:
      name: operator-require-platform-admin
    attrs:
      name: operator-require-platform-admin
      expression: |
        return ak_is_group_member(request.user, name="dezky-platform-admins")

  - model: authentik_policies.policybinding
    state: present
    identifiers:
      target: !KeyOf operator-application
      policy: !KeyOf operator-require-platform-admin
    attrs:
      enabled: true
      order: 0
