[{"data":1,"prerenderedAt":2907},["ShallowReactive",2],{"fougere:post.list:{}":3,"reference:\u002Freference\u002Fcli":6,"reference-pages":2689},{"items":4,"hasMore":5},[],false,{"id":7,"title":8,"body":9,"description":2681,"extension":2682,"file":2683,"meta":2684,"navigation":623,"path":2685,"seo":2686,"stem":2687,"__hash__":2688},"reference\u002Freference\u002F01.cli.md","CLI",{"type":10,"value":11,"toc":2641},"minimark",[12,16,24,50,58,96,123,154,181,302,329,358,361,369,449,454,461,495,506,524,535,538,944,965,978,1028,1049,1068,1083,1099,1106,1151,1158,1165,1185,1197,1315,1325,1336,1438,1449,1460,1467,1474,1546,1556,1587,1591,1640,1654,1666,1672,1698,1716,1738,1741,1748,1763,1770,1867,1877,1884,1940,1943,1949,1969,1972,1978,1985,1991,2003,2009,2015,2018,2024,2027,2035,2042,2063,2071,2077,2080,2086,2089,2096,2149,2159,2165,2232,2239,2245,2252,2291,2311,2318,2339,2345,2356,2363,2389,2400,2406,2413,2419,2460,2470,2481,2488,2495,2502,2517,2524,2527,2534,2549,2560,2567,2588,2596,2603,2618,2637],[13,14,8],"h1",{"id":15},"cli",[17,18,19,23],"p",{},[20,21,22],"code",{},"@fougere\u002Fcli"," creates a workspace, hosts a frond in a separate process, and invokes an\noperation from a shell. The CLI itself uses entities and handlers, so its options are\nvalidated from their schemas.",[25,26,27],"blockquote",{},[17,28,29,33,34,37,38,41,42,45,46,49],{},[30,31,32],"strong",{},"Alpha."," On npm under the ",[20,35,36],{},"alpha"," tag — ",[20,39,40],{},"npx fougere@alpha"," runs it without\ninstalling, ",[20,43,44],{},"npm create fougere"," enters it at ",[20,47,48],{},"new",". The commands and flags below are\nwhat ships.",[51,52,54,57],"h2",{"id":53},"fougere-new-compose-a-workspace",[20,55,56],{},"fougere new"," — compose a workspace",[59,60,65],"pre",{"className":61,"code":62,"language":63,"meta":64,"style":64},"language-bash shiki shiki-themes material-theme-lighter fougere-pastel material-theme-palenight","fougere new shop --frond blog --app nuxt\n","bash","",[20,66,67],{"__ignoreMap":64},[68,69,72,76,80,83,87,90,93],"span",{"class":70,"line":71},"line",1,[68,73,75],{"class":74},"sV8pK","fougere",[68,77,79],{"class":78},"sN-8n"," new",[68,81,82],{"class":78}," shop",[68,84,86],{"class":85},"svHQO"," --frond",[68,88,89],{"class":78}," blog",[68,91,92],{"class":85}," --app",[68,94,95],{"class":78}," nuxt\n",[17,97,98,99,102,103,106,107,110,111,114,115,118,119,122],{},"With no ",[20,100,101],{},"--frond",", ",[20,104,105],{},"--app"," or ",[20,108,109],{},"--blank",", it asks in three steps — the project, its fronds, its\napps — and draws beside each one the tree it will write and the command above that writes it again\nwith no prompt. ",[20,112,113],{},"+"," adds a second piece of the same template, ",[20,116,117],{},"r"," renames one, ← goes back. A name\nthat already exists is offered for replacement, and the old project goes only once the new one is\nwhole; ",[20,120,121],{},"--force"," replaces without asking. Nothing touches the disk before the last ⏎, and a write\nthat fails halfway leaves nothing either. Without a terminal it asks nothing and refuses, naming\nthe flags.",[17,124,125,126,102,129,102,132,102,135,138,139,142,143,146,147,149,150,153],{},"The composer offers ",[20,127,128],{},"nuxt",[20,130,131],{},"next",[20,133,134],{},"react",[20,136,137],{},"svelte"," and ",[20,140,141],{},"admin"," — the hosts ",[20,144,145],{},"door:check"," runs\nend to end from a fresh workspace; ",[20,148,105],{}," also takes ",[20,151,152],{},"oclif",".",[17,155,156,159,160,162,163,166,167,102,170,102,173,176,177,180],{},[30,157,158],{},"An app's shell is its host's own."," ",[20,161,56],{}," runs the host's official tool — ",[20,164,165],{},"create-nuxt",",\n",[20,168,169],{},"create-next-app",[20,171,172],{},"create-vite",[20,174,175],{},"sv create"," — with a major pinned, so the versions, the tsconfig\nand the config file are what that tool writes today, not what someone copied once. Fougere then\nadds its part, which each host declares in its package (",[20,178,179],{},"template\u002Fscaffold.json","):",[182,183,184,200],"table",{},[185,186,187],"thead",{},[188,189,190,194,197],"tr",{},[191,192,193],"th",{},"Host",[191,195,196],{},"Its tool",[191,198,199],{},"What Fougere adds",[201,202,203,224,247,273,290],"tbody",{},[188,204,205,210,215],{},[206,207,208],"td",{},[20,209,128],{},[206,211,212],{},[20,213,214],{},"create-nuxt@3",[206,216,217,220,221],{},[20,218,219],{},"@fougere\u002Fnuxt"," in ",[20,222,223],{},"modules",[188,225,226,230,235],{},[206,227,228],{},[20,229,131],{},[206,231,232],{},[20,233,234],{},"create-next-app@16",[206,236,237,240,241,220,244],{},[20,238,239],{},"withFougere(nextConfig)",", the call and session routes, ",[20,242,243],{},"@fronds\u002Ffacade",[20,245,246],{},"paths",[188,248,249,255,260],{},[206,250,251,102,253],{},[20,252,134],{},[20,254,141],{},[206,256,257],{},[20,258,259],{},"create-vite@9 --template react-ts",[206,261,262,265,266,102,269,220,271],{},[20,263,264],{},"fougere()"," first in ",[20,267,268],{},"plugins",[20,270,243],{},[20,272,246],{},[188,274,275,279,284],{},[206,276,277],{},[20,278,137],{},[206,280,281],{},[20,282,283],{},"sv@0.17 create --template minimal",[206,285,286,265,288],{},[20,287,264],{},[20,289,268],{},[188,291,292,296,299],{},[206,293,294],{},[20,295,152],{},[206,297,298],{},"—",[206,300,301],{},"the whole starter, copied: no tool writes a terminal app's shell",[17,303,304,305,308,309,312,313,316,317,320,321,324,325,328],{},"Every app also gets Fougere's dependencies and its first page, and loses what the page replaces.\nWith the ",[20,306,307],{},"blog"," frond, each app also gets ",[20,310,311],{},"\u002Fposts",": one page that lists the posts, creates a draft\nwith ",[20,314,315],{},"useFormFor(Post)"," and publishes it with ",[20,318,319],{},"useCommand(post, 'publish')"," — the three primitives,\nin that host's own syntax. It lives in the CLI, never in the frond: a frond names no host.\nNone of them names the workspace: a host finds its fronds by walking up from the app to the\nnearest directory that holds ",[20,322,323],{},"fronds\u002F",", so ",[20,326,327],{},"root"," is only written when they sit elsewhere.\nThe shell is the one step that needs the network.",[59,330,332],{"className":61,"code":331,"language":63,"meta":64,"style":64},"fougere new shop --frond blog --app \"nuxt:web,oclif:ops\"\n",[20,333,334],{"__ignoreMap":64},[68,335,336,338,340,342,344,346,348,352,355],{"class":70,"line":71},[68,337,75],{"class":74},[68,339,79],{"class":78},[68,341,82],{"class":78},[68,343,86],{"class":85},[68,345,89],{"class":78},[68,347,92],{"class":85},[68,349,351],{"class":350},"sDDC1"," \"",[68,353,354],{"class":78},"nuxt:web,oclif:ops",[68,356,357],{"class":350},"\"\n",[17,359,360],{},"The command creates fronds first, followed by the apps that consume them. It produces a\nworkspace whose members are the apps:",[59,362,367],{"className":363,"code":365,"language":366},[364],"language-text","shop\u002F\n  fougere.config.ts          ← sources, auth, topology\n  package.json               ← \"workspaces\": [\"apps\u002F*\"], and the fronds' dependencies\n  tests\u002Fboots.test.ts        ← `npm test`: the whole project boots, as `fronds:` places it\n  fronds\u002Fblog\u002F               ← the domain\n    entities\u002FPost.ts\n    handlers\u002FPostHandler.ts\n  apps\u002Fnuxt\u002F                 ← the consumer — create-nuxt's shell\n    nuxt.config.ts             ← + @fougere\u002Fnuxt\n    app\u002Fpages\u002Findex.vue        ← Fougere's first page\n","text",[20,368,365],{"__ignoreMap":64},[182,370,371,381],{},[185,372,373],{},[188,374,375,378],{},[191,376,377],{},"Flag",[191,379,380],{},"What it does",[201,382,383,397,407,416,430,439],{},[188,384,385,390],{},[206,386,387],{},[20,388,389],{},"--frond blog,api:catalog",[206,391,392,393,396],{},"Fronds to add — ",[20,394,395],{},"template:name"," renames; the template name is the default name",[188,398,399,404],{},[206,400,401],{},[20,402,403],{},"--app nuxt:web",[206,405,406],{},"same, for apps",[188,408,409,413],{},[206,410,411],{},[20,412,109],{},[206,414,415],{},"the empty shell, nothing composed",[188,417,418,423],{},[206,419,420],{},[20,421,422],{},"--local",[206,424,425,426,429],{},"link ",[20,427,428],{},"@fougere\u002F*"," to a local Fougere checkout (development)",[188,431,432,436],{},[206,433,434],{},[20,435,121],{},[206,437,438],{},"overwrite an existing directory",[188,440,441,446],{},[206,442,443],{},[20,444,445],{},"--package-manager \u003Cnpm|pnpm|bun|yarn>",[206,447,448],{},"Write the project for this one, whoever ran the command",[450,451,453],"h3",{"id":452},"which-package-manager","Which package manager",[17,455,456,457,460],{},"The project is written for one package manager — its scripts, its workspace file, its build\npermissions, its ",[20,458,459],{},"packageManager"," field. Nothing asks which, unless nothing can tell:",[462,463,464,471,487,492],"ol",{},[465,466,467,470],"li",{},[20,468,469],{},"--package-manager",", when the command states it;",[465,472,473,474,102,477,102,480,102,483,486],{},"the one that launched the command — ",[20,475,476],{},"npm create",[20,478,479],{},"pnpx",[20,481,482],{},"bunx",[20,484,485],{},"yarn dlx",";",[465,488,489,490,486],{},"the project the new one is created inside — its lockfile or its ",[20,491,459],{},[465,493,494],{},"asked, when a terminal is there to answer; npm otherwise, said in the output.",[17,496,497,498,501,502,505],{},"npm, pnpm, bun and yarn 4 are written for. yarn 1 has neither ",[20,499,500],{},"dlx"," nor ",[20,503,504],{},"workspaces foreach",", so a\nproject it starts is written for npm.",[17,507,508,509,512,513,515,516,519,520,523],{},"A Frond is not a member of the workspace: ",[20,510,511],{},"@fronds\u002F\u003Cname>"," resolves by the ",[20,514,246],{}," of its\n",[20,517,518],{},"tsconfig.json"," and by each host, never through ",[20,521,522],{},"node_modules",", so a frond created a second ago\nanswers without an install.",[17,525,526,529,530,138,532,534],{},[30,527,528],{},"Arguments or interactive mode."," With ",[20,531,101],{},[20,533,105],{},", the command asks no\nquestions and can run in a script or CI job. Without these options, it prompts for\ntemplates in a TTY. Interactive mode is not available without a TTY.",[17,536,537],{},"The generated frond contains an entity, the five operations its repository gives, a business operation,\nand a repository holding the one query worth a name:",[59,539,543],{"className":540,"code":541,"language":542,"meta":64,"style":64},"language-ts shiki shiki-themes material-theme-lighter fougere-pastel material-theme-palenight","\u002F\u002F services\u002FPostRepository.ts\nexport class PostCard extends Post.pick('id', 'title', 'status') {}\n\nexport default class PostRepository extends Repository\u003CPost> {\n  published(): Promise\u003CPostCard[]> {\n    return this.output(PostCard).findAllBy({ status: 'published' });\n  }\n}\n\n\u002F\u002F handlers\u002FPostHandler.ts\nexport default class PostHandler extends Repository\u003CPost> {\n  constructor(private posts: PostRepository) {\n    super();\n  }\n\n  \u002F** The draft→published transition. *\u002F\n  async publish(id: Post['id']): Promise\u003CPost> { … }\n\n  \u002F** Only published posts, projected to the card. *\u002F\n  async listPublished(): Promise\u003CPostCard[]> {\n    return this.posts.published();\n  }\n}\n","ts",[20,544,545,551,618,625,655,680,734,740,746,751,757,781,804,816,821,826,832,880,885,891,913,934,939],{"__ignoreMap":64},[68,546,547],{"class":70,"line":71},[68,548,550],{"class":549},"skXKP","\u002F\u002F services\u002FPostRepository.ts\n",[68,552,554,558,562,566,569,573,576,580,584,587,590,592,595,598,601,603,605,607,610,612,615],{"class":70,"line":553},2,[68,555,557],{"class":556},"sK6XW","export",[68,559,561],{"class":560},"s76I7"," class",[68,563,565],{"class":564},"sBZYL"," PostCard",[68,567,568],{"class":560}," extends",[68,570,572],{"class":571},"sPEhv"," Post",[68,574,153],{"class":575},"s15xx",[68,577,579],{"class":578},"s4mR9","pick",[68,581,583],{"class":582},"srlTG","(",[68,585,586],{"class":350},"'",[68,588,589],{"class":78},"id",[68,591,586],{"class":350},[68,593,594],{"class":575},",",[68,596,597],{"class":350}," '",[68,599,600],{"class":78},"title",[68,602,586],{"class":350},[68,604,594],{"class":575},[68,606,597],{"class":350},[68,608,609],{"class":78},"status",[68,611,586],{"class":350},[68,613,614],{"class":582},")",[68,616,617],{"class":575}," {}\n",[68,619,621],{"class":70,"line":620},3,[68,622,624],{"emptyLinePlaceholder":623},true,"\n",[68,626,628,630,633,635,638,640,643,646,649,652],{"class":70,"line":627},4,[68,629,557],{"class":556},[68,631,632],{"class":556}," default",[68,634,561],{"class":560},[68,636,637],{"class":564}," PostRepository",[68,639,568],{"class":560},[68,641,642],{"class":564}," Repository",[68,644,645],{"class":575},"\u003C",[68,647,648],{"class":564},"Post",[68,650,651],{"class":575},">",[68,653,654],{"class":575}," {\n",[68,656,658,662,665,668,670,673,676,678],{"class":70,"line":657},5,[68,659,661],{"class":660},"shDkW","  published",[68,663,664],{"class":575},"():",[68,666,667],{"class":564}," Promise",[68,669,645],{"class":575},[68,671,672],{"class":564},"PostCard",[68,674,675],{"class":582},"[]",[68,677,651],{"class":575},[68,679,654],{"class":575},[68,681,683,686,690,692,695,698,700,702,704,707,709,712,716,719,721,724,726,729,731],{"class":70,"line":682},6,[68,684,685],{"class":556},"    return",[68,687,689],{"class":688},"sxG60"," this",[68,691,153],{"class":575},[68,693,694],{"class":578},"output",[68,696,583],{"class":697},"spAFX",[68,699,672],{"class":571},[68,701,614],{"class":697},[68,703,153],{"class":575},[68,705,706],{"class":578},"findAllBy",[68,708,583],{"class":697},[68,710,711],{"class":575},"{",[68,713,715],{"class":714},"sHtqg"," status",[68,717,718],{"class":575},":",[68,720,597],{"class":350},[68,722,723],{"class":78},"published",[68,725,586],{"class":350},[68,727,728],{"class":575}," }",[68,730,614],{"class":697},[68,732,733],{"class":575},";\n",[68,735,737],{"class":70,"line":736},7,[68,738,739],{"class":575},"  }\n",[68,741,743],{"class":70,"line":742},8,[68,744,745],{"class":575},"}\n",[68,747,749],{"class":70,"line":748},9,[68,750,624],{"emptyLinePlaceholder":623},[68,752,754],{"class":70,"line":753},10,[68,755,756],{"class":549},"\u002F\u002F handlers\u002FPostHandler.ts\n",[68,758,760,762,764,766,769,771,773,775,777,779],{"class":70,"line":759},11,[68,761,557],{"class":556},[68,763,632],{"class":556},[68,765,561],{"class":560},[68,767,768],{"class":564}," PostHandler",[68,770,568],{"class":560},[68,772,642],{"class":564},[68,774,645],{"class":575},[68,776,648],{"class":564},[68,778,651],{"class":575},[68,780,654],{"class":575},[68,782,784,787,789,792,796,798,800,802],{"class":70,"line":783},12,[68,785,786],{"class":560},"  constructor",[68,788,583],{"class":575},[68,790,791],{"class":560},"private",[68,793,795],{"class":794},"shDUQ"," posts",[68,797,718],{"class":575},[68,799,637],{"class":564},[68,801,614],{"class":575},[68,803,654],{"class":575},[68,805,807,811,814],{"class":70,"line":806},13,[68,808,810],{"class":809},"sTljH","    super",[68,812,813],{"class":697},"()",[68,815,733],{"class":575},[68,817,819],{"class":70,"line":818},14,[68,820,739],{"class":575},[68,822,824],{"class":70,"line":823},15,[68,825,624],{"emptyLinePlaceholder":623},[68,827,829],{"class":70,"line":828},16,[68,830,831],{"class":549},"  \u002F** The draft→published transition. *\u002F\n",[68,833,835,838,841,843,845,847,849,852,854,856,858,861,863,865,867,869,871,874,878],{"class":70,"line":834},17,[68,836,837],{"class":560},"  async",[68,839,840],{"class":660}," publish",[68,842,583],{"class":575},[68,844,589],{"class":794},[68,846,718],{"class":575},[68,848,572],{"class":564},[68,850,851],{"class":582},"[",[68,853,586],{"class":350},[68,855,589],{"class":78},[68,857,586],{"class":350},[68,859,860],{"class":582},"]",[68,862,180],{"class":575},[68,864,667],{"class":564},[68,866,645],{"class":575},[68,868,648],{"class":564},[68,870,651],{"class":575},[68,872,873],{"class":575}," {",[68,875,877],{"class":876},"ssXpW"," … ",[68,879,745],{"class":575},[68,881,883],{"class":70,"line":882},18,[68,884,624],{"emptyLinePlaceholder":623},[68,886,888],{"class":70,"line":887},19,[68,889,890],{"class":549},"  \u002F** Only published posts, projected to the card. *\u002F\n",[68,892,894,896,899,901,903,905,907,909,911],{"class":70,"line":893},20,[68,895,837],{"class":560},[68,897,898],{"class":660}," listPublished",[68,900,664],{"class":575},[68,902,667],{"class":564},[68,904,645],{"class":575},[68,906,672],{"class":564},[68,908,675],{"class":582},[68,910,651],{"class":575},[68,912,654],{"class":575},[68,914,916,918,920,922,926,928,930,932],{"class":70,"line":915},21,[68,917,685],{"class":556},[68,919,689],{"class":688},[68,921,153],{"class":575},[68,923,925],{"class":924},"sy9f4","posts",[68,927,153],{"class":575},[68,929,723],{"class":578},[68,931,813],{"class":697},[68,933,733],{"class":575},[68,935,937],{"class":70,"line":936},22,[68,938,739],{"class":575},[68,940,942],{"class":70,"line":941},23,[68,943,745],{"class":575},[17,945,946,949,950,952,953,956,957,960,961,964],{},[20,947,948],{},"create"," is not redefined: ",[20,951,609],{}," is ",[20,954,955],{},"readOnly",", so the entity already refuses it on the way in.\n",[20,958,959],{},"output(PostCard)"," reads only the card's fields, so the body never leaves. The handler never\ntouches a storage: it reaches rows through the operations it inherits (",[20,962,963],{},"super.findById",") and\nthrough the repository it asked for.",[51,966,968,102,971,102,974,977],{"id":967},"fougere-dev-build-serve-one-frond-its-own-process",[20,969,970],{},"fougere dev",[20,972,973],{},"build",[20,975,976],{},"serve"," — one frond, its own process",[59,979,981],{"className":61,"code":980,"language":63,"meta":64,"style":64},"fougere dev blog --port 4100     # from the sources, booted again at every change\nfougere build                    # the project as JavaScript, in .fougere\u002Fbuild\u002F\nfougere serve blog --port 4100   # what the build wrote, with Node alone\n",[20,982,983,1002,1012],{"__ignoreMap":64},[68,984,985,987,990,992,995,999],{"class":70,"line":71},[68,986,75],{"class":74},[68,988,989],{"class":78}," dev",[68,991,89],{"class":78},[68,993,994],{"class":85}," --port",[68,996,998],{"class":997},"s3dPA"," 4100",[68,1000,1001],{"class":549},"     # from the sources, booted again at every change\n",[68,1003,1004,1006,1009],{"class":70,"line":553},[68,1005,75],{"class":74},[68,1007,1008],{"class":78}," build",[68,1010,1011],{"class":549},"                    # the project as JavaScript, in .fougere\u002Fbuild\u002F\n",[68,1013,1014,1016,1019,1021,1023,1025],{"class":70,"line":620},[68,1015,75],{"class":74},[68,1017,1018],{"class":78}," serve",[68,1020,89],{"class":78},[68,1022,994],{"class":85},[68,1024,998],{"class":997},[68,1026,1027],{"class":549},"   # what the build wrote, with Node alone\n",[17,1029,1030,1031,1034,1035,1040,1041,1044,1045,153],{},"Each starts that frond alone and exposes it over JSON-RPC on ",[20,1032,1033],{},"POST \u002F_fougere\u002Fcall",", with its REST\nand GraphQL beside it (",[1036,1037,1039],"a",{"href":1038},"\u002Fdocs\u002Fadopt\u002Fhosts#any-engine","any engine","). The consuming app sets its\naddress in ",[20,1042,1043],{},"fronds:"," to route calls to that host. See\n",[1036,1046,1048],{"href":1047},"\u002Fdocs\u002Fconcepts\u002Fconfiguration","the gradient",[17,1050,1051,1054,1055,1057,1058,1061,1062,1064,1065,1067],{},[20,1052,1053],{},"dev"," transpiles the sources as they load, so a frond created a second ago answers. ",[20,1056,976],{},"\nloads no TypeScript and no loader: ",[20,1059,1060],{},"fougere build"," compiled what the config and the statement\nreach, and ",[20,1063,511],{}," resolves through the table it wrote beside them. Without a build,\n",[20,1066,976],{}," refuses and says to run one. It needs Node 22.15 or later, or Bun.",[17,1069,1070,1071,1074,1075,1077,1078,1082],{},"It does ",[30,1072,1073],{},"not"," follow ",[20,1076,1043],{}," itself: a host ",[1079,1080,1081],"em",{},"is"," the frond, it does not route back\nout.",[25,1084,1085],{},[17,1086,1087,1090,1091,1094,1095,1098],{},[20,1088,1089],{},"serve()"," binds ",[20,1092,1093],{},"127.0.0.1"," unless ",[20,1096,1097],{},"hosts"," says otherwise: a receiver reads identity\noff the wire, so the default keeps it on the machine and widening it is a decision\nwritten down.",[51,1100,1102,1105],{"id":1101},"fougere-call-invoke-an-operation",[20,1103,1104],{},"fougere call"," — invoke an operation",[59,1107,1109],{"className":61,"code":1108,"language":63,"meta":64,"style":64},"fougere call post.list\nfougere call post.create --title \"Hello\" --body \"…\"\n",[20,1110,1111,1121],{"__ignoreMap":64},[68,1112,1113,1115,1118],{"class":70,"line":71},[68,1114,75],{"class":74},[68,1116,1117],{"class":78}," call",[68,1119,1120],{"class":78}," post.list\n",[68,1122,1123,1125,1127,1130,1133,1135,1138,1141,1144,1146,1149],{"class":70,"line":553},[68,1124,75],{"class":74},[68,1126,1117],{"class":78},[68,1128,1129],{"class":78}," post.create",[68,1131,1132],{"class":85}," --title",[68,1134,351],{"class":350},[68,1136,1137],{"class":78},"Hello",[68,1139,1140],{"class":350},"\"",[68,1142,1143],{"class":85}," --body",[68,1145,351],{"class":350},[68,1147,1148],{"class":78},"…",[68,1150,357],{"class":350},[17,1152,1153,1154,1157],{},"The command uses the same envelope, validation, and typed errors as other clients. A\n",[20,1155,1156],{},"VALIDATION_FAILED"," error therefore keeps the format received by a page.",[51,1159,1161,1164],{"id":1160},"fougere-sync-consume-a-remote-frond",[20,1162,1163],{},"fougere sync"," — consume a remote frond",[59,1166,1168],{"className":61,"code":1167,"language":63,"meta":64,"style":64},"fougere sync blog --from http:\u002F\u002Fblog-service:4100\n",[20,1169,1170],{"__ignoreMap":64},[68,1171,1172,1174,1177,1179,1182],{"class":70,"line":71},[68,1173,75],{"class":74},[68,1175,1176],{"class":78}," sync",[68,1178,89],{"class":78},[68,1180,1181],{"class":85}," --from",[68,1183,1184],{"class":78}," http:\u002F\u002Fblog-service:4100\n",[17,1186,1187,1188,1191,1192,1196],{},"Asks the host ",[20,1189,1190],{},"rpc.discover",", and writes local entity files rebuilt from the\n",[1036,1193,1195],{"href":1194},"\u002Fdocs\u002Fextending\u002Fcard-and-wire","cards"," it answers with:",[59,1198,1200],{"className":540,"code":1199,"language":542,"meta":64,"style":64},"\u002F\u002F remotes\u002Fblog\u002Fentities\u002FPost.ts — generated\nimport { Card } from '@fougere\u002Fschema';\n\nexport class Post extends Card.fromDescriptor\u003C{\n  id: string;\n  title: string;\n  createdAt: Date;\n}>({ \u002F* the card, verbatim *\u002F }).toSchema() {}\n",[20,1201,1202,1207,1231,1235,1255,1267,1278,1290],{"__ignoreMap":64},[68,1203,1204],{"class":70,"line":71},[68,1205,1206],{"class":549},"\u002F\u002F remotes\u002Fblog\u002Fentities\u002FPost.ts — generated\n",[68,1208,1209,1212,1214,1217,1219,1222,1224,1227,1229],{"class":70,"line":553},[68,1210,1211],{"class":556},"import",[68,1213,873],{"class":575},[68,1215,1216],{"class":571}," Card",[68,1218,728],{"class":575},[68,1220,1221],{"class":556}," from",[68,1223,597],{"class":350},[68,1225,1226],{"class":78},"@fougere\u002Fschema",[68,1228,586],{"class":350},[68,1230,733],{"class":575},[68,1232,1233],{"class":70,"line":620},[68,1234,624],{"emptyLinePlaceholder":623},[68,1236,1237,1239,1241,1243,1245,1247,1249,1252],{"class":70,"line":627},[68,1238,557],{"class":556},[68,1240,561],{"class":560},[68,1242,572],{"class":564},[68,1244,568],{"class":560},[68,1246,1216],{"class":571},[68,1248,153],{"class":575},[68,1250,1251],{"class":578},"fromDescriptor",[68,1253,1254],{"class":575},"\u003C{\n",[68,1256,1257,1260,1262,1265],{"class":70,"line":657},[68,1258,1259],{"class":714},"  id",[68,1261,718],{"class":575},[68,1263,1264],{"class":564}," string",[68,1266,733],{"class":575},[68,1268,1269,1272,1274,1276],{"class":70,"line":682},[68,1270,1271],{"class":714},"  title",[68,1273,718],{"class":575},[68,1275,1264],{"class":564},[68,1277,733],{"class":575},[68,1279,1280,1283,1285,1288],{"class":70,"line":736},[68,1281,1282],{"class":714},"  createdAt",[68,1284,718],{"class":575},[68,1286,1287],{"class":564}," Date",[68,1289,733],{"class":575},[68,1291,1292,1295,1297,1299,1302,1304,1306,1308,1311,1313],{"class":70,"line":742},[68,1293,1294],{"class":575},"}>",[68,1296,583],{"class":582},[68,1298,711],{"class":575},[68,1300,1301],{"class":549}," \u002F* the card, verbatim *\u002F",[68,1303,728],{"class":575},[68,1305,614],{"class":582},[68,1307,153],{"class":575},[68,1309,1310],{"class":578},"toSchema",[68,1312,813],{"class":582},[68,1314,617],{"class":575},[17,1316,1317,1318,1320,1321,1324],{},"One class, like the one you would have written by hand: ",[20,1319,648],{}," is the value — a validator\nthat validates locally, without an additional request to the host — and the type of a row\nit hands back, so ",[20,1322,1323],{},"post.titel"," does not compile. Both are read off the same card.",[17,1326,1327,1328,1331,1332,1335],{},"Next to it, ",[20,1329,1330],{},"handlers\u002FPostHandler.ts"," states what the frond serves, so a consumer can\nwrite ",[20,1333,1334],{},"Facade\u003CPostHandler>"," without holding the handler's code:",[59,1337,1339],{"className":540,"code":1338,"language":542,"meta":64,"style":64},"export interface PostHandler {\n  list(invocation?: Invocation): Promise\u003CPost[] & { total?: number; hasMore?: boolean }>;\n  findById(invocation?: Invocation): Promise\u003CPost | undefined>;\n}\n",[20,1340,1341,1352,1404,1434],{"__ignoreMap":64},[68,1342,1343,1345,1348,1350],{"class":70,"line":71},[68,1344,557],{"class":556},[68,1346,1347],{"class":560}," interface",[68,1349,768],{"class":564},[68,1351,654],{"class":575},[68,1353,1354,1357,1359,1362,1365,1368,1370,1372,1374,1376,1378,1381,1383,1386,1388,1391,1393,1396,1398,1401],{"class":70,"line":553},[68,1355,1356],{"class":660},"  list",[68,1358,583],{"class":575},[68,1360,1361],{"class":794},"invocation",[68,1363,1364],{"class":575},"?:",[68,1366,1367],{"class":564}," Invocation",[68,1369,180],{"class":575},[68,1371,667],{"class":564},[68,1373,645],{"class":575},[68,1375,648],{"class":564},[68,1377,675],{"class":582},[68,1379,1380],{"class":575}," &",[68,1382,873],{"class":575},[68,1384,1385],{"class":714}," total",[68,1387,1364],{"class":575},[68,1389,1390],{"class":564}," number",[68,1392,486],{"class":575},[68,1394,1395],{"class":714}," hasMore",[68,1397,1364],{"class":575},[68,1399,1400],{"class":564}," boolean",[68,1402,1403],{"class":575}," }>;\n",[68,1405,1406,1409,1411,1413,1415,1417,1419,1421,1423,1425,1428,1431],{"class":70,"line":620},[68,1407,1408],{"class":660},"  findById",[68,1410,583],{"class":575},[68,1412,1361],{"class":794},[68,1414,1364],{"class":575},[68,1416,1367],{"class":564},[68,1418,180],{"class":575},[68,1420,667],{"class":564},[68,1422,645],{"class":575},[68,1424,648],{"class":564},[68,1426,1427],{"class":575}," |",[68,1429,1430],{"class":564}," undefined",[68,1432,1433],{"class":575},">;\n",[68,1435,1436],{"class":70,"line":627},[68,1437,745],{"class":575},[17,1439,1440,1441,1444,1445,1448],{},"Commit ",[20,1442,1443],{},"remotes\u002F",": only the host can write it again, so a fresh clone compiles with the host down,\nand a diff of a sync shows what the host changed. ",[20,1446,1447],{},"@fronds\u002Fblog"," resolves there when no frond of the\nproject has that name, so pages use the same import path for a local or remote entity.",[17,1450,1451,1452,1455,1456,1459],{},"Re-running it ",[30,1453,1454],{},"removes what the host no longer serves",": the export and its file, since\n",[20,1457,1458],{},"@fronds\u002F*"," resolves by directory and a file left behind would still resolve to a\nclass nothing answers for. Only files carrying the generated header are removed;\nanything you put in that folder yourself is left alone.",[17,1461,1462,1463,1466],{},"The host returns entities associated with a facade, and ",[30,1464,1465],{},"the facts its fronds announce",".\nAn entity that is neither is not in the discovery result — a shape nobody exposed and\nnobody declared to leave stays home.",[17,1468,1469,1470,1473],{},"A fact has no operation, so it gets a class and no ",[20,1471,1472],{},"Handler"," interface beside it:",[59,1475,1477],{"className":540,"code":1476,"language":542,"meta":64,"style":64},"\u002F\u002F remotes\u002Fblog\u002Fentities\u002FPostPublished.ts — generated\nexport class PostPublished extends Card.fromDescriptor\u003C{ id: string; title: string; at: Date }>(…).toSchema() {}\n",[20,1478,1479,1484],{"__ignoreMap":64},[68,1480,1481],{"class":70,"line":71},[68,1482,1483],{"class":549},"\u002F\u002F remotes\u002Fblog\u002Fentities\u002FPostPublished.ts — generated\n",[68,1485,1486,1488,1490,1493,1495,1497,1499,1501,1504,1507,1509,1511,1513,1516,1518,1520,1522,1525,1527,1529,1532,1534,1536,1538,1540,1542,1544],{"class":70,"line":553},[68,1487,557],{"class":556},[68,1489,561],{"class":560},[68,1491,1492],{"class":564}," PostPublished",[68,1494,568],{"class":560},[68,1496,1216],{"class":571},[68,1498,153],{"class":575},[68,1500,1251],{"class":578},[68,1502,1503],{"class":575},"\u003C{",[68,1505,1506],{"class":714}," id",[68,1508,718],{"class":575},[68,1510,1264],{"class":564},[68,1512,486],{"class":575},[68,1514,1515],{"class":714}," title",[68,1517,718],{"class":575},[68,1519,1264],{"class":564},[68,1521,486],{"class":575},[68,1523,1524],{"class":714}," at",[68,1526,718],{"class":575},[68,1528,1287],{"class":564},[68,1530,1531],{"class":575}," }>",[68,1533,583],{"class":582},[68,1535,1148],{"class":571},[68,1537,614],{"class":582},[68,1539,153],{"class":575},[68,1541,1310],{"class":578},[68,1543,813],{"class":582},[68,1545,617],{"class":575},[17,1547,1548,1549,1552,1553,1555],{},"To have an arriving fact validated, re-export that class into one of your own fronds — the\nboot validates against an entity of a ",[30,1550,1551],{},"scanned"," frond, and ",[20,1554,1443],{}," is a\npackage, not a frond:",[59,1557,1559],{"className":540,"code":1558,"language":542,"meta":64,"style":64},"\u002F\u002F fronds\u002Fsearch\u002Fentities\u002FPostPublished.ts\nexport { default } from '@fronds\u002Fblog\u002Fentities\u002FPostPublished.js';\n",[20,1560,1561,1566],{"__ignoreMap":64},[68,1562,1563],{"class":70,"line":71},[68,1564,1565],{"class":549},"\u002F\u002F fronds\u002Fsearch\u002Fentities\u002FPostPublished.ts\n",[68,1567,1568,1570,1572,1574,1576,1578,1580,1583,1585],{"class":70,"line":553},[68,1569,557],{"class":556},[68,1571,873],{"class":575},[68,1573,632],{"class":556},[68,1575,728],{"class":575},[68,1577,1221],{"class":556},[68,1579,597],{"class":350},[68,1581,1582],{"class":78},"@fronds\u002Fblog\u002Fentities\u002FPostPublished.js",[68,1584,586],{"class":350},[68,1586,733],{"class":575},[450,1588,1590],{"id":1589},"the-rules","The rules",[182,1592,1593,1602],{},[185,1594,1595],{},[188,1596,1597,1599],{},[191,1598,20],{},[191,1600,1601],{},"what it means",[201,1603,1604,1620,1630],{},[188,1605,1606,1617],{},[206,1607,1608,102,1611,102,1614],{},[20,1609,1610],{},"directory-unreadable",[20,1612,1613],{},"handler-parse-failed",[20,1615,1616],{},"heritage-unresolved",[206,1618,1619],{},"what the scan could not do — a rule about an absence is only sound if the analysis attests it looked",[188,1621,1622,1627],{},[206,1623,1624],{},[20,1625,1626],{},"operation-unbound",[206,1628,1629],{},"an operation declares parameters and has no binding plan: it is served, and it receives none of them",[188,1631,1632,1637],{},[206,1633,1634],{},[20,1635,1636],{},"cross-frond-import",[206,1638,1639],{},"a relative import that resolves into another frond",[17,1641,1642,1643,1646,1647,1650,1651,1653],{},"The last one is a warning, not a refusal — it resolves today and the app runs. What it\nstates is that a ",[30,1644,1645],{},"colocation constraint is holding the app together and nothing declares\nit",": ",[20,1648,1649],{},"'..\u002F..\u002Fuser\u002Fentities\u002FUser.js'"," says these two folders are neighbours, in a string\nthe scan, the identity card and ",[20,1652,1043],{}," all ignore. It keeps working right up to the day\nthat folder is not there, and then it fails as a file path rather than as a model.",[17,1655,1656,1659,1660,1665],{},[20,1657,1658],{},"'@fronds\u002Fuser\u002Fentities\u002FUser.js'"," says the same dependency in terms the model reads, and it\nis the form ",[1036,1661,1663],{"href":1662},"#fougere-sync-consume-a-remote-frond",[20,1664,1163],{}," writes — so it survives\nthe frond moving out. The name resolves the same way whether the frond is local or synced.",[51,1667,1669,1671],{"id":1668},"fougere-build-write-down-what-a-scan-found",[20,1670,1060],{}," — write down what a scan found",[59,1673,1675],{"className":61,"code":1674,"language":63,"meta":64,"style":64},"fougere build                       # writes .fougere\u002Ffronds.generated.ts\nfougere build --out src\u002Ffronds.ts\n",[20,1676,1677,1686],{"__ignoreMap":64},[68,1678,1679,1681,1683],{"class":70,"line":71},[68,1680,75],{"class":74},[68,1682,1008],{"class":78},[68,1684,1685],{"class":549},"                       # writes .fougere\u002Ffronds.generated.ts\n",[68,1687,1688,1690,1692,1695],{"class":70,"line":553},[68,1689,75],{"class":74},[68,1691,1008],{"class":78},[68,1693,1694],{"class":85}," --out",[68,1696,1697],{"class":78}," src\u002Ffronds.ts\n",[17,1699,1700,1701,1704,1705,1708,1709,1711,1712,1715],{},"The scan reads a filesystem and a TypeScript program. This writes its answer down as the\nstatement you would write by hand — imports and ",[20,1702,1703],{},"frond()"," calls — so a deployment reads neither:\nhand its default export to ",[20,1706,1707],{},"createApp"," as ",[20,1710,1043],{},", and its ",[20,1713,1714],{},"vocabulary"," beside it, and nothing\ntouches a disk after that.",[17,1717,1718,1719,1723,1724,1727,1728,1730,1731,1734,1735,153],{},"It is what makes the ",[1036,1720,1722],{"href":1721},"\u002Fdocs\u002Frun\u002Fdeploy","edge"," reachable at all: a Worker has no filesystem\nand cannot ship a compiler. It is also why the scan is ",[30,1725,1726],{},"optional"," — ",[20,1729,1703],{}," declares the same\nthing by hand, and ",[20,1732,1733],{},"createApp({ fronds })"," boots with neither disk nor ",[20,1736,1737],{},"tsc",[17,1739,1740],{},"A generated file is not a second source. Nothing reads it but the boot, and regenerating it is the\nonly way to change it.",[51,1742,1744,1747],{"id":1743},"fougere-check-what-the-scan-could-not-do",[20,1745,1746],{},"fougere check"," — what the scan could not do",[59,1749,1751],{"className":61,"code":1750,"language":63,"meta":64,"style":64},"fougere check                 # from a project root; --root points elsewhere\n",[20,1752,1753],{"__ignoreMap":64},[68,1754,1755,1757,1760],{"class":70,"line":71},[68,1756,75],{"class":74},[68,1758,1759],{"class":78}," check",[68,1761,1762],{"class":549},"                 # from a project root; --root points elsewhere\n",[17,1764,1765,1766,1769],{},"It ",[30,1767,1768],{},"scans without booting",", so it reports on a project it cannot start. Seven rules\ntoday, each a stable name shared with the scan's own diagnostics:",[182,1771,1772,1782],{},[185,1773,1774],{},[188,1775,1776,1779],{},[191,1777,1778],{},"finding",[191,1780,1781],{},"means",[201,1783,1784,1801,1810,1820,1829,1843,1853],{},[188,1785,1786,1794],{},[206,1787,1788,102,1790,102,1792],{},[20,1789,1610],{},[20,1791,1613],{},[20,1793,1616],{},[206,1795,1796,1797,1800],{},"what the scan could not do — an unreadable directory, a handler that would not parse, an ",[20,1798,1799],{},"extends"," it could not follow",[188,1802,1803,1807],{},[206,1804,1805],{},[20,1806,1626],{},[206,1808,1809],{},"an operation whose parameters have no binding plan: it is served, and it receives nothing",[188,1811,1812,1817],{},[206,1813,1814],{},[20,1815,1816],{},"input-contract-ambiguous",[206,1818,1819],{},"two parameters could be the input contract, so provenance cannot pick one — refused rather than settled by parameter order",[188,1821,1822,1826],{},[206,1823,1824],{},[20,1825,1636],{},[206,1827,1828],{},"a relative import that resolves into another frond — a colocation constraint nothing declares, which holds until the day that frond is not on this disk",[188,1830,1831,1836],{},[206,1832,1833],{},[20,1834,1835],{},"frond-holds-several-domains",[206,1837,1838,1839,1842],{},"past six entities, the same threshold ",[20,1840,1841],{},"fougere graph"," uses",[188,1844,1845,1850],{},[206,1846,1847],{},[20,1848,1849],{},"unknown-adapter",[206,1851,1852],{},"an entity addressing an adapter no dependency of the project answers to — a typo, or a dependency never added",[188,1854,1855,1860],{},[206,1856,1857],{},[20,1858,1859],{},"super-linear-pattern",[206,1861,1862,1863,1866],{},"a ",[20,1864,1865],{},"pattern"," whose nested repetition backtracks super-linearly: the regex is fixed at declaration, the string tested against it is the caller's to choose",[17,1868,1869,1870,106,1873,1876],{},"Findings are ",[30,1871,1872],{},"blocking",[30,1874,1875],{},"warning",", and only a blocking one exits non-zero — which is\nwhat makes it usable in CI. An unresolvable base class with no operation is ordinary, and a\ncheck that cries wolf stops being read.",[51,1878,1880,1883],{"id":1879},"fougere-explain-the-contract-one-operation-is-served-under",[20,1881,1882],{},"fougere explain"," — the contract one operation is served under",[59,1885,1887],{"className":61,"code":1886,"language":63,"meta":64,"style":64},"fougere explain Post.publish          # from inside a project\nfougere explain Post.publish --root ..\u002Fblog\nfougere explain --names operations    # one name per line, what completion reads\nfougere explain --json\n",[20,1888,1889,1902,1916,1931],{"__ignoreMap":64},[68,1890,1891,1893,1896,1899],{"class":70,"line":71},[68,1892,75],{"class":74},[68,1894,1895],{"class":78}," explain",[68,1897,1898],{"class":78}," Post.publish",[68,1900,1901],{"class":549},"          # from inside a project\n",[68,1903,1904,1906,1908,1910,1913],{"class":70,"line":553},[68,1905,75],{"class":74},[68,1907,1895],{"class":78},[68,1909,1898],{"class":78},[68,1911,1912],{"class":85}," --root",[68,1914,1915],{"class":78}," ..\u002Fblog\n",[68,1917,1918,1920,1922,1925,1928],{"class":70,"line":620},[68,1919,75],{"class":74},[68,1921,1895],{"class":78},[68,1923,1924],{"class":85}," --names",[68,1926,1927],{"class":78}," operations",[68,1929,1930],{"class":549},"    # one name per line, what completion reads\n",[68,1932,1933,1935,1937],{"class":70,"line":627},[68,1934,75],{"class":74},[68,1936,1895],{"class":78},[68,1938,1939],{"class":85}," --json\n",[17,1941,1942],{},"Prints the resolved contract of one operation — the handler and method that run, where each\nparameter comes from, which collectors fill it, the surfaces and adapters that serve it, and the\ntwo facts about where it sits:",[59,1944,1947],{"className":1945,"code":1946,"language":366},[364],"Placement: commande \u002F local\nReach:     stock — 1 hop(s)\n",[20,1948,1946],{"__ignoreMap":64},[17,1950,1951,1954,1955,1961,1962,1964,1965,1968],{},[20,1952,1953],{},"placement"," says where it ANSWERS, ",[1036,1956,1958],{"href":1957},"\u002Fdocs\u002Frun\u002Fobserve",[20,1959,1960],{},"reach"," where its work GOES.\nComment a line out of ",[20,1963,1043],{}," and the same operation reports ",[20,1966,1967],{},"0 hop(s)"," — nothing in the\nhandler changed.",[17,1970,1971],{},"With no operation named, it lists what the project serves, frond by frond: each operation, whether it\nreads or writes, and where each protocol the project serves answers it — what the conventions deduced,\nwithout starting the app:",[59,1973,1976],{"className":1974,"code":1975,"language":366},[364],"blog → local\n  post.list      query    GET \u002Fapi\u002Fblog\u002Fposts              query posts\n  post.publish   command  POST \u002Fapi\u002Fblog\u002Fposts\u002F:id\u002Fpublish  mutation publish\n  post.update    command  PATCH \u002Fapi\u002Fblog\u002Fposts\u002F:id         mutation updatePost\n",[20,1977,1975],{"__ignoreMap":64},[17,1979,1980,1981,1984],{},"A protocol the config names but whose adapter does not say where an operation answers has no column.\n",[20,1982,1983],{},"--json"," emits a stable key order, which is the contract an agent reads.",[51,1986,1988,1990],{"id":1987},"fougere-graph-read-the-model",[20,1989,1841],{}," — read the model",[59,1992,1994],{"className":61,"code":1993,"language":63,"meta":64,"style":64},"fougere graph\n",[20,1995,1996],{"__ignoreMap":64},[68,1997,1998,2000],{"class":70,"line":71},[68,1999,75],{"class":74},[68,2001,2002],{"class":78}," graph\n",[17,2004,2005,2006,2008],{},"Two altitudes of one picture. First where the fronds run and which reaches which, read from\n",[20,2007,1043],{}," and from what a handler asks for in its constructor — so it answers with nothing\nrunning and nothing booted:",[59,2010,2013],{"className":2011,"code":2012,"language":366},[364],"  Fronds\n    commande  local   → stock\n    stock     remote  http:\u002F\u002F127.0.0.1:4100\n",[20,2014,2012],{"__ignoreMap":64},[17,2016,2017],{},"Then the entities, their references, and the number of incoming ones. Beyond six entities,\nthe command also suggests clusters calculated from that graph:",[59,2019,2022],{"className":2020,"code":2021,"language":366},[364],"  Entity Graph\n    Post → Author, Category (2 incoming)\n    Author\n",[20,2023,2021],{"__ignoreMap":64},[17,2025,2026],{},"A crossing whose far side was never scanned is left out rather than guessed: naming the frond\nbehind an address means reading its card, and a card is a discovery. An address is printed as\nhost and port, never whole.",[17,2028,2029,2030,2034],{},"The ",[1036,2031,2033],{"href":2032},"\u002Fdocs","shortest path"," page covers current and possible future\nuses of this graph.",[51,2036,2038,2041],{"id":2037},"fougere-ports-what-answers-each-port",[20,2039,2040],{},"fougere ports"," — what answers each port",[59,2043,2045],{"className":61,"code":2044,"language":63,"meta":64,"style":64},"fougere ports\nfougere ports --json\n",[20,2046,2047,2054],{"__ignoreMap":64},[68,2048,2049,2051],{"class":70,"line":71},[68,2050,75],{"class":74},[68,2052,2053],{"class":78}," ports\n",[68,2055,2056,2058,2061],{"class":70,"line":553},[68,2057,75],{"class":74},[68,2059,2060],{"class":78}," ports",[68,2062,1939],{"class":85},[17,2064,2065,2066,2070],{},"What answers each ",[1036,2067,2069],{"href":2068},"\u002Fdocs\u002Fconcepts\u002Fport#three-words","port"," of the app, and each registry. First\nwhat answers by name — the source types, the protocols, the generators, the formats, the extensions in\nthe order they rise:",[59,2072,2075],{"className":2073,"code":2074,"language":366},[364],"  By name\n    source type  ·  sqlite, pg, memory\n    protocol  ·  rest, graphql\n    extension  ·  schema → values → seeds → presenters → log\n",[20,2076,2074],{"__ignoreMap":64},[17,2078,2079],{},"Then, frond by frond, each port: its links outside in, then the realization they reach — a class, or\nwhat Fougere puts there. A frond served by another process says where, since its links stand there:",[59,2081,2084],{"className":2082,"code":2083,"language":366},[364],"  Frond billing                                       # demos\u002Fports-swap\n    Dispatcher  ·  Attempted → the rest of the call\n    Payment  ·  StripePayment\n  Frond catalog\n    Storage  ·  Recording → the realization\n\n  Frond blog                                          # demos\u002Fnuxt-blog, blog behind fronds:\n    served at  ·  http:\u002F\u002F127.0.0.1:4100\n  Frond auth\n    Collect\u003CUser>  ·  SessionCollector\n",[20,2085,2083],{"__ignoreMap":64},[17,2087,2088],{},"It boots the app as its host would, with the schema check and the seeds left out, so it reads what\nactually booted and touches no row.",[51,2090,2092,2095],{"id":2091},"fougere-load-the-scenario-the-app-already-describes",[20,2093,2094],{},"fougere load"," — the scenario the app already describes",[59,2097,2099],{"className":61,"code":2098,"language":63,"meta":64,"style":64},"fougere load                          # writes \u003Croot>\u002Fload.js\nfougere load --facade http:\u002F\u002F127.0.0.1:4200\u002F_fougere\u002Fcall\nfougere load --out \"\"                 # print it instead\nfougere load --force                  # replace an existing file\n",[20,2100,2101,2111,2123,2137],{"__ignoreMap":64},[68,2102,2103,2105,2108],{"class":70,"line":71},[68,2104,75],{"class":74},[68,2106,2107],{"class":78}," load",[68,2109,2110],{"class":549},"                          # writes \u003Croot>\u002Fload.js\n",[68,2112,2113,2115,2117,2120],{"class":70,"line":553},[68,2114,75],{"class":74},[68,2116,2107],{"class":78},[68,2118,2119],{"class":85}," --facade",[68,2121,2122],{"class":78}," http:\u002F\u002F127.0.0.1:4200\u002F_fougere\u002Fcall\n",[68,2124,2125,2127,2129,2131,2134],{"class":70,"line":620},[68,2126,75],{"class":74},[68,2128,2107],{"class":78},[68,2130,1694],{"class":85},[68,2132,2133],{"class":350}," \"\"",[68,2135,2136],{"class":549},"                 # print it instead\n",[68,2138,2139,2141,2143,2146],{"class":70,"line":627},[68,2140,75],{"class":74},[68,2142,2107],{"class":78},[68,2144,2145],{"class":85}," --force",[68,2147,2148],{"class":549},"                  # replace an existing file\n",[17,2150,2151,2152,2158],{},"Writes a ",[1036,2153,2157],{"href":2154,"rel":2155},"https:\u002F\u002Fk6.io",[2156],"nofollow","k6"," scenario covering every operation the default facade answers. What it\nderives is everything the code already states: the operations, a body for each from the entity's\nown fields, and the JSON-RPC envelope from the one function that frames a call.",[17,2160,2161,2162,2164],{},"What it does ",[30,2163,1073],{}," derive, it marks in the file where it sits — the weights, the stages and the\nthresholds are facts about your users, not about your code:",[59,2166,2170],{"className":2167,"code":2168,"language":2169,"meta":64,"style":64},"language-js shiki shiki-themes material-theme-lighter fougere-pastel material-theme-palenight","export const options = {\n  \u002F\u002F Yours: a flat rate draws flat lines and there is nothing to read in them.\n  stages: [ … ],\n  \u002F\u002F Yours: what counts as too slow is a fact about your users.\n  thresholds: { … },\n};\n","js",[20,2171,2172,2187,2192,2208,2213,2227],{"__ignoreMap":64},[68,2173,2174,2176,2179,2182,2185],{"class":70,"line":71},[68,2175,557],{"class":556},[68,2177,2178],{"class":560}," const",[68,2180,2181],{"class":571}," options ",[68,2183,2184],{"class":575},"=",[68,2186,654],{"class":575},[68,2188,2189],{"class":70,"line":553},[68,2190,2191],{"class":549},"  \u002F\u002F Yours: a flat rate draws flat lines and there is nothing to read in them.\n",[68,2193,2194,2197,2199,2202,2204,2206],{"class":70,"line":620},[68,2195,2196],{"class":714},"  stages",[68,2198,718],{"class":575},[68,2200,2201],{"class":582}," [",[68,2203,877],{"class":571},[68,2205,860],{"class":582},[68,2207,166],{"class":575},[68,2209,2210],{"class":70,"line":627},[68,2211,2212],{"class":549},"  \u002F\u002F Yours: what counts as too slow is a fact about your users.\n",[68,2214,2215,2218,2220,2222,2224],{"class":70,"line":657},[68,2216,2217],{"class":714},"  thresholds",[68,2219,718],{"class":575},[68,2221,873],{"class":575},[68,2223,877],{"class":571},[68,2225,2226],{"class":575},"},\n",[68,2228,2229],{"class":70,"line":682},[68,2230,2231],{"class":575},"};\n",[17,2233,2234,2235,2238],{},"It reads the ",[30,2236,2237],{},"scan",", never a boot: booting plants seeds, and a command that\ndescribes a project has no business writing to its database. A named surface is left out — the\nload of an app is what its default facade answers, and counting a surface would count one operation\ntwice.",[17,2240,2241,2242,153],{},"Regenerate rather than patch. A scenario written by hand drifts from the code, and then you are\ncomparing two scripts instead of two deployments — which is the whole point when the same code\nruns ",[1036,2243,2244],{"href":1047},"as one process or as several",[51,2246,2248,2251],{"id":2247},"fougere-devtools-what-the-running-apps-are-dispatching",[20,2249,2250],{},"fougere devtools"," — what the running apps are dispatching",[59,2253,2255],{"className":61,"code":2254,"language":63,"meta":64,"style":64},"fougere devtools                      # every address this project declares\nfougere devtools --url http:\u002F\u002F127.0.0.1:4100\nfougere devtools --json               # one page, then stop\n",[20,2256,2257,2267,2279],{"__ignoreMap":64},[68,2258,2259,2261,2264],{"class":70,"line":71},[68,2260,75],{"class":74},[68,2262,2263],{"class":78}," devtools",[68,2265,2266],{"class":549},"                      # every address this project declares\n",[68,2268,2269,2271,2273,2276],{"class":70,"line":553},[68,2270,75],{"class":74},[68,2272,2263],{"class":78},[68,2274,2275],{"class":85}," --url",[68,2277,2278],{"class":78}," http:\u002F\u002F127.0.0.1:4100\n",[68,2280,2281,2283,2285,2288],{"class":70,"line":620},[68,2282,75],{"class":74},[68,2284,2263],{"class":78},[68,2286,2287],{"class":85}," --json",[68,2289,2290],{"class":549},"               # one page, then stop\n",[17,2292,2293,2294,2299,2300,2303,2304,2307,2308,2310],{},"Reads the call log an app keeps when it mounted ",[1036,2295,2296],{"href":1957},[20,2297,2298],{},"@fougere\u002Fcalls",",\nover ",[20,2301,2302],{},"\u002F_fougere\u002Fcall"," like any other consumer. ",[30,2305,2306],{},"The reader pulls",": no app registers\nanywhere, and an app started alone depends on nothing. The price is knowing the addresses,\nand the project already states them — ",[20,2309,1043],{}," says where a call goes, so it also says\nwhere the other half of a call can be watched.",[17,2312,2313,2314,2317],{},"The LOCAL one is the exception: a port belongs to the host and no project states one, so\n",[20,2315,2316],{},"http:\u002F\u002F127.0.0.1:3000"," is a convention — where Nuxt, Next and the site all sit. A host that\nserves elsewhere says so the way it names a log level:",[59,2319,2321],{"className":61,"code":2320,"language":63,"meta":64,"style":64},"FOUGERE_URL=http:\u002F\u002F127.0.0.1:4100 fougere devtools\n",[20,2322,2323],{"__ignoreMap":64},[68,2324,2325,2328,2330,2333,2336],{"class":70,"line":71},[68,2326,2327],{"class":571},"FOUGERE_URL",[68,2329,2184],{"class":575},[68,2331,2332],{"class":78},"http:\u002F\u002F127.0.0.1:4100",[68,2334,2335],{"class":74}," fougere",[68,2337,2338],{"class":78}," devtools\n",[17,2340,2341,2344],{},[20,2342,2343],{},"--url"," still wins over both, and narrows the reading to that one address.",[17,2346,2347,2348,2351,2352,2355],{},"An address that did not answer is reported as a refusal rather than as silence, and the\nrefusals are not one fact but four: not started, answering but serving no call log\n(",[20,2349,2350],{},"Unknown rpc operation 'calls'. It serves discover.","), quiet — and a stranger, ",[20,2353,2354],{},"answered HTTP 404 — not a Fougere receiver?",", which is what something else on that port says for\nitself.",[51,2357,2359,2362],{"id":2358},"fougere-freeze-record-todays-shapes-under-a-name",[20,2360,2361],{},"fougere freeze"," — record today's shapes under a name",[59,2364,2366],{"className":61,"code":2365,"language":63,"meta":64,"style":64},"fougere freeze v2\nfougere freeze v2 --json\n",[20,2367,2368,2378],{"__ignoreMap":64},[68,2369,2370,2372,2375],{"class":70,"line":71},[68,2371,75],{"class":74},[68,2373,2374],{"class":78}," freeze",[68,2376,2377],{"class":78}," v2\n",[68,2379,2380,2382,2384,2387],{"class":70,"line":553},[68,2381,75],{"class":74},[68,2383,2374],{"class":78},[68,2385,2386],{"class":78}," v2",[68,2388,1939],{"class":85},[17,2390,2391,2392,2395,2396,2399],{},"Writes two artefacts, and both are needed. A ",[30,2393,2394],{},"snapshot"," alone loses the intent — a field gone\nplus a field appeared cannot be told from a rename, and the two produce opposite DDL. A ",[30,2397,2398],{},"step","\nalone corrupts in silence, with nothing to check it against. Replaying the step over the previous\nsnapshot must reproduce this one, which is what catches a missing step or a hand-edited file.",[17,2401,2402,2405],{},[30,2403,2404],{},"Nothing reaches the disk while a question stands."," When a removal and an addition could be one\nrename, the command asks — that intent is the only thing the code does not hold, and it left with\nthe person who made the change.",[17,2407,2408,2409,2412],{},"A version is what a shared database receives: freeze in the change that moves an entity, and\n",[20,2410,2411],{},"fougere migrate"," applies it everywhere else.",[51,2414,2416,2418],{"id":2415},"fougere-migrate-bring-the-database-up-to-what-was-frozen",[20,2417,2411],{}," — bring the database up to what was frozen",[59,2420,2422],{"className":61,"code":2421,"language":63,"meta":64,"style":64},"fougere migrate                   # print the plan, move nothing\nfougere migrate --apply           # run it\nfougere migrate --latest --apply  # a local database: follow the entities as they are\n",[20,2423,2424,2434,2446],{"__ignoreMap":64},[68,2425,2426,2428,2431],{"class":70,"line":71},[68,2427,75],{"class":74},[68,2429,2430],{"class":78}," migrate",[68,2432,2433],{"class":549},"                   # print the plan, move nothing\n",[68,2435,2436,2438,2440,2443],{"class":70,"line":553},[68,2437,75],{"class":74},[68,2439,2430],{"class":78},[68,2441,2442],{"class":85}," --apply",[68,2444,2445],{"class":549},"           # run it\n",[68,2447,2448,2450,2452,2455,2457],{"class":70,"line":620},[68,2449,75],{"class":74},[68,2451,2430],{"class":78},[68,2453,2454],{"class":85}," --latest",[68,2456,2442],{"class":85},[68,2458,2459],{"class":549},"  # a local database: follow the entities as they are\n",[17,2461,2462,2463,2465,2466,2469],{},"By default it applies what ",[20,2464,2361],{}," recorded, and nothing else: a frond never frozen, or\nwhose entities moved since its last version, is refused by name before any database is opened.\n",[20,2467,2468],{},"--latest"," lifts that and follows the entities as they are — for your own database while you\niterate. Refused, the command exits 1, so a release step stops there.",[17,2471,2472,2473,2476,2477,2480],{},"The one command that writes a schema — a boot only reads it, and refuses a database behind the\nentities. It boots the app the way its host would, seeds left out, so a frond an extension brings\n(auth's sessions, a workflow's journal) is migrated with the rest. Then, in this order: what\ntouches live data — a rename declared by ",[20,2474,2475],{},"previous:"," or a frozen step, a drop — and the additive\nhalf, the missing tables and columns. Without ",[20,2478,2479],{},"--apply"," it writes nothing — the plan is the\nanswer, and reading it is the point.",[17,2482,2483,2484,153],{},"A table that keeps a column no field declares while it gains one is reported before anything\nruns: that is what an undeclared rename looks like. See ",[1036,2485,2487],{"href":2486},"\u002Fdocs\u002Fdata\u002Fevolve","How a schema moves",[17,2489,2490,2491,2494],{},"A fresh table and a migrated one promise the same thing: a ",[20,2492,2493],{},"unique()"," a live table never carried\nis proposed as an index, and the statement fails on rows that already break it. That failure is\nthe answer, not an accident.",[51,2496,2498,2501],{"id":2497},"fougere-keys-the-root-a-split-deployments-grants-are-signed-by",[20,2499,2500],{},"fougere keys"," — the root a split deployment's grants are signed by",[59,2503,2505],{"className":61,"code":2504,"language":63,"meta":64,"style":64},"fougere keys              # once, at deployment time\n",[20,2506,2507],{"__ignoreMap":64},[68,2508,2509,2511,2514],{"class":70,"line":71},[68,2510,75],{"class":74},[68,2512,2513],{"class":78}," keys",[68,2515,2516],{"class":549},"              # once, at deployment time\n",[17,2518,2519,2520,2523],{},"Creates the authority and exits. Nothing stays alive, nothing is joined at boot, and no frond\nreaches anything to prove who it is. A receiver ends up holding ",[30,2521,2522],{},"one public key",", so a frond\ngranted tomorrow is admitted by a receiver deployed today without its config being touched.",[17,2525,2526],{},"The private key is written and never printed: it signs grants, and a grant is the only thing that\nhas to travel.",[51,2528,2530,2533],{"id":2529},"fougere-grant-vouch-for-one-frond",[20,2531,2532],{},"fougere grant"," — vouch for one frond",[59,2535,2537],{"className":61,"code":2536,"language":63,"meta":64,"style":64},"fougere grant billing\n",[20,2538,2539],{"__ignoreMap":64},[68,2540,2541,2543,2546],{"class":70,"line":71},[68,2542,75],{"class":74},[68,2544,2545],{"class":78}," grant",[68,2547,2548],{"class":78}," billing\n",[17,2550,2551,2552,2556,2557,2559],{},"Binds a frond's name to a fresh key, signed by the root. That is what lets a receiver\n",[1036,2553,2555],{"href":2554},"\u002Fdocs\u002Frun\u002Fsecure","establish its caller"," rather than believe a claim — ",[20,2558,1089],{}," refuses to\nstart beyond loopback with no way to verify, and this is what it verifies against.",[51,2561,2563,2566],{"id":2562},"fougere-completion-shell-completion",[20,2564,2565],{},"fougere completion"," — shell completion",[59,2568,2570],{"className":61,"code":2569,"language":63,"meta":64,"style":64},"fougere completion zsh >> ~\u002F.zshrc\n",[20,2571,2572],{"__ignoreMap":64},[68,2573,2574,2576,2579,2582,2585],{"class":70,"line":71},[68,2575,75],{"class":74},[68,2577,2578],{"class":78}," completion",[68,2580,2581],{"class":78}," zsh",[68,2583,2584],{"class":575}," >>",[68,2586,2587],{"class":78}," ~\u002F.zshrc\n",[17,2589,2590,138,2593,2595],{},[20,2591,2592],{},"zsh",[20,2594,63],{},"; the shell is auto-detected when the argument is absent. The names it\ncompletes come out of the same entities the commands ride on, so a new command needs no\nsecond list.",[51,2597,2599,2602],{"id":2598},"fougere-build-frond-publish-a-fronds-entities",[20,2600,2601],{},"fougere build-frond"," — publish a frond's entities",[59,2604,2606],{"className":61,"code":2605,"language":63,"meta":64,"style":64},"fougere build-frond blog\n",[20,2607,2608],{"__ignoreMap":64},[68,2609,2610,2612,2615],{"class":70,"line":71},[68,2611,75],{"class":74},[68,2613,2614],{"class":78}," build-frond",[68,2616,2617],{"class":78}," blog\n",[17,2619,2620,2621,2624,2625,2628,2629,2632,2633,153],{},"Compiles ",[20,2622,2623],{},"fronds\u002Fblog\u002Fentities\u002F**"," to ",[20,2626,2627],{},"dist\u002F"," with type declarations and configures the\nFrond's ",[20,2630,2631],{},"package.json",". A consumer in another repository can then install that package.\nSee ",[1036,2634,2636],{"href":2635},"\u002Fdocs\u002Fadopt\u002Fanother-repository","where the code lives",[2638,2639,2640],"style",{},"html pre.shiki code .sV8pK, html code.shiki .sV8pK{--shiki-light:#E2931D;--shiki-default:#C9B6EA;--shiki-dark:#FFCB6B}html pre.shiki code .sN-8n, html code.shiki .sN-8n{--shiki-light:#91B859;--shiki-default:#EE9F6B;--shiki-dark:#C3E88D}html pre.shiki code .svHQO, html code.shiki .svHQO{--shiki-light:#91B859;--shiki-default:#8FCF86;--shiki-dark:#C3E88D}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 .sDDC1, html code.shiki .sDDC1{--shiki-light:#39ADB5;--shiki-default:#EE9F6B;--shiki-dark:#89DDFF}html pre.shiki code .skXKP, html code.shiki .skXKP{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#7D8C80;--shiki-default-font-style:inherit;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sK6XW, html code.shiki .sK6XW{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#8FCF86;--shiki-default-font-style:inherit;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .s76I7, html code.shiki .s76I7{--shiki-light:#9C3EDA;--shiki-default:#8FCF86;--shiki-dark:#C792EA}html pre.shiki code .sBZYL, html code.shiki .sBZYL{--shiki-light:#E2931D;--shiki-default:#EFCD8F;--shiki-dark:#FFCB6B}html pre.shiki code .sPEhv, html code.shiki .sPEhv{--shiki-light:#90A4AE;--shiki-default:#DDE5DA;--shiki-dark:#BABED8}html pre.shiki code .s15xx, html code.shiki .s15xx{--shiki-light:#39ADB5;--shiki-default:#A3B0A5;--shiki-dark:#89DDFF}html pre.shiki code .s4mR9, html code.shiki .s4mR9{--shiki-light:#6182B8;--shiki-default:#C9B6EA;--shiki-dark:#82AAFF}html pre.shiki code .srlTG, html code.shiki .srlTG{--shiki-light:#90A4AE;--shiki-default:#A3B0A5;--shiki-dark:#BABED8}html pre.shiki code .shDkW, html code.shiki .shDkW{--shiki-light:#E53935;--shiki-default:#C9B6EA;--shiki-dark:#F07178}html pre.shiki code .sxG60, html code.shiki .sxG60{--shiki-light:#39ADB5;--shiki-light-font-style:inherit;--shiki-default:#8FCF86;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:inherit}html pre.shiki code .spAFX, html code.shiki .spAFX{--shiki-light:#E53935;--shiki-default:#A3B0A5;--shiki-dark:#F07178}html pre.shiki code .sHtqg, html code.shiki .sHtqg{--shiki-light:#E53935;--shiki-default:#93CFC0;--shiki-dark:#F07178}html pre.shiki code .shDUQ, html code.shiki .shDUQ{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#DDE5DA;--shiki-default-font-style:inherit;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sTljH, html code.shiki .sTljH{--shiki-light:#90A4AE;--shiki-light-font-style:inherit;--shiki-default:#8FCF86;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:inherit}html pre.shiki code .ssXpW, html code.shiki .ssXpW{--shiki-light:#E53935;--shiki-default:#DDE5DA;--shiki-dark:#F07178}html pre.shiki code .sy9f4, html code.shiki .sy9f4{--shiki-light:#90A4AE;--shiki-default:#93CFC0;--shiki-dark:#BABED8}html pre.shiki code .s3dPA, html code.shiki .s3dPA{--shiki-light:#F76D47;--shiki-default:#EE9F6B;--shiki-dark:#F78C6C}",{"title":64,"searchDepth":553,"depth":553,"links":2642},[2643,2647,2649,2651,2655,2657,2659,2661,2663,2665,2667,2669,2671,2673,2675,2677,2679],{"id":53,"depth":553,"text":2644,"children":2645},"fougere new — compose a workspace",[2646],{"id":452,"depth":620,"text":453},{"id":967,"depth":553,"text":2648},"fougere dev, build, serve — one frond, its own process",{"id":1101,"depth":553,"text":2650},"fougere call — invoke an operation",{"id":1160,"depth":553,"text":2652,"children":2653},"fougere sync — consume a remote frond",[2654],{"id":1589,"depth":620,"text":1590},{"id":1668,"depth":553,"text":2656},"fougere build — write down what a scan found",{"id":1743,"depth":553,"text":2658},"fougere check — what the scan could not do",{"id":1879,"depth":553,"text":2660},"fougere explain — the contract one operation is served under",{"id":1987,"depth":553,"text":2662},"fougere graph — read the model",{"id":2037,"depth":553,"text":2664},"fougere ports — what answers each port",{"id":2091,"depth":553,"text":2666},"fougere load — the scenario the app already describes",{"id":2247,"depth":553,"text":2668},"fougere devtools — what the running apps are dispatching",{"id":2358,"depth":553,"text":2670},"fougere freeze — record today's shapes under a name",{"id":2415,"depth":553,"text":2672},"fougere migrate — bring the database up to what was frozen",{"id":2497,"depth":553,"text":2674},"fougere keys — the root a split deployment's grants are signed by",{"id":2529,"depth":553,"text":2676},"fougere grant — vouch for one frond",{"id":2562,"depth":553,"text":2678},"fougere completion — shell completion",{"id":2598,"depth":553,"text":2680},"fougere build-frond — publish a frond's entities","fougere new, serve, call, sync, graph — composing a workspace, hosting one frond, invoking an operation from a shell.","md",null,{},"\u002Freference\u002Fcli",{"title":8,"description":2681},"reference\u002F01.cli","Fmf67C5AmymMLttJQrytP11s_zzkxpCxv45aE34OLVs",[2690,2691,2696,2701,2706,2711,2716,2721,2726,2731,2736,2741,2746,2751,2756,2761,2766,2771,2776,2781,2786,2791,2795,2799,2804,2809,2814,2819,2824,2829,2834,2839,2844,2848,2853,2858,2863,2868,2872,2877,2882,2887,2892,2897,2902],{"path":2685,"title":8,"description":2681,"stem":2687},{"path":2692,"title":2693,"description":2694,"stem":2695},"\u002Freference\u002Ferrors","Error codes","Every code an operation can refuse with, and its HTTP status.","reference\u002F02.errors",{"path":2697,"title":2698,"description":2699,"stem":2700},"\u002Freference\u002Fconfig","fougere.config.ts","Every key the app config admits, and which package answers each one.","reference\u002F03.config",{"path":2702,"title":2703,"description":2704,"stem":2705},"\u002Freference\u002Ffrond-config","frond.config.ts","Every key a frond's own config admits.","reference\u002F04.frond-config",{"path":2707,"title":2708,"description":2709,"stem":2710},"\u002Freference\u002Fsources","Source types","Every type an entry of sources: may name, and the keys it admits.","reference\u002F05.sources",{"path":2712,"title":2713,"description":2714,"stem":2715},"\u002Freference\u002Fprotocols","Protocols","What protocols: may serve, and what each admits.","reference\u002F06.protocols",{"path":2717,"title":2718,"description":2719,"stem":2720},"\u002Freference\u002Fstates","State keepers","How state: may keep a caller's values.","reference\u002F07.states",{"path":2722,"title":2723,"description":2724,"stem":2725},"\u002Freference\u002Fforms","Forms","The types a frond is written with — each one read by the scan.","reference\u002F08.forms",{"path":2727,"title":2728,"description":2729,"stem":2730},"\u002Freference\u002Fports","Ports Fougere opens","The classes you stand in front of, or extend, to change what the framework does.","reference\u002F09.ports",{"path":2732,"title":2733,"description":2734,"stem":2735},"\u002Freference\u002Finterfaces","Interfaces to extend","The empty interfaces a package augments with declare module, and who augments each.","reference\u002F10.interfaces",{"path":2737,"title":2738,"description":2739,"stem":2740},"\u002Freference\u002Fdiagnostics","Boot and check diagnostics","Every code a boot, the scan or fougere check can raise, and what it says.","reference\u002F11.diagnostics",{"path":2742,"title":2743,"description":2744,"stem":2745},"\u002Freference\u002Fpackages\u002Fadapter-duckdb","@fougere\u002Fadapter-duckdb","Read across an app's sources — one SQL query over what DuckDB can attach.","reference\u002Fpackages\u002Fadapter-duckdb",{"path":2747,"title":2748,"description":2749,"stem":2750},"\u002Freference\u002Fpackages\u002Fadapter-env","@fougere\u002Fadapter-env","The process environment as a source — MEILI_URL read as Meili's url, judged at boot.","reference\u002Fpackages\u002Fadapter-env",{"path":2752,"title":2753,"description":2754,"stem":2755},"\u002Freference\u002Fpackages\u002Fadapter-file","@fougere\u002Fadapter-file","Rows as files — one JSON or YAML file per row, in a directory per entity.","reference\u002Fpackages\u002Fadapter-file",{"path":2757,"title":2758,"description":2759,"stem":2760},"\u002Freference\u002Fpackages\u002Fadapter-graphql","@fougere\u002Fadapter-graphql","Entity → GraphQL types, inputs and CRUD, through Pothos.","reference\u002Fpackages\u002Fadapter-graphql",{"path":2762,"title":2763,"description":2764,"stem":2765},"\u002Freference\u002Fpackages\u002Fadapter-memory","@fougere\u002Fadapter-memory","Rows in a Map — the source a first run meets, and the one that ships no driver.","reference\u002Fpackages\u002Fadapter-memory",{"path":2767,"title":2768,"description":2769,"stem":2770},"\u002Freference\u002Fpackages\u002Fadapter-rest","@fougere\u002Fadapter-rest","Entity → REST routes.","reference\u002Fpackages\u002Fadapter-rest",{"path":2772,"title":2773,"description":2774,"stem":2775},"\u002Freference\u002Fpackages\u002Fadapter-sql","@fougere\u002Fadapter-sql","Entity → SQL tables through Kysely (SQLite, PostgreSQL, MySQL, SQL Server).","reference\u002Fpackages\u002Fadapter-sql",{"path":2777,"title":2778,"description":2779,"stem":2780},"\u002Freference\u002Fpackages\u002Fadmin","@fougere\u002Fadmin","A back-office derived from what the app already says it hosts — a react-admin DataProvider over the Fougere wire.","reference\u002Fpackages\u002Fadmin",{"path":2782,"title":2783,"description":2784,"stem":2785},"\u002Freference\u002Fpackages\u002Fapp","@fougere\u002Fapp","The host-independent half of a Fougere app: boot, call envelope, REST table, form contract.","reference\u002Fpackages\u002Fapp",{"path":2787,"title":2788,"description":2789,"stem":2790},"\u002Freference\u002Fpackages\u002Fauth-better","@fougere\u002Fauth-better","Fougere's auth — a translation layer onto better-auth.","reference\u002Fpackages\u002Fauth-better",{"path":2792,"title":2298,"description":2793,"stem":2794},"\u002Freference\u002Fpackages\u002Fcalls","Optional call log for Fougere: a bounded ring of every dispatch, served as an rpc operation. Read it with `fougere devtools`.","reference\u002Fpackages\u002Fcalls",{"path":2796,"title":22,"description":2797,"stem":2798},"\u002Freference\u002Fpackages\u002Fcli","The Fougere CLI — compose a workspace, serve a frond, call an operation.","reference\u002Fpackages\u002Fcli",{"path":2800,"title":2801,"description":2802,"stem":2803},"\u002Freference\u002Fpackages\u002Fcompiler","@fougere\u002Fcompiler","The scan: Fougere reading a project's source to produce the descriptors core boots from. Needs a filesystem and a TypeScript program.","reference\u002Fpackages\u002Fcompiler",{"path":2805,"title":2806,"description":2807,"stem":2808},"\u002Freference\u002Fpackages\u002Fcontainer","@fougere\u002Fcontainer","Fougere's DI container: resolution by type, wired from the AST scan. Zero dependencies.","reference\u002Fpackages\u002Fcontainer",{"path":2810,"title":2811,"description":2812,"stem":2813},"\u002Freference\u002Fpackages\u002Fcore","@fougere\u002Fcore","The core — scan, call contract, façades, remote stand-ins.","reference\u002Fpackages\u002Fcore",{"path":2815,"title":2816,"description":2817,"stem":2818},"\u002Freference\u002Fpackages\u002Fdecorators","@fougere\u002Fdecorators","Configuration sugar (@config) — declarative, never hidden runtime.","reference\u002Fpackages\u002Fdecorators",{"path":2820,"title":2821,"description":2822,"stem":2823},"\u002Freference\u002Fpackages\u002Fdefaults","@fougere\u002Fdefaults","The conventional boot of a Fougere app — the one place storage is wired.","reference\u002Fpackages\u002Fdefaults",{"path":2825,"title":2826,"description":2827,"stem":2828},"\u002Freference\u002Fpackages\u002Fgraph","@fougere\u002Fgraph","Fougere's graph: a labelled directed multigraph, and the four questions asked of it — order, cycles, components, reach. Zero dependencies.","reference\u002Fpackages\u002Fgraph",{"path":2830,"title":2831,"description":2832,"stem":2833},"\u002Freference\u002Fpackages\u002Fhttp","@fougere\u002Fhttp","The words every HTTP door speaks — a method, an answer, the headers a state travels in.","reference\u002Fpackages\u002Fhttp",{"path":2835,"title":2836,"description":2837,"stem":2838},"\u002Freference\u002Fpackages\u002Flog","@fougere\u002Flog","Logging for Fougere: two lines for every call, in every process, and a file destination for the lines.","reference\u002Fpackages\u002Flog",{"path":2840,"title":2841,"description":2842,"stem":2843},"\u002Freference\u002Fpackages\u002Fnext","@fougere\u002Fnext","The Next.js adapter: mounting, and the one import that is genuinely Next.","reference\u002Fpackages\u002Fnext",{"path":2845,"title":219,"description":2846,"stem":2847},"\u002Freference\u002Fpackages\u002Fnuxt","The Nuxt module: Fougere's client primitives and server surface.","reference\u002Fpackages\u002Fnuxt",{"path":2849,"title":2850,"description":2851,"stem":2852},"\u002Freference\u002Fpackages\u002Fobservability","@fougere\u002Fobservability","Optional observability for Fougere: one span per operation, W3C Trace Context across any transport.","reference\u002Fpackages\u002Fobservability",{"path":2854,"title":2855,"description":2856,"stem":2857},"\u002Freference\u002Fpackages\u002Foclif","@fougere\u002Foclif","A frond's operations, as a terminal: topics, flags and help derived from what it declares.","reference\u002Fpackages\u002Foclif",{"path":2859,"title":2860,"description":2861,"stem":2862},"\u002Freference\u002Fpackages\u002Freact","@fougere\u002Freact","Fougere's four primitives as React hooks — host-independent.","reference\u002Fpackages\u002Freact",{"path":2864,"title":2865,"description":2866,"stem":2867},"\u002Freference\u002Fpackages\u002Fregistry","@fougere\u002Fregistry","Fougere's registry: one answer per name, refused when a second one arrives, and a reload that says it replaces. Zero dependencies.","reference\u002Fpackages\u002Fregistry",{"path":2869,"title":1226,"description":2870,"stem":2871},"\u002Freference\u002Fpackages\u002Fschema","The entity and its 4 axes — shape, role, lifecycle, boundary. Subject-owned judgments, edge-safe.","reference\u002Fpackages\u002Fschema",{"path":2873,"title":2874,"description":2875,"stem":2876},"\u002Freference\u002Fpackages\u002Fstate-cookie","@fougere\u002Fstate-cookie","A caller's state kept in a cookie — what `state: { cart: { cookie: {} } }` names, signed by core, carried by every HTTP door.","reference\u002Fpackages\u002Fstate-cookie",{"path":2878,"title":2879,"description":2880,"stem":2881},"\u002Freference\u002Fpackages\u002Fstate-session","@fougere\u002Fstate-session","A caller's state kept in a session — what `state: { cart: { session: {} } }` names: one cookie holds a reference, the values a row in a source.","reference\u002Fpackages\u002Fstate-session",{"path":2883,"title":2884,"description":2885,"stem":2886},"\u002Freference\u002Fpackages\u002Fsvelte","@fougere\u002Fsvelte","Fougere's four primitives as Svelte stores — host-independent.","reference\u002Fpackages\u002Fsvelte",{"path":2888,"title":2889,"description":2890,"stem":2891},"\u002Freference\u002Fpackages\u002Ftesting","@fougere\u002Ftesting","Tests derived from the declaration — cases, stubs and a gradient of realities.","reference\u002Fpackages\u002Ftesting",{"path":2893,"title":2894,"description":2895,"stem":2896},"\u002Freference\u002Fpackages\u002Ftransport-http","@fougere\u002Ftransport-http","The call contract on the wire, in JSON-RPC 2.0 (server + client).","reference\u002Fpackages\u002Ftransport-http",{"path":2898,"title":2899,"description":2900,"stem":2901},"\u002Freference\u002Fpackages\u002Fvite","@fougere\u002Fvite","The Vite plugin: what any Vite-built host must know to run a Fougere app.","reference\u002Fpackages\u002Fvite",{"path":2903,"title":2904,"description":2905,"stem":2906},"\u002Freference\u002Fpackages\u002Fworkflow","@fougere\u002Fworkflow","A release that goes to the end: the journal is three entities, the sweep is an operation, and a shared journal is one line of remotes:.","reference\u002Fpackages\u002Fworkflow",1794396612306]