@yemi33/minions 0.1.1989 → 0.1.1990
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/engine/ado-git-auth.js +52 -13
- package/package.json +1 -1
package/engine/ado-git-auth.js
CHANGED
|
@@ -66,26 +66,65 @@ function isAdoProject(project) {
|
|
|
66
66
|
return !!(project && project.repoHost === 'ado');
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
// Scope the header to the ADO host so a misconfigured remote pointing at
|
|
69
|
+
// Scope the header to the ADO host(s) so a misconfigured remote pointing at
|
|
70
70
|
// another host (e.g. github.com on a misclassified project) doesn't leak the
|
|
71
71
|
// bearer token. Falls back to the unscoped `http.extraHeader` key when we
|
|
72
|
-
// can't compute
|
|
72
|
+
// can't compute any host (still safe — git only sends extraHeader on HTTP/S
|
|
73
73
|
// transfers, and the engine only invokes ado-git-auth for ADO projects).
|
|
74
|
-
|
|
74
|
+
//
|
|
75
|
+
// W-mped1zap00069ea5 — ADO has TWO canonical URL forms for the same org:
|
|
76
|
+
// - https://dev.azure.com/<org>/... (modern, default for new clones)
|
|
77
|
+
// - https://<org>.visualstudio.com/... (legacy alias, still active)
|
|
78
|
+
// Git scopes `http.<url>.extraHeader` by URL PREFIX match: a header scoped to
|
|
79
|
+
// `office.visualstudio.com` is silently dropped when the remote is
|
|
80
|
+
// `dev.azure.com/office` (and vice-versa). The bearer token is identical for
|
|
81
|
+
// either form, so we emit the header under BOTH scopes to cover whichever
|
|
82
|
+
// alias the project's git remote happens to use.
|
|
83
|
+
function _resolveScopeUrls(project) {
|
|
75
84
|
try {
|
|
76
|
-
if (!project || !project.adoOrg) return
|
|
85
|
+
if (!isAdoProject(project) || !project.adoOrg) return [];
|
|
86
|
+
const scopes = new Set();
|
|
87
|
+
|
|
88
|
+
// Always include the modern dev.azure.com host. Remotes cloned via the
|
|
89
|
+
// current ADO UI use this form regardless of what `prUrlBase` says.
|
|
90
|
+
scopes.add('https://dev.azure.com/');
|
|
91
|
+
|
|
92
|
+
// Derive the visualstudio.com form from adoOrg. Works whether adoOrg is
|
|
93
|
+
// the bare org slug ("office") or already a full host ("office.visualstudio.com").
|
|
94
|
+
const orgName = project.adoOrg.includes('.')
|
|
95
|
+
? project.adoOrg.split('.')[0]
|
|
96
|
+
: project.adoOrg;
|
|
97
|
+
if (orgName) {
|
|
98
|
+
scopes.add(`https://${orgName}.visualstudio.com/`);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Also honor whatever host `getAdoOrgBase` resolves — covers custom
|
|
102
|
+
// prUrlBase values (e.g. self-hosted Azure DevOps Server) that don't
|
|
103
|
+
// match either canonical alias.
|
|
77
104
|
const base = shared.getAdoOrgBase(project);
|
|
78
|
-
if (typeof base
|
|
79
|
-
|
|
80
|
-
|
|
105
|
+
if (typeof base === 'string' && base.startsWith('http')) {
|
|
106
|
+
const m = base.match(/^(https?:\/\/[^/]+)/);
|
|
107
|
+
if (m) scopes.add(`${m[1]}/`);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Stable alphabetical order so tests can assert deterministically.
|
|
111
|
+
return Array.from(scopes).sort();
|
|
81
112
|
} catch (_e) {
|
|
82
|
-
return
|
|
113
|
+
return [];
|
|
83
114
|
}
|
|
84
115
|
}
|
|
85
116
|
|
|
86
|
-
function _buildHeaderArgs(token,
|
|
87
|
-
|
|
88
|
-
|
|
117
|
+
function _buildHeaderArgs(token, scopeUrls) {
|
|
118
|
+
// Empty/null scopes → degenerate unscoped fallback (matches pre-W-mped1zap
|
|
119
|
+
// behavior). Still safe because we only inject this for ADO projects.
|
|
120
|
+
if (!Array.isArray(scopeUrls) || scopeUrls.length === 0) {
|
|
121
|
+
return ['-c', `http.extraHeader=Authorization: Bearer ${token}`];
|
|
122
|
+
}
|
|
123
|
+
const args = [];
|
|
124
|
+
for (const scopeUrl of scopeUrls) {
|
|
125
|
+
args.push('-c', `http.${scopeUrl}.extraHeader=Authorization: Bearer ${token}`);
|
|
126
|
+
}
|
|
127
|
+
return args;
|
|
89
128
|
}
|
|
90
129
|
|
|
91
130
|
function _acquireToken(opts = {}) {
|
|
@@ -98,7 +137,7 @@ function getAdoGitExtraArgs(project, opts = {}) {
|
|
|
98
137
|
if (!isAdoProject(project)) return [];
|
|
99
138
|
const now = Date.now();
|
|
100
139
|
if (_cached && _cached.expiresAt > now) {
|
|
101
|
-
return _buildHeaderArgs(_cached.token,
|
|
140
|
+
return _buildHeaderArgs(_cached.token, _resolveScopeUrls(project));
|
|
102
141
|
}
|
|
103
142
|
if (now < _backoffUntil) return [];
|
|
104
143
|
try {
|
|
@@ -109,7 +148,7 @@ function getAdoGitExtraArgs(project, opts = {}) {
|
|
|
109
148
|
return [];
|
|
110
149
|
}
|
|
111
150
|
_cached = { token, expiresAt: now + TOKEN_TTL_MS };
|
|
112
|
-
return _buildHeaderArgs(token,
|
|
151
|
+
return _buildHeaderArgs(token, _resolveScopeUrls(project));
|
|
113
152
|
} catch (e) {
|
|
114
153
|
_backoffUntil = now + ACQUIRE_BACKOFF_MS;
|
|
115
154
|
const firstLine = String(e && e.message || e).split('\n')[0];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1990",
|
|
4
4
|
"description": "Multi-agent AI dev team that runs from ~/.minions/ — five autonomous agents share a single engine, dashboard, and knowledge base",
|
|
5
5
|
"bin": {
|
|
6
6
|
"minions": "bin/minions.js"
|