@victframework/runtime 0.1.0
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/dist/agent-governance.d.ts +285 -0
- package/dist/agent-governance.js +438 -0
- package/dist/agent-governance.js.map +1 -0
- package/dist/agent-registry.d.ts +103 -0
- package/dist/agent-registry.js +758 -0
- package/dist/agent-registry.js.map +1 -0
- package/dist/agent-types.d.ts +433 -0
- package/dist/agent-types.js +480 -0
- package/dist/agent-types.js.map +1 -0
- package/dist/authority.d.ts +83 -0
- package/dist/authority.js +170 -0
- package/dist/authority.js.map +1 -0
- package/dist/boundary-conformance.d.ts +51 -0
- package/dist/boundary-conformance.js +364 -0
- package/dist/boundary-conformance.js.map +1 -0
- package/dist/control-conformance.d.ts +68 -0
- package/dist/control-conformance.js +1131 -0
- package/dist/control-conformance.js.map +1 -0
- package/dist/control-in-memory.d.ts +257 -0
- package/dist/control-in-memory.js +886 -0
- package/dist/control-in-memory.js.map +1 -0
- package/dist/control-types.d.ts +1017 -0
- package/dist/control-types.js +779 -0
- package/dist/control-types.js.map +1 -0
- package/dist/durable-run.d.ts +73 -0
- package/dist/durable-run.js +262 -0
- package/dist/durable-run.js.map +1 -0
- package/dist/effect-policy.d.ts +22 -0
- package/dist/effect-policy.js +45 -0
- package/dist/effect-policy.js.map +1 -0
- package/dist/errors.d.ts +36 -0
- package/dist/errors.js +71 -0
- package/dist/errors.js.map +1 -0
- package/dist/in-memory-stores.d.ts +16 -0
- package/dist/in-memory-stores.js +522 -0
- package/dist/in-memory-stores.js.map +1 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/operator-config.d.ts +141 -0
- package/dist/operator-config.js +289 -0
- package/dist/operator-config.js.map +1 -0
- package/dist/orchestration-activation.d.ts +116 -0
- package/dist/orchestration-activation.js +223 -0
- package/dist/orchestration-activation.js.map +1 -0
- package/dist/orchestration-canary-conformance.d.ts +10 -0
- package/dist/orchestration-canary-conformance.js +726 -0
- package/dist/orchestration-canary-conformance.js.map +1 -0
- package/dist/orchestration-commands.d.ts +47 -0
- package/dist/orchestration-commands.js +538 -0
- package/dist/orchestration-commands.js.map +1 -0
- package/dist/orchestration-conformance.d.ts +59 -0
- package/dist/orchestration-conformance.js +594 -0
- package/dist/orchestration-conformance.js.map +1 -0
- package/dist/orchestration-driver-types.d.ts +163 -0
- package/dist/orchestration-driver-types.js +21 -0
- package/dist/orchestration-driver-types.js.map +1 -0
- package/dist/orchestration-driver.d.ts +48 -0
- package/dist/orchestration-driver.js +1030 -0
- package/dist/orchestration-driver.js.map +1 -0
- package/dist/orchestration-in-memory.d.ts +18 -0
- package/dist/orchestration-in-memory.js +1313 -0
- package/dist/orchestration-in-memory.js.map +1 -0
- package/dist/orchestration-join-conformance.d.ts +20 -0
- package/dist/orchestration-join-conformance.js +542 -0
- package/dist/orchestration-join-conformance.js.map +1 -0
- package/dist/orchestration-plan.d.ts +52 -0
- package/dist/orchestration-plan.js +265 -0
- package/dist/orchestration-plan.js.map +1 -0
- package/dist/orchestration-race-conformance.d.ts +35 -0
- package/dist/orchestration-race-conformance.js +1265 -0
- package/dist/orchestration-race-conformance.js.map +1 -0
- package/dist/orchestration-remediation-conformance.d.ts +54 -0
- package/dist/orchestration-remediation-conformance.js +632 -0
- package/dist/orchestration-remediation-conformance.js.map +1 -0
- package/dist/orchestration-store-types.d.ts +568 -0
- package/dist/orchestration-store-types.js +2 -0
- package/dist/orchestration-store-types.js.map +1 -0
- package/dist/pack-conformance.d.ts +59 -0
- package/dist/pack-conformance.js +222 -0
- package/dist/pack-conformance.js.map +1 -0
- package/dist/pack-install.d.ts +44 -0
- package/dist/pack-install.js +126 -0
- package/dist/pack-install.js.map +1 -0
- package/dist/registry.d.ts +107 -0
- package/dist/registry.js +481 -0
- package/dist/registry.js.map +1 -0
- package/dist/runtime.d.ts +158 -0
- package/dist/runtime.js +1341 -0
- package/dist/runtime.js.map +1 -0
- package/dist/serialization.d.ts +26 -0
- package/dist/serialization.js +162 -0
- package/dist/serialization.js.map +1 -0
- package/dist/store-conformance.d.ts +45 -0
- package/dist/store-conformance.js +876 -0
- package/dist/store-conformance.js.map +1 -0
- package/dist/store-errors.d.ts +49 -0
- package/dist/store-errors.js +48 -0
- package/dist/store-errors.js.map +1 -0
- package/dist/store-types.d.ts +331 -0
- package/dist/store-types.js +14 -0
- package/dist/store-types.js.map +1 -0
- package/dist/store-validation.d.ts +63 -0
- package/dist/store-validation.js +164 -0
- package/dist/store-validation.js.map +1 -0
- package/dist/stream-hub.d.ts +151 -0
- package/dist/stream-hub.js +402 -0
- package/dist/stream-hub.js.map +1 -0
- package/dist/testing.d.ts +25 -0
- package/dist/testing.js +19 -0
- package/dist/testing.js.map +1 -0
- package/dist/types.d.ts +221 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +45 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { CapabilityPack } from '@victframework/sdk';
|
|
2
|
+
/**
|
|
3
|
+
* Shared capability-pack conformance suite (Stage 04).
|
|
4
|
+
*
|
|
5
|
+
* Any capability pack must pass the SAME suite. The suite creates a fresh
|
|
6
|
+
* runtime per scenario so runtimes and store adapters (in-memory, SQLite,
|
|
7
|
+
* future adapters) exercise identical pack semantics. Proven per pack:
|
|
8
|
+
*
|
|
9
|
+
* 1. install + a full contract-validated run of the pure capability;
|
|
10
|
+
* 2. manifest/binding mismatches and compatibility mismatch fail closed;
|
|
11
|
+
* 3. unknown fields fail closed;
|
|
12
|
+
* 4. original-object mutation after capture has no effect;
|
|
13
|
+
* 5. the declared double runs INSTEAD of the real write (test mode);
|
|
14
|
+
* 6. the real write runs exactly once in normal mode;
|
|
15
|
+
* 7. missing required grants fail BEFORE handler invocation;
|
|
16
|
+
* 8. resolved secret values never enter manifests, events, or history.
|
|
17
|
+
*/
|
|
18
|
+
export interface CapabilityPackConformanceFixture {
|
|
19
|
+
readonly name: string;
|
|
20
|
+
/** The pack under test (the deep-frozen capture from defineCapabilityPack). */
|
|
21
|
+
readonly pack: CapabilityPack;
|
|
22
|
+
/**
|
|
23
|
+
* The id of the pack's PURE/READ capability (no permissions, no required
|
|
24
|
+
* configuration/secrets) used for the end-to-end run scenario.
|
|
25
|
+
*/
|
|
26
|
+
readonly pureCapabilityId: string;
|
|
27
|
+
/** Contract-validated input for the pure capability scenario. */
|
|
28
|
+
readonly pureInput: unknown;
|
|
29
|
+
/** The exact expected validated output of the pure capability scenario. */
|
|
30
|
+
readonly pureExpectedOutput: unknown;
|
|
31
|
+
/**
|
|
32
|
+
* The id of the pack's WRITE capability, which must declare a matching
|
|
33
|
+
* double in the pack manifest (simulation policy) and may declare
|
|
34
|
+
* permissions/secrets.
|
|
35
|
+
*/
|
|
36
|
+
readonly writeCapabilityId?: string;
|
|
37
|
+
/** Input for the write scenario (crosses the write capability's contract). */
|
|
38
|
+
readonly writeInput?: unknown;
|
|
39
|
+
/** The double's expected validated output in test/simulation mode. */
|
|
40
|
+
readonly writeDoubleOutput?: unknown;
|
|
41
|
+
/** Probe for the REAL write handler's invocation count (pack-owned counter). */
|
|
42
|
+
readonly writeInvocationCount?: () => number;
|
|
43
|
+
/**
|
|
44
|
+
* Canary that may exist ONLY inside the runtime authority surface handed
|
|
45
|
+
* to handlers — never in the manifest, events, results, or history.
|
|
46
|
+
*/
|
|
47
|
+
readonly secretCanary?: string;
|
|
48
|
+
}
|
|
49
|
+
/** Runtime-level authority profile the suite installs the fixture runtime with. */
|
|
50
|
+
export interface CapabilityPackConformanceOptions {
|
|
51
|
+
readonly grants?: readonly string[];
|
|
52
|
+
readonly configuration?: Readonly<Record<string, unknown>>;
|
|
53
|
+
readonly secrets?: Readonly<Record<string, string>>;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Run the shared capability-pack conformance suite against one fixture.
|
|
57
|
+
* Throws on the first failed invariant (like the other shared suites).
|
|
58
|
+
*/
|
|
59
|
+
export declare function runCapabilityPackConformanceSuite(fixture: CapabilityPackConformanceFixture, options?: CapabilityPackConformanceOptions): Promise<void>;
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { defineGraph } from '@victframework/sdk';
|
|
2
|
+
import { createInMemoryStores, createRuntime } from './index.js';
|
|
3
|
+
import { installCapabilityPack } from './pack-install.js';
|
|
4
|
+
import { VictRuntimeError } from './errors.js';
|
|
5
|
+
function fail(message) {
|
|
6
|
+
throw new Error(`[pack conformance: ${message}]`);
|
|
7
|
+
}
|
|
8
|
+
function buildRuntime(options) {
|
|
9
|
+
const hasAuthority = options.grants !== undefined ||
|
|
10
|
+
options.configuration !== undefined ||
|
|
11
|
+
options.secrets !== undefined;
|
|
12
|
+
return createRuntime({
|
|
13
|
+
stores: createInMemoryStores(),
|
|
14
|
+
...(hasAuthority
|
|
15
|
+
? {
|
|
16
|
+
authority: {
|
|
17
|
+
...(options.grants !== undefined ? { grants: options.grants } : {}),
|
|
18
|
+
...(options.configuration !== undefined
|
|
19
|
+
? { configuration: { get: (name) => options.configuration?.[name] } }
|
|
20
|
+
: {}),
|
|
21
|
+
...(options.secrets !== undefined
|
|
22
|
+
? { secrets: { get: async (name) => options.secrets?.[name] } }
|
|
23
|
+
: {}),
|
|
24
|
+
},
|
|
25
|
+
}
|
|
26
|
+
: {}),
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Run the shared capability-pack conformance suite against one fixture.
|
|
31
|
+
* Throws on the first failed invariant (like the other shared suites).
|
|
32
|
+
*/
|
|
33
|
+
export async function runCapabilityPackConformanceSuite(fixture, options = {}) {
|
|
34
|
+
const pack = fixture.pack;
|
|
35
|
+
// ---- 1. End-to-end: install, activate, run, contract-validated output.
|
|
36
|
+
const runtime = buildRuntime(options);
|
|
37
|
+
installCapabilityPack(runtime, pack);
|
|
38
|
+
const activation = await runtime.activate(defineGraph({
|
|
39
|
+
id: `conformance.${fixture.pureCapabilityId}`,
|
|
40
|
+
entry: 'only',
|
|
41
|
+
nodes: [{ id: 'only', capability: fixture.pureCapabilityId }],
|
|
42
|
+
edges: [],
|
|
43
|
+
}));
|
|
44
|
+
if (!activation.ok) {
|
|
45
|
+
fail(`activation failed: ${JSON.stringify(activation.issues)}`);
|
|
46
|
+
}
|
|
47
|
+
const events = [];
|
|
48
|
+
const result = await runtime.run(fixture.pureInput, {
|
|
49
|
+
mode: 'normal',
|
|
50
|
+
onEvent: (event) => events.push(event),
|
|
51
|
+
});
|
|
52
|
+
if (result.status !== 'completed') {
|
|
53
|
+
fail(`pure run did not complete: ${result.status}`);
|
|
54
|
+
}
|
|
55
|
+
if (JSON.stringify(result.output) !== JSON.stringify(fixture.pureExpectedOutput)) {
|
|
56
|
+
fail(`pure output mismatch: ${JSON.stringify(result.output)}`);
|
|
57
|
+
}
|
|
58
|
+
// ---- 8. Resolved secrets never enter manifests, events, results, history.
|
|
59
|
+
if (fixture.secretCanary !== undefined) {
|
|
60
|
+
if (JSON.stringify(pack.manifest).includes(fixture.secretCanary)) {
|
|
61
|
+
fail('the resolved secret canary leaked into the manifest');
|
|
62
|
+
}
|
|
63
|
+
if (JSON.stringify(events).includes(fixture.secretCanary)) {
|
|
64
|
+
fail('the resolved secret canary leaked into run events');
|
|
65
|
+
}
|
|
66
|
+
if (JSON.stringify(result.output).includes(fixture.secretCanary)) {
|
|
67
|
+
fail('the resolved secret canary leaked into the run result');
|
|
68
|
+
}
|
|
69
|
+
const history = await runtime.listRuns();
|
|
70
|
+
if (JSON.stringify(history).includes(fixture.secretCanary)) {
|
|
71
|
+
fail('the resolved secret canary leaked into default run history');
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// ---- 2. Manifest/binding mismatch fails closed.
|
|
75
|
+
try {
|
|
76
|
+
installCapabilityPack(createRuntime(), {
|
|
77
|
+
manifest: pack.manifest,
|
|
78
|
+
bindings: {
|
|
79
|
+
capabilities: pack.bindings.capabilities.map((binding) => binding.id === fixture.pureCapabilityId ? { ...binding, revision: '999' } : binding),
|
|
80
|
+
doubles: pack.bindings.doubles,
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
fail('a revision-mismatched binding was accepted');
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
if (!(error instanceof VictRuntimeError) || error.code !== 'VICT_PACK_INVALID') {
|
|
87
|
+
fail(`mismatch rejection threw the wrong error: ${String(error)}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// ---- 2b. Compatibility mismatch fails closed.
|
|
91
|
+
try {
|
|
92
|
+
installCapabilityPack(createRuntime(), {
|
|
93
|
+
manifest: { ...pack.manifest, victCompatibility: '>=9.0.0' },
|
|
94
|
+
bindings: pack.bindings,
|
|
95
|
+
});
|
|
96
|
+
fail('an incompatible pack was accepted');
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
if (!(error instanceof VictRuntimeError) || error.code !== 'VICT_PACK_INVALID') {
|
|
100
|
+
fail(`compatibility rejection threw the wrong error: ${String(error)}`);
|
|
101
|
+
}
|
|
102
|
+
if (!JSON.stringify(error.details).includes('PACK_COMPATIBILITY_UNMET')) {
|
|
103
|
+
fail('compatibility rejection lost its structured issue');
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// ---- 3. Unknown fields fail closed.
|
|
107
|
+
try {
|
|
108
|
+
installCapabilityPack(createRuntime(), {
|
|
109
|
+
manifest: { ...pack.manifest, manifestExtra: true },
|
|
110
|
+
bindings: pack.bindings,
|
|
111
|
+
});
|
|
112
|
+
fail('an unknown manifest field was accepted');
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
if (!(error instanceof VictRuntimeError) || error.code !== 'VICT_PACK_INVALID') {
|
|
116
|
+
fail(`unknown-field rejection threw the wrong error: ${String(error)}`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// ---- 4. Mutation of the ORIGINAL manifest has no effect after capture.
|
|
120
|
+
const mutableManifest = JSON.parse(JSON.stringify(pack.manifest));
|
|
121
|
+
const mutableCapabilities = mutableManifest.capabilities;
|
|
122
|
+
const entry = mutableCapabilities.find((candidate) => candidate.id === fixture.pureCapabilityId);
|
|
123
|
+
if (entry !== undefined) {
|
|
124
|
+
const captured = pack.manifest.capabilities.find((candidate) => candidate.id === fixture.pureCapabilityId);
|
|
125
|
+
entry.revision = 'hijacked';
|
|
126
|
+
if (captured?.revision === 'hijacked') {
|
|
127
|
+
fail('manifest capture is not isolated from the original object');
|
|
128
|
+
}
|
|
129
|
+
if (Object.isFrozen(mutableManifest)) {
|
|
130
|
+
// Mutating a frozen object silently fails in sloppy mode but throws
|
|
131
|
+
// in strict mode; either way the captured pack must be unchanged.
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
// ---- 5-7. Write scenarios when the fixture declares a write capability.
|
|
135
|
+
if (fixture.writeCapabilityId !== undefined &&
|
|
136
|
+
fixture.writeInput !== undefined &&
|
|
137
|
+
fixture.writeDoubleOutput !== undefined) {
|
|
138
|
+
const realCount = () => fixture.writeInvocationCount?.() ?? 0;
|
|
139
|
+
const writeDeclaration = pack.manifest.capabilities.find((candidate) => candidate.id === fixture.writeCapabilityId);
|
|
140
|
+
if (writeDeclaration === undefined) {
|
|
141
|
+
fail('write fixture declares an unknown capability');
|
|
142
|
+
}
|
|
143
|
+
// 5. Simulation (test mode) runs the PACK'S DECLARED double, never the
|
|
144
|
+
// real write (MED-04-B remediation): no manual registerDouble call is
|
|
145
|
+
// made anywhere in this suite — the double installed atomically by
|
|
146
|
+
// installCapabilityPack is the only substitute available.
|
|
147
|
+
const simulated = buildRuntime(options);
|
|
148
|
+
installCapabilityPack(simulated, pack);
|
|
149
|
+
await simulated.activate(defineGraph({
|
|
150
|
+
id: `conformance.${fixture.writeCapabilityId}.sim`,
|
|
151
|
+
entry: 'only',
|
|
152
|
+
nodes: [{ id: 'only', capability: fixture.writeCapabilityId }],
|
|
153
|
+
edges: [],
|
|
154
|
+
}));
|
|
155
|
+
const beforeSim = realCount();
|
|
156
|
+
const simResult = await simulated.run(fixture.writeInput, { mode: 'test' });
|
|
157
|
+
if (simResult.status !== 'completed') {
|
|
158
|
+
fail(`simulated write did not complete: ${simResult.status}`);
|
|
159
|
+
}
|
|
160
|
+
if (JSON.stringify(simResult.output) !== JSON.stringify(fixture.writeDoubleOutput)) {
|
|
161
|
+
fail(`double output mismatch: ${JSON.stringify(simResult.output)}`);
|
|
162
|
+
}
|
|
163
|
+
if (realCount() !== beforeSim) {
|
|
164
|
+
fail('the real write handler ran during simulation');
|
|
165
|
+
}
|
|
166
|
+
// 5b. Negative control: a runtime WITHOUT the pack's declared double
|
|
167
|
+
// (never manually registered) must block in test mode — proving the
|
|
168
|
+
// declared double (not a manual substitute) served the run above.
|
|
169
|
+
{
|
|
170
|
+
const bare = buildRuntime(options);
|
|
171
|
+
installCapabilityPack(bare, pack);
|
|
172
|
+
const bareDouble = bare.hasDouble(fixture.writeCapabilityId);
|
|
173
|
+
if (!bareDouble) {
|
|
174
|
+
fail('installCapabilityPack did not install the pack-declared double');
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// 6. Normal mode runs the real handler exactly once (when granted).
|
|
178
|
+
const requiredPermissions = writeDeclaration.permissions ?? [];
|
|
179
|
+
const granted = requiredPermissions.every((permissionId) => (options.grants ?? []).includes(permissionId));
|
|
180
|
+
if (granted) {
|
|
181
|
+
const real = buildRuntime(options);
|
|
182
|
+
installCapabilityPack(real, pack);
|
|
183
|
+
await real.activate(defineGraph({
|
|
184
|
+
id: `conformance.${fixture.writeCapabilityId}.real`,
|
|
185
|
+
entry: 'only',
|
|
186
|
+
nodes: [{ id: 'only', capability: fixture.writeCapabilityId }],
|
|
187
|
+
edges: [],
|
|
188
|
+
}));
|
|
189
|
+
const beforeReal = realCount();
|
|
190
|
+
const realResult = await real.run(fixture.writeInput, { mode: 'normal' });
|
|
191
|
+
if (realResult.status !== 'completed') {
|
|
192
|
+
fail(`real write did not complete: ${realResult.status}`);
|
|
193
|
+
}
|
|
194
|
+
if (realCount() - beforeReal !== 1) {
|
|
195
|
+
fail(`real write invocation delta is ${realCount() - beforeReal}`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
// 7. Missing required grants fail BEFORE handler invocation.
|
|
199
|
+
if (requiredPermissions.length > 0) {
|
|
200
|
+
const ungranted = createRuntime({ stores: createInMemoryStores() });
|
|
201
|
+
installCapabilityPack(ungranted, pack);
|
|
202
|
+
await ungranted.activate(defineGraph({
|
|
203
|
+
id: `conformance.${fixture.writeCapabilityId}.ungranted`,
|
|
204
|
+
entry: 'only',
|
|
205
|
+
nodes: [{ id: 'only', capability: fixture.writeCapabilityId }],
|
|
206
|
+
edges: [],
|
|
207
|
+
}));
|
|
208
|
+
const beforeUngranted = realCount();
|
|
209
|
+
const denied = await ungranted.run(fixture.writeInput, { mode: 'normal' });
|
|
210
|
+
if (denied.status !== 'failed') {
|
|
211
|
+
fail(`ungranted write did not fail: ${denied.status}`);
|
|
212
|
+
}
|
|
213
|
+
if (denied.error?.code !== 'VICT_RUNTIME_PERMISSION_DENIED') {
|
|
214
|
+
fail(`ungranted write failed with the wrong code: ${String(denied.error?.code)}`);
|
|
215
|
+
}
|
|
216
|
+
if (realCount() !== beforeUngranted) {
|
|
217
|
+
fail('the real write handler ran without a required grant');
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
//# sourceMappingURL=pack-conformance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pack-conformance.js","sourceRoot":"","sources":["../src/pack-conformance.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { CapabilityPack } from '@victframework/sdk';
|
|
2
|
+
import type { VictRuntime } from './runtime.js';
|
|
3
|
+
/**
|
|
4
|
+
* Stage 04: explicit, LOCAL capability-pack installation.
|
|
5
|
+
*
|
|
6
|
+
* Loading a pack is a deliberate act: the manifest is cross-validated
|
|
7
|
+
* against the executable bindings (missing, duplicate, extra, or
|
|
8
|
+
* revision-mismatched bindings fail deterministically), the declared
|
|
9
|
+
* Vict compatibility is checked against the consuming runtime's version,
|
|
10
|
+
* and only then are contracts, capabilities, and declared doubles
|
|
11
|
+
* registered ATOMICALLY.
|
|
12
|
+
*
|
|
13
|
+
* Audit remediation (HIGH-04-A): installation is a registry-level STAGED
|
|
14
|
+
* BATCH. Every contract, capability, and declared double is validated and
|
|
15
|
+
* preflighted (including collisions against the live registry and inside
|
|
16
|
+
* the batch) BEFORE any live map is touched; the complete batch commits
|
|
17
|
+
* only when every step succeeds. A failed installation leaves the registry
|
|
18
|
+
* byte-for-byte semantically unchanged: no capability, contract, or double
|
|
19
|
+
* from the attempted pack is resolvable afterwards. There is no best-effort
|
|
20
|
+
* rollback of partially registered entries because nothing is registered
|
|
21
|
+
* until success is certain.
|
|
22
|
+
*
|
|
23
|
+
* Audit remediation (MED-04-B): the pack's declared doubles
|
|
24
|
+
* (`manifest.doubles` + `bindings.doubles`) are installed atomically WITH
|
|
25
|
+
* the pack. A pack-declared double is eligible ONLY in the modes its
|
|
26
|
+
* manifest declares (`modes: ['test','simulate']`); it never runs in
|
|
27
|
+
* normal mode. No manual `runtime.registerDouble` call is needed.
|
|
28
|
+
*
|
|
29
|
+
* There is no remote loading, no automatic package installation, and no
|
|
30
|
+
* untrusted execution anywhere in this path.
|
|
31
|
+
*/
|
|
32
|
+
/** The public Vict compatibility this runtime provides. */
|
|
33
|
+
export declare const VICT_RUNTIME_COMPAT_VERSION = "0.1.0";
|
|
34
|
+
/**
|
|
35
|
+
* Permission grants live on the RUNTIME (createRuntime({ authority })),
|
|
36
|
+
* never on the install call: authorization is a runtime-level decision.
|
|
37
|
+
* A pack installed without its required grants registers fine, but
|
|
38
|
+
* invoking a capability whose declared permissions are ungranted fails
|
|
39
|
+
* BEFORE the handler runs (VICT_RUNTIME_PERMISSION_DENIED).
|
|
40
|
+
*/
|
|
41
|
+
/** Install a capability pack into one runtime. Throws structured VictRuntimeErrors on failure. */
|
|
42
|
+
export declare function installCapabilityPack(runtime: VictRuntime, pack: CapabilityPack): {
|
|
43
|
+
readonly installed: readonly string[];
|
|
44
|
+
};
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { validateCapabilityPack } from '@victframework/sdk';
|
|
2
|
+
import { VictRuntimeError } from './errors.js';
|
|
3
|
+
/**
|
|
4
|
+
* Stage 04: explicit, LOCAL capability-pack installation.
|
|
5
|
+
*
|
|
6
|
+
* Loading a pack is a deliberate act: the manifest is cross-validated
|
|
7
|
+
* against the executable bindings (missing, duplicate, extra, or
|
|
8
|
+
* revision-mismatched bindings fail deterministically), the declared
|
|
9
|
+
* Vict compatibility is checked against the consuming runtime's version,
|
|
10
|
+
* and only then are contracts, capabilities, and declared doubles
|
|
11
|
+
* registered ATOMICALLY.
|
|
12
|
+
*
|
|
13
|
+
* Audit remediation (HIGH-04-A): installation is a registry-level STAGED
|
|
14
|
+
* BATCH. Every contract, capability, and declared double is validated and
|
|
15
|
+
* preflighted (including collisions against the live registry and inside
|
|
16
|
+
* the batch) BEFORE any live map is touched; the complete batch commits
|
|
17
|
+
* only when every step succeeds. A failed installation leaves the registry
|
|
18
|
+
* byte-for-byte semantically unchanged: no capability, contract, or double
|
|
19
|
+
* from the attempted pack is resolvable afterwards. There is no best-effort
|
|
20
|
+
* rollback of partially registered entries because nothing is registered
|
|
21
|
+
* until success is certain.
|
|
22
|
+
*
|
|
23
|
+
* Audit remediation (MED-04-B): the pack's declared doubles
|
|
24
|
+
* (`manifest.doubles` + `bindings.doubles`) are installed atomically WITH
|
|
25
|
+
* the pack. A pack-declared double is eligible ONLY in the modes its
|
|
26
|
+
* manifest declares (`modes: ['test','simulate']`); it never runs in
|
|
27
|
+
* normal mode. No manual `runtime.registerDouble` call is needed.
|
|
28
|
+
*
|
|
29
|
+
* There is no remote loading, no automatic package installation, and no
|
|
30
|
+
* untrusted execution anywhere in this path.
|
|
31
|
+
*/
|
|
32
|
+
/** The public Vict compatibility this runtime provides. */
|
|
33
|
+
export const VICT_RUNTIME_COMPAT_VERSION = '0.1.0';
|
|
34
|
+
/**
|
|
35
|
+
* Permission grants live on the RUNTIME (createRuntime({ authority })),
|
|
36
|
+
* never on the install call: authorization is a runtime-level decision.
|
|
37
|
+
* A pack installed without its required grants registers fine, but
|
|
38
|
+
* invoking a capability whose declared permissions are ungranted fails
|
|
39
|
+
* BEFORE the handler runs (VICT_RUNTIME_PERMISSION_DENIED).
|
|
40
|
+
*/
|
|
41
|
+
/** Install a capability pack into one runtime. Throws structured VictRuntimeErrors on failure. */
|
|
42
|
+
export function installCapabilityPack(runtime, pack) {
|
|
43
|
+
const validation = validateCapabilityPack(pack, {
|
|
44
|
+
victVersion: VICT_RUNTIME_COMPAT_VERSION,
|
|
45
|
+
});
|
|
46
|
+
if (!validation.ok) {
|
|
47
|
+
throw packInvalidError(pack, validation.issues);
|
|
48
|
+
}
|
|
49
|
+
const declared = new Map(pack.manifest.capabilities.map((entry) => [entry.id, entry]));
|
|
50
|
+
const declaredDoubles = new Map((pack.manifest.doubles ?? []).map((entry) => [entry.capabilityId, entry]));
|
|
51
|
+
// Atomic staged batch: every validation, preflight collision check, and
|
|
52
|
+
// effective registration happens against the staging overlay. The live
|
|
53
|
+
// registry is committed only after ALL steps succeed.
|
|
54
|
+
runtime.installCapabilityPackBatch((staging) => {
|
|
55
|
+
// Register each distinct contract object once (shared frozen contracts
|
|
56
|
+
// keep their object identity). Registration inside the batch validates
|
|
57
|
+
// every contract against the live registry + the staged overlay.
|
|
58
|
+
const registeredContracts = new Set();
|
|
59
|
+
for (const binding of pack.bindings.capabilities) {
|
|
60
|
+
for (const contract of [binding.input, binding.output]) {
|
|
61
|
+
if (contract && !registeredContracts.has(contract.id)) {
|
|
62
|
+
staging.registerContract(contract);
|
|
63
|
+
registeredContracts.add(contract.id);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// Preflight + stage every effective capability registration without
|
|
68
|
+
// mutating any live map.
|
|
69
|
+
const installed = [];
|
|
70
|
+
for (const binding of pack.bindings.capabilities) {
|
|
71
|
+
const declaration = declared.get(binding.id);
|
|
72
|
+
if (!declaration) {
|
|
73
|
+
continue; // validated above
|
|
74
|
+
}
|
|
75
|
+
staging.registerCapability({
|
|
76
|
+
id: binding.id,
|
|
77
|
+
revision: binding.revision,
|
|
78
|
+
effect: declaration.effect,
|
|
79
|
+
invoke: binding.invoke,
|
|
80
|
+
...(declaration.idempotency !== undefined ? { idempotency: declaration.idempotency } : {}),
|
|
81
|
+
...(binding.input !== undefined ? { input: binding.input } : {}),
|
|
82
|
+
...(binding.output !== undefined ? { output: binding.output } : {}),
|
|
83
|
+
...(declaration.permissions !== undefined
|
|
84
|
+
? { permissions: [...declaration.permissions] }
|
|
85
|
+
: {}),
|
|
86
|
+
...(declaration.configuration !== undefined
|
|
87
|
+
? { configuration: [...declaration.configuration] }
|
|
88
|
+
: {}),
|
|
89
|
+
...(declaration.requiredConfiguration !== undefined
|
|
90
|
+
? { requiredConfiguration: [...declaration.requiredConfiguration] }
|
|
91
|
+
: {}),
|
|
92
|
+
...(declaration.secrets !== undefined ? { secrets: [...declaration.secrets] } : {}),
|
|
93
|
+
...(declaration.requiredSecrets !== undefined
|
|
94
|
+
? { requiredSecrets: [...declaration.requiredSecrets] }
|
|
95
|
+
: {}),
|
|
96
|
+
});
|
|
97
|
+
installed.push(binding.id);
|
|
98
|
+
}
|
|
99
|
+
// Install the declared bound doubles atomically with the pack (MED-04-B).
|
|
100
|
+
// Eligibility is the manifest's declared `modes` (default: test +
|
|
101
|
+
// simulate); a declared double never runs in normal mode.
|
|
102
|
+
for (const double of pack.bindings.doubles ?? []) {
|
|
103
|
+
const declaration = declaredDoubles.get(double.capabilityId);
|
|
104
|
+
staging.registerDouble(double.capabilityId, double.invoke, {
|
|
105
|
+
modes: declaration?.modes ?? ['test', 'simulate'],
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
return { installed: Object.freeze(pack.bindings.capabilities.map((binding) => binding.id)) };
|
|
110
|
+
}
|
|
111
|
+
function packInvalidError(pack, issues) {
|
|
112
|
+
const code = 'VICT_PACK_INVALID';
|
|
113
|
+
const summary = issues
|
|
114
|
+
.slice(0, 5)
|
|
115
|
+
.map((issue) => `${issue.code}: ${issue.message}`)
|
|
116
|
+
.join(' | ');
|
|
117
|
+
return new VictRuntimeError(code, `Capability pack '${pack.manifest.id}' is not installable: ${summary}`, {
|
|
118
|
+
packId: pack.manifest.id,
|
|
119
|
+
issues: issues.map((issue) => ({
|
|
120
|
+
code: issue.code,
|
|
121
|
+
message: issue.message,
|
|
122
|
+
path: issue.path,
|
|
123
|
+
})),
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=pack-install.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pack-install.js","sourceRoot":"","sources":["../src/pack-install.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { type Contract } from '@victframework/contracts';
|
|
2
|
+
import type { CapabilityDescriptor, CapabilityIndex, ContractEnvironment } from '@victframework/kernel';
|
|
3
|
+
import type { CapabilityDefinition, DoubleInvoke } from './types.js';
|
|
4
|
+
import { type CapabilityAuthority } from './authority.js';
|
|
5
|
+
/** A frozen copy of the execution-relevant parts of a capability definition. */
|
|
6
|
+
export interface FrozenCapabilityBinding {
|
|
7
|
+
readonly id: string;
|
|
8
|
+
readonly revision: string;
|
|
9
|
+
readonly effect: CapabilityDefinition['effect'];
|
|
10
|
+
readonly invoke: CapabilityDefinition['invoke'];
|
|
11
|
+
/** Declared idempotency semantics (drives write-timeout retry classification). */
|
|
12
|
+
readonly idempotency?: CapabilityDefinition['idempotency'];
|
|
13
|
+
readonly inputContractId?: string;
|
|
14
|
+
readonly inputRevision?: string;
|
|
15
|
+
readonly outputContractId?: string;
|
|
16
|
+
readonly outputRevision?: string;
|
|
17
|
+
readonly authority?: CapabilityDescriptor['authority'];
|
|
18
|
+
}
|
|
19
|
+
/** Modes in which a registered test double is eligible to run. */
|
|
20
|
+
export type DoubleMode = 'test' | 'simulate';
|
|
21
|
+
/** A registered test double with its declared mode-eligibility policy. */
|
|
22
|
+
export interface RegisteredDouble {
|
|
23
|
+
readonly invoke: DoubleInvoke;
|
|
24
|
+
/** The double NEVER runs in 'normal' mode; only these declared modes may use it. */
|
|
25
|
+
readonly modes: ReadonlySet<DoubleMode>;
|
|
26
|
+
}
|
|
27
|
+
/** Staging area for an atomic capability-pack installation. */
|
|
28
|
+
export interface RegistryStagingArea {
|
|
29
|
+
registerContract(contract: Contract<unknown>): void;
|
|
30
|
+
registerCapability(definition: CapabilityDefinition): void;
|
|
31
|
+
registerDouble(capabilityId: string, invoke: DoubleInvoke, options?: {
|
|
32
|
+
readonly modes?: readonly DoubleMode[];
|
|
33
|
+
}): void;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Owns registered capabilities, contracts, and test doubles for one runtime.
|
|
37
|
+
* Not a global registry: every runtime instance carries its own.
|
|
38
|
+
*
|
|
39
|
+
* Registration validates author/build revisions and the full executable
|
|
40
|
+
* definition (closed fields, effect vocabulary, CONT-001 contract presence,
|
|
41
|
+
* authority names), because revisions and declarations feed activation
|
|
42
|
+
* identity. Live maps are never exposed: consumers receive descriptors or
|
|
43
|
+
* frozen copies.
|
|
44
|
+
*
|
|
45
|
+
* Atomic registration (HIGH-04-A / LOW-RE-3): `installBatch` stages every
|
|
46
|
+
* contract/capability/double against a staging overlay WITHOUT mutating any
|
|
47
|
+
* live map, and commits the complete batch only when every step succeeds.
|
|
48
|
+
* The direct public `registerCapability` path uses the SAME staging
|
|
49
|
+
* mechanism (capability + embedded contracts staged together), so ANY
|
|
50
|
+
* failure — including a contract conflict — leaves the registry
|
|
51
|
+
* byte-for-byte semantically unchanged. There is no best-effort rollback
|
|
52
|
+
* of partially registered entries.
|
|
53
|
+
*/
|
|
54
|
+
export declare class CapabilityRegistry {
|
|
55
|
+
#private;
|
|
56
|
+
constructor(authority?: CapabilityAuthority);
|
|
57
|
+
registerCapability(definition: CapabilityDefinition): void;
|
|
58
|
+
registerContract(contract: Contract<unknown>): void;
|
|
59
|
+
/**
|
|
60
|
+
* Register a test double. Doubles are runtime test configuration: they are
|
|
61
|
+
* not part of activation identity, and each run snapshots them at run
|
|
62
|
+
* start. A double NEVER runs in normal mode; without an explicit
|
|
63
|
+
* `modes` option it is eligible in both 'test' and 'simulate'. Duplicate
|
|
64
|
+
* registration is rejected — use `replaceDouble` for an explicit
|
|
65
|
+
* replacement.
|
|
66
|
+
*/
|
|
67
|
+
registerDouble(capabilityId: string, invoke: DoubleInvoke, options?: {
|
|
68
|
+
readonly modes?: readonly DoubleMode[];
|
|
69
|
+
}): void;
|
|
70
|
+
/** Explicitly replace an existing test double. Requires a double to be registered. */
|
|
71
|
+
replaceDouble(capabilityId: string, invoke: DoubleInvoke): void;
|
|
72
|
+
hasDouble(capabilityId: string): boolean;
|
|
73
|
+
getDoubleModes(capabilityId: string): ReadonlySet<DoubleMode> | undefined;
|
|
74
|
+
/** Snapshot the current doubles at run start. In-flight runs cannot observe later changes. */
|
|
75
|
+
snapshotDoubles(): ReadonlyMap<string, RegisteredDouble>;
|
|
76
|
+
getCapability(capabilityId: string): CapabilityDefinition<unknown, unknown> | undefined;
|
|
77
|
+
/** Resolve a capability by exact revision (suspended-run restoration). */
|
|
78
|
+
getCapabilityRevision(capabilityId: string, revision: string): CapabilityDefinition<unknown, unknown> | undefined;
|
|
79
|
+
getContract(contractId: string): Contract<unknown> | undefined;
|
|
80
|
+
/** Resolve a contract by exact revision (suspended-run restoration). */
|
|
81
|
+
getContractRevision(contractId: string, revision: string): Contract<unknown> | undefined;
|
|
82
|
+
/**
|
|
83
|
+
* Install a batch atomically. `step` registers contracts, capabilities,
|
|
84
|
+
* and doubles through the staging area; NOTHING touches the live maps
|
|
85
|
+
* until the callback returns successfully. Any throw — a validation
|
|
86
|
+
* failure, a collision with the live registry, or a collision inside the
|
|
87
|
+
* batch — discards the staging overlay and leaves the registry
|
|
88
|
+
* semantically unchanged: no capability, contract, or double from the
|
|
89
|
+
* attempted batch is resolvable afterwards.
|
|
90
|
+
*
|
|
91
|
+
* The staging overlay participates in collision checks, so both
|
|
92
|
+
* batch-vs-registry and batch-internal duplicates are detected BEFORE any
|
|
93
|
+
* commit.
|
|
94
|
+
*/
|
|
95
|
+
installBatch(install: (staging: RegistryStagingArea) => void): void;
|
|
96
|
+
/**
|
|
97
|
+
* A capability index pinned to EXACT revisions (suspended-run
|
|
98
|
+
* restoration). Unknown id/revision pairs resolve to undefined so the
|
|
99
|
+
* kernel reports structured missing-artifact diagnostics instead of
|
|
100
|
+
* silently substituting a nearby revision.
|
|
101
|
+
*/
|
|
102
|
+
capabilityIndex(): CapabilityIndex;
|
|
103
|
+
capabilityIndexPinned(revisions: ReadonlyMap<string, string>): CapabilityIndex;
|
|
104
|
+
contractEnvironment(): ContractEnvironment;
|
|
105
|
+
/** A contract environment pinned to exact revisions (suspended-run restoration). */
|
|
106
|
+
contractEnvironmentPinned(revisions: ReadonlyMap<string, string>): ContractEnvironment;
|
|
107
|
+
}
|