[{"data":1,"prerenderedAt":398},["ShallowReactive",2],{"page-\u002Fv1\u002Fcookbook\u002Fidentity-directory":3},{"id":4,"title":5,"body":6,"description":391,"extension":392,"meta":393,"navigation":199,"path":394,"seo":395,"stem":396,"__hash__":397},"content\u002Fv1\u002Fcookbook\u002Fidentity-directory.md","Identity ↔ Directory",{"type":7,"value":8,"toc":383},"minimark",[9,14,18,63,69,74,125,129,139,143,243,247,258,272,279,283,341,345,371,379],[10,11,13],"h1",{"id":12},"cookbook-identity-directory","Cookbook — Identity ↔ Directory",[15,16,17],"p",{},"Illustrative bounded contexts only. Rename to your domains; do not import product module trees.",[19,20,21,34],"table",{},[22,23,24],"thead",{},[25,26,27,31],"tr",{},[28,29,30],"th",{},"Module",[28,32,33],{},"Owns",[35,36,37,49],"tbody",{},[25,38,39,46],{},[40,41,42],"td",{},[43,44,45],"strong",{},"Identity",[40,47,48],{},"Credentials, sessions\u002Ftokens, authentication challenges, “who is signed in”",[25,50,51,56],{},[40,52,53],{},[43,54,55],{},"Directory",[40,57,58,59,62],{},"Member\u002Forganisation profile, roles ",[43,60,61],{},"as Directory sees them",", eligibility tiers",[15,64,65,68],{},[43,66,67],{},"Design test:"," If Identity is replaced by an external IdP, Directory Application\u002FDomain still compile (Directory talks to a local port \u002F events — not Identity Entities).",[70,71,73],"h2",{"id":72},"bridges-used","Bridges used",[19,75,76,86],{},[22,77,78],{},[25,79,80,83],{},[28,81,82],{},"Need",[28,84,85],{},"Bridge",[35,87,88,100,113],{},[25,89,90,93],{},[40,91,92],{},"Directory must know “subject X is authenticated” for an admin action",[40,94,95,96,99],{},"Sync ACL to Identity ",[43,97,98],{},"or"," host middleware that already resolved a subject code into the Use Case DTO",[25,101,102,105],{},[40,103,104],{},"After signup, Directory creates a member shell",[40,106,107,108,112],{},"Domain Event ",[109,110,111],"code",{},"IdentityUserRegistered"," → Directory translation listener → inbound Use Case",[25,114,115,118],{},[40,116,117],{},"Ordering checks member tier",[40,119,120,121,124],{},"Sync ACL ",[43,122,123],{},"Ordering → Directory"," (Identity not involved)",[70,126,128],{"id":127},"folder-sketch","Folder sketch",[130,131,137],"pre",{"className":132,"code":134,"language":135,"meta":136},[133],"language-text","Identity\u002F\n  Domain\u002F\n    Events\u002FUserRegistered.php          # rich: userId, email hash\u002Fcode, occurredAt, schemaVersion, eventId\n    Ports\u002FModule\u002FIdentityAuthModuleInterface.php   # thin: validate token \u002F resolve subject\n  Application\u002FUseCases\u002FAuth\u002F…\n  Infrastructure\u002F…\n\nDirectory\u002F\n  Domain\u002FPorts\u002FAcl\u002FAuthenticatedSubjectPortInterface.php   # optional if Directory must verify\n  Domain\u002FPorts\u002FModule\u002FDirectoryMemberModuleInterface.php   # thin: getTier(memberCode), …\n  Application\u002FUseCases\u002FMember\u002FProvisionMemberFromRegistrationUseCase.php\n  Infrastructure\u002F\n    ExternalServices\u002F…                 # ACL adapters\n    Messaging\u002FIdentityUserRegisteredTranslationListener.php\n","text","",[109,138,134],{"__ignoreMap":136},[70,140,142],{"id":141},"sequence-register-then-provision","Sequence — register then provision",[130,144,148],{"className":145,"code":146,"language":147,"meta":136,"style":136},"language-mermaid shiki shiki-themes github-light github-dark","sequenceDiagram\n    autonumber\n    participant UI as Identity UI\n    participant RUC as RegisterUserUseCase\n    participant DISP as EventDispatcher\n    participant L as Directory translation listener\n    participant PUC as ProvisionMember…UseCase\n\n    UI->>RUC: RegisterUserDTO\n    RUC->>RUC: persist identity credential aggregate\n    RUC->>DISP: UserRegistered (rich payload)\n    DISP-->>L: deliver (queued)\n    L->>L: map → ProvisionMemberDTO\u003Cbr\u002F>idempotent on eventId\n    L->>PUC: __invoke\n    PUC->>PUC: create Directory member shell\n","mermaid",[109,149,150,158,164,170,176,182,188,194,201,207,213,219,225,231,237],{"__ignoreMap":136},[151,152,155],"span",{"class":153,"line":154},"line",1,[151,156,157],{},"sequenceDiagram\n",[151,159,161],{"class":153,"line":160},2,[151,162,163],{},"    autonumber\n",[151,165,167],{"class":153,"line":166},3,[151,168,169],{},"    participant UI as Identity UI\n",[151,171,173],{"class":153,"line":172},4,[151,174,175],{},"    participant RUC as RegisterUserUseCase\n",[151,177,179],{"class":153,"line":178},5,[151,180,181],{},"    participant DISP as EventDispatcher\n",[151,183,185],{"class":153,"line":184},6,[151,186,187],{},"    participant L as Directory translation listener\n",[151,189,191],{"class":153,"line":190},7,[151,192,193],{},"    participant PUC as ProvisionMember…UseCase\n",[151,195,197],{"class":153,"line":196},8,[151,198,200],{"emptyLinePlaceholder":199},true,"\n",[151,202,204],{"class":153,"line":203},9,[151,205,206],{},"    UI->>RUC: RegisterUserDTO\n",[151,208,210],{"class":153,"line":209},10,[151,211,212],{},"    RUC->>RUC: persist identity credential aggregate\n",[151,214,216],{"class":153,"line":215},11,[151,217,218],{},"    RUC->>DISP: UserRegistered (rich payload)\n",[151,220,222],{"class":153,"line":221},12,[151,223,224],{},"    DISP-->>L: deliver (queued)\n",[151,226,228],{"class":153,"line":227},13,[151,229,230],{},"    L->>L: map → ProvisionMemberDTO\u003Cbr\u002F>idempotent on eventId\n",[151,232,234],{"class":153,"line":233},14,[151,235,236],{},"    L->>PUC: __invoke\n",[151,238,240],{"class":153,"line":239},15,[151,241,242],{},"    PUC->>PUC: create Directory member shell\n",[70,244,246],{"id":245},"sequence-resolve-subject-for-a-directory-admin-action","Sequence — resolve subject for a Directory admin action",[15,248,249,250,253,254,257],{},"Prefer resolving the subject ",[43,251,252],{},"in UI\u002FInfrastructure"," (host auth middleware) and passing a ",[43,255,256],{},"subject code"," into the Directory Application DTO. If Directory Application must verify:",[15,259,260,263,264,267,268,271],{},[109,261,262],{},"Directory Use Case"," → ",[109,265,266],{},"AuthenticatedSubjectPortInterface"," → ACL → ",[109,269,270],{},"IdentityAuthModuleInterface::resolve(token)"," → local result DTO.",[15,273,274,275,278],{},"Never inject ",[109,276,277],{},"IdentityAuthModuleInterface"," into Directory Use Cases.",[70,280,282],{"id":281},"ownership-pitfalls","Ownership pitfalls",[19,284,285,295],{},[22,286,287],{},[25,288,289,292],{},[28,290,291],{},"Pitfall",[28,293,294],{},"Fix",[35,296,297,305,313,333],{},[25,298,299,302],{},[40,300,301],{},"Directory stores passwords",[40,303,304],{},"Credentials stay in Identity",[25,306,307,310],{},[40,308,309],{},"Identity stores member pricing tier",[40,311,312],{},"Tier is Directory (or another BC); Identity may only hold auth attributes",[25,314,315,322],{},[40,316,317,318,321],{},"Shared ",[109,319,320],{},"User"," entity for both",[40,323,324,325,328,329,332],{},"Split models; share only opaque ",[109,326,327],{},"userId"," \u002F ",[109,330,331],{},"memberCode"," via contracts",[25,334,335,338],{},[40,336,337],{},"Filament\u002Fadmin in Directory importing Identity Eloquent",[40,339,340],{},"ACL or host auth bridge",[70,342,344],{"id":343},"related-core","Related Core",[346,347,348,357,364],"ul",{},[349,350,351,356],"li",{},[352,353,355],"a",{"href":354},"\u002Fv1\u002Fcore\u002Fcross-module-contracts","Contracts"," — thin Identity\u002FDirectory façades",[349,358,359,363],{},[352,360,362],{"href":361},"\u002Fv1\u002Fcore\u002Fevent-delivery","Event delivery"," — idempotent provisioning",[349,365,366,370],{},[352,367,369],{"href":368},"\u002Fv1\u002Fcore\u002Freads-and-reporting","Reads"," — profile screens vs auth",[15,372,373,374,378],{},"Also see ",[352,375,377],{"href":376},"\u002Fv1\u002Fcookbook\u002Fordering-warehouse","Ordering ↔ Warehouse",".",[380,381,382],"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":136,"searchDepth":160,"depth":160,"links":384},[385,386,387,388,389,390],{"id":72,"depth":160,"text":73},{"id":127,"depth":160,"text":128},{"id":141,"depth":160,"text":142},{"id":245,"depth":160,"text":246},{"id":281,"depth":160,"text":282},{"id":343,"depth":160,"text":344},"Greenfield cookbook — authentication ownership in Identity, member profile\u002Feligibility in Directory, bridged by ACL and Events.","md",{},"\u002Fv1\u002Fcookbook\u002Fidentity-directory",{"title":5,"description":391},"v1\u002Fcookbook\u002Fidentity-directory","18LV83CDpDkL_ai_qrLShyiKoS33KVVP0qTEQBsJ37Q",1786241413011]