Tenant Isolation & Redaction Manifest (FL5)
Purpose: Document how Findings Ledger enforces tenant boundaries and which fields are redacted in deterministic exports.
Isolation controls
- Storage: all ledger, projection, history, and merkle tables are LIST-partitioned by
tenant_id(PostgreSQL). Cross-tenant queries are disallowed at repo level. - Queueing: Merkle batches and projector pipelines are keyed by
(tenant_id, chain_id); no mixing. - Writes: ledger events are written into the tenant of the authenticated principal. The ingest request carries no tenant, the advanced-assurance append refuses a fixture of another tenant before writing, and decisions are recorded in the caller’s tenant, not in one named by the alert id (see the Findings architecture dossier, “Ledger writes are bound to the authenticated tenant”).
- Exports:
/ledger/export/*requiresX-StellaOps-TenantId; service rejects multi-tenant requests. - Hashing: event/projection hashes include
tenant_idas part of canonical envelope, preventing replay across tenants.
Redaction policy
- User-generated content (comments, attachments metadata) is excluded from compact exports and masked in canonical exports per manifest.
- Actor identifiers are truncated to realm (
user:<realm>); emails/PII never emitted. - Evidence bundle references are retained, but inline evidence payloads are not stored in ledger.
Manifest
- Path:
docs/modules/findings/ledger/redaction-manifest.yaml(JSON twin:redaction-manifest.jsonfor offline tooling). - Content: declarative list of fields redacted or truncated for each export shape.
- The manifest is signed in checksum list
docs/modules/findings/ledger/golden-checksums.json; sha256 must match before release.
Applying the manifest
- Canonical exports apply
redact: maskrules only to PII (actorId,comment); compact exports drop (drop: true) the same fields plus verbose rationale arrays. - Log pipelines ensure
event_bodyis never written to logs; only metadata/hashes appear (seeobservability.md).
Validation steps
sha256sum docs/modules/findings/ledger/redaction-manifest.yamlmatchesgolden-checksums.json.- Run
python tools/LedgerReplayHarness/scripts/verify_export.py --input fixtures/golden/findings-canonical.ndjson --schema export.v1.canonical --manifest docs/modules/findings/ledger/redaction-manifest.json(script enforces mask/drop rules offline). - Confirm export responses in staging omit masked fields for the requesting tenant.
