diff --git a/plugins/reporting-governance/README.md b/plugins/reporting-governance/README.md index fcaf80e..4a28ff5 100644 --- a/plugins/reporting-governance/README.md +++ b/plugins/reporting-governance/README.md @@ -93,6 +93,7 @@ Current **public package surface** is intentionally narrow: `@openclaw/plugin-reporting-governance/adapters` 目前只代表 **runtime adapter entrypoints**。 `createRuntimeBinding(...)`、`loadDeploymentProfileArtifact(...)`、`createDeploymentBindingContract(...)` 不再掛在 `./adapters` barrel;前者仍由 root export 提供,後兩者屬於 storage/profile artifact slice。 +目前 `storage` / `profile-artifact` 也**不是公開 subpath**;若要使用其能力,請以 root export / 已宣告 exports 為準,不要 deep import `src/storage/*`。 What is currently exposed from the root export: diff --git a/plugins/reporting-governance/test/exports-boundary.integration.test.mjs b/plugins/reporting-governance/test/exports-boundary.integration.test.mjs index 78b1207..7c2f45b 100644 --- a/plugins/reporting-governance/test/exports-boundary.integration.test.mjs +++ b/plugins/reporting-governance/test/exports-boundary.integration.test.mjs @@ -71,6 +71,7 @@ test('package root export resolves public package surface only', () => { hasPlanDecisionExecution: typeof plugin.planDecisionExecution, hasExecuteGovernanceContract: typeof plugin.executeGovernanceContract, hasExecuteRuntimeIntegratedGovernance: typeof plugin.executeRuntimeIntegratedGovernance, + hasCreateRuntimeBinding: typeof plugin.createRuntimeBinding, hasCreateDecisionRecordArtifact: typeof plugin.createDecisionRecordArtifact, hasCreateFileDecisionStore: typeof plugin.createFileDecisionStore, })); @@ -85,6 +86,7 @@ test('package root export resolves public package surface only', () => { assert.equal(result.hasPlanDecisionExecution, 'function'); assert.equal(result.hasExecuteGovernanceContract, 'function'); assert.equal(result.hasExecuteRuntimeIntegratedGovernance, 'function'); + assert.equal(result.hasCreateRuntimeBinding, 'function'); assert.equal(result.hasCreateDecisionRecordArtifact, 'function'); assert.equal(result.hasCreateFileDecisionStore, 'function'); } finally { @@ -115,6 +117,36 @@ test('adapters subpath export resolves package-owned adapter entrypoints only', } }); +test('storage/profile-artifact deep subpaths stay outside package exports boundary', () => { + const root = createFixtureRoot(); + try { + installPackageAlias(root); + const result = runNodeEval(root, ` + import('@openclaw/plugin-reporting-governance/src/storage/profile-artifact.mjs') + .then(() => { + process.stdout.write(JSON.stringify({ ok: true })); + }) + .catch((error) => { + process.stdout.write(JSON.stringify({ + ok: false, + code: error?.code ?? null, + name: error?.name ?? null, + message: error?.message ?? null, + })); + }); + `); + + assert.equal(result.status, 0, result.stderr); + const payload = JSON.parse((result.stdout ?? '').trim()); + assert.equal(payload.ok, false); + assert.equal(payload.code, 'ERR_PACKAGE_PATH_NOT_EXPORTED'); + assert.equal(payload.name, 'Error'); + assert.match(payload.message ?? '', /Package subpath '\.\/src\/storage\/profile-artifact\.mjs' is not defined by "exports"/); + } finally { + fs.rmSync(root, { recursive: true, force: true }); + } +}); + test('deep runtime-binding subpath stays outside package exports boundary', () => { const root = createFixtureRoot(); try {