@affiant/core 0.1.0-alpha.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/LICENSE +202 -0
- package/README.md +354 -0
- package/dist/context.d.ts +136 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +30 -0
- package/dist/context.js.map +1 -0
- package/dist/docket/entry.d.ts +421 -0
- package/dist/docket/entry.d.ts.map +1 -0
- package/dist/docket/entry.js +155 -0
- package/dist/docket/entry.js.map +1 -0
- package/dist/docket/expiry.d.ts +82 -0
- package/dist/docket/expiry.d.ts.map +1 -0
- package/dist/docket/expiry.js +106 -0
- package/dist/docket/expiry.js.map +1 -0
- package/dist/docket/memory.d.ts +163 -0
- package/dist/docket/memory.d.ts.map +1 -0
- package/dist/docket/memory.js +528 -0
- package/dist/docket/memory.js.map +1 -0
- package/dist/docket/store.d.ts +387 -0
- package/dist/docket/store.d.ts.map +1 -0
- package/dist/docket/store.js +51 -0
- package/dist/docket/store.js.map +1 -0
- package/dist/errors.d.ts +153 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +164 -0
- package/dist/errors.js.map +1 -0
- package/dist/gate/coverage.d.ts +152 -0
- package/dist/gate/coverage.d.ts.map +1 -0
- package/dist/gate/coverage.js +114 -0
- package/dist/gate/coverage.js.map +1 -0
- package/dist/gate/decide.d.ts +207 -0
- package/dist/gate/decide.d.ts.map +1 -0
- package/dist/gate/decide.js +559 -0
- package/dist/gate/decide.js.map +1 -0
- package/dist/gate/gate.d.ts +212 -0
- package/dist/gate/gate.d.ts.map +1 -0
- package/dist/gate/gate.js +175 -0
- package/dist/gate/gate.js.map +1 -0
- package/dist/gate/pipeline.d.ts +285 -0
- package/dist/gate/pipeline.d.ts.map +1 -0
- package/dist/gate/pipeline.js +515 -0
- package/dist/gate/pipeline.js.map +1 -0
- package/dist/gate/policy.d.ts +272 -0
- package/dist/gate/policy.d.ts.map +1 -0
- package/dist/gate/policy.js +396 -0
- package/dist/gate/policy.js.map +1 -0
- package/dist/gate/wrap.d.ts +107 -0
- package/dist/gate/wrap.d.ts.map +1 -0
- package/dist/gate/wrap.js +164 -0
- package/dist/gate/wrap.js.map +1 -0
- package/dist/index.d.ts +95 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +111 -0
- package/dist/index.js.map +1 -0
- package/dist/model/affidavit.d.ts +354 -0
- package/dist/model/affidavit.d.ts.map +1 -0
- package/dist/model/affidavit.js +417 -0
- package/dist/model/affidavit.js.map +1 -0
- package/dist/model/amendments.d.ts +160 -0
- package/dist/model/amendments.d.ts.map +1 -0
- package/dist/model/amendments.js +183 -0
- package/dist/model/amendments.js.map +1 -0
- package/dist/model/canonical.d.ts +311 -0
- package/dist/model/canonical.d.ts.map +1 -0
- package/dist/model/canonical.js +665 -0
- package/dist/model/canonical.js.map +1 -0
- package/dist/model/money.d.ts +127 -0
- package/dist/model/money.d.ts.map +1 -0
- package/dist/model/money.js +177 -0
- package/dist/model/money.js.map +1 -0
- package/dist/model/provenance.d.ts +315 -0
- package/dist/model/provenance.d.ts.map +1 -0
- package/dist/model/provenance.js +223 -0
- package/dist/model/provenance.js.map +1 -0
- package/dist/ports.d.ts +269 -0
- package/dist/ports.d.ts.map +1 -0
- package/dist/ports.js +34 -0
- package/dist/ports.js.map +1 -0
- package/dist/store-memory.d.ts +21 -0
- package/dist/store-memory.d.ts.map +1 -0
- package/dist/store-memory.js +20 -0
- package/dist/store-memory.js.map +1 -0
- package/dist/telemetry-keys.d.ts +65 -0
- package/dist/telemetry-keys.d.ts.map +1 -0
- package/dist/telemetry-keys.js +72 -0
- package/dist/telemetry-keys.js.map +1 -0
- package/dist/telemetry.d.ts +77 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +43 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/testing.d.ts +574 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +1291 -0
- package/dist/testing.js.map +1 -0
- package/package.json +75 -0
- package/telemetry-keys.json +92 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/** One entry in the telemetry-key registry (TL-1). */
|
|
2
|
+
export interface TelemetryKeyEntry {
|
|
3
|
+
/** The event name. Never renamed, never removed — only deprecated. */
|
|
4
|
+
readonly key: string;
|
|
5
|
+
/** The package version this key first shipped in. */
|
|
6
|
+
readonly since: string;
|
|
7
|
+
/** What the event means, in one line. */
|
|
8
|
+
readonly description: string;
|
|
9
|
+
/**
|
|
10
|
+
* The attribute names the gate carries on this event. Filled per key by the
|
|
11
|
+
* pull request that starts emitting it; OpenTelemetry's `gen_ai.*` vocabulary
|
|
12
|
+
* is used where a name exists there (TL-2).
|
|
13
|
+
*/
|
|
14
|
+
readonly attributes: readonly string[];
|
|
15
|
+
}
|
|
16
|
+
/** The version of the registry itself. */
|
|
17
|
+
export declare const TELEMETRY_REGISTRY_VERSION = "0.1.0-alpha.0";
|
|
18
|
+
/** Every telemetry key, in registry order. */
|
|
19
|
+
export declare const TELEMETRY_KEYS: readonly [{
|
|
20
|
+
readonly key: "affidavit.filed";
|
|
21
|
+
readonly since: "0.1.0-alpha.0";
|
|
22
|
+
readonly description: "An Affidavit was filed as a Docket entry.";
|
|
23
|
+
readonly attributes: readonly ["gen_ai.tool.name", "gen_ai.conversation.id", "entry.id", "docket.requirement", "docket.status", "affidavit.field_count", "created"];
|
|
24
|
+
}, {
|
|
25
|
+
readonly key: "affidavit.refused.substance";
|
|
26
|
+
readonly since: "0.1.0-alpha.0";
|
|
27
|
+
readonly description: "A proposal was refused before filing because it swore to nothing (GT-3).";
|
|
28
|
+
readonly attributes: readonly ["gen_ai.tool.name", "gen_ai.conversation.id", "affidavit.field_count", "reason"];
|
|
29
|
+
}, {
|
|
30
|
+
readonly key: "coverage.refused";
|
|
31
|
+
readonly since: "0.1.0-alpha.0";
|
|
32
|
+
readonly description: "A tool the gate must cover could not be intercepted, or a tool the host declared uncovered produced a proposal (CV-4).";
|
|
33
|
+
readonly attributes: readonly ["gen_ai.tool.name", "coverage.category", "phase"];
|
|
34
|
+
}, {
|
|
35
|
+
readonly key: "docket.transition";
|
|
36
|
+
readonly since: "0.1.0-alpha.0";
|
|
37
|
+
readonly description: "A Docket entry changed state (DK-1).";
|
|
38
|
+
readonly attributes: readonly ["entry.id", "gen_ai.conversation.id", "from", "to", "execution", "decision.kind", "attestation.kind", "amended"];
|
|
39
|
+
}, {
|
|
40
|
+
readonly key: "docket.expired";
|
|
41
|
+
readonly since: "0.1.0-alpha.0";
|
|
42
|
+
readonly description: "A pending Docket entry passed its expiry (DK-3).";
|
|
43
|
+
readonly attributes: readonly ["entry.id"];
|
|
44
|
+
}, {
|
|
45
|
+
readonly key: "decision.unauthorized";
|
|
46
|
+
readonly since: "0.1.0-alpha.0";
|
|
47
|
+
readonly description: "A decision was refused on identity grounds: no resolved principal, another tenant, or the host's authorization port said no (AZ-2).";
|
|
48
|
+
readonly attributes: readonly ["entry.id", "gen_ai.conversation.id", "reason", "principal.kind", "path"];
|
|
49
|
+
}, {
|
|
50
|
+
readonly key: "standing-order.fired";
|
|
51
|
+
readonly since: "0.1.0-alpha.0";
|
|
52
|
+
readonly description: "A Standing Order policy approved a write with no person present (AZ-1).";
|
|
53
|
+
readonly attributes: readonly ["policy.id", "policy.version", "entry.id", "risk.score"];
|
|
54
|
+
}, {
|
|
55
|
+
readonly key: "standing-order.blocked";
|
|
56
|
+
readonly since: "0.1.0-alpha.0";
|
|
57
|
+
readonly description: "A Standing Order verdict was not honoured: a proposed field the entity requires had no known value (GT-5), an unbound provenance input (PV-4), or a risk score above the policy's threshold (GT-5). `blocked.reason` is the stable code to alert on - `mandatory-field-empty`, `unbound-declared-input` or `risk-above-threshold`; `reason` is the sentence the reviewer sees on the card and is free to be rephrased.";
|
|
58
|
+
readonly attributes: readonly ["policy.id", "policy.version", "blocked.reason", "reason", "provenance.field", "provenance.source", "affidavit.empty_mandatory_fields", "risk.score", "risk.threshold"];
|
|
59
|
+
}, {
|
|
60
|
+
readonly key: "policy.invalid";
|
|
61
|
+
readonly since: "0.1.0-alpha.0";
|
|
62
|
+
readonly description: "A host's approval policy broke its own contract: an unusable deadline, or an evaluate that threw (GT-4, CV-1).";
|
|
63
|
+
readonly attributes: readonly ["policy.id", "policy.version", "option", "reason"];
|
|
64
|
+
}];
|
|
65
|
+
//# sourceMappingURL=telemetry-keys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry-keys.d.ts","sourceRoot":"","sources":["../src/telemetry-keys.ts"],"names":[],"mappings":"AAIA,sDAAsD;AACtD,MAAM,WAAW,iBAAiB;IAChC,sEAAsE;IACtE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,qDAAqD;IACrD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,yCAAyC;IACzC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC;AAED,0CAA0C;AAC1C,eAAO,MAAM,0BAA0B,kBAAkB,CAAC;AAE1D,8CAA8C;AAC9C,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgEsB,CAAC"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// GENERATED FILE — DO NOT EDIT BY HAND.
|
|
2
|
+
// Produced by scripts/generate-telemetry-keys.mjs from telemetry-keys.json.
|
|
3
|
+
// To change it: edit telemetry-keys.json, then run `pnpm -C packages/core generate`.
|
|
4
|
+
/** The version of the registry itself. */
|
|
5
|
+
export const TELEMETRY_REGISTRY_VERSION = "0.1.0-alpha.0";
|
|
6
|
+
/** Every telemetry key, in registry order. */
|
|
7
|
+
export const TELEMETRY_KEYS = [
|
|
8
|
+
/** An Affidavit was filed as a Docket entry. Since 0.1.0-alpha.0. */
|
|
9
|
+
{
|
|
10
|
+
key: "affidavit.filed",
|
|
11
|
+
since: "0.1.0-alpha.0",
|
|
12
|
+
description: "An Affidavit was filed as a Docket entry.",
|
|
13
|
+
attributes: ["gen_ai.tool.name", "gen_ai.conversation.id", "entry.id", "docket.requirement", "docket.status", "affidavit.field_count", "created"],
|
|
14
|
+
},
|
|
15
|
+
/** A proposal was refused before filing because it swore to nothing (GT-3). Since 0.1.0-alpha.0. */
|
|
16
|
+
{
|
|
17
|
+
key: "affidavit.refused.substance",
|
|
18
|
+
since: "0.1.0-alpha.0",
|
|
19
|
+
description: "A proposal was refused before filing because it swore to nothing (GT-3).",
|
|
20
|
+
attributes: ["gen_ai.tool.name", "gen_ai.conversation.id", "affidavit.field_count", "reason"],
|
|
21
|
+
},
|
|
22
|
+
/** A tool the gate must cover could not be intercepted, or a tool the host declared uncovered produced a proposal (CV-4). Since 0.1.0-alpha.0. */
|
|
23
|
+
{
|
|
24
|
+
key: "coverage.refused",
|
|
25
|
+
since: "0.1.0-alpha.0",
|
|
26
|
+
description: "A tool the gate must cover could not be intercepted, or a tool the host declared uncovered produced a proposal (CV-4).",
|
|
27
|
+
attributes: ["gen_ai.tool.name", "coverage.category", "phase"],
|
|
28
|
+
},
|
|
29
|
+
/** A Docket entry changed state (DK-1). Since 0.1.0-alpha.0. */
|
|
30
|
+
{
|
|
31
|
+
key: "docket.transition",
|
|
32
|
+
since: "0.1.0-alpha.0",
|
|
33
|
+
description: "A Docket entry changed state (DK-1).",
|
|
34
|
+
attributes: ["entry.id", "gen_ai.conversation.id", "from", "to", "execution", "decision.kind", "attestation.kind", "amended"],
|
|
35
|
+
},
|
|
36
|
+
/** A pending Docket entry passed its expiry (DK-3). Since 0.1.0-alpha.0. */
|
|
37
|
+
{
|
|
38
|
+
key: "docket.expired",
|
|
39
|
+
since: "0.1.0-alpha.0",
|
|
40
|
+
description: "A pending Docket entry passed its expiry (DK-3).",
|
|
41
|
+
attributes: ["entry.id"],
|
|
42
|
+
},
|
|
43
|
+
/** A decision was refused on identity grounds: no resolved principal, another tenant, or the host's authorization port said no (AZ-2). Since 0.1.0-alpha.0. */
|
|
44
|
+
{
|
|
45
|
+
key: "decision.unauthorized",
|
|
46
|
+
since: "0.1.0-alpha.0",
|
|
47
|
+
description: "A decision was refused on identity grounds: no resolved principal, another tenant, or the host's authorization port said no (AZ-2).",
|
|
48
|
+
attributes: ["entry.id", "gen_ai.conversation.id", "reason", "principal.kind", "path"],
|
|
49
|
+
},
|
|
50
|
+
/** A Standing Order policy approved a write with no person present (AZ-1). Since 0.1.0-alpha.0. */
|
|
51
|
+
{
|
|
52
|
+
key: "standing-order.fired",
|
|
53
|
+
since: "0.1.0-alpha.0",
|
|
54
|
+
description: "A Standing Order policy approved a write with no person present (AZ-1).",
|
|
55
|
+
attributes: ["policy.id", "policy.version", "entry.id", "risk.score"],
|
|
56
|
+
},
|
|
57
|
+
/** A Standing Order verdict was not honoured: a proposed field the entity requires had no known value (GT-5), an unbound provenance input (PV-4), or a risk score above the policy's threshold (GT-5). `blocked.reason` is the stable code to alert on - `mandatory-field-empty`, `unbound-declared-input` or `risk-above-threshold`; `reason` is the sentence the reviewer sees on the card and is free to be rephrased. Since 0.1.0-alpha.0. */
|
|
58
|
+
{
|
|
59
|
+
key: "standing-order.blocked",
|
|
60
|
+
since: "0.1.0-alpha.0",
|
|
61
|
+
description: "A Standing Order verdict was not honoured: a proposed field the entity requires had no known value (GT-5), an unbound provenance input (PV-4), or a risk score above the policy's threshold (GT-5). `blocked.reason` is the stable code to alert on - `mandatory-field-empty`, `unbound-declared-input` or `risk-above-threshold`; `reason` is the sentence the reviewer sees on the card and is free to be rephrased.",
|
|
62
|
+
attributes: ["policy.id", "policy.version", "blocked.reason", "reason", "provenance.field", "provenance.source", "affidavit.empty_mandatory_fields", "risk.score", "risk.threshold"],
|
|
63
|
+
},
|
|
64
|
+
/** A host's approval policy broke its own contract: an unusable deadline, or an evaluate that threw (GT-4, CV-1). Since 0.1.0-alpha.0. */
|
|
65
|
+
{
|
|
66
|
+
key: "policy.invalid",
|
|
67
|
+
since: "0.1.0-alpha.0",
|
|
68
|
+
description: "A host's approval policy broke its own contract: an unusable deadline, or an evaluate that threw (GT-4, CV-1).",
|
|
69
|
+
attributes: ["policy.id", "policy.version", "option", "reason"],
|
|
70
|
+
},
|
|
71
|
+
];
|
|
72
|
+
//# sourceMappingURL=telemetry-keys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry-keys.js","sourceRoot":"","sources":["../src/telemetry-keys.ts"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,4EAA4E;AAC5E,qFAAqF;AAkBrF,0CAA0C;AAC1C,MAAM,CAAC,MAAM,0BAA0B,GAAG,eAAe,CAAC;AAE1D,8CAA8C;AAC9C,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,qEAAqE;IACrE;QACE,GAAG,EAAE,iBAAiB;QACtB,KAAK,EAAE,eAAe;QACtB,WAAW,EAAE,2CAA2C;QACxD,UAAU,EAAE,CAAC,kBAAkB,EAAE,wBAAwB,EAAE,UAAU,EAAE,oBAAoB,EAAE,eAAe,EAAE,uBAAuB,EAAE,SAAS,CAAC;KAClJ;IACD,oGAAoG;IACpG;QACE,GAAG,EAAE,6BAA6B;QAClC,KAAK,EAAE,eAAe;QACtB,WAAW,EAAE,0EAA0E;QACvF,UAAU,EAAE,CAAC,kBAAkB,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,QAAQ,CAAC;KAC9F;IACD,kJAAkJ;IAClJ;QACE,GAAG,EAAE,kBAAkB;QACvB,KAAK,EAAE,eAAe;QACtB,WAAW,EAAE,wHAAwH;QACrI,UAAU,EAAE,CAAC,kBAAkB,EAAE,mBAAmB,EAAE,OAAO,CAAC;KAC/D;IACD,gEAAgE;IAChE;QACE,GAAG,EAAE,mBAAmB;QACxB,KAAK,EAAE,eAAe;QACtB,WAAW,EAAE,sCAAsC;QACnD,UAAU,EAAE,CAAC,UAAU,EAAE,wBAAwB,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,eAAe,EAAE,kBAAkB,EAAE,SAAS,CAAC;KAC9H;IACD,4EAA4E;IAC5E;QACE,GAAG,EAAE,gBAAgB;QACrB,KAAK,EAAE,eAAe;QACtB,WAAW,EAAE,kDAAkD;QAC/D,UAAU,EAAE,CAAC,UAAU,CAAC;KACzB;IACD,+JAA+J;IAC/J;QACE,GAAG,EAAE,uBAAuB;QAC5B,KAAK,EAAE,eAAe;QACtB,WAAW,EAAE,qIAAqI;QAClJ,UAAU,EAAE,CAAC,UAAU,EAAE,wBAAwB,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,CAAC;KACvF;IACD,mGAAmG;IACnG;QACE,GAAG,EAAE,sBAAsB;QAC3B,KAAK,EAAE,eAAe;QACtB,WAAW,EAAE,yEAAyE;QACtF,UAAU,EAAE,CAAC,WAAW,EAAE,gBAAgB,EAAE,UAAU,EAAE,YAAY,CAAC;KACtE;IACD,kbAAkb;IAClb;QACE,GAAG,EAAE,wBAAwB;QAC7B,KAAK,EAAE,eAAe;QACtB,WAAW,EAAE,wZAAwZ;QACra,UAAU,EAAE,CAAC,WAAW,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,QAAQ,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,kCAAkC,EAAE,YAAY,EAAE,gBAAgB,CAAC;KACrL;IACD,0IAA0I;IAC1I;QACE,GAAG,EAAE,gBAAgB;QACrB,KAAK,EAAE,eAAe;QACtB,WAAW,EAAE,gHAAgH;QAC7H,UAAU,EAAE,CAAC,WAAW,EAAE,gBAAgB,EAAE,QAAQ,EAAE,QAAQ,CAAC;KAChE;CAC8C,CAAC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The telemetry port, the event shape, and the versioned key registry.
|
|
3
|
+
*
|
|
4
|
+
* **Rules served: TL-1** (the telemetry-key registry is a versioned API),
|
|
5
|
+
* **TL-2** (where a public standard names the same thing, the registry uses its
|
|
6
|
+
* name).
|
|
7
|
+
*
|
|
8
|
+
* TL-1 in one sentence: *every event and attribute the gate emits is named in a
|
|
9
|
+
* versioned registry; a key is never renamed, only deprecated.* The registry lives
|
|
10
|
+
* beside this file as {@link https://github.com/Sakwala/affiant-ts/blob/main/packages/core/telemetry-keys.json `telemetry-keys.json`}
|
|
11
|
+
* and is generated into `./telemetry-keys.ts` by `scripts/generate-telemetry-keys.mjs`,
|
|
12
|
+
* the same way `@affiant/contract` generates its schema module — one record a
|
|
13
|
+
* reader edits, one TypeScript module every runtime can load.
|
|
14
|
+
*
|
|
15
|
+
* The registry is what makes the gate's behaviour *observable* rather than
|
|
16
|
+
* inferable: substance refusal (GT-3), coverage refusal (CV-4) and every Docket
|
|
17
|
+
* transition (DK-1) are events with fixed names, so an operator can alert on a
|
|
18
|
+
* refusal rate without reading the gate's source.
|
|
19
|
+
*
|
|
20
|
+
* The default port is a no-op. The gate emits whether or not a host is listening,
|
|
21
|
+
* which is what keeps the emitting call sites honest.
|
|
22
|
+
*
|
|
23
|
+
* @packageDocumentation
|
|
24
|
+
*/
|
|
25
|
+
import { TELEMETRY_KEYS } from "./telemetry-keys.js";
|
|
26
|
+
export { TELEMETRY_KEYS, TELEMETRY_REGISTRY_VERSION, type TelemetryKeyEntry, } from "./telemetry-keys.js";
|
|
27
|
+
/**
|
|
28
|
+
* The name of one event the gate emits. Derived from the registry, so a key that
|
|
29
|
+
* is not in `telemetry-keys.json` is a compile error at the emitting call site.
|
|
30
|
+
*/
|
|
31
|
+
export type TelemetryKey = (typeof TELEMETRY_KEYS)[number]["key"];
|
|
32
|
+
/** Whether `value` names an event in the registry. */
|
|
33
|
+
export declare function isTelemetryKey(value: unknown): value is TelemetryKey;
|
|
34
|
+
/**
|
|
35
|
+
* The attributes carried on one event.
|
|
36
|
+
*
|
|
37
|
+
* Scalars only, and `null` rather than `undefined` for "no value" — the same rule
|
|
38
|
+
* the wire types follow, so an event survives a JSON round trip into whatever the
|
|
39
|
+
* host's collector is without a shape change. Never put a field value, an utterance
|
|
40
|
+
* or a principal id in here: telemetry is operational, and the audit record is the
|
|
41
|
+
* Affidavit.
|
|
42
|
+
*/
|
|
43
|
+
export type TelemetryAttributes = {
|
|
44
|
+
readonly [name: string]: string | number | boolean | null;
|
|
45
|
+
};
|
|
46
|
+
/** One thing that happened, named by the registry. */
|
|
47
|
+
export interface TelemetryEvent {
|
|
48
|
+
/** Which event this is. */
|
|
49
|
+
readonly key: TelemetryKey;
|
|
50
|
+
/**
|
|
51
|
+
* When it happened, as an ISO 8601 instant in UTC — read from the gate's
|
|
52
|
+
* `Clock` port, never from an ambient timer.
|
|
53
|
+
*/
|
|
54
|
+
readonly at: string;
|
|
55
|
+
/** The attributes for this event. `{}` when there are none. */
|
|
56
|
+
readonly attributes: TelemetryAttributes;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Where the gate's events go. Supplied by the host; the gate never chooses a sink.
|
|
60
|
+
*
|
|
61
|
+
* `emit` is synchronous and must not throw: an event is a side channel, and a
|
|
62
|
+
* collector that is down cannot be allowed to fail a write. Buffer or drop inside
|
|
63
|
+
* the implementation.
|
|
64
|
+
*/
|
|
65
|
+
export interface TelemetryPort {
|
|
66
|
+
/** Record one event. Must not throw. */
|
|
67
|
+
emit(event: TelemetryEvent): void;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The port used when a host supplies none. Drops every event.
|
|
71
|
+
*
|
|
72
|
+
* It exists so the gate's emitting call sites are unconditional — no
|
|
73
|
+
* `telemetry?.emit(...)` at each site, and no branch that could quietly stop
|
|
74
|
+
* emitting.
|
|
75
|
+
*/
|
|
76
|
+
export declare const noopTelemetry: TelemetryPort;
|
|
77
|
+
//# sourceMappingURL=telemetry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,EACL,cAAc,EACd,0BAA0B,EAC1B,KAAK,iBAAiB,GACvB,MAAM,qBAAqB,CAAC;AAE7B;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC;AAElE,sDAAsD;AACtD,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,YAAY,CAIpE;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;CAC3D,CAAC;AAEF,sDAAsD;AACtD,MAAM,WAAW,cAAc;IAC7B,2BAA2B;IAC3B,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,+DAA+D;IAC/D,QAAQ,CAAC,UAAU,EAAE,mBAAmB,CAAC;CAC1C;AAED;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B,wCAAwC;IACxC,IAAI,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;CACnC;AAED;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,EAAE,aAI3B,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The telemetry port, the event shape, and the versioned key registry.
|
|
3
|
+
*
|
|
4
|
+
* **Rules served: TL-1** (the telemetry-key registry is a versioned API),
|
|
5
|
+
* **TL-2** (where a public standard names the same thing, the registry uses its
|
|
6
|
+
* name).
|
|
7
|
+
*
|
|
8
|
+
* TL-1 in one sentence: *every event and attribute the gate emits is named in a
|
|
9
|
+
* versioned registry; a key is never renamed, only deprecated.* The registry lives
|
|
10
|
+
* beside this file as {@link https://github.com/Sakwala/affiant-ts/blob/main/packages/core/telemetry-keys.json `telemetry-keys.json`}
|
|
11
|
+
* and is generated into `./telemetry-keys.ts` by `scripts/generate-telemetry-keys.mjs`,
|
|
12
|
+
* the same way `@affiant/contract` generates its schema module — one record a
|
|
13
|
+
* reader edits, one TypeScript module every runtime can load.
|
|
14
|
+
*
|
|
15
|
+
* The registry is what makes the gate's behaviour *observable* rather than
|
|
16
|
+
* inferable: substance refusal (GT-3), coverage refusal (CV-4) and every Docket
|
|
17
|
+
* transition (DK-1) are events with fixed names, so an operator can alert on a
|
|
18
|
+
* refusal rate without reading the gate's source.
|
|
19
|
+
*
|
|
20
|
+
* The default port is a no-op. The gate emits whether or not a host is listening,
|
|
21
|
+
* which is what keeps the emitting call sites honest.
|
|
22
|
+
*
|
|
23
|
+
* @packageDocumentation
|
|
24
|
+
*/
|
|
25
|
+
import { TELEMETRY_KEYS } from "./telemetry-keys.js";
|
|
26
|
+
export { TELEMETRY_KEYS, TELEMETRY_REGISTRY_VERSION, } from "./telemetry-keys.js";
|
|
27
|
+
/** Whether `value` names an event in the registry. */
|
|
28
|
+
export function isTelemetryKey(value) {
|
|
29
|
+
return (typeof value === "string" && TELEMETRY_KEYS.some((entry) => entry.key === value));
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The port used when a host supplies none. Drops every event.
|
|
33
|
+
*
|
|
34
|
+
* It exists so the gate's emitting call sites are unconditional — no
|
|
35
|
+
* `telemetry?.emit(...)` at each site, and no branch that could quietly stop
|
|
36
|
+
* emitting.
|
|
37
|
+
*/
|
|
38
|
+
export const noopTelemetry = {
|
|
39
|
+
emit() {
|
|
40
|
+
// Intentionally empty: the default sink drops events.
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=telemetry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,EACL,cAAc,EACd,0BAA0B,GAE3B,MAAM,qBAAqB,CAAC;AAQ7B,sDAAsD;AACtD,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ,IAAI,cAAc,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAE,KAAK,CAAC,GAAc,KAAK,KAAK,CAAC,CAC7F,CAAC;AACJ,CAAC;AAwCD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,aAAa,GAAkB;IAC1C,IAAI;QACF,sDAAsD;IACxD,CAAC;CACF,CAAC"}
|