merge: integrate feature/0713-dev into main

# Conflicts:
#	mindspace-page-data-finish-guard.mjs
#	page-data-delivery-assess.mjs
This commit is contained in:
john
2026-07-13 15:33:45 +08:00
76 changed files with 4348 additions and 189 deletions
+33 -2
View File
@@ -171,6 +171,16 @@ function assertRegisteredDatasetTables(userDataSpace, registryDatasets, usage) {
}
}
async function assertRegisteredDatasetTablesAsync(userDataSpace, registryDatasets, usage) {
for (const dataset of registryDatasets) {
const adapter = {
listTableColumns: () => userDataSpace.listTableColumns(dataset.table),
};
const columns = await adapter.listTableColumns();
assertRegisteredDatasetTables({ listTableColumns: () => columns }, [dataset], usage);
}
}
/**
* Page Data policy must be derived from a registered SQLite dataset, never
* accepted solely from an Agent-supplied policy. This runs before page or
@@ -213,6 +223,27 @@ export function resolveRegisteredPageDataPolicy({
};
}
export async function resolveRegisteredPageDataPolicyAsync(options = {}) {
const { html, userId, accessMode, pageDataPolicy = null, userDataSpace } = options;
const usage = detectPageDataDatasetUsageFromHtml(html);
if (!usage.size) return null;
if (!userDataSpace) throw new Error('缺少 Page Data 数据空间');
if (pageDataPolicy?.datasets) assertPolicyMatchesHtmlDatasets(html, pageDataPolicy.datasets);
const registryDatasets = await userDataSpace.listDatasets();
const datasets = buildPageDataPolicyDatasetsFromRegistry({ html, registryDatasets, usage });
await assertRegisteredDatasetTablesAsync(
userDataSpace,
registryDatasets.filter((dataset) => datasets[dataset.name]),
usage,
);
return {
...pageDataPolicy,
ownerUserId: String(pageDataPolicy?.ownerUserId ?? userId).trim(),
accessMode: pageDataPolicy?.accessMode ?? accessMode,
datasets,
};
}
export async function bindWorkspaceHtmlForPageData({
pool,
h5Root,
@@ -236,8 +267,8 @@ export async function bindWorkspaceHtmlForPageData({
const normalizedAccessMode = resolvePageDataBindAccess(accessMode);
const resolvedPassword = resolvePageDataBindPassword(normalizedAccessMode, password);
const userDataSpace = createUserDataSpaceService({ workspaceRoot });
const resolvedPageDataPolicy = resolveRegisteredPageDataPolicy({
const userDataSpace = createUserDataSpaceService({ workspaceRoot, userId, query: pool });
const resolvedPageDataPolicy = await resolveRegisteredPageDataPolicyAsync({
html: content,
userId,
accessMode: normalizedAccessMode,