@north-light/cli 0.3.507 → 0.3.509
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/client.d.ts +2 -1
- package/dist/api/client.js +3 -3
- package/dist/api/contract.d.ts +1 -1
- package/dist/api/contract.js +1 -1
- package/dist/api/dto/docs.d.ts +4 -0
- package/dist/api/routes.d.ts +1 -0
- package/dist/api/routes.js +1 -1
- package/dist/clients/attach/assets/mermaid.min.js +3631 -0
- package/dist/clients/attach/render/doc-links.d.ts +2 -5
- package/dist/clients/attach/render/doc-links.js +1 -1
- package/dist/clients/attach/session/document-links.d.ts +6 -18
- package/dist/clients/attach/session/document-links.js +1 -1
- package/dist/clients/attach/session/file-links.d.ts +0 -2
- package/dist/clients/attach/session/file-links.js +1 -1
- package/dist/clients/attach/viewer.js +558 -625
- package/dist/core/config.js +1 -1
- package/dist/core/graph/events.d.ts +1 -0
- package/dist/core/graph/events.js +6 -6
- package/dist/core/graph/names.d.ts +6 -3
- package/dist/core/graph/names.js +3 -3
- package/dist/core/user-settings.d.ts +4 -4
- package/dist/core/user-settings.js +1 -1
- package/dist/daemon/api/bridge.js +3 -3
- package/dist/daemon/api/document-listener.d.ts +7 -0
- package/dist/daemon/api/document-listener.js +11 -0
- package/dist/daemon/api/document-merge.d.ts +2 -0
- package/dist/daemon/api/document-merge.js +1 -0
- package/dist/daemon/api/document-secret.d.ts +2 -0
- package/dist/daemon/api/document-secret.js +1 -0
- package/dist/daemon/api/handlers/docs.d.ts +14 -0
- package/dist/daemon/api/handlers/docs.js +1 -1
- package/dist/daemon/api/handlers/document-access.d.ts +2 -0
- package/dist/daemon/api/handlers/document-access.js +1 -0
- package/dist/daemon/api/handlers/objects.js +3 -3
- package/dist/daemon/api/map.js +2 -2
- package/dist/daemon/api/operations.js +1 -1
- package/dist/daemon/api/router.js +1 -1
- package/dist/daemon/api/server.js +1 -1
- package/dist/daemon/api/vendor-signin.d.ts +1 -0
- package/dist/daemon/api/vendor-signin.js +1 -1
- package/dist/daemon/crtrd.js +9 -9
- package/dist/daemon/peer/ingress.js +1 -1
- package/dist/doc-editor/editor.css +1 -0
- package/dist/doc-editor/editor.js +53 -0
- package/dist/types.d.ts +2 -9
- package/dist/types.js +1 -1
- package/package.json +13 -2
- package/packages/crouter-identity/package.json +1 -1
- package/runtime.lock.json +364 -12
- package/dist/clients/attach/session/doc-html.d.ts +0 -8
- package/dist/clients/attach/session/doc-html.js +0 -66
- package/dist/clients/attach/session/doc-materialize.d.ts +0 -57
- package/dist/clients/attach/session/doc-materialize.js +0 -3
|
@@ -3,6 +3,7 @@ import { type StartedFlow } from '../../core/model-auth/flows.js';
|
|
|
3
3
|
import type { AppPrincipalResolver } from './principal.js';
|
|
4
4
|
export declare const VENDOR_SIGNIN_PATH = "/signin/vendor";
|
|
5
5
|
export declare function isVendorSignInPath(pathname: string): boolean;
|
|
6
|
+
export declare function escapeHtml(value: string): string;
|
|
6
7
|
export declare function anthropicPage(flow: StartedFlow, nonce: string, returnTo: string, handoff: string): string;
|
|
7
8
|
export declare function openaiPage(flow: StartedFlow, nonce: string, returnTo: string, handoff: string, now?: number): string;
|
|
8
9
|
/** Serve one `/signin/vendor*` request; errors propagate as RunErrors so the
|
|
@@ -189,4 +189,4 @@ ${h(3,"Approve the sign-in",`<span class="small">When OpenAI shows an account em
|
|
|
189
189
|
<div class="alert" id="expired" role="alert" hidden>${s("warn")}
|
|
190
190
|
<div class="text"><strong>The code expired before it was approved</strong>Codes last 15 minutes. Getting a new one starts the sign-in over.</div>
|
|
191
191
|
<div class="act"><button class="btn primary sm" type="button" id="renew">Get a new code</button></div></div>
|
|
192
|
-
</div>`,config:{kind:"openai",base:`${c}/${encodeURIComponent(e.flow_id)}`,returnTo:n,handoff:r,userCode:o,expiresAt:e.expires_at,remainingSeconds:X(e,i)}})}a(Y,"openaiPage");async function K(e,t,n,r){const i=w(n.searchParams,"handoff"),o=await M(r,i);if(x(o.jti))throw f();const l=w(n.searchParams,"return_to");let g;try{g=l===void 0?void 0:new URL(l).origin}catch{g=void 0}if(l===void 0||g!==new URL(r.issuer).origin)throw new d(400,"invalid_request","return_to must be an absolute URL on the directory origin","return_to");const p=w(n.searchParams,"vendor");if(p!=="anthropic"&&p!=="openai")throw new d(400,"invalid_request","vendor must be anthropic or openai","vendor");if(!E(o.jti,o.exp))throw f();let b;try{b=await N({provider:I(p),jti:o.jti})}catch(L){console.error("[vendor-signin] start failed:",L instanceof Error?L.message:L),t.writeHead(303,{Location:B(l,"failed"),"Cache-Control":"no-store","Referrer-Policy":"no-referrer"}),t.end();return}const v=A(16).toString("base64"),T=p==="anthropic"?W(b,v,l,i):Y(b,v,l,i);t.writeHead(200,{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store","Referrer-Policy":"no-referrer","X-Content-Type-Options":"nosniff","Content-Security-Policy":`default-src 'none'; script-src 'nonce-${v}'; style-src 'nonce-${v}'; connect-src 'self'; form-action 'none'; base-uri 'none'; frame-ancestors 'none'`}),t.end(T)}a(K,"startPage");async function S(e,t,n){const r=await M(t,D(e)),i=C(n);if(!i){if(x(r.jti))return!1;throw f()}if(i.jti===void 0||i.jti!==r.jti)throw f();return!0}a(S,"followUpFlow");async function Q(e,t,n,r){if(!await S(e,n,r)){m(t,200,{status:"failed"});return}const i=await G(e);try{await j(r,i.input),m(t,200,{status:"connected"})}catch(o){const l=C(r);if(l&&l.status!=="pending"){m(t,200,{status:"failed"});return}throw o}}a(Q,"submitCode");async function e1(e,t,n,r){if(!await S(e,n,r)){m(t,200,{status:"failed"});return}const i=new AbortController;t.once("close",()=>i.abort());const o=await P(r,H,i.signal);m(t,200,{status:o?.status??"failed"})}a(e1,"waitFlow");async function d1(e,t,n,r){const i=e.method??"GET";if(n.pathname===c&&i==="GET"){await K(e,t,n,r);return}const o=n.pathname.slice(c.length+1).split("/");let l="";try{l=o[0]?decodeURIComponent(o[0]):""}catch{throw new d(404,"not_found","unknown operation")}if(l&&o.length===1&&i==="POST"){await Q(e,t,r,l);return}if(l&&o.length===2&&o[1]==="wait"&&i==="GET"){await e1(e,t,r,l);return}throw new d(404,"not_found","unknown operation")}a(d1,"handleVendorSignIn");export{c as VENDOR_SIGNIN_PATH,W as anthropicPage,d1 as handleVendorSignIn,s1 as isVendorSignInPath,Y as openaiPage};
|
|
192
|
+
</div>`,config:{kind:"openai",base:`${c}/${encodeURIComponent(e.flow_id)}`,returnTo:n,handoff:r,userCode:o,expiresAt:e.expires_at,remainingSeconds:X(e,i)}})}a(Y,"openaiPage");async function K(e,t,n,r){const i=w(n.searchParams,"handoff"),o=await M(r,i);if(x(o.jti))throw f();const l=w(n.searchParams,"return_to");let g;try{g=l===void 0?void 0:new URL(l).origin}catch{g=void 0}if(l===void 0||g!==new URL(r.issuer).origin)throw new d(400,"invalid_request","return_to must be an absolute URL on the directory origin","return_to");const p=w(n.searchParams,"vendor");if(p!=="anthropic"&&p!=="openai")throw new d(400,"invalid_request","vendor must be anthropic or openai","vendor");if(!E(o.jti,o.exp))throw f();let b;try{b=await N({provider:I(p),jti:o.jti})}catch(L){console.error("[vendor-signin] start failed:",L instanceof Error?L.message:L),t.writeHead(303,{Location:B(l,"failed"),"Cache-Control":"no-store","Referrer-Policy":"no-referrer"}),t.end();return}const v=A(16).toString("base64"),T=p==="anthropic"?W(b,v,l,i):Y(b,v,l,i);t.writeHead(200,{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store","Referrer-Policy":"no-referrer","X-Content-Type-Options":"nosniff","Content-Security-Policy":`default-src 'none'; script-src 'nonce-${v}'; style-src 'nonce-${v}'; connect-src 'self'; form-action 'none'; base-uri 'none'; frame-ancestors 'none'`}),t.end(T)}a(K,"startPage");async function S(e,t,n){const r=await M(t,D(e)),i=C(n);if(!i){if(x(r.jti))return!1;throw f()}if(i.jti===void 0||i.jti!==r.jti)throw f();return!0}a(S,"followUpFlow");async function Q(e,t,n,r){if(!await S(e,n,r)){m(t,200,{status:"failed"});return}const i=await G(e);try{await j(r,i.input),m(t,200,{status:"connected"})}catch(o){const l=C(r);if(l&&l.status!=="pending"){m(t,200,{status:"failed"});return}throw o}}a(Q,"submitCode");async function e1(e,t,n,r){if(!await S(e,n,r)){m(t,200,{status:"failed"});return}const i=new AbortController;t.once("close",()=>i.abort());const o=await P(r,H,i.signal);m(t,200,{status:o?.status??"failed"})}a(e1,"waitFlow");async function d1(e,t,n,r){const i=e.method??"GET";if(n.pathname===c&&i==="GET"){await K(e,t,n,r);return}const o=n.pathname.slice(c.length+1).split("/");let l="";try{l=o[0]?decodeURIComponent(o[0]):""}catch{throw new d(404,"not_found","unknown operation")}if(l&&o.length===1&&i==="POST"){await Q(e,t,r,l);return}if(l&&o.length===2&&o[1]==="wait"&&i==="GET"){await e1(e,t,r,l);return}throw new d(404,"not_found","unknown operation")}a(d1,"handleVendorSignIn");export{c as VENDOR_SIGNIN_PATH,W as anthropicPage,u as escapeHtml,d1 as handleVendorSignIn,s1 as isVendorSignInPath,Y as openaiPage};
|
package/dist/daemon/crtrd.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
var Ee=Object.defineProperty;var a=(t,n)=>Ee(t,"name",{value:n,configurable:!0});import{startPeerOutbox as Re}from"./peer/outbox.js";import{reportMachineStatus as xe}from"../core/peer/directory.js";import{createPeerRelay as Pe}from"./peer/relay-service.js";import{writeFileSync as Ie,readFileSync as Te,rmSync as De,mkdirSync as Z,existsSync as k,chmodSync as Ce}from"node:fs";import{createServer as ee}from"node:http";import{dirname as $e}from"node:path";import{envCrtrdTcp as Le}from"../shared/env.js";import{serveCanvasConversationStore as Ae}from"../core/canvas/sessions.js";import{pollRunObservers as Ne}from"./runs/observer.js";import{randomBytes as Me}from"node:crypto";import{apiSocketPath as Oe,crtrHome as Ge}from"../core/canvas/paths.js";import{activeAppUsers as Fe}from"../core/spaces/users.js";import{ensureAppSpace as He,ensureUserFiles as je}from"../core/spaces/space.js";import{LAUNCHER_SOCKET as x}from"../launcher/spec.js";import{launcherRequest as I}from"../launcher/client.js";import{installLauncherEventSink as Be}from"./launcher-events.js";import{initializeEmptyLayout as qe,layoutNeedsMigration as ze,socketDir as re}from"../core/layout.js";import{migrateLooseKeys as We}from"../core/layout-migrate/loose-keys.js";import{relocateProfileFolders as Ue}from"../core/profiles/relocate.js";import{getNode as Ke,listNodesForSupervision as te,setFrozen as ne}from"../core/canvas/index.js";import{createApiServer as Je}from"./api/server.js";import{createAppListener as Ve}from"./api/app-listener.js";import{installLocalTerminalGrant as Qe}from"../core/grants/local.js";import{onRunEventAppended as Ye}from"../core/runs/events.js";import{runNotices as Xe}from"./run-notices.js";import{createGrantSync as Ze,GRANT_SYNC_INTERVAL_S as er}from"../core/grants/sync.js";import{runRemovalCascades as rr}from"../core/grants/remove.js";import{sweepSandboxes as tr}from"../core/grants/on-sync.js";import{rebuildCronExecutions as nr}from"./cron/run-socket.js";import{hasSyncedGrants as or}from"../core/grants/mirror.js";import{readConfig as ir}from"../core/config.js";import{reconcileUndeliveredTickets as sr}from"./human/sweep.js";import{resetHandedOffDeliveries as ar}from"../core/canvas/deliveries.js";import{resetHandedOffDaemonActions as cr}from"../core/canvas/daemon-actions.js";import{sweepReviews as dr}from"./review/sweep.js";import{pidfilePath as F}from"./pidfile.js";import{rendererWarning as lr}from"../core/runtime/package-health.js";import{DEFAULT_INTERVAL_MS as pr}from"./supervise-cadence.js";import{createResumeDetector as mr}from"./resume-detector.js";import{BrokerSupervisionReconciler as fr}from"./reconcilers/broker-supervision.js";import{ControllerDeathReconciler as ur}from"./reconcilers/controller-death.js";import{NodeLifecycleReconciler as hr}from"./reconcilers/node-lifecycle/tick.js";import{NodeDeadlineReconciler as vr}from"./reconcilers/node-deadline.js";import{CronLaneReconciler as wr}from"./reconcilers/cron-lane.js";import{DeliveryLaneReconciler as gr}from"./reconcilers/delivery-lane.js";import{ActionLaneReconciler as yr}from"./reconcilers/action-lane.js";import{endLiveExecution as Sr,migrateLegacyExecutionIdentities as _r}from"../core/canvas/executions.js";import{revokePriorEpochNodeTokens as br}from"../core/canvas/node-tokens.js";import{PendingReviewSubmitReconciler as kr}from"./reconcilers/pending-review-submit.js";import{StorageMaintenanceReconciler as Er}from"./reconcilers/storage-maintenance.js";import{StorageDueWorkReconciler as Rr}from"./reconcilers/storage-due-work.js";import{BashDeadlineReconciler as xr}from"./reconcilers/bash-deadline.js";import{FaultRetryBackstopReconciler as Pr}from"./reconcilers/fault-retry-backstop.js";import{StructuredRequestReconciler as Ir}from"./reconcilers/structured-request-lane.js";import{reconcileStructuredRequestSidecars as Tr}from"./structured-requests/boot.js";import{captureLivenessSnapshot as oe,capturePidCommand as Dr,captureTeardownSnapshot as ie,isPidAlive as Cr,isAnyPidAlive as se,killProcessTreePids as ae}from"../core/canvas/pid.js";import{bindFleet as $r,boundFleet as Lr}from"../core/runtime/fleet.js";import{bindDaemonControl as Ar,clearDaemonControl as Nr}from"./control.js";import{execDaemon as Mr,spawnDaemon as Or}from"./manage.js";import{reconcileAndMigrateBoot as Gr}from"../core/canvas/boot.js";import{resolveInstallId as Fr}from"../core/canvas/install-id.js";import{setInstallId as Hr}from"../core/runtime/nodes.js";import{claimDaemonOwnership as jr,releaseDaemonOwnership as ce}from"../core/canvas/daemon-owner.js";import{migrate as Br,openDb as de,withCanvasWrite as qr,bindDaemonCanvasOpenHook as zr,clearDaemonCanvasOpenHook as le}from"../core/canvas/db.js";import{brokerSignalBus as H}from"./broker-signals/bus.js";import{brokerSignalStreams as Wr}from"./api/handlers/broker-signals.js";import{reconcilePackages as Ur}from"../core/graph/package-reconcile.js";import{startRepoSync as Kr}from"../core/graph/repo-sync/index.js";import{prewarmRecentRecipes as Jr,reapStaleSpares as Vr}from"../core/runtime/warm-pool.js";import{DaemonFleet as Qr}from"./fleet.js";import{BOOT_MIGRATIONS as Yr}from"./boot-migrations.js";import{applyJoinedOwner as Xr}from"./joined-owner.js";import{emitEvent as u}from"../core/events/emit.js";import{operationIdContext as S}from"../core/events/operation-id.js";import{bindDaemonEventSource as Zr}from"../core/events/source.js";import{activateCanvasImport as et,MigrationBlockedError as rt,runForcedCanvasImport as tt}from"../migrations/activation.js";import{convertLegacyProviderStore as nt,convertLegacyScopedStore as ot}from"../core/scoped-state/migrate.js";import{userScopeRoot as it}from"../core/scope.js";import{secretsDir as st}from"../core/layout.js";function j(t,n){return t.includes(` --canvas-home ${n} `)}a(j,"brokerCommandDeclaresCanvasHome");function B(t){return/ --epoch (\S+) /.exec(t)?.[1]??null}a(B,"brokerCommandEpoch");const at=5e3,pe=150;async function ct(t){const n=oe();if(n===null)throw u({level:"error",event:"daemon.census.snapshot_failed",fields:{invariant:"prior-epoch brokers are reaped before readiness"}}),new Error("prior-epoch broker census could not capture the process table");const c=Ge(),m=[];for(const[s,p]of n.processes){const y=p.command;if(p.zombie||!y.includes("broker-cli.js")||!j(y,c)||B(y)===t)continue;const _=y.trim().split(/\s+/).at(-1)??"";_===""||_.endsWith("broker-cli.js")||m.push({pid:s,nodeId:_})}let f=0;const o=[];for(const s of m){const p=Dr(s.pid);if(p===null||!p.includes("broker-cli.js")||!j(p,c)||B(p)===t||p.trim().split(/\s+/).at(-1)!==s.nodeId)continue;const y=ie(s.pid,null);if(!y.reused){try{process.platform==="linux"&&k(x)?await I({operation:"stop",pid:s.pid}):process.kill(s.pid,"SIGTERM")}catch{continue}f++,o.push({pid:s.pid,snap:y})}}const g=Date.now()+at;for(;Date.now()<g&&o.some(s=>se(s.snap.tree.length>0?s.snap.tree:[s.pid]));)await new Promise(s=>setTimeout(s,pe));let v=0;for(const s of o){const p=s.snap.tree.length>0?s.snap.tree:[s.pid];se(p)&&(process.platform==="linux"&&k(x)?await I({operation:"stop",pid:s.pid}):ae(p,"SIGKILL",s.snap.identities),v++)}v>0&&await new Promise(s=>setTimeout(s,pe));const d=oe();if(d===null)throw u({level:"error",event:"daemon.census.snapshot_failed",fields:{invariant:"prior-epoch brokers are reaped before readiness",stage:"final"}}),new Error("prior-epoch broker census could not capture the final process table");const l=[];for(const[s,p]of d.processes){const y=p.command;p.zombie||!y.includes("broker-cli.js")||j(y,c)&&B(y)!==t&&l.push(s)}if(l.length>0)throw new Error(`prior-epoch broker census could not prove termination of pid(s): ${l.join(", ")}`);u({level:"info",event:"daemon.census.completed",fields:{prior_epoch_brokers:m.length,sigtermed:f,sigkilled:v}})}a(ct,"reapPriorEpochBrokers");const dt=5e3;async function lt(t){const n=Array.from(t.entries());if(n.length===0)return;for(const[o]of n){const g=Ke(o)?.status;(g==="active"||g==="idle")&&ne(o,new Date().toISOString())}const c=n.map(([,o])=>({pid:o.pid,snap:ie(o.pid,null),exited:o.handle.exited}));for(const o of c)if(!o.snap.reused)try{process.platform==="linux"&&k(x)?await I({operation:"stop",pid:o.pid}):process.kill(o.pid,"SIGTERM")}catch{}const m=new Promise(o=>{setTimeout(o,dt).unref()});await Promise.allSettled(c.map(o=>Promise.race([o.exited.then(()=>{}),m])));const f=[];for(const o of c)Cr(o.pid)&&(process.platform==="linux"&&k(x)?await I({operation:"stop",pid:o.pid}):ae(o.snap.tree.length>0?o.snap.tree:[o.pid],"SIGKILL",o.snap.identities),f.push(o));await Promise.all(f.map(o=>o.exited));for(const[o]of n)Sr(o,{reason:"daemon-teardown"});u({level:"info",event:"daemon.fleet_teardown.completed",fields:{brokers:c.length,sigkilled:f.length}})}a(lt,"teardownFleet");function me(){Z($e(F()),{recursive:!0}),Ie(F(),String(process.pid),"utf8")}a(me,"writePidfile");function fe(t){return typeof t=="object"&&t!==null&&t.code==="ENOENT"}a(fe,"isMissingPathError");function ue(t){const n=F();let c;try{c=Te(n,"utf8")}catch(m){if(fe(m))return;throw m}if(c.trim()!==String(t))throw new Error(`daemon readiness mirror does not name this invocation (expected pid ${t})`);try{De(n)}catch(m){if(fe(m))return;throw m}}a(ue,"removeOwnedPidfileMirror");const pt={acceptsDetachedWork:a(()=>!0,"acceptsDetachedWork"),registerDetached:a(t=>{t.catch(()=>{})},"registerDetached")},q=new fr,mt=new ur,ft=new hr,ut=new vr,ht=new wr,vt=new gr,wt=new yr,gt=new kr,yt=new Er,St=new Rr,_t=new xr,bt=new Pr,kt=new Ir;async function Et(t=Date.now(),n=pt){const c=Lr(),m=await q.runFleetPreamble(c);let f,o;try{const v=te();f=v.filter(d=>d.status==="active"||d.status==="idle"),o=v.filter(d=>d.status==="done"||d.status==="canceled"||d.status==="dead")}catch(v){u({level:"error",event:"canvas.node_list.failed",error:v});return}await q.run(t,{rows:f,fleet:c,lifecycle:n}),mt.run(t,{rows:f});const g=await ft.run(t,{rows:[...f,...o],fleet:c});ut.run(t),kt.run(t),ht.run(t,{lifecycle:n}),vt.run(t,{lifecycle:n}),wt.run(t,{lifecycle:n}),gt.run(t,{lifecycle:n}),yt.run(t,{lifecycle:n,fleet:c}),St.run(t,{lifecycle:n}),Ne(),bt.run(t,{fleet:c,lifecycle:n}),await _t.run(t,{rows:f}),q.warnIfSaturated({fleet:c,lifecycle:n,thresholds:m,frozen:g})}a(Et,"superviseTick");async function Rt(t){Z(re(),{recursive:!0,mode:493}),process.platform==="linux"&&Ce(re(),493);const n=Oe();if(k(n))throw new Error(`layout refusal cannot bind occupied socket: ${n}`);const c=ee((d,l)=>{if(d.method==="GET"&&d.url==="/healthz"){l.writeHead(200,{"content-type":"application/json; charset=utf-8"}),l.end(JSON.stringify({ok:!1,daemon_up:!0,store_accessible:!1,brokers_reconciled:!1,startup_phase:"blocked",startup_blocked:"layout_migration_required"}));return}l.writeHead(503,{"content-type":"application/json; charset=utf-8"}),l.end(JSON.stringify({error:{code:"layout_migration_required",message:"run crtr sys migrate while the runtime is offline",type:"server_error",origin:"runtime",retryable:!1}}))});await new Promise((d,l)=>{c.once("error",l),c.listen(n,()=>{c.off("error",l),d()})});let m;const f=t.tcp??Le();if(f){const d=/^(.*):(\d+)$/.exec(f);if(!d||Number(d[2])>65535)throw new Error(`invalid refusal TCP address: ${f}`);const l=ee(c.listeners("request")[0]);await new Promise((s,p)=>{l.once("error",p),l.listen(Number(d[2]),d[1],()=>{l.off("error",p),s()})}),m=l}me();let o;const g=a(()=>(o??=(async()=>{c.closeAllConnections(),m?.closeAllConnections(),await Promise.all([c,m].filter(d=>d!==void 0).map(d=>new Promise((l,s)=>d.close(p=>p?s(p):l())))),ue(process.pid),process.off("SIGINT",v),process.off("SIGTERM",v)})(),o),"cleanup"),v=a(()=>{g().then(()=>process.exit(0),d=>{process.stderr.write(`[crtrd] layout refusal cleanup failed: ${String(d)}
|
|
2
|
-
`),process.exit(1)})},"onSignal");return process.on("SIGINT",
|
|
1
|
+
var Pe=Object.defineProperty;var a=(t,n)=>Pe(t,"name",{value:n,configurable:!0});import{startPeerOutbox as xe}from"./peer/outbox.js";import{reportMachineStatus as Ie}from"../core/peer/directory.js";import{createPeerRelay as De}from"./peer/relay-service.js";import{writeFileSync as Te,readFileSync as Ce,rmSync as $e,mkdirSync as ee,existsSync as E,chmodSync as Le}from"node:fs";import{createServer as re}from"node:http";import{dirname as Ae}from"node:path";import{envCrtrdTcp as Ne}from"../shared/env.js";import{serveCanvasConversationStore as Me}from"../core/canvas/sessions.js";import{pollRunObservers as Oe}from"./runs/observer.js";import{randomBytes as Ge}from"node:crypto";import{apiSocketPath as Fe,crtrHome as He}from"../core/canvas/paths.js";import{activeAppUsers as je}from"../core/spaces/users.js";import{ensureAppSpace as Be,ensureUserFiles as qe}from"../core/spaces/space.js";import{LAUNCHER_SOCKET as x}from"../launcher/spec.js";import{launcherRequest as D}from"../launcher/client.js";import{installLauncherEventSink as ze}from"./launcher-events.js";import{initializeEmptyLayout as We,layoutNeedsMigration as Ue,socketDir as te}from"../core/layout.js";import{migrateLooseKeys as Ke}from"../core/layout-migrate/loose-keys.js";import{relocateProfileFolders as Je}from"../core/profiles/relocate.js";import{getNode as Ve,listNodesForSupervision as ne,setFrozen as oe}from"../core/canvas/index.js";import{createApiServer as Qe}from"./api/server.js";import{createDocumentListener as Ye}from"./api/document-listener.js";import{documentSecret as Xe}from"./api/document-secret.js";import{createAppListener as Ze}from"./api/app-listener.js";import{installLocalTerminalGrant as er}from"../core/grants/local.js";import{onRunEventAppended as rr}from"../core/runs/events.js";import{runNotices as tr}from"./run-notices.js";import{createGrantSync as nr,GRANT_SYNC_INTERVAL_S as or}from"../core/grants/sync.js";import{runRemovalCascades as ir}from"../core/grants/remove.js";import{sweepSandboxes as sr}from"../core/grants/on-sync.js";import{rebuildCronExecutions as ar}from"./cron/run-socket.js";import{hasSyncedGrants as cr}from"../core/grants/mirror.js";import{readConfig as ie}from"../core/config.js";import{reconcileUndeliveredTickets as dr}from"./human/sweep.js";import{resetHandedOffDeliveries as lr}from"../core/canvas/deliveries.js";import{resetHandedOffDaemonActions as pr}from"../core/canvas/daemon-actions.js";import{sweepReviews as mr}from"./review/sweep.js";import{pidfilePath as j}from"./pidfile.js";import{rendererWarning as fr}from"../core/runtime/package-health.js";import{DEFAULT_INTERVAL_MS as ur}from"./supervise-cadence.js";import{createResumeDetector as hr}from"./resume-detector.js";import{BrokerSupervisionReconciler as vr}from"./reconcilers/broker-supervision.js";import{ControllerDeathReconciler as wr}from"./reconcilers/controller-death.js";import{NodeLifecycleReconciler as gr}from"./reconcilers/node-lifecycle/tick.js";import{NodeDeadlineReconciler as yr}from"./reconcilers/node-deadline.js";import{CronLaneReconciler as Sr}from"./reconcilers/cron-lane.js";import{DeliveryLaneReconciler as _r}from"./reconcilers/delivery-lane.js";import{ActionLaneReconciler as br}from"./reconcilers/action-lane.js";import{endLiveExecution as kr,migrateLegacyExecutionIdentities as Er}from"../core/canvas/executions.js";import{revokePriorEpochNodeTokens as Rr}from"../core/canvas/node-tokens.js";import{PendingReviewSubmitReconciler as Pr}from"./reconcilers/pending-review-submit.js";import{StorageMaintenanceReconciler as xr}from"./reconcilers/storage-maintenance.js";import{StorageDueWorkReconciler as Ir}from"./reconcilers/storage-due-work.js";import{BashDeadlineReconciler as Dr}from"./reconcilers/bash-deadline.js";import{FaultRetryBackstopReconciler as Tr}from"./reconcilers/fault-retry-backstop.js";import{StructuredRequestReconciler as Cr}from"./reconcilers/structured-request-lane.js";import{reconcileStructuredRequestSidecars as $r}from"./structured-requests/boot.js";import{captureLivenessSnapshot as se,capturePidCommand as Lr,captureTeardownSnapshot as ae,isPidAlive as Ar,isAnyPidAlive as ce,killProcessTreePids as de}from"../core/canvas/pid.js";import{bindFleet as Nr,boundFleet as Mr}from"../core/runtime/fleet.js";import{bindDaemonControl as Or,clearDaemonControl as Gr}from"./control.js";import{execDaemon as Fr,spawnDaemon as Hr}from"./manage.js";import{reconcileAndMigrateBoot as jr}from"../core/canvas/boot.js";import{resolveInstallId as Br}from"../core/canvas/install-id.js";import{setInstallId as qr}from"../core/runtime/nodes.js";import{claimDaemonOwnership as zr,releaseDaemonOwnership as le}from"../core/canvas/daemon-owner.js";import{migrate as Wr,openDb as pe,withCanvasWrite as Ur,bindDaemonCanvasOpenHook as Kr,clearDaemonCanvasOpenHook as me}from"../core/canvas/db.js";import{brokerSignalBus as B}from"./broker-signals/bus.js";import{brokerSignalStreams as Jr}from"./api/handlers/broker-signals.js";import{reconcilePackages as Vr}from"../core/graph/package-reconcile.js";import{startRepoSync as Qr}from"../core/graph/repo-sync/index.js";import{prewarmRecentRecipes as Yr,reapStaleSpares as Xr}from"../core/runtime/warm-pool.js";import{DaemonFleet as Zr}from"./fleet.js";import{BOOT_MIGRATIONS as et}from"./boot-migrations.js";import{applyJoinedOwner as rt}from"./joined-owner.js";import{emitEvent as f}from"../core/events/emit.js";import{operationIdContext as _}from"../core/events/operation-id.js";import{bindDaemonEventSource as tt}from"../core/events/source.js";import{activateCanvasImport as nt,MigrationBlockedError as ot,runForcedCanvasImport as it}from"../migrations/activation.js";import{convertLegacyProviderStore as st,convertLegacyScopedStore as at}from"../core/scoped-state/migrate.js";import{userScopeRoot as ct}from"../core/scope.js";import{secretsDir as dt}from"../core/layout.js";function q(t,n){return t.includes(` --canvas-home ${n} `)}a(q,"brokerCommandDeclaresCanvasHome");function z(t){return/ --epoch (\S+) /.exec(t)?.[1]??null}a(z,"brokerCommandEpoch");const lt=5e3,fe=150;async function pt(t){const n=se();if(n===null)throw f({level:"error",event:"daemon.census.snapshot_failed",fields:{invariant:"prior-epoch brokers are reaped before readiness"}}),new Error("prior-epoch broker census could not capture the process table");const c=He(),u=[];for(const[s,m]of n.processes){const y=m.command;if(m.zombie||!y.includes("broker-cli.js")||!q(y,c)||z(y)===t)continue;const b=y.trim().split(/\s+/).at(-1)??"";b===""||b.endsWith("broker-cli.js")||u.push({pid:s,nodeId:b})}let h=0;const o=[];for(const s of u){const m=Lr(s.pid);if(m===null||!m.includes("broker-cli.js")||!q(m,c)||z(m)===t||m.trim().split(/\s+/).at(-1)!==s.nodeId)continue;const y=ae(s.pid,null);if(!y.reused){try{process.platform==="linux"&&E(x)?await D({operation:"stop",pid:s.pid}):process.kill(s.pid,"SIGTERM")}catch{continue}h++,o.push({pid:s.pid,snap:y})}}const g=Date.now()+lt;for(;Date.now()<g&&o.some(s=>ce(s.snap.tree.length>0?s.snap.tree:[s.pid]));)await new Promise(s=>setTimeout(s,fe));let w=0;for(const s of o){const m=s.snap.tree.length>0?s.snap.tree:[s.pid];ce(m)&&(process.platform==="linux"&&E(x)?await D({operation:"stop",pid:s.pid}):de(m,"SIGKILL",s.snap.identities),w++)}w>0&&await new Promise(s=>setTimeout(s,fe));const d=se();if(d===null)throw f({level:"error",event:"daemon.census.snapshot_failed",fields:{invariant:"prior-epoch brokers are reaped before readiness",stage:"final"}}),new Error("prior-epoch broker census could not capture the final process table");const p=[];for(const[s,m]of d.processes){const y=m.command;m.zombie||!y.includes("broker-cli.js")||q(y,c)&&z(y)!==t&&p.push(s)}if(p.length>0)throw new Error(`prior-epoch broker census could not prove termination of pid(s): ${p.join(", ")}`);f({level:"info",event:"daemon.census.completed",fields:{prior_epoch_brokers:u.length,sigtermed:h,sigkilled:w}})}a(pt,"reapPriorEpochBrokers");const mt=5e3;async function ft(t){const n=Array.from(t.entries());if(n.length===0)return;for(const[o]of n){const g=Ve(o)?.status;(g==="active"||g==="idle")&&oe(o,new Date().toISOString())}const c=n.map(([,o])=>({pid:o.pid,snap:ae(o.pid,null),exited:o.handle.exited}));for(const o of c)if(!o.snap.reused)try{process.platform==="linux"&&E(x)?await D({operation:"stop",pid:o.pid}):process.kill(o.pid,"SIGTERM")}catch{}const u=new Promise(o=>{setTimeout(o,mt).unref()});await Promise.allSettled(c.map(o=>Promise.race([o.exited.then(()=>{}),u])));const h=[];for(const o of c)Ar(o.pid)&&(process.platform==="linux"&&E(x)?await D({operation:"stop",pid:o.pid}):de(o.snap.tree.length>0?o.snap.tree:[o.pid],"SIGKILL",o.snap.identities),h.push(o));await Promise.all(h.map(o=>o.exited));for(const[o]of n)kr(o,{reason:"daemon-teardown"});f({level:"info",event:"daemon.fleet_teardown.completed",fields:{brokers:c.length,sigkilled:h.length}})}a(ft,"teardownFleet");function ue(){ee(Ae(j()),{recursive:!0}),Te(j(),String(process.pid),"utf8")}a(ue,"writePidfile");function he(t){return typeof t=="object"&&t!==null&&t.code==="ENOENT"}a(he,"isMissingPathError");function ve(t){const n=j();let c;try{c=Ce(n,"utf8")}catch(u){if(he(u))return;throw u}if(c.trim()!==String(t))throw new Error(`daemon readiness mirror does not name this invocation (expected pid ${t})`);try{$e(n)}catch(u){if(he(u))return;throw u}}a(ve,"removeOwnedPidfileMirror");const ut={acceptsDetachedWork:a(()=>!0,"acceptsDetachedWork"),registerDetached:a(t=>{t.catch(()=>{})},"registerDetached")},W=new vr,ht=new wr,vt=new gr,wt=new yr,gt=new Sr,yt=new _r,St=new br,_t=new Pr,bt=new xr,kt=new Ir,Et=new Dr,Rt=new Tr,Pt=new Cr;async function xt(t=Date.now(),n=ut){const c=Mr(),u=await W.runFleetPreamble(c);let h,o;try{const w=ne();h=w.filter(d=>d.status==="active"||d.status==="idle"),o=w.filter(d=>d.status==="done"||d.status==="canceled"||d.status==="dead")}catch(w){f({level:"error",event:"canvas.node_list.failed",error:w});return}await W.run(t,{rows:h,fleet:c,lifecycle:n}),ht.run(t,{rows:h});const g=await vt.run(t,{rows:[...h,...o],fleet:c});wt.run(t),Pt.run(t),gt.run(t,{lifecycle:n}),yt.run(t,{lifecycle:n}),St.run(t,{lifecycle:n}),_t.run(t,{lifecycle:n}),bt.run(t,{lifecycle:n,fleet:c}),kt.run(t,{lifecycle:n}),Oe(),Rt.run(t,{fleet:c,lifecycle:n}),await Et.run(t,{rows:h}),W.warnIfSaturated({fleet:c,lifecycle:n,thresholds:u,frozen:g})}a(xt,"superviseTick");async function It(t){ee(te(),{recursive:!0,mode:493}),process.platform==="linux"&&Le(te(),493);const n=Fe();if(E(n))throw new Error(`layout refusal cannot bind occupied socket: ${n}`);const c=re((d,p)=>{if(d.method==="GET"&&d.url==="/healthz"){p.writeHead(200,{"content-type":"application/json; charset=utf-8"}),p.end(JSON.stringify({ok:!1,daemon_up:!0,store_accessible:!1,brokers_reconciled:!1,startup_phase:"blocked",startup_blocked:"layout_migration_required"}));return}p.writeHead(503,{"content-type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:{code:"layout_migration_required",message:"run crtr sys migrate while the runtime is offline",type:"server_error",origin:"runtime",retryable:!1}}))});await new Promise((d,p)=>{c.once("error",p),c.listen(n,()=>{c.off("error",p),d()})});let u;const h=t.tcp??Ne();if(h){const d=/^(.*):(\d+)$/.exec(h);if(!d||Number(d[2])>65535)throw new Error(`invalid refusal TCP address: ${h}`);const p=re(c.listeners("request")[0]);await new Promise((s,m)=>{p.once("error",m),p.listen(Number(d[2]),d[1],()=>{p.off("error",m),s()})}),u=p}ue();let o;const g=a(()=>(o??=(async()=>{c.closeAllConnections(),u?.closeAllConnections(),await Promise.all([c,u].filter(d=>d!==void 0).map(d=>new Promise((p,s)=>d.close(m=>m?s(m):p())))),ve(process.pid),process.off("SIGINT",w),process.off("SIGTERM",w)})(),o),"cleanup"),w=a(()=>{g().then(()=>process.exit(0),d=>{process.stderr.write(`[crtrd] layout refusal cleanup failed: ${String(d)}
|
|
2
|
+
`),process.exit(1)})},"onSignal");return process.on("SIGINT",w),process.on("SIGTERM",w),g}a(It,"serveLayoutRefusal");async function Dt(t={}){if(Ue())return It(t);We();const n=zr(Ge(16).toString("hex"));if(!n.claimed){if(n.reason==="incumbent_alive")process.stderr.write(`[crtrd] already running (pid ${n.incumbentPid??"?"})
|
|
3
3
|
`);else{const r=[n.incumbentPid!==void 0?`pid ${n.incumbentPid}`:void 0,n.verdict!==void 0?`verdict ${n.verdict}`:void 0].filter(i=>i!==void 0),e=r.length>0?` (${r.join(", ")})`:"";process.stderr.write(`[crtrd] claim lost: ${n.reason}${e}
|
|
4
|
-
`),n.reason==="own_identity_indeterminate"&&process.stderr.write("[crtrd] cannot read its own process identity. crouter needs /proc on Linux, or the `ps` command elsewhere (Debian/Ubuntu: apt-get install procps).\n"),(n.reason==="own_identity_indeterminate"||n.reason==="incumbent_malformed")&&(process.exitCode=1)}return async()=>{}}const c=n.claim;let
|
|
5
|
-
`);if(process.platform==="darwin"){const{readConfig:e,updateConfig:i}=await import("../core/config.js");if(e("user").paths?.user_files===void 0){const{homedir:
|
|
6
|
-
`);
|
|
4
|
+
`),n.reason==="own_identity_indeterminate"&&process.stderr.write("[crtrd] cannot read its own process identity. crouter needs /proc on Linux, or the `ps` command elsewhere (Debian/Ubuntu: apt-get install procps).\n"),(n.reason==="own_identity_indeterminate"||n.reason==="incumbent_malformed")&&(process.exitCode=1)}return async()=>{}}const c=n.claim;let u=null;try{await pt(c.token),at({kind:"user",root:ct()});for(const e of Je())process.stderr.write(`[crtrd] ${e}
|
|
5
|
+
`);if(process.platform==="darwin"){const{readConfig:e,updateConfig:i}=await import("../core/config.js");if(e("user").paths?.user_files===void 0){const{homedir:l}=await import("node:os");i("user",S=>{S.paths??={},S.paths.user_files??=l()})}}await st(dt());for(const e of Ke())process.stderr.write(`[crtrd] ${e}
|
|
6
|
+
`);Wr(pe()),Kr(e=>B.install(e));const r=Ur(e=>Vr(e));for(const e of r.conflicts)process.stderr.write(`[crtrd] plugin documents not reconciled: ${e.message}
|
|
7
7
|
`);for(const e of r.invalid)process.stderr.write(`[crtrd] package file is not a document: ${e.path}: ${e.error}
|
|
8
8
|
`);for(const e of r.quarantined)process.stderr.write(`[crtrd] plugin "${e.name}" has a damaged ${e.file} (${e.reason}); ${e.movedTo!==void 0?`moved to ${e.movedTo}`:"left in place and skipped"}
|
|
9
9
|
`);for(const e of r.kinds.refused)process.stderr.write(`[crtrd] plugin "${e.plugin}" kind ${e.kind} not registered: ${e.message}
|
|
10
10
|
`);for(const e of r.kinds.invalid)process.stderr.write(`[crtrd] plugin "${e.plugin}" declares invalid object kinds or scopes; no kinds registered and no app token: ${e.error}
|
|
11
|
-
`);
|
|
11
|
+
`);u=rt(),process.platform==="linux"&&E(x)&&(ze(),await D({operation:"users.sync",users:je()})),Rr(c.token)}catch(r){me(),B.close();try{const{released:e}=le(c);if(!e)throw new Error("daemon ownership claim was not released")}catch(e){throw new AggregateError([r,e],"daemon startup failed and cleanup also failed")}throw r}let h=!0,o,g=Promise.resolve(),w=!1,d,p;const s=new Set;let m=!1,y=!1,b,A,O,U=!1,N,T,C,$,G;const we=hr();let R,v={phase:"initializing",message:"daemon startup is running the canvas import and normal services are unavailable",blockerPaths:[]},I="initial startup activation",ge=null;function ye(){return v.phase==="ready"?null:{phase:v.phase,message:v.message,blockerPaths:v.blockerPaths}}a(ye,"startupBlock");function k(r){s.add(r),r.finally(()=>{s.delete(r)}).catch(()=>{})}a(k,"registerDetached");const K={acceptsDetachedWork:a(()=>h,"acceptsDetachedWork"),registerDetached:k};Qr(K,pe);async function Se(){try{h=!1,Jr.close(),me(),B.close(),d!==void 0&&(clearInterval(d),d=void 0),C!==void 0&&(clearInterval(C),C=void 0),G?.(),G=void 0;let r;do r=g,await r;while(r!==g);for(;s.size>0;)await Promise.allSettled([...s]);if(p!==void 0&&(await ft(p),p.dispose()),O!==void 0&&await O.close(),A!==void 0&&!U&&(U=!0,await A.close()),$!==void 0){const e=$;$=void 0,await e.stop()}if(T!==void 0){const e=T;T=void 0,await e.close()}if(N!==void 0){const e=N;N=void 0,await e.close()}if(m||(ve(process.pid),m=!0),m&&!y){const{released:e}=le(c);if(!e)throw new Error("daemon ownership claim was not released");y=!0}}finally{Gr(),process.off("SIGINT",Q),process.off("SIGTERM",Y),process.off("exit",X)}}a(Se,"cleanupAttempt");const M=1e3;let J=!1;function _e(){return J?{graceMs:M}:(J=!0,_.fresh(()=>{f({level:"info",event:"daemon.handover.armed",fields:{pid:process.pid,grace_ms:M}})}),setTimeout(()=>{be()},M),{graceMs:M})}a(_e,"requestHandover");async function be(){try{await P()}catch(r){const e=r instanceof Error?r.stack??r.message:String(r);process.stderr.write(`[crtrd] handover cleanup failed:
|
|
12
12
|
${e}
|
|
13
|
-
`),process.exit(1)}try{process.platform==="linux"&&
|
|
14
|
-
`),process.exit(1)}process.exit(0)}a(
|
|
13
|
+
`),process.exit(1)}try{process.platform==="linux"&&E(x)&&(await D({operation:"daemon.handover"}),process.exit(0)),process.pid===1&&await Fr();const r=await Hr({waitForJoinLock:!0});_.fresh(()=>{f({level:"info",event:"daemon.handover.completed",fields:{predecessor_pid:process.pid,successor_pid:r.pid??r.existing_pid??null,spawned:r.started}})})}catch(r){_.fresh(()=>{f({level:"error",event:"daemon.handover.successor_failed",error:r})});const e=r instanceof Error?r.message:String(r);process.stderr.write(`[crtrd] handover successor failed to start: ${e}
|
|
14
|
+
`),process.exit(1)}process.exit(0)}a(be,"performHandover");function P(){if(b!==void 0)return b;const r=Se();return b=r,r.then(()=>{b===r&&(b=void 0)},()=>{b===r&&(b=void 0)}),r}a(P,"requestCleanup");async function V(r){try{await P(),process.exit(0)}catch(e){process.exitCode=1;const i=e instanceof Error?e.stack??`${e.name}: ${e.message}`:String(e);process.stderr.write(`[crtrd] ${r} cleanup failed:
|
|
15
15
|
${i}
|
|
16
|
-
`),process.exit(1)}}a(
|
|
16
|
+
`),process.exit(1)}}a(V,"handleSignal");function Q(){V("SIGINT")}a(Q,"onSigint");function Y(){V("SIGTERM")}a(Y,"onSigterm");function X(){P().catch(()=>{})}a(X,"onExit");function F(r){h&&(g=g.then(r).then(()=>{},e=>{_.fresh(()=>{f({level:"error",event:"daemon.lane_job.failed",error:e})})}))}a(F,"enqueue");function Z(){!h||w||(we.check()&&R&&(f({level:"info",event:"daemon.resume.detected"}),k(R().catch(()=>{}))),w=!0,F(async()=>{if(w=!1,!!h)try{await xt(Date.now(),K)}catch(r){_.fresh(()=>{f({level:"error",event:"daemon.tick.failed",error:r})})}}))}a(Z,"enqueueTick");let L=null;async function ke(){if(L!==null)throw{status:500,code:"admission_failed",message:`daemon admission previously failed: ${L instanceof Error?L.message:String(L)}`};if(v.phase==="ready")return{admitted:!1,already_admitted:!0,startup_phase:"ready"};if(v.phase!=="prepared"&&v.phase!=="recovering")throw{status:409,code:"not_prepared",message:v.message};const r=v.phase==="prepared";try{return await H(),v={phase:"ready",message:"",blockerPaths:[]},r?{admitted:!0,already_admitted:!1,startup_phase:"ready"}:{admitted:!1,already_admitted:!0,startup_phase:"ready"}}catch(e){throw L=e,{status:500,code:"admission_failed",message:`daemon admission failed: ${e instanceof Error?e.message:String(e)}`}}}a(ke,"admitStartup");async function Ee(r){if(I!==null)throw{status:409,code:"migration_in_progress",message:`the canvas import is already running (${I})`};I="repair";try{const e=await it({dryRun:r.dryRun});if(r.dryRun||e.pending||v.phase!=="blocked")return{result:e,resumed:!1};if(t.prepare)return v={phase:"prepared",message:"daemon storage is prepared and normal services are unavailable until admission",blockerPaths:[]},{result:e,resumed:!1};try{return await H(),v={phase:"ready",message:"",blockerPaths:[]},{result:e,resumed:!0}}catch(i){const l=i instanceof Error?i.message:String(i);return setTimeout(()=>{P().catch(()=>{})},1e3),{result:e,resumed:!1,resumeError:l}}}finally{I=null}}a(Ee,"repairMigrations");async function Re(){o=t.intervalMs??ur;const r=c.token;p=new Zr({epoch:r,enqueue:F}),Nr(p),v={phase:"recovering",message:"daemon startup recovery is running and normal services are unavailable",blockerPaths:[]},_.fresh(()=>{f({level:"info",event:"daemon.started",fields:{pid:process.pid,interval_ms:o}})});const e=Br();if(qr(e),_.fresh(()=>{f({level:"info",event:"daemon.install_id.resolved",fields:{install_id:e}})}),_.fresh(()=>{let i;try{i=fr()}catch{return}i!==null&&f({level:"warn",event:"daemon.startup.warning",fields:{stage:"termrender",warning:i.slice(0,2048)}})}),await _.fresh(async()=>{await mr(),await dr(),lr(Date.now()),pr(Date.now())}),_.fresh(()=>{const{reconcile:i,migrated:l}=jr(Er);i.changed&&f({level:"info",event:"daemon.boot_change.reconciled",fields:{cleared_count:i.cleared.length,same_boot_proven:i.sameBootProven}}),l.length>0&&f({level:"info",event:"daemon.pid_identity.migrated",fields:{migrated_count:l.length}})}),_.fresh(()=>{for(const i of ne())i.status!=="active"||i.pi_pid!=null||i.frozen_at!=null||i.respawn_not_before!=null||(oe(i.node_id,new Date().toISOString()),f({level:"warn",event:"daemon.startup.launch_debt_recorded",node_id:i.node_id}))}),_.fresh(()=>{$r();for(const i of et){const l=i.apply();l.changed&&f({level:"info",event:"daemon.boot_migration.applied",fields:{migration:i.id,...l.summary}})}}),k(ar()),R){const i=a(()=>{k(R().catch(()=>{})),k(Ie().then(l=>$?.observe(l)).then(()=>{},l=>{f({level:"warn",event:"daemon.peer.status_failed",error:l})}))},"refresh");k(ir().catch(()=>{})),k(sr().then(({completion:l})=>l).catch(l=>{f({level:"error",event:"daemon.grants.sweep_failed",error:l})})),i(),C=setInterval(i,or*1e3),C.unref(),G=xe({joined:!0,register:k})}F(()=>{Xr(),Yr()}),d=setInterval(Z,o),Z()}a(Re,"completeStartup");function H(){return ge??=Re().catch(r=>{throw v={phase:"initializing",message:"daemon startup recovery failed and normal services are unavailable",blockerPaths:[]},r})}a(H,"resumeStartup");try{process.on("SIGINT",Q),process.on("SIGTERM",Y),process.on("exit",X),tt(),u!==null&&f({level:"info",event:"daemon.joined_owner.applied",fields:{owner:u.owner,rows:u.rows}}),N=await Me();const r=c.token;Or({epoch:r,requestHandover:_e,registerDetached:k,startupBlock:ye,admitStartup:ke,repairMigrations:Ee}),ue(),A=Qe({tcp:t.tcp}),await A.ready;const e=ie("user").document_port,i=Ye(e,Xe());try{await i.ready,O=i}catch(S){f({level:"warn",event:"daemon.document_listener.bind_failed",fields:{port:e,error:S instanceof Error?S.message:String(S)}})}const l=ie("user").runtime;l?.issuer?(R=nr(l.issuer,k),l.unsandboxed===!0&&($=De({syncGrants:R})),rr(S=>tr().appended(S))):er(),l?.unsandboxed===!0&&l.listener!==void 0&&f({level:"warn",event:"daemon.app_listener.refused_unsandboxed",fields:{reason:"runtime.unsandboxed is set; runtime.listener is ignored"}}),l!==void 0&&l.listener!==void 0&&l.unsandboxed!==!0&&(T=Ze(l,()=>cr(l.issuer.replace(/\/$/,"")),R),await T.ready);try{await nt()}catch(S){if(I=null,S instanceof ot)return v={phase:"blocked",message:S.message,blockerPaths:S.blockerPaths},P;throw S}process.platform==="linux"&&E(x)&&(qe(),await Be("app:terminal"));try{t.prepare?v={phase:"prepared",message:"daemon storage is prepared and normal services are unavailable until admission",blockerPaths:[]}:(await H(),v={phase:"ready",message:"",blockerPaths:[]})}finally{I=null}return P}catch(r){try{await P()}catch(e){throw new AggregateError([r,e],"daemon startup failed and cleanup also failed")}throw r}}a(Dt,"runDaemon");var io=Dt;export{q as brokerCommandDeclaresCanvasHome,z as brokerCommandEpoch,io as default,Dt as runDaemon,xt as superviseTick,ft as teardownFleet};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var H=Object.defineProperty;var o=(e,t)=>H(e,"name",{value:t,configurable:!0});import{randomUUID as j}from"node:crypto";import{verifyCallToken as z}from"@north-light/identity";import{ENVELOPE_HEADER as I}from"../../core/peer/envelope.js";import{mirrorGrantLink as L,peerAuthority as U}from"./authority.js";import{peerVersionRefusal as q,PEER_VERSION_HEADER as D}from"../../core/peer/version.js";import{auditOutcome as v,writePeerAudit as G}from"../../core/audit.js";import{emitEvent as C}from"../../core/events/emit.js";import{joinedOwner as P}from"../../core/directory/join.js";import{allGrants as N}from"../../core/grants/mirror.js";import{errorCodes as T}from"../../api/error-codes.js";let O;function S(){return O??=import("../api/server.js").then(e=>e.buildRouter(()=>null)),O}o(S,"defaultRouter");async function x(e,t){return(await S()).match(e.toUpperCase(),t)!==null}o(x,"isDaemonRoute");function V(e,t,r,a,i,m){if(e.headersSent){e.destroy();return}const l=T[r];e.writeHead(t,{"content-type":"application/json; charset=utf-8","Request-Id":i,"X-Content-Type-Options":"nosniff"}),e.end(JSON.stringify({error:{code:r,message:a,...m===void 0?{}:{details:m},...l?{type:l.type}:{},request_id:i}}))}o(V,"refuse");const _=o((e,t)=>{const r=e.headers[t.toLowerCase()];return Array.isArray(r)?r[0]:r},"header");function ee(){try{const e=P();if(e!==null)return e;const t=new Set(N().map(r=>r.sub));return t.size===1?[...t][0]:null}catch{return null}}o(ee,"runtimeOwner");async function te(e,t,r,a){const i=t.getHeader("Request-Id")?.toString()??j();t.setHeader("Request-Id",i);const m=_(e,I),l=new URL(e.url??"/","http://peer.local"),E=(e.method??"GET").toUpperCase();let d={class:m===void 0?"machine":"forwarded",grantee:null,sub:null,via:"unauthenticated",operation:`${E} ${l.pathname}`,node_id:null},R=!1;const b=o((n,c={})=>{if(!R){R=!0;try{G({request_id:i,resource:l.pathname,...d,...c,outcome:n})}catch(u){C({level:"error",event:"daemon.peer.audit_failed",error:u instanceof Error?u:new Error(String(u)),fields:{request_id:i}})}}},"record"),s=o((n,c,u,f)=>{b(v(n)),V(t,n,c,u,i,f)},"deny");try{if(r.ready&&!r.ready()){s(503,"runtime_starting","runtime_starting");return}let n;if(a!==void 0&&!("chain"in a)){s(a.status,a.code,a.message);return}if(a!==void 0)n=a;else{const y=r.audience();if(y===null){s(503,"runtime_starting","this machine does not yet know its own address");return}const g=_(e,"authorization");if(!g?.startsWith("Bearer ")||g.length<=7){s(401,"unauthorized","a machine token is required");return}try{n=await z({token:g.slice(7),jwks:r.jwks,issuer:r.issuer,audience:y})}catch{s(401,"unauthorized","invalid machine token");return}}d={...d,grantee:n.sub,sub:n.sub,via:n.chain[0]?.sub??"unauthenticated"};const c=await(r.router??S)(),u=c.match(E,l.pathname);d={...d,operation:u?.operation.name??d.operation,node_id:u?.params.id??null};const f=r.owner(),p=await U(n,m,{self:r.self,relation:o(y=>f!==null&&y===f?"owner":null,"relation"),grantLink:L(r.syncGrants??(async()=>{}))});if("status"in p){s(p.status,p.code,p.message);return}const h=q(_(e,D));if(h!==null){s(426,h.code,h.message,h.details);return}const{principal:w}=p,k=w.class==="forwarded"&&w.actor.kind==="app"?w.actor:null,A={grantee:k?.app??n.sub,node_id:k?.node??d.node_id};t.once("close",()=>b(t.writableFinished?v(t.statusCode):"aborted",A)),await c.handle(e,t,null,w)}catch(n){C({level:"error",event:"daemon.peer.ingress_failed",error:n instanceof Error?n:new Error(String(n)),fields:{request_id:i}}),s(500,"server_failure","peer request failed")}}o(te,"servePeer");export{x as isDaemonRoute,ee as runtimeOwner,te as servePeer};
|
|
1
|
+
var H=Object.defineProperty;var o=(e,t)=>H(e,"name",{value:t,configurable:!0});import{randomUUID as j}from"node:crypto";import{verifyCallToken as z}from"@north-light/identity";import{ENVELOPE_HEADER as I}from"../../core/peer/envelope.js";import{mirrorGrantLink as L,peerAuthority as U}from"./authority.js";import{peerVersionRefusal as q,PEER_VERSION_HEADER as D}from"../../core/peer/version.js";import{auditOutcome as v,writePeerAudit as G}from"../../core/audit.js";import{emitEvent as C}from"../../core/events/emit.js";import{joinedOwner as P}from"../../core/directory/join.js";import{allGrants as N}from"../../core/grants/mirror.js";import{errorCodes as T}from"../../api/error-codes.js";let O;function S(){return O??=import("../api/server.js").then(e=>e.buildRouter(()=>null)),O}o(S,"defaultRouter");async function x(e,t){return(await S()).match(e.toUpperCase(),t)!==null}o(x,"isDaemonRoute");function V(e,t,r,a,i,m){if(e.headersSent){e.destroy();return}const l=T[r];e.writeHead(t,{"content-type":"application/json; charset=utf-8","Request-Id":i,"X-Content-Type-Options":"nosniff"}),e.end(JSON.stringify({error:{code:r,message:a,origin:"runtime",...m===void 0?{}:{details:m},...l?{type:l.type}:{},request_id:i}}))}o(V,"refuse");const _=o((e,t)=>{const r=e.headers[t.toLowerCase()];return Array.isArray(r)?r[0]:r},"header");function ee(){try{const e=P();if(e!==null)return e;const t=new Set(N().map(r=>r.sub));return t.size===1?[...t][0]:null}catch{return null}}o(ee,"runtimeOwner");async function te(e,t,r,a){const i=t.getHeader("Request-Id")?.toString()??j();t.setHeader("Request-Id",i);const m=_(e,I),l=new URL(e.url??"/","http://peer.local"),E=(e.method??"GET").toUpperCase();let d={class:m===void 0?"machine":"forwarded",grantee:null,sub:null,via:"unauthenticated",operation:`${E} ${l.pathname}`,node_id:null},R=!1;const b=o((n,c={})=>{if(!R){R=!0;try{G({request_id:i,resource:l.pathname,...d,...c,outcome:n})}catch(u){C({level:"error",event:"daemon.peer.audit_failed",error:u instanceof Error?u:new Error(String(u)),fields:{request_id:i}})}}},"record"),s=o((n,c,u,f)=>{b(v(n)),V(t,n,c,u,i,f)},"deny");try{if(r.ready&&!r.ready()){s(503,"runtime_starting","runtime_starting");return}let n;if(a!==void 0&&!("chain"in a)){s(a.status,a.code,a.message);return}if(a!==void 0)n=a;else{const y=r.audience();if(y===null){s(503,"runtime_starting","this machine does not yet know its own address");return}const g=_(e,"authorization");if(!g?.startsWith("Bearer ")||g.length<=7){s(401,"unauthorized","a machine token is required");return}try{n=await z({token:g.slice(7),jwks:r.jwks,issuer:r.issuer,audience:y})}catch{s(401,"unauthorized","invalid machine token");return}}d={...d,grantee:n.sub,sub:n.sub,via:n.chain[0]?.sub??"unauthenticated"};const c=await(r.router??S)(),u=c.match(E,l.pathname);d={...d,operation:u?.operation.name??d.operation,node_id:u?.params.id??null};const f=r.owner(),p=await U(n,m,{self:r.self,relation:o(y=>f!==null&&y===f?"owner":null,"relation"),grantLink:L(r.syncGrants??(async()=>{}))});if("status"in p){s(p.status,p.code,p.message);return}const h=q(_(e,D));if(h!==null){s(426,h.code,h.message,h.details);return}const{principal:w}=p,k=w.class==="forwarded"&&w.actor.kind==="app"?w.actor:null,A={grantee:k?.app??n.sub,node_id:k?.node??d.node_id};t.once("close",()=>b(t.writableFinished?v(t.statusCode):"aborted",A)),await c.handle(e,t,null,w)}catch(n){C({level:"error",event:"daemon.peer.ingress_failed",error:n instanceof Error?n:new Error(String(n)),fields:{request_id:i}}),s(500,"server_failure","peer request failed")}}o(te,"servePeer");export{x as isDaemonRoute,ee as runtimeOwner,te as servePeer};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
:root{color-scheme:light dark;--fg: #1f2328;--muted: #656d76;--bg: #fff;--panel: #f6f8fa;--border: #d0d7de;--accent: #0969da;--error: #b42318}@media(prefers-color-scheme:dark){:root{--fg: #e6edf3;--muted: #8d96a0;--bg: #0d1117;--panel: #161b22;--border: #30363d;--accent: #4493f8;--error: #ff8e85}}*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--fg);font:16px/1.6 -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif}header{position:sticky;top:0;z-index:5;display:flex;align-items:center;gap:24px;padding:12px 24px;background:var(--panel);border-bottom:1px solid var(--border)}.identity{min-width:0;flex:1}.name{font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.meta{color:var(--muted);font-size:12px;overflow-wrap:anywhere}.toolbar,.actions{display:flex;gap:8px}button,input,textarea{font:inherit;color:inherit}button{background:var(--bg);border:1px solid var(--border);border-radius:6px;padding:5px 13px;font-size:13px;cursor:pointer;white-space:nowrap}button:hover:not(:disabled){border-color:var(--accent)}button.primary{background:var(--accent);color:#fff;border-color:var(--accent)}button:disabled{opacity:.45;cursor:default}:focus-visible{outline:2px solid var(--accent);outline-offset:3px}main{max-width:860px;margin:0 auto;padding:24px 24px 100px}.status{color:var(--muted);font-size:14px;margin-bottom:12px}.status:empty{display:none}.status.error{color:var(--error)}.rationale{display:block;width:100%;background:transparent;border:0;border-bottom:1px solid var(--border);padding:8px 0;margin:0 0 28px;font-size:13px}.rationale:disabled{display:none}.ProseMirror{outline:none;white-space:pre-wrap;overflow-wrap:break-word}.ProseMirror>:first-child{margin-top:0}.ProseMirror h1,.ProseMirror h2{border-bottom:1px solid var(--border);padding-bottom:.3em;line-height:1.3}.ProseMirror h1{font-size:2em}.ProseMirror h2{margin-top:1.6em}.ProseMirror p{margin:1em 0}.ProseMirror a{color:var(--accent);cursor:pointer}.ProseMirror code,textarea{font:85%/1.6 ui-monospace,SFMono-Regular,Menlo,monospace}.ProseMirror code{background:var(--panel);padding:.2em .4em;border-radius:4px}.ProseMirror pre{background:var(--panel);padding:14px 16px;border-radius:6px;overflow:auto;white-space:pre-wrap}.ProseMirror pre code{background:none;padding:0}.ProseMirror pre[data-language]:before{content:attr(data-language);display:block;color:var(--muted);font:11px/1.5 ui-monospace,monospace;margin-bottom:8px}.ProseMirror blockquote{margin:0;padding:0 1em;color:var(--muted);border-left:.25em solid var(--border)}.ProseMirror table{border-collapse:collapse;width:100%;table-layout:fixed}.ProseMirror th,.ProseMirror td{position:relative;border:1px solid var(--border);padding:6px 13px;min-width:60px}.ProseMirror th{background:var(--panel)}.ProseMirror td p,.ProseMirror th p{margin:.25em 0}.ProseMirror tr:nth-child(2n){background:var(--panel)}.ProseMirror .selectedCell:after{position:absolute;inset:0;content:"";background:var(--accent);opacity:.15;pointer-events:none}.ProseMirror img{max-width:100%}.ProseMirror li>p{margin:.35em 0}.ProseMirror .doc-ref{font-size:.92em;text-decoration:none;border-bottom:1px dotted var(--accent)}.source-block{border:1px dashed var(--border)}.source-block:before{content:"Read-only source";display:block;color:var(--muted);font:11px/1.5 -apple-system,sans-serif;margin-bottom:8px}.diagram{text-align:center;margin:24px 0 0;overflow:auto}.diagram svg{max-width:100%;height:auto}.ProseMirror-selectednode{outline:2px solid var(--accent)}.ProseMirror-gapcursor{display:none;pointer-events:none;position:absolute}.ProseMirror-gapcursor:after{content:"";display:block;position:absolute;top:-2px;width:20px;border-top:1px solid var(--fg);animation:blink 1.1s steps(2,start) infinite}.ProseMirror-focused .ProseMirror-gapcursor{display:block}@keyframes blink{to{visibility:hidden}}dialog{background:var(--bg);color:var(--fg);border:1px solid var(--border);border-radius:10px;padding:24px;width:min(1120px,95vw);max-height:90vh}dialog::backdrop{background:#0008}dialog h2{margin:0;font-size:21px}dialog p{color:var(--muted);font-size:14px}.versions{display:grid;grid-template-columns:1fr 1fr;gap:20px}.versions label{font-size:13px;font-weight:600}.versions textarea{display:block;width:100%;height:45vh;margin-top:8px;padding:12px;background:var(--panel);border:1px solid var(--border);border-radius:6px;resize:vertical;white-space:pre}.actions{justify-content:flex-end;margin-top:20px}@media(max-width:600px){header{padding:10px 16px;gap:12px}main{padding:20px 16px 60px}.toolbar{gap:4px}button{padding:5px 9px}.versions{grid-template-columns:1fr}.versions textarea{height:25vh}}
|