# stella drift (Facet Analysis) - Command Guide **Sprint:** SPRINT_20260105_002_004_CLI **Task:** CLI-016 - Facet drift command documentation ## Overview The `stella drift` command analyzes facet drift between a baseline seal and the current state of a container image. Unlike reachability drift (which tracks call paths to vulnerable code), facet drift tracks file-level changes within categorized image layers. ## Commands ### stella drift Analyze facet drift for an image against a baseline seal. ```bash stella drift [OPTIONS] ``` #### Arguments | Argument | Description | |----------|-------------| | `IMAGE` | Image reference or digest to analyze (required) | #### Options | Option | Alias | Description | Default | |--------|-------|-------------|---------| | `--baseline ` | `-b` | Baseline seal ID for comparison | latest seal | | `--format ` | `-f` | Output format: `table`, `json`, `yaml` | `table` | | `--verbose` | `-v` | Show detailed file changes | `false` | | `--fail-on-breach` | | Exit with error code if quota breached | `false` | #### Examples ##### Basic drift analysis ```bash stella drift sha256:abc123def456... ``` ##### With specific baseline ```bash stella drift myregistry.io/app:v2.0 --baseline seal-xyz789 ``` ##### JSON output for CI integration ```bash stella drift sha256:abc123 --format json > drift-report.json ``` ##### Fail build on quota breach ```bash stella drift sha256:abc123 --fail-on-breach ``` ##### Verbose output with file details ```bash stella drift sha256:abc123 --verbose ``` --- ## Output Formats ### Table Format (Default) ``` Overall Verdict: Warning Total Changed Files: 15 +----------+-------+---------+----------+---------+-----------+ | Facet | Added | Removed | Modified | Churn % | Verdict | +----------+-------+---------+----------+---------+-----------+ | runtime | 2 | 1 | 3 | 12.5% | Warning | | config | 5 | 0 | 2 | 8.2% | Ok | | static | 0 | 2 | 0 | 3.1% | Ok | +----------+-------+---------+----------+---------+-----------+ ``` With `--verbose`: ``` File Changes: runtime + /usr/lib/libcrypto.so.3.0.1 + /usr/lib/libssl.so.3.0.1 - /usr/lib/libcrypto.so.3.0.0 ~ /usr/bin/app (sha256:old -> sha256:new) ~ /etc/app/config.yaml ~ /var/lib/app/data.db ``` ### JSON Format ```json { "imageDigest": "sha256:abc123...", "baselineSealId": "seal-xyz789", "analyzedAt": "2026-01-05T10:30:00Z", "overallVerdict": "warning", "totalChangedFiles": 15, "facetDrifts": [ { "facetId": "runtime", "baselineFileCount": 48, "added": [ { "path": "/usr/lib/libcrypto.so.3.0.1", "digest": "sha256:new...", "sizeBytes": 3145728, "modifiedAt": null } ], "removed": [ { "path": "/usr/lib/libcrypto.so.3.0.0", "digest": "sha256:old...", "sizeBytes": 3145600, "modifiedAt": null } ], "modified": [ { "path": "/usr/bin/app", "previousDigest": "sha256:prev...", "currentDigest": "sha256:curr...", "previousSizeBytes": 15728640, "currentSizeBytes": 15730000 } ], "driftScore": 25.5, "churnPercent": 12.5, "quotaVerdict": "warning" } ] } ``` ### YAML Format ```yaml imageDigest: sha256:abc123... baselineSealId: seal-xyz789 overallVerdict: warning totalChangedFiles: 15 facetDrifts: - facetId: runtime added: 2 removed: 1 modified: 3 churnPercent: 12.50 verdict: warning - facetId: config added: 5 removed: 0 modified: 2 churnPercent: 8.20 verdict: ok ``` --- ## Quota Verdicts | Verdict | Description | Exit Code | |---------|-------------|-----------| | `Ok` | Drift within acceptable limits | 0 | | `Warning` | Approaching quota limits | 0 | | `Blocked` | Quota exceeded, deployment should be blocked | 2 | | `RequiresVex` | Significant drift, requires VEX authorization | 2 | ## Exit Codes | Code | Description | |------|-------------| | `0` | Success (no breach, or breach without `--fail-on-breach`) | | `1` | Error (no baseline seal, image not found, etc.) | | `2` | Quota breached (with `--fail-on-breach`) | --- ## CI/CD Integration ### GitHub Actions ```yaml - name: Check Facet Drift run: | stella drift ${{ env.IMAGE_DIGEST }} \ --format json \ --fail-on-breach > drift.json continue-on-error: true id: drift-check - name: Upload Drift Report uses: actions/upload-artifact@v4 with: name: facet-drift-report path: drift.json - name: Generate VEX if needed if: failure() && steps.drift-check.outcome == 'failure' run: | stella vex gen --from-drift \ --image ${{ env.IMAGE_DIGEST }} \ --output vex-request.json ``` ### GitLab CI ```yaml facet-drift-check: script: - stella drift $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA --fail-on-breach --format json > drift.json artifacts: paths: - drift.json reports: codequality: drift.json allow_failure: true ``` --- ## Workflow: Handling Drift Breaches When drift exceeds quotas: 1. **Review the drift report** ```bash stella drift sha256:abc123 --verbose ``` 2. **Determine if changes are intentional** - Legitimate updates: Generate VEX authorization - Unexpected changes: Investigate and remediate 3. **For intentional changes, generate VEX** ```bash stella vex gen --from-drift --image sha256:abc123 --output vex.json ``` 4. **Review and sign the VEX** ```bash stella vex sign --input vex.json --key /path/to/key ``` 5. **Or re-seal to establish new baseline** ```bash stella seal sha256:abc123 --store ``` --- ## Related Documentation - [Facet Seal Command](./seal.md) - [VEX Generation from Drift](./vex.md#stella-vex-gen---from-drift) - [Reachability Drift (different concept)](./drift.md) - [Admission Webhook Configuration](../admin/admission-webhook.md)