@secondlayer/sentinel 0.1.0 → 0.2.0
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/README.md +1 -1
- package/dist/cli.js +458 -48
- package/dist/index.js +23 -3
- package/dist/kind.d.ts +42 -0
- package/dist/mcp.js +358 -30
- package/dist/sentinel-client.d.ts +86 -6
- package/package.json +1 -1
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Client for the Sentinel v1 API (docs/api.md). Shared by the MCP server and the CLI. No dependencies:
|
|
3
3
|
* global fetch. Auth is one function, `authHeader`, so another credential can be swapped in later.
|
|
4
4
|
*/
|
|
5
|
+
import type { AlertLevel, FindingKind } from "./kind";
|
|
5
6
|
export declare const DEFAULT_BASE_URL = "https://api.runsentinel.app";
|
|
6
7
|
export declare class SentinelError extends Error {
|
|
7
8
|
readonly status: number;
|
|
@@ -47,8 +48,25 @@ export type Finding = {
|
|
|
47
48
|
verdict: string;
|
|
48
49
|
disposition: string;
|
|
49
50
|
poc?: string;
|
|
51
|
+
/** What the finding is for the people watching (client/kind.ts), stamped by the API. */
|
|
52
|
+
kind?: FindingKind;
|
|
53
|
+
/** How the finding's watch pages; absent on a refuted finding. */
|
|
54
|
+
alertLevel?: AlertLevel;
|
|
55
|
+
reverified?: boolean;
|
|
56
|
+
/** "fn" when `targetFn` names the function; "contract" when no single function carries it. */
|
|
57
|
+
scope?: "fn" | "contract";
|
|
58
|
+
/** Trust findings: the powers held by design, one entry each. */
|
|
59
|
+
powers?: Power[];
|
|
60
|
+
/** The watch row's subject, a short fn-level phrase (verified owners only). */
|
|
61
|
+
watchSubject?: string;
|
|
50
62
|
[field: string]: unknown;
|
|
51
63
|
};
|
|
64
|
+
/** One power a trust finding describes (monitoring/adjudication.ts `Power`, copied: no deps). */
|
|
65
|
+
export type Power = {
|
|
66
|
+
holder: string;
|
|
67
|
+
can: string;
|
|
68
|
+
fn?: string;
|
|
69
|
+
};
|
|
52
70
|
/** A plan at the caller's access level: `access` is absent on the teaser. */
|
|
53
71
|
export type PlanView = {
|
|
54
72
|
view: string;
|
|
@@ -114,6 +132,11 @@ export type WatchSubject = {
|
|
|
114
132
|
} | {
|
|
115
133
|
kind: "asset";
|
|
116
134
|
asset: string;
|
|
135
|
+
}
|
|
136
|
+
/** Control changes: one group over every fn that changes who controls the contract. */
|
|
137
|
+
| {
|
|
138
|
+
kind: "group";
|
|
139
|
+
group: "control";
|
|
117
140
|
};
|
|
118
141
|
export type WatchStatus = "suggested" | "live" | "paused";
|
|
119
142
|
export type Units = {
|
|
@@ -146,8 +169,57 @@ export type StoredWatch = {
|
|
|
146
169
|
updatedAt: string;
|
|
147
170
|
units: Units | null;
|
|
148
171
|
};
|
|
172
|
+
export type IntentKind = "money_out" | "control" | "finding" | "owner_fn";
|
|
173
|
+
/**
|
|
174
|
+
* One intent watch: what a team sees (Money out per asset, Control changes, one per finding, a fn the team
|
|
175
|
+
* added). `rows` are the stored watches behind it: what a rule edit, a switch or a mute acts on.
|
|
176
|
+
*/
|
|
177
|
+
export type IntentWatch<R = StoredWatch & {
|
|
178
|
+
on: boolean;
|
|
179
|
+
}> = {
|
|
180
|
+
id: string;
|
|
181
|
+
kind: IntentKind;
|
|
182
|
+
title: string;
|
|
183
|
+
tag: string;
|
|
184
|
+
summary: string;
|
|
185
|
+
on: boolean;
|
|
186
|
+
alertLevel: "urgent" | "normal";
|
|
187
|
+
watchIds: string[];
|
|
188
|
+
rows: R[];
|
|
189
|
+
members: {
|
|
190
|
+
group: string;
|
|
191
|
+
fns: string[];
|
|
192
|
+
}[];
|
|
193
|
+
/** Money out: the asset, its token units and its threshold (null amount: every outflow alerts). */
|
|
194
|
+
asset?: string;
|
|
195
|
+
units?: Units | null;
|
|
196
|
+
threshold?: {
|
|
197
|
+
amount: string | null;
|
|
198
|
+
basis: string;
|
|
199
|
+
confirmed: boolean;
|
|
200
|
+
suggested: {
|
|
201
|
+
amount: string;
|
|
202
|
+
basis: string;
|
|
203
|
+
} | null;
|
|
204
|
+
};
|
|
205
|
+
findingRef?: {
|
|
206
|
+
title: string;
|
|
207
|
+
index: number | null;
|
|
208
|
+
};
|
|
209
|
+
};
|
|
210
|
+
/** The stored rows behind a list of intent watches, in order. */
|
|
211
|
+
export declare const rowsOf: <R>(intents: {
|
|
212
|
+
rows: R[];
|
|
213
|
+
}[]) => R[];
|
|
149
214
|
export type WatchesView = {
|
|
150
|
-
|
|
215
|
+
intents: IntentWatch[];
|
|
216
|
+
/** "N of M on", over intent watches. */
|
|
217
|
+
counts: {
|
|
218
|
+
on: number;
|
|
219
|
+
total: number;
|
|
220
|
+
};
|
|
221
|
+
/** Finding-based watches hidden until the account verifies control (a count only). */
|
|
222
|
+
locked: number;
|
|
151
223
|
events: {
|
|
152
224
|
id: string;
|
|
153
225
|
watchId: string;
|
|
@@ -167,13 +239,13 @@ export type StartedMonitoring = {
|
|
|
167
239
|
contractId: string;
|
|
168
240
|
planId: string;
|
|
169
241
|
status: "draft" | "requested" | "live";
|
|
170
|
-
|
|
242
|
+
intents: IntentWatch<StoredWatchView>[];
|
|
171
243
|
webhookUrl: string | null;
|
|
172
244
|
slackUrl: string | null;
|
|
173
245
|
emailAlerts: boolean;
|
|
174
246
|
hasSigningSecret: boolean;
|
|
175
247
|
};
|
|
176
|
-
type StoredWatchView = Pick<StoredWatch, "id" | "subject" | "rule" | "status" | "title">;
|
|
248
|
+
type StoredWatchView = Pick<StoredWatch, "id" | "subject" | "rule" | "suggestedRule" | "delivery" | "provenance" | "status" | "title" | "reason" | "units">;
|
|
177
249
|
export type WatchChoice = {
|
|
178
250
|
watchId?: string;
|
|
179
251
|
fn: string;
|
|
@@ -200,7 +272,8 @@ export type DeliveryResult = {
|
|
|
200
272
|
detail: string;
|
|
201
273
|
};
|
|
202
274
|
export declare const subjectKey: (s: WatchSubject) => string;
|
|
203
|
-
|
|
275
|
+
export declare const CONTROL_NAME = "Control changes";
|
|
276
|
+
/** The subject's display name: the fn name, the token's symbol (never the raw token id), or the group's. */
|
|
204
277
|
export declare function subjectName(s: WatchSubject, units: Units | null): string;
|
|
205
278
|
type HasSubject = {
|
|
206
279
|
subject: WatchSubject;
|
|
@@ -220,7 +293,8 @@ export declare class SubjectError extends Error {
|
|
|
220
293
|
export declare function groupSubjects<W extends HasSubject>(watches: W[]): SubjectMatch<W>[];
|
|
221
294
|
/**
|
|
222
295
|
* The watches on the subject `name` points at: its display name (fn name, token symbol, or the part
|
|
223
|
-
* after
|
|
296
|
+
* after `::`, or "Control changes" / "control"), its subjectKey (`fn:…` / `asset:…` / `group:control`) or a
|
|
297
|
+
* full asset id, case-insensitive. A name that
|
|
224
298
|
* matches nothing, or more than one subject, throws a SubjectError listing the candidates.
|
|
225
299
|
*/
|
|
226
300
|
export declare function resolveSubject<W extends HasSubject>(watches: W[], name: string): SubjectMatch<W>;
|
|
@@ -231,6 +305,8 @@ export declare function ruleSummary(rule: WatchRule, units: Units | null): strin
|
|
|
231
305
|
export type WatchKindTag = "finding" | "outflow" | "who-acts" | "governance" | "upgrade";
|
|
232
306
|
/** The plain tag a rule is listed under. */
|
|
233
307
|
export declare function kindTag(rule: WatchRule): WatchKindTag;
|
|
308
|
+
/** An intent watch's one line: a Money out threshold in token units (or its fail-safe), else its summary. */
|
|
309
|
+
export declare function intentLine(i: Pick<IntentWatch<unknown>, "kind" | "summary" | "threshold" | "units">): string;
|
|
234
310
|
/** A subject's status from its rules: live if any is, else paused if all are, else suggested. */
|
|
235
311
|
export declare function subjectStatus(ws: {
|
|
236
312
|
status: WatchStatus;
|
|
@@ -355,7 +431,11 @@ export type WatchContext = {
|
|
|
355
431
|
contractId: string;
|
|
356
432
|
/** The plan's access level for this caller; a claimed one hides exploit detail. */
|
|
357
433
|
access: PlanView["access"];
|
|
358
|
-
|
|
434
|
+
intents: IntentWatch[];
|
|
435
|
+
/** The stored rows behind the intents: what subjects resolve over. */
|
|
436
|
+
watches: (StoredWatch & {
|
|
437
|
+
on: boolean;
|
|
438
|
+
})[];
|
|
359
439
|
};
|
|
360
440
|
/** The caller's watches for a plan. */
|
|
361
441
|
export declare function watchContext(client: SentinelClient, planId: string): Promise<WatchContext>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@secondlayer/sentinel",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Sentinel from a terminal or an agent: the CLI, an MCP server and a client for your Stacks contract monitoring.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "https://runsentinel.app/docs",
|