[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6C1TPVYPCFD9P376BWX894Y":3,"skill-same:01M6C1TPVYPCFD9P376BWX894Y":73},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":34,"linkOnly":35,"markdownContent":36,"markdownBody":37,"frontMatter":38,"refName":43,"commitSha":44,"skillDirectory":45,"forksCount":46,"repositoryHtmlUrl":47,"repositoryHomepageUrl":48,"ownerHtmlUrl":49,"ownerBlogUrl":50,"ownerDescription":51,"updatedAt":52,"install":53,"resources":66},"01M6C1TPVYPCFD9P376BWX894Y","integrity-verification",null,"SHA-256 checksum manifest generation, self-verification, and PREMIS fixity patterns","jmagly\u002Faiwg","jmagly","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F1159087?v=4","01M6C10AK8N2WCSQN11FYGTJWN","Joseph Magly","01M6C10AQ8A2RMED1Y1BSVY7NF",229,"MIT","https:\u002F\u002Fgithub.com\u002Fjmagly\u002Faiwg\u002Fblob\u002Fmain\u002Fagentic\u002Fcode\u002Fframeworks\u002Fmedia-curator\u002Fskills\u002Fintegrity-verification\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[24,25,26,27,28,29,30,31,32,33],"verification","integrity","integrity verification","manifest","sha-256","Media","checksum","patterns","self","generation","2026-11-10 10:12:30",false,"---\nnamespace: aiwg\nplatforms: [all]\nname: integrity-verification\ndescription: SHA-256 checksum manifest generation, self-verification, and PREMIS fixity patterns\ncategory: media-curator\n---\n\n# Integrity Verification\n\nCryptographic checksum verification patterns for detecting bit rot, tampering, and transfer errors in media archives. Implements self-verifying manifests with PREMIS fixity metadata.\n\n## Manifest Generation Script\n\nComplete bash implementation for generating self-verifying checksum manifests:\n\n```bash\n#!\u002Fbin\u002Fbash\nset -euo pipefail\n\n# Archive Checksum Manifest Generator\n# Generates self-verifying SHA-256 checksum manifest\n# Usage: .\u002Fgenerate-checksums.sh \u002Fpath\u002Fto\u002Farchive\n\nARCHIVE_PATH=\"${1:-.}\"\nCHECKSUM_FILE=\"CHECKSUMS.sha256\"\nTEMP_FILE=\"\u002Ftmp\u002Fchecksums-$$.tmp\"\n\n# Validate archive exists\nif [ ! -d \"$ARCHIVE_PATH\" ]; then\n  echo \"Error: Archive directory not found: $ARCHIVE_PATH\" >&2\n  exit 1\nfi\n\ncd \"$ARCHIVE_PATH\"\n\necho \"Generating checksums for: $ARCHIVE_PATH\"\n\n# Find all files, exclude checksum manifest itself\n# Use null-terminated strings for handling filenames with spaces\nfind . -type f ! -name \"$CHECKSUM_FILE\" -print0 | \\\n  sort -z | \\\n  xargs -0 sha256sum > \"$TEMP_FILE\"\n\n# Count files\nFILE_COUNT=$(wc -l \u003C \"$TEMP_FILE\")\necho \"Found $FILE_COUNT files\"\n\n# Compute manifest hash (hash of the checksum content)\nMANIFEST_HASH=$(sha256sum \"$TEMP_FILE\" | awk '{print $1}')\n\n# Generate timestamp (ISO 8601 UTC with nanosecond precision)\nTIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%S.%NZ)\n\n# Write final manifest with self-verifying header\n{\n  echo \"# MANIFEST_HASH: $MANIFEST_HASH\"\n  echo \"# Generated: $TIMESTAMP\"\n  echo \"# Verify with: tail -n +4 $CHECKSUM_FILE | sha256sum\"\n  cat \"$TEMP_FILE\"\n} > \"$CHECKSUM_FILE\"\n\n# Clean up\nrm \"$TEMP_FILE\"\n\necho \"✓ Generated $CHECKSUM_FILE\"\necho \"  Manifest hash: $MANIFEST_HASH\"\necho \"  Timestamp: $TIMESTAMP\"\necho \"  Files: $FILE_COUNT\"\n```\n\n**Key features**:\n- Handles filenames with spaces via null-terminated strings (`-print0`, `-z`, `-0`)\n- Deterministic output (sorted by path)\n- Self-verifying header with manifest hash\n- ISO 8601 UTC timestamps with nanosecond precision\n- Exit on error (`set -euo pipefail`)\n\n## Verification Commands\n\n### Quick Manifest Integrity Check\n\nVerify manifest has not been tampered with (sub-second):\n\n```bash\n#!\u002Fbin\u002Fbash\n# Quick verification - manifest integrity only\n\nCHECKSUM_FILE=\"CHECKSUMS.sha256\"\n\nif [ ! -f \"$CHECKSUM_FILE\" ]; then\n  echo \"✗ Checksum manifest not found: $CHECKSUM_FILE\" >&2\n  exit 1\nfi\n\n# Extract expected hash from header\nEXPECTED=$(grep '^# MANIFEST_HASH:' \"$CHECKSUM_FILE\" | awk '{print $3}')\n\nif [ -z \"$EXPECTED\" ]; then\n  echo \"✗ Manifest header missing or malformed\" >&2\n  exit 1\nfi\n\n# Compute actual hash of manifest content (lines 4+)\nACTUAL=$(tail -n +4 \"$CHECKSUM_FILE\" | sha256sum | awk '{print $1}')\n\n# Compare\nif [ \"$EXPECTED\" = \"$ACTUAL\" ]; then\n  echo \"✓ Manifest integrity verified\"\n  echo \"  Hash: $EXPECTED\"\n  exit 0\nelse\n  echo \"✗ Manifest has been tampered with\" >&2\n  echo \"  Expected: $EXPECTED\" >&2\n  echo \"  Actual:   $ACTUAL\" >&2\n  exit 1\nfi\n```\n\n**Use case**: Daily automated checks. Fast execution regardless of archive size.\n\n**Exit codes**:\n- `0` - Manifest integrity verified\n- `1` - Manifest corrupted or tampered\n\n### Full File Verification\n\nVerify all files match their checksums:\n\n```bash\n#!\u002Fbin\u002Fbash\n# Full verification - manifest integrity + all files\n\nCHECKSUM_FILE=\"CHECKSUMS.sha256\"\n\n# Step 1: Verify manifest integrity\necho \"Step 1: Verifying manifest integrity...\"\nEXPECTED=$(grep '^# MANIFEST_HASH:' \"$CHECKSUM_FILE\" | awk '{print $3}')\nACTUAL=$(tail -n +4 \"$CHECKSUM_FILE\" | sha256sum | awk '{print $1}')\n\nif [ \"$EXPECTED\" != \"$ACTUAL\" ]; then\n  echo \"✗ Manifest integrity check failed - stopping\" >&2\n  exit 1\nfi\n\necho \"✓ Manifest integrity verified\"\n\n# Step 2: Verify all files\necho \"Step 2: Verifying all files...\"\nif tail -n +4 \"$CHECKSUM_FILE\" | sha256sum -c; then\n  echo \"✓ All files verified successfully\"\n  exit 0\nelse\n  echo \"✗ One or more files failed verification\" >&2\n  exit 1\nfi\n```\n\n**Output format** (from `sha256sum -c`):\n```\n.\u002Faudio\u002Fepisode-001.opus: OK\n.\u002Faudio\u002Fepisode-002.opus: OK\n.\u002Fvideo\u002Frecording.mp4: FAILED\nsha256sum: WARNING: 1 computed checksum did NOT match\n```\n\n**Exit codes**:\n- `0` - All files verified successfully\n- `1` - Verification failed (manifest or files)\n\n### Quiet Mode\n\nShow only failures:\n\n```bash\n#!\u002Fbin\u002Fbash\n# Quiet verification - only show failures\n\nCHECKSUM_FILE=\"CHECKSUMS.sha256\"\n\n# Quick manifest check (silent)\nEXPECTED=$(grep '^# MANIFEST_HASH:' \"$CHECKSUM_FILE\" | awk '{print $3}')\nACTUAL=$(tail -n +4 \"$CHECKSUM_FILE\" | sha256sum | awk '{print $1}')\n\nif [ \"$EXPECTED\" != \"$ACTUAL\" ]; then\n  echo \"MANIFEST: FAILED\" >&2\n  exit 1\nfi\n\n# Verify files (quiet mode - only show failures)\ntail -n +4 \"$CHECKSUM_FILE\" | sha256sum -c --quiet\n\nEXIT_CODE=$?\n\nif [ $EXIT_CODE -eq 0 ]; then\n  # Silent success\n  exit 0\nelse\n  # sha256sum already printed failures to stderr\n  exit 1\nfi\n```\n\n**Use case**: Cron jobs, automated monitoring, CI\u002FCD pipelines.\n\n**Output**: Nothing on success, only failed files on failure.\n\n## Regeneration After Changes\n\nScript for regenerating manifest after archive modifications:\n\n```bash\n#!\u002Fbin\u002Fbash\nset -euo pipefail\n\n# Regenerate checksum manifest after archive changes\n# Usage: .\u002Ffix-checksums.sh \u002Fpath\u002Fto\u002Farchive\n\nARCHIVE_PATH=\"${1:-.}\"\nCHECKSUM_FILE=\"CHECKSUMS.sha256\"\nBACKUP_FILE=\"CHECKSUMS.sha256.bak\"\nTEMP_FILE=\"\u002Ftmp\u002Fchecksums-$$.tmp\"\n\ncd \"$ARCHIVE_PATH\"\n\n# Backup existing manifest\nif [ -f \"$CHECKSUM_FILE\" ]; then\n  cp \"$CHECKSUM_FILE\" \"$BACKUP_FILE\"\n  echo \"Backed up existing manifest to $BACKUP_FILE\"\nfi\n\n# Generate new manifest\necho \"Regenerating checksums...\"\nfind . -type f ! -name \"$CHECKSUM_FILE\" ! -name \"$BACKUP_FILE\" -print0 | \\\n  sort -z | \\\n  xargs -0 sha256sum > \"$TEMP_FILE\"\n\nFILE_COUNT=$(wc -l \u003C \"$TEMP_FILE\")\nMANIFEST_HASH=$(sha256sum \"$TEMP_FILE\" | awk '{print $1}')\nTIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%S.%NZ)\n\n{\n  echo \"# MANIFEST_HASH: $MANIFEST_HASH\"\n  echo \"# Generated: $TIMESTAMP\"\n  echo \"# Verify with: tail -n +4 $CHECKSUM_FILE | sha256sum\"\n  cat \"$TEMP_FILE\"\n} > \"$CHECKSUM_FILE\"\n\nrm \"$TEMP_FILE\"\n\n# Detect changes\nif [ -f \"$BACKUP_FILE\" ]; then\n  echo \"\"\n  echo \"Changes detected:\"\n\n  # Extract file paths from old and new manifests\n  tail -n +4 \"$BACKUP_FILE\" | awk '{print $2}' | sort > \u002Ftmp\u002Fold-files-$$.txt\n  tail -n +4 \"$CHECKSUM_FILE\" | awk '{print $2}' | sort > \u002Ftmp\u002Fnew-files-$$.txt\n\n  # Added files\n  ADDED=$(comm -13 \u002Ftmp\u002Fold-files-$$.txt \u002Ftmp\u002Fnew-files-$$.txt)\n  if [ -n \"$ADDED\" ]; then\n    echo \"  Added:\"\n    echo \"$ADDED\" | sed 's\u002F^\u002F    \u002F'\n  fi\n\n  # Removed files\n  REMOVED=$(comm -23 \u002Ftmp\u002Fold-files-$$.txt \u002Ftmp\u002Fnew-files-$$.txt)\n  if [ -n \"$REMOVED\" ]; then\n    echo \"  Removed:\"\n    echo \"$REMOVED\" | sed 's\u002F^\u002F    \u002F'\n  fi\n\n  # Modified files (different hash for same path)\n  # This requires comparing hashes, not just paths\n  COMMON_FILES=$(comm -12 \u002Ftmp\u002Fold-files-$$.txt \u002Ftmp\u002Fnew-files-$$.txt)\n  if [ -n \"$COMMON_FILES\" ]; then\n    while IFS= read -r file; do\n      OLD_HASH=$(grep -F \"$file\" \"$BACKUP_FILE\" | awk '{print $1}')\n      NEW_HASH=$(grep -F \"$file\" \"$CHECKSUM_FILE\" | awk '{print $1}')\n      if [ \"$OLD_HASH\" != \"$NEW_HASH\" ]; then\n        echo \"  Modified: $file\"\n      fi\n    done \u003C\u003C\u003C \"$COMMON_FILES\"\n  fi\n\n  rm \u002Ftmp\u002Fold-files-$$.txt \u002Ftmp\u002Fnew-files-$$.txt\nfi\n\necho \"\"\necho \"✓ Generated new $CHECKSUM_FILE\"\necho \"  Manifest hash: $MANIFEST_HASH\"\necho \"  Files: $FILE_COUNT\"\n```\n\n**Features**:\n- Backs up existing manifest to `.bak` file\n- Regenerates checksums for all current files\n- Reports added, removed, and modified files\n- Preserves backup for comparison\n\n## VERIFY.md Template\n\nHuman-readable instructions placed in archive root:\n\n```markdown\n# Archive Integrity Verification\n\nThis archive contains a self-verifying checksum manifest (`CHECKSUMS.sha256`) for detecting corruption, tampering, or transfer errors.\n\n## Archive Information\n\n- **Generated**: {TIMESTAMP}\n- **Total files**: {FILE_COUNT}\n- **Total size**: {TOTAL_SIZE}\n- **Manifest hash**: {MANIFEST_HASH}\n\n## Quick Verification (30 seconds)\n\nVerify the manifest has not been tampered with:\n\n\\`\\`\\`bash\nEXPECTED=$(grep '^# MANIFEST_HASH:' CHECKSUMS.sha256 | awk '{print $3}')\nACTUAL=$(tail -n +4 CHECKSUMS.sha256 | sha256sum | awk '{print $1}')\n[ \"$EXPECTED\" = \"$ACTUAL\" ] && echo \"✓ Verified\" || echo \"✗ Tampered\"\n\\`\\`\\`\n\n## Full Verification (10-60 minutes)\n\nVerify all files match their checksums:\n\n\\`\\`\\`bash\ntail -n +4 CHECKSUMS.sha256 | sha256sum -c\n\\`\\`\\`\n\n## Recommended Schedule\n\n| Frequency | Verification Type | Purpose |\n|-----------|-------------------|---------|\n| Daily | Quick (manifest only) | Detect tampering |\n| Weekly | Full (all files) | Detect bit rot |\n| After transfer | Full | Verify transfer integrity |\n| Before backup | Full | Ensure source integrity |\n\n## Automated Monitoring\n\nAdd to crontab for daily verification:\n\n\\`\\`\\`cron\n# Daily quick check at 2am\n0 2 * * * cd \u002Fpath\u002Fto\u002Farchive && tail -n +4 CHECKSUMS.sha256 | sha256sum -c --quiet || echo \"Verification failed\" | mail -s \"Archive Alert\" admin@example.com\n\\`\\`\\`\n\n## If Verification Fails\n\n### Manifest Integrity Failure\n\nThe manifest itself has been corrupted or tampered with.\n\n**Recovery**:\n1. Restore `CHECKSUMS.sha256` from backup\n2. If no backup, regenerate manifest (see below)\n\n### File Verification Failure\n\nOne or more files have been corrupted or modified.\n\n**Identify failures**:\n\\`\\`\\`bash\ntail -n +4 CHECKSUMS.sha256 | sha256sum -c 2>&1 | grep FAILED\n\\`\\`\\`\n\n**Recovery**:\n1. Restore failed files from backup\n2. If intentional modification, regenerate manifest\n\n## Regenerate Manifest\n\nAfter making changes to the archive (add\u002Fremove\u002Fmodify files):\n\n\\`\\`\\`bash\n# Backup existing manifest\ncp CHECKSUMS.sha256 CHECKSUMS.sha256.bak\n\n# Regenerate\nfind . -type f ! -name \"CHECKSUMS.sha256\" -print0 | \\\\\n  sort -z | \\\\\n  xargs -0 sha256sum > \u002Ftmp\u002Fchecksums.tmp\n\nMANIFEST_HASH=$(sha256sum \u002Ftmp\u002Fchecksums.tmp | awk '{print $1}')\nTIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%S.%NZ)\n\n{\n  echo \"# MANIFEST_HASH: $MANIFEST_HASH\"\n  echo \"# Generated: $TIMESTAMP\"\n  echo \"# Verify with: tail -n +4 CHECKSUMS.sha256 | sha256sum\"\n  cat \u002Ftmp\u002Fchecksums.tmp\n} > CHECKSUMS.sha256\n\nrm \u002Ftmp\u002Fchecksums.tmp\n\\`\\`\\`\n\n## Technical Details\n\n- **Hash algorithm**: SHA-256 (NIST FIPS 180-4)\n- **Timestamp format**: ISO 8601 UTC with nanosecond precision\n- **Self-verification**: Manifest hash prevents undetected tampering\n- **Coverage**: All files except `CHECKSUMS.sha256` itself\n\n## Support\n\nFor questions or issues:\n- Documentation: https:\u002F\u002Faiwg.io\u002Fmedia-curator\n- Issues: https:\u002F\u002Fgithub.com\u002Fjmagly\u002Faiwg\u002Fissues\n- Command reference: `aiwg verify-archive --help`\n\n---\n\n*Generated by AIWG Media Curator v{VERSION}*\n```\n\n**Template variables**:\n- `{TIMESTAMP}` - ISO 8601 generation timestamp\n- `{FILE_COUNT}` - Number of files in manifest\n- `{TOTAL_SIZE}` - Archive size (e.g., \"4.2 GB\")\n- `{MANIFEST_HASH}` - SHA-256 hash of manifest\n- `{VERSION}` - AIWG version\n\n## Scheduled Verification\n\n### Cron Pattern for Daily Checks\n\n```cron\n# Quick verification daily at 2am\n0 2 * * * cd \u002Fmedia\u002Farchives\u002Fpodcast && \u002Fusr\u002Flocal\u002Fbin\u002Faiwg verify-archive . --verify --quiet || echo \"Archive verification failed: $(pwd)\" | mail -s \"Archive Alert\" admin@example.com\n\n# Full verification weekly on Sunday at 3am\n0 3 * * 0 cd \u002Fmedia\u002Farchives\u002Fpodcast && \u002Fusr\u002Flocal\u002Fbin\u002Faiwg verify-archive . --verify 2>&1 | mail -s \"Weekly Archive Verification\" admin@example.com\n```\n\n### Systemd Timer\n\n**Service file** (`\u002Fetc\u002Fsystemd\u002Fsystem\u002Farchive-verify.service`):\n\n```ini\n[Unit]\nDescription=Verify media archive checksums\nAfter=network.target\n\n[Service]\nType=oneshot\nUser=media\nWorkingDirectory=\u002Fmedia\u002Farchives\u002Fpodcast\nExecStart=\u002Fusr\u002Flocal\u002Fbin\u002Faiwg verify-archive . --verify --quiet\nStandardOutput=journal\nStandardError=journal\n```\n\n**Timer file** (`\u002Fetc\u002Fsystemd\u002Fsystem\u002Farchive-verify.timer`):\n\n```ini\n[Unit]\nDescription=Daily archive verification\n\n[Timer]\nOnCalendar=daily\nPersistent=true\n\n[Install]\nWantedBy=timers.target\n```\n\n**Enable timer**:\n```bash\nsudo systemctl enable archive-verify.timer\nsudo systemctl start archive-verify.timer\n```\n\n### Monitoring Integration\n\n**Prometheus exporter pattern**:\n\n```bash\n#!\u002Fbin\u002Fbash\n# Export verification status as Prometheus metrics\n\nCHECKSUM_FILE=\"CHECKSUMS.sha256\"\nMETRICS_FILE=\"\u002Fvar\u002Flib\u002Fprometheus\u002Fnode_exporter\u002Farchive_integrity.prom\"\n\n# Quick verification\nEXPECTED=$(grep '^# MANIFEST_HASH:' \"$CHECKSUM_FILE\" | awk '{print $3}')\nACTUAL=$(tail -n +4 \"$CHECKSUM_FILE\" | sha256sum | awk '{print $1}')\n\nif [ \"$EXPECTED\" = \"$ACTUAL\" ]; then\n  MANIFEST_OK=1\nelse\n  MANIFEST_OK=0\nfi\n\n# Write metrics\ncat > \"$METRICS_FILE\" \u003C\u003CEOF\n# HELP archive_manifest_integrity Archive manifest integrity status (1=ok, 0=failed)\n# TYPE archive_manifest_integrity gauge\narchive_manifest_integrity{path=\"$PWD\"} $MANIFEST_OK\n\n# HELP archive_manifest_check_timestamp Unix timestamp of last verification\n# TYPE archive_manifest_check_timestamp gauge\narchive_manifest_check_timestamp{path=\"$PWD\"} $(date +%s)\nEOF\n```\n\n**Grafana alert rule**:\n```yaml\ngroups:\n  - name: archive_integrity\n    interval: 5m\n    rules:\n      - alert: ArchiveManifestCorrupted\n        expr: archive_manifest_integrity == 0\n        for: 5m\n        labels:\n          severity: critical\n        annotations:\n          summary: \"Archive manifest integrity check failed\"\n          description: \"Archive at {{ $labels.path }} has corrupted or tampered manifest\"\n```\n\n## Standards Reference\n\n| Standard | Specification | Purpose |\n|----------|---------------|---------|\n| **SHA-256** | NIST FIPS 180-4 | Cryptographic hash function for file integrity |\n| **PREMIS 3.0** | Library of Congress | Preservation metadata for digital objects |\n| **W3C PROV-O** | W3C Recommendation 2013 | Provenance ontology for tracking derivation |\n| **ISO 8601** | ISO 8601:2019 | Date and time format (UTC timestamps) |\n| **JSON-LD 1.1** | W3C Recommendation 2020 | Linked data format for provenance records |\n\n### SHA-256 (NIST FIPS 180-4)\n\n**Properties**:\n- 256-bit hash output (64 hexadecimal characters)\n- Collision resistance: 2^128 operations\n- Pre-image resistance: 2^256 operations\n- Deterministic: same input always produces same output\n\n**Command**: `sha256sum \u003Cfile>`\n\n**Format**: `\u003C64-char-hex>  \u003Cpath>`\n\n### PREMIS 3.0 Fixity\n\n**Purpose**: Record fixity information for digital preservation.\n\n**Key elements**:\n- `messageDigest` - Hash value with algorithm prefix (e.g., `sha256:abc123...`)\n- `messageDigestAlgorithm` - Algorithm name (`SHA-256`)\n- `messageDigestOriginator` - Software that computed hash\n- `fixityCheckDateTime` - When fixity was verified\n\n**Use case**: Long-term digital preservation requiring audit trails.\n\n### W3C PROV-O\n\n**Entity-Activity-Agent model**:\n- **Entity**: Archive or checksum manifest\n- **Activity**: Checksum generation or verification\n- **Agent**: Software (AIWG Media Curator) that performed activity\n\n**Key relationships**:\n- `wasGeneratedBy` - Entity generated by activity\n- `used` - Activity used entity\n- `wasAssociatedWith` - Activity performed by agent\n- `wasAttributedTo` - Entity attributed to agent\n\n### ISO 8601 Timestamps\n\n**Format**: `YYYY-MM-DDTHH:MM:SS.NNNNNNNNNZ`\n\n**Requirements**:\n- Always UTC (trailing `Z`)\n- Nanosecond precision (9 decimal places)\n- Monotonic (lexicographically sortable)\n\n**Bash command**: `date -u +%Y-%m-%dT%H:%M:%S.%NZ`\n\n**Example**: `2026-02-14T18:45:22.387654321Z`\n\n## Performance Characteristics\n\n| Operation | Time Complexity | Example Duration (100 GB archive) |\n|-----------|-----------------|-----------------------------------|\n| Quick verify (manifest only) | O(1) | \u003C 1 second |\n| Full verify (all files) | O(n × file_size) | 10-60 minutes (disk-bound) |\n| Generate manifest | O(n × file_size) | 10-60 minutes (disk-bound) |\n\n**Optimization tips**:\n- Use SSD storage for faster checksumming\n- Enable parallel hashing for multi-core systems (GNU parallel)\n- Quick verification detects 99% of tampering instantly\n- Schedule full verification during off-peak hours\n\n## Error Scenarios\n\n| Error | Cause | Recovery |\n|-------|-------|----------|\n| Manifest integrity failure | Manifest file corrupted\u002Ftampered | Restore from backup or regenerate |\n| File verification failure | File corrupted or modified | Restore file from backup |\n| Missing manifest | New archive or manifest deleted | Generate new manifest |\n| Permission denied | Cannot read files | Fix permissions, run as appropriate user |\n| Disk full | Cannot write manifest | Free disk space |\n| Hash mismatch | File changed since manifest generated | Regenerate manifest if intentional |\n\n## Integration Examples\n\n### Git Pre-Commit Hook\n\nVerify archive integrity before committing:\n\n```bash\n#!\u002Fbin\u002Fbash\n# .git\u002Fhooks\u002Fpre-commit\n\nif [ -f CHECKSUMS.sha256 ]; then\n  echo \"Verifying archive integrity...\"\n  if ! aiwg verify-archive . --verify --quiet; then\n    echo \"Error: Archive verification failed\" >&2\n    echo \"Run 'aiwg verify-archive . --fix' to regenerate checksums\" >&2\n    exit 1\n  fi\n  echo \"✓ Archive integrity verified\"\nfi\n```\n\n### CI\u002FCD Pipeline\n\nGitHub Actions workflow:\n\n```yaml\nname: Verify Archive Integrity\non: [push, pull_request]\n\njobs:\n  verify:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v3\n      - name: Install AIWG\n        run: npm install -g aiwg\n      - name: Verify archive\n        run: aiwg verify-archive media\u002Farchives\u002Fpodcast --verify\n```\n\n### Backup Verification\n\nVerify backup integrity after rsync:\n\n```bash\n#!\u002Fbin\u002Fbash\n# Backup and verify script\n\nSOURCE=\"\u002Fmedia\u002Fsource\u002Fpodcast\"\nDEST=\"\u002Fmedia\u002Fbackup\u002Fpodcast\"\n\n# Sync files\nrsync -av --delete \"$SOURCE\u002F\" \"$DEST\u002F\"\n\n# Verify destination\ncd \"$DEST\"\nif aiwg verify-archive . --verify --quiet; then\n  echo \"✓ Backup verified successfully\"\nelse\n  echo \"✗ Backup verification failed\" >&2\n  exit 1\nfi\n```\n\n## References\n\n- @$AIWG_ROOT\u002Fagentic\u002Fcode\u002Faddons\u002Faiwg-utils\u002Frules\u002Fhuman-authorization.md — Seek explicit authorization before regenerating checksums (overwrites existing CHECKSUMS.sha256)\n- @$AIWG_ROOT\u002Fagentic\u002Fcode\u002Fframeworks\u002Fmedia-curator\u002Fskills\u002Facquire\u002FSKILL.md — Acquisition skill that invokes integrity verification via --verify-after flag\n- @$AIWG_ROOT\u002Fagentic\u002Fcode\u002Fframeworks\u002Fmedia-curator\u002Fskills\u002Fprovenance-tracking\u002FSKILL.md — Provenance tracking that records fixity events alongside checksums\n- @$AIWG_ROOT\u002Fagentic\u002Fcode\u002Fframeworks\u002Fmedia-curator\u002Fskills\u002Fverify-archive\u002FSKILL.md — High-level verify-archive skill that uses these integrity patterns\n","# Integrity Verification\n\nCryptographic checksum verification patterns for detecting bit rot, tampering, and transfer errors in media archives. Implements self-verifying manifests with PREMIS fixity metadata.\n\n## Manifest Generation Script\n\nComplete bash implementation for generating self-verifying checksum manifests:\n\n```bash\n#!\u002Fbin\u002Fbash\nset -euo pipefail\n\n# Archive Checksum Manifest Generator\n# Generates self-verifying SHA-256 checksum manifest\n# Usage: .\u002Fgenerate-checksums.sh \u002Fpath\u002Fto\u002Farchive\n\nARCHIVE_PATH=\"${1:-.}\"\nCHECKSUM_FILE=\"CHECKSUMS.sha256\"\nTEMP_FILE=\"\u002Ftmp\u002Fchecksums-$$.tmp\"\n\n# Validate archive exists\nif [ ! -d \"$ARCHIVE_PATH\" ]; then\n  echo \"Error: Archive directory not found: $ARCHIVE_PATH\" >&2\n  exit 1\nfi\n\ncd \"$ARCHIVE_PATH\"\n\necho \"Generating checksums for: $ARCHIVE_PATH\"\n\n# Find all files, exclude checksum manifest itself\n# Use null-terminated strings for handling filenames with spaces\nfind . -type f ! -name \"$CHECKSUM_FILE\" -print0 | \\\n  sort -z | \\\n  xargs -0 sha256sum > \"$TEMP_FILE\"\n\n# Count files\nFILE_COUNT=$(wc -l \u003C \"$TEMP_FILE\")\necho \"Found $FILE_COUNT files\"\n\n# Compute manifest hash (hash of the checksum content)\nMANIFEST_HASH=$(sha256sum \"$TEMP_FILE\" | awk '{print $1}')\n\n# Generate timestamp (ISO 8601 UTC with nanosecond precision)\nTIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%S.%NZ)\n\n# Write final manifest with self-verifying header\n{\n  echo \"# MANIFEST_HASH: $MANIFEST_HASH\"\n  echo \"# Generated: $TIMESTAMP\"\n  echo \"# Verify with: tail -n +4 $CHECKSUM_FILE | sha256sum\"\n  cat \"$TEMP_FILE\"\n} > \"$CHECKSUM_FILE\"\n\n# Clean up\nrm \"$TEMP_FILE\"\n\necho \"✓ Generated $CHECKSUM_FILE\"\necho \"  Manifest hash: $MANIFEST_HASH\"\necho \"  Timestamp: $TIMESTAMP\"\necho \"  Files: $FILE_COUNT\"\n```\n\n**Key features**:\n- Handles filenames with spaces via null-terminated strings (`-print0`, `-z`, `-0`)\n- Deterministic output (sorted by path)\n- Self-verifying header with manifest hash\n- ISO 8601 UTC timestamps with nanosecond precision\n- Exit on error (`set -euo pipefail`)\n\n## Verification Commands\n\n### Quick Manifest Integrity Check\n\nVerify manifest has not been tampered with (sub-second):\n\n```bash\n#!\u002Fbin\u002Fbash\n# Quick verification - manifest integrity only\n\nCHECKSUM_FILE=\"CHECKSUMS.sha256\"\n\nif [ ! -f \"$CHECKSUM_FILE\" ]; then\n  echo \"✗ Checksum manifest not found: $CHECKSUM_FILE\" >&2\n  exit 1\nfi\n\n# Extract expected hash from header\nEXPECTED=$(grep '^# MANIFEST_HASH:' \"$CHECKSUM_FILE\" | awk '{print $3}')\n\nif [ -z \"$EXPECTED\" ]; then\n  echo \"✗ Manifest header missing or malformed\" >&2\n  exit 1\nfi\n\n# Compute actual hash of manifest content (lines 4+)\nACTUAL=$(tail -n +4 \"$CHECKSUM_FILE\" | sha256sum | awk '{print $1}')\n\n# Compare\nif [ \"$EXPECTED\" = \"$ACTUAL\" ]; then\n  echo \"✓ Manifest integrity verified\"\n  echo \"  Hash: $EXPECTED\"\n  exit 0\nelse\n  echo \"✗ Manifest has been tampered with\" >&2\n  echo \"  Expected: $EXPECTED\" >&2\n  echo \"  Actual:   $ACTUAL\" >&2\n  exit 1\nfi\n```\n\n**Use case**: Daily automated checks. Fast execution regardless of archive size.\n\n**Exit codes**:\n- `0` - Manifest integrity verified\n- `1` - Manifest corrupted or tampered\n\n### Full File Verification\n\nVerify all files match their checksums:\n\n```bash\n#!\u002Fbin\u002Fbash\n# Full verification - manifest integrity + all files\n\nCHECKSUM_FILE=\"CHECKSUMS.sha256\"\n\n# Step 1: Verify manifest integrity\necho \"Step 1: Verifying manifest integrity...\"\nEXPECTED=$(grep '^# MANIFEST_HASH:' \"$CHECKSUM_FILE\" | awk '{print $3}')\nACTUAL=$(tail -n +4 \"$CHECKSUM_FILE\" | sha256sum | awk '{print $1}')\n\nif [ \"$EXPECTED\" != \"$ACTUAL\" ]; then\n  echo \"✗ Manifest integrity check failed - stopping\" >&2\n  exit 1\nfi\n\necho \"✓ Manifest integrity verified\"\n\n# Step 2: Verify all files\necho \"Step 2: Verifying all files...\"\nif tail -n +4 \"$CHECKSUM_FILE\" | sha256sum -c; then\n  echo \"✓ All files verified successfully\"\n  exit 0\nelse\n  echo \"✗ One or more files failed verification\" >&2\n  exit 1\nfi\n```\n\n**Output format** (from `sha256sum -c`):\n```\n.\u002Faudio\u002Fepisode-001.opus: OK\n.\u002Faudio\u002Fepisode-002.opus: OK\n.\u002Fvideo\u002Frecording.mp4: FAILED\nsha256sum: WARNING: 1 computed checksum did NOT match\n```\n\n**Exit codes**:\n- `0` - All files verified successfully\n- `1` - Verification failed (manifest or files)\n\n### Quiet Mode\n\nShow only failures:\n\n```bash\n#!\u002Fbin\u002Fbash\n# Quiet verification - only show failures\n\nCHECKSUM_FILE=\"CHECKSUMS.sha256\"\n\n# Quick manifest check (silent)\nEXPECTED=$(grep '^# MANIFEST_HASH:' \"$CHECKSUM_FILE\" | awk '{print $3}')\nACTUAL=$(tail -n +4 \"$CHECKSUM_FILE\" | sha256sum | awk '{print $1}')\n\nif [ \"$EXPECTED\" != \"$ACTUAL\" ]; then\n  echo \"MANIFEST: FAILED\" >&2\n  exit 1\nfi\n\n# Verify files (quiet mode - only show failures)\ntail -n +4 \"$CHECKSUM_FILE\" | sha256sum -c --quiet\n\nEXIT_CODE=$?\n\nif [ $EXIT_CODE -eq 0 ]; then\n  # Silent success\n  exit 0\nelse\n  # sha256sum already printed failures to stderr\n  exit 1\nfi\n```\n\n**Use case**: Cron jobs, automated monitoring, CI\u002FCD pipelines.\n\n**Output**: Nothing on success, only failed files on failure.\n\n## Regeneration After Changes\n\nScript for regenerating manifest after archive modifications:\n\n```bash\n#!\u002Fbin\u002Fbash\nset -euo pipefail\n\n# Regenerate checksum manifest after archive changes\n# Usage: .\u002Ffix-checksums.sh \u002Fpath\u002Fto\u002Farchive\n\nARCHIVE_PATH=\"${1:-.}\"\nCHECKSUM_FILE=\"CHECKSUMS.sha256\"\nBACKUP_FILE=\"CHECKSUMS.sha256.bak\"\nTEMP_FILE=\"\u002Ftmp\u002Fchecksums-$$.tmp\"\n\ncd \"$ARCHIVE_PATH\"\n\n# Backup existing manifest\nif [ -f \"$CHECKSUM_FILE\" ]; then\n  cp \"$CHECKSUM_FILE\" \"$BACKUP_FILE\"\n  echo \"Backed up existing manifest to $BACKUP_FILE\"\nfi\n\n# Generate new manifest\necho \"Regenerating checksums...\"\nfind . -type f ! -name \"$CHECKSUM_FILE\" ! -name \"$BACKUP_FILE\" -print0 | \\\n  sort -z | \\\n  xargs -0 sha256sum > \"$TEMP_FILE\"\n\nFILE_COUNT=$(wc -l \u003C \"$TEMP_FILE\")\nMANIFEST_HASH=$(sha256sum \"$TEMP_FILE\" | awk '{print $1}')\nTIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%S.%NZ)\n\n{\n  echo \"# MANIFEST_HASH: $MANIFEST_HASH\"\n  echo \"# Generated: $TIMESTAMP\"\n  echo \"# Verify with: tail -n +4 $CHECKSUM_FILE | sha256sum\"\n  cat \"$TEMP_FILE\"\n} > \"$CHECKSUM_FILE\"\n\nrm \"$TEMP_FILE\"\n\n# Detect changes\nif [ -f \"$BACKUP_FILE\" ]; then\n  echo \"\"\n  echo \"Changes detected:\"\n\n  # Extract file paths from old and new manifests\n  tail -n +4 \"$BACKUP_FILE\" | awk '{print $2}' | sort > \u002Ftmp\u002Fold-files-$$.txt\n  tail -n +4 \"$CHECKSUM_FILE\" | awk '{print $2}' | sort > \u002Ftmp\u002Fnew-files-$$.txt\n\n  # Added files\n  ADDED=$(comm -13 \u002Ftmp\u002Fold-files-$$.txt \u002Ftmp\u002Fnew-files-$$.txt)\n  if [ -n \"$ADDED\" ]; then\n    echo \"  Added:\"\n    echo \"$ADDED\" | sed 's\u002F^\u002F    \u002F'\n  fi\n\n  # Removed files\n  REMOVED=$(comm -23 \u002Ftmp\u002Fold-files-$$.txt \u002Ftmp\u002Fnew-files-$$.txt)\n  if [ -n \"$REMOVED\" ]; then\n    echo \"  Removed:\"\n    echo \"$REMOVED\" | sed 's\u002F^\u002F    \u002F'\n  fi\n\n  # Modified files (different hash for same path)\n  # This requires comparing hashes, not just paths\n  COMMON_FILES=$(comm -12 \u002Ftmp\u002Fold-files-$$.txt \u002Ftmp\u002Fnew-files-$$.txt)\n  if [ -n \"$COMMON_FILES\" ]; then\n    while IFS= read -r file; do\n      OLD_HASH=$(grep -F \"$file\" \"$BACKUP_FILE\" | awk '{print $1}')\n      NEW_HASH=$(grep -F \"$file\" \"$CHECKSUM_FILE\" | awk '{print $1}')\n      if [ \"$OLD_HASH\" != \"$NEW_HASH\" ]; then\n        echo \"  Modified: $file\"\n      fi\n    done \u003C\u003C\u003C \"$COMMON_FILES\"\n  fi\n\n  rm \u002Ftmp\u002Fold-files-$$.txt \u002Ftmp\u002Fnew-files-$$.txt\nfi\n\necho \"\"\necho \"✓ Generated new $CHECKSUM_FILE\"\necho \"  Manifest hash: $MANIFEST_HASH\"\necho \"  Files: $FILE_COUNT\"\n```\n\n**Features**:\n- Backs up existing manifest to `.bak` file\n- Regenerates checksums for all current files\n- Reports added, removed, and modified files\n- Preserves backup for comparison\n\n## VERIFY.md Template\n\nHuman-readable instructions placed in archive root:\n\n```markdown\n# Archive Integrity Verification\n\nThis archive contains a self-verifying checksum manifest (`CHECKSUMS.sha256`) for detecting corruption, tampering, or transfer errors.\n\n## Archive Information\n\n- **Generated**: {TIMESTAMP}\n- **Total files**: {FILE_COUNT}\n- **Total size**: {TOTAL_SIZE}\n- **Manifest hash**: {MANIFEST_HASH}\n\n## Quick Verification (30 seconds)\n\nVerify the manifest has not been tampered with:\n\n\\`\\`\\`bash\nEXPECTED=$(grep '^# MANIFEST_HASH:' CHECKSUMS.sha256 | awk '{print $3}')\nACTUAL=$(tail -n +4 CHECKSUMS.sha256 | sha256sum | awk '{print $1}')\n[ \"$EXPECTED\" = \"$ACTUAL\" ] && echo \"✓ Verified\" || echo \"✗ Tampered\"\n\\`\\`\\`\n\n## Full Verification (10-60 minutes)\n\nVerify all files match their checksums:\n\n\\`\\`\\`bash\ntail -n +4 CHECKSUMS.sha256 | sha256sum -c\n\\`\\`\\`\n\n## Recommended Schedule\n\n| Frequency | Verification Type | Purpose |\n|-----------|-------------------|---------|\n| Daily | Quick (manifest only) | Detect tampering |\n| Weekly | Full (all files) | Detect bit rot |\n| After transfer | Full | Verify transfer integrity |\n| Before backup | Full | Ensure source integrity |\n\n## Automated Monitoring\n\nAdd to crontab for daily verification:\n\n\\`\\`\\`cron\n# Daily quick check at 2am\n0 2 * * * cd \u002Fpath\u002Fto\u002Farchive && tail -n +4 CHECKSUMS.sha256 | sha256sum -c --quiet || echo \"Verification failed\" | mail -s \"Archive Alert\" admin@example.com\n\\`\\`\\`\n\n## If Verification Fails\n\n### Manifest Integrity Failure\n\nThe manifest itself has been corrupted or tampered with.\n\n**Recovery**:\n1. Restore `CHECKSUMS.sha256` from backup\n2. If no backup, regenerate manifest (see below)\n\n### File Verification Failure\n\nOne or more files have been corrupted or modified.\n\n**Identify failures**:\n\\`\\`\\`bash\ntail -n +4 CHECKSUMS.sha256 | sha256sum -c 2>&1 | grep FAILED\n\\`\\`\\`\n\n**Recovery**:\n1. Restore failed files from backup\n2. If intentional modification, regenerate manifest\n\n## Regenerate Manifest\n\nAfter making changes to the archive (add\u002Fremove\u002Fmodify files):\n\n\\`\\`\\`bash\n# Backup existing manifest\ncp CHECKSUMS.sha256 CHECKSUMS.sha256.bak\n\n# Regenerate\nfind . -type f ! -name \"CHECKSUMS.sha256\" -print0 | \\\\\n  sort -z | \\\\\n  xargs -0 sha256sum > \u002Ftmp\u002Fchecksums.tmp\n\nMANIFEST_HASH=$(sha256sum \u002Ftmp\u002Fchecksums.tmp | awk '{print $1}')\nTIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%S.%NZ)\n\n{\n  echo \"# MANIFEST_HASH: $MANIFEST_HASH\"\n  echo \"# Generated: $TIMESTAMP\"\n  echo \"# Verify with: tail -n +4 CHECKSUMS.sha256 | sha256sum\"\n  cat \u002Ftmp\u002Fchecksums.tmp\n} > CHECKSUMS.sha256\n\nrm \u002Ftmp\u002Fchecksums.tmp\n\\`\\`\\`\n\n## Technical Details\n\n- **Hash algorithm**: SHA-256 (NIST FIPS 180-4)\n- **Timestamp format**: ISO 8601 UTC with nanosecond precision\n- **Self-verification**: Manifest hash prevents undetected tampering\n- **Coverage**: All files except `CHECKSUMS.sha256` itself\n\n## Support\n\nFor questions or issues:\n- Documentation: https:\u002F\u002Faiwg.io\u002Fmedia-curator\n- Issues: https:\u002F\u002Fgithub.com\u002Fjmagly\u002Faiwg\u002Fissues\n- Command reference: `aiwg verify-archive --help`\n\n---\n\n*Generated by AIWG Media Curator v{VERSION}*\n```\n\n**Template variables**:\n- `{TIMESTAMP}` - ISO 8601 generation timestamp\n- `{FILE_COUNT}` - Number of files in manifest\n- `{TOTAL_SIZE}` - Archive size (e.g., \"4.2 GB\")\n- `{MANIFEST_HASH}` - SHA-256 hash of manifest\n- `{VERSION}` - AIWG version\n\n## Scheduled Verification\n\n### Cron Pattern for Daily Checks\n\n```cron\n# Quick verification daily at 2am\n0 2 * * * cd \u002Fmedia\u002Farchives\u002Fpodcast && \u002Fusr\u002Flocal\u002Fbin\u002Faiwg verify-archive . --verify --quiet || echo \"Archive verification failed: $(pwd)\" | mail -s \"Archive Alert\" admin@example.com\n\n# Full verification weekly on Sunday at 3am\n0 3 * * 0 cd \u002Fmedia\u002Farchives\u002Fpodcast && \u002Fusr\u002Flocal\u002Fbin\u002Faiwg verify-archive . --verify 2>&1 | mail -s \"Weekly Archive Verification\" admin@example.com\n```\n\n### Systemd Timer\n\n**Service file** (`\u002Fetc\u002Fsystemd\u002Fsystem\u002Farchive-verify.service`):\n\n```ini\n[Unit]\nDescription=Verify media archive checksums\nAfter=network.target\n\n[Service]\nType=oneshot\nUser=media\nWorkingDirectory=\u002Fmedia\u002Farchives\u002Fpodcast\nExecStart=\u002Fusr\u002Flocal\u002Fbin\u002Faiwg verify-archive . --verify --quiet\nStandardOutput=journal\nStandardError=journal\n```\n\n**Timer file** (`\u002Fetc\u002Fsystemd\u002Fsystem\u002Farchive-verify.timer`):\n\n```ini\n[Unit]\nDescription=Daily archive verification\n\n[Timer]\nOnCalendar=daily\nPersistent=true\n\n[Install]\nWantedBy=timers.target\n```\n\n**Enable timer**:\n```bash\nsudo systemctl enable archive-verify.timer\nsudo systemctl start archive-verify.timer\n```\n\n### Monitoring Integration\n\n**Prometheus exporter pattern**:\n\n```bash\n#!\u002Fbin\u002Fbash\n# Export verification status as Prometheus metrics\n\nCHECKSUM_FILE=\"CHECKSUMS.sha256\"\nMETRICS_FILE=\"\u002Fvar\u002Flib\u002Fprometheus\u002Fnode_exporter\u002Farchive_integrity.prom\"\n\n# Quick verification\nEXPECTED=$(grep '^# MANIFEST_HASH:' \"$CHECKSUM_FILE\" | awk '{print $3}')\nACTUAL=$(tail -n +4 \"$CHECKSUM_FILE\" | sha256sum | awk '{print $1}')\n\nif [ \"$EXPECTED\" = \"$ACTUAL\" ]; then\n  MANIFEST_OK=1\nelse\n  MANIFEST_OK=0\nfi\n\n# Write metrics\ncat > \"$METRICS_FILE\" \u003C\u003CEOF\n# HELP archive_manifest_integrity Archive manifest integrity status (1=ok, 0=failed)\n# TYPE archive_manifest_integrity gauge\narchive_manifest_integrity{path=\"$PWD\"} $MANIFEST_OK\n\n# HELP archive_manifest_check_timestamp Unix timestamp of last verification\n# TYPE archive_manifest_check_timestamp gauge\narchive_manifest_check_timestamp{path=\"$PWD\"} $(date +%s)\nEOF\n```\n\n**Grafana alert rule**:\n```yaml\ngroups:\n  - name: archive_integrity\n    interval: 5m\n    rules:\n      - alert: ArchiveManifestCorrupted\n        expr: archive_manifest_integrity == 0\n        for: 5m\n        labels:\n          severity: critical\n        annotations:\n          summary: \"Archive manifest integrity check failed\"\n          description: \"Archive at {{ $labels.path }} has corrupted or tampered manifest\"\n```\n\n## Standards Reference\n\n| Standard | Specification | Purpose |\n|----------|---------------|---------|\n| **SHA-256** | NIST FIPS 180-4 | Cryptographic hash function for file integrity |\n| **PREMIS 3.0** | Library of Congress | Preservation metadata for digital objects |\n| **W3C PROV-O** | W3C Recommendation 2013 | Provenance ontology for tracking derivation |\n| **ISO 8601** | ISO 8601:2019 | Date and time format (UTC timestamps) |\n| **JSON-LD 1.1** | W3C Recommendation 2020 | Linked data format for provenance records |\n\n### SHA-256 (NIST FIPS 180-4)\n\n**Properties**:\n- 256-bit hash output (64 hexadecimal characters)\n- Collision resistance: 2^128 operations\n- Pre-image resistance: 2^256 operations\n- Deterministic: same input always produces same output\n\n**Command**: `sha256sum \u003Cfile>`\n\n**Format**: `\u003C64-char-hex>  \u003Cpath>`\n\n### PREMIS 3.0 Fixity\n\n**Purpose**: Record fixity information for digital preservation.\n\n**Key elements**:\n- `messageDigest` - Hash value with algorithm prefix (e.g., `sha256:abc123...`)\n- `messageDigestAlgorithm` - Algorithm name (`SHA-256`)\n- `messageDigestOriginator` - Software that computed hash\n- `fixityCheckDateTime` - When fixity was verified\n\n**Use case**: Long-term digital preservation requiring audit trails.\n\n### W3C PROV-O\n\n**Entity-Activity-Agent model**:\n- **Entity**: Archive or checksum manifest\n- **Activity**: Checksum generation or verification\n- **Agent**: Software (AIWG Media Curator) that performed activity\n\n**Key relationships**:\n- `wasGeneratedBy` - Entity generated by activity\n- `used` - Activity used entity\n- `wasAssociatedWith` - Activity performed by agent\n- `wasAttributedTo` - Entity attributed to agent\n\n### ISO 8601 Timestamps\n\n**Format**: `YYYY-MM-DDTHH:MM:SS.NNNNNNNNNZ`\n\n**Requirements**:\n- Always UTC (trailing `Z`)\n- Nanosecond precision (9 decimal places)\n- Monotonic (lexicographically sortable)\n\n**Bash command**: `date -u +%Y-%m-%dT%H:%M:%S.%NZ`\n\n**Example**: `2026-02-14T18:45:22.387654321Z`\n\n## Performance Characteristics\n\n| Operation | Time Complexity | Example Duration (100 GB archive) |\n|-----------|-----------------|-----------------------------------|\n| Quick verify (manifest only) | O(1) | \u003C 1 second |\n| Full verify (all files) | O(n × file_size) | 10-60 minutes (disk-bound) |\n| Generate manifest | O(n × file_size) | 10-60 minutes (disk-bound) |\n\n**Optimization tips**:\n- Use SSD storage for faster checksumming\n- Enable parallel hashing for multi-core systems (GNU parallel)\n- Quick verification detects 99% of tampering instantly\n- Schedule full verification during off-peak hours\n\n## Error Scenarios\n\n| Error | Cause | Recovery |\n|-------|-------|----------|\n| Manifest integrity failure | Manifest file corrupted\u002Ftampered | Restore from backup or regenerate |\n| File verification failure | File corrupted or modified | Restore file from backup |\n| Missing manifest | New archive or manifest deleted | Generate new manifest |\n| Permission denied | Cannot read files | Fix permissions, run as appropriate user |\n| Disk full | Cannot write manifest | Free disk space |\n| Hash mismatch | File changed since manifest generated | Regenerate manifest if intentional |\n\n## Integration Examples\n\n### Git Pre-Commit Hook\n\nVerify archive integrity before committing:\n\n```bash\n#!\u002Fbin\u002Fbash\n# .git\u002Fhooks\u002Fpre-commit\n\nif [ -f CHECKSUMS.sha256 ]; then\n  echo \"Verifying archive integrity...\"\n  if ! aiwg verify-archive . --verify --quiet; then\n    echo \"Error: Archive verification failed\" >&2\n    echo \"Run 'aiwg verify-archive . --fix' to regenerate checksums\" >&2\n    exit 1\n  fi\n  echo \"✓ Archive integrity verified\"\nfi\n```\n\n### CI\u002FCD Pipeline\n\nGitHub Actions workflow:\n\n```yaml\nname: Verify Archive Integrity\non: [push, pull_request]\n\njobs:\n  verify:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v3\n      - name: Install AIWG\n        run: npm install -g aiwg\n      - name: Verify archive\n        run: aiwg verify-archive media\u002Farchives\u002Fpodcast --verify\n```\n\n### Backup Verification\n\nVerify backup integrity after rsync:\n\n```bash\n#!\u002Fbin\u002Fbash\n# Backup and verify script\n\nSOURCE=\"\u002Fmedia\u002Fsource\u002Fpodcast\"\nDEST=\"\u002Fmedia\u002Fbackup\u002Fpodcast\"\n\n# Sync files\nrsync -av --delete \"$SOURCE\u002F\" \"$DEST\u002F\"\n\n# Verify destination\ncd \"$DEST\"\nif aiwg verify-archive . --verify --quiet; then\n  echo \"✓ Backup verified successfully\"\nelse\n  echo \"✗ Backup verification failed\" >&2\n  exit 1\nfi\n```\n\n## References\n\n- @$AIWG_ROOT\u002Fagentic\u002Fcode\u002Faddons\u002Faiwg-utils\u002Frules\u002Fhuman-authorization.md — Seek explicit authorization before regenerating checksums (overwrites existing CHECKSUMS.sha256)\n- @$AIWG_ROOT\u002Fagentic\u002Fcode\u002Fframeworks\u002Fmedia-curator\u002Fskills\u002Facquire\u002FSKILL.md — Acquisition skill that invokes integrity verification via --verify-after flag\n- @$AIWG_ROOT\u002Fagentic\u002Fcode\u002Fframeworks\u002Fmedia-curator\u002Fskills\u002Fprovenance-tracking\u002FSKILL.md — Provenance tracking that records fixity events alongside checksums\n- @$AIWG_ROOT\u002Fagentic\u002Fcode\u002Fframeworks\u002Fmedia-curator\u002Fskills\u002Fverify-archive\u002FSKILL.md — High-level verify-archive skill that uses these integrity patterns\n",{"name":5,"category":39,"namespace":40,"platforms":41,"description":7},"media-curator","aiwg",[42],"all","main","6754967c344ccb087a8de06972f55a41067b291b","agentic\u002Fcode\u002Fframeworks\u002Fmedia-curator\u002Fskills\u002Fintegrity-verification",36,"https:\u002F\u002Fgithub.com\u002Fjmagly\u002Faiwg","https:\u002F\u002Faiwg.io","https:\u002F\u002Fgithub.com\u002Fjmagly","https:\u002F\u002Fintegrolabs.io","ml\u002Fai, industrial automation, safety\u002Fsecurity, ssi\r\n\r\nmagly.net\r\nintegrolabs.io\r\naiwg.io\r\nfortemi.com\r\npagenary.com\r\nbytecask.com","2026-11-12 00:33:10",{"source":8,"skillName":5,"commands":54,"prompt":64,"zipAvailable":65},[55,58,61],{"tool":56,"command":57},"npx","npx skills add jmagly\u002Faiwg --skill integrity-verification",{"tool":59,"command":60},"bunx","bunx skills add jmagly\u002Faiwg --skill integrity-verification",{"tool":62,"command":63},"pnpm","pnpm dlx skills add jmagly\u002Faiwg --skill integrity-verification","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fjmagly\u002Faiwg\u002Fblob\u002Fmain\u002Fagentic\u002Fcode\u002Fframeworks\u002Fmedia-curator\u002Fskills\u002Fintegrity-verification\u002FSKILL.md",true,[67],{"path":68,"resourceType":69,"resourceTypeDesc":70,"sizeBytes":71,"sourceHtmlUrl":72},"tools.sdn","OTHER","其他",758,"https:\u002F\u002Fgithub.com\u002Formastes\u002Fsimple\u002Fblob\u002Fmain\u002Fexamples\u002F05_stdlib\u002Fspipe\u002Fdoc\u002F00_llm_process\u002Fskill_command\u002Fskills\u002Fpipe\u002Fverify\u002Fbug_review\u002Ftools.sdn",[74,101,125,131,138,152],{"skillNo":75,"name":76,"nameZh":6,"description":77,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":78,"categories":79,"keywords":81,"publishedAt":34},"01M70QA0BSYJ49EES9V4RE8QH1","host-hardening","Read-only system hardening baseline and plan-first host hardening recommendations for SSH, Docker bind addresses, firewall persistence, datastores, exporters and audit retention.","https:\u002F\u002Fgithub.com\u002Fjmagly\u002Faiwg\u002Fblob\u002Fmain\u002Fagentic\u002Fcode\u002Fplugins\u002Fsecurity-engineering\u002Fskills\u002Fhost-hardening\u002FSKILL.md",[80],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[82,83,84,85,86,87,88,89,90,24,91,92,93,94,95,96,97,98,99,100],"host","host hardening","hardening","read","re","recommendations","remediation","plan","port","Bash","access","only","retention","audit","never","firewall","bind","secrets","request",{"skillNo":102,"name":103,"nameZh":6,"description":104,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":105,"categories":106,"keywords":111,"publishedAt":34},"01M70PNT2Z4HMZPRBTAF6073NN","exposure-analysis","Read-only firewall analysis and effective host exposure reconstruction for Docker published ports, UFW bypass, stale rules, CDN scope, IPv6 asymmetry and external probe allowlists.","https:\u002F\u002Fgithub.com\u002Fjmagly\u002Faiwg\u002Fblob\u002Fmain\u002Fagentic\u002Fcode\u002Fplugins\u002Fforensics\u002Fskills\u002Fexposure-analysis\u002FSKILL.md",[107,110],{"categoryNo":108,"categoryName":109,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000011","运维与部署",{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[112,113,114,85,115,90,116,117,91,118,82,119,93,120,121,96,97,122,123,124],"exposure analysis","analysis","unknown","credentials","collection","ufw","ports","internet","local","scope","reconstruction","operator","write",{"skillNo":126,"name":76,"nameZh":6,"description":77,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":127,"categories":128,"keywords":130,"publishedAt":34},"01M70P8QATMPKA78E4FT5D2TNA","https:\u002F\u002Fgithub.com\u002Fjmagly\u002Faiwg\u002Fblob\u002Fmain\u002Fagentic\u002Fcode\u002Fframeworks\u002Fsecurity-engineering\u002Fskills\u002Fhost-hardening\u002FSKILL.md",[129],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[84,82,83,92,85,100,88,87,95,89,90,24,91,99,93,94,86,96,97,98],{"skillNo":132,"name":103,"nameZh":6,"description":104,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":133,"categories":134,"keywords":137,"publishedAt":34},"01M70NMPVJ5H0JH131P60FW4R8","https:\u002F\u002Fgithub.com\u002Fjmagly\u002Faiwg\u002Fblob\u002Fmain\u002Fagentic\u002Fcode\u002Fframeworks\u002Fforensics-complete\u002Fskills\u002Fexposure-analysis\u002FSKILL.md",[135,136],{"categoryNo":108,"categoryName":109,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[113,112,96,115,90,116,91,114,82,119,93,120,121,85,97,118,117,122,123,124],{"skillNo":139,"name":140,"nameZh":6,"description":141,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":142,"categories":143,"keywords":145,"publishedAt":34},"01M6CB4DDR0B4NNCFK7ZK7449H","fixture-skill","Exercise rule delivery.","https:\u002F\u002Fgithub.com\u002Fjmagly\u002Faiwg\u002Fblob\u002Fmain\u002Ftest\u002Ffixtures\u002Frule-delivery\u002Fskills\u002Ffixture-skill\u002FSKILL.md",[144],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[146,147,148,149,150,151],"fixture skill","fixture","rule","delivery","true","exercise",{"skillNo":153,"name":154,"nameZh":6,"description":155,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":156,"categories":157,"keywords":159,"publishedAt":34},"01M6CB4AVK1W76MFMPP0JP32CJ","pi-local","Pi-local duplicate-precedence fixture.","https:\u002F\u002Fgithub.com\u002Fjmagly\u002Faiwg\u002Fblob\u002Fmain\u002Ftest\u002Ffixtures\u002Fproviders\u002Fpi\u002Fproject\u002F.pi\u002Fskills\u002Fpi-local\u002FSKILL.md",[158],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[160,161,120,162,147],"pi","pi local","duplicate"]