@guilz-dev/belay 0.9.0 → 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -1
- package/dist/adapters/claude/runtime-entry.js +2 -0
- package/dist/adapters/codex/runtime-entry.js +2 -0
- package/dist/adapters/cursor/hooks.d.ts +6 -1
- package/dist/adapters/cursor/hooks.js +23 -0
- package/dist/adapters/cursor/runtime-entry.js +5 -0
- package/dist/adapters/shared/gate-runtime.d.ts +1 -0
- package/dist/adapters/shared/gate-runtime.js +49 -52
- package/dist/bundle/claude-runtime.mjs +4295 -3624
- package/dist/bundle/codex-runtime.mjs +4136 -3465
- package/dist/bundle/cursor-runtime.mjs +4137 -3463
- package/dist/commands/doctor.js +21 -3
- package/dist/core/audit-analysis.js +7 -4
- package/dist/core/audit-io.d.ts +1 -0
- package/dist/core/audit-io.js +8 -6
- package/dist/core/audit-legacy-archive.d.ts +7 -0
- package/dist/core/audit-legacy-archive.js +56 -0
- package/dist/core/audit-metrics.d.ts +4 -0
- package/dist/core/audit-metrics.js +2 -2
- package/dist/core/audit-query.d.ts +2 -0
- package/dist/core/audit-query.js +33 -9
- package/dist/core/audit-recovery-metrics.js +2 -2
- package/dist/core/audit-serialize.d.ts +9 -0
- package/dist/core/audit-serialize.js +179 -0
- package/dist/core/audit-types.d.ts +1 -0
- package/dist/core/capability/policy-engine.js +32 -13
- package/dist/core/decision-config-fingerprint.d.ts +3 -0
- package/dist/core/decision-config-fingerprint.js +6 -0
- package/dist/core/effect-ir/shell-lower.js +208 -2
- package/dist/core/verdict/egress-classify.js +1 -0
- package/dist/core/verdict/launcher-resolve.js +51 -10
- package/dist/core/verdict/makefile-expand.d.ts +4 -0
- package/dist/core/verdict/makefile-expand.js +151 -0
- package/dist/core/verdict/parser.d.ts +1 -0
- package/dist/core/verdict/parser.js +24 -12
- package/dist/corpus/benign-probe-cores.d.ts +1 -1
- package/dist/corpus/benign-probe-cores.js +2 -0
- package/dist/defaults.js +5 -4
- package/dist/egress-daemon.js +20 -4
- package/dist/installer.js +3 -0
- package/dist/runtime-provenance.d.ts +10 -0
- package/dist/runtime-provenance.js +63 -0
- package/dist/templates.js +12 -7
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -1
package/dist/egress-daemon.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { mkdir, writeFile } from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { belayStateDir, loadApprovalState, loadConfigFile, repoLocalStateDirFor, } from './config-io.js';
|
|
4
|
+
import { serializeAuditRecordV3 } from './core/audit-serialize.js';
|
|
4
5
|
import { scrubOptionsFromConfig } from './core/config.js';
|
|
5
6
|
import { startEgressProxy as bindEgressProxy } from './core/egress/proxy-server.js';
|
|
6
|
-
import {
|
|
7
|
+
import { resolveActiveAuditCohort } from './runtime-provenance.js';
|
|
7
8
|
import { clearEgressDaemonState, createEgressApprovalStore, writeEgressDaemonState, } from './services/egress-service.js';
|
|
8
9
|
async function main() {
|
|
9
10
|
const repoRoot = process.env.BELAY_EGRESS_REPO_ROOT;
|
|
@@ -30,9 +31,24 @@ async function main() {
|
|
|
30
31
|
},
|
|
31
32
|
async onAudit(event) {
|
|
32
33
|
await mkdir(path.dirname(auditPath), { recursive: true });
|
|
33
|
-
const
|
|
34
|
-
const
|
|
35
|
-
|
|
34
|
+
const cohort = await resolveActiveAuditCohort(repoRoot, config);
|
|
35
|
+
const record = {
|
|
36
|
+
timestamp: new Date().toISOString(),
|
|
37
|
+
...(cohort
|
|
38
|
+
? {
|
|
39
|
+
runtimeBuildStamp: cohort.runtimeBuildStamp,
|
|
40
|
+
...(cohort.runtimeArtifactHash
|
|
41
|
+
? { runtimeArtifactHash: cohort.runtimeArtifactHash }
|
|
42
|
+
: {}),
|
|
43
|
+
decisionConfigFingerprint: cohort.decisionConfigFingerprint,
|
|
44
|
+
boundaryProfile: cohort.boundaryProfile,
|
|
45
|
+
configFingerprint: cohort.configFingerprint,
|
|
46
|
+
}
|
|
47
|
+
: {}),
|
|
48
|
+
...event,
|
|
49
|
+
};
|
|
50
|
+
const serialized = serializeAuditRecordV3(record, scrubOptionsFromConfig(config));
|
|
51
|
+
await writeFile(auditPath, `${JSON.stringify(serialized)}\n`, { encoding: 'utf8', flag: 'a' });
|
|
36
52
|
},
|
|
37
53
|
});
|
|
38
54
|
await writeEgressDaemonState({ stateDir, pid: process.pid, host, port, repoRoot });
|
package/dist/installer.js
CHANGED
|
@@ -8,6 +8,7 @@ import { getAdapter } from './adapters/registry.js';
|
|
|
8
8
|
import { dogfoodProject } from './commands/dogfood.js';
|
|
9
9
|
import { detectAdapterName, loadConfigFile, mergeAndWriteConfig, writeConfigFile, } from './config-io.js';
|
|
10
10
|
import { appendCliAuditEvent } from './core/audit-io.js';
|
|
11
|
+
import { archiveLegacyAuditLogIfNeeded } from './core/audit-legacy-archive.js';
|
|
11
12
|
import { isFreshConfigInput, mergeConfig, normalizeConfig, } from './core/config.js';
|
|
12
13
|
import { runtimeIntegrityFiles, writeIntegrityManifest } from './core/integrity.js';
|
|
13
14
|
import { hasValidCloudConsent, isCloudJudgeConfig, migrateImplicitLocalJudgeIfNeeded, resolveInitJudgeConfig, } from './core/judge-config.js';
|
|
@@ -72,6 +73,7 @@ export async function initCursorProject(options = {}) {
|
|
|
72
73
|
await mkdir(path.dirname(paths.hooksSettingsPath), { recursive: true });
|
|
73
74
|
await writeFile(paths.hooksSettingsPath, `${JSON.stringify(mergedHooks, null, 2)}\n`, 'utf8');
|
|
74
75
|
await writeIntegrityManifest(repoRoot, cursorLayout, runtimeIntegrityFiles(cursorLayout, paths));
|
|
76
|
+
await archiveLegacyAuditLogIfNeeded(repoRoot, config);
|
|
75
77
|
return { repoRoot, withSkill };
|
|
76
78
|
}
|
|
77
79
|
export async function upgradeCursorProject(options = {}) {
|
|
@@ -89,6 +91,7 @@ export async function upgradeCursorProject(options = {}) {
|
|
|
89
91
|
await writeSkillArtifacts('cursor', paths);
|
|
90
92
|
}
|
|
91
93
|
await writeIntegrityManifest(repoRoot, cursorLayout, runtimeIntegrityFiles(cursorLayout, paths));
|
|
94
|
+
await archiveLegacyAuditLogIfNeeded(repoRoot, config);
|
|
92
95
|
return { repoRoot };
|
|
93
96
|
}
|
|
94
97
|
function resolveAdapterName(options, repoRoot) {
|
|
@@ -3,6 +3,16 @@ import type { BelayConfigV3 } from './core/config.js';
|
|
|
3
3
|
export interface InstalledRuntimeProvenance {
|
|
4
4
|
stamp?: string;
|
|
5
5
|
version?: string;
|
|
6
|
+
artifactHash?: string;
|
|
6
7
|
}
|
|
8
|
+
export interface RuntimeBuildProvenanceInput {
|
|
9
|
+
runtimeVersion?: unknown;
|
|
10
|
+
runtimeBuildStamp?: unknown;
|
|
11
|
+
runtimeArtifactHash?: unknown;
|
|
12
|
+
}
|
|
13
|
+
export { hashDecisionConfig } from './core/decision-config-fingerprint.js';
|
|
14
|
+
export declare function resolveRuntimeArtifactHash(artifactHash?: string): string | undefined;
|
|
15
|
+
export declare function buildAuditProvenanceFields(config: BelayConfigV3, runtime?: RuntimeBuildProvenanceInput): Record<string, string>;
|
|
16
|
+
export declare function matchesAuditCohort(record: Record<string, unknown>, cohort: AuditCohortIdentity): boolean;
|
|
7
17
|
export declare function readInstalledRuntimeProvenance(corePath: string): Promise<InstalledRuntimeProvenance>;
|
|
8
18
|
export declare function resolveActiveAuditCohort(repoRoot: string, config: BelayConfigV3): Promise<AuditCohortIdentity | null>;
|
|
@@ -3,15 +3,72 @@ import path from 'node:path';
|
|
|
3
3
|
import { getAdapterLayout } from './adapters/layouts/index.js';
|
|
4
4
|
import { resolveScopedPaths } from './adapters/layouts/scope.js';
|
|
5
5
|
import { resolveAdapterName } from './config-io.js';
|
|
6
|
+
import { isValidAuditFingerprint } from './core/audit-serialize.js';
|
|
7
|
+
import { resolveBoundaryProfile } from './core/capability/boundary-profile.js';
|
|
8
|
+
import { hashDecisionConfig } from './core/decision-config-fingerprint.js';
|
|
6
9
|
import { canonicalStringify, hashValue } from './core/fingerprint.js';
|
|
10
|
+
import { PACKAGE_VERSION } from './version.js';
|
|
11
|
+
export { hashDecisionConfig } from './core/decision-config-fingerprint.js';
|
|
12
|
+
export function resolveRuntimeArtifactHash(artifactHash) {
|
|
13
|
+
if (typeof artifactHash === 'string' && isValidAuditFingerprint(artifactHash)) {
|
|
14
|
+
return artifactHash;
|
|
15
|
+
}
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
export function buildAuditProvenanceFields(config, runtime) {
|
|
19
|
+
const runtimeVersion = typeof runtime?.runtimeVersion === 'string' ? runtime.runtimeVersion : PACKAGE_VERSION;
|
|
20
|
+
const runtimeBuildStamp = typeof runtime?.runtimeBuildStamp === 'string'
|
|
21
|
+
? runtime.runtimeBuildStamp
|
|
22
|
+
: `${PACKAGE_VERSION}@source`;
|
|
23
|
+
const fields = {
|
|
24
|
+
runtimeVersion,
|
|
25
|
+
runtimeBuildStamp,
|
|
26
|
+
decisionConfigFingerprint: hashDecisionConfig(config),
|
|
27
|
+
boundaryProfile: resolveBoundaryProfile({ config }),
|
|
28
|
+
configFingerprint: hashValue(canonicalStringify(config)),
|
|
29
|
+
};
|
|
30
|
+
const runtimeArtifactHash = resolveRuntimeArtifactHash(typeof runtime?.runtimeArtifactHash === 'string' ? runtime.runtimeArtifactHash : undefined);
|
|
31
|
+
if (runtimeArtifactHash) {
|
|
32
|
+
fields.runtimeArtifactHash = runtimeArtifactHash;
|
|
33
|
+
}
|
|
34
|
+
return fields;
|
|
35
|
+
}
|
|
36
|
+
export function matchesAuditCohort(record, cohort) {
|
|
37
|
+
const artifactHash = typeof record.runtimeArtifactHash === 'string' ? record.runtimeArtifactHash : undefined;
|
|
38
|
+
const decisionFingerprint = typeof record.decisionConfigFingerprint === 'string'
|
|
39
|
+
? record.decisionConfigFingerprint
|
|
40
|
+
: undefined;
|
|
41
|
+
const boundaryProfile = typeof record.boundaryProfile === 'string' ? record.boundaryProfile : undefined;
|
|
42
|
+
const hasPartialV3Field = artifactHash !== undefined || decisionFingerprint !== undefined || boundaryProfile !== undefined;
|
|
43
|
+
if (hasPartialV3Field) {
|
|
44
|
+
if (!artifactHash ||
|
|
45
|
+
!decisionFingerprint ||
|
|
46
|
+
!boundaryProfile ||
|
|
47
|
+
!isValidAuditFingerprint(artifactHash)) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
if (artifactHash !== cohort.runtimeArtifactHash ||
|
|
51
|
+
decisionFingerprint !== cohort.decisionConfigFingerprint) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
if (boundaryProfile !== cohort.boundaryProfile) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
return (record.runtimeBuildStamp === cohort.runtimeBuildStamp &&
|
|
60
|
+
record.configFingerprint === cohort.configFingerprint);
|
|
61
|
+
}
|
|
7
62
|
export async function readInstalledRuntimeProvenance(corePath) {
|
|
8
63
|
try {
|
|
9
64
|
const content = await readFile(corePath, 'utf8');
|
|
10
65
|
const stampMatch = content.match(/RUNTIME_BUILD_STAMP\s*=\s*"([^"]+)"/);
|
|
11
66
|
const versionMatch = content.match(/RUNTIME_PACKAGE_VERSION\s*=\s*"([^"]+)"/);
|
|
67
|
+
const artifactMatch = content.match(/RUNTIME_ARTIFACT_HASH\s*=\s*"([^"]+)"/);
|
|
12
68
|
return {
|
|
13
69
|
stamp: stampMatch?.[1],
|
|
14
70
|
version: versionMatch?.[1],
|
|
71
|
+
artifactHash: artifactMatch?.[1],
|
|
15
72
|
};
|
|
16
73
|
}
|
|
17
74
|
catch {
|
|
@@ -27,7 +84,13 @@ export async function resolveActiveAuditCohort(repoRoot, config) {
|
|
|
27
84
|
if (!runtime.stamp) {
|
|
28
85
|
return null;
|
|
29
86
|
}
|
|
87
|
+
const boundaryProfile = resolveBoundaryProfile({ config });
|
|
88
|
+
const decisionConfigFingerprint = hashDecisionConfig(config);
|
|
89
|
+
const runtimeArtifactHash = resolveRuntimeArtifactHash(runtime.artifactHash) ?? '';
|
|
30
90
|
return {
|
|
91
|
+
runtimeArtifactHash,
|
|
92
|
+
decisionConfigFingerprint,
|
|
93
|
+
boundaryProfile,
|
|
31
94
|
runtimeBuildStamp: runtime.stamp,
|
|
32
95
|
configFingerprint: hashValue(canonicalStringify(config)),
|
|
33
96
|
};
|
package/dist/templates.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { hashValue } from './core/fingerprint.js';
|
|
4
5
|
import { PACKAGE_VERSION } from './version.js';
|
|
5
6
|
function inlineJson(value) {
|
|
6
7
|
return JSON.stringify(value, null, 2);
|
|
@@ -45,17 +46,21 @@ async function readRuntimeBundle(adapter = 'cursor') {
|
|
|
45
46
|
}
|
|
46
47
|
export async function renderRuntimeCore(adapter = 'cursor') {
|
|
47
48
|
const bundle = await readRuntimeBundle(adapter);
|
|
48
|
-
const
|
|
49
|
+
const withoutStamp = bundle
|
|
50
|
+
.replace(/^export const RUNTIME_BUILD_STAMP = .*;\n/gm, '')
|
|
51
|
+
.replace(/^export const RUNTIME_PACKAGE_VERSION = .*;\n/gm, '')
|
|
52
|
+
.replace(/^export const RUNTIME_ARTIFACT_HASH = .*;\n/gm, '')
|
|
53
|
+
.replace(/^var RUNTIME_PACKAGE_VERSION = .*;\n/gm, '')
|
|
54
|
+
.replace(/\n {2}RUNTIME_PACKAGE_VERSION,\n/, '\n');
|
|
55
|
+
const runtimeArtifactHash = hashValue(withoutStamp);
|
|
56
|
+
const runtimeBuildStamp = `${PACKAGE_VERSION}@${runtimeArtifactHash.slice(0, 16)}`;
|
|
49
57
|
const stamp = `export const RUNTIME_BUILD_STAMP = ${JSON.stringify(runtimeBuildStamp)};\n`;
|
|
58
|
+
const artifactHashLine = `export const RUNTIME_ARTIFACT_HASH = ${JSON.stringify(runtimeArtifactHash)};\n`;
|
|
50
59
|
const versionLine = `export const RUNTIME_PACKAGE_VERSION = ${JSON.stringify(PACKAGE_VERSION)};\n`;
|
|
51
60
|
const provenance = `globalThis[Symbol.for("agent-belay.runtime-provenance")] = ${JSON.stringify({
|
|
52
61
|
runtimeVersion: PACKAGE_VERSION,
|
|
53
62
|
runtimeBuildStamp,
|
|
63
|
+
runtimeArtifactHash,
|
|
54
64
|
})};\n`;
|
|
55
|
-
|
|
56
|
-
.replace(/^export const RUNTIME_BUILD_STAMP = .*;\n/gm, '')
|
|
57
|
-
.replace(/^export const RUNTIME_PACKAGE_VERSION = .*;\n/gm, '')
|
|
58
|
-
.replace(/^var RUNTIME_PACKAGE_VERSION = .*;\n/gm, '')
|
|
59
|
-
.replace(/\n {2}RUNTIME_PACKAGE_VERSION,\n/, '\n');
|
|
60
|
-
return `${versionLine}${stamp}${provenance}${withoutStamp}`;
|
|
65
|
+
return `${versionLine}${artifactHashLine}${stamp}${provenance}${withoutStamp}`;
|
|
61
66
|
}
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const PACKAGE_VERSION = "0.9.
|
|
1
|
+
export declare const PACKAGE_VERSION = "0.9.2";
|
package/dist/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Generated by scripts/sync-version.mjs — do not edit.
|
|
2
|
-
export const PACKAGE_VERSION = '0.9.
|
|
2
|
+
export const PACKAGE_VERSION = '0.9.2';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@guilz-dev/belay",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.2",
|
|
4
4
|
"description": "Belay-style approval and audit gating for agent runtimes.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -57,6 +57,7 @@
|
|
|
57
57
|
"typecheck": "tsc --noEmit",
|
|
58
58
|
"test": "pnpm build && vitest run",
|
|
59
59
|
"test:structural": "pnpm build && vitest run src/__tests__/verdict/structural-suite.test.ts",
|
|
60
|
+
"test:docker": "pnpm build && vitest run src/__tests__/capability/boundary-container-isolation.test.ts src/__tests__/capability/boundary-driver-container.test.ts",
|
|
60
61
|
"test:stable": "pnpm build && vitest run && vitest run && vitest run",
|
|
61
62
|
"corpus": "pnpm build && node scripts/corpus.mjs",
|
|
62
63
|
"probe:adversarial": "pnpm build && node scripts/adversarial-probe.mjs",
|