[{"data":1,"prerenderedAt":3000},["ShallowReactive",2],{"navigation":3,"\u002Fdocs\u002Fprotocols":135,"\u002Fdocs\u002Fprotocols-surround":2995},[4],{"title":5,"path":6,"stem":7,"children":8,"page":134},"Docs","\u002Fdocs","docs",[9,13,17,21,25,29,33,37,41,45,49,53,57,61,70,74,78,82,86,90,94,98,102,106,110,114,118,122,126,130],{"title":10,"path":11,"stem":12},"AI harnesses: LLM tools, MCP servers and agents","\u002Fdocs\u002Fai-tools","docs\u002Fai-tools",{"title":14,"path":15,"stem":16},"Architecture","\u002Fdocs\u002Farchitecture","docs\u002Farchitecture",{"title":18,"path":19,"stem":20},"Web \u002F native bridges","\u002Fdocs\u002Fbridges","docs\u002Fbridges",{"title":22,"path":23,"stem":24},"Broadcast channels and tests","\u002Fdocs\u002Fchannels-and-tests","docs\u002Fchannels-and-tests",{"title":26,"path":27,"stem":28},"CLI reference","\u002Fdocs\u002Fcli","docs\u002Fcli",{"title":30,"path":31,"stem":32},"Completeness: how far an answer reaches","\u002Fdocs\u002Fcompleteness","docs\u002Fcompleteness",{"title":34,"path":35,"stem":36},"Configuration","\u002Fdocs\u002Fconfiguration","docs\u002Fconfiguration",{"title":38,"path":39,"stem":40},"External systems","\u002Fdocs\u002Fexternal","docs\u002Fexternal",{"title":42,"path":43,"stem":44},"Generated, copied and vendored files","\u002Fdocs\u002Fgenerated","docs\u002Fgenerated",{"title":46,"path":47,"stem":48},"Installing and updating cg","\u002Fdocs\u002Finstall","docs\u002Finstall",{"title":50,"path":51,"stem":52},"Java","\u002Fdocs\u002Fjava","docs\u002Fjava",{"title":54,"path":55,"stem":56},"Kotlin","\u002Fdocs\u002Fkotlin","docs\u002Fkotlin",{"title":58,"path":59,"stem":60},"Known limitations","\u002Fdocs\u002Flimitations","docs\u002Flimitations",{"title":62,"path":63,"stem":64,"children":65},"MCP server","\u002Fdocs\u002Fmcp","docs\u002Fmcp",[66],{"title":67,"path":68,"stem":69},"code-graph MCP: sample outputs (real calls via the MCP Python SDK stdio client)","\u002Fdocs\u002Fmcp\u002Fsample_outputs","docs\u002Fmcp\u002Fsample_outputs",{"title":71,"path":72,"stem":73},"Rust, C and C++","\u002Fdocs\u002Fnative","docs\u002Fnative",{"title":75,"path":76,"stem":77},"Port gaps: cg parity","\u002Fdocs\u002Fparity","docs\u002Fparity",{"title":79,"path":80,"stem":81},"PHP","\u002Fdocs\u002Fphp","docs\u002Fphp",{"title":83,"path":84,"stem":85},"Planned changes","\u002Fdocs\u002Fplans","docs\u002Fplans",{"title":87,"path":88,"stem":89},"Platform-specific code","\u002Fdocs\u002Fplatforms","docs\u002Fplatforms",{"title":91,"path":92,"stem":93},"Protocol links","\u002Fdocs\u002Fprotocols","docs\u002Fprotocols",{"title":95,"path":96,"stem":97},"Python","\u002Fdocs\u002Fpython","docs\u002Fpython",{"title":99,"path":100,"stem":101},"Quick start","\u002Fdocs\u002Fquickstart","docs\u002Fquickstart",{"title":103,"path":104,"stem":105},"Graph schema","\u002Fdocs\u002Fschema","docs\u002Fschema",{"title":107,"path":108,"stem":109},"Attack surface","\u002Fdocs\u002Fsurface","docs\u002Fsurface",{"title":111,"path":112,"stem":113},"Swift","\u002Fdocs\u002Fswift","docs\u002Fswift",{"title":115,"path":116,"stem":117},"TypeScript \u002F JavaScript frameworks","\u002Fdocs\u002Fts-frameworks","docs\u002Fts-frameworks",{"title":119,"path":120,"stem":121},"How we validate","\u002Fdocs\u002Fvalidation","docs\u002Fvalidation",{"title":123,"path":124,"stem":125},"Validation log","\u002Fdocs\u002Fvalidation-log","docs\u002Fvalidation-log",{"title":127,"path":128,"stem":129},"Value facts and resolutions","\u002Fdocs\u002Fvalue-facts","docs\u002Fvalue-facts",{"title":131,"path":132,"stem":133},"Visual view","\u002Fdocs\u002Fviz","docs\u002Fviz",false,{"id":136,"title":91,"body":137,"description":2989,"extension":2990,"meta":2991,"navigation":2992,"path":92,"seo":2993,"stem":93,"__hash__":2994},"docs\u002Fdocs\u002Fprotocols.md",{"type":138,"value":139,"toc":2977},"minimark",[140,168,173,183,329,363,381,385,437,621,807,811,827,941,945,948,1054,1072,1126,1131,1227,1245,1251,1274,1278,1285,1344,1354,1402,1414,1429,1432,1652,1678,1683,1717,1770,1777,1830,1906,1962,1966,2928,2937,2941,2973],[141,142,143,144,148,149,148,152,155,156,159,160,163,164,167],"p",{},"cg pairs a sender with the code that receives it: HTTP, channels, Nest messages, job queues,\nevents, bridges, and named endpoints of messaging protocols. ",[145,146,147],"code",{},"impact",", ",[145,150,151],{},"reaches",[145,153,154],{},"path"," and\n",[145,157,158],{},"downstream"," cross those edges in one repo and, after ",[145,161,162],{},"cg link",", between two. ",[145,165,166],{},"cg protocols","\nlists endpoints with senders, receivers, guards and checks.",[169,170,172],"h2",{"id":171},"model","Model",[174,175,180],"pre",{"className":176,"code":178,"language":179},[177],"language-text","sender  -SENDS_TO->  endpoint:\u003Cprotocol>:\u003Cname>  -RECEIVED_BY->  handler\nsend-side endpoint  -MATCHES_ENDPOINT->  receive-side endpoint\n","text",[145,181,178],{"__ignoreMap":182},"",[184,185,186,199],"table",{},[187,188,189],"thead",{},[190,191,192,196],"tr",{},[193,194,195],"th",{},"piece",[193,197,198],{},"meaning",[200,201,202,265,287,297,307],"tbody",{},[190,203,204,210],{},[205,206,207],"td",{},[145,208,209],{},"endpoint:\u003Cprotocol>:\u003Cname>",[205,211,212,213,148,216,148,219,222,223,226,227,148,230,148,233,148,236,239,240,243,244,247,248,148,251,148,254,148,257,260,261,264],{},"normalised topic \u002F subject \u002F event \u002F method; ",[145,214,215],{},"${id}",[145,217,218],{},"{{id}}",[145,220,221],{},"\u002F:id"," become ",[145,224,225],{},"{id}",". Attrs: ",[145,228,229],{},"protocol",[145,231,232],{},"transport",[145,234,235],{},"pattern",[145,237,238],{},"side"," (send, receive, both), ",[145,241,242],{},"guards"," (",[145,245,246],{},"[]"," = known none), ",[145,249,250],{},"namespace",[145,252,253],{},"event",[145,255,256],{},"schema",[145,258,259],{},"test_only",". A network receiver is a ",[145,262,263],{},"message_handler"," entry.",[190,266,267,272],{},[205,268,269],{},[145,270,271],{},"SENDS_TO",[205,273,274,275,278,279,282,283,286],{},"code → endpoint. ",[145,276,277],{},"role",": send, publish, emit, request, invoke, enqueue. From tests: ",[145,280,281],{},"TEST_CALLS"," with ",[145,284,285],{},"orig"," = SENDS_TO.",[190,288,289,294],{},[205,290,291],{},[145,292,293],{},"RECEIVED_BY",[205,295,296],{},"endpoint → handler.",[190,298,299,304],{},[205,300,301],{},[145,302,303],{},"QUEUE_ROUTES",[205,305,306],{},"queue endpoint → one task. Does not propagate: a send runs that job, not every job on the queue.",[190,308,309,314],{},[205,310,311],{},[145,312,313],{},"MATCHES_ENDPOINT",[205,315,316,317,320,321,324,325,328],{},"names differ but the matcher fits. ",[145,318,319],{},"resolved"," for a wildcard or ",[145,322,323],{},"{param}","; ",[145,326,327],{},"heuristic"," for a template fitted to a literal, or an ambiguous tie. Identical ids need no edge.",[141,330,331,332,335,336,338,339,342,343,346,347,350,351,354,355,358,359,362],{},"Matching runs at the end of ",[145,333,334],{},"cg index"," and again in ",[145,337,162],{},". Link stats add ",[145,340,341],{},"protocols"," only\nwhen the graphs hold these endpoints. Names in ",[145,344,345],{},".cg.yaml"," ",[145,348,349],{},"protocols.external"," count as\n",[145,352,353],{},"external",", not ",[145,356,357],{},"no_receiver"," \u002F ",[145,360,361],{},"no_sender",".",[141,364,365,366,243,369,372,373,376,377,380],{},"Socket.IO is directional: one endpoint per event, and every edge records ",[145,367,368],{},"process",[145,370,371],{},"server"," \u002F\n",[145,374,375],{},"client","). A server ",[145,378,379],{},"emit"," reaches client handlers only, and the reverse. A side with no known\nprocess matches either.",[169,382,384],{"id":383},"registry","Registry",[141,386,387,390,391,394,395,148,398,148,400,403,404,407,408,148,411,414,415,148,418,148,420,243,423,148,426,148,429,432,433,436],{},[145,388,389],{},"cg_code_graph\u002Fprotocols\u002F"," holds one ",[145,392,393],{},"Protocol",": ",[145,396,397],{},"name",[145,399,232],{},[145,401,402],{},"ports",", URL ",[145,405,406],{},"schemes",", a\nnormaliser, a ",[145,409,410],{},"matcher",[145,412,413],{},"fanout"," (every match) or most-specific-with-ties, ",[145,416,417],{},"entry",[145,419,242],{},[145,421,422],{},"source",[145,424,425],{},"endpoint",[145,427,428],{},"adapter",[145,430,431],{},"bridges","). Plugins call ",[145,434,435],{},"register"," and the builders:",[174,438,442],{"className":439,"code":440,"language":441,"meta":182,"style":182},"language-python shiki shiki-themes cg-light cg-light cg-dark","from cg_code_graph.protocols import protocol_receive, protocol_send\nprotocol_send(builder, \"mqtt\", \"devices\u002F42\u002Fstate\", fn_id, file, line, \"exact\", role=\"publish\", library=\"paho-mqtt\")\nprotocol_receive(builder, \"mqtt\", \"devices\u002F+\u002Fstate\", handler_id, file, line, \"exact\", guards=[])\n","python",[145,443,444,475,565],{"__ignoreMap":182},[445,446,449,453,457,460,463,466,469,472],"span",{"class":447,"line":448},"line",1,[445,450,452],{"class":451},"sHkq1","from",[445,454,456],{"class":455},"snmWg"," cg_code_graph",[445,458,362],{"class":459},"sZ_TN",[445,461,462],{"class":455},"protocols ",[445,464,465],{"class":451},"import",[445,467,468],{"class":455}," protocol_receive",[445,470,471],{"class":459},",",[445,473,474],{"class":455}," protocol_send\n",[445,476,478,482,485,488,490,493,497,500,502,504,507,509,511,514,516,519,521,524,526,528,531,533,535,538,541,543,546,548,550,553,555,557,560,562],{"class":447,"line":477},2,[445,479,481],{"class":480},"sZJo5","protocol_send",[445,483,484],{"class":459},"(",[445,486,487],{"class":480},"builder",[445,489,471],{"class":459},[445,491,492],{"class":459}," \"",[445,494,496],{"class":495},"sha9Y","mqtt",[445,498,499],{"class":459},"\"",[445,501,471],{"class":459},[445,503,492],{"class":459},[445,505,506],{"class":495},"devices\u002F42\u002Fstate",[445,508,499],{"class":459},[445,510,471],{"class":459},[445,512,513],{"class":480}," fn_id",[445,515,471],{"class":459},[445,517,518],{"class":455}," file",[445,520,471],{"class":459},[445,522,523],{"class":480}," line",[445,525,471],{"class":459},[445,527,492],{"class":459},[445,529,530],{"class":495},"exact",[445,532,499],{"class":459},[445,534,471],{"class":459},[445,536,537],{"class":455}," role",[445,539,540],{"class":459},"=",[445,542,499],{"class":459},[445,544,545],{"class":495},"publish",[445,547,499],{"class":459},[445,549,471],{"class":459},[445,551,552],{"class":455}," library",[445,554,540],{"class":459},[445,556,499],{"class":459},[445,558,559],{"class":495},"paho-mqtt",[445,561,499],{"class":459},[445,563,564],{"class":459},")\n",[445,566,568,571,573,575,577,579,581,583,585,587,590,592,594,597,599,601,603,605,607,609,611,613,615,618],{"class":447,"line":567},3,[445,569,570],{"class":480},"protocol_receive",[445,572,484],{"class":459},[445,574,487],{"class":480},[445,576,471],{"class":459},[445,578,492],{"class":459},[445,580,496],{"class":495},[445,582,499],{"class":459},[445,584,471],{"class":459},[445,586,492],{"class":459},[445,588,589],{"class":495},"devices\u002F+\u002Fstate",[445,591,499],{"class":459},[445,593,471],{"class":459},[445,595,596],{"class":480}," handler_id",[445,598,471],{"class":459},[445,600,518],{"class":455},[445,602,471],{"class":459},[445,604,523],{"class":480},[445,606,471],{"class":459},[445,608,492],{"class":459},[445,610,530],{"class":495},[445,612,499],{"class":459},[445,614,471],{"class":459},[445,616,617],{"class":455}," guards",[445,619,620],{"class":459},"=[])\n",[184,622,623,634],{},[187,624,625],{},[190,626,627,629,632],{},[193,628,410],{},[193,630,631],{},"rules",[193,633,341],{},[200,635,636,654,676,697,720,740,755,772,784],{},[190,637,638,642,651],{},[205,639,640],{},[145,641,154],{},[205,643,644,645,358,647,650],{},"URL segments, ",[145,646,323],{},[145,648,649],{},"{rest*}",", one shared literal segment",[205,652,653],{},"http, ws, sse, coap",[190,655,656,660,674],{},[205,657,658],{},[145,659,496],{},[205,661,662,665,666,669,670,673],{},[145,663,664],{},"\u002F"," levels, ",[145,667,668],{},"+"," one level, ",[145,671,672],{},"#"," the rest",[205,675,496],{},[190,677,678,683,695],{},[205,679,680],{},[145,681,682],{},"nats",[205,684,685,687,688,691,692,673],{},[145,686,362],{}," tokens, ",[145,689,690],{},"*"," one, ",[145,693,694],{},">",[205,696,682],{},[190,698,699,704,718],{},[205,700,701],{},[145,702,703],{},"amqp",[205,705,706,707,358,709,358,711,713,714,717],{},"same exchange, then topic key (",[145,708,362],{},[145,710,690],{},[145,712,672],{},"); ",[145,715,716],{},"queue:\u003Cname>"," exact",[205,719,703],{},[190,721,722,727,737],{},[205,723,724],{},[145,725,726],{},"glob",[205,728,729,358,731,358,734],{},[145,730,690],{},[145,732,733],{},"?",[145,735,736],{},"[...]",[205,738,739],{},"kafka, redis-pubsub, osc",[190,741,742,747,752],{},[205,743,744],{},[145,745,746],{},"template",[205,748,749,750],{},"whole-name ",[145,751,323],{},[205,753,754],{},"socketio, unix, pipe",[190,756,757,762,769],{},[205,758,759],{},[145,760,761],{},"dotted",[205,763,764,766,767],{},[145,765,362],{}," segments with ",[145,768,323],{},[205,770,771],{},"pusher",[190,773,774,778,781],{},[205,775,776],{},[145,777,530],{},[205,779,780],{},"same name",[205,782,783],{},"bridges, nest-*, jobs, events, llm_tool, grpc, thrift, trpc, jsonrpc, graphql, redis-stream, tcp, udp",[190,785,786,791,799],{},[205,787,788],{},[145,789,790],{},"mcp",[205,792,793,324,796,798],{},[145,794,795],{},"\u003Cserver>\u002F\u003Cname>",[145,797,690],{}," if the client omits the server",[205,800,801,802,806],{},"mcp_tool, mcp_resource, mcp_prompt (",[803,804,805],"a",{"href":11},"AI tools",")",[169,808,810],{"id":809},"existing-kinds","Existing kinds",[141,812,813,815,816,818,819,822,823,826],{},[145,814,166],{}," reads these through adapters. Node ids stay as they are; ",[145,817,162],{},",\n",[145,820,821],{},"cg channels"," and ",[145,824,825],{},"cg bridges"," keep their own views.",[184,828,829,844],{},[187,830,831],{},[190,832,833,836,838,841],{},[193,834,835],{},"kind",[193,837,229],{},[193,839,840],{},"send",[193,842,843],{},"receive",[200,845,846,865,883,899,914,928],{},[190,847,848,856,859,862],{},[205,849,850,358,853],{},[145,851,852],{},"http",[145,854,855],{},"route",[205,857,858],{},"http, ws, sse, graphql",[205,860,861],{},"HTTP_CALLS \u002F TEST_HTTP",[205,863,864],{},"ROUTES_TO, MATCHES_ROUTE",[190,866,867,875,877,880],{},[205,868,869,358,872],{},[145,870,871],{},"channel",[145,873,874],{},"channel_sub",[205,876,771],{},[205,878,879],{},"BROADCASTS_ON",[205,881,882],{},"SUBSCRIBES_CHANNEL",[190,884,885,890,893,896],{},[205,886,887],{},[145,888,889],{},"message",[205,891,892],{},"nest-rpc, nest-event, nest-ws, grpc",[205,894,895],{},"DISPATCHES",[205,897,898],{},"HANDLED_BY",[190,900,901,906,909,912],{},[205,902,903],{},[145,904,905],{},"job",[205,907,908],{},"bull, laravel-queue, celery",[205,910,911],{},"DISPATCHES, SCHEDULES",[205,913,898],{},[190,915,916,920,923,925],{},[205,917,918],{},[145,919,253],{},[205,921,922],{},"laravel-event, nest-event-emitter, django-signal",[205,924,895],{},[205,926,927],{},"LISTENED_BY \u002F HANDLED_BY",[190,929,930,934,937,939],{},[205,931,932],{},[145,933,425],{},[205,935,936],{},"capacitor, react-native, flutter, pigeon, electron, tauri",[205,938,271],{},[205,940,293],{},[169,942,944],{"id":943},"checks","Checks",[141,946,947],{},"A side is judged only when the graph has some endpoint of that protocol on the other side.",[184,949,950,959],{},[187,951,952],{},[190,953,954,957],{},[193,955,956],{},"check",[193,958,198],{},[200,960,961,970,979,989,999,1009,1019,1039],{},[190,962,963,967],{},[205,964,965],{},[145,966,357],{},[205,968,969],{},"sent; nothing here receives it",[190,971,972,976],{},[205,973,974],{},[145,975,361],{},[205,977,978],{},"received; nothing sends it (or the producer is outside the repos)",[190,980,981,986],{},[205,982,983],{},[145,984,985],{},"test_sender_only",[205,987,988],{},"received, sent from tests only",[190,990,991,996],{},[205,992,993],{},[145,994,995],{},"ambiguous",[205,997,998],{},"several receivers matched equally",[190,1000,1001,1006],{},[205,1002,1003],{},[145,1004,1005],{},"schema_mismatch",[205,1007,1008],{},"both sides name a message type, and they differ (no extractor records types yet)",[190,1010,1011,1016],{},[205,1012,1013],{},[145,1014,1015],{},"no_consumer",[205,1017,1018],{},"jobs are sent to a queue, workers of that framework run, none consumes it",[190,1020,1021,1026],{},[205,1022,1023],{},[145,1024,1025],{},"unguarded",[205,1027,1028,1029,822,1032,324,1035,1038],{},"an outside-reachable receiver with no auth guard (HTTP \u002F WS \u002F GraphQL routes, server Socket.IO). Nest message handlers record ",[145,1030,1031],{},"@UseGuards",[145,1033,1034],{},"APP_GUARD",[145,1036,1037],{},"app.useGlobalGuards()"," is HTTP only",[190,1040,1041,1045],{},[205,1042,1043],{},[145,1044,353],{},[205,1046,1047,1049,1050,1053],{},[145,1048,345],{},", a third-party HTTP origin, a framework signal (",[145,1051,1052],{},"post_save",", …), or a bridge module outside the repo",[141,1055,1056,1057,394,1059,148,1062,1065,1066,358,1068,358,1070,362],{},"Bridge checks stay in ",[803,1058,18],{"href":19},[145,1060,1061],{},"missing_on",[145,1063,1064],{},"unregistered",", plus\n",[145,1067,357],{},[145,1069,361],{},[145,1071,353],{},[174,1073,1077],{"className":1074,"code":1075,"language":1076,"meta":182,"style":182},"language-yaml shiki shiki-themes cg-light cg-light cg-dark","protocols:\n  external: [\"kafka:audit.*\", \"socketio:\u002F#audit:*\", \"http:GET \u002Fstatus\"]\n","yaml",[145,1078,1079,1087],{"__ignoreMap":182},[445,1080,1081,1084],{"class":447,"line":448},[445,1082,341],{"class":1083},"s4LKg",[445,1085,1086],{"class":459},":\n",[445,1088,1089,1092,1095,1098,1100,1103,1105,1107,1109,1112,1114,1116,1118,1121,1123],{"class":447,"line":477},[445,1090,1091],{"class":1083},"  external",[445,1093,1094],{"class":459},":",[445,1096,1097],{"class":459}," [",[445,1099,499],{"class":459},[445,1101,1102],{"class":495},"kafka:audit.*",[445,1104,499],{"class":459},[445,1106,471],{"class":459},[445,1108,492],{"class":459},[445,1110,1111],{"class":495},"socketio:\u002F#audit:*",[445,1113,499],{"class":459},[445,1115,471],{"class":459},[445,1117,492],{"class":459},[445,1119,1120],{"class":495},"http:GET \u002Fstatus",[445,1122,499],{"class":459},[445,1124,1125],{"class":459},"]\n",[169,1127,1129],{"id":1128},"cg-protocols",[145,1130,166],{},[174,1132,1136],{"className":1133,"code":1134,"language":1135,"meta":182,"style":182},"language-bash shiki shiki-themes cg-light cg-light cg-dark","cg protocols --db combined.db\ncg protocols --db combined.db --protocol socketio\ncg protocols 'orders.*' --db combined.db\ncg protocols --db combined.db --unmatched --side send\ncg protocols --db g.db --listeners          # TCP\u002FUDP listeners: port, exposure, bind, handler\n","bash",[145,1137,1138,1152,1169,1188,1208],{"__ignoreMap":182},[445,1139,1140,1143,1146,1149],{"class":447,"line":448},[445,1141,1142],{"class":480},"cg",[445,1144,1145],{"class":495}," protocols",[445,1147,1148],{"class":495}," --db",[445,1150,1151],{"class":495}," combined.db\n",[445,1153,1154,1156,1158,1160,1163,1166],{"class":447,"line":477},[445,1155,1142],{"class":480},[445,1157,1145],{"class":495},[445,1159,1148],{"class":495},[445,1161,1162],{"class":495}," combined.db",[445,1164,1165],{"class":495}," --protocol",[445,1167,1168],{"class":495}," socketio\n",[445,1170,1171,1173,1175,1178,1181,1184,1186],{"class":447,"line":567},[445,1172,1142],{"class":480},[445,1174,1145],{"class":495},[445,1176,1177],{"class":459}," '",[445,1179,1180],{"class":495},"orders.*",[445,1182,1183],{"class":459},"'",[445,1185,1148],{"class":495},[445,1187,1151],{"class":495},[445,1189,1191,1193,1195,1197,1199,1202,1205],{"class":447,"line":1190},4,[445,1192,1142],{"class":480},[445,1194,1145],{"class":495},[445,1196,1148],{"class":495},[445,1198,1162],{"class":495},[445,1200,1201],{"class":495}," --unmatched",[445,1203,1204],{"class":495}," --side",[445,1206,1207],{"class":495}," send\n",[445,1209,1211,1213,1215,1217,1220,1223],{"class":447,"line":1210},5,[445,1212,1142],{"class":480},[445,1214,1145],{"class":495},[445,1216,1148],{"class":495},[445,1218,1219],{"class":495}," g.db",[445,1221,1222],{"class":495}," --listeners",[445,1224,1226],{"class":1225},"seS0s","          # TCP\u002FUDP listeners: port, exposure, bind, handler\n",[141,1228,1229,394,1232,148,1235,1238,1239,1241,1242,362],{},[145,1230,1231],{},"--json",[145,1233,1234],{},"summary",[145,1236,1237],{},"endpoints"," (id, kind, protocol, name, side, linked, checks, external,\nguards, senders, receivers, matches, at, transport), ",[145,1240,383],{},". MCP:\n",[145,1243,1244],{},"protocol_links(pattern?, protocol?, side?, unmatched?, listeners?)",[174,1246,1249],{"className":1247,"code":1248,"language":179,"meta":182},[177],"$ cg protocols --db combined.db --protocol socketio\nsocketio: 2 endpoint(s), 1 linked  (no_receiver 0, no_sender 0)\nsocketio:\u002Forders#order:created  side: both\n    sent by orders.create @ api\u002Froutes.py:40 [exact, client]\n    received by worker.on_order @ worker\u002Fhandlers.py:12 [exact, server]\n",[145,1250,1248],{"__ignoreMap":182},[141,1252,1253,1256,1257,1260,1261,1263,1264,1263,1266,1269,1270,362],{},[145,1254,1255],{},"cg path \"route:POST \u002Forders\" table:orders"," on the ",[145,1258,1259],{},"tests\u002Fprotocol_fixtures"," link runs route →\nhandler → ",[145,1262,271],{}," → ",[145,1265,293],{},[145,1267,1268],{},"WRITES_TABLE",". Corpus numbers:\n",[803,1271,1273],{"href":1272},"\u002Fdocs\u002Fvalidation-log#protocol-links-shared-endpoint-model-31","protocol links",[169,1275,1277],{"id":1276},"webhook-verification","Webhook verification",[141,1279,1280,1281,1284],{},"A receiver is a route a third party calls. ",[145,1282,1283],{},"cg_code_graph\u002Fwebhooks.py"," walks the handler, two levels\nof calls, and its middleware.",[184,1286,1287,1297],{},[187,1288,1289],{},[190,1290,1291,1294],{},[193,1292,1293],{},"result",[193,1295,1296],{},"when",[200,1298,1299,1326],{},[190,1300,1301,1304],{},[205,1302,1303],{},"verified",[205,1305,1306,1307,1310,1311,1314,1315,1317,1318,1321,1322,1325],{},"Stripe ",[145,1308,1309],{},"constructEvent",", svix ",[145,1312,1313],{},"verify",", GitHub ",[145,1316,1313],{},", Twilio ",[145,1319,1320],{},"validateRequest",", Shopify ",[145,1323,1324],{},"webhooks.validate",", or an HMAC plus a constant-time compare (or a provider signature header), or a route middleware that verifies (see below)",[190,1327,1328,1331],{},[205,1329,1330],{},"unverified",[205,1332,1333,1334,148,1337,148,1340,1343],{},"the handler reads ",[145,1335,1336],{},"Stripe-Signature",[145,1338,1339],{},"X-Hub-Signature-256",[145,1341,1342],{},"svix-signature",", … and nothing above checks it",[141,1345,1346,1347,1350,1351,1353],{},"A verifying middleware marks the route verified. ",[145,1348,1349],{},"how"," names the middleware and ",[145,1352,956],{}," points at the verifying call (the route line when only the name is known). Signs of one:",[1355,1356,1357,1378,1381],"ul",{},[1358,1359,1360,1361,1364,1365,243,1368,822,1370,1373,1374,1377],"li",{},"an alias such as ",[145,1362,1363],{},"verify.\u003Cprovider>.signature"," or ",[145,1366,1367],{},"verify-\u003Cprovider>-webhook",[145,1369,362],{},[145,1371,1372],{},"-"," read as ",[145,1375,1376],{},"_",");",[1358,1379,1380],{},"a resolved middleware class whose name matches, also when it is reached through an alias;",[1358,1382,1383,1384,1317,1387,346,1390,243,1393,148,1396,1364,1399,1401],{},"a middleware body with a known verification: an HMAC plus constant-time compare, Stripe ",[145,1385,1386],{},"Webhook::constructEvent",[145,1388,1389],{},"RequestValidator",[145,1391,1392],{},"validate",[145,1394,1395],{},"->",[145,1397,1398],{},"::",[145,1400,362],{},").",[141,1403,1404,1405,822,1408,1411,1412,362],{},"A route is never labeled ",[145,1406,1407],{},"SECRET-CHECKED",[145,1409,1410],{},"WEBHOOK UNVERIFIED"," together. A provider header read with no verifying middleware or call stays ",[145,1413,1410],{},[141,1415,1416,1419,1420,1422,1423,1425,1426,362],{},[145,1417,1418],{},"cg routes"," shows a verified check as a guard and flags ",[145,1421,1410],{},". Provider events\nare never ",[145,1424,361],{},". A signed POST from this repo is a sender of\n",[145,1427,1428],{},"endpoint:webhook:\u003Cthis project>:\u003Cevent>",[141,1430,1431],{},"Framework conventions (#152):",[184,1433,1434,1444],{},[187,1435,1436],{},[190,1437,1438,1441],{},[193,1439,1440],{},"convention",[193,1442,1443],{},"receiver",[200,1445,1446,1474,1516,1559,1585,1634],{},[190,1447,1448,1451],{},[205,1449,1450],{},"Laravel Cashier",[205,1452,1453,1454,1457,1458,1461,1462,324,1465,1461,1468,243,1471,1473],{},"a controller that extends ",[145,1455,1456],{},"Laravel\\Cashier\\Http\\Controllers\\WebhookController",", or a subclass of one. ",[145,1459,1460],{},"handleCustomerSubscriptionCreated"," receives ",[145,1463,1464],{},"customer.subscription.created",[145,1466,1467],{},"handleInvoicePaymentActionRequired",[145,1469,1470],{},"invoice.payment_action_required",[145,1472,327],{},"). The route is verified because Cashier checks the signature before those methods. A class that does not extend that controller is not a Cashier receiver",[190,1475,1476,1479],{},[205,1477,1478],{},"spatie\u002Flaravel-webhook-client",[205,1480,1481,1484,1485,1487,1488,1491,1492,1495,1496,1499,1500,1503,1504,1507,1508,1511,1512,1515],{},[145,1482,1483],{},"Route::webhooks('payments\u002Fhooks', 'payments')"," plus the matching ",[145,1486,397],{}," in ",[145,1489,1490],{},"config\u002Fwebhook-client.php",". The job's ",[145,1493,1494],{},"handle"," and the profile's ",[145,1497,1498],{},"shouldProcess"," receive the route. Verified when ",[145,1501,1502],{},"signing_secret"," is set and ",[145,1505,1506],{},"signature_validator"," is omitted or is ",[145,1509,1510],{},"DefaultSignatureValidator",". A custom validator is verified only when that class checks a signature, and the guard is labeled ",[145,1513,1514],{},"custom validator",". No validator and no secret stays unverified. A config name that is not in the file is left unbound",[190,1517,1518,1521],{},[205,1519,1520],{},"spatie\u002Flaravel-route-attributes",[205,1522,1523,358,1526,1529,1530,358,1533,358,1536,358,1539,358,1542,358,1545,358,1548,1551,1552,1555,1556],{},[145,1524,1525],{},"#[Prefix]",[145,1527,1528],{},"#[Middleware]"," on the class combine with the same attributes on the method. ",[145,1531,1532],{},"#[Get]",[145,1534,1535],{},"#[Post]",[145,1537,1538],{},"#[Put]",[145,1540,1541],{},"#[Patch]",[145,1543,1544],{},"#[Delete]",[145,1546,1547],{},"#[Any]",[145,1549,1550],{},"#[Route]"," are Laravel routes and merge with ",[145,1553,1554],{},"routes\u002F*.php"," when the method and path already exist. Inline guards apply. See ",[803,1557,79],{"href":1558},"\u002Fdocs\u002Fphp#route-attributes",[190,1560,1561,1564],{},[205,1562,1563],{},"plugin RPC",[205,1565,1566,1569,1570,1573,1574,822,1577,1580,1581],{},[145,1567,1568],{},"router.post(\"github.webhooks\", handler)"," (a dotted literal with no leading slash) is ",[145,1571,1572],{},"POST \u002Fgithub.webhooks",". ",[145,1575,1576],{},"router.post(\"\u002Fpath\")",[145,1578,1579],{},"router.post(\"\u002Facme.events\")"," stay ordinary HTTP routes. See ",[803,1582,1584],{"href":1583},"\u002Fdocs\u002Fts-frameworks#express-koa-fastify-hono-elysia","TypeScript frameworks",[190,1586,1587,1596],{},[205,1588,1589,1590,1592,1593],{},"Kotlin ",[145,1591,1296],{}," \u002F Rust ",[145,1594,1595],{},"match",[205,1597,1598,1599,1602,1603,243,1605,148,1608,148,1611,148,1614,1617,1618,148,1621,1624,1625,1628,1629,358,1631,1633],{},"same event literals as ",[145,1600,1601],{},"switch"," \u002F PHP ",[145,1604,1595],{},[145,1606,1607],{},"\"push\" ->",[145,1609,1610],{},"\"a\", \"b\" ->",[145,1612,1613],{},"Some(\"push\") =>",[145,1615,1616],{},"\"a\" | \"b\" =>",") when the subject is an event header or event field (",[145,1619,1620],{},"headers[\"X-GitHub-Event\"]",[145,1622,1623],{},"event[\"type\"]",", including ",[145,1626,1627],{},".as_str()","). A ",[145,1630,1296],{},[145,1632,1595],{}," on another string is not an event",[190,1635,1636,1639],{},[205,1637,1638],{},"signature constant",[205,1640,1641,1642,148,1645,148,1648,1651],{},"a class or module constant whose value is a signature header counts in that class or module, or where it is imported (",[145,1643,1644],{},"self::NAME",[145,1646,1647],{},"\\App\\Billing\\Notifier::NAME",[145,1649,1650],{},"import { NAME }","). An unresolved name is not a header",[141,1653,1654,1655,1657,1658,1660,1661,1663,1664,1666,1667,1670,1671,1674,1675,1677],{},"Cashier builds the method as ",[145,1656,1494],{}," plus StudlyCase of the event type after ",[145,1659,362],{}," is replaced with ",[145,1662,1376],{},". The method name does not record which separator was used. Published Stripe event types are matched back, so ",[145,1665,1470],{}," is not read as ",[145,1668,1669],{},"invoice.payment.action.required",". A ",[145,1672,1673],{},"handle\u003CStudly>"," method that matches no published type is the Studly words joined with ",[145,1676,362],{},", which can hide underscores.",[1679,1680,1682],"h3",{"id":1681},"subscriptions-callbacks-and-drivers-152-part-b","Subscriptions, callbacks and drivers (#152 part B)",[141,1684,1685,1689,1690,148,1693,1696,1697,1700,1701,1704,1705,1707,1708,282,1710,822,1713,1716],{},[1686,1687,1688],"strong",{},"Stored event names."," A sender whose event name is read from a stored subscription (",[145,1691,1692],{},"$subscription->event",[145,1694,1695],{},"webhook.event_type",", a ",[145,1698,1699],{},"sub.events"," loop, a ",[145,1702,1703],{},"triggerEvent"," passed from a row) sends one ",[145,1706,1428],{}," per event the repo declares for those rows, each ",[145,1709,327],{},[145,1711,1712],{},"attrs.via = \"stored subscription\"",[145,1714,1715],{},"attrs.source"," naming the list. The first of these sources that names events wins:",[1718,1719,1720,1743,1754],"ol",{},[1358,1721,1722,1723,1726,1727,358,1730,148,1733,1736,1737,358,1739,1742],{},"a validation list: an enum or const list named like a webhook \u002F subscription event list, or tied to the rows by a model ",[145,1724,1725],{},"$casts"," entry, ",[145,1728,1729],{},"Rule::enum",[145,1731,1732],{},"Rule::in",[145,1734,1735],{},"z.enum",", or an ",[145,1738,253],{},[145,1740,1741],{},"event_type"," field type (PHP, TypeScript, Python);",[1358,1744,1745,1746,1749,1750,1753],{},"a config ",[145,1747,1748],{},"events"," list (",[145,1751,1752],{},"config\u002Fwebhooks.php",", a TS or Python settings file that mentions webhooks);",[1358,1755,1756,1757,148,1760,148,1763,148,1766,1769],{},"seeder, factory, fixture and migration data (",[145,1758,1759],{},"'event' => 'order.paid'",[145,1761,1762],{},"'events' => [...]",[145,1764,1765],{},"->enum('event', [...])",[145,1767,1768],{},"->default(...)",", JSON \u002F YAML fixtures).",[141,1771,1772,1773,1776],{},"A sender with no declared list keeps ",[145,1774,1775],{},"{event}"," (heuristic). Test files are not read as a source.",[141,1778,1779,1782,1783,1786,1787,148,1790,1793,1794,243,1797,148,1800,1803,1804,1806,1807,1810,1811,346,1813,1816,1817,1820,1821,346,1823,1825,1826,1829],{},[1686,1780,1781],{},"Subscriber URLs."," An absolute URL that seed data, config or ",[145,1784,1785],{},".env.example"," gives as a subscriber target (",[145,1788,1789],{},"'url' => 'https:\u002F\u002Fbookstore-api.test\u002Fwebhooks\u002Forders'",[145,1791,1792],{},"WEBHOOK_URL=...",", a TS config object) is recorded on the sender endpoints as ",[145,1795,1796],{},"attrs.subscriber_urls",[145,1798,1799],{},"url",[145,1801,1802],{},"at","). ",[145,1805,162],{}," matches each URL path against the other repos' routes with the same matcher as client calls (method ",[145,1808,1809],{},"POST",") and adds a ",[145,1812,327],{},[145,1814,1815],{},"MATCHES_ROUTE"," from the sender endpoint to the route (",[145,1818,1819],{},"attrs.via = \"subscriber url\"","). Receiver endpoints on that route that carry the same event get a ",[145,1822,327],{},[145,1824,313],{},". The link report lists each URL under \"Webhook subscriptions paired by URL\", or as ",[145,1827,1828],{},"unpaired"," with the reason. A paired route no longer counts as \"without a client call\".",[141,1831,1832,1835,1836,148,1839,148,1842,148,1845,1848,1849,1852,1853,1856,1857,1860,1861,1864,1865,1868,1869,1872,1873,148,1876,1364,1879,1882,1883,1885,1886,148,1889,148,1892,1895,1896,1898,1899,1902,1903,1905],{},[1686,1833,1834],{},"Callback URLs."," A URL built from the app's own base (",[145,1837,1838],{},"config('app.url') . '\u002Fapi\u002Fwebhooks\u002Fpayments\u002F' . $store->slug",[145,1840,1841],{},"url('\u002F...')",[145,1843,1844],{},"route('webhooks.payments', $store)",[145,1846,1847],{},"env('APP_URL')",", TypeScript ",[145,1850,1851],{},"${process.env.APP_URL}\u002F...",", Python ",[145,1854,1855],{},"settings.BASE_URL + '\u002F...'",", an f-string or ",[145,1858,1859],{},"urljoin",") that resolves to one of the app's own routes and is sent out adds ",[145,1862,1863],{},"REGISTERS_CALLBACK"," from the building function to that route (",[145,1866,1867],{},"attrs.body_key",", and ",[145,1870,1871],{},"attrs.endpoint"," when the outbound call is a known HTTP endpoint). \"Sent out\" is a body key such as ",[145,1874,1875],{},"callback_url",[145,1877,1878],{},"notify_url",[145,1880,1881],{},"webhook_url"," next to an outbound HTTP call, or the ",[145,1884,1799],{}," of an SDK registration (",[145,1887,1888],{},"client.webhooks.create(url=...)",[145,1890,1891],{},"->webhooks->create(['url' => ...])",[145,1893,1894],{},"attrs.via = \"SDK webhook registration\"","). A URL on another host, a path that is not one of the app's routes, and a URL built in a helper the function only calls are not callbacks. ",[145,1897,1418],{}," shows ",[145,1900,1901],{},"client: external callback (PaymentsClient::createPayment)"," on the route. ",[145,1904,162],{}," lists it under \"Routes called back by external parties\" instead of \"Backend routes without a client call\", when the repo is linked as a backend or both.",[141,1907,1908,1911,1912,358,1915,1918,1919,148,1922,1925,1926,148,1929,1932,1933,346,1935,1938,1939,1942,1943,282,1945,243,1947,1628,1949,1951,1952,822,1955,324,1958,1961],{},[1686,1909,1910],{},"Drivers resolved at run time."," A route handler that calls ",[145,1913,1914],{},"handleWebhook()",[145,1916,1917],{},"processWebhookRequest()"," (also ",[145,1920,1921],{},"processWebhook",[145,1923,1924],{},"handleWebhookRequest",", snake_case) on an object it does not name statically (",[145,1927,1928],{},"Gateway::driver($name)",[145,1930,1931],{},"$this->gateways[$row->gateway]",", a container-resolved interface) gets the implementations of that method: methods of that name in classes with an interface or base class that declares it, at most 12, plus what they call two levels down. Each gets a ",[145,1934,327],{},[145,1936,1937],{},"ROUTES_TO"," from the route (",[145,1940,1941],{},"via = driver","), and event comparisons inside them become ",[145,1944,293],{},[145,1946,1941],{},[145,1948,327],{},[145,1950,1309],{}," or HMAC plus constant-time check inside an implementation marks the route verified with ",[145,1953,1954],{},"how = \"driver \u003CClass>\"",[145,1956,1957],{},"attrs.webhook.via = \"driver\"",[145,1959,1960],{},"attrs.webhook.drivers"," lists the implementations. With no implementation in the repo the route is unchanged. One verifying driver marks the route verified even when another implementation does not check.",[169,1963,1965],{"id":1964},"protocol-index","Protocol index",[184,1967,1968,1985],{},[187,1969,1970],{},[190,1971,1972,1974,1977,1979,1982],{},[193,1973,229],{},[193,1975,1976],{},"id",[193,1978,410],{},[193,1980,1981],{},"example",[193,1983,1984],{},"not covered",[200,1986,1987,2027,2062,2093,2122,2154,2173,2204,2231,2253,2280,2305,2329,2359,2386,2408,2446,2478,2510,2531,2572,2600,2629,2660,2688,2714,2739,2764,2791,2814,2840,2864,2886,2906],{},[190,1988,1989,1992,1997,1999,2012],{},[205,1990,1991],{},"socketio",[205,1993,1994],{},[145,1995,1996],{},"endpoint:socketio:\u003Cns>#\u003Cevent>",[205,1998,746],{},[205,2000,2001,2004,2005,358,2008,2011],{},[145,2002,2003],{},"sio.emit('order:created')"," ↔ ",[145,2006,2007],{},"@sio.on",[145,2009,2010],{},"socket.on"," (Py, JS, Nest gateway, Dart, Kotlin, Swift, Rust)",[205,2013,2014,358,2017,324,2020,358,2023,2026],{},[145,2015,2016],{},"connect",[145,2018,2019],{},"disconnect",[145,2021,2022],{},".svelte",[145,2024,2025],{},".vue","; rooms as endpoints",[190,2028,2029,2032,2041,2043,2055],{},[205,2030,2031],{},"ws",[205,2033,2034,2037,2038],{},[145,2035,2036],{},"route:WS \u003Cpath>",", client ",[145,2039,2040],{},"http:WS \u003Cpath>",[205,2042,154],{},[205,2044,2045,2048,2049,2004,2052],{},[145,2046,2047],{},"new WebSocketServer({path})"," \u002F Ktor ",[145,2050,2051],{},"webSocket",[145,2053,2054],{},"new WebSocket(url)",[205,2056,2057,2058,2061],{},"message names inside the socket; Python and Rust clients; ",[145,2059,2060],{},"noServer"," path only when the upgrade handler names it",[190,2063,2064,2067,2073,2075,2086],{},[205,2065,2066],{},"sse",[205,2068,2069,2070],{},"HTTP route, ",[145,2071,2072],{},"stream: sse",[205,2074,154],{},[205,2076,2077,1364,2080,2004,2083],{},[145,2078,2079],{},"text\u002Fevent-stream",[145,2081,2082],{},"@Sse()",[145,2084,2085],{},"new EventSource(url)",[205,2087,2088,2089,2092],{},"SSE ",[145,2090,2091],{},"event:"," names",[190,2094,2095,2098,2103,2106,2116],{},[205,2096,2097],{},"webhook",[205,2099,2100],{},[145,2101,2102],{},"endpoint:webhook:\u003Cprovider>:\u003Cevent>",[205,2104,2105],{},"exact; hmac\u002Fsvix scheme is heuristic",[205,2107,2108,2111,2112,2115],{},[145,2109,2110],{},"event.type === 'invoice.paid'"," receives; svix ",[145,2113,2114],{},"eventType"," or a signed POST sends",[205,2117,2118,2119,2121],{},"a stored event name with no list in the repo (stays ",[145,2120,1775],{},"), callback URLs built in a helper, drivers that share no interface or base class",[190,2123,2124,2127,2138,2140,2148],{},[205,2125,2126],{},"worker",[205,2128,2129,148,2132,148,2135],{},[145,2130,2131],{},"\u003Cscript>",[145,2133,2134],{},"\u003Cscript>:out",[145,2136,2137],{},"service-worker",[205,2139,530],{},[205,2141,2142,2004,2145],{},[145,2143,2144],{},"new Worker('.\u002Fw.ts')",[145,2146,2147],{},"self.onmessage",[205,2149,2150,2151],{},"worker message types, ",[145,2152,2153],{},"MessageChannel",[190,2155,2156,2159,2164,2166,2171],{},[205,2157,2158],{},"broadcastchannel",[205,2160,2161],{},[145,2162,2163],{},"\u003Cname>",[205,2165,530],{},[205,2167,2168],{},[145,2169,2170],{},"new BroadcastChannel(name).postMessage",[205,2172],{},[190,2174,2175,2178,2185,2187,2195],{},[205,2176,2177],{},"postmessage",[205,2179,2180,1364,2183],{},[145,2181,2182],{},"\u003Ctype>",[145,2184,690],{},[205,2186,726],{},[205,2188,2189,2004,2192],{},[145,2190,2191],{},"postMessage({type})",[145,2193,2194],{},"event.data.type ===",[205,2196,2197,2200,2201],{},[145,2198,2199],{},"targetOrigin"," is a guard when the handler reads ",[145,2202,2203],{},"event.origin",[190,2205,2206,2209,2216,2218,2226],{},[205,2207,2208],{},"extension",[205,2210,2211,148,2213],{},[145,2212,2182],{},[145,2214,2215],{},"port:\u003Cname>",[205,2217,726],{},[205,2219,2220,2004,2223],{},[145,2221,2222],{},"chrome.runtime.sendMessage",[145,2224,2225],{},"onMessage",[205,2227,2228],{},[145,2229,2230],{},"externally_connectable",[190,2232,2233,2236,2241,2243,2251],{},[205,2234,2235],{},"native-messaging",[205,2237,2238],{},[145,2239,2240],{},"\u003Chost>",[205,2242,530],{},[205,2244,2245,2248,2249],{},[145,2246,2247],{},"connectNative('com.app.host')"," ↔ host manifest ",[145,2250,154],{},[205,2252],{},[190,2254,2255,2258,2263,2265,2273],{},[205,2256,2257],{},"unix",[205,2259,2260],{},[145,2261,2262],{},"\u003Cpath>",[205,2264,746],{},[205,2266,2267,2004,2270],{},[145,2268,2269],{},"UnixListener::bind(p)",[145,2271,2272],{},"connect(p)",[205,2274,2275,2276,2279],{},"abstract ",[145,2277,2278],{},"\\0"," names, systemd socket activation",[190,2281,2282,2285,2289,2291,2303],{},[205,2283,2284],{},"pipe",[205,2286,2287],{},[145,2288,2163],{},[205,2290,746],{},[205,2292,2293,358,2296,2299,2300],{},[145,2294,2295],{},"CreateNamedPipe",[145,2297,2298],{},"mkfifo"," ↔ writer ",[145,2301,2302],{},"open",[205,2304],{},[190,2306,2307,2310,2315,2317,2326],{},[205,2308,2309],{},"dbus",[205,2311,2312],{},[145,2313,2314],{},"\u003Ciface>.\u003CMember>",[205,2316,530],{},[205,2318,2319,2320,2004,2323],{},"zbus ",[145,2321,2322],{},"#[interface]",[145,2324,2325],{},"#[proxy]",[205,2327,2328],{},"D-Bus service files",[190,2330,2331,2334,2339,2341,2352],{},[205,2332,2333],{},"intent",[205,2335,2336],{},[145,2337,2338],{},"\u003Ccomponent FQN>",[205,2340,530],{},[205,2342,2343,2004,2346,358,2349],{},[145,2344,2345],{},"Intent(ctx, Foo::class.java)",[145,2347,2348],{},"onCreate",[145,2350,2351],{},"onStartCommand",[205,2353,2354,2355,2358],{},"extras, ",[145,2356,2357],{},"content:\u002F\u002F",", Messenger",[190,2360,2361,2364,2369,2372,2380],{},[205,2362,2363],{},"intent-action",[205,2365,2366],{},[145,2367,2368],{},"\u003Caction>",[205,2370,2371],{},"exact, fan-out",[205,2373,2374,2377,2378],{},[145,2375,2376],{},"Intent(\"com.x.ACTION\")"," ↔ manifest ",[145,2379,2368],{},[205,2381,2382,2385],{},[145,2383,2384],{},"android.*"," \u002F SDK actions",[190,2387,2388,2391,2396,2398,2406],{},[205,2389,2390],{},"aidl",[205,2392,2393],{},[145,2394,2395],{},"\u003Cpkg.IFace>.\u003Cmethod>",[205,2397,530],{},[205,2399,2400,2004,2403],{},[145,2401,2402],{},"Stub.asInterface(b).m()",[145,2404,2405],{},"IFace.Stub",[205,2407],{},[190,2409,2410,2412,2420,2422,2437],{},[205,2411,368],{},[205,2413,2414,148,2417],{},[145,2415,2416],{},"\u003Cprogram>",[145,2418,2419],{},"\u003Cprogram>:out",[205,2421,530],{},[205,2423,2424,2425,358,2428,358,2431,2004,2434],{},"in-repo ",[145,2426,2427],{},"spawn",[145,2429,2430],{},"subprocess",[145,2432,2433],{},"artisan",[145,2435,2436],{},"process.on('message')",[205,2438,2439,148,2442,2445],{},[145,2440,2441],{},"cluster.fork",[145,2443,2444],{},"python -c"," (a call, not a program)",[190,2447,2448,2451,2459,2461,2472],{},[205,2449,2450],{},"isolate",[205,2452,2453,148,2456],{},[145,2454,2455],{},"\u003Cfile>#\u003Centry>",[145,2457,2458],{},":out",[205,2460,530],{},[205,2462,2463,358,2466,2004,2469],{},[145,2464,2465],{},"Isolate.spawn",[145,2467,2468],{},"compute",[145,2470,2471],{},"port.listen",[205,2473,2474,2475],{},"later messages on a returned ",[145,2476,2477],{},"SendPort",[190,2479,2480,2483,2491,2493,2501],{},[205,2481,2482],{},"xpc",[205,2484,2485,148,2488],{},[145,2486,2487],{},"\u003Cservice>",[145,2489,2490],{},"\u003CProtocol>.\u003Cmethod>",[205,2492,530],{},[205,2494,2495,2004,2498],{},[145,2496,2497],{},"NSXPCConnection(machServiceName:)",[145,2499,2500],{},"shouldAcceptNewConnection",[205,2502,2503,346,2506,2509],{},[145,2504,2505],{},"Info.plist",[145,2507,2508],{},"NSXPCListener.service()",", dependency protocols",[190,2511,2512,2515,2519,2521,2529],{},[205,2513,2514],{},"darwin-notification",[205,2516,2517],{},[145,2518,2163],{},[205,2520,2371],{},[205,2522,2523,2004,2526],{},[145,2524,2525],{},"CFNotificationCenterPostNotification",[145,2527,2528],{},"AddObserver",[205,2530],{},[190,2532,2533,2536,2544,2551,2563],{},[205,2534,2535],{},"tcp, udp",[205,2537,2538,148,2541],{},[145,2539,2540],{},"endpoint:tcp:\u003Cport>",[145,2542,2543],{},"udp:\u003Cport>",[205,2545,2546,2547,2550],{},"same port; ",[145,2548,2549],{},"env:KEY"," is heuristic",[205,2552,2553,2004,2556,2559,2560],{},[145,2554,2555],{},"listen(6379)",[145,2557,2558],{},"connect(6379)"," across the languages in ",[145,2561,2562],{},"cg_code_graph\u002Fsockets.py",[205,2564,2565,2566,2569,2570],{},"proof they speak; QUIC; WebRTC; port only in a config file; ",[145,2567,2568],{},"env:"," across ",[145,2571,162],{},[190,2573,2574,2577,2580,2583,2598],{},[205,2575,2576],{},"mdns, osc, coap, ssdp",[205,2578,2579],{},"service type, OSC address, CoAP path, SSDP USN",[205,2581,2582],{},"exact \u002F glob \u002F path",[205,2584,2585,2586,2004,2589,324,2592,2004,2595],{},"zeroconf ",[145,2587,2588],{},"ServiceInfo",[145,2590,2591],{},"ServiceBrowser",[145,2593,2594],{},"dispatcher.map",[145,2596,2597],{},"send_message",[205,2599],{},[190,2601,2602,2605,2610,2613,2622],{},[205,2603,2604],{},"grpc",[205,2606,2607],{},[145,2608,2609],{},"endpoint:grpc:\u003Cpkg>.\u003CService>\u002F\u003CMethod>",[205,2611,2612],{},"contract method, case-insensitive",[205,2614,2615,346,2618,2621],{},[145,2616,2617],{},".proto",[145,2619,2620],{},"rpc"," ↔ servicer class \u002F stub call",[205,2623,2624,2625,2628],{},"Go; Nest ",[145,2626,2627],{},"@GrpcMethod"," not merged onto the contract node",[190,2630,2631,2634,2639,2645,2657],{},[205,2632,2633],{},"thrift",[205,2635,2636],{},[145,2637,2638],{},"endpoint:thrift:\u003Cstem>.\u003CService>\u002F\u003Cmethod>",[205,2640,2641,2642],{},"same, including ",[145,2643,2644],{},"extends",[205,2646,2647,2650,2651,358,2654],{},[145,2648,2649],{},".thrift"," service ↔ ",[145,2652,2653],{},"Svc.Client",[145,2655,2656],{},"Processor",[205,2658,2659],{},"Java sources (heuristic plugin; Thrift receivers are not linked yet)",[190,2661,2662,2665,2670,2673,2682],{},[205,2663,2664],{},"trpc",[205,2666,2667],{},[145,2668,2669],{},"endpoint:trpc:\u003Cdotted.path>",[205,2671,2672],{},"exact path",[205,2674,2675,2678,2679],{},[145,2676,2677],{},"createTRPCRouter"," procedure ↔ ",[145,2680,2681],{},"x.post.create.useQuery",[205,2683,2684,2687],{},[145,2685,2686],{},"lazy()"," routers",[190,2689,2690,2693,2698,2700,2711],{},[205,2691,2692],{},"jsonrpc",[205,2694,2695],{},[145,2696,2697],{},"endpoint:jsonrpc:\u003Cmethod>",[205,2699,530],{},[205,2701,2702,358,2705,2004,2708],{},[145,2703,2704],{},"addMethod(\"x\")",[145,2706,2707],{},"@method",[145,2709,2710],{},".request(\"x\")",[205,2712,2713],{},"MCP (its own endpoints); LSP methods",[190,2715,2716,2719,2724,2726,2732],{},[205,2717,2718],{},"graphql",[205,2720,2721],{},[145,2722,2723],{},"endpoint:graphql:\u003CRoot>.\u003Cfield>",[205,2725,530],{},[205,2727,2728,2729],{},"SDL or graphene \u002F strawberry \u002F ariadne \u002F Nest ↔ Apollo ",[145,2730,2731],{},"useQuery",[205,2733,2734,2735,2738],{},"object-type fields; ",[145,2736,2737],{},".graphql"," ops with no hook; Lighthouse, Rust, Spring, Apollo mobile",[190,2740,2741,2743,2748,2751,2761],{},[205,2742,905],{},[205,2744,2745],{},[145,2746,2747],{},"endpoint:job:\u003Cfw>:\u003Cname>",[205,2749,2750],{},"task name",[205,2752,2753,2754,2004,2757,2760],{},"Celery ",[145,2755,2756],{},"send_task(\"billing.charge\")",[145,2758,2759],{},"@app.task(name=)","; also RQ, Dramatiq, Bull, Laravel, Messenger",[205,2762,2763],{},"Huey, arq, Spring JMS, Agenda; project wrappers",[190,2765,2766,2769,2774,2777,2789],{},[205,2767,2768],{},"queue",[205,2770,2771],{},[145,2772,2773],{},"endpoint:queue:\u003Cfw>\u002F\u003Cname>",[205,2775,2776],{},"queue name",[205,2778,2779,2780,358,2783,358,2786],{},"enqueue ↔ ",[145,2781,2782],{},"celery -Q",[145,2784,2785],{},"queue:work",[145,2787,2788],{},"messenger:consume",[205,2790],{},[190,2792,2793,2796,2801,2803,2811],{},[205,2794,2795],{},"kafka",[205,2797,2798],{},[145,2799,2800],{},"kafka:\u003Ctopic>",[205,2802,726],{},[205,2804,2805,2004,2808],{},[145,2806,2807],{},"producer.send({topic})",[145,2809,2810],{},"subscribe",[205,2812,2813],{},"SQS, SNS, Pub\u002FSub, Service Bus, STOMP, ZeroMQ, JetStream",[190,2815,2816,2818,2826,2828,2837],{},[205,2817,703],{},[205,2819,2820,148,2823],{},[145,2821,2822],{},"amqp:\u003Cexchange>\u002F\u003Ckey>",[145,2824,2825],{},"amqp:queue:\u003Cname>",[205,2827,703],{},[205,2829,2830,2833,2834],{},[145,2831,2832],{},"basic_publish"," ↔ queue bound with ",[145,2835,2836],{},"consume",[205,2838,2839],{},"bindings only in Terraform \u002F SAM",[190,2841,2842,2845,2850,2856,2862],{},[205,2843,2844],{},"redis-pubsub",[205,2846,2847],{},[145,2848,2849],{},"redis-pubsub:\u003Cchannel>",[205,2851,2852,2853],{},"glob for ",[145,2854,2855],{},"PSUBSCRIBE",[205,2857,2858,2004,2860],{},[145,2859,545],{},[145,2861,2810],{},[205,2863],{},[190,2865,2866,2869,2874,2876,2884],{},[205,2867,2868],{},"redis-stream",[205,2870,2871],{},[145,2872,2873],{},"redis-stream:\u003Ckey>",[205,2875,530],{},[205,2877,2878,2004,2881],{},[145,2879,2880],{},"xadd",[145,2882,2883],{},"xreadgroup",[205,2885],{},[190,2887,2888,2890,2895,2897,2904],{},[205,2889,496],{},[205,2891,2892],{},[145,2893,2894],{},"mqtt:\u003Ctopic>",[205,2896,496],{},[205,2898,2899,2004,2902],{},[145,2900,2901],{},"publish(topic)",[145,2903,2810],{},[205,2905],{},[190,2907,2908,2910,2915,2917,2926],{},[205,2909,682],{},[205,2911,2912],{},[145,2913,2914],{},"nats:\u003Csubject>",[205,2916,682],{},[205,2918,2919,358,2921,2004,2924],{},[145,2920,545],{},[145,2922,2923],{},"request",[145,2925,2810],{},[205,2927],{},[141,2929,2930,2931,2933,2934,2936],{},"Broker and job names come from literals, constants, enums and templates (",[145,2932,225],{}," is heuristic).\nA repository wrapper that rewrites the topic is skipped. Kotlin (Spring listeners,\nkafka-clients, RabbitMQ) and Rust (lapin, rdkafka, async-nats) use the same ids. ",[145,2935,162],{}," joins\nthem across repos.",[169,2938,2940],{"id":2939},"not-covered-yet","Not covered yet",[1355,2942,2943,2952,2960,2963,2966],{},[1358,2944,2945,2946,2948,2949,2951],{},"Guards on Bull processors are not copied onto the adapted ",[145,2947,905],{}," node, so ",[145,2950,1025],{}," is not\nchecked there.",[1358,2953,2954,2956,2957,2959],{},[145,2955,1005],{}," needs ",[145,2958,256],{}," on both sides.",[1358,2961,2962],{},"Broker and host nodes are not attached to endpoints yet.",[1358,2964,2965],{},"Go has no plugin (gRPC, sockets, brokers). Java has a heuristic plugin; RPC shapes still add no\nedges.",[1358,2967,2968,2969,2972],{},"GraphQL: code-first schemas (TypeGraphQL, Pothos), ",[145,2970,2971],{},"@deprecated"," and field guards.",[2974,2975,2976],"style",{},"html pre.shiki code .sHkq1, html code.shiki .sHkq1{--shiki-light:#6FAF00;--shiki-default:#6FAF00;--shiki-dark:#A3E635}html pre.shiki code .snmWg, html code.shiki .snmWg{--shiki-light:#27272A;--shiki-default:#27272A;--shiki-dark:#E4E4E7}html pre.shiki code .sZ_TN, html code.shiki .sZ_TN{--shiki-light:#71717A;--shiki-default:#71717A;--shiki-dark:#A1A1AA}html pre.shiki code .sZJo5, html code.shiki .sZJo5{--shiki-light:#65A30D;--shiki-default:#65A30D;--shiki-dark:#84CC16}html pre.shiki code .sha9Y, html code.shiki .sha9Y{--shiki-light:#9F8CFF;--shiki-default:#9F8CFF;--shiki-dark:#C4B5FD}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 .s4LKg, html code.shiki .s4LKg{--shiki-light:#4D7C0F;--shiki-default:#4D7C0F;--shiki-dark:#84CC16}html pre.shiki code .seS0s, html code.shiki .seS0s{--shiki-light:#71717A;--shiki-light-font-style:italic;--shiki-default:#71717A;--shiki-default-font-style:italic;--shiki-dark:#A1A1AA;--shiki-dark-font-style:italic}",{"title":182,"searchDepth":1190,"depth":477,"links":2978},[2979,2980,2981,2982,2983,2984,2987,2988],{"id":171,"depth":477,"text":172},{"id":383,"depth":477,"text":384},{"id":809,"depth":477,"text":810},{"id":943,"depth":477,"text":944},{"id":1128,"depth":477,"text":166},{"id":1276,"depth":477,"text":1277,"children":2985},[2986],{"id":1681,"depth":567,"text":1682},{"id":1964,"depth":477,"text":1965},{"id":2939,"depth":477,"text":2940},"cg pairs a sender with the code that receives it: HTTP, channels, Nest messages, job queues,\nevents, bridges, and named endpoints of messaging protocols. impact, reaches, path and\ndownstream cross those edges in one repo and, after cg link, between two. cg protocols\nlists endpoints with senders, receivers, guards and checks.","md",{},true,{"title":91,"description":2989},"K0-troy7302rXO6Ik6cQG1agjKnRrgUv8grovg-6jZE",[2996,2998],{"title":87,"path":88,"stem":89,"description":2997,"children":-1},"Per-platform code is tagged with the targets it is built for. --platform ios drops what that\ntarget does not build. cg platforms divergence lists variants that leave a declared target\nuncovered, and calls that are live where the callee is absent.",{"title":95,"path":96,"stem":97,"description":2999,"children":-1},"What .py adds beyond Install, CLI specs, and Graph schema: source roots and module names, reference how values, and FastAPI \u002F Starlette \u002F Flask route ids.\nThe parser is the stdlib ast module. A checkout needs no virtualenv, and the project is never imported.\nWhy a file is unmapped: cg coverage. The python.source_roots key: Configuration.",1792170236770]