instar 1.3.448 → 1.3.449
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/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +15 -2
- package/dist/commands/server.js.map +1 -1
- package/dist/permissions/RelationshipAnomalyScorer.d.ts +24 -0
- package/dist/permissions/RelationshipAnomalyScorer.d.ts.map +1 -1
- package/dist/permissions/RelationshipAnomalyScorer.js +100 -35
- package/dist/permissions/RelationshipAnomalyScorer.js.map +1 -1
- package/dist/permissions/RelationshipBehaviorStore.d.ts +110 -1
- package/dist/permissions/RelationshipBehaviorStore.d.ts.map +1 -1
- package/dist/permissions/RelationshipBehaviorStore.js +193 -4
- package/dist/permissions/RelationshipBehaviorStore.js.map +1 -1
- package/package.json +1 -1
- package/src/data/builtin-manifest.json +2 -2
- package/upgrades/1.3.449.md +26 -0
- package/upgrades/side-effects/slack-anomaly-poisoning-resistance.md +52 -0
|
@@ -34,8 +34,24 @@ function emptyProfile(slackUserId, now) {
|
|
|
34
34
|
urgentCount: 0,
|
|
35
35
|
firstSeen: now,
|
|
36
36
|
lastSeen: now,
|
|
37
|
+
buckets: [],
|
|
37
38
|
};
|
|
38
39
|
}
|
|
40
|
+
function emptyBucket(startMs) {
|
|
41
|
+
return {
|
|
42
|
+
startMs,
|
|
43
|
+
count: 0,
|
|
44
|
+
actionCounts: {},
|
|
45
|
+
tierCounts: [0, 0, 0, 0, 0],
|
|
46
|
+
hourCounts: new Array(24).fill(0),
|
|
47
|
+
lengthSum: 0,
|
|
48
|
+
lengthSqSum: 0,
|
|
49
|
+
urgentCount: 0,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
export const DEFAULT_BUCKET_MS = 24 * 60 * 60 * 1000; // 1 day
|
|
53
|
+
export const DEFAULT_MAX_OBSERVATIONS_PER_WINDOW = 50;
|
|
54
|
+
export const DEFAULT_MAX_BUCKETS = 90;
|
|
39
55
|
/** Validate a slackUserId for safe use as a filename key (prevents path traversal). */
|
|
40
56
|
function isSafeKey(id) {
|
|
41
57
|
return /^[A-Za-z0-9_-]{1,64}$/.test(id);
|
|
@@ -43,10 +59,24 @@ function isSafeKey(id) {
|
|
|
43
59
|
export class RelationshipBehaviorStore {
|
|
44
60
|
file;
|
|
45
61
|
now;
|
|
46
|
-
|
|
62
|
+
bucketMs;
|
|
63
|
+
maxObservationsPerWindow;
|
|
64
|
+
maxBuckets;
|
|
65
|
+
onCapDrop;
|
|
66
|
+
constructor(stateDir, now = () => new Date().toISOString(), options = {}) {
|
|
47
67
|
/* state-registry: slack-relationship-baselines */
|
|
48
68
|
this.file = path.join(stateDir, 'slack-relationship-baselines.json');
|
|
49
69
|
this.now = now;
|
|
70
|
+
// Nullish-coalescing (not ||) so a deliberate 0 disables the cap (per Dawn key-pattern).
|
|
71
|
+
this.bucketMs = options.bucketMs && options.bucketMs > 0 ? options.bucketMs : DEFAULT_BUCKET_MS;
|
|
72
|
+
this.maxObservationsPerWindow =
|
|
73
|
+
options.maxObservationsPerWindow ?? DEFAULT_MAX_OBSERVATIONS_PER_WINDOW;
|
|
74
|
+
this.maxBuckets = options.maxBuckets && options.maxBuckets > 0 ? options.maxBuckets : DEFAULT_MAX_BUCKETS;
|
|
75
|
+
this.onCapDrop = options.onCapDrop;
|
|
76
|
+
}
|
|
77
|
+
/** The bucket-window length (ms) this store records into — read by the scorer for decay. */
|
|
78
|
+
get bucketWindowMs() {
|
|
79
|
+
return this.bucketMs;
|
|
50
80
|
}
|
|
51
81
|
get path() {
|
|
52
82
|
return this.file;
|
|
@@ -62,19 +92,49 @@ export class RelationshipBehaviorStore {
|
|
|
62
92
|
try {
|
|
63
93
|
const all = this.readAll();
|
|
64
94
|
const now = this.now();
|
|
95
|
+
const nowMs = Date.parse(now);
|
|
65
96
|
const prof = all[slackUserId] ?? emptyProfile(slackUserId, now);
|
|
97
|
+
// ── #3b: per-window observation-rate cap ──────────────────────────────────────
|
|
98
|
+
// Resolve the current bucket. If recording this observation would exceed the
|
|
99
|
+
// per-window cap, DROP it (log via onCapDrop) — the cumulative counts are NOT
|
|
100
|
+
// touched either, so the buckets-sum invariant holds and the cap actually bites.
|
|
101
|
+
const bucket = this.currentBucket(prof, nowMs);
|
|
102
|
+
if (this.maxObservationsPerWindow > 0 &&
|
|
103
|
+
bucket.count >= this.maxObservationsPerWindow) {
|
|
104
|
+
// Over the cap for this window — drop, don't record. lastSeen is intentionally
|
|
105
|
+
// NOT advanced for a dropped observation (a dropped obs is not "an interaction").
|
|
106
|
+
try {
|
|
107
|
+
this.onCapDrop?.(slackUserId, bucket.startMs, 1);
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
/* logging must never break the path */
|
|
111
|
+
}
|
|
112
|
+
all[slackUserId] = prof; // persist any bucket pruning done while resolving
|
|
113
|
+
this.writeAll(all);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
const tier = Math.max(0, Math.min(4, Math.floor(obs.tier)));
|
|
117
|
+
const hour = Math.max(0, Math.min(23, Math.floor(obs.hour)));
|
|
118
|
+
const len = Math.max(0, Math.floor(obs.length));
|
|
119
|
+
// Cumulative counts (backward-compat — old readers see the same numbers).
|
|
66
120
|
prof.interactionCount += 1;
|
|
67
121
|
prof.actionCounts[obs.action] = (prof.actionCounts[obs.action] ?? 0) + 1;
|
|
68
|
-
const tier = Math.max(0, Math.min(4, Math.floor(obs.tier)));
|
|
69
122
|
prof.tierCounts[tier] = (prof.tierCounts[tier] ?? 0) + 1;
|
|
70
|
-
const hour = Math.max(0, Math.min(23, Math.floor(obs.hour)));
|
|
71
123
|
prof.hourCounts[hour] = (prof.hourCounts[hour] ?? 0) + 1;
|
|
72
|
-
const len = Math.max(0, Math.floor(obs.length));
|
|
73
124
|
prof.lengthSum += len;
|
|
74
125
|
prof.lengthSqSum += len * len;
|
|
75
126
|
if (obs.urgent)
|
|
76
127
|
prof.urgentCount += 1;
|
|
77
128
|
prof.lastSeen = now;
|
|
129
|
+
// Time-bucketed counts (kept in lock-step with the cumulative totals).
|
|
130
|
+
bucket.count += 1;
|
|
131
|
+
bucket.actionCounts[obs.action] = (bucket.actionCounts[obs.action] ?? 0) + 1;
|
|
132
|
+
bucket.tierCounts[tier] = (bucket.tierCounts[tier] ?? 0) + 1;
|
|
133
|
+
bucket.hourCounts[hour] = (bucket.hourCounts[hour] ?? 0) + 1;
|
|
134
|
+
bucket.lengthSum += len;
|
|
135
|
+
bucket.lengthSqSum += len * len;
|
|
136
|
+
if (obs.urgent)
|
|
137
|
+
bucket.urgentCount += 1;
|
|
78
138
|
all[slackUserId] = prof;
|
|
79
139
|
this.writeAll(all);
|
|
80
140
|
}
|
|
@@ -82,6 +142,30 @@ export class RelationshipBehaviorStore {
|
|
|
82
142
|
// Observe-only baseline must NEVER break the message path.
|
|
83
143
|
}
|
|
84
144
|
}
|
|
145
|
+
/**
|
|
146
|
+
* Resolve (and lazily migrate) the bucket covering `nowMs`, pruning to `maxBuckets`.
|
|
147
|
+
* Backfills a missing `buckets` array on a pre-hardening profile WITHOUT moving its
|
|
148
|
+
* cumulative counts into a bucket (those counts predate bucketing and have unknown
|
|
149
|
+
* timestamps — they keep weight as the un-decayable "legacy" base; see the scorer's
|
|
150
|
+
* decay logic). New observations land in fresh, timestamped buckets.
|
|
151
|
+
*/
|
|
152
|
+
currentBucket(prof, nowMs) {
|
|
153
|
+
if (!Array.isArray(prof.buckets))
|
|
154
|
+
prof.buckets = [];
|
|
155
|
+
const ms = Number.isFinite(nowMs) ? nowMs : Date.now();
|
|
156
|
+
const start = Math.floor(ms / this.bucketMs) * this.bucketMs;
|
|
157
|
+
let bucket = prof.buckets.find((b) => b.startMs === start);
|
|
158
|
+
if (!bucket) {
|
|
159
|
+
bucket = emptyBucket(start);
|
|
160
|
+
prof.buckets.push(bucket);
|
|
161
|
+
prof.buckets.sort((a, b) => a.startMs - b.startMs);
|
|
162
|
+
// Prune oldest buckets beyond the retention bound (file-growth guard).
|
|
163
|
+
if (prof.buckets.length > this.maxBuckets) {
|
|
164
|
+
prof.buckets.splice(0, prof.buckets.length - this.maxBuckets);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return bucket;
|
|
168
|
+
}
|
|
85
169
|
/** The current baseline for a principal, or undefined if none recorded yet. */
|
|
86
170
|
profileFor(slackUserId) {
|
|
87
171
|
if (!slackUserId || !isSafeKey(slackUserId))
|
|
@@ -138,6 +222,111 @@ export function hourFraction(prof, hour) {
|
|
|
138
222
|
const h = Math.max(0, Math.min(23, Math.floor(hour)));
|
|
139
223
|
return (prof.hourCounts[h] ?? 0) / prof.interactionCount;
|
|
140
224
|
}
|
|
225
|
+
/** Baseline calendar age in milliseconds (now − firstSeen), or 0 when unknown. */
|
|
226
|
+
export function baselineAgeMs(prof, nowMs) {
|
|
227
|
+
const first = Date.parse(prof.firstSeen);
|
|
228
|
+
if (!Number.isFinite(first) || !Number.isFinite(nowMs))
|
|
229
|
+
return 0;
|
|
230
|
+
return Math.max(0, nowMs - first);
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Compute the decay-weighted effective baseline. The legacy base = cumulative totals
|
|
234
|
+
* MINUS the sum of all buckets (i.e. the part of history that predates bucketing). That
|
|
235
|
+
* base keeps full weight (weight 1.0); each bucket is weighted by 0.5^(ageWindows/halfLife).
|
|
236
|
+
*
|
|
237
|
+
* A profile with no buckets → its entire cumulative form is the legacy base at full
|
|
238
|
+
* weight → the decayed view equals the cumulative view (perfect backward-compat). A
|
|
239
|
+
* fully-bucketed profile decays purely on bucket age.
|
|
240
|
+
*/
|
|
241
|
+
export function decayedView(prof, opts) {
|
|
242
|
+
const halfLife = opts.halfLifeWindows && opts.halfLifeWindows > 0 ? opts.halfLifeWindows : 30;
|
|
243
|
+
const bucketMs = opts.bucketMs && opts.bucketMs > 0 ? opts.bucketMs : DEFAULT_BUCKET_MS;
|
|
244
|
+
const buckets = Array.isArray(prof.buckets) ? prof.buckets : [];
|
|
245
|
+
const view = {
|
|
246
|
+
effectiveCount: 0,
|
|
247
|
+
actionCounts: {},
|
|
248
|
+
tierCounts: [0, 0, 0, 0, 0],
|
|
249
|
+
hourCounts: new Array(24).fill(0),
|
|
250
|
+
lengthSum: 0,
|
|
251
|
+
lengthSqSum: 0,
|
|
252
|
+
urgentCount: 0,
|
|
253
|
+
};
|
|
254
|
+
// ── Legacy (pre-bucketing) base: cumulative totals minus what the buckets hold ──
|
|
255
|
+
// Kept at full weight so old established behavior is never decayed away.
|
|
256
|
+
const bucketedCount = buckets.reduce((s, b) => s + b.count, 0);
|
|
257
|
+
const legacyCount = Math.max(0, prof.interactionCount - bucketedCount);
|
|
258
|
+
if (legacyCount > 0 && prof.interactionCount > 0) {
|
|
259
|
+
// Reconstruct the legacy base by subtracting bucket sums from cumulative sums.
|
|
260
|
+
const legacyActions = { ...prof.actionCounts };
|
|
261
|
+
const legacyTiers = prof.tierCounts.slice();
|
|
262
|
+
const legacyHours = prof.hourCounts.slice();
|
|
263
|
+
let legacyLenSum = prof.lengthSum;
|
|
264
|
+
let legacyLenSq = prof.lengthSqSum;
|
|
265
|
+
let legacyUrgent = prof.urgentCount;
|
|
266
|
+
for (const b of buckets) {
|
|
267
|
+
for (const [a, c] of Object.entries(b.actionCounts)) {
|
|
268
|
+
legacyActions[a] = (legacyActions[a] ?? 0) - c;
|
|
269
|
+
}
|
|
270
|
+
for (let t = 0; t < 5; t++)
|
|
271
|
+
legacyTiers[t] = (legacyTiers[t] ?? 0) - (b.tierCounts[t] ?? 0);
|
|
272
|
+
for (let h = 0; h < 24; h++)
|
|
273
|
+
legacyHours[h] = (legacyHours[h] ?? 0) - (b.hourCounts[h] ?? 0);
|
|
274
|
+
legacyLenSum -= b.lengthSum;
|
|
275
|
+
legacyLenSq -= b.lengthSqSum;
|
|
276
|
+
legacyUrgent -= b.urgentCount;
|
|
277
|
+
}
|
|
278
|
+
accumulate(view, 1.0, {
|
|
279
|
+
count: legacyCount,
|
|
280
|
+
actionCounts: legacyActions,
|
|
281
|
+
tierCounts: legacyTiers,
|
|
282
|
+
hourCounts: legacyHours,
|
|
283
|
+
lengthSum: Math.max(0, legacyLenSum),
|
|
284
|
+
lengthSqSum: Math.max(0, legacyLenSq),
|
|
285
|
+
urgentCount: Math.max(0, legacyUrgent),
|
|
286
|
+
startMs: 0,
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
// ── Decayed buckets ──
|
|
290
|
+
for (const b of buckets) {
|
|
291
|
+
const ageWindows = Math.max(0, (opts.nowMs - b.startMs) / bucketMs);
|
|
292
|
+
const weight = Math.pow(0.5, ageWindows / halfLife);
|
|
293
|
+
accumulate(view, weight, b);
|
|
294
|
+
}
|
|
295
|
+
return view;
|
|
296
|
+
}
|
|
297
|
+
function accumulate(view, weight, b) {
|
|
298
|
+
view.effectiveCount += b.count * weight;
|
|
299
|
+
for (const [a, c] of Object.entries(b.actionCounts)) {
|
|
300
|
+
if (c > 0)
|
|
301
|
+
view.actionCounts[a] = (view.actionCounts[a] ?? 0) + c * weight;
|
|
302
|
+
}
|
|
303
|
+
for (let t = 0; t < 5; t++)
|
|
304
|
+
view.tierCounts[t] += (b.tierCounts[t] ?? 0) * weight;
|
|
305
|
+
for (let h = 0; h < 24; h++)
|
|
306
|
+
view.hourCounts[h] += (b.hourCounts[h] ?? 0) * weight;
|
|
307
|
+
view.lengthSum += b.lengthSum * weight;
|
|
308
|
+
view.lengthSqSum += b.lengthSqSum * weight;
|
|
309
|
+
view.urgentCount += b.urgentCount * weight;
|
|
310
|
+
}
|
|
311
|
+
/** Mean message length from a decayed view, or undefined when there is no weight. */
|
|
312
|
+
export function decayedMeanLength(view) {
|
|
313
|
+
return view.effectiveCount > 0 ? view.lengthSum / view.effectiveCount : undefined;
|
|
314
|
+
}
|
|
315
|
+
/** Population std of message length from a decayed view, or undefined when <2 effective. */
|
|
316
|
+
export function decayedStdLength(view) {
|
|
317
|
+
if (view.effectiveCount < 2)
|
|
318
|
+
return undefined;
|
|
319
|
+
const mean = view.lengthSum / view.effectiveCount;
|
|
320
|
+
const variance = view.lengthSqSum / view.effectiveCount - mean * mean;
|
|
321
|
+
return variance > 0 ? Math.sqrt(variance) : 0;
|
|
322
|
+
}
|
|
323
|
+
/** Fraction of decayed interactions in a given hour (0..1). */
|
|
324
|
+
export function decayedHourFraction(view, hour) {
|
|
325
|
+
if (view.effectiveCount <= 0)
|
|
326
|
+
return 0;
|
|
327
|
+
const h = Math.max(0, Math.min(23, Math.floor(hour)));
|
|
328
|
+
return (view.hourCounts[h] ?? 0) / view.effectiveCount;
|
|
329
|
+
}
|
|
141
330
|
export class StoreBaselineProvider {
|
|
142
331
|
store;
|
|
143
332
|
constructor(store) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RelationshipBehaviorStore.js","sourceRoot":"","sources":["../../src/permissions/RelationshipBehaviorStore.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"RelationshipBehaviorStore.js","sourceRoot":"","sources":["../../src/permissions/RelationshipBehaviorStore.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "./builtin-manifest.schema.json",
|
|
3
3
|
"schemaVersion": 1,
|
|
4
|
-
"generatedAt": "2026-06-
|
|
5
|
-
"instarVersion": "1.3.
|
|
4
|
+
"generatedAt": "2026-06-09T19:25:15.286Z",
|
|
5
|
+
"instarVersion": "1.3.449",
|
|
6
6
|
"entryCount": 199,
|
|
7
7
|
"entries": {
|
|
8
8
|
"hook:session-start": {
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Upgrade Guide — vNEXT
|
|
2
|
+
|
|
3
|
+
<!-- assembled-by: assemble-next-md -->
|
|
4
|
+
<!-- bump: patch -->
|
|
5
|
+
|
|
6
|
+
## What Changed
|
|
7
|
+
|
|
8
|
+
feat(permissions): deeper **baseline-poisoning resistance** for the Slack relationship anomaly detector — the pre-enforce follow-ups (#2/#3) from the Phase-3 adversarial review. **Observe-only / dark, additive, backward-compatible.**
|
|
9
|
+
|
|
10
|
+
- **Recency/decay (dual-view max):** the behavior store keeps optional day-bucketed counts; the scorer computes a decay-weighted view AND keeps the cumulative view, and scores each signal as the **more-suspicious of the two** (max anomaly / lower normal-ceiling / lower normal-rate). Decay can only ADD suspicion, never disarm a cumulative signal — so the never-lower invariant holds; its real job is durability (a one-time burst fades once genuine traffic resumes). Default half-life 30 day-windows.
|
|
11
|
+
- **Minimum-baseline-age (#3a):** "established" now requires `firstSeen` older than `minBaselineAgeDays` (default 7) AND `interactionCount >= establishedMin` — a high-count-but-young burst stays low-confidence (action/tier/style signals suppressed). `0` restores legacy count-only behavior.
|
|
12
|
+
- **Per-principal rate cap (#3b):** `maxObservationsPerWindow` (default 50/day-window); excess observations are dropped + logged (`onCapDrop`), never recorded — cumulative + bucket counts stay in lock-step. `0` disables.
|
|
13
|
+
- All under `permissionGate.relationshipAnomaly.poisoningResistance`; absence preserves shipped behavior. Decay is read-time only (raw counts persist) → retune/revert needs no migration. Legacy profiles (no `buckets` field) score identically (decayed view degrades to cumulative).
|
|
14
|
+
|
|
15
|
+
## What to Tell Your User
|
|
16
|
+
|
|
17
|
+
Nothing changes by default. This hardens the (still-dark) relationship anomaly detector against a patient attacker who tries to "train" the baseline — by slowly feeding normal-looking activity, or a burst of it — so a later out-of-character request looks normal. Three additive defenses: recent activity can't durably overwrite long-standing behavior, a freshly-created baseline isn't trusted until it's both old enough and large enough, and no single account can flood the baseline faster than a capped rate. It can still only ever ask for *more* verification, never less. Needed before the anomaly layer is ever switched from observe-only to enforcing.
|
|
18
|
+
|
|
19
|
+
## Summary of New Capabilities
|
|
20
|
+
|
|
21
|
+
- **`permissionGate.relationshipAnomaly.poisoningResistance: { decayHalfLifeWindows, minBaselineAgeDays, maxObservationsPerWindow, bucketMs }`** (opt-in; the whole anomaly feature stays dark by default) — recency-decay + minimum-baseline-age + per-principal observation-rate-cap, so a poisoned baseline can't disarm the detector.
|
|
22
|
+
|
|
23
|
+
## Evidence
|
|
24
|
+
|
|
25
|
+
- 32 anomaly tests (12 new): rate-cap burst / per-window / opt-out; min-age young-vs-aged / opt-out; decay durability + a "without the rate cap" counter-test proving the cap is load-bearing; backward-compat (legacy-profile decay/scoring/backfill). Counterfactuals confirm each hardening is load-bearing (with it off, the poisoning attack succeeds; on, it's caught). 61/61 with the permission-gate + routes integration. `tsc --noEmit` clean; full lint chain clean (state-registry, silent-fallback ratchet, topic-creation). (Full unit suite runs in CI, sharded — local run blocked by host CPU starvation.)
|
|
26
|
+
- Side-effects review (`upgrades/side-effects/slack-anomaly-poisoning-resistance.md`); deterministic (no LLM-in-gate-path) so reviewed by me + the counterfactual tests, never-lower preserved by the dual-view-max design.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Side-Effects Review — Slack relationship-anomaly baseline-poisoning resistance (Phase-3 follow-ups #2/#3)
|
|
2
|
+
|
|
3
|
+
**Version / slug:** `slack-anomaly-poisoning-resistance`
|
|
4
|
+
**Date:** 2026-06-09
|
|
5
|
+
**Author:** Instar Agent (echo)
|
|
6
|
+
**Second-pass reviewer:** not required (see §5 — detector-only, observe-only/dark; no blocking authority added)
|
|
7
|
+
|
|
8
|
+
## Summary of the change
|
|
9
|
+
|
|
10
|
+
Deepens baseline-poisoning resistance for the Slack relationship-aware anomaly detector (Pillar 3, SLACK-ORG-INTEGRATION-SPEC.md §7), the pre-enforce follow-ups #2/#3 flagged by the Phase-3 adversarial review (PR #1022). The threat is a patient attacker / slowly-compromised account that injects many normal-looking observations (and/or a burst) to reshape a principal's behavioral baseline so a later out-of-character request scores low. Three additive, backward-compatible, observe-only hardenings: (#2) recency/decay weighting via optional time-bucketed history + exponential bucket-age decay, scored as the max-anomaly across BOTH the cumulative and the decayed view so the hardening only ever adds resistance; (#3a) a minimum-baseline-AGE requirement (a baseline is "established" only when firstSeen is older than N days AND interactionCount ≥ establishedMin); (#3b) a per-principal observation-rate cap (excess observations in a rolling window are dropped + logged, never recorded). Files: `src/permissions/RelationshipBehaviorStore.ts` (buckets, decay helpers, rate cap), `src/permissions/RelationshipAnomalyScorer.ts` (dual-view max-anomaly scoring + min-age gate), `src/commands/server.ts` (wire `permissionGate.relationshipAnomaly.poisoningResistance` config), `docs/specs/SLACK-ORG-INTEGRATION-SPEC.md` (§7.7), `tests/unit/slack-relationship-anomaly.test.ts` (12 new tests + aged-seed fixtures). The decision point touched is the anomaly SCORER (a detector), not any authority.
|
|
11
|
+
|
|
12
|
+
## Decision-point inventory
|
|
13
|
+
|
|
14
|
+
- `RelationshipAnomalyScorer.assess/deterministicScore` — modify — strengthens the anomaly SCORE (a signal); produces no block/allow. The consuming SlackPermissionGate (the authority) is unchanged.
|
|
15
|
+
- `RelationshipBehaviorStore.record` — modify — adds a structural write-bound (rate cap) on what SHAPE gets recorded; produces no block/allow on the message path.
|
|
16
|
+
- `permissionGate.relationshipAnomaly.poisoningResistance` config (server.ts) — add — optional knobs; absence preserves shipped defaults.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 1. Over-block
|
|
21
|
+
|
|
22
|
+
No block/allow surface — over-block not applicable. The scorer produces a 0..1 anomaly score + reasons (a signal); the whole Pillar-3 feature ships observe-only/dark (§7.6: would-be step-ups are logged, never live-challenged). The closest analog to "over-fire" is a false-positive anomaly. The min-age gate (#3a) and the never-lower invariant make the hardening *more* conservative about firing on thin/young baselines, not less; the dual-view max-anomaly never invents a step-up on a no/thin baseline (a new principal still scores 0, confidence 'none'). The rate cap drops *recording*, not requests — a dropped observation never affects the message path; at worst the baseline grows slightly slower, which only lowers anomaly confidence (more conservative).
|
|
23
|
+
|
|
24
|
+
## 2. Under-block
|
|
25
|
+
|
|
26
|
+
No block/allow surface — under-block not applicable. As a detector, the residual gaps are: (a) a *very* slow attacker who stays under the rate cap for many windows AND sustains a campaign long enough that the action's share rises above the floor in BOTH views can still normalize an action — but this requires a sustained multi-week campaign the cap throttles, far harder than the single-burst / single-seeded-observation attacks #1/#2/#3 close; (b) decay half-life is a tuning choice — too short helps a recent burst, too long lets stale behavior dominate; default 30 windows is conservative and config-overridable. The floor protection (RolePolicy / Layer-0 grants) protects dangerous actions regardless of anomaly, so an under-fire is harmless (nothing is blocked in observe mode, and a floor action still needs a grant when enforcement is on).
|
|
27
|
+
|
|
28
|
+
## 3. Level-of-abstraction fit
|
|
29
|
+
|
|
30
|
+
Correct layer. The hardening lives in the same module that owns the baseline (the store) and the same scorer that owns the signal — it does not reach up into the gate/authority or down into transport. The rate cap belongs in `record()` (the single write funnel for the baseline) and the decay/age logic belongs in the scorer's read path (pure, deterministic, testable). No higher layer should own per-principal histogram robustness; no lower layer sees principal identity. The decayed-view computation is a pure read-time function — the store still persists raw counts, so the model can be retuned without a data migration.
|
|
31
|
+
|
|
32
|
+
## 4. Signal vs authority compliance
|
|
33
|
+
|
|
34
|
+
Compliant (the load-bearing question). Per `docs/signal-vs-authority.md`: the scorer is a DETECTOR — it surfaces an anomaly score + human-readable reasons and holds zero blocking power. The single authority for the permission decision (SlackPermissionGate) is untouched and still the only thing that can raise a verdict to step-up, and only ever to RAISE a would-be-allowed floor action (§7.4 never-lower). The dual-view max-anomaly design is explicitly an "only add" rule: a hardening must never DISARM a signal the pre-hardening cumulative baseline would have fired (the cumulative view is always evaluated alongside the decayed view and the more-anomalous wins). The rate cap is a structural write-bound (a validator on recorded SHAPE), not a brittle blocker on inputs. No new brittle authority is introduced.
|
|
35
|
+
|
|
36
|
+
## 5. Interactions
|
|
37
|
+
|
|
38
|
+
- **With mitigation #1 (share-floor, already merged):** complementary. #1 made out-of-character fire on low SHARE not only never-seen; #3b's rate cap keeps a burst's share *small* so #1's floor keeps biting; #2's decayed view re-arms #1 once a burst ages out. The counter-test (`WITHOUT the rate cap … demonstrating the cap is load-bearing`) proves #1 alone is defeated by an uncapped 100-obs burst and that #3b is what preserves it.
|
|
39
|
+
- **With the LLM style check (optional, fail-closed):** unchanged. It still adds-only and fails closed; it reads a coarse cumulative summary (a prose hint), not the scoring path.
|
|
40
|
+
- **Buckets-sum invariant:** the cumulative counts remain the exact sum of bucket counts + the legacy (pre-bucketing) base, so an old reader of the persisted profile sees identical numbers. A dropped observation touches NEITHER the cumulative nor the bucket counts, so the cap can't desync them.
|
|
41
|
+
- **No double-fire / no race:** `record()` is the existing single write funnel (best-effort, swallows errors, atomic temp+rename write). The rate cap adds one branch inside it; no new writer, no new file, no new timer.
|
|
42
|
+
|
|
43
|
+
## 6. External surfaces
|
|
44
|
+
|
|
45
|
+
- **Persisted state:** the `slack-relationship-baselines.json` profile gains an OPTIONAL `buckets` array (additive field under the existing `slack-relationship-baselines` state-registry category — lint-state-registry clean, no new category). A profile written by an older build (no `buckets`) is read and scored identically (degrades to its cumulative form at full weight). A profile written by this build is still readable by an older build (it ignores the unknown field).
|
|
46
|
+
- **API:** `GET /permissions/baselines` is unchanged (it serializes the profile as-is, including the new optional field). No new route.
|
|
47
|
+
- **Config:** new optional `permissionGate.relationshipAnomaly.poisoningResistance` sub-config; absence preserves shipped behavior. Feature stays dark (Null scorer default).
|
|
48
|
+
- **Cross-agent / cross-machine:** none. No Threadline, no messaging, no spawn surface touched.
|
|
49
|
+
|
|
50
|
+
## 7. Rollback cost
|
|
51
|
+
|
|
52
|
+
Low. The feature ships dark (observe-only; off unless `relationshipAnomaly.enabled` + a non-Null scorer). Back-out is a code revert of the five files — no release-incident class, no agent-state repair. The persisted `buckets` field is forward/backward-compatible, so a revert leaves existing baseline files readable by the reverted code (the extra field is ignored). The decay model is read-time only (raw counts persist), so a retune or revert needs no data migration. To disable the hardenings without reverting: `minBaselineAgeDays: 0` (legacy count-only established), `maxObservationsPerWindow: 0` (cap off), and a large `decayHalfLifeWindows` (decay ≈ off / cumulative).
|