[{"data":1,"prerenderedAt":372},["ShallowReactive",2],{"page-\u002Fv1\u002Fcore\u002Fcross-module-contracts":3},{"id":4,"title":5,"body":6,"description":365,"extension":366,"meta":367,"navigation":315,"path":368,"seo":369,"stem":370,"__hash__":371},"content\u002Fv1\u002Fcore\u002Fcross-module-contracts.md","Cross-module contracts",{"type":7,"value":8,"toc":357},"minimark",[9,13,27,49,57,64,140,150,160,164,167,249,258,270,274,300,304,347],[10,11,5],"h1",{"id":12},"cross-module-contracts",[14,15,16,17,21,22,26],"p",{},"ACL ports, ",[18,19,20],"code",{},"*ModuleInterface"," façades, and Domain Events are ",[23,24,25],"strong",{},"published contracts",". Treat them like a public API — even inside a modular monolith.",[14,28,29,30,35,36,35,40,35,44,48],{},"Related: ",[31,32,34],"a",{"href":33},"\u002Fv1\u002Fcore\u002Fcross-module-acl","ACL"," · ",[31,37,39],{"href":38},"\u002Fv1\u002Fcore\u002Fcross-module-events","Events",[31,41,43],{"href":42},"\u002Fv1\u002Fcore\u002Fevent-delivery","Event delivery",[31,45,47],{"href":46},"\u002Fv1\u002Fcore\u002Fversioning","Core versioning",".",[50,51,53,54,56],"h2",{"id":52},"thin-façades-moduleinterface","Thin façades (",[18,55,20],{},")",[14,58,59,60,63],{},"A provider’s outbound façade is ",[23,61,62],{},"not"," “every method the module has.”",[65,66,67,80],"table",{},[68,69,70],"thead",{},[71,72,73,77],"tr",{},[74,75,76],"th",{},"Rule",[74,78,79],{},"Detail",[81,82,83,106,120,130],"tbody",{},[71,84,85,91],{},[86,87,88],"td",{},[23,89,90],{},"Capability-sized",[86,92,93,94,97,98,101,102,105],{},"Prefer ",[18,95,96],{},"WarehouseAvailabilityModuleInterface"," (or a focused ",[18,99,100],{},"WarehouseModuleInterface"," with a ",[23,103,104],{},"small"," surface) over one god interface",[71,107,108,113],{},[86,109,110],{},[23,111,112],{},"Stable language",[86,114,115,116,119],{},"Methods and DTOs speak the provider’s ",[23,117,118],{},"public"," vocabulary — not ORM models, not internal Entities",[71,121,122,127],{},[86,123,124],{},[23,125,126],{},"Peer ACL only",[86,128,129],{},"Only peer Infrastructure ACL adapters may depend on it — never peer Use Cases",[71,131,132,137],{},[86,133,134],{},[23,135,136],{},"HTTP-ready",[86,138,139],{},"Each method should map cleanly to a future HTTP operation",[141,142,148],"pre",{"className":143,"code":145,"language":146,"meta":147},[144],"language-text","# Prefer focused façades as the surface grows\nDomain\u002FPorts\u002FModule\u002F\n  WarehouseAvailabilityModuleInterface.php   # sync reads peers need\n  WarehouseReservationModuleInterface.php    # sync writes peers need\n","text","",[18,149,145],{"__ignoreMap":147},[14,151,152,153,155,156,159],{},"If you already ship a single ",[18,154,100],{},", keep it ",[23,157,158],{},"thin"," and split when a second capability appears — same promote spirit as Shared.",[50,161,163],{"id":162},"event-schema-as-a-contract","Event schema as a contract",[14,165,166],{},"Published Domain Events are versioned messages:",[65,168,169,179],{},[68,170,171],{},[71,172,173,176],{},[74,174,175],{},"Field",[74,177,178],{},"Guidance",[81,180,181,195,216,229,239],{},[71,182,183,188],{},[86,184,185],{},[23,186,187],{},"Identity",[86,189,190,191,194],{},"Stable event name + explicit ",[18,192,193],{},"schemaVersion"," (int or semver string on the payload)",[71,196,197,202],{},[86,198,199],{},[23,200,201],{},"Correlation",[86,203,204,207,208,211,212,215],{},[18,205,206],{},"eventId"," (unique) + ",[18,209,210],{},"correlationId"," \u002F ",[18,213,214],{},"causationId"," when chaining",[71,217,218,223],{},[86,219,220],{},[23,221,222],{},"Payload",[86,224,225,226],{},"Primitives and small value shapes consumers need for the ",[23,227,228],{},"happy path",[71,230,231,236],{},[86,232,233],{},[23,234,235],{},"PII",[86,237,238],{},"Prefer codes \u002F opaque ids over full personal data on the bus",[71,240,241,246],{},[86,242,243],{},[23,244,245],{},"Evolution",[86,247,248],{},"Additive fields preferred; breaking changes → new event type or major schema bump",[14,250,251,254,255,48],{},[23,252,253],{},"Rich payload (normative for happy path):"," publish enough for the consumer inbound Use Case to run ",[23,256,257],{},"without calling back into the publisher’s Domain",[14,259,260,263,264,267,268,48],{},[23,261,262],{},"Allowed exception (query after the fact):"," a separate ",[23,265,266],{},"consumer-owned"," sync port for corrections, admin rebuilds, or missing optional fields — never as the default “thin ID + re-fetch Domain” pattern. See ",[31,269,43],{"href":42},[50,271,273],{"id":272},"acl-requestresponse-dtos","ACL request\u002Fresponse DTOs",[275,276,277,285,291,294],"ul",{},[278,279,280,281,284],"li",{},"Consumer local port DTOs stay in the ",[23,282,283],{},"consumer"," language.",[278,286,287,288,284],{},"Provider façade DTOs stay in the ",[23,289,290],{},"provider",[278,292,293],{},"Mapping lives only in the ACL adapter.",[278,295,296,297,48],{},"Evolve façades additively; breaking façade changes follow ",[31,298,299],{"href":46},"versioning",[50,301,303],{"id":302},"contract-checklist-before-merge","Contract checklist before merge",[275,305,308,318,329,335,341],{"className":306},[307],"contains-task-list",[278,309,312,317],{"className":310},[311],"task-list-item",[313,314],"input",{"disabled":315,"type":316},true,"checkbox"," Façade methods are few and HTTP-mappable",[278,319,321,323,324,326,327,56],{"className":320},[311],[313,322],{"disabled":315,"type":316}," Event carries ",[18,325,206],{}," + enough happy-path fields (+ ",[18,328,193],{},[278,330,332,334],{"className":331},[311],[313,333],{"disabled":315,"type":316}," No ORM models on the wire",[278,336,338,340],{"className":337},[311],[313,339],{"disabled":315,"type":316}," Consumer Application\u002FDomain still compile if the peer becomes HTTP",[278,342,344,346],{"className":343},[311],[313,345],{"disabled":315,"type":316}," Breaking change documented (major Core \u002F adapter note, or new event type)",[14,348,349,350,35,354,48],{},"Next: ",[31,351,353],{"href":352},"\u002Fv1\u002Fcore\u002Ftransactions-and-failures","transactions & failures",[31,355,356],{"href":42},"event delivery",{"title":147,"searchDepth":358,"depth":358,"links":359},2,[360,362,363,364],{"id":52,"depth":358,"text":361},"Thin façades (*ModuleInterface)",{"id":162,"depth":358,"text":163},{"id":272,"depth":358,"text":273},{"id":302,"depth":358,"text":303},"Thin façades, event schemas, ACL DTO evolution, and SemVer for Core and published contracts.","md",{},"\u002Fv1\u002Fcore\u002Fcross-module-contracts",{"title":5,"description":365},"v1\u002Fcore\u002Fcross-module-contracts","ja7nz83XW6Sq8Xh3QfIxvGoB3SLXdPYwysDKsj7ytsE",1786241412057]