{
  lib,
  writeShellScript,
  formats,
  replace-secret,
}:
let
  replaceSecretBin = "${lib.getExe replace-secret}";
in
{
  # Write a script that will set up the service's registration.yaml
  # with secrets from systemd credentials.
  #
  # The credentials should be named `${id}_as-token` and
  # `${id}_hs-token`.
  #
  # This registration file needs to be manually added to conduit by
  # messaging the admin with the yaml file.
  #
  # TODO(tlater): Conduwuit seems to support a CLI interface for this,
  # may want to migrate to that sometime.
  writeRegistrationScript =
    {
      id, # Must be unique among all registered appservices/bots
      url, # The URL on which the service listens
      sender_localpart,
      rate_limited ? false,
      namespaces ? {
        aliases = [ ];
        rooms = [ ];
        users = [ ];
      },
      extraSettings ? { },
      # The location to place the file; assumes systemd runtime dir
      runtimeRegistration ? "$RUNTIME_DIRECTORY/${id}-registration.yaml",
    }:
    let
      registrationFile = (formats.yaml { }).generate "${id}-registration.yaml" (
        {
          inherit
            id
            url
            sender_localpart
            rate_limited
            namespaces
            ;

          as_token = "@AS_TOKEN@";
          hs_token = "@HS_TOKEN@";
        }
        // extraSettings
      );
    in
    {
      inherit runtimeRegistration;
      ExecStartPre = writeShellScript "${id}-registration-setup.sh" ''
        cp -f ${registrationFile} "${runtimeRegistration}"
        chmod 600 "${runtimeRegistration}"

        # Write actual secrets into config
        ${replaceSecretBin} '@AS_TOKEN@' "$CREDENTIALS_DIRECTORY/${id}_as-token" "${runtimeRegistration}"
        ${replaceSecretBin} '@HS_TOKEN@' "$CREDENTIALS_DIRECTORY/${id}_hs-token" "${runtimeRegistration}"

        chmod 400 "${runtimeRegistration}"
      '';
    };
}