@aria-cli/server 1.0.19
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/README.md +17 -0
- package/dist/.aria-build-stamp.json +4 -0
- package/dist/auth/api-key.d.ts +106 -0
- package/dist/config.d.ts +28 -0
- package/dist/daemon-launcher.d.ts +23 -0
- package/dist/daemon-launcher.js +3 -0
- package/dist/index-5tav2m70.js +3 -0
- package/dist/index-6extw9n6.js +2 -0
- package/dist/index-9n50yafd.js +3 -0
- package/dist/index-9xs3gn0p.js +2 -0
- package/dist/index-ghh3ag4c.js +548 -0
- package/dist/index-mnt9k223.js +15 -0
- package/dist/index-pe0pkp0v.js +2 -0
- package/dist/index-raeajnr7.js +2 -0
- package/dist/index-rr0sea4c.js +2 -0
- package/dist/index-zge0mhc0.js +3 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +1 -0
- package/dist/peer-principal-auth.d.ts +37 -0
- package/dist/routes/arions.d.ts +34 -0
- package/dist/routes/council.d.ts +15 -0
- package/dist/routes/entrypoint-errors.d.ts +7 -0
- package/dist/routes/health.d.ts +6 -0
- package/dist/routes/invite-relay.d.ts +2 -0
- package/dist/routes/local-control.d.ts +3 -0
- package/dist/routes/message.d.ts +17 -0
- package/dist/routes/network.d.ts +14 -0
- package/dist/routes/pair.d.ts +57 -0
- package/dist/routes/pair.js +1 -0
- package/dist/routes/pipeline-mailbox.d.ts +10 -0
- package/dist/routes/relay.d.ts +29 -0
- package/dist/routes/resume.d.ts +2 -0
- package/dist/routes/run-control-surface.d.ts +24 -0
- package/dist/routes/run.d.ts +6 -0
- package/dist/routes/runtime-bootstrap.d.ts +3 -0
- package/dist/routes/runtime-node-advertisement.d.ts +3 -0
- package/dist/routes/runtime-run-room.d.ts +8 -0
- package/dist/routes/shared.d.ts +45 -0
- package/dist/routes/stream.d.ts +10 -0
- package/dist/routes/validation.d.ts +7 -0
- package/dist/routes/ws-revocation.d.ts +25 -0
- package/dist/runtime/attached-sender-inbox.d.ts +3 -0
- package/dist/runtime/authoritative-peer-endpoint.d.ts +27 -0
- package/dist/runtime/continuity-bind-suspicion.d.ts +39 -0
- package/dist/runtime/continuity-verification.d.ts +54 -0
- package/dist/runtime/decorate-runtime-surface.d.ts +2 -0
- package/dist/runtime/durable-network-store-surface.d.ts +51 -0
- package/dist/runtime/error-diagnostic.d.ts +12 -0
- package/dist/runtime/headless-dispatch-handler.d.ts +30 -0
- package/dist/runtime/host-supervisor.d.ts +109 -0
- package/dist/runtime/host-supervisor.js +1 -0
- package/dist/runtime/join-control.d.ts +3 -0
- package/dist/runtime/local-control-api.d.ts +63 -0
- package/dist/runtime/local-control-api.js +1 -0
- package/dist/runtime/local-control-pairing.d.ts +12 -0
- package/dist/runtime/local-control-socket.d.ts +48 -0
- package/dist/runtime/log-file-sink.d.ts +21 -0
- package/dist/runtime/network-read-control.d.ts +17 -0
- package/dist/runtime/network-state-stores.d.ts +2 -0
- package/dist/runtime/node-metadata.d.ts +22 -0
- package/dist/runtime/node-metadata.js +1 -0
- package/dist/runtime/node-runtime.d.ts +157 -0
- package/dist/runtime/node-store-revocation-store.d.ts +42 -0
- package/dist/runtime/node-store.d.ts +184 -0
- package/dist/runtime/node-store.js +1 -0
- package/dist/runtime/pinned-control-session.d.ts +41 -0
- package/dist/runtime/principal-binding-authority.d.ts +173 -0
- package/dist/runtime/reachable-control-host.d.ts +5 -0
- package/dist/runtime/runtime-admin-api.d.ts +16 -0
- package/dist/runtime/runtime-authority-registry.d.ts +55 -0
- package/dist/runtime/runtime-autonomous-loop.d.ts +40 -0
- package/dist/runtime/runtime-bootstrap-authority.d.ts +5 -0
- package/dist/runtime/runtime-bootstrap-record.d.ts +21 -0
- package/dist/runtime/runtime-event-journal.d.ts +21 -0
- package/dist/runtime/runtime-outbox.d.ts +35 -0
- package/dist/runtime/runtime-registry.d.ts +33 -0
- package/dist/runtime/runtime-registry.js +1 -0
- package/dist/runtime/runtime-run-control.d.ts +71 -0
- package/dist/runtime/stale-owner-error.d.ts +13 -0
- package/dist/runtime-run-control-0r21xdh5.js +2 -0
- package/dist/server.d.ts +84 -0
- package/dist/session-history-messages.d.ts +3 -0
- package/dist/session-history.d.ts +28 -0
- package/dist/shared-4jsvhy6g.js +1 -0
- package/dist/types.d.ts +299 -0
- package/dist/utils/rate-limiter.d.ts +25 -0
- package/dist/utils/sanitize-error.d.ts +10 -0
- package/package.json +82 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Control plane routes — join (key exchange) and message listing.
|
|
3
|
+
*
|
|
4
|
+
* POST /api/v1/message has been removed. All agent-to-agent data flows
|
|
5
|
+
* through WireGuard tunnels (Transport 3 in Mailbox). HTTPS is only used
|
|
6
|
+
* for the coordination server: key exchange (join) and peer discovery.
|
|
7
|
+
*/
|
|
8
|
+
import type { FastifyInstance } from "fastify";
|
|
9
|
+
import "../types.js";
|
|
10
|
+
/** Reset join rate limits (for testing only) */
|
|
11
|
+
export declare function resetJoinRateLimits(): void;
|
|
12
|
+
/** Reset PoW challenges (for testing only) */
|
|
13
|
+
export declare function resetPowChallenges(): void;
|
|
14
|
+
/**
|
|
15
|
+
* Register control plane routes (join + message listing).
|
|
16
|
+
*/
|
|
17
|
+
export declare function registerMessageRoute(server: FastifyInstance): Promise<void>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coordination server routes — Tailscale-style control plane for peer discovery.
|
|
3
|
+
*
|
|
4
|
+
* These endpoints manage the peer mesh: listing peers, heartbeat/registration,
|
|
5
|
+
* and revocation. All agent-to-agent data flows through WireGuard tunnels;
|
|
6
|
+
* these HTTPS endpoints are control-plane only.
|
|
7
|
+
*
|
|
8
|
+
* SECURITY: All mutation routes require MutationEnvelope auth. Legacy Ed25519
|
|
9
|
+
* signature-over-string auth has been removed — envelope is the single auth path.
|
|
10
|
+
* Peer-list control-plane access is envelope-authenticated with no bootstrap bypass.
|
|
11
|
+
*/
|
|
12
|
+
import type { FastifyInstance } from "fastify";
|
|
13
|
+
import "../types.js";
|
|
14
|
+
export declare function registerNetworkRoutes(server: FastifyInstance): Promise<void>;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pair request/response routes — AirDrop-style interactive pairing.
|
|
3
|
+
*
|
|
4
|
+
* Protocol (v2 — encrypted):
|
|
5
|
+
* 1. Initiator POSTs pair-request with ephemeral X25519 pubkey + CA cert
|
|
6
|
+
* 2. Response includes responder's signing key fingerprint + CA cert
|
|
7
|
+
* 3. Responder's CLI shows accept/reject overlay
|
|
8
|
+
* 4. Initiator long-polls GET /pair/status/:requestId via HTTPS (TLS verified by CA)
|
|
9
|
+
* 5. On accept: responder generates ephemeral X25519 → ECDH → AES-256-GCM encrypts token
|
|
10
|
+
* 6. Long-poll resolves with encrypted invite token + responder's ephemeral pubkey
|
|
11
|
+
* 7. Initiator decrypts token, calls POST /pair/accept-invite on its OWN server
|
|
12
|
+
* 8. WireGuard tunnel established automatically on both sides
|
|
13
|
+
*
|
|
14
|
+
* Security layers:
|
|
15
|
+
* - Layer 1: HTTPS via auto-generated private CA (transport encryption)
|
|
16
|
+
* - Layer 2: ECDH + AES-256-GCM (application-layer defense-in-depth)
|
|
17
|
+
* - Rate limited: 3 pair requests per IP per minute
|
|
18
|
+
* - Dedup: one pending request per durable node principal
|
|
19
|
+
* - Long-poll bound to initiator IP (prevents requestId race/MITM)
|
|
20
|
+
* - Global concurrent long-poll limit (prevents fd exhaustion)
|
|
21
|
+
* - Rate limit map capped at 10K entries (prevents spoofed-IP DoS)
|
|
22
|
+
* - Forward secrecy: ephemeral X25519 keys discarded after pairing
|
|
23
|
+
*
|
|
24
|
+
* WAN support:
|
|
25
|
+
* - POST /pair/relay: relay pair requests through coordination server
|
|
26
|
+
* - GET /pair/pending: includes relayed requests alongside local ones
|
|
27
|
+
*/
|
|
28
|
+
import type { FastifyInstance } from "fastify";
|
|
29
|
+
import "../types.js";
|
|
30
|
+
import { type PrincipalFingerprint, type NodeId, type RuntimeBootstrapRecord } from "@aria-cli/tools";
|
|
31
|
+
type SharedSigningPublicKey = RuntimeBootstrapRecord["signingPublicKey"];
|
|
32
|
+
/** Pending pair request with 5-minute TTL */
|
|
33
|
+
export interface PendingPairRequest {
|
|
34
|
+
id: string;
|
|
35
|
+
nodeId: NodeId;
|
|
36
|
+
displayNameSnapshot: string;
|
|
37
|
+
principalFingerprint: PrincipalFingerprint;
|
|
38
|
+
signingPublicKey: SharedSigningPublicKey;
|
|
39
|
+
port: number;
|
|
40
|
+
host: string;
|
|
41
|
+
responderControlHostHint?: string;
|
|
42
|
+
ingressHost: string;
|
|
43
|
+
createdAt: number;
|
|
44
|
+
expiresAt: number;
|
|
45
|
+
/** Initiator's ephemeral X25519 public key for ECDH (base64 SPKI DER) */
|
|
46
|
+
ephemeralPublicKey?: string;
|
|
47
|
+
/** Ed25519 signature over ephemeralPublicKey — binds identity to ECDH exchange */
|
|
48
|
+
ephemeralKeySignature?: string;
|
|
49
|
+
/** Initiator's TLS CA cert (PEM) — for responder to connect back via HTTPS */
|
|
50
|
+
caCert?: string;
|
|
51
|
+
/** Whether this request was relayed through the coordination server */
|
|
52
|
+
relayed?: boolean;
|
|
53
|
+
/** For relayed requests: the target node principal (who should respond) */
|
|
54
|
+
relayTargetNodeId?: NodeId;
|
|
55
|
+
}
|
|
56
|
+
export declare function registerPairRoutes(server: FastifyInstance): Promise<void>;
|
|
57
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{sa as a}from"../index-6extw9n6.js";import"../index-raeajnr7.js";import"../index-ghh3ag4c.js";import"../index-9xs3gn0p.js";export{a as registerPairRoutes};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { FastifyInstance } from "fastify";
|
|
2
|
+
import type { Mailbox } from "@aria-cli/aria/messaging";
|
|
3
|
+
import "../types.js";
|
|
4
|
+
type SessionWithMailbox = {
|
|
5
|
+
mailbox?: unknown;
|
|
6
|
+
bindRelayTransport?: ((transport: Parameters<RelayConfigurableMailbox["setRelayTransport"]>[0]) => void) | undefined;
|
|
7
|
+
} | null | undefined;
|
|
8
|
+
type RelayConfigurableMailbox = Pick<Mailbox, "setRelayTransport">;
|
|
9
|
+
export declare function bindRuntimeOutbox(server: FastifyInstance, session: SessionWithMailbox): () => void;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DERP relay route — WebSocket relay for NAT-punched WireGuard traffic.
|
|
3
|
+
*
|
|
4
|
+
* When both peers are behind symmetric NAT, direct UDP tunnels fail.
|
|
5
|
+
* This relay forwards WireGuard packets between peers via WebSocket.
|
|
6
|
+
* WireGuard payloads are encrypted end-to-end (server cannot read WireGuard content).
|
|
7
|
+
* NOTE: The mailbox fallback path sends JSON payloads through this relay — those
|
|
8
|
+
* are application-layer messages that the relay CAN read. Only WireGuard tunnel
|
|
9
|
+
* traffic has true end-to-end confidentiality.
|
|
10
|
+
*
|
|
11
|
+
* Protocol:
|
|
12
|
+
* 1. Client connects via WebSocket to /api/v1/relay
|
|
13
|
+
* 2. Client sends: { type: "auth", nodeId, signingPublicKey }
|
|
14
|
+
* 3. Server sends: { type: "challenge", nonce }
|
|
15
|
+
* 4. Client sends: { type: "challenge_response", signature }
|
|
16
|
+
* 5. Server verifies Ed25519 signature, sends: { type: "auth_ok", nodeId, displayNameSnapshot? }
|
|
17
|
+
* 6. Client sends: { type: "relay", toNodeId: "node-id", data: "<base64>" }
|
|
18
|
+
* 7. Server routes to recipient's WebSocket
|
|
19
|
+
* 8. Recipient receives: { type: "relay", fromNodeId: "node-id", displayNameSnapshot?: "...", data: "<base64>" }
|
|
20
|
+
*
|
|
21
|
+
* Security:
|
|
22
|
+
* - Ed25519 signature challenge prevents impersonation
|
|
23
|
+
* - Rate limit: 1000 packets/min per peer
|
|
24
|
+
* - Max payload: 65535 bytes (WireGuard MTU)
|
|
25
|
+
* - Only registered + active peers can connect
|
|
26
|
+
*/
|
|
27
|
+
import type { FastifyInstance } from "fastify";
|
|
28
|
+
import "../types.js";
|
|
29
|
+
export declare function registerRelayRoute(server: FastifyInstance): Promise<void>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { FastifyInstance } from "fastify";
|
|
2
|
+
import type { RuntimeRunEvent } from "@aria-cli/tools";
|
|
3
|
+
import type { AttachedClientExecutionContext, NormalizedStreamRequest, ResumeRouteRequestBody, ResumeRouteResponse, RunControlLogger, RunRouteRequestBody, RunRouteResponse } from "../runtime/runtime-run-control.js";
|
|
4
|
+
export type { ResumeRouteRequestBody, ResumeRouteResponse, RunRouteRequestBody, RunRouteResponse, } from "../runtime/runtime-run-control.js";
|
|
5
|
+
export declare function submitRunViaLoadedRuntimeControl(server: FastifyInstance, requestBody: RunRouteRequestBody, requestLog?: RunControlLogger, attachedClient?: AttachedClientExecutionContext): Promise<{
|
|
6
|
+
status: number;
|
|
7
|
+
body: RunRouteResponse;
|
|
8
|
+
}>;
|
|
9
|
+
export declare function resumeRunViaLoadedRuntimeControl(server: FastifyInstance, requestBody: ResumeRouteRequestBody, requestLog?: RunControlLogger, attachedClient?: AttachedClientExecutionContext): Promise<{
|
|
10
|
+
status: number;
|
|
11
|
+
body: ResumeRouteResponse;
|
|
12
|
+
}>;
|
|
13
|
+
export declare function loadStreamRuntimeSurface(): Promise<{
|
|
14
|
+
parseStreamRequest(payload: unknown): {
|
|
15
|
+
request?: NormalizedStreamRequest;
|
|
16
|
+
error?: string;
|
|
17
|
+
};
|
|
18
|
+
invalidStreamRequest(message: string): AsyncGenerator<RuntimeRunEvent, void, unknown>;
|
|
19
|
+
streamRunViaRuntimeControl(server: FastifyInstance, parsed: NormalizedStreamRequest, requestLog?: RunControlLogger, signal?: AbortSignal, attachedClient?: AttachedClientExecutionContext): AsyncGenerator<RuntimeRunEvent, void, unknown>;
|
|
20
|
+
getToolResultHighlight(toolName: string, toolInput: unknown, toolResult: unknown): {
|
|
21
|
+
highlighted?: string;
|
|
22
|
+
language?: string;
|
|
23
|
+
};
|
|
24
|
+
}>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { FastifyInstance } from "fastify";
|
|
2
|
+
import { Room } from "@aria-cli/aria/server-arions";
|
|
3
|
+
import { createArionManager } from "./arions.js";
|
|
4
|
+
export declare function createRequestRoom(server: FastifyInstance): Promise<{
|
|
5
|
+
room: Room;
|
|
6
|
+
manager: Awaited<ReturnType<typeof createArionManager>> | null;
|
|
7
|
+
}>;
|
|
8
|
+
export declare function activateMentionedArions(manager: Awaited<ReturnType<typeof createArionManager>> | null, room: Room, task: string): Promise<void>;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { type createRunPipeline } from "@aria-cli/aria/server-runner";
|
|
2
|
+
import type { InboxAddress } from "@aria-cli/tools";
|
|
3
|
+
import type { Message } from "@aria-cli/types";
|
|
4
|
+
export declare const APPROVAL_PAUSE_SIGNAL: unique symbol;
|
|
5
|
+
type EntrypointRunOptions = NonNullable<Parameters<typeof createRunPipeline>[0]["runOptionsOverrides"]>;
|
|
6
|
+
export interface EntrypointRunPolicyInput {
|
|
7
|
+
approvalMode?: "pause" | "approve" | "deny";
|
|
8
|
+
askUserAnswers?: string[];
|
|
9
|
+
budget?: number;
|
|
10
|
+
maxTurns?: number;
|
|
11
|
+
autonomy?: "minimal" | "balanced" | "high" | "full";
|
|
12
|
+
allowedTools?: string[];
|
|
13
|
+
deniedTools?: string[];
|
|
14
|
+
noMemory?: boolean;
|
|
15
|
+
systemPrompt?: string;
|
|
16
|
+
}
|
|
17
|
+
export declare class AskUserAnswersExhaustedError extends Error {
|
|
18
|
+
readonly code: "ASK_USER_ANSWERS_EXHAUSTED";
|
|
19
|
+
readonly questions: Array<{
|
|
20
|
+
question: string;
|
|
21
|
+
options?: string[];
|
|
22
|
+
}>;
|
|
23
|
+
constructor(message: string, questions?: Array<{
|
|
24
|
+
question: string;
|
|
25
|
+
options?: string[];
|
|
26
|
+
}>);
|
|
27
|
+
}
|
|
28
|
+
export declare function createApprovalHandler(mode: "pause" | "approve" | "deny"): () => Promise<boolean | symbol>;
|
|
29
|
+
export declare function createAskUserHandler(preloadedAnswers: string[], exhaustionMode?: "pause" | "error"): (questions: Array<{
|
|
30
|
+
question: string;
|
|
31
|
+
options?: string[];
|
|
32
|
+
}>) => Promise<Array<{
|
|
33
|
+
answer: string;
|
|
34
|
+
}>>;
|
|
35
|
+
export declare function isAskUserAnswersExhaustedError(error: unknown): error is AskUserAnswersExhaustedError;
|
|
36
|
+
export declare function getToolResultHighlight(toolName: string, toolInput: unknown, toolResult: unknown): {
|
|
37
|
+
highlighted?: string;
|
|
38
|
+
language?: string;
|
|
39
|
+
};
|
|
40
|
+
export declare function normalizeEntrypointHistory(history: ReadonlyArray<unknown> | undefined): Message[] | undefined;
|
|
41
|
+
export declare function buildEntrypointRunOptions(input: {
|
|
42
|
+
workingDir: string;
|
|
43
|
+
inboxAddress?: InboxAddress;
|
|
44
|
+
} & EntrypointRunPolicyInput): EntrypointRunOptions;
|
|
45
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { FastifyInstance } from "fastify";
|
|
2
|
+
import "../types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Register the /api/v1/stream WebSocket route.
|
|
5
|
+
* Delegates lifecycle to RunSession for parity with CLI and /run.
|
|
6
|
+
*
|
|
7
|
+
* aria-mhq.1 fix: loads config from disk (previously passed config: {}).
|
|
8
|
+
* aria-mhq.2 fix: uses server-level MemoriaFactory singleton.
|
|
9
|
+
*/
|
|
10
|
+
export declare function registerStreamRoute(server: FastifyInstance): Promise<void>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GAP-9: WebSocket endpoint for push-based revocation notifications.
|
|
3
|
+
*
|
|
4
|
+
* Peers subscribe to /api/v1/ws/revocations to receive instant revocation
|
|
5
|
+
* events instead of waiting for the 60s poll cycle. This closes the 0-60s
|
|
6
|
+
* window where a revoked peer could still operate.
|
|
7
|
+
*
|
|
8
|
+
* Protocol (Ed25519 challenge-response, same as relay.ts):
|
|
9
|
+
* 1. Client connects via WebSocket to /api/v1/ws/revocations
|
|
10
|
+
* 2. Client sends: { type: "auth", nodeId: "...", signingPublicKey: "..." }
|
|
11
|
+
* 3. Server sends: { type: "challenge", nonce: "<hex>" }
|
|
12
|
+
* 4. Client sends: { type: "challenge_response", signature: "<base64>" }
|
|
13
|
+
* 5. Server verifies Ed25519 signature, sends: { type: "auth_ok", nodeId, displayNameSnapshot? }
|
|
14
|
+
* 6. Client is now subscribed to revocation events
|
|
15
|
+
* 7. On revocation, server pushes: { type: "revocation", nodeId: "...", displayNameSnapshot?: "...", revokedAt: <ms> }
|
|
16
|
+
*
|
|
17
|
+
* Security:
|
|
18
|
+
* - Ed25519 signature challenge prevents impersonation
|
|
19
|
+
* - Only registered + active peers can subscribe
|
|
20
|
+
* - Revoked peers rejected at auth AND kicked from active subscriptions
|
|
21
|
+
* - 10s auth timeout — close if not authenticated
|
|
22
|
+
*/
|
|
23
|
+
import type { FastifyInstance } from "fastify";
|
|
24
|
+
import "../types.js";
|
|
25
|
+
export declare function registerWsRevocationRoute(server: FastifyInstance): Promise<void>;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { type InboxAddress } from "@aria-cli/tools";
|
|
2
|
+
export declare function attachedClientInboxAddress(clientId: string): InboxAddress;
|
|
3
|
+
export declare function attachSenderInboxMetadata(rawMessage: Record<string, unknown>, senderInbox: InboxAddress): Record<string, unknown>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type NodeId } from "@aria-cli/tools";
|
|
2
|
+
import { type PrincipalBindingAuthority, type ResolvedPrincipalBinding } from "./principal-binding-authority.js";
|
|
3
|
+
export type AuthoritativePeerEndpointErrorCode = "not_found" | "stale_revision" | "conflicting_revision" | "endpoint_conflict";
|
|
4
|
+
export declare class AuthoritativePeerEndpointError extends Error {
|
|
5
|
+
readonly code: AuthoritativePeerEndpointErrorCode;
|
|
6
|
+
constructor(code: AuthoritativePeerEndpointErrorCode, message: string);
|
|
7
|
+
}
|
|
8
|
+
export declare function withAuthoritativePeerEndpointMutation<T>(input: {
|
|
9
|
+
ariaHome: string;
|
|
10
|
+
ownerGeneration?: number;
|
|
11
|
+
authority: PrincipalBindingAuthority;
|
|
12
|
+
nodeId: NodeId;
|
|
13
|
+
endpointHost: string;
|
|
14
|
+
endpointPort: number;
|
|
15
|
+
endpointRevision: number;
|
|
16
|
+
apply(binding: {
|
|
17
|
+
binding: ResolvedPrincipalBinding;
|
|
18
|
+
endpointHost: string;
|
|
19
|
+
endpointPort: number;
|
|
20
|
+
endpointRevision: number;
|
|
21
|
+
decision: "applied" | "idempotent";
|
|
22
|
+
}): T;
|
|
23
|
+
}): {
|
|
24
|
+
decision: "applied" | "idempotent";
|
|
25
|
+
binding: ResolvedPrincipalBinding;
|
|
26
|
+
projected: T;
|
|
27
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Suspicious continuity bind detection.
|
|
3
|
+
*
|
|
4
|
+
* Architecture ref: 2026-03-08-network-runtime-first-principles-architecture.md §11e
|
|
5
|
+
*
|
|
6
|
+
* The runtime MUST require explicit operator approval (not auto-accept)
|
|
7
|
+
* for a continuity_bind when any of these conditions are true:
|
|
8
|
+
*
|
|
9
|
+
* 1. bindingGeneration jump > 1 (skipped generations suggest replay or out-of-order)
|
|
10
|
+
* 2. Both signing key AND transport key rotate simultaneously (total identity change)
|
|
11
|
+
* 3. Previous continuity was less than threshold ago (rapid rotation suggests compromise)
|
|
12
|
+
* 4. Nonce/timestamp outside acceptable bounds
|
|
13
|
+
*/
|
|
14
|
+
import type { ContinuityStatement } from "@aria-cli/tools/network-runtime";
|
|
15
|
+
export interface ContinuityBindSuspicionInput {
|
|
16
|
+
/** The proposed continuity statement. */
|
|
17
|
+
statement: ContinuityStatement;
|
|
18
|
+
/** The current binding generation for this peer (from the store). */
|
|
19
|
+
currentBindingGeneration: number;
|
|
20
|
+
/** The previous principal fingerprint for this peer (from the store). */
|
|
21
|
+
currentPrincipalFingerprint?: string;
|
|
22
|
+
/** The current transport public key for this peer (from the store). */
|
|
23
|
+
currentTransportPublicKey?: string;
|
|
24
|
+
/** When the last continuity bind was committed for this peer (ISO 8601). */
|
|
25
|
+
lastContinuityBindAt?: string;
|
|
26
|
+
/** Minimum interval between continuity binds (milliseconds). Default: 60000 (1 minute). */
|
|
27
|
+
rapidRotationThresholdMs?: number;
|
|
28
|
+
}
|
|
29
|
+
export type ContinuityBindSuspicionResult = {
|
|
30
|
+
suspicious: false;
|
|
31
|
+
} | {
|
|
32
|
+
suspicious: true;
|
|
33
|
+
reasons: string[];
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Assess whether a continuity bind proposal is suspicious and
|
|
37
|
+
* requires explicit operator approval before acceptance.
|
|
38
|
+
*/
|
|
39
|
+
export declare function assessContinuityBindSuspicion(input: ContinuityBindSuspicionInput): ContinuityBindSuspicionResult;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { SignedContinuityBind, PrincipalFingerprint } from "@aria-cli/tools";
|
|
2
|
+
declare const VERIFIED_CONTINUITY: unique symbol;
|
|
3
|
+
/**
|
|
4
|
+
* A `SignedContinuityBind` whose dual Ed25519 signatures, fingerprint chain,
|
|
5
|
+
* and monotonic generation have been cryptographically verified.
|
|
6
|
+
*
|
|
7
|
+
* This type can ONLY be obtained by calling `verifyContinuityBind()` and
|
|
8
|
+
* receiving a non-error result. The unique-symbol brand makes it impossible
|
|
9
|
+
* to construct manually (outside this module).
|
|
10
|
+
*/
|
|
11
|
+
export type VerifiedContinuityBind = SignedContinuityBind & {
|
|
12
|
+
readonly [VERIFIED_CONTINUITY]: true;
|
|
13
|
+
};
|
|
14
|
+
export type ContinuityBindError = {
|
|
15
|
+
kind: "delegation_signature_invalid";
|
|
16
|
+
} | {
|
|
17
|
+
kind: "acceptance_signature_invalid";
|
|
18
|
+
} | {
|
|
19
|
+
kind: "fingerprint_key_mismatch";
|
|
20
|
+
field: "previous" | "new";
|
|
21
|
+
} | {
|
|
22
|
+
kind: "generation_not_monotonic";
|
|
23
|
+
current: number;
|
|
24
|
+
proposed: number;
|
|
25
|
+
} | {
|
|
26
|
+
kind: "previous_fingerprint_mismatch";
|
|
27
|
+
expected: PrincipalFingerprint;
|
|
28
|
+
actual: PrincipalFingerprint;
|
|
29
|
+
} | {
|
|
30
|
+
kind: "revocation_generation_mismatch";
|
|
31
|
+
expected: number;
|
|
32
|
+
actual: number | undefined;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Verify a dual-signed continuity bind against the current binding state.
|
|
36
|
+
*
|
|
37
|
+
* Checks, in order:
|
|
38
|
+
* 1. previousPublicKey fingerprint matches statement.previousPrincipalFingerprint
|
|
39
|
+
* 2. newPublicKey fingerprint matches statement.newPrincipalFingerprint
|
|
40
|
+
* 3. statement.previousPrincipalFingerprint matches currentBinding.principalFingerprint
|
|
41
|
+
* 4. statement.bindingGeneration > currentBinding.continuityRevision
|
|
42
|
+
* 5. delegationSignature is valid (old key over canonical statement bytes)
|
|
43
|
+
* 6. acceptanceSignature is valid (new key over canonical statement bytes)
|
|
44
|
+
*
|
|
45
|
+
* Returns the branded `VerifiedContinuityBind` on success, or a discriminated
|
|
46
|
+
* `ContinuityBindError` on failure.
|
|
47
|
+
*/
|
|
48
|
+
export declare function verifyContinuityBind(signed: SignedContinuityBind, currentBinding: {
|
|
49
|
+
principalFingerprint: PrincipalFingerprint;
|
|
50
|
+
continuityRevision: number;
|
|
51
|
+
/** Present only when the current binding is revoked. */
|
|
52
|
+
revocationGeneration?: number;
|
|
53
|
+
}): VerifiedContinuityBind | ContinuityBindError;
|
|
54
|
+
export {};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type Database from "better-sqlite3";
|
|
2
|
+
import { DurablePairStore, DurableNonceStore, InviteConsumeLedger, PeerSigningKeyStore, PeerTrustStore } from "./network-state-stores.js";
|
|
3
|
+
export declare function createDurableNetworkStoreSurface(input: {
|
|
4
|
+
ariaHome: string;
|
|
5
|
+
networkStateDb: Database.Database;
|
|
6
|
+
ownerGeneration: number;
|
|
7
|
+
}): {
|
|
8
|
+
revocationStore: {
|
|
9
|
+
revoke(event: {
|
|
10
|
+
nodeId: import("@aria-cli/aria").NodeId;
|
|
11
|
+
displayNameSnapshot?: string;
|
|
12
|
+
fingerprint: import("@aria-cli/aria").PrincipalFingerprint;
|
|
13
|
+
revokedAt: number;
|
|
14
|
+
localNodeId: import("@aria-cli/aria").NodeId;
|
|
15
|
+
operatorConfirmation: import("@aria-cli/aria").RevocationOperatorConfirmation;
|
|
16
|
+
reason?: string;
|
|
17
|
+
revocationGeneration?: number;
|
|
18
|
+
}): void;
|
|
19
|
+
isPeerRevoked(nodeId: import("@aria-cli/aria").NodeId): boolean;
|
|
20
|
+
read(nodeId: import("@aria-cli/aria").NodeId): {
|
|
21
|
+
localNodeId: string & import("zod").$brand<"NodeId">;
|
|
22
|
+
nodeId: import("@aria-cli/aria").NodeId;
|
|
23
|
+
displayNameSnapshot?: string;
|
|
24
|
+
fingerprint: import("@aria-cli/aria").PrincipalFingerprint;
|
|
25
|
+
revokedAt: number;
|
|
26
|
+
revokedBy: import("@aria-cli/aria").NodeId;
|
|
27
|
+
operatorConfirmation: import("@aria-cli/aria").RevocationOperatorConfirmation;
|
|
28
|
+
reason?: string;
|
|
29
|
+
revocationGeneration: number;
|
|
30
|
+
} | null;
|
|
31
|
+
getPeerRevocationGeneration(nodeId: import("@aria-cli/aria").NodeId): number | null;
|
|
32
|
+
clearRevocationForNodeId(nodeId: import("@aria-cli/aria").NodeId, expectedGeneration?: number): boolean;
|
|
33
|
+
list(): {
|
|
34
|
+
localNodeId: string & import("zod").$brand<"NodeId">;
|
|
35
|
+
nodeId: import("@aria-cli/aria").NodeId;
|
|
36
|
+
displayNameSnapshot?: string;
|
|
37
|
+
fingerprint: import("@aria-cli/aria").PrincipalFingerprint;
|
|
38
|
+
revokedAt: number;
|
|
39
|
+
revokedBy: import("@aria-cli/aria").NodeId;
|
|
40
|
+
operatorConfirmation: import("@aria-cli/aria").RevocationOperatorConfirmation;
|
|
41
|
+
reason?: string;
|
|
42
|
+
revocationGeneration: number;
|
|
43
|
+
}[];
|
|
44
|
+
close(): void;
|
|
45
|
+
};
|
|
46
|
+
peerSigningKeyStore: PeerSigningKeyStore;
|
|
47
|
+
durablePairStore: DurablePairStore;
|
|
48
|
+
nonceStore: DurableNonceStore;
|
|
49
|
+
peerTrustStore: PeerTrustStore;
|
|
50
|
+
inviteConsumeLedger: InviteConsumeLedger;
|
|
51
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare function serializeErrorDiagnostic(error: unknown, seen?: Set<unknown>): Record<string, unknown>;
|
|
2
|
+
/**
|
|
3
|
+
* Sentinel error class for attached-local-client-only failures.
|
|
4
|
+
* Carries a machine-readable `reason` sub-code so callers can
|
|
5
|
+
* distinguish missing credentials from expired/invalid ones.
|
|
6
|
+
*/
|
|
7
|
+
export declare class AttachedClientAuthError extends Error {
|
|
8
|
+
readonly code: "attached-local-client-only";
|
|
9
|
+
readonly reason: AttachedClientAuthErrorReason;
|
|
10
|
+
constructor(reason: AttachedClientAuthErrorReason);
|
|
11
|
+
}
|
|
12
|
+
export type AttachedClientAuthErrorReason = "missing_client_id" | "missing_proof" | "invalid_or_expired_lease" | "no_authority";
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Daemon-side headless dispatch handler.
|
|
3
|
+
*
|
|
4
|
+
* Maps headless operation names to authority registry calls.
|
|
5
|
+
* This is the daemon's implementation of headless commands that were
|
|
6
|
+
* previously handled CLI-side. It delegates to the same subsystem
|
|
7
|
+
* instances via the RuntimeAuthorityRegistry.
|
|
8
|
+
*
|
|
9
|
+
* Returns HeadlessResult-shaped responses (ok + result or error).
|
|
10
|
+
*/
|
|
11
|
+
import type { RuntimeAuthorityRegistry } from "./runtime-authority-registry.js";
|
|
12
|
+
interface HeadlessDispatchRequest {
|
|
13
|
+
operation: string;
|
|
14
|
+
payload?: unknown;
|
|
15
|
+
arionName?: string;
|
|
16
|
+
sessionId?: string;
|
|
17
|
+
}
|
|
18
|
+
interface HeadlessDispatchResult {
|
|
19
|
+
kind: "result";
|
|
20
|
+
requestId: string;
|
|
21
|
+
op: string;
|
|
22
|
+
ok: boolean;
|
|
23
|
+
result?: unknown;
|
|
24
|
+
error?: {
|
|
25
|
+
code: string;
|
|
26
|
+
message: string;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export declare function createHeadlessDispatchHandler(registry: RuntimeAuthorityRegistry): (request: HeadlessDispatchRequest) => Promise<HeadlessDispatchResult>;
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { type ClientId, type LocalRuntimeSummary, type NodeId, type RuntimeId } from "@aria-cli/tools";
|
|
2
|
+
import type { LocalControlApi } from "./local-control-api.js";
|
|
3
|
+
import { type ResolvedNode } from "./node-metadata.js";
|
|
4
|
+
import { type NodeRuntimeAutonomousLoopBootstrapOptions, type NodeRuntimeControl, type NodeRuntimeOptions } from "./node-runtime.js";
|
|
5
|
+
import { findRuntimeOwnerRecordByAriaHome, listRuntimeOwnerRecords as listProjectedRuntimeOwnerRecords, resolveRuntimeRootDirectory, runtimeOwnerRecordPathForNodeId, runtimeSocketsDirectory, runtimeSocketPathForNodeId, type RuntimeOwnerRecord } from "./runtime-registry.js";
|
|
6
|
+
export type HostClientKind = "tui" | "daemon-launcher" | "pipe" | "local-api";
|
|
7
|
+
export interface HostSupervisorAttachInput {
|
|
8
|
+
ariaHome: string;
|
|
9
|
+
arionName: string;
|
|
10
|
+
clientKind: HostClientKind;
|
|
11
|
+
signal?: AbortSignal;
|
|
12
|
+
silent?: boolean;
|
|
13
|
+
runtimeLifecycle?: "scoped" | "persistent";
|
|
14
|
+
}
|
|
15
|
+
export interface HostSupervisorAttachment {
|
|
16
|
+
nodeId: NodeId;
|
|
17
|
+
runtimeId: RuntimeId;
|
|
18
|
+
clientId: ClientId;
|
|
19
|
+
ownership: "started" | "reattached";
|
|
20
|
+
control: LocalControlApi;
|
|
21
|
+
runtime: NodeRuntimeControl;
|
|
22
|
+
release(options?: {
|
|
23
|
+
preserveRuntime?: boolean;
|
|
24
|
+
}): Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
interface HostSupervisorRuntimeOverrides extends Pick<NodeRuntimeOptions, "memoriaFactory" | "router" | "authResolver" | "networkManager" | "port" | "mailboxRef" | "runSessionConfig" | "mcpServers" | "daemonSafetyPolicy" | "autonomousIntervalMs"> {
|
|
27
|
+
}
|
|
28
|
+
export interface HostSupervisorOptions {
|
|
29
|
+
runtimeRoot?: string;
|
|
30
|
+
heartbeatIntervalMs?: number;
|
|
31
|
+
/**
|
|
32
|
+
* How long (ms) a client can be inactive before the heartbeat loop evicts it.
|
|
33
|
+
* Prevents unbounded growth of the clients Map when CLI sessions disconnect
|
|
34
|
+
* without calling release(). Default: 10 minutes.
|
|
35
|
+
*/
|
|
36
|
+
staleClientTtlMs?: number;
|
|
37
|
+
runtimeFactory?: (options: NodeRuntimeOptions) => Promise<{
|
|
38
|
+
runtimeId?: RuntimeId;
|
|
39
|
+
start(): Promise<void>;
|
|
40
|
+
configureAutonomousLoop?: (options: NodeRuntimeAutonomousLoopBootstrapOptions) => NodeRuntimeAutonomousLoopBootstrapOptions;
|
|
41
|
+
startAutonomousLoop?: () => Promise<void>;
|
|
42
|
+
shutdown(): Promise<void>;
|
|
43
|
+
runtimeControl?: () => NodeRuntimeControl;
|
|
44
|
+
control?: () => NodeRuntimeControl;
|
|
45
|
+
}>;
|
|
46
|
+
isPidAlive?: (pid: number) => boolean;
|
|
47
|
+
now?: () => Date;
|
|
48
|
+
resolveNode?: (options: {
|
|
49
|
+
ariaHome: string;
|
|
50
|
+
}) => Promise<ResolvedNode>;
|
|
51
|
+
}
|
|
52
|
+
export declare class HostSupervisorSplitBrainError extends Error {
|
|
53
|
+
readonly nodeId: NodeId;
|
|
54
|
+
readonly ownerPid: number;
|
|
55
|
+
readonly ownerRuntimeId: RuntimeId;
|
|
56
|
+
constructor(record: RuntimeOwnerRecord);
|
|
57
|
+
}
|
|
58
|
+
export declare class HostSupervisor {
|
|
59
|
+
private readonly runtimeRoot;
|
|
60
|
+
private readonly heartbeatIntervalMs;
|
|
61
|
+
private readonly staleClientTtlMs;
|
|
62
|
+
private readonly runtimeFactory;
|
|
63
|
+
private readonly isPidAlive;
|
|
64
|
+
private heartbeatCount;
|
|
65
|
+
private memoryLogPath;
|
|
66
|
+
private peakRssMb;
|
|
67
|
+
/**
|
|
68
|
+
* Check if a runtime's heartbeat is stale (missed 3+ consecutive heartbeats).
|
|
69
|
+
* A stale heartbeat with an alive PID means the process is a zombie
|
|
70
|
+
* (e.g., GC stall, I/O block, unreaped process).
|
|
71
|
+
*/
|
|
72
|
+
private isHeartbeatStale;
|
|
73
|
+
private readonly now;
|
|
74
|
+
private readonly resolveNode;
|
|
75
|
+
private gcRanOnce;
|
|
76
|
+
constructor(options?: HostSupervisorOptions);
|
|
77
|
+
/**
|
|
78
|
+
* One-shot garbage collection of orphaned runtime artifacts (sockets + owner records)
|
|
79
|
+
* left behind by hard crashes where shutdown hooks never ran.
|
|
80
|
+
* Runs at most once per HostSupervisor instance, on the first attach() call.
|
|
81
|
+
*/
|
|
82
|
+
private runStartupGCOnce;
|
|
83
|
+
attach(input: HostSupervisorAttachInput & HostSupervisorRuntimeOverrides): Promise<HostSupervisorAttachment>;
|
|
84
|
+
shutdownRuntime(nodeId: NodeId): Promise<void>;
|
|
85
|
+
startRuntimeAutonomousLoop(nodeId: NodeId, options: NodeRuntimeAutonomousLoopBootstrapOptions): Promise<void>;
|
|
86
|
+
listRuntimes(): LocalRuntimeSummary[];
|
|
87
|
+
private attachClient;
|
|
88
|
+
private startHeartbeatLoop;
|
|
89
|
+
/**
|
|
90
|
+
* Evict clients whose lastSeenAt is older than staleClientTtlMs.
|
|
91
|
+
* Prevents unbounded growth of the clients Map when CLI sessions
|
|
92
|
+
* disconnect without calling release() (crash, network drop, etc.).
|
|
93
|
+
*/
|
|
94
|
+
private evictStaleClients;
|
|
95
|
+
/**
|
|
96
|
+
* Write a memory snapshot to ~/.aria/logs/memory-timeline.jsonl every ~60s.
|
|
97
|
+
* Captures V8 heap breakdown + RSS so post-mortem analysis can trace which
|
|
98
|
+
* memory region grew. The file is append-only; rotation is the user's concern.
|
|
99
|
+
*/
|
|
100
|
+
private logMemorySnapshot;
|
|
101
|
+
private writeHeartbeatRecord;
|
|
102
|
+
private writeRuntimeOwnerRecord;
|
|
103
|
+
private publishBootstrapRecord;
|
|
104
|
+
}
|
|
105
|
+
export declare function getHostSupervisor(): HostSupervisor;
|
|
106
|
+
export { findRuntimeOwnerRecordByAriaHome, resolveRuntimeRootDirectory, runtimeOwnerRecordPathForNodeId, runtimeSocketsDirectory, runtimeSocketPathForNodeId, listProjectedRuntimeOwnerRecords as listRuntimeOwnerRecords, };
|
|
107
|
+
export declare function readRuntimeOwnerRecord(runtimeRoot: string, nodeId: NodeId): RuntimeOwnerRecord | null;
|
|
108
|
+
export declare function removeRuntimeOwnerRecord(runtimeRoot: string, nodeId: NodeId): void;
|
|
109
|
+
export declare function writeRuntimeOwnerRecord(runtimeRoot: string, record: RuntimeOwnerRecord): RuntimeOwnerRecord;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{A as k,B as l,w as g,x as h,y as i,z as j}from"../index-mnt9k223.js";import"../index-pe0pkp0v.js";import"../index-rr0sea4c.js";import{S as a,U as b,V as c,W as d,_ as e,da as f}from"../index-9n50yafd.js";import"../index-5tav2m70.js";import"../index-6extw9n6.js";import"../index-raeajnr7.js";import"../index-ghh3ag4c.js";import"../index-9xs3gn0p.js";export{l as writeRuntimeOwnerRecord,b as runtimeSocketsDirectory,d as runtimeSocketPathForNodeId,c as runtimeOwnerRecordPathForNodeId,a as resolveRuntimeRootDirectory,k as removeRuntimeOwnerRecord,j as readRuntimeOwnerRecord,e as listRuntimeOwnerRecords,i as getHostSupervisor,f as findRuntimeOwnerRecordByAriaHome,g as HostSupervisorSplitBrainError,h as HostSupervisor};
|