@unifyplane/logsdk 0.1.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.
Files changed (170) hide show
  1. package/README.md +18 -0
  2. package/contracts/repo.capabilities.json +12 -0
  3. package/contracts/repo.runtime.json +49 -0
  4. package/contracts/schemas/repo/repo.runtime.v1.schema.json +134 -0
  5. package/dist/core/clock.d.ts +3 -0
  6. package/dist/core/clock.d.ts.map +1 -0
  7. package/dist/core/clock.js +21 -0
  8. package/dist/core/clock.js.map +1 -0
  9. package/dist/core/context.d.ts +10 -0
  10. package/dist/core/context.d.ts.map +1 -0
  11. package/dist/core/context.js +100 -0
  12. package/dist/core/context.js.map +1 -0
  13. package/dist/core/fanout.d.ts +4 -0
  14. package/dist/core/fanout.d.ts.map +1 -0
  15. package/dist/core/fanout.js +32 -0
  16. package/dist/core/fanout.js.map +1 -0
  17. package/dist/core/ids.d.ts +6 -0
  18. package/dist/core/ids.d.ts.map +1 -0
  19. package/dist/core/ids.js +27 -0
  20. package/dist/core/ids.js.map +1 -0
  21. package/dist/core/message_constraints.d.ts +4 -0
  22. package/dist/core/message_constraints.d.ts.map +1 -0
  23. package/dist/core/message_constraints.js +53 -0
  24. package/dist/core/message_constraints.js.map +1 -0
  25. package/dist/core/outcomes.d.ts +5 -0
  26. package/dist/core/outcomes.d.ts.map +1 -0
  27. package/dist/core/outcomes.js +4 -0
  28. package/dist/core/outcomes.js.map +1 -0
  29. package/dist/core/record_builder.d.ts +34 -0
  30. package/dist/core/record_builder.d.ts.map +1 -0
  31. package/dist/core/record_builder.js +188 -0
  32. package/dist/core/record_builder.js.map +1 -0
  33. package/dist/core/spool.d.ts +4 -0
  34. package/dist/core/spool.d.ts.map +1 -0
  35. package/dist/core/spool.js +31 -0
  36. package/dist/core/spool.js.map +1 -0
  37. package/dist/core/types.d.ts +33 -0
  38. package/dist/core/types.d.ts.map +1 -0
  39. package/dist/core/types.js +4 -0
  40. package/dist/core/types.js.map +1 -0
  41. package/dist/esm/core/clock.js +21 -0
  42. package/dist/esm/core/clock.js.map +1 -0
  43. package/dist/esm/core/context.js +100 -0
  44. package/dist/esm/core/context.js.map +1 -0
  45. package/dist/esm/core/fanout.js +32 -0
  46. package/dist/esm/core/fanout.js.map +1 -0
  47. package/dist/esm/core/ids.js +27 -0
  48. package/dist/esm/core/ids.js.map +1 -0
  49. package/dist/esm/core/message_constraints.js +53 -0
  50. package/dist/esm/core/message_constraints.js.map +1 -0
  51. package/dist/esm/core/outcomes.js +4 -0
  52. package/dist/esm/core/outcomes.js.map +1 -0
  53. package/dist/esm/core/record_builder.js +188 -0
  54. package/dist/esm/core/record_builder.js.map +1 -0
  55. package/dist/esm/core/spool.js +31 -0
  56. package/dist/esm/core/spool.js.map +1 -0
  57. package/dist/esm/core/types.js +4 -0
  58. package/dist/esm/core/types.js.map +1 -0
  59. package/dist/esm/index.js +52 -0
  60. package/dist/esm/index.js.map +1 -0
  61. package/dist/esm/sinks/file_ndjson.js +29 -0
  62. package/dist/esm/sinks/file_ndjson.js.map +1 -0
  63. package/dist/esm/sinks/file_ndjson_sink.js +36 -0
  64. package/dist/esm/sinks/file_ndjson_sink.js.map +1 -0
  65. package/dist/esm/sinks/sink_types.js +2 -0
  66. package/dist/esm/sinks/sink_types.js.map +1 -0
  67. package/dist/esm/sinks/stdout_sink.js +15 -0
  68. package/dist/esm/sinks/stdout_sink.js.map +1 -0
  69. package/dist/esm/validate/api_surface_guard.js +63 -0
  70. package/dist/esm/validate/api_surface_guard.js.map +1 -0
  71. package/dist/esm/validate/noncompliance.js +17 -0
  72. package/dist/esm/validate/noncompliance.js.map +1 -0
  73. package/dist/esm/validate/schema_guard.js +151 -0
  74. package/dist/esm/validate/schema_guard.js.map +1 -0
  75. package/dist/index.d.ts +26 -0
  76. package/dist/index.d.ts.map +1 -0
  77. package/dist/index.js +52 -0
  78. package/dist/index.js.map +1 -0
  79. package/dist/sinks/file_ndjson.d.ts +18 -0
  80. package/dist/sinks/file_ndjson.d.ts.map +1 -0
  81. package/dist/sinks/file_ndjson.js +29 -0
  82. package/dist/sinks/file_ndjson.js.map +1 -0
  83. package/dist/sinks/file_ndjson_sink.d.ts +7 -0
  84. package/dist/sinks/file_ndjson_sink.d.ts.map +1 -0
  85. package/dist/sinks/file_ndjson_sink.js +36 -0
  86. package/dist/sinks/file_ndjson_sink.js.map +1 -0
  87. package/dist/sinks/sink_types.d.ts +12 -0
  88. package/dist/sinks/sink_types.d.ts.map +1 -0
  89. package/dist/sinks/sink_types.js +2 -0
  90. package/dist/sinks/sink_types.js.map +1 -0
  91. package/dist/sinks/stdout_sink.d.ts +6 -0
  92. package/dist/sinks/stdout_sink.d.ts.map +1 -0
  93. package/dist/sinks/stdout_sink.js +15 -0
  94. package/dist/sinks/stdout_sink.js.map +1 -0
  95. package/dist/types/core/clock.d.ts +3 -0
  96. package/dist/types/core/clock.d.ts.map +1 -0
  97. package/dist/types/core/context.d.ts +10 -0
  98. package/dist/types/core/context.d.ts.map +1 -0
  99. package/dist/types/core/fanout.d.ts +4 -0
  100. package/dist/types/core/fanout.d.ts.map +1 -0
  101. package/dist/types/core/ids.d.ts +6 -0
  102. package/dist/types/core/ids.d.ts.map +1 -0
  103. package/dist/types/core/message_constraints.d.ts +4 -0
  104. package/dist/types/core/message_constraints.d.ts.map +1 -0
  105. package/dist/types/core/outcomes.d.ts +5 -0
  106. package/dist/types/core/outcomes.d.ts.map +1 -0
  107. package/dist/types/core/record_builder.d.ts +34 -0
  108. package/dist/types/core/record_builder.d.ts.map +1 -0
  109. package/dist/types/core/spool.d.ts +4 -0
  110. package/dist/types/core/spool.d.ts.map +1 -0
  111. package/dist/types/core/types.d.ts +33 -0
  112. package/dist/types/core/types.d.ts.map +1 -0
  113. package/dist/types/index.d.ts +26 -0
  114. package/dist/types/index.d.ts.map +1 -0
  115. package/dist/types/sinks/file_ndjson.d.ts +18 -0
  116. package/dist/types/sinks/file_ndjson.d.ts.map +1 -0
  117. package/dist/types/sinks/file_ndjson_sink.d.ts +7 -0
  118. package/dist/types/sinks/file_ndjson_sink.d.ts.map +1 -0
  119. package/dist/types/sinks/sink_types.d.ts +12 -0
  120. package/dist/types/sinks/sink_types.d.ts.map +1 -0
  121. package/dist/types/sinks/stdout_sink.d.ts +6 -0
  122. package/dist/types/sinks/stdout_sink.d.ts.map +1 -0
  123. package/dist/types/validate/api_surface_guard.d.ts +2 -0
  124. package/dist/types/validate/api_surface_guard.d.ts.map +1 -0
  125. package/dist/types/validate/noncompliance.d.ts +15 -0
  126. package/dist/types/validate/noncompliance.d.ts.map +1 -0
  127. package/dist/types/validate/schema_guard.d.ts +5 -0
  128. package/dist/types/validate/schema_guard.d.ts.map +1 -0
  129. package/dist/validate/api_surface_guard.d.ts +2 -0
  130. package/dist/validate/api_surface_guard.d.ts.map +1 -0
  131. package/dist/validate/api_surface_guard.js +63 -0
  132. package/dist/validate/api_surface_guard.js.map +1 -0
  133. package/dist/validate/noncompliance.d.ts +15 -0
  134. package/dist/validate/noncompliance.d.ts.map +1 -0
  135. package/dist/validate/noncompliance.js +17 -0
  136. package/dist/validate/noncompliance.js.map +1 -0
  137. package/dist/validate/schema_guard.d.ts +5 -0
  138. package/dist/validate/schema_guard.d.ts.map +1 -0
  139. package/dist/validate/schema_guard.js +151 -0
  140. package/dist/validate/schema_guard.js.map +1 -0
  141. package/evidence/audit/llm/llm_audit_report_2026-01-25T15-11-32Z.json +30 -0
  142. package/evidence/audit/llm/llm_audit_report_2026-01-25T15-53-20Z.json +154 -0
  143. package/evidence/audit/llm/llm_audit_report_2026-01-25T16-14-52Z.json +130 -0
  144. package/evidence/audit/llm/llm_audit_report_2026-01-25T16-15-42Z.json +152 -0
  145. package/evidence/audit/llm/llm_audit_report_2026-01-25T16-17-39Z.json +152 -0
  146. package/evidence/audit/llm/llm_audit_report_2026-01-25T16-18-51Z.json +152 -0
  147. package/evidence/audit/llm/llm_audit_report_2026-01-25T16-19-50Z.json +152 -0
  148. package/evidence/audit/llm/llm_audit_report_2026-01-25T16-20-36Z.json +152 -0
  149. package/evidence/audit/llm/llm_audit_report_2026-01-25T23-22-43Z.json +170 -0
  150. package/evidence/audit/llm/llm_audit_report_2026-01-25T23-39-03Z.json +157 -0
  151. package/filestructure.output.txt +73 -0
  152. package/package.json +16 -0
  153. package/src/core/clock.ts +25 -0
  154. package/src/core/context.ts +142 -0
  155. package/src/core/fanout.ts +38 -0
  156. package/src/core/ids.ts +35 -0
  157. package/src/core/message_constraints.ts +66 -0
  158. package/src/core/outcomes.ts +5 -0
  159. package/src/core/record_builder.ts +269 -0
  160. package/src/core/spool.ts +41 -0
  161. package/src/core/types.ts +56 -0
  162. package/src/index.ts +105 -0
  163. package/src/sinks/file_ndjson.ts +42 -0
  164. package/src/sinks/file_ndjson_sink.ts +45 -0
  165. package/src/sinks/sink_types.ts +15 -0
  166. package/src/sinks/stdout_sink.ts +20 -0
  167. package/src/validate/api_surface_guard.ts +106 -0
  168. package/src/validate/noncompliance.ts +33 -0
  169. package/src/validate/schema_guard.ts +242 -0
  170. package/unifyplane-logsdk-0.1.0.tgz +0 -0
@@ -0,0 +1,188 @@
1
+ /// <reference path="../crypto-shim.d.ts" />
2
+ import { createHash, randomUUID } from "crypto";
3
+ import { getContextHash, getContextVersion } from "./context.js";
4
+ import { monotonicNow } from "./clock.js";
5
+ import { assertValidMessage, MESSAGE_MAX_LENGTH } from "./message_constraints.js";
6
+ const RECORD_VERSION = "log.step.v1";
7
+ const HASH_ALGORITHM = "sha256";
8
+ export const message_constraints = {
9
+ maxLength: MESSAGE_MAX_LENGTH,
10
+ validate: assertValidMessage,
11
+ };
12
+ export function buildStepRecord(message, sequence, system, overrides = {}) {
13
+ const validatedMessage = message_constraints.validate(message);
14
+ validateSequence(sequence);
15
+ validateSystemOwnership(system);
16
+ const contextHash = getContextHash();
17
+ const contextVersion = getContextVersion();
18
+ const recordId = overrides.record_id ?? createRecordId();
19
+ const timestampUtc = overrides.timestamp_utc ?? new Date().toISOString();
20
+ const monotonicTime = overrides.monotonic_time ?? monotonicNow();
21
+ const baseRecord = {
22
+ record_version: RECORD_VERSION,
23
+ record_id: recordId,
24
+ sequence,
25
+ timestamp_utc: timestampUtc,
26
+ monotonic_time: monotonicTime,
27
+ institution: system.institution,
28
+ system_name: system.system_name,
29
+ system_type: system.system_type,
30
+ environment: system.environment,
31
+ system_version: system.system_version,
32
+ message: validatedMessage,
33
+ context_hash: contextHash,
34
+ context_version: contextVersion,
35
+ };
36
+ setOptionalField(baseRecord, "instance_id", system.instance_id);
37
+ setOptionalField(baseRecord, "trace_id", overrides.trace_id);
38
+ setOptionalField(baseRecord, "span_id", overrides.span_id);
39
+ setOptionalField(baseRecord, "parent_step_id", overrides.parent_step_id);
40
+ setOptionalField(baseRecord, "surface_type", overrides.surface_type);
41
+ setOptionalField(baseRecord, "surface_name", overrides.surface_name);
42
+ setOptionalField(baseRecord, "surface_instance", overrides.surface_instance);
43
+ setOptionalField(baseRecord, "source_file", overrides.source_file);
44
+ setOptionalField(baseRecord, "source_module", overrides.source_module);
45
+ setOptionalField(baseRecord, "source_function", overrides.source_function);
46
+ setOptionalField(baseRecord, "source_line", overrides.source_line);
47
+ setOptionalField(baseRecord, "message_code", overrides.message_code);
48
+ setOptionalField(baseRecord, "evidence_refs", overrides.evidence_refs);
49
+ const canonical = stableStringify(normalizeJsonValueOrdered(canonicalizeForHash(baseRecord), "$"));
50
+ const recordHash = createHash(HASH_ALGORITHM).update(canonical).digest("hex");
51
+ const record = {
52
+ ...baseRecord,
53
+ record_hash: recordHash,
54
+ hash_algorithm: HASH_ALGORITHM,
55
+ };
56
+ return deepFreeze(record);
57
+ }
58
+ function validateSequence(sequence) {
59
+ if (!Number.isInteger(sequence) || sequence < 0) {
60
+ throw new Error("Sequence must be a non-negative integer");
61
+ }
62
+ }
63
+ function validateSystemOwnership(system) {
64
+ const requiredFields = [
65
+ "institution",
66
+ "system_name",
67
+ "system_type",
68
+ "environment",
69
+ "system_version",
70
+ ];
71
+ for (const field of requiredFields) {
72
+ const value = system[field];
73
+ if (typeof value !== "string" || value.trim().length === 0) {
74
+ throw new Error(`Missing required system field: ${field}`);
75
+ }
76
+ }
77
+ if (system.instance_id !== undefined && typeof system.instance_id !== "string") {
78
+ throw new Error("instance_id must be a string when provided");
79
+ }
80
+ }
81
+ function createRecordId() {
82
+ return typeof randomUUID === "function"
83
+ ? randomUUID()
84
+ : createHash("sha256")
85
+ .update(`${Date.now()}-${Math.random()}`)
86
+ .digest("hex");
87
+ }
88
+ function deepFreeze(value) {
89
+ if (!value || typeof value !== "object") {
90
+ return value;
91
+ }
92
+ if (Object.isFrozen(value)) {
93
+ return value;
94
+ }
95
+ Object.freeze(value);
96
+ for (const key of Object.keys(value)) {
97
+ const child = value[key];
98
+ deepFreeze(child);
99
+ }
100
+ if (Array.isArray(value)) {
101
+ for (const item of value) {
102
+ deepFreeze(item);
103
+ }
104
+ }
105
+ return value;
106
+ }
107
+ function canonicalizeForHash(record) {
108
+ const ordered = {};
109
+ for (const field of HASH_FIELD_ORDER) {
110
+ const value = record[field];
111
+ if (value !== undefined) {
112
+ ordered[field] = normalizeJsonValueOrdered(value, `${String(field)}`);
113
+ }
114
+ }
115
+ return ordered;
116
+ }
117
+ function normalizeJsonValueOrdered(value, path) {
118
+ if (value === null ||
119
+ typeof value === "string" ||
120
+ typeof value === "number" ||
121
+ typeof value === "boolean") {
122
+ return value;
123
+ }
124
+ if (typeof value === "bigint") {
125
+ return value.toString();
126
+ }
127
+ if (value instanceof Date) {
128
+ return value.toISOString();
129
+ }
130
+ if (Array.isArray(value)) {
131
+ return value.map((item, index) => normalizeJsonValueOrdered(item, `${path}[${index}]`));
132
+ }
133
+ if (typeof value === "object") {
134
+ const proto = Object.getPrototypeOf(value);
135
+ if (proto !== Object.prototype && proto !== null) {
136
+ throw new Error(`Unsupported object at ${path}`);
137
+ }
138
+ const obj = value;
139
+ const result = {};
140
+ const keys = Object.keys(obj);
141
+ for (const key of keys) {
142
+ const next = obj[key];
143
+ if (next === undefined) {
144
+ throw new Error(`Undefined value at ${path}.${key}`);
145
+ }
146
+ result[key] = normalizeJsonValueOrdered(next, `${path}.${key}`);
147
+ }
148
+ return result;
149
+ }
150
+ throw new Error(`Unsupported type at ${path}`);
151
+ }
152
+ function stableStringify(value) {
153
+ return JSON.stringify(value);
154
+ }
155
+ function setOptionalField(record, key, value) {
156
+ if (value !== undefined) {
157
+ record[key] = value;
158
+ }
159
+ }
160
+ const HASH_FIELD_ORDER = [
161
+ "record_version",
162
+ "record_id",
163
+ "sequence",
164
+ "timestamp_utc",
165
+ "monotonic_time",
166
+ "institution",
167
+ "system_name",
168
+ "system_type",
169
+ "environment",
170
+ "system_version",
171
+ "instance_id",
172
+ "trace_id",
173
+ "span_id",
174
+ "parent_step_id",
175
+ "surface_type",
176
+ "surface_name",
177
+ "surface_instance",
178
+ "source_file",
179
+ "source_module",
180
+ "source_function",
181
+ "source_line",
182
+ "message",
183
+ "message_code",
184
+ "context_hash",
185
+ "context_version",
186
+ "evidence_refs",
187
+ ];
188
+ //# sourceMappingURL=record_builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"record_builder.js","sourceRoot":"","sources":["../../../src/core/record_builder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /// <reference path="../fs-shim.d.ts" />
2
+ import { promises as fs } from "fs";
3
+ import os from "os";
4
+ import path from "path";
5
+ const DEFAULT_SPOOL_NAME = "logsdk-emergency-spool.ndjson";
6
+ function getSpoolPath() {
7
+ return (process.env.LOGSDK_EMERGENCY_SPOOL_PATH ??
8
+ path.join(os.tmpdir(), DEFAULT_SPOOL_NAME));
9
+ }
10
+ export function getEmergencySpoolPath() {
11
+ return getSpoolPath();
12
+ }
13
+ export async function writeEmergencySpool(record) {
14
+ const spoolPath = getSpoolPath();
15
+ const payload = `${JSON.stringify(record)}\n`;
16
+ const handle = await fs.open(spoolPath, "a");
17
+ try {
18
+ const result = await handle.write(payload, undefined, "utf8");
19
+ if (!result || typeof result.bytesWritten !== "number") {
20
+ throw new Error("Emergency spool write did not report bytes.");
21
+ }
22
+ if (result.bytesWritten !== payload.length) {
23
+ throw new Error("Emergency spool partial write detected.");
24
+ }
25
+ await handle.sync();
26
+ }
27
+ finally {
28
+ await handle.close();
29
+ }
30
+ }
31
+ //# sourceMappingURL=spool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spool.js","sourceRoot":"","sources":["../../../src/core/spool.ts"],"names":[],"mappings":"AAAA,wCAAwC;AAExC,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAGxB,MAAM,kBAAkB,GAAG,+BAA+B,CAAC;AAE3D,SAAS,YAAY;IACnB,OAAO,CACL,OAAO,CAAC,GAAG,CAAC,2BAA2B;QACvC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,kBAAkB,CAAC,CAC3C,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,qBAAqB;IACnC,OAAO,YAAY,EAAE,CAAC;AACxB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,MAAkB;IAC1D,MAAM,SAAS,GAAG,YAAY,EAAE,CAAC;IACjC,MAAM,OAAO,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC;IAC9C,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IAE7C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;QAE9D,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,CAAC,YAAY,KAAK,QAAQ,EAAE,CAAC;YACvD,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACjE,CAAC;QAED,IAAI,MAAM,CAAC,YAAY,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC;YAC3C,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;QAC7D,CAAC;QAED,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;IACtB,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;AACH,CAAC"}
@@ -0,0 +1,4 @@
1
+ // Internal core types for LogSDK v1.0
2
+ // Types only: no runtime logic.
3
+ export {};
4
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/core/types.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,gCAAgC"}
@@ -0,0 +1,52 @@
1
+ import { initContext } from "./core/context.js";
2
+ import { createIdGenerator } from "./core/ids.js";
3
+ import { buildStepRecord } from "./core/record_builder.js";
4
+ import { assertValidMessage } from "./core/message_constraints.js";
5
+ import { fanout } from "./core/fanout.js";
6
+ import { assertApiSurface } from "./validate/api_surface_guard.js";
7
+ import { assertStepRecord } from "./validate/schema_guard.js";
8
+ import { AUTHORITATIVE_FAILURE_SWALLOWED, CONTEXT_INJECTION_VIOLATION, PAYLOAD_EMBEDDING_VIOLATION, NonComplianceError, } from "./validate/noncompliance.js";
9
+ export function initLogSDK(config) {
10
+ initContext(config.context);
11
+ const idGenerator = createIdGenerator(config.system.instance_id);
12
+ const sinks = [...config.sinks];
13
+ const api = {
14
+ async step(message) {
15
+ if (typeof message !== "string") {
16
+ if (message && typeof message === "object") {
17
+ throw new NonComplianceError(CONTEXT_INJECTION_VIOLATION, "Per-step context injection is not allowed.");
18
+ }
19
+ throw new NonComplianceError(PAYLOAD_EMBEDDING_VIOLATION, "Message must be a string.");
20
+ }
21
+ try {
22
+ assertValidMessage(message);
23
+ }
24
+ catch (error) {
25
+ throw new NonComplianceError(PAYLOAD_EMBEDDING_VIOLATION, error instanceof Error ? error.message : "Invalid message content.");
26
+ }
27
+ const record = buildStepRecord(message, idGenerator.nextSequence(), config.system, {
28
+ record_id: idGenerator.nextRecordId(),
29
+ });
30
+ assertStepRecord(record);
31
+ const outcome = await fanout(record, sinks);
32
+ if (outcome === "FAILED") {
33
+ throw new NonComplianceError(AUTHORITATIVE_FAILURE_SWALLOWED, "Authoritative sink failed to emit.");
34
+ }
35
+ },
36
+ async flush() {
37
+ for (const entry of sinks) {
38
+ if (entry.sink.flush) {
39
+ await entry.sink.flush();
40
+ }
41
+ }
42
+ },
43
+ };
44
+ assertApiSurface(api);
45
+ return api;
46
+ }
47
+ export function createLogger(config) {
48
+ return initLogSDK(config);
49
+ }
50
+ export { fileNdjsonSink } from "./sinks/file_ndjson.js";
51
+ export { authoritativeNdjsonSink } from "./sinks/file_ndjson.js";
52
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,eAAe,EAAmB,MAAM,0BAA0B,CAAC;AAC5E,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EACL,+BAA+B,EAC/B,2BAA2B,EAC3B,2BAA2B,EAC3B,kBAAkB,GACnB,MAAM,6BAA6B,CAAC;AA4BrC,MAAM,UAAU,UAAU,CAAC,MAAoB;IAC7C,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAE5B,MAAM,WAAW,GAAG,iBAAiB,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IACjE,MAAM,KAAK,GAAG,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAEhC,MAAM,GAAG,GAAW;QAClB,KAAK,CAAC,IAAI,CAAC,OAAe;YACxB,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;gBAChC,IAAI,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;oBAC3C,MAAM,IAAI,kBAAkB,CAC1B,2BAA2B,EAC3B,4CAA4C,CAC7C,CAAC;gBACJ,CAAC;gBAED,MAAM,IAAI,kBAAkB,CAC1B,2BAA2B,EAC3B,2BAA2B,CAC5B,CAAC;YACJ,CAAC;YAED,IAAI,CAAC;gBACH,kBAAkB,CAAC,OAAO,CAAC,CAAC;YAC9B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,IAAI,kBAAkB,CAC1B,2BAA2B,EAC3B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,0BAA0B,CACpE,CAAC;YACJ,CAAC;YAED,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,EAAE,WAAW,CAAC,YAAY,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE;gBACjF,SAAS,EAAE,WAAW,CAAC,YAAY,EAAE;aACtC,CAAC,CAAC;YAEH,gBAAgB,CAAC,MAAM,CAAC,CAAC;YAEzB,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YAC5C,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;gBACzB,MAAM,IAAI,kBAAkB,CAC1B,+BAA+B,EAC/B,oCAAoC,CACrC,CAAC;YACJ,CAAC;QACH,CAAC;QACD,KAAK,CAAC,KAAK;YACT,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;gBAC1B,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;oBACrB,MAAM,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;gBAC3B,CAAC;YACH,CAAC;QACH,CAAC;KACF,CAAC;IAEF,gBAAgB,CAAC,GAAG,CAAC,CAAC;IACtB,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAoB;IAC/C,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC;AAC5B,CAAC;AAED,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,29 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ export function fileNdjsonSink(pathOrOptions) {
4
+ const p = typeof pathOrOptions === "string" ? pathOrOptions : pathOrOptions.path;
5
+ const dir = path.dirname(p);
6
+ if (!fs.existsSync(dir)) {
7
+ fs.mkdirSync(dir, { recursive: true });
8
+ }
9
+ const sink = {
10
+ emit(record) {
11
+ fs.appendFileSync(p, JSON.stringify(record) + "\n", { encoding: "utf8" });
12
+ },
13
+ };
14
+ return { sink, sinkClass: "observability" };
15
+ }
16
+ export function authoritativeNdjsonSink(pathOrOptions) {
17
+ const p = typeof pathOrOptions === "string" ? pathOrOptions : pathOrOptions.path;
18
+ const dir = path.dirname(p);
19
+ if (!fs.existsSync(dir)) {
20
+ fs.mkdirSync(dir, { recursive: true });
21
+ }
22
+ const sink = {
23
+ emit(record) {
24
+ fs.appendFileSync(p, JSON.stringify(record) + "\n", { encoding: "utf8" });
25
+ },
26
+ };
27
+ return { sink, sinkClass: "authoritative" };
28
+ }
29
+ //# sourceMappingURL=file_ndjson.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file_ndjson.js","sourceRoot":"","sources":["../../../src/sinks/file_ndjson.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAexB,MAAM,UAAU,cAAc,CAAC,aAAwC;IACrE,MAAM,CAAC,GAAG,OAAO,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC;IACjF,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAC5B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,CAAC;IACD,MAAM,IAAI,GAAS;QACjB,IAAI,CAAC,MAA4B;YAC/B,EAAE,CAAC,cAAc,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;QAC5E,CAAC;KACF,CAAC;IACF,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC;AAC9C,CAAC;AACD,MAAM,UAAU,uBAAuB,CAAC,aAAwC;IAC9E,MAAM,CAAC,GAAG,OAAO,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC;IACjF,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAC5B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,CAAC;IACD,MAAM,IAAI,GAAS;QACjB,IAAI,CAAC,MAA4B;YAC/B,EAAE,CAAC,cAAc,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;QAC5E,CAAC;KACF,CAAC;IACF,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC;AAC9C,CAAC"}
@@ -0,0 +1,36 @@
1
+ /// <reference path="../fs-shim.d.ts" />
2
+ import { promises as fs } from "fs";
3
+ export function createFileNdjsonSink(filePath) {
4
+ let closed = false;
5
+ return {
6
+ async emit(record) {
7
+ if (closed) {
8
+ throw new Error("File NDJSON sink is closed.");
9
+ }
10
+ const line = JSON.stringify(record);
11
+ const payload = `${line}\n`;
12
+ const handle = await fs.open(filePath, "a");
13
+ try {
14
+ const result = await handle.write(payload, undefined, "utf8");
15
+ if (!result || typeof result.bytesWritten !== "number") {
16
+ throw new Error("File NDJSON sink write did not report bytes.");
17
+ }
18
+ if (result.bytesWritten !== payload.length) {
19
+ throw new Error("File NDJSON sink partial write detected.");
20
+ }
21
+ await handle.sync();
22
+ }
23
+ catch (error) {
24
+ const message = error instanceof Error ? error.message : String(error);
25
+ throw new Error(`File NDJSON sink write failed: ${message}`);
26
+ }
27
+ finally {
28
+ await handle.close();
29
+ }
30
+ },
31
+ async close() {
32
+ closed = true;
33
+ },
34
+ };
35
+ }
36
+ //# sourceMappingURL=file_ndjson_sink.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file_ndjson_sink.js","sourceRoot":"","sources":["../../../src/sinks/file_ndjson_sink.ts"],"names":[],"mappings":"AAAA,wCAAwC;AAExC,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,IAAI,CAAC;AAQpC,MAAM,UAAU,oBAAoB,CAAC,QAAgB;IACnD,IAAI,MAAM,GAAG,KAAK,CAAC;IAEnB,OAAO;QACL,KAAK,CAAC,IAAI,CAAC,MAAkB;YAC3B,IAAI,MAAM,EAAE,CAAC;gBACX,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;YACjD,CAAC;YAED,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;YACpC,MAAM,OAAO,GAAG,GAAG,IAAI,IAAI,CAAC;YAC5B,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;YAE5C,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;gBAC9D,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,CAAC,YAAY,KAAK,QAAQ,EAAE,CAAC;oBACvD,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;gBAClE,CAAC;gBAED,IAAI,MAAM,CAAC,YAAY,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC;oBAC3C,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;gBAC9D,CAAC;gBACD,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;YACtB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACvE,MAAM,IAAI,KAAK,CAAC,kCAAkC,OAAO,EAAE,CAAC,CAAC;YAC/D,CAAC;oBAAS,CAAC;gBACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;YACvB,CAAC;QACH,CAAC;QACD,KAAK,CAAC,KAAK;YACT,MAAM,GAAG,IAAI,CAAC;QAChB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=sink_types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sink_types.js","sourceRoot":"","sources":["../../../src/sinks/sink_types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,15 @@
1
+ /// <reference path="../process-shim.d.ts" />
2
+ export function createStdoutSink() {
3
+ return {
4
+ async emit(record) {
5
+ try {
6
+ const line = JSON.stringify(record);
7
+ process.stdout.write(`${line}\n`);
8
+ }
9
+ catch {
10
+ // Best-effort only: never throw.
11
+ }
12
+ },
13
+ };
14
+ }
15
+ //# sourceMappingURL=stdout_sink.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stdout_sink.js","sourceRoot":"","sources":["../../../src/sinks/stdout_sink.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAQ7C,MAAM,UAAU,gBAAgB;IAC9B,OAAO;QACL,KAAK,CAAC,IAAI,CAAC,MAAkB;YAC3B,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;gBACpC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC;YACpC,CAAC;YAAC,MAAM,CAAC;gBACP,iCAAiC;YACnC,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,63 @@
1
+ import { API_SURFACE_VIOLATION, NonComplianceError, } from "./noncompliance.js";
2
+ const ALLOWED_SCOPES = ["request", "job", "component"];
3
+ const FORBIDDEN_NAMES = new Set([
4
+ "withContext",
5
+ "ctx",
6
+ "meta",
7
+ "attributes",
8
+ "tags",
9
+ "labels",
10
+ "log",
11
+ "emit",
12
+ "metric",
13
+ "span",
14
+ ]);
15
+ function assertFunction(value, name, arity) {
16
+ if (typeof value !== "function") {
17
+ throw new NonComplianceError(API_SURFACE_VIOLATION, `${name} must be a function.`);
18
+ }
19
+ if (value.length !== arity) {
20
+ throw new NonComplianceError(API_SURFACE_VIOLATION, `${name} must accept exactly ${arity} argument(s).`);
21
+ }
22
+ }
23
+ function assertChildScopePolicy(child) {
24
+ const candidate = child;
25
+ const allowedScopes = candidate.allowedScopes;
26
+ if (!Array.isArray(allowedScopes) || allowedScopes.length === 0) {
27
+ throw new NonComplianceError(API_SURFACE_VIOLATION, "child() must declare allowedScopes to enforce scope union.");
28
+ }
29
+ for (const scope of allowedScopes) {
30
+ if (!ALLOWED_SCOPES.includes(scope)) {
31
+ throw new NonComplianceError(API_SURFACE_VIOLATION, `child() scope not allowed: ${String(scope)}.`);
32
+ }
33
+ }
34
+ }
35
+ export function assertApiSurface(surface) {
36
+ if (!surface || typeof surface !== "object") {
37
+ throw new NonComplianceError(API_SURFACE_VIOLATION, "API surface must be an object.");
38
+ }
39
+ const api = surface;
40
+ const keys = Object.keys(api);
41
+ for (const key of keys) {
42
+ if (FORBIDDEN_NAMES.has(key)) {
43
+ throw new NonComplianceError(API_SURFACE_VIOLATION, `Forbidden API method detected: ${key}.`);
44
+ }
45
+ }
46
+ if (!("step" in api)) {
47
+ throw new NonComplianceError(API_SURFACE_VIOLATION, "API surface must expose step(message).");
48
+ }
49
+ assertFunction(api.step, "step", 1);
50
+ if ("flush" in api) {
51
+ assertFunction(api.flush, "flush", 0);
52
+ }
53
+ if ("child" in api) {
54
+ assertFunction(api.child, "child", 1);
55
+ assertChildScopePolicy(api.child);
56
+ }
57
+ for (const key of keys) {
58
+ if (key !== "step" && key !== "child" && key !== "flush") {
59
+ throw new NonComplianceError(API_SURFACE_VIOLATION, `Unexpected API export: ${key}.`);
60
+ }
61
+ }
62
+ }
63
+ //# sourceMappingURL=api_surface_guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api_surface_guard.js","sourceRoot":"","sources":["../../../src/validate/api_surface_guard.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,cAAc,GAAG,CAAC,SAAS,EAAE,KAAK,EAAE,WAAW,CAAU,CAAC;AAIhE,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC;IAC9B,aAAa;IACb,KAAK;IACL,MAAM;IACN,YAAY;IACZ,MAAM;IACN,QAAQ;IACR,KAAK;IACL,MAAM;IACN,QAAQ;IACR,MAAM;CACP,CAAC,CAAC;AAEH,SAAS,cAAc,CAAC,KAAc,EAAE,IAAY,EAAE,KAAa;IACjE,IAAI,OAAO,KAAK,KAAK,UAAU,EAAE,CAAC;QAChC,MAAM,IAAI,kBAAkB,CAC1B,qBAAqB,EACrB,GAAG,IAAI,sBAAsB,CAC9B,CAAC;IACJ,CAAC;IAED,IAAK,KAAkB,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;QACzC,MAAM,IAAI,kBAAkB,CAC1B,qBAAqB,EACrB,GAAG,IAAI,wBAAwB,KAAK,eAAe,CACpD,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,sBAAsB,CAAC,KAAc;IAC5C,MAAM,SAAS,GAAG,KAAoC,CAAC;IACvD,MAAM,aAAa,GAAG,SAAS,CAAC,aAAa,CAAC;IAE9C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChE,MAAM,IAAI,kBAAkB,CAC1B,qBAAqB,EACrB,4DAA4D,CAC7D,CAAC;IACJ,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,aAAa,EAAE,CAAC;QAClC,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,KAAqB,CAAC,EAAE,CAAC;YACpD,MAAM,IAAI,kBAAkB,CAC1B,qBAAqB,EACrB,8BAA8B,MAAM,CAAC,KAAK,CAAC,GAAG,CAC/C,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,OAAgB;IAC/C,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAC5C,MAAM,IAAI,kBAAkB,CAC1B,qBAAqB,EACrB,gCAAgC,CACjC,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,GAAG,OAAkC,CAAC;IAC/C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAE9B,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,kBAAkB,CAC1B,qBAAqB,EACrB,kCAAkC,GAAG,GAAG,CACzC,CAAC;QACJ,CAAC;IACH,CAAC;IAED,IAAI,CAAC,CAAC,MAAM,IAAI,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,kBAAkB,CAC1B,qBAAqB,EACrB,wCAAwC,CACzC,CAAC;IACJ,CAAC;IAED,cAAc,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;IAEpC,IAAI,OAAO,IAAI,GAAG,EAAE,CAAC;QACnB,cAAc,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;IACxC,CAAC;IAED,IAAI,OAAO,IAAI,GAAG,EAAE,CAAC;QACnB,cAAc,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;QACtC,sBAAsB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC;IAED,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,GAAG,KAAK,MAAM,IAAI,GAAG,KAAK,OAAO,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;YACzD,MAAM,IAAI,kBAAkB,CAC1B,qBAAqB,EACrB,0BAA0B,GAAG,GAAG,CACjC,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,17 @@
1
+ export const API_SURFACE_VIOLATION = "API_SURFACE_VIOLATION";
2
+ export const CONTEXT_INJECTION_VIOLATION = "CONTEXT_INJECTION_VIOLATION";
3
+ export const PAYLOAD_EMBEDDING_VIOLATION = "PAYLOAD_EMBEDDING_VIOLATION";
4
+ export const CANONICAL_SCHEMA_VIOLATION = "CANONICAL_SCHEMA_VIOLATION";
5
+ export const SINK_MUTATION_VIOLATION = "SINK_MUTATION_VIOLATION";
6
+ export const NO_AUTHORITATIVE_SINK = "NO_AUTHORITATIVE_SINK";
7
+ export const FANOUT_NONDETERMINISM = "FANOUT_NONDETERMINISM";
8
+ export const AUTHORITATIVE_FAILURE_SWALLOWED = "AUTHORITATIVE_FAILURE_SWALLOWED";
9
+ export const UNBOUNDED_BUFFER_RISK = "UNBOUNDED_BUFFER_RISK";
10
+ export class NonComplianceError extends Error {
11
+ code;
12
+ constructor(code, message) {
13
+ super(message);
14
+ this.code = code;
15
+ }
16
+ }
17
+ //# sourceMappingURL=noncompliance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"noncompliance.js","sourceRoot":"","sources":["../../../src/validate/noncompliance.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,qBAAqB,GAAG,uBAAgC,CAAC;AACtE,MAAM,CAAC,MAAM,2BAA2B,GACtC,6BAAsC,CAAC;AACzC,MAAM,CAAC,MAAM,2BAA2B,GACtC,6BAAsC,CAAC;AACzC,MAAM,CAAC,MAAM,0BAA0B,GACrC,4BAAqC,CAAC;AACxC,MAAM,CAAC,MAAM,uBAAuB,GAAG,yBAAkC,CAAC;AAC1E,MAAM,CAAC,MAAM,qBAAqB,GAAG,uBAAgC,CAAC;AACtE,MAAM,CAAC,MAAM,qBAAqB,GAAG,uBAAgC,CAAC;AACtE,MAAM,CAAC,MAAM,+BAA+B,GAC1C,iCAA0C,CAAC;AAC7C,MAAM,CAAC,MAAM,qBAAqB,GAAG,uBAAgC,CAAC;AAatE,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAClC,IAAI,CAAoB;IAEjC,YAAY,IAAuB,EAAE,OAAe;QAClD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF"}
@@ -0,0 +1,151 @@
1
+ import { assertValidMessage } from "../core/message_constraints.js";
2
+ import { CANONICAL_SCHEMA_VIOLATION, CONTEXT_INJECTION_VIOLATION, NO_AUTHORITATIVE_SINK, PAYLOAD_EMBEDDING_VIOLATION, NonComplianceError, } from "./noncompliance.js";
3
+ const REQUIRED_FIELDS = [
4
+ "record_version",
5
+ "record_id",
6
+ "sequence",
7
+ "timestamp_utc",
8
+ "monotonic_time",
9
+ "institution",
10
+ "system_name",
11
+ "system_type",
12
+ "environment",
13
+ "system_version",
14
+ "message",
15
+ "context_hash",
16
+ "context_version",
17
+ "record_hash",
18
+ "hash_algorithm",
19
+ ];
20
+ const OPTIONAL_FIELDS = [
21
+ "instance_id",
22
+ "trace_id",
23
+ "span_id",
24
+ "parent_step_id",
25
+ "surface_type",
26
+ "surface_name",
27
+ "surface_instance",
28
+ "source_file",
29
+ "source_module",
30
+ "source_function",
31
+ "source_line",
32
+ "message_code",
33
+ "evidence_refs",
34
+ ];
35
+ const ALLOWED_FIELDS = new Set([...REQUIRED_FIELDS, ...OPTIONAL_FIELDS]);
36
+ const CONTEXT_FIELDS = ["context", "context_blob", "context_data", "context_value"];
37
+ // Explicit type assertion for string keys from Object.keys(schema.properties)
38
+ function asRecord(value) {
39
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
40
+ throw new NonComplianceError(CANONICAL_SCHEMA_VIOLATION, "Step record must be a plain object.");
41
+ }
42
+ return value;
43
+ }
44
+ export function assertStepRecord(record) {
45
+ const candidate = asRecord(record);
46
+ if (!Object.isFrozen(candidate)) {
47
+ throw new NonComplianceError(CANONICAL_SCHEMA_VIOLATION, "Step record must be immutable at emission time.");
48
+ }
49
+ for (const forbidden of CONTEXT_FIELDS) {
50
+ if (forbidden in candidate) {
51
+ throw new NonComplianceError(CONTEXT_INJECTION_VIOLATION, "Context must not be embedded in the step record.");
52
+ }
53
+ }
54
+ for (const key of Object.keys(candidate)) {
55
+ if (!ALLOWED_FIELDS.has(key)) {
56
+ throw new NonComplianceError(CANONICAL_SCHEMA_VIOLATION, `Unexpected field in step record: ${key}.`);
57
+ }
58
+ }
59
+ for (const field of REQUIRED_FIELDS) {
60
+ if (!(field in candidate)) {
61
+ throw new NonComplianceError(CANONICAL_SCHEMA_VIOLATION, `Missing required field: ${field}.`);
62
+ }
63
+ }
64
+ assertStringField(candidate, "record_version");
65
+ assertStringField(candidate, "record_id");
66
+ assertIntegerField(candidate, "sequence");
67
+ assertStringField(candidate, "timestamp_utc");
68
+ assertNumberField(candidate, "monotonic_time");
69
+ assertStringField(candidate, "institution");
70
+ assertStringField(candidate, "system_name");
71
+ assertStringField(candidate, "system_type");
72
+ assertStringField(candidate, "environment");
73
+ assertStringField(candidate, "system_version");
74
+ assertStringField(candidate, "context_hash");
75
+ assertStringField(candidate, "context_version");
76
+ assertStringField(candidate, "record_hash");
77
+ assertStringField(candidate, "hash_algorithm");
78
+ if (candidate.record_version !== "log.step.v1") {
79
+ throw new NonComplianceError(CANONICAL_SCHEMA_VIOLATION, "record_version must be log.step.v1.");
80
+ }
81
+ try {
82
+ assertValidMessage(candidate.message);
83
+ }
84
+ catch (error) {
85
+ throw new NonComplianceError(PAYLOAD_EMBEDDING_VIOLATION, error instanceof Error ? error.message : "Invalid message content.");
86
+ }
87
+ if (typeof candidate.timestamp_utc === "string") {
88
+ const parsed = Date.parse(candidate.timestamp_utc);
89
+ if (Number.isNaN(parsed)) {
90
+ throw new NonComplianceError(CANONICAL_SCHEMA_VIOLATION, "timestamp_utc must be a valid ISO-8601 string.");
91
+ }
92
+ }
93
+ assertOptionalStringField(candidate, "instance_id");
94
+ assertOptionalStringField(candidate, "trace_id");
95
+ assertOptionalStringField(candidate, "span_id");
96
+ assertOptionalStringField(candidate, "parent_step_id");
97
+ assertOptionalStringField(candidate, "surface_type");
98
+ assertOptionalStringField(candidate, "surface_name");
99
+ assertOptionalStringField(candidate, "surface_instance");
100
+ assertOptionalStringField(candidate, "source_file");
101
+ assertOptionalStringField(candidate, "source_module");
102
+ assertOptionalStringField(candidate, "source_function");
103
+ assertOptionalStringField(candidate, "message_code");
104
+ if ("source_line" in candidate && candidate.source_line !== undefined) {
105
+ assertNumberField(candidate, "source_line");
106
+ }
107
+ if ("evidence_refs" in candidate && candidate.evidence_refs !== undefined) {
108
+ if (!Array.isArray(candidate.evidence_refs)) {
109
+ throw new NonComplianceError(CANONICAL_SCHEMA_VIOLATION, "evidence_refs must be an array of strings.");
110
+ }
111
+ for (const ref of candidate.evidence_refs) {
112
+ if (typeof ref !== "string" || ref.length === 0) {
113
+ throw new NonComplianceError(CANONICAL_SCHEMA_VIOLATION, "evidence_refs must contain non-empty strings.");
114
+ }
115
+ }
116
+ }
117
+ }
118
+ // Explicit type assertion for string keys from Object.keys(schema.properties)
119
+ export function assertHasAuthoritativeSink(sinks) {
120
+ const hasAuthoritative = sinks.some((entry) => entry.sinkClass === "authoritative");
121
+ if (!hasAuthoritative) {
122
+ throw new NonComplianceError(NO_AUTHORITATIVE_SINK, "At least one authoritative sink is required.");
123
+ }
124
+ }
125
+ function assertStringField(record, field) {
126
+ const value = record[field];
127
+ if (typeof value !== "string" || value.length === 0) {
128
+ throw new NonComplianceError(CANONICAL_SCHEMA_VIOLATION, `${field} must be a non-empty string.`);
129
+ }
130
+ }
131
+ function assertOptionalStringField(record, field) {
132
+ if (field in record && record[field] !== undefined) {
133
+ const value = record[field];
134
+ if (typeof value !== "string" || value.length === 0) {
135
+ throw new NonComplianceError(CANONICAL_SCHEMA_VIOLATION, `${field} must be a non-empty string when provided.`);
136
+ }
137
+ }
138
+ }
139
+ function assertNumberField(record, field) {
140
+ const value = record[field];
141
+ if (typeof value !== "number" || !Number.isFinite(value)) {
142
+ throw new NonComplianceError(CANONICAL_SCHEMA_VIOLATION, `${field} must be a finite number.`);
143
+ }
144
+ }
145
+ function assertIntegerField(record, field) {
146
+ const value = record[field];
147
+ if (typeof value !== "number" || !Number.isInteger(value) || value < 0) {
148
+ throw new NonComplianceError(CANONICAL_SCHEMA_VIOLATION, `${field} must be a non-negative integer.`);
149
+ }
150
+ }
151
+ //# sourceMappingURL=schema_guard.js.map