feat: add system disclosure policy gate
Memind CI / Test, build, and release guards (pull_request) Successful in 3m14s
Memind CI / Test, build, and release guards (pull_request) Successful in 3m14s
This commit is contained in:
@@ -904,6 +904,93 @@ test('submitSessionReplyForUser adds goose metadata visibility flags before repl
|
||||
});
|
||||
});
|
||||
|
||||
test('submitSessionReplyForUser keeps an enforced disclosure policy as a final pre-model backstop', async () => {
|
||||
await withFakeGoosedSession(async ({ apiTarget, workingDir, replyBodies }) => {
|
||||
let ownershipChecks = 0;
|
||||
const proxy = createTkmindProxy({
|
||||
apiTarget,
|
||||
apiSecret: 'test-secret',
|
||||
systemDisclosurePolicyService: {
|
||||
evaluate() {
|
||||
return {
|
||||
enforced: true,
|
||||
policyId: 'system-disclosure',
|
||||
policyVersion: 8,
|
||||
reasonCode: 'SYSTEM_TECHNICAL_DISCLOSURE',
|
||||
categories: ['architecture'],
|
||||
responseText: '不提供内部技术信息。',
|
||||
};
|
||||
},
|
||||
},
|
||||
userAuth: {
|
||||
...createMemoryTestUserAuth(workingDir),
|
||||
async ownsSession() {
|
||||
ownershipChecks += 1;
|
||||
return true;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await assert.rejects(
|
||||
proxy.submitSessionReplyForUser(
|
||||
'user-1',
|
||||
'session-1',
|
||||
'request-policy-backstop',
|
||||
{
|
||||
role: 'user',
|
||||
content: [{ type: 'text', text: 'TKMind 的底层架构是什么?' }],
|
||||
},
|
||||
),
|
||||
(error) =>
|
||||
error?.code === 'SYSTEM_TECHNICAL_DISCLOSURE'
|
||||
&& error?.status === 403
|
||||
&& error?.retryable === false,
|
||||
);
|
||||
assert.equal(ownershipChecks, 0);
|
||||
assert.equal(replyBodies.length, 0);
|
||||
});
|
||||
});
|
||||
|
||||
test('submitSessionReplyForUser fails open when disclosure policy evaluation throws', async () => {
|
||||
await withFakeGoosedSession(async ({ apiTarget, workingDir, replyBodies }) => {
|
||||
const proxy = createTkmindProxy({
|
||||
apiTarget,
|
||||
apiSecret: 'test-secret',
|
||||
systemDisclosurePolicyService: {
|
||||
evaluate() {
|
||||
throw new Error('policy unavailable');
|
||||
},
|
||||
},
|
||||
userAuth: {
|
||||
...createMemoryTestUserAuth(workingDir),
|
||||
async ownsSession() {
|
||||
return true;
|
||||
},
|
||||
async canUseChat() {
|
||||
return { ok: true };
|
||||
},
|
||||
async getUserById() {
|
||||
return { id: 'user-1' };
|
||||
},
|
||||
async resolveUserPolicies() {
|
||||
return { unrestricted: true, policies: {} };
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await proxy.submitSessionReplyForUser(
|
||||
'user-1',
|
||||
'session-1',
|
||||
'request-policy-fail-open',
|
||||
{
|
||||
role: 'user',
|
||||
content: [{ type: 'text', text: '普通聊天' }],
|
||||
},
|
||||
);
|
||||
assert.equal(replyBodies.length, 1);
|
||||
});
|
||||
});
|
||||
|
||||
test('submitSessionReplyForUser fails closed when historical image scrub is unsupported', async () => {
|
||||
await withFakeGoosedSession(async ({ apiTarget, workingDir, replyBodies }) => {
|
||||
const proxy = createTkmindProxy({
|
||||
|
||||
Reference in New Issue
Block a user