@senpi/runtime 3.0.57 → 3.0.59
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/actions/action-events.d.ts +3 -3
- package/dist/actions/action-events.d.ts.map +1 -1
- package/dist/actions/action-events.js +24 -16
- package/dist/actions/action-events.js.map +1 -1
- package/dist/actions/action-runtime-module.d.ts.map +1 -1
- package/dist/actions/action-runtime-module.js +18 -1
- package/dist/actions/action-runtime-module.js.map +1 -1
- package/dist/actions/close-position/close-position.action.d.ts.map +1 -1
- package/dist/actions/close-position/close-position.action.js +84 -11
- package/dist/actions/close-position/close-position.action.js.map +1 -1
- package/dist/actions/event-derivation.d.ts +40 -2
- package/dist/actions/event-derivation.d.ts.map +1 -1
- package/dist/actions/event-derivation.js +178 -5
- package/dist/actions/event-derivation.js.map +1 -1
- package/dist/actions/open-position/open-position.action.d.ts.map +1 -1
- package/dist/actions/open-position/open-position.action.js +103 -16
- package/dist/actions/open-position/open-position.action.js.map +1 -1
- package/dist/actions/position-tracker/position-tracker.action.d.ts +2 -1
- package/dist/actions/position-tracker/position-tracker.action.d.ts.map +1 -1
- package/dist/actions/position-tracker/position-tracker.action.js +47 -15
- package/dist/actions/position-tracker/position-tracker.action.js.map +1 -1
- package/dist/actions/skipped-signal-results.d.ts +16 -0
- package/dist/actions/skipped-signal-results.d.ts.map +1 -0
- package/dist/actions/skipped-signal-results.js +47 -0
- package/dist/actions/skipped-signal-results.js.map +1 -0
- package/dist/cli/guide-commands.d.ts.map +1 -1
- package/dist/cli/guide-commands.js +28 -2
- package/dist/cli/guide-commands.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -1
- package/dist/runtime/lifecycle-events.d.ts +13 -0
- package/dist/runtime/lifecycle-events.d.ts.map +1 -1
- package/dist/runtime/lifecycle-events.js +32 -0
- package/dist/runtime/lifecycle-events.js.map +1 -1
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +3 -1
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/runtime/supervisor/long-running-supervisor.d.ts +8 -0
- package/dist/runtime/supervisor/long-running-supervisor.d.ts.map +1 -1
- package/dist/runtime/supervisor/long-running-supervisor.js +1 -0
- package/dist/runtime/supervisor/long-running-supervisor.js.map +1 -1
- package/dist/runtime-api/intake/intake-events.d.ts +19 -3
- package/dist/runtime-api/intake/intake-events.d.ts.map +1 -1
- package/dist/runtime-api/intake/intake-events.js +64 -2
- package/dist/runtime-api/intake/intake-events.js.map +1 -1
- package/dist/runtime-api/intake/process-signal-post.d.ts.map +1 -1
- package/dist/runtime-api/intake/process-signal-post.js +7 -1
- package/dist/runtime-api/intake/process-signal-post.js.map +1 -1
- package/dist/runtime-api/intake/scanner-launcher.d.ts.map +1 -1
- package/dist/runtime-api/intake/scanner-launcher.js +12 -0
- package/dist/runtime-api/intake/scanner-launcher.js.map +1 -1
- package/dist/runtime-api/intake/types.d.ts +24 -0
- package/dist/runtime-api/intake/types.d.ts.map +1 -1
- package/dist/runtime-api/routes/signals.d.ts.map +1 -1
- package/dist/runtime-api/routes/signals.js +10 -1
- package/dist/runtime-api/routes/signals.js.map +1 -1
- package/dist/runtime-api/routes/signals.schema.d.ts +10 -0
- package/dist/runtime-api/routes/signals.schema.d.ts.map +1 -1
- package/dist/runtime-api/routes/signals.schema.js +14 -0
- package/dist/runtime-api/routes/signals.schema.js.map +1 -1
- package/dist/scanners/events.d.ts +7 -0
- package/dist/scanners/events.d.ts.map +1 -1
- package/dist/scanners/events.js.map +1 -1
- package/dist/scanners/external/scaffold/delivery.py +23 -12
- package/dist/scanners/external/scaffold/http_post.py +10 -2
- package/dist/scanners/external/scaffold/import_check.py +6 -1
- package/dist/scanners/external/scaffold/preflight.py +6 -2
- package/dist/scanners/external/scaffold/scaffold.py +63 -11
- package/dist/scanners/runtime-module.d.ts.map +1 -1
- package/dist/scanners/runtime-module.js +10 -2
- package/dist/scanners/runtime-module.js.map +1 -1
- package/dist/telemetry/event-builders.d.ts +45 -6
- package/dist/telemetry/event-builders.d.ts.map +1 -1
- package/dist/telemetry/event-builders.js +99 -11
- package/dist/telemetry/event-builders.js.map +1 -1
- package/dist/telemetry/metrics.d.ts +14 -2
- package/dist/telemetry/metrics.d.ts.map +1 -1
- package/dist/telemetry/metrics.js +19 -4
- package/dist/telemetry/metrics.js.map +1 -1
- package/dist/telemetry/scanner-tick-event.d.ts +32 -0
- package/dist/telemetry/scanner-tick-event.d.ts.map +1 -0
- package/dist/telemetry/scanner-tick-event.js +32 -0
- package/dist/telemetry/scanner-tick-event.js.map +1 -0
- package/dist/utils/event-catalog.d.ts +76 -0
- package/dist/utils/event-catalog.d.ts.map +1 -1
- package/dist/utils/event-catalog.js +7 -0
- package/dist/utils/event-catalog.js.map +1 -1
- package/dist/validate/codes.d.ts +2 -0
- package/dist/validate/codes.d.ts.map +1 -1
- package/dist/validate/codes.js +6 -0
- package/dist/validate/codes.js.map +1 -1
- package/dist/validate/import-stage.d.ts.map +1 -1
- package/dist/validate/import-stage.js +7 -1
- package/dist/validate/import-stage.js.map +1 -1
- package/dist/validate/live-stage.d.ts +26 -0
- package/dist/validate/live-stage.d.ts.map +1 -1
- package/dist/validate/live-stage.js +65 -9
- package/dist/validate/live-stage.js.map +1 -1
- package/dist/validate/proof.d.ts.map +1 -1
- package/dist/validate/proof.js +37 -24
- package/dist/validate/proof.js.map +1 -1
- package/dist/validate/recipe-checks.d.ts.map +1 -1
- package/dist/validate/recipe-checks.js +4 -1
- package/dist/validate/recipe-checks.js.map +1 -1
- package/dist/validate/report.d.ts.map +1 -1
- package/dist/validate/report.js +3 -1
- package/dist/validate/report.js.map +1 -1
- package/dist/validate/run.d.ts.map +1 -1
- package/dist/validate/run.js +41 -14
- package/dist/validate/run.js.map +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
|
@@ -28,13 +28,36 @@ export interface IntakeSignal {
|
|
|
28
28
|
marginPct?: number;
|
|
29
29
|
leverage?: number;
|
|
30
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Per-tick facts about the SCAN, sent alongside whichever exit the scaffold's tick took.
|
|
33
|
+
* `candidate_count` is what this tick's `scan()` returned — the `signals` array cannot stand in for
|
|
34
|
+
* it, since the delivery sink prepends still-pending retries from earlier ticks. Optional on both
|
|
35
|
+
* bodies: a scaffold predating the block still gets its scan recorded, minus duration/seq.
|
|
36
|
+
*/
|
|
37
|
+
export interface IntakeTickMeta {
|
|
38
|
+
/** The scaffold's per-child tick counter; 1-based. */
|
|
39
|
+
seq: number;
|
|
40
|
+
duration_ms: number;
|
|
41
|
+
candidate_count: number;
|
|
42
|
+
}
|
|
31
43
|
/** Request body for POST /signals. */
|
|
32
44
|
export interface SignalsBody {
|
|
33
45
|
scanner_id: string;
|
|
34
46
|
signals: IntakeSignal[];
|
|
47
|
+
tick?: IntakeTickMeta;
|
|
35
48
|
}
|
|
36
49
|
/** Per-signal outcome in the response. */
|
|
37
50
|
export interface PerSignalStatus {
|
|
51
|
+
/**
|
|
52
|
+
* The producer's `signal_id`, echoed back verbatim. The producer matches
|
|
53
|
+
* outcomes by this key and NEVER by array position, so a status without it is
|
|
54
|
+
* unmatchable — the signal stays pending and is retried until it expires.
|
|
55
|
+
*
|
|
56
|
+
* Optional only because a direct (non-route) caller can supply an unusable
|
|
57
|
+
* signal_id; over the wire TypeBox guarantees a non-empty string, so every
|
|
58
|
+
* status the producer sees carries it.
|
|
59
|
+
*/
|
|
60
|
+
signal_id?: string;
|
|
38
61
|
status: "accepted" | "expired" | "superseded" | "rejected";
|
|
39
62
|
correlationId?: string;
|
|
40
63
|
reason?: string;
|
|
@@ -51,6 +74,7 @@ export interface SignalsErrorResponse {
|
|
|
51
74
|
export interface ErrorsBody {
|
|
52
75
|
scanner_id: string;
|
|
53
76
|
error: Record<string, unknown>;
|
|
77
|
+
tick?: IntakeTickMeta;
|
|
54
78
|
}
|
|
55
79
|
/** Response for POST /errors. */
|
|
56
80
|
export interface ErrorsResponse {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/runtime-api/intake/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,2CAA2C;AAC3C,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,sCAAsC;AACtC,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,YAAY,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/runtime-api/intake/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,2CAA2C;AAC3C,MAAM,WAAW,YAAY;IAC3B;;;;OAIG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,sDAAsD;IACtD,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,sCAAsC;AACtC,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,IAAI,CAAC,EAAE,cAAc,CAAC;CACvB;AAED,0CAA0C;AAC1C,MAAM,WAAW,eAAe;IAC9B;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,YAAY,GAAG,UAAU,CAAC;IAC3D,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,0CAA0C;AAC1C,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,eAAe,EAAE,CAAC;CAC5B;AAED,gDAAgD;AAChD,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,qCAAqC;AACrC,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,IAAI,CAAC,EAAE,cAAc,CAAC;CACvB;AAED,iCAAiC;AACjC,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signals.d.ts","sourceRoot":"","sources":["../../../src/runtime-api/routes/signals.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAgC,MAAM,SAAS,CAAC;AAO7E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAc,KAAK,MAAM,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"signals.d.ts","sourceRoot":"","sources":["../../../src/runtime-api/routes/signals.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAgC,MAAM,SAAS,CAAC;AAO7E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAc,KAAK,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAehE,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,eAAe,CAAC;IAC1B,MAAM,EAAE,gBAAgB,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,MAAM,CAAC;IACjC,cAAc,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1D,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7E,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACtE;;;;OAIG;IACH,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,wFAAwF;IACxF,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,eAAe,EACxB,IAAI,EAAE,wBAAwB,GAC7B,IAAI,CA+ON"}
|
|
@@ -10,7 +10,7 @@ import { processErrorPost } from "../intake/process-error-post.js";
|
|
|
10
10
|
import { noopLogger } from "../../utils/logger.js";
|
|
11
11
|
import { emitEvent } from "../../actions/event-derivation.js";
|
|
12
12
|
import { recordSignalIntake } from "../../telemetry/metrics.js";
|
|
13
|
-
import { buildSignalDispositionEvent, buildSignalRejectedEvent, buildScaffoldErrorEvent, } from "../intake/intake-events.js";
|
|
13
|
+
import { buildSignalDispositionEvent, buildSignalRejectedEvent, buildScaffoldErrorEvent, buildSignalsTickEvent, buildErrorsTickEvent, } from "../intake/intake-events.js";
|
|
14
14
|
/**
|
|
15
15
|
* Register the supervised intake /signals and /errors routes.
|
|
16
16
|
*/
|
|
@@ -136,6 +136,11 @@ export function registerSignalsRoute(fastify, opts) {
|
|
|
136
136
|
error: { code: result.reason, message: result.reason },
|
|
137
137
|
});
|
|
138
138
|
}
|
|
139
|
+
// One `scanner.tick` per clean scaffold tick — the "a scan happened" record, emitted here so
|
|
140
|
+
// the single call covers both the empty and signal-bearing branches below. It is deliberately
|
|
141
|
+
// NOT emitted on the three refusals above (invalid shape, oversized batch, unknown scanner):
|
|
142
|
+
// none is a scan, and each already has its own coded `signal.rejected`.
|
|
143
|
+
emitEvent(logger, () => buildSignalsTickEvent(ctx, body.tick, body.signals.length));
|
|
139
144
|
// Empty signals list — a no-op liveness ping (a watch-only scanner POSTs empty
|
|
140
145
|
// every tick), not a catalogued disposition. Log at debug so it doesn't drown
|
|
141
146
|
// the real per-signal outcome events emitted below.
|
|
@@ -213,6 +218,10 @@ export function registerSignalsRoute(fastify, opts) {
|
|
|
213
218
|
wallet: resolved?.wallet,
|
|
214
219
|
};
|
|
215
220
|
emitEvent(logger, () => buildScaffoldErrorEvent(body.error, ctx));
|
|
221
|
+
// The same scan, on the `scanner.tick` plane. Only whole failed ticks qualify — a
|
|
222
|
+
// `candidate_rejected` body rides an otherwise-clean tick that also POSTs `/signals`, and
|
|
223
|
+
// counting it there would give one scan two rows.
|
|
224
|
+
emitEvent(logger, () => buildErrorsTickEvent(ctx, body.error, body.tick));
|
|
216
225
|
enrichIntakeSpan({
|
|
217
226
|
"senpi.scanner.id": body.scanner_id,
|
|
218
227
|
"senpi.intake.disposition": "scaffold_error",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signals.js","sourceRoot":"","sources":["../../../src/runtime-api/routes/signals.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,KAAK,EAAmB,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAEhD,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAGnE,OAAO,EAAE,UAAU,EAAe,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EACL,2BAA2B,EAC3B,wBAAwB,EACxB,uBAAuB,
|
|
1
|
+
{"version":3,"file":"signals.js","sourceRoot":"","sources":["../../../src/runtime-api/routes/signals.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,10 +22,20 @@ export declare const SignalsBodySchema: import("@sinclair/typebox").TObject<{
|
|
|
22
22
|
marginPct: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
|
23
23
|
leverage: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
|
24
24
|
}>>;
|
|
25
|
+
tick: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
|
|
26
|
+
seq: import("@sinclair/typebox").TInteger;
|
|
27
|
+
duration_ms: import("@sinclair/typebox").TInteger;
|
|
28
|
+
candidate_count: import("@sinclair/typebox").TInteger;
|
|
29
|
+
}>>;
|
|
25
30
|
}>;
|
|
26
31
|
/** TypeBox schema for the /errors request body. */
|
|
27
32
|
export declare const ErrorsBodySchema: import("@sinclair/typebox").TObject<{
|
|
28
33
|
scanner_id: import("@sinclair/typebox").TString;
|
|
29
34
|
error: import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TUnknown>;
|
|
35
|
+
tick: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
|
|
36
|
+
seq: import("@sinclair/typebox").TInteger;
|
|
37
|
+
duration_ms: import("@sinclair/typebox").TInteger;
|
|
38
|
+
candidate_count: import("@sinclair/typebox").TInteger;
|
|
39
|
+
}>>;
|
|
30
40
|
}>;
|
|
31
41
|
//# sourceMappingURL=signals.schema.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signals.schema.d.ts","sourceRoot":"","sources":["../../../src/runtime-api/routes/signals.schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA+
|
|
1
|
+
{"version":3,"file":"signals.schema.d.ts","sourceRoot":"","sources":["../../../src/runtime-api/routes/signals.schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA+CH,yDAAyD;AACzD,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;EAO7B,CAAC;AAEF,mDAAmD;AACnD,eAAO,MAAM,gBAAgB;;;;;;;;EAO5B,CAAC"}
|
|
@@ -32,14 +32,28 @@ const IntakeSignalSchema = Type.Object({
|
|
|
32
32
|
// No max on leverage — it is clamped downstream by the exchange.
|
|
33
33
|
leverage: Type.Optional(Type.Number({ exclusiveMinimum: 0 })),
|
|
34
34
|
}, { additionalProperties: false });
|
|
35
|
+
/**
|
|
36
|
+
* TypeBox schema for the per-tick facts the scaffold reports alongside whichever exit its tick took.
|
|
37
|
+
* These describe the SCAN, not the payload: `candidate_count` is what this tick's `scan()` returned,
|
|
38
|
+
* which the `signals` array cannot stand in for (the delivery sink prepends still-pending retries
|
|
39
|
+
* from earlier ticks). Optional on both bodies on purpose — a runtime running against a scaffold that
|
|
40
|
+
* predates the block still records that the scan happened, just without duration/seq.
|
|
41
|
+
*/
|
|
42
|
+
const TickMetaSchema = Type.Object({
|
|
43
|
+
seq: Type.Integer({ minimum: 1 }),
|
|
44
|
+
duration_ms: Type.Integer({ minimum: 0 }),
|
|
45
|
+
candidate_count: Type.Integer({ minimum: 0 }),
|
|
46
|
+
}, { additionalProperties: false });
|
|
35
47
|
/** TypeBox schema for the full /signals request body. */
|
|
36
48
|
export const SignalsBodySchema = Type.Object({
|
|
37
49
|
scanner_id: Type.String({ minLength: 1 }),
|
|
38
50
|
signals: Type.Array(IntakeSignalSchema),
|
|
51
|
+
tick: Type.Optional(TickMetaSchema),
|
|
39
52
|
}, { additionalProperties: false });
|
|
40
53
|
/** TypeBox schema for the /errors request body. */
|
|
41
54
|
export const ErrorsBodySchema = Type.Object({
|
|
42
55
|
scanner_id: Type.String({ minLength: 1 }),
|
|
43
56
|
error: Type.Record(Type.String(), Type.Unknown()),
|
|
57
|
+
tick: Type.Optional(TickMetaSchema),
|
|
44
58
|
}, { additionalProperties: false });
|
|
45
59
|
//# sourceMappingURL=signals.schema.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signals.schema.js","sourceRoot":"","sources":["../../../src/runtime-api/routes/signals.schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC,iEAAiE;AACjE,MAAM,kBAAkB,GAAG,IAAI,CAAC,MAAM,CACpC;IACE,6EAA6E;IAC7E,8EAA8E;IAC9E,+EAA+E;IAC/E,sDAAsD;IACtD,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;IACxC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;IACpC,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IACpE,WAAW,EAAE,IAAI,CAAC,MAAM,EAAE;IAC1B,WAAW,EAAE,IAAI,CAAC,MAAM,EAAE;IAC1B,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;IAChD,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;IACzC,+EAA+E;IAC/E,iFAAiF;IACjF,0EAA0E;IAC1E,iBAAiB;IACjB,gFAAgF;IAChF,oFAAoF;IACpF,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,gBAAgB,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;IAC5E,iEAAiE;IACjE,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,gBAAgB,EAAE,CAAC,EAAE,CAAC,CAAC;CAC9D,EACD,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAChC,CAAC;AAEF,yDAAyD;AACzD,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC,MAAM,CAC1C;IACE,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;IACzC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"signals.schema.js","sourceRoot":"","sources":["../../../src/runtime-api/routes/signals.schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC,iEAAiE;AACjE,MAAM,kBAAkB,GAAG,IAAI,CAAC,MAAM,CACpC;IACE,6EAA6E;IAC7E,8EAA8E;IAC9E,+EAA+E;IAC/E,sDAAsD;IACtD,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;IACxC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;IACpC,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IACpE,WAAW,EAAE,IAAI,CAAC,MAAM,EAAE;IAC1B,WAAW,EAAE,IAAI,CAAC,MAAM,EAAE;IAC1B,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;IAChD,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;IACzC,+EAA+E;IAC/E,iFAAiF;IACjF,0EAA0E;IAC1E,iBAAiB;IACjB,gFAAgF;IAChF,oFAAoF;IACpF,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,gBAAgB,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;IAC5E,iEAAiE;IACjE,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,gBAAgB,EAAE,CAAC,EAAE,CAAC,CAAC;CAC9D,EACD,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAChC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,CAChC;IACE,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;IACjC,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;IACzC,eAAe,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;CAC9C,EACD,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAChC,CAAC;AAEF,yDAAyD;AACzD,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC,MAAM,CAC1C;IACE,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;IACzC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC;IACvC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC;CACpC,EACD,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAChC,CAAC;AAEF,mDAAmD;AACnD,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CAAC,MAAM,CACzC;IACE,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;IACzC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;IACjD,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC;CACpC,EACD,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAChC,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ScanStatus, type ScanResult, type ScannerId } from "./types.js";
|
|
2
|
+
import type { ScannerScheduleMode } from "./scanner-definition.js";
|
|
2
3
|
/** Emitted when one scanner execution attempt starts. */
|
|
3
4
|
export interface ScannerRunStartEvent {
|
|
4
5
|
address: string;
|
|
@@ -13,6 +14,8 @@ export interface ScannerRunCompleteEvent {
|
|
|
13
14
|
result: ScanResult;
|
|
14
15
|
/** Epoch ms of the matching run start (data stamping for telemetry; absent if no start was seen). */
|
|
15
16
|
startedAt?: number;
|
|
17
|
+
/** How the scanner is driven (data stamping for telemetry; absent if the registration is gone). */
|
|
18
|
+
scheduleMode?: ScannerScheduleMode;
|
|
16
19
|
}
|
|
17
20
|
/** Emitted when one scanner execution attempt terminates with a skip-like status. */
|
|
18
21
|
export interface ScannerRunSkipEvent {
|
|
@@ -23,6 +26,8 @@ export interface ScannerRunSkipEvent {
|
|
|
23
26
|
reason: string;
|
|
24
27
|
/** Epoch ms of the matching run start (data stamping for telemetry; absent if no start was seen). */
|
|
25
28
|
startedAt?: number;
|
|
29
|
+
/** How the scanner is driven (data stamping for telemetry; absent if the registration is gone). */
|
|
30
|
+
scheduleMode?: ScannerScheduleMode;
|
|
26
31
|
}
|
|
27
32
|
/** Emitted when one scanner execution attempt fails with an error status. */
|
|
28
33
|
export interface ScannerRunErrorEvent {
|
|
@@ -32,6 +37,8 @@ export interface ScannerRunErrorEvent {
|
|
|
32
37
|
error: unknown;
|
|
33
38
|
/** Epoch ms of the matching run start (data stamping for telemetry; absent if no start was seen). */
|
|
34
39
|
startedAt?: number;
|
|
40
|
+
/** How the scanner is driven (data stamping for telemetry; absent if the registration is gone). */
|
|
41
|
+
scheduleMode?: ScannerScheduleMode;
|
|
35
42
|
}
|
|
36
43
|
/** Scanner runtime pub/sub event map. */
|
|
37
44
|
export interface ScannerRuntimeEventMap {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/scanners/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/scanners/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AACzE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAEnE,yDAAyD;AACzD,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,SAAS,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,sFAAsF;AACtF,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,SAAS,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,UAAU,CAAC;IACnB,qGAAqG;IACrG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mGAAmG;IACnG,YAAY,CAAC,EAAE,mBAAmB,CAAC;CACpC;AAED,qFAAqF;AACrF,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,SAAS,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,qGAAqG;IACrG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mGAAmG;IACnG,YAAY,CAAC,EAAE,mBAAmB,CAAC;CACpC;AAED,6EAA6E;AAC7E,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,SAAS,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;IACf,qGAAqG;IACrG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mGAAmG;IACnG,YAAY,CAAC,EAAE,mBAAmB,CAAC;CACpC;AAED,yCAAyC;AACzC,MAAM,WAAW,sBAAsB;IACrC,mBAAmB,EAAE,oBAAoB,CAAC;IAC1C,sBAAsB,EAAE,uBAAuB,CAAC;IAChD,kBAAkB,EAAE,mBAAmB,CAAC;IACxC,mBAAmB,EAAE,oBAAoB,CAAC;CAC3C;AAED,qEAAqE;AACrE,MAAM,MAAM,uBAAuB,GAAG,MAAM,sBAAsB,CAAC;AAEnE,sFAAsF;AACtF,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,CAAC,SAAS,EAAE,uBAAuB,EAAE,KAAK,EAAE,sBAAsB,CAAC,uBAAuB,CAAC,KAAK,IAAI,EAC1G,MAAM,EAAE,UAAU,GACjB,IAAI,CAiCN"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/scanners/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAmC,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/scanners/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAmC,MAAM,YAAY,CAAC;AA0DzE,sFAAsF;AACtF,MAAM,UAAU,2BAA2B,CACzC,IAA0G,EAC1G,MAAkB;IAElB,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;IACnC,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,CAAC,KAAK,EAAE,CAAC;QACvC,IAAI,CAAC,mBAAmB,EAAE;YACxB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,SAAS;YACT,KAAK,EAAE,MAAM,CAAC,MAAM,IAAI,wBAAwB;SACjD,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,IACE,MAAM,CAAC,MAAM,KAAK,UAAU,CAAC,OAAO;QACpC,MAAM,CAAC,MAAM,KAAK,UAAU,CAAC,MAAM;QACnC,MAAM,CAAC,MAAM,KAAK,UAAU,CAAC,QAAQ,EACrC,CAAC;QACD,IAAI,CAAC,kBAAkB,EAAE;YACvB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,SAAS;YACT,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,sBAAsB;SAChD,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,IAAI,CAAC,sBAAsB,EAAE;QAC3B,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,SAAS;QACT,MAAM;KACP,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -11,17 +11,18 @@ build_delivery_sink(
|
|
|
11
11
|
clock: Callable[[], float] = time.time,
|
|
12
12
|
) -> sink
|
|
13
13
|
|
|
14
|
-
The returned sink is a callable: sink(candidates)
|
|
14
|
+
The returned sink is a callable: sink(candidates, *, tick=None)
|
|
15
15
|
On each call it:
|
|
16
16
|
1. Replays journal on first call (if file-backed), re-queuing valid undelivered entries
|
|
17
17
|
2. Flushes still-valid undelivered entries from prior ticks (retry)
|
|
18
18
|
3. Wraps this tick's candidates into wire signals (skips invalid ones)
|
|
19
19
|
4. Drops locally superseded / expired entries
|
|
20
|
-
5. POSTs {scanner_id, signals:[...]} to <intake_url>/signals
|
|
20
|
+
5. POSTs {scanner_id, signals:[...]} to <intake_url>/signals, plus the caller's
|
|
21
|
+
per-tick `tick` block when one was supplied
|
|
21
22
|
6. Interprets the response: accepted/expired/superseded/rejected = delivered;
|
|
22
23
|
transport failure or non-success envelope leaves entry queued for retry
|
|
23
24
|
|
|
24
|
-
sink.post_error(error: dict) -> None
|
|
25
|
+
sink.post_error(error: dict, *, tick=None) -> None
|
|
25
26
|
POSTs {scanner_id, error} to <intake_url>/errors. Fire-and-forget.
|
|
26
27
|
|
|
27
28
|
Module constants:
|
|
@@ -93,7 +94,11 @@ def build_delivery_sink(
|
|
|
93
94
|
return to_send
|
|
94
95
|
|
|
95
96
|
def _on_reject(reason: dict) -> None:
|
|
96
|
-
"""Loud rejection: log AND POST to /errors
|
|
97
|
+
"""Loud rejection: log AND POST to /errors — never a silent drop.
|
|
98
|
+
|
|
99
|
+
Deliberately carries NO tick block: this is a per-candidate reject inside an otherwise-clean
|
|
100
|
+
tick that also POSTs /signals, so a block here would report the same scan twice.
|
|
101
|
+
"""
|
|
97
102
|
log_event("delivery_candidate_invalid", **reason)
|
|
98
103
|
_post_error({"type": "candidate_rejected", **reason})
|
|
99
104
|
|
|
@@ -139,9 +144,12 @@ def build_delivery_sink(
|
|
|
139
144
|
result.append((sig, entry_id))
|
|
140
145
|
return result
|
|
141
146
|
|
|
142
|
-
def _post_signals(signals: list[dict]) -> tuple[int, Any]:
|
|
143
|
-
"""POST the signals list to the intake."""
|
|
144
|
-
body = {"scanner_id": scanner_id, "signals": signals}
|
|
147
|
+
def _post_signals(signals: list[dict], tick: dict | None) -> tuple[int, Any]:
|
|
148
|
+
"""POST the signals list to the intake, with the tick block when the caller has one."""
|
|
149
|
+
body: dict = {"scanner_id": scanner_id, "signals": signals}
|
|
150
|
+
# Only send the key when there is a block: the wire schema rejects a null.
|
|
151
|
+
if tick is not None:
|
|
152
|
+
body["tick"] = tick
|
|
145
153
|
# Log the exact wire shape so a 400 can be matched to the field that broke.
|
|
146
154
|
if signals:
|
|
147
155
|
log_event(
|
|
@@ -220,7 +228,7 @@ def build_delivery_sink(
|
|
|
220
228
|
# The sink callable
|
|
221
229
|
# ------------------------------------------------------------------
|
|
222
230
|
|
|
223
|
-
def _sink(candidates) -> None:
|
|
231
|
+
def _sink(candidates, *, tick: dict | None = None) -> None:
|
|
224
232
|
# Replay journal on very first invocation
|
|
225
233
|
if not replayed[0]:
|
|
226
234
|
replayed[0] = True
|
|
@@ -255,7 +263,7 @@ def build_delivery_sink(
|
|
|
255
263
|
|
|
256
264
|
# 3. POST (always, even when signals==[])
|
|
257
265
|
try:
|
|
258
|
-
status, parsed = _post_signals(all_signals)
|
|
266
|
+
status, parsed = _post_signals(all_signals, tick)
|
|
259
267
|
except TransportError as exc:
|
|
260
268
|
log_event("delivery_transport_error", error=str(exc))
|
|
261
269
|
# All signals remain undelivered -> retry on next tick
|
|
@@ -267,9 +275,12 @@ def build_delivery_sink(
|
|
|
267
275
|
# produced entries (all_eids). Empty no-ops: no eids.
|
|
268
276
|
_interpret_response(status, parsed, all_eids, [])
|
|
269
277
|
|
|
270
|
-
def _post_error(error: dict) -> None:
|
|
271
|
-
"""POST an error dict. Fire-and-forget."""
|
|
272
|
-
body = {"scanner_id": scanner_id, "error": error}
|
|
278
|
+
def _post_error(error: dict, *, tick: dict | None = None) -> None:
|
|
279
|
+
"""POST an error dict, with the tick block when the caller has one. Fire-and-forget."""
|
|
280
|
+
body: dict = {"scanner_id": scanner_id, "error": error}
|
|
281
|
+
# Only send the key when there is a block: the wire schema rejects a null.
|
|
282
|
+
if tick is not None:
|
|
283
|
+
body["tick"] = tick
|
|
273
284
|
url = intake_url.rstrip("/") + ERRORS_PATH
|
|
274
285
|
try:
|
|
275
286
|
post_json(url, body, timeout)
|
|
@@ -42,8 +42,16 @@ class EgressBlocked(RuntimeError):
|
|
|
42
42
|
# installation. Nothing is configured to receive a post during a validation run, so in practice
|
|
43
43
|
# there is nowhere for one to go — but "nothing is configured" is a property of how the caller was
|
|
44
44
|
# set up, provable only by tracing several layers, and one refactor away from silently ceasing to
|
|
45
|
-
# be true.
|
|
46
|
-
#
|
|
45
|
+
# be true.
|
|
46
|
+
#
|
|
47
|
+
# What this is NOT: a security boundary. Author code runs in this process and can set the flag back,
|
|
48
|
+
# reach past the client wrapper, or build its own client from the environment — all reproducible in
|
|
49
|
+
# a single scan(). It is deliberately not hardened against that, because hardening here would buy a
|
|
50
|
+
# false sense of one: the invariants that actually hold live at the MCP and engine layers, where
|
|
51
|
+
# they hold no matter what a scanner does.
|
|
52
|
+
#
|
|
53
|
+
# What it IS: the ordinary path, closed by default, failing loudly instead of silently delivering
|
|
54
|
+
# during a check. That is worth having on its own terms.
|
|
47
55
|
PREFLIGHT = False
|
|
48
56
|
|
|
49
57
|
|
|
@@ -32,7 +32,12 @@ from .entrypoint_loader import (
|
|
|
32
32
|
|
|
33
33
|
# Modules a scanner is expected to reach for. Anything here means data is arriving by a route the
|
|
34
34
|
# runtime cannot see, which the scan contract does not sanction.
|
|
35
|
-
|
|
35
|
+
# Routes that fetch data where the runtime cannot see it. `subprocess` belongs here for the same
|
|
36
|
+
# reason as `socket`: shelling out to curl is a data source, and one that also escapes the
|
|
37
|
+
# in-process guards entirely.
|
|
38
|
+
_UNSANCTIONED_SOURCES = {
|
|
39
|
+
"urllib", "urllib.request", "requests", "http", "http.client", "httpx", "socket", "subprocess",
|
|
40
|
+
}
|
|
36
41
|
|
|
37
42
|
|
|
38
43
|
def _stdlib_names() -> set:
|
|
@@ -3,8 +3,12 @@
|
|
|
3
3
|
python3 -m scaffold.preflight <launch-config.json>
|
|
4
4
|
|
|
5
5
|
Runs the author's `scan()` exactly once against live data, through the same loop production uses,
|
|
6
|
-
and reports what happened as one JSON document
|
|
7
|
-
|
|
6
|
+
and reports what happened as one JSON document, written to the `result_path` the caller names.
|
|
7
|
+
|
|
8
|
+
Signals are collected and returned rather than delivered — the runtime's own delivery funnel is
|
|
9
|
+
closed for the duration and raises if used. That covers the sanctioned path, which is the one
|
|
10
|
+
authored code is supposed to take; a scanner reaching for a socket directly is caught statically at
|
|
11
|
+
the import depth, not stopped here. So: nothing leaves by the route the scaffold owns.
|
|
8
12
|
|
|
9
13
|
## What this adds beyond running the loop
|
|
10
14
|
|
|
@@ -203,7 +203,12 @@ def run_scaffold(
|
|
|
203
203
|
break
|
|
204
204
|
|
|
205
205
|
tick_count += 1
|
|
206
|
-
|
|
206
|
+
# Monotonic, not time.time(): it is the marker for both the reported duration_ms and
|
|
207
|
+
# the inter-tick sleep, and neither may see a clock step. The wire schema refuses a
|
|
208
|
+
# negative duration_ms and rejects the whole body with it, so a backwards step would
|
|
209
|
+
# cost that tick's real signals; the same step would inflate the sleep by its own
|
|
210
|
+
# size and park the scanner for that long.
|
|
211
|
+
tick_started_monotonic = time.monotonic()
|
|
207
212
|
tick_status = "ok"
|
|
208
213
|
tick_error = None
|
|
209
214
|
candidates: list = []
|
|
@@ -218,13 +223,17 @@ def run_scaffold(
|
|
|
218
223
|
# malformed (a tuple — the old v1 shape — included).
|
|
219
224
|
if not isinstance(result, list):
|
|
220
225
|
tick_status = "malformed"
|
|
226
|
+
malformed_reason = (
|
|
227
|
+
f"scan() returned {type(result).__name__!r}; expected a "
|
|
228
|
+
f"plain list[dict] (the v1 (candidates, state) tuple is gone)"
|
|
229
|
+
)
|
|
230
|
+
# Carried on the error record, not only in this log line: the sink is what
|
|
231
|
+
# a caller reads, and "malformed" without the reason is not actionable.
|
|
232
|
+
tick_error = {"type": "malformed", "message": malformed_reason}
|
|
221
233
|
log_event(
|
|
222
234
|
"scaffold_tick_malformed",
|
|
223
235
|
tick=tick_count,
|
|
224
|
-
reason=
|
|
225
|
-
f"scan() returned {type(result).__name__!r}; expected a "
|
|
226
|
-
f"plain list[dict] (the v1 (candidates, state) tuple is gone)"
|
|
227
|
-
),
|
|
236
|
+
reason=malformed_reason,
|
|
228
237
|
)
|
|
229
238
|
else:
|
|
230
239
|
candidates = result
|
|
@@ -256,7 +265,17 @@ def run_scaffold(
|
|
|
256
265
|
if armed:
|
|
257
266
|
_disarm_tick_alarm()
|
|
258
267
|
|
|
259
|
-
duration_ms = int((time.
|
|
268
|
+
duration_ms = int((time.monotonic() - tick_started_monotonic) * 1000)
|
|
269
|
+
|
|
270
|
+
# Facts about the SCAN itself, threaded to whichever exit this tick takes so the
|
|
271
|
+
# runtime records that a scan happened even when it produced nothing or failed.
|
|
272
|
+
# candidate_count is what scan() returned — the delivered signal list is not the same
|
|
273
|
+
# number, since the sink prepends still-pending retries from earlier ticks.
|
|
274
|
+
tick_meta = {
|
|
275
|
+
"seq": tick_count,
|
|
276
|
+
"duration_ms": duration_ms,
|
|
277
|
+
"candidate_count": len(candidates),
|
|
278
|
+
}
|
|
260
279
|
|
|
261
280
|
# --- Clean tick: commit ctx.state, deliver candidates ---
|
|
262
281
|
if tick_status == "ok":
|
|
@@ -289,11 +308,12 @@ def run_scaffold(
|
|
|
289
308
|
),
|
|
290
309
|
},
|
|
291
310
|
tick_count,
|
|
311
|
+
tick_meta,
|
|
292
312
|
)
|
|
293
313
|
|
|
294
314
|
if committed and sink is not None:
|
|
295
315
|
try:
|
|
296
|
-
sink
|
|
316
|
+
_call_sink(sink, candidates, tick_meta)
|
|
297
317
|
except Exception as sink_exc: # noqa: BLE001
|
|
298
318
|
log_event(
|
|
299
319
|
"scaffold_sink_error",
|
|
@@ -308,7 +328,7 @@ def run_scaffold(
|
|
|
308
328
|
ctx.state.rollback()
|
|
309
329
|
if sink is not None and hasattr(sink, "post_error"):
|
|
310
330
|
_post_error_safe(
|
|
311
|
-
sink, tick_error or {"type": tick_status}, tick_count
|
|
331
|
+
sink, tick_error or {"type": tick_status}, tick_count, tick_meta
|
|
312
332
|
)
|
|
313
333
|
|
|
314
334
|
log_event(
|
|
@@ -346,7 +366,7 @@ def run_scaffold(
|
|
|
346
366
|
break
|
|
347
367
|
|
|
348
368
|
# --- Inter-tick sleep ---
|
|
349
|
-
elapsed = time.
|
|
369
|
+
elapsed = time.monotonic() - tick_started_monotonic
|
|
350
370
|
sleep_for = max(0.0, interval - elapsed)
|
|
351
371
|
if sleep_for > 0 and not stop_event.is_set():
|
|
352
372
|
_interruptible_sleep(sleep_for, stop_event)
|
|
@@ -357,10 +377,42 @@ def run_scaffold(
|
|
|
357
377
|
return tick_count
|
|
358
378
|
|
|
359
379
|
|
|
360
|
-
def
|
|
380
|
+
def _accepts_tick(fn: Any, args: tuple, tick: dict) -> bool:
|
|
381
|
+
"""True when `fn(*args, tick=tick)` is a call `fn` can actually take.
|
|
382
|
+
|
|
383
|
+
A sink is caller-supplied (tests, embedders), so one predating the tick block takes candidates
|
|
384
|
+
only. Bind the whole intended call rather than looking for a parameter NAMED `tick`: a sink whose
|
|
385
|
+
candidates parameter happens to be called `tick` matches by name, then dies on "multiple values"
|
|
386
|
+
— and the caller's guard would swallow that into a silent, permanent delivery drop. Feature-detect
|
|
387
|
+
rather than call-and-retry-on-TypeError: a retry would deliver the tick twice whenever the sink
|
|
388
|
+
raises TypeError from inside its own body.
|
|
389
|
+
"""
|
|
390
|
+
try:
|
|
391
|
+
sig = inspect.signature(fn)
|
|
392
|
+
except (TypeError, ValueError):
|
|
393
|
+
return False
|
|
394
|
+
try:
|
|
395
|
+
sig.bind(*args, tick=tick)
|
|
396
|
+
except TypeError:
|
|
397
|
+
return False
|
|
398
|
+
return True
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
def _call_sink(sink: Any, candidates: list, tick: dict) -> None:
|
|
402
|
+
"""Deliver a clean tick's candidates, passing the tick block when the sink accepts one."""
|
|
403
|
+
if _accepts_tick(sink, (candidates,), tick):
|
|
404
|
+
sink(candidates, tick=tick)
|
|
405
|
+
else:
|
|
406
|
+
sink(candidates)
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
def _post_error_safe(sink: Any, error: dict, tick_count: int, tick: dict) -> None:
|
|
361
410
|
"""Call sink.post_error(error), swallowing/logging any failure."""
|
|
362
411
|
try:
|
|
363
|
-
sink.post_error(error)
|
|
412
|
+
if _accepts_tick(sink.post_error, (error,), tick):
|
|
413
|
+
sink.post_error(error, tick=tick)
|
|
414
|
+
else:
|
|
415
|
+
sink.post_error(error)
|
|
364
416
|
except Exception as perr: # noqa: BLE001
|
|
365
417
|
log_event(
|
|
366
418
|
"scaffold_post_error_failed",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime-module.d.ts","sourceRoot":"","sources":["../../src/scanners/runtime-module.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"runtime-module.d.ts","sourceRoot":"","sources":["../../src/scanners/runtime-module.ts"],"names":[],"mappings":"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"}
|
|
@@ -51,12 +51,20 @@ class DefaultScannerRuntimeModule {
|
|
|
51
51
|
this.events.emit("scanner:run:start", event);
|
|
52
52
|
},
|
|
53
53
|
onRunResult: (result) => {
|
|
54
|
-
// Stamp the matching run start
|
|
54
|
+
// Stamp the matching run start and how the scanner is driven onto the terminal event
|
|
55
|
+
// (telemetry duration + producer attribution); data only.
|
|
55
56
|
const startKey = telemetryKey(result.address, result.scannerId);
|
|
56
57
|
const startedAt = runStarts.get(startKey);
|
|
57
58
|
runStarts.delete(startKey);
|
|
59
|
+
const scheduleMode = this.engine
|
|
60
|
+
.describeRegistrations(result.address)
|
|
61
|
+
.find((registration) => registration.scannerId === result.scannerId)?.scheduleMode;
|
|
58
62
|
emitTerminalScannerRunEvent((eventName, event) => {
|
|
59
|
-
this.events.emit(eventName,
|
|
63
|
+
this.events.emit(eventName, {
|
|
64
|
+
...event,
|
|
65
|
+
...(startedAt === undefined ? {} : { startedAt }),
|
|
66
|
+
...(scheduleMode === undefined ? {} : { scheduleMode }),
|
|
67
|
+
});
|
|
60
68
|
}, result);
|
|
61
69
|
},
|
|
62
70
|
},
|