[{"data":1,"prerenderedAt":1235},["ShallowReactive",2],{"docs-nav:en":3,"docs:\u002Fdocs\u002Fbusiness\u002Frepositories":186},[4],{"title":5,"path":6,"stem":7,"children":8},"Docs","\u002Fdocs","docs",[9,12,16,20,24,28,50,75,120,145],{"title":10,"path":6,"stem":11},"What is Fougere","docs\u002Findex",{"title":13,"path":14,"stem":15},"Getting started","\u002Fdocs\u002Fgetting-started","docs\u002F01.getting-started",{"title":17,"path":18,"stem":19},"An app you already have","\u002Fdocs\u002Fexisting-app","docs\u002F02.existing-app",{"title":21,"path":22,"stem":23},"Bring your schema","\u002Fdocs\u002Fbring-your-schema","docs\u002F03.bring-your-schema",{"title":25,"path":26,"stem":27},"The CLI","\u002Fdocs\u002Fcli","docs\u002F04.cli",{"title":29,"path":30,"stem":31,"children":32,"page":49},"Concepts","\u002Fdocs\u002Fconcepts","docs\u002F2.concepts",[33,37,41,45],{"title":34,"path":35,"stem":36},"Philosophy","\u002Fdocs\u002Fconcepts\u002Fphilosophy","docs\u002F2.concepts\u002F1.philosophy",{"title":38,"path":39,"stem":40},"The Frond","\u002Fdocs\u002Fconcepts\u002Ffrond","docs\u002F2.concepts\u002F2.frond",{"title":42,"path":43,"stem":44},"The shortest path","\u002Fdocs\u002Fconcepts\u002Fshortest-path","docs\u002F2.concepts\u002F3.shortest-path",{"title":46,"path":47,"stem":48},"The base","\u002Fdocs\u002Fconcepts\u002Fthe-base","docs\u002F2.concepts\u002F4.the-base",false,{"title":51,"path":52,"stem":53,"children":54,"page":49},"Schema","\u002Fdocs\u002Fschema","docs\u002F3.schema",[55,59,63,67,71],{"title":56,"path":57,"stem":58},"Entities","\u002Fdocs\u002Fschema\u002Fentities","docs\u002F3.schema\u002F1.entities",{"title":60,"path":61,"stem":62},"Views","\u002Fdocs\u002Fschema\u002Fviews","docs\u002F3.schema\u002F2.views",{"title":64,"path":65,"stem":66},"The identity card","\u002Fdocs\u002Fschema\u002Fcard","docs\u002F3.schema\u002F3.card",{"title":68,"path":69,"stem":70},"Standard Schema","\u002Fdocs\u002Fschema\u002Fstandard-schema","docs\u002F3.schema\u002F4.standard-schema",{"title":72,"path":73,"stem":74},"How a schema moves","\u002Fdocs\u002Fschema\u002Fevolution","docs\u002F3.schema\u002F5.evolution",{"title":76,"path":77,"stem":78,"children":79,"page":49},"Business","\u002Fdocs\u002Fbusiness","docs\u002F4.business",[80,84,88,92,96,100,104,108,112,116],{"title":81,"path":82,"stem":83},"Handlers","\u002Fdocs\u002Fbusiness\u002Fhandlers","docs\u002F4.business\u002F1.handlers",{"title":85,"path":86,"stem":87},"Ports","\u002Fdocs\u002Fbusiness\u002Fports","docs\u002F4.business\u002F10.ports",{"title":89,"path":90,"stem":91},"Presenters","\u002Fdocs\u002Fbusiness\u002Fpresenters","docs\u002F4.business\u002F2.presenters",{"title":93,"path":94,"stem":95},"Collectors","\u002Fdocs\u002Fbusiness\u002Fcollectors","docs\u002F4.business\u002F3.collectors",{"title":97,"path":98,"stem":99},"Errors","\u002Fdocs\u002Fbusiness\u002Ferrors","docs\u002F4.business\u002F4.errors",{"title":101,"path":102,"stem":103},"Seeds","\u002Fdocs\u002Fbusiness\u002Fseeds","docs\u002F4.business\u002F5.seeds",{"title":105,"path":106,"stem":107},"Facts","\u002Fdocs\u002Fbusiness\u002Ffacts","docs\u002F4.business\u002F6.facts",{"title":109,"path":110,"stem":111},"Storage","\u002Fdocs\u002Fbusiness\u002Fstorage","docs\u002F4.business\u002F7.storage",{"title":113,"path":114,"stem":115},"Writes that stand or fall as one","\u002Fdocs\u002Fbusiness\u002Ftogether","docs\u002F4.business\u002F8.together",{"title":117,"path":118,"stem":119},"Repositories","\u002Fdocs\u002Fbusiness\u002Frepositories","docs\u002F4.business\u002F9.repositories",{"title":121,"path":122,"stem":123,"children":124,"page":49},"Client","\u002Fdocs\u002Fclient","docs\u002F5.client",[125,129,133,137,141],{"title":126,"path":127,"stem":128},"Queries & commands","\u002Fdocs\u002Fclient\u002Fqueries-commands","docs\u002F5.client\u002F1.queries-commands",{"title":130,"path":131,"stem":132},"Forms","\u002Fdocs\u002Fclient\u002Fforms","docs\u002F5.client\u002F2.forms",{"title":134,"path":135,"stem":136},"Session","\u002Fdocs\u002Fclient\u002Fsession","docs\u002F5.client\u002F3.session",{"title":138,"path":139,"stem":140},"invoke","\u002Fdocs\u002Fclient\u002Finvoke","docs\u002F5.client\u002F4.invoke",{"title":142,"path":143,"stem":144},"Back-office","\u002Fdocs\u002Fclient\u002Fadmin","docs\u002F5.client\u002F5.admin",{"title":146,"path":147,"stem":148,"children":149,"page":49},"Infrastructure","\u002Fdocs\u002Finfra","docs\u002F6.infra",[150,154,158,162,166,170,174,178,182],{"title":151,"path":152,"stem":153},"The gradient","\u002Fdocs\u002Finfra\u002Fgradient","docs\u002F6.infra\u002F1.gradient",{"title":155,"path":156,"stem":157},"Surfaces — REST & GraphQL","\u002Fdocs\u002Finfra\u002Fsurfaces","docs\u002F6.infra\u002F2.surfaces",{"title":159,"path":160,"stem":161},"Deployment","\u002Fdocs\u002Finfra\u002Fdeployment","docs\u002F6.infra\u002F3.deployment",{"title":163,"path":164,"stem":165},"Hosts","\u002Fdocs\u002Finfra\u002Fhosts","docs\u002F6.infra\u002F4.hosts",{"title":167,"path":168,"stem":169},"Sources","\u002Fdocs\u002Finfra\u002Fsources","docs\u002F6.infra\u002F5.sources",{"title":171,"path":172,"stem":173},"Lifecycle","\u002Fdocs\u002Finfra\u002Flifecycle","docs\u002F6.infra\u002F6.lifecycle",{"title":175,"path":176,"stem":177},"Identity across Fronds","\u002Fdocs\u002Finfra\u002Fidentity","docs\u002F6.infra\u002F7.identity",{"title":179,"path":180,"stem":181},"Observability","\u002Fdocs\u002Finfra\u002Fobservability","docs\u002F6.infra\u002F8.observability",{"title":183,"path":184,"stem":185},"Testing","\u002Fdocs\u002Finfra\u002Ftesting","docs\u002F6.infra\u002F9.testing",{"id":187,"title":117,"body":188,"description":1230,"extension":1231,"meta":1232,"navigation":405,"path":118,"seo":1233,"stem":119,"__hash__":1234},"docs_en\u002Fdocs\u002F4.business\u002F9.repositories.md",{"type":189,"value":190,"toc":1222},"minimark",[191,195,205,216,352,355,481,491,496,507,518,521,547,564,589,593,600,608,611,624,628,642,649,925,928,934,937,974,979,985,1182,1189,1195,1199,1210,1213,1218],[192,193,117],"h1",{"id":194},"repositories",[196,197,198,204],"p",{},[199,200,201],"a",{"href":110},[202,203,109],"code",{}," is a port: generic gestures, no flavour of domain. \"The\nloud readings\" is not one of them, so that query ends up spelled at the call site, in the\nmiddle of the calculation it feeds. A query with no home squats in the answer.",[196,206,207,210,211,215],{},[202,208,209],{},"Repository(Entity)"," gives it one, and ",[212,213,214],"strong",{},"is"," that entity's storage — every gesture of the\nport, plus whatever you name on top:",[217,218,223],"pre",{"className":219,"code":220,"language":221,"meta":222,"style":222},"language-ts shiki shiki-themes material-theme-lighter github-light github-dark","\u002F\u002F repositories\u002FReadingRepository.ts\nexport default class ReadingRepository extends Repository(Reading) {\n  loud(): Promise\u003CReading[]> {\n    return this.findAllBy({ loud: true });\n  }\n}\n","ts","",[202,224,225,234,267,299,340,346],{"__ignoreMap":222},[226,227,230],"span",{"class":228,"line":229},"line",1,[226,231,233],{"class":232},"sutJx","\u002F\u002F repositories\u002FReadingRepository.ts\n",[226,235,237,241,244,248,252,255,259,263],{"class":228,"line":236},2,[226,238,240],{"class":239},"sVHd0","export",[226,242,243],{"class":239}," default",[226,245,247],{"class":246},"sbsja"," class",[226,249,251],{"class":250},"sbgvK"," ReadingRepository",[226,253,254],{"class":246}," extends",[226,256,258],{"class":257},"sGLFI"," Repository",[226,260,262],{"class":261},"su5hD","(Reading) ",[226,264,266],{"class":265},"sP7_E","{\n",[226,268,270,274,277,281,284,287,290,293,296],{"class":228,"line":269},3,[226,271,273],{"class":272},"sVXei","  loud",[226,275,276],{"class":265},"()",[226,278,280],{"class":279},"smGrS",":",[226,282,283],{"class":250}," Promise",[226,285,286],{"class":265},"\u003C",[226,288,289],{"class":250},"Reading",[226,291,292],{"class":261},"[]",[226,294,295],{"class":265},">",[226,297,298],{"class":265}," {\n",[226,300,302,305,309,312,315,319,322,325,327,331,334,337],{"class":228,"line":301},4,[226,303,304],{"class":239},"    return",[226,306,308],{"class":307},"s39Yj"," this",[226,310,311],{"class":265},".",[226,313,314],{"class":257},"findAllBy",[226,316,318],{"class":317},"skxfh","(",[226,320,321],{"class":265},"{",[226,323,324],{"class":317}," loud",[226,326,280],{"class":265},[226,328,330],{"class":329},"syTEX"," true",[226,332,333],{"class":265}," }",[226,335,336],{"class":317},")",[226,338,339],{"class":265},";\n",[226,341,343],{"class":228,"line":342},5,[226,344,345],{"class":265},"  }\n",[226,347,349],{"class":228,"line":348},6,[226,350,351],{"class":265},"}\n",[196,353,354],{},"The handler asks the question, and never spells the storage:",[217,356,358],{"className":219,"code":357,"language":221,"meta":222,"style":222},"\u002F\u002F handlers\u002FReadingHandler.ts\nexport default class ReadingHandler {\n  constructor(private readings: ReadingRepository) {}\n\n  async loud() { return this.readings.loud(); }\n  async all()  { return this.readings.list(); }   \u002F\u002F the port's own gestures, forwarded\n}\n",[202,359,360,365,378,401,407,442,476],{"__ignoreMap":222},[226,361,362],{"class":228,"line":229},[226,363,364],{"class":232},"\u002F\u002F handlers\u002FReadingHandler.ts\n",[226,366,367,369,371,373,376],{"class":228,"line":236},[226,368,240],{"class":239},[226,370,243],{"class":239},[226,372,247],{"class":246},[226,374,375],{"class":250}," ReadingHandler",[226,377,298],{"class":265},[226,379,380,383,385,388,392,394,396,398],{"class":228,"line":269},[226,381,382],{"class":246},"  constructor",[226,384,318],{"class":265},[226,386,387],{"class":246},"private",[226,389,391],{"class":390},"s99_P"," readings",[226,393,280],{"class":279},[226,395,251],{"class":250},[226,397,336],{"class":265},[226,399,400],{"class":265}," {}\n",[226,402,403],{"class":228,"line":301},[226,404,406],{"emptyLinePlaceholder":405},true,"\n",[226,408,409,412,414,416,419,422,424,426,429,431,434,436,439],{"class":228,"line":342},[226,410,411],{"class":246},"  async",[226,413,324],{"class":272},[226,415,276],{"class":265},[226,417,418],{"class":265}," {",[226,420,421],{"class":239}," return",[226,423,308],{"class":307},[226,425,311],{"class":265},[226,427,428],{"class":261},"readings",[226,430,311],{"class":265},[226,432,433],{"class":257},"loud",[226,435,276],{"class":317},[226,437,438],{"class":265},";",[226,440,441],{"class":265}," }\n",[226,443,444,446,449,451,454,456,458,460,462,464,467,469,471,473],{"class":228,"line":348},[226,445,411],{"class":246},[226,447,448],{"class":272}," all",[226,450,276],{"class":265},[226,452,453],{"class":265},"  {",[226,455,421],{"class":239},[226,457,308],{"class":307},[226,459,311],{"class":265},[226,461,428],{"class":261},[226,463,311],{"class":265},[226,465,466],{"class":257},"list",[226,468,276],{"class":317},[226,470,438],{"class":265},[226,472,333],{"class":265},[226,474,475],{"class":232},"   \u002F\u002F the port's own gestures, forwarded\n",[226,477,479],{"class":228,"line":478},7,[226,480,351],{"class":265},[196,482,483,486,487,490],{},[202,484,485],{},"repositories\u002F"," is scanned like ",[202,488,489],{},"services\u002F"," — the class registers as a provider, and its\nconstructor dependencies resolve by type as anywhere else.",[492,493,495],"h2",{"id":494},"write-none-and-you-lose-nothing","Write none and you lose nothing",[196,497,498,499,502,503,506],{},"Every entity gets a repository whether or not you wrote the file: the boot registers the\nguarded port under ",[202,500,501],{},"\u003CEntity>Repository",". So a handler may ask for one before anyone writes\nthe class, and declaring one later wins under that key — exactly as a ",[202,504,505],{},"Crud"," operation\nredefined in a subclass wins over the prefab's.",[196,508,509,510,513,514,517],{},"The two forms answer the same names, which is what makes the convention true: ",[202,511,512],{},"list()",",\n",[202,515,516],{},"create()"," and the rest are there either way, and a named query is the only difference.",[196,519,520],{},"With no file written, there is no class to point at, so name the shape:",[217,522,524],{"className":219,"code":523,"language":221,"meta":222,"style":222},"constructor(private nodes: RepositoryOf\u003CNode>) {}\n",[202,525,526],{"__ignoreMap":222},[226,527,528,531,534,536,539,541,544],{"class":228,"line":229},[226,529,530],{"class":257},"constructor",[226,532,533],{"class":261},"(private nodes: RepositoryOf",[226,535,286],{"class":279},[226,537,538],{"class":261},"Node",[226,540,295],{"class":279},[226,542,543],{"class":261},") ",[226,545,546],{"class":265},"{}\n",[196,548,549,552,553,556,557,552,560,563],{},[202,550,551],{},"RepositoryOf\u003CNode>"," is to ",[202,554,555],{},"NodeRepository"," what ",[202,558,559],{},"Storage\u003CNode>",[202,561,562],{},"NodeStorage",": one\nspelling of one container key.",[565,566,567],"warning",{},[196,568,569,570,573,574,576,577,580,581,584,585,588],{},"Injection matches the ",[212,571,572],{},"name of the type written on the parameter",", and the container key\nis ",[202,575,501],{},". A declared class must therefore be called ",[202,578,579],{},"ReadingRepository"," —\nnot ",[202,582,583],{},"Readings",", not ",[202,586,587],{},"ReadingQueries"," — or nothing resolves it.",[492,590,592],{"id":591},"the-port-is-not-a-word-of-your-vocabulary","The port is not a word of your vocabulary",[196,594,595,596,599],{},"A handler, a presenter and a collector cannot ask for ",[202,597,598],{},"Storage\u003CE>",". The boot refuses it\nby name and points at the repository:",[217,601,606],{"className":602,"code":604,"language":605},[603],"language-text","PostHandler asks for PostStorage. Storage is reached through a repository, never through\nthe port:\n    constructor(private post: PostRepository) {}\n","text",[202,607,604],{"__ignoreMap":222},[196,609,610],{},"One way in, and one word for it. What that buys beyond tidiness is the paragraph below: the\nday an entity belongs to an aggregate, no call site moves, because none of them ever spelled\nthe storage.",[196,612,613,614,617,618,623],{},"A ",[212,615,616],{},"holder"," is the exception, and it is the same rule read the other way: a class a prefab\nbuilt over its own entity may name that entity's port, which is how a\n",[199,619,620],{"href":110},[202,621,622],{},"Mirror"," writes the copy it owns. A door judges and projects; a holder\nkeeps the storage.",[492,625,627],{"id":626},"from-two-entities-on-it-owns-them","From two entities on, it owns them",[196,629,630,633,634,637,638,641],{},[202,631,632],{},"balance"," and the sum of a ledger's ",[202,635,636],{},"amount"," are one fact. Nothing could say so: the judge\nreads one row, and a ",[199,639,640],{"href":114},"frame"," makes two writes atomic without saying\nwhich ones may happen at all. Debit 100 and journal 50 and the database takes it.",[196,643,644,645,648],{},"The missing half was never a checker. It was a door: as long as ",[202,646,647],{},"Storage\u003CLedger>"," is handed\nto whoever asks, no file can be the only way in. Name both entities and it becomes one:",[217,650,652],{"className":219,"code":651,"language":221,"meta":222,"style":222},"\u002F\u002F repositories\u002FAccountRepository.ts\nexport default class AccountRepository extends Repository(Account, Ledger) {\n  async withdraw(id: string, amount: number) {\n    const [accounts, ledger] = this.storages;\n    const account = await accounts.findById(id);\n    if (account!.balance \u003C amount) throw new Error('insufficient funds');\n\n    await accounts.update(id, { balance: account!.balance - amount });\n    await ledger.create({ account: id, amount: -amount });\n  }\n}\n",[202,653,654,659,685,717,749,777,827,831,876,915,920],{"__ignoreMap":222},[226,655,656],{"class":228,"line":229},[226,657,658],{"class":232},"\u002F\u002F repositories\u002FAccountRepository.ts\n",[226,660,661,663,665,667,670,672,674,677,680,683],{"class":228,"line":236},[226,662,240],{"class":239},[226,664,243],{"class":239},[226,666,247],{"class":246},[226,668,669],{"class":250}," AccountRepository",[226,671,254],{"class":246},[226,673,258],{"class":257},[226,675,676],{"class":261},"(Account",[226,678,679],{"class":265},",",[226,681,682],{"class":261}," Ledger) ",[226,684,266],{"class":265},[226,686,687,689,692,694,697,699,703,705,708,710,713,715],{"class":228,"line":269},[226,688,411],{"class":246},[226,690,691],{"class":272}," withdraw",[226,693,318],{"class":265},[226,695,696],{"class":390},"id",[226,698,280],{"class":279},[226,700,702],{"class":701},"sZMiF"," string",[226,704,679],{"class":265},[226,706,707],{"class":390}," amount",[226,709,280],{"class":279},[226,711,712],{"class":701}," number",[226,714,336],{"class":265},[226,716,298],{"class":265},[226,718,719,722,725,729,731,734,737,740,742,744,747],{"class":228,"line":301},[226,720,721],{"class":246},"    const",[226,723,724],{"class":265}," [",[226,726,728],{"class":727},"s_hVV","accounts",[226,730,679],{"class":265},[226,732,733],{"class":727}," ledger",[226,735,736],{"class":265},"]",[226,738,739],{"class":279}," =",[226,741,308],{"class":307},[226,743,311],{"class":265},[226,745,746],{"class":261},"storages",[226,748,339],{"class":265},[226,750,751,753,756,758,761,764,766,769,771,773,775],{"class":228,"line":342},[226,752,721],{"class":246},[226,754,755],{"class":727}," account",[226,757,739],{"class":279},[226,759,760],{"class":239}," await",[226,762,763],{"class":261}," accounts",[226,765,311],{"class":265},[226,767,768],{"class":257},"findById",[226,770,318],{"class":317},[226,772,696],{"class":261},[226,774,336],{"class":317},[226,776,339],{"class":265},[226,778,779,782,785,788,791,793,795,798,800,802,805,808,811,813,817,821,823,825],{"class":228,"line":348},[226,780,781],{"class":239},"    if",[226,783,784],{"class":317}," (",[226,786,787],{"class":261},"account",[226,789,790],{"class":279},"!",[226,792,311],{"class":265},[226,794,632],{"class":261},[226,796,797],{"class":279}," \u003C",[226,799,707],{"class":261},[226,801,543],{"class":317},[226,803,804],{"class":239},"throw",[226,806,807],{"class":279}," new",[226,809,810],{"class":257}," Error",[226,812,318],{"class":317},[226,814,816],{"class":815},"sjJ54","'",[226,818,820],{"class":819},"s_sjI","insufficient funds",[226,822,816],{"class":815},[226,824,336],{"class":317},[226,826,339],{"class":265},[226,828,829],{"class":228,"line":478},[226,830,406],{"emptyLinePlaceholder":405},[226,832,834,837,839,841,844,846,848,850,852,855,857,859,861,863,865,868,870,872,874],{"class":228,"line":833},8,[226,835,836],{"class":239},"    await",[226,838,763],{"class":261},[226,840,311],{"class":265},[226,842,843],{"class":257},"update",[226,845,318],{"class":317},[226,847,696],{"class":261},[226,849,679],{"class":265},[226,851,418],{"class":265},[226,853,854],{"class":317}," balance",[226,856,280],{"class":265},[226,858,755],{"class":261},[226,860,790],{"class":279},[226,862,311],{"class":265},[226,864,632],{"class":261},[226,866,867],{"class":279}," -",[226,869,707],{"class":261},[226,871,333],{"class":265},[226,873,336],{"class":317},[226,875,339],{"class":265},[226,877,879,881,883,885,888,890,892,894,896,899,901,903,905,907,909,911,913],{"class":228,"line":878},9,[226,880,836],{"class":239},[226,882,733],{"class":261},[226,884,311],{"class":265},[226,886,887],{"class":257},"create",[226,889,318],{"class":317},[226,891,321],{"class":265},[226,893,755],{"class":317},[226,895,280],{"class":265},[226,897,898],{"class":261}," id",[226,900,679],{"class":265},[226,902,707],{"class":317},[226,904,280],{"class":265},[226,906,867],{"class":279},[226,908,636],{"class":261},[226,910,333],{"class":265},[226,912,336],{"class":317},[226,914,339],{"class":265},[226,916,918],{"class":228,"line":917},10,[226,919,345],{"class":265},[226,921,923],{"class":228,"line":922},11,[226,924,351],{"class":265},[196,926,927],{},"The rule is ordinary TypeScript, in the method that does the writing. Nothing was added to\nexpress it — what was added is that nowhere else can write those two tables.",[196,929,930,933],{},[212,931,932],{},"The arity is the declaration."," One entity is a place to name questions; two or more is a\nboundary. There is no flag, and a repository of one owns nothing — a boundary between one\nthing and nothing is not a boundary, and the judge already sits on that entity's rows.",[196,935,936],{},"Three things follow, and each is the shape refusing rather than a rule written down:",[938,939,940,951,964],"ul",{},[941,942,943,946,947,950],"li",{},[212,944,945],{},"No default repository"," is registered for any member. ",[202,948,949],{},"LedgerRepository"," does not exist,\nso nothing can ask for it.",[941,952,953,956,957,959,960,963],{},[212,954,955],{},"No gesture is forwarded."," Which entity would ",[202,958,887],{}," write to? So the only surface is\nwhat you name. An owned entity therefore has no automatic CRUD — ",[202,961,962],{},"Crud(Ledger)"," has no\nstorage to run on — and the boot says so by name rather than letting the app start and fail\nat its first request.",[941,965,966,969,970,973],{},[212,967,968],{},"Two aggregates cannot claim one entity."," Refused at boot naming both, for the reason\n",[202,971,972],{},"ports:"," refuses two implementations: whichever won would depend on scan order, and one of\nthe two boundaries would be silently unenforced.",[975,976,978],"h3",{"id":977},"the-boundary-is-not-the-unit-of-work","The boundary is not the unit of work",[196,980,981,982,984],{},"An aggregate says the rules of these entities hold together. A ",[199,983,640],{"href":114},"\nsays these writes land together. The two lists coincide often, and they are not the same\nstatement — so a frame is asked for here as anywhere else:",[217,986,988],{"className":219,"code":987,"language":221,"meta":222,"style":222},"export default class AccountRepository extends Repository(Account, Ledger) {\n  constructor(\n    accounts: AccountStorage,\n    ledger: LedgerStorage,\n    private frame: Together\u003C[Account, Ledger]>,\n  ) { super(accounts, ledger); }\n\n  async withdraw(id: string, amount: number) {\n    return this.frame.run(async ([accounts, ledger]) => { \u002F* both, or neither *\u002F });\n  }\n}\n",[202,989,990,1012,1019,1031,1043,1074,1098,1102,1128,1174,1178],{"__ignoreMap":222},[226,991,992,994,996,998,1000,1002,1004,1006,1008,1010],{"class":228,"line":229},[226,993,240],{"class":239},[226,995,243],{"class":239},[226,997,247],{"class":246},[226,999,669],{"class":250},[226,1001,254],{"class":246},[226,1003,258],{"class":257},[226,1005,676],{"class":261},[226,1007,679],{"class":265},[226,1009,682],{"class":261},[226,1011,266],{"class":265},[226,1013,1014,1016],{"class":228,"line":236},[226,1015,382],{"class":246},[226,1017,1018],{"class":265},"(\n",[226,1020,1021,1024,1026,1029],{"class":228,"line":269},[226,1022,1023],{"class":390},"    accounts",[226,1025,280],{"class":279},[226,1027,1028],{"class":250}," AccountStorage",[226,1030,513],{"class":265},[226,1032,1033,1036,1038,1041],{"class":228,"line":301},[226,1034,1035],{"class":390},"    ledger",[226,1037,280],{"class":279},[226,1039,1040],{"class":250}," LedgerStorage",[226,1042,513],{"class":265},[226,1044,1045,1048,1051,1053,1056,1058,1061,1064,1066,1069,1071],{"class":228,"line":342},[226,1046,1047],{"class":246},"    private",[226,1049,1050],{"class":390}," frame",[226,1052,280],{"class":279},[226,1054,1055],{"class":250}," Together",[226,1057,286],{"class":265},[226,1059,1060],{"class":261},"[",[226,1062,1063],{"class":250},"Account",[226,1065,679],{"class":265},[226,1067,1068],{"class":250}," Ledger",[226,1070,736],{"class":261},[226,1072,1073],{"class":265},">,\n",[226,1075,1076,1079,1081,1084,1086,1088,1090,1092,1094,1096],{"class":228,"line":348},[226,1077,1078],{"class":265},"  )",[226,1080,418],{"class":265},[226,1082,1083],{"class":727}," super",[226,1085,318],{"class":317},[226,1087,728],{"class":261},[226,1089,679],{"class":265},[226,1091,733],{"class":261},[226,1093,336],{"class":317},[226,1095,438],{"class":265},[226,1097,441],{"class":265},[226,1099,1100],{"class":228,"line":478},[226,1101,406],{"emptyLinePlaceholder":405},[226,1103,1104,1106,1108,1110,1112,1114,1116,1118,1120,1122,1124,1126],{"class":228,"line":833},[226,1105,411],{"class":246},[226,1107,691],{"class":272},[226,1109,318],{"class":265},[226,1111,696],{"class":390},[226,1113,280],{"class":279},[226,1115,702],{"class":701},[226,1117,679],{"class":265},[226,1119,707],{"class":390},[226,1121,280],{"class":279},[226,1123,712],{"class":701},[226,1125,336],{"class":265},[226,1127,298],{"class":265},[226,1129,1130,1132,1134,1136,1138,1140,1143,1145,1148,1151,1153,1155,1157,1160,1163,1165,1168,1170,1172],{"class":228,"line":878},[226,1131,304],{"class":239},[226,1133,308],{"class":307},[226,1135,311],{"class":265},[226,1137,640],{"class":261},[226,1139,311],{"class":265},[226,1141,1142],{"class":257},"run",[226,1144,318],{"class":317},[226,1146,1147],{"class":246},"async",[226,1149,1150],{"class":265}," ([",[226,1152,728],{"class":390},[226,1154,679],{"class":265},[226,1156,733],{"class":390},[226,1158,1159],{"class":265},"])",[226,1161,1162],{"class":246}," =>",[226,1164,418],{"class":265},[226,1166,1167],{"class":232}," \u002F* both, or neither *\u002F",[226,1169,333],{"class":265},[226,1171,336],{"class":317},[226,1173,339],{"class":265},[226,1175,1176],{"class":228,"line":917},[226,1177,345],{"class":265},[226,1179,1180],{"class":228,"line":922},[226,1181,351],{"class":265},[196,1183,1184,1185,1188],{},"Deriving the frame from the membership would have made a read-only aggregate carry one —\nrefusals included — and put ",[202,1186,1187],{},"Together\u003C[Account, Ledger], [RateMirror]>"," out of reach forever.",[196,1190,1191,1192,1194],{},"The port's names come back in that constructor, and only there: this class ",[212,1193,214],{}," the holder,\nwhich is the one case the rule above allows.",[492,1196,1198],{"id":1197},"it-is-not-a-door","It is not a door",[196,1200,1201,1202,1205,1206,1209],{},"A repository has no façade, so nothing it carries is reachable from the wire. That is what\nmakes it free to hold whatever the domain asks — but it also means a ",[212,1203,1204],{},"judge does not\nbelong here",". Rules about who may act stay in the\n",[199,1207,1208],{"href":82},"handler",", the one place a refusal cannot be walked around. What\nbelongs here is the other kind: a rule about what the data may be.",[196,1211,1212],{},"Writes are still judged, because they go through the port: a value the entity forbids is\nrefused whether a repository or a handler issued it.",[196,1214,1215,1216,311],{},"Next: ",[199,1217,85],{"href":86},[1219,1220,1221],"style",{},"html pre.shiki code .sutJx, html code.shiki .sutJx{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}html pre.shiki code .sVHd0, html code.shiki .sVHd0{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sVXei, html code.shiki .sVXei{--shiki-light:#E53935;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .s39Yj, html code.shiki .s39Yj{--shiki-light:#39ADB5;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .syTEX, html code.shiki .syTEX{--shiki-light:#FF5370;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}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);}html pre.shiki code .s99_P, html code.shiki .s99_P{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#E36209;--shiki-default-font-style:inherit;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit}html pre.shiki code .sZMiF, html code.shiki .sZMiF{--shiki-light:#E2931D;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s_hVV, html code.shiki .s_hVV{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":222,"searchDepth":236,"depth":236,"links":1223},[1224,1225,1226,1229],{"id":494,"depth":236,"text":495},{"id":591,"depth":236,"text":592},{"id":626,"depth":236,"text":627,"children":1227},[1228],{"id":977,"depth":269,"text":978},{"id":1197,"depth":236,"text":1198},"Who owns an entity's storage — the one way in, the default you get without writing anything, and what changes from two entities on.","md",{},{"title":117,"description":1230},"vJZUczA04b8Q-sDuKHwOYAODGOiQT9STPpEJcQmxlxI",1788560230783]