@north-light/cli 0.3.566 → 0.3.568
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/contract.d.ts +1 -1
- package/dist/api/contract.js +1 -1
- package/dist/clients/attach/viewer.js +440 -440
- package/dist/core/config.js +1 -1
- package/dist/core/directory/issuer.d.ts +5 -0
- package/dist/core/directory/issuer.js +1 -0
- package/dist/core/graph/objects.d.ts +3 -0
- package/dist/core/graph/objects.js +8 -8
- package/dist/core/graph/reader.js +3 -3
- package/dist/core/ledger/charges.d.ts +2 -4
- package/dist/core/ledger/charges.js +1 -1
- package/dist/core/ledger/index.d.ts +1 -1
- package/dist/core/ledger/index.js +1 -1
- package/dist/core/ledger/infra-allowance.d.ts +0 -2
- package/dist/core/ledger/infra-allowance.js +1 -1
- package/dist/core/ledger/rates.d.ts +24 -0
- package/dist/core/ledger/rates.js +1 -0
- package/dist/core/ledger/read.d.ts +5 -2
- package/dist/core/ledger/read.js +2 -2
- package/dist/core/peer/client.js +1 -1
- package/dist/core/peer/directory.d.ts +0 -2
- package/dist/core/peer/directory.js +1 -1
- package/dist/core/peer/home.js +2 -2
- package/dist/core/providers/audit.d.ts +2 -0
- package/dist/core/providers/audit.js +2 -2
- package/dist/core/providers/bundles.js +2 -2
- package/dist/core/providers/call.js +1 -1
- package/dist/core/providers/mint.d.ts +1 -1
- package/dist/core/providers/mint.js +1 -1
- package/dist/core/runs/operations.d.ts +4 -0
- package/dist/core/runs/operations.js +7 -7
- package/dist/core/storage/client.js +2 -2
- package/dist/core/user-settings.d.ts +0 -4
- package/dist/core/user-settings.js +1 -1
- package/dist/daemon/api/app-listener.d.ts +8 -0
- package/dist/daemon/api/app-listener.js +13 -13
- package/dist/daemon/api/handlers/charges.js +1 -1
- package/dist/daemon/api/handlers/plugin-app-token.js +1 -1
- package/dist/daemon/api/handlers/providers.js +1 -1
- package/dist/daemon/api/handlers/runs.js +1 -1
- package/dist/daemon/api/handlers/transfer.js +1 -1
- package/dist/daemon/api/reader.js +1 -1
- package/dist/daemon/api/server.js +1 -1
- package/dist/daemon/cron/authority.js +1 -1
- package/dist/daemon/crtrd.js +10 -10
- package/dist/daemon/peer/relay-service.js +1 -1
- package/dist/daemon/readiness.d.ts +2 -1
- package/dist/daemon/readiness.js +1 -1
- package/dist/daemon/reconcilers/ledger-r2.js +5 -5
- package/dist/daemon/reconcilers/ledger-sandbox.d.ts +0 -1
- package/dist/daemon/reconcilers/ledger-sandbox.js +4 -4
- package/dist/daemon/reconcilers/ledger-storage.js +3 -3
- package/dist/types.d.ts +0 -16
- package/package.json +2 -2
- package/packages/crouter-identity/package.json +1 -1
- package/runtime.lock.json +13 -13
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
var Q=Object.defineProperty;var
|
|
2
|
-
data: ${JSON.stringify(
|
|
1
|
+
var Q=Object.defineProperty;var i=(e,n)=>Q(e,"name",{value:n,configurable:!0});import{AsyncResource as W}from"node:async_hooks";import{randomUUID as q}from"node:crypto";import{createServer as K}from"node:http";import{Router as V,causedByOf as Z}from"./router.js";import{toErrorBody as ee}from"./map.js";import{objectRoutes as te}from"./handlers/objects.js";import{customObjectRoutes as ne}from"./handlers/custom-objects.js";import{checkRoutes as re}from"./handlers/check.js";import{chargeRoutes as ae}from"./handlers/charges.js";import{docRoutes as oe}from"./handlers/docs.js";import{relationRoutes as ie}from"./handlers/relations.js";import{schemaRoutes as se}from"./handlers/schemas.js";import{OPERATIONS as ue}from"./operations.js";import{runtimeReadiness as de}from"../readiness.js";import{errorCodes as X}from"../../api/error-codes.js";import{MINIMUM_RUNTIME_VERSION_HEADER as ce,RUNTIME_VERSION_HEADER as le,minimumRuntimeRefusal as me}from"../../api/runtime-version.js";import{CONTRACT_HEADER as fe,CONTRACT_LEVEL as $,REQUIRED_CONTRACT_HEADER as pe,contractRefusal as he}from"../../api/contract.js";import{crtrVersion as j}from"../../shared/crtr-version.js";import{newTraceId as we,parseTraceparent as ye}from"../../shared/traceparent.js";import{AppPrincipalResolver as _e}from"./principal.js";import{isDaemonRoute as ge,runtimeOwner as ve,servePeer as z}from"../peer/ingress.js";import{applySyncNotice as Re}from"./sync-notice.js";import{ownMachineId as Oe}from"../../core/peer/directory.js";import{handleRunOperation as be,integer as Ee}from"./handlers/runs.js";import{llmCallerOf as Ae,parseLlmRequest as Se,runLlm as Te}from"../../core/llm/run.js";import{parseUsageMonth as Ne,usageFor as Ce}from"../../core/ledger/index.js";import{capFields as Ie}from"./handlers/llm.js";import{CONTROL_BODY_MAX_BYTES as Pe,MODEL_CONTEXT_BODY_MAX_BYTES as ke}from"../../core/llm/body-limits.js";import{RunError as m,cloudPersonScope as He,runIsRunning as Me}from"../../core/runs/operations.js";import{requireRun as J}from"./router.js";import{deferHead as De}from"./deferred-head.js";import{readRunEvents as G,registerGrantStream as xe,subscribeRunEvents as Be}from"../../core/runs/events.js";import{activeGrant as Y,payerOfGrant as je}from"../../core/grants/mirror.js";async function Je(e){if(await je(e)==="app")throw new m(401,"grant_revoked","this app-paid grant is no longer active");return null}i(Je,"appPaidGone");import{releaseGrantWaiters as Le}from"../../core/grants/watch.js";import{emitEvent as Ue}from"../../core/events/emit.js";import{runNotices as Ve}from"../run-notices.js";import{handleVendorSignIn as Xe,isVendorSignInPath as $e}from"./vendor-signin.js";import{listAppProfiles as ze}from"./handlers/app-profiles.js";import{handleTransferDownload as Ge,handleTransferOperation as Ye,TRANSFER_OPERATIONS as Fe}from"./handlers/transfer.js";import{handleQuestionOperation as Qe,QUESTION_OPERATIONS as We}from"./handlers/questions.js";import{removeVendorAccount as qe,vendorStatus as Ke}from"./handlers/vendor-status.js";import{handleMemoryOperation as Ze,MEMORY_OPERATIONS as et}from"./handlers/memory.js";import{EXEC_BODY_MAX_BYTES as tt,handleExec as nt}from"./handlers/exec.js";import{abortOnClose as F,callerFromApp as rt,handleProviderOperation as at,PROVIDER_OPERATIONS as ot,providerFailure as it}from"./handlers/providers.js";function st(e){return Object.prototype.hasOwnProperty.call(X,e)?X[e]:void 0}i(st,"fixedRow");function ut(e){const n=st(e);return n?n.type:e==="stream_gap"||e==="provider_error"||e==="runtime_version_unsupported"?"invalid_request_error":"server_error"}i(ut,"errorType");function dt(e){if(!e||typeof e!="object"||Array.isArray(e)||!("rate_limit"in e))return e;const{rate_limit:n,...o}=e;return o}i(dt,"appDetails");function B(e,n,o){const l=dt(e.details);return{error:{code:e.code,message:e.message,...l===void 0?{}:{details:l},type:ut(e.code),...e.param?{param:e.param}:{},origin:"runtime",retryable:e.retryable||e.code==="stream_dropped",request_id:n,...o?{run_id:o}:{},...e.scope?{scope:e.scope}:{},...e.code==="unauthorized"?{user_action:"reconnect"}:{},...Ie(e),...e.code==="all_routes_exhausted"?{retry_after_s:e.details.retry_after_s}:{}}}}i(B,"envelope");function ct(e,n,o,l,d){const w=n instanceof m?n:new m(500,"server_failure","runtime request failed");if(n instanceof m||console.error("[app-listener]",`trace_id=${l}`,n),e.headersSent&&!String(e.getHeader("Content-Type")??"").startsWith("text/event-stream")){e.destroy();return}if(e.headersSent){e.end(`event: error
|
|
2
|
+
data: ${JSON.stringify(B(w,o,d))}
|
|
3
3
|
|
|
4
|
-
`);return}e.writeHead(
|
|
4
|
+
`);return}e.writeHead(w.status,{"Content-Type":"application/json; charset=utf-8","Request-Id":o,"X-Content-Type-Options":"nosniff",...w.code==="all_routes_exhausted"?{"Retry-After":String(w.details.retry_after_s)}:{}}),e.end(JSON.stringify(B(w,o,d)))}i(ct,"fail");function L(e){return Array.isArray(e)?e[0]:e}i(L,"headerValue");function g(e,n,o){e.writeHead(n,{"Content-Type":"application/json; charset=utf-8"}),e.end(JSON.stringify(o))}i(g,"json");async function I(e,n=Pe){const o=[];let l=0;for await(const d of e){if(l+=d.length,l>n)throw new m(400,"invalid_request","request body too large");o.push(d)}if(l)try{return JSON.parse(Buffer.concat(o).toString("utf8"))}catch{throw new m(400,"invalid_request","invalid JSON body")}}i(I,"bodyOf");function lt(e,n){const o=e.headers["last-event-id"]??n.get("after");if(Array.isArray(o))throw new m(400,"invalid_request","invalid cursor","after");return Ee(o??null,"after",0,Number.MAX_SAFE_INTEGER,0)}i(lt,"cursor");function mt(e){return`id: ${e.sequence_number}
|
|
5
5
|
event: ${e.type}
|
|
6
6
|
data: ${JSON.stringify(e)}
|
|
7
7
|
|
|
8
|
-
`}
|
|
8
|
+
`}i(mt,"frame");const ft=6e4;async function pt(e,n,o,l,d,w,A,S={},r){await J(l,o);let t=await G(o,d);if(d>t.latest_sequence)throw new m(400,"invalid_request","cursor is beyond the run","after");if(d<t.latest_sequence&&(t.earliest_sequence===null||d<t.earliest_sequence-1))throw new m(409,"stream_gap","events have expired",void 0,{earliest_sequence:t.earliest_sequence,latest_sequence:t.latest_sequence});if(n.destroyed)return n.destroy(),Promise.resolve();n.writeHead(200,{"Content-Type":A==="sse"?"text/event-stream":"application/x-ndjson","Cache-Control":"no-cache","X-Accel-Buffering":"no"}),A==="sse"?n.write(`: connected
|
|
9
9
|
|
|
10
|
-
`):n.flushHeaders();let
|
|
11
|
-
data: ${JSON.stringify(
|
|
10
|
+
`):n.flushHeaders();let p=d;const y=await Ve().streamOpened(o);let v=!1,T=!1,N=!1,O;const h=new Promise(f=>{O=f}),R=i(()=>{v||(v=!0,y(p).catch(f=>console.error("[app-listener]",...r===void 0?[]:[`trace_id=${r}`],f)),clearInterval(x),clearInterval(H),C(),u(),n.off("close",R),n.off("drain",a),n.end(),O())},"end"),a=i(()=>{N=!1,b()},"onDrain"),M=i(f=>{v||n.write(A==="sse"?`event: error
|
|
11
|
+
data: ${JSON.stringify(B(f,w,o))}
|
|
12
12
|
|
|
13
|
-
`:`${JSON.stringify({type:"error",...
|
|
14
|
-
`),
|
|
15
|
-
`),
|
|
13
|
+
`:`${JSON.stringify({type:"error",...B(f,w,o)})}
|
|
14
|
+
`),R()},"error"),b=i(async()=>{if(!(v||T)){T=!0;try{if(!await D()){P();return}if(await J(l,o),t=await G(o,p),t.backlog_count>1e3||t.backlog_bytes>32*1024*1024){M(new m(503,"stream_dropped","stream reader fell behind",void 0,{last_sequence:p}));return}for(const f of t.events){if(N)break;N=!n.write(A==="sse"?mt(f):`${JSON.stringify(f)}
|
|
15
|
+
`),p=f.sequence_number}}catch(f){M(f instanceof m?f:new m(500,"server_failure","stream failed"))}finally{T=!1}}},"flush"),P=i(()=>M(new m(401,"grant_revoked","grant is not active")),"revoked"),D=i(async()=>"class"in l||await Y(l.grant)!==null,"grantActive"),C=await Be(o,W.bind(b)),u="class"in l?()=>{}:xe(l.grant,P),x=setInterval(()=>{!v&&!N&&A==="sse"&&n.write(`: keepalive
|
|
16
16
|
|
|
17
|
-
`)},15e3),
|
|
17
|
+
`)},15e3),s=S.idleMs??ft,_=S.isRunning??Me;let c=Date.now(),E=p;const k=i(async()=>{if(v||A!=="sse")return;const f=Date.now();let U=!0;try{U=await _(o)}catch{}if(!v){if(U||p!==E){c=f,E=p;return}f-c<s||N||(n.write(`event: idle
|
|
18
18
|
data: {}
|
|
19
19
|
|
|
20
|
-
`),
|
|
20
|
+
`),R())}},"checkIdle"),H=setInterval(()=>{k().catch(f=>Ue({level:"error",event:"api.run_stream.idle_check_failed",error:f}))},S.idleCheckMs??1e3);return H.unref(),n.on("drain",a),n.on("close",R),await b(),h}i(pt,"streamRunEvents");function ht(e,n,o,l={}){const d=new V,w=new Map;for(const r of ue.filter(t=>t.stage!==void 0)){const t=i(()=>({status:500}),"handler");d.register({method:r.method,pattern:r.path,handler:t}),w.set(t,r)}const A=new V().registerAll(te).registerAll(ne).registerAll(oe).registerAll(se).registerAll(ie).registerAll(re).registerAll(ae);return i((r,t,p)=>(async()=>{De(r,t,l.deferHead);const y=q();t.setHeader("Request-Id",y);const v=ye(L(r.headers.traceparent))??we();t.setHeader(le,j()),t.setHeader(fe,$);let T;try{const N=L(r.headers[ce.toLowerCase()]),O=me(N,j())??he(L(r.headers[pe.toLowerCase()]),$,{legacyMinimum:N,runtimeVersion:j()});if(O!==null)throw O.status===400?new m(400,O.code,O.message,O.param):new m(426,O.code,O.message,void 0,O.details);const h=new URL(r.url??"/","http://runtime.local");if($e(h.pathname)){await Xe(r,t,h,e);return}const R=d.match(r.method??"GET",h.pathname),a=R?w.get(R.handler):void 0,M=a?.name==="runtime.sync-notice"||a?.name==="runtime.vendor-status"||a?.name==="runtime.vendor-account-remove";let b,P;if(p!==void 0)b=p;else if(!M&&r.headers.authorization!==void 0)try{b=await e.verifyCall(r.headers.authorization)}catch(s){P=s}const D={issuer:e.issuer,jwks:e.jwks,audience:i(async()=>e.audience,"audience"),owner:ve,self:Oe,syncGrants:o,ready:i(async()=>e.isReady()&&await n(),"ready")};if(b?.chain[0]?.sub.startsWith("runtime:")){await z(r,t,D,b);return}if(b===void 0&&a===void 0&&await ge(r.method??"GET",h.pathname)){await z(r,t,D,{status:401,code:"unauthorized",message:P===void 0?"a machine token is required":"invalid machine token"});return}if(a?.name==="ready"){const s=await n(),_=await de({jwksReady:e.isReady(),grantsReady:i(()=>s,"grantsReady")});g(t,_.ready?200:503,_);return}if((r.method!=="GET"||h.pathname!=="/v1/health")&&(!e.isReady()||!await n()))throw new m(503,"runtime_starting","runtime_starting");if(!R||!a)throw new m(404,"not_found","unknown operation");T=R.params.run_id;const C=Z(r.headers);if(a.name==="health"){g(t,200,{status:"ok",api_version:"2026-09-23"});return}if(a.name==="runtime.sync-notice"){await Re(await e.verifySyncNotice(r.headers.authorization),o,y),t.writeHead(204),t.end();return}if(a.name==="runtime.vendor-status"){await e.verifyDirectoryRead(r.headers.authorization,"vendor_status"),g(t,200,await Ke());return}if(a.name==="runtime.vendor-account-remove"){await e.verifyDirectoryRead(r.headers.authorization,"vendor_account_remove"),g(t,200,await qe(await I(r)));return}if(b===void 0)throw P??new m(401,"unauthorized","a directory access token is required");const u=await e.resolveVerified(b,a.scope);if(t.setHeader("Request-Id",y),T&&await J(u,T,["run.message","run.interrupt","run.cancel","run.rename","run.delete"].includes(a.name),a.name==="run.delete"),a.stage==="objects"){const s=A.match(a.method,h.pathname);if(!s)throw new m(404,"not_found","unknown operation");const _={...C===void 0?{}:{causedBy:C},method:a.method,path:h.pathname,params:s.params,query:h.searchParams,body:await I(r,s.maxBodyBytes),ceiling:u.resolved,principal:{class:"app",app:u.grantee,scopes:u.resolved,sub:u.sub},req:r,res:t};let c;try{c=await s.handler(_)}catch(E){const{status:k,body:H}=ee(E);throw k>=500&&console.error("[app-listener]",`trace_id=${v}`,E),new m(k,H.error.code,H.error.message,void 0,H.error.details)}if(t.headersSent)return;if(c.rawBody!==void 0||c.status===204||c.body===void 0){t.writeHead(c.status,c.headers??{}),t.end(c.rawBody);return}t.writeHead(c.status,{"Content-Type":"application/json; charset=utf-8",...c.headers??{}}),t.end(JSON.stringify(c.body));return}if(a.stream==="bytes"){await Ge(r,t,u,h.searchParams);return}if(a.stream){await pt(r,t,T,u,lt(r,h.searchParams),y,"sse",l.stream,v);return}if(a.name==="llm"){const s=Se(await I(r,ke)),_=new AbortController,c=i(()=>_.abort(),"abort");t.on("close",c);try{const E=await Te(s,_.signal,s.stream?k=>{t.headersSent||t.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache","X-Accel-Buffering":"no"}),t.write(`data: ${JSON.stringify(k)}
|
|
21
21
|
|
|
22
|
-
`)}:void 0,void 0,{grantee:u.grantee,sub:u.sub,spend_cap:u.spend_cap,request:y},Ae(await Y(u.grant)??await
|
|
22
|
+
`)}:void 0,void 0,{grantee:u.grantee,sub:u.sub,spend_cap:u.spend_cap,request:y},Ae(await Y(u.grant)??await Je(u.grant)),C);s.stream?(t.headersSent||t.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache","X-Accel-Buffering":"no"}),t.end(`data: [DONE]
|
|
23
23
|
|
|
24
|
-
`)):g(t,200,
|
|
24
|
+
`)):g(t,200,E.completion)}finally{t.off("close",c)}return}if(a.name==="exec"){const{signal:s,release:_}=F(t);try{g(t,200,await nt(u,await I(r,tt),s))}finally{_()}return}if(a.name==="usage.get"){g(t,200,await Ce(u.grantee,Ne(h.searchParams.get("month")),He(u.sub)));return}if(a.name==="profile.list"){g(t,200,await ze(u));return}if(We.has(a.name)){const s=await Qe(a.name,u,R.params.question_id,a.method==="POST"?await I(r):void 0);g(t,s.status,s.body);return}if(ot.has(a.name)){const{signal:s,release:_}=F(t);try{const c=await at(a.name,rt(u),{params:R.params,body:a.method==="POST"?await I(r):void 0,query:h.searchParams},{requestId:y,traceId:v,signal:s,...C===void 0?{}:{causedBy:C}});g(t,c.status,c.body)}catch(c){const E=it(c,y,!0);t.writeHead(E.status,{"Content-Type":"application/json; charset=utf-8","X-Content-Type-Options":"nosniff",...E.headers}),t.end(JSON.stringify(E.body))}finally{_()}return}if(et.has(a.name)){const s=await Ze(a.name,{class:"app",app:u.grantee,scopes:u.resolved},h.searchParams);g(t,s.status,s.body);return}if(Fe.has(a.name)){const s=await Ye(a,u,R.params,h.searchParams,await I(r));g(t,s.status,s.body);return}const x=await be(a,u,T,h.searchParams,await I(r),r.headers["idempotency-key"],C);g(t,x.status,x.body)}catch(N){ct(t,N,y,v,T)}})(),"handle")}i(ht,"createAppRequestHandler");async function un(e,n,o,l={}){const d=e.listener;if(!e.issuer||!e.audience||!d?.address||!Number.isInteger(d.port)||d.port<1||d.port>65535)throw new Error("runtime issuer, audience and listener address/port are required");if(["0.0.0.0","::","[::]"].includes(d.address))throw new Error("runtime listener must bind a specific address");const w=new _e(e.issuer,e.audience,o,e.jwksUrl),A=ht(w,n,o,l),S=K((t,p)=>{A(t,p)});return{ready:new Promise((t,p)=>{S.once("error",p),S.listen(d.port,d.address,()=>{S.off("error",p),t()})}),close:i(async()=>{w.close(),Le(),S.closeAllConnections(),await new Promise((t,p)=>S.close(y=>y?p(y):t()))},"close")}}i(un,"createAppListener");export{ft as RUN_STREAM_IDLE_MS,un as createAppListener,ht as createAppRequestHandler,lt as cursor,pt as streamRunEvents};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var _=Object.defineProperty;var s=(n,e)=>_(n,"name",{value:e,configurable:!0});import{ApiError as p}from"../../../api/errors.js";import{personIdAsync as $}from"../../../core/canvas/person.js";import{assertReference as q,deleteLimit as R,listCharges as E,listLimits as w,monthTotals as L,parseUsageMonth as O,upsertLimit as T}from"../../../core/ledger/index.js";import{payersOf as b}from"../../../core/ledger/read.js";import{integer as N}from"./runs.js";import{invalidRequest as
|
|
1
|
+
var _=Object.defineProperty;var s=(n,e)=>_(n,"name",{value:e,configurable:!0});import{ApiError as p}from"../../../api/errors.js";import{personIdAsync as $}from"../../../core/canvas/person.js";import{assertReference as q,deleteLimit as R,listCharges as E,listLimits as w,monthTotals as L,parseUsageMonth as O,upsertLimit as T}from"../../../core/ledger/index.js";import{payersOf as b}from"../../../core/ledger/read.js";import{integer as N}from"./runs.js";import{cloudPersonScope as P}from"../../../core/runs/operations.js";import{invalidRequest as S,objectBody as W}from"./validate.js";function k(n){const{principal:e}=n;if(e.class==="app"||e.class==="broker"){const r=P(e.sub);return r===void 0?{app:e.app}:{app:e.app,sub:r}}if(e.class==="person")return e.sub===void 0?void 0:{person:e.sub};throw new p(403,"owner_only","charges are read by the person, a node or an app")}s(k,"readerOf");async function F(n){const e=k(n),r=n.query.get("under"),t=n.query.get("after"),o=n.query.get("month"),i=r===null||o!==null?O(o):void 0,{charges:a,next:d}=await E({...i===void 0?{}:{month:i},...e===void 0?{}:{reader:e},...r===null?{}:{under:q(r)},...t===null?{}:{after:t},limit:N(n.query.get("limit"),"limit",1,1e4,1e3)}),f=r!==null||e!==void 0&&!("person"in e)?void 0:await L(i,e===void 0?void 0:e.person);return{...i===void 0?{}:{month:i},charges:a,next:d,...f===void 0?{}:{totals:f}}}s(F,"listRoute");const g=["bill","subscription","key","endpoint","take","legacy"],l="person:";function m(n){const{principal:e}=n;if(e.class!=="person")throw new p(403,"owner_only","spend limits are set by a person");return e.sub===void 0?void 0:e.sub.startsWith("user:")?e.sub:`user:${e.sub}`}s(m,"limitOwner");function v(n,e){const r=n.params.id??"";if(!r.startsWith(l)||r.length===l.length||r.length>128)throw new p(400,"invalid_request",`a person limit id starts with \`${l}\`; received ${r}`,{violations:[{field:"id",problem:`must start with ${l}`,received:r}]});if(e===void 0)return r;const t=r.slice(l.length);if(t.includes("/"))throw new p(400,"invalid_request","a person limit name has no `/`",{violations:[{field:"id",problem:"must not contain /",received:r}]});return`${l}${e.slice(5)}/${t}`}s(v,"idOf");function c(n,e,r){const t=n[e];if(t==null)return t;if(typeof t!="string"||t===""){r.push({field:e,problem:"must be a non-empty string or null",received:t});return}return t}s(c,"nullableString");async function G(n){const e=m(n),r=v(n,e),t=[],o=W(n.body,["payer","usd_per_month","funding","grantee","provider","sub"],t),i=o.payer;(typeof i!="string"||!/^(user|app):.+/.test(i))&&t.push({field:"payer",problem:"must be user:<id> or app:<id>",...i===void 0?{}:{received:i}});const a=o.usd_per_month;(typeof a!="number"||!Number.isFinite(a)||a<0)&&t.push({field:"usd_per_month",problem:"must be a number of at least 0",...a===void 0?{}:{received:a}});const d=c(o,"funding",t);typeof d=="string"&&!g.includes(d)&&t.push({field:"funding",problem:`must be one of ${g.join(", ")}`,received:d});const f=c(o,"grantee",t),y=c(o,"provider",t),h=c(o,"sub",t);t.length>0&&S("spend limit request",t);const u=o;if(e===void 0){if(u.payer.startsWith("user:")&&u.payer!==await $())throw new p(403,"owner_only","a person sets limits only on their own payer or on an app",{payer:u.payer})}else if(!(await b(e)).includes(u.payer))throw new p(403,"owner_only","a person sets limits only on their own payer or on an app they hold",{payer:u.payer});return await T({id:r,payer:u.payer,usd_per_month:u.usd_per_month,source:"person",...d===void 0?{}:{funding:d},...f===void 0?{}:{grantee:f},...y===void 0?{}:{provider:y},...h===void 0?{}:{sub:h}})}s(G,"setRoute");async function I(n){const e=m(n),r=await w();if(e===void 0)return{limits:r};const t=new Set(await b(e)),o=`${l}${e.slice(5)}/`;return{limits:r.filter(i=>i.id.startsWith(o)||i.payer!==null&&t.has(i.payer)||i.account===e)}}s(I,"listLimitsRoute");async function U(n){const e=v(n,m(n));if((await w({source:"person"})).find(t=>t.id===e)===void 0||!await R(e))throw new p(404,"not_found",`no person limit ${e}`);return{id:e,removed:!0}}s(U,"removeRoute");const H=[{method:"GET",pattern:"/v1/charges",handler:s(async n=>({status:200,body:await F(n)}),"handler")}],J=[{method:"GET",pattern:"/v1/spend-limits",handler:s(async n=>({status:200,body:await I(n)}),"handler")},{method:"PUT",pattern:"/v1/spend-limits/:id",handler:s(async n=>({status:200,body:await G(n)}),"handler")},{method:"DELETE",pattern:"/v1/spend-limits/:id",handler:s(async n=>({status:200,body:await U(n)}),"handler")}];export{H as chargeRoutes,J as spendLimitRoutes};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var h=Object.defineProperty;var o=(e,n)=>h(e,"name",{value:n,configurable:!0});import{ApiError as l}from"../../../api/errors.js";import{getNode as g}from"../../../core/canvas/canvas.js";import{formatCrtrCaller as y}from"../../../core/command-plugins/caller-header.js";import{isLoopbackHostname as w}from"../../../core/command-plugins/endpoint.js";import{crtrSignature as _}from"../../../core/command-plugins/transport/sign.js";import{
|
|
1
|
+
var h=Object.defineProperty;var o=(e,n)=>h(e,"name",{value:n,configurable:!0});import{ApiError as l}from"../../../api/errors.js";import{getNode as g}from"../../../core/canvas/canvas.js";import{formatCrtrCaller as y}from"../../../core/command-plugins/caller-header.js";import{isLoopbackHostname as w}from"../../../core/command-plugins/endpoint.js";import{crtrSignature as _}from"../../../core/command-plugins/transport/sign.js";import{ownMachineId as k}from"../../../core/peer/directory.js";import{directoryIssuer as b}from"../../../core/directory/issuer.js";import{pluginAppCredential as m}from"../../../core/plugin-app.js";import{findPluginByName as v}from"../../../core/resolver.js";import{isRecord as C}from"./validate.js";const c=/^[0-9a-f]{64}$/,p=o(e=>{throw new l(404,"not_found",`plugin "${e}" is not installed, enabled and valid`)},"notFound");function A(e){const{principal:n}=e;if(n.class==="broker"&&n.uid!==process.getuid?.())throw new l(403,"forbidden","this node may not read a plugin app token");const r=e.params.name,t=m(r);return t===null?p(r):{status:200,body:{token:t.token,socket:t.socket}}}o(A,"appToken");function R(e){const n=o(i=>{throw new l(400,"invalid_request",`invalid ${i}`)},"bad");if(!C(e))return n("call-headers request");const{method:r,url:t,body_sha256:s,header_names:d,headers_sha256:a}=e;return(typeof r!="string"||r==="")&&n("method"),typeof t!="string"&&n("url"),(typeof s!="string"||!c.test(s))&&n("body_sha256"),(!Array.isArray(d)||d.some(i=>typeof i!="string"))&&n("header_names"),(typeof a!="string"||!c.test(a))&&n("headers_sha256"),e}o(R,"parseRequest");async function E(e){if(e.class==="forwarded"){const r=e.actor.kind==="app"?e.actor:null;return{node:r?.node??void 0,run:r?.place.run,machine:e.via}}const n=e.class==="broker"?e.node:void 0;return{...n===void 0?{}:{node:n,run:e.class==="broker"?e.run??void 0:void 0,profile:(await g(n))?.profile_id??void 0},machine:b()!==null?k():void 0}}o(E,"callerFields");async function H(e,n,r){const t=v(e);if(t===null||!t.enabled||t.manifest.provider!==void 0)return p(e);const s=y(await E(n)),d={};s!==""&&(d["Crtr-Caller"]=s);const a=m(e);if(a!==null&&a.endpoint!==null){let i;try{i=new URL(r.url)}catch{throw new l(400,"invalid_request","invalid url")}const u=new URL(a.endpoint);if(i.origin===u.origin&&w(u.hostname))try{d["Crtr-Signature"]=_({token:a.token,method:r.method,url:i,body_sha256:r.body_sha256,caller:s,header_names:r.header_names,headers_sha256:r.headers_sha256,now:Date.now()})}catch(f){throw new l(400,"invalid_request",f instanceof Error?f.message:"invalid signed header list")}}return{headers:d}}o(H,"signCallHeaders");async function L(e){return{status:200,body:await H(e.params.name,e.principal,R(e.body))}}o(L,"callHeaders");const G=[{method:"GET",pattern:"/v1/plugins/:name/app-token",handler:A},{method:"POST",pattern:"/v1/plugins/:name/call-headers",handler:L}];export{G as pluginAppRoutes,H as signCallHeaders};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var I=Object.defineProperty;var s=(e,r)=>I(e,"name",{value:r,configurable:!0});import{randomUUID as R}from"node:crypto";import{cloudPersonScope as $}from"../../../core/runs/operations.js";import{directoryIssuer as O}from"../../../core/directory/issuer.js";import{activeGrantForApp as q,grantFor as G,localGrants as _}from"../../../core/grants/mirror.js";import{getNode as N}from"../../../core/canvas/canvas.js";import{scopeAllowed as T}from"../../../core/scopes.js";import{ProviderError as f,providerErrorBody as F,scopeMissing as x}from"../../../core/providers/errors.js";import{callProvider as j,providerTools as k}from"../../../core/providers/call.js";import{providerIdsFromGrants as C,providerInstallState as B}from"../../../core/providers/bundles.js";import{providerRootClaims as D,resolveProviderRef as M}from"../../../core/providers/roots.js";import{listInstalledPlugins as U}from"../../../core/resolver.js";import{listAudit as z,writeProviderAudit as L}from"../../../core/providers/audit.js";import{emitEvent as g}from"../../../core/events/emit.js";import{resolvedScopes as y}from"../router.js";const _e=new Set(["provider.tools","provider.call","audit.list"]);async function V(e){if(e.class==="forwarded"){if(e.actor.kind==="person")return{class:"person",sub:null,grantee:null,client_id:null,resolved:null,nodeScopes:null,run_id:null,node_id:null,origin:{node:null,run:null,machine:e.via}};const r=await G(e.actor.app,e.sub);if(!r)throw new f("grant_revoked",`app ${e.actor.app} has no active grant`);return{class:"app",sub:e.sub,grantee:e.actor.app,client_id:null,resolved:r.resolved,nodeScopes:e.actor.node_scopes,run_id:null,node_id:null,origin:{node:e.actor.node,run:e.actor.place?.run??null,machine:e.via}}}if(e.class==="machine")throw new f("permission_error","this operation is not available to the caller");if(e.class==="person"&&e.sub!==void 0)throw new f("permission_error","provider calls are made by the install's person, a node or an app");if(e.class==="person")return{class:"person",sub:null,grantee:null,client_id:null,resolved:null,nodeScopes:null,run_id:null,node_id:null};if(e.class==="app"){const r=await q(e.app);if(!r)throw new f("grant_revoked",`app ${e.app} has no active grant`);return{class:"app",sub:r.sub,grantee:e.app,client_id:null,resolved:r.resolved,nodeScopes:e.scopes,run_id:null,node_id:null}}return e.class==="cron"?{class:"app",sub:e.sub,grantee:e.app,client_id:null,resolved:await y(e),nodeScopes:e.scopes,run_id:e.origin_run,node_id:null}:{class:"broker",sub:e.sub,grantee:e.app,client_id:e.client_id,resolved:await y(e),nodeScopes:e.scopes,run_id:e.run??(await N(e.node))?.run_id??null,node_id:e.node}}s(V,"callerFromRequest");function ge(e){return{class:"app",sub:e.sub,grantee:e.grantee,client_id:e.client_id,resolved:e.resolved,nodeScopes:null,run_id:null,node_id:null}}s(ge,"callerFromApp");const Z=/^([A-Za-z0-9_-]{1,64}):([A-Za-z0-9_-]{1,64})$/;function W(e){const r=Z.exec(e);return r!==null&&r[1]!=="crtr"}s(W,"isProviderScope");const S=new WeakMap;function J(e){let r=S.get(e);return r===void 0&&(r=new Set(e),S.set(e,r)),r}s(J,"heldSet");function A(e,r){return e===null?!0:W(r)?J(e).has(r):T(e,r)}s(A,"holds");function P(e,r){return e.class==="person"?!0:A(e.resolved??[],r)&&A(e.nodeScopes,r)}s(P,"callerAllows");function ye(e,r,t){const o=`${r}:${t}`;if(!P(e,o))throw x(o)}s(ye,"requireGroup");function X(){return!!O()}s(X,"providerOperationsEnabled");const H=/^[A-Za-z0-9_-]{1,64}$/;function m(e,r){return new f("invalid_request",e,{param:r})}s(m,"invalid");function E(e){if(typeof e!="string"||!H.test(e)||e==="crtr")throw m("provider must be a provider id","provider");return e}s(E,"parseProvider");function K(e){if(!e||typeof e!="object"||Array.isArray(e))throw new f("invalid_request","a JSON object is required");const r=e,t=E(r.provider),o=r.tool;if(typeof o!="string"||!o.trim())throw m("tool must be a non-empty string","tool");const i=r.arguments??{};if(!i||typeof i!="object"||Array.isArray(i))throw m("arguments must be an object","arguments");const d=r.version;if(d!==void 0&&(typeof d!="number"||!Number.isInteger(d)||d<1))throw m("version must be an integer >= 1","version");const a=r.approval;if(a!==void 0&&(typeof a!="string"||!a))throw m("approval must be a question id","approval");const l=r.machine;if(l!==void 0&&(typeof l!="string"||!l.trim()))throw m("machine must be a machine id","machine");return{provider:t,tool:o.trim(),arguments:i,...d===void 0?{}:{version:d},...a===void 0?{}:{approval:a},...l===void 0?{}:{machine:l.trim()}}}s(K,"parseCallInput");async function Q(e,r=new URLSearchParams){const t=s((u,v,w)=>{const c=r.get(u);if(c===null)return v;if(!/^\d+$/.test(c)||Number(c)>w||Number(c)<1)throw m(`invalid ${u}`,u);return Number(c)},"numeric"),o=r.has("after")?t("after",0,Number.MAX_SAFE_INTEGER):void 0,i=t("limit",100,1e3),d=Object.fromEntries(["operation","outcome","run_id","since","until"].filter(u=>r.has(u)).map(u=>[u,r.get(u)])),a=$(e.sub),l=a===void 0?{}:{sub:a};return{status:200,body:await z(e.class==="person"?null:e.grantee,{after:o,limit:i,...l,...d})}}s(Q,"auditList");async function Y(e,r,t){let o=r;const i=performance.now(),d=U("user"),{skipped:a}=D(d),l=new Set(d.filter(n=>n.enabled&&n.manifest.provider?.id===n.name&&!a.has(n.name)).map(n=>n.name)),u=C(await _()).filter(n=>!a.has(n)),v=[...new Set([...l,...u])].sort();if(o!==void 0){const n=M(o);if(n===null)throw new f("not_found",`provider "${o}" is not available`);o=n}if(o!==void 0&&!v.includes(o))throw new f("not_found",`provider "${o}" is not available`);const w=o===void 0?v:[o],c=e.class==="person"?(await _()).flatMap(n=>n.status==="active"?n.resolved_scopes.map(({scope:p})=>p):[]):e.resolved??[],h=await Promise.all(w.map(async n=>{if(l.has(n))return k(e,n);if(!c.some(b=>b.startsWith(`${n}:`)&&P(e,b)))return null;const p=B(n);return{provider:n,display_name:n,status:p.status,...p.error?{error:p.error}:{},groups:[],commands:[]}})).then(n=>n.filter(p=>p!==null));if(g({level:"debug",event:"api.provider.tools",duration_ms:performance.now()-i,fields:{caller:e.class,provider:o??null,providers:h.length}}),o!==void 0){if(h.length===0)throw new f("not_found",`provider "${o}" is not available`);return{status:200,body:h[0]}}return{status:200,body:{providers:h}}}s(Y,"providerTools");async function ee(e,r,t){return j(e,r,t)}s(ee,"providerCall");async function re(e,r,t,o){if(!X())throw new f("not_found","provider operations need a directory-connected runtime");if(e==="audit.list")return await Q(r,t.query);if(e==="provider.tools")return Y(r,t.params.provider===void 0?void 0:E(t.params.provider),o);if(e==="provider.call"){let i;try{i=K(t.body)}catch(d){const a=t.body&&typeof t.body=="object"&&!Array.isArray(t.body)?t.body:{};throw await L({request_id:o.requestId,caller:r,provider:typeof a.provider=="string"?a.provider:"",tool:typeof a.tool=="string"?a.tool:"",outcome:`refused:${d instanceof f?d.code:"invalid_request"}`}),d}return ee(r,i,o)}throw new f("not_found","unknown operation")}s(re,"handleProviderOperation");function oe(e){const r=new AbortController,t=s(()=>{e.writableFinished||r.abort()},"abort");return e.on("close",t),{signal:r.signal,release:s(()=>e.off("close",t),"release")}}s(oe,"abortOnClose");function te(e,r,t,o){const i=F(e,r,t,o??void 0);return i.status>=500&&!(e instanceof f)&&g({event:"api.provider.failed",level:"error",error:e instanceof Error?e:new Error(String(e)),fields:{request_id:r}}),i}s(te,"providerFailure");const Se=[{method:"GET",pattern:"/v1/audit",name:"audit.list"},{method:"GET",pattern:"/v1/providers/tools",name:"provider.tools"},{method:"GET",pattern:"/v1/providers/:provider/tools",name:"provider.tools"},{method:"POST",pattern:"/v1/provider/call",name:"provider.call"}].map(({method:e,pattern:r,name:t})=>({method:e,pattern:r,handler:s(async o=>{const i=R(),{signal:d,release:a}=oe(o.res);let l=null;try{return l=await V(o.principal),{...await re(t,l,{params:o.params,body:o.body,query:new URL(o.req.url??"/","http://runtime.local").searchParams},{requestId:i,signal:d,...o.causedBy===void 0?{}:{causedBy:o.causedBy}}),headers:{"Request-Id":i}}}catch(u){return te(u,i,!1,l?.run_id)}finally{a()}},"handler")}));export{_e as PROVIDER_OPERATIONS,oe as abortOnClose,P as callerAllows,ge as callerFromApp,V as callerFromRequest,re as handleProviderOperation,K as parseCallInput,E as parseProvider,te as providerFailure,X as providerOperationsEnabled,Se as providerRoutes,ye as requireGroup};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var S=Object.defineProperty;var c=(
|
|
1
|
+
var S=Object.defineProperty;var c=(a,t)=>S(a,"name",{value:t,configurable:!0});import{callerGrant as g}from"../principal.js";import{grantVersion as b,payerOfGrant as O}from"../../../core/grants/mirror.js";import{holdGrant as $}from"../../../core/grants/watch.js";import{RunError as n,idempotencyKeyOf as v,cancelRun as N,cloudPersonScope as A,deleteRun as j,interruptRun as x,listRuns as B,messageRun as J,renameRun as z,requestedScopes as D,startRun as E,traceRun as G,waitRun as K}from"../../../core/runs/operations.js";import{canReadRun as y,requireRun as w,runCallerApp as M}from"../router.js";import{waitSeconds as q}from"../long-poll-wait.js";import{outputSchemaProblem as P}from"../../../core/runtime/structured-output.js";function m(a){if(!a||typeof a!="object"||Array.isArray(a))throw new n(400,"invalid_request","a JSON object is required");return a}c(m,"object");function k(a,t,i,u,l){if(a===null)return l;if(!/^(0|[1-9]\d*)$/.test(a)||!Number.isSafeInteger(Number(a))||Number(a)<i||Number(a)>u)throw new n(400,"invalid_request",`invalid ${t}`,t);return Number(a)}c(k,"integer");const T=256*1024;async function Y(a,t,i,u,l,_,h){switch(a.name){case"grant.get":{if("class"in t)throw new n(403,"permission_error","an app token is required");const e=q("grant.get",u),s=u.get("since");if(s!==null&&!/^[A-Za-z0-9_-]{1,64}$/.test(s))throw new n(400,"invalid_request","invalid since","since");const d=e&&s!==null?$(t.grant):void 0;let o;try{if(o=await g(t),d){const f=Date.now()+e*1e3;for(;b(o)===s&&Date.now()<f;)await d.changed(Math.max(0,(f-Date.now())/1e3)),o=await g(t)}}finally{d?.release()}return{status:200,body:{sub:t.sub,grantee:t.grantee,client_id:t.client_id,grant:t.grant,rev:o.rev,resolved_scopes:o.resolved_scopes,spend_cap:o.spend_cap,exp:t.exp,payer:await O(t.grant),dependencies:o.dependencies??{},version:b(o)}}}case"run.start":{if("class"in t)throw new n(403,"permission_error","an app token is required");const e=m(l),s=["mode","parent","fork_from","node_id","env","tools","system_prompt"];for(const r of s)if(e[r]!==void 0)throw new n(403,"owner_only",`${r} is owner-only`,r);const d=["payer","model_policy","kind"];for(const r of d)if(e[r]!==void 0)throw new n(400,"invalid_request",`${r} is not available`,r);for(const r of Object.keys(e))if(!["prompt","scopes","metadata","profile","isolated","cwd","worktree","output_schema","message","model","deadline"].includes(r))throw new n(400,"invalid_request",`unknown field ${r}`,r);if(e.model!==void 0&&(typeof e.model!="string"||!e.model.trim()))throw new n(400,"invalid_request","model must be a non-empty string","model");if(e.deadline!==void 0&&(typeof e.deadline!="string"||!e.deadline.trim()))throw new n(400,"invalid_request","deadline must be a duration string such as 10m","deadline");if(e.profile!==void 0&&(typeof e.profile!="string"||!e.profile))throw new n(400,"invalid_request","profile must be a profile id","profile");if(e.isolated!==void 0&&typeof e.isolated!="boolean")throw new n(400,"invalid_request","isolated must be a boolean","isolated");if(e.cwd!==void 0&&(e.isolated!==!0||typeof e.cwd!="string"||!e.cwd))throw new n(400,"invalid_request","cwd is available only for an isolated run and must be an absolute path inside its root folder","cwd");if(e.worktree!==void 0&&e.isolated!==!0)throw new n(400,"invalid_request","worktree is not available","worktree");if(e.isolated===!0&&e.worktree!==void 0)throw new n(400,"invalid_request","worktree is unavailable for an isolated run","worktree");if(typeof e.prompt!="string"||!e.prompt.trim())throw new n(400,"invalid_request","prompt is required","prompt");if(e.message!==void 0&&(typeof e.message!="string"||!e.message.trim()))throw new n(400,"invalid_request","message must be a non-empty string","message");const o=e.metadata===void 0?{}:m(e.metadata);if(Buffer.byteLength(JSON.stringify(o))>4096)throw new n(400,"invalid_request","metadata exceeds 4 KB","metadata");let f;if(e.output_schema!==void 0){const r=e.output_schema;if(!r||typeof r!="object"||Array.isArray(r))throw new n(400,"invalid_request","output_schema must be a JSON Schema object","output_schema");if(Buffer.byteLength(JSON.stringify(r))>T)throw new n(400,"invalid_request","output_schema exceeds 256 KB","output_schema");const p=await P(r);if(p!==null)throw new n(400,"invalid_request",`output_schema is not usable: ${p}`,"output_schema");f=r}const R=D(t.resolved,e.scopes,t.grantee);return{status:201,body:await E(t,{prompt:e.prompt,scopes:R,metadata:o,profile:e.profile,isolated:e.isolated,cwd:e.cwd,...e.model===void 0?{}:{model:e.model},...e.deadline===void 0?{}:{deadline:e.deadline},...f===void 0?{}:{output_schema:f},...e.message===void 0?{}:{message:e.message},...h===void 0?{}:{causedBy:h}},v(_))}}case"run.list":{const e=u.get("status")??void 0;if(e&&!["running","waiting_on_user","idle","settled"].includes(e))throw new n(400,"invalid_request","invalid status","status");const s=u.get("app");if(s!==null&&!/^(?:app:)?[a-z0-9][a-z0-9-]*$/.test(s))throw new n(400,"invalid_request","invalid app","app");const d=s===null?M(t):s.startsWith("app:")?s:`app:${s}`;if(d!==null&&!await y(t,d))throw new n(404,"not_found","run not found");const o=A(t.sub);return{status:200,body:await B(d,{status:e,...o===void 0?{}:{sub:o},after:u.get("after")??void 0,limit:k(u.get("limit"),"limit",1,100,50),..."class"in t&&(t.class==="broker"||t.class==="cron")&&d!==null?{visible:c(async f=>await y(t,d,f),"visible")}:{}})}}case"run.get":{const e=q("run.get",u),s=await w(t,i),d=await K(i,s.grantee,e);return await w(t,i),{status:200,body:d}}case"run.message":{const e=m(l);if(typeof e.message!="string"||!e.message.trim())throw new n(400,"invalid_request","message is required","message");if(e.start_turn!==void 0&&typeof e.start_turn!="boolean")throw new n(400,"invalid_request","start_turn must be a boolean","start_turn");return{status:202,body:await J(await w(t,i,!0),e.message,void 0,e.start_turn,v(_))}}case"run.interrupt":{const e=m(l===void 0?{}:l);if(e.children!==void 0&&e.children!=="stop"&&e.children!=="continue")throw new n(400,"invalid_request","invalid children","children");return{status:200,body:await x(await w(t,i,!0),e.children)}}case"run.cancel":{const e=m(l===void 0?{}:l);if(e.keep_schedules!==void 0&&typeof e.keep_schedules!="boolean")throw new n(400,"invalid_request","invalid keep_schedules","keep_schedules");return{status:200,body:await N(await w(t,i,!0),{keepSchedules:e.keep_schedules})}}case"run.rename":{const e=m(l);for(const s of Object.keys(e))if(s!=="name")throw new n(400,"invalid_request",`unknown field ${s}`,s);return{status:200,body:await z(await w(t,i,!0),e.name)}}case"run.delete":{const{uploads_pending:e}=await j(await w(t,i,!0,!0));return{status:200,body:{run_id:i,uploads_pending:e}}}case"trace.get":{const e=u.get("format")??void 0;if(e&&e!=="entries")throw new n(400,"invalid_request","unknown trace format","format");const s=await w(t,i);return{status:200,body:await G(i,s.grantee,e)}}default:throw new n(404,"not_found","unknown operation")}}c(Y,"handleRunOperation");export{Y as handleRunOperation,k as integer};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var h=Object.defineProperty;var s=(e,a)=>h(e,"name",{value:a,configurable:!0});import{isAbsolute as m,resolve as _}from"node:path";import{isCloudRole as y}from"../../../core/canvas/person-state.js";import{RunError as r}from"../../../core/runs/operations.js";import{invalidStorageName as g,storageClient as p,StorageRefused as b,UPLOAD_MAX_BYTES as q}from"../../../core/storage/client.js";import{serveDownload as v}from"../../../core/storage/download.js";import{createShare as A,deleteOwnShare as S,listOwnShares as k}from"../../../core/storage/shares.js";import{getUpload as O,insertUpload as x,uploadUseAt as z}from"../../../core/storage/tables.js";import{requireRun as R}from"../router.js";const B=new Set(["upload.create","attachment.link","file.download","share.create","share.list","share.delete"]);function f(e){if(!e||typeof e!="object"||Array.isArray(e))throw new r(400,"invalid_request","a JSON object is required");return e}s(f,"object");function c(e){return{app:e.grantee,resolved:e.resolved,launched:null}}s(c,"fileCaller");const T=/^[A-Za-z0-9][A-Za-z0-9!#$&^_.+-]{0,126}\/[A-Za-z0-9][A-Za-z0-9!#$&^_.+-]{0,126}(?:\s*;.{0,200})?$/;async function D(e,a){const i=f(a);for(const l of Object.keys(i))if(!["name","media_type","size"].includes(l))throw new r(400,"invalid_request",`unknown field ${l}`,l);const{name:n,media_type:o,size:t}=i;if(typeof t!="number"||!Number.isSafeInteger(t)||t<0)throw new r(400,"invalid_request","size must be a non-negative integer","size");if(t>q)throw new r(400,"invalid_request","size exceeds 100 MiB","size");if(typeof n!="string")throw new r(400,"invalid_request","name is required","name");const d=g(n);if(d)throw new r(400,"invalid_request",d,"name");if(typeof o!="string"||!T.test(o))throw new r(400,"invalid_request","media_type must be a media type","media_type");const u=await p().createUpload({name:n,media_type:o,size:t});return await x({upload_id:u.upload_id,grantee:e.grantee,name:n,media_type:o,size:t,created_at:new Date().toISOString()}),{upload_id:u.upload_id,url:u.url,upload_link:u.upload_link,expires_at:u.expires_at}}s(D,"uploadCreate");async function E(e,a){if(!a)throw new r(400,"invalid_request","path is required","path");if(!m(a))throw new r(400,"invalid_request","path must be absolute","path");const i=await z(_(a)),n=s(()=>new r(404,"not_found","no upload is recorded at that path"),"missing");if(!i)throw n();try{await R(e,i.run_id)}catch(t){throw t instanceof r&&t.code==="not_found"?n():t}const o=await O(i.upload_id);if(!o||o.delete_pending_since)throw n();try{return await p().signDownload(i.upload_id)}catch(t){throw t instanceof b?n():t}}s(E,"attachmentLink");function w(e){if(y())throw new r(403,"permission_error",`${e} is not served by a cloud role: file transfer is not yet scoped to a person`)}s(w,"refuseOnCloudRole");async function L(e,a,i,n,o){switch(e.name!=="attachment.link"&&w(e.name),e.name){case"upload.create":return{status:201,body:await D(a,o)};case"attachment.link":return{status:200,body:await E(a,n.get("path"))};case"share.create":{const t=f(o);for(const d of Object.keys(t))if(!["path","expires_at"].includes(d))throw new r(400,"invalid_request",`unknown field ${d}`,d);return{status:201,body:await A(c(a),{path:t.path,expires_at:t.expires_at})}}case"share.list":return{status:200,body:await k(a.grantee)};case"share.delete":return{status:200,body:await S(a.grantee,i.share_id)};default:throw new r(404,"not_found","unknown operation")}}s(L,"handleTransferOperation");function Y(e,a,i,n){return w("file.download"),v(e,a,c(i),n.get("path"))}s(Y,"handleTransferDownload");export{B as TRANSFER_OPERATIONS,c as fileCaller,Y as handleTransferDownload,L as handleTransferOperation};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var R=Object.defineProperty;var
|
|
1
|
+
var R=Object.defineProperty;var p=(n,e)=>R(n,"name",{value:e,configurable:!0});import{ApiError as d}from"../../api/index.js";import{readerFor as N,warmNodeRepos as h}from"../../core/graph/reader.js";import{canRead as g}from"../../core/graph/access.js";import{ownersByHandle as y,resolveName as I,viewOf as x}from"../../core/graph/names.js";import{ensureOwner as F,ownerForGrantee as j,profileHandle as v}from"../../core/graph/objects.js";import{checkoutsForCwd as L,reposForCwd as O,warmCheckoutIdentities as A}from"../../core/graph/repo-sync/repos.js";import{lookupProfile as D}from"../../core/profiles/manifest.js";import{openDb as $}from"../../core/canvas/db.js";import{filterAsync as S,mapAsync as _}from"../../core/async-array.js";import{personId as b}from"../../core/canvas/person.js";async function Q(n,e){return await N(n,e.principal,async o=>await L(n,o))}p(Q,"readerFor");async function V(n,e){e!==void 0&&await A(e),n.class==="broker"&&await h(await $(),n.node)}p(V,"warmReaderRepos");async function X(n){const e=await $(),o=await e.prepareUncached("SELECT DISTINCT w.watcher FROM watches w JOIN objects o ON o.id = w.watcher AND o.type = 'node' WHERE w.object = ?").all(n);for(const{watcher:r}of o)await h(e,r)}p(X,"warmDocumentWatchers");async function Y(n,e,o){const r=await I(n,e,o);if("object"in r)return r.object;if("deleted"in r||"remote"in r)return r;if("ambiguous"in r){const s=await _(r.ambiguous,async m=>`${await k(n,m)}/${m.name}`);throw new d(409,"ambiguous_name",`'${o}' names more than one object: ${s.join(", ")}`,{candidates:s,next:"Read one of them by its full `<type>:<owner>/<name>`."})}const t=o.replace(/^\s*\[\[(.*)\]\]\s*$/,"$1").trim(),i=/^(person|app|repo|profile):([^/]+)$/.exec(t),a=await S(i?await y(n,i[2],i[1]):(await y(n,t)).filter(s=>s.type!=="node"),async s=>await g(n,e,s));if(a.length>0){const s=await x(n,e),m=p(u=>{const f=s.findIndex(E=>E.id===u.id);return f<0?1/0:f},"rank"),l=[...a].sort((u,f)=>m(u)-m(f))[0];if(m(l)===1/0&&a.length>1){const u=a.map(f=>`${f.type}:${f.name}`);throw new d(409,"ambiguous_name",`'${o}' names more than one owner: ${u.join(", ")}`,{candidates:u,next:"Name one as `<type>:<handle>`."})}return l.deleted_at?{deleted:l}:l}const c=`'${o}' not found: no object by that name in your view`,w=`Search for it with \`crtr canvas search ${t}\`.`;throw new d(404,"not_found",c,{error:"not_found",message:c,next:w})}p(Y,"resolveRef");async function k(n,e){if(e.owner===null)return"";const o=await n.prepare("SELECT type, id, name FROM objects WHERE id = ?").get(e.owner);return o.type==="node"?o.id:`${o.type}:${o.name}`}p(k,"typedOwnerHandle");async function Z(n,e,o,r){const t=o??(e.class==="node"?"node":e.class==="person"?"user":"app"),i=p(a=>new d(400,"invalid_owner",a,{next:"Run `crtr doc write --owner -h`."}),"refuse");if(t==="node"){if(e.class!=="node")throw i("`--owner node` needs a node; you are not running as one");return e.node}if(t==="user")return await j(n,b());if(t==="app"){if(e.class==="person")throw i("`--owner app` needs an app; a person has none \u2014 use `--owner user`");return e.app}if(t==="profile"){if(e.class!=="node"||!e.profile)throw i("`--owner profile` needs a profile; you have none");return e.profile}if(t==="repo"){const a=r?await O(n,r):[],c=a[0]?a:e.class==="node"?e.repos:[];if(!c[0])throw i(`\`--owner repo\` needs a repo; ${r??(e.class==="node"?e.cwd:"your directory")} is not inside one`);return c[0]}if(t.startsWith("repo:"))return await C(n,"repo",t.slice(5),i);if(t.startsWith("profile:")){const a=t.slice(8),c=await n.prepare("SELECT * FROM objects WHERE type = 'profile' AND name = ? AND home_machine IS NULL").get(a);if(c)return c;const w=D(a);if(w.kind!=="resolved")throw i(`no profile named '${a}'`);const s=e.class==="person"?e.person:e.app;return await F(n,"profile","profile",w.entry.profileId,v(w.entry.profileId,w.entry.manifest.name),s)}throw i(`unknown --owner value '${t}'`)}p(Z,"ownerFromFlag");async function C(n,e,o,r){const t=await n.prepare("SELECT * FROM objects WHERE type = ? AND name = ? AND deleted_at IS NULL AND home_machine IS NULL").get(e,o);if(!t)throw r(`no ${e} named '${o}'`);return t}p(C,"namedOwner");export{Z as ownerFromFlag,Q as readerFor,Y as resolveRef,X as warmDocumentWatchers,V as warmReaderRepos};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var Ce=Object.defineProperty;var i=(e,r)=>Ce(e,"name",{value:r,configurable:!0});import{createServer as Q}from"node:http";import{createServer as Oe}from"node:https";import{chmodSync as Ue,existsSync as D,readFileSync as q,unlinkSync as ee}from"node:fs";import{MINIMUM_RUNTIME_VERSION_HEADER as re,RUNTIME_VERSION_HEADER as x,minimumRuntimeRefusal as ke}from"../../api/runtime-version.js";import{CONTRACT_HEADER as $,CONTRACT_LEVEL as te,REQUIRED_CONTRACT_HEADER as ne,contractRefusal as Pe}from"../../api/contract.js";import{crtrVersion as j}from"../../shared/crtr-version.js";import{apiSocketPath as Ne}from"../../core/canvas/paths.js";import{resolveNodeToken as ze}from"../../core/canvas/node-tokens.js";import{isCloudRole as J,runAsPerson as M}from"../../core/canvas/person.js";import{personBearerVerifier as oe}from"./auth/person-bearer.js";import{personHasSnapshot as ie}from"../../core/scoped-state/person-store.js";import{loadPersonSettings as se}from"../../core/scoped-state/person-rows.js";import{AppPrincipalResolver as He}from"./principal.js";import{handleVendorSignIn as Ie,isVendorSignInPath as Le}from"./vendor-signin.js";import{RunError as b}from"../../core/runs/operations.js";import{removeVendorAccount as Be,vendorStatus as De}from"./handlers/vendor-status.js";import{toErrorBody as xe}from"./map.js";import{CONTROL_BODY_MAX_BYTES as $e}from"../../core/llm/body-limits.js";import{grantFor as je,hasSyncedGrants as Je}from"../../core/grants/mirror.js";import{readConfig as V}from"../../core/config.js";import{peerUid as Me}from"../../native/linux.js";import{findScopedApiToken as Ve,getApiToken as Ge,listScopedApiTokens as We}from"../../core/secrets.js";import{emitEvent as R}from"../../core/events/emit.js";import{envCrtrdTcp as Fe,envCrtrdToken as Ye}from"../../shared/env.js";import{Router as ae,actsAsPerson as le}from"./router.js";import{handleAttachUpgrade as Ze,refuseUpgrade as y}from"./bridge.js";import{boundDaemonControl as Ke}from"../control.js";import{attachRoutes as Xe,mayAttachNode as ce}from"./handlers/attach.js";import{peerRoutes as Qe}from"../peer/handlers.js";import{bashJobRoutes as qe}from"./handlers/bash-jobs.js";import{bashRoutes as er}from"./handlers/bash.js";import{hookExecRoutes as rr}from"./handlers/hook-exec.js";import{brokerOperationRoutes as ue}from"./handlers/broker-ops.js";import{brokerSignalRoutes as tr,brokerSignalStreams as nr}from"./handlers/broker-signals.js";import{brokerRecoveryRoutes as de,nodeFaultRoutes as or}from"./handlers/broker-recovery.js";import{canvasRoutes as ir}from"./handlers/canvas.js";import{conversationRoutes as sr}from"./handlers/conversations.js";import{chatInventoryRoutes as ar}from"./handlers/chat-inventory.js";import{daemonRoutes as lr}from"./handlers/daemon.js";import{fileRoutes as cr}from"./handlers/files.js";import{focusRoutes as ur}from"./handlers/focus.js";import{analyticsRoutes as dr}from"./handlers/analytics.js";import{memoryReadsRoutes as pr}from"./handlers/memory-reads.js";import{memoryRoutes as fr}from"./handlers/memory.js";import{healthRoutes as mr}from"./handlers/health.js";import{humanRequestRoutes as gr}from"./handlers/human-requests.js";import{inboxRoutes as hr}from"./handlers/inbox.js";import{feedbackCommentRoutes as Rr}from"./handlers/feedback-comments.js";import{objectRoutes as Ar}from"./handlers/objects.js";import{shareRoutes as yr}from"./handlers/shares.js";import{customObjectRoutes as vr}from"./handlers/custom-objects.js";import{docRoutes as wr}from"./handlers/docs.js";import{deliveryRoutes as pe}from"./handlers/delivery.js";import{deliveryRetryRoutes as _r}from"./handlers/delivery-retry.js";import{packageDocRoutes as Sr}from"./handlers/package-docs.js";import{documentAccessRoutes as Er}from"./handlers/document-access.js";import{pluginAppRoutes as Tr}from"./handlers/plugin-app-token.js";import{brokerMailRoutes as fe,messageRoutes as br}from"./handlers/messages.js";import{modelAuthRoutes as Cr}from"./handlers/modelauth.js";import{llmRoutes as Or}from"./handlers/llm.js";import{providerRoutes as Ur}from"./handlers/providers.js";import{modelConfigRoutes as kr}from"./handlers/model-config.js";import{settingsRoutes as Pr}from"./handlers/settings.js";import{nodeRoutes as Nr}from"./handlers/nodes.js";import{nodeRecordRoutes as zr}from"./handlers/node-records.js";import{nodeOutcomeRoutes as Hr}from"./handlers/node-outcomes.js";import{nodeEventRoutes as Ir}from"./handlers/node-events.js";import{profileRoutes as Lr}from"./handlers/profiles.js";import{prospectiveChatInventoryRoutes as Br}from"./handlers/prospective-chat-inventory.js";import{reportRoutes as Dr}from"./handlers/reports.js";import{runRoutes as xr}from"./handlers/run-routes.js";import{reviewCommentRoutes as $r}from"./handlers/review-comments.js";import{reviewRoutes as jr}from"./handlers/reviews.js";import{subscriptionRoutes as Jr}from"./handlers/subscriptions.js";import{structuredRequestRoutes as Mr}from"./handlers/structured-requests.js";import{cronRoutes as Vr}from"./handlers/crons.js";import{setCronRequestHandler as me}from"../cron/run-socket.js";import{worktreeRoutes as Gr}from"./handlers/worktree.js";import{limitsRoutes as Wr}from"./handlers/limits.js";import{chargeRoutes as Fr,spendLimitRoutes as Yr}from"./handlers/charges.js";import{executionStartRoutes as Zr}from"./handlers/execution-start.js";import{gitCredentialRoutes as Kr}from"./handlers/git-credential.js";function Xr(e){return new ae().registerAll(mr(e)).registerAll(lr).registerAll(yr).registerAll(Nr).registerAll(zr).registerAll(Hr).registerAll(_r).registerAll(Ir).registerAll(qe).registerAll(er).registerAll(rr).registerAll(ue).registerAll(tr).registerAll(pe).registerAll(de).registerAll(or).registerAll(Gr).registerAll(Wr).registerAll(Fr).registerAll(Zr).registerAll(Kr).registerAll(Yr).registerAll(fe).registerAll(br).registerAll(Dr).registerAll(xr).registerAll(Mr).registerAll(Xe).registerAll(ir).registerAll(sr).registerAll(dr).registerAll(pr).registerAll(fr).registerAll(cr).registerAll(Ar).registerAll(vr).registerAll(wr).registerAll(Sr).registerAll(Er).registerAll(Tr).registerAll(ur).registerAll(Jr).registerAll(Vr).registerAll(Lr).registerAll(Cr).registerAll(Or).registerAll(Ur).registerAll(kr).registerAll(Pr).registerAll(jr).registerAll($r).registerAll(hr).registerAll(gr).registerAll(ar).registerAll(Br).registerAll(Rr).registerAll(Qe)}i(Xr,"buildRouter");function Qr(e,r){if(e.toUpperCase()!=="GET")return null;const s=r.split("/").filter(f=>f.length>0);if(s.length!==4||s[0]!=="v1"||s[1]!=="nodes"||s[3]!=="attach")return null;const o=s[2];return o===void 0||o===""?null:decodeURIComponent(o)}i(Qr,"attachNodeId");function qr(e){const r=e.trim();if(r==="")return null;const s=r.lastIndexOf(":");if(s<0)return null;const o=r.slice(0,s),f=r.slice(s+1),d=Number(f);return!Number.isInteger(d)||d<0||d>65535?null:{host:o===""?"0.0.0.0":o,port:d}}i(qr,"parseTcp");function et(e,r){return`${e.includes(":")?`[${e}]`:e}:${r}`}i(et,"formatTcpAddress");const E={code:"unauthorized",message:"missing or invalid bearer token"},H={code:"owner_only",message:"attach is owner-only; a scoped token does not reach it"},k={code:"person_bearer_not_supported",message:"this listener accepts a person bearer only on a cloud role with CRTR_DIRECTORY_URL and CRTR_PUBLIC_API_URL set; call with a node, app or public token"},G={class:"anonymous",app:"",node:"",run:null,uid:-1,sub:"",grant:null,client_id:null,scopes:[]},C=new WeakMap;function P(e){return C.get(e)}i(P,"socketPrincipal");async function ge(e,r){const s=process.platform==="linux"?Me(e.socket):null,o=e.headers.authorization;if(o===void 0)return s===null||r.has(s)?{class:"person"}:"unauthorized";if(typeof o!="string"||!o.startsWith("Bearer "))return"unauthorized";if(o.slice(7).startsWith("crtr_pub_"))return G;if(o.slice(7).startsWith(W)){const f=ye(o.slice(7));return f!==void 0&&(s===null||r.has(s))?f.principal:"unauthorized"}return he(o.slice(7),s)}i(ge,"resolveSocketPrincipal");async function he(e,r){const s=await ze(e);if(!s||r!==null&&r!==s.uid)return"unauthorized";const o=V("user").runtime?.issuer;if(o&&!await Je(o.replace(/\/$/,"")))return"runtime_starting";const f=s.grant??(await je("app:terminal",s.sub))?.id??null;return{class:"broker",...s,grant:f}}i(he,"brokerPrincipal");function Re(e){if(e.class!=="anonymous")return e.sub!==void 0&&e.sub!==""?e.sub:void 0}i(Re,"requestPerson");function Ae(e,r){r.class==="broker"&&R({event:"api.request.principal",level:r.app==="app:terminal"?"debug":"info",node_id:r.node,fields:{principal:`${r.app} node:${r.node}`,method:e.method,path:e.url}})}i(Ae,"noteBrokerRequest");const W="crtr_app_";function ye(e){const r=e.startsWith(W)?Ve(e):void 0;return r===void 0?void 0:{principal:{class:"app",app:r.grantee,scopes:r.scopes},ceiling:r.scopes}}i(ye,"appBearer");function rt(e){const r=new Map;for(const s of We("user"))r.set(s.token,{principal:{class:"app",app:s.grantee,scopes:s.scopes},ceiling:s.scopes});return e!==void 0&&r.set(e,{principal:{class:"person"},ceiling:null}),r}i(rt,"resolveBearers");const tt=/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]*$/;async function ve(e,r){const s=e.headers.authorization;if(s===void 0&&(e.method??"GET").toUpperCase()==="GET"&&(e.url??"").split("?")[0]==="/healthz")return{principal:G,ceiling:null};if(typeof s!="string"||!s.startsWith("Bearer "))return"unauthorized";const o=s.slice(7);if(o.startsWith("crtr_pub_"))return{principal:G,ceiling:null};if(o.startsWith(W))return ye(o)??"unauthorized";const f=r.get(o);if(f!==void 0)return f;if(tt.test(o)){const h=J()?oe():null;if(h===null)return"person_bearer";const m=await h.verify(o);return m===null?"unauthorized":{principal:{class:"person",sub:m},ceiling:null}}const d=await he(o,null);return typeof d=="string"?d:{principal:d,ceiling:null}}i(ve,"authorizeTcp");let I;function nt(){if(I!==void 0)return I;const e=process.env.CRTR_DIRECTORY_URL||void 0,r=process.env.CRTR_PUBLIC_API_URL||void 0;return I=e===void 0||r===void 0?null:new He(e,r,async()=>{}),I}i(nt,"vendorHandoffResolver");async function ot(e,r){T(r),O(r);const s=nt();try{if(s===null)throw new b(503,"runtime_starting","vendor sign-in is not configured on this listener");await Ie(e,r,new URL(e.url??"/","http://runtime.local"),s)}catch(o){if(!(o instanceof b))throw o;if(r.headersSent){r.destroy();return}r.writeHead(o.status,{"content-type":"application/json; charset=utf-8","cache-control":"no-store"}),r.end(JSON.stringify({error:{code:o.code,message:o.message,...o.param?{param:o.param}:{},origin:"runtime"}}))}}i(ot,"serveVendorSignIn");function it(){const e=process.env.CRTRD_TLS_CERT||void 0,r=process.env.CRTRD_TLS_KEY||void 0;if(e===void 0&&r===void 0)return null;if(e===void 0||r===void 0)throw new Error("CRTRD_TLS_CERT and CRTRD_TLS_KEY must be set together");return{cert:q(e),key:q(r)}}i(it,"tcpTls");function T(e){e.setHeader(x,j()),e.setHeader($,te)}i(T,"advertiseRuntime");function O(e){e.setHeader("Access-Control-Allow-Origin","*"),e.setHeader("Access-Control-Expose-Headers",`${x}, ${$}`)}i(O,"exposeRuntimeHeaders");function st(e,r){return(e.method??"GET").toUpperCase()!=="OPTIONS"?!1:(T(r),r.writeHead(204,{"Access-Control-Allow-Origin":"*","Access-Control-Expose-Headers":`${x}, ${$}`,"Access-Control-Allow-Headers":`authorization, content-type, ${re.toLowerCase()}, ${ne.toLowerCase()}`,"Access-Control-Allow-Methods":"GET, POST, PATCH, PUT, DELETE, OPTIONS","Access-Control-Max-Age":"600"}),r.end(),!0)}i(st,"answerPreflight");function L(e,r=!1){T(e),r&&O(e),e.writeHead(401,{"content-type":"application/json; charset=utf-8"}),e.end(JSON.stringify({error:{...E,origin:"runtime"}}))}i(L,"writeUnauthorized");function at(e){T(e),O(e),e.writeHead(401,{"content-type":"application/json; charset=utf-8"}),e.end(JSON.stringify({error:{...k,origin:"runtime"}}))}i(at,"writePersonBearerRefused");const lt={"/v1/runtime/vendor-status":{method:"GET",purpose:"vendor_status"},"/v1/runtime/vendor-account-remove":{method:"POST",purpose:"vendor_account_remove"}};async function ct(e,r){if(!J())return!1;const s=new URL(e.url??"/","http://runtime.local").pathname,o=lt[s];if(o===void 0||e.method!==o.method)return!1;const f=i((d,h)=>{T(r),O(r),r.writeHead(d,{"content-type":"application/json; charset=utf-8"}),r.end(JSON.stringify(h))},"answer");try{const d=oe();if(d===null)throw new b(401,k.code,k.message);const h=e.headers.authorization,m=h?.startsWith("Bearer ")?await d.verifyPurpose(h.slice(7),o.purpose):null;if(m===null)throw new b(401,"unauthorized","invalid directory token");const B=o.purpose==="vendor_status"?void 0:await ut(e);f(200,await M(m,async()=>o.purpose==="vendor_status"?De():await Be(B)))}catch(d){const{status:h,body:m}=xe(d);f(h,m)}return!0}i(ct,"serveCloudVendorRoute");async function ut(e){const r=[];let s=0;for await(const o of e){if(s+=o.length,s>$e)throw new b(400,"invalid_request","request body too large");r.push(o)}if(s!==0)try{return JSON.parse(Buffer.concat(r).toString("utf8"))}catch{throw new b(400,"invalid_request","invalid JSON body")}}i(ut,"readVendorBody");function we(e){T(e),e.writeHead(503,{"content-type":"application/json; charset=utf-8"}),e.end(JSON.stringify({error:{code:"runtime_starting",message:"grant sync is not ready",type:"server_error",origin:"runtime",retryable:!0}}))}i(we,"writeRuntimeStarting");function dt(e,r){e.writeHead(503,{"content-type":"application/json; charset=utf-8"}),e.end(JSON.stringify({error:{code:"startup_blocked",message:r,origin:"runtime"}}))}i(dt,"writeStartupBlocked");function _e(e,r,s){return new Promise(o=>{if(s===void 0){try{e.closeAllConnections()}catch{}e.close(()=>o());return}const f=[];e.close(()=>{for(const m of f)clearTimeout(m);o()});for(const m of r)m.destroy();const d=setInterval(()=>e.closeIdleConnections(),250),h=setTimeout(()=>e.closeAllConnections(),s);f.push(d,h),e.closeIdleConnections()})}i(_e,"closeServer");function Vn(e={}){let r=null;const s=Xr(()=>r),o=new ae().registerAll(ue).registerAll(pe).registerAll(de).registerAll(fe),f=i((t,n)=>{const l=Ke()?.startupBlock()??null;return l===null||t==="GET"&&(n==="/healthz"||n==="/v1/status"||n==="/v1/ready")||t==="POST"&&(n==="/v1/daemon/migrate"||n==="/v1/daemon/admit")||l.phase==="recovering"&&o.match(t,n)!==null?null:l},"startupBlockFor"),d=e.socketPath??Ne(),h=new Set([process.getuid?.()??0,...V("user").runtime?.person_uids??[]]),m=i((t,n,l)=>{T(n);const u=i(a=>Array.isArray(a)?a[0]:a,"first"),S=u(t.headers[re.toLowerCase()]),g=ke(S,j())??Pe(u(t.headers[ne.toLowerCase()]),te,{legacyMinimum:S,runtimeVersion:j()});if(g!==null){n.writeHead(g.status,{"content-type":"application/json; charset=utf-8"}),n.end(JSON.stringify({error:{code:g.code,message:g.message,type:"invalid_request_error",origin:"runtime",retryable:!1,..."param"in g?{param:g.param}:{details:g.details}}}));return}const v=i(a=>{const c=P(t);R({event:"api.request.failed",level:"error",...c?.class==="broker"?{node_id:c.node}:{},error:a instanceof Error?a:new Error(String(a))});try{n.headersSent||n.writeHead(500,{"content-type":"application/json; charset=utf-8"}),n.end(JSON.stringify({error:{code:"internal",message:"internal error",origin:"runtime"}}))}catch{}},"internalFailure");let _;try{_=new URL(t.url??"/","http://127.0.0.1")}catch{try{n.writeHead(400,{"content-type":"application/json; charset=utf-8"}),n.end(JSON.stringify({error:{code:"invalid_request",message:"request URL is invalid",origin:"runtime"}}))}catch{}return}try{const a=f((t.method??"GET").toUpperCase(),_.pathname);if(a!==null){dt(n,a.message);return}const c=P(t)??{class:"person"},p=Re(c),A=i(()=>s.handle(t,n,l,c),"handled");(p===void 0?A():M(p,i(async()=>{ie()||await se(p),await A()},"handledAsPerson"))).catch(v)}catch(a){v(a)}},"onRequest"),B=i(async(t,n,l)=>{const u=P(t);return u===void 0||le(u)||await ce(u,"either",l)?!0:(y(n,404,"Not Found","node_not_found",`no node ${l}`),!1)},"authorizeAttachUpgrade"),N=new Set,F=i((t,n,l)=>{N.add(n),n.once("close",()=>N.delete(n)),n.on("error",()=>{});try{const u=new URL(t.url??"/","http://127.0.0.1"),S=f((t.method??"GET").toUpperCase(),u.pathname);if(S!==null){y(n,503,"Service Unavailable","startup_blocked",S.message);return}const g=Qr(t.method??"GET",u.pathname);if(g===null){n.destroy();return}const v=(()=>{const a=P(t);return a===void 0?void 0:Re(a)})(),_=i(()=>B(t,n,g).then(a=>a?Ze(t,n,l,g,async c=>{const p=P(t);return p===void 0||le(p)||await ce(p,c,g)}):void 0),"attach");(v===void 0?_():M(v,async()=>{ie()||await se(v),await _()})).catch(()=>{try{n.destroy()}catch{}})}catch{try{n.destroy()}catch{}}},"onUpgrade"),Se=i(t=>{t.on("error",n=>{R({event:"api.server.failed",level:"error",error:n})})},"bindErrorHandler"),Ee=i(async(t,n)=>{try{const l=await ge(t,h);if(l==="unauthorized"){R({event:"api.principal.denied",level:"warn",fields:{method:t.method}}),L(n);return}if(l==="runtime_starting"){we(n);return}C.set(t,l),Ae(t,l),m(t,n,l.class==="app"?l.scopes:null)}catch(l){R({event:"api.principal.failed",level:"error",error:l instanceof Error?l:new Error(String(l))}),L(n)}},"onSocketRequest"),U=Q((t,n)=>{Ee(t,n).catch(l=>R({event:"api.principal.failed",level:"error",error:l instanceof Error?l:new Error(String(l))}))}),Te=i(async(t,n,l)=>{try{const u=await ge(t,h);if(u==="unauthorized"||u==="runtime_starting"){u==="unauthorized"&&R({event:"api.principal.denied",level:"warn",fields:{method:t.method}}),y(n,u==="unauthorized"?401:503,"Unauthorized",u,"socket principal unavailable");return}if(u.class!=="person"&&u.class!=="broker"){y(n,403,"Forbidden",H.code,H.message);return}C.set(t,u),F(t,n,l)}catch(u){R({event:"api.principal.failed",level:"error",error:u instanceof Error?u:new Error(String(u))}),y(n,401,"Unauthorized",E.code,E.message)}},"onSocketUpgrade");U.on("upgrade",(t,n,l)=>{Te(t,n,l).catch(u=>R({event:"api.principal.failed",level:"error",error:u instanceof Error?u:new Error(String(u))}))}),me((t,n,l)=>{C.set(t,l),m(t,n,null)});let Y=!1,Z,K;const be=new Promise((t,n)=>{Z=t,K=n});U.once("listening",()=>{Y=!0,Z()}),U.on("error",t=>{R({event:"api.server.failed",level:"error",error:t}),Y||K(t)});try{D(d)&&ee(d)}catch{}U.listen(d,()=>{try{Ue(d,process.platform==="linux"&&D("/run/crtr/launcher.sock")?438:384)}catch(t){R({event:"api.socket.chmod_failed",level:"error",error:t instanceof Error?t:new Error(String(t))})}});let w;const z=e.tcp??Fe()??V("user").api.tcp;if(z!==void 0&&z!==""){const t=qr(z);if(t===null)R({event:"api.tcp.invalid",level:"error",error:new Error(`invalid CRTRD_TCP/--tcp spec: ${z}`)});else{const n=e.token??Ye()??Ge("user"),l=rt(n),u=i(async(a,c)=>{if(st(a,c))return;if(J()&&Le(new URL(a.url??"/","http://runtime.local").pathname)){await ot(a,c);return}if(await ct(a,c))return;const p=await ve(a,l);if(p==="runtime_starting"){O(c),we(c);return}if(p==="person_bearer"){at(c);return}if(p==="unauthorized"){R({event:"api.principal.denied",level:"warn",fields:{method:a.method,listener:"tcp"}}),L(c,!0);return}C.set(a,p.principal),Ae(a,p.principal),O(c),m(a,c,p.ceiling)},"tcpOnRequest"),S=i(async(a,c,p)=>{const A=await ve(a,l);if(A==="runtime_starting"){y(c,503,"Service Unavailable","runtime_starting","grant sync is not ready");return}if(A==="person_bearer"){y(c,401,"Unauthorized",k.code,k.message);return}if(A==="unauthorized"){y(c,401,"Unauthorized",E.code,E.message);return}if(A.ceiling!==null||A.principal.class==="anonymous"){y(c,403,"Forbidden",H.code,H.message);return}C.set(a,A.principal),F(a,c,p)},"tcpOnUpgrade"),g=i(a=>{R({event:"api.principal.failed",level:"error",error:a instanceof Error?a:new Error(String(a))})},"failed"),v=i((a,c)=>{u(a,c).catch(p=>{g(p),c.headersSent?c.destroy():L(c,!0)})},"listener"),_=it();w=_===null?Q(v):Oe(_,v),w.on("upgrade",(a,c,p)=>{c.on("error",()=>{}),S(a,c,p).catch(A=>{g(A),y(c,401,"Unauthorized",E.code,E.message)})}),Se(w),w.once("listening",()=>{const a=w?.address();if(a!==null&&typeof a=="object"){const{address:c,port:p}=a;r=et(c,p)}}),w.listen(t.port,t.host)}}let X=!1;return{ready:be,tcpAddress:i(()=>r,"tcpAddress"),close:i(async(t={})=>{if(!X){X=!0,me(null),nr.close(),await Promise.all([_e(U,N,t.graceMs),w!==void 0?_e(w,N,t.graceMs):Promise.resolve()]);try{D(d)&&ee(d)}catch{}}},"close")}}i(Vn,"createApiServer");export{Xr as buildRouter,_e as closeServer,Vn as createApiServer,P as socketPrincipal};
|
|
1
|
+
var Ue=Object.defineProperty;var i=(e,r)=>Ue(e,"name",{value:r,configurable:!0});import{createServer as ee}from"node:http";import{createServer as Pe}from"node:https";import{chmodSync as ke,existsSync as $,readFileSync as re,unlinkSync as te}from"node:fs";import{MINIMUM_RUNTIME_VERSION_HEADER as ne,RUNTIME_VERSION_HEADER as j,minimumRuntimeRefusal as ze}from"../../api/runtime-version.js";import{CONTRACT_HEADER as M,CONTRACT_LEVEL as oe,REQUIRED_CONTRACT_HEADER as ie,contractRefusal as Ne}from"../../api/contract.js";import{crtrVersion as V}from"../../shared/crtr-version.js";import{apiSocketPath as He}from"../../core/canvas/paths.js";import{resolveNodeToken as Ie}from"../../core/canvas/node-tokens.js";import{isCloudRole as P,runAsPerson as B}from"../../core/canvas/person.js";import{personBearerVerifier as se}from"./auth/person-bearer.js";import{personHasSnapshot as W}from"../../core/scoped-state/person-store.js";import{loadPersonSettings as F}from"../../core/scoped-state/person-rows.js";import{AppPrincipalResolver as Le}from"./principal.js";import{createAppRequestHandler as Be}from"./app-listener.js";import{decodeJwt as De}from"jose";import{handleVendorSignIn as xe,isVendorSignInPath as Je}from"./vendor-signin.js";import{RunError as E}from"../../core/runs/operations.js";import{removeVendorAccount as $e,vendorStatus as je}from"./handlers/vendor-status.js";import{toErrorBody as Me}from"./map.js";import{CONTROL_BODY_MAX_BYTES as Ve}from"../../core/llm/body-limits.js";import{grantFor as We,hasSyncedGrants as Fe}from"../../core/grants/mirror.js";import{readConfig as ae}from"../../core/config.js";import{directoryIssuer as Ge}from"../../core/directory/issuer.js";import{peerUid as Ye}from"../../native/linux.js";import{findScopedApiToken as Ze,getApiToken as Ke,listScopedApiTokens as Xe}from"../../core/secrets.js";import{emitEvent as A}from"../../core/events/emit.js";import{envCrtrdTcp as Qe,envCrtrdToken as qe}from"../../shared/env.js";import{Router as le,actsAsPerson as ce}from"./router.js";import{handleAttachUpgrade as er,refuseUpgrade as y}from"./bridge.js";import{boundDaemonControl as rr}from"../control.js";import{attachRoutes as tr,mayAttachNode as ue}from"./handlers/attach.js";import{peerRoutes as nr}from"../peer/handlers.js";import{bashJobRoutes as or}from"./handlers/bash-jobs.js";import{bashRoutes as ir}from"./handlers/bash.js";import{hookExecRoutes as sr}from"./handlers/hook-exec.js";import{brokerOperationRoutes as de}from"./handlers/broker-ops.js";import{brokerSignalRoutes as ar,brokerSignalStreams as lr}from"./handlers/broker-signals.js";import{brokerRecoveryRoutes as pe,nodeFaultRoutes as cr}from"./handlers/broker-recovery.js";import{canvasRoutes as ur}from"./handlers/canvas.js";import{conversationRoutes as dr}from"./handlers/conversations.js";import{chatInventoryRoutes as pr}from"./handlers/chat-inventory.js";import{daemonRoutes as fr}from"./handlers/daemon.js";import{fileRoutes as mr}from"./handlers/files.js";import{focusRoutes as gr}from"./handlers/focus.js";import{analyticsRoutes as hr}from"./handlers/analytics.js";import{memoryReadsRoutes as Rr}from"./handlers/memory-reads.js";import{memoryRoutes as Ar}from"./handlers/memory.js";import{healthRoutes as yr}from"./handlers/health.js";import{humanRequestRoutes as vr}from"./handlers/human-requests.js";import{inboxRoutes as wr}from"./handlers/inbox.js";import{feedbackCommentRoutes as _r}from"./handlers/feedback-comments.js";import{objectRoutes as Sr}from"./handlers/objects.js";import{shareRoutes as Er}from"./handlers/shares.js";import{customObjectRoutes as br}from"./handlers/custom-objects.js";import{docRoutes as Tr}from"./handlers/docs.js";import{deliveryRoutes as fe}from"./handlers/delivery.js";import{deliveryRetryRoutes as Cr}from"./handlers/delivery-retry.js";import{packageDocRoutes as Or}from"./handlers/package-docs.js";import{documentAccessRoutes as Ur}from"./handlers/document-access.js";import{pluginAppRoutes as Pr}from"./handlers/plugin-app-token.js";import{brokerMailRoutes as me,messageRoutes as kr}from"./handlers/messages.js";import{modelAuthRoutes as zr}from"./handlers/modelauth.js";import{llmRoutes as Nr}from"./handlers/llm.js";import{providerRoutes as Hr}from"./handlers/providers.js";import{modelConfigRoutes as Ir}from"./handlers/model-config.js";import{settingsRoutes as Lr}from"./handlers/settings.js";import{nodeRoutes as Br}from"./handlers/nodes.js";import{nodeRecordRoutes as Dr}from"./handlers/node-records.js";import{nodeOutcomeRoutes as xr}from"./handlers/node-outcomes.js";import{nodeEventRoutes as Jr}from"./handlers/node-events.js";import{profileRoutes as $r}from"./handlers/profiles.js";import{prospectiveChatInventoryRoutes as jr}from"./handlers/prospective-chat-inventory.js";import{reportRoutes as Mr}from"./handlers/reports.js";import{runRoutes as Vr}from"./handlers/run-routes.js";import{reviewCommentRoutes as Wr}from"./handlers/review-comments.js";import{reviewRoutes as Fr}from"./handlers/reviews.js";import{subscriptionRoutes as Gr}from"./handlers/subscriptions.js";import{structuredRequestRoutes as Yr}from"./handlers/structured-requests.js";import{cronRoutes as Zr}from"./handlers/crons.js";import{setCronRequestHandler as ge}from"../cron/run-socket.js";import{worktreeRoutes as Kr}from"./handlers/worktree.js";import{limitsRoutes as Xr}from"./handlers/limits.js";import{chargeRoutes as Qr,spendLimitRoutes as qr}from"./handlers/charges.js";import{executionStartRoutes as et}from"./handlers/execution-start.js";import{gitCredentialRoutes as rt}from"./handlers/git-credential.js";function tt(e){return new le().registerAll(yr(e)).registerAll(fr).registerAll(Er).registerAll(Br).registerAll(Dr).registerAll(xr).registerAll(Cr).registerAll(Jr).registerAll(or).registerAll(ir).registerAll(sr).registerAll(de).registerAll(ar).registerAll(fe).registerAll(pe).registerAll(cr).registerAll(Kr).registerAll(Xr).registerAll(Qr).registerAll(et).registerAll(rt).registerAll(qr).registerAll(me).registerAll(kr).registerAll(Mr).registerAll(Vr).registerAll(Yr).registerAll(tr).registerAll(ur).registerAll(dr).registerAll(hr).registerAll(Rr).registerAll(Ar).registerAll(mr).registerAll(Sr).registerAll(br).registerAll(Tr).registerAll(Or).registerAll(Ur).registerAll(Pr).registerAll(gr).registerAll(Gr).registerAll(Zr).registerAll($r).registerAll(zr).registerAll(Nr).registerAll(Hr).registerAll(Ir).registerAll(Lr).registerAll(Fr).registerAll(Wr).registerAll(wr).registerAll(vr).registerAll(pr).registerAll(jr).registerAll(_r).registerAll(nr)}i(tt,"buildRouter");function nt(e,r){if(e.toUpperCase()!=="GET")return null;const s=r.split("/").filter(f=>f.length>0);if(s.length!==4||s[0]!=="v1"||s[1]!=="nodes"||s[3]!=="attach")return null;const o=s[2];return o===void 0||o===""?null:decodeURIComponent(o)}i(nt,"attachNodeId");function ot(e){const r=e.trim();if(r==="")return null;const s=r.lastIndexOf(":");if(s<0)return null;const o=r.slice(0,s),f=r.slice(s+1),p=Number(f);return!Number.isInteger(p)||p<0||p>65535?null:{host:o===""?"0.0.0.0":o,port:p}}i(ot,"parseTcp");function it(e,r){return`${e.includes(":")?`[${e}]`:e}:${r}`}i(it,"formatTcpAddress");const T={code:"unauthorized",message:"missing or invalid bearer token"},k={code:"owner_only",message:"attach is owner-only; a scoped token does not reach it"},H={code:"person_bearer_not_supported",message:"this listener accepts a person bearer only on a cloud role with CRTR_DIRECTORY_URL and CRTR_PUBLIC_API_URL set; call with a node, app or public token"},G={class:"anonymous",app:"",node:"",run:null,uid:-1,sub:"",grant:null,client_id:null,scopes:[]},z=new WeakMap;function I(e){return z.get(e)}i(I,"socketPrincipal");async function he(e,r){const s=process.platform==="linux"?Ye(e.socket):null,o=e.headers.authorization;if(o===void 0)return s===null||r.has(s)?{class:"person"}:"unauthorized";if(typeof o!="string"||!o.startsWith("Bearer "))return"unauthorized";if(o.slice(7).startsWith("crtr_pub_"))return G;if(o.slice(7).startsWith(Y)){const f=ve(o.slice(7));return f!==void 0&&(s===null||r.has(s))?f.principal:"unauthorized"}return Re(o.slice(7),s)}i(he,"resolveSocketPrincipal");async function Re(e,r){const s=await Ie(e);if(!s||r!==null&&r!==s.uid)return"unauthorized";const o=Ge();if(o&&!P()&&!await Fe(o))return"runtime_starting";const f=s.grant??(await We("app:terminal",s.sub))?.id??null;return{class:"broker",...s,grant:f}}i(Re,"brokerPrincipal");function Ae(e){if(e.class!=="anonymous")return e.sub!==void 0&&e.sub!==""?e.sub:void 0}i(Ae,"requestPerson");function ye(e,r){r.class==="broker"&&A({event:"api.request.principal",level:r.app==="app:terminal"?"debug":"info",node_id:r.node,fields:{principal:`${r.app} node:${r.node}`,method:e.method,path:e.url}})}i(ye,"noteBrokerRequest");const Y="crtr_app_";function ve(e){const r=e.startsWith(Y)?Ze(e):void 0;return r===void 0?void 0:{principal:{class:"app",app:r.grantee,scopes:r.scopes},ceiling:r.scopes}}i(ve,"appBearer");function st(e){const r=new Map;for(const s of Xe("user"))r.set(s.token,{principal:{class:"app",app:s.grantee,scopes:s.scopes},ceiling:s.scopes});return e!==void 0&&r.set(e,{principal:{class:"person"},ceiling:null}),r}i(st,"resolveBearers");function at(e){try{return De(e).act!==void 0}catch{return!1}}i(at,"carriesAct");const lt=/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]*$/;async function we(e,r){const s=e.headers.authorization;if(s===void 0&&(e.method??"GET").toUpperCase()==="GET"&&(e.url??"").split("?")[0]==="/healthz")return{principal:G,ceiling:null};if(typeof s!="string"||!s.startsWith("Bearer "))return"unauthorized";const o=s.slice(7);if(o.startsWith("crtr_pub_"))return{principal:G,ceiling:null};if(o.startsWith(Y))return ve(o)??"unauthorized";const f=r.get(o);if(f!==void 0)return f;if(lt.test(o)){if(P()&&at(o)){const U=x();if(U===null)return"person_bearer";try{const v=await U.verifyCall(s);return v.chain[0]?.sub.startsWith("app:")?{call:v}:"unauthorized"}catch(v){return v instanceof E&&v.status===503?"runtime_starting":"unauthorized"}}const R=P()?se():null;if(R===null)return"person_bearer";const m=await R.verify(o);return m===null?"unauthorized":{principal:{class:"person",sub:m},ceiling:null}}const p=await Re(o,null);return typeof p=="string"?p:{principal:p,ceiling:null}}i(we,"authorizeTcp");let D;function x(){if(D!==void 0)return D;const e=process.env.CRTR_DIRECTORY_URL||void 0,r=process.env.CRTR_PUBLIC_API_URL||void 0;return D=e===void 0||r===void 0?null:new Le(e,r,async()=>{}),D}i(x,"cloudCallResolver");let _e;function ct(){const e=x();if(e===null)throw new E(503,"runtime_starting","app calls are not configured on this listener");return _e??=Be(e,async()=>!0,async()=>{}),_e}i(ct,"cloudAppCalls");async function ut(e,r){C(r),O(r);const s=x();try{if(s===null)throw new E(503,"runtime_starting","vendor sign-in is not configured on this listener");await xe(e,r,new URL(e.url??"/","http://runtime.local"),s)}catch(o){if(!(o instanceof E))throw o;if(r.headersSent){r.destroy();return}r.writeHead(o.status,{"content-type":"application/json; charset=utf-8","cache-control":"no-store"}),r.end(JSON.stringify({error:{code:o.code,message:o.message,...o.param?{param:o.param}:{},origin:"runtime"}}))}}i(ut,"serveVendorSignIn");function dt(){const e=process.env.CRTRD_TLS_CERT||void 0,r=process.env.CRTRD_TLS_KEY||void 0;if(e===void 0&&r===void 0)return null;if(e===void 0||r===void 0)throw new Error("CRTRD_TLS_CERT and CRTRD_TLS_KEY must be set together");return{cert:re(e),key:re(r)}}i(dt,"tcpTls");function C(e){e.setHeader(j,V()),e.setHeader(M,oe)}i(C,"advertiseRuntime");function O(e){e.setHeader("Access-Control-Allow-Origin","*"),e.setHeader("Access-Control-Expose-Headers",`${j}, ${M}`)}i(O,"exposeRuntimeHeaders");function pt(e,r){return(e.method??"GET").toUpperCase()!=="OPTIONS"?!1:(C(r),r.writeHead(204,{"Access-Control-Allow-Origin":"*","Access-Control-Expose-Headers":`${j}, ${M}`,"Access-Control-Allow-Headers":`authorization, content-type, ${ne.toLowerCase()}, ${ie.toLowerCase()}`,"Access-Control-Allow-Methods":"GET, POST, PATCH, PUT, DELETE, OPTIONS","Access-Control-Max-Age":"600"}),r.end(),!0)}i(pt,"answerPreflight");function J(e,r=!1){C(e),r&&O(e),e.writeHead(401,{"content-type":"application/json; charset=utf-8"}),e.end(JSON.stringify({error:{...T,origin:"runtime"}}))}i(J,"writeUnauthorized");function ft(e){C(e),O(e),e.writeHead(401,{"content-type":"application/json; charset=utf-8"}),e.end(JSON.stringify({error:{...H,origin:"runtime"}}))}i(ft,"writePersonBearerRefused");const mt={"/v1/runtime/vendor-status":{method:"GET",purpose:"vendor_status"},"/v1/runtime/vendor-account-remove":{method:"POST",purpose:"vendor_account_remove"}};async function gt(e,r){if(!P())return!1;const s=new URL(e.url??"/","http://runtime.local").pathname,o=mt[s];if(o===void 0||e.method!==o.method)return!1;const f=i((p,R)=>{C(r),O(r),r.writeHead(p,{"content-type":"application/json; charset=utf-8"}),r.end(JSON.stringify(R))},"answer");try{const p=se();if(p===null)throw new E(401,H.code,H.message);const R=e.headers.authorization,m=R?.startsWith("Bearer ")?await p.verifyPurpose(R.slice(7),o.purpose):null;if(m===null)throw new E(401,"unauthorized","invalid directory token");const U=o.purpose==="vendor_status"?void 0:await ht(e);f(200,await B(m,async()=>o.purpose==="vendor_status"?je():await $e(U)))}catch(p){const{status:R,body:m}=Me(p);f(R,m)}return!0}i(gt,"serveCloudVendorRoute");async function ht(e){const r=[];let s=0;for await(const o of e){if(s+=o.length,s>Ve)throw new E(400,"invalid_request","request body too large");r.push(o)}if(s!==0)try{return JSON.parse(Buffer.concat(r).toString("utf8"))}catch{throw new E(400,"invalid_request","invalid JSON body")}}i(ht,"readVendorBody");function Se(e){C(e),e.writeHead(503,{"content-type":"application/json; charset=utf-8"}),e.end(JSON.stringify({error:{code:"runtime_starting",message:"grant sync is not ready",type:"server_error",origin:"runtime",retryable:!0}}))}i(Se,"writeRuntimeStarting");function Rt(e,r){e.writeHead(503,{"content-type":"application/json; charset=utf-8"}),e.end(JSON.stringify({error:{code:"startup_blocked",message:r,origin:"runtime"}}))}i(Rt,"writeStartupBlocked");function Ee(e,r,s){return new Promise(o=>{if(s===void 0){try{e.closeAllConnections()}catch{}e.close(()=>o());return}const f=[];e.close(()=>{for(const m of f)clearTimeout(m);o()});for(const m of r)m.destroy();const p=setInterval(()=>e.closeIdleConnections(),250),R=setTimeout(()=>e.closeAllConnections(),s);f.push(p,R),e.closeIdleConnections()})}i(Ee,"closeServer");function qn(e={}){let r=null;const s=tt(()=>r),o=new le().registerAll(de).registerAll(fe).registerAll(pe).registerAll(me),f=i((t,n)=>{const c=rr()?.startupBlock()??null;return c===null||t==="GET"&&(n==="/healthz"||n==="/v1/status"||n==="/v1/ready")||t==="POST"&&(n==="/v1/daemon/migrate"||n==="/v1/daemon/admit")||c.phase==="recovering"&&o.match(t,n)!==null?null:c},"startupBlockFor"),p=e.socketPath??He(),R=new Set([process.getuid?.()??0,...ae("user").runtime?.person_uids??[]]),m=i((t,n,c)=>{C(n);const u=i(a=>Array.isArray(a)?a[0]:a,"first"),b=u(t.headers[ne.toLowerCase()]),g=ze(b,V())??Ne(u(t.headers[ie.toLowerCase()]),oe,{legacyMinimum:b,runtimeVersion:V()});if(g!==null){n.writeHead(g.status,{"content-type":"application/json; charset=utf-8"}),n.end(JSON.stringify({error:{code:g.code,message:g.message,type:"invalid_request_error",origin:"runtime",retryable:!1,..."param"in g?{param:g.param}:{details:g.details}}}));return}const w=i(a=>{const l=I(t);A({event:"api.request.failed",level:"error",...l?.class==="broker"?{node_id:l.node}:{},error:a instanceof Error?a:new Error(String(a))});try{n.headersSent||n.writeHead(500,{"content-type":"application/json; charset=utf-8"}),n.end(JSON.stringify({error:{code:"internal",message:"internal error",origin:"runtime"}}))}catch{}},"internalFailure");let S;try{S=new URL(t.url??"/","http://127.0.0.1")}catch{try{n.writeHead(400,{"content-type":"application/json; charset=utf-8"}),n.end(JSON.stringify({error:{code:"invalid_request",message:"request URL is invalid",origin:"runtime"}}))}catch{}return}try{const a=f((t.method??"GET").toUpperCase(),S.pathname);if(a!==null){Rt(n,a.message);return}const l=I(t)??{class:"person"},d=Ae(l),h=i(()=>s.handle(t,n,c,l),"handled");(d===void 0?h():B(d,i(async()=>{W()||await F(d),await h()},"handledAsPerson"))).catch(w)}catch(a){w(a)}},"onRequest"),U=i(async(t,n,c)=>{const u=I(t);return u===void 0||ce(u)||await ue(u,"either",c)?!0:(y(n,404,"Not Found","node_not_found",`no node ${c}`),!1)},"authorizeAttachUpgrade"),v=new Set,Z=i((t,n,c)=>{v.add(n),n.once("close",()=>v.delete(n)),n.on("error",()=>{});try{const u=new URL(t.url??"/","http://127.0.0.1"),b=f((t.method??"GET").toUpperCase(),u.pathname);if(b!==null){y(n,503,"Service Unavailable","startup_blocked",b.message);return}const g=nt(t.method??"GET",u.pathname);if(g===null){n.destroy();return}const w=(()=>{const a=I(t);return a===void 0?void 0:Ae(a)})(),S=i(()=>U(t,n,g).then(a=>a?er(t,n,c,g,async l=>{const d=I(t);return d===void 0||ce(d)||await ue(d,l,g)}):void 0),"attach");(w===void 0?S():B(w,async()=>{W()||await F(w),await S()})).catch(()=>{try{n.destroy()}catch{}})}catch{try{n.destroy()}catch{}}},"onUpgrade"),be=i(t=>{t.on("error",n=>{A({event:"api.server.failed",level:"error",error:n})})},"bindErrorHandler"),Te=i(async(t,n)=>{try{const c=await he(t,R);if(c==="unauthorized"){A({event:"api.principal.denied",level:"warn",fields:{method:t.method}}),J(n);return}if(c==="runtime_starting"){Se(n);return}z.set(t,c),ye(t,c),m(t,n,c.class==="app"?c.scopes:null)}catch(c){A({event:"api.principal.failed",level:"error",error:c instanceof Error?c:new Error(String(c))}),J(n)}},"onSocketRequest"),N=ee((t,n)=>{Te(t,n).catch(c=>A({event:"api.principal.failed",level:"error",error:c instanceof Error?c:new Error(String(c))}))}),Ce=i(async(t,n,c)=>{try{const u=await he(t,R);if(u==="unauthorized"||u==="runtime_starting"){u==="unauthorized"&&A({event:"api.principal.denied",level:"warn",fields:{method:t.method}}),y(n,u==="unauthorized"?401:503,"Unauthorized",u,"socket principal unavailable");return}if(u.class!=="person"&&u.class!=="broker"){y(n,403,"Forbidden",k.code,k.message);return}z.set(t,u),Z(t,n,c)}catch(u){A({event:"api.principal.failed",level:"error",error:u instanceof Error?u:new Error(String(u))}),y(n,401,"Unauthorized",T.code,T.message)}},"onSocketUpgrade");N.on("upgrade",(t,n,c)=>{Ce(t,n,c).catch(u=>A({event:"api.principal.failed",level:"error",error:u instanceof Error?u:new Error(String(u))}))}),ge((t,n,c)=>{z.set(t,c),m(t,n,null)});let K=!1,X,Q;const Oe=new Promise((t,n)=>{X=t,Q=n});N.once("listening",()=>{K=!0,X()}),N.on("error",t=>{A({event:"api.server.failed",level:"error",error:t}),K||Q(t)});try{$(p)&&te(p)}catch{}N.listen(p,()=>{try{ke(p,process.platform==="linux"&&$("/run/crtr/launcher.sock")?438:384)}catch(t){A({event:"api.socket.chmod_failed",level:"error",error:t instanceof Error?t:new Error(String(t))})}});let _;const L=e.tcp??Qe()??ae("user").api.tcp;if(L!==void 0&&L!==""){const t=ot(L);if(t===null)A({event:"api.tcp.invalid",level:"error",error:new Error(`invalid CRTRD_TCP/--tcp spec: ${L}`)});else{P()&&x();const n=e.token??qe()??Ke("user"),c=st(n),u=i(async(a,l)=>{if(pt(a,l))return;if(P()&&Je(new URL(a.url??"/","http://runtime.local").pathname)){await ut(a,l);return}if(await gt(a,l))return;const d=await we(a,c);if(d==="runtime_starting"){O(l),Se(l);return}if(d==="person_bearer"){ft(l);return}if(d==="unauthorized"){A({event:"api.principal.denied",level:"warn",fields:{method:a.method,listener:"tcp"}}),J(l,!0);return}if("call"in d){O(l);const h=d.call.sub;await B(h,async()=>{W()||await F(h),await ct()(a,l,d.call)});return}z.set(a,d.principal),ye(a,d.principal),O(l),m(a,l,d.ceiling)},"tcpOnRequest"),b=i(async(a,l,d)=>{const h=await we(a,c);if(h==="runtime_starting"){y(l,503,"Service Unavailable","runtime_starting","grant sync is not ready");return}if(h==="person_bearer"){y(l,401,"Unauthorized",H.code,H.message);return}if(h==="unauthorized"){y(l,401,"Unauthorized",T.code,T.message);return}if("call"in h){y(l,403,"Forbidden",k.code,k.message);return}if(h.ceiling!==null||h.principal.class==="anonymous"){y(l,403,"Forbidden",k.code,k.message);return}z.set(a,h.principal),Z(a,l,d)},"tcpOnUpgrade"),g=i(a=>{A({event:"api.principal.failed",level:"error",error:a instanceof Error?a:new Error(String(a))})},"failed"),w=i((a,l)=>{u(a,l).catch(d=>{g(d),l.headersSent?l.destroy():J(l,!0)})},"listener"),S=dt();_=S===null?ee(w):Pe(S,w),_.on("upgrade",(a,l,d)=>{l.on("error",()=>{}),b(a,l,d).catch(h=>{g(h),y(l,401,"Unauthorized",T.code,T.message)})}),be(_),_.once("listening",()=>{const a=_?.address();if(a!==null&&typeof a=="object"){const{address:l,port:d}=a;r=it(l,d)}}),_.listen(t.port,t.host)}}let q=!1;return{ready:Oe,tcpAddress:i(()=>r,"tcpAddress"),close:i(async(t={})=>{if(!q){q=!0,ge(null),lr.close(),await Promise.all([Ee(N,v,t.graceMs),_!==void 0?Ee(_,v,t.graceMs):Promise.resolve()]);try{$(p)&&te(p)}catch{}}},"close")}}i(qn,"createApiServer");export{tt as buildRouter,Ee as closeServer,qn as createApiServer,I as socketPrincipal};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var u=Object.defineProperty;var i=(e,t)=>u(e,"name",{value:t,configurable:!0});import{covers as d}from"@north-light/identity";import{ApiError as c}from"../../api/index.js";import{
|
|
1
|
+
var u=Object.defineProperty;var i=(e,t)=>u(e,"name",{value:t,configurable:!0});import{covers as d}from"@north-light/identity";import{ApiError as c}from"../../api/index.js";import{directoryIssuer as g}from"../../core/directory/issuer.js";import{activeRecord as l,grantRecord as f}from"../../core/grants/mirror.js";import{modelAuthReadiness as m}from"../../core/model-auth/readiness.js";import{isUnsandboxedMachine as _}from"../../core/runtime/unsandboxed.js";import{isOwnMemoryScope as h,scopeAllowed as a}from"../../core/scopes.js";function n(e,t,r){return{allowed:!1,reason:e,message:t,...r===void 0?{}:{url:r}}}i(n,"refuse");function p(){const e=g();return e===null?null:`${e}/account/ai-subscription`}i(p,"modelSignInUrl");function R(e){return e.reason==="model_sign_in_required"?new c(409,"model_sign_in_required",e.message,e.url===void 0?void 0:{url:e.url}):e.reason==="scope_missing"?new c(403,"scope_missing",e.message):new c(401,"grant_revoked",e.message)}i(R,"cronRefusalError");async function $(e){if(e.grantee!=="app:terminal"&&_())return n("unsandboxed_machine",`This computer runs only your own terminal agents; ${e.grantee} runs on your hosted machine.`);let t;if(e.grant_id===null)return n("grant_missing",`cron has no grant for ${e.grantee}; re-arm it from a node of that app`);{const r=await f(e.grant_id);if(r===null)return n("grant_missing",`grant ${e.grant_id} is not in this runtime's grant mirror`);if(r.status!=="active")return n("grant_revoked",`grant ${e.grant_id} is ${r.status}`);if(r.expires_at!==null&&Date.parse(r.expires_at)<=Date.now())return n("grant_revoked",`grant ${e.grant_id} expired at ${r.expires_at}`);if(r.grantee!==e.grantee||r.sub!==e.sub)return n("grant_revoked",`grant ${e.grant_id} no longer belongs to ${e.grantee} for ${e.sub}`);const o=l(r);if(o===null)return n("grant_revoked",`grant ${e.grant_id} cannot be read`);t=o.resolved}if(e.scopes!==null){const r=e.scopes.find(o=>!h(o,e.grantee)&&!t.some(s=>d(s,o)));if(r!==void 0)return n("scope_narrowed",`scope ${r} is no longer covered by the grant`)}return!a(t,"crtr:schedule")||!a(e.scopes,"crtr:schedule")?n("scope_missing","the cron no longer holds crtr:schedule"):{allowed:!0,effectiveScopes:t}}i($,"checkCronFire");async function q(e,t={}){const r=await $(e);if(!r.allowed)return r;if(!a(r.effectiveScopes,"crtr:act")||!a(e.scopes,"crtr:act"))return n("scope_missing","the cron no longer holds crtr:act");if(e.from_exec===!0){const o=await m(t);if(o.credential!=="ready"){const s=p()??void 0;return n("model_sign_in_required",`Starting an agent needs a signed-in AI subscription for ${o.provider}; sign in${s===void 0?" on your Northlight account":` at ${s}`}, then try again.`,s)}}return r}i(q,"checkCronBirth");function I(e){return{grantee:e.grantee,sub:e.sub,grant_id:e.grant_id,scopes:e.scopes,from_exec:e.armed_from_exec}}i(I,"cronPrincipalOf");export{q as checkCronBirth,$ as checkCronFire,I as cronPrincipalOf,R as cronRefusalError,p as modelSignInUrl};
|