deadbyte-mcp 0.15.41 → 0.15.42
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/DEADBYTE-MCP.cmd +8 -4
- package/MANIFEST.SHA256 +84 -41
- package/PROVENANCE.json +53 -15
- package/README.txt +27 -18
- package/RELEASE.json +43 -15
- package/SBOM.cdx.json +2 -2
- package/TEST-MATRIX.json +106 -14
- package/bridge/package.json +1 -1
- package/controller/deadbyte-controller.ps1 +132 -12
- package/controller/deadbyte-process-policy.json +4 -4
- package/docs/R65-AUTHORITY-CONTINUITY-DESIGN.json +27 -0
- package/docs/R65-REFERENCE-GAP-MATRIX.json +22 -0
- package/package.json +5 -4
- package/scripts/deploy-r48.mjs +123 -7
- package/scripts/gate-windows-r65-prepublish.ps1 +65 -0
- package/scripts/npm-publication-r65.mjs +139 -0
- package/scripts/npm-release-r48.mjs +56 -37
- package/scripts/r65-canonical-full.mjs +45 -0
- package/scripts/r65-focused.mjs +37 -0
- package/scripts/verify-r65-parent-source.mjs +75 -0
- package/src/activation-continuity-engine-r65.mjs +225 -0
- package/src/activation-lock-r65.mjs +155 -0
- package/src/activation-preflight-r65.mjs +197 -0
- package/src/authority-continuity-r65.mjs +541 -0
- package/src/authority-epoch-cli-r65.mjs +10 -0
- package/src/autonomous-policy.mjs +7 -3
- package/src/coding-plane.mjs +12 -3
- package/src/desktop-policy-r40.mjs +6 -3
- package/src/doctor-transactions-r58.mjs +1 -1
- package/src/host-plane.mjs +9 -3
- package/src/process-policy.mjs +7 -4
- package/src/remote-authority.mjs +10 -1
- package/src/runtime-update.mjs +15 -5
- package/src/version.mjs +1 -1
- package/test/audit-context.test.mjs +15 -4
- package/test/autonomous-local-supervisor.test.mjs +7 -6
- package/test/autonomous-supervisor-integration.test.mjs +8 -7
- package/test/capability-resolver.test.mjs +11 -5
- package/test/codex-autonomous-r44.test.mjs +7 -6
- package/test/coding-observation.test.mjs +4 -3
- package/test/commander-real-parity-r47.test.mjs +5 -4
- package/test/commander-torture-r47.test.mjs +5 -4
- package/test/desktop-policy-r40.test.mjs +6 -4
- package/test/desktop-runtime-r40.test.mjs +8 -3
- package/test/host-inline-r45.test.mjs +4 -3
- package/test/machine-fs-runtime.test.mjs +4 -3
- package/test/process-longrun-r36.test.mjs +3 -2
- package/test/process-policy.test.mjs +10 -6
- package/test/process-runtime.test.mjs +9 -6
- package/test/r52-host-revocation.test.mjs +1 -0
- package/test/r59-tool-surface-compat.test.mjs +1 -1
- package/test/r64-release-contract.test.mjs +2 -1
- package/test/r65-activation-lock-recovery.test.mjs +72 -0
- package/test/r65-activation-lock.test.mjs +59 -0
- package/test/r65-activation-orchestration.test.mjs +179 -0
- package/test/r65-activation-preflight.test.mjs +35 -0
- package/test/r65-authority-continuity-decision.test.mjs +58 -0
- package/test/r65-authority-durable-policy-binding.test.mjs +34 -0
- package/test/r65-authority-epoch-cli.test.mjs +125 -0
- package/test/r65-authority-epoch-races.test.mjs +87 -0
- package/test/r65-authority-epoch-recovery.test.mjs +82 -0
- package/test/r65-authority-epoch-store.test.mjs +94 -0
- package/test/r65-authority-fixture.mjs +41 -0
- package/test/r65-authority-grant-capture.test.mjs +37 -0
- package/test/r65-authority-observation-epoch.test.mjs +25 -0
- package/test/r65-authority-policy-envelope.test.mjs +46 -0
- package/test/r65-authority-restored-safe.test.mjs +75 -0
- package/test/r65-authority-runtime-epoch.test.mjs +115 -0
- package/test/r65-authority-runtime-policy-binding.test.mjs +29 -0
- package/test/r65-authority-test-trust.mjs +20 -0
- package/test/r65-cli-invocation.test.mjs +38 -0
- package/test/r65-controller-authority-epoch-live.test.mjs +100 -0
- package/test/r65-controller-authority-epoch.test.mjs +37 -0
- package/test/r65-deploy-preflight.test.mjs +55 -0
- package/test/r65-epoch-native-activation-integration.test.mjs +141 -0
- package/test/r65-epoch-native-continuity-engine.test.mjs +112 -0
- package/test/r65-epoch-native-cross-plane.test.mjs +95 -0
- package/test/r65-legacy-authority-migration.test.mjs +63 -0
- package/test/r65-legacy-auto-restore-rejection.test.mjs +17 -0
- package/test/r65-npm-publication.test.mjs +114 -0
- package/test/r65-parent-source-verifier.test.mjs +63 -0
- package/test/r65-release-contract.test.mjs +74 -0
- package/test/r65-transaction-precondition.test.mjs +36 -0
- package/test/remote-session-cli.test.mjs +6 -6
- package/test/standing-grants.test.mjs +20 -4
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": "deadbyte.process-policy.v1",
|
|
3
3
|
"enabled": true,
|
|
4
|
-
"grant_file": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.
|
|
5
|
-
"state_dir": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.
|
|
4
|
+
"grant_file": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.42-r65\\controller\\runtime\\process-grant.json",
|
|
5
|
+
"state_dir": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.42-r65\\controller\\runtime\\process-state",
|
|
6
6
|
"native_host": {
|
|
7
|
-
"path": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.
|
|
7
|
+
"path": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.42-r65\\bin\\deadbyte-process-host.exe",
|
|
8
8
|
"sha256": "daf9cfb371bee88cafbf5597eaa507fec504dbe0b0ddd40d0c3c2e02817f49e4"
|
|
9
9
|
},
|
|
10
10
|
"roots": {
|
|
11
11
|
"core": {
|
|
12
|
-
"path": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.
|
|
12
|
+
"path": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.42-r65",
|
|
13
13
|
"deny_paths": [
|
|
14
14
|
"node_modules",
|
|
15
15
|
"controller/runtime",
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": "deadbyte.r65-authority-continuity-design.v1",
|
|
3
|
+
"status": "PARTIAL_IMPLEMENTATION",
|
|
4
|
+
"authority": "Current R65 candidate source and read-only R64 generation policies; production remains immutable.",
|
|
5
|
+
"observed_contracts": {
|
|
6
|
+
"controller": "controller/deadbyte-controller.ps1 Get-*GrantStatus checks schema and policy_sha256; Process/Coding/Autonomous/Desktop additionally carry scope and instance_nonce; Host carries nonce but no explicit scope.",
|
|
7
|
+
"process": "src/process-policy.mjs rechecks policy hash, nonce, profile_ids and root_ids; grant schema deadbyte.process-grant.v1.",
|
|
8
|
+
"coding": "src/coding-plane.mjs rechecks policy hash, nonce and root_ids; standing grant schema deadbyte.coding-grant.v2.",
|
|
9
|
+
"autonomous": "controller/deadbyte-controller.ps1 requires a Coding grant, coding_policy_sha256 and root_ids; grant schema deadbyte.autonomous-grant.v2.",
|
|
10
|
+
"desktop": "src/desktop-policy-r40.mjs and controller validate policy hash, nonce and action_kinds; grant schema deadbyte.desktop-grant.v1.",
|
|
11
|
+
"host": "controller/deadbyte-controller.ps1 validates policy hash; grant schema deadbyte.host-grant.v2 includes instance_nonce and granted_at_utc but no scoped IDs.",
|
|
12
|
+
"revocation": "R64 controller arm/disarm replace/delete grant files but expose no durable monotonic per-plane revocation epoch or transaction-owned temporary revoke. An absent grant after temporary revoke cannot prove no independent user revoke occurred."
|
|
13
|
+
},
|
|
14
|
+
"selected_method": {
|
|
15
|
+
"policy_envelope": "Derive canonical authority-bearing fields from each known policy schema; omit only operational grant/evidence storage paths and presentation descriptions. Unknown fields fail closed. Raw policy SHA remains evidence, not the sole ceiling comparator.",
|
|
16
|
+
"comparison": "EQUAL, NARROWER, WIDER, UNVERIFIED. Added capabilities, relaxed deny rules and larger ceilings are WIDER. Changed executable/native pins or disjoint roots are UNVERIFIED. Both deny automatic restoration.",
|
|
17
|
+
"r64_predecessor_continuity": "Because R64 has no durable revocation epoch, an armed predecessor cannot receive automatic cross-generation restoration. Outcome must be REAUTH_REQUIRED and disarmed unless a later explicit user grant is observed.",
|
|
18
|
+
"updater_boundary": "One restoration engine is required. The current inner updater's Process/Coding/Autonomous re-arm must be disabled or constrained by a verified continuity plan before any R65 activation with standing authority is permitted.",
|
|
19
|
+
"current_safety_guard": "scripts/deploy-r48.mjs --preflight returns AUTHORITY_POLICY_UNVERIFIED for armed vectors before opening an update transaction. This guard must not be removed until continuity integration is proven."
|
|
20
|
+
},
|
|
21
|
+
"acceptance_open": [
|
|
22
|
+
"Read-only capture of exact grant bytes and scope, bound to predecessor release/generation and candidate manifest.",
|
|
23
|
+
"Durable transaction-owned revocation epoch with crash-safe exclusion of external revocation/replacement.",
|
|
24
|
+
"Single restoration decision path across updater and deploy; separate runtime and authority outcomes.",
|
|
25
|
+
"Isolated end-to-end activation, interruption, rollback and independent receipt verification."
|
|
26
|
+
]
|
|
27
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": "deadbyte.r65-reference-gap-matrix.v1",
|
|
3
|
+
"purpose": "Release/control-plane mechanisms only; donor source is read-only and no donor bytes are copied.",
|
|
4
|
+
"license_review": {
|
|
5
|
+
"better-remote-commander": "package.json declares MIT; no source bytes copied",
|
|
6
|
+
"cua": "pyproject.toml declares MIT; no source bytes copied",
|
|
7
|
+
"desktop-commander": "root LICENSE declares MIT; no source bytes copied",
|
|
8
|
+
"open-remote-mcp": "no root LICENSE or package declaration confirmed in this pass; architecture principle only, no source bytes copied",
|
|
9
|
+
"remcp": "package.json declares MIT; no source bytes copied",
|
|
10
|
+
"secure-host-mcp": "package.json declares MIT; no source bytes copied",
|
|
11
|
+
"winremote-mcp": "pyproject.toml declares MIT; no source bytes copied"
|
|
12
|
+
},
|
|
13
|
+
"decisions": [
|
|
14
|
+
{"reference":"better-remote-commander","evidence_path":"packages/agent/src/transport/ws-client.ts","mechanism":"bounded exponential reconnect and explicit unauthorized branch","deadbyte_comparison":"R64 has remote guardian and recovery, but npm visibility after accepted publish was not reconciled","decision":"ADAPT","r65_action":"bounded registry availability polling and terminal/unknown classification; no relay or multi-device import"},
|
|
15
|
+
{"reference":"cua","evidence_path":"rfcs/3007-cua-driver-lifecycle-sessions.md","mechanism":"idempotent lifecycle cleanup and host-held resume identity","deadbyte_comparison":"DEADBYTE has owned supervisor and signed transaction evidence; deterministic precondition failures still need terminality","decision":"ADAPT","r65_action":"preflight/transaction boundary tests and exact ownership preservation; no desktop redesign"},
|
|
16
|
+
{"reference":"desktop-commander","evidence_path":"dist/utils/toolHistory.js","mechanism":"bounded presentation history and trim target","deadbyte_comparison":"DEADBYTE evidence durability and bounded LIVELOG are stronger for authoritative release receipts","decision":"KEEP-OURS","r65_action":"do not batch or trim authoritative transaction journals"},
|
|
17
|
+
{"reference":"open-remote-mcp","evidence_path":"docs/ARCHITECTURE.md","mechanism":"relay policy may narrow but local device remains final enforcement","deadbyte_comparison":"DEADBYTE already enforces local authority planes; activation restore must preserve exact vector","decision":"KEEP-OURS","r65_action":"regress no-widening during activation orchestration"},
|
|
18
|
+
{"reference":"remcp","evidence_path":"packages/client/test/cli-update-runtime.test.mjs","mechanism":"separate client/runtime update and coherence checks","deadbyte_comparison":"DEADBYTE has immutable slots and version binding; exact-version npm invocation needs reproducible tests","decision":"ADAPT","r65_action":"CLI/package resolution matrix and isolated install test without runtime dependency"},
|
|
19
|
+
{"reference":"secure-host-mcp","evidence_path":"src/runtime.ts","mechanism":"explicit bounded runtime state vocabulary","deadbyte_comparison":"DEADBYTE has verified identities but activation preflight was not a separate read-only state classification","decision":"ADAPT","r65_action":"typed preflight classification; reject dirty/unknown state before mutation"},
|
|
20
|
+
{"reference":"winremote-mcp","evidence_path":"src/winremote/process_mgr.py","mechanism":"Windows process enumeration with stale-process handling","deadbyte_comparison":"DEADBYTE ledger binds PID to creation identity and hash, stronger than PID/name kill paths","decision":"SKIP","r65_action":"retain verified ownership; never adopt caller-selected PID/name termination"}
|
|
21
|
+
]
|
|
22
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "deadbyte-mcp",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.42",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Authenticated MCP agentic runtime with signed skills, persistent model backends, identity-bound remote devices, durable job supervision, immutable release slots, and separately revocable machine authority.",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"node": ">=22"
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
|
-
"test": "node --test test/*.test.mjs",
|
|
11
|
+
"test": "node --test --test-concurrency=4 test/*.test.mjs",
|
|
12
12
|
"manifest:write": "node scripts/release-manifest.mjs write",
|
|
13
13
|
"manifest:verify": "node scripts/release-manifest.mjs verify",
|
|
14
14
|
"r41:parent:verify": "node scripts/verify-r41-parent.mjs",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"contained:run": "node src/contained-cli.mjs workspaces/demo input.txt",
|
|
43
43
|
"contained:smoke": "node src/contained-smoke.mjs",
|
|
44
44
|
"mcp:contained:smoke": "node src/mcp-contained-smoke-client.mjs",
|
|
45
|
-
"gate:windows": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/gate-windows-
|
|
45
|
+
"gate:windows": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/gate-windows-r65-prepublish.ps1",
|
|
46
46
|
"authority:smoke": "node src/authority-smoke.mjs",
|
|
47
47
|
"mcp:remote:smoke": "node src/remote-mcp-smoke-client.mjs",
|
|
48
48
|
"mcp:host:smoke": "node src/mcp-host-smoke-client.mjs",
|
|
@@ -89,7 +89,8 @@
|
|
|
89
89
|
"r61:focused:test": "node --test --test-concurrency=1 test/r61-release-contract.test.mjs test/r61-release-bridge-binding.test.mjs test/r61-control-lane.test.mjs test/r61-live-timeline-bounds.test.mjs test/r61-npm-artifact-identity.test.mjs test/remote-live-log-r37.test.mjs test/bridge-runtime-r59.test.mjs test/commander-schema-differential-r48.test.mjs test/package-boundary.test.mjs test/r60-bridge-dispatch.test.mjs test/r60-authority-enforcement.test.mjs",
|
|
90
90
|
"r62:focused:test": "node --test --test-concurrency=1 test/r62-release-contract.test.mjs test/r62-doctor-transactions-reconcile.test.mjs test/r62-doctor-receipt-semantics.test.mjs test/r62-rollback-failure-receipt.test.mjs test/r58-doctor-transactions.test.mjs test/r58-completed-update-receipt.test.mjs test/runtime-self-update.test.mjs test/r56-rollback-launcher-restore.test.mjs",
|
|
91
91
|
"r63:focused:test": "node --test --test-concurrency=1 test/r63-release-contract.test.mjs test/r63-one-shot-coherence.test.mjs test/r51-runtime-coherence.test.mjs test/remote-session-cli.test.mjs",
|
|
92
|
-
"r64:focused:test": "node --test --test-concurrency=1 test/r64-release-contract.test.mjs test/r64-machine-fs-large-read.test.mjs test/machine-fs-runtime.test.mjs test/compact-gateway-r36.test.mjs test/r61-control-lane.test.mjs test/r60-bridge-dispatch.test.mjs"
|
|
92
|
+
"r64:focused:test": "node --test --test-concurrency=1 test/r64-release-contract.test.mjs test/r64-machine-fs-large-read.test.mjs test/machine-fs-runtime.test.mjs test/compact-gateway-r36.test.mjs test/r61-control-lane.test.mjs test/r60-bridge-dispatch.test.mjs",
|
|
93
|
+
"r65:focused:test": "node scripts/r65-focused.mjs"
|
|
93
94
|
},
|
|
94
95
|
"bundleDependencies": [
|
|
95
96
|
"@modelcontextprotocol/server",
|
package/scripts/deploy-r48.mjs
CHANGED
|
@@ -1,17 +1,91 @@
|
|
|
1
|
-
import { createHash } from 'node:crypto';
|
|
2
|
-
import { readFile, access } from 'node:fs/promises';
|
|
1
|
+
import { createHash,randomBytes } from 'node:crypto';
|
|
2
|
+
import { readFile, access,open,mkdir,unlink,lstat } from 'node:fs/promises';
|
|
3
3
|
import os from 'node:os';
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
import { spawnSync } from 'node:child_process';
|
|
6
6
|
import { fileURLToPath } from 'node:url';
|
|
7
|
-
import { runSlotUpdateCli } from '../src/runtime-update.mjs';
|
|
7
|
+
import { runSlotUpdateCli,windowsPowerShellEnvironment,loadPowerShellDataFile } from '../src/runtime-update.mjs';
|
|
8
8
|
import { parseActivePointer } from '../src/release-slot.mjs';
|
|
9
|
+
import {parseAuthorityObservation} from '../src/remote-authority.mjs';
|
|
10
|
+
import {classifyActivationPreflight,classifyAuthorityContinuity,orchestrateActivation} from '../src/activation-preflight-r65.mjs';
|
|
11
|
+
import {createEpochNativeContinuityEngine} from '../src/activation-continuity-engine-r65.mjs';
|
|
12
|
+
import {createActivationClaimManager} from '../src/activation-lock-r65.mjs';
|
|
9
13
|
|
|
10
14
|
const root=path.resolve(path.dirname(fileURLToPath(import.meta.url)),'..');
|
|
11
15
|
const state=path.resolve(process.env.DEADBYTE_STATE_ROOT||path.join(os.homedir(),'.deadbyte-mcp'));
|
|
12
16
|
const sha=async f=>createHash('sha256').update(await readFile(f)).digest('hex');
|
|
13
17
|
const sleep=ms=>new Promise(resolve=>setTimeout(resolve,ms));
|
|
14
18
|
|
|
19
|
+
async function writeExclusive(file,value){
|
|
20
|
+
const handle=await open(file,'wx',0o600);
|
|
21
|
+
try{await handle.writeFile(JSON.stringify(value)+'\n');await handle.sync();}
|
|
22
|
+
finally{await handle.close();}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const activationClaimManager=createActivationClaimManager({stateRoot:state});
|
|
26
|
+
let activationClaimOperationId=null;
|
|
27
|
+
|
|
28
|
+
async function claimActivation(subjectSha256){
|
|
29
|
+
const claim=await activationClaimManager.claim(subjectSha256);
|
|
30
|
+
activationClaimOperationId=claim.operation_id;
|
|
31
|
+
return claim.release;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async function activePolicyPaths(){
|
|
35
|
+
const active=parseActivePointer(await readFile(path.join(state,'active-release.json'),'utf8'));
|
|
36
|
+
const config=await loadPowerShellDataFile(active.config_path);
|
|
37
|
+
const fields={process:'ProcessPolicyFile',coding:'CodingPolicyFile',autonomous:'AutonomousPolicyFile',desktop:'DesktopPolicyFile',host:'HostPolicyFile'};
|
|
38
|
+
return Object.fromEntries(Object.entries(fields).map(([plane,key])=>{
|
|
39
|
+
const file=config[key];
|
|
40
|
+
return [plane,typeof file==='string'&&path.isAbsolute(file)?path.resolve(file):null];
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async function observeController(){
|
|
45
|
+
const launcher=path.join(state,'bin','DEADBYTE-MCP.ps1');
|
|
46
|
+
const powershell=path.join(process.env.SystemRoot||'C:\\Windows','System32','WindowsPowerShell','v1.0','powershell.exe');
|
|
47
|
+
const run=spawnSync(powershell,['-NoLogo','-NoProfile','-ExecutionPolicy','Bypass','-File',launcher,'status','-Json'],{
|
|
48
|
+
cwd:root,env:windowsPowerShellEnvironment(),encoding:'utf8',timeout:20000,stdio:['ignore','pipe','pipe'],windowsHide:true});
|
|
49
|
+
if(run.error||run.status!==0)throw new Error(`activation preflight controller observation failed exit=${run.status} code=${run.error?.code??'none'}`);
|
|
50
|
+
const observed=parseAuthorityObservation(run.stdout);
|
|
51
|
+
const active=parseActivePointer(await readFile(path.join(state,'active-release.json'),'utf8'));
|
|
52
|
+
const policyPaths=await activePolicyPaths(),policySha256={};
|
|
53
|
+
for(const [plane,file] of Object.entries(policyPaths)){
|
|
54
|
+
if(!observed.authority[plane].configured){policySha256[plane]=null;continue;}
|
|
55
|
+
if(typeof file!=='string'||!path.isAbsolute(file))throw new Error(`activation ${plane} policy path missing`);
|
|
56
|
+
const info=await lstat(file);
|
|
57
|
+
if(!info.isFile()||info.isSymbolicLink())throw new Error(`activation ${plane} policy must be a regular file`);
|
|
58
|
+
policySha256[plane]=await sha(file);
|
|
59
|
+
}
|
|
60
|
+
return {...observed,policy_sha256:policySha256,policy_paths:policyPaths,active_release_id:active.release_id,active_manifest_sha256:active.manifest_sha256,
|
|
61
|
+
active_generation_manifest_sha256:active.generation_manifest_sha256};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function controllerCommand(command){
|
|
65
|
+
if(!/^(?:arm|disarm)(?:process|coding|autonomous|desktop|host)$|^supervisorstop$|^stop$/.test(command))throw new Error('activation controller command not declared');
|
|
66
|
+
const launcher=path.join(state,'bin','DEADBYTE-MCP.ps1');
|
|
67
|
+
const powershell=path.join(process.env.SystemRoot||'C:\\Windows','System32','WindowsPowerShell','v1.0','powershell.exe');
|
|
68
|
+
const run=spawnSync(powershell,['-NoLogo','-NoProfile','-ExecutionPolicy','Bypass','-File',launcher,command],{
|
|
69
|
+
cwd:root,env:windowsPowerShellEnvironment(),encoding:'utf8',timeout:30000,stdio:['ignore','pipe','pipe'],windowsHide:true});
|
|
70
|
+
if(run.error||run.status!==0)throw new Error(`activation controller ${command} failed exit=${run.status} code=${run.error?.code??'none'}`);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async function activationPreflight(manifest,pkg,pointer){
|
|
74
|
+
const release=JSON.parse(await readFile(path.join(root,'RELEASE.json'),'utf8'));
|
|
75
|
+
const observed=await observeController();
|
|
76
|
+
const result=classifyActivationPreflight({pointer,expectedParent:release.parent,
|
|
77
|
+
candidate:{version:pkg.version,manifest_sha256:manifest},
|
|
78
|
+
expectedCandidate:{version:release.version,manifest_sha256:manifest},observation:observed});
|
|
79
|
+
const continuity=classifyAuthorityContinuity(observed);
|
|
80
|
+
if(continuity.state==='UNVERIFIED')return {...result,state:'AUTHORITY_CONTINUITY_UNVERIFIED',safe_to_activate:false,
|
|
81
|
+
reason:continuity.reason??'authority continuity observation unverified',authority_continuity:'UNVERIFIED',reauth_planes:continuity.reauth_planes??[]};
|
|
82
|
+
if(continuity.state==='EPOCH_NATIVE')return {...result,authority_continuity:'EPOCH_NATIVE',
|
|
83
|
+
epoch_planes:continuity.epoch_planes??[],reauth_planes:[]};
|
|
84
|
+
if(continuity.state==='LEGACY_REAUTH_REQUIRED'||continuity.state==='MIXED_REAUTH_REQUIRED')
|
|
85
|
+
return {...result,authority_continuity:'REAUTH_REQUIRED',reauth_planes:continuity.reauth_planes??continuity.armed_planes??[]};
|
|
86
|
+
return {...result,authority_continuity:'NOT_APPLICABLE',reauth_planes:[]};
|
|
87
|
+
}
|
|
88
|
+
|
|
15
89
|
async function waitForActivation({handoffPath,expectedVersion,expectedManifest,timeoutMs=900000,pollMs=1000}){
|
|
16
90
|
const evidenceDir=path.dirname(path.resolve(handoffPath));
|
|
17
91
|
const statePath=path.join(evidenceDir,'state.json');
|
|
@@ -62,6 +136,15 @@ const bridgeRoot=path.join(root,'bridge');
|
|
|
62
136
|
const bridgeScript=path.join(bridgeRoot,'src','bridge.mjs');
|
|
63
137
|
const pkg=JSON.parse(await readFile(path.join(root,'package.json'),'utf8'));
|
|
64
138
|
const expectedVersion=pkg.version;
|
|
139
|
+
const release=JSON.parse(await readFile(path.join(root,'RELEASE.json'),'utf8'));
|
|
140
|
+
const preflight=await activationPreflight(manifest,pkg,pointer);
|
|
141
|
+
if(process.argv.includes('--preflight')){
|
|
142
|
+
console.log(JSON.stringify(preflight));
|
|
143
|
+
process.exit(0);
|
|
144
|
+
}
|
|
145
|
+
if(process.argv.length>2)throw new Error('deploy accepts only --preflight');
|
|
146
|
+
if(!['ONLINE_READY','ONLINE_HOST_ARMED','PARKED_DIRTY','OFFLINE_CLEAN'].includes(preflight.state))
|
|
147
|
+
throw new Error(`activation preflight rejected: ${preflight.state} subject=${preflight.subject_sha256??'<incomplete>'}`);
|
|
65
148
|
const args=[
|
|
66
149
|
'--stage',root,'--development-root',root,'--expected-version',expectedVersion,'--expected-manifest',manifest,
|
|
67
150
|
'--process-policy',path.join(root,'controller','deadbyte-process-policy.json'),'--process-policy-sha256',await sha(path.join(root,'controller','deadbyte-process-policy.json')),
|
|
@@ -70,9 +153,40 @@ const args=[
|
|
|
70
153
|
'--bridge-root',bridgeRoot,'--bridge-script-sha256',await sha(bridgeScript),
|
|
71
154
|
'--enable-machine-fs','--enable-observation','--enable-desktop','--enable-autonomous-supervisor','--recover-offline-predecessor'
|
|
72
155
|
];
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
156
|
+
let result=null,verification=null,activationOutcomePath=null;
|
|
157
|
+
let continuityEngine=null,continuityUpdateId=null;
|
|
158
|
+
|
|
159
|
+
async function recordActivationOutcome(outcome){
|
|
160
|
+
if(typeof activationClaimOperationId!=='string')throw new Error('activation claim operation id unavailable');
|
|
161
|
+
const outcomeFile=path.join(state,'evidence','updates',`r65-activation-outcome-${Date.now()}-${randomBytes(8).toString('hex')}.json`);
|
|
162
|
+
await writeExclusive(outcomeFile,{schema:'deadbyte.r65-activation-outcome.v1',claim_operation_id:activationClaimOperationId,
|
|
163
|
+
candidate_version:expectedVersion,candidate_manifest_sha256:manifest,
|
|
164
|
+
predecessor_release_id:pointer.release_id,preflight_subject_sha256:preflight.subject_sha256,outcome,
|
|
165
|
+
update_id:result?.update_id??null,continuity_update_id:continuityUpdateId,
|
|
166
|
+
state_path:result?.state_path??null,observed_at_utc:new Date().toISOString()});
|
|
167
|
+
activationOutcomePath=outcomeFile;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if(preflight.authority_continuity==='EPOCH_NATIVE'){
|
|
171
|
+
const predecessorObservation=await observeController();
|
|
172
|
+
continuityUpdateId=`r65-${randomBytes(16).toString('hex')}`;
|
|
173
|
+
continuityEngine=createEpochNativeContinuityEngine({stateRoot:state,predecessorPolicyPaths:predecessorObservation.policy_paths,
|
|
174
|
+
successorPolicyPaths:async()=>activePolicyPaths(),updateId:continuityUpdateId});
|
|
175
|
+
}
|
|
176
|
+
const outcome=await orchestrateActivation({pointer,expectedParent:release.parent,
|
|
177
|
+
candidate:{version:expectedVersion,manifest_sha256:manifest},expectedCandidate:{version:release.version,manifest_sha256:manifest},
|
|
178
|
+
observe:async()=>observeController(),command:async command=>controllerCommand(command),claim:claimActivation,continuityEngine,
|
|
179
|
+
recordOutcome:recordActivationOutcome,
|
|
180
|
+
activate:async()=>{
|
|
181
|
+
result=await runSlotUpdateCli(args,{stateRoot:state});
|
|
182
|
+
if(!result.handed_off)throw new Error('release activation unexpectedly completed inline');
|
|
183
|
+
verification=await waitForActivation({handoffPath:result.handoff_path,expectedVersion,expectedManifest:manifest});
|
|
184
|
+
return {verified:true,release_id:verification.release_id};
|
|
185
|
+
}});
|
|
186
|
+
if(outcome.state!=='ACTIVATED'){
|
|
187
|
+
console.log(JSON.stringify({...outcome,update_id:result?.update_id??null,state_path:result?.state_path??null,outcome_path:activationOutcomePath}));
|
|
188
|
+
process.exitCode=2;
|
|
189
|
+
}else{
|
|
76
190
|
console.log(JSON.stringify({
|
|
77
191
|
status:'activated',
|
|
78
192
|
manifest_sha256:manifest,
|
|
@@ -81,5 +195,7 @@ console.log(JSON.stringify({
|
|
|
81
195
|
supervisor_pid:result.supervisor_pid,
|
|
82
196
|
release_id:verification.release_id,
|
|
83
197
|
receipt_path:verification.receiptPath,
|
|
84
|
-
state_path:verification.statePath
|
|
198
|
+
state_path:verification.statePath,
|
|
199
|
+
outcome_path:activationOutcomePath
|
|
85
200
|
},null,2));
|
|
201
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
param(
|
|
2
|
+
[ValidateSet('all','preflight','focused','full','manifest','doctor')]
|
|
3
|
+
[string]$Stage='all'
|
|
4
|
+
)
|
|
5
|
+
|
|
6
|
+
$ErrorActionPreference='Stop'
|
|
7
|
+
Set-StrictMode -Version 3.0
|
|
8
|
+
$root=Split-Path $PSScriptRoot -Parent
|
|
9
|
+
Set-Location -LiteralPath $root
|
|
10
|
+
|
|
11
|
+
function Invoke-Npm([string]$Name,[string[]]$NpmArgs){
|
|
12
|
+
Write-Host "==== $Name ===="
|
|
13
|
+
& npm.cmd @NpmArgs
|
|
14
|
+
if($LASTEXITCODE -ne 0){ throw "R65 prepublish gate failed at $Name exit=$LASTEXITCODE" }
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function Get-FileSha256([string]$File){
|
|
18
|
+
$hasher=[Security.Cryptography.SHA256]::Create()
|
|
19
|
+
try{
|
|
20
|
+
$bytes=[IO.File]::ReadAllBytes($File)
|
|
21
|
+
return (($hasher.ComputeHash($bytes) | ForEach-Object { $_.ToString('x2') }) -join '')
|
|
22
|
+
}finally{ $hasher.Dispose() }
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
$sourceRoot='D:\Projects\deadbyte-mcp\development\deadbyte-mcp-0.15.41-r64'
|
|
26
|
+
$sourceManifest='63a78ad159ad3003db3fefafcd468bef22599c829a867f4f10a46c7a20748b3e'
|
|
27
|
+
if(-not (Test-Path -LiteralPath $sourceRoot -PathType Container)){ throw 'R65 source predecessor missing' }
|
|
28
|
+
$observedSourceManifest=Get-FileSha256 (Join-Path $sourceRoot 'MANIFEST.SHA256')
|
|
29
|
+
if($observedSourceManifest -ne $sourceManifest){ throw 'R65 source predecessor manifest identity mismatch' }
|
|
30
|
+
& node (Join-Path $root 'scripts\\verify-r65-parent-source.mjs') --root $sourceRoot --expected-manifest-sha256 $sourceManifest
|
|
31
|
+
if($LASTEXITCODE -ne 0){ throw 'R65 source predecessor declared-manifest verification failed' }
|
|
32
|
+
|
|
33
|
+
$stateRoot=Join-Path $env:USERPROFILE '.deadbyte-mcp'
|
|
34
|
+
$pointer=Join-Path $stateRoot 'active-release.json'
|
|
35
|
+
if(-not (Test-Path -LiteralPath $pointer -PathType Leaf)){ throw "R65 runtime predecessor pointer missing: $pointer" }
|
|
36
|
+
$active=Get-Content -LiteralPath $pointer -Raw | ConvertFrom-Json
|
|
37
|
+
if($active.release_id -ne 'v0.15.41-63a78ad159ad3003'){ throw "R65 runtime predecessor release mismatch: $($active.release_id)" }
|
|
38
|
+
if($active.manifest_sha256 -ne '63a78ad159ad3003db3fefafcd468bef22599c829a867f4f10a46c7a20748b3e'){ throw 'R65 runtime predecessor manifest mismatch' }
|
|
39
|
+
if($active.generation_manifest_sha256 -ne '19ae2efcdcde9f80c474f0e55851d4ada51c22813d3e05af03b11acb28c3fca5'){ throw 'R65 runtime predecessor generation mismatch' }
|
|
40
|
+
if($Stage -eq 'preflight'){Write-Host '==== R65 WINDOWS GATE: PASS preflight ====';return}
|
|
41
|
+
|
|
42
|
+
if($Stage -eq 'all' -or $Stage -eq 'focused'){
|
|
43
|
+
Invoke-Npm 'r65-focused' @('run','r65:focused:test')
|
|
44
|
+
if($Stage -eq 'focused'){Write-Host '==== R65 WINDOWS GATE: PASS focused ====';return}
|
|
45
|
+
}
|
|
46
|
+
if($Stage -eq 'all' -or $Stage -eq 'full'){
|
|
47
|
+
Invoke-Npm 'full-regression' @('test')
|
|
48
|
+
if($Stage -eq 'full'){Write-Host '==== R65 WINDOWS GATE: PASS full ====';return}
|
|
49
|
+
}
|
|
50
|
+
if($Stage -eq 'all' -or $Stage -eq 'manifest'){
|
|
51
|
+
Invoke-Npm 'manifest-write' @('run','manifest:write')
|
|
52
|
+
Invoke-Npm 'manifest-verify' @('run','manifest:verify')
|
|
53
|
+
if($Stage -eq 'manifest'){Write-Host '==== R65 WINDOWS GATE: PASS manifest ====';return}
|
|
54
|
+
}
|
|
55
|
+
if($Stage -eq 'all' -or $Stage -eq 'doctor'){
|
|
56
|
+
$doctorRoot='D:\Projects\deadbyte-mcp\testing\0.15.42-r65\doctor-isolated-empty'
|
|
57
|
+
if(Test-Path -LiteralPath (Join-Path $doctorRoot 'active-release.json')){ throw 'R65 isolated doctor root unexpectedly contains a release pointer' }
|
|
58
|
+
$priorStateRoot=$env:DEADBYTE_STATE_ROOT
|
|
59
|
+
try{
|
|
60
|
+
$env:DEADBYTE_STATE_ROOT=$doctorRoot
|
|
61
|
+
Invoke-Npm 'doctor-isolated-empty-state' @('run','doctor')
|
|
62
|
+
}finally{ $env:DEADBYTE_STATE_ROOT=$priorStateRoot }
|
|
63
|
+
if($Stage -eq 'doctor'){Write-Host '==== R65 WINDOWS GATE: PASS doctor ====';return}
|
|
64
|
+
}
|
|
65
|
+
Write-Host '==== R65 PREPUBLISH WINDOWS GATE: PASS ===='
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import {createHash, randomBytes} from 'node:crypto';
|
|
2
|
+
import {mkdir, open, readFile, readdir, link, unlink} from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import {performance} from 'node:perf_hooks';
|
|
5
|
+
import {verifyPublishedTarballIdentity} from './npm-artifact-identity-r61.mjs';
|
|
6
|
+
|
|
7
|
+
const HEX64=/^[0-9a-f]{64}$/;
|
|
8
|
+
const digest=bytes=>createHash('sha256').update(bytes).digest('hex');
|
|
9
|
+
const pause=ms=>new Promise(resolve=>setTimeout(resolve,ms));
|
|
10
|
+
|
|
11
|
+
async function writeExclusive(file,value){
|
|
12
|
+
const handle=await open(file,'wx',0o600);
|
|
13
|
+
try{await handle.writeFile(JSON.stringify(value)+'\n');await handle.sync();}
|
|
14
|
+
finally{await handle.close();}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async function publishClaim(file,value){
|
|
18
|
+
const temporary=`${file}.private-${process.pid}-${randomBytes(8).toString('hex')}`;
|
|
19
|
+
try{
|
|
20
|
+
await writeExclusive(temporary,value);
|
|
21
|
+
await link(temporary,file); // Atomic, no-clobber visibility of complete bytes.
|
|
22
|
+
}finally{
|
|
23
|
+
await unlink(temporary).catch(error=>{if(error?.code!=='ENOENT')throw error;});
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function readClaim(file){
|
|
28
|
+
try{return JSON.parse(await readFile(file,'utf8'));}
|
|
29
|
+
catch(error){
|
|
30
|
+
if(error?.code==='ENOENT')return null;
|
|
31
|
+
if(error instanceof SyntaxError)return {incomplete:true};
|
|
32
|
+
throw error;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async function event(recordPath,state,detail={}){
|
|
37
|
+
const file=path.join(recordPath,`event-${Date.now()}-${randomBytes(8).toString('hex')}.json`);
|
|
38
|
+
await writeExclusive(file,{schema:'deadbyte.npm-publication-event.r65.v1',state,at_utc:new Date().toISOString(),...detail});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async function priorState(recordPath){
|
|
42
|
+
const names=(await readdir(recordPath)).filter(name=>/^event-\d+-[0-9a-f]{16}\.json$/.test(name));
|
|
43
|
+
if(names.length>1024)throw new Error('npm publication evidence event budget exceeded');
|
|
44
|
+
const states=[];
|
|
45
|
+
for(const name of names){
|
|
46
|
+
const value=JSON.parse(await readFile(path.join(recordPath,name),'utf8'));
|
|
47
|
+
if(value.schema!=='deadbyte.npm-publication-event.r65.v1')throw new Error('npm publication event schema invalid');
|
|
48
|
+
states.push(value);
|
|
49
|
+
}
|
|
50
|
+
return states;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function result(state,extra={}){return Object.freeze({state,...extra});}
|
|
54
|
+
|
|
55
|
+
// The no-clobber claim is the dispatch fence: once it exists, no invocation may
|
|
56
|
+
// submit the same immutable npm version again, even if the first process dies.
|
|
57
|
+
export async function reconcileNpmPublication({recordPath,version,manifestSha256,localBytes,publish,lookup,tags,fetchTarball,
|
|
58
|
+
timeoutMs=180000,pollMs=1500,sleep=pause,now=()=>performance.now()}){
|
|
59
|
+
if(!path.isAbsolute(recordPath)||!/^\d+\.\d+\.\d+$/.test(version)||!HEX64.test(String(manifestSha256))||!Buffer.isBuffer(localBytes)||
|
|
60
|
+
!Number.isSafeInteger(timeoutMs)||timeoutMs<0||timeoutMs>900000||!Number.isSafeInteger(pollMs)||pollMs<1||pollMs>30000||
|
|
61
|
+
[publish,lookup,tags,fetchTarball,sleep,now].some(fn=>typeof fn!=='function'))throw new Error('npm publication reconciliation inputs invalid');
|
|
62
|
+
const tarballSha256=digest(localBytes);
|
|
63
|
+
if(!HEX64.test(tarballSha256))throw new Error('npm tarball digest invalid');
|
|
64
|
+
await mkdir(recordPath,{recursive:true});
|
|
65
|
+
const claimFile=path.join(recordPath,'claim.json');
|
|
66
|
+
let claim=await readClaim(claimFile);
|
|
67
|
+
if(claim?.incomplete)return result('OUTCOME_UNKNOWN',{reason:'publication claim incomplete; manual reconciliation required'});
|
|
68
|
+
if(claim&&(claim.schema!=='deadbyte.npm-publication-claim.r65.v1'||claim.version!==version||claim.manifest_sha256!==manifestSha256||claim.tarball_sha256!==tarballSha256))
|
|
69
|
+
return result('REGISTRY_REJECTED',{reason:'local artifact differs from existing immutable publication claim'});
|
|
70
|
+
|
|
71
|
+
const observe=async()=>{
|
|
72
|
+
let published;
|
|
73
|
+
try{published=await lookup();}
|
|
74
|
+
catch(error){if(error?.code==='E404'||error?.status===404)return null;throw error;}
|
|
75
|
+
if(!published)return null;
|
|
76
|
+
let registryBytes;
|
|
77
|
+
try{registryBytes=await fetchTarball(published);}
|
|
78
|
+
catch(error){if(error?.status===404||error?.code==='E404')throw Object.assign(new Error('registry tarball is still processing'),{code:'REGISTRY_PROCESSING'});throw error;}
|
|
79
|
+
const distTags=await tags();
|
|
80
|
+
const identity=verifyPublishedTarballIdentity({version,localBytes,registryBytes,published,tags:distTags});
|
|
81
|
+
return {identity,registry:{version:published.version,integrity:published.dist?.integrity,shasum:published.dist?.shasum,
|
|
82
|
+
tarball:published.dist?.tarball,latest:distTags.latest}};
|
|
83
|
+
};
|
|
84
|
+
const check=async()=>{
|
|
85
|
+
try{const evidence=await observe();return evidence?result('REGISTRY_IDENTITY_VERIFIED',evidence):null;}
|
|
86
|
+
catch(error){
|
|
87
|
+
if(error?.code==='REGISTRY_PROCESSING')return result('REGISTRY_PROCESSING');
|
|
88
|
+
if(/metadata does not match|bytes differ|latest tag mismatch/.test(String(error?.message)))return result('REGISTRY_REJECTED',{reason:String(error.message)});
|
|
89
|
+
return result('OUTCOME_UNKNOWN',{reason:String(error?.code??error?.message??error)});
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
let observed=await check();
|
|
94
|
+
if(observed?.state==='REGISTRY_IDENTITY_VERIFIED'||observed?.state==='REGISTRY_REJECTED'){
|
|
95
|
+
if(claim)await event(recordPath,observed.state,{tarball_sha256:tarballSha256,registry:observed.registry??null});
|
|
96
|
+
return observed;
|
|
97
|
+
}
|
|
98
|
+
if(!claim){
|
|
99
|
+
if(observed)return observed; // Registry outage: do not submit while identity is unknown.
|
|
100
|
+
let created=false;
|
|
101
|
+
try{
|
|
102
|
+
await publishClaim(claimFile,{schema:'deadbyte.npm-publication-claim.r65.v1',version,manifest_sha256:manifestSha256,tarball_sha256:tarballSha256,created_at_utc:new Date().toISOString()});
|
|
103
|
+
claim={version,manifest_sha256:manifestSha256,tarball_sha256:tarballSha256};created=true;
|
|
104
|
+
}catch(error){
|
|
105
|
+
if(error?.code!=='EEXIST')throw error;
|
|
106
|
+
claim=await readClaim(claimFile);
|
|
107
|
+
if(claim?.incomplete||!claim)return result('OUTCOME_UNKNOWN',{reason:'concurrent publication claim unavailable or incomplete'});
|
|
108
|
+
if(claim.version!==version||claim.manifest_sha256!==manifestSha256||claim.tarball_sha256!==tarballSha256)return result('REGISTRY_REJECTED',{reason:'concurrent publication claim differs'});
|
|
109
|
+
}
|
|
110
|
+
// Only the creator of the claim may dispatch publish.
|
|
111
|
+
if(created){
|
|
112
|
+
await event(recordPath,'SUBMISSION_STARTED',{tarball_sha256:tarballSha256});
|
|
113
|
+
try{
|
|
114
|
+
await publish();
|
|
115
|
+
await event(recordPath,'SUBMISSION_ACCEPTED',{tarball_sha256:tarballSha256});
|
|
116
|
+
}catch(error){
|
|
117
|
+
const auth=/E401|E403|EOTP|authentication|one-time password|2FA/i.test(String(error?.code??'')+' '+String(error?.message??''));
|
|
118
|
+
await event(recordPath,auth?'AUTH_REQUIRED':'OUTCOME_UNKNOWN',{error_code:String(error?.code??'UNKNOWN').slice(0,64)});
|
|
119
|
+
return result(auth?'AUTH_REQUIRED':'OUTCOME_UNKNOWN',{reason:String(error?.code??error?.message??error)});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
const states=await priorState(recordPath);
|
|
124
|
+
if(states.some(item=>item.state==='AUTH_REQUIRED'))return result('AUTH_REQUIRED');
|
|
125
|
+
const accepted=states.some(item=>item.state==='SUBMISSION_ACCEPTED');
|
|
126
|
+
const started=now();
|
|
127
|
+
do{
|
|
128
|
+
observed=await check();
|
|
129
|
+
if(observed?.state==='REGISTRY_IDENTITY_VERIFIED'||observed?.state==='REGISTRY_REJECTED'){
|
|
130
|
+
await event(recordPath,observed.state,{tarball_sha256:tarballSha256,registry:observed.registry??null});return observed;
|
|
131
|
+
}
|
|
132
|
+
if(observed?.state==='OUTCOME_UNKNOWN')return observed;
|
|
133
|
+
const remaining=timeoutMs-(now()-started);
|
|
134
|
+
if(remaining<=0)break;
|
|
135
|
+
await sleep(Math.min(pollMs,remaining));
|
|
136
|
+
}while(true);
|
|
137
|
+
await event(recordPath,accepted?'REGISTRY_PROCESSING':'OUTCOME_UNKNOWN',{tarball_sha256:tarballSha256});
|
|
138
|
+
return result(accepted?'REGISTRY_PROCESSING':'OUTCOME_UNKNOWN');
|
|
139
|
+
}
|