@indexnetwork/protocol 14.3.2-rc.477.1 → 16.1.1-rc.478.1
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 +107 -0
- package/IMPLEMENTATION.md +50 -52
- package/STABILITY.md +3 -3
- package/dist/chat/chat.agent.js +2 -2
- package/dist/chat/chat.graph.d.ts +41 -1
- package/dist/chat/chat.graph.js +108 -127
- package/dist/discovery/hyde.frame.d.ts +4 -4
- package/dist/discovery/hyde.graph.d.ts +71 -12
- package/dist/discovery/hyde.graph.js +337 -335
- package/dist/discovery/lens.inferrer.d.ts +6 -6
- package/dist/enrichment/enrichment.graph.d.ts +127 -9
- package/dist/enrichment/enrichment.graph.js +633 -655
- package/dist/enrichment/enrichment.state.d.ts +1 -1
- package/dist/enrichment/enrichment.tools.context-read.d.ts +10 -0
- package/dist/enrichment/enrichment.tools.context-read.js +353 -0
- package/dist/enrichment/enrichment.tools.context-write.d.ts +9 -0
- package/dist/enrichment/enrichment.tools.context-write.js +417 -0
- package/dist/enrichment/enrichment.tools.d.ts +11 -1
- package/dist/enrichment/enrichment.tools.helpers.d.ts +139 -0
- package/dist/enrichment/enrichment.tools.helpers.js +234 -0
- package/dist/enrichment/enrichment.tools.js +16 -975
- package/dist/index.d.ts +27 -48
- package/dist/index.js +17 -27
- package/dist/intents/application/intent.graph.d.ts +71 -67
- package/dist/intents/application/intent.graph.execute.d.ts +59 -0
- package/dist/intents/application/intent.graph.execute.js +301 -0
- package/dist/intents/application/intent.graph.infer.d.ts +44 -0
- package/dist/intents/application/intent.graph.infer.js +97 -0
- package/dist/intents/application/intent.graph.js +96 -888
- package/dist/intents/application/intent.graph.reconcile.d.ts +71 -0
- package/dist/intents/application/intent.graph.reconcile.js +274 -0
- package/dist/intents/application/intent.graph.shared.d.ts +70 -0
- package/dist/intents/application/intent.graph.shared.js +153 -0
- package/dist/intents/domain/intent.state.d.ts +1 -1
- package/dist/maintenance/maintenance.graph.d.ts +66 -3
- package/dist/maintenance/maintenance.graph.js +155 -156
- package/dist/mcp/mcp.authorization-policy.d.ts +24 -28
- package/dist/mcp/mcp.authorization-policy.js +14 -34
- package/dist/mcp/mcp.server.d.ts +3 -3
- package/dist/mcp/mcp.server.js +12 -16
- package/dist/negotiations/application/negotiation.candidates.d.ts +83 -0
- package/dist/negotiations/application/negotiation.candidates.js +162 -0
- package/dist/negotiations/application/negotiation.graph.d.ts +91 -157
- package/dist/negotiations/application/negotiation.graph.finalize.d.ts +5 -0
- package/dist/negotiations/application/negotiation.graph.finalize.js +280 -0
- package/dist/negotiations/application/negotiation.graph.init.d.ts +54 -0
- package/dist/negotiations/application/negotiation.graph.init.js +227 -0
- package/dist/negotiations/application/negotiation.graph.js +69 -1388
- package/dist/negotiations/application/negotiation.graph.screen.d.ts +23 -0
- package/dist/negotiations/application/negotiation.graph.screen.js +108 -0
- package/dist/negotiations/application/negotiation.graph.shared.d.ts +75 -0
- package/dist/negotiations/application/negotiation.graph.shared.js +125 -0
- package/dist/negotiations/application/negotiation.graph.turn.d.ts +105 -0
- package/dist/negotiations/application/negotiation.graph.turn.js +484 -0
- package/dist/negotiations/domain/negotiation.state.d.ts +1 -1
- package/dist/negotiations/domain/negotiation.state.js +0 -1
- package/dist/networks/application/indexer.graph.d.ts +165 -7
- package/dist/networks/application/indexer.graph.js +339 -388
- package/dist/networks/application/indexer.state.d.ts +1 -1
- package/dist/networks/application/membership.graph.d.ts +83 -5
- package/dist/networks/application/membership.graph.js +177 -207
- package/dist/networks/application/network.graph.d.ts +148 -5
- package/dist/networks/application/network.graph.js +249 -278
- package/dist/networks/domain/membership.state.d.ts +1 -1
- package/dist/networks/domain/network.state.d.ts +1 -1
- package/dist/opportunities/application/delivery-card.cache.d.ts +1 -1
- package/dist/opportunities/application/delivery-card.cache.js +2 -2
- package/dist/opportunities/application/index.d.ts +2 -2
- package/dist/opportunities/application/index.js +2 -2
- package/dist/opportunities/application/opportunity.evaluator.js +1 -1
- package/dist/opportunities/application/opportunity.graph.d.ts +686 -473
- package/dist/opportunities/application/opportunity.graph.discovery-strategies.d.ts +109 -0
- package/dist/opportunities/application/opportunity.graph.discovery-strategies.js +451 -0
- package/dist/opportunities/application/opportunity.graph.discovery.d.ts +69 -0
- package/dist/opportunities/application/opportunity.graph.discovery.js +397 -0
- package/dist/opportunities/application/opportunity.graph.evaluation.d.ts +82 -0
- package/dist/opportunities/application/opportunity.graph.evaluation.js +608 -0
- package/dist/opportunities/application/opportunity.graph.js +120 -3690
- package/dist/opportunities/application/opportunity.graph.modes.d.ts +538 -0
- package/dist/opportunities/application/opportunity.graph.modes.js +538 -0
- package/dist/opportunities/application/opportunity.graph.negotiate.d.ts +109 -0
- package/dist/opportunities/application/opportunity.graph.negotiate.js +392 -0
- package/dist/opportunities/application/opportunity.graph.persist-node.d.ts +93 -0
- package/dist/opportunities/application/opportunity.graph.persist-node.js +765 -0
- package/dist/opportunities/application/opportunity.graph.prep.d.ts +150 -0
- package/dist/opportunities/application/opportunity.graph.prep.js +381 -0
- package/dist/opportunities/application/opportunity.graph.shared.d.ts +173 -0
- package/dist/opportunities/application/opportunity.graph.shared.js +199 -0
- package/dist/opportunities/application/opportunity.presentation.d.ts +399 -0
- package/dist/opportunities/application/{opportunity.presenter.js → opportunity.presentation.js} +735 -9
- package/dist/opportunities/application/opportunity.tools.cards.d.ts +152 -0
- package/dist/opportunities/application/opportunity.tools.cards.js +235 -0
- package/dist/opportunities/application/opportunity.tools.d.ts +8 -114
- package/dist/opportunities/application/opportunity.tools.js +28 -711
- package/dist/opportunities/application/opportunity.tools.list.d.ts +10 -0
- package/dist/opportunities/application/opportunity.tools.list.js +493 -0
- package/dist/opportunities/domain/index.d.ts +3 -3
- package/dist/opportunities/domain/index.js +3 -3
- package/dist/opportunities/domain/opportunity.state.d.ts +19 -19
- package/dist/opportunities/index.d.ts +6 -6
- package/dist/opportunities/index.js +4 -4
- package/dist/opportunities/ports/opportunity.tools.port.d.ts +1 -1
- package/dist/opportunities/radar/radar.graph.d.ts +57 -13
- package/dist/opportunities/radar/radar.graph.js +470 -471
- package/dist/premises/premise.graph.d.ts +88 -20
- package/dist/premises/premise.graph.js +207 -218
- package/dist/questions/domain/question.schema.d.ts +40 -40
- package/dist/shared/agent/tool.helpers.d.ts +21 -0
- package/dist/shared/agent/tool.registry.d.ts +4 -3
- package/dist/shared/agent/tool.registry.js +1 -1
- package/dist/shared/interfaces/database.capabilities.d.ts +100 -0
- package/dist/shared/interfaces/database.capabilities.js +7 -0
- package/dist/shared/interfaces/database.entities.d.ts +533 -0
- package/dist/shared/interfaces/database.entities.js +10 -0
- package/dist/shared/interfaces/database.identity-queries.d.ts +294 -0
- package/dist/shared/interfaces/database.identity-queries.js +4 -0
- package/dist/shared/interfaces/database.interface.d.ts +15 -2277
- package/dist/shared/interfaces/database.interface.js +8 -0
- package/dist/shared/interfaces/database.member-queries.d.ts +228 -0
- package/dist/shared/interfaces/database.member-queries.js +4 -0
- package/dist/shared/interfaces/database.negotiation.d.ts +305 -0
- package/dist/shared/interfaces/database.negotiation.js +26 -0
- package/dist/shared/interfaces/database.network-queries.d.ts +277 -0
- package/dist/shared/interfaces/database.network-queries.js +4 -0
- package/dist/shared/interfaces/database.opportunity-queries.d.ts +285 -0
- package/dist/shared/interfaces/database.opportunity-queries.js +4 -0
- package/dist/shared/interfaces/database.port.d.ts +322 -0
- package/dist/shared/interfaces/database.port.js +29 -0
- package/dist/shared/schemas/discovery-question.schema.d.ts +14 -14
- package/dist/shared/schemas/negotiation-digest.schema.d.ts +2 -2
- package/package.json +2 -15
- package/dist/opportunities/application/opportunity.card-presentation.d.ts +0 -44
- package/dist/opportunities/application/opportunity.card-presentation.js +0 -93
- package/dist/opportunities/application/opportunity.presenter.d.ts +0 -156
- package/dist/opportunities/domain/opportunity.presentation-cache.d.ts +0 -5
- package/dist/opportunities/domain/opportunity.presentation-cache.js +0 -11
- package/dist/opportunities/domain/opportunity.presentation.d.ts +0 -76
- package/dist/opportunities/domain/opportunity.presentation.js +0 -516
- package/dist/opportunities/domain/opportunity.safe-presentation.d.ts +0 -104
- package/dist/opportunities/domain/opportunity.safe-presentation.js +0 -102
|
@@ -21,167 +21,16 @@ const FRESHNESS_WINDOW_MS = 12 * 60 * 60 * 1000; // 12 hours
|
|
|
21
21
|
*/
|
|
22
22
|
export class MaintenanceGraphFactory {
|
|
23
23
|
constructor(database, cache, queue) {
|
|
24
|
-
this.
|
|
25
|
-
this.cache = cache;
|
|
26
|
-
this.queue = queue;
|
|
24
|
+
this.deps = { database, cache, queue };
|
|
27
25
|
}
|
|
28
26
|
/** Compile and return the maintenance graph. */
|
|
29
27
|
createGraph() {
|
|
30
|
-
const
|
|
31
|
-
if (!state.userId) {
|
|
32
|
-
return { error: 'userId is required' };
|
|
33
|
-
}
|
|
34
|
-
try {
|
|
35
|
-
const raw = await this.database.getOpportunitiesForUser(state.userId, { limit: 150 });
|
|
36
|
-
const actionable = raw.filter((opp) => isActionableForViewer(opp.actors, opp.status, state.userId));
|
|
37
|
-
const expired = raw.filter((opp) => opp.status === 'expired' && canUserSeeOpportunity(opp.actors, opp.status, state.userId));
|
|
38
|
-
const activeIntents = await this.database.getActiveIntents(state.userId);
|
|
39
|
-
// Read last rediscovery timestamp from cache
|
|
40
|
-
let lastRediscoveryAt = null;
|
|
41
|
-
try {
|
|
42
|
-
const cached = await this.cache.get(`rediscovery:lastRun:${state.userId}`);
|
|
43
|
-
if (typeof cached?.triggeredAt === 'string') {
|
|
44
|
-
const parsed = Date.parse(cached.triggeredAt);
|
|
45
|
-
if (Number.isFinite(parsed)) {
|
|
46
|
-
lastRediscoveryAt = parsed;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
catch {
|
|
51
|
-
// Cache unavailable — treat as no data
|
|
52
|
-
}
|
|
53
|
-
return {
|
|
54
|
-
currentOpportunities: actionable,
|
|
55
|
-
expiredCount: expired.length,
|
|
56
|
-
activeIntents: activeIntents ?? [],
|
|
57
|
-
lastRediscoveryAt,
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
catch (e) {
|
|
61
|
-
logger.error('MaintenanceGraph loadCurrentRadar failed', { error: e });
|
|
62
|
-
return { error: 'Failed to load current radar' };
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
const scoreRadarHealthNode = async (state) => {
|
|
66
|
-
if (state.error)
|
|
67
|
-
return {};
|
|
68
|
-
try {
|
|
69
|
-
const opps = state.currentOpportunities ?? [];
|
|
70
|
-
let connectionCount = 0;
|
|
71
|
-
let connectorFlowCount = 0;
|
|
72
|
-
for (const opp of opps) {
|
|
73
|
-
const category = classifyOpportunity(opp, state.userId);
|
|
74
|
-
if (category === 'connection')
|
|
75
|
-
connectionCount++;
|
|
76
|
-
else if (category === 'connector-flow')
|
|
77
|
-
connectorFlowCount++;
|
|
78
|
-
}
|
|
79
|
-
const healthResult = computeRadarHealth({
|
|
80
|
-
connectionCount,
|
|
81
|
-
connectorFlowCount,
|
|
82
|
-
expiredCount: state.expiredCount,
|
|
83
|
-
totalActionable: opps.length,
|
|
84
|
-
lastRediscoveryAt: state.lastRediscoveryAt,
|
|
85
|
-
freshnessWindowMs: FRESHNESS_WINDOW_MS,
|
|
86
|
-
});
|
|
87
|
-
logger.verbose('Radar health scored', {
|
|
88
|
-
userId: state.userId,
|
|
89
|
-
score: healthResult.score,
|
|
90
|
-
shouldMaintain: healthResult.shouldMaintain,
|
|
91
|
-
connectorFlowCount,
|
|
92
|
-
});
|
|
93
|
-
return { healthResult, connectorFlowCount };
|
|
94
|
-
}
|
|
95
|
-
catch (e) {
|
|
96
|
-
logger.error('MaintenanceGraph scoreRadarHealth failed', { error: e });
|
|
97
|
-
return { error: 'Failed to score radar health' };
|
|
98
|
-
}
|
|
99
|
-
};
|
|
100
|
-
const shouldRediscover = (state) => {
|
|
101
|
-
if (state.error)
|
|
102
|
-
return 'introducerDiscovery';
|
|
103
|
-
if (state.healthResult?.shouldMaintain && state.activeIntents.length > 0) {
|
|
104
|
-
return 'rediscover';
|
|
105
|
-
}
|
|
106
|
-
return 'introducerDiscovery';
|
|
107
|
-
};
|
|
108
|
-
const rediscoverNode = async (state) => {
|
|
109
|
-
try {
|
|
110
|
-
const bucket = Math.floor(Date.now() / (6 * 60 * 60 * 1000));
|
|
111
|
-
const results = await Promise.allSettled(state.activeIntents.map((intent) => this.queue.addJob({ intentId: intent.id, userId: state.userId }, { priority: 10, jobId: `rediscovery-${state.userId}-${intent.id}-${bucket}` })));
|
|
112
|
-
for (const r of results) {
|
|
113
|
-
if (r.status === 'rejected') {
|
|
114
|
-
const errMsg = r.reason instanceof Error ? r.reason.message : String(r.reason);
|
|
115
|
-
logger.error('Rediscovery job enqueue failed', { error: errMsg });
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
const enqueued = results.filter((r) => r.status === 'fulfilled').length;
|
|
119
|
-
// Record last run timestamp
|
|
120
|
-
if (enqueued > 0) {
|
|
121
|
-
try {
|
|
122
|
-
await this.cache.set(`rediscovery:lastRun:${state.userId}`, { triggeredAt: new Date().toISOString() }, { ttl: 24 * 60 * 60 });
|
|
123
|
-
}
|
|
124
|
-
catch {
|
|
125
|
-
// Cache write failure is non-fatal
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
return { rediscoveryJobsEnqueued: enqueued };
|
|
129
|
-
}
|
|
130
|
-
catch (e) {
|
|
131
|
-
logger.error('MaintenanceGraph rediscover failed', { error: e });
|
|
132
|
-
return { error: 'Failed to enqueue rediscovery jobs' };
|
|
133
|
-
}
|
|
134
|
-
};
|
|
135
|
-
const introducerDiscoveryNode = async (state) => {
|
|
136
|
-
if (!isIntroducerDiscoveryEnabled()) {
|
|
137
|
-
logger.info('Introducer discovery skipped — disabled by configuration', {
|
|
138
|
-
userId: state.userId,
|
|
139
|
-
});
|
|
140
|
-
return {};
|
|
141
|
-
}
|
|
142
|
-
try {
|
|
143
|
-
const connectorFlowTarget = RADAR_SOFT_TARGETS.connectorFlow;
|
|
144
|
-
if (!shouldRunIntroducerDiscovery(state.connectorFlowCount, connectorFlowTarget)) {
|
|
145
|
-
logger.verbose('Introducer discovery skipped — connector-flow target met', {
|
|
146
|
-
userId: state.userId,
|
|
147
|
-
connectorFlowCount: state.connectorFlowCount,
|
|
148
|
-
connectorFlowTarget,
|
|
149
|
-
});
|
|
150
|
-
return {};
|
|
151
|
-
}
|
|
152
|
-
// Cast database/queue to introducer discovery interfaces (they are compatible)
|
|
153
|
-
const result = await runIntroducerDiscovery(this.database, this.queue, state.userId);
|
|
154
|
-
logger.info('Introducer discovery complete', {
|
|
155
|
-
userId: state.userId,
|
|
156
|
-
contactsEvaluated: result.contactsEvaluated,
|
|
157
|
-
jobsEnqueued: result.jobsEnqueued,
|
|
158
|
-
skippedReason: result.skippedReason,
|
|
159
|
-
});
|
|
160
|
-
return { introducerDiscoveryJobsEnqueued: result.jobsEnqueued };
|
|
161
|
-
}
|
|
162
|
-
catch (e) {
|
|
163
|
-
logger.error('MaintenanceGraph introducerDiscovery failed', { error: e });
|
|
164
|
-
// Non-fatal: do not set error, just log and continue
|
|
165
|
-
return {};
|
|
166
|
-
}
|
|
167
|
-
};
|
|
168
|
-
const logMaintenanceNode = async (state) => {
|
|
169
|
-
logger.info('Maintenance complete', {
|
|
170
|
-
userId: state.userId,
|
|
171
|
-
score: state.healthResult?.score,
|
|
172
|
-
shouldMaintain: state.healthResult?.shouldMaintain,
|
|
173
|
-
rediscoveryJobs: state.rediscoveryJobsEnqueued,
|
|
174
|
-
introducerDiscoveryJobs: state.introducerDiscoveryJobsEnqueued,
|
|
175
|
-
activeIntents: state.activeIntents.length,
|
|
176
|
-
connectorFlowCount: state.connectorFlowCount,
|
|
177
|
-
});
|
|
178
|
-
return {};
|
|
179
|
-
};
|
|
28
|
+
const deps = this.deps;
|
|
180
29
|
const graph = new StateGraph(MaintenanceGraphState)
|
|
181
|
-
.addNode('loadCurrentRadar', loadCurrentRadarNode)
|
|
30
|
+
.addNode('loadCurrentRadar', (state) => loadCurrentRadarNode(state, deps))
|
|
182
31
|
.addNode('scoreRadarHealth', scoreRadarHealthNode)
|
|
183
|
-
.addNode('rediscover', rediscoverNode)
|
|
184
|
-
.addNode('introducerDiscovery', introducerDiscoveryNode)
|
|
32
|
+
.addNode('rediscover', (state) => rediscoverNode(state, deps))
|
|
33
|
+
.addNode('introducerDiscovery', (state) => introducerDiscoveryNode(state, deps))
|
|
185
34
|
.addNode('logMaintenance', logMaintenanceNode)
|
|
186
35
|
.addEdge(START, 'loadCurrentRadar')
|
|
187
36
|
.addConditionalEdges('loadCurrentRadar', (state) => (state.error ? 'end' : 'scoreRadarHealth'), {
|
|
@@ -198,3 +47,153 @@ export class MaintenanceGraphFactory {
|
|
|
198
47
|
return graph.compile();
|
|
199
48
|
}
|
|
200
49
|
}
|
|
50
|
+
export async function loadCurrentRadarNode(state, deps) {
|
|
51
|
+
if (!state.userId) {
|
|
52
|
+
return { error: 'userId is required' };
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
const raw = await deps.database.getOpportunitiesForUser(state.userId, { limit: 150 });
|
|
56
|
+
const actionable = raw.filter((opp) => isActionableForViewer(opp.actors, opp.status, state.userId));
|
|
57
|
+
const expired = raw.filter((opp) => opp.status === 'expired' && canUserSeeOpportunity(opp.actors, opp.status, state.userId));
|
|
58
|
+
const activeIntents = await deps.database.getActiveIntents(state.userId);
|
|
59
|
+
// Read last rediscovery timestamp from cache
|
|
60
|
+
let lastRediscoveryAt = null;
|
|
61
|
+
try {
|
|
62
|
+
const cached = await deps.cache.get(`rediscovery:lastRun:${state.userId}`);
|
|
63
|
+
if (typeof cached?.triggeredAt === 'string') {
|
|
64
|
+
const parsed = Date.parse(cached.triggeredAt);
|
|
65
|
+
if (Number.isFinite(parsed)) {
|
|
66
|
+
lastRediscoveryAt = parsed;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// Cache unavailable — treat as no data
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
currentOpportunities: actionable,
|
|
75
|
+
expiredCount: expired.length,
|
|
76
|
+
activeIntents: activeIntents ?? [],
|
|
77
|
+
lastRediscoveryAt,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
catch (e) {
|
|
81
|
+
logger.error('MaintenanceGraph loadCurrentRadar failed', { error: e });
|
|
82
|
+
return { error: 'Failed to load current radar' };
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
export async function scoreRadarHealthNode(state) {
|
|
86
|
+
if (state.error)
|
|
87
|
+
return {};
|
|
88
|
+
try {
|
|
89
|
+
const opps = state.currentOpportunities ?? [];
|
|
90
|
+
let connectionCount = 0;
|
|
91
|
+
let connectorFlowCount = 0;
|
|
92
|
+
for (const opp of opps) {
|
|
93
|
+
const category = classifyOpportunity(opp, state.userId);
|
|
94
|
+
if (category === 'connection')
|
|
95
|
+
connectionCount++;
|
|
96
|
+
else if (category === 'connector-flow')
|
|
97
|
+
connectorFlowCount++;
|
|
98
|
+
}
|
|
99
|
+
const healthResult = computeRadarHealth({
|
|
100
|
+
connectionCount,
|
|
101
|
+
connectorFlowCount,
|
|
102
|
+
expiredCount: state.expiredCount,
|
|
103
|
+
totalActionable: opps.length,
|
|
104
|
+
lastRediscoveryAt: state.lastRediscoveryAt,
|
|
105
|
+
freshnessWindowMs: FRESHNESS_WINDOW_MS,
|
|
106
|
+
});
|
|
107
|
+
logger.verbose('Radar health scored', {
|
|
108
|
+
userId: state.userId,
|
|
109
|
+
score: healthResult.score,
|
|
110
|
+
shouldMaintain: healthResult.shouldMaintain,
|
|
111
|
+
connectorFlowCount,
|
|
112
|
+
});
|
|
113
|
+
return { healthResult, connectorFlowCount };
|
|
114
|
+
}
|
|
115
|
+
catch (e) {
|
|
116
|
+
logger.error('MaintenanceGraph scoreRadarHealth failed', { error: e });
|
|
117
|
+
return { error: 'Failed to score radar health' };
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
export function shouldRediscover(state) {
|
|
121
|
+
if (state.error)
|
|
122
|
+
return 'introducerDiscovery';
|
|
123
|
+
if (state.healthResult?.shouldMaintain && state.activeIntents.length > 0) {
|
|
124
|
+
return 'rediscover';
|
|
125
|
+
}
|
|
126
|
+
return 'introducerDiscovery';
|
|
127
|
+
}
|
|
128
|
+
export async function rediscoverNode(state, deps) {
|
|
129
|
+
try {
|
|
130
|
+
const bucket = Math.floor(Date.now() / (6 * 60 * 60 * 1000));
|
|
131
|
+
const results = await Promise.allSettled(state.activeIntents.map((intent) => deps.queue.addJob({ intentId: intent.id, userId: state.userId }, { priority: 10, jobId: `rediscovery-${state.userId}-${intent.id}-${bucket}` })));
|
|
132
|
+
for (const r of results) {
|
|
133
|
+
if (r.status === 'rejected') {
|
|
134
|
+
const errMsg = r.reason instanceof Error ? r.reason.message : String(r.reason);
|
|
135
|
+
logger.error('Rediscovery job enqueue failed', { error: errMsg });
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
const enqueued = results.filter((r) => r.status === 'fulfilled').length;
|
|
139
|
+
// Record last run timestamp
|
|
140
|
+
if (enqueued > 0) {
|
|
141
|
+
try {
|
|
142
|
+
await deps.cache.set(`rediscovery:lastRun:${state.userId}`, { triggeredAt: new Date().toISOString() }, { ttl: 24 * 60 * 60 });
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
// Cache write failure is non-fatal
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return { rediscoveryJobsEnqueued: enqueued };
|
|
149
|
+
}
|
|
150
|
+
catch (e) {
|
|
151
|
+
logger.error('MaintenanceGraph rediscover failed', { error: e });
|
|
152
|
+
return { error: 'Failed to enqueue rediscovery jobs' };
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
export async function introducerDiscoveryNode(state, deps) {
|
|
156
|
+
if (!isIntroducerDiscoveryEnabled()) {
|
|
157
|
+
logger.info('Introducer discovery skipped — disabled by configuration', {
|
|
158
|
+
userId: state.userId,
|
|
159
|
+
});
|
|
160
|
+
return {};
|
|
161
|
+
}
|
|
162
|
+
try {
|
|
163
|
+
const connectorFlowTarget = RADAR_SOFT_TARGETS.connectorFlow;
|
|
164
|
+
if (!shouldRunIntroducerDiscovery(state.connectorFlowCount, connectorFlowTarget)) {
|
|
165
|
+
logger.verbose('Introducer discovery skipped — connector-flow target met', {
|
|
166
|
+
userId: state.userId,
|
|
167
|
+
connectorFlowCount: state.connectorFlowCount,
|
|
168
|
+
connectorFlowTarget,
|
|
169
|
+
});
|
|
170
|
+
return {};
|
|
171
|
+
}
|
|
172
|
+
// Cast database/queue to introducer discovery interfaces (they are compatible)
|
|
173
|
+
const result = await runIntroducerDiscovery(deps.database, deps.queue, state.userId);
|
|
174
|
+
logger.info('Introducer discovery complete', {
|
|
175
|
+
userId: state.userId,
|
|
176
|
+
contactsEvaluated: result.contactsEvaluated,
|
|
177
|
+
jobsEnqueued: result.jobsEnqueued,
|
|
178
|
+
skippedReason: result.skippedReason,
|
|
179
|
+
});
|
|
180
|
+
return { introducerDiscoveryJobsEnqueued: result.jobsEnqueued };
|
|
181
|
+
}
|
|
182
|
+
catch (e) {
|
|
183
|
+
logger.error('MaintenanceGraph introducerDiscovery failed', { error: e });
|
|
184
|
+
// Non-fatal: do not set error, just log and continue
|
|
185
|
+
return {};
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
export async function logMaintenanceNode(state) {
|
|
189
|
+
logger.info('Maintenance complete', {
|
|
190
|
+
userId: state.userId,
|
|
191
|
+
score: state.healthResult?.score,
|
|
192
|
+
shouldMaintain: state.healthResult?.shouldMaintain,
|
|
193
|
+
rediscoveryJobs: state.rediscoveryJobsEnqueued,
|
|
194
|
+
introducerDiscoveryJobs: state.introducerDiscoveryJobsEnqueued,
|
|
195
|
+
activeIntents: state.activeIntents.length,
|
|
196
|
+
connectorFlowCount: state.connectorFlowCount,
|
|
197
|
+
});
|
|
198
|
+
return {};
|
|
199
|
+
}
|
|
@@ -13,10 +13,10 @@ export declare const McpToolPermissionRequirementSchema: z.ZodObject<{
|
|
|
13
13
|
*/
|
|
14
14
|
reach: z.ZodDefault<z.ZodEnum<["principal", "network"]>>;
|
|
15
15
|
}, "strict", z.ZodTypeAny, {
|
|
16
|
-
action: "manage:
|
|
16
|
+
action: "manage:negotiations" | "manage:intents" | "manage:opportunities" | "manage:identity" | "manage:premises" | "manage:networks";
|
|
17
17
|
reach: "network" | "principal";
|
|
18
18
|
}, {
|
|
19
|
-
action: "manage:
|
|
19
|
+
action: "manage:negotiations" | "manage:intents" | "manage:opportunities" | "manage:identity" | "manage:premises" | "manage:networks";
|
|
20
20
|
reach?: "network" | "principal" | undefined;
|
|
21
21
|
}>;
|
|
22
22
|
export type McpToolPermissionRequirement = z.infer<typeof McpToolPermissionRequirementSchema>;
|
|
@@ -38,19 +38,19 @@ export declare const McpToolAccessRuleSchema: z.ZodEffects<z.ZodObject<{
|
|
|
38
38
|
}, "strict", z.ZodTypeAny, {
|
|
39
39
|
reach: "network" | "principal";
|
|
40
40
|
access: "removed" | "permission" | "authenticated" | "human_only" | "agent_admin" | "informational" | "delivery_only";
|
|
41
|
-
actions?: ("manage:
|
|
41
|
+
actions?: ("manage:negotiations" | "manage:intents" | "manage:opportunities" | "manage:identity" | "manage:premises" | "manage:networks")[] | undefined;
|
|
42
42
|
}, {
|
|
43
43
|
reach: "network" | "principal";
|
|
44
44
|
access: "removed" | "permission" | "authenticated" | "human_only" | "agent_admin" | "informational" | "delivery_only";
|
|
45
|
-
actions?: ("manage:
|
|
45
|
+
actions?: ("manage:negotiations" | "manage:intents" | "manage:opportunities" | "manage:identity" | "manage:premises" | "manage:networks")[] | undefined;
|
|
46
46
|
}>, {
|
|
47
47
|
reach: "network" | "principal";
|
|
48
48
|
access: "removed" | "permission" | "authenticated" | "human_only" | "agent_admin" | "informational" | "delivery_only";
|
|
49
|
-
actions?: ("manage:
|
|
49
|
+
actions?: ("manage:negotiations" | "manage:intents" | "manage:opportunities" | "manage:identity" | "manage:premises" | "manage:networks")[] | undefined;
|
|
50
50
|
}, {
|
|
51
51
|
reach: "network" | "principal";
|
|
52
52
|
access: "removed" | "permission" | "authenticated" | "human_only" | "agent_admin" | "informational" | "delivery_only";
|
|
53
|
-
actions?: ("manage:
|
|
53
|
+
actions?: ("manage:negotiations" | "manage:intents" | "manage:opportunities" | "manage:identity" | "manage:premises" | "manage:networks")[] | undefined;
|
|
54
54
|
}>;
|
|
55
55
|
export type McpToolAccessRule = z.infer<typeof McpToolAccessRuleSchema>;
|
|
56
56
|
export type McpToolAccessRuleMap = ReadonlyMap<string, McpToolAccessRule>;
|
|
@@ -63,7 +63,7 @@ export declare function defineMcpToolAccessRules(rules: Readonly<Record<string,
|
|
|
63
63
|
* retain domain ownership, membership, exact-scope, and approval checks.
|
|
64
64
|
*/
|
|
65
65
|
export declare const CANONICAL_MCP_TOOL_ACCESS_RULES: McpToolAccessRuleMap;
|
|
66
|
-
/** Tools visible
|
|
66
|
+
/** Tools visible on the REST Tool API while web/CLI onboarding is incomplete. MCP does not use this allowlist. */
|
|
67
67
|
export declare const ONBOARDING_ALLOWED: ReadonlySet<string>;
|
|
68
68
|
/** Agent administration inventory. */
|
|
69
69
|
export declare const MCP_AGENT_ADMIN_TOOLS: ReadonlySet<string>;
|
|
@@ -84,72 +84,68 @@ export declare const McpPolicyAgentSnapshotSchema: z.ZodObject<{
|
|
|
84
84
|
userId: string;
|
|
85
85
|
scope: "network" | "global" | "node";
|
|
86
86
|
scopeId: string | null;
|
|
87
|
-
agentId: string;
|
|
88
87
|
actions: string[];
|
|
88
|
+
agentId: string;
|
|
89
89
|
}, {
|
|
90
90
|
userId: string;
|
|
91
91
|
scope: "network" | "global" | "node";
|
|
92
92
|
scopeId: string | null;
|
|
93
|
-
agentId: string;
|
|
94
93
|
actions: string[];
|
|
94
|
+
agentId: string;
|
|
95
95
|
}>, "many">;
|
|
96
96
|
}, "strict", z.ZodTypeAny, {
|
|
97
97
|
id: string;
|
|
98
98
|
type: "system" | "personal" | "external";
|
|
99
99
|
status: "active" | "inactive";
|
|
100
|
-
ownerId: string;
|
|
101
100
|
permissions: {
|
|
102
101
|
userId: string;
|
|
103
102
|
scope: "network" | "global" | "node";
|
|
104
103
|
scopeId: string | null;
|
|
105
|
-
agentId: string;
|
|
106
104
|
actions: string[];
|
|
105
|
+
agentId: string;
|
|
107
106
|
}[];
|
|
107
|
+
ownerId: string;
|
|
108
108
|
}, {
|
|
109
109
|
id: string;
|
|
110
110
|
type: "system" | "personal" | "external";
|
|
111
111
|
status: "active" | "inactive";
|
|
112
|
-
ownerId: string;
|
|
113
112
|
permissions: {
|
|
114
113
|
userId: string;
|
|
115
114
|
scope: "network" | "global" | "node";
|
|
116
115
|
scopeId: string | null;
|
|
117
|
-
agentId: string;
|
|
118
116
|
actions: string[];
|
|
117
|
+
agentId: string;
|
|
119
118
|
}[];
|
|
119
|
+
ownerId: string;
|
|
120
120
|
}>;
|
|
121
121
|
export type McpPolicyAgentSnapshot = z.infer<typeof McpPolicyAgentSnapshotSchema>;
|
|
122
|
-
export declare const McpPrincipalProfileSchema: z.ZodEnum<["session_human", "
|
|
122
|
+
export declare const McpPrincipalProfileSchema: z.ZodEnum<["session_human", "enrollment_key", "unregistered_key", "registered_global_agent", "registered_network_agent", "hermes_agent", "delivery_agent", "invalid_agent"]>;
|
|
123
123
|
export type McpPrincipalProfile = z.infer<typeof McpPrincipalProfileSchema>;
|
|
124
124
|
export declare const McpCapabilitySubjectSchema: z.ZodObject<{
|
|
125
|
-
profile: z.ZodEnum<["session_human", "
|
|
125
|
+
profile: z.ZodEnum<["session_human", "enrollment_key", "unregistered_key", "registered_global_agent", "registered_network_agent", "hermes_agent", "delivery_agent", "invalid_agent"]>;
|
|
126
126
|
userId: z.ZodString;
|
|
127
127
|
agentId: z.ZodOptional<z.ZodString>;
|
|
128
128
|
agentType: z.ZodOptional<z.ZodEnum<["personal", "external", "system"]>>;
|
|
129
|
-
isOnboarding: z.ZodBoolean;
|
|
130
129
|
networkScopeId: z.ZodNullable<z.ZodString>;
|
|
131
130
|
permissions: z.ZodArray<z.ZodEnum<["manage:identity", "manage:premises", "manage:intents", "manage:networks", "manage:opportunities", "manage:negotiations"]>, "many">;
|
|
132
131
|
}, "strict", z.ZodTypeAny, {
|
|
133
132
|
userId: string;
|
|
134
|
-
profile: "session_human" | "
|
|
135
|
-
permissions: ("manage:
|
|
133
|
+
profile: "session_human" | "enrollment_key" | "unregistered_key" | "registered_global_agent" | "registered_network_agent" | "hermes_agent" | "delivery_agent" | "invalid_agent";
|
|
134
|
+
permissions: ("manage:negotiations" | "manage:intents" | "manage:opportunities" | "manage:identity" | "manage:premises" | "manage:networks")[];
|
|
136
135
|
networkScopeId: string | null;
|
|
137
|
-
isOnboarding: boolean;
|
|
138
136
|
agentId?: string | undefined;
|
|
139
137
|
agentType?: "system" | "personal" | "external" | undefined;
|
|
140
138
|
}, {
|
|
141
139
|
userId: string;
|
|
142
|
-
profile: "session_human" | "
|
|
143
|
-
permissions: ("manage:
|
|
140
|
+
profile: "session_human" | "enrollment_key" | "unregistered_key" | "registered_global_agent" | "registered_network_agent" | "hermes_agent" | "delivery_agent" | "invalid_agent";
|
|
141
|
+
permissions: ("manage:negotiations" | "manage:intents" | "manage:opportunities" | "manage:identity" | "manage:premises" | "manage:networks")[];
|
|
144
142
|
networkScopeId: string | null;
|
|
145
|
-
isOnboarding: boolean;
|
|
146
143
|
agentId?: string | undefined;
|
|
147
144
|
agentType?: "system" | "personal" | "external" | undefined;
|
|
148
145
|
}>;
|
|
149
146
|
export type McpCapabilitySubject = z.infer<typeof McpCapabilitySubjectSchema>;
|
|
150
147
|
export type ResolveMcpCapabilitySubjectInput = {
|
|
151
148
|
identity: McpResolvedIdentity;
|
|
152
|
-
isOnboarding: boolean;
|
|
153
149
|
agent?: McpPolicyAgentSnapshot | null;
|
|
154
150
|
};
|
|
155
151
|
/**
|
|
@@ -166,13 +162,13 @@ export declare function projectStoredPermissionActions(actions: readonly string[
|
|
|
166
162
|
export declare function resolveMcpCapabilitySubject(input: ResolveMcpCapabilitySubjectInput): McpCapabilitySubject;
|
|
167
163
|
/**
|
|
168
164
|
* Maps a resolved capability subject to the typed caller context consumed by
|
|
169
|
-
* the centralized activity-summary projection. Session
|
|
170
|
-
*
|
|
171
|
-
*
|
|
172
|
-
*
|
|
165
|
+
* the centralized activity-summary projection. Session humans own the
|
|
166
|
+
* summarized data and receive the full owner view; every other profile is
|
|
167
|
+
* projected as an agent bounded by its granted permissions and (for network
|
|
168
|
+
* agents) its bound community.
|
|
173
169
|
*/
|
|
174
170
|
export declare function resolveMcpActivityCaller(subject: McpCapabilitySubject): McpActivityCaller;
|
|
175
|
-
export declare const McpCapabilityDecisionReasonSchema: z.ZodEnum<["session_human", "
|
|
171
|
+
export declare const McpCapabilityDecisionReasonSchema: z.ZodEnum<["session_human", "enrollment", "authenticated", "agent_self_read", "informational", "permission_granted", "delivery", "enrollment_required", "unregistered_principal", "invalid_agent", "agent_admin_denied", "human_read_own_agent_denied", "human_only", "permission_missing", "delivery_required", "removed", "tool_unclassified"]>;
|
|
176
172
|
export type McpCapabilityDecision = {
|
|
177
173
|
allowed: boolean;
|
|
178
174
|
reason: z.infer<typeof McpCapabilityDecisionReasonSchema>;
|
|
@@ -113,7 +113,6 @@ export const CANONICAL_MCP_TOOL_ACCESS_RULES = defineMcpToolAccessRules({
|
|
|
113
113
|
update_user_context: { access: 'permission', actions: ['manage:identity'], reach: 'principal' },
|
|
114
114
|
get_enrichment_run: { access: 'permission', actions: ['manage:identity'], reach: 'principal' },
|
|
115
115
|
cancel_enrichment_run: { access: 'permission', actions: ['manage:identity'], reach: 'principal' },
|
|
116
|
-
complete_onboarding: { access: 'human_only', reach: 'principal' },
|
|
117
116
|
// Premises are meta-network; a network-scoped agent retains principal reach.
|
|
118
117
|
read_premises: { access: 'permission', actions: ['manage:premises'], reach: 'principal' },
|
|
119
118
|
create_premise: { access: 'permission', actions: ['manage:premises'], reach: 'principal' },
|
|
@@ -204,7 +203,7 @@ export const CANONICAL_MCP_TOOL_ACCESS_RULES = defineMcpToolAccessRules({
|
|
|
204
203
|
// unknown before any authorization work. read_activity_summary (above) is
|
|
205
204
|
// the only public activity-reporting name; no legacy alias is retained.
|
|
206
205
|
});
|
|
207
|
-
/** Tools visible
|
|
206
|
+
/** Tools visible on the REST Tool API while web/CLI onboarding is incomplete. MCP does not use this allowlist. */
|
|
208
207
|
export const ONBOARDING_ALLOWED = new Set([
|
|
209
208
|
'register_agent',
|
|
210
209
|
'read_docs',
|
|
@@ -249,7 +248,6 @@ export const McpPolicyAgentSnapshotSchema = z.object({
|
|
|
249
248
|
}).strict();
|
|
250
249
|
export const McpPrincipalProfileSchema = z.enum([
|
|
251
250
|
'session_human',
|
|
252
|
-
'onboarding_human',
|
|
253
251
|
'enrollment_key',
|
|
254
252
|
'unregistered_key',
|
|
255
253
|
'registered_global_agent',
|
|
@@ -263,7 +261,6 @@ export const McpCapabilitySubjectSchema = z.object({
|
|
|
263
261
|
userId: z.string().min(1),
|
|
264
262
|
agentId: z.string().min(1).optional(),
|
|
265
263
|
agentType: z.enum(['personal', 'external', 'system']).optional(),
|
|
266
|
-
isOnboarding: z.boolean(),
|
|
267
264
|
networkScopeId: z.string().min(1).nullable(),
|
|
268
265
|
permissions: z.array(McpPermissionActionSchema),
|
|
269
266
|
}).strict();
|
|
@@ -336,12 +333,11 @@ function resolveAgentPermissions(identity, agent) {
|
|
|
336
333
|
* Resolves a request-local, runtime-validated principal profile.
|
|
337
334
|
*/
|
|
338
335
|
export function resolveMcpCapabilitySubject(input) {
|
|
339
|
-
const { identity
|
|
336
|
+
const { identity } = input;
|
|
340
337
|
if (identity.isSessionAuth === true) {
|
|
341
338
|
return McpCapabilitySubjectSchema.parse({
|
|
342
|
-
profile:
|
|
339
|
+
profile: 'session_human',
|
|
343
340
|
userId: identity.userId,
|
|
344
|
-
isOnboarding,
|
|
345
341
|
networkScopeId: null,
|
|
346
342
|
permissions: [],
|
|
347
343
|
});
|
|
@@ -350,7 +346,6 @@ export function resolveMcpCapabilitySubject(input) {
|
|
|
350
346
|
return McpCapabilitySubjectSchema.parse({
|
|
351
347
|
profile: identity.enrollmentCapable === true ? 'enrollment_key' : 'unregistered_key',
|
|
352
348
|
userId: identity.userId,
|
|
353
|
-
isOnboarding,
|
|
354
349
|
networkScopeId: null,
|
|
355
350
|
permissions: [],
|
|
356
351
|
});
|
|
@@ -364,7 +359,6 @@ export function resolveMcpCapabilitySubject(input) {
|
|
|
364
359
|
profile: 'invalid_agent',
|
|
365
360
|
userId: identity.userId,
|
|
366
361
|
agentId: identity.agentId,
|
|
367
|
-
isOnboarding,
|
|
368
362
|
networkScopeId: identity.networkScopeId ?? null,
|
|
369
363
|
permissions: [],
|
|
370
364
|
});
|
|
@@ -382,20 +376,19 @@ export function resolveMcpCapabilitySubject(input) {
|
|
|
382
376
|
userId: identity.userId,
|
|
383
377
|
agentId: identity.agentId,
|
|
384
378
|
agentType: agent.type,
|
|
385
|
-
isOnboarding,
|
|
386
379
|
networkScopeId: identity.networkScopeId ?? null,
|
|
387
380
|
permissions: resolveAgentPermissions(identity, agent),
|
|
388
381
|
});
|
|
389
382
|
}
|
|
390
383
|
/**
|
|
391
384
|
* Maps a resolved capability subject to the typed caller context consumed by
|
|
392
|
-
* the centralized activity-summary projection. Session
|
|
393
|
-
*
|
|
394
|
-
*
|
|
395
|
-
*
|
|
385
|
+
* the centralized activity-summary projection. Session humans own the
|
|
386
|
+
* summarized data and receive the full owner view; every other profile is
|
|
387
|
+
* projected as an agent bounded by its granted permissions and (for network
|
|
388
|
+
* agents) its bound community.
|
|
396
389
|
*/
|
|
397
390
|
export function resolveMcpActivityCaller(subject) {
|
|
398
|
-
const isHuman = subject.profile === 'session_human'
|
|
391
|
+
const isHuman = subject.profile === 'session_human';
|
|
399
392
|
return McpActivityCallerSchema.parse({
|
|
400
393
|
kind: isHuman ? 'human' : 'agent',
|
|
401
394
|
permissions: isHuman ? [] : subject.permissions,
|
|
@@ -404,14 +397,12 @@ export function resolveMcpActivityCaller(subject) {
|
|
|
404
397
|
}
|
|
405
398
|
export const McpCapabilityDecisionReasonSchema = z.enum([
|
|
406
399
|
'session_human',
|
|
407
|
-
'onboarding',
|
|
408
400
|
'enrollment',
|
|
409
401
|
'authenticated',
|
|
410
402
|
'agent_self_read',
|
|
411
403
|
'informational',
|
|
412
404
|
'permission_granted',
|
|
413
405
|
'delivery',
|
|
414
|
-
'onboarding_required',
|
|
415
406
|
'enrollment_required',
|
|
416
407
|
'unregistered_principal',
|
|
417
408
|
'invalid_agent',
|
|
@@ -475,9 +466,6 @@ export class McpCapabilityPolicy {
|
|
|
475
466
|
? { allowed: true, reason: 'enrollment', reach: rule.reach }
|
|
476
467
|
: { allowed: false, reason: 'enrollment_required', reach: rule.reach };
|
|
477
468
|
}
|
|
478
|
-
if (subject.isOnboarding && !ONBOARDING_ALLOWED.has(toolName)) {
|
|
479
|
-
return { allowed: false, reason: 'onboarding_required', reach: rule.reach };
|
|
480
|
-
}
|
|
481
469
|
if (subject.profile === 'hermes_agent') {
|
|
482
470
|
const requirement = HERMES_AGENT_MCP_TOOL_PERMISSIONS.get(toolName);
|
|
483
471
|
if (!requirement)
|
|
@@ -516,27 +504,19 @@ export class McpCapabilityPolicy {
|
|
|
516
504
|
? { allowed: true, reason: 'agent_self_read', reach: rule.reach }
|
|
517
505
|
: { allowed: false, reason: 'agent_admin_denied', reach: rule.reach };
|
|
518
506
|
}
|
|
519
|
-
// Session
|
|
520
|
-
//
|
|
521
|
-
if (subject.profile === 'session_human'
|
|
507
|
+
// Session humans get every agent_admin tool EXCEPT read_own_agent,
|
|
508
|
+
// which is reserved for agent principals.
|
|
509
|
+
if (subject.profile === 'session_human') {
|
|
522
510
|
return toolName === 'read_own_agent'
|
|
523
511
|
? { allowed: false, reason: 'human_read_own_agent_denied', reach: rule.reach }
|
|
524
|
-
: {
|
|
525
|
-
allowed: true,
|
|
526
|
-
reason: subject.profile === 'onboarding_human' ? 'onboarding' : 'session_human',
|
|
527
|
-
reach: rule.reach,
|
|
528
|
-
};
|
|
512
|
+
: { allowed: true, reason: 'session_human', reach: rule.reach };
|
|
529
513
|
}
|
|
530
514
|
// Every other profile (enrollment/unregistered/invalid) is handled above
|
|
531
515
|
// and never reaches here; fail closed for completeness.
|
|
532
516
|
return { allowed: false, reason: 'agent_admin_denied', reach: rule.reach };
|
|
533
517
|
}
|
|
534
|
-
if (subject.profile === 'session_human'
|
|
535
|
-
return {
|
|
536
|
-
allowed: true,
|
|
537
|
-
reason: subject.profile === 'onboarding_human' ? 'onboarding' : 'session_human',
|
|
538
|
-
reach: rule.reach,
|
|
539
|
-
};
|
|
518
|
+
if (subject.profile === 'session_human') {
|
|
519
|
+
return { allowed: true, reason: 'session_human', reach: rule.reach };
|
|
540
520
|
}
|
|
541
521
|
if (rule.access === 'human_only') {
|
|
542
522
|
return { allowed: false, reason: 'human_only', reach: rule.reach };
|
package/dist/mcp/mcp.server.d.ts
CHANGED
|
@@ -77,9 +77,9 @@ export interface ScopedDepsFactory {
|
|
|
77
77
|
export declare const applyNetworkScopeToContext: (context: ResolvedToolContext, networkScopeId: string | null | undefined) => void;
|
|
78
78
|
export { ONBOARDING_ALLOWED } from './mcp.authorization-policy.js';
|
|
79
79
|
/**
|
|
80
|
-
* Builds the onboarding gate message for
|
|
81
|
-
* chat
|
|
82
|
-
*
|
|
80
|
+
* Builds the onboarding gate message for REST Tool API callers. Condensed
|
|
81
|
+
* from the chat onboarding flow into a 6-step tool-error guide. MCP does
|
|
82
|
+
* not use this gate.
|
|
83
83
|
*/
|
|
84
84
|
export declare function buildMcpOnboardingMessage(ctx: ResolvedToolContext): string;
|
|
85
85
|
export declare const MCP_INSTRUCTIONS: string;
|