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
RemoteVersionfrom configuration alone.url_downloadis a separate flow (not a registered strategy) because it must download the file to determine the version. Both end indiscovery/resolve.py, which reuses the previous download when the strategy reports the same version as last run (or the server answers HTTP 304 forurl_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
DiscoveryStrategyin a new module underdiscovery/, then add it to the table indiscovery/registry.py - New CLI command: Create
napt/cli/<command>.pywith thecmd_<name>()handler and aregister(subparsers)hook, callregisterfrommain()innapt/cli/main.py, and addtests/cli/test_<command>.py(strict one module per command) - New config option: Update schema in
config/loader.py, add validation invalidation.py, document in recipe schema
See also
- Discovery manager - Discovery orchestration
- Discovery API - Discovery strategy implementations
- Build API - Package building functions
- Upload API - Intune upload pipeline
- Auth API - Entra ID sign-in and app registration
- Graph API - Microsoft Graph transport and Intune calls
- Config API - Configuration loading
- Exceptions API - Exception hierarchy