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