Skip to content

nupm Drift Detection

tonythethompson edited this page Jul 10, 2026 · 1 revision

nupm Drift Detection

nupm Drift Detection is a mechanism within Numan designed to identify discrepancies between an imported package's current state in the nupm source directory and its recorded state at the time of import into Numan's immutable revision store. Since Numan uses one-way imports (snapshots) rather than live links, drift detection allows users to monitor when local nupm modules have been modified, requiring an explicit re-import to synchronize changes.

Core Architecture and Logic

The drift detection system operates by comparing live filesystem metadata and payload hashes against the provenance records stored in state/nupm-imports.json. The process ensures that Numan remains independent of nupm's mutable layouts while providing visibility into source changes.

Detection Workflow

The comparison logic follows a structured sequence to determine the specific nature of the drift:

  1. Identity Verification: Confirms the package exists in the Numan lockfile and was originally an nupm_import.
  2. Provenance Retrieval: Loads the recorded nupm source path and metadata SHA256 from the Numan imports state.
  3. Classification: Re-scans the live source path to ensure it is still an "ImportableModule" and free of unsafe filesystem changes (e.g., symlink escapes).
  4. Content Hashing: Computes live SHA256 hashes for both the nupm.nuon metadata and the actual module payload.

The following diagram illustrates the logical flow of the compare_import function:

flowchart TD
    Start[Start Compare] --> LF[Load Lockfile]
    LF --> IsNupm{Origin == nupm?}
    IsNupm -- No --> CantCompare[Status: CannotCompare]
    IsNupm -- Yes --> LoadProv[Load Provenance State]
    LoadProv --> SrcExist{Source Path Exists?}
    SrcExist -- No --> SrcMissing[Status: SourceMissing]
    SrcExist -- Yes --> Classify[Classify Live Source]
    Classify --> Valid{Is Eligible?}
    Valid -- No --> Unsafe[Status: UnsafeSourceTreeChange]
    Valid -- Yes --> HashMeta[Compute Metadata Hash]
    HashMeta --> MetaDiff{Metadata Changed?}
    MetaDiff -- Yes --> MetaChange[Status: MetadataChanged]
    MetaDiff -- No --> HashPayload[Compute Payload Hash]
    HashPayload --> PayDiff{Payload Changed?}
    PayDiff -- Yes --> PayChange[Status: PayloadChanged]
    PayDiff -- No --> Unchanged[Status: Unchanged]
Loading

The diagram shows how Numan prioritizes safety checks (classification) before performing expensive hashing operations.

Data Structures

Drift Status Types

Drift detection results are categorized into specific statuses to help the user understand what has changed.

Status Description
Unchanged The source metadata and payload match the recorded import hashes.
SourceMissing The recorded nupm source directory no longer exists on disk.
MetadataChanged The nupm.nuon file has been modified since the last import.
PayloadChanged The module's functional code (.nu files) has been modified.
UnsafeSourceTreeChange The source is no longer eligible for import (e.g., build hooks added or unsafe symlinks).
CannotCompare Comparison failed because the package is not a Numan-managed nupm import.

Drift Report

The DriftReport struct encapsulates the full context of a drift check, facilitating both CLI output and the numan doctor health checks.

pub struct DriftReport {
    pub package_id: String,
    pub status: DriftStatus,
    pub recorded_source: PathBuf,
    pub installed_revision_id: Option<String>,
    pub recorded_source_payload_sha256: String,
    pub live_source_payload_sha256: Option<String>,
    pub recorded_metadata_sha256: String,
    pub live_metadata_sha256: Option<String>,
}

Integration and Reporting

Drift detection is integrated into several Numan commands to provide a comprehensive view of system health.

numan doctor Integration

The numan doctor command includes a specific check for nupm drift. It uses the count_drifted_imports function to scan all imported packages. If drift is detected, it issues a Severity::Warn finding and suggests the numan nupm diff <owner/name> command as a fix hint.

CLI Output Formatter

The system provides specialized formatters in src/nupm_compat/report.rs to present drift data to the user, including the live vs. recorded SHA256 hashes for transparency.

sequenceDiagram
    participant CLI as numan nupm diff
    participant Drift as nupm_compat::drift
    participant State as prov: nupm-imports.json
    participant FS as Live Filesystem

    CLI->>Drift: compare_import(root, pkg_id)
    Drift->>State: Load recorded hashes
    Drift->>FS: Read nupm.nuon & payload
    FS-->>Drift: Bytes & Path status
    Drift->>Drift: Compute live SHA256
    Drift-->>CLI: DriftReport
    CLI->>CLI: format_drift_report()
Loading

The sequence diagram demonstrates the interaction between the CLI, the immutable state, and the mutable nupm source files.

Re-import Policy

Numan does not automatically synchronize drifted packages to maintain the principle of immutable payloads. When drift is identified (e.g., through numan nupm diff), the user must manually trigger numan nupm import <path> --as owner/name --yes. This creates a new Numan revision while preserving the old revision for rollback purposes.

Clone this wiki locally