88 lines
5.0 KiB
Markdown
88 lines
5.0 KiB
Markdown
# Campaign Access Explanation Coverage
|
|
|
|
Campaign access explanations are resource-specific evidence. They inherit the
|
|
parent Campaign decision only where the child has no independent grant model,
|
|
and they must identify that inheritance explicitly.
|
|
|
|
## Implemented
|
|
|
|
- Campaign
|
|
- Campaign version
|
|
- Campaign delivery job / built message
|
|
- Computed Campaign report, identified by Campaign, version, and report kind
|
|
- Recipient row, identified by `<version UUID>:<job UUID>`
|
|
- Frozen recipient source snapshot, identified by its Campaign-version UUID
|
|
- Campaign attachment binding and version-bound frozen attachment resolution
|
|
- Persisted validation issue, version-bound review decision, and attachment-policy override
|
|
- SMTP, IMAP append, Postbox, and printable-output attempts
|
|
- Message action, message-action attempt, and job reconciliation decision
|
|
- Campaign share and Core-owned Campaign ownership-transfer record
|
|
- Independently user-owned recipient import mapping profile
|
|
- Saved recipient import execution, identified by `<version UUID>:<import UUID>`
|
|
- Persisted validation, build, execution-snapshot, and review evidence, identified
|
|
by `<version UUID>:<artifact kind>`
|
|
|
|
All persisted child IDs are random UUIDs. Embedded build/review children use a
|
|
version UUID plus a random job UUID, so callers cannot enumerate a recipient
|
|
index or infer an address. A version mismatch is reported as a stale reference.
|
|
Missing and cross-tenant children use the same non-disclosing not-found
|
|
provenance. Explanations never include recipient addresses, source rows,
|
|
filenames, object locators, transport responses, worker claims, target
|
|
snapshots, diagnostic text, or reconciliation notes.
|
|
|
|
## Permission matrix
|
|
|
|
| Evidence | Parent boundary | Further restriction |
|
|
| --- | --- | --- |
|
|
| Recipient row or source snapshot | Campaign read/owner/share | `campaigns:recipient:read` |
|
|
| Attachment binding/resolution, validation, review, override | Campaign read/owner/share | Campaign review and `campaigns:diagnostic:read` |
|
|
| Delivery status | Campaign read/owner/share | `campaigns:report:read` |
|
|
| Transport or worker diagnostics | Campaign read/owner/share | `campaigns:diagnostic:read` |
|
|
| Exported delivery evidence | Campaign read/owner/share | `campaigns:report:export` |
|
|
| Reconciliation decision | Campaign read/owner/share | Campaign reconcile and diagnostic read |
|
|
| Share or ownership transfer | Campaign governance | Campaign share, transfer-participant, group-acceptance, or recovery authority; content access remains a separate decision |
|
|
| Import mapping profile | Independent user owner | `campaigns:recipient:import`; no Campaign share is inherited |
|
|
| Import execution | Campaign read/owner/share | Recipient read and import authority |
|
|
| Persisted protocol artifact | Campaign read/owner/share | Recipient, review, report, diagnostic, or export authority appropriate to the artifact |
|
|
|
|
Postbox, Mail/IMAP, and printable attempts keep bounded Campaign-owned evidence
|
|
after provider acceptance. Their explanation therefore remains available when
|
|
an optional provider module is later disabled. A missing attempt reports only
|
|
the optional owner and `unavailable_or_hidden`; it does not distinguish absence
|
|
from hidden data.
|
|
|
|
## Optional and unsupported owner boundaries
|
|
|
|
Reusable templates and template revisions are independently governed by the
|
|
optional Templates module; Campaign never treats a Campaign share as a template
|
|
grant. Durable export packages are independently governed by the optional
|
|
Reporting module. Asking the Campaign provider to explain either class therefore
|
|
fails closed with `independently_governed_by_optional_module` and
|
|
`unavailable_or_hidden`. The response does not reveal whether the optional
|
|
module is absent, the object does not exist, or the caller cannot see it.
|
|
|
|
Campaign reports generated on demand remain non-persisted, version-bound
|
|
resources. Their explanation names the report kind and its Campaign/version
|
|
parent, and keeps report read, export, and diagnostic permissions distinct.
|
|
|
|
Each child explanation must include:
|
|
|
|
- the child resource identity and current state;
|
|
- the parent Campaign and version where applicable;
|
|
- whether access is inherited, independently granted, or further restricted;
|
|
- effective owner/share/policy provenance;
|
|
- missing-module or unavailable-evidence reasons without leaking the hidden
|
|
object;
|
|
- a stable resource identifier suitable for audit and support links.
|
|
|
|
Delivery attempts, review decisions, reports, and exports can contain more
|
|
sensitive evidence than the Campaign summary. Their read and diagnostic/export
|
|
permissions therefore remain independently enforceable even when the parent
|
|
Campaign is readable.
|
|
|
|
Import explanations include only the stable import identity, source type,
|
|
opaque source identity, source revision, and whether additional provenance was
|
|
recorded. They never return imported rows, filenames, column mappings, or source
|
|
metadata. Mapping-profile explanations expose only non-reversible header
|
|
fingerprints and shape information; headers and mappings remain hidden.
|