@equipe-tech/observability 0.2.0 → 0.3.5

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.
Files changed (177) hide show
  1. package/README.md +11 -9
  2. package/dist/BrowserEvents.d.ts +89 -12
  3. package/dist/BrowserEvents.js +67 -13
  4. package/dist/Correlation.d.ts +51 -0
  5. package/dist/Correlation.js +95 -0
  6. package/dist/Metrics.d.ts +19 -3
  7. package/dist/Metrics.js +16 -0
  8. package/dist/MetricsRuntime.d.ts +45 -3
  9. package/dist/MetricsRuntime.js +478 -120
  10. package/dist/PolicyOtlpLogger.d.ts +18 -0
  11. package/dist/PolicyOtlpLogger.js +142 -0
  12. package/dist/RedactionPolicy.d.ts +2 -9
  13. package/dist/RedactionPolicy.js +2 -246
  14. package/dist/ResourceIdentity.d.ts +47 -0
  15. package/dist/ResourceIdentity.js +82 -0
  16. package/dist/Telemetry.d.ts +18 -3
  17. package/dist/Telemetry.js +43 -25
  18. package/dist/TelemetryConfig.d.ts +11 -4
  19. package/dist/TelemetryConfig.js +38 -10
  20. package/dist/audit/AuditCommitDocument.d.ts +41 -0
  21. package/dist/audit/AuditCommitDocument.js +58 -0
  22. package/dist/audit/AuditDigest.d.ts +11 -0
  23. package/dist/audit/AuditDigest.js +25 -0
  24. package/dist/audit/AuditOutbox.d.ts +75 -0
  25. package/dist/audit/AuditOutbox.js +104 -0
  26. package/dist/audit/AuditPublisher.d.ts +49 -0
  27. package/dist/audit/AuditPublisher.js +60 -0
  28. package/dist/audit/AuditRecord.d.ts +128 -0
  29. package/dist/audit/AuditRecord.js +172 -0
  30. package/dist/audit/CommittedAuditRecordInternal.d.ts +11 -0
  31. package/dist/audit/CommittedAuditRecordInternal.js +13 -0
  32. package/dist/audit/InvalidAuditRecord.d.ts +12 -0
  33. package/dist/audit/InvalidAuditRecord.js +16 -0
  34. package/dist/audit/index.d.ts +7 -0
  35. package/dist/audit/index.js +7 -0
  36. package/dist/browser/BrowserClient.d.ts +82 -3
  37. package/dist/browser/BrowserClient.js +322 -28
  38. package/dist/browser/BrowserEventLimits.d.ts +8 -0
  39. package/dist/browser/BrowserEventLimits.js +8 -0
  40. package/dist/browser/BrowserMetricRecorder.d.ts +17 -0
  41. package/dist/browser/BrowserMetricRecorder.js +35 -0
  42. package/dist/browser/BrowserTelemetry.d.ts +40 -0
  43. package/dist/browser/BrowserTelemetry.js +105 -0
  44. package/dist/browser/ClientPolicy.d.ts +3 -0
  45. package/dist/browser/ClientPolicy.js +52 -0
  46. package/dist/browser/client.d.ts +3 -2
  47. package/dist/browser/client.js +2 -1
  48. package/dist/browser/index.d.ts +4 -37
  49. package/dist/browser/index.js +3 -95
  50. package/dist/contract/ContractCompatibility.d.ts +31 -0
  51. package/dist/contract/ContractCompatibility.js +274 -0
  52. package/dist/contract/ContractIndex.d.ts +54 -0
  53. package/dist/contract/ContractIndex.js +178 -0
  54. package/dist/contract/ContractSurface.d.ts +111 -0
  55. package/dist/contract/ContractSurface.js +116 -0
  56. package/dist/contract/EventName.d.ts +6 -0
  57. package/dist/contract/EventName.js +55 -0
  58. package/dist/contract/EventProducer.d.ts +123 -0
  59. package/dist/contract/EventProducer.js +209 -0
  60. package/dist/contract/MetricContractError.d.ts +19 -0
  61. package/dist/contract/MetricContractError.js +19 -0
  62. package/dist/contract/MetricDefinition.d.ts +61 -0
  63. package/dist/contract/MetricDefinition.js +91 -0
  64. package/dist/contract/MetricProducer.d.ts +42 -0
  65. package/dist/contract/MetricProducer.js +123 -0
  66. package/dist/contract/OrganizationEvents.d.ts +165 -0
  67. package/dist/contract/OrganizationEvents.js +97 -0
  68. package/dist/contract/TelemetryContract.d.ts +95 -0
  69. package/dist/contract/TelemetryContract.js +451 -0
  70. package/dist/contract/TelemetryContractError.d.ts +44 -0
  71. package/dist/contract/TelemetryContractError.js +64 -0
  72. package/dist/contract/TelemetryEvent.d.ts +59 -0
  73. package/dist/contract/TelemetryEvent.js +54 -0
  74. package/dist/contract/index.d.ts +11 -0
  75. package/dist/contract/index.js +11 -0
  76. package/dist/effect/WideEvent.d.ts +3 -0
  77. package/dist/effect/WideEvent.js +20 -0
  78. package/dist/effect/WideEventSink.d.ts +3 -0
  79. package/dist/effect/WideEventSink.js +79 -0
  80. package/dist/effect/index.d.ts +2 -0
  81. package/dist/effect/index.js +2 -0
  82. package/dist/index.d.ts +17 -2
  83. package/dist/index.js +11 -2
  84. package/dist/metrics/InstrumentGrammar.d.ts +5 -0
  85. package/dist/metrics/InstrumentGrammar.js +12 -0
  86. package/dist/metrics/MetricScalar.d.ts +3 -0
  87. package/dist/metrics/MetricScalar.js +5 -0
  88. package/dist/node/AuditDigest.d.ts +3 -0
  89. package/dist/node/AuditDigest.js +6 -0
  90. package/dist/node/BrowserEventIngest.d.ts +7 -2
  91. package/dist/node/BrowserEventIngest.js +111 -19
  92. package/dist/node/LocalCollector.d.ts +20 -0
  93. package/dist/node/LocalCollector.js +188 -0
  94. package/dist/node/Observability.d.ts +49 -0
  95. package/dist/node/Observability.js +190 -0
  96. package/dist/node/Runtime.d.ts +4 -1
  97. package/dist/node/index.d.ts +4 -0
  98. package/dist/node/index.js +3 -0
  99. package/dist/policy/BrowserFieldPolicy.d.ts +7 -0
  100. package/dist/policy/BrowserFieldPolicy.js +298 -0
  101. package/dist/policy/DataPolicy.d.ts +19 -0
  102. package/dist/policy/DataPolicy.js +254 -0
  103. package/dist/policy/DataPolicyError.d.ts +22 -0
  104. package/dist/policy/DataPolicyError.js +25 -0
  105. package/dist/policy/Deduplication.d.ts +13 -0
  106. package/dist/policy/Deduplication.js +44 -0
  107. package/dist/policy/DefectEnvelope.d.ts +25 -0
  108. package/dist/policy/DefectEnvelope.js +52 -0
  109. package/dist/policy/MetricLabelPolicy.d.ts +5 -0
  110. package/dist/policy/MetricLabelPolicy.js +65 -0
  111. package/dist/policy/PolicyTransform.d.ts +16 -0
  112. package/dist/policy/PolicyTransform.js +136 -0
  113. package/dist/policy/PolicyVocabulary.d.ts +10 -0
  114. package/dist/policy/PolicyVocabulary.js +84 -0
  115. package/dist/policy/ResourceAttributePolicy.d.ts +9 -0
  116. package/dist/policy/ResourceAttributePolicy.js +33 -0
  117. package/dist/policy/entrypoint.d.ts +2 -0
  118. package/dist/policy/entrypoint.js +2 -0
  119. package/dist/policy/index.d.ts +17 -0
  120. package/dist/policy/index.js +9 -0
  121. package/dist/profile/DataPolicy.d.ts +2 -0
  122. package/dist/profile/DataPolicy.js +1 -0
  123. package/dist/profile/EnvironmentPolicy.d.ts +22 -0
  124. package/dist/profile/EnvironmentPolicy.js +41 -0
  125. package/dist/profile/LifecycleRegistry.d.ts +24 -0
  126. package/dist/profile/LifecycleRegistry.js +240 -0
  127. package/dist/profile/ObservabilityAdapter.d.ts +115 -0
  128. package/dist/profile/ObservabilityAdapter.js +50 -0
  129. package/dist/profile/ObservabilityConfig.d.ts +68 -0
  130. package/dist/profile/ObservabilityConfig.js +125 -0
  131. package/dist/profile/ObservabilityConfigError.d.ts +23 -0
  132. package/dist/profile/ObservabilityConfigError.js +39 -0
  133. package/dist/profile/ObservabilityProfile.d.ts +49 -0
  134. package/dist/profile/ObservabilityProfile.js +121 -0
  135. package/dist/profile/ReactWebProfile.d.ts +8 -0
  136. package/dist/profile/ReactWebProfile.js +7 -0
  137. package/dist/profile/index.d.ts +5 -0
  138. package/dist/profile/index.js +5 -0
  139. package/dist/testing/conformance/ConformanceAssertions.d.ts +5 -0
  140. package/dist/testing/conformance/ConformanceAssertions.js +31 -0
  141. package/dist/testing/conformance/ConformanceFailure.d.ts +35 -0
  142. package/dist/testing/conformance/ConformanceFailure.js +56 -0
  143. package/dist/testing/conformance/ConformanceModel.d.ts +97 -0
  144. package/dist/testing/conformance/ConformanceModel.js +8 -0
  145. package/dist/testing/conformance/ConformanceRegistry.d.ts +13 -0
  146. package/dist/testing/conformance/ConformanceRegistry.js +190 -0
  147. package/dist/testing/conformance/ConformanceRunner.d.ts +5 -0
  148. package/dist/testing/conformance/ConformanceRunner.js +198 -0
  149. package/dist/testing/conformance/TelemetryEvidence.d.ts +91 -0
  150. package/dist/testing/conformance/TelemetryEvidence.js +370 -0
  151. package/dist/testing/conformance/index.d.ts +10 -0
  152. package/dist/testing/conformance/index.js +6 -0
  153. package/dist/testing/contract.d.ts +81 -0
  154. package/dist/testing/contract.js +93 -0
  155. package/dist/testing/deployedCanary.d.ts +1 -0
  156. package/dist/testing/deployedCanary.js +1 -0
  157. package/dist/testing/index.d.ts +40 -3
  158. package/dist/testing/index.js +122 -5
  159. package/dist/trace/HttpServerOtlpTracer.d.ts +42 -0
  160. package/dist/trace/HttpServerOtlpTracer.js +301 -0
  161. package/package.json +16 -29
  162. package/dist/WideEvent.d.ts +0 -5
  163. package/dist/WideEvent.js +0 -6
  164. package/dist/nestjs/BrowserEventsController.d.ts +0 -21
  165. package/dist/nestjs/BrowserEventsController.js +0 -52
  166. package/dist/nestjs/HttpRoutePolicy.d.ts +0 -23
  167. package/dist/nestjs/HttpRoutePolicy.js +0 -179
  168. package/dist/nestjs/HttpServerOtlpTracer.d.ts +0 -15
  169. package/dist/nestjs/HttpServerOtlpTracer.js +0 -154
  170. package/dist/nestjs/RequestWideEventTraceCorrelation.d.ts +0 -15
  171. package/dist/nestjs/RequestWideEventTraceCorrelation.js +0 -13
  172. package/dist/nestjs/TelemetryInterceptor.d.ts +0 -31
  173. package/dist/nestjs/TelemetryInterceptor.js +0 -268
  174. package/dist/nestjs/TelemetryModule.d.ts +0 -53
  175. package/dist/nestjs/TelemetryModule.js +0 -428
  176. package/dist/nestjs/index.d.ts +0 -5
  177. package/dist/nestjs/index.js +0 -4
@@ -0,0 +1,128 @@
1
+ import { Effect, Option, Schema } from "effect";
2
+ import { CorrelationContext } from "../Correlation.js";
3
+ import type { TelemetryContract, TelemetryContractInput } from "../contract/TelemetryContract.js";
4
+ import { InvalidAuditRecord } from "./InvalidAuditRecord.js";
5
+ export declare const AuditRecordId: Schema.brand<Schema.NonEmptyString, "AuditRecordId">;
6
+ export type AuditRecordId = typeof AuditRecordId.Type;
7
+ export declare const AuditTenantId: Schema.brand<Schema.NonEmptyString, "AuditTenantId">;
8
+ export type AuditTenantId = typeof AuditTenantId.Type;
9
+ export declare const AuditActorId: Schema.brand<Schema.NonEmptyString, "AuditActorId">;
10
+ export type AuditActorId = typeof AuditActorId.Type;
11
+ export declare const AuditResourceId: Schema.brand<Schema.NonEmptyString, "AuditResourceId">;
12
+ export type AuditResourceId = typeof AuditResourceId.Type;
13
+ export declare const AuditResourceType: Schema.brand<Schema.NonEmptyString, "AuditResourceType">;
14
+ export type AuditResourceType = typeof AuditResourceType.Type;
15
+ export declare const AuditAction: Schema.brand<Schema.NonEmptyString, "AuditAction">;
16
+ export type AuditAction = typeof AuditAction.Type;
17
+ export declare const AuditReasonCode: Schema.brand<Schema.NonEmptyString, "AuditReasonCode">;
18
+ export type AuditReasonCode = typeof AuditReasonCode.Type;
19
+ export declare const AuditOutcome: Schema.Literals<readonly ["success", "failure", "cancelled", "denied"]>;
20
+ export type AuditOutcome = typeof AuditOutcome.Type;
21
+ export declare const AuditActor: Schema.Union<readonly [Schema.Struct<{
22
+ readonly kind: Schema.Literal<"user">;
23
+ readonly id: Schema.brand<Schema.NonEmptyString, "AuditActorId">;
24
+ }>, Schema.Struct<{
25
+ readonly kind: Schema.Literal<"service">;
26
+ readonly id: Schema.brand<Schema.NonEmptyString, "AuditActorId">;
27
+ }>, Schema.Struct<{
28
+ readonly kind: Schema.Literal<"system">;
29
+ }>]>;
30
+ export type AuditActor = typeof AuditActor.Type;
31
+ export type AuditActorInput = {
32
+ readonly kind: "user";
33
+ readonly id: string;
34
+ } | {
35
+ readonly kind: "service";
36
+ readonly id: string;
37
+ } | {
38
+ readonly kind: "system";
39
+ };
40
+ export declare const AuditResource: Schema.Struct<{
41
+ readonly type: Schema.brand<Schema.NonEmptyString, "AuditResourceType">;
42
+ readonly id: Schema.brand<Schema.NonEmptyString, "AuditResourceId">;
43
+ }>;
44
+ export type AuditResource = typeof AuditResource.Type;
45
+ export declare const AuditContext: Schema.Struct<{
46
+ readonly action: Schema.brand<Schema.NonEmptyString, "AuditAction">;
47
+ readonly actor: Schema.Union<readonly [Schema.Struct<{
48
+ readonly kind: Schema.Literal<"user">;
49
+ readonly id: Schema.brand<Schema.NonEmptyString, "AuditActorId">;
50
+ }>, Schema.Struct<{
51
+ readonly kind: Schema.Literal<"service">;
52
+ readonly id: Schema.brand<Schema.NonEmptyString, "AuditActorId">;
53
+ }>, Schema.Struct<{
54
+ readonly kind: Schema.Literal<"system">;
55
+ }>]>;
56
+ readonly resourceType: Schema.brand<Schema.NonEmptyString, "AuditResourceType">;
57
+ readonly resourceId: Schema.brand<Schema.NonEmptyString, "AuditResourceId">;
58
+ readonly reasonCode: Schema.optionalKey<Schema.String>;
59
+ }>;
60
+ export type AuditContext = typeof AuditContext.Type;
61
+ export declare const AuditOccurredAt: Schema.brand<Schema.String, "AuditOccurredAt">;
62
+ export type AuditOccurredAt = typeof AuditOccurredAt.Type;
63
+ declare const AuditRecordFields: Schema.Struct<{
64
+ readonly schemaVersion: Schema.Literal<1>;
65
+ readonly recordId: Schema.brand<Schema.NonEmptyString, "AuditRecordId">;
66
+ readonly action: Schema.brand<Schema.NonEmptyString, "AuditAction">;
67
+ readonly actor: Schema.Union<readonly [Schema.Struct<{
68
+ readonly kind: Schema.Literal<"user">;
69
+ readonly id: Schema.brand<Schema.NonEmptyString, "AuditActorId">;
70
+ }>, Schema.Struct<{
71
+ readonly kind: Schema.Literal<"service">;
72
+ readonly id: Schema.brand<Schema.NonEmptyString, "AuditActorId">;
73
+ }>, Schema.Struct<{
74
+ readonly kind: Schema.Literal<"system">;
75
+ }>]>;
76
+ readonly resource: Schema.Struct<{
77
+ readonly type: Schema.brand<Schema.NonEmptyString, "AuditResourceType">;
78
+ readonly id: Schema.brand<Schema.NonEmptyString, "AuditResourceId">;
79
+ }>;
80
+ readonly outcome: Schema.Literals<readonly ["success", "failure", "cancelled", "denied"]>;
81
+ readonly reasonCode: Schema.Option<Schema.brand<Schema.NonEmptyString, "AuditReasonCode">>;
82
+ readonly tenantId: Schema.Option<Schema.brand<Schema.NonEmptyString, "AuditTenantId">>;
83
+ readonly occurredAt: Schema.brand<Schema.String, "AuditOccurredAt">;
84
+ readonly correlation: typeof CorrelationContext;
85
+ }>;
86
+ type AuditRecordFields = typeof AuditRecordFields.Type;
87
+ declare const parsedAuditRecordBrand: unique symbol;
88
+ export type AuditRecord = AuditRecordFields & {
89
+ readonly [parsedAuditRecordBrand]: true;
90
+ };
91
+ export type AuditRecordInput = {
92
+ readonly recordId: string;
93
+ readonly action: string;
94
+ readonly actor: AuditActorInput;
95
+ readonly resource: {
96
+ readonly id: string;
97
+ };
98
+ readonly outcome: AuditOutcome;
99
+ readonly reasonCode?: string | Option.Option<string>;
100
+ readonly tenantId?: string | Option.Option<string>;
101
+ readonly occurredAt: string;
102
+ readonly correlation?: CorrelationContext;
103
+ };
104
+ export declare const reparseAuditRecord: (record: {
105
+ readonly schemaVersion: 1;
106
+ readonly recordId: string & import("effect/Brand").Brand<"AuditRecordId">;
107
+ readonly action: string & import("effect/Brand").Brand<"AuditAction">;
108
+ readonly actor: {
109
+ readonly kind: "user";
110
+ readonly id: string & import("effect/Brand").Brand<"AuditActorId">;
111
+ } | {
112
+ readonly kind: "service";
113
+ readonly id: string & import("effect/Brand").Brand<"AuditActorId">;
114
+ } | {
115
+ readonly kind: "system";
116
+ };
117
+ readonly resource: {
118
+ readonly type: string & import("effect/Brand").Brand<"AuditResourceType">;
119
+ readonly id: string & import("effect/Brand").Brand<"AuditResourceId">;
120
+ };
121
+ readonly outcome: "cancelled" | "denied" | "failure" | "success";
122
+ readonly reasonCode: Option.Option<string & import("effect/Brand").Brand<"AuditReasonCode">>;
123
+ readonly tenantId: Option.Option<string & import("effect/Brand").Brand<"AuditTenantId">>;
124
+ readonly occurredAt: string & import("effect/Brand").Brand<"AuditOccurredAt">;
125
+ readonly correlation: CorrelationContext;
126
+ }) => Effect.Effect<AuditRecord, InvalidAuditRecord, never>;
127
+ export declare const parseAuditRecord: <Definition extends TelemetryContractInput>(contract: TelemetryContract<Definition>, input: AuditRecordInput) => Effect.Effect<AuditRecord, InvalidAuditRecord, never>;
128
+ export {};
@@ -0,0 +1,172 @@
1
+ import { Effect, Option, Predicate, Schema } from "effect";
2
+ import { CorrelationContext, CurrentCorrelation } from "../Correlation.js";
3
+ import { InvalidAuditRecord } from "./InvalidAuditRecord.js";
4
+ const isControlCharacterFree = (value) => {
5
+ for (const character of value) {
6
+ const codePoint = character.codePointAt(0);
7
+ if (codePoint !== undefined && (codePoint <= 31 || codePoint === 127))
8
+ return false;
9
+ }
10
+ return true;
11
+ };
12
+ const withoutControlCharacters = Schema.makeFilter(isControlCharacterFree, {
13
+ expected: "a value without control characters",
14
+ });
15
+ const boundedIdentifier = Schema.NonEmptyString.check(withoutControlCharacters, Schema.isMaxLength(128));
16
+ export const AuditRecordId = boundedIdentifier.pipe(Schema.brand("AuditRecordId"));
17
+ export const AuditTenantId = boundedIdentifier.pipe(Schema.brand("AuditTenantId"));
18
+ export const AuditActorId = boundedIdentifier.pipe(Schema.brand("AuditActorId"));
19
+ export const AuditResourceId = boundedIdentifier.pipe(Schema.brand("AuditResourceId"));
20
+ export const AuditResourceType = Schema.NonEmptyString.check(withoutControlCharacters, Schema.isMaxLength(64), Schema.isPattern(/^[a-z][a-z0-9_]*(?:\.[a-z][a-z0-9_]*)*$/)).pipe(Schema.brand("AuditResourceType"));
21
+ export const AuditAction = Schema.NonEmptyString.check(withoutControlCharacters, Schema.isMinLength(3), Schema.isMaxLength(128), Schema.isPattern(/^[a-z][a-z0-9_]*(?:\.[a-z][a-z0-9_]*)+$/)).pipe(Schema.brand("AuditAction"));
22
+ export const AuditReasonCode = Schema.NonEmptyString.check(withoutControlCharacters, Schema.isMaxLength(64), Schema.isPattern(/^[a-z][a-z0-9_]*(?:\.[a-z][a-z0-9_]*)*$/)).pipe(Schema.brand("AuditReasonCode"));
23
+ export const AuditOutcome = Schema.Literals(["success", "failure", "cancelled", "denied"]);
24
+ export const AuditActor = Schema.Union([
25
+ Schema.Struct({ kind: Schema.Literal("user"), id: AuditActorId }),
26
+ Schema.Struct({ kind: Schema.Literal("service"), id: AuditActorId }),
27
+ Schema.Struct({ kind: Schema.Literal("system") }),
28
+ ]);
29
+ export const AuditResource = Schema.Struct({
30
+ type: AuditResourceType,
31
+ id: AuditResourceId,
32
+ });
33
+ export const AuditContext = Schema.Struct({
34
+ action: AuditAction,
35
+ actor: AuditActor,
36
+ resourceType: AuditResourceType,
37
+ resourceId: AuditResourceId,
38
+ reasonCode: Schema.String.pipe(Schema.optionalKey),
39
+ });
40
+ const canonicalOccurredAtPattern = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
41
+ export const AuditOccurredAt = Schema.String.check(Schema.makeFilter((value) => canonicalOccurredAtPattern.test(value) &&
42
+ isControlCharacterFree(value) &&
43
+ Date.parse(value) >= 0 &&
44
+ new Date(value).toISOString() === value, { expected: "a canonical RFC 3339 UTC timestamp with millisecond precision" })).pipe(Schema.brand("AuditOccurredAt"));
45
+ const AuditRecordFields = Schema.Struct({
46
+ schemaVersion: Schema.Literal(1),
47
+ recordId: AuditRecordId,
48
+ action: AuditAction,
49
+ actor: AuditActor,
50
+ resource: AuditResource,
51
+ outcome: AuditOutcome,
52
+ reasonCode: Schema.Option(AuditReasonCode),
53
+ tenantId: Schema.Option(AuditTenantId),
54
+ occurredAt: AuditOccurredAt,
55
+ correlation: CorrelationContext,
56
+ });
57
+ const parsedAuditRecordBrand = Symbol("@equipe-tech/observability/ParsedAuditRecord");
58
+ const AuditRecordInputDocument = Schema.Struct({
59
+ recordId: Schema.Any,
60
+ action: Schema.Any,
61
+ actor: Schema.Any,
62
+ resource: Schema.Any,
63
+ outcome: Schema.Any,
64
+ reasonCode: Schema.optional(Schema.Any),
65
+ tenantId: Schema.optional(Schema.Any),
66
+ occurredAt: Schema.Any,
67
+ correlation: Schema.optional(Schema.Any),
68
+ });
69
+ const AuditResourceInputDocument = Schema.Struct({ id: Schema.Any });
70
+ const AuditOptionalStringInput = Schema.Union([
71
+ Schema.String,
72
+ Schema.Option(Schema.String),
73
+ Schema.Undefined,
74
+ ]);
75
+ const decodeAuditRecordInput = Schema.decodeUnknownEffect(AuditRecordInputDocument);
76
+ const decodeAuditResourceInput = Schema.decodeUnknownEffect(AuditResourceInputDocument);
77
+ const decodeOptionalStringInput = Schema.decodeUnknownEffect(AuditOptionalStringInput);
78
+ const decodeSchemaVersion = Schema.decodeUnknownEffect(Schema.Literal(1));
79
+ const decodeAction = Schema.decodeUnknownEffect(AuditAction);
80
+ const decodeRecordId = Schema.decodeUnknownEffect(AuditRecordId);
81
+ const decodeActor = Schema.decodeUnknownEffect(AuditActor);
82
+ const decodeResourceId = Schema.decodeUnknownEffect(AuditResourceId);
83
+ const decodeResourceType = Schema.decodeUnknownEffect(AuditResourceType);
84
+ const decodeOutcome = Schema.decodeUnknownEffect(AuditOutcome);
85
+ const decodeReasonCode = Schema.decodeUnknownEffect(AuditReasonCode);
86
+ const decodeTenantId = Schema.decodeUnknownEffect(AuditTenantId);
87
+ const decodeOccurredAt = Schema.decodeUnknownEffect(AuditOccurredAt);
88
+ const decodeCorrelation = Schema.decodeUnknownEffect(CorrelationContext);
89
+ const decodeReasonCodeOption = Schema.decodeUnknownEffect(Schema.Option(AuditReasonCode));
90
+ const decodeTenantIdOption = Schema.decodeUnknownEffect(Schema.Option(AuditTenantId));
91
+ const invalid = (code, message, field, action) => action === undefined
92
+ ? new InvalidAuditRecord({ code, message, field })
93
+ : new InvalidAuditRecord({ code, message, field, action });
94
+ const optionalString = (value) => value === undefined ? Option.none() : Predicate.isString(value) ? Option.some(value) : value;
95
+ export const reparseAuditRecord = Effect.fn("reparseAuditRecord")(function* (record) {
96
+ const invalidField = (field) => invalid("OBS_AUDIT_INVALID_FIELD", `Audit record field ${field} is invalid. Parse the record before committing it.`, field);
97
+ const schemaVersion = yield* decodeSchemaVersion(record.schemaVersion).pipe(Effect.mapError(() => invalidField("schemaVersion")));
98
+ const recordId = yield* decodeRecordId(record.recordId).pipe(Effect.mapError(() => invalidField("recordId")));
99
+ const action = yield* Schema.decodeUnknownEffect(AuditAction)(record.action).pipe(Effect.mapError(() => invalidField("action")));
100
+ const actor = yield* decodeActor(record.actor).pipe(Effect.mapError(() => invalidField("actor")));
101
+ const resource = yield* Schema.decodeUnknownEffect(AuditResource)(record.resource).pipe(Effect.mapError(() => invalidField("resource")));
102
+ const outcome = yield* decodeOutcome(record.outcome).pipe(Effect.mapError(() => invalidField("outcome")));
103
+ const reasonCode = yield* decodeReasonCodeOption(record.reasonCode).pipe(Effect.mapError(() => invalidField("reasonCode")));
104
+ const tenantId = yield* decodeTenantIdOption(record.tenantId).pipe(Effect.mapError(() => invalidField("tenantId")));
105
+ const occurredAt = yield* decodeOccurredAt(record.occurredAt).pipe(Effect.mapError(() => invalidField("occurredAt")));
106
+ const correlation = yield* decodeCorrelation(record.correlation).pipe(Effect.mapError(() => invalidField("correlation")));
107
+ const parsed = {
108
+ schemaVersion,
109
+ recordId,
110
+ action,
111
+ actor: Object.freeze(actor),
112
+ resource: Object.freeze(resource),
113
+ outcome,
114
+ reasonCode,
115
+ tenantId,
116
+ occurredAt,
117
+ correlation,
118
+ [parsedAuditRecordBrand]: true,
119
+ };
120
+ return Object.freeze(parsed);
121
+ });
122
+ export const parseAuditRecord = Effect.fn("parseAuditRecord")(function* (contract, input) {
123
+ const document = yield* decodeAuditRecordInput(input).pipe(Effect.mapError(() => invalid("OBS_AUDIT_INVALID_FIELD", "Audit record input is malformed. Provide every required audit field with its documented type.", "record")));
124
+ const parsedAction = yield* decodeAction(document.action).pipe(Effect.mapError(() => invalid("OBS_AUDIT_UNKNOWN_ACTION", "Audit action is malformed. Use a declared dotted lowercase action up to 128 characters.", "action")));
125
+ const action = contract.auditActionByName.get(parsedAction);
126
+ if (action === undefined) {
127
+ return yield* invalid("OBS_AUDIT_UNKNOWN_ACTION", "Audit action is not declared by the telemetry contract. Use a declared action.", "action", parsedAction);
128
+ }
129
+ const recordId = yield* decodeRecordId(document.recordId).pipe(Effect.mapError(() => invalid("OBS_AUDIT_INVALID_FIELD", "Audit record ID is invalid. Use 1 to 128 characters without control characters.", "recordId", parsedAction)));
130
+ const actor = yield* decodeActor(document.actor).pipe(Effect.mapError(() => invalid("OBS_AUDIT_INVALID_ACTOR", "Audit actor is invalid. Use a bounded user or service snapshot, or the system actor.", "actor", parsedAction)));
131
+ const resource = yield* decodeAuditResourceInput(document.resource).pipe(Effect.mapError(() => invalid("OBS_AUDIT_INVALID_RESOURCE", "Audit resource is malformed. Provide an object with a bounded ID.", "resource", parsedAction)));
132
+ const resourceId = yield* decodeResourceId(resource.id).pipe(Effect.mapError(() => invalid("OBS_AUDIT_INVALID_RESOURCE", "Audit resource ID is invalid. Use 1 to 128 characters without control characters.", "resource.id", parsedAction)));
133
+ const resourceType = yield* decodeResourceType(action.resourceType).pipe(Effect.orDie);
134
+ const outcome = yield* decodeOutcome(document.outcome).pipe(Effect.mapError(() => invalid("OBS_AUDIT_INVALID_OUTCOME", "Audit outcome is invalid. Use success, failure, cancelled, or denied.", "outcome", parsedAction)));
135
+ if (!action.allowedOutcomes.includes(outcome)) {
136
+ return yield* invalid("OBS_AUDIT_INVALID_OUTCOME", "Audit outcome is not declared for this action. Use an allowed outcome.", "outcome", parsedAction);
137
+ }
138
+ const reasonCodeInput = yield* decodeOptionalStringInput(document.reasonCode).pipe(Effect.mapError(() => invalid("OBS_AUDIT_UNKNOWN_REASON_CODE", "Audit reason code is malformed. Use a dotted lowercase code up to 64 characters.", "reasonCode", parsedAction)));
139
+ const rawReasonCode = optionalString(reasonCodeInput);
140
+ const reasonCode = yield* Option.match(rawReasonCode, {
141
+ onNone: () => Effect.succeed(Option.none()),
142
+ onSome: (value) => Effect.gen(function* () {
143
+ const parsed = yield* decodeReasonCode(value).pipe(Effect.mapError(() => invalid("OBS_AUDIT_UNKNOWN_REASON_CODE", "Audit reason code is malformed. Use a dotted lowercase code up to 64 characters.", "reasonCode", parsedAction)));
144
+ if (!action.reasonCodes.includes(parsed)) {
145
+ return yield* invalid("OBS_AUDIT_UNKNOWN_REASON_CODE", "Audit reason code is not declared for this action. Use a declared reason code or omit it.", "reasonCode", parsedAction);
146
+ }
147
+ return Option.some(parsed);
148
+ }),
149
+ });
150
+ const tenantIdInput = yield* decodeOptionalStringInput(document.tenantId).pipe(Effect.mapError(() => invalid("OBS_AUDIT_INVALID_FIELD", "Audit tenant ID is invalid. Use 1 to 128 characters without control characters.", "tenantId", parsedAction)));
151
+ const rawTenantId = optionalString(tenantIdInput);
152
+ const tenantId = yield* Option.match(rawTenantId, {
153
+ onNone: () => Effect.succeed(Option.none()),
154
+ onSome: (value) => decodeTenantId(value).pipe(Effect.map(Option.some), Effect.mapError(() => invalid("OBS_AUDIT_INVALID_FIELD", "Audit tenant ID is invalid. Use 1 to 128 characters without control characters.", "tenantId", parsedAction))),
155
+ });
156
+ const occurredAt = yield* decodeOccurredAt(document.occurredAt).pipe(Effect.mapError(() => invalid("OBS_AUDIT_INVALID_FIELD", "Audit occurrence time is invalid. Use an RFC 3339 UTC timestamp.", "occurredAt", parsedAction)));
157
+ const correlation = document.correlation === undefined
158
+ ? yield* CurrentCorrelation
159
+ : yield* decodeCorrelation(document.correlation).pipe(Effect.mapError(() => invalid("OBS_AUDIT_INVALID_FIELD", "Audit correlation is invalid. Use a canonical traced or untraced correlation context.", "correlation", parsedAction)));
160
+ return yield* reparseAuditRecord({
161
+ schemaVersion: 1,
162
+ recordId,
163
+ action: action.action,
164
+ actor,
165
+ resource: { type: resourceType, id: resourceId },
166
+ outcome,
167
+ reasonCode,
168
+ tenantId,
169
+ occurredAt,
170
+ correlation,
171
+ });
172
+ });
@@ -0,0 +1,11 @@
1
+ import type { AuditHash } from "./AuditDigest.js";
2
+ import type { AuditOccurredAt, AuditRecord } from "./AuditRecord.js";
3
+ declare const committedAuditRecordBrand: unique symbol;
4
+ export type CommittedAuditRecord = AuditRecord & {
5
+ readonly committedAt: AuditOccurredAt;
6
+ readonly ledgerHash: AuditHash;
7
+ readonly [committedAuditRecordBrand]: true;
8
+ };
9
+ export declare const sealCommittedAuditRecord: (record: AuditRecord, committedAt: AuditOccurredAt, ledgerHash: AuditHash) => CommittedAuditRecord;
10
+ export declare const isCommittedAuditRecord: (record: CommittedAuditRecord) => boolean;
11
+ export {};
@@ -0,0 +1,13 @@
1
+ const committedAuditRecordBrand = Symbol("CommittedAuditRecord");
2
+ const committedAuditRecords = new WeakSet();
3
+ export const sealCommittedAuditRecord = (record, committedAt, ledgerHash) => {
4
+ const committed = {
5
+ ...record,
6
+ committedAt,
7
+ ledgerHash,
8
+ [committedAuditRecordBrand]: true,
9
+ };
10
+ committedAuditRecords.add(committed);
11
+ return Object.freeze(committed);
12
+ };
13
+ export const isCommittedAuditRecord = (record) => committedAuditRecords.has(record);
@@ -0,0 +1,12 @@
1
+ import { Schema } from "effect";
2
+ export declare const AuditRecordErrorCode: Schema.Literals<readonly ["OBS_AUDIT_UNKNOWN_ACTION", "OBS_AUDIT_INVALID_ACTOR", "OBS_AUDIT_INVALID_RESOURCE", "OBS_AUDIT_INVALID_OUTCOME", "OBS_AUDIT_UNKNOWN_REASON_CODE", "OBS_AUDIT_INVALID_FIELD"]>;
3
+ export type AuditRecordErrorCode = typeof AuditRecordErrorCode.Type;
4
+ declare const InvalidAuditRecord_base: Schema.Class<InvalidAuditRecord, Schema.TaggedStruct<"InvalidAuditRecord", {
5
+ readonly code: Schema.Literals<readonly ["OBS_AUDIT_UNKNOWN_ACTION", "OBS_AUDIT_INVALID_ACTOR", "OBS_AUDIT_INVALID_RESOURCE", "OBS_AUDIT_INVALID_OUTCOME", "OBS_AUDIT_UNKNOWN_REASON_CODE", "OBS_AUDIT_INVALID_FIELD"]>;
6
+ readonly message: Schema.String;
7
+ readonly field: Schema.String;
8
+ readonly action: Schema.optionalKey<Schema.String>;
9
+ }>, import("effect/Cause").YieldableError>;
10
+ export declare class InvalidAuditRecord extends InvalidAuditRecord_base {
11
+ }
12
+ export {};
@@ -0,0 +1,16 @@
1
+ import { Schema } from "effect";
2
+ export const AuditRecordErrorCode = Schema.Literals([
3
+ "OBS_AUDIT_UNKNOWN_ACTION",
4
+ "OBS_AUDIT_INVALID_ACTOR",
5
+ "OBS_AUDIT_INVALID_RESOURCE",
6
+ "OBS_AUDIT_INVALID_OUTCOME",
7
+ "OBS_AUDIT_UNKNOWN_REASON_CODE",
8
+ "OBS_AUDIT_INVALID_FIELD",
9
+ ]);
10
+ export class InvalidAuditRecord extends Schema.TaggedError()("InvalidAuditRecord", {
11
+ code: AuditRecordErrorCode,
12
+ message: Schema.String,
13
+ field: Schema.String,
14
+ action: Schema.String.pipe(Schema.optionalKey),
15
+ }) {
16
+ }
@@ -0,0 +1,7 @@
1
+ export { AuditCommitDocument } from "./AuditCommitDocument.js";
2
+ export { AuditDigest, AuditHash, canonicalAuditPayload } from "./AuditDigest.js";
3
+ export { AuditOutbox, AuditOutboxClaimKey, AuditOutboxDocument, AuditOutboxFailure, drainAuditOutbox, type AuditOutboxDrainReport, type AuditOutboxEntry, type AuditOutboxSettlement, type AuditOutboxValue, } from "./AuditOutbox.js";
4
+ export { isCommittedAuditRecord } from "./CommittedAuditRecordInternal.js";
5
+ export { AuditPublisher, commitAuditRecord, recordAudit, unboundAuditPublisher, type AuditDropReason, type AuditPublisherService, type AuditPublishReasonCounts, type AuditPublishReceipt, type AuditPublishReport, type CommitAuditResult, type CommittedAuditRecord, type RecordAuditResult, } from "./AuditPublisher.js";
6
+ export { AuditAction, AuditActor, AuditActorId, AuditContext, AuditOccurredAt, AuditOutcome, AuditReasonCode, AuditRecordId, AuditResource, AuditResourceId, AuditResourceType, AuditTenantId, parseAuditRecord, type AuditActorInput, type AuditRecord, type AuditRecordInput, } from "./AuditRecord.js";
7
+ export { AuditRecordErrorCode, InvalidAuditRecord } from "./InvalidAuditRecord.js";
@@ -0,0 +1,7 @@
1
+ export { AuditCommitDocument } from "./AuditCommitDocument.js";
2
+ export { AuditDigest, AuditHash, canonicalAuditPayload } from "./AuditDigest.js";
3
+ export { AuditOutbox, AuditOutboxClaimKey, AuditOutboxDocument, AuditOutboxFailure, drainAuditOutbox, } from "./AuditOutbox.js";
4
+ export { isCommittedAuditRecord } from "./CommittedAuditRecordInternal.js";
5
+ export { AuditPublisher, commitAuditRecord, recordAudit, unboundAuditPublisher, } from "./AuditPublisher.js";
6
+ export { AuditAction, AuditActor, AuditActorId, AuditContext, AuditOccurredAt, AuditOutcome, AuditReasonCode, AuditRecordId, AuditResource, AuditResourceId, AuditResourceType, AuditTenantId, parseAuditRecord, } from "./AuditRecord.js";
7
+ export { AuditRecordErrorCode, InvalidAuditRecord } from "./InvalidAuditRecord.js";
@@ -1,17 +1,63 @@
1
1
  export type BrowserTelemetryClientFields = {
2
2
  readonly [field: string]: string | number | boolean;
3
3
  };
4
+ export type BrowserTelemetryClientError = {
5
+ readonly type: string;
6
+ readonly message: string;
7
+ readonly retryable: boolean;
8
+ };
9
+ export type BrowserTraceContext = {
10
+ readonly traceId: string;
11
+ readonly spanId: string;
12
+ };
4
13
  export type BrowserTelemetryClientEvent = {
5
14
  readonly id: string;
6
15
  readonly name: string;
7
16
  readonly occurredAt: number;
8
17
  readonly fields: BrowserTelemetryClientFields;
18
+ readonly error?: BrowserTelemetryClientError;
19
+ readonly trace?: BrowserTraceContext;
20
+ };
21
+ export type BrowserTelemetryClientSpan = BrowserTraceContext & {
22
+ readonly parentSpanId?: string;
23
+ readonly name: string;
24
+ readonly startedAt: number;
25
+ readonly endedAt: number;
26
+ readonly fields: BrowserTelemetryClientFields;
27
+ };
28
+ export type BrowserTelemetryClientMetric = {
29
+ readonly name: string;
30
+ readonly value: number;
31
+ readonly occurredAt: number;
32
+ readonly fields: BrowserTelemetryClientFields;
33
+ };
34
+ export type BrowserTraceHandle = {
35
+ readonly context: BrowserTraceContext;
36
+ readonly end: (fields?: BrowserTelemetryClientFields) => void;
37
+ };
38
+ export type BrowserCounter = {
39
+ readonly add: (value?: number, fields?: BrowserTelemetryClientFields) => void;
40
+ };
41
+ export type BrowserTelemetryDefectInput = {
42
+ readonly id?: string;
43
+ readonly name: string;
44
+ readonly error: BrowserTelemetryClientError;
45
+ readonly fields?: BrowserTelemetryClientFields;
46
+ };
47
+ export type BrowserTelemetryClientResource = {
48
+ readonly serviceName: string;
49
+ readonly serviceVersion: string;
50
+ readonly environment: string;
9
51
  };
10
52
  export type BrowserTelemetryClientBatch = {
11
- readonly version: 1;
53
+ readonly version: number;
54
+ readonly resource?: BrowserTelemetryClientResource;
12
55
  readonly events: ReadonlyArray<BrowserTelemetryClientEvent>;
56
+ readonly spans?: ReadonlyArray<BrowserTelemetryClientSpan>;
57
+ readonly metrics?: ReadonlyArray<BrowserTelemetryClientMetric>;
13
58
  };
14
59
  export type BrowserTelemetryClientTransport = (batch: BrowserTelemetryClientBatch, signal: AbortSignal) => Promise<void>;
60
+ export type BrowserTelemetryFieldTransform = (fields: BrowserTelemetryClientFields) => BrowserTelemetryClientFields;
15
61
  export type BrowserTelemetryClientConfig = {
16
62
  readonly disabled?: boolean;
17
63
  readonly endpoint?: string;
@@ -19,12 +65,23 @@ export type BrowserTelemetryClientConfig = {
19
65
  readonly maxQueueSize?: number;
20
66
  readonly flushIntervalMs?: number;
21
67
  readonly shutdownTimeoutMs?: number;
68
+ readonly metrics?: boolean;
69
+ readonly resource?: BrowserTelemetryClientResource;
22
70
  readonly transport?: BrowserTelemetryClientTransport;
71
+ readonly policy?: BrowserTelemetryFieldTransform;
23
72
  };
24
73
  export type BrowserTelemetryClient = {
25
- emit(name: string, fields?: BrowserTelemetryClientFields): void;
74
+ emit(name: string, fields?: BrowserTelemetryClientFields, trace?: BrowserTraceContext): void;
75
+ emitDefect(input: BrowserTelemetryDefectInput): void;
76
+ readonly traces: {
77
+ readonly startSpan: (name: string, fields?: BrowserTelemetryClientFields, parent?: BrowserTraceContext) => BrowserTraceHandle;
78
+ };
79
+ readonly metrics: {
80
+ readonly counter: (name: string) => BrowserCounter;
81
+ };
26
82
  flush(): Promise<void>;
27
83
  pending(): number;
84
+ dropped(): number;
28
85
  dispose(): Promise<void>;
29
86
  };
30
87
  export declare class BrowserTelemetryClientDeliveryError extends Error {
@@ -40,6 +97,7 @@ export declare class BrowserTelemetryClientShutdownError extends Error {
40
97
  readonly retryable = true;
41
98
  constructor(timeoutMs: number);
42
99
  }
100
+ export declare const browserBatchByteLength: (batch: BrowserTelemetryClientBatch) => number;
43
101
  export declare const normalizePositiveInteger: (value: number | undefined, fallback: number) => number;
44
102
  type BrowserClientEngineOptions = {
45
103
  readonly disabled: boolean;
@@ -47,12 +105,18 @@ type BrowserClientEngineOptions = {
47
105
  readonly maxQueueSize: number;
48
106
  readonly flushIntervalMs: number;
49
107
  readonly shutdownTimeoutMs: number;
108
+ readonly metrics: boolean;
109
+ readonly resource: BrowserTelemetryClientResource | undefined;
50
110
  readonly transport: BrowserTelemetryClientTransport;
111
+ readonly policy: BrowserTelemetryFieldTransform | undefined;
51
112
  readonly startTimer: boolean;
52
113
  };
53
114
  export declare class BrowserClientEngine implements BrowserTelemetryClient {
54
115
  private readonly options;
55
116
  private events;
117
+ private spans;
118
+ private metricPoints;
119
+ private activeSpans;
56
120
  private activeFlush;
57
121
  private activeDelivery;
58
122
  private readonly activeControllers;
@@ -61,13 +125,28 @@ export declare class BrowserClientEngine implements BrowserTelemetryClient {
61
125
  private timer;
62
126
  private droppedEvents;
63
127
  constructor(options: BrowserClientEngineOptions);
64
- emit(name: string, fields?: BrowserTelemetryClientFields): void;
128
+ readonly traces: {
129
+ startSpan: (name: string, fields?: BrowserTelemetryClientFields, parent?: BrowserTraceContext) => BrowserTraceHandle;
130
+ };
131
+ readonly metrics: {
132
+ counter: (name: string) => BrowserCounter;
133
+ };
134
+ emit(name: string, fields?: BrowserTelemetryClientFields, trace?: BrowserTraceContext): void;
135
+ emitDefect(input: BrowserTelemetryDefectInput): void;
136
+ private sanitizeFields;
137
+ private batchWithResource;
138
+ private deliveryBatch;
139
+ private enqueue;
140
+ private enqueueSpan;
141
+ private enqueueMetric;
142
+ private ensureQueueCapacity;
65
143
  flush(): Promise<void>;
66
144
  pending(): number;
67
145
  dropped(): number;
68
146
  dispose(): Promise<void>;
69
147
  private shutdown;
70
148
  private abandonActiveDelivery;
149
+ private dropPending;
71
150
  private flushQueued;
72
151
  }
73
152
  export declare const createBrowserTelemetryClient: (config?: BrowserTelemetryClientConfig) => BrowserTelemetryClient;