[{"data":1,"prerenderedAt":2206},["ShallowReactive",2],{"navigation_docs_hu":3,"-hu-concepts-codegen-pipeline":442,"-hu-concepts-codegen-pipeline-surround":2201},[4,45,60,81,112,129,146,173,197,213,242,280,357,373,385,404,430],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":44},"Kezdő lépések","i-lucide-rocket","\u002Fhu\u002Fgetting-started","hu\u002F1.getting-started",[10,15,20,24,29,34,39],{"title":11,"path":12,"stem":13,"icon":14},"Bevezetés","\u002Fhu\u002Fgetting-started\u002Fintroduction","hu\u002F1.getting-started\u002F1.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Laravelből érkezőknek","\u002Fhu\u002Fgetting-started\u002Fcoming-from-laravel","hu\u002F1.getting-started\u002F2.coming-from-laravel","i-lucide-arrow-right-left",{"title":21,"path":22,"stem":23,"icon":19},"Symfonyból érkezőknek","\u002Fhu\u002Fgetting-started\u002Fcoming-from-symfony","hu\u002F1.getting-started\u002F3.coming-from-symfony",{"title":25,"path":26,"stem":27,"icon":28},"Telepítés","\u002Fhu\u002Fgetting-started\u002Finstallation","hu\u002F1.getting-started\u002F4.installation","i-lucide-download",{"title":30,"path":31,"stem":32,"icon":33},"Az első modulod","\u002Fhu\u002Fgetting-started\u002Ffirst-module","hu\u002F1.getting-started\u002F5.first-module","i-lucide-package-plus",{"title":35,"path":36,"stem":37,"icon":38},"Projektstruktúra","\u002Fhu\u002Fgetting-started\u002Fproject-structure","hu\u002F1.getting-started\u002F6.project-structure","i-lucide-folder-tree",{"title":40,"path":41,"stem":42,"icon":43},"A shop mintaalkalmazás","\u002Fhu\u002Fgetting-started\u002Fsample-app","hu\u002F1.getting-started\u002F7.sample-app","i-lucide-shopping-cart",false,{"title":46,"icon":47,"path":48,"stem":49,"children":50,"page":44},"queue","i-lucide-layers","\u002Fhu\u002Fqueue","hu\u002F10.queue",[51,56],{"title":52,"path":53,"stem":54,"icon":55},"Áttekintés","\u002Fhu\u002Fqueue\u002Foverview","hu\u002F10.queue\u002F1.overview","i-lucide-list-ordered",{"title":57,"path":58,"stem":59,"icon":47},"Taskok","\u002Fhu\u002Fqueue\u002Ftasks","hu\u002F10.queue\u002F2.tasks",{"title":61,"icon":62,"path":63,"stem":64,"children":65,"page":44},"events","i-lucide-workflow","\u002Fhu\u002Fevents","hu\u002F11.events",[66,71,76],{"title":67,"path":68,"stem":69,"icon":70},"Események","\u002Fhu\u002Fevents\u002Foverview","hu\u002F11.events\u002F1.overview","i-lucide-radio",{"title":72,"path":73,"stem":74,"icon":75},"Outbox","\u002Fhu\u002Fevents\u002Foutbox","hu\u002F11.events\u002F2.outbox","i-lucide-inbox",{"title":77,"path":78,"stem":79,"icon":80},"Ütemezés","\u002Fhu\u002Fevents\u002Fscheduler","hu\u002F11.events\u002F3.scheduler","i-lucide-calendar-clock",{"title":82,"icon":83,"path":84,"stem":85,"children":86,"page":44},"auth","i-lucide-shield-check","\u002Fhu\u002Fauth","hu\u002F12.auth",[87,92,97,102,107],{"title":88,"path":89,"stem":90,"icon":91},"Autentikáció","\u002Fhu\u002Fauth\u002Foverview","hu\u002F12.auth\u002F1.overview","i-lucide-key-round",{"title":93,"path":94,"stem":95,"icon":96},"RBAC","\u002Fhu\u002Fauth\u002Frbac","hu\u002F12.auth\u002F2.rbac","i-lucide-users",{"title":98,"path":99,"stem":100,"icon":101},"Policy-k","\u002Fhu\u002Fauth\u002Fpolicy","hu\u002F12.auth\u002F3.policy","i-lucide-gavel",{"title":103,"path":104,"stem":105,"icon":106},"Az auth önálló használata","\u002Fhu\u002Fauth\u002Fstandalone","hu\u002F12.auth\u002F4.standalone","i-lucide-plug",{"title":108,"path":109,"stem":110,"icon":111},"Social login goth-tal, önállóan","\u002Fhu\u002Fauth\u002Fsocial-standalone","hu\u002F12.auth\u002F5.social-standalone","i-lucide-log-in",{"title":113,"icon":114,"path":115,"stem":116,"children":117,"page":44},"mail","i-lucide-mail","\u002Fhu\u002Fmail","hu\u002F13.mail",[118,121,125],{"title":52,"path":119,"stem":120,"icon":114},"\u002Fhu\u002Fmail\u002Foverview","hu\u002F13.mail\u002F1.overview",{"title":122,"path":123,"stem":124,"icon":114},"SMTP","\u002Fhu\u002Fmail\u002Fsmtp","hu\u002F13.mail\u002F2.smtp",{"title":126,"path":127,"stem":128,"icon":114},"MJML","\u002Fhu\u002Fmail\u002Fmjml","hu\u002F13.mail\u002F3.mjml",{"title":130,"icon":131,"path":132,"stem":133,"children":134,"page":44},"notify","i-lucide-bell","\u002Fhu\u002Fnotify","hu\u002F14.notify",[135,138,142],{"title":52,"path":136,"stem":137,"icon":131},"\u002Fhu\u002Fnotify\u002Foverview","hu\u002F14.notify\u002F1.overview",{"title":139,"path":140,"stem":141,"icon":131},"Database csatorna","\u002Fhu\u002Fnotify\u002Fdatabase","hu\u002F14.notify\u002F2.database",{"title":143,"path":144,"stem":145,"icon":131},"Broadcast csatorna","\u002Fhu\u002Fnotify\u002Fbroadcast","hu\u002F14.notify\u002F3.broadcast",{"title":147,"icon":148,"path":149,"stem":150,"children":151,"page":44},"storage","i-lucide-hard-drive","\u002Fhu\u002Fstorage","hu\u002F15.storage",[152,155,159,163,168],{"title":52,"path":153,"stem":154,"icon":148},"\u002Fhu\u002Fstorage\u002Foverview","hu\u002F15.storage\u002F1.overview",{"title":156,"path":157,"stem":158},"Disk API","\u002Fhu\u002Fstorage\u002Fdisk-api","hu\u002F15.storage\u002F2.disk-api",{"title":160,"path":161,"stem":162,"icon":148},"Memória és helyi lemez","\u002Fhu\u002Fstorage\u002Flocal","hu\u002F15.storage\u002F3.local",{"title":164,"path":165,"stem":166,"icon":167},"S3","\u002Fhu\u002Fstorage\u002Fs3","hu\u002F15.storage\u002F4.s3","i-lucide-cloud",{"title":169,"path":170,"stem":171,"icon":172},"Tesztelés","\u002Fhu\u002Fstorage\u002Ftesting","hu\u002F15.storage\u002F5.testing","i-lucide-flask-conical",{"title":174,"icon":175,"path":176,"stem":177,"children":178,"page":44},"telemetry","i-lucide-activity","\u002Fhu\u002Ftelemetry","hu\u002F16.telemetry",[179,182,187,192],{"title":52,"path":180,"stem":181,"icon":175},"\u002Fhu\u002Ftelemetry\u002Foverview","hu\u002F16.telemetry\u002F1.overview",{"title":183,"path":184,"stem":185,"icon":186},"Logolás","\u002Fhu\u002Ftelemetry\u002Flogging","hu\u002F16.telemetry\u002F2.logging","i-lucide-scroll-text",{"title":188,"path":189,"stem":190,"icon":191},"OpenTelemetry","\u002Fhu\u002Ftelemetry\u002Fopentelemetry","hu\u002F16.telemetry\u002F3.opentelemetry","i-lucide-radar",{"title":193,"path":194,"stem":195,"icon":196},"Sentry","\u002Fhu\u002Ftelemetry\u002Fsentry","hu\u002F16.telemetry\u002F4.sentry","i-lucide-bug",{"title":198,"icon":199,"path":200,"stem":201,"children":202,"page":44},"Referencia","i-lucide-book-open","\u002Fhu\u002Freference","hu\u002F17.reference",[203,208],{"title":204,"path":205,"stem":206,"icon":207},"Konfiguráció","\u002Fhu\u002Freference\u002Fconfiguration","hu\u002F17.reference\u002F1.configuration","i-lucide-settings",{"title":209,"path":210,"stem":211,"icon":212},"Külső függőségek","\u002Fhu\u002Freference\u002Fdependencies","hu\u002F17.reference\u002F2.dependencies","i-lucide-package",{"title":214,"icon":215,"path":216,"stem":217,"children":218,"page":44},"Koncepciók","i-lucide-lightbulb","\u002Fhu\u002Fconcepts","hu\u002F2.concepts",[219,223,228,232,237],{"title":220,"path":221,"stem":222,"icon":47},"Architektúra","\u002Fhu\u002Fconcepts\u002Farchitecture","hu\u002F2.concepts\u002F1.architecture",{"title":224,"path":225,"stem":226,"icon":227},"Hibamodell","\u002Fhu\u002Fconcepts\u002Ferror-model","hu\u002F2.concepts\u002F2.error-model","i-lucide-shield-alert",{"title":204,"path":229,"stem":230,"icon":231},"\u002Fhu\u002Fconcepts\u002Fconfiguration","hu\u002F2.concepts\u002F3.configuration","i-lucide-settings-2",{"title":233,"path":234,"stem":235,"icon":236},"Codegen pipeline","\u002Fhu\u002Fconcepts\u002Fcodegen-pipeline","hu\u002F2.concepts\u002F4.codegen-pipeline","i-lucide-file-json",{"title":238,"path":239,"stem":240,"icon":241},"Design patternek","\u002Fhu\u002Fconcepts\u002Fdesign-patterns","hu\u002F2.concepts\u002F5.design-patterns","i-lucide-puzzle",{"title":243,"icon":244,"path":245,"stem":246,"children":247,"page":44},"A kit","i-lucide-box","\u002Fhu\u002Fkit","hu\u002F3.kit",[248,252,257,262,267,271,276],{"title":249,"path":250,"stem":251,"icon":244},"A kit áttekintése","\u002Fhu\u002Fkit\u002Foverview","hu\u002F3.kit\u002F1.overview",{"title":253,"path":254,"stem":255,"icon":256},"Alkalmazás-életciklus","\u002Fhu\u002Fkit\u002Fapp","hu\u002F3.kit\u002F2.app","i-lucide-power",{"title":258,"path":259,"stem":260,"icon":261},"Szerver","\u002Fhu\u002Fkit\u002Fserver","hu\u002F3.kit\u002F3.server","i-lucide-server",{"title":263,"path":264,"stem":265,"icon":266},"Worker","\u002Fhu\u002Fkit\u002Fworker","hu\u002F3.kit\u002F4.worker","i-lucide-cog",{"title":268,"path":269,"stem":270,"icon":70},"Realtime","\u002Fhu\u002Fkit\u002Frealtime","hu\u002F3.kit\u002F5.realtime",{"title":272,"path":273,"stem":274,"icon":275},"Migrációk","\u002Fhu\u002Fkit\u002Fmigrations","hu\u002F3.kit\u002F6.migrations","i-lucide-file-stack",{"title":277,"path":278,"stem":279,"icon":111},"Social login","\u002Fhu\u002Fkit\u002Fsocial-login","hu\u002F3.kit\u002F7.social-login",{"title":281,"icon":282,"path":283,"stem":284,"children":285,"page":44},"CLI referencia","i-lucide-terminal","\u002Fhu\u002Fcli","hu\u002F4.cli",[286,289,294,299,304,309,314,319,324,329,334,338,343,348,352],{"title":52,"path":287,"stem":288,"icon":282},"\u002Fhu\u002Fcli\u002Foverview","hu\u002F4.cli\u002F1.overview",{"title":290,"path":291,"stem":292,"icon":293},"add db","\u002Fhu\u002Fcli\u002Fadd-db","hu\u002F4.cli\u002F10.add-db","i-lucide-database-zap",{"title":295,"path":296,"stem":297,"icon":298},"add compose \u002F add docker","\u002Fhu\u002Fcli\u002Fadd-compose","hu\u002F4.cli\u002F11.add-compose","i-lucide-container",{"title":300,"path":301,"stem":302,"icon":303},"add mail","\u002Fhu\u002Fcli\u002Fadd-mail","hu\u002F4.cli\u002F12.add-mail","i-lucide-mail-plus",{"title":305,"path":306,"stem":307,"icon":308},"add notification","\u002Fhu\u002Fcli\u002Fadd-notification","hu\u002F4.cli\u002F13.add-notification","i-lucide-bell-plus",{"title":310,"path":311,"stem":312,"icon":313},"add realtime","\u002Fhu\u002Fcli\u002Fadd-realtime","hu\u002F4.cli\u002F14.add-realtime","i-lucide-radio-tower",{"title":315,"path":316,"stem":317,"icon":318},"add seeder","\u002Fhu\u002Fcli\u002Fadd-seeder","hu\u002F4.cli\u002F15.add-seeder","i-lucide-sprout",{"title":320,"path":321,"stem":322,"icon":323},"new project","\u002Fhu\u002Fcli\u002Fnew-project","hu\u002F4.cli\u002F2.new-project","i-lucide-folder-plus",{"title":325,"path":326,"stem":327,"icon":328},"new module","\u002Fhu\u002Fcli\u002Fnew-module","hu\u002F4.cli\u002F3.new-module","i-lucide-blocks",{"title":330,"path":331,"stem":332,"icon":333},"add surface","\u002Fhu\u002Fcli\u002Fadd-surface","hu\u002F4.cli\u002F4.add-surface","i-lucide-layers-2",{"title":335,"path":336,"stem":337,"icon":244},"add core","\u002Fhu\u002Fcli\u002Fadd-core","hu\u002F4.cli\u002F5.add-core",{"title":339,"path":340,"stem":341,"icon":342},"add handler","\u002Fhu\u002Fcli\u002Fadd-handler","hu\u002F4.cli\u002F6.add-handler","i-lucide-webhook",{"title":344,"path":345,"stem":346,"icon":347},"new migration","\u002Fhu\u002Fcli\u002Fnew-migration","hu\u002F4.cli\u002F7.new-migration","i-lucide-file-plus",{"title":349,"path":350,"stem":351,"icon":266},"worker generátorok","\u002Fhu\u002Fcli\u002Fworker-generators","hu\u002F4.cli\u002F8.worker-generators",{"title":353,"path":354,"stem":355,"icon":356},"upgrade templates","\u002Fhu\u002Fcli\u002Fupgrade-templates","hu\u002F4.cli\u002F9.upgrade-templates","i-lucide-refresh-cw",{"title":358,"icon":227,"path":359,"stem":360,"children":361,"page":44},"errs","\u002Fhu\u002Ferrs","hu\u002F5.errs",[362,365,369],{"title":52,"path":363,"stem":364,"icon":227},"\u002Fhu\u002Ferrs\u002Foverview","hu\u002F5.errs\u002F1.overview",{"title":366,"path":367,"stem":368},"API","\u002Fhu\u002Ferrs\u002Fapi","hu\u002F5.errs\u002F2.api",{"title":370,"path":371,"stem":372,"icon":227},"Integráció","\u002Fhu\u002Ferrs\u002Fintegration","hu\u002F5.errs\u002F3.integration",{"title":374,"icon":231,"path":375,"stem":376,"children":377,"page":44},"envconf","\u002Fhu\u002Fenvconf","hu\u002F6.envconf",[378,381],{"title":52,"path":379,"stem":380,"icon":231},"\u002Fhu\u002Fenvconf\u002Foverview","hu\u002F6.envconf\u002F1.overview",{"title":382,"path":383,"stem":384},"Receptek","\u002Fhu\u002Fenvconf\u002Frecipes","hu\u002F6.envconf\u002F2.recipes",{"title":386,"icon":387,"path":388,"stem":389,"children":390,"page":44},"httperr","i-lucide-globe","\u002Fhu\u002Fhttperr","hu\u002F7.httperr",[391,394,399],{"title":52,"path":392,"stem":393,"icon":387},"\u002Fhu\u002Fhttperr\u002Foverview","hu\u002F7.httperr\u002F1.overview",{"title":395,"path":396,"stem":397,"icon":398},"Hibaválaszok","\u002Fhu\u002Fhttperr\u002Ferror-responses","hu\u002F7.httperr\u002F2.error-responses","i-lucide-octagon-alert",{"title":400,"path":401,"stem":402,"icon":403},"Validáció","\u002Fhu\u002Fhttperr\u002Fvalidation","hu\u002F7.httperr\u002F3.validation","i-lucide-badge-check",{"title":405,"icon":406,"path":407,"stem":408,"children":409,"page":44},"dbx","i-lucide-database","\u002Fhu\u002Fdbx","hu\u002F8.dbx",[410,413,417,421,426],{"title":52,"path":411,"stem":412,"icon":406},"\u002Fhu\u002Fdbx\u002Foverview","hu\u002F8.dbx\u002F1.overview",{"title":414,"path":415,"stem":416,"icon":106},"pgx","\u002Fhu\u002Fdbx\u002Fpg","hu\u002F8.dbx\u002F2.pg",{"title":418,"path":419,"stem":420,"icon":47},"bun","\u002Fhu\u002Fdbx\u002Fbunx","hu\u002F8.dbx\u002F3.bunx",{"title":422,"path":423,"stem":424,"icon":425},"Tranzakciók","\u002Fhu\u002Fdbx\u002Ftransactions","hu\u002F8.dbx\u002F4.transactions","i-lucide-git-merge",{"title":427,"path":428,"stem":429,"icon":318},"Seederek","\u002Fhu\u002Fdbx\u002Fseed","hu\u002F8.dbx\u002F5.seed",{"title":431,"icon":55,"path":432,"stem":433,"children":434,"page":44},"paginate","\u002Fhu\u002Fpaginate","hu\u002F9.paginate",[435,438],{"title":52,"path":436,"stem":437,"icon":55},"\u002Fhu\u002Fpaginate\u002Foverview","hu\u002F9.paginate\u002F1.overview",{"title":439,"path":440,"stem":441,"icon":19},"Cursor-lapozás","\u002Fhu\u002Fpaginate\u002Fcursor","hu\u002F9.paginate\u002F2.cursor",{"id":443,"title":233,"body":444,"description":2194,"extension":2195,"links":2196,"meta":2197,"navigation":2198,"path":234,"seo":2199,"stem":235,"__hash__":2200},"docs_hu\u002Fhu\u002F2.concepts\u002F4.codegen-pipeline.md",{"type":445,"value":446,"toc":2181},"minimark",[447,456,467,539,544,616,634,638,657,785,796,817,898,907,1121,1131,1505,1539,1543,1575,1580,1593,1597,1619,1625,1628,1732,1746,1750,1757,1879,1921,1928,1935,2089,2100,2104,2153,2157,2177],[448,449,450,451,455],"p",{},"A gpsystem projektek API-kontraktusa ",[452,453,454],"strong",{},"spec-first",": a source of truth a TypeSpec, abból fordul OpenAPI, abból pedig szigorú (\"strict\") szerver-interfész. Így egy spec-eltérés nem futásidejű meglepetés, hanem fordítási hiba:",[457,458,463],"pre",{"className":459,"code":461,"language":462},[460],"language-text","spec\u002Ftypespec\u002F**.tsp ──tsp compile──▶ api\u002Fopenapi\u002F\u003CNamespace>.yaml\n        │                                     │\n        │ source of truth                     │ oapi-codegen v2.8.x\n        │ (kézzel + generátorokkal)           │ + engine-specifikus template-ek\n        ▼                                     ▼\n  gpsystem CLI                internal\u002Fmodules\u002F\u003Cm>\u002Fsurfaces\u002F\u003Cs>\u002Fhttp\u002Fgen\u002Fapi.gen.go\n","text",[464,465,461],"code",{"__ignoreMap":466},"",[448,468,469,470,473,474,477,478,477,481,477,484,487,488,491,492,495,496,499,500,503,504,507,508,511,512,515,516,519,520,523,524,527,528,531,532,534,535,538],{},"A ",[464,471,472],{},"mise run generate"," futtatja a teljes láncot: ",[464,475,476],{},"tsp compile"," → ",[464,479,480],{},"go generate .\u002F...",[464,482,483],{},"go mod tidy",[464,485,486],{},"go build .\u002F...",". A ",[464,489,490],{},"go:generate"," direktíva a surface ",[464,493,494],{},"http\u002Fhandler.go","-jában él, és az ",[464,497,498],{},"api\u002Foapi-codegen\u002F\u003Cmodul>-\u003Csurface>.yaml"," konfigot hajtja (a ",[464,501,502],{},"surfaces\u002F"," wrapper miatt a benne hivatkozott relatív útvonalak hat szinttel lépnek feljebb: ",[464,505,506],{},"..\u002F..\u002F..\u002F..\u002F..\u002F..\u002F","). Ez a fájl csak a ",[464,509,510],{},"Handler"," structot, a ",[464,513,514],{},"New","-t és az interfész-assertiont tartalmazza; maguk a handler-metódusok ",[452,517,518],{},"kategóriánként egy fájlban"," élnek (",[464,521,522],{},"\u003Cmodul>_handler.go",", vagy ",[464,525,526],{},"\u003Cmodul>_\u003Ccsoport>_handler.go"," egy olyan kategóriának, mint ",[464,529,530],{},"notifications","), így az ",[464,533,339],{}," futtatása műveletek szerint csoportosít, nem szór szét egy fájlt függvényenként (lásd ",[536,537,339],"a",{"href":340},").",[540,541,543],"h2",{"id":542},"typespec-konvenciók","TypeSpec konvenciók",[545,546,547,582,609],"ul",{},[548,549,550,551,554,555,558,559,562,563,566,567,570,571,574,575,578,579,538],"li",{},"Minden surface saját ",[464,552,553],{},"@service"," ",[464,556,557],{},"@server(\"\u002Fapi\u002Fv1\u003Cbase>\")","-zel. Az emitter a kimeneti fájlt a ",[452,560,561],{},"namespace-ről"," nevezi el, ezért a namespace-ek determinisztikusak: ",[464,564,565],{},"Project.Module"," az ",[464,568,569],{},"api"," surface-re, ",[464,572,573],{},"Project.Module\u003CSurface>"," minden másra (a shopban: ",[464,576,577],{},"Shop.Shop"," és ",[464,580,581],{},"Shop.ShopAdmin",[548,583,469,584,587,588,591,592,594,595,587,598,601,602,591,605,608],{},[464,585,586],{},"shared\u002Ferrors.tsp"," a ",[464,589,590],{},"httperr.Problem"," tükre (",[536,593,224],{"href":225},"); a ",[464,596,597],{},"shared\u002Fpaginator.tsp",[464,599,600],{},"paginate.Page[T]"," \u002F ",[464,603,604],{},"paginate.CursorPage[T]",[536,606,607],{"href":436},"Lapozás","). Tartsd őket szinkronban a Go-oldallal.",[548,610,611,612,615],{},"Az OpenAPI kimenet ",[452,613,614],{},"3.0-ra"," van rögzítve (az oapi-codegen nem olvas 3.1-et).",[617,618,620,621,623,624,587,627,629,630,633],"warning",{"title":619},"A namespace-ek testvérek legyenek","Soha ne ágyazz egy ",[464,622,553],{}," namespace-t egy másikba (pl. ",[464,625,626],{},"Shop.Shop.Admin",[464,628,577],{}," alá). A TypeSpec összefésüli a route-jaikat, és ",[464,631,632],{},"duplicate-operation"," hibával áll le. A generátorok mindig testvér namespace-eket emittálnak.",[540,635,637],{"id":636},"egy-művelet-útja-a-shop-terméklistája","Egy művelet útja: a shop terméklistája",[448,639,640,643,644,646,647,650,651,587,653,656],{},[452,641,642],{},"1. A kontraktus."," A shop ",[464,645,569],{}," surface-ének ",[464,648,649],{},".tsp","-jében: az ",[464,652,339],{},[464,654,655],{},"\u002F\u002F gpsystem:operations"," anchorhoz illeszt, de kézzel is ugyanide írsz:",[457,658,663],{"className":659,"code":660,"filename":661,"language":662,"meta":466,"style":466},"language-tsp shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","@tag(\"shop\")\ninterface ShopApi {\n  \u002F\u002F gpsystem:operations\n  @get\n  @route(\"\u002Fproducts\")\n  @operationId(\"ListProducts\")\n  @summary(\"List products\")\n  listProducts(...CursorQuery): CursorPage\u003CProduct>;\n}\n","spec\u002Ftypespec\u002Fmodules\u002Fshop\u002Fapi.tsp","tsp",[464,664,665,685,699,706,712,725,738,751,779],{"__ignoreMap":466},[666,667,670,674,678,682],"span",{"class":668,"line":669},"line",1,[666,671,673],{"class":672},"swJcz","@tag",[666,675,677],{"class":676},"sMK4o","(",[666,679,681],{"class":680},"sfazB","\"shop\"",[666,683,684],{"class":676},")\n",[666,686,688,692,696],{"class":668,"line":687},2,[666,689,691],{"class":690},"sbssI","interface",[666,693,695],{"class":694},"sBMFI"," ShopApi",[666,697,698],{"class":676}," {\n",[666,700,702],{"class":668,"line":701},3,[666,703,705],{"class":704},"sHwdD","  \u002F\u002F gpsystem:operations\n",[666,707,709],{"class":668,"line":708},4,[666,710,711],{"class":672},"  @get\n",[666,713,715,718,720,723],{"class":668,"line":714},5,[666,716,717],{"class":672},"  @route",[666,719,677],{"class":676},[666,721,722],{"class":680},"\"\u002Fproducts\"",[666,724,684],{"class":676},[666,726,728,731,733,736],{"class":668,"line":727},6,[666,729,730],{"class":672},"  @operationId",[666,732,677],{"class":676},[666,734,735],{"class":680},"\"ListProducts\"",[666,737,684],{"class":676},[666,739,741,744,746,749],{"class":668,"line":740},7,[666,742,743],{"class":672},"  @summary",[666,745,677],{"class":676},[666,747,748],{"class":680},"\"List products\"",[666,750,684],{"class":676},[666,752,754,758,761,764,767,770,773,776],{"class":668,"line":753},8,[666,755,757],{"class":756},"s2Zo4","  listProducts",[666,759,760],{"class":676},"(...",[666,762,763],{"class":694},"CursorQuery",[666,765,766],{"class":676},"):",[666,768,769],{"class":694}," CursorPage",[666,771,772],{"class":676},"\u003C",[666,774,775],{"class":694},"Product",[666,777,778],{"class":676},">;\n",[666,780,782],{"class":668,"line":781},9,[666,783,784],{"class":676},"}\n",[448,786,469,787,601,789,792,793,795],{},[464,788,763],{},[464,790,791],{},"CursorPage\u003CT>"," a scaffoldolt ",[464,794,597],{},"-ből jön: cursor-lapozott lista egyetlen sorban.",[448,797,798,801,802,804,805,808,809,812,813,816],{},[452,799,800],{},"2. A generált interfész."," A ",[464,803,476],{}," után az oapi-codegen egy strict interfészt emittál a ",[464,806,807],{},"gen"," csomagba: a request\u002Fresponse típusnevekben nincs ",[464,810,811],{},"Object"," utótag, és a szignatúra semmi mástól nem függ, csak a ",[464,814,815],{},"context.Context","-től és sima Go típusoktól:",[457,818,823],{"className":819,"code":820,"filename":821,"language":822,"meta":466,"style":466},"language-go shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","type StrictServerInterface interface {\n    \u002F\u002F (GET \u002Fproducts)\n    ListProducts(ctx context.Context, request ListProductsRequest) (ListProductsResponse, error)\n    \u002F\u002F ...\n}\n","internal\u002Fmodules\u002Fshop\u002Fsurfaces\u002Fapi\u002Fhttp\u002Fgen\u002Fapi.gen.go (generált, ne szerkeszd)","go",[464,824,825,838,843,889,894],{"__ignoreMap":466},[666,826,827,830,833,836],{"class":668,"line":669},[666,828,829],{"class":676},"type",[666,831,832],{"class":694}," StrictServerInterface",[666,834,835],{"class":676}," interface",[666,837,698],{"class":676},[666,839,840],{"class":668,"line":687},[666,841,842],{"class":704},"    \u002F\u002F (GET \u002Fproducts)\n",[666,844,845,848,850,854,857,860,863,866,869,872,875,878,881,883,887],{"class":668,"line":701},[666,846,847],{"class":756},"    ListProducts",[666,849,677],{"class":676},[666,851,853],{"class":852},"sHdIc","ctx",[666,855,856],{"class":694}," context",[666,858,859],{"class":676},".",[666,861,862],{"class":694},"Context",[666,864,865],{"class":676},",",[666,867,868],{"class":852}," request",[666,870,871],{"class":694}," ListProductsRequest",[666,873,874],{"class":676},")",[666,876,877],{"class":676}," (",[666,879,880],{"class":694},"ListProductsResponse",[666,882,865],{"class":676},[666,884,886],{"class":885},"spNyl"," error",[666,888,684],{"class":676},[666,890,891],{"class":668,"line":708},[666,892,893],{"class":704},"    \u002F\u002F ...\n",[666,895,896],{"class":668,"line":714},[666,897,784],{"class":676},[448,899,900,903,904,906],{},[452,901,902],{},"3. A handler."," Ezt már te írod (a vázat az ",[464,905,339],{}," adja):",[457,908,911],{"className":819,"code":909,"filename":910,"language":822,"meta":466,"style":466},"func (h *Handler) ListProducts(ctx context.Context, req gen.ListProductsRequest) (gen.ListProductsResponse, error) {\n    page, err := h.svc.ListProducts(ctx, req.Params.Cursor, req.Params.Limit)\n    if err != nil {\n        return nil, service.ErrListProducts.Wrap(err, \"api: list products\")\n    }\n    return gen.ListProducts200JSONResponse(page), nil\n}\n","internal\u002Fmodules\u002Fshop\u002Fsurfaces\u002Fapi\u002Fhttp\u002Fshop_handler.go",[464,912,913,974,1034,1050,1089,1094,1117],{"__ignoreMap":466},[666,914,915,918,920,923,926,928,930,933,935,937,939,941,943,945,948,951,953,956,958,960,962,964,966,968,970,972],{"class":668,"line":669},[666,916,917],{"class":676},"func",[666,919,877],{"class":676},[666,921,922],{"class":852},"h ",[666,924,925],{"class":676},"*",[666,927,510],{"class":694},[666,929,874],{"class":676},[666,931,932],{"class":756}," ListProducts",[666,934,677],{"class":676},[666,936,853],{"class":852},[666,938,856],{"class":694},[666,940,859],{"class":676},[666,942,862],{"class":694},[666,944,865],{"class":676},[666,946,947],{"class":852}," req",[666,949,950],{"class":694}," gen",[666,952,859],{"class":676},[666,954,955],{"class":694},"ListProductsRequest",[666,957,874],{"class":676},[666,959,877],{"class":676},[666,961,807],{"class":694},[666,963,859],{"class":676},[666,965,880],{"class":694},[666,967,865],{"class":676},[666,969,886],{"class":885},[666,971,874],{"class":676},[666,973,698],{"class":676},[666,975,976,980,982,985,988,991,993,996,998,1001,1003,1005,1007,1009,1011,1014,1016,1019,1021,1023,1025,1027,1029,1032],{"class":668,"line":687},[666,977,979],{"class":978},"sTEyZ","    page",[666,981,865],{"class":676},[666,983,984],{"class":978}," err ",[666,986,987],{"class":676},":=",[666,989,990],{"class":978}," h",[666,992,859],{"class":676},[666,994,995],{"class":978},"svc",[666,997,859],{"class":676},[666,999,1000],{"class":756},"ListProducts",[666,1002,677],{"class":676},[666,1004,853],{"class":978},[666,1006,865],{"class":676},[666,1008,947],{"class":978},[666,1010,859],{"class":676},[666,1012,1013],{"class":978},"Params",[666,1015,859],{"class":676},[666,1017,1018],{"class":978},"Cursor",[666,1020,865],{"class":676},[666,1022,947],{"class":978},[666,1024,859],{"class":676},[666,1026,1013],{"class":978},[666,1028,859],{"class":676},[666,1030,1031],{"class":978},"Limit",[666,1033,684],{"class":676},[666,1035,1036,1040,1042,1045,1048],{"class":668,"line":701},[666,1037,1039],{"class":1038},"s7zQu","    if",[666,1041,984],{"class":978},[666,1043,1044],{"class":676},"!=",[666,1046,1047],{"class":676}," nil",[666,1049,698],{"class":676},[666,1051,1052,1055,1058,1061,1063,1066,1068,1071,1073,1076,1078,1081,1084,1087],{"class":668,"line":708},[666,1053,1054],{"class":1038},"        return",[666,1056,1057],{"class":676}," nil,",[666,1059,1060],{"class":978}," service",[666,1062,859],{"class":676},[666,1064,1065],{"class":978},"ErrListProducts",[666,1067,859],{"class":676},[666,1069,1070],{"class":756},"Wrap",[666,1072,677],{"class":676},[666,1074,1075],{"class":978},"err",[666,1077,865],{"class":676},[666,1079,1080],{"class":676}," \"",[666,1082,1083],{"class":680},"api: list products",[666,1085,1086],{"class":676},"\"",[666,1088,684],{"class":676},[666,1090,1091],{"class":668,"line":714},[666,1092,1093],{"class":676},"    }\n",[666,1095,1096,1099,1101,1103,1106,1108,1111,1114],{"class":668,"line":727},[666,1097,1098],{"class":1038},"    return",[666,1100,950],{"class":978},[666,1102,859],{"class":676},[666,1104,1105],{"class":756},"ListProducts200JSONResponse",[666,1107,677],{"class":676},[666,1109,1110],{"class":978},"page",[666,1112,1113],{"class":676},"),",[666,1115,1116],{"class":676}," nil\n",[666,1118,1119],{"class":668,"line":740},[666,1120,784],{"class":676},[448,1122,1123,1126,1127,1130],{},[452,1124,1125],{},"4. A bekötés."," A generált drótozás a ",[464,1128,1129],{},"register.go","-ban:",[457,1132,1135],{"className":819,"code":1133,"filename":1134,"language":822,"meta":466,"style":466},"func RegisterApi(router chi.Router, deps Dependencies) {\n    apiSvc := apiservice.New()\n    apiHandler := apihttp.New(apiSvc)\n    apiPolicies := apipolicy.New()\n    router.Route(\"\u002Fshop\", func(r chi.Router) {\n        shopapigen.HandlerWithOptions(shopapigen.NewStrictHandlerWithOptions(\n            apiHandler,\n            []shopapigen.StrictMiddlewareFunc{\n                server.StrictValidator[shopapigen.StrictHandlerFunc](nil),\n                \u002F\u002F Az utolsó a legkülső: az authorizáció a validáció előtt fut.\n                policy.Enforcer[shopapigen.StrictHandlerFunc](apiPolicies, shopapigen.PermissionByOperation, shopapigen.PolicyByOperation),\n            },\n            shopapigen.StrictHTTPServerOptions{\n                RequestErrorHandlerFunc:  httperr.WriteBadRequest,\n                ResponseErrorHandlerFunc: server.WriteError,\n            },\n        ), shopapigen.ChiServerOptions{\n            BaseRouter:       r,\n            ErrorHandlerFunc: httperr.WriteBadRequest,\n        })\n    })\n}\n","internal\u002Fmodules\u002Fshop\u002Fregister.go",[464,1136,1137,1169,1186,1207,1223,1260,1283,1291,1306,1329,1335,1382,1388,1401,1420,1438,1443,1458,1471,1488,1494,1500],{"__ignoreMap":466},[666,1138,1139,1141,1144,1146,1149,1152,1154,1157,1159,1162,1165,1167],{"class":668,"line":669},[666,1140,917],{"class":676},[666,1142,1143],{"class":756}," RegisterApi",[666,1145,677],{"class":676},[666,1147,1148],{"class":852},"router",[666,1150,1151],{"class":694}," chi",[666,1153,859],{"class":676},[666,1155,1156],{"class":694},"Router",[666,1158,865],{"class":676},[666,1160,1161],{"class":852}," deps",[666,1163,1164],{"class":694}," Dependencies",[666,1166,874],{"class":676},[666,1168,698],{"class":676},[666,1170,1171,1174,1176,1179,1181,1183],{"class":668,"line":687},[666,1172,1173],{"class":978},"    apiSvc ",[666,1175,987],{"class":676},[666,1177,1178],{"class":978}," apiservice",[666,1180,859],{"class":676},[666,1182,514],{"class":756},[666,1184,1185],{"class":676},"()\n",[666,1187,1188,1191,1193,1196,1198,1200,1202,1205],{"class":668,"line":701},[666,1189,1190],{"class":978},"    apiHandler ",[666,1192,987],{"class":676},[666,1194,1195],{"class":978}," apihttp",[666,1197,859],{"class":676},[666,1199,514],{"class":756},[666,1201,677],{"class":676},[666,1203,1204],{"class":978},"apiSvc",[666,1206,684],{"class":676},[666,1208,1209,1212,1214,1217,1219,1221],{"class":668,"line":708},[666,1210,1211],{"class":978},"    apiPolicies ",[666,1213,987],{"class":676},[666,1215,1216],{"class":978}," apipolicy",[666,1218,859],{"class":676},[666,1220,514],{"class":756},[666,1222,1185],{"class":676},[666,1224,1225,1228,1230,1233,1235,1237,1240,1242,1244,1247,1250,1252,1254,1256,1258],{"class":668,"line":714},[666,1226,1227],{"class":978},"    router",[666,1229,859],{"class":676},[666,1231,1232],{"class":756},"Route",[666,1234,677],{"class":676},[666,1236,1086],{"class":676},[666,1238,1239],{"class":680},"\u002Fshop",[666,1241,1086],{"class":676},[666,1243,865],{"class":676},[666,1245,1246],{"class":676}," func(",[666,1248,1249],{"class":852},"r",[666,1251,1151],{"class":694},[666,1253,859],{"class":676},[666,1255,1156],{"class":694},[666,1257,874],{"class":676},[666,1259,698],{"class":676},[666,1261,1262,1265,1267,1270,1272,1275,1277,1280],{"class":668,"line":727},[666,1263,1264],{"class":978},"        shopapigen",[666,1266,859],{"class":676},[666,1268,1269],{"class":756},"HandlerWithOptions",[666,1271,677],{"class":676},[666,1273,1274],{"class":978},"shopapigen",[666,1276,859],{"class":676},[666,1278,1279],{"class":756},"NewStrictHandlerWithOptions",[666,1281,1282],{"class":676},"(\n",[666,1284,1285,1288],{"class":668,"line":740},[666,1286,1287],{"class":978},"            apiHandler",[666,1289,1290],{"class":676},",\n",[666,1292,1293,1296,1298,1300,1303],{"class":668,"line":753},[666,1294,1295],{"class":676},"            []",[666,1297,1274],{"class":694},[666,1299,859],{"class":676},[666,1301,1302],{"class":694},"StrictMiddlewareFunc",[666,1304,1305],{"class":676},"{\n",[666,1307,1308,1311,1313,1316,1319,1321,1323,1326],{"class":668,"line":781},[666,1309,1310],{"class":978},"                server",[666,1312,859],{"class":676},[666,1314,1315],{"class":756},"StrictValidator",[666,1317,1318],{"class":676},"[",[666,1320,1274],{"class":694},[666,1322,859],{"class":676},[666,1324,1325],{"class":694},"StrictHandlerFunc",[666,1327,1328],{"class":676},"](nil),\n",[666,1330,1332],{"class":668,"line":1331},10,[666,1333,1334],{"class":704},"                \u002F\u002F Az utolsó a legkülső: az authorizáció a validáció előtt fut.\n",[666,1336,1338,1341,1343,1346,1348,1350,1352,1354,1357,1360,1362,1365,1367,1370,1372,1374,1376,1379],{"class":668,"line":1337},11,[666,1339,1340],{"class":978},"                policy",[666,1342,859],{"class":676},[666,1344,1345],{"class":756},"Enforcer",[666,1347,1318],{"class":676},[666,1349,1274],{"class":694},[666,1351,859],{"class":676},[666,1353,1325],{"class":694},[666,1355,1356],{"class":676},"](",[666,1358,1359],{"class":978},"apiPolicies",[666,1361,865],{"class":676},[666,1363,1364],{"class":978}," shopapigen",[666,1366,859],{"class":676},[666,1368,1369],{"class":978},"PermissionByOperation",[666,1371,865],{"class":676},[666,1373,1364],{"class":978},[666,1375,859],{"class":676},[666,1377,1378],{"class":978},"PolicyByOperation",[666,1380,1381],{"class":676},"),\n",[666,1383,1385],{"class":668,"line":1384},12,[666,1386,1387],{"class":676},"            },\n",[666,1389,1391,1394,1396,1399],{"class":668,"line":1390},13,[666,1392,1393],{"class":694},"            shopapigen",[666,1395,859],{"class":676},[666,1397,1398],{"class":694},"StrictHTTPServerOptions",[666,1400,1305],{"class":676},[666,1402,1404,1407,1410,1413,1415,1418],{"class":668,"line":1403},14,[666,1405,1406],{"class":978},"                RequestErrorHandlerFunc",[666,1408,1409],{"class":676},":",[666,1411,1412],{"class":978},"  httperr",[666,1414,859],{"class":676},[666,1416,1417],{"class":978},"WriteBadRequest",[666,1419,1290],{"class":676},[666,1421,1423,1426,1428,1431,1433,1436],{"class":668,"line":1422},15,[666,1424,1425],{"class":978},"                ResponseErrorHandlerFunc",[666,1427,1409],{"class":676},[666,1429,1430],{"class":978}," server",[666,1432,859],{"class":676},[666,1434,1435],{"class":978},"WriteError",[666,1437,1290],{"class":676},[666,1439,1441],{"class":668,"line":1440},16,[666,1442,1387],{"class":676},[666,1444,1446,1449,1451,1453,1456],{"class":668,"line":1445},17,[666,1447,1448],{"class":676},"        ),",[666,1450,1364],{"class":694},[666,1452,859],{"class":676},[666,1454,1455],{"class":694},"ChiServerOptions",[666,1457,1305],{"class":676},[666,1459,1461,1464,1466,1469],{"class":668,"line":1460},18,[666,1462,1463],{"class":978},"            BaseRouter",[666,1465,1409],{"class":676},[666,1467,1468],{"class":978},"       r",[666,1470,1290],{"class":676},[666,1472,1474,1477,1479,1482,1484,1486],{"class":668,"line":1473},19,[666,1475,1476],{"class":978},"            ErrorHandlerFunc",[666,1478,1409],{"class":676},[666,1480,1481],{"class":978}," httperr",[666,1483,859],{"class":676},[666,1485,1417],{"class":978},[666,1487,1290],{"class":676},[666,1489,1491],{"class":668,"line":1490},20,[666,1492,1493],{"class":676},"        })\n",[666,1495,1497],{"class":668,"line":1496},21,[666,1498,1499],{"class":676},"    })\n",[666,1501,1503],{"class":668,"line":1502},22,[666,1504,784],{"class":676},[448,1506,1507,1508,1511,1512,1515,1516,1519,1520,566,1522,1524,1525,1524,1528,1531,1532,1534,1535,1538],{},"A kérésvalidáció a ",[464,1509,1510],{},"server.StrictValidator"," strict middleware-ként fut, a lánc legbelső elemeként; a hibarenderelés (mind a validációból\u002Fdekódolásból, mind egy visszaadott üzleti hibából) a ",[464,1513,1514],{},"server.WriteError","-on és a ",[464,1517,1518],{},"httperr.WriteBadRequest","-en megy át, a generált kód hibahookjaiba kötve. A ",[464,1521,1514],{},[464,1523,82],{},"\u002F",[464,1526,1527],{},"rbac",[464,1529,1530],{},"policy"," sentineleket (lásd ",[536,1533,98],{"href":99},") Problemre képezi, mielőtt mindent mást a ",[464,1536,1537],{},"httperr.WriteError","-ra delegálna. Az üzleti kódodat egyik sem érinti.",[540,1540,1542],{"id":1541},"a-template-készlet-upstream-routing-minimális-strict-override","A template-készlet: upstream routing + minimális strict override",[448,1544,1545,1546,554,1549,1552,1553,1556,1557,1560,1561,1564,1565,1567,1568,1570,1571,1574],{},"A projektek az oapi-codegen ",[452,1547,1548],{},"beépített",[464,1550,1551],{},"chi-server"," routing template-jeit használják (ezek naprakészek upstreamben), plusz egy minimális kit-override-ot (",[464,1554,1555],{},"internal\u002Ftemplates\u002Foapichi\u002F","): a két strict template-et (",[464,1558,1559],{},"strict\u002Fstrict-interface.tmpl",", ",[464,1562,1563],{},"strict\u002Fstrict-http.tmpl",") egyetlen érdemi eltéréssel: a generált request\u002Fresponse típusnevekről lekerül az ",[464,1566,811],{}," utótag (",[464,1569,955],{},", nem ",[464,1572,1573],{},"ListProductsRequestObject","), így az általad írt üzleti handler-kód mindenhol mentes marad ettől az utótagtól.",[1576,1577,1579],"h3",{"id":1578},"hogyan-marad-ez-biztonságos","Hogyan marad ez biztonságos",[448,1581,1582,1583,1585,1586,1588,1589,1592],{},"Az override a kit repóban van pinelve és tesztelve, egy kontraktus-teszttel, ami a register-snippet által használt azonosítókat, a ",[464,1584,1325],{}," alakját és az ",[464,1587,811],{},"-mentes neveket pineli, és lefordítja a generált csomagot. Az oapi-codegen verzióemelése ",[452,1590,1591],{},"először ezt a tesztet töri",", sosem egy fogyasztó projektet.",[540,1594,1596],{"id":1595},"deklaratív-authorizáció-permission-és-policy","Deklaratív authorizáció: @permission és @policy",[448,1598,1599,1600,1603,1604,1607,1608,1610,1611,1614,1615,1618],{},"A projekt-scaffold egy kis decorator-libet szállít (",[464,1601,1602],{},"spec\u002Ftypespec\u002Flib\u002Fpolicy.tsp"," + ",[464,1605,1606],{},"policy.js","), így minden surface ",[464,1609,649],{},"-ben elérhető a ",[464,1612,1613],{},"@permission(\"...\")"," és a ",[464,1616,1617],{},"@policy(\"...\")",". A lánc végig gépi:",[457,1620,1623],{"className":1621,"code":1622,"language":462},[460],"@permission(\"orders.place\") \u002F @policy(\"orders.owner\") a műveleten\n  → x-permission \u002F x-policy extension az emittált OpenAPI-ban (setExtension)\n  → a strict template PermissionByOperation \u002F PolicyByOperation mapeket generál a gen csomagba\n  → a register.go-ba kötött policy.Enforcer middleware\n    RBAC-permissiont ellenőriz, és a surface policy\u002F registry-jéből futtatja a policy-t\n",[464,1624,1622],{"__ignoreMap":466},[448,1626,1627],{},"A generált mapek így néznek ki:",[457,1629,1632],{"className":819,"code":1630,"filename":1631,"language":822,"meta":466,"style":466},"var PermissionByOperation = map[string]string{\n    \"PlaceOrder\": \"orders.place\",\n}\n\nvar PolicyByOperation = map[string]string{\n    \"GetOrder\": \"orders.owner\",\n}\n","gen\u002Fapi.gen.go (generált)",[464,1633,1634,1658,1679,1683,1689,1708,1728],{"__ignoreMap":466},[666,1635,1636,1639,1642,1645,1648,1651,1654,1656],{"class":668,"line":669},[666,1637,1638],{"class":676},"var",[666,1640,1641],{"class":978}," PermissionByOperation ",[666,1643,1644],{"class":676},"=",[666,1646,1647],{"class":676}," map[",[666,1649,1650],{"class":885},"string",[666,1652,1653],{"class":676},"]",[666,1655,1650],{"class":885},[666,1657,1305],{"class":676},[666,1659,1660,1663,1666,1668,1670,1672,1675,1677],{"class":668,"line":687},[666,1661,1662],{"class":676},"    \"",[666,1664,1665],{"class":680},"PlaceOrder",[666,1667,1086],{"class":676},[666,1669,1409],{"class":676},[666,1671,1080],{"class":676},[666,1673,1674],{"class":680},"orders.place",[666,1676,1086],{"class":676},[666,1678,1290],{"class":676},[666,1680,1681],{"class":668,"line":701},[666,1682,784],{"class":676},[666,1684,1685],{"class":668,"line":708},[666,1686,1688],{"emptyLinePlaceholder":1687},true,"\n",[666,1690,1691,1693,1696,1698,1700,1702,1704,1706],{"class":668,"line":714},[666,1692,1638],{"class":676},[666,1694,1695],{"class":978}," PolicyByOperation ",[666,1697,1644],{"class":676},[666,1699,1647],{"class":676},[666,1701,1650],{"class":885},[666,1703,1653],{"class":676},[666,1705,1650],{"class":885},[666,1707,1305],{"class":676},[666,1709,1710,1712,1715,1717,1719,1721,1724,1726],{"class":668,"line":727},[666,1711,1662],{"class":676},[666,1713,1714],{"class":680},"GetOrder",[666,1716,1086],{"class":676},[666,1718,1409],{"class":676},[666,1720,1080],{"class":676},[666,1722,1723],{"class":680},"orders.owner",[666,1725,1086],{"class":676},[666,1727,1290],{"class":676},[666,1729,1730],{"class":668,"line":740},[666,1731,784],{"class":676},[448,1733,1734,1735,1738,1739,1742,1743,1745],{},"Az enforcer a strict-middleware lánc legkülső eleme: már a teljesen bekötött, típusos requestet látja, a belépett usert a contextből olvassa, és 401\u002F403-mal rövidre zár, mielőtt az üzleti handler futna. ",[452,1736,1737],{},"Fail-closed",": a ",[464,1740,1741],{},"@policy","-val megjelölt, de a registry-ben nem regisztrált policy nem átenged, hanem hibázik. A szemantikát és a policy-írást a ",[536,1744,98],{"href":99}," oldal írja le.",[540,1747,1749],{"id":1748},"a-gpsystemyaml-manifest","A gpsystem.yaml manifest",[448,1751,1752,1753,1756],{},"A projekt gyökerében élő ",[464,1754,1755],{},"gpsystem.yaml"," jelöli ki a projekt-gyökeret a CLI-nek, és rögzíti, mit generált eddig:",[457,1758,1762],{"className":1759,"code":1760,"filename":1755,"language":1761,"meta":466,"style":466},"language-yaml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","version: 1\nname: shop\nmodule: github.com\u002Facme\u002Fshop\nkit: github.com\u002Fgp-system\u002Fgpsystem\ndb: pgx              # vagy bun\ntemplatesSHA: 3f2a…  # a bemásolt oapi template-készlet checksumja\nmodules:\n  shop:\n    surfaces: [api, admin]\n    events: [orderPlaced]\n","yaml",[464,1763,1764,1774,1784,1794,1804,1817,1830,1838,1845,1865],{"__ignoreMap":466},[666,1765,1766,1769,1771],{"class":668,"line":669},[666,1767,1768],{"class":672},"version",[666,1770,1409],{"class":676},[666,1772,1773],{"class":690}," 1\n",[666,1775,1776,1779,1781],{"class":668,"line":687},[666,1777,1778],{"class":672},"name",[666,1780,1409],{"class":676},[666,1782,1783],{"class":680}," shop\n",[666,1785,1786,1789,1791],{"class":668,"line":701},[666,1787,1788],{"class":672},"module",[666,1790,1409],{"class":676},[666,1792,1793],{"class":680}," github.com\u002Facme\u002Fshop\n",[666,1795,1796,1799,1801],{"class":668,"line":708},[666,1797,1798],{"class":672},"kit",[666,1800,1409],{"class":676},[666,1802,1803],{"class":680}," github.com\u002Fgp-system\u002Fgpsystem\n",[666,1805,1806,1809,1811,1814],{"class":668,"line":714},[666,1807,1808],{"class":672},"db",[666,1810,1409],{"class":676},[666,1812,1813],{"class":680}," pgx",[666,1815,1816],{"class":704},"              # vagy bun\n",[666,1818,1819,1822,1824,1827],{"class":668,"line":727},[666,1820,1821],{"class":672},"templatesSHA",[666,1823,1409],{"class":676},[666,1825,1826],{"class":680}," 3f2a…",[666,1828,1829],{"class":704},"  # a bemásolt oapi template-készlet checksumja\n",[666,1831,1832,1835],{"class":668,"line":740},[666,1833,1834],{"class":672},"modules",[666,1836,1837],{"class":676},":\n",[666,1839,1840,1843],{"class":668,"line":753},[666,1841,1842],{"class":672},"  shop",[666,1844,1837],{"class":676},[666,1846,1847,1850,1852,1855,1857,1859,1862],{"class":668,"line":781},[666,1848,1849],{"class":672},"    surfaces",[666,1851,1409],{"class":676},[666,1853,1854],{"class":676}," [",[666,1856,569],{"class":680},[666,1858,865],{"class":676},[666,1860,1861],{"class":680}," admin",[666,1863,1864],{"class":676},"]\n",[666,1866,1867,1870,1872,1874,1877],{"class":668,"line":1331},[666,1868,1869],{"class":672},"    events",[666,1871,1409],{"class":676},[666,1873,1854],{"class":676},[666,1875,1876],{"class":680},"orderPlaced",[666,1878,1864],{"class":676},[545,1880,1881,1895,1909],{},[548,1882,469,1883,1885,1886,1560,1888,1890,1891,1894],{},[464,1884,1808],{}," dönti el, melyik template-fát renderelik a generátorok (",[464,1887,330],{},[464,1889,339],{},", ...); a választás ",[536,1892,1893],{"href":321},"projekt-létrehozáskor"," történik.",[548,1896,469,1897,1899,1900,1904,1905,1908],{},[464,1898,1821],{}," alapján ismeri fel az ",[536,1901,1902],{"href":354},[464,1903,353],{},", hogy módosítottad-e lokálisan a bemásolt template-eket: módosítottat csak ",[464,1906,1907],{},"--force","-szal ír felül.",[548,1910,469,1911,1913,1914,1916,1917,1920],{},[464,1912,1834],{}," bejegyzésekből tudja az ",[464,1915,330],{},", hogy mi létezik már, és az ",[464,1918,1919],{},"add listener",", hogy létező eventre iratkozol-e fel.",[540,1922,469,1924,1927],{"id":1923},"a-gpsystem-anchorok",[464,1925,1926],{},"\u002F\u002F gpsystem:*"," anchorok",[448,1929,1930,1931,1934],{},"A generátorok meglévő fájlt ",[452,1932,1933],{},"soha nem írnak felül",", kizárólag megjelölt anchor-kommenteknél illesztenek be. A fontosabbak:",[1936,1937,1938,1954],"table",{},[1939,1940,1941],"thead",{},[1942,1943,1944,1948,1951],"tr",{},[1945,1946,1947],"th",{},"Anchor",[1945,1949,1950],{},"Fájl",[1945,1952,1953],{},"Ki illeszt ide",[1955,1956,1957,1976,1992,2012,2028,2049,2074],"tbody",{},[1942,1958,1959,1965,1970],{},[1960,1961,1962],"td",{},[464,1963,1964],{},"gpsystem:modules",[1960,1966,1967],{},[464,1968,1969],{},"spec\u002Ftypespec\u002Fmain.tsp",[1960,1971,1972,601,1974],{},[464,1973,325],{},[464,1975,330],{},[1942,1977,1978,1983,1988],{},[1960,1979,1980],{},[464,1981,1982],{},"gpsystem:operations",[1960,1984,1985],{},[464,1986,1987],{},"\u003Csurface>.tsp",[1960,1989,1990],{},[464,1991,339],{},[1942,1993,1994,2002,2006],{},[1960,1995,1996,1560,1999],{},[464,1997,1998],{},"gpsystem:surfaces",[464,2000,2001],{},"gpsystem:imports",[1960,2003,2004],{},[464,2005,1129],{},[1960,2007,2008,601,2010],{},[464,2009,325],{},[464,2011,330],{},[1942,2013,2014,2019,2024],{},[1960,2015,2016],{},[464,2017,2018],{},"gpsystem:registrations",[1960,2020,2021],{},[464,2022,2023],{},"cmd\u002F\u003Cmodul>\u002Fmain.go",[1960,2025,2026],{},[464,2027,330],{},[1942,2029,2030,2038,2043],{},[1960,2031,2032,1560,2035],{},[464,2033,2034],{},"gpsystem:dependencies",[464,2036,2037],{},"gpsystem:dependencies-init",[1960,2039,2040,2042],{},[464,2041,1129],{}," \u002F entrypointok",[1960,2044,2045,2048],{},[464,2046,2047],{},"add event"," (dispatcher-bekötés)",[1942,2050,2051,2059,2067],{},[1960,2052,2053,1560,2056],{},[464,2054,2055],{},"gpsystem:listeners",[464,2057,2058],{},"gpsystem:jobs",[1960,2060,2061,601,2064],{},[464,2062,2063],{},"listeners\u002Fregister.go",[464,2065,2066],{},"jobs\u002Fregister.go",[1960,2068,2069,601,2071],{},[464,2070,1919],{},[464,2072,2073],{},"add job",[1942,2075,2076,2081,2086],{},[1960,2077,2078],{},[464,2079,2080],{},"gpsystem:config",[1960,2082,2083],{},[464,2084,2085],{},"internal\u002Fplatform\u002Fconfig\u002Fconfig.go",[1960,2087,2088],{},"jövőbeli konfig-bővítések",[448,2090,2091,2092,2095,2096,2099],{},"Az illesztések idempotensek (kétszer futtatva nem duplikálnak), és a fájl goimports-szal formázódik utánuk. Ha egy anchort kitörölsz, az érintett generátor ",[452,2093,2094],{},"hangosan hibázik",", nem próbál tippelni: a hibaüzenet előtt kiírja a beillesztendő snippetet és a visszaállítandó anchor-sort, hogy kézzel be tudd illeszteni a megfelelő helyre. Az anchorokat hagyd a helyükön, ahogy a ",[536,2097,2098],{"href":41},"mintaalkalmazás"," is teszi.",[540,2101,2103],{"id":2102},"használt-patternek","Használt patternek",[545,2105,2106,2128,2139],{},[548,2107,2108,2111,2112,2115,2116,2122,2123,859],{},[452,2109,2110],{},"Spec-first codegen"," (TypeSpec → OpenAPI 3.0 → oapi-codegen strict szerver): ",[536,2113,238],{"href":2114},"\u002Fhu\u002Fconcepts\u002Fdesign-patterns#spec-first-codegen",". A TypeSpec nyelv hivatalos dokumentációja: ",[536,2117,2121],{"href":2118,"rel":2119},"https:\u002F\u002Ftypespec.io\u002Fdocs",[2120],"nofollow","typespec.io\u002Fdocs","; az oapi-codegen projekt: ",[536,2124,2127],{"href":2125,"rel":2126},"https:\u002F\u002Fgithub.com\u002Foapi-codegen\u002Foapi-codegen",[2120],"github.com\u002Foapi-codegen\u002Foapi-codegen",[548,2129,2130,877,2133,2135,2136,859],{},[452,2131,2132],{},"Anchor-comment kód-injektálás",[464,2134,1926],{},", idempotens, whitespace-normalizált): ",[536,2137,238],{"href":2138},"\u002Fhu\u002Fconcepts\u002Fdesign-patterns#anchor-comment-k%C3%B3d-injekt%C3%A1l%C3%A1s",[548,2140,2141,587,2144,1524,2147,2149,2150,859],{},[452,2142,2143],{},"Fail-closed policy enforcement",[464,2145,2146],{},"@permission",[464,2148,1741],{}," enforcer láncban: ",[536,2151,238],{"href":2152},"\u002Fhu\u002Fconcepts\u002Fdesign-patterns#fail-closed-policy-enforcement",[540,2154,2156],{"id":2155},"kapcsolódó-oldalak","Kapcsolódó oldalak",[545,2158,2159,2167,2172],{},[548,2160,2161,2163,2164,2166],{},[536,2162,339],{"href":340},": művelet scaffoldolása a ",[464,2165,649],{},"-be és a handlerbe.",[548,2168,2169,2171],{},[536,2170,400],{"href":401},": hogyan validál a generált binding.",[548,2173,2174,2176],{},[536,2175,98],{"href":99},": az enforcer és a policy-registry.",[2178,2179,2180],"style",{},"html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}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 .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}",{"title":466,"searchDepth":687,"depth":687,"links":2182},[2183,2184,2185,2188,2189,2190,2192,2193],{"id":542,"depth":687,"text":543},{"id":636,"depth":687,"text":637},{"id":1541,"depth":687,"text":1542,"children":2186},[2187],{"id":1578,"depth":701,"text":1579},{"id":1595,"depth":687,"text":1596},{"id":1748,"depth":687,"text":1749},{"id":1923,"depth":687,"text":2191},"A \u002F\u002F gpsystem:* anchorok",{"id":2102,"depth":687,"text":2103},{"id":2155,"depth":687,"text":2156},"TypeSpec → OpenAPI 3.0 → szigorú, típusos szerverkód chi\u002Fnet-http-n.","md",null,{},{"icon":236},{"title":233,"description":2194},"PkMIMYHz9QBtD1B5CUpiYKEA3Z4-rKWCJerEGlZM_-E",[2202,2204],{"title":204,"path":229,"stem":230,"description":2203,"icon":231,"children":-1},"Egy projekt konfigurációjának összeállítása modul-Config structokból: envconf, env-prefix konvenciók és a .env.",{"title":238,"path":239,"stem":240,"description":2205,"icon":241,"children":-1},"A kitben visszatérő tervezési minták katalógusa: kódpéldával, előfordulási hellyel és a kanonikus külső forrással.",1785445879807]