[{"data":1,"prerenderedAt":567},["ShallowReactive",2],{"navigation_docs":3,"-platform-defense-in-depth":213,"-platform-defense-in-depth-surround":562},[4,142],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":36},"Kinotic Apps","i-lucide-rocket","\u002Fapps","01.apps",[10,14,18,37,58,91,102,122,127],{"title":11,"path":12,"stem":13},"Introduction","\u002Fapps\u002Fintroduction","01.apps\u002F01.introduction",{"title":15,"path":16,"stem":17},"Quick Start","\u002Fapps\u002Fquick-start","01.apps\u002F02.quick-start",{"title":19,"icon":20,"path":21,"stem":22,"children":23,"page":36},"Application Structure","i-lucide-folder-tree","\u002Fapps\u002Fapplication-structure","01.apps\u002F03.application-structure",[24,28,32],{"title":25,"path":26,"stem":27},"Overview","\u002Fapps\u002Fapplication-structure\u002Foverview","01.apps\u002F03.application-structure\u002F01.overview",{"title":29,"path":30,"stem":31},"Applications and Projects","\u002Fapps\u002Fapplication-structure\u002Fapplications-and-projects","01.apps\u002F03.application-structure\u002F02.applications-and-projects",{"title":33,"path":34,"stem":35},"Artifact Types","\u002Fapps\u002Fapplication-structure\u002Fartifact-types","01.apps\u002F03.application-structure\u002F03.artifact-types",false,{"title":38,"icon":39,"path":40,"stem":41,"children":42,"page":36},"Services","i-lucide-network","\u002Fapps\u002Fservices","01.apps\u002F04.services",[43,46,50,54],{"title":25,"path":44,"stem":45},"\u002Fapps\u002Fservices\u002Foverview","01.apps\u002F04.services\u002F01.overview",{"title":47,"path":48,"stem":49},"Publishing Services","\u002Fapps\u002Fservices\u002Fpublishing-services","01.apps\u002F04.services\u002F02.publishing-services",{"title":51,"path":52,"stem":53},"Service Proxies","\u002Fapps\u002Fservices\u002Fservice-proxies","01.apps\u002F04.services\u002F03.service-proxies",{"title":55,"path":56,"stem":57},"Streaming","\u002Fapps\u002Fservices\u002Fstreaming","01.apps\u002F04.services\u002F04.streaming",{"title":59,"icon":60,"path":61,"stem":62,"children":63,"page":36},"Persistence","i-lucide-database","\u002Fapps\u002Fpersistence","01.apps\u002F05.persistence",[64,67,71,75,79,83,87],{"title":25,"path":65,"stem":66},"\u002Fapps\u002Fpersistence\u002Foverview","01.apps\u002F05.persistence\u002F01.overview",{"title":68,"path":69,"stem":70},"Defining Entities","\u002Fapps\u002Fpersistence\u002Fdefining-entities","01.apps\u002F05.persistence\u002F02.defining-entities",{"title":72,"path":73,"stem":74},"Entity Decorators","\u002Fapps\u002Fpersistence\u002Fentity-decorators","01.apps\u002F05.persistence\u002F03.entity-decorators",{"title":76,"path":77,"stem":78},"CRUD Operations","\u002Fapps\u002Fpersistence\u002Fcrud-operations","01.apps\u002F05.persistence\u002F04.crud-operations",{"title":80,"path":81,"stem":82},"Named Queries","\u002Fapps\u002Fpersistence\u002Fnamed-queries","01.apps\u002F05.persistence\u002F05.named-queries",{"title":84,"path":85,"stem":86},"Multi-Tenancy","\u002Fapps\u002Fpersistence\u002Fmulti-tenancy","01.apps\u002F05.persistence\u002F06.multi-tenancy",{"title":88,"path":89,"stem":90},"Migrations","\u002Fapps\u002Fpersistence\u002Fmigrations","01.apps\u002F05.persistence\u002F07.migrations",{"title":92,"icon":93,"path":94,"stem":95,"children":96,"page":36},"Security","i-lucide-shield-check","\u002Fapps\u002Fsecurity","01.apps\u002F06.security",[97],{"title":98,"path":99,"stem":100,"icon":101},"Authentication","\u002Fapps\u002Fsecurity\u002Fauthentication","01.apps\u002F06.security\u002F01.authentication","i-lucide-key-round",{"title":103,"icon":104,"path":105,"stem":106,"children":107,"page":36},"Deployment","i-lucide-cloud-upload","\u002Fapps\u002Fdeployment","01.apps\u002F07.deployment",[108,113,118],{"title":109,"path":110,"stem":111,"icon":112},"Deployment Workflow","\u002Fapps\u002Fdeployment\u002Fworkflow","01.apps\u002F07.deployment\u002F01.workflow","i-lucide-git-branch",{"title":114,"path":115,"stem":116,"icon":117},"Environments","\u002Fapps\u002Fdeployment\u002Fenvironments","01.apps\u002F07.deployment\u002F02.environments","i-lucide-server",{"title":119,"path":120,"stem":121,"icon":6},"Push to Deploy","\u002Fapps\u002Fdeployment\u002Fpush-to-deploy","01.apps\u002F07.deployment\u002F03.push-to-deploy",{"title":123,"path":124,"stem":125,"icon":126},"CLI Reference","\u002Fapps\u002Fcli-reference","01.apps\u002F08.cli-reference","i-lucide-terminal",{"title":128,"icon":129,"path":130,"stem":131,"children":132,"page":36},"Reference","i-lucide-book-open","\u002Fapps\u002Freference","01.apps\u002F09.reference",[133,138],{"title":134,"path":135,"stem":136,"icon":137},"Decorators Reference","\u002Fapps\u002Freference\u002Fdecorators","01.apps\u002F09.reference\u002F01.decorators","i-lucide-at-sign",{"title":139,"path":140,"stem":141,"icon":60},"Migration SQL Grammar","\u002Fapps\u002Freference\u002Fmigration-sql-grammar","01.apps\u002F09.reference\u002F02.migration-sql-grammar",{"title":143,"icon":117,"path":144,"stem":145,"children":146,"page":36},"Kinotic OS","\u002Fplatform","02.platform",[147,152,156,161,166,171,175,180,185,190,195],{"title":148,"path":149,"stem":150,"icon":151},"System Architecture","\u002Fplatform\u002Farchitecture","02.platform\u002F01.architecture","i-lucide-boxes",{"title":153,"path":154,"stem":155,"icon":6},"Deployment Guide","\u002Fplatform\u002Fdeployment-guide","02.platform\u002F02.deployment-guide",{"title":157,"path":158,"stem":159,"icon":160},"Configuration","\u002Fplatform\u002Fconfiguration","02.platform\u002F03.configuration","i-lucide-settings",{"title":162,"path":163,"stem":164,"icon":165},"Organization Management","\u002Fplatform\u002Forganization-management","02.platform\u002F04.organization-management","i-lucide-building",{"title":167,"path":168,"stem":169,"icon":170},"System Security","\u002Fplatform\u002Fsystem-security","02.platform\u002F05.system-security","i-lucide-shield",{"title":172,"path":173,"stem":174,"icon":93},"Defense in Depth","\u002Fplatform\u002Fdefense-in-depth","02.platform\u002F06.defense-in-depth",{"title":176,"path":177,"stem":178,"icon":179},"MCP Tools","\u002Fplatform\u002Fmcp-tools","02.platform\u002F07.mcp-tools","i-lucide-bot",{"title":181,"path":182,"stem":183,"icon":184},"Observability","\u002Fplatform\u002Fobservability","02.platform\u002F08.observability","i-lucide-activity",{"title":186,"path":187,"stem":188,"icon":189},"Contributing","\u002Fplatform\u002Fcontributing","02.platform\u002F09.contributing","i-lucide-git-pull-request",{"title":191,"path":192,"stem":193,"icon":194},"System Migrations","\u002Fplatform\u002Fsystem-migrations","02.platform\u002F10.system-migrations","i-lucide-database-zap",{"title":128,"icon":129,"path":196,"stem":197,"children":198,"page":36},"\u002Fplatform\u002Freference","02.platform\u002F11.reference",[199,204,209],{"title":200,"path":201,"stem":202,"icon":203},"CRI Format","\u002Fplatform\u002Freference\u002Fcri-format","02.platform\u002F11.reference\u002F01.cri-format","i-lucide-link",{"title":205,"path":206,"stem":207,"icon":208},"Grind Jobs","\u002Fplatform\u002Freference\u002Fgrind-jobs","02.platform\u002F11.reference\u002F02.grind-jobs","i-lucide-workflow",{"title":210,"path":211,"stem":212,"icon":151},"Project Publishing Design","\u002Fplatform\u002Freference\u002Fproject-publishing-design","02.platform\u002F11.reference\u002F03.project-publishing-design",{"id":214,"title":172,"body":215,"description":555,"extension":556,"links":557,"meta":558,"navigation":559,"path":173,"seo":560,"stem":174,"__hash__":561},"docs\u002F02.platform\u002F06.defense-in-depth.md",{"type":216,"value":217,"toc":544},"minimark",[218,222,230,233,254,258,261,264,267,270,302,306,317,320,356,360,363,394,398,405,422,425,449,453,456,496,503,507,513,537],[219,220,25],"h2",{"id":221},"overview",[223,224,225,226,229],"p",{},"The platform is built so that no single defect — a buggy query filter, corrupted stored data, a misbehaving client, a replayed token — can widen access on its own. Every request path crosses at least two independent enforcement layers that would each have to fail for an unauthorized action to succeed. This page catalogs those layers; the operational security model (scopes, credentials, OIDC) is on ",[227,228,167],"a",{"href":168},".",[223,231,232],{},"Two principles run through all of it:",[234,235,236,248],"ul",{},[237,238,239,243,244,247],"li",{},[240,241,242],"strong",{},"Enforcement is structural, not pattern-based."," Authorization decisions read typed values — the participant type, the zone parsed from the ",[227,245,246],{"href":201},"CRI"," — never string patterns a crafted input might slip past.",[237,249,250,253],{},[240,251,252],{},"Internal faults are logged, not leaked."," When an internal invariant is violated, the full detail (CRIs, ids) goes to the server log for operators, and the caller receives a generic error indistinguishable from a routine failure.",[219,255,257],{"id":256},"network-architecture","Network Architecture",[223,259,260],{},"The target deployment shape gives every participant type its own plane — its own server, gateway, and credential surface — so isolation comes from what code exists where and what listens where, not from configuration flags.",[262,263],"architecture-diagram",{},[223,265,266],{},"Reading the diagram: solid lines are network paths (every internet crossing is one of two public HTTPS listeners, or the VPN gate); dotted lines are data access; dashed enclosures are security boundaries. The system server has no public listener — its only ingress is the VPN gate for operators, the VNet-internal path from workload nodes, and the OS-bus cluster interconnect. The two buses are never linked; shared data stores — every access scoped System, Org, or App — are the only coupling between the buses.",[223,268,269],{},"The layers, from the outside in:",[271,272,273,279,284,290,296],"ol",{},[237,274,275,278],{},[240,276,277],{},"Network"," — three internet ingress points: two public HTTPS gateways and a VPN gate. The system server is reachable only through the VPN or from inside the VNet; the two buses are never linked.",[237,280,281,283],{},[240,282,98],{}," — a dedicated SecurityService per plane; each accepts only its own participant types, with the others' code absent, not disabled.",[237,285,286,289],{},[240,287,288],{},"Authorization"," — zone rules plus service-level RBAC; machine identities are role-narrowed, one identity per node, instantly revocable.",[237,291,292,295],{},[240,293,294],{},"Isolation"," — workloads run sandboxed; credentials reach them only as short-lived secret references, resolved at execution.",[237,297,298,301],{},[240,299,300],{},"Data"," — every access scoped System, Org, or App over shared clusters, with least-privilege storage principals underneath.",[219,303,305],{"id":304},"zone-authorization","Zone Authorization",[223,307,308,309,313,314,229],{},"Every routable address carries its zone in the CRI itself, so the isolation boundary travels with the message and is validated wherever the message goes. Which zones a participant may address is derived from the participant type in one place — ",[310,311,312],"code",{},"ZoneRules"," — and every enforcement point uses that same derivation. The full participant × zone matrix is in the ",[227,315,316],{"href":201},"CRI format reference",[223,318,319],{},"The derivation defends its own inputs:",[234,321,322,332,350],{},[237,323,324,327,328,331],{},[240,325,326],{},"Ids are validated before they form a zone."," An organization or application id must be a single dot-free label. A crafted id containing a dot would shift the ",[310,329,330],{},"app.\u003CorganizationId>.\u003CapplicationId>"," label structure — letting one (org, app) pair produce the same zone as a different pair plus a sub-zone — so such an id fails authentication instead of widening access.",[237,333,334,337,338,341,342,345,346,349],{},[240,335,336],{},"Sub-zone matching respects label boundaries."," ",[310,339,340],{},"app.acme-org.orders-app.billing"," is a sub-zone of ",[310,343,344],{},"app.acme-org.orders-app",", but ",[310,347,348],{},"app.acme-org.orders-app-2"," is not — the match requires a dot at the boundary, so a similarly-prefixed zone name grants nothing.",[237,351,352,355],{},[240,353,354],{},"Un-zoned addresses are system-only."," An address without a zone carries no isolation boundary, so only participants allowed to send anywhere may address it.",[219,357,359],{"id":358},"stomp-endpoint","STOMP Endpoint",[223,361,362],{},"Every frame on a connection is checked against the participant's zones — authenticating once does not exempt any later send or subscribe:",[234,364,365,371,381],{},[237,366,367,370],{},[240,368,369],{},"Sends"," must target a zone the participant may address, or match a single-use, exact-CRI temporary grant issued by the server for a specific expected message.",[237,372,373,376,377,380],{},[240,374,375],{},"Subscriptions"," are limited to the participant's subscribable zones plus its own reply destinations. Reply destinations are scoped by a server-generated ",[310,378,379],{},"replyToId"," — the client cannot pick a guessable or colliding value, and a connection can never subscribe to another connection's replies.",[237,382,383,393],{},[240,384,385,388,389,392],{},[310,386,387],{},"management-api"," and ",[310,390,391],{},"app-api"," are hosted in-process only."," No external connection may subscribe in those zones, so no external node can register itself as a platform service and intercept calls.",[219,395,397],{"id":396},"mcp-endpoint","MCP Endpoint",[223,399,400,401,404],{},"An MCP ",[310,402,403],{},"tools\u002Fcall"," crosses two independent authorization layers:",[271,406,407,413],{},[237,408,409,412],{},[240,410,411],{},"Resolution is scoped."," The tool lookup queries Elasticsearch with the caller's zone visibility filter — a tool outside the participant's zones is not found at all, exactly as if it did not exist.",[237,414,415,418,419,421],{},[240,416,417],{},"Dispatch is re-authorized."," Before the call is sent, the invoker re-checks the resolved CRI against the same ",[310,420,312],{}," the STOMP path enforces. If the stored directory data or the visibility query were ever wrong, the dispatch is refused, the CRIs are logged as a server fault, and the caller sees an unknown tool.",[223,423,424],{},"The surrounding surface is hardened the same way:",[234,426,427,433,443],{},[237,428,429,432],{},[240,430,431],{},"Tool names are always minted, never parsed."," A name is derived from the service's qualified name and function, making it unique system wide; no override exists, and nothing ever parses a name apart to make a decision — resolution is a caller-scoped directory query and authorization reads the zone from the stored CRI, so the name is never a trust input.",[237,434,435,438,439,442],{},[240,436,437],{},"Listings never expose dispatch addresses."," The tool listing query excludes the CRI at the Elasticsearch ",[310,440,441],{},"_source"," level, so the internal address never leaves the data store for a listing.",[237,444,445,448],{},[240,446,447],{},"Duplicate names are refused, not resolved."," Minted names are unique system wide, so more than one match for a name means the directory index is corrupted. The platform never picks a winner: the providing CRIs are logged for operators and the caller receives a generic internal error.",[219,450,452],{"id":451},"github-install-binding","GitHub Install Binding",[223,454,455],{},"Linking a GitHub account stores the record that authorizes every later repository operation for that org — repo creation, pushes, token minting all trace back to it — so the bind itself crosses three independent proofs before it is persisted:",[234,457,458,471,477],{},[237,459,460,337,463,466,467,470],{},[240,461,462],{},"The state token binds the round-trip to the org.",[310,464,465],{},"startInstall"," mints a single-use, 10-minute state bound to the caller's organization; ",[310,468,469],{},"completeInstall"," consumes it atomically and rejects a state staged for a different org. A replayed or forged callback dies here.",[237,472,473,476],{},[240,474,475],{},"The user-authorization code binds the round-trip to a GitHub user."," The App requests user authorization (OAuth) during installation, so GitHub's post-install redirect carries a code that only the person who authenticated at GitHub in that browser can produce. The server exchanges it — using the GitHub App's own OAuth credential — for that user's access token.",[237,478,479,482,483,486,487,491,492,495],{},[240,480,481],{},"GitHub attests the user controls the installation."," The ",[310,484,485],{},"installation_id"," in the redirect is browser-supplied and therefore attacker-controlled; installation ids are small sequential integers, and the App itself can resolve ",[488,489,490],"em",{},"any"," of its installations, so no App-credential lookup can vet one. Instead the server asks GitHub which installations of this App the authorizing user can access (",[310,493,494],{},"GET \u002Fuser\u002Finstallations"," with the user's token) and persists the binding only when the claimed id — with a matching App id — appears on that list. Claiming another customer's installation fails with an authorization error and nothing is stored.",[223,497,498,499,502],{},"The account login and type stored on the binding are read from the attested ",[310,500,501],{},"\u002Fuser\u002Finstallations"," entry, never from a lookup made with the App's own credentials.",[219,504,506],{"id":505},"authentication-cross-checks","Authentication Cross-Checks",[223,508,509,510,512],{},"Documented in full on ",[227,511,167],{"href":168},", one check is defense-in-depth by design:",[234,514,515],{},[237,516,517,520,521,524,525,528,529,532,533,536],{},[240,518,519],{},"JWT scope claims are cross-checked against the user record."," A Kinotic-minted JWT carries ",[310,522,523],{},"organizationId","\u002F",[310,526,527],{},"applicationId"," claims, and authentication requires them to match the ",[310,530,531],{},"ParticipantIdentity"," the ",[310,534,535],{},"sub"," claim resolves to — a token minted before the user was moved or re-scoped is rejected even though its signature verifies.",[223,538,539,540,543],{},"Credential failures are also uniform: an unknown email and a wrong password produce the same ",[310,541,542],{},"Invalid credentials"," error, so the login surface cannot be used to enumerate which accounts exist.",{"title":545,"searchDepth":546,"depth":546,"links":547},"",2,[548,549,550,551,552,553,554],{"id":221,"depth":546,"text":25},{"id":256,"depth":546,"text":257},{"id":304,"depth":546,"text":305},{"id":358,"depth":546,"text":359},{"id":396,"depth":546,"text":397},{"id":451,"depth":546,"text":452},{"id":505,"depth":546,"text":506},"The layered enforcement strategies applied to every request path in Kinotic OS.","md",null,{},{"icon":93},{"title":172,"description":555},"yc8P3YgE4x__5ckvEuQMPiebPD0OO1j_EQm7JVqnlI4",[563,565],{"title":167,"path":168,"stem":169,"description":564,"icon":170,"children":-1},"Platform-level security architecture in Kinotic OS — scope isolation, credential separation, OIDC model.",{"title":176,"path":177,"stem":178,"description":566,"icon":179,"children":-1},"Expose published service functions as Model Context Protocol tools.",1788549863676]