Guard Mail Move
Destination-folder allowlist validator for b.mail.agent.move. Refuses moves to system folders the actor doesn't have admin scope for, refuses cross-account moves (fromFolder and toFolder must belong to the same agent context), and refuses path-traversal-shaped folder names (.. / leading . / NUL / bidi).
System folders the framework treats specially:
- **INBOX / Sent / Drafts**: always writable by the owner; no admin scope required. - **Junk / Trash**: always writable (Junk is the default Sieve junk destination; Trash is the soft-delete target). - **Archive**: always writable. - any operator-created folder: writable when in the actor's allowed-folders list (per the operator's RBAC) OR when the actor has mailScope: "admin".
The guard does NOT touch the underlying mail-store; that composition lives in b.mail.agent.move. The guard validates the SHAPE of the move call.
b.guardMailMove.validate(move, opts?) #
{
profile: "strict" | "balanced" | "permissive",
posture: "hipaa" | "pci-dss" | "gdpr" | "soc2",
}
Validate a { actor, fromFolder, toFolder, objectIds } shape.
b.guardMailMove.validate({
actor: { id: "u1", mailScope: "user" },
fromFolder: "INBOX",
toFolder: "Archive",
objectIds: ["abc123"],
});
b.guardMailMove.compliancePosture(name) #
Return the effective profile NAME for a compliance posture, or null for a name this parser does not map. Unlike the content-guard variant this returns the resolved profile string (every line-protocol parser composes gateContract.ALL_STRICT_POSTURES, so "hipaa" / "pci-dss" / "gdpr" / "soc2" all resolve to "strict") and never throws — the parser shape carries no overlay-clone, no buildProfile, and no loadRulePack. Wired by gateContract.defineParser.
b.guardMailMove.compliancePosture("hipaa"); // → "strict"
b.guardMailMove.compliancePosture("not-a-regime"); // → null
Last updated 2026-08-08T16:39:49.652Z by seeder.