{
  system ? builtins.currentSystem,
  sources ? import ../npins,
  pkgs ? import sources.nixpkgs {
    inherit system;
    config = { };
    overlays = [ (import ./nix/overlay.nix) ];
  },
}:
let
  inherit (pkgs) lib;
  manage = pkgs.writeScriptBin "manage" ''
    exec ${pkgs.lib.getExe pkgs.python3} ${toString ./src/manage.py} $@
  '';
in
{
  shell = pkgs.mkShellNoCC {
    inputsFrom = [ (pkgs.callPackage ./nix/package.nix { }) ];
    packages = [
      pkgs.npins
      manage
    ];
    env = {
      NPINS_DIRECTORY = toString ../npins;
      # explicitly use nix, as e.g. lix does not have configurable-impure-env
      NIX_BIN = lib.getExe pkgs.nix;
      REPO_DIR = toString ../.;
      CREDENTIALS_DIRECTORY = builtins.toString ./.credentials;
      DATABASE_URL = "sqlite:///${toString ./src}/db.sqlite3";
    };
    shellHook = ''
      ln -sf ${sources.htmx}/dist/htmx.js src/panel/static/htmx.min.js
      # in production, secrets are passed via CREDENTIALS_DIRECTORY by systemd.
      # use this directory for testing with local secrets
      mkdir -p $CREDENTIALS_DIRECTORY
      echo secret > ${builtins.toString ./.credentials}/SECRET_KEY
    '';
  };

  module = import ./nix/configuration.nix;
  tests = pkgs.callPackage ./nix/tests.nix { };

  # re-export inputs so they can be overridden granularly
  # (they can't be accessed from the outside any other way)
  inherit
    sources
    system
    pkgs
    ;
}