open-design/apps/daemon/tests/live-artifacts-schema.test.ts
marco 5dd70b5016
Some checks failed
ci / Validate workspace (push) Successful in 12m32s
landing-page-ci / Validate landing page (push) Successful in 9m41s
landing-page-deploy / Deploy landing page (push) Failing after 5m23s
github-metrics / Generate repository metrics SVG (push) Failing after 2m3s
refresh-contributors-wall / Refresh contributors wall cache bust (push) Failing after 11s
Initial import: open-design source for helix-mind.ai distribution
This repository contains the open-design daemon CLI source code, built
and packaged at https://helix-mind.ai/cli/open-design/latest.tgz for use
by the HelixMind /design slash command.

Licenses: Apache-2.0 (root) + MIT (skills/*)
2026-05-06 20:50:24 +02:00

287 lines
9.3 KiB
TypeScript

import { readFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { describe, expect, it } from 'vitest';
import {
validateBoundedJsonObject,
validateLiveArtifactCreateInput,
validatePersistedLiveArtifact,
} from '../src/live-artifacts/schema.js';
const here = dirname(fileURLToPath(import.meta.url));
const examplesDir = join(here, '../../../specs/2026-04-29-live-artifacts/examples');
const forbiddenJsonKeys = [
'raw',
'rawResponse',
'payload',
'body',
'headers',
'cookie',
'authorization',
'token',
'secret',
'credential',
'password',
] as const;
function readJsonFixture(exampleName: string, fileName: string): unknown {
return JSON.parse(readFileSync(join(examplesDir, exampleName, fileName), 'utf8'));
}
function validCreateInput() {
return {
title: 'Fixture artifact',
preview: {
type: 'html',
entry: 'index.html',
},
document: {
format: 'html_template_v1',
templatePath: 'template.html',
generatedPreviewPath: 'index.html',
dataPath: 'data.json',
dataJson: {
title: 'Fixture artifact',
},
},
};
}
describe('live artifact schema validation', () => {
it.each(forbiddenJsonKeys)('rejects forbidden bounded JSON key %s', (key) => {
const result = validateBoundedJsonObject({ safe: { [key]: 'must not persist' } }, 'data');
expect(result.ok).toBe(false);
if (!result.ok) expect(result.issues.some((issue) => issue.path === `data.safe.${key}`)).toBe(true);
});
it('rejects invalid fixture artifacts with raw provider or credential-like fields', () => {
const rawFields = validateLiveArtifactCreateInput(readJsonFixture('invalid-forbidden-raw-fields', 'artifact.json'));
const credentials = validateLiveArtifactCreateInput(readJsonFixture('invalid-credential-like-fields', 'artifact.json'));
expect(rawFields.ok).toBe(false);
if (!rawFields.ok) {
expect(rawFields.issues.map((issue) => issue.path)).toEqual(
expect.arrayContaining(['input.document.dataJson.rawResponse', 'input.document.dataJson.rawResponse.payload']),
);
}
expect(credentials.ok).toBe(false);
if (!credentials.ok) {
expect(credentials.issues.map((issue) => issue.path)).toEqual(
expect.arrayContaining(['input.document.sourceJson.input.token', 'input.document.sourceJson.input.password']),
);
}
});
it('rejects path traversal and absolute paths in preview, sources, and provenance refs', () => {
const previewTraversal = validateLiveArtifactCreateInput({
...validCreateInput(),
preview: { type: 'html', entry: '../index.html' },
});
const sourceTraversal = validateLiveArtifactCreateInput({
...validCreateInput(),
document: {
...validCreateInput().document,
sourceJson: {
type: 'local_file',
toolName: 'project_files.read_json',
input: { path: 'reports/../../secrets.json' },
refreshPermission: 'none',
},
},
});
const sourceAbsolutePath = validateLiveArtifactCreateInput({
...validCreateInput(),
document: {
...validCreateInput().document,
sourceJson: {
type: 'local_file',
toolName: 'project_files.read_json',
input: { file: '/etc/passwd' },
refreshPermission: 'none',
},
},
});
const sourceWindowsAbsolutePath = validateLiveArtifactCreateInput({
...validCreateInput(),
document: {
...validCreateInput().document,
sourceJson: {
type: 'local_file',
toolName: 'project_files.read_json',
input: { file: 'C:\\Users\\secrets.json' },
refreshPermission: 'none',
},
},
});
const sourceBackslashAbsolutePath = validateLiveArtifactCreateInput({
...validCreateInput(),
document: {
...validCreateInput().document,
sourceJson: {
type: 'local_file',
toolName: 'project_files.read_json',
input: { file: '\\etc\\passwd' },
refreshPermission: 'none',
},
},
});
for (const result of [
previewTraversal,
sourceTraversal,
sourceAbsolutePath,
sourceWindowsAbsolutePath,
sourceBackslashAbsolutePath,
]) {
expect(result.ok).toBe(false);
}
});
it('persists only connector references and rejects credential material in connector metadata', () => {
const result = validateLiveArtifactCreateInput({
...validCreateInput(),
document: {
...validCreateInput().document,
sourceJson: {
type: 'connector_tool',
toolName: 'docs.search',
input: { query: 'launch' },
connector: {
connectorId: 'docs',
accountLabel: 'docs@example.com',
toolName: 'docs.search',
approvalPolicy: 'manual_refresh_granted_for_read_only',
accessToken: 'oauth-secret-token',
headers: { authorization: 'Bearer oauth-secret-token' },
},
oauthState: 'state-that-must-not-persist',
refreshPermission: 'manual_refresh_granted_for_read_only',
},
},
});
expect(result.ok).toBe(false);
if (!result.ok) {
expect(result.issues.map((issue) => issue.path)).toEqual(expect.arrayContaining([
'input.document.sourceJson.connector.accessToken',
'input.document.sourceJson.connector.headers',
'input.document.sourceJson.oauthState',
]));
}
});
it('requires connector metadata for connector_tool sources', () => {
const result = validateLiveArtifactCreateInput({
...validCreateInput(),
document: {
...validCreateInput().document,
sourceJson: {
type: 'connector_tool',
toolName: 'docs.search',
input: { query: 'launch' },
refreshPermission: 'manual_refresh_granted_for_read_only',
},
},
});
expect(result.ok).toBe(false);
if (!result.ok) {
expect(result.issues).toEqual(expect.arrayContaining([
expect.objectContaining({ path: 'input.document.sourceJson.connector' }),
]));
}
});
it('does not require connector approval metadata for connector_tool sources', () => {
const result = validateLiveArtifactCreateInput({
...validCreateInput(),
document: {
...validCreateInput().document,
sourceJson: {
type: 'connector_tool',
toolName: 'docs.search',
input: { query: 'launch' },
connector: {
connectorId: 'docs',
toolName: 'docs.search',
},
refreshPermission: 'none',
},
},
});
expect(result.ok).toBe(true);
if (result.ok) expect(result.value.document?.sourceJson?.connector).toEqual({ connectorId: 'docs', toolName: 'docs.search' });
});
it('requires connector source tool name to match connector metadata', () => {
const result = validateLiveArtifactCreateInput({
...validCreateInput(),
document: {
...validCreateInput().document,
sourceJson: {
type: 'connector_tool',
toolName: 'docs.search',
input: { query: 'launch' },
connector: {
connectorId: 'docs',
toolName: 'docs.lookup',
approvalPolicy: 'read_only_auto',
},
refreshPermission: 'manual_refresh_granted_for_read_only',
},
},
});
expect(result.ok).toBe(false);
if (!result.ok) {
expect(result.issues).toEqual(expect.arrayContaining([
expect.objectContaining({ path: 'input.document.sourceJson.toolName' }),
]));
}
});
it('requires toolName for daemon_tool sources', () => {
const result = validateLiveArtifactCreateInput({
...validCreateInput(),
document: {
...validCreateInput().document,
sourceJson: {
type: 'daemon_tool',
input: { query: 'launch' },
refreshPermission: 'none',
},
},
});
expect(result.ok).toBe(false);
if (!result.ok) {
expect(result.issues).toEqual(expect.arrayContaining([
expect.objectContaining({
path: 'input.document.sourceJson.toolName',
message: 'input.document.sourceJson.toolName is required for daemon_tool sources',
}),
]));
}
});
it('rejects oversized bounded JSON payloads', () => {
const oversized = Object.fromEntries(Array.from({ length: 100 }, (_, index) => [`field${index}`, 'x'.repeat(3_000)]));
const result = validateBoundedJsonObject(oversized, 'data');
expect(result.ok).toBe(false);
if (!result.ok) expect(result.issues.some((issue) => issue.message.includes('max serialized size'))).toBe(true);
});
it.each(['minimal-static'])('accepts valid fixture artifact %s', (exampleName) => {
const artifact = readJsonFixture(exampleName, 'artifact.json');
const data = readJsonFixture(exampleName, 'data.json');
expect(validatePersistedLiveArtifact(artifact).ok).toBe(true);
expect(validateBoundedJsonObject(data).ok).toBe(true);
});
});