@aopslabs/aops-server 0.2.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/LICENSE +19 -0
- package/NOTICE +7 -0
- package/README.md +28 -0
- package/THIRD_PARTY_NOTICES +13409 -0
- package/THIRD_PARTY_NOTICES.inventory.json +2768 -0
- package/build/client/_app/immutable/chunks/2_TffmqH.js +1 -0
- package/build/client/_app/immutable/chunks/3DOfIKW0.js +1 -0
- package/build/client/_app/immutable/chunks/B2EkC-sy.js +1 -0
- package/build/client/_app/immutable/chunks/BlANKL2r.js +1 -0
- package/build/client/_app/immutable/chunks/CMkIcmi1.js +2 -0
- package/build/client/_app/immutable/chunks/rqnVXeyB.js +1 -0
- package/build/client/_app/immutable/chunks/wbPk3Yxo.js +81 -0
- package/build/client/_app/immutable/entry/app.a0iGCm6X.js +2 -0
- package/build/client/_app/immutable/entry/start.Df7u6fQ1.js +1 -0
- package/build/client/_app/immutable/nodes/0.BYBfjxZ5.js +1 -0
- package/build/client/_app/immutable/nodes/1.BtbjYUHR.js +1 -0
- package/build/client/_app/version.json +1 -0
- package/build/env.js +69 -0
- package/build/handler.js +15 -0
- package/build/index.js +138 -0
- package/build/server/chunks/0-RfB6m2nq.js +6 -0
- package/build/server/chunks/1-UJuUicIe.js +8 -0
- package/build/server/chunks/_server.ts-6bdzoHJH.js +83 -0
- package/build/server/chunks/_server.ts-AwMeEYiZ.js +9 -0
- package/build/server/chunks/_server.ts-B9gjXi95.js +260 -0
- package/build/server/chunks/_server.ts-BX4X0tW0.js +16 -0
- package/build/server/chunks/_server.ts-BkxSxdd0.js +172 -0
- package/build/server/chunks/_server.ts-Bly8fCZa.js +90 -0
- package/build/server/chunks/_server.ts-Bz-Erv-1.js +43 -0
- package/build/server/chunks/_server.ts-CRKd0KAC.js +43 -0
- package/build/server/chunks/_server.ts-CjzSQgpk.js +95 -0
- package/build/server/chunks/_server.ts-Cv-yaXZI.js +6 -0
- package/build/server/chunks/_server.ts-DQWRrk5C.js +14 -0
- package/build/server/chunks/_server.ts-DQzYSH_C.js +125 -0
- package/build/server/chunks/_server.ts-DaIr3NkR.js +10 -0
- package/build/server/chunks/_server.ts-DbdAfdYo.js +8 -0
- package/build/server/chunks/_server.ts-De9ZrSV0.js +84 -0
- package/build/server/chunks/_server.ts-DsTeOL2P.js +17 -0
- package/build/server/chunks/_server.ts-N61POKjl.js +84 -0
- package/build/server/chunks/_server.ts-Ua5Ieisy.js +37 -0
- package/build/server/chunks/_server.ts-XmKDT59M.js +37 -0
- package/build/server/chunks/_server.ts-o9pJceJP.js +54 -0
- package/build/server/chunks/_server.ts-u2UWBqNN.js +276 -0
- package/build/server/chunks/admission-snapshot-C2wGfTWE.js +1034 -0
- package/build/server/chunks/agent-gateway-runtime-C7Kvvy0H.js +2614 -0
- package/build/server/chunks/aops-runtime-config-CHpDUCdE.js +185 -0
- package/build/server/chunks/auth-provider-C07OUlnz.js +18 -0
- package/build/server/chunks/canonical-text-order-DbXJJnFD.js +5 -0
- package/build/server/chunks/commercial-admission-loader-V_vXHdVa.js +2077 -0
- package/build/server/chunks/discovery-BvDEgiqC.js +897 -0
- package/build/server/chunks/error.svelte-B9R6O_Hn.js +44 -0
- package/build/server/chunks/handler-DurXhqww.js +1472 -0
- package/build/server/chunks/hooks.server-DYGrWbgh.js +62 -0
- package/build/server/chunks/index.js-BQnOaW3H.js +11573 -0
- package/build/server/chunks/manifest.js-CCJDdahY.js +180 -0
- package/build/server/chunks/plugin-error-normalize-DNeRsopQ.js +309 -0
- package/build/server/chunks/project-alias-BdnRxWft.js +28 -0
- package/build/server/chunks/registry-DO8ob5o1.js +660 -0
- package/build/server/chunks/request-base-url-zKJpVUv5.js +35 -0
- package/build/server/chunks/request-context-9wzBoKrz.js +421 -0
- package/build/server/chunks/xf-result-BRDjvftr.js +16 -0
- package/build/shims.js +32 -0
- package/cockpit/.vite/manifest.json +198 -0
- package/cockpit/assets/dm-sans-latin-400-normal-BwCSEQnW.woff +0 -0
- package/cockpit/assets/dm-sans-latin-400-normal-CW0RaeGs.woff2 +0 -0
- package/cockpit/assets/dm-sans-latin-500-normal-B9HHJjqV.woff2 +0 -0
- package/cockpit/assets/dm-sans-latin-500-normal-Dr3UlScf.woff +0 -0
- package/cockpit/assets/dm-sans-latin-700-normal-CUSSCpQX.woff +0 -0
- package/cockpit/assets/dm-sans-latin-700-normal-DvUfVpUG.woff2 +0 -0
- package/cockpit/assets/dm-sans-latin-ext-400-normal-BjWJ59Pq.woff +0 -0
- package/cockpit/assets/dm-sans-latin-ext-400-normal-BtiwyxMk.woff2 +0 -0
- package/cockpit/assets/dm-sans-latin-ext-500-normal-BJfUCQsA.woff2 +0 -0
- package/cockpit/assets/dm-sans-latin-ext-500-normal-DR84L5F-.woff +0 -0
- package/cockpit/assets/dm-sans-latin-ext-700-normal-BLI3TTWz.woff +0 -0
- package/cockpit/assets/dm-sans-latin-ext-700-normal-CJIcxD6K.woff2 +0 -0
- package/cockpit/assets/index-CkhZWZ2f.js +18 -0
- package/cockpit/assets/index-TSfC5rf2.css +1 -0
- package/cockpit/assets/jetbrains-mono-cyrillic-400-normal-BEIGL1Tu.woff2 +0 -0
- package/cockpit/assets/jetbrains-mono-cyrillic-400-normal-ugxPyKxw.woff +0 -0
- package/cockpit/assets/jetbrains-mono-greek-400-normal-B9oWc5Lo.woff +0 -0
- package/cockpit/assets/jetbrains-mono-greek-400-normal-C190GLew.woff2 +0 -0
- package/cockpit/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff +0 -0
- package/cockpit/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
- package/cockpit/assets/jetbrains-mono-latin-ext-400-normal-Bc8Ftmh3.woff2 +0 -0
- package/cockpit/assets/jetbrains-mono-latin-ext-400-normal-fXTG6kC5.woff +0 -0
- package/cockpit/assets/jetbrains-mono-vietnamese-400-normal-CqNFfHCs.woff +0 -0
- package/cockpit/assets/outfit-latin-400-normal-BGsTXAXT.woff2 +0 -0
- package/cockpit/assets/outfit-latin-400-normal-DMwTpYkH.woff +0 -0
- package/cockpit/assets/outfit-latin-600-normal-B7SfZ07L.woff2 +0 -0
- package/cockpit/assets/outfit-latin-600-normal-BEfTtDA7.woff +0 -0
- package/cockpit/assets/outfit-latin-ext-400-normal-5tcqmc2S.woff2 +0 -0
- package/cockpit/assets/outfit-latin-ext-400-normal-DHm7mdGe.woff +0 -0
- package/cockpit/assets/outfit-latin-ext-600-normal-B85nYjL1.woff2 +0 -0
- package/cockpit/assets/outfit-latin-ext-600-normal-CWJcPgd7.woff +0 -0
- package/cockpit/assets/unbounded-cyrillic-600-normal-B-s5c2Kn.woff +0 -0
- package/cockpit/assets/unbounded-cyrillic-600-normal-DW6uzIMB.woff2 +0 -0
- package/cockpit/assets/unbounded-latin-600-normal-BPdB_PEv.woff +0 -0
- package/cockpit/assets/unbounded-latin-600-normal-oRSANpZr.woff2 +0 -0
- package/cockpit/assets/unbounded-latin-ext-600-normal-0iZLtTDV.woff2 +0 -0
- package/cockpit/assets/unbounded-latin-ext-600-normal-ClMPf-bu.woff +0 -0
- package/cockpit/assets/unbounded-vietnamese-600-normal-BzfrgZ_C.woff +0 -0
- package/cockpit/assets/unbounded-vietnamese-600-normal-Cx2bTSHN.woff2 +0 -0
- package/cockpit/community.module-inventory.json +2439 -0
- package/cockpit/index.html +14 -0
- package/community-postgres.json +13 -0
- package/migrations/agentspace/0000_thin_carlie_cooper.sql +764 -0
- package/migrations/agentspace/meta/_journal.json +13 -0
- package/migrations/chatv3/0000_dry_ego.sql +218 -0
- package/migrations/chatv3/0001_nosy_obadiah_stane.sql +35 -0
- package/migrations/chatv3/0002_narrow_darkhawk.sql +4 -0
- package/migrations/chatv3/0003_damp_zarek.sql +2 -0
- package/migrations/chatv3/0004_nervous_martin_li.sql +60 -0
- package/migrations/chatv3/0005_chatv3_server_encrypted_mode.sql +1 -0
- package/migrations/chatv3/0006_chatv3_database_server_keyring.sql +21 -0
- package/migrations/chatv3/meta/_journal.json +55 -0
- package/migrations/docman/0000_curvy_valeria_richards.sql +257 -0
- package/migrations/docman/0001_massive_risque.sql +2 -0
- package/migrations/docman/0002_simple_logan.sql +50 -0
- package/migrations/docman/0003_quick_index.sql +45 -0
- package/migrations/docman/0004_known_summary.sql +9 -0
- package/migrations/docman/0005_vector_signal.sql +9 -0
- package/migrations/docman/0006_document_version_current_invariant.sql +15 -0
- package/migrations/docman/meta/_journal.json +55 -0
- package/migrations/projectman/0000_smooth_klaw.sql +257 -0
- package/migrations/projectman/0001_worthless_zodiak.sql +9 -0
- package/migrations/projectman/0002_board_rename.sql +108 -0
- package/migrations/projectman/0003_review_request.sql +62 -0
- package/migrations/projectman/0004_review_request_idempotency.sql +3 -0
- package/migrations/projectman/0005_allow_multi_sprint_per_task.sql +1 -0
- package/migrations/projectman/meta/_journal.json +48 -0
- package/migrations/sys/0000_loose_praxagora.sql +31 -0
- package/migrations/sys/0001_awesome_ronan.sql +2 -0
- package/migrations/sys/0002_steady_maximus.sql +2 -0
- package/migrations/sys/0003_escalating_rate_limiter.sql +2 -0
- package/migrations/sys/0004_rate_limiter_timestamptz.sql +22 -0
- package/migrations/sys/0005_sys_counters.sql +21 -0
- package/migrations/sys/meta/_journal.json +48 -0
- package/npm-shrinkwrap.json +5069 -0
- package/package.json +88 -0
- package/runtime/agentspace-host-adapter.mjs +64 -0
- package/runtime/agentspace-tooling.mjs +389 -0
- package/runtime/commercial-integrity-worker.mjs +1643 -0
- package/runtime/docman-host-adapter.mjs +177 -0
- package/runtime/docman-policy.mjs +450 -0
- package/runtime/docman-tooling.mjs +20 -0
- package/runtime/projectman-host-adapter.mjs +597 -0
- package/runtime/scope-context.mjs +99 -0
- package/runtime-closure.package.json +376 -0
- package/scripts/community-host.mjs +919 -0
- package/scripts/community-migration-policy-package-v1.json +11854 -0
|
@@ -0,0 +1,660 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { pathToFileURL, fileURLToPath } from 'node:url';
|
|
4
|
+
import { validateHostConfig, DomainPluginRegistry, normalizeDomainName } from '@aopslabs/host-core';
|
|
5
|
+
import { p as private_env } from './index.js-BQnOaW3H.js';
|
|
6
|
+
import './aops-runtime-config-CHpDUCdE.js';
|
|
7
|
+
import { existsSync } from 'node:fs';
|
|
8
|
+
import { Worker } from 'node:worker_threads';
|
|
9
|
+
import { A as AdmissionDecisionCache, b as buildAdmittedDomainSnapshot, C as CommercialArtifactError } from './admission-snapshot-C2wGfTWE.js';
|
|
10
|
+
|
|
11
|
+
const COMMUNITY_FREE_DOMAIN_IDS = Object.freeze([
|
|
12
|
+
"agentspace",
|
|
13
|
+
"chatv3",
|
|
14
|
+
"docman",
|
|
15
|
+
"projectman",
|
|
16
|
+
"sys"
|
|
17
|
+
]);
|
|
18
|
+
const COMMERCIAL_INTEGRITY_LISTENER_READY_EVENT = "aops-community:commercial-integrity-listener-ready";
|
|
19
|
+
const COMMERCIAL_INTEGRITY_HOST_SHUTDOWN_EVENT = "aops-community:commercial-integrity-host-shutdown";
|
|
20
|
+
const SCHEDULE_RETRY_MS = 6e4;
|
|
21
|
+
const MAX_TIMER_DELAY_MS = 2147e6;
|
|
22
|
+
const COMMERCIAL_INTEGRITY_WORKER_TIMEOUT_MS = 15 * 6e4;
|
|
23
|
+
function resolveCommercialIntegrityWorkerModuleUrl(moduleUrl = import.meta.url) {
|
|
24
|
+
const modulePath = fileURLToPath(moduleUrl);
|
|
25
|
+
const moduleDirectory = path.dirname(modulePath);
|
|
26
|
+
const builtChunk = modulePath.includes(
|
|
27
|
+
`${path.sep}build${path.sep}server${path.sep}chunks${path.sep}`
|
|
28
|
+
);
|
|
29
|
+
const packageRoot = path.resolve(
|
|
30
|
+
moduleDirectory,
|
|
31
|
+
...builtChunk ? ["..", "..", ".."] : ["..", ".."]
|
|
32
|
+
);
|
|
33
|
+
return pathToFileURL(path.join(
|
|
34
|
+
packageRoot,
|
|
35
|
+
"runtime",
|
|
36
|
+
"commercial-integrity-worker.mjs"
|
|
37
|
+
));
|
|
38
|
+
}
|
|
39
|
+
const cache = new AdmissionDecisionCache(buildAdmittedDomainSnapshot({
|
|
40
|
+
generation: 1,
|
|
41
|
+
freeDomains: COMMUNITY_FREE_DOMAIN_IDS
|
|
42
|
+
}));
|
|
43
|
+
let commercialRuntime = null;
|
|
44
|
+
let commercialFailureLatched = false;
|
|
45
|
+
let integrityTimer = null;
|
|
46
|
+
let integrityWorkerRunning = false;
|
|
47
|
+
let integritySchedulerStopped = false;
|
|
48
|
+
let activeIntegrityWorker = null;
|
|
49
|
+
let integrityRuntime = Object.freeze({
|
|
50
|
+
state: "disabled",
|
|
51
|
+
listenerReady: false,
|
|
52
|
+
dueAt: null,
|
|
53
|
+
lastVerifiedAt: null,
|
|
54
|
+
failure: null
|
|
55
|
+
});
|
|
56
|
+
function normalizedFailure(error, now) {
|
|
57
|
+
return Object.freeze({
|
|
58
|
+
stage: error instanceof CommercialArtifactError ? error.stage : "commercial-integrity-scheduler",
|
|
59
|
+
decision: error instanceof CommercialArtifactError ? error.decision : "deny",
|
|
60
|
+
reason: error instanceof CommercialArtifactError ? error.reason : error instanceof Error ? error.message : "scheduled_verification_failed",
|
|
61
|
+
detectedAt: now.toISOString()
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
function applyScheduledCommercialIntegrityFailure(error, now) {
|
|
65
|
+
if (commercialFailureLatched) return;
|
|
66
|
+
commercialFailureLatched = true;
|
|
67
|
+
cache.replace(buildAdmittedDomainSnapshot({
|
|
68
|
+
generation: cache.read().generation + 1,
|
|
69
|
+
freeDomains: COMMUNITY_FREE_DOMAIN_IDS,
|
|
70
|
+
now
|
|
71
|
+
}));
|
|
72
|
+
commercialRuntime = null;
|
|
73
|
+
integrityRuntime = Object.freeze({
|
|
74
|
+
state: "failed-closed",
|
|
75
|
+
listenerReady: integrityRuntime.listenerReady,
|
|
76
|
+
dueAt: null,
|
|
77
|
+
lastVerifiedAt: integrityRuntime.lastVerifiedAt,
|
|
78
|
+
failure: normalizedFailure(error, now)
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
const configuredAdmission = process.env.AOPS_COMMERCIAL_ADMISSION_CONFIG?.trim();
|
|
82
|
+
if (configuredAdmission) {
|
|
83
|
+
try {
|
|
84
|
+
const { loadCommercialAdmissionSnapshot } = await import('./commercial-admission-loader-V_vXHdVa.js');
|
|
85
|
+
const loaded = loadCommercialAdmissionSnapshot(
|
|
86
|
+
configuredAdmission,
|
|
87
|
+
COMMUNITY_FREE_DOMAIN_IDS
|
|
88
|
+
);
|
|
89
|
+
cache.replace(loaded.snapshot);
|
|
90
|
+
commercialRuntime = loaded.runtime;
|
|
91
|
+
integrityRuntime = Object.freeze({
|
|
92
|
+
...integrityRuntime,
|
|
93
|
+
state: "waiting"
|
|
94
|
+
});
|
|
95
|
+
} catch (error) {
|
|
96
|
+
applyScheduledCommercialIntegrityFailure(error, /* @__PURE__ */ new Date());
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function getHostAdmissionSnapshot() {
|
|
100
|
+
return cache.read();
|
|
101
|
+
}
|
|
102
|
+
function getCommercialRuntimeProjection() {
|
|
103
|
+
return commercialRuntime;
|
|
104
|
+
}
|
|
105
|
+
function runCommercialIntegrityVerificationWorker(input, now, options = {}) {
|
|
106
|
+
return new Promise((resolve, reject) => {
|
|
107
|
+
const workerData = {
|
|
108
|
+
input,
|
|
109
|
+
now: now.toISOString()
|
|
110
|
+
};
|
|
111
|
+
const worker = options.workerSource ? new Worker(options.workerSource, {
|
|
112
|
+
eval: true,
|
|
113
|
+
workerData
|
|
114
|
+
}) : new Worker(options.workerModuleUrl ?? resolveCommercialIntegrityWorkerModuleUrl(), {
|
|
115
|
+
workerData
|
|
116
|
+
});
|
|
117
|
+
activeIntegrityWorker = worker;
|
|
118
|
+
let settled = false;
|
|
119
|
+
let timeout = null;
|
|
120
|
+
const markSettled = () => {
|
|
121
|
+
if (settled) return false;
|
|
122
|
+
settled = true;
|
|
123
|
+
activeIntegrityWorker = null;
|
|
124
|
+
if (timeout) clearTimeout(timeout);
|
|
125
|
+
timeout = null;
|
|
126
|
+
return true;
|
|
127
|
+
};
|
|
128
|
+
const fail = (error) => {
|
|
129
|
+
if (!markSettled()) return;
|
|
130
|
+
reject(error);
|
|
131
|
+
};
|
|
132
|
+
worker.once("error", fail);
|
|
133
|
+
worker.once("exit", (code) => {
|
|
134
|
+
if (!settled) {
|
|
135
|
+
fail(new Error(code === 0 ? "commercial_integrity_worker_no_result" : "commercial_integrity_worker_failed"));
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
worker.once("message", (message) => {
|
|
139
|
+
if (!markSettled()) return;
|
|
140
|
+
if (message.ok) resolve();
|
|
141
|
+
else reject(new CommercialArtifactError(
|
|
142
|
+
message.stage,
|
|
143
|
+
message.reason,
|
|
144
|
+
message.decision === "quarantine" ? "quarantine" : "deny"
|
|
145
|
+
));
|
|
146
|
+
});
|
|
147
|
+
timeout = setTimeout(() => {
|
|
148
|
+
void worker.terminate();
|
|
149
|
+
fail(new Error("commercial_integrity_worker_timeout"));
|
|
150
|
+
}, options.timeoutMs ?? COMMERCIAL_INTEGRITY_WORKER_TIMEOUT_MS);
|
|
151
|
+
timeout.unref();
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
function setIntegrityTimer(callback, delayMs) {
|
|
155
|
+
if (integritySchedulerStopped) return;
|
|
156
|
+
if (integrityTimer) clearTimeout(integrityTimer);
|
|
157
|
+
integrityTimer = setTimeout(callback, Math.min(Math.max(delayMs, 0), MAX_TIMER_DELAY_MS));
|
|
158
|
+
integrityTimer.unref();
|
|
159
|
+
}
|
|
160
|
+
async function runScheduledIntegrityVerification() {
|
|
161
|
+
if (!configuredAdmission || integrityWorkerRunning || integritySchedulerStopped) return;
|
|
162
|
+
integrityWorkerRunning = true;
|
|
163
|
+
const now = /* @__PURE__ */ new Date();
|
|
164
|
+
integrityRuntime = Object.freeze({
|
|
165
|
+
...integrityRuntime,
|
|
166
|
+
state: "verifying",
|
|
167
|
+
listenerReady: true,
|
|
168
|
+
dueAt: now.toISOString()
|
|
169
|
+
});
|
|
170
|
+
try {
|
|
171
|
+
const { resolveCommercialIntegrityWorkerInput } = await import('./commercial-admission-loader-V_vXHdVa.js');
|
|
172
|
+
await runCommercialIntegrityVerificationWorker(
|
|
173
|
+
resolveCommercialIntegrityWorkerInput(configuredAdmission),
|
|
174
|
+
now
|
|
175
|
+
);
|
|
176
|
+
integrityRuntime = Object.freeze({
|
|
177
|
+
state: commercialFailureLatched ? "recovery-verified-restart-required" : "verified",
|
|
178
|
+
listenerReady: true,
|
|
179
|
+
dueAt: null,
|
|
180
|
+
lastVerifiedAt: now.toISOString(),
|
|
181
|
+
failure: integrityRuntime.failure
|
|
182
|
+
});
|
|
183
|
+
} catch (error) {
|
|
184
|
+
applyScheduledCommercialIntegrityFailure(error, /* @__PURE__ */ new Date());
|
|
185
|
+
} finally {
|
|
186
|
+
integrityWorkerRunning = false;
|
|
187
|
+
if (!integritySchedulerStopped) {
|
|
188
|
+
setIntegrityTimer(() => {
|
|
189
|
+
void planScheduledIntegrityVerification();
|
|
190
|
+
}, SCHEDULE_RETRY_MS);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
async function planScheduledIntegrityVerification() {
|
|
195
|
+
if (!configuredAdmission || integrityWorkerRunning || integritySchedulerStopped) return;
|
|
196
|
+
const now = /* @__PURE__ */ new Date();
|
|
197
|
+
try {
|
|
198
|
+
const { readCommercialAdmissionIntegritySchedule } = await import('./commercial-admission-loader-V_vXHdVa.js');
|
|
199
|
+
const schedule = readCommercialAdmissionIntegritySchedule(configuredAdmission, now);
|
|
200
|
+
if (schedule.state === "authority-unavailable" || schedule.state === "quarantined") {
|
|
201
|
+
applyScheduledCommercialIntegrityFailure(
|
|
202
|
+
new Error(schedule.state === "quarantined" ? "integrity_scheduled_quarantine_active" : "integrity_authority_unavailable"),
|
|
203
|
+
now
|
|
204
|
+
);
|
|
205
|
+
setIntegrityTimer(() => {
|
|
206
|
+
void planScheduledIntegrityVerification();
|
|
207
|
+
}, SCHEDULE_RETRY_MS);
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
if (schedule.state === "due" || !schedule.dueAt) {
|
|
211
|
+
await runScheduledIntegrityVerification();
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
const delayMs = Math.max(0, Date.parse(schedule.dueAt) - now.getTime());
|
|
215
|
+
integrityRuntime = Object.freeze({
|
|
216
|
+
state: commercialFailureLatched ? "recovery-verified-restart-required" : "waiting",
|
|
217
|
+
listenerReady: true,
|
|
218
|
+
dueAt: schedule.dueAt,
|
|
219
|
+
lastVerifiedAt: schedule.verifiedAt,
|
|
220
|
+
failure: integrityRuntime.failure
|
|
221
|
+
});
|
|
222
|
+
setIntegrityTimer(() => {
|
|
223
|
+
void planScheduledIntegrityVerification();
|
|
224
|
+
}, delayMs);
|
|
225
|
+
} catch (error) {
|
|
226
|
+
applyScheduledCommercialIntegrityFailure(error, now);
|
|
227
|
+
setIntegrityTimer(() => {
|
|
228
|
+
void planScheduledIntegrityVerification();
|
|
229
|
+
}, SCHEDULE_RETRY_MS);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
function startHostCommercialIntegrityScheduler() {
|
|
233
|
+
if (!configuredAdmission || integrityRuntime.listenerReady) return;
|
|
234
|
+
integritySchedulerStopped = false;
|
|
235
|
+
integrityRuntime = Object.freeze({ ...integrityRuntime, listenerReady: true });
|
|
236
|
+
void planScheduledIntegrityVerification();
|
|
237
|
+
}
|
|
238
|
+
function stopHostCommercialIntegrityScheduler() {
|
|
239
|
+
integritySchedulerStopped = true;
|
|
240
|
+
if (integrityTimer) clearTimeout(integrityTimer);
|
|
241
|
+
integrityTimer = null;
|
|
242
|
+
if (activeIntegrityWorker) void activeIntegrityWorker.terminate();
|
|
243
|
+
activeIntegrityWorker = null;
|
|
244
|
+
}
|
|
245
|
+
process.once(
|
|
246
|
+
COMMERCIAL_INTEGRITY_LISTENER_READY_EVENT,
|
|
247
|
+
startHostCommercialIntegrityScheduler
|
|
248
|
+
);
|
|
249
|
+
process.once(
|
|
250
|
+
COMMERCIAL_INTEGRITY_HOST_SHUTDOWN_EVENT,
|
|
251
|
+
stopHostCommercialIntegrityScheduler
|
|
252
|
+
);
|
|
253
|
+
function checkHostDomainAdmission(domain, operationId, now) {
|
|
254
|
+
return cache.check(domain, operationId, now);
|
|
255
|
+
}
|
|
256
|
+
function getAdmittedDomainIds() {
|
|
257
|
+
return getHostAdmissionSnapshot().orderedDomains.map((decision) => decision.domain);
|
|
258
|
+
}
|
|
259
|
+
function getHostAdmissionDiagnostics() {
|
|
260
|
+
const snapshot = getHostAdmissionSnapshot();
|
|
261
|
+
return Object.freeze({
|
|
262
|
+
schemaVersion: 1,
|
|
263
|
+
generation: snapshot.generation,
|
|
264
|
+
createdAt: snapshot.createdAt,
|
|
265
|
+
runtimeRegistration: Object.freeze({
|
|
266
|
+
state: commercialRuntime ? "derived-from-verified-evidence" : "community-only",
|
|
267
|
+
domain: commercialRuntime?.domain ?? null
|
|
268
|
+
}),
|
|
269
|
+
commercialIntegrity: integrityRuntime,
|
|
270
|
+
domains: Object.freeze(snapshot.orderedDomains.map((decision) => Object.freeze({
|
|
271
|
+
domain: decision.domain,
|
|
272
|
+
plane: decision.plane,
|
|
273
|
+
state: decision.state,
|
|
274
|
+
reason: decision.reason,
|
|
275
|
+
productId: decision.productId,
|
|
276
|
+
manifestDigest: decision.manifestDigest,
|
|
277
|
+
closureDigest: decision.closureDigest,
|
|
278
|
+
entitlementEpoch: decision.entitlementEpoch,
|
|
279
|
+
refreshAfter: decision.refreshAfter,
|
|
280
|
+
fullUntil: decision.fullUntil,
|
|
281
|
+
expiresAt: decision.expiresAt,
|
|
282
|
+
migrationEligible: decision.migrationEligible
|
|
283
|
+
})))
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
const host = { "name": "aops-community-server", "apiBasePath": "/api" };
|
|
287
|
+
const runtime = { "env": { "AOPS_PG_URL": { "fromEnv": "AOPS_PG_URL", "required": true } } };
|
|
288
|
+
const pluginLoader = { "strictAllowlist": true, "tolerantBootstrap": false, "allowlist": ["@aopslabs/domain-host-plugin-sys", "./runtime/agentspace-host-adapter.mjs", "./runtime/docman-host-adapter.mjs", "./runtime/projectman-host-adapter.mjs", "@aopslabs/domain-host-plugin-chatv3"] };
|
|
289
|
+
const diagnostics = { "exposePluginBootstrap": true };
|
|
290
|
+
const agentGateway = { "enabled": true, "includeLocal": true, "catalog": { "enabled": true, "manifestProviders": [{ "id": "sys-dcm", "domain": "sys", "enabled": true, "module": "@aopslabs/domain-kit-sys", "exportName": "buildSysDomainCapabilityManifest", "options": { "domainVersion": "0.0.1", "includeDocs": true } }, { "id": "agentspace-dcm", "domain": "agentspace", "enabled": true, "module": "./runtime/agentspace-tooling.mjs", "exportName": "buildCommunityAgentspaceDomainCapabilityManifest", "options": { "domainVersion": "0.0.4", "includeDocs": true } }, { "id": "docman-dcm", "domain": "docman", "enabled": true, "module": "./runtime/docman-tooling.mjs", "exportName": "buildAopsDocmanDomainCapabilityManifest", "options": { "domainVersion": "0.1.3", "includeDocs": true } }, { "id": "projectman-dcm", "domain": "projectman", "enabled": true, "module": "@aopslabs/domain-kit-projectman", "exportName": "buildProjectmanDomainCapabilityManifest", "options": { "domainVersion": "0.1.2", "includeDocs": true } }, { "id": "chatv3-dcm", "domain": "chatv3", "enabled": true, "module": "@aopslabs/domain-kit-chatv3", "exportName": "buildChatv3DomainCapabilityManifest", "options": { "domainVersion": "0.1.0", "includeDocs": true } }] }, "sources": [] };
|
|
291
|
+
const plugins = [{ "domain": "sys", "enabled": true, "module": "@aopslabs/domain-host-plugin-sys", "factory": "createSysPlugin" }, { "domain": "agentspace", "enabled": true, "module": "./runtime/agentspace-host-adapter.mjs", "factory": "createCommunityAgentspacePlugin", "options": { "defaultTenantId": "123e4567-e89b-41d4-a000-000000000001" } }, { "domain": "docman", "enabled": true, "module": "./runtime/docman-host-adapter.mjs", "factory": "createDocmanPlugin", "options": { "defaultScopeId": "00000000-0000-4000-8000-000000000000" } }, { "domain": "projectman", "enabled": true, "module": "./runtime/projectman-host-adapter.mjs", "factory": "createProjectmanPlugin", "options": { "defaultProjectId": "123e4567-e89b-41d4-a000-000000000000", "enableAopsWriteback": true, "failOnWritebackError": false } }, { "domain": "chatv3", "enabled": true, "module": "@aopslabs/domain-host-plugin-chatv3", "factory": "createChatv3Plugin" }];
|
|
292
|
+
const configRaw = {
|
|
293
|
+
host,
|
|
294
|
+
runtime,
|
|
295
|
+
pluginLoader,
|
|
296
|
+
diagnostics,
|
|
297
|
+
agentGateway,
|
|
298
|
+
plugins
|
|
299
|
+
};
|
|
300
|
+
const MODULE_DIR = path.dirname(fileURLToPath(import.meta.url));
|
|
301
|
+
const SERVER_PACKAGE_ROOT_CANDIDATE = [
|
|
302
|
+
path.resolve(MODULE_DIR, "../../.."),
|
|
303
|
+
path.resolve(MODULE_DIR, "../../../.."),
|
|
304
|
+
path.resolve(MODULE_DIR, "../..")
|
|
305
|
+
].find(
|
|
306
|
+
(candidate) => existsSync(path.join(candidate, "runtime", "agentspace-host-adapter.mjs"))
|
|
307
|
+
);
|
|
308
|
+
if (!SERVER_PACKAGE_ROOT_CANDIDATE) {
|
|
309
|
+
throw new Error("community_server_package_root_not_found");
|
|
310
|
+
}
|
|
311
|
+
const SERVER_PACKAGE_ROOT = SERVER_PACKAGE_ROOT_CANDIDATE;
|
|
312
|
+
function resolveCommunityPackageModule(moduleName) {
|
|
313
|
+
if (!moduleName) throw new Error("community_host_module_missing");
|
|
314
|
+
if (!moduleName.startsWith("./runtime/")) return moduleName;
|
|
315
|
+
return path.join(SERVER_PACKAGE_ROOT, moduleName.slice(2));
|
|
316
|
+
}
|
|
317
|
+
const COMMUNITY_PLUGIN_MODULES = Object.freeze([
|
|
318
|
+
"@aopslabs/domain-host-plugin-sys",
|
|
319
|
+
resolveCommunityPackageModule("./runtime/agentspace-host-adapter.mjs"),
|
|
320
|
+
resolveCommunityPackageModule("./runtime/docman-host-adapter.mjs"),
|
|
321
|
+
resolveCommunityPackageModule("./runtime/projectman-host-adapter.mjs"),
|
|
322
|
+
"@aopslabs/domain-host-plugin-chatv3"
|
|
323
|
+
]);
|
|
324
|
+
const COMMUNITY_RUNTIME_ENV_KEYS = Object.freeze(["AOPS_PG_URL"]);
|
|
325
|
+
const codepointCompare = (left, right) => left < right ? -1 : left > right ? 1 : 0;
|
|
326
|
+
const sorted = (values) => [...values].sort(codepointCompare);
|
|
327
|
+
const normalize = (value) => String(value ?? "").trim().toLowerCase();
|
|
328
|
+
function exactSet(label, actual, expected) {
|
|
329
|
+
const left = sorted(actual.map(normalize).filter(Boolean));
|
|
330
|
+
const right = sorted(expected.map(normalize).filter(Boolean));
|
|
331
|
+
if (new Set(left).size !== left.length || new Set(right).size !== right.length || left.length !== right.length || !left.every((value, index) => value === right[index])) {
|
|
332
|
+
throw new Error(`community_host_config_set_mismatch:${label}:expected=${right.join(",")}:actual=${left.join(",")}`);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
function inventory(config) {
|
|
336
|
+
return {
|
|
337
|
+
pluginDomains: (config.plugins ?? []).map((plugin) => normalize(plugin.domain)).filter(Boolean),
|
|
338
|
+
manifestProviderDomains: (config.agentGateway?.catalog?.manifestProviders ?? []).map((provider) => normalize(provider.domain)).filter(Boolean),
|
|
339
|
+
sourceDomains: (config.agentGateway?.sources ?? []).map((source) => normalize(source.domain)).filter(Boolean)
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
function validateStaticCommunityConfig(input) {
|
|
343
|
+
const config = structuredClone(input);
|
|
344
|
+
config.plugins = (config.plugins ?? []).map((plugin) => ({
|
|
345
|
+
...plugin,
|
|
346
|
+
module: resolveCommunityPackageModule(plugin.module)
|
|
347
|
+
}));
|
|
348
|
+
if (config.agentGateway?.catalog) {
|
|
349
|
+
config.agentGateway.catalog.manifestProviders = (config.agentGateway.catalog.manifestProviders ?? []).map((provider) => ({
|
|
350
|
+
...provider,
|
|
351
|
+
module: resolveCommunityPackageModule(provider.module)
|
|
352
|
+
}));
|
|
353
|
+
}
|
|
354
|
+
if (config.pluginLoader) {
|
|
355
|
+
config.pluginLoader.allowlist = (config.pluginLoader.allowlist ?? []).map(resolveCommunityPackageModule);
|
|
356
|
+
}
|
|
357
|
+
const commercial = getCommercialRuntimeProjection();
|
|
358
|
+
if (commercial) {
|
|
359
|
+
config.plugins = [
|
|
360
|
+
...config.plugins ?? [],
|
|
361
|
+
{
|
|
362
|
+
domain: commercial.domain,
|
|
363
|
+
enabled: true,
|
|
364
|
+
module: commercial.pluginModule,
|
|
365
|
+
factory: commercial.pluginFactory
|
|
366
|
+
}
|
|
367
|
+
];
|
|
368
|
+
const catalog = config.agentGateway?.catalog;
|
|
369
|
+
if (!catalog) throw new Error("community_host_config_catalog_missing");
|
|
370
|
+
catalog.manifestProviders = [
|
|
371
|
+
...catalog.manifestProviders ?? [],
|
|
372
|
+
{
|
|
373
|
+
id: `${commercial.domain}-commercial-dcm`,
|
|
374
|
+
domain: commercial.domain,
|
|
375
|
+
enabled: true,
|
|
376
|
+
module: commercial.manifestModule,
|
|
377
|
+
exportName: commercial.manifestExport
|
|
378
|
+
}
|
|
379
|
+
];
|
|
380
|
+
const loader = config.pluginLoader;
|
|
381
|
+
if (!loader) throw new Error("community_host_config_plugin_loader_missing");
|
|
382
|
+
loader.allowlist = [...loader.allowlist ?? [], commercial.pluginModule];
|
|
383
|
+
}
|
|
384
|
+
const issues = validateHostConfig(config);
|
|
385
|
+
if (issues.length > 0) {
|
|
386
|
+
const first = issues[0];
|
|
387
|
+
throw new Error(`host_config_invalid:${first.code}:${first.path}`);
|
|
388
|
+
}
|
|
389
|
+
const domains = inventory(config);
|
|
390
|
+
const admittedDomains = getAdmittedDomainIds();
|
|
391
|
+
exactSet("plugins", domains.pluginDomains, admittedDomains);
|
|
392
|
+
exactSet("manifest-providers", domains.manifestProviderDomains, admittedDomains);
|
|
393
|
+
exactSet("remote-sources", domains.sourceDomains, []);
|
|
394
|
+
exactSet(
|
|
395
|
+
"plugin-loader",
|
|
396
|
+
config.pluginLoader?.allowlist ?? [],
|
|
397
|
+
commercial ? [...COMMUNITY_PLUGIN_MODULES, commercial.pluginModule] : COMMUNITY_PLUGIN_MODULES
|
|
398
|
+
);
|
|
399
|
+
exactSet("runtime-env", Object.keys(config.runtime?.env ?? {}), COMMUNITY_RUNTIME_ENV_KEYS);
|
|
400
|
+
if (config.pluginLoader?.strictAllowlist !== true || config.pluginLoader?.tolerantBootstrap !== false || config.agentGateway?.enabled !== true || config.agentGateway?.includeLocal !== true || config.agentGateway?.catalog?.enabled !== true) {
|
|
401
|
+
throw new Error("community_host_config_policy_mismatch");
|
|
402
|
+
}
|
|
403
|
+
return config;
|
|
404
|
+
}
|
|
405
|
+
const STATIC_HOST_CONFIG = validateStaticCommunityConfig(configRaw);
|
|
406
|
+
const EMPTY_INVENTORY = Object.freeze({
|
|
407
|
+
pluginDomains: [],
|
|
408
|
+
manifestProviderDomains: [],
|
|
409
|
+
sourceDomains: []
|
|
410
|
+
});
|
|
411
|
+
function getHostConfig() {
|
|
412
|
+
return structuredClone(STATIC_HOST_CONFIG);
|
|
413
|
+
}
|
|
414
|
+
function getHostRegistrationDiagnostics() {
|
|
415
|
+
const explicit = inventory(STATIC_HOST_CONFIG);
|
|
416
|
+
return {
|
|
417
|
+
registrationsDir: "<disabled:community-static-host-config>",
|
|
418
|
+
count: 0,
|
|
419
|
+
precedence: ["host.config.json"],
|
|
420
|
+
explicit,
|
|
421
|
+
installed: structuredClone(EMPTY_INVENTORY),
|
|
422
|
+
effective: structuredClone(explicit),
|
|
423
|
+
registrations: []
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
function applyHostRuntimeEnv(config) {
|
|
427
|
+
const processEnv = process.env;
|
|
428
|
+
const bindings = config.runtime?.env ?? {};
|
|
429
|
+
exactSet("runtime-env-apply", Object.keys(bindings), COMMUNITY_RUNTIME_ENV_KEYS);
|
|
430
|
+
for (const [targetKey, binding] of Object.entries(bindings)) {
|
|
431
|
+
const resolved = (typeof binding.value === "string" ? binding.value : void 0) ?? (typeof binding.fromEnv === "string" ? private_env[binding.fromEnv] ?? processEnv[binding.fromEnv] : void 0) ?? (typeof binding.default === "string" ? binding.default : void 0);
|
|
432
|
+
if ((!resolved || resolved.trim().length === 0) && binding.required === true) {
|
|
433
|
+
throw new Error(`host_runtime_env_required:${targetKey}`);
|
|
434
|
+
}
|
|
435
|
+
if (resolved && resolved.trim().length > 0) processEnv[targetKey] = resolved;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
function guardCommercialPluginExecution(instance, domain, checkAdmission) {
|
|
439
|
+
const baseExecute = instance.execute;
|
|
440
|
+
if (typeof baseExecute !== "function") return instance;
|
|
441
|
+
return {
|
|
442
|
+
...instance,
|
|
443
|
+
execute: async (args) => {
|
|
444
|
+
const operationId = String(args?.match?.route?.operation ?? "").trim();
|
|
445
|
+
if (!operationId) {
|
|
446
|
+
throw new Error(`domain_admission_denied:${domain}:operation_not_admitted`);
|
|
447
|
+
}
|
|
448
|
+
const admission = checkAdmission(domain, operationId);
|
|
449
|
+
if (!admission.allowed) {
|
|
450
|
+
throw new Error(`domain_admission_denied:${domain}:${admission.reason}`);
|
|
451
|
+
}
|
|
452
|
+
return baseExecute.call(instance, args);
|
|
453
|
+
}
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
const runtimeImport = new Function("specifier", "return import(specifier)");
|
|
457
|
+
const nodeRequire = createRequire(import.meta.url);
|
|
458
|
+
let pluginImportVersion = 0;
|
|
459
|
+
const DEFAULT_DIAGNOSTICS = {
|
|
460
|
+
attempt: 0,
|
|
461
|
+
state: "idle",
|
|
462
|
+
loadedDomains: [],
|
|
463
|
+
plugins: []
|
|
464
|
+
};
|
|
465
|
+
let singletonPromise = null;
|
|
466
|
+
let bootstrapAttempt = 0;
|
|
467
|
+
let registryDiagnostics = { ...DEFAULT_DIAGNOSTICS };
|
|
468
|
+
function extractErrorMessage(error) {
|
|
469
|
+
if (error instanceof Error) return error.message;
|
|
470
|
+
return String(error ?? "unknown_error");
|
|
471
|
+
}
|
|
472
|
+
function resolveModuleSpecifier(moduleName) {
|
|
473
|
+
const trimmed = moduleName.trim();
|
|
474
|
+
if (!trimmed) return trimmed;
|
|
475
|
+
if (trimmed.startsWith("file://")) return trimmed;
|
|
476
|
+
if (path.isAbsolute(trimmed)) return pathToFileURL(trimmed).href;
|
|
477
|
+
if (!trimmed.startsWith(".")) {
|
|
478
|
+
const resolvePaths = [process.cwd(), path.resolve(process.cwd(), "apps/aops-server")];
|
|
479
|
+
try {
|
|
480
|
+
const resolved = nodeRequire.resolve(trimmed, { paths: resolvePaths });
|
|
481
|
+
return pathToFileURL(resolved).href;
|
|
482
|
+
} catch {
|
|
483
|
+
return trimmed;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
const absolutePath = path.resolve(process.cwd(), trimmed);
|
|
487
|
+
return pathToFileURL(absolutePath).href;
|
|
488
|
+
}
|
|
489
|
+
function withImportVersion(specifier) {
|
|
490
|
+
if (!specifier.startsWith("file://")) return specifier;
|
|
491
|
+
const url = new URL(specifier);
|
|
492
|
+
url.searchParams.set("v", String(pluginImportVersion));
|
|
493
|
+
return url.href;
|
|
494
|
+
}
|
|
495
|
+
function isModuleAllowed(moduleName, resolvedSpecifier, policy) {
|
|
496
|
+
const allowlist = policy.allowlist ?? [];
|
|
497
|
+
if (allowlist.length === 0) return policy.strictAllowlist === false;
|
|
498
|
+
return allowlist.includes(moduleName) || allowlist.includes(resolvedSpecifier);
|
|
499
|
+
}
|
|
500
|
+
function assertModuleAllowed(moduleName, resolvedSpecifier, pluginConfig, policy) {
|
|
501
|
+
if (isModuleAllowed(moduleName, resolvedSpecifier, policy)) return;
|
|
502
|
+
if ((policy.allowlist ?? []).length === 0 && policy.strictAllowlist) {
|
|
503
|
+
throw new Error(`plugin_module_allowlist_empty:${pluginConfig.domain}`);
|
|
504
|
+
}
|
|
505
|
+
throw new Error(`plugin_module_not_allowed:${pluginConfig.domain}:${moduleName}`);
|
|
506
|
+
}
|
|
507
|
+
async function createPluginFromConfig(pluginConfig, policy) {
|
|
508
|
+
const moduleName = pluginConfig.module;
|
|
509
|
+
if (!moduleName) {
|
|
510
|
+
throw new Error(`plugin_module_missing:${pluginConfig.domain}`);
|
|
511
|
+
}
|
|
512
|
+
const resolvedSpecifier = resolveModuleSpecifier(moduleName);
|
|
513
|
+
assertModuleAllowed(moduleName, resolvedSpecifier, pluginConfig, policy);
|
|
514
|
+
const exportName = pluginConfig.factory?.trim() || "createPlugin";
|
|
515
|
+
let mod;
|
|
516
|
+
try {
|
|
517
|
+
mod = await runtimeImport(withImportVersion(resolvedSpecifier));
|
|
518
|
+
} catch (error) {
|
|
519
|
+
throw new Error(
|
|
520
|
+
`plugin_module_import_failed:${pluginConfig.domain}:${moduleName}:${extractErrorMessage(error)}`
|
|
521
|
+
);
|
|
522
|
+
}
|
|
523
|
+
const maybeFactory = mod[exportName] ?? mod.default;
|
|
524
|
+
if (typeof maybeFactory !== "function") {
|
|
525
|
+
throw new Error(`plugin_factory_not_found:${pluginConfig.domain}:${moduleName}#${exportName}`);
|
|
526
|
+
}
|
|
527
|
+
const instance = await Promise.resolve(
|
|
528
|
+
maybeFactory(pluginConfig.options)
|
|
529
|
+
);
|
|
530
|
+
if (!instance || typeof instance !== "object") {
|
|
531
|
+
throw new Error(`plugin_factory_invalid_result:${pluginConfig.domain}`);
|
|
532
|
+
}
|
|
533
|
+
const configDomain = normalizeDomainName(pluginConfig.domain);
|
|
534
|
+
const pluginDomain = normalizeDomainName(instance.domain ?? "");
|
|
535
|
+
if (configDomain && pluginDomain && configDomain !== pluginDomain) {
|
|
536
|
+
throw new Error(`plugin_config_domain_mismatch:${configDomain}:${pluginDomain}`);
|
|
537
|
+
}
|
|
538
|
+
return guardCommercialPluginExecution(
|
|
539
|
+
instance,
|
|
540
|
+
configDomain,
|
|
541
|
+
checkHostDomainAdmission
|
|
542
|
+
);
|
|
543
|
+
}
|
|
544
|
+
async function buildRegistry() {
|
|
545
|
+
const registry = new DomainPluginRegistry();
|
|
546
|
+
const config = getHostConfig();
|
|
547
|
+
const policy = config.pluginLoader ?? {
|
|
548
|
+
allowlist: [],
|
|
549
|
+
strictAllowlist: false,
|
|
550
|
+
tolerantBootstrap: false
|
|
551
|
+
};
|
|
552
|
+
const tolerantBootstrap = policy.tolerantBootstrap === true;
|
|
553
|
+
const plugins2 = config.plugins ?? [];
|
|
554
|
+
const diagnostics2 = {
|
|
555
|
+
attempt: ++bootstrapAttempt,
|
|
556
|
+
state: "building",
|
|
557
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
558
|
+
loadedDomains: [],
|
|
559
|
+
plugins: []
|
|
560
|
+
};
|
|
561
|
+
registryDiagnostics = diagnostics2;
|
|
562
|
+
applyHostRuntimeEnv(config);
|
|
563
|
+
const failedDomains = [];
|
|
564
|
+
try {
|
|
565
|
+
for (const pluginConfig of plugins2) {
|
|
566
|
+
const pluginStart = Date.now();
|
|
567
|
+
const domain = normalizeDomainName(pluginConfig.domain ?? "");
|
|
568
|
+
const moduleName = pluginConfig.module?.trim() || null;
|
|
569
|
+
const factoryName = pluginConfig.factory?.trim() || "createPlugin";
|
|
570
|
+
if (pluginConfig.enabled === false) {
|
|
571
|
+
diagnostics2.plugins.push({
|
|
572
|
+
domain,
|
|
573
|
+
module: moduleName,
|
|
574
|
+
factory: factoryName,
|
|
575
|
+
status: "skipped",
|
|
576
|
+
durationMs: Date.now() - pluginStart
|
|
577
|
+
});
|
|
578
|
+
continue;
|
|
579
|
+
}
|
|
580
|
+
if (!checkHostDomainAdmission(domain).allowed) {
|
|
581
|
+
diagnostics2.plugins.push({
|
|
582
|
+
domain,
|
|
583
|
+
module: moduleName,
|
|
584
|
+
factory: factoryName,
|
|
585
|
+
status: "skipped",
|
|
586
|
+
durationMs: Date.now() - pluginStart,
|
|
587
|
+
error: "domain_not_admitted"
|
|
588
|
+
});
|
|
589
|
+
continue;
|
|
590
|
+
}
|
|
591
|
+
try {
|
|
592
|
+
const plugin = await createPluginFromConfig(pluginConfig, policy);
|
|
593
|
+
registry.register(plugin);
|
|
594
|
+
diagnostics2.plugins.push({
|
|
595
|
+
domain: normalizeDomainName(plugin.domain ?? domain),
|
|
596
|
+
module: moduleName,
|
|
597
|
+
factory: factoryName,
|
|
598
|
+
status: "loaded",
|
|
599
|
+
durationMs: Date.now() - pluginStart
|
|
600
|
+
});
|
|
601
|
+
} catch (error) {
|
|
602
|
+
const message = extractErrorMessage(error);
|
|
603
|
+
diagnostics2.plugins.push({
|
|
604
|
+
domain,
|
|
605
|
+
module: moduleName,
|
|
606
|
+
factory: factoryName,
|
|
607
|
+
status: "failed",
|
|
608
|
+
durationMs: Date.now() - pluginStart,
|
|
609
|
+
error: message
|
|
610
|
+
});
|
|
611
|
+
if (tolerantBootstrap) {
|
|
612
|
+
failedDomains.push(domain);
|
|
613
|
+
continue;
|
|
614
|
+
}
|
|
615
|
+
throw new Error(`plugin_bootstrap_failed:${domain}:${message}`);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
diagnostics2.state = "ready";
|
|
619
|
+
if (failedDomains.length > 0) {
|
|
620
|
+
diagnostics2.error = `plugin_bootstrap_partial_failure:${failedDomains.join(",")}`;
|
|
621
|
+
}
|
|
622
|
+
diagnostics2.loadedDomains = registry.listDomains();
|
|
623
|
+
diagnostics2.finishedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
624
|
+
registryDiagnostics = diagnostics2;
|
|
625
|
+
return registry;
|
|
626
|
+
} catch (error) {
|
|
627
|
+
diagnostics2.state = "failed";
|
|
628
|
+
diagnostics2.error = extractErrorMessage(error);
|
|
629
|
+
diagnostics2.loadedDomains = registry.listDomains();
|
|
630
|
+
diagnostics2.finishedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
631
|
+
registryDiagnostics = diagnostics2;
|
|
632
|
+
throw error;
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
async function getHostPluginRegistry() {
|
|
636
|
+
if (singletonPromise) return singletonPromise;
|
|
637
|
+
singletonPromise = buildRegistry().catch((error) => {
|
|
638
|
+
singletonPromise = null;
|
|
639
|
+
throw error;
|
|
640
|
+
});
|
|
641
|
+
return singletonPromise;
|
|
642
|
+
}
|
|
643
|
+
function getHostPluginRegistryDiagnostics() {
|
|
644
|
+
return {
|
|
645
|
+
...registryDiagnostics,
|
|
646
|
+
loadedDomains: [...registryDiagnostics.loadedDomains],
|
|
647
|
+
plugins: registryDiagnostics.plugins.map((plugin) => ({ ...plugin }))
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
function resetHostPluginRegistry() {
|
|
651
|
+
singletonPromise = null;
|
|
652
|
+
pluginImportVersion += 1;
|
|
653
|
+
registryDiagnostics = {
|
|
654
|
+
...DEFAULT_DIAGNOSTICS,
|
|
655
|
+
loadedDomains: [],
|
|
656
|
+
plugins: []
|
|
657
|
+
};
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
export { getHostRegistrationDiagnostics as a, getHostPluginRegistryDiagnostics as b, getHostAdmissionDiagnostics as c, checkHostDomainAdmission as d, getHostPluginRegistry as e, resetHostPluginRegistry as f, getHostConfig as g, resolveCommunityPackageModule as r };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
function isLoopbackHostname(value) {
|
|
2
|
+
const hostname = value.trim().toLowerCase();
|
|
3
|
+
if (hostname === "localhost" || hostname === "[::1]") return true;
|
|
4
|
+
const match = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(hostname);
|
|
5
|
+
if (!match) return false;
|
|
6
|
+
const octets = match.slice(1).map(Number);
|
|
7
|
+
return octets[0] === 127 && octets.every((octet) => octet >= 0 && octet <= 255);
|
|
8
|
+
}
|
|
9
|
+
const VALIDATED_PUBLIC_ORIGIN_HEADER = "x-aops-validated-public-origin";
|
|
10
|
+
function exposureFromEnvironment(processEnv) {
|
|
11
|
+
const exposure = String(processEnv.AOPS_SERVER_EXPOSURE ?? "").trim();
|
|
12
|
+
const legacy = String(processEnv.AOPS_COMMUNITY_HOST_MODE ?? "").trim();
|
|
13
|
+
if (exposure && legacy && exposure !== legacy) {
|
|
14
|
+
throw new Error("community_server_exposure_env_mismatch");
|
|
15
|
+
}
|
|
16
|
+
return exposure || legacy || "loopback";
|
|
17
|
+
}
|
|
18
|
+
function resolveRequestBaseUrl(request, url, processEnv = process.env) {
|
|
19
|
+
if (url.protocol !== "http:" && url.protocol !== "https:" || url.username || url.password || !isLoopbackHostname(url.hostname)) {
|
|
20
|
+
throw new Error("community_server_loopback_request_origin_required");
|
|
21
|
+
}
|
|
22
|
+
const exposure = exposureFromEnvironment(processEnv);
|
|
23
|
+
const forwardedOrigin = request.headers.get(VALIDATED_PUBLIC_ORIGIN_HEADER);
|
|
24
|
+
if (exposure === "authenticated-network") {
|
|
25
|
+
throw new Error(
|
|
26
|
+
"community_server_authenticated_network_retired_use_remote_session_target"
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
if (forwardedOrigin) {
|
|
30
|
+
throw new Error("community_server_validated_public_origin_unexpected");
|
|
31
|
+
}
|
|
32
|
+
return url.origin;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export { resolveRequestBaseUrl as r };
|