@nodii/telemetry 0.0.1 → 0.1.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/README.md +223 -1
- package/dist/active-span.d.ts +12 -0
- package/dist/active-span.d.ts.map +1 -0
- package/dist/active-span.js +20 -0
- package/dist/active-span.js.map +1 -0
- package/dist/agent-invocable.d.ts +24 -0
- package/dist/agent-invocable.d.ts.map +1 -0
- package/dist/agent-invocable.js +64 -0
- package/dist/agent-invocable.js.map +1 -0
- package/dist/audit.d.ts +47 -0
- package/dist/audit.d.ts.map +1 -0
- package/dist/audit.js +78 -0
- package/dist/audit.js.map +1 -0
- package/dist/context.d.ts +40 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +70 -0
- package/dist/context.js.map +1 -0
- package/dist/index.d.ts +18 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +29 -5
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts +39 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.js +114 -0
- package/dist/init.js.map +1 -0
- package/dist/intent.d.ts +21 -0
- package/dist/intent.d.ts.map +1 -0
- package/dist/intent.js +123 -0
- package/dist/intent.js.map +1 -0
- package/dist/logger.d.ts +19 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +99 -0
- package/dist/logger.js.map +1 -0
- package/dist/metrics.d.ts +53 -0
- package/dist/metrics.d.ts.map +1 -0
- package/dist/metrics.js +152 -0
- package/dist/metrics.js.map +1 -0
- package/dist/otlp-adapter.d.ts +44 -0
- package/dist/otlp-adapter.d.ts.map +1 -0
- package/dist/otlp-adapter.js +351 -0
- package/dist/otlp-adapter.js.map +1 -0
- package/dist/outbox-emit.d.ts +34 -0
- package/dist/outbox-emit.d.ts.map +1 -0
- package/dist/outbox-emit.js +58 -0
- package/dist/outbox-emit.js.map +1 -0
- package/dist/redaction.d.ts +51 -0
- package/dist/redaction.d.ts.map +1 -0
- package/dist/redaction.js +173 -0
- package/dist/redaction.js.map +1 -0
- package/dist/sdk-counters.d.ts +14 -0
- package/dist/sdk-counters.d.ts.map +1 -0
- package/dist/sdk-counters.js +42 -0
- package/dist/sdk-counters.js.map +1 -0
- package/dist/tracer.d.ts +63 -0
- package/dist/tracer.d.ts.map +1 -0
- package/dist/tracer.js +214 -0
- package/dist/tracer.js.map +1 -0
- package/dist/types.d.ts +230 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +66 -0
- package/dist/types.js.map +1 -0
- package/dist/uuid.d.ts +5 -0
- package/dist/uuid.d.ts.map +1 -0
- package/dist/uuid.js +34 -0
- package/dist/uuid.js.map +1 -0
- package/package.json +28 -6
package/README.md
CHANGED
|
@@ -1,5 +1,227 @@
|
|
|
1
1
|
# @nodii/telemetry
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Substrate observability library for the Nodii microservice stack. v0.1.0
|
|
4
|
+
ships the SDK surface — bootstrap, log envelope, tracer, meter, audit
|
|
5
|
+
signal, intent lifecycle, agent registry, context propagation — without
|
|
6
|
+
the OTel-SDK wiring (deferred to a v0.1.x follow-up; see
|
|
7
|
+
`.agent-todo.md` TS-12).
|
|
4
8
|
|
|
5
9
|
**Spec**: `https://planning.dev.nucleus-cloud.in/api/v1/feature-docs?serviceId=nodii-libs&docKey=telemetry`
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
bun add @nodii/telemetry
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Bootstrap (D152)
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { initTelemetry } from "@nodii/telemetry";
|
|
21
|
+
|
|
22
|
+
initTelemetry({
|
|
23
|
+
serviceName: "nodii-billing-service",
|
|
24
|
+
env: process.env.APPLICATION_STATE!, // 'dev' | 'uat' | 'prod'
|
|
25
|
+
otlpEndpoint: process.env.OTLP_ENDPOINT,
|
|
26
|
+
vocabularyRegistry: {
|
|
27
|
+
billing_payments_total: {
|
|
28
|
+
family: "async_worker",
|
|
29
|
+
description: "Payments processed",
|
|
30
|
+
decision: "D23",
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
intentTypes: {
|
|
34
|
+
"billing.invoice.create": {
|
|
35
|
+
typeName: "billing.invoice.create",
|
|
36
|
+
server_mintable: true,
|
|
37
|
+
client_mintable: false,
|
|
38
|
+
timeout_seconds: 300,
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Subsequent `initTelemetry()` calls warn-log + no-op. Calling any public
|
|
45
|
+
API before init throws `TelemetryNotInitialized`.
|
|
46
|
+
|
|
47
|
+
## Logger (D13)
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
import { logger } from "@nodii/telemetry";
|
|
51
|
+
|
|
52
|
+
logger.info("payment.charged", { invoice_id, amount_minor_units });
|
|
53
|
+
logger.error("saga.compensation.failed", { saga_id, step, reason });
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The 11-field envelope (`level, ts, msg, service, env, tenant_id,
|
|
57
|
+
user_id, request_id, trace_id, span_id, intent_id`) is auto-attached
|
|
58
|
+
from the active `NodiiContext` + the init config + the active OTel
|
|
59
|
+
span. **Do not pass envelope fields yourself** — they get filled in.
|
|
60
|
+
|
|
61
|
+
D15 redaction runs on every line (structured-field keys against the D2
|
|
62
|
+
PII list + regex pass on the message string) and is **fail-closed**:
|
|
63
|
+
if redaction throws, the line is DROPPED and
|
|
64
|
+
`telemetry.sdk.redaction_failure_total{reason}` bumps.
|
|
65
|
+
|
|
66
|
+
## Tracer (D26 / D27 / D28)
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
import { tracer, withSpanAttributes } from "@nodii/telemetry";
|
|
70
|
+
|
|
71
|
+
await withSpanAttributes({ invoice_id }, async () => {
|
|
72
|
+
await tracer.span("billing.invoice.create", async (span) => {
|
|
73
|
+
span.setAttribute("payment.method", method);
|
|
74
|
+
// ... business logic; mandatory attrs auto-applied
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Mandatory attributes (`tenant_id, request_id, intent_id`) are stamped
|
|
80
|
+
on span start. 4 KB per-value cap with `_truncated=true` marker. D27
|
|
81
|
+
status mapping: `recordException` auto-pairs with `ERROR`; clean
|
|
82
|
+
return defaults to `OK`.
|
|
83
|
+
|
|
84
|
+
## Metrics (D18 / D19 / D20 / D24)
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
import { metrics } from "@nodii/telemetry";
|
|
88
|
+
|
|
89
|
+
const paymentsCounter = metrics.counter("billing_payments_total", {
|
|
90
|
+
family: "async_worker",
|
|
91
|
+
description: "Payments processed",
|
|
92
|
+
});
|
|
93
|
+
paymentsCounter.inc({ tenant_id, pgw, status });
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Names must exist in the vocabulary registry passed to
|
|
97
|
+
`initTelemetry({ vocabularyRegistry })` — D24 ADR-gated. Mismatched
|
|
98
|
+
family or off-vocab name → `MetricVocabularyError` + bumps
|
|
99
|
+
`telemetry.sdk.cardinality_rejected_total{family, reason}`.
|
|
100
|
+
|
|
101
|
+
D20 bare-label discipline: registration rejects `tenant.id` and
|
|
102
|
+
`tenantId` variants.
|
|
103
|
+
|
|
104
|
+
D19: exponential histograms, max 160 buckets.
|
|
105
|
+
|
|
106
|
+
## Audit (D17 / D33)
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
import { audit } from "@nodii/telemetry";
|
|
110
|
+
|
|
111
|
+
await audit.emit({
|
|
112
|
+
action: "payment.refund.issued",
|
|
113
|
+
target_kind: "payment",
|
|
114
|
+
target_id: payment.id,
|
|
115
|
+
payload: { amount_minor_units, reason },
|
|
116
|
+
});
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
The library ships the adapter (write path); the emission policy
|
|
120
|
+
(method-level interceptor, saga lifecycle events, agent-layer
|
|
121
|
+
double-emission) and the `audit_log` schema live in the audit
|
|
122
|
+
doctrine + each consuming service.
|
|
123
|
+
|
|
124
|
+
## Intent lifecycle (D46 / D155)
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
import { intent } from "@nodii/telemetry";
|
|
128
|
+
|
|
129
|
+
const id = await intent.begin("billing.invoice.create", { invoice_id });
|
|
130
|
+
try {
|
|
131
|
+
// work
|
|
132
|
+
await intent.complete(id, { result: "ok" });
|
|
133
|
+
} catch (err) {
|
|
134
|
+
await intent.abandon(id, "error");
|
|
135
|
+
throw err;
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
`intent.begin` HARD-validates the type name against the registry
|
|
140
|
+
(D155); unknown type → `IntentTypeNotRegistered`. Activates the intent
|
|
141
|
+
on the active `NodiiContext` (sets `intent_id`). Nested begins stack
|
|
142
|
+
by id match.
|
|
143
|
+
|
|
144
|
+
`intent.progress` is a no-op stub at v0.1.0 per D155 § M02
|
|
145
|
+
carry-forward.
|
|
146
|
+
|
|
147
|
+
## @agentInvocable (D156)
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
import { agentInvocable } from "@nodii/telemetry";
|
|
151
|
+
|
|
152
|
+
class PaymentService {
|
|
153
|
+
@agentInvocable({
|
|
154
|
+
mode: "composable",
|
|
155
|
+
authTier: "confirmation-required",
|
|
156
|
+
sideEffects: ["payment.refund"],
|
|
157
|
+
idempotency: "keyed-by-request-id",
|
|
158
|
+
description: "Refund a captured payment",
|
|
159
|
+
})
|
|
160
|
+
async refundPayment(req: RefundRequest): Promise<RefundResult> {
|
|
161
|
+
/* ... */
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Runtime is a no-op at v0.1.0 (D156). The decorator attaches the
|
|
167
|
+
config to the method + the class prototype under a symbol-keyed
|
|
168
|
+
property; the build-time codegen (separate tool, deferred) walks the
|
|
169
|
+
tsc AST + falls back to the runtime registry to emit
|
|
170
|
+
`agent-methods.generated.json`.
|
|
171
|
+
|
|
172
|
+
## Context propagation (D40 / D41)
|
|
173
|
+
|
|
174
|
+
```ts
|
|
175
|
+
import {
|
|
176
|
+
type NodiiContext,
|
|
177
|
+
withContext,
|
|
178
|
+
getContext,
|
|
179
|
+
requireContext,
|
|
180
|
+
} from "@nodii/telemetry";
|
|
181
|
+
|
|
182
|
+
const ctx: NodiiContext = {
|
|
183
|
+
tenant_id: "...",
|
|
184
|
+
user_id: "...",
|
|
185
|
+
actor_type: "user",
|
|
186
|
+
on_behalf_of: null,
|
|
187
|
+
role: "owner",
|
|
188
|
+
request_id: "...",
|
|
189
|
+
intent_id: null,
|
|
190
|
+
};
|
|
191
|
+
await withContext(ctx, async () => {
|
|
192
|
+
/* every log / span / metric / audit emit picks up this context */
|
|
193
|
+
});
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Read with `getContext()` (returns null when no scope active) or
|
|
197
|
+
`requireContext()` (throws). SDK middleware adapters (deferred to
|
|
198
|
+
TS-9) are the ONLY writers of the parent-scope context per D41 lock;
|
|
199
|
+
service code uses `withContext` for child scopes only.
|
|
200
|
+
|
|
201
|
+
## SDK-internal counters
|
|
202
|
+
|
|
203
|
+
The library increments these on its own behaviors (do not register
|
|
204
|
+
them in your vocabulary):
|
|
205
|
+
|
|
206
|
+
- `telemetry.sdk.redaction_failure_total{reason}` — D15 fail-closed
|
|
207
|
+
drop.
|
|
208
|
+
- `telemetry.sdk.cardinality_rejected_total{family, reason}` — D18.
|
|
209
|
+
- `telemetry.sdk.export_failures_total{signal, reason}` — D153.
|
|
210
|
+
- `telemetry.sdk.trace_propagation_missing_total` — § 5.9 D25.
|
|
211
|
+
|
|
212
|
+
## Deferred to v0.1.x
|
|
213
|
+
|
|
214
|
+
See `.agent-todo.md` at the repo root:
|
|
215
|
+
|
|
216
|
+
- **TS-9**: Subpath adapters (`/grpc`, `/bullmq`, `/outbox`,
|
|
217
|
+
`/system-process`, `/lambda`).
|
|
218
|
+
- **TS-12**: Real OTel SDK wiring — replaces the no-op
|
|
219
|
+
`SpanEmitter` + the default JSON log sink with the OTLP
|
|
220
|
+
exporters.
|
|
221
|
+
- **TS-13**: Smoke service per D157 at `ts/telemetry-smoke/`.
|
|
222
|
+
- **TS-14**: Telemetry-tax-budget benchmark (D28 ≤ 200µs SDK-side
|
|
223
|
+
per typical RPC).
|
|
224
|
+
|
|
225
|
+
## License
|
|
226
|
+
|
|
227
|
+
MIT
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface ActiveSpanRef {
|
|
2
|
+
trace_id: string;
|
|
3
|
+
span_id: string;
|
|
4
|
+
}
|
|
5
|
+
export type ActiveSpanGetter = () => ActiveSpanRef | null;
|
|
6
|
+
/** SDK-internal: the tracer module installs this on initialization. */
|
|
7
|
+
export declare function _setActiveSpanGetter(g: ActiveSpanGetter): void;
|
|
8
|
+
/** Read the active span ids. Returns null when no span is active. */
|
|
9
|
+
export declare function getActiveSpan(): ActiveSpanRef | null;
|
|
10
|
+
/** Test-only reset. */
|
|
11
|
+
export declare function _resetActiveSpanForTests(): void;
|
|
12
|
+
//# sourceMappingURL=active-span.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"active-span.d.ts","sourceRoot":"","sources":["../src/active-span.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,gBAAgB,GAAG,MAAM,aAAa,GAAG,IAAI,CAAC;AAI1D,uEAAuE;AACvE,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAE9D;AAED,qEAAqE;AACrE,wBAAgB,aAAa,IAAI,aAAa,GAAG,IAAI,CAEpD;AAED,uBAAuB;AACvB,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Active-span hooks. The tracer (§ 5.3) registers a getter that returns
|
|
2
|
+
// the current `{ trace_id, span_id }` pair, or null if no span is
|
|
3
|
+
// active. The logger reads this on every log line so envelope fields
|
|
4
|
+
// `trace_id` and `span_id` (D13) are auto-stamped without the logger
|
|
5
|
+
// importing the tracer (avoids a cycle and lets the OTel wiring land
|
|
6
|
+
// in TS-12 as a strict module-internal swap).
|
|
7
|
+
let getter = () => null;
|
|
8
|
+
/** SDK-internal: the tracer module installs this on initialization. */
|
|
9
|
+
export function _setActiveSpanGetter(g) {
|
|
10
|
+
getter = g;
|
|
11
|
+
}
|
|
12
|
+
/** Read the active span ids. Returns null when no span is active. */
|
|
13
|
+
export function getActiveSpan() {
|
|
14
|
+
return getter();
|
|
15
|
+
}
|
|
16
|
+
/** Test-only reset. */
|
|
17
|
+
export function _resetActiveSpanForTests() {
|
|
18
|
+
getter = () => null;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=active-span.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"active-span.js","sourceRoot":"","sources":["../src/active-span.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,kEAAkE;AAClE,qEAAqE;AACrE,qEAAqE;AACrE,qEAAqE;AACrE,8CAA8C;AAS9C,IAAI,MAAM,GAAqB,GAAG,EAAE,CAAC,IAAI,CAAC;AAE1C,uEAAuE;AACvE,MAAM,UAAU,oBAAoB,CAAC,CAAmB;IACtD,MAAM,GAAG,CAAC,CAAC;AACb,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,aAAa;IAC3B,OAAO,MAAM,EAAE,CAAC;AAClB,CAAC;AAED,uBAAuB;AACvB,MAAM,UAAU,wBAAwB;IACtC,MAAM,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC;AACtB,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type AgentInvocableConfig } from "./types";
|
|
2
|
+
export declare const AGENT_INVOCABLE_METADATA: unique symbol;
|
|
3
|
+
/**
|
|
4
|
+
* Method decorator. TS legacy decorators are still the only widely
|
|
5
|
+
* deployed form for class methods; we attach metadata under a
|
|
6
|
+
* symbol-keyed property on the method itself + on the class prototype.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
*
|
|
10
|
+
* class PaymentService {
|
|
11
|
+
* @agentInvocable({ mode: 'composable', authTier: 'confirmation-required',
|
|
12
|
+
* sideEffects: ['payment.refund'], idempotency: 'keyed-by-request-id',
|
|
13
|
+
* description: 'Refund a captured payment' })
|
|
14
|
+
* async refundPayment(req) { ... }
|
|
15
|
+
* }
|
|
16
|
+
*/
|
|
17
|
+
export declare function agentInvocable(cfg: AgentInvocableConfig): (target: object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => PropertyDescriptor;
|
|
18
|
+
/**
|
|
19
|
+
* Read the registry from a class. Used by tests + the codegen fallback
|
|
20
|
+
* (when AST discovery doesn't find a decorator, e.g. when the file was
|
|
21
|
+
* transformed by a different toolchain).
|
|
22
|
+
*/
|
|
23
|
+
export declare function readAgentRegistry<T extends object>(ctor: T): Record<string | symbol, AgentInvocableConfig>;
|
|
24
|
+
//# sourceMappingURL=agent-invocable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-invocable.d.ts","sourceRoot":"","sources":["../src/agent-invocable.ts"],"names":[],"mappings":"AASA,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,SAAS,CAAC;AAEjB,eAAO,MAAM,wBAAwB,eAEpC,CAAC;AAoBF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,oBAAoB,IAGpD,QAAQ,MAAM,EACd,aAAa,MAAM,GAAG,MAAM,EAC5B,YAAY,kBAAkB,KAC7B,kBAAkB,CAuBtB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,MAAM,EAChD,IAAI,EAAE,CAAC,GACN,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,oBAAoB,CAAC,CAM/C"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// `@agentInvocable` decorator per D156. Runtime no-op at v0.1.0 — the
|
|
2
|
+
// agent dispatcher consumes the build-time codegen registry
|
|
3
|
+
// (`agent-methods.generated.json`), not the runtime metadata.
|
|
4
|
+
//
|
|
5
|
+
// At v0.1.0 we attach the supplied config to the method's prototype
|
|
6
|
+
// under a well-known symbol so the codegen step (a separate tsc AST
|
|
7
|
+
// walk in TS-8 wave 2) can also discover registrations via runtime
|
|
8
|
+
// import if it falls back from the AST path.
|
|
9
|
+
import { AGENT_INVOCABLE_SIDE_EFFECTS, } from "./types";
|
|
10
|
+
export const AGENT_INVOCABLE_METADATA = Symbol.for("@nodii/telemetry/agentInvocable");
|
|
11
|
+
function validate(cfg) {
|
|
12
|
+
if (cfg.mode === "strict-only" && !cfg.allowedPipelines?.length) {
|
|
13
|
+
throw new Error("@agentInvocable: `allowedPipelines` is required when `mode = 'strict-only'`");
|
|
14
|
+
}
|
|
15
|
+
for (const eff of cfg.sideEffects) {
|
|
16
|
+
if (!AGENT_INVOCABLE_SIDE_EFFECTS.includes(eff)) {
|
|
17
|
+
throw new Error(`@agentInvocable: sideEffect '${eff}' is not in the locked vocabulary (D156).`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
if (!cfg.description) {
|
|
21
|
+
throw new Error("@agentInvocable: `description` is required");
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Method decorator. TS legacy decorators are still the only widely
|
|
26
|
+
* deployed form for class methods; we attach metadata under a
|
|
27
|
+
* symbol-keyed property on the method itself + on the class prototype.
|
|
28
|
+
*
|
|
29
|
+
* Usage:
|
|
30
|
+
*
|
|
31
|
+
* class PaymentService {
|
|
32
|
+
* @agentInvocable({ mode: 'composable', authTier: 'confirmation-required',
|
|
33
|
+
* sideEffects: ['payment.refund'], idempotency: 'keyed-by-request-id',
|
|
34
|
+
* description: 'Refund a captured payment' })
|
|
35
|
+
* async refundPayment(req) { ... }
|
|
36
|
+
* }
|
|
37
|
+
*/
|
|
38
|
+
export function agentInvocable(cfg) {
|
|
39
|
+
validate(cfg);
|
|
40
|
+
return function decorate(target, propertyKey, descriptor) {
|
|
41
|
+
const original = descriptor.value;
|
|
42
|
+
if (typeof original !== "function") {
|
|
43
|
+
throw new Error("@agentInvocable can only be applied to methods (PropertyDescriptor.value must be a function).");
|
|
44
|
+
}
|
|
45
|
+
// Attach metadata to the method function itself.
|
|
46
|
+
original[AGENT_INVOCABLE_METADATA] =
|
|
47
|
+
cfg;
|
|
48
|
+
// Mirror onto a class-level registry under the same symbol.
|
|
49
|
+
const ctor = target.constructor;
|
|
50
|
+
const existing = ctor[AGENT_INVOCABLE_METADATA] ?? {};
|
|
51
|
+
existing[propertyKey] = cfg;
|
|
52
|
+
ctor[AGENT_INVOCABLE_METADATA] = existing;
|
|
53
|
+
return descriptor;
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Read the registry from a class. Used by tests + the codegen fallback
|
|
58
|
+
* (when AST discovery doesn't find a decorator, e.g. when the file was
|
|
59
|
+
* transformed by a different toolchain).
|
|
60
|
+
*/
|
|
61
|
+
export function readAgentRegistry(ctor) {
|
|
62
|
+
return (ctor[AGENT_INVOCABLE_METADATA] ?? {});
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=agent-invocable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-invocable.js","sourceRoot":"","sources":["../src/agent-invocable.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,4DAA4D;AAC5D,8DAA8D;AAC9D,EAAE;AACF,oEAAoE;AACpE,oEAAoE;AACpE,mEAAmE;AACnE,6CAA6C;AAE7C,OAAO,EACL,4BAA4B,GAE7B,MAAM,SAAS,CAAC;AAEjB,MAAM,CAAC,MAAM,wBAAwB,GAAG,MAAM,CAAC,GAAG,CAChD,iCAAiC,CAClC,CAAC;AAEF,SAAS,QAAQ,CAAC,GAAyB;IACzC,IAAI,GAAG,CAAC,IAAI,KAAK,aAAa,IAAI,CAAC,GAAG,CAAC,gBAAgB,EAAE,MAAM,EAAE,CAAC;QAChE,MAAM,IAAI,KAAK,CACb,6EAA6E,CAC9E,CAAC;IACJ,CAAC;IACD,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;QAClC,IAAI,CAAC,4BAA4B,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAChD,MAAM,IAAI,KAAK,CACb,gCAAgC,GAAG,2CAA2C,CAC/E,CAAC;QACJ,CAAC;IACH,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAChE,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,cAAc,CAAC,GAAyB;IACtD,QAAQ,CAAC,GAAG,CAAC,CAAC;IACd,OAAO,SAAS,QAAQ,CACtB,MAAc,EACd,WAA4B,EAC5B,UAA8B;QAE9B,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC;QAClC,IAAI,OAAO,QAAQ,KAAK,UAAU,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CACb,+FAA+F,CAChG,CAAC;QACJ,CAAC;QACD,iDAAiD;QAChD,QAA+C,CAAC,wBAAwB,CAAC;YACxE,GAAG,CAAC;QACN,4DAA4D;QAC5D,MAAM,IAAI,GAAI,MAAkC,CAAC,WAGhD,CAAC;QACF,MAAM,QAAQ,GACX,IAAI,CAAC,wBAAwB,CAEhB,IAAI,EAAE,CAAC;QACvB,QAAQ,CAAC,WAAW,CAAC,GAAG,GAAG,CAAC;QAC5B,IAAI,CAAC,wBAAwB,CAAC,GAAG,QAAQ,CAAC;QAC1C,OAAO,UAAU,CAAC;IACpB,CAAC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAC/B,IAAO;IAEP,OAAO,CACH,IAA2C,CAC3C,wBAAwB,CACyB,IAAI,EAAE,CAC1D,CAAC;AACJ,CAAC"}
|
package/dist/audit.d.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export interface AuditEvent {
|
|
2
|
+
/** D33-locked vocabulary, e.g. `payment.refund.issued`. */
|
|
3
|
+
action: string;
|
|
4
|
+
/** D33: target_kind, e.g. `payment`, `service`, `feature_doc`. */
|
|
5
|
+
target_kind: string;
|
|
6
|
+
/** Stable id of the row being acted on. May be null for create-then-id. */
|
|
7
|
+
target_id: string | null;
|
|
8
|
+
/** Free-form payload; redaction happens in `audit.emit`. */
|
|
9
|
+
payload?: Record<string, unknown>;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* The pluggable Postgres-write path. Services wire this on init by
|
|
13
|
+
* passing `auditWriter` to `initTelemetry({ ... })` (deferred) OR by
|
|
14
|
+
* calling `_setAuditWriter` from a `@nodii/db-rls` adapter. v0.1.0 ships
|
|
15
|
+
* a default no-op writer; consumers replace it.
|
|
16
|
+
*/
|
|
17
|
+
export type AuditWriter = (row: {
|
|
18
|
+
actor: string;
|
|
19
|
+
action: string;
|
|
20
|
+
target_kind: string;
|
|
21
|
+
target_id: string | null;
|
|
22
|
+
payload: Record<string, unknown> | null;
|
|
23
|
+
tenant_id: string | null;
|
|
24
|
+
request_id: string | null;
|
|
25
|
+
intent_id: string | null;
|
|
26
|
+
ts: string;
|
|
27
|
+
}) => Promise<void> | void;
|
|
28
|
+
/**
|
|
29
|
+
* SDK-internal: services or the `@nodii/db-rls` adapter sets the
|
|
30
|
+
* writer. Public callers MUST NOT call this; the override exists for
|
|
31
|
+
* the adapter layer.
|
|
32
|
+
*/
|
|
33
|
+
export declare function _setAuditWriter(w: AuditWriter): void;
|
|
34
|
+
/** Test-only restore. */
|
|
35
|
+
export declare function _resetAuditWriterForTests(): void;
|
|
36
|
+
/**
|
|
37
|
+
* The `audit.emit` API. Awaits the writer so the caller can await one
|
|
38
|
+
* write before responding; failures propagate to the caller (audit is
|
|
39
|
+
* NOT best-effort the way logs are — D33 requires durable emission for
|
|
40
|
+
* mutations).
|
|
41
|
+
*/
|
|
42
|
+
declare function emit(event: AuditEvent): Promise<void>;
|
|
43
|
+
export declare const audit: {
|
|
44
|
+
readonly emit: typeof emit;
|
|
45
|
+
};
|
|
46
|
+
export {};
|
|
47
|
+
//# sourceMappingURL=audit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../src/audit.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,UAAU;IACzB,2DAA2D;IAC3D,MAAM,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,WAAW,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,4DAA4D;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACxC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,EAAE,EAAE,MAAM,CAAC;CACZ,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAQ3B;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,WAAW,GAAG,IAAI,CAEpD;AAED,yBAAyB;AACzB,wBAAgB,yBAAyB,IAAI,IAAI,CAEhD;AAED;;;;;GAKG;AACH,iBAAe,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAepD;AAwBD,eAAO,MAAM,KAAK;;CAER,CAAC"}
|
package/dist/audit.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// Audit signal class per D17 + D33 + D149. Separate from logs.
|
|
2
|
+
//
|
|
3
|
+
// "If a tenant could legitimately need to see this row, it's audit, not
|
|
4
|
+
// log." — D17 cultural rule.
|
|
5
|
+
//
|
|
6
|
+
// The library ships the adapter (the write path); the audit emission
|
|
7
|
+
// policy (D33 three paths: method-level interceptor, saga lifecycle,
|
|
8
|
+
// agent-layer double-emission) and the audit_log SCHEMA live in the
|
|
9
|
+
// audit doctrine, not here. `@nodii/telemetry`'s job is to provide
|
|
10
|
+
// `audit.emit(...)` that lands the row in:
|
|
11
|
+
// - per-service Postgres audit_log table (via the configured writer)
|
|
12
|
+
// - ClickHouse mirror (via OTLP audit signal; deferred to TS-12)
|
|
13
|
+
import { getContext } from "./context";
|
|
14
|
+
import { requireTelemetry } from "./init";
|
|
15
|
+
const noopWriter = () => {
|
|
16
|
+
/* no-op default; services wire a real writer */
|
|
17
|
+
};
|
|
18
|
+
let writer = noopWriter;
|
|
19
|
+
/**
|
|
20
|
+
* SDK-internal: services or the `@nodii/db-rls` adapter sets the
|
|
21
|
+
* writer. Public callers MUST NOT call this; the override exists for
|
|
22
|
+
* the adapter layer.
|
|
23
|
+
*/
|
|
24
|
+
export function _setAuditWriter(w) {
|
|
25
|
+
writer = w;
|
|
26
|
+
}
|
|
27
|
+
/** Test-only restore. */
|
|
28
|
+
export function _resetAuditWriterForTests() {
|
|
29
|
+
writer = noopWriter;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The `audit.emit` API. Awaits the writer so the caller can await one
|
|
33
|
+
* write before responding; failures propagate to the caller (audit is
|
|
34
|
+
* NOT best-effort the way logs are — D33 requires durable emission for
|
|
35
|
+
* mutations).
|
|
36
|
+
*/
|
|
37
|
+
async function emit(event) {
|
|
38
|
+
requireTelemetry(); // throws if SDK not init'd
|
|
39
|
+
const ctx = getContext();
|
|
40
|
+
const actor = formatActor(ctx);
|
|
41
|
+
await writer({
|
|
42
|
+
actor,
|
|
43
|
+
action: event.action,
|
|
44
|
+
target_kind: event.target_kind,
|
|
45
|
+
target_id: event.target_id,
|
|
46
|
+
payload: event.payload ?? null,
|
|
47
|
+
tenant_id: ctx?.tenant_id ?? null,
|
|
48
|
+
request_id: ctx?.request_id ?? null,
|
|
49
|
+
intent_id: ctx?.intent_id ?? null,
|
|
50
|
+
ts: new Date().toISOString(),
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
function formatActor(ctx) {
|
|
54
|
+
if (!ctx)
|
|
55
|
+
return "system";
|
|
56
|
+
switch (ctx.actor_type) {
|
|
57
|
+
case "user":
|
|
58
|
+
return ctx.user_id ? `user:${ctx.user_id}` : "user:unknown";
|
|
59
|
+
case "agent":
|
|
60
|
+
return ctx.on_behalf_of
|
|
61
|
+
? `agent:on_behalf_of:${ctx.on_behalf_of}`
|
|
62
|
+
: "agent:unknown";
|
|
63
|
+
case "service":
|
|
64
|
+
return "service";
|
|
65
|
+
case "system":
|
|
66
|
+
return "system";
|
|
67
|
+
default: {
|
|
68
|
+
// Exhaustiveness check.
|
|
69
|
+
const _exhaustive = ctx.actor_type;
|
|
70
|
+
void _exhaustive;
|
|
71
|
+
return "unknown";
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
export const audit = {
|
|
76
|
+
emit,
|
|
77
|
+
};
|
|
78
|
+
//# sourceMappingURL=audit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../src/audit.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,EAAE;AACF,wEAAwE;AACxE,6BAA6B;AAC7B,EAAE;AACF,qEAAqE;AACrE,qEAAqE;AACrE,oEAAoE;AACpE,mEAAmE;AACnE,2CAA2C;AAC3C,uEAAuE;AACvE,mEAAmE;AAEnE,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,QAAQ,CAAC;AA+B1C,MAAM,UAAU,GAAgB,GAAG,EAAE;IACnC,gDAAgD;AAClD,CAAC,CAAC;AAEF,IAAI,MAAM,GAAgB,UAAU,CAAC;AAErC;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,CAAc;IAC5C,MAAM,GAAG,CAAC,CAAC;AACb,CAAC;AAED,yBAAyB;AACzB,MAAM,UAAU,yBAAyB;IACvC,MAAM,GAAG,UAAU,CAAC;AACtB,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,IAAI,CAAC,KAAiB;IACnC,gBAAgB,EAAE,CAAC,CAAC,2BAA2B;IAC/C,MAAM,GAAG,GAAG,UAAU,EAAE,CAAC;IACzB,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAC/B,MAAM,MAAM,CAAC;QACX,KAAK;QACL,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,IAAI;QAC9B,SAAS,EAAE,GAAG,EAAE,SAAS,IAAI,IAAI;QACjC,UAAU,EAAE,GAAG,EAAE,UAAU,IAAI,IAAI;QACnC,SAAS,EAAE,GAAG,EAAE,SAAS,IAAI,IAAI;QACjC,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KAC7B,CAAC,CAAC;AACL,CAAC;AAED,SAAS,WAAW,CAAC,GAAkC;IACrD,IAAI,CAAC,GAAG;QAAE,OAAO,QAAQ,CAAC;IAC1B,QAAQ,GAAG,CAAC,UAAU,EAAE,CAAC;QACvB,KAAK,MAAM;YACT,OAAO,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC;QAC9D,KAAK,OAAO;YACV,OAAO,GAAG,CAAC,YAAY;gBACrB,CAAC,CAAC,sBAAsB,GAAG,CAAC,YAAY,EAAE;gBAC1C,CAAC,CAAC,eAAe,CAAC;QACtB,KAAK,SAAS;YACZ,OAAO,SAAS,CAAC;QACnB,KAAK,QAAQ;YACX,OAAO,QAAQ,CAAC;QAClB,OAAO,CAAC,CAAC,CAAC;YACR,wBAAwB;YACxB,MAAM,WAAW,GAAU,GAAG,CAAC,UAAU,CAAC;YAC1C,KAAK,WAAW,CAAC;YACjB,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,IAAI;CACI,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { NodiiContext } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Returns the active `NodiiContext`, or null if no middleware adapter
|
|
4
|
+
* has set one for this async scope (cron-flow before the
|
|
5
|
+
* `system-process` adapter runs; raw scripts; tests without harness).
|
|
6
|
+
*/
|
|
7
|
+
export declare function getContext(): NodiiContext | null;
|
|
8
|
+
/**
|
|
9
|
+
* Like `getContext()` but throws if no context is active. Use this in
|
|
10
|
+
* code that is allowed to assume an adapter ran — typically inside a
|
|
11
|
+
* request handler.
|
|
12
|
+
*/
|
|
13
|
+
export declare function requireContext(): NodiiContext;
|
|
14
|
+
/**
|
|
15
|
+
* Run `fn` inside a child scope where `ctx` is the active context. Per
|
|
16
|
+
* D41: never mutates the parent scope — child finishes and the parent
|
|
17
|
+
* scope's context is unaffected.
|
|
18
|
+
*/
|
|
19
|
+
export declare function withContext<T>(ctx: NodiiContext, fn: () => T): T;
|
|
20
|
+
/**
|
|
21
|
+
* SDK-internal use only. The middleware adapters (§ 5.9) call this on
|
|
22
|
+
* request entry to set the active context. Service code MUST NOT call
|
|
23
|
+
* this directly — use `withContext()` for child scopes only. Not part
|
|
24
|
+
* of the public barrel; subpath adapters import it via the package
|
|
25
|
+
* internal path.
|
|
26
|
+
*/
|
|
27
|
+
export declare function setContextForCurrentScope(ctx: NodiiContext): void;
|
|
28
|
+
/**
|
|
29
|
+
* Update the active context's `intent_id` only. Used by the intent
|
|
30
|
+
* lifecycle (§ 5.6) when `intent.begin()` / `intent.complete()` /
|
|
31
|
+
* `intent.abandon()` activate or deactivate an intent. Returns the new
|
|
32
|
+
* context so callers can verify; throws if no context is active (intent
|
|
33
|
+
* lifecycle must run inside an established `NodiiContext`).
|
|
34
|
+
*
|
|
35
|
+
* This is the ONLY mutation API per D41. It exists because intent
|
|
36
|
+
* activation is a per-scope assignment that the intent lifecycle owns,
|
|
37
|
+
* not a service-code mutation.
|
|
38
|
+
*/
|
|
39
|
+
export declare function _setIntentIdInCurrentScope(intentId: string | null): NodiiContext;
|
|
40
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAI5C;;;;GAIG;AACH,wBAAgB,UAAU,IAAI,YAAY,GAAG,IAAI,CAEhD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,YAAY,CAQ7C;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,GAAG,EAAE,YAAY,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAEhE;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI,CAEjE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,MAAM,GAAG,IAAI,GACtB,YAAY,CAUd"}
|
package/dist/context.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// Context propagation per D40 / D41.
|
|
2
|
+
//
|
|
3
|
+
// SDK middleware (§ 5.9 of the feature_doc) is the ONLY writer of
|
|
4
|
+
// `NodiiContext`. Service code reads via `getContext()`; child scopes
|
|
5
|
+
// only via `withContext({...}, fn)`. There is no public mutate-in-place
|
|
6
|
+
// API — that's an invariant of D41.
|
|
7
|
+
//
|
|
8
|
+
// Implementation: Node's `AsyncLocalStorage`, which works under both
|
|
9
|
+
// Node and Bun. The store holds a `NodiiContext` directly.
|
|
10
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
11
|
+
const als = new AsyncLocalStorage();
|
|
12
|
+
/**
|
|
13
|
+
* Returns the active `NodiiContext`, or null if no middleware adapter
|
|
14
|
+
* has set one for this async scope (cron-flow before the
|
|
15
|
+
* `system-process` adapter runs; raw scripts; tests without harness).
|
|
16
|
+
*/
|
|
17
|
+
export function getContext() {
|
|
18
|
+
return als.getStore() ?? null;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Like `getContext()` but throws if no context is active. Use this in
|
|
22
|
+
* code that is allowed to assume an adapter ran — typically inside a
|
|
23
|
+
* request handler.
|
|
24
|
+
*/
|
|
25
|
+
export function requireContext() {
|
|
26
|
+
const ctx = als.getStore();
|
|
27
|
+
if (!ctx) {
|
|
28
|
+
throw new Error("No NodiiContext active. SDK middleware (or `withContext`) must run before this code path.");
|
|
29
|
+
}
|
|
30
|
+
return ctx;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Run `fn` inside a child scope where `ctx` is the active context. Per
|
|
34
|
+
* D41: never mutates the parent scope — child finishes and the parent
|
|
35
|
+
* scope's context is unaffected.
|
|
36
|
+
*/
|
|
37
|
+
export function withContext(ctx, fn) {
|
|
38
|
+
return als.run(ctx, fn);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* SDK-internal use only. The middleware adapters (§ 5.9) call this on
|
|
42
|
+
* request entry to set the active context. Service code MUST NOT call
|
|
43
|
+
* this directly — use `withContext()` for child scopes only. Not part
|
|
44
|
+
* of the public barrel; subpath adapters import it via the package
|
|
45
|
+
* internal path.
|
|
46
|
+
*/
|
|
47
|
+
export function setContextForCurrentScope(ctx) {
|
|
48
|
+
als.enterWith(ctx);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Update the active context's `intent_id` only. Used by the intent
|
|
52
|
+
* lifecycle (§ 5.6) when `intent.begin()` / `intent.complete()` /
|
|
53
|
+
* `intent.abandon()` activate or deactivate an intent. Returns the new
|
|
54
|
+
* context so callers can verify; throws if no context is active (intent
|
|
55
|
+
* lifecycle must run inside an established `NodiiContext`).
|
|
56
|
+
*
|
|
57
|
+
* This is the ONLY mutation API per D41. It exists because intent
|
|
58
|
+
* activation is a per-scope assignment that the intent lifecycle owns,
|
|
59
|
+
* not a service-code mutation.
|
|
60
|
+
*/
|
|
61
|
+
export function _setIntentIdInCurrentScope(intentId) {
|
|
62
|
+
const cur = als.getStore();
|
|
63
|
+
if (!cur) {
|
|
64
|
+
throw new Error("Cannot set intent_id: no NodiiContext active. SDK middleware must run before `intent.begin()`.");
|
|
65
|
+
}
|
|
66
|
+
const next = { ...cur, intent_id: intentId };
|
|
67
|
+
als.enterWith(next);
|
|
68
|
+
return next;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,EAAE;AACF,kEAAkE;AAClE,sEAAsE;AACtE,wEAAwE;AACxE,oCAAoC;AACpC,EAAE;AACF,qEAAqE;AACrE,2DAA2D;AAE3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAGrD,MAAM,GAAG,GAAG,IAAI,iBAAiB,EAAgB,CAAC;AAElD;;;;GAIG;AACH,MAAM,UAAU,UAAU;IACxB,OAAO,GAAG,CAAC,QAAQ,EAAE,IAAI,IAAI,CAAC;AAChC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,GAAG,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC;IAC3B,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CACb,2FAA2F,CAC5F,CAAC;IACJ,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAI,GAAiB,EAAE,EAAW;IAC3D,OAAO,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;AAC1B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,yBAAyB,CAAC,GAAiB;IACzD,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;AACrB,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,0BAA0B,CACxC,QAAuB;IAEvB,MAAM,GAAG,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC;IAC3B,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CACb,gGAAgG,CACjG,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAiB,EAAE,GAAG,GAAG,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC;IAC3D,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACpB,OAAO,IAAI,CAAC;AACd,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
1
|
+
export { initTelemetry } from "./init";
|
|
2
|
+
export { forceFlush, getOtlpAdapterHandle, installOtlpAdapter, shutdownOtlpAdapter, } from "./otlp-adapter";
|
|
3
|
+
export type { OtlpAdapterHandle, OtlpAdapterConfig } from "./otlp-adapter";
|
|
4
|
+
export { logger } from "./logger";
|
|
5
|
+
export { tracer, withSpanAttributes, getSagaTracer } from "./tracer";
|
|
6
|
+
export type { Span, SpanKind, SpanRecord, SpanStatus } from "./tracer";
|
|
7
|
+
export { metrics, MetricVocabularyError } from "./metrics";
|
|
8
|
+
export type { CounterHandle, HistogramHandle, MetricRegistration, } from "./metrics";
|
|
9
|
+
export { audit } from "./audit";
|
|
10
|
+
export type { AuditEvent } from "./audit";
|
|
11
|
+
export { intent, IntentTypeNotRegistered } from "./intent";
|
|
12
|
+
export { agentInvocable, readAgentRegistry, AGENT_INVOCABLE_METADATA, } from "./agent-invocable";
|
|
13
|
+
export { getContext, requireContext, withContext, } from "./context";
|
|
14
|
+
export { isPiiFieldName, redactString, redactFields, PII_FIELD_NAMES, } from "./redaction";
|
|
15
|
+
export { uuidv7, isUuidv7 } from "./uuid";
|
|
16
|
+
export { TelemetryNotInitialized } from "./types";
|
|
17
|
+
export type { ActorType, AgentInvocableAuthTier, AgentInvocableConfig, AgentInvocableIdempotency, AgentInvocableMode, AgentInvocableRateLimit, AgentInvocableSideEffect, AutoInstrumentationConfig, ErrorHandlingConfig, ExportFailureReason, InitTelemetryConfig, IntentTypeDefinition, IntentTypeRegistry, LogEnvelope, LogLevel, MetricFamily, MetricVocabularyEntry, MetricVocabularyRegistry, NodiiContext, ResourceAttributes, SamplingConfig, } from "./types";
|
|
18
|
+
export { DEFAULT_SAMPLING_CONFIG, METRIC_FAMILIES, AGENT_INVOCABLE_SIDE_EFFECTS, } from "./types";
|
|
3
19
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EACL,UAAU,EACV,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAC3E,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACrE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACvE,OAAO,EAAE,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAC3D,YAAY,EACV,aAAa,EACb,eAAe,EACf,kBAAkB,GACnB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAC3D,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,wBAAwB,GACzB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,UAAU,EACV,cAAc,EACd,WAAW,GACZ,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,eAAe,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAC1C,OAAO,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAC;AAClD,YAAY,EACV,SAAS,EACT,sBAAsB,EACtB,oBAAoB,EACpB,yBAAyB,EACzB,kBAAkB,EAClB,uBAAuB,EACvB,wBAAwB,EACxB,yBAAyB,EACzB,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,WAAW,EACX,QAAQ,EACR,YAAY,EACZ,qBAAqB,EACrB,wBAAwB,EACxB,YAAY,EACZ,kBAAkB,EAClB,cAAc,GACf,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,uBAAuB,EACvB,eAAe,EACf,4BAA4B,GAC7B,MAAM,SAAS,CAAC"}
|