mirror of
https://github.com/stablyai/orca.git
synced 2026-10-22 00:03:47 +00:00
feat(skills): bound install diagnostics
This commit is contained in:
@@ -723,6 +723,11 @@ record before the multi-distro gate.
|
||||
|
||||
## 11. Implement and validate SSH targets
|
||||
|
||||
The 2026-08-11 live Orca inventory contains only the connected `windows 2` environment and no
|
||||
non-local worktree or repository. Real SSH validation therefore requires registering an isolated
|
||||
SSH macOS, Ubuntu 20.04, or supported Windows target; implementation and contract tests continue
|
||||
without treating the missing external topology as a product failure.
|
||||
|
||||
- [x] Define a host-side installer command that invokes the same installer core and structured
|
||||
result contract.
|
||||
- [x] Transfer immutable packages through the existing SSH/SFTP provider into bounded private
|
||||
@@ -766,7 +771,10 @@ record before the multi-distro gate.
|
||||
URLs, upload policies, download grants, and credentials.
|
||||
- [x] Redact sensitive network values before logger invocation, not after ingestion.
|
||||
- [x] Audit authorization and lifecycle events without instruction or script contents.
|
||||
- [ ] Verify diagnostics and support bundles preserve the same exclusions.
|
||||
- [x] Verify diagnostics and support bundles preserve the same exclusions. Desktop install spans
|
||||
map requests and results to bounded labels before the tracer boundary; regression coverage
|
||||
proves raw paths, filenames, manifests, ACL values, durable share URLs, upload policies,
|
||||
download grants, credentials, and raw error text never enter the collected bundle.
|
||||
|
||||
### Security review
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import { downloadSkillPackageGrant } from './skill-package-download'
|
||||
import { detectSkillProvidersInWsl } from './skill-wsl-provider-detection'
|
||||
import { createWslSkillInstallFilesystem } from './skill-wsl-install-filesystem'
|
||||
import { skillInstallFailureFromError } from './skill-install-operation-error'
|
||||
import { startSkillInstallOperation } from './skill-operation-observability'
|
||||
|
||||
type StagedSkillPackage = {
|
||||
archivePath: string
|
||||
@@ -68,6 +69,21 @@ export async function executeSkillInstallRequest(
|
||||
dependencies: SkillInstallRequestDependencies
|
||||
): Promise<SkillInstallResult> {
|
||||
const request = SkillInstallRequestSchema.parse(input)
|
||||
const operation = startSkillInstallOperation(request)
|
||||
try {
|
||||
const result = await executeParsedSkillInstallRequest(request, dependencies)
|
||||
operation.complete(result)
|
||||
return result
|
||||
} catch (error) {
|
||||
operation.fail(error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
async function executeParsedSkillInstallRequest(
|
||||
request: SkillInstallRequest,
|
||||
dependencies: SkillInstallRequestDependencies
|
||||
): Promise<SkillInstallResult> {
|
||||
const destination = await resolveSkillInstallDestination(
|
||||
request.destination,
|
||||
dependencies.authority
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import { afterEach, beforeEach, describe, expect, it } from 'vitest'
|
||||
import type { SkillInstallRequest, SkillInstallResult } from '../../shared/skill-install-contract'
|
||||
import { collectBundle } from '../observability/bundle'
|
||||
import { _resetTracerForTests, setActiveSink, type TracerSink } from '../observability/tracer'
|
||||
import { startSkillInstallOperation } from './skill-operation-observability'
|
||||
|
||||
type CapturingSink = TracerSink & { records: unknown[] }
|
||||
|
||||
const PRIVATE_VALUES = {
|
||||
localPath: '/Users/private/team skills/payroll-skill.tar.gz',
|
||||
canonicalPath: '/Users/private/.agents/skills/payroll',
|
||||
providerPath: '/Users/private/.codex/skills/payroll',
|
||||
connectionId: 'private-production-ssh',
|
||||
skillName: 'payroll-instructions',
|
||||
filename: 'salary-review.md',
|
||||
manifest: 'manifest={private-instructions}',
|
||||
acl: 'acl=private-user-id',
|
||||
shareUrl: 'orca://skill-share/private-share-id',
|
||||
uploadPolicy: 'policy=private-signed-upload',
|
||||
downloadGrant: 'https://storage.googleapis.com/private-bucket/object?X-Goog-Signature=secret',
|
||||
credential: 'authorization=Bearer private-access-token'
|
||||
}
|
||||
|
||||
function request(): SkillInstallRequest {
|
||||
return {
|
||||
operationId: 'operation-private',
|
||||
package: {
|
||||
packageId: 'package-123',
|
||||
versionId: 'version-456',
|
||||
packageDigest: 'a'.repeat(64),
|
||||
archiveSha256: 'b'.repeat(64),
|
||||
compressedBytes: 1234
|
||||
},
|
||||
ingress: { kind: 'local-file', path: PRIVATE_VALUES.localPath },
|
||||
destination: {
|
||||
scope: 'global',
|
||||
executionTarget: { kind: 'ssh', connectionId: PRIVATE_VALUES.connectionId }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function result(): SkillInstallResult {
|
||||
return {
|
||||
operationId: 'operation-private',
|
||||
status: 'installed',
|
||||
name: PRIVATE_VALUES.skillName,
|
||||
packageDigest: 'a'.repeat(64),
|
||||
canonicalPath: PRIVATE_VALUES.canonicalPath,
|
||||
placements: [
|
||||
{
|
||||
provider: 'codex',
|
||||
path: PRIVATE_VALUES.providerPath,
|
||||
topology: 'provider-alias',
|
||||
status: 'installed'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
let sink: CapturingSink
|
||||
let directory: string
|
||||
|
||||
beforeEach(() => {
|
||||
sink = {
|
||||
records: [],
|
||||
push(record) {
|
||||
this.records.push(record)
|
||||
},
|
||||
flush() {},
|
||||
close() {}
|
||||
}
|
||||
directory = mkdtempSync(join(tmpdir(), 'orca-skill-observability-'))
|
||||
setActiveSink(sink)
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
_resetTracerForTests()
|
||||
rmSync(directory, { recursive: true, force: true })
|
||||
})
|
||||
|
||||
describe('skill operation observability', () => {
|
||||
it('maps install results to bounded labels without private operation data', () => {
|
||||
const operation = startSkillInstallOperation(request())
|
||||
operation.complete(result())
|
||||
|
||||
const serialized = JSON.stringify(sink.records)
|
||||
expect(serialized).toContain('package-123')
|
||||
expect(serialized).toContain('version-456')
|
||||
expect(serialized).toContain('global-ssh')
|
||||
expect(serialized).toContain('provider-alias')
|
||||
for (const value of Object.values(PRIVATE_VALUES)) {
|
||||
expect(serialized).not.toContain(value)
|
||||
}
|
||||
})
|
||||
|
||||
it('keeps support bundles free of paths, filenames, share URLs, policies, ACLs, and grants', () => {
|
||||
const operation = startSkillInstallOperation({
|
||||
...request(),
|
||||
ingress: {
|
||||
kind: 'download-grant',
|
||||
url: PRIVATE_VALUES.downloadGrant,
|
||||
expiresAt: '2030-01-01T00:00:00Z'
|
||||
}
|
||||
})
|
||||
operation.fail(new Error(Object.values(PRIVATE_VALUES).join(' ')))
|
||||
const traceFile = join(directory, 'trace.ndjson')
|
||||
writeFileSync(traceFile, `${sink.records.map((record) => JSON.stringify(record)).join('\n')}\n`)
|
||||
|
||||
const bundle = collectBundle({
|
||||
traceFilePath: traceFile,
|
||||
maxFiles: 1,
|
||||
appVersion: 'test',
|
||||
platform: 'darwin',
|
||||
arch: 'arm64',
|
||||
osRelease: 'test',
|
||||
orcaChannel: 'dev'
|
||||
})
|
||||
|
||||
expect(bundle.payload).toContain('skill-install-unknown')
|
||||
for (const value of Object.values(PRIVATE_VALUES)) {
|
||||
expect(bundle.payload).not.toContain(value)
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,76 @@
|
||||
import type {
|
||||
SkillInstallDestination,
|
||||
SkillInstallRequest,
|
||||
SkillInstallResult,
|
||||
SkillPlacementResult
|
||||
} from '../../shared/skill-install-contract'
|
||||
import { startSpan, type ActiveSpan } from '../observability/tracer'
|
||||
import { skillInstallFailureFromError } from './skill-install-operation-error'
|
||||
|
||||
const SAFE_LABEL = /^[a-z0-9][a-z0-9._-]{0,63}$/i
|
||||
|
||||
export type SkillInstallOperationSpan = {
|
||||
complete(result: SkillInstallResult): void
|
||||
fail(error: unknown): void
|
||||
}
|
||||
|
||||
function safeLabel(value: string | undefined, fallback: string): string {
|
||||
return value && SAFE_LABEL.test(value) ? value : fallback
|
||||
}
|
||||
|
||||
function destinationLabel(destination: SkillInstallDestination): string {
|
||||
if (destination.scope === 'workspace') {
|
||||
return 'workspace'
|
||||
}
|
||||
return `global-${destination.executionTarget?.kind ?? 'host'}`
|
||||
}
|
||||
|
||||
function recordPlacement(span: ActiveSpan, placement: SkillPlacementResult): void {
|
||||
span.addEvent('skill.placement', {
|
||||
provider: safeLabel(placement.provider, 'unknown'),
|
||||
topology: placement.topology,
|
||||
status: placement.status,
|
||||
errorCategory: safeLabel(placement.errorCategory, 'none')
|
||||
})
|
||||
}
|
||||
|
||||
export function startSkillInstallOperation(
|
||||
request: SkillInstallRequest
|
||||
): SkillInstallOperationSpan {
|
||||
const span = startSpan('skill.install', {
|
||||
attributes: {
|
||||
packageId: request.package.packageId,
|
||||
versionId: request.package.versionId,
|
||||
phase: 'install',
|
||||
destination: destinationLabel(request.destination),
|
||||
transport: request.ingress.kind,
|
||||
compressedBytes: request.package.compressedBytes
|
||||
}
|
||||
})
|
||||
return {
|
||||
complete(result) {
|
||||
span.setAttribute('status', result.status)
|
||||
span.setAttribute('placementCount', result.placements.length)
|
||||
for (const placement of result.placements) {
|
||||
recordPlacement(span, placement)
|
||||
}
|
||||
if (result.status === 'cancelled') {
|
||||
span.interrupt(safeLabel(result.errorCategory, 'skill-install-cancelled'))
|
||||
} else if (result.status === 'failed') {
|
||||
span.fail(safeLabel(result.errorCategory, 'skill-install-failed'))
|
||||
} else {
|
||||
span.end()
|
||||
}
|
||||
},
|
||||
fail(error) {
|
||||
const failure = skillInstallFailureFromError(error)
|
||||
const code = safeLabel(failure?.code, 'skill-install-unknown')
|
||||
span.setAttribute('status', failure?.category === 'cancelled' ? 'cancelled' : 'failed')
|
||||
if (failure?.category === 'cancelled') {
|
||||
span.interrupt(code)
|
||||
} else {
|
||||
span.fail(code)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user