mirror of
https://github.com/stablyai/orca.git
synced 2026-10-02 08:02:02 +00:00
fix(artifacts): enforce recovery content limit
This commit is contained in:
@@ -3,7 +3,11 @@ import { mkdtemp, readFile, readdir, rm, stat, truncate, writeFile } from 'node:
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
import { ARTIFACT_MAX_REQUEST_BYTES, artifactWriteRequestByteLength } from '../../shared/artifacts'
|
||||
import {
|
||||
ARTIFACT_MAX_CONTENT_BYTES,
|
||||
ARTIFACT_MAX_REQUEST_BYTES,
|
||||
artifactWriteRequestByteLength
|
||||
} from '../../shared/artifacts'
|
||||
import {
|
||||
MAX_ARTIFACT_CREATE_INTENT_BYTES,
|
||||
MAX_PENDING_ARTIFACT_CREATES,
|
||||
@@ -270,9 +274,9 @@ describe('artifact create intent store', () => {
|
||||
).toThrow(/unsupported format/)
|
||||
})
|
||||
|
||||
it('persists a valid artifact request near the recovery limit', async () => {
|
||||
it('persists a 5 MiB escaped artifact within the recovery limit', async () => {
|
||||
const userDataPath = await createUserDataPath()
|
||||
const nearLimitBody = { ...body, content: 'x'.repeat(ARTIFACT_MAX_REQUEST_BYTES - 200) }
|
||||
const nearLimitBody = { ...body, content: '"'.repeat(ARTIFACT_MAX_CONTENT_BYTES) }
|
||||
expect(
|
||||
artifactWriteRequestByteLength({ sourceKey: '/repo/report.html', ...nearLimitBody })
|
||||
).toBeLessThanOrEqual(ARTIFACT_MAX_REQUEST_BYTES)
|
||||
@@ -289,7 +293,21 @@ describe('artifact create intent store', () => {
|
||||
).not.toThrow()
|
||||
const directory = join(userDataPath, 'profiles', 'local-profile', 'artifact-create-intents')
|
||||
const [fileName] = await readdir(directory)
|
||||
expect((await stat(join(directory, fileName))).size).toBeGreaterThan(ARTIFACT_MAX_REQUEST_BYTES)
|
||||
expect((await stat(join(directory, fileName))).size).toBeGreaterThan(ARTIFACT_MAX_CONTENT_BYTES)
|
||||
})
|
||||
|
||||
it('rejects oversized artifact content before creating a recovery record', async () => {
|
||||
const userDataPath = await createUserDataPath()
|
||||
expect(() =>
|
||||
getOrCreateArtifactCreateIntent(
|
||||
'local-profile',
|
||||
userDataPath,
|
||||
'/repo/report.html',
|
||||
scope,
|
||||
'key-a',
|
||||
{ ...body, content: 'x'.repeat(ARTIFACT_MAX_CONTENT_BYTES + 1) }
|
||||
)
|
||||
).toThrow(/5 MiB limit/)
|
||||
})
|
||||
|
||||
it('rejects an oversized recovery record before reading it', async () => {
|
||||
|
||||
@@ -10,7 +10,11 @@ import {
|
||||
writeFileSync
|
||||
} from 'node:fs'
|
||||
import { join } from 'node:path'
|
||||
import { ARTIFACT_MAX_REQUEST_BYTES } from '../../shared/artifacts'
|
||||
import {
|
||||
ARTIFACT_MAX_CONTENT_BYTES,
|
||||
ARTIFACT_MAX_REQUEST_BYTES,
|
||||
artifactContentByteLength
|
||||
} from '../../shared/artifacts'
|
||||
import {
|
||||
bestEffortFsyncDirectorySync,
|
||||
fsyncFileSync,
|
||||
@@ -116,6 +120,7 @@ function isWriteBody(value: unknown): value is ArtifactWriteBody {
|
||||
const body = value as Partial<ArtifactWriteBody>
|
||||
return (
|
||||
typeof body.content === 'string' &&
|
||||
artifactContentByteLength(body.content) <= ARTIFACT_MAX_CONTENT_BYTES &&
|
||||
(body.contentType === 'text/html' || body.contentType === 'text/markdown') &&
|
||||
typeof body.fileName === 'string' &&
|
||||
(body.title === undefined || typeof body.title === 'string')
|
||||
@@ -193,6 +198,9 @@ export function getOrCreateArtifactCreateIntent(
|
||||
idempotencyKey: string,
|
||||
body: ArtifactWriteBody
|
||||
): ArtifactCreateIntent {
|
||||
if (artifactContentByteLength(body.content) > ARTIFACT_MAX_CONTENT_BYTES) {
|
||||
throw new Error('Artifact content exceeds the 5 MiB limit.')
|
||||
}
|
||||
const existing = getArtifactCreateIntent(profileId, userDataPath, sourceKey, scope)
|
||||
if (existing) {
|
||||
return existing
|
||||
|
||||
Reference in New Issue
Block a user