From aee27bdc90dc73cfa0095302765077cfe0f0ff5f Mon Sep 17 00:00:00 2001 From: Kieran Klukas Date: Mon, 17 Aug 2026 15:50:26 -0400 Subject: [PATCH] kloe: proper roles --- machines/terebithia/default.nix | 41 ++++++++++++++++++++++++++++++-- secrets/kloe.age | Bin 1081 -> 1166 bytes 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/machines/terebithia/default.nix b/machines/terebithia/default.nix index accdc93..dd798b7 100644 --- a/machines/terebithia/default.nix +++ b/machines/terebithia/default.nix @@ -567,9 +567,38 @@ issuer = "https://indiko.dunkirk.sh"; clientId = "ikc_cskXitSS6XFSDzvyq3NBA"; clientSecret = "$KLOE_CLIENT_SECRET"; - allowedSubs = [ "https://dunkirk.sh/" ]; + # Anyone with an indiko account may sign in; roles decide what they + # get. A role is held by name or by what indiko calls someone, and a + # name wins: indiko only reports a role during a fresh login, where a + # name here applies the moment it deploys. + allowedSubs = [ ]; + roles = { + owner = { + admin = true; + sandbox = true; + publish = true; + subs = [ "https://dunkirk.sh/" ]; + # "admin" is what the kloe client offers in indiko; "owner" is kept + # in case the client is ever renamed to match this side. + providerRoles = [ + "admin" + "owner" + ]; + }; + # Everyone else: chat, whichever models are marked for guests, and + # whatever they connect their own account to. No shell, which is this + # machine, and no public links, which are this domain. + guest = { + providerRoles = [ "guest" ]; + }; + }; }; + # Encrypts the provider credentials users hand over (their own hyper + # grant, a pasted key). Without it kloe refuses to store one rather than + # writing it into a database that gets backed up offsite. + security.credentialKey = "$KLOE_CREDENTIAL_KEY"; + lard = { enabled = true; baseUrl = "https://lard.dunkirk.sh"; @@ -587,7 +616,9 @@ apiKey = "$CERAMIC_API_KEY"; } ]; - maxResults = 5; + # Asked of each backend and kept after fusion. Ceramic will go to 50; + # this is the dial that decides how much of a search the model reads. + maxResults = 10; }; fetch.renderer = { @@ -614,6 +645,12 @@ apiEndpoint = "https://hyper.charm.land/v1"; type = "hyper"; maxConcurrency = 4; + # The device endpoints sit at the app root, not under /v1, so a user + # can approve kloe from hyper's own page and spend their own credits. + oauth = { + flow = "hyper-device"; + baseUrl = "https://hyper.charm.land"; + }; } { id = "llmsolutions"; diff --git a/secrets/kloe.age b/secrets/kloe.age index 85acc33b27e70b5fcc536af77116f947ec1c5caf..d86fe1cebb2003081aa84e76f4734ecdc6454952 100644 GIT binary patch delta 1141 zcmdnV(Z@MKqdqAl$k$K5Qa`QK+{~>a+$%9B#m~(s+bJVEKPV$I&(Fg$#Hh+QGAl2j z$k!+`$2}~~xG=|~!Y9)_F`%qCxs)s1)xt5rF{{F&$TToD+oZzLu`tlT%q*-bFWn&3 zBOtWgHP0Z_U)wy%)4YJk>crwKT;j#LvW4J0-HBz%enf!oSGPH#pcYxGKXeEGIarsw65su)wr3IK(Z* zB%q`;sa`ugr7WE*%-zYS$TYmzJSELrKhr%pxWvOL%g{e5r_wCNB{ehAC(SwE)4S5N z$~mH{B%<6s!z(y1*(9vOJJ2vA)!(^_%he@6(y6e}CEctnExRNqJ-E!>A}u(@IoUfh zDKs)r+r=a}$uGpK&@3s-FDJrPzdTDnB+@7~sXi#nI3uGpIE72w#K6Tk(X_zbBhT3& zDI+^M+a=uFOWVi8Fv-WqG}zNS$*jb}+#lYC?Yo_ zD>>XO$igrrqnN8=^2(0S+2(V1&X!r0aOlLf)4z3%nh&=Je@|Mq@7luFD-%|nYk8?& zsGNW148OeLVkL$6d5$L+#M~_3^XyRd*6(x5l}0QyKWFOytw~s)!67n#^Br47r7}~k^7M?EOD&8;Ub(MgXx_Mri%G-SC$=X; zYqpuUNZ^g{8NAa@&&k#Ay#BxM*pI6hlg^e|y3`lm|JhqGt#Qv`bCLG>uCH4|_HE;J z*%fwVX7T#}`y2K?J$=o_Wal2A^qs|L9^SopGNt?4Y$x;o7Au!+om4Lyk@)+m+P8-7 zS&d>=g#jf?#3!@(o_Ld-u)OraqaSPY_Fnz}Z_zDT`?WZQsY1%W3OfsQ1|U`TN$=vcjEQ8-4Bhp6IgZt^UcY%5{5cy1`#p&pp$497{?q z*2exboxW~Ya{mN)rF*xVv(wY@Y^IX9nsdTAvsGnG=bkOneb>)9W9IgyM++N| mI;@d<%o+XsVa)sR^^do3)P65EU%Wy8)sLvNkF`(Px&i=D*5aA~ delta 1056 zcmeC<+{rOPqdwQr$1*kFJJZ*!#JJ4TIKy$*{!HGR(Ei&9Th8 zthmD8xv)4OJ*pt2%qYCXA|>6=*@G*kATZN7C*LqTCom)`(cP&mydonsN8c~6$TYYx zDJ`ftB;C@_C!@&3CnYp6peWDJJw4Z;(%0MEwM;wDtllS|%PAsFJIg)4px8GxB{<5g zFgw66E3G6XJhI5i&(gv*F)uf~+%F{~C&f^^D&IRaJkl#8%r_{bz%RqH&@#Zef=k~t zKQk@ZEFiteBF!u*$u%g&BgE7qGuL0cD6^!>A|$E8$=}sEH_a?R$kfOr$;2ZkH_0Tz zI4Q!!wBFssAUJ}{JVQG;G}0_IIWIHZJK4j}xYQ{uC_7a@-?%W{$1^=D)5KdpDb={7 zA}PB{J0meMLO;>d!XwYzvoNF}q$<;kt2iY;q98xb)zQf%*|j`O-_)=$In*UH(A+XG zq%f?|sKl|bs4(BpFuN){qQc*z*e^IQ#5l^#vp&ewq`*HU(TFQ4+n_uo#Z14du*}KC z)2qlQ&?(5mJl!ZSzq~NqD?{70G$%(pC@agw&)g!Qz%Zc9GT6sC!@p8Lw6wr7ATol> zG~G2gEjZmIyeKuv$RkI)*e5KjD$+4LI4G>t*vl|2KPe^DE8DxQu+-5sH9x?_-z&s8 zqQ1f_)!D!(yU^S-jf+cHS69I|Gq*g?-z}-cIHJfUD#@oHtFSO6)Z05dqRiFAAS1~w z&DF^$ved62)srhP%rx(zRHUW*JmFbAFW5w{^Zq@Z@_v!!?>JYM&p)QdE!F+y|L=;z zwpHAHrZHA|UFB{@CzvMbuk!GjrKH$>O@8(9dbK5$`x=xq4s6~mzxPRT^ zo8RDnySzw9>SKo7#E+q$!zN9MsK_r+Ka{)vUvANf-{)=pE^5~QIdETj_4MM)22U@} zzMG>Lv{K`z#_PGqCd9HRFWZ*vEph$!=Y)qDs@3NlZf-jq`OD2k*_8M8|Da7}0cV9R zlF}Q~XT4utp8rp6!Q$4$M<-VQ?^t7a{gd+R6D@c1^3G3s)zlTA8W|n4O>Va9_id3y yuXB$YYBnUl{T*JB6Uuq~B9r77#VWJApPxG4_{`ojBji}upF?qT4tzK-ya@o|Nw_lr -- 2.51.2