Skip to content

Developer reference

Overview of NAPT's codebase structure, architecture, and key concepts for contributors.

Code organization

Here's the file structure:

napt/
├── __init__.py              # Package overview docstring
├── exceptions.py            # Exception hierarchy
├── logging.py               # Logging configuration
├── paths.py                 # Safe filenames and folder names from external input
├── powershell.py            # PowerShell string quoting for generated scripts
├── results.py               # Result dataclasses returned by napt commands
├── validation.py            # Recipe validation logic
├── version.py               # NAPT's own version, read from package metadata
├── auth/                    # Microsoft Entra ID authentication
│   ├── credentials.py          # Token resolution and the napt auth login session
│   └── registration.py         # App registration provisioning (napt auth setup)
├── build/                   # PSADT package building
│   ├── manager.py              # Package building orchestration
│   ├── packager.py             # .intunewin package creation
│   └── template.py             # PSADT template generation
├── cli/                     # Command-line interface (one module per command)
│   ├── main.py                 # Parser assembly and dispatch
│   ├── auth.py                 # napt auth login/logout/status/setup
│   ├── build.py                # napt build
│   ├── discover.py             # napt discover
│   ├── init.py                 # napt init
│   ├── package.py              # napt package
│   ├── promote.py              # napt promote plan/apply
│   ├── status.py               # napt status
│   ├── upload.py               # napt upload
│   └── validate.py             # napt validate
├── config/                  # Configuration loading
│   └── loader.py               # 3-layer configuration system
├── discovery/               # Discovery strategies
│   ├── api_github.py           # GitHub Releases API strategy
│   ├── api_json.py             # Generic JSON API strategy
│   ├── base.py                 # Strategy protocol and shared helpers
│   ├── registry.py             # Strategy name-to-class table
│   ├── url_download.py         # Direct URL download strategy
│   └── web_scrape.py           # Web scraping strategy
├── download/                # HTTP file downloads
│   └── download.py             # HTTP downloads with ETag support
├── graph/                   # Microsoft Graph client
│   ├── client.py               # HTTP transport with retry and error mapping
│   └── intune.py               # Win32 app upload, queries, and assignments
├── psadt/                   # PSADT release management
│   └── release.py              # PSADT release download and caching
├── state/                   # State persistence
│   ├── deployment.py           # Authoritative per-app record of published and pending releases
│   └── stamp.py                # Provenance stamp linking Intune apps to deployment state
├── upload/                  # Intune upload pipeline
│   ├── manager.py              # Upload orchestration
│   └── intunewin.py            # .intunewin package parser
└── versioning/              # Version extraction and ordering
    ├── msi.py                  # MSI metadata extraction backends
    ├── msix.py                 # MSIX metadata extraction (AppxManifest)
    └── ordering.py             # Version ordering, mirroring the device-side comparison

Data flow

Recipe YAML
[config/loader.py] Load and merge configuration
[discovery/] Discover version and download
[state/deployment.py] Record pending release
[build/manager.py] Build PSADT package
[build/packager.py] Create .intunewin
[upload/manager.py] Upload to Microsoft Intune
Result (dataclass)

Key concepts

  • Discovery Strategies: Protocol-based, stateless, listed in an explicit registry table (api_github, api_json, web_scrape). All return a RemoteVersion from configuration alone. url_download is a separate flow (not a registered strategy) because it must download the file to determine the version. Both end in discovery/resolve.py, which reuses the previous download when the strategy reports the same version as last run (or the server answers HTTP 304 for url_download), and otherwise downloads the file, reads the version from an MSI or MSIX installer, and files it under that version
  • Configuration: 3-layer system (org → vendor → recipe) with deep merging
  • State Management: Authoritative per-app deployment state (state/deployment/<id>.json) records what is published and pending. The downloads folder is disposable; discovery reuses what it finds there and never treats it as a record
  • Exceptions: All NAPT domain errors use custom exceptions inheriting from NAPTError (ConfigError, NetworkError, PackagingError, StateError, AuthError) - allows catching all NAPT errors or specific types
  • Return Types: Frozen dataclasses from results.py, one per napt command's underlying operation

Common contributor tasks

  • New discovery strategy: Implement DiscoveryStrategy in a new module under discovery/, then add it to the table in discovery/registry.py
  • New CLI command: Create napt/cli/<command>.py with the cmd_<name>() handler and a register(subparsers) hook, call register from main() in napt/cli/main.py, and add tests/cli/test_<command>.py (strict one module per command)
  • New config option: Update schema in config/loader.py, add validation in validation.py, document in recipe schema

See also