@skrr-ai/cli 0.1.93 → 0.1.95
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 +153 -165
- package/bin/run.js +32 -0
- package/bin/update-npm-runner.cjs +33 -0
- package/bin/update-session.cjs +194 -0
- package/bin/update-worker.cjs +208 -0
- package/dist/base-command.js +0 -15
- package/dist/commands/agents/operating-plan.d.ts +11 -0
- package/dist/commands/agents/operating-plan.js +54 -0
- package/dist/commands/agents/roles/example.d.ts +11 -0
- package/dist/commands/agents/roles/example.js +30 -0
- package/dist/commands/{commitments/mode.d.ts → agents/roles/export.d.ts} +5 -5
- package/dist/commands/agents/roles/export.js +81 -0
- package/dist/commands/agents/roles/install.d.ts +12 -0
- package/dist/commands/agents/roles/install.js +48 -0
- package/dist/commands/agents/roles/list.d.ts +11 -0
- package/dist/commands/agents/roles/list.js +36 -0
- package/dist/commands/agents/roles/preview.d.ts +14 -0
- package/dist/commands/agents/roles/preview.js +49 -0
- package/dist/commands/agents/roles/withdraw.d.ts +13 -0
- package/dist/commands/agents/roles/withdraw.js +43 -0
- package/dist/commands/code/doctor.d.ts +1 -0
- package/dist/commands/code/doctor.js +6 -0
- package/dist/commands/code/index.js +4 -0
- package/dist/commands/code/install.d.ts +5 -62
- package/dist/commands/code/install.js +86 -279
- package/dist/commands/code/rollback.d.ts +8 -0
- package/dist/commands/code/rollback.js +20 -0
- package/dist/commands/code/update.d.ts +8 -37
- package/dist/commands/code/update.js +134 -213
- package/dist/commands/commitments/{autonomy-requests → cadence-requests}/decide.d.ts +5 -7
- package/dist/commands/commitments/{autonomy-requests → cadence-requests}/decide.js +13 -15
- package/dist/commands/commitments/cost.d.ts +1 -1
- package/dist/commands/commitments/cost.js +1 -1
- package/dist/commands/commitments/create.d.ts +0 -7
- package/dist/commands/commitments/create.js +9 -98
- package/dist/commands/commitments/delivery.js +3 -21
- package/dist/commands/commitments/doctor.js +28 -27
- package/dist/commands/commitments/effective-policy.js +5 -36
- package/dist/commands/commitments/evaluations.d.ts +15 -0
- package/dist/commands/commitments/evaluations.js +54 -0
- package/dist/commands/commitments/pack/activate.d.ts +11 -0
- package/dist/commands/commitments/pack/activate.js +22 -0
- package/dist/commands/commitments/pack/bind.js +1 -1
- package/dist/commands/commitments/remediate.js +2 -5
- package/dist/commands/commitments/show.js +1 -1
- package/dist/commands/commitments/update.js +9 -9
- package/dist/commands/commitments/wake-capabilities.d.ts +1 -3
- package/dist/commands/commitments/wake-capabilities.js +5 -21
- package/dist/commands/daemon/install.js +4 -0
- package/dist/commands/generate-recovery-code.d.ts +13 -1
- package/dist/commands/generate-recovery-code.js +146 -13
- package/dist/commands/instructions/guide.d.ts +20 -0
- package/dist/commands/instructions/guide.js +84 -0
- package/dist/commands/instructions/install.js +57 -33
- package/dist/commands/instructions/setup.d.ts +14 -0
- package/dist/commands/instructions/setup.js +72 -0
- package/dist/commands/integrations/execute.js +1 -1
- package/dist/commands/login.d.ts +5 -6
- package/dist/commands/login.js +27 -11
- package/dist/commands/logout.js +7 -7
- package/dist/commands/security/overview.d.ts +11 -0
- package/dist/commands/security/overview.js +158 -0
- package/dist/commands/spaces/claim.d.ts +12 -0
- package/dist/commands/spaces/claim.js +42 -0
- package/dist/commands/spaces/ownership.d.ts +12 -0
- package/dist/commands/spaces/ownership.js +46 -0
- package/dist/commands/tasks/cancel-cascade.js +1 -1
- package/dist/commands/tasks/create-tree.d.ts +5 -1
- package/dist/commands/tasks/create-tree.js +35 -7
- package/dist/commands/tasks/interrupt.js +2 -2
- package/dist/commands/tasks/pause-schedule.js +1 -1
- package/dist/commands/token/list.d.ts +3 -5
- package/dist/commands/token/list.js +99 -57
- package/dist/commands/update.d.ts +14 -0
- package/dist/commands/update.js +61 -0
- package/dist/generated/managed-instruction-guides.json +9 -0
- package/dist/hooks/init.d.ts +5 -0
- package/dist/hooks/init.js +27 -0
- package/dist/lib/commitment-product.d.ts +0 -6
- package/dist/lib/commitment-product.js +1 -30
- package/dist/lib/commitments.d.ts +9 -53
- package/dist/lib/commitments.js +23 -146
- package/dist/lib/daemon-installer.d.ts +2 -0
- package/dist/lib/daemon-installer.js +100 -24
- package/dist/lib/first-party-harness-doctor.js +31 -1
- package/dist/lib/first-party-harness-remote-install.d.ts +71 -0
- package/dist/lib/first-party-harness-remote-install.js +310 -0
- package/dist/lib/first-party-harness-remote-update.d.ts +46 -0
- package/dist/lib/first-party-harness-remote-update.js +242 -0
- package/dist/lib/first-party-harness-startup-update.d.ts +26 -0
- package/dist/lib/first-party-harness-startup-update.js +166 -0
- package/dist/lib/first-party-harness-update.d.ts +46 -0
- package/dist/lib/first-party-harness-update.js +289 -0
- package/dist/lib/first-party-harness.js +7 -4
- package/dist/lib/managed-instruction-local.d.ts +12 -0
- package/dist/lib/managed-instruction-local.js +58 -0
- package/dist/lib/managed-instruction-setup.d.ts +35 -0
- package/dist/lib/managed-instruction-setup.js +306 -0
- package/dist/lib/memory-sync.d.ts +1 -0
- package/dist/lib/memory-sync.js +279 -68
- package/dist/lib/northstars.js +1 -1
- package/dist/lib/platform-update-local.d.ts +2 -0
- package/dist/lib/platform-update-local.js +113 -0
- package/dist/lib/platform-update.d.ts +39 -0
- package/dist/lib/platform-update.js +84 -0
- package/dist/lib/profile-machine-identity-guard.d.ts +2 -0
- package/dist/lib/profile-machine-identity-guard.js +13 -0
- package/dist/lib/prompt.d.ts +1 -0
- package/dist/lib/prompt.js +4 -3
- package/dist/lib/roles.d.ts +98 -0
- package/dist/lib/roles.js +45 -0
- package/dist/lib/task-batch.d.ts +9 -0
- package/dist/lib/task-batch.js +94 -17
- package/dist/lib/task-instruction-offer.d.ts +1 -4
- package/dist/lib/task-instruction-offer.js +3 -129
- package/dist/lib/update-check.d.ts +61 -53
- package/dist/lib/update-check.js +453 -314
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/commitmentExecutionContract.d.ts +45 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/commitmentExecutionContract.js +550 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessChannels.d.ts +3 -4
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessChannels.js +3 -4
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessReleaseKeys.d.ts +82 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessReleaseKeys.js +105 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessUpdater.d.ts +110 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessUpdater.js +945 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/harnessPermissionControls.d.ts +32 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/harnessPermissionControls.js +62 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.d.ts +2 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.js +4 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/machineUuid.js +35 -5
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/releasePolicy.d.ts +63 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/releasePolicy.js +169 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/releaseVersions.d.ts +2 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/releaseVersions.js +44 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/sessionPermissionAuthority.d.ts +7 -44
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/sessionPermissionAuthority.js +8 -47
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/commitmentExecutionContract.d.ts +45 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/commitmentExecutionContract.js +545 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessChannels.d.ts +3 -4
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessChannels.js +3 -4
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessReleaseKeys.d.ts +82 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessReleaseKeys.js +102 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessUpdater.d.ts +110 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessUpdater.js +923 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/harnessPermissionControls.d.ts +32 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/harnessPermissionControls.js +59 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.d.ts +2 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.js +2 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/machineUuid.js +35 -5
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/releasePolicy.d.ts +63 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/releasePolicy.js +163 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/releaseVersions.d.ts +2 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/releaseVersions.js +41 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/sessionPermissionAuthority.d.ts +7 -44
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/sessionPermissionAuthority.js +8 -47
- package/dist/node_modules/@skrr-ai/auth-core/package.json +41 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +7362 -7232
- package/dist/node_modules/@skrr-ai/data-provider/package.json +2 -2
- package/docs/v1/README.md +28 -0
- package/docs/v1/api.md +55 -0
- package/docs/v1/changelog.md +16 -0
- package/docs/v1/check-examples.mjs +178 -0
- package/docs/v1/examples/api-readonly.mjs +144 -0
- package/docs/v1/operations.md +87 -0
- package/docs/v1/quickstart.md +71 -0
- package/oclif.manifest.json +46381 -45478
- package/package.json +16 -11
- package/dist/commands/commitments/autonomy.d.ts +0 -30
- package/dist/commands/commitments/autonomy.js +0 -67
- package/dist/commands/commitments/mode.js +0 -58
- package/dist/commands/commitments/pack/promote.d.ts +0 -19
- package/dist/commands/commitments/pack/promote.js +0 -46
- package/dist/commands/commitments/pack/shadow.d.ts +0 -20
- package/dist/commands/commitments/pack/shadow.js +0 -42
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/** Mode-free responsibility context. Tool permissions belong to the Agent runtime. */
|
|
2
|
+
export declare const COMMITMENT_EXECUTION_CONTRACT_VERSION: 3;
|
|
3
|
+
export declare const COMMITMENT_EXECUTION_CONTRACT_CAPABILITY = "commitment_execution_contract_v3";
|
|
4
|
+
export interface CommitmentExecutionContract {
|
|
5
|
+
version: 3;
|
|
6
|
+
kind: 'commitment' | 'task_delivery';
|
|
7
|
+
responsibilityRef: {
|
|
8
|
+
kind: 'commitment' | 'task';
|
|
9
|
+
id: string;
|
|
10
|
+
version: number;
|
|
11
|
+
};
|
|
12
|
+
responsibility: string;
|
|
13
|
+
event: Record<string, unknown> | null;
|
|
14
|
+
workspace: {
|
|
15
|
+
kind: 'ephemeral';
|
|
16
|
+
base: string;
|
|
17
|
+
fetchBase?: true;
|
|
18
|
+
};
|
|
19
|
+
delivery: {
|
|
20
|
+
version: 1;
|
|
21
|
+
mode: 'report_only' | 'local_patch' | 'draft_pr' | 'push_branch' | 'direct_branch';
|
|
22
|
+
[key: string]: unknown;
|
|
23
|
+
};
|
|
24
|
+
capabilitySources: unknown[];
|
|
25
|
+
evidence?: {
|
|
26
|
+
version: 1;
|
|
27
|
+
ci: unknown[];
|
|
28
|
+
};
|
|
29
|
+
workspacePolicy: Record<string, unknown>;
|
|
30
|
+
deliverySource?: {
|
|
31
|
+
parentTaskId: string;
|
|
32
|
+
branch: string;
|
|
33
|
+
headSha: string;
|
|
34
|
+
baseCommit: string;
|
|
35
|
+
runtime: {
|
|
36
|
+
kind: 'local_daemon' | 'hosted_machine';
|
|
37
|
+
id: string;
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
mustNot: string[];
|
|
41
|
+
return: 'commitment_result_v1' | 'task_output';
|
|
42
|
+
}
|
|
43
|
+
export declare function eventRepository(event: Record<string, unknown> | null | undefined): string;
|
|
44
|
+
/** One strict parser used at storage admission and at runtime admission. */
|
|
45
|
+
export declare function normalizeCommitmentExecutionContract(value: unknown): CommitmentExecutionContract | null;
|
|
@@ -0,0 +1,550 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.COMMITMENT_EXECUTION_CONTRACT_CAPABILITY = exports.COMMITMENT_EXECUTION_CONTRACT_VERSION = void 0;
|
|
4
|
+
exports.eventRepository = eventRepository;
|
|
5
|
+
exports.normalizeCommitmentExecutionContract = normalizeCommitmentExecutionContract;
|
|
6
|
+
const node_util_1 = require("node:util");
|
|
7
|
+
/** Mode-free responsibility context. Tool permissions belong to the Agent runtime. */
|
|
8
|
+
exports.COMMITMENT_EXECUTION_CONTRACT_VERSION = 3;
|
|
9
|
+
exports.COMMITMENT_EXECUTION_CONTRACT_CAPABILITY = 'commitment_execution_contract_v3';
|
|
10
|
+
const DELIVERY_MODES = new Set([
|
|
11
|
+
'report_only',
|
|
12
|
+
'local_patch',
|
|
13
|
+
'draft_pr',
|
|
14
|
+
'push_branch',
|
|
15
|
+
'direct_branch',
|
|
16
|
+
]);
|
|
17
|
+
const FACT_KEYS = new Set([
|
|
18
|
+
'id',
|
|
19
|
+
'source',
|
|
20
|
+
'type',
|
|
21
|
+
'eventType',
|
|
22
|
+
'checkName',
|
|
23
|
+
'workflowName',
|
|
24
|
+
'workflowRunId',
|
|
25
|
+
'revision',
|
|
26
|
+
'appId',
|
|
27
|
+
'appSlug',
|
|
28
|
+
'slug',
|
|
29
|
+
'app',
|
|
30
|
+
'action',
|
|
31
|
+
'status',
|
|
32
|
+
'conclusion',
|
|
33
|
+
'sha',
|
|
34
|
+
'headSha',
|
|
35
|
+
'head_sha',
|
|
36
|
+
'branch',
|
|
37
|
+
'headBranch',
|
|
38
|
+
'head_branch',
|
|
39
|
+
'repo',
|
|
40
|
+
'repository',
|
|
41
|
+
'fullName',
|
|
42
|
+
'full_name',
|
|
43
|
+
'repoFullName',
|
|
44
|
+
'prNumber',
|
|
45
|
+
'owner',
|
|
46
|
+
'name',
|
|
47
|
+
'number',
|
|
48
|
+
'checkRunId',
|
|
49
|
+
'check_run_id',
|
|
50
|
+
'runId',
|
|
51
|
+
'run_id',
|
|
52
|
+
'url',
|
|
53
|
+
'runUrl',
|
|
54
|
+
'htmlUrl',
|
|
55
|
+
'html_url',
|
|
56
|
+
'createdAt',
|
|
57
|
+
'updatedAt',
|
|
58
|
+
'occurredAt',
|
|
59
|
+
'completed_at',
|
|
60
|
+
'started_at',
|
|
61
|
+
'check_run',
|
|
62
|
+
'check_suite',
|
|
63
|
+
'workflow_run',
|
|
64
|
+
'pull_request',
|
|
65
|
+
'base',
|
|
66
|
+
'head',
|
|
67
|
+
'ref',
|
|
68
|
+
'eventId',
|
|
69
|
+
'rerun',
|
|
70
|
+
'checkAnnotations',
|
|
71
|
+
'path',
|
|
72
|
+
'startLine',
|
|
73
|
+
'endLine',
|
|
74
|
+
'level',
|
|
75
|
+
'message',
|
|
76
|
+
'title',
|
|
77
|
+
]);
|
|
78
|
+
const CAPABILITY_SOURCE_KEYS = new Set([
|
|
79
|
+
'source',
|
|
80
|
+
'provider',
|
|
81
|
+
'capability',
|
|
82
|
+
'scope',
|
|
83
|
+
'status',
|
|
84
|
+
'attestation',
|
|
85
|
+
'accountFingerprint',
|
|
86
|
+
'testedAt',
|
|
87
|
+
'expiresAt',
|
|
88
|
+
'runtimeId',
|
|
89
|
+
'reason',
|
|
90
|
+
]);
|
|
91
|
+
const WORKSPACE_CONSTRAINT_KEYS = new Set([
|
|
92
|
+
'allowedCommitmentDeliveryModes',
|
|
93
|
+
'requireAttestedAccessForDeliveryModes',
|
|
94
|
+
'maxInitiativesPerDay',
|
|
95
|
+
'maxAutoRunsPerDay',
|
|
96
|
+
'maxCommitmentActionRunsPerDay',
|
|
97
|
+
'maxCommitmentObservationRunsPerDay',
|
|
98
|
+
'maxCommitmentConcurrentRuns',
|
|
99
|
+
'maxCommitmentCostUsdPerDay',
|
|
100
|
+
'requireApprovalRiskLevels',
|
|
101
|
+
'requireApprovalActionClasses',
|
|
102
|
+
'blockedSourceKinds',
|
|
103
|
+
]);
|
|
104
|
+
const CAPABILITY_SOURCES = new Set([
|
|
105
|
+
'event_payload',
|
|
106
|
+
'cloud_runtime',
|
|
107
|
+
'local_harness',
|
|
108
|
+
'platform_grant',
|
|
109
|
+
]);
|
|
110
|
+
const CAPABILITY_STATUSES = new Set(['available', 'unavailable', 'unknown', 'stale']);
|
|
111
|
+
const CAPABILITY_ATTESTATIONS = new Set(['platform', 'runtime', 'machine', 'none']);
|
|
112
|
+
function plainObject(value) {
|
|
113
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
114
|
+
return false;
|
|
115
|
+
const prototype = Object.getPrototypeOf(value);
|
|
116
|
+
return prototype === Object.prototype || prototype === null;
|
|
117
|
+
}
|
|
118
|
+
function hasOnlyKeys(value, allowed) {
|
|
119
|
+
return plainObject(value) && Object.keys(value).every((key) => allowed.has(key));
|
|
120
|
+
}
|
|
121
|
+
function boundedString(value, max = 1000) {
|
|
122
|
+
return typeof value === 'string' && value.length > 0 && value.length <= max;
|
|
123
|
+
}
|
|
124
|
+
function optionalString(value, max = 1000) {
|
|
125
|
+
return typeof value === 'string' && value.length <= max;
|
|
126
|
+
}
|
|
127
|
+
function isoTimestamp(value) {
|
|
128
|
+
return (typeof value === 'string' &&
|
|
129
|
+
value.length <= 40 &&
|
|
130
|
+
Number.isFinite(Date.parse(value)) &&
|
|
131
|
+
new Date(value).toISOString() === value);
|
|
132
|
+
}
|
|
133
|
+
function normalizedEventFactValue(item, depth) {
|
|
134
|
+
if (typeof item === 'string') {
|
|
135
|
+
if (containsCredentialSignature(item))
|
|
136
|
+
return undefined;
|
|
137
|
+
return item.slice(0, 1000);
|
|
138
|
+
}
|
|
139
|
+
if (typeof item === 'number' || typeof item === 'boolean')
|
|
140
|
+
return item;
|
|
141
|
+
if (Array.isArray(item)) {
|
|
142
|
+
return item
|
|
143
|
+
.slice(0, 20)
|
|
144
|
+
.map((entry) => normalizedEventFacts(entry, depth + 1))
|
|
145
|
+
.filter((entry) => entry !== undefined);
|
|
146
|
+
}
|
|
147
|
+
return normalizedEventFacts(item, depth + 1);
|
|
148
|
+
}
|
|
149
|
+
const CREDENTIAL_SIGNATURE_RE = /(?:bearer\s+(?!\[REDACTED\](?:\s|$))\S{8,}|github_pat_[A-Za-z0-9_]{8,}|gh[pousr]_[A-Za-z0-9_]{8,}|xox[baprs]-[A-Za-z0-9-]{8,}|sk_(?:live|test)_[A-Za-z0-9]{8,}|(?:AKIA|ASIA)[A-Z0-9]{16}|eyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}|[a-z][a-z0-9+.-]*:\/\/[^\s:/@]+:(?!\[REDACTED\]@)[^\s/@]+@|-----BEGIN [A-Z ]*PRIVATE KEY-----)/i;
|
|
150
|
+
function containsCredentialSignature(value) {
|
|
151
|
+
return typeof value === 'string' && CREDENTIAL_SIGNATURE_RE.test(value);
|
|
152
|
+
}
|
|
153
|
+
function normalizedEventFacts(value, depth = 0) {
|
|
154
|
+
if (!plainObject(value) || depth > 3)
|
|
155
|
+
return undefined;
|
|
156
|
+
return Object.fromEntries(Object.entries(value)
|
|
157
|
+
.filter(([key]) => FACT_KEYS.has(key))
|
|
158
|
+
.slice(0, 30)
|
|
159
|
+
.map(([key, item]) => [key, normalizedEventFactValue(item, depth)])
|
|
160
|
+
.filter(([, item]) => item !== undefined));
|
|
161
|
+
}
|
|
162
|
+
const CI_LOG_EVIDENCE_KEYS = new Set([
|
|
163
|
+
'version',
|
|
164
|
+
'provider',
|
|
165
|
+
'kind',
|
|
166
|
+
'repoFullName',
|
|
167
|
+
'checkRunId',
|
|
168
|
+
'workflowRunId',
|
|
169
|
+
'jobId',
|
|
170
|
+
'capability',
|
|
171
|
+
'attestation',
|
|
172
|
+
'fetchedAt',
|
|
173
|
+
'status',
|
|
174
|
+
'reason',
|
|
175
|
+
'byteLength',
|
|
176
|
+
'lineCount',
|
|
177
|
+
'excerptLines',
|
|
178
|
+
'excerpt',
|
|
179
|
+
'digest',
|
|
180
|
+
// Attribution facts, taken off the job row the server had to fetch to prove
|
|
181
|
+
// identity. Allowed on an UNREADABLE row: attribution happens before the
|
|
182
|
+
// download, so the failing step name survives a log the server could not
|
|
183
|
+
// read. Only text FROM the log is withheld when the read failed.
|
|
184
|
+
'jobName',
|
|
185
|
+
'failedStepName',
|
|
186
|
+
'failedStepNumber',
|
|
187
|
+
]);
|
|
188
|
+
const CI_LOG_EVIDENCE_STATUSES = new Set(['available', 'truncated', 'unavailable', 'unauthorized']);
|
|
189
|
+
const CI_LOG_EVIDENCE_READABLE = new Set(['available', 'truncated']);
|
|
190
|
+
const CI_LOG_EXCERPT_MAX_CHARS = 12_000;
|
|
191
|
+
function validCiLogEvidence(value) {
|
|
192
|
+
if (!hasOnlyKeys(value, CI_LOG_EVIDENCE_KEYS))
|
|
193
|
+
return false;
|
|
194
|
+
if (value.version !== 1 ||
|
|
195
|
+
value.provider !== 'github' ||
|
|
196
|
+
value.kind !== 'actions_job_log' ||
|
|
197
|
+
value.capability !== 'github:actions:read' ||
|
|
198
|
+
value.attestation !== 'platform' ||
|
|
199
|
+
!CI_LOG_EVIDENCE_STATUSES.has(String(value.status)) ||
|
|
200
|
+
!isoTimestamp(value.fetchedAt) ||
|
|
201
|
+
!/^[\w.-]+\/[\w.-]+$/.test(String(value.repoFullName || '')) ||
|
|
202
|
+
!/^\d{1,20}$/.test(String(value.checkRunId || '')))
|
|
203
|
+
return false;
|
|
204
|
+
for (const key of ['workflowRunId', 'jobId']) {
|
|
205
|
+
if (value[key] !== undefined && !/^\d{1,20}$/.test(String(value[key])))
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
for (const key of ['byteLength', 'lineCount', 'excerptLines', 'failedStepNumber']) {
|
|
209
|
+
const item = value[key];
|
|
210
|
+
if (item !== undefined && (!Number.isSafeInteger(item) || item < 0))
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
for (const key of ['jobName', 'failedStepName']) {
|
|
214
|
+
if (value[key] !== undefined && !boundedString(value[key], 200))
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
217
|
+
if (value.reason !== undefined && !/^[a-z0-9_]{1,80}$/.test(String(value.reason)))
|
|
218
|
+
return false;
|
|
219
|
+
if (value.digest !== undefined && !/^[a-f0-9]{16}$/.test(String(value.digest)))
|
|
220
|
+
return false;
|
|
221
|
+
// A read that failed carries no text: an unreadable log must not be able to
|
|
222
|
+
// arrive looking like a readable one.
|
|
223
|
+
if (!CI_LOG_EVIDENCE_READABLE.has(String(value.status))) {
|
|
224
|
+
return value.excerpt === undefined && value.digest === undefined && Boolean(value.reason);
|
|
225
|
+
}
|
|
226
|
+
return boundedString(value.excerpt, CI_LOG_EXCERPT_MAX_CHARS) && value.jobId !== undefined;
|
|
227
|
+
}
|
|
228
|
+
function validEvidence(value) {
|
|
229
|
+
if (!hasOnlyKeys(value, new Set(['version', 'ci'])))
|
|
230
|
+
return false;
|
|
231
|
+
return (value.version === 1 &&
|
|
232
|
+
Array.isArray(value.ci) &&
|
|
233
|
+
value.ci.length >= 1 &&
|
|
234
|
+
value.ci.length <= 4 &&
|
|
235
|
+
value.ci.every(validCiLogEvidence));
|
|
236
|
+
}
|
|
237
|
+
// Mirror of `validObserve` in
|
|
238
|
+
// api/server/services/Commitments/CommitmentExecutionContract.js. The daemon
|
|
239
|
+
// has no projector, so canonical form is part of validity on both sides:
|
|
240
|
+
// `egress` must be strictly ascending (sorted AND unique). The shared parity
|
|
241
|
+
// fixture holds the two to one verdict.
|
|
242
|
+
const OBSERVE_KEYS = new Set(['egress', 'web', 'shell', 'browser']);
|
|
243
|
+
const OBSERVE_EGRESS_MAX = 32;
|
|
244
|
+
const OBSERVE_HOST_PATTERN = /^(\*\.)?[a-z0-9.-]+$/;
|
|
245
|
+
const OBSERVE_HOST_LABEL = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
|
|
246
|
+
function evidenceMatchesEvent(row, event) {
|
|
247
|
+
if (!plainObject(row) || !plainObject(event))
|
|
248
|
+
return true;
|
|
249
|
+
const same = (a, b) => String(a).toLowerCase() === String(b).toLowerCase();
|
|
250
|
+
if (event.repoFullName !== undefined && !same(row.repoFullName, event.repoFullName))
|
|
251
|
+
return false;
|
|
252
|
+
if (event.checkRunId !== undefined && !same(row.checkRunId, event.checkRunId))
|
|
253
|
+
return false;
|
|
254
|
+
if (row.workflowRunId !== undefined &&
|
|
255
|
+
event.workflowRunId !== undefined &&
|
|
256
|
+
!same(row.workflowRunId, event.workflowRunId))
|
|
257
|
+
return false;
|
|
258
|
+
return true;
|
|
259
|
+
}
|
|
260
|
+
function validCapabilitySource(value) {
|
|
261
|
+
if (!hasOnlyKeys(value, CAPABILITY_SOURCE_KEYS))
|
|
262
|
+
return false;
|
|
263
|
+
if (!CAPABILITY_SOURCES.has(String(value.source)) ||
|
|
264
|
+
!boundedString(value.provider, 80) ||
|
|
265
|
+
!/^[a-z0-9_.-]{1,80}$/i.test(value.provider) ||
|
|
266
|
+
!boundedString(value.capability, 120) ||
|
|
267
|
+
!/^[a-z0-9_:.-]{1,120}$/i.test(value.capability) ||
|
|
268
|
+
!CAPABILITY_STATUSES.has(String(value.status)) ||
|
|
269
|
+
!CAPABILITY_ATTESTATIONS.has(String(value.attestation)))
|
|
270
|
+
return false;
|
|
271
|
+
if (value.scope !== undefined && !optionalString(value.scope, 500))
|
|
272
|
+
return false;
|
|
273
|
+
if (value.accountFingerprint !== undefined &&
|
|
274
|
+
!/^[a-f0-9]{64}$/i.test(String(value.accountFingerprint)))
|
|
275
|
+
return false;
|
|
276
|
+
if (value.testedAt !== undefined && !isoTimestamp(value.testedAt))
|
|
277
|
+
return false;
|
|
278
|
+
if (value.expiresAt !== undefined && !isoTimestamp(value.expiresAt))
|
|
279
|
+
return false;
|
|
280
|
+
if (value.testedAt &&
|
|
281
|
+
value.expiresAt &&
|
|
282
|
+
Date.parse(String(value.expiresAt)) <= Date.parse(String(value.testedAt)))
|
|
283
|
+
return false;
|
|
284
|
+
if (value.runtimeId !== undefined && !boundedString(value.runtimeId, 200))
|
|
285
|
+
return false;
|
|
286
|
+
if (value.reason !== undefined && !optionalString(value.reason, 1000))
|
|
287
|
+
return false;
|
|
288
|
+
if (value.source === 'event_payload' && value.attestation !== 'platform')
|
|
289
|
+
return false;
|
|
290
|
+
if (value.source === 'platform_grant' && value.attestation !== 'platform')
|
|
291
|
+
return false;
|
|
292
|
+
if (value.source === 'local_harness' &&
|
|
293
|
+
(!['machine', 'none'].includes(String(value.attestation)) ||
|
|
294
|
+
(value.status === 'available' &&
|
|
295
|
+
(value.attestation !== 'machine' ||
|
|
296
|
+
!value.accountFingerprint ||
|
|
297
|
+
!value.testedAt ||
|
|
298
|
+
!value.expiresAt ||
|
|
299
|
+
!value.runtimeId))))
|
|
300
|
+
return false;
|
|
301
|
+
if (value.source === 'cloud_runtime' &&
|
|
302
|
+
(!['runtime', 'none'].includes(String(value.attestation)) ||
|
|
303
|
+
(value.status === 'available' &&
|
|
304
|
+
(value.attestation !== 'runtime' ||
|
|
305
|
+
!value.accountFingerprint ||
|
|
306
|
+
!value.testedAt ||
|
|
307
|
+
!value.expiresAt ||
|
|
308
|
+
!value.runtimeId))))
|
|
309
|
+
return false;
|
|
310
|
+
return true;
|
|
311
|
+
}
|
|
312
|
+
function validStringArray(value, max, values) {
|
|
313
|
+
return (Array.isArray(value) &&
|
|
314
|
+
value.length <= max &&
|
|
315
|
+
value.every((item) => boundedString(item, 120) && (!values || values.has(item))));
|
|
316
|
+
}
|
|
317
|
+
function validWorkspacePolicy(value) {
|
|
318
|
+
if (!hasOnlyKeys(value, new Set(['hardStop', 'hardConstraints'])))
|
|
319
|
+
return false;
|
|
320
|
+
if (value.hardStop !== undefined && value.hardStop !== null) {
|
|
321
|
+
if (!hasOnlyKeys(value.hardStop, new Set(['enabled', 'reason', 'scope'])))
|
|
322
|
+
return false;
|
|
323
|
+
if (typeof value.hardStop.enabled !== 'boolean')
|
|
324
|
+
return false;
|
|
325
|
+
if (value.hardStop.reason !== undefined && !optionalString(value.hardStop.reason, 1000))
|
|
326
|
+
return false;
|
|
327
|
+
if (value.hardStop.scope !== undefined && !optionalString(value.hardStop.scope, 100))
|
|
328
|
+
return false;
|
|
329
|
+
}
|
|
330
|
+
if (value.hardConstraints === undefined)
|
|
331
|
+
return true;
|
|
332
|
+
if (!hasOnlyKeys(value.hardConstraints, WORKSPACE_CONSTRAINT_KEYS))
|
|
333
|
+
return false;
|
|
334
|
+
for (const [key, item] of Object.entries(value.hardConstraints)) {
|
|
335
|
+
if (item === null)
|
|
336
|
+
continue;
|
|
337
|
+
if (key === 'allowedCommitmentDeliveryModes' ||
|
|
338
|
+
key === 'requireAttestedAccessForDeliveryModes') {
|
|
339
|
+
if (!validStringArray(item, 5, DELIVERY_MODES))
|
|
340
|
+
return false;
|
|
341
|
+
}
|
|
342
|
+
else if (key === 'maxCommitmentCostUsdPerDay') {
|
|
343
|
+
if (typeof item !== 'number' || !Number.isFinite(item) || item < 0)
|
|
344
|
+
return false;
|
|
345
|
+
}
|
|
346
|
+
else if (key.startsWith('max')) {
|
|
347
|
+
if (!Number.isSafeInteger(item) || Number(item) < 0)
|
|
348
|
+
return false;
|
|
349
|
+
}
|
|
350
|
+
else if (key === 'requireApprovalRiskLevels') {
|
|
351
|
+
if (!validStringArray(item, 3, new Set(['low', 'medium', 'high'])))
|
|
352
|
+
return false;
|
|
353
|
+
}
|
|
354
|
+
else if (!validStringArray(item, key === 'blockedSourceKinds' ? 50 : 20))
|
|
355
|
+
return false;
|
|
356
|
+
}
|
|
357
|
+
return true;
|
|
358
|
+
}
|
|
359
|
+
function validBranch(value) {
|
|
360
|
+
return (boundedString(value, 255) &&
|
|
361
|
+
value !== 'HEAD' &&
|
|
362
|
+
!value.startsWith('refs/') &&
|
|
363
|
+
!value.startsWith('origin/') &&
|
|
364
|
+
!value.startsWith('-') &&
|
|
365
|
+
!value.startsWith('/') &&
|
|
366
|
+
!value.endsWith('/') &&
|
|
367
|
+
!value.endsWith('.') &&
|
|
368
|
+
// Control characters are exactly what this rejects: a Git ref name may not
|
|
369
|
+
// contain them, so the class is deliberate rather than an oversight.
|
|
370
|
+
// eslint-disable-next-line no-control-regex
|
|
371
|
+
!/[\s~^:?*[\\\x00-\x1f\x7f]/.test(value) &&
|
|
372
|
+
!value.includes('..') &&
|
|
373
|
+
!value.includes('@{') &&
|
|
374
|
+
!value.includes('//') &&
|
|
375
|
+
value !== '@' &&
|
|
376
|
+
!value.split('/').some((part) => part.startsWith('.') || part.endsWith('.lock')));
|
|
377
|
+
}
|
|
378
|
+
function validDelivery(value) {
|
|
379
|
+
if (!hasOnlyKeys(value, new Set(['version', 'mode', 'repo', 'baseBranch', 'expectations'])))
|
|
380
|
+
return false;
|
|
381
|
+
if (value.version !== 1 || !DELIVERY_MODES.has(String(value.mode)))
|
|
382
|
+
return false;
|
|
383
|
+
if (value.repo !== undefined &&
|
|
384
|
+
(!/^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(String(value.repo)) ||
|
|
385
|
+
String(value.repo) !== String(value.repo).toLowerCase()))
|
|
386
|
+
return false;
|
|
387
|
+
if (value.baseBranch !== undefined && !validBranch(value.baseBranch))
|
|
388
|
+
return false;
|
|
389
|
+
if (['draft_pr', 'push_branch', 'direct_branch'].includes(String(value.mode)) &&
|
|
390
|
+
(!value.repo || !value.baseBranch))
|
|
391
|
+
return false;
|
|
392
|
+
if (value.expectations !== undefined) {
|
|
393
|
+
if (!Array.isArray(value.expectations) || value.expectations.length > 20)
|
|
394
|
+
return false;
|
|
395
|
+
const ids = new Set();
|
|
396
|
+
const allowed = new Set([
|
|
397
|
+
'id',
|
|
398
|
+
'shape',
|
|
399
|
+
'kind',
|
|
400
|
+
'format',
|
|
401
|
+
'target',
|
|
402
|
+
'minimumAuthority',
|
|
403
|
+
'description',
|
|
404
|
+
'presetKey',
|
|
405
|
+
]);
|
|
406
|
+
for (const expectation of value.expectations) {
|
|
407
|
+
if (!hasOnlyKeys(expectation, allowed) ||
|
|
408
|
+
!['code', 'page', 'url', 'file', 'message', 'dataset'].includes(String(expectation.kind)))
|
|
409
|
+
return false;
|
|
410
|
+
if (expectation.id !== undefined) {
|
|
411
|
+
if (!boundedString(expectation.id, 64) ||
|
|
412
|
+
expectation.id === 'commitment-delivery' ||
|
|
413
|
+
ids.has(expectation.id))
|
|
414
|
+
return false;
|
|
415
|
+
ids.add(expectation.id);
|
|
416
|
+
}
|
|
417
|
+
if (expectation.shape !== undefined &&
|
|
418
|
+
!['checkable', 'judged'].includes(String(expectation.shape)))
|
|
419
|
+
return false;
|
|
420
|
+
if (expectation.minimumAuthority !== undefined &&
|
|
421
|
+
!['self_reported', 'human_confirmed', 'observation_backed'].includes(String(expectation.minimumAuthority)))
|
|
422
|
+
return false;
|
|
423
|
+
for (const [key, max] of [
|
|
424
|
+
['format', 40],
|
|
425
|
+
['target', 500],
|
|
426
|
+
['description', 500],
|
|
427
|
+
['presetKey', 64],
|
|
428
|
+
]) {
|
|
429
|
+
if (expectation[key] !== undefined && !optionalString(expectation[key], max))
|
|
430
|
+
return false;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
return true;
|
|
435
|
+
}
|
|
436
|
+
function validDeliverySource(value) {
|
|
437
|
+
if (!hasOnlyKeys(value, new Set(['parentTaskId', 'branch', 'headSha', 'baseCommit', 'runtime'])))
|
|
438
|
+
return false;
|
|
439
|
+
return (typeof value.parentTaskId === 'string' &&
|
|
440
|
+
value.parentTaskId.length > 0 &&
|
|
441
|
+
value.parentTaskId.length <= 200 &&
|
|
442
|
+
typeof value.branch === 'string' &&
|
|
443
|
+
/^[A-Za-z0-9][A-Za-z0-9_./-]{0,239}$/.test(value.branch) &&
|
|
444
|
+
!value.branch.includes('..') &&
|
|
445
|
+
!value.branch.includes('@{') &&
|
|
446
|
+
/^[a-f0-9]{40,64}$/i.test(value.headSha) &&
|
|
447
|
+
typeof value.baseCommit === 'string' &&
|
|
448
|
+
/^[a-f0-9]{40,64}$/i.test(value.baseCommit) &&
|
|
449
|
+
hasOnlyKeys(value.runtime, new Set(['kind', 'id'])) &&
|
|
450
|
+
['local_daemon', 'hosted_machine'].includes(String(value.runtime.kind)) &&
|
|
451
|
+
boundedString(value.runtime.id, 200) &&
|
|
452
|
+
(value.runtime.kind !== 'hosted_machine' || value.runtime.id.startsWith('sbs_')));
|
|
453
|
+
}
|
|
454
|
+
function eventSourceRevision(event) {
|
|
455
|
+
if (!event)
|
|
456
|
+
return '';
|
|
457
|
+
const nestedCheck = event.check_run;
|
|
458
|
+
const nestedWorkflow = event.workflow_run;
|
|
459
|
+
const value = event.headSha ||
|
|
460
|
+
event.head_sha ||
|
|
461
|
+
event.sha ||
|
|
462
|
+
nestedCheck?.head_sha ||
|
|
463
|
+
nestedWorkflow?.head_sha;
|
|
464
|
+
return /^[a-f0-9]{40,64}$/i.test(String(value || '')) ? String(value).toLowerCase() : '';
|
|
465
|
+
}
|
|
466
|
+
function eventRepository(event) {
|
|
467
|
+
if (!event)
|
|
468
|
+
return '';
|
|
469
|
+
const repository = event.repository;
|
|
470
|
+
const value = event.repoFullName || repository?.full_name || repository?.fullName;
|
|
471
|
+
return /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(String(value || ''))
|
|
472
|
+
? String(value).toLowerCase()
|
|
473
|
+
: '';
|
|
474
|
+
}
|
|
475
|
+
function failedGitHubCheck(event) {
|
|
476
|
+
const eventType = String(event?.eventType || event?.type || '').toLowerCase();
|
|
477
|
+
return eventType === 'github.check_run_failed' || eventType === 'check_run_failed';
|
|
478
|
+
}
|
|
479
|
+
/** One strict parser used at storage admission and at runtime admission. */
|
|
480
|
+
function normalizeCommitmentExecutionContract(value) {
|
|
481
|
+
if (!hasOnlyKeys(value, new Set([
|
|
482
|
+
'version',
|
|
483
|
+
'kind',
|
|
484
|
+
'responsibilityRef',
|
|
485
|
+
'responsibility',
|
|
486
|
+
'event',
|
|
487
|
+
'workspace',
|
|
488
|
+
'delivery',
|
|
489
|
+
'capabilitySources',
|
|
490
|
+
'evidence',
|
|
491
|
+
'workspacePolicy',
|
|
492
|
+
'deliverySource',
|
|
493
|
+
'mustNot',
|
|
494
|
+
'return',
|
|
495
|
+
])))
|
|
496
|
+
return null;
|
|
497
|
+
const contract = value;
|
|
498
|
+
const event = contract.event === undefined ? null : contract.event;
|
|
499
|
+
const eventSha = eventSourceRevision(event);
|
|
500
|
+
const eventRepo = eventRepository(event);
|
|
501
|
+
const taskDelivery = contract.kind === 'task_delivery';
|
|
502
|
+
if (contract.version !== exports.COMMITMENT_EXECUTION_CONTRACT_VERSION ||
|
|
503
|
+
!['commitment', 'task_delivery'].includes(contract.kind) ||
|
|
504
|
+
!hasOnlyKeys(contract.responsibilityRef, new Set(['kind', 'id', 'version'])) ||
|
|
505
|
+
contract.responsibilityRef.kind !== (taskDelivery ? 'task' : 'commitment') ||
|
|
506
|
+
!boundedString(contract.responsibilityRef.id, 240) ||
|
|
507
|
+
!Number.isSafeInteger(contract.responsibilityRef.version) ||
|
|
508
|
+
contract.responsibilityRef.version < 1 ||
|
|
509
|
+
!boundedString(contract.responsibility, 2000) ||
|
|
510
|
+
!hasOnlyKeys(contract.workspace, new Set(['kind', 'base', 'fetchBase'])) ||
|
|
511
|
+
contract.workspace.kind !== 'ephemeral' ||
|
|
512
|
+
!boundedString(contract.workspace.base, 255) ||
|
|
513
|
+
(contract.workspace.fetchBase !== undefined &&
|
|
514
|
+
(contract.workspace.fetchBase !== true || contract.workspace.kind !== 'ephemeral')) ||
|
|
515
|
+
!validDelivery(contract.delivery) ||
|
|
516
|
+
!Array.isArray(contract.capabilitySources) ||
|
|
517
|
+
contract.capabilitySources.length > 32 ||
|
|
518
|
+
!contract.capabilitySources.every(validCapabilitySource) ||
|
|
519
|
+
!validWorkspacePolicy(contract.workspacePolicy ?? {}) ||
|
|
520
|
+
!(0, node_util_1.isDeepStrictEqual)(contract.mustNot, [
|
|
521
|
+
'change_workspace_administration',
|
|
522
|
+
'broaden_credentials',
|
|
523
|
+
...(taskDelivery ? ['reimplement_source_work'] : []),
|
|
524
|
+
]) ||
|
|
525
|
+
(taskDelivery
|
|
526
|
+
? contract.return !== 'task_output'
|
|
527
|
+
: contract.return !== 'commitment_result_v1') ||
|
|
528
|
+
(event !== null &&
|
|
529
|
+
(!plainObject(event) || !(0, node_util_1.isDeepStrictEqual)(event, normalizedEventFacts(event)))) ||
|
|
530
|
+
(eventSha && contract.workspace.base.toLowerCase() !== eventSha) ||
|
|
531
|
+
(eventRepo &&
|
|
532
|
+
contract.delivery.repo &&
|
|
533
|
+
String(contract.delivery.repo).toLowerCase() !== eventRepo) ||
|
|
534
|
+
(failedGitHubCheck(event) && (!eventSha || !eventRepo)) ||
|
|
535
|
+
(contract.evidence !== undefined &&
|
|
536
|
+
(taskDelivery ||
|
|
537
|
+
!validEvidence(contract.evidence) ||
|
|
538
|
+
!contract.evidence.ci.every((row) => evidenceMatchesEvent(row, event)))) ||
|
|
539
|
+
(taskDelivery &&
|
|
540
|
+
(event !== null ||
|
|
541
|
+
!['draft_pr', 'push_branch', 'direct_branch'].includes(contract.delivery.mode) ||
|
|
542
|
+
contract.workspace.kind !== 'ephemeral' ||
|
|
543
|
+
!validDeliverySource(contract.deliverySource) ||
|
|
544
|
+
contract.responsibilityRef.id !== contract.deliverySource?.parentTaskId ||
|
|
545
|
+
contract.workspace.base.toLowerCase() !==
|
|
546
|
+
String(contract.deliverySource?.baseCommit).toLowerCase())) ||
|
|
547
|
+
(!taskDelivery && contract.deliverySource !== undefined))
|
|
548
|
+
return null;
|
|
549
|
+
return JSON.parse(JSON.stringify(contract));
|
|
550
|
+
}
|
|
@@ -18,10 +18,9 @@
|
|
|
18
18
|
* quietly redeclaring. This follows that road rather than reopening the one it
|
|
19
19
|
* replaced.
|
|
20
20
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* performs them.
|
|
21
|
+
* Channel vocabulary stays here. The shared signed installer lives beside it
|
|
22
|
+
* in firstPartyHarnessUpdater.ts, used by CLI, Daemon and Desktop so updating
|
|
23
|
+
* a local engine needs neither a running daemon nor an account.
|
|
25
24
|
*
|
|
26
25
|
* Every product-named value comes from `firstPartyHarness.ts`; nothing in this
|
|
27
26
|
* file spells the product.
|
|
@@ -19,10 +19,9 @@
|
|
|
19
19
|
* quietly redeclaring. This follows that road rather than reopening the one it
|
|
20
20
|
* replaced.
|
|
21
21
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* performs them.
|
|
22
|
+
* Channel vocabulary stays here. The shared signed installer lives beside it
|
|
23
|
+
* in firstPartyHarnessUpdater.ts, used by CLI, Daemon and Desktop so updating
|
|
24
|
+
* a local engine needs neither a running daemon nor an account.
|
|
26
25
|
*
|
|
27
26
|
* Every product-named value comes from `firstPartyHarness.ts`; nothing in this
|
|
28
27
|
* file spells the product.
|