@undefineds.co/xpod 0.4.14 → 0.4.15
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/config/cloud.json +0 -3
- package/config/local.json +0 -3
- package/config/xpod.base.json +0 -24
- package/dist/api/ai-config/AiConfigStore.d.ts +2 -2
- package/dist/api/ai-config/AiConfigStore.js +4 -1
- package/dist/api/ai-gateway/auth/CallerPodAccess.d.ts +2 -5
- package/dist/api/ai-gateway/auth/CallerPodAccess.js +3 -42
- package/dist/api/ai-gateway/auth/GatewayApiKeyAuthenticator.d.ts +2 -1
- package/dist/api/ai-gateway/auth/GatewayApiKeyAuthenticator.js +1 -1
- package/dist/api/ai-gateway/auth/PodGatewayAccessKeyRepository.d.ts +3 -8
- package/dist/api/ai-gateway/auth/PodGatewayAccessKeyRepository.js +9 -32
- package/dist/api/ai-gateway/connect/index.d.ts +3 -3
- package/dist/api/ai-gateway/connect/index.js +9 -38
- package/dist/api/ai-gateway/errors.js +2 -1
- package/dist/api/ai-gateway/models/PodModelSelectionRepository.d.ts +3 -3
- package/dist/api/ai-gateway/models/PodModelSelectionRepository.js +7 -11
- package/dist/api/ai-gateway/pod/HostedPodRoute.d.ts +27 -0
- package/dist/api/ai-gateway/pod/HostedPodRoute.js +47 -0
- package/dist/api/ai-gateway/pod/OwnerPodAccess.d.ts +79 -0
- package/dist/api/ai-gateway/pod/OwnerPodAccess.js +192 -0
- package/dist/api/ai-gateway/pod/PodInterfaceKeyStore.d.ts +52 -0
- package/dist/api/ai-gateway/pod/PodInterfaceKeyStore.js +61 -0
- package/dist/api/ai-gateway/quota/ProviderQuotaAdapter.d.ts +3 -3
- package/dist/api/ai-gateway/quota/ProviderQuotaAdapter.js +7 -32
- package/dist/api/auth/ClientCredentialsAuthenticator.js +5 -28
- package/dist/api/auth/TokenEndpointRoute.d.ts +18 -0
- package/dist/api/auth/TokenEndpointRoute.js +36 -0
- package/dist/api/chatkit/pod-store.d.ts +4 -4
- package/dist/api/chatkit/pod-store.js +24 -95
- package/dist/api/container/common.js +36 -23
- package/dist/api/container/local.js +62 -29
- package/dist/api/container/routes.js +39 -7
- package/dist/api/container/types.d.ts +2 -2
- package/dist/api/handlers/AiGatewayManagementHandler.d.ts +6 -0
- package/dist/api/handlers/AiGatewayManagementHandler.js +17 -4
- package/dist/api/handlers/NetworkSettingsHandler.d.ts +7 -0
- package/dist/api/handlers/NetworkSettingsHandler.js +7 -0
- package/dist/api/handlers/PodSettingsHandler.d.ts +3 -3
- package/dist/api/handlers/PodSettingsHandler.js +3 -3
- package/dist/api/handlers/ProvisionHandler.d.ts +29 -0
- package/dist/api/handlers/ProvisionHandler.js +46 -0
- package/dist/api/handlers/ReachabilityHandler.js +3 -1
- package/dist/api/runtime.d.ts +9 -0
- package/dist/api/runtime.js +16 -3
- package/dist/cli/commands/start.d.ts +9 -2
- package/dist/cli/commands/start.js +15 -17
- package/dist/components/components.jsonld +1 -1
- package/dist/components/context.jsonld +5 -42
- package/dist/edge/EdgeNodeAgent.d.ts +10 -0
- package/dist/edge/EdgeNodeAgent.js +55 -0
- package/dist/edge/EdgeNodeAgent.jsonld +8 -0
- package/dist/edge/reachability/ReachabilitySessionService.js +4 -1
- package/dist/edge/reachability/RouteSetBuilder.d.ts +18 -1
- package/dist/edge/reachability/RouteSetBuilder.js +47 -0
- package/dist/edge/reachability/RouteSetBuilder.jsonld +29 -0
- package/dist/edge/reachability/types.d.ts +8 -2
- package/dist/http/SubgraphSparqlHttpHandler.d.ts +1 -25
- package/dist/http/SubgraphSparqlHttpHandler.js +0 -100
- package/dist/http/SubgraphSparqlHttpHandler.jsonld +0 -8
- package/dist/identity/drizzle/PodInterfaceKeyRepository.d.ts +33 -0
- package/dist/identity/drizzle/PodInterfaceKeyRepository.js +78 -0
- package/dist/identity/drizzle/db.d.ts +7 -0
- package/dist/identity/drizzle/db.js +30 -0
- package/dist/identity/drizzle/schema.pg.d.ts +9 -0
- package/dist/identity/drizzle/schema.pg.js +16 -1
- package/dist/identity/drizzle/schema.sqlite.d.ts +106 -0
- package/dist/identity/drizzle/schema.sqlite.js +16 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.js +3 -5
- package/dist/runtime/GatewayAdminProxyAuth.d.ts +1 -16
- package/dist/runtime/GatewayAdminProxyAuth.js +2 -71
- package/dist/runtime/Proxy.d.ts +10 -1
- package/dist/runtime/Proxy.js +95 -28
- package/dist/runtime/bootstrap.d.ts +10 -0
- package/dist/runtime/bootstrap.js +24 -0
- package/dist/runtime/host/node/NodeRuntimeHost.js +5 -3
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/index.js +2 -3
- package/dist/runtime/js-runtime.js +10 -3
- package/dist/runtime/lifecycle.js +5 -4
- package/dist/runtime/port-finder.d.ts +9 -13
- package/dist/runtime/port-finder.js +18 -37
- package/dist/tunnel/AutoTunnelProvider.d.ts +56 -0
- package/dist/tunnel/AutoTunnelProvider.js +181 -0
- package/dist/tunnel/index.d.ts +1 -0
- package/dist/tunnel/index.js +3 -1
- package/node_modules/@undefineds.co/ai-connections/dist/error-wording.js +7 -2
- package/node_modules/@undefineds.co/solid-sdk/dist/access-route.cjs +230 -0
- package/node_modules/@undefineds.co/solid-sdk/dist/access-route.d.ts +76 -0
- package/node_modules/@undefineds.co/solid-sdk/dist/access-route.js +115 -0
- package/node_modules/@undefineds.co/solid-sdk/dist/index.cjs +89 -0
- package/node_modules/@undefineds.co/solid-sdk/dist/index.d.ts +1 -0
- package/node_modules/@undefineds.co/solid-sdk/dist/index.js +1 -0
- package/node_modules/@undefineds.co/solid-sdk/package.json +6 -1
- package/package.json +2 -2
- package/static/app/assets/inrupt-smoke.js +23 -23
- package/static/auth-callback/assets/{AiConfigContext-DCXpjzpj.js → AiConfigContext-Bx0HCAW5.js} +1 -1
- package/static/auth-callback/assets/{AiConfigPage-fe-xMIXa.js → AiConfigPage-ChQImMbm.js} +1 -1
- package/static/auth-callback/assets/{DocumentProcessingPanel-BGnkfMuU.js → DocumentProcessingPanel-D830H4SH.js} +1 -1
- package/static/auth-callback/assets/{IndexLifecyclePanel-42Jups0j.js → IndexLifecyclePanel-CnlkjMF8.js} +1 -1
- package/static/auth-callback/assets/{IndexSubjectPanel-CYyLOlQU.js → IndexSubjectPanel-CdEfg_CO.js} +1 -1
- package/static/auth-callback/assets/{ModelAssignmentsPanel-BOvUH4yr.js → ModelAssignmentsPanel-D-8A8dZx.js} +1 -1
- package/static/auth-callback/assets/{ModelsPage-DwyITxt7.js → ModelsPage-Cim7cubp.js} +3 -3
- package/static/auth-callback/assets/{NetworkPage-CG9RelJA.js → NetworkPage-CfK3x-pb.js} +2 -2
- package/static/auth-callback/assets/{PaneListHeader-yvd5ohs6.js → PaneListHeader-Bf_kEd4U.js} +1 -1
- package/static/auth-callback/assets/{SearchIndexingPanel-2_a6ezzj.js → SearchIndexingPanel-4kD4RBEQ.js} +1 -1
- package/static/auth-callback/assets/{StatusSubjectPanel-8qtVxnzC.js → StatusSubjectPanel-Bw9AiTSf.js} +1 -1
- package/static/auth-callback/assets/{StatusWorkspace-CBdRahCF.js → StatusWorkspace-C-301H-0.js} +1 -1
- package/static/auth-callback/assets/{SystemSettingsPage-BZJ6vWkg.js → SystemSettingsPage-BbWn-eG6.js} +1 -1
- package/static/auth-callback/assets/{SystemSettingsSubjectPanel-xm08UhXP.js → SystemSettingsSubjectPanel-DA4wvNSm.js} +1 -1
- package/static/auth-callback/assets/{XpodAiConnectionsPodStore-V6vgGfuw.js → XpodAiConnectionsPodStore-CohdyLoX.js} +1 -1
- package/static/auth-callback/assets/{activity-CeM7xly8.js → activity-CCsb9Oam.js} +1 -1
- package/static/auth-callback/assets/ai-connections-DexTPyfC.js +1 -0
- package/static/auth-callback/assets/{auth-callback-DTG8cSj7.js → auth-callback-Ds-c62W3.js} +5 -5
- package/static/auth-callback/assets/{badge-qJo2Zr4d.js → badge-CQm5OyzR.js} +1 -1
- package/static/auth-callback/assets/{collection-runtime-Bztsz31a.js → collection-runtime-DlAuU5TW.js} +1 -1
- package/static/auth-callback/assets/{dialog-D-h6x5x0.js → dialog-CnGzg5Ff.js} +1 -1
- package/static/auth-callback/assets/{download-C2ir4lmR.js → download-DwMONJvm.js} +1 -1
- package/static/auth-callback/assets/{external-link-THLDL4On.js → external-link-Bu5AGqCO.js} +1 -1
- package/static/auth-callback/assets/{index-BlVZb9A7.js → index-B0T-1YO8.js} +1 -1
- package/static/auth-callback/assets/{index-BRpv4yO3.js → index-C8QZf_4W.js} +1 -1
- package/static/auth-callback/assets/{index-D983R1FV.js → index-DwIlrIDG.js} +1 -1
- package/static/auth-callback/assets/{index-browser-3FvR0aaf.js → index-browser-lRsMcP_7.js} +1 -1
- package/static/auth-callback/assets/{key-round-C9U5j1Ly.js → key-round-BDMtU57P.js} +1 -1
- package/static/auth-callback/assets/{rotate-ccw-DP45cD4o.js → rotate-ccw-CoKIGCsQ.js} +1 -1
- package/static/auth-callback/assets/{skeleton-Dn4EiSCS.js → skeleton-CPoSWHDr.js} +1 -1
- package/static/auth-callback/assets/{waypoints-uqFQ3uEG.js → waypoints-BeYHxqHv.js} +1 -1
- package/static/auth-callback/assets/{workspace-layout-DLYK0Wwu.js → workspace-layout-xA5YxiK3.js} +1 -1
- package/static/auth-callback/auth-callback.html +1 -1
- package/static/dashboard/assets/{AiConfigContext-DJcMECNw.js → AiConfigContext-rWx4TyiH.js} +1 -1
- package/static/dashboard/assets/{AiConfigPage-BvE7dOTy.js → AiConfigPage-StVJpDFT.js} +1 -1
- package/static/dashboard/assets/{DocumentProcessingPanel-D9780krf.js → DocumentProcessingPanel-DJ5yul2O.js} +1 -1
- package/static/dashboard/assets/{IndexLifecyclePanel-SjsUcnbM.js → IndexLifecyclePanel-CpjtgezK.js} +1 -1
- package/static/dashboard/assets/{IndexSubjectPanel-C-ym2Tqi.js → IndexSubjectPanel-BVKcot1_.js} +1 -1
- package/static/dashboard/assets/{ModelAssignmentsPanel-BRjZ-arB.js → ModelAssignmentsPanel-BxVgWZPc.js} +1 -1
- package/static/dashboard/assets/{ModelsPage-BtTU6du3.js → ModelsPage-CECBwmeO.js} +3 -3
- package/static/dashboard/assets/{NetworkPage-CV9qpkDg.js → NetworkPage-zQgFscEW.js} +2 -2
- package/static/dashboard/assets/{PaneListHeader-KyPTTBsv.js → PaneListHeader-DIPe8pS6.js} +1 -1
- package/static/dashboard/assets/{SearchIndexingPanel-DolHGawg.js → SearchIndexingPanel-lalFJ3c8.js} +1 -1
- package/static/dashboard/assets/{StatusSubjectPanel-_YZvKiYi.js → StatusSubjectPanel-CpY_KU-G.js} +1 -1
- package/static/dashboard/assets/{StatusWorkspace-Dlbh_G40.js → StatusWorkspace-BwWCii3A.js} +1 -1
- package/static/dashboard/assets/{SystemSettingsPage-Be7QSIoz.js → SystemSettingsPage-BKZxX-_n.js} +1 -1
- package/static/dashboard/assets/{SystemSettingsSubjectPanel-DBp0gja7.js → SystemSettingsSubjectPanel-BZrqb2C5.js} +1 -1
- package/static/dashboard/assets/{XpodAiConnectionsPodStore-ClpSjzpP.js → XpodAiConnectionsPodStore-Bbpx9dTN.js} +1 -1
- package/static/dashboard/assets/{activity-lsNbTXJu.js → activity-BJ15TLVP.js} +1 -1
- package/static/dashboard/assets/ai-connections-GG6qkTJt.js +1 -0
- package/static/dashboard/assets/{badge-CVatKjaG.js → badge-BBX5FlaB.js} +1 -1
- package/static/dashboard/assets/{collection-runtime-Ec4UnY28.js → collection-runtime-UBbHBzdf.js} +1 -1
- package/static/dashboard/assets/{dashboard-BEzsRsvF.js → dashboard-7Y6BHyV9.js} +62 -62
- package/static/dashboard/assets/{dialog-BuyelQ4V.js → dialog-QrOJ-hB0.js} +1 -1
- package/static/dashboard/assets/{download-B4Nf678F.js → download-DK9x-VOP.js} +1 -1
- package/static/dashboard/assets/{external-link-PYv9CvKL.js → external-link-Cnkn87mJ.js} +1 -1
- package/static/dashboard/assets/{index-C9XPE-mI.js → index-B1z84it5.js} +1 -1
- package/static/dashboard/assets/{index-awr7ulur.js → index-DzjauX3N.js} +1 -1
- package/static/dashboard/assets/{index-Cx69bTNh.js → index-cIa8_efI.js} +1 -1
- package/static/dashboard/assets/{key-round-VsY80U1Z.js → key-round-BoS6UqKz.js} +1 -1
- package/static/dashboard/assets/{rotate-ccw-Cz1K4vE9.js → rotate-ccw-BeWV76i0.js} +1 -1
- package/static/dashboard/assets/{skeleton-BhNv_8tO.js → skeleton-CypcJL07.js} +1 -1
- package/static/dashboard/assets/{waypoints-DYS9XFYV.js → waypoints-zHOOqfhi.js} +1 -1
- package/static/dashboard/assets/{workspace-layout-OZJAFx5V.js → workspace-layout-DZ9JuxnM.js} +1 -1
- package/static/dashboard/dashboard.html +1 -1
- package/static/settings/assets/{AiConfigContext-B8JS3MXF.js → AiConfigContext-D3b1l_Kw.js} +1 -1
- package/static/settings/assets/{AiConfigPage-C3Zl8LUl.js → AiConfigPage-DYKw-atP.js} +1 -1
- package/static/settings/assets/{DocumentProcessingPanel-DpDZAQvf.js → DocumentProcessingPanel-DguRfsIV.js} +1 -1
- package/static/settings/assets/{IndexLifecyclePanel-Ec1XF88t.js → IndexLifecyclePanel-B85qJJA4.js} +1 -1
- package/static/settings/assets/{IndexSubjectPanel-BulT9BmO.js → IndexSubjectPanel-CsN7IxaV.js} +1 -1
- package/static/settings/assets/{ModelAssignmentsPanel-BcGSmYjb.js → ModelAssignmentsPanel-DEp9byI6.js} +1 -1
- package/static/settings/assets/{ModelsPage-CvTCKy1T.js → ModelsPage-CzTnPs_G.js} +3 -3
- package/static/settings/assets/{NetworkPage-DQF5u9Bn.js → NetworkPage-BDVnmUU0.js} +2 -2
- package/static/settings/assets/{PaneListHeader-D40hqcVl.js → PaneListHeader-Cpe39N76.js} +1 -1
- package/static/settings/assets/{SearchIndexingPanel-iCUPOx_0.js → SearchIndexingPanel-DA9w8lLL.js} +1 -1
- package/static/settings/assets/{StatusSubjectPanel-E--ZHSql.js → StatusSubjectPanel-BU0Aq0CS.js} +1 -1
- package/static/settings/assets/{StatusWorkspace-YjDAx1II.js → StatusWorkspace-D1AC1i5N.js} +1 -1
- package/static/settings/assets/{SystemSettingsPage-CDdV3mC9.js → SystemSettingsPage-ChKvOioO.js} +1 -1
- package/static/settings/assets/{SystemSettingsSubjectPanel-Br8WazDq.js → SystemSettingsSubjectPanel-DyTpOnD2.js} +1 -1
- package/static/settings/assets/{XpodAiConnectionsPodStore-CLr38P_Z.js → XpodAiConnectionsPodStore-VU5Bsz1a.js} +1 -1
- package/static/settings/assets/{activity-C5DAHHTE.js → activity-DGpLfsQB.js} +1 -1
- package/static/settings/assets/ai-connections-DexTPyfC.js +1 -0
- package/static/settings/assets/{badge-D8eIyxKt.js → badge-_hCrrWRP.js} +1 -1
- package/static/settings/assets/{collection-runtime-DLc9zil8.js → collection-runtime-E40TZ8Cl.js} +1 -1
- package/static/settings/assets/{dialog-CyuR7Va4.js → dialog-DTr2JkHn.js} +1 -1
- package/static/settings/assets/{download-c0oxZrCz.js → download-B_D21DDX.js} +1 -1
- package/static/settings/assets/{external-link-D3Z34fP_.js → external-link-BATYaM13.js} +1 -1
- package/static/settings/assets/{index-CSr3-2Cj.js → index-BAlAVi-J.js} +1 -1
- package/static/settings/assets/{index-ComidxAm.js → index-Ckh4h9jj.js} +1 -1
- package/static/settings/assets/{index-CKGbRFlc.js → index-DOiwLF4B.js} +1 -1
- package/static/settings/assets/{index-browser-CAscEbae.js → index-browser-DFFWN3Kr.js} +1 -1
- package/static/settings/assets/{key-round-DyjLmXuB.js → key-round-ZTVU_1O1.js} +1 -1
- package/static/settings/assets/{rotate-ccw-679HF_ec.js → rotate-ccw-DDdw8PTU.js} +1 -1
- package/static/settings/assets/{settings-DKknqu4C.js → settings-CyLnISOv.js} +62 -62
- package/static/settings/assets/{skeleton-CkopNkPB.js → skeleton-DEzA3hc2.js} +1 -1
- package/static/settings/assets/{waypoints-CrqfAftE.js → waypoints-BSdfNvEb.js} +1 -1
- package/static/settings/assets/{workspace-layout-UN6c4qTG.js → workspace-layout-BOQnl_3d.js} +1 -1
- package/static/settings/settings.html +1 -1
- package/dist/api/ai-gateway/pod/HostedPodDataAccess.d.ts +0 -31
- package/dist/api/ai-gateway/pod/HostedPodDataAccess.js +0 -330
- package/dist/http/InternalPodDataHttpHandler.d.ts +0 -57
- package/dist/http/InternalPodDataHttpHandler.js +0 -551
- package/dist/http/InternalPodDataHttpHandler.jsonld +0 -243
- package/static/auth-callback/assets/ai-connections-C6yaE6WQ.js +0 -1
- package/static/dashboard/assets/ai-connections-CXp5gd1J.js +0 -1
- package/static/settings/assets/ai-connections-C6yaE6WQ.js +0 -1
|
@@ -1,551 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.InternalPodDataHttpHandler = void 0;
|
|
4
|
-
const node_crypto_1 = require("node:crypto");
|
|
5
|
-
const promises_1 = require("node:stream/promises");
|
|
6
|
-
const global_logger_factory_1 = require("global-logger-factory");
|
|
7
|
-
const sparqljs_1 = require("sparqljs");
|
|
8
|
-
const community_server_1 = require("@solid/community-server");
|
|
9
|
-
const AiConnectionsServiceAccess_1 = require("../api/ai-gateway/service-access/AiConnectionsServiceAccess");
|
|
10
|
-
const AiConfigServiceAccess_1 = require("../api/ai-gateway/service-access/AiConfigServiceAccess");
|
|
11
|
-
const GatewayAdminProxyAuth_1 = require("../runtime/GatewayAdminProxyAuth");
|
|
12
|
-
const ResourceReadContext_1 = require("../storage/ResourceReadContext");
|
|
13
|
-
const ALLOWED_METHODS = new Set(['GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE']);
|
|
14
|
-
const DEFAULT_NONCE_TTL_MS = 120_000;
|
|
15
|
-
const DEFAULT_NONCE_MAX_ENTRIES = 10_000;
|
|
16
|
-
const MODEL_QUERY_MAX_BODY_BYTES = 256 * 1024;
|
|
17
|
-
class InternalPodDataHttpHandler extends community_server_1.HttpHandler {
|
|
18
|
-
constructor(options) {
|
|
19
|
-
super();
|
|
20
|
-
this.logger = (0, global_logger_factory_1.getLoggerFor)(this);
|
|
21
|
-
this.eTagHandler = new community_server_1.BasicETagHandler();
|
|
22
|
-
this.conditionsParser = new community_server_1.BasicConditionsParser(this.eTagHandler);
|
|
23
|
-
this.resourceStore = options.resourceStore;
|
|
24
|
-
this.gatewayAdminProxyAuthSecret = options.gatewayAdminProxyAuthSecret ?? process.env.XPOD_GATEWAY_ADMIN_PROXY_AUTH_SECRET;
|
|
25
|
-
this.patchBodyParser = options.patchBodyParser;
|
|
26
|
-
this.sparqlHandler = options.sparqlHandler;
|
|
27
|
-
this.deploymentBaseUrl = this.parseOptionalUrl(options.baseUrl ?? process.env.CSS_BASE_URL);
|
|
28
|
-
this.basePath = options.basePath ?? '/.internal/pod-data';
|
|
29
|
-
const nonceOptions = options;
|
|
30
|
-
this.seenNonces = new BoundedTtlNonceCache({
|
|
31
|
-
ttlMs: nonceOptions.nonceTtlMs ?? DEFAULT_NONCE_TTL_MS,
|
|
32
|
-
maxEntries: nonceOptions.nonceMaxEntries ?? DEFAULT_NONCE_MAX_ENTRIES,
|
|
33
|
-
now: nonceOptions.now,
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
async canHandle({ request }) {
|
|
37
|
-
if (this.requestPathname(request) !== this.basePath) {
|
|
38
|
-
throw new community_server_1.NotImplementedHttpError('Not an internal Pod data request.');
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
async handle({ request, response }) {
|
|
42
|
-
if (this.requestPathname(request) !== this.basePath) {
|
|
43
|
-
throw new community_server_1.NotImplementedHttpError('Not an internal Pod data request.');
|
|
44
|
-
}
|
|
45
|
-
const intent = this.verifyRequest(request);
|
|
46
|
-
if (!intent) {
|
|
47
|
-
this.writeNotFound(response);
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
try {
|
|
51
|
-
await (0, ResourceReadContext_1.withDirectDataRead)(() => this.delegate(request, response, intent));
|
|
52
|
-
}
|
|
53
|
-
catch (error) {
|
|
54
|
-
if (isHttpNotFound(error)) {
|
|
55
|
-
if (intent.method === 'GET' && !isGatewayAccessKeySecretResource(intent)) {
|
|
56
|
-
this.writeEmptyGraph(response);
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
this.writeNotFound(response);
|
|
60
|
-
}
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
throw error;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
verifyRequest(request) {
|
|
67
|
-
const method = request.method?.toUpperCase();
|
|
68
|
-
if (!ALLOWED_METHODS.has(method ?? '')) {
|
|
69
|
-
this.logRejectedRequest('method_not_allowed');
|
|
70
|
-
return undefined;
|
|
71
|
-
}
|
|
72
|
-
if (!(0, GatewayAdminProxyAuth_1.isLoopbackRemoteAddress)(request.socket.remoteAddress)) {
|
|
73
|
-
this.logRejectedRequest('non_loopback_transport');
|
|
74
|
-
return undefined;
|
|
75
|
-
}
|
|
76
|
-
const verification = (0, GatewayAdminProxyAuth_1.verifyGatewayAdminProxyHeaders)({
|
|
77
|
-
headers: request.headers,
|
|
78
|
-
secret: this.gatewayAdminProxyAuthSecret,
|
|
79
|
-
method,
|
|
80
|
-
url: request.url,
|
|
81
|
-
});
|
|
82
|
-
if (!verification.valid || !verification.originalClientLoopback || !verification.intent || !verification.nonce) {
|
|
83
|
-
this.logRejectedRequest(verification.reason ?? 'invalid_runtime_marker');
|
|
84
|
-
return undefined;
|
|
85
|
-
}
|
|
86
|
-
if (!this.intentMatchesRequest(verification.intent, method)) {
|
|
87
|
-
this.logRejectedRequest('intent_mismatch');
|
|
88
|
-
return undefined;
|
|
89
|
-
}
|
|
90
|
-
if (!this.isHostedOwnerResource(verification.intent)) {
|
|
91
|
-
this.logRejectedRequest('owner_resource_outside_deployment');
|
|
92
|
-
return undefined;
|
|
93
|
-
}
|
|
94
|
-
if (!this.isAllowedAiConnectionResource(verification.intent)) {
|
|
95
|
-
this.logRejectedRequest('resource_not_allowed');
|
|
96
|
-
return undefined;
|
|
97
|
-
}
|
|
98
|
-
if (!this.seenNonces.consume(verification.nonce)) {
|
|
99
|
-
this.logRejectedRequest('nonce_rejected');
|
|
100
|
-
return undefined;
|
|
101
|
-
}
|
|
102
|
-
return verification.intent;
|
|
103
|
-
}
|
|
104
|
-
logRejectedRequest(reason) {
|
|
105
|
-
this.logger.warn(`Rejected internal Pod data request: ${reason}`);
|
|
106
|
-
}
|
|
107
|
-
intentMatchesRequest(intent, method) {
|
|
108
|
-
if (intent.method !== method) {
|
|
109
|
-
return false;
|
|
110
|
-
}
|
|
111
|
-
if (intent.scopes.length === 0) {
|
|
112
|
-
return false;
|
|
113
|
-
}
|
|
114
|
-
if (intent.principalKind === 'gateway-key-verifier') {
|
|
115
|
-
return intent.scopes.length === 1 && ((intent.scopes[0] === 'ai:gateway-key:verify' && (method === 'GET' || method === 'HEAD' || method === 'POST'))
|
|
116
|
-
|| (intent.scopes[0] === 'ai:gateway-key:touch' && (method === 'GET' || method === 'HEAD' || method === 'PATCH')));
|
|
117
|
-
}
|
|
118
|
-
if (method === 'POST') {
|
|
119
|
-
const endpointKind = trustedSparqlEndpointKind(resourceOwnerWebId(intent), intent.resourceUrl);
|
|
120
|
-
if (endpointKind === 'settings') {
|
|
121
|
-
return intentHasScope(intent, 'ai:credentials:read') || intentHasScope(intent, 'ai:credentials:write');
|
|
122
|
-
}
|
|
123
|
-
if (endpointKind === 'models') {
|
|
124
|
-
return intentHasScope(intent, 'ai:credentials:read');
|
|
125
|
-
}
|
|
126
|
-
if (endpointKind === 'gatewayAccessKeys') {
|
|
127
|
-
return intentHasScope(intent, 'ai:credentials:read');
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
return intentHasScope(intent, method === 'GET' || method === 'HEAD' ? 'ai:credentials:read' : 'ai:credentials:write');
|
|
131
|
-
}
|
|
132
|
-
isHostedOwnerResource(intent) {
|
|
133
|
-
if (!this.deploymentBaseUrl) {
|
|
134
|
-
return false;
|
|
135
|
-
}
|
|
136
|
-
let resourceUrl;
|
|
137
|
-
try {
|
|
138
|
-
resourceUrl = new URL(intent.resourceUrl);
|
|
139
|
-
}
|
|
140
|
-
catch {
|
|
141
|
-
return false;
|
|
142
|
-
}
|
|
143
|
-
const podRoot = podRootFromIntent(intent);
|
|
144
|
-
if (!podRoot || !this.isInsideDeployment(podRoot) || !this.isInsideDeployment(resourceUrl)) {
|
|
145
|
-
return false;
|
|
146
|
-
}
|
|
147
|
-
return resourceUrl.origin === podRoot.origin &&
|
|
148
|
-
resourceUrl.pathname.startsWith(podRoot.pathname);
|
|
149
|
-
}
|
|
150
|
-
isAllowedAiConnectionResource(intent) {
|
|
151
|
-
let resourceUrl;
|
|
152
|
-
try {
|
|
153
|
-
resourceUrl = new URL(intent.resourceUrl);
|
|
154
|
-
}
|
|
155
|
-
catch {
|
|
156
|
-
return false;
|
|
157
|
-
}
|
|
158
|
-
if (intent.principalKind === 'gateway-key-verifier') {
|
|
159
|
-
return isAllowedGatewayKeyVerifierResource(intent, resourceUrl);
|
|
160
|
-
}
|
|
161
|
-
const resourceOwner = resourceOwnerWebId(intent);
|
|
162
|
-
const sparqlQuery = trustedSparqlQueryForOwner(resourceOwner, resourceUrl);
|
|
163
|
-
if (sparqlQuery !== undefined) {
|
|
164
|
-
return intent.method === 'GET';
|
|
165
|
-
}
|
|
166
|
-
if (trustedSparqlEndpointKind(resourceOwner, intent.resourceUrl) !== undefined) {
|
|
167
|
-
return intent.method === 'POST' && !resourceUrl.search && !resourceUrl.hash;
|
|
168
|
-
}
|
|
169
|
-
if (resourceUrl.hash || resourceUrl.search) {
|
|
170
|
-
return false;
|
|
171
|
-
}
|
|
172
|
-
const allowed = (0, AiConnectionsServiceAccess_1.createAiConnectionsServiceAccess)({
|
|
173
|
-
ownerWebId: resourceOwner,
|
|
174
|
-
serviceWebId: intent.ownerWebId,
|
|
175
|
-
}).resources.map((resource) => resource.url);
|
|
176
|
-
allowed.push(...(0, AiConfigServiceAccess_1.createAiConfigResourceUrls)(resourceOwner));
|
|
177
|
-
return allowed.includes(resourceUrl.href);
|
|
178
|
-
}
|
|
179
|
-
async delegate(request, response, intent) {
|
|
180
|
-
const resourceUrl = new URL(intent.resourceUrl);
|
|
181
|
-
const sparqlOperation = await trustedSparqlOperationForRequest(request, resourceOwnerWebId(intent), resourceUrl, intent.method);
|
|
182
|
-
if (sparqlOperation !== undefined) {
|
|
183
|
-
if (!this.sparqlHandler) {
|
|
184
|
-
throw new community_server_1.NotImplementedHttpError('Internal settings SPARQL delegation is not configured.');
|
|
185
|
-
}
|
|
186
|
-
if (!intentAllowsSparqlOperation(intent, sparqlOperation.kind)) {
|
|
187
|
-
this.logRejectedRequest(`sparql_scope_mismatch:${sparqlOperation.kind}`);
|
|
188
|
-
this.writeNotFound(response);
|
|
189
|
-
return;
|
|
190
|
-
}
|
|
191
|
-
if (intent.method === 'POST' && intent.bodyDigest !== sparqlOperation.bodyDigest) {
|
|
192
|
-
this.logRejectedRequest(`sparql_body_digest_mismatch:${intent.bodyDigest?.slice(0, 12) ?? 'missing'}:${sparqlOperation.bodyDigest?.slice(0, 12) ?? 'missing'}`);
|
|
193
|
-
this.writeNotFound(response);
|
|
194
|
-
return;
|
|
195
|
-
}
|
|
196
|
-
const input = {
|
|
197
|
-
ownerWebId: resourceOwnerWebId(intent),
|
|
198
|
-
endpointUrl: intent.resourceUrl,
|
|
199
|
-
query: sparqlOperation.sparql,
|
|
200
|
-
request,
|
|
201
|
-
response,
|
|
202
|
-
};
|
|
203
|
-
if (sparqlOperation.kind === 'query') {
|
|
204
|
-
await this.sparqlHandler.handleTrustedInternalSelect(input);
|
|
205
|
-
}
|
|
206
|
-
else {
|
|
207
|
-
await this.sparqlHandler.handleTrustedInternalUpdate(input);
|
|
208
|
-
}
|
|
209
|
-
return;
|
|
210
|
-
}
|
|
211
|
-
if (trustedSparqlEndpointKind(resourceOwnerWebId(intent), intent.resourceUrl) !== undefined) {
|
|
212
|
-
this.logRejectedRequest(`sparql_operation_unsupported:${firstHeader(request.headers['content-type']) ?? 'missing-content-type'}`);
|
|
213
|
-
this.writeNotFound(response);
|
|
214
|
-
return;
|
|
215
|
-
}
|
|
216
|
-
const identifier = { path: intent.resourceUrl };
|
|
217
|
-
switch (intent.method) {
|
|
218
|
-
case 'GET': {
|
|
219
|
-
const representation = await this.resourceStore.getRepresentation(identifier, resourceReadPreferences(intent));
|
|
220
|
-
response.statusCode = 200;
|
|
221
|
-
response.setHeader('Content-Type', representation.metadata.contentType ?? 'text/turtle');
|
|
222
|
-
this.writeETag(representation, response);
|
|
223
|
-
await this.pipeRepresentation(representation, response);
|
|
224
|
-
return;
|
|
225
|
-
}
|
|
226
|
-
case 'HEAD': {
|
|
227
|
-
const representation = await this.resourceStore.getRepresentation(identifier, resourceReadPreferences(intent));
|
|
228
|
-
response.statusCode = 200;
|
|
229
|
-
response.setHeader('Content-Type', representation.metadata.contentType ?? 'text/turtle');
|
|
230
|
-
this.writeETag(representation, response);
|
|
231
|
-
representation.data.destroy();
|
|
232
|
-
response.end();
|
|
233
|
-
return;
|
|
234
|
-
}
|
|
235
|
-
case 'PUT': {
|
|
236
|
-
const conditions = await this.conditionsParser.handleSafe(request);
|
|
237
|
-
await this.resourceStore.setRepresentation(identifier, this.createRepresentation(request, intent.resourceUrl), conditions);
|
|
238
|
-
response.statusCode = 204;
|
|
239
|
-
response.end();
|
|
240
|
-
return;
|
|
241
|
-
}
|
|
242
|
-
case 'PATCH': {
|
|
243
|
-
await this.resourceStore.modifyResource(identifier, await this.createPatch(request, intent.resourceUrl));
|
|
244
|
-
response.statusCode = 204;
|
|
245
|
-
response.end();
|
|
246
|
-
return;
|
|
247
|
-
}
|
|
248
|
-
case 'DELETE': {
|
|
249
|
-
await this.resourceStore.deleteResource(identifier);
|
|
250
|
-
response.statusCode = 204;
|
|
251
|
-
response.end();
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
createRepresentation(request, resourceUrl) {
|
|
256
|
-
const contentType = firstHeader(request.headers['content-type']) ?? 'text/turtle';
|
|
257
|
-
return new community_server_1.BasicRepresentation(request, new community_server_1.RepresentationMetadata({ path: resourceUrl }, contentType));
|
|
258
|
-
}
|
|
259
|
-
writeETag(representation, response) {
|
|
260
|
-
const eTag = this.eTagHandler.getETag(representation.metadata);
|
|
261
|
-
if (eTag) {
|
|
262
|
-
response.setHeader('ETag', eTag);
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
async createPatch(request, resourceUrl) {
|
|
266
|
-
if (!this.patchBodyParser) {
|
|
267
|
-
throw new community_server_1.NotImplementedHttpError('Internal Pod data PATCH requires a PatchBodyParser.');
|
|
268
|
-
}
|
|
269
|
-
const contentType = firstHeader(request.headers['content-type']) ?? 'application/sparql-update';
|
|
270
|
-
const metadata = new community_server_1.RepresentationMetadata({ path: resourceUrl }, contentType);
|
|
271
|
-
return this.patchBodyParser.handleSafe({ request, metadata });
|
|
272
|
-
}
|
|
273
|
-
async pipeRepresentation(representation, response) {
|
|
274
|
-
await (0, promises_1.pipeline)(representation.data, response);
|
|
275
|
-
}
|
|
276
|
-
writeNotFound(response) {
|
|
277
|
-
response.statusCode = 404;
|
|
278
|
-
response.setHeader('Cache-Control', 'no-store');
|
|
279
|
-
response.end('Not Found');
|
|
280
|
-
}
|
|
281
|
-
writeEmptyGraph(response) {
|
|
282
|
-
response.statusCode = 200;
|
|
283
|
-
response.setHeader('Content-Type', 'text/turtle');
|
|
284
|
-
response.setHeader('Cache-Control', 'no-store');
|
|
285
|
-
response.end();
|
|
286
|
-
}
|
|
287
|
-
requestPathname(request) {
|
|
288
|
-
const requestUrl = request.url ?? '/';
|
|
289
|
-
try {
|
|
290
|
-
// Route ownership is path-based. Do not let an untrusted or proxy-shaped
|
|
291
|
-
// Host header make URL parsing throw and silently skip this first handler.
|
|
292
|
-
return requestUrl.startsWith('/')
|
|
293
|
-
? new URL(requestUrl, 'http://xpod.internal').pathname
|
|
294
|
-
: new URL(requestUrl).pathname;
|
|
295
|
-
}
|
|
296
|
-
catch {
|
|
297
|
-
return undefined;
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
parseOptionalUrl(value) {
|
|
301
|
-
if (!value) {
|
|
302
|
-
return undefined;
|
|
303
|
-
}
|
|
304
|
-
try {
|
|
305
|
-
return new URL(ensureTrailingSlash(value));
|
|
306
|
-
}
|
|
307
|
-
catch {
|
|
308
|
-
return undefined;
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
isInsideDeployment(url) {
|
|
312
|
-
return this.deploymentBaseUrl !== undefined &&
|
|
313
|
-
url.origin === this.deploymentBaseUrl.origin &&
|
|
314
|
-
url.pathname.startsWith(this.deploymentBaseUrl.pathname);
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
exports.InternalPodDataHttpHandler = InternalPodDataHttpHandler;
|
|
318
|
-
function isHttpNotFound(error) {
|
|
319
|
-
return typeof error === 'object' &&
|
|
320
|
-
error !== null &&
|
|
321
|
-
('statusCode' in error ? error.statusCode === 404 : error.name === 'NotFoundHttpError');
|
|
322
|
-
}
|
|
323
|
-
function firstHeader(value) {
|
|
324
|
-
return Array.isArray(value) ? value[0] : value;
|
|
325
|
-
}
|
|
326
|
-
function hostedPodRootFromOwner(ownerUrl) {
|
|
327
|
-
if (ownerUrl.hash !== '#me') {
|
|
328
|
-
return undefined;
|
|
329
|
-
}
|
|
330
|
-
if (!ownerUrl.pathname.endsWith('/profile/card')) {
|
|
331
|
-
return undefined;
|
|
332
|
-
}
|
|
333
|
-
const podPath = ownerUrl.pathname.slice(0, -'profile/card'.length);
|
|
334
|
-
if (!podPath || !podPath.endsWith('/')) {
|
|
335
|
-
return undefined;
|
|
336
|
-
}
|
|
337
|
-
return new URL(podPath, ownerUrl.origin);
|
|
338
|
-
}
|
|
339
|
-
function podRootFromIntent(intent) {
|
|
340
|
-
if (!intent.podBaseUrl) {
|
|
341
|
-
try {
|
|
342
|
-
return hostedPodRootFromOwner(new URL(intent.ownerWebId));
|
|
343
|
-
}
|
|
344
|
-
catch {
|
|
345
|
-
return undefined;
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
try {
|
|
349
|
-
const root = new URL(intent.podBaseUrl);
|
|
350
|
-
root.search = '';
|
|
351
|
-
root.hash = '';
|
|
352
|
-
root.pathname = ensureTrailingSlash(root.pathname);
|
|
353
|
-
return root;
|
|
354
|
-
}
|
|
355
|
-
catch {
|
|
356
|
-
return undefined;
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
function resourceOwnerWebId(intent) {
|
|
360
|
-
const podRoot = podRootFromIntent(intent);
|
|
361
|
-
return podRoot ? new URL('profile/card#me', podRoot).href : intent.ownerWebId;
|
|
362
|
-
}
|
|
363
|
-
function resourceReadPreferences(intent) {
|
|
364
|
-
return isGatewayAccessKeySecretResource(intent)
|
|
365
|
-
? { type: { 'application/json': 1, '*/*': 0.1 } }
|
|
366
|
-
: { type: { 'text/turtle': 1, '*/*': 0.1 } };
|
|
367
|
-
}
|
|
368
|
-
function isGatewayAccessKeySecretResource(intent) {
|
|
369
|
-
try {
|
|
370
|
-
const resource = new URL(intent.resourceUrl);
|
|
371
|
-
const expected = new URL((0, AiConnectionsServiceAccess_1.resolveGatewayAccessKeySecretResourceUrl)(resourceOwnerWebId(intent)));
|
|
372
|
-
return resource.href === expected.href;
|
|
373
|
-
}
|
|
374
|
-
catch {
|
|
375
|
-
return false;
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
async function trustedSparqlOperationForRequest(request, ownerWebId, resourceUrl, method) {
|
|
379
|
-
const queryFromUrl = trustedSparqlQueryForOwner(ownerWebId, resourceUrl);
|
|
380
|
-
if (queryFromUrl !== undefined) {
|
|
381
|
-
return method === 'GET' ? { kind: 'query', sparql: queryFromUrl } : undefined;
|
|
382
|
-
}
|
|
383
|
-
const endpointKind = trustedSparqlEndpointKind(ownerWebId, resourceUrl);
|
|
384
|
-
if (method !== 'POST' || !endpointKind || resourceUrl.search || resourceUrl.hash) {
|
|
385
|
-
return undefined;
|
|
386
|
-
}
|
|
387
|
-
const body = await readRequestBody(request);
|
|
388
|
-
if (!body) {
|
|
389
|
-
return undefined;
|
|
390
|
-
}
|
|
391
|
-
const contentType = firstHeader(request.headers['content-type'])?.split(';', 1)[0].trim().toLowerCase();
|
|
392
|
-
let declaredKind;
|
|
393
|
-
let sparql;
|
|
394
|
-
if (contentType === 'application/sparql-query') {
|
|
395
|
-
declaredKind = 'query';
|
|
396
|
-
sparql = body.toString('utf8').trim();
|
|
397
|
-
}
|
|
398
|
-
else if (contentType === 'application/sparql-update') {
|
|
399
|
-
declaredKind = 'update';
|
|
400
|
-
sparql = body.toString('utf8').trim();
|
|
401
|
-
}
|
|
402
|
-
else if (contentType === 'application/x-www-form-urlencoded') {
|
|
403
|
-
const params = new URLSearchParams(body.toString('utf8'));
|
|
404
|
-
const keys = Array.from(params.keys());
|
|
405
|
-
const operation = keys.length === 1 && (keys[0] === 'query' || keys[0] === 'update')
|
|
406
|
-
? keys[0]
|
|
407
|
-
: undefined;
|
|
408
|
-
if (operation) {
|
|
409
|
-
declaredKind = operation;
|
|
410
|
-
sparql = params.get(operation)?.trim();
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
const parsedKind = sparql ? parseSparqlKind(sparql) : undefined;
|
|
414
|
-
if (!declaredKind || !sparql || parsedKind !== declaredKind ||
|
|
415
|
-
(endpointKind !== 'settings' && parsedKind !== 'query')) {
|
|
416
|
-
return undefined;
|
|
417
|
-
}
|
|
418
|
-
return {
|
|
419
|
-
kind: parsedKind,
|
|
420
|
-
sparql,
|
|
421
|
-
bodyDigest: (0, node_crypto_1.createHash)('sha256').update(body).digest('hex'),
|
|
422
|
-
};
|
|
423
|
-
}
|
|
424
|
-
function trustedSparqlQueryForOwner(ownerWebId, resourceUrl) {
|
|
425
|
-
if (!trustedSparqlEndpointKind(ownerWebId, resourceUrl) || resourceUrl.hash) {
|
|
426
|
-
return undefined;
|
|
427
|
-
}
|
|
428
|
-
const keys = Array.from(resourceUrl.searchParams.keys());
|
|
429
|
-
if (keys.length !== 1 || keys[0] !== 'query') {
|
|
430
|
-
return undefined;
|
|
431
|
-
}
|
|
432
|
-
const query = resourceUrl.searchParams.get('query')?.trim();
|
|
433
|
-
return query && parseSparqlKind(query) === 'query' ? query : undefined;
|
|
434
|
-
}
|
|
435
|
-
function trustedSparqlEndpointKind(ownerWebId, resourceUrlValue) {
|
|
436
|
-
let ownerUrl;
|
|
437
|
-
let resourceUrl;
|
|
438
|
-
try {
|
|
439
|
-
ownerUrl = new URL(ownerWebId);
|
|
440
|
-
resourceUrl = typeof resourceUrlValue === 'string' ? new URL(resourceUrlValue) : resourceUrlValue;
|
|
441
|
-
}
|
|
442
|
-
catch {
|
|
443
|
-
return undefined;
|
|
444
|
-
}
|
|
445
|
-
const podRoot = hostedPodRootFromOwner(ownerUrl);
|
|
446
|
-
if (!podRoot || resourceUrl.origin !== podRoot.origin) {
|
|
447
|
-
return undefined;
|
|
448
|
-
}
|
|
449
|
-
if (resourceUrl.pathname === `${podRoot.pathname}settings/providers/-/sparql`) {
|
|
450
|
-
return 'models';
|
|
451
|
-
}
|
|
452
|
-
if ((0, AiConnectionsServiceAccess_1.isGatewayAccessKeySparqlEndpoint)(ownerWebId, resourceUrl)) {
|
|
453
|
-
return 'gatewayAccessKeys';
|
|
454
|
-
}
|
|
455
|
-
return resourceUrl.pathname === `${podRoot.pathname}settings/-/sparql` ? 'settings' : undefined;
|
|
456
|
-
}
|
|
457
|
-
function isAllowedGatewayKeyVerifierResource(intent, resourceUrl) {
|
|
458
|
-
const ownerWebId = resourceOwnerWebId(intent);
|
|
459
|
-
let documentUrl;
|
|
460
|
-
try {
|
|
461
|
-
documentUrl = new URL((0, AiConnectionsServiceAccess_1.resolveGatewayAccessKeyResourceUrl)(ownerWebId));
|
|
462
|
-
}
|
|
463
|
-
catch {
|
|
464
|
-
return false;
|
|
465
|
-
}
|
|
466
|
-
const exactDocument = resourceUrl.href === documentUrl.href;
|
|
467
|
-
if (intent.scopes[0] === 'ai:gateway-key:touch') {
|
|
468
|
-
return exactDocument && (intent.method === 'GET' || intent.method === 'HEAD' || intent.method === 'PATCH');
|
|
469
|
-
}
|
|
470
|
-
if (intent.scopes[0] !== 'ai:gateway-key:verify') {
|
|
471
|
-
return false;
|
|
472
|
-
}
|
|
473
|
-
if (exactDocument) {
|
|
474
|
-
return intent.method === 'GET' || intent.method === 'HEAD';
|
|
475
|
-
}
|
|
476
|
-
if (!(0, AiConnectionsServiceAccess_1.isGatewayAccessKeySparqlEndpoint)(ownerWebId, resourceUrl)) {
|
|
477
|
-
return false;
|
|
478
|
-
}
|
|
479
|
-
if (intent.method === 'GET') {
|
|
480
|
-
return trustedSparqlQueryForOwner(ownerWebId, resourceUrl) !== undefined;
|
|
481
|
-
}
|
|
482
|
-
return intent.method === 'POST' && !resourceUrl.search && !resourceUrl.hash;
|
|
483
|
-
}
|
|
484
|
-
function parseSparqlKind(value) {
|
|
485
|
-
try {
|
|
486
|
-
const parsed = new sparqljs_1.Parser({ baseIRI: 'urn:xpod:internal-sparql:' }).parse(value);
|
|
487
|
-
return parsed.type === 'update' ? 'update' : parsed.type === 'query' ? 'query' : undefined;
|
|
488
|
-
}
|
|
489
|
-
catch {
|
|
490
|
-
return undefined;
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
function intentHasScope(intent, requiredScope) {
|
|
494
|
-
return intent.scopes.some((scope) => scope === requiredScope || scope === 'ai:credentials:*' || scope === 'ai:*');
|
|
495
|
-
}
|
|
496
|
-
function intentAllowsSparqlOperation(intent, operation) {
|
|
497
|
-
if (intent.principalKind === 'gateway-key-verifier') {
|
|
498
|
-
return operation === 'query'
|
|
499
|
-
&& intent.scopes.length === 1
|
|
500
|
-
&& intent.scopes[0] === 'ai:gateway-key:verify';
|
|
501
|
-
}
|
|
502
|
-
return intentHasScope(intent, operation === 'query' ? 'ai:credentials:read' : 'ai:credentials:write');
|
|
503
|
-
}
|
|
504
|
-
async function readRequestBody(request) {
|
|
505
|
-
const chunks = [];
|
|
506
|
-
let size = 0;
|
|
507
|
-
for await (const chunk of request) {
|
|
508
|
-
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
509
|
-
size += buffer.byteLength;
|
|
510
|
-
if (size > MODEL_QUERY_MAX_BODY_BYTES) {
|
|
511
|
-
return undefined;
|
|
512
|
-
}
|
|
513
|
-
chunks.push(buffer);
|
|
514
|
-
}
|
|
515
|
-
if (size === 0) {
|
|
516
|
-
return undefined;
|
|
517
|
-
}
|
|
518
|
-
return Buffer.concat(chunks, size);
|
|
519
|
-
}
|
|
520
|
-
function ensureTrailingSlash(value) {
|
|
521
|
-
return value.endsWith('/') ? value : `${value}/`;
|
|
522
|
-
}
|
|
523
|
-
class BoundedTtlNonceCache {
|
|
524
|
-
constructor(options) {
|
|
525
|
-
this.entries = new Map();
|
|
526
|
-
this.ttlMs = Math.max(1, options.ttlMs);
|
|
527
|
-
this.maxEntries = Math.max(1, options.maxEntries);
|
|
528
|
-
this.now = options.now ?? Date.now;
|
|
529
|
-
}
|
|
530
|
-
consume(nonce) {
|
|
531
|
-
const now = this.now();
|
|
532
|
-
this.pruneExpired(now);
|
|
533
|
-
if (this.entries.has(nonce)) {
|
|
534
|
-
return false;
|
|
535
|
-
}
|
|
536
|
-
if (this.entries.size >= this.maxEntries) {
|
|
537
|
-
return false;
|
|
538
|
-
}
|
|
539
|
-
this.entries.set(nonce, now + this.ttlMs);
|
|
540
|
-
return true;
|
|
541
|
-
}
|
|
542
|
-
pruneExpired(now) {
|
|
543
|
-
for (const [nonce, expiresAt] of this.entries) {
|
|
544
|
-
if (expiresAt > now) {
|
|
545
|
-
continue;
|
|
546
|
-
}
|
|
547
|
-
this.entries.delete(nonce);
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
//# sourceMappingURL=InternalPodDataHttpHandler.js.map
|