@privos_ai/app-server 0.6.2 → 0.7.1

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.
@@ -0,0 +1,81 @@
1
+ import type { Server } from 'node:http';
2
+ import { type Express } from 'express';
3
+ import type { AppDescriptor } from './app-descriptor.js';
4
+ import { type ReadinessCheckResult } from './direct/http-ingress.js';
5
+ import { type RoomBoundHubClient } from './relay/hub-rest-as-bot-client.js';
6
+ import { connectRelay, type RelayHandle } from './relay/relay-client.js';
7
+ import { createStandaloneRelayIdentityController } from './relay/standalone-control.js';
8
+ import { loadStandaloneIdentity } from './relay/standalone-identity.js';
9
+ import { resolveRuntimeMode, type RuntimeMode } from './runtime-mode.js';
10
+ import type { AppMcpHandler, UiResourceProvider } from './runtime.js';
11
+ import { getWorkloadIdentityClient, type WorkloadIdentityClient } from './workload/workload-identity.js';
12
+ /** Fallback listen port when no explicit `port`, `HTTP_PORT`, or `PORT` is set. */
13
+ export declare const DEFAULT_SERVE_APP_PORT = 8080;
14
+ /** Dev-only transport selector — the API form of the demo's `PRIVOS_TRANSPORT`. */
15
+ export type ServeAppTransportOverride = 'http' | 'relay';
16
+ /**
17
+ * Everything an app's handler factory needs, resolved for the active mode. The
18
+ * app builds its `McpHandler` from this and never touches transport internals.
19
+ */
20
+ export interface ServeAppHandlerContext {
21
+ mode: RuntimeMode;
22
+ /**
23
+ * Hub REST transport authenticating as this app's own installation bot,
24
+ * wired to the correct Hub-origin source for the mode. Same
25
+ * `RoomBoundHubClient` shape in every mode.
26
+ */
27
+ agentBotHub: RoomBoundHubClient;
28
+ /**
29
+ * The managed workload identity SINGLETON — present only in `managed` mode.
30
+ * Managed-ingress room authority is WeakMap-keyed by this exact instance, so
31
+ * the handler MUST use this one (never construct a fresh `WorkloadIdentityClient`).
32
+ */
33
+ workloadIdentityClient?: WorkloadIdentityClient;
34
+ /** Resolve the Hub's own origin (managed: broker; standalone: paired file; dev: `PRIVOS_URL`). */
35
+ resolveHubOrigin(): Promise<string | undefined>;
36
+ }
37
+ export interface ServeAppOptions {
38
+ descriptor: AppDescriptor | (() => AppDescriptor | Promise<AppDescriptor>);
39
+ ui?: UiResourceProvider;
40
+ /** Build the app's MCP handler from the resolved runtime context. */
41
+ createHandler: (context: ServeAppHandlerContext) => AppMcpHandler | Promise<AppMcpHandler>;
42
+ /** Explicit listen port. Precedence: explicit > `HTTP_PORT` > `PORT` > {@link DEFAULT_SERVE_APP_PORT}. */
43
+ port?: number;
44
+ /** Explicit bind host. Default `0.0.0.0`, except `development` which defaults to loopback `127.0.0.1`. */
45
+ host?: string;
46
+ /** DEVELOPMENT-ONLY. Any value under managed or standalone-production is a boot error. */
47
+ transportOverride?: ServeAppTransportOverride;
48
+ /** Standalone `/ready` manifest input. Default: parse `${cwd}/privos-app.json` fresh each check. */
49
+ resolveManifest?: () => unknown | Promise<unknown>;
50
+ /**
51
+ * Express escape hatch — mount app-owned routes (/public, /ui, diagnostics)
52
+ * BEFORE the MCP router, so the router's CORS middleware (ACAO:* + OPTIONS
53
+ * short-circuit) never stamps or swallows them.
54
+ */
55
+ configure?: (app: Express) => void | Promise<void>;
56
+ /** Own SIGTERM/SIGINT (stop relay + close server). Default true. */
57
+ installSignalHandlers?: boolean;
58
+ logger?: (event: string, fields: Record<string, unknown>) => void;
59
+ /** Test-only seams; never set in production. */
60
+ __test?: ServeAppTestSeams;
61
+ }
62
+ /** Internal seams so unit tests can inject mode, workload posture, and relay without real sockets. */
63
+ export interface ServeAppTestSeams {
64
+ env?: NodeJS.ProcessEnv;
65
+ resolveRuntimeMode?: typeof resolveRuntimeMode;
66
+ getWorkloadIdentityClient?: typeof getWorkloadIdentityClient;
67
+ loadStandaloneIdentity?: typeof loadStandaloneIdentity;
68
+ createStandaloneRelayIdentityController?: typeof createStandaloneRelayIdentityController;
69
+ connectRelay?: typeof connectRelay;
70
+ }
71
+ export interface ServeAppHandle {
72
+ mode: RuntimeMode;
73
+ server: Server;
74
+ /** Present only in standalone-production (MCP rides Relay). */
75
+ relayHandle?: RelayHandle;
76
+ /** The active `/ready` check for the resolved mode. */
77
+ readiness(): Promise<ReadinessCheckResult>;
78
+ close(): Promise<void>;
79
+ }
80
+ export declare function serveApp(options: ServeAppOptions): Promise<ServeAppHandle>;
81
+ //# sourceMappingURL=serve-app.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve-app.d.ts","sourceRoot":"","sources":["../src/serve-app.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,277 @@
1
+ /**
2
+ * `serveApp` — the single entrypoint that hides transport + trust bootstrap
3
+ * across all three runtime modes. A developer writes ONE app, declares its
4
+ * descriptor/ui/handler, and calls `serveApp(...)`; the SDK resolves the mode
5
+ * (`resolveRuntimeMode`) and wires the right transport, the workload/agent-bot
6
+ * hub client, and the readiness/health surface internally. App code never
7
+ * imports `connectRelay`, `loadStandaloneIdentity`, the identity controller,
8
+ * readiness checks, or the workload broker directly.
9
+ *
10
+ * What stays VISIBLE by design (hide plumbing, not trust): serveApp NEVER
11
+ * creates or rotates an identity file and NEVER invokes pairing on a missing
12
+ * one — it surfaces `StandaloneIdentityError` / `RuntimeModeError` verbatim.
13
+ * The pairing fingerprint/TOFU ceremony lives in `pairOverWebSocket` and the
14
+ * app's own pair scripts, and stays there.
15
+ *
16
+ * Mode matrix:
17
+ * - managed: the `getWorkloadIdentityClient()` SINGLETON + agent-bot hub from
18
+ * the workload broker + a Direct HTTP `createDirectRouter` with
19
+ * `workloadSecurity: 'required'` HARD-CODED (never 'auto': 'auto' accepts
20
+ * unsigned traffic whenever the socket is absent, including a managed
21
+ * container whose socket vanishes mid-life).
22
+ * - development: no workload client; the Direct HTTP router accepts unsigned
23
+ * traffic, so it binds loopback (127.0.0.1) by default — exposing it on
24
+ * 0.0.0.0 requires an explicit `host`. `transportOverride: 'relay'` steps
25
+ * aside for an app-owned dev relay loop (the interactive pairing prompt is
26
+ * app-local by design), serving only health/ready/ui/configure over HTTP.
27
+ * - standalone-production: `loadStandaloneIdentity` (fatal if missing/invalid)
28
+ * + the standalone identity controller + agent-bot hub from the paired Hub
29
+ * origin + `connectRelay` (MCP rides the Relay WebSocket, not HTTP) + the
30
+ * SDK readiness check. Any persisted agent-bot credential is adopted at boot.
31
+ *
32
+ * `/health` and `/ready` exist in ALL modes (marketplace Docker HEALTHCHECK and
33
+ * the cluster monitor probe them). Ambiguous identity or production-without-
34
+ * identity fails closed via `RuntimeModeError`, unchanged.
35
+ */
36
+ import { readFileSync } from 'node:fs';
37
+ import path from 'node:path';
38
+ import express from 'express';
39
+ import { createDirectRouter } from './direct/express-router.js';
40
+ import { resolveHttpIngressListen } from './direct/http-ingress.js';
41
+ import { setAdoptedAgentBotCredential } from './relay/agent-bot-credential.js';
42
+ import { createAgentBotHubClient, createAgentBotHubClientFromHubOrigin, createAgentBotHubClientFromWorkloadIdentity, } from './relay/hub-rest-as-bot-client.js';
43
+ import { connectRelay } from './relay/relay-client.js';
44
+ import { createStandaloneRelayIdentityController, } from './relay/standalone-control.js';
45
+ import { loadStandaloneIdentity, } from './relay/standalone-identity.js';
46
+ import { createStandaloneReadinessCheck } from './relay/standalone-readiness.js';
47
+ import { resolveRuntimeMode, RuntimeModeError } from './runtime-mode.js';
48
+ import { getWorkloadIdentityClient, } from './workload/workload-identity.js';
49
+ /** Fallback listen port when no explicit `port`, `HTTP_PORT`, or `PORT` is set. */
50
+ export const DEFAULT_SERVE_APP_PORT = 8080;
51
+ function defaultLogger(event, fields) {
52
+ if (event.includes('error') || event.includes('fail') || event.includes('rejected')) {
53
+ console.error(`[serveApp] ✗ ${event}`, fields);
54
+ }
55
+ else {
56
+ console.log(`[serveApp] · ${event}`);
57
+ }
58
+ }
59
+ /** Dev-only Hub origin: the legacy relay `PRIVOS_URL`, the only Hub address available outside a paired/managed runtime. */
60
+ function developmentHubOrigin(env) {
61
+ const url = env.PRIVOS_URL;
62
+ return url && /^https?:\/\//.test(url) ? url.replace(/\/+$/, '') : undefined;
63
+ }
64
+ function defaultManifestResolver() {
65
+ return JSON.parse(readFileSync(path.resolve(process.cwd(), 'privos-app.json'), 'utf8'));
66
+ }
67
+ export async function serveApp(options) {
68
+ const env = options.__test?.env ?? process.env;
69
+ const logger = options.logger ?? defaultLogger;
70
+ const resolveMode = options.__test?.resolveRuntimeMode ?? resolveRuntimeMode;
71
+ // Fail closed on ambiguous / production-without-identity, exactly as before.
72
+ const resolution = resolveMode({ env });
73
+ const mode = resolution.mode;
74
+ logger('serveApp.mode_resolved', { mode, reason: resolution.reason });
75
+ if (options.transportOverride !== undefined && mode !== 'development') {
76
+ // H1: transportOverride is the API form of PRIVOS_TRANSPORT and is a
77
+ // development affordance only. Accepting it under a production mode would
78
+ // let it override the mode's fixed, trusted transport — a boot error.
79
+ throw new RuntimeModeError('TRANSPORT_OVERRIDE_NOT_ALLOWED', `transportOverride is development-only; runtime mode is '${mode}'. Remove transportOverride, ` +
80
+ 'or run without the managed workload socket / standalone identity file for local development.');
81
+ }
82
+ // Per-mode wiring, all resolved BEFORE the handler is built so the handler
83
+ // context is complete when createHandler runs.
84
+ let workloadIdentityClient;
85
+ let agentBotHub;
86
+ let resolveHubOrigin;
87
+ let loaded;
88
+ let identityController;
89
+ let mountDirectRouter = false;
90
+ if (mode === 'managed') {
91
+ const getClient = options.__test?.getWorkloadIdentityClient ?? getWorkloadIdentityClient;
92
+ workloadIdentityClient = getClient();
93
+ resolveHubOrigin = async () => {
94
+ try {
95
+ return (await workloadIdentityClient.brokerContext()).hubOrigin;
96
+ }
97
+ catch {
98
+ return undefined;
99
+ }
100
+ };
101
+ agentBotHub = createAgentBotHubClientFromWorkloadIdentity(workloadIdentityClient);
102
+ mountDirectRouter = true;
103
+ }
104
+ else if (mode === 'standalone-production') {
105
+ const load = options.__test?.loadStandaloneIdentity ?? loadStandaloneIdentity;
106
+ loaded = load();
107
+ // Boot-seed a persisted agent-bot credential so a delivered credential
108
+ // survives restart and is usable before any live control-channel push.
109
+ if (loaded.identity.agentBotCredential)
110
+ setAdoptedAgentBotCredential(loaded.identity.agentBotCredential);
111
+ const makeController = options.__test?.createStandaloneRelayIdentityController ?? createStandaloneRelayIdentityController;
112
+ identityController = makeController(loaded, {
113
+ logger: (event, fields) => logger(event, fields),
114
+ });
115
+ resolveHubOrigin = async () => loaded.relay.privosUrl;
116
+ agentBotHub = createAgentBotHubClientFromHubOrigin(loaded.relay.privosUrl);
117
+ mountDirectRouter = false; // MCP rides Relay, not HTTP.
118
+ }
119
+ else {
120
+ resolveHubOrigin = async () => developmentHubOrigin(env);
121
+ agentBotHub = createAgentBotHubClient({ resolveHubOrigin });
122
+ // Default dev transport is Direct HTTP; 'relay' steps aside for an
123
+ // app-owned dev relay loop and serves only the HTTP support surface.
124
+ mountDirectRouter = options.transportOverride !== 'relay';
125
+ }
126
+ const handler = await options.createHandler({
127
+ mode,
128
+ agentBotHub,
129
+ workloadIdentityClient,
130
+ resolveHubOrigin,
131
+ });
132
+ // A ref-cell for the relay handle so the readiness closure can observe a
133
+ // connection that is opened AFTER the HTTP server begins listening (M5).
134
+ const relayRef = {};
135
+ const readiness = buildReadiness({
136
+ mode,
137
+ workloadIdentityClient,
138
+ relayRef,
139
+ resolveManifest: options.resolveManifest ?? defaultManifestResolver,
140
+ });
141
+ // Mount order: health/ready → configure → router. The router's CORS
142
+ // middleware stamps ACAO:* and short-circuits OPTIONS on everything mounted
143
+ // after it, so app-owned configure routes MUST come first.
144
+ const app = express();
145
+ app.get('/health', (_req, res) => {
146
+ res.status(200).json({ ok: true, status: 'alive', mode });
147
+ });
148
+ app.get('/ready', async (_req, res, next) => {
149
+ try {
150
+ const result = await readiness();
151
+ const status = result.ok ? 200 : (result.status ?? 503);
152
+ res.status(status).json({ ok: result.ok, status: result.ok ? 'ready' : 'not_ready', ...(result.body ?? {}) });
153
+ }
154
+ catch (error) {
155
+ next(error);
156
+ }
157
+ });
158
+ if (options.configure)
159
+ await options.configure(app);
160
+ if (mountDirectRouter) {
161
+ app.use(createDirectRouter({
162
+ descriptor: options.descriptor,
163
+ handler,
164
+ ui: options.ui,
165
+ // H2: managed hard-codes 'required' (never accept unsigned traffic).
166
+ // Development leaves the default 'auto', which with no workload
167
+ // socket accepts unsigned — safe only because dev binds loopback.
168
+ ...(mode === 'managed' ? { workloadSecurity: 'required', workloadIdentityClient } : {}),
169
+ }));
170
+ }
171
+ const listen = resolveHttpIngressListen({ env, defaultPort: DEFAULT_SERVE_APP_PORT });
172
+ // serveApp ALWAYS serves the HTTP support surface (/health + /ready in every
173
+ // mode), so HTTP_INGRESS=off is not honored here: never fall through to
174
+ // resolveHttpIngressListen's disabled port 0 (which would bind a random port).
175
+ const port = options.port ?? (listen.enabled ? listen.port : DEFAULT_SERVE_APP_PORT);
176
+ // H2: unsigned dev traffic must not leak off-host; loopback unless opted out.
177
+ const host = options.host ?? (mode === 'development' ? '127.0.0.1' : '0.0.0.0');
178
+ // Listen BEFORE any async identity bootstrap (M5): the cluster's
179
+ // waitForHealthy is a 30s window and must see the port up promptly.
180
+ const server = await new Promise((resolve, reject) => {
181
+ const created = app.listen(port, host, () => {
182
+ logger('serveApp.listening', { mode, host, port, mountDirectRouter });
183
+ resolve(created);
184
+ });
185
+ created.on('error', reject);
186
+ });
187
+ // Standalone connects the Relay AFTER the HTTP surface is live. connectRelay
188
+ // is non-blocking (returns a handle, connects in the background).
189
+ if (mode === 'standalone-production') {
190
+ const doConnect = options.__test?.connectRelay ?? connectRelay;
191
+ relayRef.current = doConnect({
192
+ privosUrl: loaded.relay.privosUrl,
193
+ standaloneIdentity: identityController,
194
+ descriptor: options.descriptor,
195
+ handler,
196
+ ui: options.ui,
197
+ logger: (event, fields) => logger(event, fields),
198
+ });
199
+ }
200
+ // Managed: warm the workload attestation in the background (the post-listen
201
+ // bootstrap the SDK's startHttpIngress does) and keep it fresh, so /ready
202
+ // reads a converged LAST-KNOWN-GOOD cache instead of forcing a synchronous
203
+ // broker token mint on every probe. dispose() stops the monitor.
204
+ if (mode === 'managed' && workloadIdentityClient) {
205
+ void workloadIdentityClient.getEffectiveCapabilities({ forceRefresh: true }).catch(() => undefined);
206
+ workloadIdentityClient.startCapabilityMonitor(30_000);
207
+ }
208
+ let signalHandlers = [];
209
+ const handle = {
210
+ mode,
211
+ server,
212
+ relayHandle: relayRef.current,
213
+ readiness,
214
+ async close() {
215
+ for (const { signal, handler: fn } of signalHandlers)
216
+ process.removeListener(signal, fn);
217
+ signalHandlers = [];
218
+ if (relayRef.current)
219
+ await relayRef.current.stop();
220
+ await new Promise((resolve, reject) => {
221
+ server.close((error) => (error ? reject(error) : resolve()));
222
+ });
223
+ workloadIdentityClient?.dispose();
224
+ },
225
+ };
226
+ if (options.installSignalHandlers ?? true) {
227
+ for (const signal of ['SIGTERM', 'SIGINT']) {
228
+ const fn = () => {
229
+ logger('serveApp.shutdown', { signal });
230
+ handle.close().catch((error) => {
231
+ logger('serveApp.shutdown_failed', { error: String(error) });
232
+ process.exitCode = 1;
233
+ });
234
+ };
235
+ process.once(signal, fn);
236
+ signalHandlers.push({ signal, handler: fn });
237
+ }
238
+ }
239
+ return handle;
240
+ }
241
+ function buildReadiness(input) {
242
+ if (input.mode === 'managed') {
243
+ const client = input.workloadIdentityClient;
244
+ // Read the LAST-KNOWN-GOOD attestation (no broker round-trip). The Docker
245
+ // HEALTHCHECK probes /ready every 30s with a 3s timeout, so it must not
246
+ // force a synchronous token mint that a transient broker latency spike
247
+ // could push past the timeout and flap the container. Freshness comes from
248
+ // the background capability monitor `serveApp` starts after listen.
249
+ return async () => {
250
+ const caps = client.peekEffectiveCapabilities();
251
+ const ok = caps.status === 'paired' || caps.status === 'active';
252
+ return {
253
+ ok,
254
+ status: ok ? 200 : 503,
255
+ body: {
256
+ mode: 'managed',
257
+ workload: caps.status,
258
+ scopes: caps.scopes.length,
259
+ ...(caps.reason ? { reason: caps.reason } : {}),
260
+ },
261
+ };
262
+ };
263
+ }
264
+ if (input.mode === 'standalone-production') {
265
+ const check = createStandaloneReadinessCheck({
266
+ isRelayAuthenticated: () => input.relayRef.current?.isConnected() ?? false,
267
+ resolveManifest: input.resolveManifest,
268
+ });
269
+ return async () => {
270
+ const result = await check();
271
+ return { ok: result.ok, status: result.status, body: result.body };
272
+ };
273
+ }
274
+ // development: trivial 200 — no trust to attest, unsigned local surface.
275
+ return async () => ({ ok: true, status: 200, body: { mode: 'development' } });
276
+ }
277
+ //# sourceMappingURL=serve-app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve-app.js","sourceRoot":"","sources":["../src/serve-app.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@privos_ai/app-server",
3
- "version": "0.6.2",
3
+ "version": "0.7.1",
4
4
  "description": "Business-agnostic PrivOS MCP App server runtime — Direct HTTP + Relay WebSocket",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",