@yemi33/minions 0.1.1127 → 0.1.1129
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/CHANGELOG.md +51 -0
- package/engine/ado.js +7 -3
- package/engine/shared.js +52 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,56 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.1129 (2026-04-18)
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
- redact ADO tokens and JWTs from engine/log.json writes (#1297)
|
|
7
|
+
- SEC-02 — replace curl shell-out in ado.js with adoFetch (#1296)
|
|
8
|
+
- validate project name and path on POST /api/projects/add (SEC-04, SEC-05) (#1298)
|
|
9
|
+
- seed realActivityMap at spawn time, stamp pid in live-output (#1200)
|
|
10
|
+
|
|
11
|
+
### Fixes
|
|
12
|
+
- preserve buildErrorLog through transient states, persist poll time (#1273)
|
|
13
|
+
- auto-fetch PR title on link-pr (closes #1283) (#1299)
|
|
14
|
+
- scheduler double-fire within same cron minute (#1277)
|
|
15
|
+
- gate auto-fix dispatch on throttle state to prevent stale-data spurious fixes
|
|
16
|
+
- preserve buildErrorLog through transient build states (#1232) (#1274)
|
|
17
|
+
- annotate fast-exit empty-output failures with diagnostic hint (#1276)
|
|
18
|
+
- invalidate PRD cache on pr-links.json change + guard aggregate PRs (#1220) (#1272)
|
|
19
|
+
- pass --add-dir for minions + ~/.claude to agents (#1271)
|
|
20
|
+
- preserve VERDICT marker by tail-slicing agent output (#1234) (#1270)
|
|
21
|
+
- PRD info cache staleness and aggregate PR bleed-through (#1222)
|
|
22
|
+
- avoid no-op work item writes
|
|
23
|
+
- resilient claude binary resolution + surface spawn errors
|
|
24
|
+
- resolve native claude.exe from npm wrapper on Windows
|
|
25
|
+
- cap temp-agent creation at maxConcurrent per tick (#1219)
|
|
26
|
+
- reassign pending items from unspawned temp agents to idle named agents (#1204) (#1212)
|
|
27
|
+
- guard undefined agent in pending dispatch loop (closes #1206) (#1210)
|
|
28
|
+
- improve fallback meeting conclusion
|
|
29
|
+
- remove command center chevron
|
|
30
|
+
- stamp live-output.log stub before spawn (#1198)
|
|
31
|
+
- harden settings save and migrate pr poll config
|
|
32
|
+
|
|
33
|
+
### Other
|
|
34
|
+
- refactor: hoist fixThrottled before PR loop and drop underscore prefix
|
|
35
|
+
- docs(skill): add substitute-scheduler-template-vars (#1278)
|
|
36
|
+
- Clarify PR poll labels
|
|
37
|
+
- Prevent modal opens on text selection
|
|
38
|
+
- refactor: clarify settings page section structure and PR polling dependencies
|
|
39
|
+
- refactor: extract _probeClaudePackage helper, use shared.log for spawn errors
|
|
40
|
+
- Make work item descriptions scrollable
|
|
41
|
+
- Use PAT for publish merges
|
|
42
|
+
- test(queries): add unit tests for invalidateDispatchCache/getInbox/getAgentCharter (#1214)
|
|
43
|
+
- test(shared): add unit tests for truncateTextBytes/tailTextBytes/execSilent/trackReviewMetric/parseCanonicalPrId (#1215)
|
|
44
|
+
- Fix publish workflow merge
|
|
45
|
+
- chore: raise default meeting round timeout
|
|
46
|
+
- Harden prompt context handling
|
|
47
|
+
- Harden loop watch conversion
|
|
48
|
+
- Add watches sidebar activity badge
|
|
49
|
+
- test(cli): add unit tests for handleCommand, start, stop, kill, spawn (#1191)
|
|
50
|
+
- chore: untrack pipeline files — local config only
|
|
51
|
+
- restore: recover daily-arch-improvement and weekly-dead-code-cleanup pipelines
|
|
52
|
+
- Harden CC stream resilience
|
|
53
|
+
|
|
3
54
|
## 0.1.1127 (2026-04-18)
|
|
4
55
|
|
|
5
56
|
### Features
|
package/engine/ado.js
CHANGED
|
@@ -104,11 +104,12 @@ async function adoFetch(url, token, opts = {}) {
|
|
|
104
104
|
const _retryCount = typeof opts === 'number' ? opts : (opts._retryCount || 0); // backward compat
|
|
105
105
|
const method = (typeof opts === 'object' && opts.method) || 'GET';
|
|
106
106
|
const body = (typeof opts === 'object' && opts.body) || undefined;
|
|
107
|
+
const timeout = (typeof opts === 'object' && Number.isFinite(opts.timeout)) ? opts.timeout : 30000;
|
|
107
108
|
const MAX_RETRIES = 1;
|
|
108
109
|
const res = await fetch(url, {
|
|
109
110
|
method,
|
|
110
111
|
headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' },
|
|
111
|
-
signal: AbortSignal.timeout(
|
|
112
|
+
signal: AbortSignal.timeout(timeout),
|
|
112
113
|
body,
|
|
113
114
|
});
|
|
114
115
|
// ── Throttle detection: intercept 429/503 BEFORE generic !res.ok ──
|
|
@@ -811,8 +812,11 @@ async function checkLiveReviewStatus(pr, project) {
|
|
|
811
812
|
const prNum = shared.getPrNumber(pr);
|
|
812
813
|
if (!prNum) return null;
|
|
813
814
|
const url = `${orgBase}/${project.adoProject}/_apis/git/repositories/${project.repositoryId}/pullrequests/${prNum}?api-version=7.1`;
|
|
814
|
-
|
|
815
|
-
|
|
815
|
+
// SEC-02: use in-process adoFetch rather than a shell-out — keeps the bearer
|
|
816
|
+
// token out of the process argv list where any local process could read it.
|
|
817
|
+
// 4s timeout preserves the original request-cancellation semantics via AbortSignal.
|
|
818
|
+
const prData = await adoFetch(url, token, { timeout: 4000 });
|
|
819
|
+
if (!prData) return null;
|
|
816
820
|
const votes = (prData.reviewers || []).map(r => r.vote).filter(v => v !== undefined);
|
|
817
821
|
if (votes.length === 0) return 'pending';
|
|
818
822
|
return votesToReviewStatus(votes);
|
package/engine/shared.js
CHANGED
|
@@ -20,6 +20,46 @@ function ts() { return new Date().toISOString(); }
|
|
|
20
20
|
function logTs() { return new Date().toLocaleTimeString(); }
|
|
21
21
|
function dateStamp() { return new Date().toISOString().slice(0, 10); }
|
|
22
22
|
|
|
23
|
+
// ── Secret Redaction (SEC-09) ──────────────────────────────────────────────
|
|
24
|
+
// Pure, side-effect-free redactor applied to every entry on the log write path
|
|
25
|
+
// so ADO tokens, JWTs, and azureauth stdout dumps never land in engine/log.json
|
|
26
|
+
// (2500-entry ring buffer readable by any local process).
|
|
27
|
+
//
|
|
28
|
+
// Replacements (order matters — azureauth first, then Bearer, then bare JWT):
|
|
29
|
+
// 1. `"token":"<20+ char base64-ish>"` → `"token":"[REDACTED_AZUREAUTH]"`
|
|
30
|
+
// Redacts the value only, not the whole line, so surrounding JSON
|
|
31
|
+
// context (e.g. expiresOn) remains debuggable.
|
|
32
|
+
// 2. `Bearer <20+ char base64-ish>` → `Bearer [REDACTED]`
|
|
33
|
+
// 3. `ey<b64url>.<b64url>[.<b64url>]` → `[REDACTED_JWT]`
|
|
34
|
+
// Catches bare JWTs in error messages or stack traces (anything left
|
|
35
|
+
// after Bearer replacement has consumed its tokens).
|
|
36
|
+
//
|
|
37
|
+
// `redactSecrets` also recurses into objects and arrays — used by `log()` to
|
|
38
|
+
// sanitize both the message and the meta payload before persistence.
|
|
39
|
+
const _BEARER_RE = /Bearer\s+[A-Za-z0-9+/=._\-]{20,}/g;
|
|
40
|
+
const _JWT_RE = /ey[A-Za-z0-9_\-]{10,}\.[A-Za-z0-9_\-]{10,}(?:\.[A-Za-z0-9_\-]{10,})?/g;
|
|
41
|
+
const _AZUREAUTH_RE = /"token"\s*:\s*"[A-Za-z0-9+/=._\-]{20,}"/g;
|
|
42
|
+
|
|
43
|
+
function _redactString(s) {
|
|
44
|
+
if (typeof s !== 'string' || s.length === 0) return s;
|
|
45
|
+
return s
|
|
46
|
+
.replace(_AZUREAUTH_RE, '"token":"[REDACTED_AZUREAUTH]"')
|
|
47
|
+
.replace(_BEARER_RE, 'Bearer [REDACTED]')
|
|
48
|
+
.replace(_JWT_RE, '[REDACTED_JWT]');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function redactSecrets(value) {
|
|
52
|
+
if (value == null) return value;
|
|
53
|
+
if (typeof value === 'string') return _redactString(value);
|
|
54
|
+
if (Array.isArray(value)) return value.map(redactSecrets);
|
|
55
|
+
if (typeof value === 'object') {
|
|
56
|
+
const out = {};
|
|
57
|
+
for (const k of Object.keys(value)) out[k] = redactSecrets(value[k]);
|
|
58
|
+
return out;
|
|
59
|
+
}
|
|
60
|
+
return value;
|
|
61
|
+
}
|
|
62
|
+
|
|
23
63
|
// ── Log Buffering ──────────────────────────────────────────────────────────
|
|
24
64
|
// Buffer log entries in memory and flush to disk periodically to reduce lock
|
|
25
65
|
// contention (~139 calls/tick → 1 lock acquisition per flush).
|
|
@@ -27,9 +67,14 @@ const _logBuffer = [];
|
|
|
27
67
|
let _logFlushTimer = null;
|
|
28
68
|
|
|
29
69
|
function log(level, msg, meta = {}) {
|
|
30
|
-
|
|
31
|
-
//
|
|
32
|
-
|
|
70
|
+
// SEC-09: redact sensitive patterns (ADO tokens, JWTs, azureauth stdout)
|
|
71
|
+
// before both the in-memory buffer push and the console echo — ensures
|
|
72
|
+
// nothing sensitive is persisted to engine/log.json or engine stdout logs.
|
|
73
|
+
const safeMsg = typeof msg === 'string' ? _redactString(msg) : msg;
|
|
74
|
+
const safeMeta = redactSecrets(meta) || {};
|
|
75
|
+
const entry = { timestamp: ts(), level, message: safeMsg, ...safeMeta };
|
|
76
|
+
// Console output remains immediate (also redacted)
|
|
77
|
+
console.log(`[${logTs()}] [${level}] ${safeMsg}`);
|
|
33
78
|
|
|
34
79
|
_logBuffer.push(entry);
|
|
35
80
|
|
|
@@ -50,7 +95,9 @@ function log(level, msg, meta = {}) {
|
|
|
50
95
|
|
|
51
96
|
function _flushLogBuffer() {
|
|
52
97
|
if (_logBuffer.length === 0) return;
|
|
53
|
-
|
|
98
|
+
// SEC-09 defense-in-depth: redact again at flush time so any direct
|
|
99
|
+
// `_logBuffer.push(entry)` callers (tests, future paths) can't leak secrets.
|
|
100
|
+
const entries = _logBuffer.splice(0).map(redactSecrets);
|
|
54
101
|
try {
|
|
55
102
|
mutateJsonFileLocked(LOG_PATH, (logData) => {
|
|
56
103
|
if (!Array.isArray(logData)) logData = logData?.entries || [];
|
|
@@ -1719,6 +1766,7 @@ module.exports = {
|
|
|
1719
1766
|
_WIN_RESERVED_NAMES, // exported for testing
|
|
1720
1767
|
LOCK_STALE_MS,
|
|
1721
1768
|
flushLogs,
|
|
1769
|
+
redactSecrets,
|
|
1722
1770
|
slugify,
|
|
1723
1771
|
safeSlugComponent,
|
|
1724
1772
|
formatTranscriptEntry,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1129",
|
|
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"
|