[{"data":1,"prerenderedAt":559},["ShallowReactive",2],{"page-\u002Fv1\u002Fcore\u002Fcross-module-acl":3},{"id":4,"title":5,"body":6,"description":552,"extension":553,"meta":554,"navigation":131,"path":555,"seo":556,"stem":557,"__hash__":558},"content\u002Fv1\u002Fcore\u002Fcross-module-acl.md","Cross-module ACL",{"type":7,"value":8,"toc":543},"minimark",[9,14,26,49,62,67,173,247,257,261,381,386,389,402,406,414,418,443,452,456,529,539],[10,11,13],"h1",{"id":12},"cross-module-acl-sync","Cross-module ACL (sync)",[15,16,17,21,22,25],"p",{},[18,19,20],"strong",{},"Purpose:"," when a Use Case needs ",[18,23,24],{},"another module’s answer in the same request",".",[15,27,28,31,32,36,37,40,41,44,45,48],{},[18,29,30],{},"Illustrative example:"," Ordering checks stock via ",[33,34,35],"code",{},"WarehouseAvailabilityPortInterface"," → ",[33,38,39],{},"WarehouseAvailabilityAclAdapter"," → thin ",[33,42,43],{},"WarehouseAvailabilityModuleInterface"," (or a small ",[33,46,47],{},"WarehouseModuleInterface",").",[15,50,51,52,57,58,25],{},"Failure \u002F transaction rules: ",[53,54,56],"a",{"href":55},"\u002Fv1\u002Fcore\u002Ftransactions-and-failures","Transactions and failures",". Façade thinness: ",[53,59,61],{"href":60},"\u002Fv1\u002Fcore\u002Fcross-module-contracts","Cross-module contracts",[63,64,66],"h2",{"id":65},"two-different-ports","Two different ports",[68,69,74],"pre",{"className":70,"code":71,"language":72,"meta":73,"style":73},"language-mermaid shiki shiki-themes github-light github-dark","flowchart LR\n    subgraph Consumer[\"Consumer — Ordering\"]\n        UC[Use Case]\n        LP[\"Local port\u003Cbr\u002F>WarehouseAvailabilityPortInterface\"]\n        AD[\"ACL adapter\"]\n        UC -->|\"Ordering language\"| LP\n        LP -.bind.-> AD\n    end\n\n    subgraph Provider[\"Provider — Warehouse\"]\n        MI[\"Thin outbound façade\u003Cbr\u002F>WarehouseAvailabilityModuleInterface\"]\n        IMP[Warehouse engine]\n        MI --> IMP\n    end\n\n    AD -->|\"maps DTOs; only Infra imports Warehouse\"| MI\n","mermaid","",[33,75,76,84,90,96,102,108,114,120,126,133,139,145,151,157,162,167],{"__ignoreMap":73},[77,78,81],"span",{"class":79,"line":80},"line",1,[77,82,83],{},"flowchart LR\n",[77,85,87],{"class":79,"line":86},2,[77,88,89],{},"    subgraph Consumer[\"Consumer — Ordering\"]\n",[77,91,93],{"class":79,"line":92},3,[77,94,95],{},"        UC[Use Case]\n",[77,97,99],{"class":79,"line":98},4,[77,100,101],{},"        LP[\"Local port\u003Cbr\u002F>WarehouseAvailabilityPortInterface\"]\n",[77,103,105],{"class":79,"line":104},5,[77,106,107],{},"        AD[\"ACL adapter\"]\n",[77,109,111],{"class":79,"line":110},6,[77,112,113],{},"        UC -->|\"Ordering language\"| LP\n",[77,115,117],{"class":79,"line":116},7,[77,118,119],{},"        LP -.bind.-> AD\n",[77,121,123],{"class":79,"line":122},8,[77,124,125],{},"    end\n",[77,127,129],{"class":79,"line":128},9,[77,130,132],{"emptyLinePlaceholder":131},true,"\n",[77,134,136],{"class":79,"line":135},10,[77,137,138],{},"    subgraph Provider[\"Provider — Warehouse\"]\n",[77,140,142],{"class":79,"line":141},11,[77,143,144],{},"        MI[\"Thin outbound façade\u003Cbr\u002F>WarehouseAvailabilityModuleInterface\"]\n",[77,146,148],{"class":79,"line":147},12,[77,149,150],{},"        IMP[Warehouse engine]\n",[77,152,154],{"class":79,"line":153},13,[77,155,156],{},"        MI --> IMP\n",[77,158,160],{"class":79,"line":159},14,[77,161,125],{},[77,163,165],{"class":79,"line":164},15,[77,166,132],{"emptyLinePlaceholder":131},[77,168,170],{"class":79,"line":169},16,[77,171,172],{},"    AD -->|\"maps DTOs; only Infra imports Warehouse\"| MI\n",[174,175,176,195],"table",{},[177,178,179],"thead",{},[180,181,182,186,189,192],"tr",{},[183,184,185],"th",{},"Port",[183,187,188],{},"Name pattern",[183,190,191],{},"Owned by",[183,193,194],{},"Injected into",[196,197,198,219],"tbody",{},[180,199,200,206,211,216],{},[201,202,203],"td",{},[18,204,205],{},"Local (inbound need)",[201,207,208],{},[33,209,210],{},"{Need}PortInterface",[201,212,213],{},[18,214,215],{},"Consumer",[201,217,218],{},"Consumer Use Cases",[180,220,221,226,235,240],{},[201,222,223],{},[18,224,225],{},"Outbound façade",[201,227,228,231,232],{},[33,229,230],{},"{This}ModuleInterface"," or capability-sized ",[33,233,234],{},"*ModuleInterface",[201,236,237],{},[18,238,239],{},"Provider",[201,241,242,243,246],{},"Peer ",[18,244,245],{},"ACL adapters only"," — never peer Use Cases",[15,248,249,250,253,254,48],{},"Keep façades ",[18,251,252],{},"thin"," and HTTP-mappable. Split when the surface grows (",[53,255,256],{"href":60},"contracts",[63,258,260],{"id":259},"sequence-place-order-checks-availability","Sequence — place order checks availability",[68,262,264],{"className":70,"code":263,"language":72,"meta":73,"style":73},"sequenceDiagram\n    autonumber\n    participant Ctrl as Ordering Controller\n    participant UC as PlaceOrderUseCase\n    participant LP as WarehouseAvailabilityPortInterface\n    participant ACL as WarehouseAvailabilityAclAdapter\n    participant MI as WarehouseAvailabilityModuleInterface\n    participant Eng as Warehouse internals\n\n    Ctrl->>UC: PlaceOrderDTO\n    Note over UC: Prefer ACL validate before local commit\n    UC->>LP: isAvailable(itemCode, qty)\n    LP->>ACL: bound implementation\n    ACL->>ACL: map → provider request shape\n    ACL->>MI: isStockAvailable(…)\n    MI->>Eng: check stock\n    Eng-->>MI: availability result\n    MI-->>ACL: peer result\n    ACL->>ACL: map → Ordering-local result\n    ACL-->>LP: local result\n    LP-->>UC: available?\n    UC-->>Ctrl: OrderEntity \u002F failure\n",[33,265,266,271,276,281,286,291,296,301,306,310,315,320,325,330,335,340,345,351,357,363,369,375],{"__ignoreMap":73},[77,267,268],{"class":79,"line":80},[77,269,270],{},"sequenceDiagram\n",[77,272,273],{"class":79,"line":86},[77,274,275],{},"    autonumber\n",[77,277,278],{"class":79,"line":92},[77,279,280],{},"    participant Ctrl as Ordering Controller\n",[77,282,283],{"class":79,"line":98},[77,284,285],{},"    participant UC as PlaceOrderUseCase\n",[77,287,288],{"class":79,"line":104},[77,289,290],{},"    participant LP as WarehouseAvailabilityPortInterface\n",[77,292,293],{"class":79,"line":110},[77,294,295],{},"    participant ACL as WarehouseAvailabilityAclAdapter\n",[77,297,298],{"class":79,"line":116},[77,299,300],{},"    participant MI as WarehouseAvailabilityModuleInterface\n",[77,302,303],{"class":79,"line":122},[77,304,305],{},"    participant Eng as Warehouse internals\n",[77,307,308],{"class":79,"line":128},[77,309,132],{"emptyLinePlaceholder":131},[77,311,312],{"class":79,"line":135},[77,313,314],{},"    Ctrl->>UC: PlaceOrderDTO\n",[77,316,317],{"class":79,"line":141},[77,318,319],{},"    Note over UC: Prefer ACL validate before local commit\n",[77,321,322],{"class":79,"line":147},[77,323,324],{},"    UC->>LP: isAvailable(itemCode, qty)\n",[77,326,327],{"class":79,"line":153},[77,328,329],{},"    LP->>ACL: bound implementation\n",[77,331,332],{"class":79,"line":159},[77,333,334],{},"    ACL->>ACL: map → provider request shape\n",[77,336,337],{"class":79,"line":164},[77,338,339],{},"    ACL->>MI: isStockAvailable(…)\n",[77,341,342],{"class":79,"line":169},[77,343,344],{},"    MI->>Eng: check stock\n",[77,346,348],{"class":79,"line":347},17,[77,349,350],{},"    Eng-->>MI: availability result\n",[77,352,354],{"class":79,"line":353},18,[77,355,356],{},"    MI-->>ACL: peer result\n",[77,358,360],{"class":79,"line":359},19,[77,361,362],{},"    ACL->>ACL: map → Ordering-local result\n",[77,364,366],{"class":79,"line":365},20,[77,367,368],{},"    ACL-->>LP: local result\n",[77,370,372],{"class":79,"line":371},21,[77,373,374],{},"    LP-->>UC: available?\n",[77,376,378],{"class":79,"line":377},22,[77,379,380],{},"    UC-->>Ctrl: OrderEntity \u002F failure\n",[382,383,385],"h3",{"id":384},"why-mapping-exists","Why mapping exists",[15,387,388],{},"Warehouse speaks Warehouse language (location codes, reservation statuses). Ordering Application\u002FDomain must not import those types. The adapter converts:",[390,391,392,396,399],"ul",{},[393,394,395],"li",{},"Peer codes → values Ordering stores on lines",[393,397,398],{},"Availability flags → booleans or local result DTOs",[393,400,401],{},"Failures → exceptions \u002F results the Ordering Use Case can apply policy to",[63,403,405],{"id":404},"folder-layout-both-sides","Folder layout (both sides)",[68,407,412],{"className":408,"code":410,"language":411,"meta":73},[409],"language-text","# Consumer (Ordering)\nDomain\u002FPorts\u002FAcl\u002FWarehouseAvailabilityPortInterface.php\nInfrastructure\u002FExternalServices\u002FWarehouseAvailabilityAclAdapter.php\nApplication\u002FProviders\u002F…   # bind local port → adapter\n\n# Provider (Warehouse)\nDomain\u002FPorts\u002FModule\u002FWarehouseAvailabilityModuleInterface.php\nApplication\u002FProviders\u002F…   # bind ModuleInterface → implementation\n","text",[33,413,410],{"__ignoreMap":73},[63,415,417],{"id":416},"replaceability-test","Replaceability test",[68,419,421],{"className":70,"code":420,"language":72,"meta":73,"style":73},"flowchart TD\n    A[Today: ACL adapter calls Warehouse façade in-process] --> B{Warehouse extracted to HTTP?}\n    B -->|Yes| C[Rewrite only the ACL adapter to an HTTP client]\n    C --> D[Ordering Use Cases + local port unchanged]\n",[33,422,423,428,433,438],{"__ignoreMap":73},[77,424,425],{"class":79,"line":80},[77,426,427],{},"flowchart TD\n",[77,429,430],{"class":79,"line":86},[77,431,432],{},"    A[Today: ACL adapter calls Warehouse façade in-process] --> B{Warehouse extracted to HTTP?}\n",[77,434,435],{"class":79,"line":92},[77,436,437],{},"    B -->|Yes| C[Rewrite only the ACL adapter to an HTTP client]\n",[77,439,440],{"class":79,"line":98},[77,441,442],{},"    C --> D[Ordering Use Cases + local port unchanged]\n",[15,444,445,446,448,449,25],{},"If Ordering Use Cases already type-hint the Warehouse ",[33,447,234],{},", the test ",[18,450,451],{},"fails",[63,453,455],{"id":454},"anti-patterns","Anti-patterns",[174,457,458,468],{},[177,459,460],{},[180,461,462,465],{},[183,463,464],{},"Anti-pattern",[183,466,467],{},"Fix",[196,469,470,481,492,503,511,519],{},[180,471,472,478],{},[201,473,474,477],{},[33,475,476],{},"use …Warehouse\\…"," inside Ordering Use Case",[201,479,480],{},"Local port + ACL",[180,482,483,489],{},[201,484,485,486,488],{},"Injecting peer ",[33,487,234],{}," into Ordering Use Case",[201,490,491],{},"Same",[180,493,494,500],{},[201,495,496,497,499],{},"God ",[33,498,47],{}," with dozens of unrelated methods",[201,501,502],{},"Split capability façades",[180,504,505,508],{},[201,506,507],{},"Conversion logic in Use Case with foreign enums",[201,509,510],{},"Keep conversion in adapter",[180,512,513,516],{},[201,514,515],{},"Shared business enum in Shared kernel “for reuse”",[201,517,518],{},"Never Shared for business concepts",[180,520,521,524],{},[201,522,523],{},"Peer write + local commit with no failure story",[201,525,526],{},[53,527,528],{"href":55},"Transactions",[15,530,531,532,536,537,25],{},"Next: ",[53,533,535],{"href":534},"\u002Fv1\u002Fcore\u002Fcross-module-events","cross-module events"," · ",[53,538,256],{"href":60},[540,541,542],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":73,"searchDepth":86,"depth":86,"links":544},[545,546,549,550,551],{"id":65,"depth":86,"text":66},{"id":259,"depth":86,"text":260,"children":547},[548],{"id":384,"depth":92,"text":385},{"id":404,"depth":86,"text":405},{"id":416,"depth":86,"text":417},{"id":454,"depth":86,"text":455},"Sync Anti-Corruption Layer — local port plus adapter to a thin peer ModuleInterface.","md",{},"\u002Fv1\u002Fcore\u002Fcross-module-acl",{"title":5,"description":552},"v1\u002Fcore\u002Fcross-module-acl","CHuF21-UJ0CdG9EeM8m1mS_b3XJ81mKZXsVwOnRWdUM",1786241411877]