@camstack/server 1.2.592 → 1.2.594
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/addon-root-inventory.js +11 -50
- package/dist/agent/addon-scan.js +6 -44
- package/dist/agent/agent-addon-runtime.js +3 -8
- package/dist/agent/agent-addon-updates.js +12 -52
- package/dist/agent/agent-cap-dispatch-service.js +3 -5
- package/dist/agent/agent-config.js +7 -42
- package/dist/agent/agent-deploy-swap.js +5 -41
- package/dist/agent/agent-group-runner.js +8 -47
- package/dist/agent/agent-http-auth.js +10 -22
- package/dist/agent/agent-http.js +69 -115
- package/dist/agent/agent-hub-addon-update.js +10 -16
- package/dist/agent/agent-hub-registration.js +4 -7
- package/dist/agent/agent-infra-capabilities.js +5 -9
- package/dist/agent/agent-json-file.js +5 -42
- package/dist/agent/agent-mesh-gate.js +5 -8
- package/dist/agent/agent-node-certificates.js +25 -28
- package/dist/agent/agent-pairing-local.js +10 -47
- package/dist/agent/agent-pairing-routes.js +16 -20
- package/dist/agent/agent-pairing-store.js +18 -58
- package/dist/agent/agent-reconnect.js +1 -4
- package/dist/agent/agent-service.js +42 -78
- package/dist/agent/agent-sniffing-listener.js +11 -48
- package/dist/agent/agent-undeploy.js +5 -41
- package/dist/agent/agent-update-routes.js +14 -19
- package/dist/agent/agent-update-service.js +38 -80
- package/dist/agent/apply-model-distribution.js +1 -4
- package/dist/agent/apply-stage-dev-uploads.js +6 -9
- package/dist/agent/derive-hub-url.js +3 -8
- package/dist/agent/fetch-bundle-from-hub.js +6 -9
- package/dist/agent/hubs-found.js +6 -43
- package/dist/agent/infra-boot-guard.js +1 -4
- package/dist/agent/infra-boot-plan.js +2 -6
- package/dist/agent/main.js +158 -186
- package/dist/agent/register-agent-cap-dispatch.js +3 -6
- package/dist/agent/serial-queue.js +2 -7
- package/dist/agent-status-page.js +1 -4
- package/dist/api/addon-upload.js +22 -61
- package/dist/api/agent-addon-delivery.js +6 -11
- package/dist/api/auth-whoami.js +1 -4
- package/dist/api/backup-download-pump.js +5 -9
- package/dist/api/backup-download.js +7 -10
- package/dist/api/core/addon-settings.router.js +16 -19
- package/dist/api/core/agent-pairing.router.js +76 -79
- package/dist/api/core/agents.router.js +21 -24
- package/dist/api/core/auth-admin-tokens.procedures.js +48 -52
- package/dist/api/core/auth-device-cert.procedures.js +62 -67
- package/dist/api/core/auth-limits.js +16 -25
- package/dist/api/core/auth-reauth.procedures.js +32 -37
- package/dist/api/core/auth-revoke-credentials.procedures.js +22 -26
- package/dist/api/core/auth-sessions.procedures.js +52 -56
- package/dist/api/core/auth.router.js +300 -304
- package/dist/api/core/cap-providers.js +74 -121
- package/dist/api/core/capabilities.router.js +34 -37
- package/dist/api/core/capability-preference-writes.js +10 -17
- package/dist/api/core/certificates.router.js +106 -109
- package/dist/api/core/cluster-nodes.router.js +15 -18
- package/dist/api/core/collection-preference.js +2 -6
- package/dist/api/core/event-bus-proxy.router.js +34 -37
- package/dist/api/core/failure-contributions.js +4 -8
- package/dist/api/core/hwaccel.router.js +17 -20
- package/dist/api/core/integration-secrets.js +8 -12
- package/dist/api/core/lifecycle-job-runner.js +13 -49
- package/dist/api/core/live-events.router.js +29 -32
- package/dist/api/core/load-contributions.js +4 -8
- package/dist/api/core/logging-settings.js +30 -43
- package/dist/api/core/logs.router.js +40 -43
- package/dist/api/core/notifications.router.js +15 -18
- package/dist/api/core/public-event-filter.js +4 -8
- package/dist/api/core/repl.router.js +18 -21
- package/dist/api/core/request-census-settings.js +11 -16
- package/dist/api/core/server-management.provider.js +1 -4
- package/dist/api/core/server-name.js +9 -17
- package/dist/api/core/site-location.js +16 -24
- package/dist/api/core/stream-probe.router.js +21 -24
- package/dist/api/core/system-events.router.js +23 -26
- package/dist/api/cors/cors-policy.js +20 -29
- package/dist/api/cors/register-cors-policy.js +9 -14
- package/dist/api/deploy-stage-registry.js +6 -10
- package/dist/api/dev-uploads-bundle.js +12 -50
- package/dist/api/health/adaptive-probe.routes.js +9 -13
- package/dist/api/health/health.routes.js +8 -13
- package/dist/api/hub-cluster-url.js +3 -9
- package/dist/api/model-distributor.js +12 -50
- package/dist/api/oauth2/consent-page.js +10 -13
- package/dist/api/oauth2/oauth2-routes.js +17 -25
- package/dist/api/oauth2/private-host.js +1 -4
- package/dist/api/server-upload-propagate.js +15 -51
- package/dist/api/server-upload.js +13 -50
- package/dist/api/sse-no-compression.js +1 -4
- package/dist/api/static/frame-policy.js +4 -9
- package/dist/api/static/precompressed-asset.js +15 -57
- package/dist/api/static/spa-mount.js +8 -47
- package/dist/api/static/spa-static.js +5 -12
- package/dist/api/tarball-manifest.js +7 -44
- package/dist/api/trpc/cap-mount-helpers.js +7 -12
- package/dist/api/trpc/cap-route-error-formatter.js +10 -13
- package/dist/api/trpc/cap-router-runtime.js +40 -51
- package/dist/api/trpc/client-ip.js +9 -20
- package/dist/api/trpc/core-cap-bridge.js +32 -42
- package/dist/api/trpc/device-collection-dispatch.js +23 -27
- package/dist/api/trpc/device-config-secret-redaction.js +24 -40
- package/dist/api/trpc/generated-cap-mounts.js +219 -221
- package/dist/api/trpc/generated-cap-routers.js +4878 -4726
- package/dist/api/trpc/http-request-census-hook.js +8 -11
- package/dist/api/trpc/http-request-census.js +34 -41
- package/dist/api/trpc/http-request-census.singleton.js +4 -8
- package/dist/api/trpc/localized-schema-paths.js +1 -4
- package/dist/api/trpc/principal-visibility.js +14 -22
- package/dist/api/trpc/remote-addon-update-grant.js +1 -4
- package/dist/api/trpc/scope-access.js +10 -15
- package/dist/api/trpc/server-provided-caps.js +3 -7
- package/dist/api/trpc/share-view-access.js +6 -14
- package/dist/api/trpc/trpc-error-device-tags.js +3 -6
- package/dist/api/trpc/trpc-error-principal.js +2 -6
- package/dist/api/trpc/trpc.context.js +20 -25
- package/dist/api/trpc/trpc.middleware.js +38 -46
- package/dist/api/trpc/trpc.router.js +58 -99
- package/dist/api/trpc/user-error.js +5 -8
- package/dist/api/trpc/ws-request-census.js +17 -24
- package/dist/api/trpc/ws-slow-consumer-guard.js +11 -16
- package/dist/api/upload-auth.js +5 -9
- package/dist/auth/addon-route-jwt-gate.js +4 -7
- package/dist/auth/addon-route-share-gate.js +7 -12
- package/dist/auth/app-confirm-page.js +17 -22
- package/dist/auth/app-confirm-routes.js +26 -31
- package/dist/auth/app-confirmations.js +7 -44
- package/dist/auth/app-page-shell.js +17 -30
- package/dist/auth/app-page-strings.js +11 -17
- package/dist/auth/app-passkey-page.js +16 -21
- package/dist/auth/app-passkey-routes.js +37 -41
- package/dist/auth/app-refused-route.js +13 -18
- package/dist/auth/auth-network-policy.js +11 -15
- package/dist/auth/auth-provider-gate.js +4 -9
- package/dist/auth/auth-rate-limit.js +3 -7
- package/dist/auth/client-address.js +6 -9
- package/dist/auth/device-enroll-proofs.js +6 -43
- package/dist/auth/external-link-intents.js +3 -7
- package/dist/auth/hub-sessions.js +6 -12
- package/dist/auth/native-link-completions.js +7 -11
- package/dist/auth/native-return.js +9 -13
- package/dist/auth/passkey-provider.js +26 -32
- package/dist/auth/second-factors.js +6 -10
- package/dist/auth/session-connections.js +6 -12
- package/dist/auth/session-cookie.js +12 -23
- package/dist/auth/session-lifetimes.js +8 -12
- package/dist/auth/session-mint.js +4 -11
- package/dist/auth/sso-finish-app.js +13 -16
- package/dist/auth/sso-finish-deps.js +21 -27
- package/dist/auth/sso-finish.js +28 -38
- package/dist/auth/sso-routes.js +22 -25
- package/dist/auth/used-bridge-ids.js +1 -5
- package/dist/boot/boot-config.js +16 -55
- package/dist/boot/init-sequence.js +1 -4
- package/dist/boot/integration-id-backfill.js +3 -8
- package/dist/boot/platform-keychain-key.js +5 -42
- package/dist/boot/post-boot.service.js +14 -18
- package/dist/boot/reconcile-lifecycle-jobs.js +3 -6
- package/dist/boot/retired-public-url-env.js +4 -8
- package/dist/bootstrap-packages.js +1 -4
- package/dist/closure-node-modules.js +2 -38
- package/dist/closure-patches/patch-reach.json +6 -2
- package/dist/core/addon/addon-call-gateway.js +1 -5
- package/dist/core/addon/addon-package.service.js +83 -123
- package/dist/core/addon/addon-process-view.js +2 -6
- package/dist/core/addon/addon-realign-plan.js +1 -4
- package/dist/core/addon/addon-registry.service.js +254 -197
- package/dist/core/addon/addon-row-manifest.js +1 -4
- package/dist/core/addon/addon-search.service.js +3 -7
- package/dist/core/addon/addon-settings-provider.js +1 -3
- package/dist/core/addon/addon-uninstall.js +4 -11
- package/dist/core/addon/addon.tokens.js +2 -5
- package/dist/core/addon/device-meta-mirror.js +8 -13
- package/dist/core/addon/forked-custom-actions.js +6 -11
- package/dist/core/addon/integration-visibility.js +3 -6
- package/dist/core/addon/materialize-route-path.js +1 -4
- package/dist/core/addon/package-dir-utils.js +8 -45
- package/dist/core/addon/prune-misplaced-addons.js +5 -43
- package/dist/core/addon/runner-convergence.js +1 -4
- package/dist/core/addon/runner-serialization.js +1 -4
- package/dist/core/addon/runner-spawn-fanout.js +3 -8
- package/dist/core/addon/settings-door-wiring.js +5 -8
- package/dist/core/addon/single-flight-refresh.js +1 -4
- package/dist/core/addon-bridge/addon-bridge.service.js +7 -44
- package/dist/core/addon-pages/addon-pages.service.js +3 -40
- package/dist/core/addon-widgets/addon-widgets.service.js +4 -42
- package/dist/core/agent/agent-addon-backfill.js +9 -17
- package/dist/core/agent/agent-delivery-ledger.js +3 -7
- package/dist/core/agent/agent-liveness-event.js +2 -6
- package/dist/core/agent/agent-pairing-http.js +41 -45
- package/dist/core/agent/agent-registry.service.js +53 -92
- package/dist/core/agent/cluster-node-history-mirror.js +3 -7
- package/dist/core/agent/cluster-node-history-store.js +113 -58
- package/dist/core/agent/hub-agent-pairing.js +1 -5
- package/dist/core/agent/node-certificates-client.js +3 -6
- package/dist/core/agent/node-directory.js +1 -4
- package/dist/core/app-links/well-known-app-links.js +2 -6
- package/dist/core/auth/auth.service.js +3 -8
- package/dist/core/auth/handoff-code.service.js +11 -49
- package/dist/core/auth/record-kinds.js +35 -0
- package/dist/core/auth/share-token.service.js +174 -122
- package/dist/core/capability/capability.service.js +1 -5
- package/dist/core/config/config.schema.js +1 -6
- package/dist/core/config/config.service.js +2 -6
- package/dist/core/events/event-bus.service.js +3 -7
- package/dist/core/feature/feature.service.js +2 -6
- package/dist/core/lifecycle/lifecycle-runner.singleton.js +5 -10
- package/dist/core/lifecycle/lifecycle-state-machine.js +1 -5
- package/dist/core/logging/log-ring-buffer.js +1 -5
- package/dist/core/logging/logging.service.js +5 -9
- package/dist/core/logging/scoped-logger.js +1 -5
- package/dist/core/moleculer/agent-readiness-pull.js +1 -4
- package/dist/core/moleculer/agent-registration-request.js +3 -7
- package/dist/core/moleculer/cap-call-fn.js +39 -5
- package/dist/core/moleculer/cap-route-authority.js +3 -8
- package/dist/core/moleculer/hub-mesh-guard.js +5 -9
- package/dist/core/moleculer/moleculer.service.js +108 -119
- package/dist/core/network/network-quality.service.js +2 -6
- package/dist/core/notification/notification-wrapper.service.js +3 -7
- package/dist/core/notification/toast-wrapper.service.js +3 -7
- package/dist/core/provider/provider.tokens.js +1 -4
- package/dist/core/repl/repl-engine.service.js +4 -8
- package/dist/core/runner-health/runner-boot-check.js +7 -15
- package/dist/core/runner-health/update-preflight.js +9 -14
- package/dist/core/server-update/server-update.service.js +12 -49
- package/dist/core/server-update/system-apply-closure-patches.js +6 -42
- package/dist/core/server-update/system-ensure-prebuilds.js +3 -6
- package/dist/core/server-update/system-exec-npm.js +2 -5
- package/dist/core/storage/fs-storage-backend.js +1 -5
- package/dist/core/storage/storage-location-manager.js +1 -5
- package/dist/core/storage/storage.service.js +2 -6
- package/dist/core/streaming/ffmpeg-stream-info.js +3 -8
- package/dist/core/streaming/stream-probe.service.js +12 -16
- package/dist/core/streaming/ttl-cache.js +1 -5
- package/dist/core/topology/topology-emitter.service.js +19 -23
- package/dist/core/update-availability-emitter.js +3 -7
- package/dist/core/update-availability-store.js +8 -45
- package/dist/core/updates/agent-installed-packages.js +5 -9
- package/dist/core/updates/restart-marker.js +3 -8
- package/dist/core/updates/update-check-scheduler.js +13 -18
- package/dist/core/updates/wrapper-update-checker.js +3 -7
- package/dist/first-boot-addon-plan.js +2 -6
- package/dist/framework-nodepath.js +2 -38
- package/dist/i18n/request-lang.js +7 -11
- package/dist/launcher.js +30 -65
- package/dist/lifecycle-journal-path.js +2 -38
- package/dist/main.js +287 -324
- package/dist/manual-boot.js +120 -157
- package/dist/node-role.js +1 -4
- package/dist/package-inventory.js +7 -48
- package/dist/pending-restore.js +7 -43
- package/dist/single-copy-cleanup-runner.js +9 -45
- package/dist/single-copy-cleanup.js +7 -15
- package/dist/sqlite-restore.js +9 -48
- package/dist/starter.js +4 -39
- package/dist/ui-serving/lazy-ui-serving.js +3 -39
- package/package.json +13 -13
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createAgentPairingRouter = createAgentPairingRouter;
|
|
4
|
-
const node_crypto_1 = require("node:crypto");
|
|
1
|
+
import { X509Certificate } from 'node:crypto';
|
|
5
2
|
/**
|
|
6
3
|
* Agent pairing — fixed core API for System -> Cluster -> Agents (D857).
|
|
7
4
|
*
|
|
@@ -21,67 +18,67 @@ const node_crypto_1 = require("node:crypto");
|
|
|
21
18
|
* the hub checks it against the code it computed itself. A page that sends back
|
|
22
19
|
* `code` from `getPairing` defeats the check and is a bug.
|
|
23
20
|
*/
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
21
|
+
import { browseAgentsMdns } from '@camstack/develop/hub-discovery';
|
|
22
|
+
import { getProcessMeshCaState, getProcessMeshCertificateRegistry, getProcessPeerLeaf, HubPairing, isProcessVerifiedMeshPeer, dropProcessPeer, processMeshCrl, revokeMeshCertificate, DEFAULT_HUB_TLS_TCP_PORT, } from '@camstack/system';
|
|
23
|
+
import { TRPCError } from '@trpc/server';
|
|
24
|
+
import { z } from 'zod';
|
|
25
|
+
import { createHttpAgentPairingTransport } from '../../core/agent/agent-pairing-http.js';
|
|
26
|
+
import { HubAgentPairing } from '../../core/agent/hub-agent-pairing.js';
|
|
27
|
+
import { adminProcedure, trpcRouter } from '../trpc/trpc.middleware.js';
|
|
31
28
|
const HUB_NODE_ID = 'hub';
|
|
32
29
|
const BROWSE_TIMEOUT_MS = 3_000;
|
|
33
|
-
const EndpointSchema =
|
|
34
|
-
host:
|
|
35
|
-
port:
|
|
30
|
+
const EndpointSchema = z.object({
|
|
31
|
+
host: z.string().min(1).max(253),
|
|
32
|
+
port: z.number().int().min(1).max(65535).default(4444),
|
|
36
33
|
});
|
|
37
|
-
const PairingViewSchema =
|
|
38
|
-
pairingId:
|
|
39
|
-
nodeId:
|
|
40
|
-
endpoint:
|
|
34
|
+
const PairingViewSchema = z.object({
|
|
35
|
+
pairingId: z.string(),
|
|
36
|
+
nodeId: z.string(),
|
|
37
|
+
endpoint: z.object({ host: z.string(), port: z.number() }),
|
|
41
38
|
/**
|
|
42
39
|
* The six digits the hub computed. For DISPLAY next to the agent's own: the operator
|
|
43
40
|
* confirms by typing the code the AGENT shows, never by echoing this one.
|
|
44
41
|
*/
|
|
45
|
-
code:
|
|
46
|
-
state:
|
|
47
|
-
hubConfirmed:
|
|
48
|
-
agentConfirmed:
|
|
49
|
-
expiresAt:
|
|
50
|
-
failure:
|
|
42
|
+
code: z.string(),
|
|
43
|
+
state: z.enum(['awaiting-confirmation', 'completing', 'paired', 'rejected', 'expired', 'failed']),
|
|
44
|
+
hubConfirmed: z.boolean(),
|
|
45
|
+
agentConfirmed: z.boolean(),
|
|
46
|
+
expiresAt: z.number(),
|
|
47
|
+
failure: z.string().nullable(),
|
|
51
48
|
});
|
|
52
|
-
const DiscoveredAgentSchema =
|
|
53
|
-
nodeId:
|
|
54
|
-
host:
|
|
55
|
-
port:
|
|
56
|
-
version:
|
|
57
|
-
state:
|
|
58
|
-
fingerprint:
|
|
59
|
-
source:
|
|
60
|
-
connected:
|
|
49
|
+
const DiscoveredAgentSchema = z.object({
|
|
50
|
+
nodeId: z.string(),
|
|
51
|
+
host: z.string(),
|
|
52
|
+
port: z.number(),
|
|
53
|
+
version: z.string().nullable(),
|
|
54
|
+
state: z.enum(['unpaired', 'pending', 'paired']),
|
|
55
|
+
fingerprint: z.string().nullable(),
|
|
56
|
+
source: z.enum(['mdns', 'address']),
|
|
57
|
+
connected: z.boolean(),
|
|
61
58
|
pairing: PairingViewSchema.nullable(),
|
|
62
59
|
});
|
|
63
|
-
const UnpairResultSchema =
|
|
64
|
-
nodeId:
|
|
60
|
+
const UnpairResultSchema = z.object({
|
|
61
|
+
nodeId: z.string(),
|
|
65
62
|
/** The agent acknowledged and is erasing its certificate; `false` when it could not be reached. */
|
|
66
|
-
agentNotified:
|
|
67
|
-
revokedSerials:
|
|
68
|
-
disconnected:
|
|
69
|
-
next:
|
|
63
|
+
agentNotified: z.boolean(),
|
|
64
|
+
revokedSerials: z.array(z.string()),
|
|
65
|
+
disconnected: z.number().int(),
|
|
66
|
+
next: z.string(),
|
|
70
67
|
});
|
|
71
|
-
function createAgentPairingRouter(deps) {
|
|
72
|
-
const transport = deps.transport ??
|
|
68
|
+
export function createAgentPairingRouter(deps) {
|
|
69
|
+
const transport = deps.transport ?? createHttpAgentPairingTransport();
|
|
73
70
|
const meshCa = deps.meshCa ??
|
|
74
71
|
(() => {
|
|
75
|
-
const state =
|
|
72
|
+
const state = getProcessMeshCaState();
|
|
76
73
|
return state.state === 'ready' ? state.ca : null;
|
|
77
74
|
});
|
|
78
|
-
const meshRegistry = deps.meshRegistry ??
|
|
79
|
-
const crl = deps.crl ??
|
|
75
|
+
const meshRegistry = deps.meshRegistry ?? getProcessMeshCertificateRegistry;
|
|
76
|
+
const crl = deps.crl ?? processMeshCrl;
|
|
80
77
|
const peers = deps.peers ?? {
|
|
81
|
-
peerLeaf: (nodeId) =>
|
|
82
|
-
dropPeer: (nodeId) =>
|
|
78
|
+
peerLeaf: (nodeId) => getProcessPeerLeaf(nodeId),
|
|
79
|
+
dropPeer: (nodeId) => dropProcessPeer(nodeId),
|
|
83
80
|
};
|
|
84
|
-
const isNodeConnected = deps.isNodeConnected ??
|
|
81
|
+
const isNodeConnected = deps.isNodeConnected ?? isProcessVerifiedMeshPeer;
|
|
85
82
|
const localNetwork = () => {
|
|
86
83
|
const provider = deps.registry?.getSingleton('local-network');
|
|
87
84
|
if (!provider) {
|
|
@@ -100,10 +97,10 @@ function createAgentPairingRouter(deps) {
|
|
|
100
97
|
}
|
|
101
98
|
return {
|
|
102
99
|
hubUrl,
|
|
103
|
-
hubMeshAddress: `${new URL(internal).hostname}:${
|
|
100
|
+
hubMeshAddress: `${new URL(internal).hostname}:${DEFAULT_HUB_TLS_TCP_PORT}`,
|
|
104
101
|
};
|
|
105
102
|
});
|
|
106
|
-
const pairing = new
|
|
103
|
+
const pairing = new HubPairing({
|
|
107
104
|
transport,
|
|
108
105
|
ca: meshCa,
|
|
109
106
|
hubNodeId: HUB_NODE_ID,
|
|
@@ -121,19 +118,19 @@ function createAgentPairingRouter(deps) {
|
|
|
121
118
|
const registry = meshRegistry();
|
|
122
119
|
if (registry === null)
|
|
123
120
|
return;
|
|
124
|
-
const keep = keepCertPem === undefined ? undefined : new
|
|
121
|
+
const keep = keepCertPem === undefined ? undefined : new X509Certificate(keepCertPem).fingerprint256;
|
|
125
122
|
await registry.revokeAllForNode(nodeId, reason, crl(), keep);
|
|
126
123
|
},
|
|
127
124
|
isLeafPresented: (nodeId, certPem) => {
|
|
128
125
|
const seen = peers.peerLeaf?.(nodeId)?.fingerprint;
|
|
129
126
|
const norm = (f) => f.replaceAll(':', '').toLowerCase();
|
|
130
|
-
return seen !== undefined && norm(seen) === norm(new
|
|
127
|
+
return seen !== undefined && norm(seen) === norm(new X509Certificate(certPem).fingerprint256);
|
|
131
128
|
},
|
|
132
129
|
revokeLeaf: async (_nodeId, certPem, reason) => {
|
|
133
130
|
const registry = meshRegistry();
|
|
134
131
|
if (registry === null)
|
|
135
132
|
return;
|
|
136
|
-
await registry.revoke(new
|
|
133
|
+
await registry.revoke(new X509Certificate(certPem).fingerprint256, reason, crl());
|
|
137
134
|
},
|
|
138
135
|
// Ids the registry has ever issued for: a node id differing only in case from one of them is refused.
|
|
139
136
|
knownNodeIds: () => meshRegistry()
|
|
@@ -147,11 +144,11 @@ function createAgentPairingRouter(deps) {
|
|
|
147
144
|
});
|
|
148
145
|
},
|
|
149
146
|
});
|
|
150
|
-
const service = new
|
|
147
|
+
const service = new HubAgentPairing({
|
|
151
148
|
pairing,
|
|
152
149
|
transport,
|
|
153
150
|
browse: deps.browse ??
|
|
154
|
-
(() =>
|
|
151
|
+
(() => browseAgentsMdns({
|
|
155
152
|
timeoutMs: BROWSE_TIMEOUT_MS,
|
|
156
153
|
onProblem: (message) => deps.log.warn(`agent browse problem: ${message}`),
|
|
157
154
|
})),
|
|
@@ -164,51 +161,51 @@ function createAgentPairingRouter(deps) {
|
|
|
164
161
|
return await run();
|
|
165
162
|
}
|
|
166
163
|
catch (err) {
|
|
167
|
-
if (err instanceof
|
|
164
|
+
if (err instanceof TRPCError)
|
|
168
165
|
throw err;
|
|
169
|
-
throw new
|
|
166
|
+
throw new TRPCError({
|
|
170
167
|
code: 'PRECONDITION_FAILED',
|
|
171
168
|
message: err instanceof Error ? err.message : String(err),
|
|
172
169
|
});
|
|
173
170
|
}
|
|
174
171
|
};
|
|
175
|
-
return
|
|
172
|
+
return trpcRouter({
|
|
176
173
|
/** Agents found over mDNS and addresses typed so far, with any pairing in progress. */
|
|
177
|
-
listDiscoveredAgents:
|
|
178
|
-
.input(
|
|
179
|
-
.output(
|
|
180
|
-
agents:
|
|
181
|
-
scannedAt:
|
|
174
|
+
listDiscoveredAgents: adminProcedure
|
|
175
|
+
.input(z.object({ refresh: z.boolean().optional() }).optional())
|
|
176
|
+
.output(z.object({
|
|
177
|
+
agents: z.array(DiscoveredAgentSchema),
|
|
178
|
+
scannedAt: z.number().nullable(),
|
|
182
179
|
}))
|
|
183
180
|
.query(({ input }) => guard(() => service.listDiscovered({ refresh: input?.refresh === true }))),
|
|
184
181
|
/** Probe an address the operator typed. The agent must be on a private / local address. */
|
|
185
|
-
addAgentByAddress:
|
|
186
|
-
.input(
|
|
187
|
-
host:
|
|
188
|
-
port:
|
|
182
|
+
addAgentByAddress: adminProcedure
|
|
183
|
+
.input(z.object({
|
|
184
|
+
host: z.string().min(1).max(253),
|
|
185
|
+
port: z.number().int().min(1).max(65535).optional(),
|
|
189
186
|
}))
|
|
190
187
|
.output(DiscoveredAgentSchema)
|
|
191
188
|
.mutation(({ input }) => guard(() => service.addByAddress(input.host.trim(), input.port))),
|
|
192
189
|
/** Offer the mesh CA to an agent and derive the code both screens show. */
|
|
193
|
-
beginPairing:
|
|
190
|
+
beginPairing: adminProcedure
|
|
194
191
|
.input(EndpointSchema)
|
|
195
192
|
.output(PairingViewSchema)
|
|
196
193
|
.mutation(({ input }) => guard(() => service.begin({ host: input.host.trim(), port: input.port }))),
|
|
197
|
-
getPairing:
|
|
198
|
-
.input(
|
|
194
|
+
getPairing: adminProcedure
|
|
195
|
+
.input(z.object({ pairingId: z.string().min(1) }))
|
|
199
196
|
.output(PairingViewSchema)
|
|
200
197
|
.query(({ input }) => guard(() => service.get(input.pairingId))),
|
|
201
|
-
listPairings:
|
|
202
|
-
.input(
|
|
203
|
-
.output(
|
|
198
|
+
listPairings: adminProcedure
|
|
199
|
+
.input(z.void())
|
|
200
|
+
.output(z.array(PairingViewSchema))
|
|
204
201
|
.query(() => service.list().map((p) => p)),
|
|
205
202
|
/** The operator typed the code shown on the AGENT. Wrong three times cancels the pairing. */
|
|
206
|
-
confirmPairing:
|
|
207
|
-
.input(
|
|
203
|
+
confirmPairing: adminProcedure
|
|
204
|
+
.input(z.object({ pairingId: z.string().min(1), code: z.string().min(1).max(16) }))
|
|
208
205
|
.output(PairingViewSchema)
|
|
209
206
|
.mutation(({ input }) => guard(() => service.confirm(input.pairingId, input.code))),
|
|
210
|
-
rejectPairing:
|
|
211
|
-
.input(
|
|
207
|
+
rejectPairing: adminProcedure
|
|
208
|
+
.input(z.object({ pairingId: z.string().min(1) }))
|
|
212
209
|
.output(PairingViewSchema)
|
|
213
210
|
.mutation(({ input }) => guard(() => service.reject(input.pairingId))),
|
|
214
211
|
/**
|
|
@@ -217,8 +214,8 @@ function createAgentPairingRouter(deps) {
|
|
|
217
214
|
* because revoking drops its connection. An unreachable agent is still revoked (it can no longer
|
|
218
215
|
* connect); it is then unpaired by hand on its own page.
|
|
219
216
|
*/
|
|
220
|
-
unpairAgent:
|
|
221
|
-
.input(
|
|
217
|
+
unpairAgent: adminProcedure
|
|
218
|
+
.input(z.object({ nodeId: z.string().min(1) }))
|
|
222
219
|
.output(UnpairResultSchema)
|
|
223
220
|
.mutation(({ input }) => guard(async () => {
|
|
224
221
|
if (input.nodeId === HUB_NODE_ID) {
|
|
@@ -243,7 +240,7 @@ function createAgentPairingRouter(deps) {
|
|
|
243
240
|
});
|
|
244
241
|
}
|
|
245
242
|
}
|
|
246
|
-
const revoked = await
|
|
243
|
+
const revoked = await revokeMeshCertificate({
|
|
247
244
|
nodeId: input.nodeId,
|
|
248
245
|
registry,
|
|
249
246
|
crl: crl(),
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createAgentsRouter = createAgentsRouter;
|
|
4
1
|
/**
|
|
5
2
|
* Agents router — fixed core API (not a capability).
|
|
6
3
|
*
|
|
@@ -9,13 +6,13 @@ exports.createAgentsRouter = createAgentsRouter;
|
|
|
9
6
|
* node listing remain; protocol endpoints (register, heartbeat, task
|
|
10
7
|
* dispatch) are handled natively by the Moleculer service mesh.
|
|
11
8
|
*/
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const AgentRoleSchema =
|
|
15
|
-
function createAgentsRouter(ar, moleculer) {
|
|
16
|
-
return
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
import { trpcRouter, adminProcedure } from '../trpc/trpc.middleware.js';
|
|
11
|
+
const AgentRoleSchema = z.enum(['decoder', 'transcoder', 'detector', 'recorder']);
|
|
12
|
+
export function createAgentsRouter(ar, moleculer) {
|
|
13
|
+
return trpcRouter({
|
|
17
14
|
// ── Node listing (replaces listAgents / listConnected) ────────────
|
|
18
|
-
listNodes:
|
|
15
|
+
listNodes: adminProcedure.input(z.void()).query(async () => {
|
|
19
16
|
const items = await ar.listNodes();
|
|
20
17
|
// Spread to mutable copies: AgentListItem uses readonly arrays; Zod output schema uses mutable.
|
|
21
18
|
return items.map((a) => ({
|
|
@@ -33,7 +30,7 @@ function createAgentsRouter(ar, moleculer) {
|
|
|
33
30
|
}));
|
|
34
31
|
}),
|
|
35
32
|
// ── Capability discovery (via Moleculer service list) ─────────────
|
|
36
|
-
getAgentCapabilities:
|
|
33
|
+
getAgentCapabilities: adminProcedure.input(z.void()).query(async () => {
|
|
37
34
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access -- moleculer.broker.call typing chain unresolvable; runtime shape validated by the cast below
|
|
38
35
|
const services = (await moleculer.broker.call('$node.services', {}));
|
|
39
36
|
const capSet = new Set();
|
|
@@ -45,27 +42,27 @@ function createAgentsRouter(ar, moleculer) {
|
|
|
45
42
|
return [...capSet].toSorted();
|
|
46
43
|
}),
|
|
47
44
|
// ── Role assignments ──────────────────────────────────────────────
|
|
48
|
-
getAssignments:
|
|
49
|
-
.input(
|
|
45
|
+
getAssignments: adminProcedure
|
|
46
|
+
.input(z.object({ cameraId: z.number().optional() }))
|
|
50
47
|
.query(({ input }) => ar.getAssignments(input.cameraId)),
|
|
51
|
-
setAssignment:
|
|
52
|
-
.input(
|
|
53
|
-
cameraId:
|
|
48
|
+
setAssignment: adminProcedure
|
|
49
|
+
.input(z.object({
|
|
50
|
+
cameraId: z.number(),
|
|
54
51
|
role: AgentRoleSchema,
|
|
55
|
-
agentId:
|
|
56
|
-
priority:
|
|
57
|
-
rtspUrl:
|
|
52
|
+
agentId: z.string(),
|
|
53
|
+
priority: z.enum(['primary', 'backup', 'overflow']),
|
|
54
|
+
rtspUrl: z.string().optional(),
|
|
58
55
|
}))
|
|
59
56
|
.mutation(({ input }) => ar.setAssignment(input)),
|
|
60
|
-
removeAssignment:
|
|
61
|
-
.input(
|
|
62
|
-
cameraId:
|
|
57
|
+
removeAssignment: adminProcedure
|
|
58
|
+
.input(z.object({
|
|
59
|
+
cameraId: z.number(),
|
|
63
60
|
role: AgentRoleSchema,
|
|
64
61
|
}))
|
|
65
62
|
.mutation(({ input }) => ar.removeAssignment(input.cameraId, input.role)),
|
|
66
|
-
activateBackup:
|
|
67
|
-
.input(
|
|
68
|
-
cameraId:
|
|
63
|
+
activateBackup: adminProcedure
|
|
64
|
+
.input(z.object({
|
|
65
|
+
cameraId: z.number(),
|
|
69
66
|
role: AgentRoleSchema,
|
|
70
67
|
}))
|
|
71
68
|
.mutation(({ input }) => ar.activateBackup(input.cameraId, input.role)),
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.AuthAuditRecordSchema = exports.AdminTokenSchema = exports.ADMIN_TOKEN_MAX_DAYS = exports.ADMIN_TOKEN_DEFAULT_DAYS = void 0;
|
|
4
|
-
exports.createAdminTokenProcedures = createAdminTokenProcedures;
|
|
5
1
|
/**
|
|
6
2
|
* Admin tokens (`csa_`) and the auth audit trail, as the `auth` router serves
|
|
7
3
|
* them. The token store and its rules are local-auth's
|
|
@@ -9,44 +5,44 @@ exports.createAdminTokenProcedures = createAdminTokenProcedures;
|
|
|
9
5
|
* real signed-in session (never a token minting a token), right after
|
|
10
6
|
* re-authenticating. Every create / use / revoke is audited.
|
|
11
7
|
*/
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
8
|
+
import { ADMIN_TOKEN_MAX_LIFETIME_MS } from '@camstack/system';
|
|
9
|
+
import { TRPCError } from '@trpc/server';
|
|
10
|
+
import { z } from 'zod';
|
|
11
|
+
import { userManagementInternal } from '../../auth/hub-sessions.js';
|
|
12
|
+
import { adminProcedure } from '../trpc/trpc.middleware.js';
|
|
13
|
+
import { assertReauthenticated, ReauthTokenInput } from './auth-reauth.procedures.js';
|
|
18
14
|
const DAY_MS = 86_400_000;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
id:
|
|
23
|
-
createdBy:
|
|
24
|
-
name:
|
|
25
|
-
tokenPrefix:
|
|
26
|
-
createdAt:
|
|
27
|
-
expiresAt:
|
|
28
|
-
lastUsedAt:
|
|
29
|
-
revokedAt:
|
|
15
|
+
export const ADMIN_TOKEN_DEFAULT_DAYS = 7;
|
|
16
|
+
export const ADMIN_TOKEN_MAX_DAYS = ADMIN_TOKEN_MAX_LIFETIME_MS / DAY_MS;
|
|
17
|
+
export const AdminTokenSchema = z.object({
|
|
18
|
+
id: z.string(),
|
|
19
|
+
createdBy: z.string(),
|
|
20
|
+
name: z.string(),
|
|
21
|
+
tokenPrefix: z.string(),
|
|
22
|
+
createdAt: z.number(),
|
|
23
|
+
expiresAt: z.number(),
|
|
24
|
+
lastUsedAt: z.number().nullable(),
|
|
25
|
+
revokedAt: z.number().nullable(),
|
|
30
26
|
});
|
|
31
|
-
|
|
32
|
-
id:
|
|
33
|
-
at:
|
|
34
|
-
action:
|
|
35
|
-
userId:
|
|
36
|
-
ip:
|
|
37
|
-
detail:
|
|
27
|
+
export const AuthAuditRecordSchema = z.object({
|
|
28
|
+
id: z.string(),
|
|
29
|
+
at: z.number(),
|
|
30
|
+
action: z.string(),
|
|
31
|
+
userId: z.string().optional(),
|
|
32
|
+
ip: z.string().optional(),
|
|
33
|
+
detail: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])).optional(),
|
|
38
34
|
});
|
|
39
35
|
function requireInternal(registry) {
|
|
40
|
-
const internal = registry === null ? null :
|
|
36
|
+
const internal = registry === null ? null : userManagementInternal(registry);
|
|
41
37
|
if (internal === null) {
|
|
42
|
-
throw new
|
|
38
|
+
throw new TRPCError({
|
|
43
39
|
code: 'PRECONDITION_FAILED',
|
|
44
40
|
message: 'User management is not available',
|
|
45
41
|
});
|
|
46
42
|
}
|
|
47
43
|
return internal;
|
|
48
44
|
}
|
|
49
|
-
function createAdminTokenProcedures(deps) {
|
|
45
|
+
export function createAdminTokenProcedures(deps) {
|
|
50
46
|
return {
|
|
51
47
|
/**
|
|
52
48
|
* ADMIN — mint an admin token for an ops script. Requires a real
|
|
@@ -54,28 +50,28 @@ function createAdminTokenProcedures(deps) {
|
|
|
54
50
|
* re-authentication. Expiry mandatory: 1–90 days, default 7. The token
|
|
55
51
|
* is in this answer only.
|
|
56
52
|
*/
|
|
57
|
-
createAdminToken:
|
|
58
|
-
.input(
|
|
59
|
-
name:
|
|
60
|
-
expiresInDays:
|
|
53
|
+
createAdminToken: adminProcedure
|
|
54
|
+
.input(z.object({
|
|
55
|
+
name: z.string().trim().min(1).max(80),
|
|
56
|
+
expiresInDays: z
|
|
61
57
|
.number()
|
|
62
58
|
.int()
|
|
63
59
|
.min(1)
|
|
64
|
-
.max(
|
|
65
|
-
.default(
|
|
66
|
-
reauthToken:
|
|
60
|
+
.max(ADMIN_TOKEN_MAX_DAYS)
|
|
61
|
+
.default(ADMIN_TOKEN_DEFAULT_DAYS),
|
|
62
|
+
reauthToken: ReauthTokenInput.optional(),
|
|
67
63
|
}))
|
|
68
|
-
.output(
|
|
64
|
+
.output(z.object({ token: z.string(), record: AdminTokenSchema }))
|
|
69
65
|
.mutation(async ({ ctx, input }) => {
|
|
70
66
|
if (ctx.user.isScoped === true ||
|
|
71
67
|
ctx.user.shareView !== undefined ||
|
|
72
68
|
ctx.user.credential !== undefined) {
|
|
73
|
-
throw new
|
|
69
|
+
throw new TRPCError({
|
|
74
70
|
code: 'FORBIDDEN',
|
|
75
71
|
message: 'An admin token can only be created from a signed-in admin session',
|
|
76
72
|
});
|
|
77
73
|
}
|
|
78
|
-
|
|
74
|
+
assertReauthenticated(deps.auth, ctx.user, input.reauthToken);
|
|
79
75
|
const internal = requireInternal(deps.registry);
|
|
80
76
|
const created = await internal.adminTokens.create({
|
|
81
77
|
createdBy: ctx.user.id,
|
|
@@ -97,14 +93,14 @@ function createAdminTokenProcedures(deps) {
|
|
|
97
93
|
return created;
|
|
98
94
|
}),
|
|
99
95
|
/** ADMIN — every admin token not yet reaped (no secrets). */
|
|
100
|
-
listAdminTokens:
|
|
101
|
-
.input(
|
|
102
|
-
.output(
|
|
96
|
+
listAdminTokens: adminProcedure
|
|
97
|
+
.input(z.void())
|
|
98
|
+
.output(z.array(AdminTokenSchema))
|
|
103
99
|
.query(async () => [...(await requireInternal(deps.registry).adminTokens.list())]),
|
|
104
100
|
/** ADMIN — revoke one admin token; it stops working at once. */
|
|
105
|
-
revokeAdminToken:
|
|
106
|
-
.input(
|
|
107
|
-
.output(
|
|
101
|
+
revokeAdminToken: adminProcedure
|
|
102
|
+
.input(z.object({ id: z.string().min(1) }))
|
|
103
|
+
.output(z.object({ success: z.boolean() }))
|
|
108
104
|
.mutation(async ({ ctx, input }) => {
|
|
109
105
|
const internal = requireInternal(deps.registry);
|
|
110
106
|
const success = await internal.adminTokens.revoke(input.id);
|
|
@@ -120,14 +116,14 @@ function createAdminTokenProcedures(deps) {
|
|
|
120
116
|
return { success };
|
|
121
117
|
}),
|
|
122
118
|
/** ADMIN — the authentication audit trail, newest first. */
|
|
123
|
-
listAuthAudit:
|
|
124
|
-
.input(
|
|
119
|
+
listAuthAudit: adminProcedure
|
|
120
|
+
.input(z
|
|
125
121
|
.object({
|
|
126
|
-
limit:
|
|
127
|
-
userId:
|
|
122
|
+
limit: z.number().int().min(1).max(500).optional(),
|
|
123
|
+
userId: z.string().min(1).optional(),
|
|
128
124
|
})
|
|
129
125
|
.optional())
|
|
130
|
-
.output(
|
|
126
|
+
.output(z.array(AuthAuditRecordSchema))
|
|
131
127
|
.query(async ({ input }) => [
|
|
132
128
|
...(await requireInternal(deps.registry).audit.list({
|
|
133
129
|
...(input?.limit !== undefined ? { limit: input.limit } : {}),
|