TenantAtlas/specs/120-secret-redaction-integrity/data-model.md
ahmido cd811cff4f Spec 120: harden secret redaction integrity (#146)
## Summary
- replace broad substring-based masking with a shared exact/path-based secret classifier and workspace-scoped fingerprint hashing
- persist protected snapshot metadata on `policy_versions` and keep secret-only changes visible in compare, drift, restore, review, verification, and ops surfaces
- add Spec 120 artifacts, audit documentation, and focused Pest regression coverage for snapshot, audit, verification, review-pack, and notification behavior

## Validation
- `vendor/bin/sail artisan test --compact tests/Feature/Intune/PolicySnapshotRedactionTest.php tests/Feature/Intune/PolicySnapshotFingerprintIsolationTest.php tests/Feature/ReviewPack/ReviewPackRedactionIntegrityTest.php tests/Feature/OpsUx/OperationRunNotificationRedactionTest.php tests/Feature/Verification/VerificationReportViewerDbOnlyTest.php`
- `vendor/bin/sail bin pint --dirty --format agent`

## Spec / checklist status
| Checklist | Total | Completed | Incomplete | Status |
|-----------|-------|-----------|------------|--------|
| requirements.md | 16 | 16 | 0 | ✓ PASS |

- `tasks.md`: T001-T032 complete
- `tasks.md`: T033 manual quickstart validation is still open and noted for follow-up

## Filament / platform notes
- Livewire v4 compliance is unchanged
- no panel provider changes; `bootstrap/providers.php` remains the registration location
- no new globally searchable resources were introduced, so global search requirements are unchanged
- no new destructive Filament actions were added
- no new Filament assets were added; no `filament:assets` deployment change is required

## Testing coverage touched
- snapshot persistence and fingerprint isolation
- compare/drift protected-change evidence
- audit, verification, review-pack, ops-failure, and notification sanitization
- viewer/read-only Filament presentation updates

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #146
2026-03-07 16:43:01 +00:00

3.3 KiB

Data Model — Secret Redaction Hardening & Snapshot Data Integrity (Spec 120)

This spec extends existing persistence and introduces no new base tables.

Entities

1) PolicyVersion (existing: App\Models\PolicyVersion)

Tenant-owned immutable policy evidence.

New / changed fields

  • workspace_id (existing required scope field for newer rows; used for workspace-scoped fingerprint derivation)
  • snapshot (JSON/array): protected snapshot payload with non-secret values preserved and secret values replaced by [REDACTED]
  • assignments (JSON/array|null): protected assignment payload under the same contract
  • scope_tags (JSON/array|null): protected scope-tag payload under the same contract
  • secret_fingerprints (new JSON/array):
    • shape:
      • snapshot: object keyed by RFC 6901 JSON Pointer
      • assignments: object keyed by RFC 6901 JSON Pointer
      • scope_tags: object keyed by RFC 6901 JSON Pointer
    • values: lowercase HMAC-SHA256 hex digests
  • redaction_version (new integer contract marker for compliant writes):
    • 1 = protected under the Spec 120 classifier contract

Relationships

  • Belongs to Tenant
  • Belongs to Policy
  • Belongs to OperationRun (nullable)
  • Belongs to BaselineProfile (nullable)

Validation / invariants

  • New writes must set redaction_version = 1.
  • If a protected value is persisted as [REDACTED], a matching digest entry must exist in secret_fingerprints for the same source bucket + JSON Pointer.
  • If redaction_version = 1, secret_fingerprints may be empty only when no protected fields were classified.
  • Version identity for dedupe must consider both the protected payload and secret_fingerprints so secret-only changes create a new version.

2) ProtectedSnapshotResult (new transient service DTO)

The canonical output of the new protection pipeline before persistence.

Fields

  • snapshot (array)
  • assignments (array|null)
  • scope_tags (array|null)
  • secret_fingerprints (array{snapshot: array<string, string>, assignments: array<string, string>, scope_tags: array<string, string>})
  • redaction_version (int)
  • protected_paths_count (int)

Validation / invariants

  • Must be deterministic for the same input payload, workspace, and classifier version.
  • Must preserve original object/list shape.
  • Must never include raw secret values in any field.

3) SecretClassificationRule (new application-level value object)

Non-persisted classifier rule consumed by snapshot, audit, verification, and ops sanitizers.

Fields

  • source_bucket (snapshot|assignments|scope_tags|audit|verification|ops_failure)
  • json_pointer (string|null)
  • field_name (string)
  • decision (protected|visible)
  • reason (exact_key, exact_path, message_pattern, default_visible)

Validation / invariants

  • Exact-path rules take precedence over exact-key rules.
  • Unknown fields default to visible unless a protected rule matches.
  • Message-level sanitizers may protect by exact token pattern, but must not broad-match harmless phrases.

Derived / Computed Values

  • protection_digest (implementation detail): composite hash of protected payload + secret_fingerprints, used for version dedupe.
  • protected_change_detected (derived): true when compare/drift sees a fingerprint difference for the same protected path even though the visible payload remains [REDACTED].