@privos_ai/app-server 0.6.1 → 0.7.0
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/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/relay/agent-bot-credential.d.ts +71 -0
- package/dist/relay/agent-bot-credential.d.ts.map +1 -0
- package/dist/relay/agent-bot-credential.js +92 -0
- package/dist/relay/agent-bot-credential.js.map +1 -0
- package/dist/relay/hub-rest-as-bot-client.d.ts +77 -0
- package/dist/relay/hub-rest-as-bot-client.d.ts.map +1 -0
- package/dist/relay/hub-rest-as-bot-client.js +136 -0
- package/dist/relay/hub-rest-as-bot-client.js.map +1 -0
- package/dist/relay/relay-client.d.ts +15 -0
- package/dist/relay/relay-client.d.ts.map +1 -1
- package/dist/relay/relay-client.js +7 -2
- package/dist/relay/relay-client.js.map +1 -1
- package/dist/relay/standalone-control.d.ts +2 -1
- package/dist/relay/standalone-control.d.ts.map +1 -1
- package/dist/relay/standalone-control.js +39 -0
- package/dist/relay/standalone-control.js.map +1 -1
- package/dist/relay/standalone-identity.d.ts +9 -0
- package/dist/relay/standalone-identity.d.ts.map +1 -1
- package/dist/relay/standalone-identity.js +12 -1
- package/dist/relay/standalone-identity.js.map +1 -1
- package/dist/runtime-mode.d.ts +1 -1
- package/dist/runtime-mode.d.ts.map +1 -1
- package/dist/runtime-mode.js.map +1 -1
- package/dist/serve-app.d.ts +81 -0
- package/dist/serve-app.d.ts.map +1 -0
- package/dist/serve-app.js +277 -0
- package/dist/serve-app.js.map +1 -0
- package/package.json +1 -1
|
@@ -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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"}
|