[{"data":1,"prerenderedAt":2304},["ShallowReactive",2],{"docs-nav:en":3,"docs:\u002Fdocs\u002Fschema\u002Fcard":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":64,"body":188,"description":2299,"extension":2300,"meta":2301,"navigation":280,"path":65,"seo":2302,"stem":66,"__hash__":2303},"docs_en\u002Fdocs\u002F3.schema\u002F3.card.md",{"type":189,"value":190,"toc":2283},"minimark",[191,195,204,223,354,364,378,439,444,459,1058,1075,1080,1087,1201,1222,1228,1234,1400,1409,1420,1444,1450,1456,1479,1485,1489,1502,1582,1596,1600,1603,1630,1633,1640,1650,2105,2140,2153,2157,2163,2181,2190,2200,2204,2207,2261,2264,2273,2279],[192,193,64],"h1",{"id":194},"the-identity-card",[196,197,198,199,203],"p",{},"A TypeScript class cannot be serialized directly. Its ",[200,201,202],"strong",{},"card"," is a JSON document that\ndescribes the schema and lets a consumer rebuild a validation class.",[196,205,206,207,214,215,218,219,222],{},"The two are duals. ",[208,209,210],"a",{"href":69},[211,212,213],"code",{},"~standard"," hands the ",[200,216,217],{},"live"," judge to\na library in the same process; the card is the ",[200,220,221],{},"serializable"," description of the same\ndeclaration, for exchanges across processes or languages.",[224,225,230],"pre",{"className":226,"code":227,"language":228,"meta":229,"style":229},"language-ts shiki shiki-themes material-theme-lighter github-light github-dark","import { Bundle, Card } from '@fougere\u002Fschema';\n\nconst descriptor = Card.fromSchema(Post).descriptor;       \u002F\u002F schema to JSON document\nconst Rebuilt = Card.fromDescriptor(descriptor).toSchema(); \u002F\u002F document to living schema\n","ts","",[211,231,232,275,282,321],{"__ignoreMap":229},[233,234,237,241,245,249,252,255,258,261,265,269,272],"span",{"class":235,"line":236},"line",1,[233,238,240],{"class":239},"sVHd0","import",[233,242,244],{"class":243},"sP7_E"," {",[233,246,248],{"class":247},"su5hD"," Bundle",[233,250,251],{"class":243},",",[233,253,254],{"class":247}," Card",[233,256,257],{"class":243}," }",[233,259,260],{"class":239}," from",[233,262,264],{"class":263},"sjJ54"," '",[233,266,268],{"class":267},"s_sjI","@fougere\u002Fschema",[233,270,271],{"class":263},"'",[233,273,274],{"class":243},";\n",[233,276,278],{"class":235,"line":277},2,[233,279,281],{"emptyLinePlaceholder":280},true,"\n",[233,283,285,289,293,297,299,302,306,309,311,314,317],{"class":235,"line":284},3,[233,286,288],{"class":287},"sbsja","const",[233,290,292],{"class":291},"s_hVV"," descriptor",[233,294,296],{"class":295},"smGrS"," =",[233,298,254],{"class":247},[233,300,301],{"class":243},".",[233,303,305],{"class":304},"sGLFI","fromSchema",[233,307,308],{"class":247},"(Post)",[233,310,301],{"class":243},[233,312,313],{"class":247},"descriptor",[233,315,316],{"class":243},";",[233,318,320],{"class":319},"sutJx","       \u002F\u002F schema to JSON document\n",[233,322,324,326,329,331,333,335,338,341,343,346,349,351],{"class":235,"line":323},4,[233,325,288],{"class":287},[233,327,328],{"class":291}," Rebuilt",[233,330,296],{"class":295},[233,332,254],{"class":247},[233,334,301],{"class":243},[233,336,337],{"class":304},"fromDescriptor",[233,339,340],{"class":247},"(descriptor)",[233,342,301],{"class":243},[233,344,345],{"class":304},"toSchema",[233,347,348],{"class":247},"()",[233,350,316],{"class":243},[233,352,353],{"class":319}," \u002F\u002F document to living schema\n",[196,355,356,359,360,363],{},[211,357,358],{},"Card.fromSchema"," produces the canonical document used by adapters. ",[211,361,362],{},"Card.toSchema","\nrebuilds the schema at the consumer, which can then validate data locally.",[196,365,366,367,370,371,377],{},"State the shape of a row and the rebuilt schema is a class in the full sense — one name\ncarrying the judge and the type of what it judges, exactly like ",[211,368,369],{},"class Post extends entity({…}) {}",". This is what ",[208,372,374],{"href":373},"\u002Fdocs\u002Fcli#fougere-sync--consume-a-remote-frond",[211,375,376],{},"fougere sync","\nwrites:",[224,379,381],{"className":226,"code":380,"language":228,"meta":229,"style":229},"class Post extends Card.fromDescriptor\u003C{ id: string; title: string }>(descriptor).toSchema() {}\n",[211,382,383],{"__ignoreMap":229},[233,384,385,388,392,395,397,399,401,404,408,411,415,417,420,422,424,427,429,431,433,436],{"class":235,"line":236},[233,386,387],{"class":287},"class",[233,389,391],{"class":390},"sbgvK"," Post",[233,393,394],{"class":287}," extends",[233,396,254],{"class":247},[233,398,301],{"class":243},[233,400,337],{"class":304},[233,402,403],{"class":243},"\u003C{",[233,405,407],{"class":406},"sucvu"," id",[233,409,410],{"class":295},":",[233,412,414],{"class":413},"sZMiF"," string",[233,416,316],{"class":243},[233,418,419],{"class":406}," title",[233,421,410],{"class":295},[233,423,414],{"class":413},[233,425,426],{"class":243}," }>",[233,428,340],{"class":247},[233,430,301],{"class":243},[233,432,345],{"class":304},[233,434,435],{"class":247},"() ",[233,437,438],{"class":243},"{}\n",[440,441,443],"h2",{"id":442},"the-structure","The structure",[196,445,446,447,450,451,454,455,458],{},"The card is a valid JSON Schema document. The ",[211,448,449],{},"shape"," axis ",[200,452,453],{},"is"," that vocabulary, so its\nkeywords sit at the field's top level; the three other axes live under the ",[211,456,457],{},"x-fougere","\nextension key.",[224,460,464],{"className":461,"code":462,"language":463,"meta":229,"style":229},"language-jsonc shiki shiki-themes material-theme-lighter github-light github-dark","{\n  \"title\": \"post\",\n  \"type\": \"object\",\n  \"properties\": {\n    \"id\": {\n      \"type\": \"string\",\n      \"x-fougere\": {\n        \"role\": { \"primary\": true },\n        \"lifecycle\": { \"create\": { \"generate\": \"cuid2\" } }\n      }\n    },\n    \"title\": { \"type\": \"string\", \"minLength\": 3, \"maxLength\": 120 },\n    \"status\": { \"type\": \"string\", \"enum\": [\"draft\", \"published\"] },\n    \"publishedAt\": {\n      \"type\": [\"string\", \"null\"],\n      \"format\": \"date-time\",\n      \"x-fougere\": { \"lifecycle\": { \"update\": \"forbidden\" } }\n    },\n    \"secret\": { \"type\": \"string\", \"x-fougere\": { \"boundary\": { \"out\": \"closed\" } } }\n  },\n  \"required\": [\"title\", \"status\"],\n  \"x-fougere-version\": 1,\n  \"x-fougere-vendor\": \"fougere\"\n}\n","jsonc",[211,465,466,471,497,517,531,546,568,581,613,660,666,672,729,792,806,837,858,901,906,979,985,1015,1032,1052],{"__ignoreMap":229},[233,467,468],{"class":235,"line":236},[233,469,470],{"class":243},"{\n",[233,472,473,477,481,484,486,489,492,494],{"class":235,"line":277},[233,474,476],{"class":475},"s39Yj","  \"",[233,478,480],{"class":479},"sseR_","title",[233,482,483],{"class":475},"\"",[233,485,410],{"class":243},[233,487,488],{"class":263}," \"",[233,490,491],{"class":267},"post",[233,493,483],{"class":263},[233,495,496],{"class":243},",\n",[233,498,499,501,504,506,508,510,513,515],{"class":235,"line":284},[233,500,476],{"class":475},[233,502,503],{"class":479},"type",[233,505,483],{"class":475},[233,507,410],{"class":243},[233,509,488],{"class":263},[233,511,512],{"class":267},"object",[233,514,483],{"class":263},[233,516,496],{"class":243},[233,518,519,521,524,526,528],{"class":235,"line":323},[233,520,476],{"class":475},[233,522,523],{"class":479},"properties",[233,525,483],{"class":475},[233,527,410],{"class":243},[233,529,530],{"class":243}," {\n",[233,532,534,537,540,542,544],{"class":235,"line":533},5,[233,535,536],{"class":475},"    \"",[233,538,539],{"class":413},"id",[233,541,483],{"class":475},[233,543,410],{"class":243},[233,545,530],{"class":243},[233,547,549,552,555,557,559,561,564,566],{"class":235,"line":548},6,[233,550,551],{"class":475},"      \"",[233,553,503],{"class":554},"srdBf",[233,556,483],{"class":475},[233,558,410],{"class":243},[233,560,488],{"class":263},[233,562,563],{"class":267},"string",[233,565,483],{"class":263},[233,567,496],{"class":243},[233,569,571,573,575,577,579],{"class":235,"line":570},7,[233,572,551],{"class":475},[233,574,457],{"class":554},[233,576,483],{"class":475},[233,578,410],{"class":243},[233,580,530],{"class":243},[233,582,584,587,591,593,595,597,599,603,605,607,610],{"class":235,"line":583},8,[233,585,586],{"class":475},"        \"",[233,588,590],{"class":589},"swQdS","role",[233,592,483],{"class":475},[233,594,410],{"class":243},[233,596,244],{"class":243},[233,598,488],{"class":475},[233,600,602],{"class":601},"sAQsV","primary",[233,604,483],{"class":475},[233,606,410],{"class":243},[233,608,609],{"class":475}," true",[233,611,612],{"class":243}," },\n",[233,614,616,618,621,623,625,627,629,632,634,636,638,640,644,646,648,650,653,655,657],{"class":235,"line":615},9,[233,617,586],{"class":475},[233,619,620],{"class":589},"lifecycle",[233,622,483],{"class":475},[233,624,410],{"class":243},[233,626,244],{"class":243},[233,628,488],{"class":475},[233,630,631],{"class":601},"create",[233,633,483],{"class":475},[233,635,410],{"class":243},[233,637,244],{"class":243},[233,639,488],{"class":475},[233,641,643],{"class":642},"sptTA","generate",[233,645,483],{"class":475},[233,647,410],{"class":243},[233,649,488],{"class":263},[233,651,652],{"class":267},"cuid2",[233,654,483],{"class":263},[233,656,257],{"class":243},[233,658,659],{"class":243}," }\n",[233,661,663],{"class":235,"line":662},10,[233,664,665],{"class":243},"      }\n",[233,667,669],{"class":235,"line":668},11,[233,670,671],{"class":243},"    },\n",[233,673,675,677,679,681,683,685,687,689,691,693,695,697,699,701,703,706,708,710,713,715,717,720,722,724,727],{"class":235,"line":674},12,[233,676,536],{"class":475},[233,678,480],{"class":413},[233,680,483],{"class":475},[233,682,410],{"class":243},[233,684,244],{"class":243},[233,686,488],{"class":475},[233,688,503],{"class":554},[233,690,483],{"class":475},[233,692,410],{"class":243},[233,694,488],{"class":263},[233,696,563],{"class":267},[233,698,483],{"class":263},[233,700,251],{"class":243},[233,702,488],{"class":475},[233,704,705],{"class":554},"minLength",[233,707,483],{"class":475},[233,709,410],{"class":243},[233,711,712],{"class":554}," 3",[233,714,251],{"class":243},[233,716,488],{"class":475},[233,718,719],{"class":554},"maxLength",[233,721,483],{"class":475},[233,723,410],{"class":243},[233,725,726],{"class":554}," 120",[233,728,612],{"class":243},[233,730,732,734,737,739,741,743,745,747,749,751,753,755,757,759,761,764,766,768,771,773,776,778,780,782,785,787,790],{"class":235,"line":731},13,[233,733,536],{"class":475},[233,735,736],{"class":413},"status",[233,738,483],{"class":475},[233,740,410],{"class":243},[233,742,244],{"class":243},[233,744,488],{"class":475},[233,746,503],{"class":554},[233,748,483],{"class":475},[233,750,410],{"class":243},[233,752,488],{"class":263},[233,754,563],{"class":267},[233,756,483],{"class":263},[233,758,251],{"class":243},[233,760,488],{"class":475},[233,762,763],{"class":554},"enum",[233,765,483],{"class":475},[233,767,410],{"class":243},[233,769,770],{"class":243}," [",[233,772,483],{"class":263},[233,774,775],{"class":267},"draft",[233,777,483],{"class":263},[233,779,251],{"class":243},[233,781,488],{"class":263},[233,783,784],{"class":267},"published",[233,786,483],{"class":263},[233,788,789],{"class":243},"]",[233,791,612],{"class":243},[233,793,795,797,800,802,804],{"class":235,"line":794},14,[233,796,536],{"class":475},[233,798,799],{"class":413},"publishedAt",[233,801,483],{"class":475},[233,803,410],{"class":243},[233,805,530],{"class":243},[233,807,809,811,813,815,817,819,821,823,825,827,829,832,834],{"class":235,"line":808},15,[233,810,551],{"class":475},[233,812,503],{"class":554},[233,814,483],{"class":475},[233,816,410],{"class":243},[233,818,770],{"class":243},[233,820,483],{"class":263},[233,822,563],{"class":267},[233,824,483],{"class":263},[233,826,251],{"class":243},[233,828,488],{"class":263},[233,830,831],{"class":267},"null",[233,833,483],{"class":263},[233,835,836],{"class":243},"],\n",[233,838,840,842,845,847,849,851,854,856],{"class":235,"line":839},16,[233,841,551],{"class":475},[233,843,844],{"class":554},"format",[233,846,483],{"class":475},[233,848,410],{"class":243},[233,850,488],{"class":263},[233,852,853],{"class":267},"date-time",[233,855,483],{"class":263},[233,857,496],{"class":243},[233,859,861,863,865,867,869,871,873,875,877,879,881,883,886,888,890,892,895,897,899],{"class":235,"line":860},17,[233,862,551],{"class":475},[233,864,457],{"class":554},[233,866,483],{"class":475},[233,868,410],{"class":243},[233,870,244],{"class":243},[233,872,488],{"class":475},[233,874,620],{"class":589},[233,876,483],{"class":475},[233,878,410],{"class":243},[233,880,244],{"class":243},[233,882,488],{"class":475},[233,884,885],{"class":601},"update",[233,887,483],{"class":475},[233,889,410],{"class":243},[233,891,488],{"class":263},[233,893,894],{"class":267},"forbidden",[233,896,483],{"class":263},[233,898,257],{"class":243},[233,900,659],{"class":243},[233,902,904],{"class":235,"line":903},18,[233,905,671],{"class":243},[233,907,909,911,914,916,918,920,922,924,926,928,930,932,934,936,938,940,942,944,946,948,951,953,955,957,959,962,964,966,968,971,973,975,977],{"class":235,"line":908},19,[233,910,536],{"class":475},[233,912,913],{"class":413},"secret",[233,915,483],{"class":475},[233,917,410],{"class":243},[233,919,244],{"class":243},[233,921,488],{"class":475},[233,923,503],{"class":554},[233,925,483],{"class":475},[233,927,410],{"class":243},[233,929,488],{"class":263},[233,931,563],{"class":267},[233,933,483],{"class":263},[233,935,251],{"class":243},[233,937,488],{"class":475},[233,939,457],{"class":554},[233,941,483],{"class":475},[233,943,410],{"class":243},[233,945,244],{"class":243},[233,947,488],{"class":475},[233,949,950],{"class":589},"boundary",[233,952,483],{"class":475},[233,954,410],{"class":243},[233,956,244],{"class":243},[233,958,488],{"class":475},[233,960,961],{"class":601},"out",[233,963,483],{"class":475},[233,965,410],{"class":243},[233,967,488],{"class":263},[233,969,970],{"class":267},"closed",[233,972,483],{"class":263},[233,974,257],{"class":243},[233,976,257],{"class":243},[233,978,659],{"class":243},[233,980,982],{"class":235,"line":981},20,[233,983,984],{"class":243},"  },\n",[233,986,988,990,993,995,997,999,1001,1003,1005,1007,1009,1011,1013],{"class":235,"line":987},21,[233,989,476],{"class":475},[233,991,992],{"class":479},"required",[233,994,483],{"class":475},[233,996,410],{"class":243},[233,998,770],{"class":243},[233,1000,483],{"class":263},[233,1002,480],{"class":267},[233,1004,483],{"class":263},[233,1006,251],{"class":243},[233,1008,488],{"class":263},[233,1010,736],{"class":267},[233,1012,483],{"class":263},[233,1014,836],{"class":243},[233,1016,1018,1020,1023,1025,1027,1030],{"class":235,"line":1017},22,[233,1019,476],{"class":475},[233,1021,1022],{"class":479},"x-fougere-version",[233,1024,483],{"class":475},[233,1026,410],{"class":243},[233,1028,1029],{"class":554}," 1",[233,1031,496],{"class":243},[233,1033,1035,1037,1040,1042,1044,1046,1049],{"class":235,"line":1034},23,[233,1036,476],{"class":475},[233,1038,1039],{"class":479},"x-fougere-vendor",[233,1041,483],{"class":475},[233,1043,410],{"class":243},[233,1045,488],{"class":263},[233,1047,1048],{"class":267},"fougere",[233,1050,1051],{"class":263},"\"\n",[233,1053,1055],{"class":235,"line":1054},24,[233,1056,1057],{"class":243},"}\n",[196,1059,1060,1061,1064,1065,1068,1069,1071,1072,1074],{},"A nullable field folds into the union ",[211,1062,1063],{},"type: [\"T\", \"null\"]"," — nullability is shape, hence\nplain JSON Schema. An embedded object (",[211,1066,1067],{},"json(Entity)",") carries its nested ",[211,1070,523],{}," and\n",[211,1073,992],{},", themselves shape-only.",[1076,1077,1079],"h3",{"id":1078},"a-view-says-what-it-is-a-view-of","A view says what it is a view of",[196,1081,1082,1083,1086],{},"The card of a ",[208,1084,1085],{"href":61},"view"," carries one extra key, absent from a declaration\nthat derives from nothing:",[224,1088,1090],{"className":461,"code":1089,"language":463,"meta":229,"style":229},"\"x-fougere-derived\": {\n  \"from\": \"Post\",\n  \"survived\": { \"id\": \"id\", \"title\": \"title\", \"body\": null, \"status\": null }\n}\n",[211,1091,1092,1106,1126,1197],{"__ignoreMap":229},[233,1093,1094,1096,1099,1101,1104],{"class":235,"line":236},[233,1095,483],{"class":263},[233,1097,1098],{"class":267},"x-fougere-derived",[233,1100,483],{"class":263},[233,1102,1103],{"class":247},": ",[233,1105,470],{"class":243},[233,1107,1108,1110,1113,1115,1117,1119,1122,1124],{"class":235,"line":277},[233,1109,476],{"class":475},[233,1111,1112],{"class":479},"from",[233,1114,483],{"class":475},[233,1116,410],{"class":243},[233,1118,488],{"class":263},[233,1120,1121],{"class":267},"Post",[233,1123,483],{"class":263},[233,1125,496],{"class":243},[233,1127,1128,1130,1133,1135,1137,1139,1141,1143,1145,1147,1149,1151,1153,1155,1157,1159,1161,1163,1165,1167,1169,1171,1173,1176,1178,1180,1183,1185,1187,1189,1191,1193,1195],{"class":235,"line":284},[233,1129,476],{"class":475},[233,1131,1132],{"class":479},"survived",[233,1134,483],{"class":475},[233,1136,410],{"class":243},[233,1138,244],{"class":243},[233,1140,488],{"class":475},[233,1142,539],{"class":413},[233,1144,483],{"class":475},[233,1146,410],{"class":243},[233,1148,488],{"class":263},[233,1150,539],{"class":267},[233,1152,483],{"class":263},[233,1154,251],{"class":243},[233,1156,488],{"class":475},[233,1158,480],{"class":413},[233,1160,483],{"class":475},[233,1162,410],{"class":243},[233,1164,488],{"class":263},[233,1166,480],{"class":267},[233,1168,483],{"class":263},[233,1170,251],{"class":243},[233,1172,488],{"class":475},[233,1174,1175],{"class":413},"body",[233,1177,483],{"class":475},[233,1179,410],{"class":243},[233,1181,1182],{"class":475}," null",[233,1184,251],{"class":243},[233,1186,488],{"class":475},[233,1188,736],{"class":413},[233,1190,483],{"class":475},[233,1192,410],{"class":243},[233,1194,1182],{"class":475},[233,1196,659],{"class":243},[233,1198,1199],{"class":235,"line":323},[233,1200,1057],{"class":243},[196,1202,1203,1205,1206,1208,1209,1211,1212,1218,1219,1221],{},[211,1204,1112],{}," names the origin and ",[211,1207,1132],{}," says what the cut left, keyed by the origin's field\nnames — a dropped field is present and null. ",[211,1210,480],{}," already carried the origin's name, and\ncarried it alone: two views of one entity described identically, and nothing in the card\nsaid which served which fields. A reader can now answer ",[1213,1214,1215,1216],"em",{},"a Post without ",[211,1217,1175],{},", and\n",[211,1220,376],{}," can write the derivation rather than a flattened shape.",[440,1223,1225,1226],{"id":1224},"the-three-axes-under-x-fougere","The three axes under ",[211,1227,457],{},[196,1229,1230,1231,1233],{},"The values under ",[211,1232,457],{}," are names and JSON structures. No separate descriptor is\nrequired.",[1235,1236,1237,1253],"table",{},[1238,1239,1240],"thead",{},[1241,1242,1243,1247,1250],"tr",{},[1244,1245,1246],"th",{},"key",[1244,1248,1249],{},"values",[1244,1251,1252],{},"what it states",[1254,1255,1256,1272,1287,1301,1323,1348,1365,1383],"tbody",{},[1241,1257,1258,1264,1269],{},[1259,1260,1261],"td",{},[211,1262,1263],{},"role.primary",[1259,1265,1266],{},[211,1267,1268],{},"true",[1259,1270,1271],{},"identity — the system owns it",[1241,1273,1274,1279,1284],{},[1259,1275,1276],{},[211,1277,1278],{},"role.unique",[1259,1280,1281],{},[211,1282,1283],{},"[[\"slug\"], [\"listId\",\"docId\"]]",[1259,1285,1286],{},"the unique constraints this field is a member of — one member list each, members named. A lone field is the degenerate case: a constraint of one. The DDL emits them",[1241,1288,1289,1294,1298],{},[1259,1290,1291],{},[211,1292,1293],{},"role.index",[1259,1295,1296],{},[211,1297,1268],{},[1259,1299,1300],{},"storage constraint — the DDL emits it",[1241,1302,1303,1308,1313],{},[1259,1304,1305],{},[211,1306,1307],{},"role.relation",[1259,1309,1310],{},[211,1311,1312],{},"{ to, kind: 'one'|'many', onDelete? }",[1259,1314,1315,1318,1319,1322],{},[211,1316,1317],{},"to"," is a ",[200,1320,1321],{},"name",", not an inlined schema",[1241,1324,1325,1330,1345],{},[1259,1326,1327],{},[211,1328,1329],{},"lifecycle.create",[1259,1331,1332,1335,1336,1335,1339,1335,1342],{},[211,1333,1334],{},"{ value }"," | ",[211,1337,1338],{},"'now'",[211,1340,1341],{},"{ generate }",[211,1343,1344],{},"'optional'",[1259,1346,1347],{},"who writes at creation, and when",[1241,1349,1350,1355,1362],{},[1259,1351,1352],{},[211,1353,1354],{},"lifecycle.update",[1259,1356,1357,1335,1359],{},[211,1358,1338],{},[211,1360,1361],{},"'forbidden'",[1259,1363,1364],{},"who writes on update",[1241,1366,1367,1372,1380],{},[1259,1368,1369],{},[211,1370,1371],{},"boundary.in",[1259,1373,1374,1335,1377],{},[211,1375,1376],{},"'closed'",[211,1378,1379],{},"{ decode }",[1259,1381,1382],{},"read-only, or a named inbound conversion",[1241,1384,1385,1390,1397],{},[1259,1386,1387],{},[211,1388,1389],{},"boundary.out",[1259,1391,1392,1335,1394],{},[211,1393,1376],{},[211,1395,1396],{},"{ encode }",[1259,1398,1399],{},"write-only, or a named outbound conversion",[196,1401,1402,1403,1405,1406,1408],{},"An absent key means open: no ",[211,1404,1329],{}," means the caller must supply the value; no\n",[211,1407,950],{}," means identity in both directions.",[196,1410,1411,1412,1415,1416,1419],{},"Only an explicitly declared boundary is emitted. Behaviour inferred from the shape, such\nas decoding a ",[211,1413,1414],{},"format: date-time"," field into a ",[211,1417,1418],{},"Date",", is derived again during\nreconstruction.",[196,1421,1422,1424,1425,1428,1429,1432,1433,1435,1436,1439,1440,1443],{},[211,1423,1278],{}," always names its members in the document, including a single-field constraint\n(",[211,1426,1427],{},"[[\"slug\"]]","). In memory a lone ",[211,1430,1431],{},"unique()"," does not yet know its key; ",[211,1434,358],{}," resolves\nit from the object passed to ",[211,1437,1438],{},"entity({...})",". A compound constraint such as\n",[211,1441,1442],{},"(listId, docId)"," appears in full on each member.",[440,1445,1447,1449],{"id":1446},"required-semantics",[211,1448,992],{}," semantics",[196,1451,1452,1453,1455],{},"In a Fougere card, ",[211,1454,992],{}," has a narrower meaning than in JSON Schema alone.",[196,1457,1458,1460,1461,1464,1465,1467,1468,1471,1472,1475,1476,1478],{},[211,1459,992],{}," lists ",[200,1462,1463],{},"the names a caller must supply at creation"," — those no ",[211,1466,1329],{},"\nrule answers the absence of, and that are not a ",[211,1469,1470],{},"many"," relation (absent → ",[211,1473,1474],{},"[]","). It is\nnarrower than JSON Schema's ",[211,1477,992],{},", which is context-free and answers \"what is always\npresent when read?\".",[196,1480,1481,1482,1484],{},"A nullable field therefore remains required: the caller may supply ",[211,1483,831],{},", but may not\nomit the key. Presence and nullability remain separate concepts.",[440,1486,1488],{"id":1487},"the-bundle-several-entities-relations-included","The bundle — several entities, relations included",[196,1490,1491,1494,1495,1498,1499,301],{},[211,1492,1493],{},"Bundle.fromSchemas"," produces a self-contained ",[211,1496,1497],{},"$defs"," document. Each entity uses its lowercased\nname, matching the value carried by ",[211,1500,1501],{},"relation.to",[224,1503,1505],{"className":226,"code":1504,"language":228,"meta":229,"style":229},"const bundle = Bundle.fromSchemas({ post: Post, author: Author });\nconst { post, author } = bundle.toSchemas();\n",[211,1506,1507,1555],{"__ignoreMap":229},[233,1508,1509,1511,1514,1516,1518,1520,1523,1526,1529,1533,1535,1537,1539,1542,1544,1547,1550,1553],{"class":235,"line":236},[233,1510,288],{"class":287},[233,1512,1513],{"class":291}," bundle",[233,1515,296],{"class":295},[233,1517,248],{"class":247},[233,1519,301],{"class":243},[233,1521,1522],{"class":304},"fromSchemas",[233,1524,1525],{"class":247},"(",[233,1527,1528],{"class":243},"{",[233,1530,1532],{"class":1531},"skxfh"," post",[233,1534,410],{"class":243},[233,1536,391],{"class":247},[233,1538,251],{"class":243},[233,1540,1541],{"class":1531}," author",[233,1543,410],{"class":243},[233,1545,1546],{"class":247}," Author ",[233,1548,1549],{"class":243},"}",[233,1551,1552],{"class":247},")",[233,1554,274],{"class":243},[233,1556,1557,1559,1561,1563,1565,1567,1569,1571,1573,1575,1578,1580],{"class":235,"line":277},[233,1558,288],{"class":287},[233,1560,244],{"class":243},[233,1562,1532],{"class":291},[233,1564,251],{"class":243},[233,1566,1541],{"class":291},[233,1568,257],{"class":243},[233,1570,296],{"class":295},[233,1572,1513],{"class":247},[233,1574,301],{"class":243},[233,1576,1577],{"class":304},"toSchemas",[233,1579,348],{"class":247},[233,1581,274],{"class":243},[196,1583,1584,1585,1588,1589,1591,1592,1595],{},"A relation is a pointer rather than an inlined sub-schema: ",[211,1586,1587],{},"Post → Author → Post"," produces\ntwo references instead of recursive nesting. ",[211,1590,362],{}," keeps the names;\n",[211,1593,1594],{},"Bundle.toSchemas"," resolves them to the target entities expected by adapters.",[440,1597,1599],{"id":1598},"serialization-limits","Serialization limits",[196,1601,1602],{},"A card can contain only serializable data:",[1604,1605,1606,1620],"ul",{},[1607,1608,1609,1612,1613,1615,1616,1619],"li",{},[200,1610,1611],{},"a relation becomes a name."," ",[211,1614,1594],{}," can resolve the ",[211,1617,1618],{},"() => Author"," thunk\nwithin a bundle.",[1607,1621,1622,1625,1626,1629],{},[200,1623,1624],{},"a custom generator or conversion is referenced by name",", then resolved against the\nconsumer's registry. An unknown name produces a local ",[211,1627,1628],{},"unknown generator"," error.",[196,1631,1632],{},"The axes therefore do not accept JavaScript closures, which cannot be serialized.",[440,1634,1636,1639],{"id":1635},"rpcdiscover-a-whole-apps-card",[211,1637,1638],{},"rpc.discover"," — a whole app's card",[196,1641,1642,1643,1645,1646,1649],{},"A host answers the reserved ",[211,1644,1638],{}," operation with what it hosts. Each frond\npublishes ",[200,1647,1648],{},"two lists, and they are duals",": what you may call, and what leaves on its own.",[224,1651,1653],{"className":461,"code":1652,"language":463,"meta":229,"style":229},"{\n  \"fronds\": [{\n    \"name\": \"blog\",\n    \"doors\": [{\n      \"name\": \"post\",\n      \"ops\": [\n        { \"name\": \"list\",     \"kind\": \"query\",   \"output\": { \u002F* a card *\u002F } },\n        { \"name\": \"findById\", \"kind\": \"query\",   \"output\": { \u002F* a card *\u002F } },\n        { \"name\": \"create\",   \"kind\": \"command\", \"input\": { \u002F* a card *\u002F },\n                                                 \"output\": { \u002F* a card *\u002F } },\n        { \"name\": \"delete\",   \"kind\": \"command\" },\n        { \"name\": \"publish\",  \"kind\": \"command\", \"description\": \"Make the post public.\" }\n      ],\n      \"schema\": { \u002F* a card *\u002F }\n    }],\n    \"facts\": [\n      { \"name\": \"postPublished\", \"schema\": { \u002F* a card *\u002F } }\n    ]\n  }]\n}\n",[211,1654,1655,1659,1673,1692,1705,1723,1737,1797,1850,1902,1921,1958,2013,2018,2035,2040,2053,2091,2096,2101],{"__ignoreMap":229},[233,1656,1657],{"class":235,"line":236},[233,1658,470],{"class":243},[233,1660,1661,1663,1666,1668,1670],{"class":235,"line":277},[233,1662,476],{"class":475},[233,1664,1665],{"class":479},"fronds",[233,1667,483],{"class":475},[233,1669,410],{"class":243},[233,1671,1672],{"class":243}," [{\n",[233,1674,1675,1677,1679,1681,1683,1685,1688,1690],{"class":235,"line":284},[233,1676,536],{"class":475},[233,1678,1321],{"class":413},[233,1680,483],{"class":475},[233,1682,410],{"class":243},[233,1684,488],{"class":263},[233,1686,1687],{"class":267},"blog",[233,1689,483],{"class":263},[233,1691,496],{"class":243},[233,1693,1694,1696,1699,1701,1703],{"class":235,"line":323},[233,1695,536],{"class":475},[233,1697,1698],{"class":413},"doors",[233,1700,483],{"class":475},[233,1702,410],{"class":243},[233,1704,1672],{"class":243},[233,1706,1707,1709,1711,1713,1715,1717,1719,1721],{"class":235,"line":533},[233,1708,551],{"class":475},[233,1710,1321],{"class":554},[233,1712,483],{"class":475},[233,1714,410],{"class":243},[233,1716,488],{"class":263},[233,1718,491],{"class":267},[233,1720,483],{"class":263},[233,1722,496],{"class":243},[233,1724,1725,1727,1730,1732,1734],{"class":235,"line":548},[233,1726,551],{"class":475},[233,1728,1729],{"class":554},"ops",[233,1731,483],{"class":475},[233,1733,410],{"class":243},[233,1735,1736],{"class":243}," [\n",[233,1738,1739,1742,1744,1746,1748,1750,1752,1755,1757,1759,1762,1765,1767,1769,1771,1774,1776,1778,1781,1784,1786,1788,1790,1793,1795],{"class":235,"line":570},[233,1740,1741],{"class":243},"        {",[233,1743,488],{"class":475},[233,1745,1321],{"class":589},[233,1747,483],{"class":475},[233,1749,410],{"class":243},[233,1751,488],{"class":263},[233,1753,1754],{"class":267},"list",[233,1756,483],{"class":263},[233,1758,251],{"class":243},[233,1760,1761],{"class":475},"     \"",[233,1763,1764],{"class":589},"kind",[233,1766,483],{"class":475},[233,1768,410],{"class":243},[233,1770,488],{"class":263},[233,1772,1773],{"class":267},"query",[233,1775,483],{"class":263},[233,1777,251],{"class":243},[233,1779,1780],{"class":475},"   \"",[233,1782,1783],{"class":589},"output",[233,1785,483],{"class":475},[233,1787,410],{"class":243},[233,1789,244],{"class":243},[233,1791,1792],{"class":319}," \u002F* a card *\u002F",[233,1794,257],{"class":243},[233,1796,612],{"class":243},[233,1798,1799,1801,1803,1805,1807,1809,1811,1814,1816,1818,1820,1822,1824,1826,1828,1830,1832,1834,1836,1838,1840,1842,1844,1846,1848],{"class":235,"line":583},[233,1800,1741],{"class":243},[233,1802,488],{"class":475},[233,1804,1321],{"class":589},[233,1806,483],{"class":475},[233,1808,410],{"class":243},[233,1810,488],{"class":263},[233,1812,1813],{"class":267},"findById",[233,1815,483],{"class":263},[233,1817,251],{"class":243},[233,1819,488],{"class":475},[233,1821,1764],{"class":589},[233,1823,483],{"class":475},[233,1825,410],{"class":243},[233,1827,488],{"class":263},[233,1829,1773],{"class":267},[233,1831,483],{"class":263},[233,1833,251],{"class":243},[233,1835,1780],{"class":475},[233,1837,1783],{"class":589},[233,1839,483],{"class":475},[233,1841,410],{"class":243},[233,1843,244],{"class":243},[233,1845,1792],{"class":319},[233,1847,257],{"class":243},[233,1849,612],{"class":243},[233,1851,1852,1854,1856,1858,1860,1862,1864,1866,1868,1870,1872,1874,1876,1878,1880,1883,1885,1887,1889,1892,1894,1896,1898,1900],{"class":235,"line":615},[233,1853,1741],{"class":243},[233,1855,488],{"class":475},[233,1857,1321],{"class":589},[233,1859,483],{"class":475},[233,1861,410],{"class":243},[233,1863,488],{"class":263},[233,1865,631],{"class":267},[233,1867,483],{"class":263},[233,1869,251],{"class":243},[233,1871,1780],{"class":475},[233,1873,1764],{"class":589},[233,1875,483],{"class":475},[233,1877,410],{"class":243},[233,1879,488],{"class":263},[233,1881,1882],{"class":267},"command",[233,1884,483],{"class":263},[233,1886,251],{"class":243},[233,1888,488],{"class":475},[233,1890,1891],{"class":589},"input",[233,1893,483],{"class":475},[233,1895,410],{"class":243},[233,1897,244],{"class":243},[233,1899,1792],{"class":319},[233,1901,612],{"class":243},[233,1903,1904,1907,1909,1911,1913,1915,1917,1919],{"class":235,"line":662},[233,1905,1906],{"class":475},"                                                 \"",[233,1908,1783],{"class":589},[233,1910,483],{"class":475},[233,1912,410],{"class":243},[233,1914,244],{"class":243},[233,1916,1792],{"class":319},[233,1918,257],{"class":243},[233,1920,612],{"class":243},[233,1922,1923,1925,1927,1929,1931,1933,1935,1938,1940,1942,1944,1946,1948,1950,1952,1954,1956],{"class":235,"line":668},[233,1924,1741],{"class":243},[233,1926,488],{"class":475},[233,1928,1321],{"class":589},[233,1930,483],{"class":475},[233,1932,410],{"class":243},[233,1934,488],{"class":263},[233,1936,1937],{"class":267},"delete",[233,1939,483],{"class":263},[233,1941,251],{"class":243},[233,1943,1780],{"class":475},[233,1945,1764],{"class":589},[233,1947,483],{"class":475},[233,1949,410],{"class":243},[233,1951,488],{"class":263},[233,1953,1882],{"class":267},[233,1955,483],{"class":263},[233,1957,612],{"class":243},[233,1959,1960,1962,1964,1966,1968,1970,1972,1975,1977,1979,1981,1983,1985,1987,1989,1991,1993,1995,1997,2000,2002,2004,2006,2009,2011],{"class":235,"line":674},[233,1961,1741],{"class":243},[233,1963,488],{"class":475},[233,1965,1321],{"class":589},[233,1967,483],{"class":475},[233,1969,410],{"class":243},[233,1971,488],{"class":263},[233,1973,1974],{"class":267},"publish",[233,1976,483],{"class":263},[233,1978,251],{"class":243},[233,1980,476],{"class":475},[233,1982,1764],{"class":589},[233,1984,483],{"class":475},[233,1986,410],{"class":243},[233,1988,488],{"class":263},[233,1990,1882],{"class":267},[233,1992,483],{"class":263},[233,1994,251],{"class":243},[233,1996,488],{"class":475},[233,1998,1999],{"class":589},"description",[233,2001,483],{"class":475},[233,2003,410],{"class":243},[233,2005,488],{"class":263},[233,2007,2008],{"class":267},"Make the post public.",[233,2010,483],{"class":263},[233,2012,659],{"class":243},[233,2014,2015],{"class":235,"line":731},[233,2016,2017],{"class":243},"      ],\n",[233,2019,2020,2022,2025,2027,2029,2031,2033],{"class":235,"line":794},[233,2021,551],{"class":475},[233,2023,2024],{"class":554},"schema",[233,2026,483],{"class":475},[233,2028,410],{"class":243},[233,2030,244],{"class":243},[233,2032,1792],{"class":319},[233,2034,659],{"class":243},[233,2036,2037],{"class":235,"line":808},[233,2038,2039],{"class":243},"    }],\n",[233,2041,2042,2044,2047,2049,2051],{"class":235,"line":839},[233,2043,536],{"class":475},[233,2045,2046],{"class":413},"facts",[233,2048,483],{"class":475},[233,2050,410],{"class":243},[233,2052,1736],{"class":243},[233,2054,2055,2058,2060,2062,2064,2066,2068,2071,2073,2075,2077,2079,2081,2083,2085,2087,2089],{"class":235,"line":860},[233,2056,2057],{"class":243},"      {",[233,2059,488],{"class":475},[233,2061,1321],{"class":554},[233,2063,483],{"class":475},[233,2065,410],{"class":243},[233,2067,488],{"class":263},[233,2069,2070],{"class":267},"postPublished",[233,2072,483],{"class":263},[233,2074,251],{"class":243},[233,2076,488],{"class":475},[233,2078,2024],{"class":554},[233,2080,483],{"class":475},[233,2082,410],{"class":243},[233,2084,244],{"class":243},[233,2086,1792],{"class":319},[233,2088,257],{"class":243},[233,2090,659],{"class":243},[233,2092,2093],{"class":235,"line":903},[233,2094,2095],{"class":243},"    ]\n",[233,2097,2098],{"class":235,"line":908},[233,2099,2100],{"class":243},"  }]\n",[233,2102,2103],{"class":235,"line":981},[233,2104,1057],{"class":243},[196,2106,2107,2108,2110,2111,2113,2114,2116,2117,2119,2120,2123,2124,2127,2128,2130,2131,2133,2134,2136,2137,2139],{},"An operation always says its ",[211,2109,1321],{}," and its ",[211,2112,1764],{}," — ",[211,2115,1773],{}," reads, ",[211,2118,1882],{}," writes, which\nis the same call REST turns into ",[211,2121,2122],{},"GET"," versus ",[211,2125,2126],{},"POST",". The rest is present when there is\nsomething to say: ",[211,2129,1891],{}," and ",[211,2132,1783],{}," when the contract names a view, and ",[211,2135,1999],{},"\nwhen the method carries a doc sentence. ",[211,2138,1937],{}," names neither view above because a boolean\nis not a shape.",[196,2141,2142,2144,2145,2148,2149,2152],{},[211,2143,2024],{}," is optional on both lists, and its absence says something different on each. A\n",[200,2146,2147],{},"door"," with no schema stores nothing — a health check, a computation, a search across\nseveral shapes. A ",[200,2150,2151],{},"fact"," with no schema announces a type the host does not store.",[1076,2154,2156],{"id":2155},"why-facts-are-a-separate-list","Why facts are a separate list",[196,2158,2159,2160,2162],{},"Hosting means answering: an entity with no façade is deliberately absent from ",[211,2161,1698],{},", or\nthe card would publish the shape of tables nobody can reach — the auth tables, typically.",[196,2164,2165,2166,2168,2169,2172,2173,2176,2177,2180],{},"A ",[208,2167,2151],{"href":106}," is the opposite case. It carries no operation either, but\nsomeone ",[200,2170,2171],{},"wrote"," that it leaves (",[211,2174,2175],{},"Emit\u003CPostPublished>","), so publishing its shape honours a statement instead of\nleaking one. Without this list a fact stopped at the repository boundary: colocation gives\nthe contract, ",[211,2178,2179],{},"remotes:"," gives only the location, and across two repositories there is no\ncolocation. The subscriber had to hand-copy the emitter's declaration.",[196,2182,2183,2185,2186,2189],{},[211,2184,2046],{}," is the same on every ",[208,2187,2188],{"href":156},"surface"," — a door has an audience, a\nfact does not.",[196,2191,2192,2193,2195,2196,2199],{},"The doublure router reads ",[211,2194,1698],{}," only, and uses them to associate entities with the\naddresses declared in ",[211,2197,2198],{},"remotes",". A fact is not routable: nobody calls it, it arrives.",[440,2201,2203],{"id":2202},"writing-a-frond-elsewhere","Writing a Frond elsewhere",[196,2205,2206],{},"None of this assumes TypeScript. A frond written in another language joins the topology if\nit honours three things:",[2208,2209,2210,2225,2236],"ol",{},[1607,2211,2212,2113,2215,2218,2219,2222,2223,301],{},[200,2213,2214],{},"the wire",[211,2216,2217],{},"POST \u002F_fougere\u002Fcall",", JSON-RPC 2.0, ",[211,2220,2221],{},"method = \"entity.op\"",";\nsee ",[208,2224,151],{"href":152},[1607,2226,2227,2113,2230,2232,2233,301],{},[200,2228,2229],{},"the card",[211,2231,1638],{}," returns the envelope above, ",[211,2234,2235],{},"x-fougere-version: 1",[1607,2237,2238,2241,2242,2245,2246,2249,2250,2252,2253,2256,2257,2260],{},[200,2239,2240],{},"the error vocabulary"," — a whole ",[211,2243,2244],{},"FougereError"," in ",[211,2247,2248],{},"error.data",", its ",[211,2251,211],{}," a\n",[208,2254,2255],{"href":98},"semantic code","; the ",[211,2258,2259],{},"-32000"," integer stays the JSON-RPC spec's.",[196,2262,2263],{},"The consumer then rebuilds the schema and validates data locally with the same rules.",[196,2265,2266,2269,2270,2272],{},[211,2267,2268],{},"demos\u002Frust-frond\u002F"," is one, in Rust — one entity, three operations, no ",[211,2271,1438],{},"\nclass anywhere.",[196,2274,2275,2276,2278],{},"Next: ",[208,2277,81],{"href":82}," — operations, binding rules, output scoping.",[2280,2281,2282],"style",{},"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 .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}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}html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .s_hVV, html code.shiki .s_hVV{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}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 .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 .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sucvu, html code.shiki .sucvu{--shiki-light:#E53935;--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sZMiF, html code.shiki .sZMiF{--shiki-light:#E2931D;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s39Yj, html code.shiki .s39Yj{--shiki-light:#39ADB5;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sseR_, html code.shiki .sseR_{--shiki-light:#9C3EDA;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .swQdS, html code.shiki .swQdS{--shiki-light:#E53935;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sAQsV, html code.shiki .sAQsV{--shiki-light:#916B53;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sptTA, html code.shiki .sptTA{--shiki-light:#6182B8;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}",{"title":229,"searchDepth":277,"depth":277,"links":2284},[2285,2288,2290,2292,2293,2294,2298],{"id":442,"depth":277,"text":443,"children":2286},[2287],{"id":1078,"depth":284,"text":1079},{"id":1224,"depth":277,"text":2289},"The three axes under x-fougere",{"id":1446,"depth":277,"text":2291},"required semantics",{"id":1487,"depth":277,"text":1488},{"id":1598,"depth":277,"text":1599},{"id":1635,"depth":277,"text":2295,"children":2296},"rpc.discover — a whole app's card",[2297],{"id":2155,"depth":284,"text":2156},{"id":2202,"depth":277,"text":2203},"The portable JSON format for a Fougere schema and its x-fougere extensions.","md",{},{"title":64,"description":2299},"VB-_FeiTvuoOc5UR7WnaS15_2vxpy8lxHj648WNyciA",1788560230923]