opensip-cli 0.1.6 → 0.1.8
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/bootstrap/admit-tool-package.d.ts.map +1 -1
- package/dist/bootstrap/admit-tool-package.js +8 -3
- package/dist/bootstrap/admit-tool-package.js.map +1 -1
- package/dist/bootstrap/bind-tool-context.d.ts.map +1 -1
- package/dist/bootstrap/bind-tool-context.js +5 -3
- package/dist/bootstrap/bind-tool-context.js.map +1 -1
- package/dist/bootstrap/build-command-registration-input.d.ts +7 -0
- package/dist/bootstrap/build-command-registration-input.d.ts.map +1 -1
- package/dist/bootstrap/build-command-registration-input.js +11 -4
- package/dist/bootstrap/build-command-registration-input.js.map +1 -1
- package/dist/bootstrap/build-per-run-scope.d.ts +12 -0
- package/dist/bootstrap/build-per-run-scope.d.ts.map +1 -1
- package/dist/bootstrap/build-per-run-scope.js +92 -10
- package/dist/bootstrap/build-per-run-scope.js.map +1 -1
- package/dist/bootstrap/bundled-manifest.d.ts +5 -0
- package/dist/bootstrap/bundled-manifest.d.ts.map +1 -0
- package/dist/bootstrap/bundled-manifest.js +13 -0
- package/dist/bootstrap/bundled-manifest.js.map +1 -0
- package/dist/bootstrap/bundled-tools.manifest.json +19 -1
- package/dist/bootstrap/config-and-capabilities.d.ts.map +1 -1
- package/dist/bootstrap/config-and-capabilities.js +5 -4
- package/dist/bootstrap/config-and-capabilities.js.map +1 -1
- package/dist/bootstrap/constants.d.ts +3 -0
- package/dist/bootstrap/constants.d.ts.map +1 -0
- package/dist/bootstrap/constants.js +3 -0
- package/dist/bootstrap/constants.js.map +1 -0
- package/dist/bootstrap/decorate-tool-primary.d.ts +50 -0
- package/dist/bootstrap/decorate-tool-primary.d.ts.map +1 -0
- package/dist/bootstrap/decorate-tool-primary.js +111 -0
- package/dist/bootstrap/decorate-tool-primary.js.map +1 -0
- package/dist/bootstrap/execute-post-bailout-bootstrap.d.ts.map +1 -1
- package/dist/bootstrap/execute-post-bailout-bootstrap.js +10 -0
- package/dist/bootstrap/execute-post-bailout-bootstrap.js.map +1 -1
- package/dist/bootstrap/index.d.ts +7 -1
- package/dist/bootstrap/index.d.ts.map +1 -1
- package/dist/bootstrap/index.js +15 -6
- package/dist/bootstrap/index.js.map +1 -1
- package/dist/bootstrap/io-plane.d.ts +47 -0
- package/dist/bootstrap/io-plane.d.ts.map +1 -0
- package/dist/bootstrap/io-plane.js +73 -0
- package/dist/bootstrap/io-plane.js.map +1 -0
- package/dist/bootstrap/load-tool-capabilities.d.ts.map +1 -1
- package/dist/bootstrap/load-tool-capabilities.js +18 -2
- package/dist/bootstrap/load-tool-capabilities.js.map +1 -1
- package/dist/bootstrap/owning-tool-init.d.ts.map +1 -1
- package/dist/bootstrap/owning-tool-init.js +7 -4
- package/dist/bootstrap/owning-tool-init.js.map +1 -1
- package/dist/bootstrap/phase-map.d.ts +20 -0
- package/dist/bootstrap/phase-map.d.ts.map +1 -0
- package/dist/bootstrap/phase-map.js +108 -0
- package/dist/bootstrap/phase-map.js.map +1 -0
- package/dist/bootstrap/pre-action-hook.d.ts.map +1 -1
- package/dist/bootstrap/pre-action-hook.js +24 -2
- package/dist/bootstrap/pre-action-hook.js.map +1 -1
- package/dist/bootstrap/register-tools-discovery.d.ts +42 -59
- package/dist/bootstrap/register-tools-discovery.d.ts.map +1 -1
- package/dist/bootstrap/register-tools-discovery.js +175 -97
- package/dist/bootstrap/register-tools-discovery.js.map +1 -1
- package/dist/bootstrap/register-tools-mount.d.ts +18 -1
- package/dist/bootstrap/register-tools-mount.d.ts.map +1 -1
- package/dist/bootstrap/register-tools-mount.js +118 -18
- package/dist/bootstrap/register-tools-mount.js.map +1 -1
- package/dist/bootstrap/register-tools.d.ts +58 -14
- package/dist/bootstrap/register-tools.d.ts.map +1 -1
- package/dist/bootstrap/register-tools.js +185 -14
- package/dist/bootstrap/register-tools.js.map +1 -1
- package/dist/bootstrap/root-version.d.ts +26 -0
- package/dist/bootstrap/root-version.d.ts.map +1 -0
- package/dist/bootstrap/root-version.js +36 -0
- package/dist/bootstrap/root-version.js.map +1 -0
- package/dist/bootstrap/scope-access.d.ts +26 -1
- package/dist/bootstrap/scope-access.d.ts.map +1 -1
- package/dist/bootstrap/scope-access.js +38 -1
- package/dist/bootstrap/scope-access.js.map +1 -1
- package/dist/bootstrap/skip-installed-plugins.d.ts +23 -0
- package/dist/bootstrap/skip-installed-plugins.d.ts.map +1 -0
- package/dist/bootstrap/skip-installed-plugins.js +30 -0
- package/dist/bootstrap/skip-installed-plugins.js.map +1 -0
- package/dist/bootstrap/tool-lifecycle.d.ts +0 -22
- package/dist/bootstrap/tool-lifecycle.d.ts.map +1 -1
- package/dist/bootstrap/tool-lifecycle.js +0 -23
- package/dist/bootstrap/tool-lifecycle.js.map +1 -1
- package/dist/bootstrap/tool-trust.d.ts +22 -2
- package/dist/bootstrap/tool-trust.d.ts.map +1 -1
- package/dist/bootstrap/tool-trust.js +25 -2
- package/dist/bootstrap/tool-trust.js.map +1 -1
- package/dist/bootstrap/validate-tool.d.ts +10 -4
- package/dist/bootstrap/validate-tool.d.ts.map +1 -1
- package/dist/bootstrap/validate-tool.js +76 -22
- package/dist/bootstrap/validate-tool.js.map +1 -1
- package/dist/cli-context.d.ts +2 -2
- package/dist/cli-context.d.ts.map +1 -1
- package/dist/cli-context.js +20 -35
- package/dist/cli-context.js.map +1 -1
- package/dist/commands/agent-catalog.d.ts +29 -0
- package/dist/commands/agent-catalog.d.ts.map +1 -1
- package/dist/commands/agent-catalog.js +77 -36
- package/dist/commands/agent-catalog.js.map +1 -1
- package/dist/commands/clear.d.ts.map +1 -1
- package/dist/commands/clear.js +0 -1
- package/dist/commands/clear.js.map +1 -1
- package/dist/commands/command-scope-index.d.ts +15 -1
- package/dist/commands/command-scope-index.d.ts.map +1 -1
- package/dist/commands/command-scope-index.js +10 -1
- package/dist/commands/command-scope-index.js.map +1 -1
- package/dist/commands/completion.d.ts +67 -6
- package/dist/commands/completion.d.ts.map +1 -1
- package/dist/commands/completion.js +84 -12
- package/dist/commands/completion.js.map +1 -1
- package/dist/commands/configure.d.ts.map +1 -1
- package/dist/commands/configure.js +0 -1
- package/dist/commands/configure.js.map +1 -1
- package/dist/commands/host-command-specs.d.ts +16 -9
- package/dist/commands/host-command-specs.d.ts.map +1 -1
- package/dist/commands/host-command-specs.js +45 -19
- package/dist/commands/host-command-specs.js.map +1 -1
- package/dist/commands/host-config-flag.d.ts +21 -0
- package/dist/commands/host-config-flag.d.ts.map +1 -0
- package/dist/commands/host-config-flag.js +21 -0
- package/dist/commands/host-config-flag.js.map +1 -0
- package/dist/commands/host-subcommand-groups.d.ts +46 -5
- package/dist/commands/host-subcommand-groups.d.ts.map +1 -1
- package/dist/commands/host-subcommand-groups.js +97 -65
- package/dist/commands/host-subcommand-groups.js.map +1 -1
- package/dist/commands/index.d.ts +1 -1
- package/dist/commands/index.js +1 -1
- package/dist/commands/internal-command-visibility.d.ts +42 -0
- package/dist/commands/internal-command-visibility.d.ts.map +1 -0
- package/dist/commands/internal-command-visibility.js +54 -0
- package/dist/commands/internal-command-visibility.js.map +1 -0
- package/dist/commands/mount-command-action.d.ts +5 -0
- package/dist/commands/mount-command-action.d.ts.map +1 -1
- package/dist/commands/mount-command-action.js +26 -2
- package/dist/commands/mount-command-action.js.map +1 -1
- package/dist/commands/mount-command-spec.d.ts +9 -2
- package/dist/commands/mount-command-spec.d.ts.map +1 -1
- package/dist/commands/mount-command-spec.js +9 -1
- package/dist/commands/mount-command-spec.js.map +1 -1
- package/dist/commands/plugin/domain-resolution.d.ts +12 -13
- package/dist/commands/plugin/domain-resolution.d.ts.map +1 -1
- package/dist/commands/plugin/domain-resolution.js +12 -58
- package/dist/commands/plugin/domain-resolution.js.map +1 -1
- package/dist/commands/plugin/host-dir.d.ts +0 -1
- package/dist/commands/plugin/host-dir.d.ts.map +1 -1
- package/dist/commands/plugin/host-dir.js +1 -1
- package/dist/commands/plugin/host-dir.js.map +1 -1
- package/dist/commands/plugin.d.ts +20 -14
- package/dist/commands/plugin.d.ts.map +1 -1
- package/dist/commands/plugin.js +39 -47
- package/dist/commands/plugin.js.map +1 -1
- package/dist/commands/render-outcome.d.ts.map +1 -1
- package/dist/commands/render-outcome.js.map +1 -1
- package/dist/commands/shared.d.ts +9 -0
- package/dist/commands/shared.d.ts.map +1 -1
- package/dist/commands/tools/create.d.ts +11 -0
- package/dist/commands/tools/create.d.ts.map +1 -0
- package/dist/commands/tools/create.js +84 -0
- package/dist/commands/tools/create.js.map +1 -0
- package/dist/commands/tools/index.d.ts.map +1 -1
- package/dist/commands/tools/index.js +31 -0
- package/dist/commands/tools/index.js.map +1 -1
- package/dist/commands/tools/runtime-probe-entry.d.ts.map +1 -1
- package/dist/commands/tools/runtime-probe-entry.js +4 -2
- package/dist/commands/tools/runtime-probe-entry.js.map +1 -1
- package/dist/commands/tools/validate.d.ts.map +1 -1
- package/dist/commands/tools/validate.js +12 -5
- package/dist/commands/tools/validate.js.map +1 -1
- package/dist/commands/uninstall.d.ts.map +1 -1
- package/dist/commands/uninstall.js +0 -1
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/env/host-env-specs.d.ts +18 -0
- package/dist/env/host-env-specs.d.ts.map +1 -1
- package/dist/env/host-env-specs.js +58 -2
- package/dist/env/host-env-specs.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +33 -11
- package/dist/index.js.map +1 -1
- package/dist/report-compose.d.ts.map +1 -1
- package/dist/report-compose.js +2 -2
- package/dist/report-compose.js.map +1 -1
- package/dist/session-replay-registry.d.ts +1 -1
- package/dist/session-replay-registry.d.ts.map +1 -1
- package/dist/session-replay-registry.js +3 -1
- package/dist/session-replay-registry.js.map +1 -1
- package/dist/telemetry/command-label.d.ts +19 -0
- package/dist/telemetry/command-label.d.ts.map +1 -0
- package/dist/telemetry/command-label.js +26 -0
- package/dist/telemetry/command-label.js.map +1 -0
- package/dist/telemetry/sdk-init.d.ts +9 -0
- package/dist/telemetry/sdk-init.d.ts.map +1 -1
- package/dist/telemetry/sdk-init.js +32 -0
- package/dist/telemetry/sdk-init.js.map +1 -1
- package/dist/ui/result-to-view.d.ts +27 -7
- package/dist/ui/result-to-view.d.ts.map +1 -1
- package/dist/ui/result-to-view.js +68 -75
- package/dist/ui/result-to-view.js.map +1 -1
- package/dist/ui/views/misc-views.d.ts.map +1 -1
- package/dist/ui/views/misc-views.js +3 -1
- package/dist/ui/views/misc-views.js.map +1 -1
- package/dist/ui/views/tools-views.d.ts +2 -1
- package/dist/ui/views/tools-views.d.ts.map +1 -1
- package/dist/ui/views/tools-views.js +29 -0
- package/dist/ui/views/tools-views.js.map +1 -1
- package/package.json +32 -32
- package/dist/bootstrap/authored-tool-admission.d.ts +0 -23
- package/dist/bootstrap/authored-tool-admission.d.ts.map +0 -1
- package/dist/bootstrap/authored-tool-admission.js +0 -54
- package/dist/bootstrap/authored-tool-admission.js.map +0 -1
- package/dist/bootstrap/egress-plane.d.ts +0 -22
- package/dist/bootstrap/egress-plane.d.ts.map +0 -1
- package/dist/bootstrap/egress-plane.js +0 -37
- package/dist/bootstrap/egress-plane.js.map +0 -1
- package/dist/bootstrap/installed-tool-admission.d.ts +0 -20
- package/dist/bootstrap/installed-tool-admission.d.ts.map +0 -1
- package/dist/bootstrap/installed-tool-admission.js +0 -60
- package/dist/bootstrap/installed-tool-admission.js.map +0 -1
- package/dist/bootstrap/live-plane.d.ts +0 -51
- package/dist/bootstrap/live-plane.d.ts.map +0 -1
- package/dist/bootstrap/live-plane.js +0 -72
- package/dist/bootstrap/live-plane.js.map +0 -1
- package/dist/bootstrap/register-tools-bundled.d.ts +0 -28
- package/dist/bootstrap/register-tools-bundled.d.ts.map +0 -1
- package/dist/bootstrap/register-tools-bundled.js +0 -107
- package/dist/bootstrap/register-tools-bundled.js.map +0 -1
- package/dist/bootstrap/register-tools-shared.d.ts +0 -40
- package/dist/bootstrap/register-tools-shared.d.ts.map +0 -1
- package/dist/bootstrap/register-tools-shared.js +0 -98
- package/dist/bootstrap/register-tools-shared.js.map +0 -1
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single orchestration vocabulary: maps lifecycle steps, pre-action phases, and
|
|
3
|
+
* the implementing modules. Replaces parallel taxonomies in tool-lifecycle.ts
|
|
4
|
+
* and pre-action-bootstrap-phases.ts as the one source of truth.
|
|
5
|
+
*/
|
|
6
|
+
import { PRE_ACTION_PHASES } from './pre-action-bootstrap-phases.js';
|
|
7
|
+
import { TOOL_LIFECYCLE_STEPS } from './tool-lifecycle.js';
|
|
8
|
+
/**
|
|
9
|
+
* Canonical phase map. Startup steps 1–4 live in `bootstrapCli`; step 8 in
|
|
10
|
+
* `mountAllToolCommands`; steps 5–7 and 9 in the pre-action executor.
|
|
11
|
+
*/
|
|
12
|
+
export const BOOTSTRAP_PHASE_MAP = [
|
|
13
|
+
{
|
|
14
|
+
lifecycleStep: TOOL_LIFECYCLE_STEPS.discover,
|
|
15
|
+
module: 'bootstrap/index.ts',
|
|
16
|
+
symbol: 'bootstrapCli → registerFirstPartyTools / discoverAndRegisterToolPackages',
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
lifecycleStep: TOOL_LIFECYCLE_STEPS.compat,
|
|
20
|
+
module: 'bootstrap/admit-tool-package.ts',
|
|
21
|
+
symbol: 'admitToolPackage',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
lifecycleStep: TOOL_LIFECYCLE_STEPS.trust,
|
|
25
|
+
module: 'bootstrap/register-tools-discovery.ts',
|
|
26
|
+
symbol: 'admitProjectLocalTool',
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
lifecycleStep: TOOL_LIFECYCLE_STEPS.import,
|
|
30
|
+
module: 'bootstrap/validate-tool.ts',
|
|
31
|
+
symbol: 'isValidTool + ToolRegistry.register',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
lifecycleStep: TOOL_LIFECYCLE_STEPS.config,
|
|
35
|
+
preActionPhase: PRE_ACTION_PHASES.buildScope,
|
|
36
|
+
module: 'bootstrap/config-and-capabilities.ts',
|
|
37
|
+
symbol: 'composeAndValidateToolConfig',
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
lifecycleStep: TOOL_LIFECYCLE_STEPS.scope,
|
|
41
|
+
preActionPhase: PRE_ACTION_PHASES.buildScope,
|
|
42
|
+
module: 'bootstrap/build-per-run-scope.ts',
|
|
43
|
+
symbol: 'buildPerRunScope → resolveToolHooks().contributeScope',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
lifecycleStep: TOOL_LIFECYCLE_STEPS.capabilities,
|
|
47
|
+
preActionPhase: PRE_ACTION_PHASES.toolPreflight,
|
|
48
|
+
module: 'bootstrap/config-and-capabilities.ts',
|
|
49
|
+
symbol: 'wireCapabilityRegistry + loadOwningToolCapabilities',
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
lifecycleStep: TOOL_LIFECYCLE_STEPS.mount,
|
|
53
|
+
module: 'bootstrap/register-tools-mount.ts',
|
|
54
|
+
symbol: 'mountAllToolCommands (composition root)',
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
lifecycleStep: TOOL_LIFECYCLE_STEPS.initialize,
|
|
58
|
+
preActionPhase: PRE_ACTION_PHASES.toolPreflight,
|
|
59
|
+
module: 'bootstrap/owning-tool-init.ts',
|
|
60
|
+
symbol: 'maybeInitializeOwningTool',
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
lifecycleStep: TOOL_LIFECYCLE_STEPS.dispatch,
|
|
64
|
+
module: 'commands/mount-command-spec.ts',
|
|
65
|
+
symbol: 'mountCommandSpec action',
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
preActionPhase: PRE_ACTION_PHASES.readCommandOptions,
|
|
69
|
+
module: 'bootstrap/plan-pre-action-bootstrap.ts',
|
|
70
|
+
symbol: 'planPreActionBootstrap',
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
preActionPhase: PRE_ACTION_PHASES.mergeCliDefaults,
|
|
74
|
+
module: 'bootstrap/plan-pre-action-bootstrap.ts',
|
|
75
|
+
symbol: 'planPreActionBootstrap → mergeCliDefaults',
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
preActionPhase: PRE_ACTION_PHASES.resolveProject,
|
|
79
|
+
module: 'bootstrap/plan-pre-action-bootstrap.ts',
|
|
80
|
+
symbol: 'planPreActionBootstrap → resolveProjectContext',
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
preActionPhase: PRE_ACTION_PHASES.bailoutWindow,
|
|
84
|
+
module: 'bootstrap/pre-action-guards.ts',
|
|
85
|
+
symbol: 'pre-action guards',
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
preActionPhase: PRE_ACTION_PHASES.projectSideEffects,
|
|
89
|
+
module: 'bootstrap/execute-post-bailout-bootstrap.ts',
|
|
90
|
+
symbol: 'executePostBailoutBootstrap → projectSideEffects',
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
preActionPhase: PRE_ACTION_PHASES.enterScope,
|
|
94
|
+
module: 'bootstrap/execute-post-bailout-bootstrap.ts',
|
|
95
|
+
symbol: 'enterScope',
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
preActionPhase: PRE_ACTION_PHASES.hostStartEffects,
|
|
99
|
+
module: 'bootstrap/execute-post-bailout-bootstrap.ts',
|
|
100
|
+
symbol: 'executePostBailoutBootstrap → hostStartEffects',
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
preActionPhase: PRE_ACTION_PHASES.dispose,
|
|
104
|
+
module: 'bootstrap/pre-action-hook.ts',
|
|
105
|
+
symbol: 'disposeCurrentScope',
|
|
106
|
+
},
|
|
107
|
+
];
|
|
108
|
+
//# sourceMappingURL=phase-map.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"phase-map.js","sourceRoot":"","sources":["../../src/bootstrap/phase-map.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAU3D;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAA6B;IAC3D;QACE,aAAa,EAAE,oBAAoB,CAAC,QAAQ;QAC5C,MAAM,EAAE,oBAAoB;QAC5B,MAAM,EAAE,0EAA0E;KACnF;IACD;QACE,aAAa,EAAE,oBAAoB,CAAC,MAAM;QAC1C,MAAM,EAAE,iCAAiC;QACzC,MAAM,EAAE,kBAAkB;KAC3B;IACD;QACE,aAAa,EAAE,oBAAoB,CAAC,KAAK;QACzC,MAAM,EAAE,uCAAuC;QAC/C,MAAM,EAAE,uBAAuB;KAChC;IACD;QACE,aAAa,EAAE,oBAAoB,CAAC,MAAM;QAC1C,MAAM,EAAE,4BAA4B;QACpC,MAAM,EAAE,qCAAqC;KAC9C;IACD;QACE,aAAa,EAAE,oBAAoB,CAAC,MAAM;QAC1C,cAAc,EAAE,iBAAiB,CAAC,UAAU;QAC5C,MAAM,EAAE,sCAAsC;QAC9C,MAAM,EAAE,8BAA8B;KACvC;IACD;QACE,aAAa,EAAE,oBAAoB,CAAC,KAAK;QACzC,cAAc,EAAE,iBAAiB,CAAC,UAAU;QAC5C,MAAM,EAAE,kCAAkC;QAC1C,MAAM,EAAE,uDAAuD;KAChE;IACD;QACE,aAAa,EAAE,oBAAoB,CAAC,YAAY;QAChD,cAAc,EAAE,iBAAiB,CAAC,aAAa;QAC/C,MAAM,EAAE,sCAAsC;QAC9C,MAAM,EAAE,qDAAqD;KAC9D;IACD;QACE,aAAa,EAAE,oBAAoB,CAAC,KAAK;QACzC,MAAM,EAAE,mCAAmC;QAC3C,MAAM,EAAE,yCAAyC;KAClD;IACD;QACE,aAAa,EAAE,oBAAoB,CAAC,UAAU;QAC9C,cAAc,EAAE,iBAAiB,CAAC,aAAa;QAC/C,MAAM,EAAE,+BAA+B;QACvC,MAAM,EAAE,2BAA2B;KACpC;IACD;QACE,aAAa,EAAE,oBAAoB,CAAC,QAAQ;QAC5C,MAAM,EAAE,gCAAgC;QACxC,MAAM,EAAE,yBAAyB;KAClC;IACD;QACE,cAAc,EAAE,iBAAiB,CAAC,kBAAkB;QACpD,MAAM,EAAE,wCAAwC;QAChD,MAAM,EAAE,wBAAwB;KACjC;IACD;QACE,cAAc,EAAE,iBAAiB,CAAC,gBAAgB;QAClD,MAAM,EAAE,wCAAwC;QAChD,MAAM,EAAE,2CAA2C;KACpD;IACD;QACE,cAAc,EAAE,iBAAiB,CAAC,cAAc;QAChD,MAAM,EAAE,wCAAwC;QAChD,MAAM,EAAE,gDAAgD;KACzD;IACD;QACE,cAAc,EAAE,iBAAiB,CAAC,aAAa;QAC/C,MAAM,EAAE,gCAAgC;QACxC,MAAM,EAAE,mBAAmB;KAC5B;IACD;QACE,cAAc,EAAE,iBAAiB,CAAC,kBAAkB;QACpD,MAAM,EAAE,6CAA6C;QACrD,MAAM,EAAE,kDAAkD;KAC3D;IACD;QACE,cAAc,EAAE,iBAAiB,CAAC,UAAU;QAC5C,MAAM,EAAE,6CAA6C;QACrD,MAAM,EAAE,YAAY;KACrB;IACD;QACE,cAAc,EAAE,iBAAiB,CAAC,gBAAgB;QAClD,MAAM,EAAE,6CAA6C;QACrD,MAAM,EAAE,gDAAgD;KACzD;IACD;QACE,cAAc,EAAE,iBAAiB,CAAC,OAAO;QACzC,MAAM,EAAE,8BAA8B;QACtC,MAAM,EAAE,qBAAqB;KAC9B;CACO,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pre-action-hook.d.ts","sourceRoot":"","sources":["../../src/bootstrap/pre-action-hook.ts"],"names":[],"mappings":"AACA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"pre-action-hook.d.ts","sourceRoot":"","sources":["../../src/bootstrap/pre-action-hook.ts"],"names":[],"mappings":"AACA;;;;;;GAMG;AAWH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AAC5E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,YAAY,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,gBAAgB,EACzB,aAAa,EAAE,iBAAiB,GAC/B,IAAI,CA6CN;AAED,wBAAgB,mBAAmB,IAAI,IAAI,CAiB1C"}
|
|
@@ -6,14 +6,27 @@
|
|
|
6
6
|
* {@link executePostBailoutBootstrap} (phases 5–9). This module wires those
|
|
7
7
|
* to Commander's preAction/postAction hooks.
|
|
8
8
|
*/
|
|
9
|
-
import { currentScope, generatePrefixedId } from '@opensip-cli/core';
|
|
9
|
+
import { currentScope, exitScope, generatePrefixedId } from '@opensip-cli/core';
|
|
10
10
|
import { commandPath } from '../commands/command-scope-index.js';
|
|
11
|
+
import { hostEnv } from '../env/host-env-specs.js';
|
|
12
|
+
import { setResolvedCommandLabel } from '../telemetry/command-label.js';
|
|
11
13
|
import { executePostBailoutBootstrap } from './execute-post-bailout-bootstrap.js';
|
|
12
14
|
import { planPreActionBootstrap } from './plan-pre-action-bootstrap.js';
|
|
13
15
|
export { resolveOwningTool } from './owning-tool-init.js';
|
|
14
16
|
export function installPreActionHook(program, version, runtime, commandScopes) {
|
|
15
17
|
program.hook('preAction', async (_thisCommand, actionCommand) => {
|
|
16
|
-
|
|
18
|
+
// M12: stamp the RESOLVED command name for the duration metric's label
|
|
19
|
+
// (bounded cardinality) before any bootstrap that might throw — set as early
|
|
20
|
+
// as the matched command is known.
|
|
21
|
+
setResolvedCommandLabel(actionCommand.name());
|
|
22
|
+
// B1 ("Child runId behavior"): resolve `runId` env-FIRST. A forked/spawned
|
|
23
|
+
// child re-enters this hook and inherits its parent's run via `OPENSIP_RUN_ID`
|
|
24
|
+
// (set in the child env by `correlationToEnv`); a top-level invocation, with
|
|
25
|
+
// no `OPENSIP_RUN_ID` set, mints a fresh id. This is the single inheritance
|
|
26
|
+
// seam — the spec JSON deliberately never carries `runId`, because the logger
|
|
27
|
+
// that stamps every worker line is already live before the spec is parsed.
|
|
28
|
+
const inherited = hostEnv.get('OPENSIP_RUN_ID');
|
|
29
|
+
const runId = inherited && inherited.length > 0 ? inherited : generatePrefixedId('run');
|
|
17
30
|
const opts = actionCommand.opts();
|
|
18
31
|
const cwd = opts.cwd ?? process.cwd();
|
|
19
32
|
const cwdExplicit = actionCommand.getOptionValueSource('cwd') === 'cli';
|
|
@@ -49,5 +62,14 @@ export function disposeCurrentScope() {
|
|
|
49
62
|
catch {
|
|
50
63
|
// @swallow-ok dispose errors on shutdown; the run has already produced its outcome.
|
|
51
64
|
}
|
|
65
|
+
finally {
|
|
66
|
+
// Complete the per-command lifecycle: clear the ambient ALS slot so a
|
|
67
|
+
// subsequent command in the same process (a long-lived host driving
|
|
68
|
+
// Commander sequentially) starts with a clean slot and its `enterScope`
|
|
69
|
+
// does not trip the always-on re-entrancy guard against this finished run.
|
|
70
|
+
// Production runs one command per process, so this is normally the final
|
|
71
|
+
// teardown; it is a no-op when no scope is current.
|
|
72
|
+
exitScope();
|
|
73
|
+
}
|
|
52
74
|
}
|
|
53
75
|
//# sourceMappingURL=pre-action-hook.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pre-action-hook.js","sourceRoot":"","sources":["../../src/bootstrap/pre-action-hook.ts"],"names":[],"mappings":"AAAA,qOAAqO;AACrO;;;;;;GAMG;AAEH,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"pre-action-hook.js","sourceRoot":"","sources":["../../src/bootstrap/pre-action-hook.ts"],"names":[],"mappings":"AAAA,qOAAqO;AACrO;;;;;;GAMG;AAEH,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEhF,OAAO,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACnD,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAExE,OAAO,EAAE,2BAA2B,EAAE,MAAM,qCAAqC,CAAC;AAClF,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAMxE,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAG1D,MAAM,UAAU,oBAAoB,CAClC,OAAgB,EAChB,OAAe,EACf,OAAyB,EACzB,aAAgC;IAEhC,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,EAAE;QAC9D,uEAAuE;QACvE,6EAA6E;QAC7E,mCAAmC;QACnC,uBAAuB,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,CAAC;QAC9C,2EAA2E;QAC3E,+EAA+E;QAC/E,6EAA6E;QAC7E,4EAA4E;QAC5E,8EAA8E;QAC9E,2EAA2E;QAC3E,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAS,gBAAgB,CAAC,CAAC;QACxD,MAAM,KAAK,GAAG,SAAS,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC;QACxF,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,EAAE,CAAC;QAClC,MAAM,GAAG,GAAI,IAAI,CAAC,GAAc,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QAClD,MAAM,WAAW,GAAG,aAAa,CAAC,oBAAoB,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC;QAExE,MAAM,IAAI,GAAG,sBAAsB,CAAC;YAClC,IAAI,EAAE,IAAI;YACV,GAAG;YACH,WAAW;YACX,KAAK;YACL,WAAW,EAAE,aAAa,CAAC,IAAI,EAAE;YACjC,WAAW,EAAE,WAAW,CAAC,aAAa,CAAC;YACvC,aAAa;YACb,kBAAkB,EAAE,IAAI,CAAC,MAA4B;SACtD,CAAC,CAAC;QAEH,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,2BAA2B,CAAC;YAClD,IAAI;YACJ,OAAO;YACP,OAAO;YACP,iIAAiI;YACjI,OAAO,EAAE,aAAa,CAAC,eAAe,EAAE,CAAC,KAAK,KAAK,KAAK;YACxD,MAAM,EAAE,IAAI,CAAC,MAA4B;SAC1C,CAAC,CAAC;QACH,KAAK,CAAC,WAAW,CAAC,KAAK,CACrB,MAAM,EACN,OAAO,EACP,sCAAsC,aAAa,CAAC,IAAI,EAAE,GAAG,CAC9D,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,mBAAmB,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,mBAAmB;IACjC,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,YAAY,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;YACzC,CAAC,CAAC,OAAO,EAAE,CAAC;QACd,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,oFAAoF;IACtF,CAAC;YAAS,CAAC;QACT,sEAAsE;QACtE,oEAAoE;QACpE,wEAAwE;QACxE,2EAA2E;QAC3E,yEAAyE;QACzE,oDAAoD;QACpD,SAAS,EAAE,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -1,4 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* register-tools-discovery — installed + authored tool admission and discovery.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from register-tools.ts so the bundled registration path stays a
|
|
5
|
+
* focused module under the file-length soft limit.
|
|
6
|
+
*/
|
|
1
7
|
import { type ToolPluginManifest, type ToolProvenance, type ToolRegistry, type ToolDiscoverySource } from '@opensip-cli/core';
|
|
8
|
+
import { type ToolRuntimeLoad } from './admit-tool-package.js';
|
|
9
|
+
import type { ToolAdmission } from './tool-admission-types.js';
|
|
10
|
+
export type AuthoredAdmission = ToolAdmission;
|
|
11
|
+
/**
|
|
12
|
+
* Admit or reject a PROJECT-LOCAL authored tool under the deny-by-default trust
|
|
13
|
+
* policy. The trust decision always precedes module import; a non-allowlisted
|
|
14
|
+
* tool fails closed before any authored code can run.
|
|
15
|
+
*
|
|
16
|
+
* @throws {PluginIncompatibleError} When the sidecar manifest is missing,
|
|
17
|
+
* malformed, incompatible, or not trusted by the project-tool allowlist.
|
|
18
|
+
*/
|
|
19
|
+
export declare function admitProjectLocalTool(args: {
|
|
20
|
+
readonly dir: string;
|
|
21
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
22
|
+
}): AuthoredAdmission;
|
|
23
|
+
/**
|
|
24
|
+
* Admit a USER-GLOBAL authored tool — trusted-by-default because the user placed
|
|
25
|
+
* it in their own home-dir tool host, but still fail-closed on a missing or
|
|
26
|
+
* incompatible manifest.
|
|
27
|
+
*/
|
|
28
|
+
export declare function admitUserGlobalTool(args: {
|
|
29
|
+
readonly dir: string;
|
|
30
|
+
}): AuthoredAdmission;
|
|
31
|
+
/**
|
|
32
|
+
* Emit the best-effort stderr line + structured warning for a discovered
|
|
33
|
+
* INSTALLED tool whose runtime failed to load. Each failure reason maps to its
|
|
34
|
+
* own diagnostic while preserving the installed leg's skip-not-crash posture.
|
|
35
|
+
*/
|
|
36
|
+
/** Stderr + structured log when an installed tool is skipped by the trust gate. */
|
|
37
|
+
export declare function emitInstalledTrustDenied(toolId: string, packageName: string, packageDir: string): void;
|
|
38
|
+
export declare function emitInstalledLoadFailure(name: string, load: Extract<ToolRuntimeLoad, {
|
|
39
|
+
ok: false;
|
|
40
|
+
}>): void;
|
|
2
41
|
export interface DiscoveryOptions {
|
|
3
42
|
/**
|
|
4
43
|
* Ordered tool-discovery sources (precedence: first wins on duplicate
|
|
@@ -7,6 +46,8 @@ export interface DiscoveryOptions {
|
|
|
7
46
|
* and stays unit-testable with explicit anchors.
|
|
8
47
|
*/
|
|
9
48
|
readonly sources: readonly ToolDiscoverySource[];
|
|
49
|
+
/** Injectable env for installed-tool trust (bootstrap-time; defaults to `process.env`). */
|
|
50
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
10
51
|
}
|
|
11
52
|
/**
|
|
12
53
|
* Build the ordered tool-discovery sources. Order is precedence
|
|
@@ -23,69 +64,11 @@ export interface DiscoveryOptions {
|
|
|
23
64
|
* source.
|
|
24
65
|
*/
|
|
25
66
|
export declare function buildToolDiscoverySources(cwd: string, cliInstallDir: string): ToolDiscoverySource[];
|
|
26
|
-
/**
|
|
27
|
-
* Discover and register third-party tool packages from npm — any
|
|
28
|
-
* `package.json` declaring `opensipTools.kind === 'tool'`. Built-in
|
|
29
|
-
* ids are skipped to avoid double-registration warnings. Discovery spans
|
|
30
|
-
* the supplied sources (the user-global tool host dir, the project tree +
|
|
31
|
-
* its `.runtime` tool host dir, and the CLI install dir — see
|
|
32
|
-
* {@link buildToolDiscoverySources}).
|
|
33
|
-
*
|
|
34
|
-
* Each discovered package runs through the SAME `admitTool` gate the
|
|
35
|
-
* bundled path uses (launch, Phase 3) BEFORE its module is imported:
|
|
36
|
-
* the static `package.json#opensipTools` manifest is read with source
|
|
37
|
-
* `'installed'`, the compatibility gate runs, and only an `admit` verdict
|
|
38
|
-
* proceeds to import + register. An installed tool is best-effort
|
|
39
|
-
* `explicitlyRequested: false`, so an incompatible one `skip`s (logged)
|
|
40
|
-
* rather than failing the whole CLI — a stray incompatible plugin must not
|
|
41
|
-
* take fit/graph/sim down. Admitted tools' `ToolProvenance` is pushed onto
|
|
42
|
-
* the optional `provenance` collector for Phase 4's `plugin list`.
|
|
43
|
-
*
|
|
44
|
-
* @param provenance Optional sink for admitted tools' provenance records.
|
|
45
|
-
*/
|
|
46
67
|
export declare function discoverAndRegisterToolPackages(registry: ToolRegistry, opts: DiscoveryOptions, builtInIds: ReadonlySet<string>, provenance?: ToolProvenance[], manifests?: ToolPluginManifest[]): Promise<void>;
|
|
47
68
|
/**
|
|
48
69
|
* Discover + admit + register AUTHORED Tool sidecars from the two authored
|
|
49
70
|
* roots, then dynamic-import each admitted runtime through the shared
|
|
50
|
-
* `importToolRuntime` seam
|
|
51
|
-
* bundled and installed legs travel (ADR-0027; this is the leg that makes the
|
|
52
|
-
* dormant {@link admitProjectLocalTool} live).
|
|
53
|
-
*
|
|
54
|
-
* Two roots, two trust postures:
|
|
55
|
-
* - **global** (`~/.opensip-cli/tools/`) → {@link admitUserGlobalTool},
|
|
56
|
-
* trusted-by-default.
|
|
57
|
-
* - **project** (`<project>/opensip-cli/tools/`) → {@link admitProjectLocalTool},
|
|
58
|
-
* deny-by-default (allowlist via `OPENSIP_CLI_ALLOW_PROJECT_TOOLS`).
|
|
59
|
-
*
|
|
60
|
-
* Global is processed FIRST so a project-authored tool cannot shadow a same-id
|
|
61
|
-
* global one — matching the `~/.opensip-cli/plugins` precedence note in
|
|
62
|
-
* {@link buildToolDiscoverySources} (first-writer-wins via the registry).
|
|
63
|
-
* `builtInIds` are skipped so an authored tool never shadows a bundled one.
|
|
64
|
-
*
|
|
65
|
-
* **Trust-before-import.** For each candidate, the admit step (which EMBEDS the
|
|
66
|
-
* trust decision — deny-by-default inside `admitProjectLocalTool`) runs to
|
|
67
|
-
* completion BEFORE `importToolRuntime`. A non-allowlisted project tool THROWS
|
|
68
|
-
* `PluginIncompatibleError` (exit 5) here, propagated out of the walk: it must
|
|
69
|
-
* fail the run loudly — that is the clone-protection contract.
|
|
70
|
-
*
|
|
71
|
-
* **Error-posture asymmetry (deliberate).** An un-allowlisted *project* tool is
|
|
72
|
-
* fail-closed by policy (clone-risk; the user must opt in). A *global* tool that
|
|
73
|
-
* fails to load is also fail-closed (the user explicitly authored it into
|
|
74
|
-
* `$HOME`). This differs from the *installed* npm leg, where a stray bad plugin
|
|
75
|
-
* skips-with-diagnostic so it can't take fit/graph/sim down — authored tools are
|
|
76
|
-
* first-party-intent, installed tools are ambient.
|
|
77
|
-
*
|
|
78
|
-
* @param registry The per-invocation tool registry to populate.
|
|
79
|
-
* @param opts.projectAuthoredDir `resolveProjectPaths(root).authoredToolsDir`,
|
|
80
|
-
* or `undefined` when there is no resolvable project context.
|
|
81
|
-
* @param opts.globalAuthoredDir `resolveUserPaths().authoredToolsDir`.
|
|
82
|
-
* @param opts.env Environment carrying the project allowlist (default
|
|
83
|
-
* `process.env`); injectable for tests.
|
|
84
|
-
* @param builtInIds Bundled-tool ids to skip on a name collision.
|
|
85
|
-
* @param provenance Sink for admitted authored tools' provenance records.
|
|
86
|
-
* @param manifests Sink for admitted authored tools' manifests (§5.3).
|
|
87
|
-
* @throws {PluginIncompatibleError} for an un-allowlisted project tool, or any
|
|
88
|
-
* authored tool whose sidecar/runtime is missing/incompatible (fail-closed).
|
|
71
|
+
* `importToolRuntime` seam.
|
|
89
72
|
*/
|
|
90
73
|
export declare function discoverAndRegisterAuthoredTools(registry: ToolRegistry, opts: {
|
|
91
74
|
readonly projectAuthoredDir?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"register-tools-discovery.d.ts","sourceRoot":"","sources":["../../src/bootstrap/register-tools-discovery.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"register-tools-discovery.d.ts","sourceRoot":"","sources":["../../src/bootstrap/register-tools-discovery.ts"],"names":[],"mappings":"AACA;;;;;GAKG;AAEH,OAAO,EAYL,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,mBAAmB,EAEzB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,yBAAyB,CAAC;AAIjC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D,MAAM,MAAM,iBAAiB,GAAG,aAAa,CAAC;AAsC9C;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IAC1C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CAClC,GAAG,iBAAiB,CAgBpB;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE;IAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,iBAAiB,CAErF;AAoCD;;;;GAIG;AACH,mFAAmF;AACnF,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,GACjB,IAAI,CAaN;AAED,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,OAAO,CAAC,eAAe,EAAE;IAAE,EAAE,EAAE,KAAK,CAAA;CAAE,CAAC,GAC5C,IAAI,CA0BN;AAED,MAAM,WAAW,gBAAgB;IAC/B;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACjD,2FAA2F;IAC3F,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CAClC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,yBAAyB,CACvC,GAAG,EAAE,MAAM,EACX,aAAa,EAAE,MAAM,GACpB,mBAAmB,EAAE,CAqBvB;AA2DD,wBAAsB,+BAA+B,CACnD,QAAQ,EAAE,YAAY,EACtB,IAAI,EAAE,gBAAgB,EACtB,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,EAC/B,UAAU,GAAE,cAAc,EAAO,EACjC,SAAS,GAAE,kBAAkB,EAAO,GACnC,OAAO,CAAC,IAAI,CAAC,CAmCf;AAED;;;;GAIG;AACH,wBAAsB,gCAAgC,CACpD,QAAQ,EAAE,YAAY,EACtB,IAAI,EAAE;IACJ,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CAClC,EACD,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,EAC/B,UAAU,GAAE,cAAc,EAAO,EACjC,SAAS,GAAE,kBAAkB,EAAO,GACnC,OAAO,CAAC,IAAI,CAAC,CAuBf"}
|
|
@@ -1,9 +1,135 @@
|
|
|
1
1
|
// @fitness-ignore-file performance-anti-patterns -- sequential await across discovered tool packages preserves load order for plugin-conflict detection; bounded by installed plugin count
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
/**
|
|
3
|
+
* register-tools-discovery — installed + authored tool admission and discovery.
|
|
4
|
+
*
|
|
5
|
+
* Extracted from register-tools.ts so the bundled registration path stays a
|
|
6
|
+
* focused module under the file-length soft limit.
|
|
7
|
+
*/
|
|
8
|
+
import { admitTool, assertManifestMatchesTool, discoverAuthoredToolSidecars, discoverToolPackagesFromAnchors, logger, PluginIncompatibleError, PROJECT_LOCAL_MANIFEST_FILE, resolveProjectContext, resolveProjectPaths, resolveUserPaths, loadToolManifest, } from '@opensip-cli/core';
|
|
9
|
+
import { hostRuntimeImportPolicyFor, importToolRuntime, } from './admit-tool-package.js';
|
|
10
|
+
import { BOOTSTRAP_MODULE } from './constants.js';
|
|
11
|
+
import { isInstalledToolTrusted, isProjectLocalToolTrusted } from './tool-trust.js';
|
|
12
|
+
/**
|
|
13
|
+
* The shared admission tail for both authored sources. When `preloadedManifest`
|
|
14
|
+
* is supplied we use that snapshot so the trust decision and compatibility gate
|
|
15
|
+
* see the identical declaration.
|
|
16
|
+
*
|
|
17
|
+
* @throws {PluginIncompatibleError} When the sidecar manifest is missing,
|
|
18
|
+
* malformed, or rejected by the compatibility gate.
|
|
19
|
+
*/
|
|
20
|
+
function admitAuthoredTool(source, dir, preloadedManifest) {
|
|
21
|
+
const rawManifest = preloadedManifest ?? loadToolManifest(source, dir);
|
|
22
|
+
if (rawManifest === undefined) {
|
|
23
|
+
throw new PluginIncompatibleError(`${source} tool at '${dir}' has no conformant ${PROJECT_LOCAL_MANIFEST_FILE} sidecar`, { diagnostic: 'manifest missing or malformed' });
|
|
24
|
+
}
|
|
25
|
+
const result = admitTool({
|
|
26
|
+
manifest: rawManifest,
|
|
27
|
+
source,
|
|
28
|
+
dir,
|
|
29
|
+
explicitlyRequested: true,
|
|
30
|
+
});
|
|
31
|
+
if (result.decision !== 'admit') {
|
|
32
|
+
throw new PluginIncompatibleError(`${source} tool '${rawManifest.id}' is incompatible: ${result.diagnostic ?? 'compatibility gate rejected it'}`, { diagnostic: result.diagnostic });
|
|
33
|
+
}
|
|
34
|
+
return { provenance: result.provenance, manifest: result.manifest };
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Admit or reject a PROJECT-LOCAL authored tool under the deny-by-default trust
|
|
38
|
+
* policy. The trust decision always precedes module import; a non-allowlisted
|
|
39
|
+
* tool fails closed before any authored code can run.
|
|
40
|
+
*
|
|
41
|
+
* @throws {PluginIncompatibleError} When the sidecar manifest is missing,
|
|
42
|
+
* malformed, incompatible, or not trusted by the project-tool allowlist.
|
|
43
|
+
*/
|
|
44
|
+
export function admitProjectLocalTool(args) {
|
|
45
|
+
const manifest = loadToolManifest('project-local', args.dir);
|
|
46
|
+
if (manifest === undefined) {
|
|
47
|
+
throw new PluginIncompatibleError(`project-local tool at '${args.dir}' has no conformant ${PROJECT_LOCAL_MANIFEST_FILE} sidecar`, { diagnostic: 'manifest missing or malformed' });
|
|
48
|
+
}
|
|
49
|
+
if (!isProjectLocalToolTrusted(manifest.id, args.env)) {
|
|
50
|
+
throw new PluginIncompatibleError(`project-local tool '${manifest.id}' is not trusted to load (deny-by-default). ` +
|
|
51
|
+
`Allowlist it via OPENSIP_CLI_ALLOW_PROJECT_TOOLS='${manifest.id}' to admit it.`, { diagnostic: 'project-local tool not allowlisted (deny-by-default)' });
|
|
52
|
+
}
|
|
53
|
+
return admitAuthoredTool('project-local', args.dir, manifest);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Admit a USER-GLOBAL authored tool — trusted-by-default because the user placed
|
|
57
|
+
* it in their own home-dir tool host, but still fail-closed on a missing or
|
|
58
|
+
* incompatible manifest.
|
|
59
|
+
*/
|
|
60
|
+
export function admitUserGlobalTool(args) {
|
|
61
|
+
return admitAuthoredTool('user-global', args.dir);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Run the admission gate over a discovered INSTALLED tool package before its
|
|
65
|
+
* module is imported. Installed tools are best-effort: incompatible or malformed
|
|
66
|
+
* ambient packages skip with diagnostics rather than crashing unrelated commands.
|
|
67
|
+
*/
|
|
68
|
+
function admitInstalledTool(pkg, builtInIds) {
|
|
69
|
+
const manifest = loadToolManifest('installed', pkg.packageDir);
|
|
70
|
+
if (manifest === undefined) {
|
|
71
|
+
process.stderr.write(`opensip: tool package ${pkg.name} has no conformant package.json#opensipTools manifest — skipping\n`);
|
|
72
|
+
logger.warn({
|
|
73
|
+
evt: 'cli.tool.manifest_invalid',
|
|
74
|
+
module: BOOTSTRAP_MODULE,
|
|
75
|
+
name: pkg.name,
|
|
76
|
+
});
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
if (builtInIds.has(manifest.id))
|
|
80
|
+
return undefined;
|
|
81
|
+
const result = admitTool({
|
|
82
|
+
manifest,
|
|
83
|
+
source: 'installed',
|
|
84
|
+
dir: pkg.packageDir,
|
|
85
|
+
packageName: pkg.name,
|
|
86
|
+
explicitlyRequested: false,
|
|
87
|
+
});
|
|
88
|
+
if (result.decision !== 'admit')
|
|
89
|
+
return undefined;
|
|
90
|
+
return { provenance: result.provenance, manifest: result.manifest };
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Emit the best-effort stderr line + structured warning for a discovered
|
|
94
|
+
* INSTALLED tool whose runtime failed to load. Each failure reason maps to its
|
|
95
|
+
* own diagnostic while preserving the installed leg's skip-not-crash posture.
|
|
96
|
+
*/
|
|
97
|
+
/** Stderr + structured log when an installed tool is skipped by the trust gate. */
|
|
98
|
+
export function emitInstalledTrustDenied(toolId, packageName, packageDir) {
|
|
99
|
+
process.stderr.write(`opensip: installed tool ${packageName} (${toolId}) is not trusted to load (deny-by-default). ` +
|
|
100
|
+
`Allowlist it via OPENSIP_CLI_ALLOW_INSTALLED_TOOLS='${toolId}' to admit it ` +
|
|
101
|
+
`(or OPENSIP_CLI_ALLOW_INSTALLED_TOOLS='*' for all). See opensip.ai/docs/opensip-cli/70-reference/10-environment-variables/\n`);
|
|
102
|
+
logger.warn({
|
|
103
|
+
evt: 'cli.tool.installed_trust_denied',
|
|
104
|
+
module: BOOTSTRAP_MODULE,
|
|
105
|
+
toolId,
|
|
106
|
+
packageName,
|
|
107
|
+
packageDir,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
export function emitInstalledLoadFailure(name, load) {
|
|
111
|
+
if (load.reason === 'no-entry') {
|
|
112
|
+
process.stderr.write(`opensip: tool package ${name} has no resolvable entry point — skipping\n`);
|
|
113
|
+
logger.warn({ evt: 'cli.tool.no_entry', module: BOOTSTRAP_MODULE, name });
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
if (load.reason === 'invalid-shape') {
|
|
117
|
+
process.stderr.write(`opensip: tool package ${name} does not export a valid \`tool\` — skipping\n`);
|
|
118
|
+
logger.warn({
|
|
119
|
+
evt: 'cli.tool.invalid_shape',
|
|
120
|
+
module: BOOTSTRAP_MODULE,
|
|
121
|
+
name,
|
|
122
|
+
});
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
process.stderr.write(`opensip: failed to load tool ${name}: ${load.detail ?? 'import failed'}\n`);
|
|
126
|
+
logger.warn({
|
|
127
|
+
evt: 'cli.tool.load_failed',
|
|
128
|
+
module: BOOTSTRAP_MODULE,
|
|
129
|
+
name,
|
|
130
|
+
error: load.detail,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
7
133
|
/**
|
|
8
134
|
* Build the ordered tool-discovery sources. Order is precedence
|
|
9
135
|
* (first-occurrence-wins on duplicate name):
|
|
@@ -57,45 +183,52 @@ export function buildToolDiscoverySources(cwd, cliInstallDir) {
|
|
|
57
183
|
*
|
|
58
184
|
* @param provenance Optional sink for admitted tools' provenance records.
|
|
59
185
|
*/
|
|
186
|
+
async function registerDiscoveredInstalledPackage(pkg, args) {
|
|
187
|
+
const admission = admitInstalledTool(pkg, args.builtInIds);
|
|
188
|
+
if (admission === undefined)
|
|
189
|
+
return;
|
|
190
|
+
if (!isInstalledToolTrusted(admission.manifest.id, args.env)) {
|
|
191
|
+
emitInstalledTrustDenied(admission.manifest.id, pkg.name, pkg.packageDir);
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
const load = await importToolRuntime(pkg.packageDir, hostRuntimeImportPolicyFor('installed'));
|
|
195
|
+
if (!load.ok) {
|
|
196
|
+
emitInstalledLoadFailure(pkg.name, load);
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
if (args.builtInIds.has(load.tool.metadata.name ?? load.tool.metadata.id))
|
|
200
|
+
return;
|
|
201
|
+
// Stable-UUID collision (ADR-0048): skip a re-discovered copy of an already-
|
|
202
|
+
// registered tool (see discoverAndRegisterToolPackages JSDoc).
|
|
203
|
+
if (args.registeredStableIds.has(load.tool.metadata.id))
|
|
204
|
+
return;
|
|
205
|
+
assertManifestMatchesTool(admission.manifest, load.tool);
|
|
206
|
+
// @fitness-ignore-next-line detached-promises -- ToolRegistry.register(...) returns void (registry.ts:46); the detached-promise heuristic misfires on the discarded non-promise call result.
|
|
207
|
+
args.registry.register(load.tool, { sourcePackage: pkg.name });
|
|
208
|
+
args.provenance.push(admission.provenance);
|
|
209
|
+
args.manifests.push(admission.manifest);
|
|
210
|
+
}
|
|
60
211
|
export async function discoverAndRegisterToolPackages(registry, opts, builtInIds, provenance = [], manifests = []) {
|
|
61
|
-
// `builtInIds` is the set of already-registered bundled-tool *human ids* (manifest.id)
|
|
62
|
-
// to skip on a name collision (launch — passed explicitly by the composition root, which
|
|
63
|
-
// derives it from the bundled MANIFESTS it just loaded; compare against runtime
|
|
64
|
-
// metadata.name for the human key).
|
|
65
212
|
const discovered = discoverToolPackagesFromAnchors(opts.sources);
|
|
213
|
+
// Stable-UUID collision guard (ADR-0048): a discovered package whose runtime
|
|
214
|
+
// `metadata.id` (the stable UUID) is already registered is the SAME tool
|
|
215
|
+
// re-discovered via a stray anchor — e.g. a second copy of `@opensip-cli/*`
|
|
216
|
+
// in a node_modules ABOVE the project root. The human-name skip alone misses
|
|
217
|
+
// it when the two copies disagree on `metadata.name` (e.g. one built before
|
|
218
|
+
// the verb-rename), which would otherwise double-register and trip the
|
|
219
|
+
// session-replay duplicate guard. UUID is identity; skip on a UUID match.
|
|
220
|
+
const registeredStableIds = new Set(registry.list().map((t) => t.metadata.id));
|
|
221
|
+
const env = opts.env ?? process.env;
|
|
66
222
|
for (const pkg of discovered) {
|
|
67
223
|
try {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
// from `packageDir` so a tool living in a host dir off the CLI's own
|
|
77
|
-
// module-resolution path still loads. An installed tool is best-effort:
|
|
78
|
-
// any load failure skips-with-diagnostic (it must not take fit/graph/sim
|
|
79
|
-
// down), in contrast to the bundled path's fail-closed.
|
|
80
|
-
const load = await importToolRuntime(pkg.packageDir, hostRuntimeImportPolicyFor('installed'));
|
|
81
|
-
if (!load.ok) {
|
|
82
|
-
emitInstalledLoadFailure(pkg.name, load);
|
|
83
|
-
continue;
|
|
84
|
-
}
|
|
85
|
-
// builtInIds holds human ids (from bundled manifests); compare against runtime human name
|
|
86
|
-
if (builtInIds.has(load.tool.metadata.name ?? load.tool.metadata.id))
|
|
87
|
-
continue;
|
|
88
|
-
// Drift guard — the SAME manifest⇔runtime identity check the bundled and
|
|
89
|
-
// authored legs run. For an installed tool a mismatch throws into the
|
|
90
|
-
// surrounding catch (skip-with-diagnostic posture), never crashing the CLI.
|
|
91
|
-
assertManifestMatchesTool(admission.manifest, load.tool);
|
|
92
|
-
registry.register(load.tool, { sourcePackage: pkg.name });
|
|
93
|
-
// Record provenance + manifest only now that the tool actually
|
|
94
|
-
// registered — `plugin list` and the per-run capability registry must
|
|
95
|
-
// never include a tool whose runtime failed to load (parity with the
|
|
96
|
-
// bundled/authored legs, which also record after registration).
|
|
97
|
-
provenance.push(admission.provenance);
|
|
98
|
-
manifests.push(admission.manifest);
|
|
224
|
+
await registerDiscoveredInstalledPackage(pkg, {
|
|
225
|
+
registry,
|
|
226
|
+
builtInIds,
|
|
227
|
+
env,
|
|
228
|
+
registeredStableIds,
|
|
229
|
+
provenance,
|
|
230
|
+
manifests,
|
|
231
|
+
});
|
|
99
232
|
}
|
|
100
233
|
catch (error) {
|
|
101
234
|
const msg = error instanceof Error ? error.message : String(error);
|
|
@@ -112,48 +245,9 @@ export async function discoverAndRegisterToolPackages(registry, opts, builtInIds
|
|
|
112
245
|
/**
|
|
113
246
|
* Discover + admit + register AUTHORED Tool sidecars from the two authored
|
|
114
247
|
* roots, then dynamic-import each admitted runtime through the shared
|
|
115
|
-
* `importToolRuntime` seam
|
|
116
|
-
* bundled and installed legs travel (ADR-0027; this is the leg that makes the
|
|
117
|
-
* dormant {@link admitProjectLocalTool} live).
|
|
118
|
-
*
|
|
119
|
-
* Two roots, two trust postures:
|
|
120
|
-
* - **global** (`~/.opensip-cli/tools/`) → {@link admitUserGlobalTool},
|
|
121
|
-
* trusted-by-default.
|
|
122
|
-
* - **project** (`<project>/opensip-cli/tools/`) → {@link admitProjectLocalTool},
|
|
123
|
-
* deny-by-default (allowlist via `OPENSIP_CLI_ALLOW_PROJECT_TOOLS`).
|
|
124
|
-
*
|
|
125
|
-
* Global is processed FIRST so a project-authored tool cannot shadow a same-id
|
|
126
|
-
* global one — matching the `~/.opensip-cli/plugins` precedence note in
|
|
127
|
-
* {@link buildToolDiscoverySources} (first-writer-wins via the registry).
|
|
128
|
-
* `builtInIds` are skipped so an authored tool never shadows a bundled one.
|
|
129
|
-
*
|
|
130
|
-
* **Trust-before-import.** For each candidate, the admit step (which EMBEDS the
|
|
131
|
-
* trust decision — deny-by-default inside `admitProjectLocalTool`) runs to
|
|
132
|
-
* completion BEFORE `importToolRuntime`. A non-allowlisted project tool THROWS
|
|
133
|
-
* `PluginIncompatibleError` (exit 5) here, propagated out of the walk: it must
|
|
134
|
-
* fail the run loudly — that is the clone-protection contract.
|
|
135
|
-
*
|
|
136
|
-
* **Error-posture asymmetry (deliberate).** An un-allowlisted *project* tool is
|
|
137
|
-
* fail-closed by policy (clone-risk; the user must opt in). A *global* tool that
|
|
138
|
-
* fails to load is also fail-closed (the user explicitly authored it into
|
|
139
|
-
* `$HOME`). This differs from the *installed* npm leg, where a stray bad plugin
|
|
140
|
-
* skips-with-diagnostic so it can't take fit/graph/sim down — authored tools are
|
|
141
|
-
* first-party-intent, installed tools are ambient.
|
|
142
|
-
*
|
|
143
|
-
* @param registry The per-invocation tool registry to populate.
|
|
144
|
-
* @param opts.projectAuthoredDir `resolveProjectPaths(root).authoredToolsDir`,
|
|
145
|
-
* or `undefined` when there is no resolvable project context.
|
|
146
|
-
* @param opts.globalAuthoredDir `resolveUserPaths().authoredToolsDir`.
|
|
147
|
-
* @param opts.env Environment carrying the project allowlist (default
|
|
148
|
-
* `process.env`); injectable for tests.
|
|
149
|
-
* @param builtInIds Bundled-tool ids to skip on a name collision.
|
|
150
|
-
* @param provenance Sink for admitted authored tools' provenance records.
|
|
151
|
-
* @param manifests Sink for admitted authored tools' manifests (§5.3).
|
|
152
|
-
* @throws {PluginIncompatibleError} for an un-allowlisted project tool, or any
|
|
153
|
-
* authored tool whose sidecar/runtime is missing/incompatible (fail-closed).
|
|
248
|
+
* `importToolRuntime` seam.
|
|
154
249
|
*/
|
|
155
250
|
export async function discoverAndRegisterAuthoredTools(registry, opts, builtInIds, provenance = [], manifests = []) {
|
|
156
|
-
// Global FIRST (trusted-by-default), then project (deny-by-default).
|
|
157
251
|
for (const candidate of discoverAuthoredToolSidecars(opts.globalAuthoredDir)) {
|
|
158
252
|
await admitAndRegisterAuthored({
|
|
159
253
|
registry,
|
|
@@ -166,8 +260,6 @@ export async function discoverAndRegisterAuthoredTools(registry, opts, builtInId
|
|
|
166
260
|
}
|
|
167
261
|
if (opts.projectAuthoredDir !== undefined) {
|
|
168
262
|
for (const candidate of discoverAuthoredToolSidecars(opts.projectAuthoredDir)) {
|
|
169
|
-
// admitProjectLocalTool embeds the deny-by-default trust gate; a
|
|
170
|
-
// non-allowlisted tool THROWS here, BEFORE importToolRuntime below.
|
|
171
263
|
await admitAndRegisterAuthored({
|
|
172
264
|
registry,
|
|
173
265
|
admission: admitProjectLocalTool({ dir: candidate.dir, env: opts.env }),
|
|
@@ -179,22 +271,10 @@ export async function discoverAndRegisterAuthoredTools(registry, opts, builtInId
|
|
|
179
271
|
}
|
|
180
272
|
}
|
|
181
273
|
}
|
|
182
|
-
/**
|
|
183
|
-
* Shared register-step for an already-ADMITTED authored tool: skip a
|
|
184
|
-
* built-in-id collision, dynamic-import the runtime (fail-closed on failure —
|
|
185
|
-
* an authored tool is first-party-intent), run the manifest⇔runtime drift
|
|
186
|
-
* guard, register, and record provenance + manifest. Admission (incl. the trust
|
|
187
|
-
* decision) has already happened by the time this is called — so import here
|
|
188
|
-
* never precedes a trust decision.
|
|
189
|
-
*
|
|
190
|
-
* @throws {PluginIncompatibleError} when the authored tool's runtime fails to
|
|
191
|
-
* load via the plugin path — an authored tool is first-party-intent, so a
|
|
192
|
-
* load failure is fail-closed (surfaced), never silently skipped.
|
|
193
|
-
*/
|
|
274
|
+
/** @throws {PluginIncompatibleError} When the authored tool runtime fails to load. */
|
|
194
275
|
async function admitAndRegisterAuthored(args) {
|
|
195
276
|
const { registry, admission, dir, builtInIds, provenance, manifests } = args;
|
|
196
277
|
const { provenance: prov, manifest } = admission;
|
|
197
|
-
// Never shadow a bundled tool (defense in depth; the registry also dedupes).
|
|
198
278
|
if (builtInIds.has(prov.id))
|
|
199
279
|
return;
|
|
200
280
|
const load = await importToolRuntime(dir, hostRuntimeImportPolicyFor(prov.source));
|
|
@@ -202,8 +282,6 @@ async function admitAndRegisterAuthored(args) {
|
|
|
202
282
|
const detailSuffix = load.detail ? `: ${load.detail}` : '';
|
|
203
283
|
throw new PluginIncompatibleError(`${prov.source} tool '${prov.id}' failed to load via the plugin path (${load.reason}${detailSuffix})`, { diagnostic: `authored tool runtime load failed: ${load.reason}` });
|
|
204
284
|
}
|
|
205
|
-
// Drift guard: the static sidecar and the runtime tool are two declarations
|
|
206
|
-
// of the same identity — catch a sidecar that fell out of sync.
|
|
207
285
|
assertManifestMatchesTool(manifest, load.tool);
|
|
208
286
|
registry.register(load.tool);
|
|
209
287
|
provenance.push(prov);
|