@unifyplane/logsdk 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/copilot-instructions.md +48 -0
- package/README.md +8 -0
- package/contracts/specs/LogSDKFuntionalSpec.md +394 -0
- package/contracts/specs/fanout-semantics.v1.md +244 -0
- package/contracts/specs/sink-contract.v1.md +223 -0
- package/contracts/specs/step-record.v1.md +292 -0
- package/contracts/specs/validation-rules.v1.md +324 -0
- package/docs/LogSDK-Unified-Execution-Logging-Framework.md +93 -0
- package/docs/log_sdk_test_cases_traceability_plan.md +197 -0
- package/docs/log_sdk_test_coverage_report.md +198 -0
- package/docs/prompts/AuditorSDK.txt +214 -0
- package/package.json +29 -0
- package/src/core/clock.ts +25 -0
- package/src/core/context.ts +142 -0
- package/src/core/fanout.ts +38 -0
- package/src/core/ids.ts +35 -0
- package/src/core/message_constraints.ts +66 -0
- package/src/core/outcomes.ts +5 -0
- package/src/core/record_builder.ts +269 -0
- package/src/core/spool.ts +41 -0
- package/src/core/types.ts +56 -0
- package/src/crypto-shim.d.ts +9 -0
- package/src/fs-shim.d.ts +15 -0
- package/src/index.ts +107 -0
- package/src/node-test-shim.d.ts +1 -0
- package/src/perf_hooks-shim.d.ts +7 -0
- package/src/process-shim.d.ts +1 -0
- package/src/sinks/file_ndjson.ts +42 -0
- package/src/sinks/file_ndjson_sink.ts +45 -0
- package/src/sinks/sink_types.ts +15 -0
- package/src/sinks/stdout_sink.ts +20 -0
- package/src/validate/api_surface_guard.ts +106 -0
- package/src/validate/noncompliance.ts +33 -0
- package/src/validate/schema_guard.ts +238 -0
- package/tests/fanout.test.ts +51 -0
- package/tests/fanout_spool.test.ts +96 -0
- package/tests/message_constraints.test.ts +7 -0
- package/tests/node-shim.d.ts +1 -0
- package/tests/record_builder.test.ts +32 -0
- package/tests/sequence_monotonic.test.ts +62 -0
- package/tests/sinks_file_ndjson.test.ts +53 -0
- package/tests/step1_compliance.test.ts +192 -0
- package/tools/test_results/generate-test-traceability.js +60 -0
- package/tools/test_results/normalize-test-results.js +57 -0
- package/tools/test_results/run-tests-then-prebuild.js +103 -0
- package/tools/test_results/test-case-map.json +9 -0
- package/tsconfig.json +31 -0
- package/validators/bootstrap/validate-repo-structure.ts +590 -0
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
Proceeding with **4️⃣ Define Validation & Non-Compliance Rules**.
|
|
2
|
+
|
|
3
|
+
This locks what it means to be **LogSDK v1.0 compliant** and what CI/validators must enforce.
|
|
4
|
+
**No code. Language-neutral. Frozen once accepted.**
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# 🧩 LogSDK Core — Validation & Non-Compliance Rules (v1.0)
|
|
9
|
+
|
|
10
|
+
## Table of Contents
|
|
11
|
+
|
|
12
|
+
- [0. Purpose (Non-Negotiable)](#section-0-purpose)
|
|
13
|
+
- [1. Compliance Domains (What Must Be Validated)](#section-1-compliance-domains)
|
|
14
|
+
- [2. API Surface Compliance (Hard Rules)](#section-2-api-surface-compliance)
|
|
15
|
+
- [3. Canonical Step Record Compliance (Hard Rules)](#section-3-canonical-step-record-compliance)
|
|
16
|
+
- [4. Sink / Emitter Compliance (Hard Rules)](#section-4-sink-emitter-compliance)
|
|
17
|
+
- [5. Fan-Out Semantics Compliance (Hard Rules)](#section-5-fan-out-semantics-compliance)
|
|
18
|
+
- [6. Compliance Artifacts (What CI Must Prove)](#section-6-compliance-artifacts)
|
|
19
|
+
- [7. Non-Compliance Taxonomy (Standard Failure Reasons)](#section-7-non-compliance-taxonomy)
|
|
20
|
+
- [8. Freeze Statement](#section-8-freeze-statement)
|
|
21
|
+
- [✅ Closure](#section-closure)
|
|
22
|
+
|
|
23
|
+
<a id="section-0-purpose"></a>
|
|
24
|
+
## 0. Purpose (Non-Negotiable)
|
|
25
|
+
|
|
26
|
+
Validation exists to ensure:
|
|
27
|
+
|
|
28
|
+
* **the developer surface stays minimal**
|
|
29
|
+
* **records remain canonical + bounded**
|
|
30
|
+
* **fan-out semantics are deterministic**
|
|
31
|
+
* **evidence ownership is preserved**
|
|
32
|
+
* **no drift introduces “context injection” or payload logging**
|
|
33
|
+
|
|
34
|
+
Validation is how the SDK remains governable across versions.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
<a id="section-1-compliance-domains"></a>
|
|
39
|
+
## 1. Compliance Domains (What Must Be Validated)
|
|
40
|
+
|
|
41
|
+
Validation is divided into four domains:
|
|
42
|
+
|
|
43
|
+
1. **API Surface Compliance**
|
|
44
|
+
2. **Record Shape & Constraint Compliance**
|
|
45
|
+
3. **Emitter/Sink Compliance**
|
|
46
|
+
4. **Fan-Out Semantics Compliance**
|
|
47
|
+
|
|
48
|
+
Each domain has explicit PASS/FAIL rules.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
<a id="section-2-api-surface-compliance"></a>
|
|
53
|
+
## 2. API Surface Compliance (Hard Rules)
|
|
54
|
+
|
|
55
|
+
### 2.1 Allowed developer method
|
|
56
|
+
|
|
57
|
+
✅ Only:
|
|
58
|
+
|
|
59
|
+
* `step(message_string)`
|
|
60
|
+
|
|
61
|
+
### 2.2 Forbidden API capabilities (FAIL if present)
|
|
62
|
+
|
|
63
|
+
❌ Any of:
|
|
64
|
+
|
|
65
|
+
* `step(message, anythingElse)`
|
|
66
|
+
* `withContext`, `ctx`, `meta`, `attributes`, `tags`, `labels`
|
|
67
|
+
* `log(event)`, `emit(payload)`, `metric()`, `span()`
|
|
68
|
+
* `step({ ... })` object-based steps
|
|
69
|
+
* any method that enables per-call enrichment
|
|
70
|
+
|
|
71
|
+
### 2.3 Scope methods (Conditional allowance)
|
|
72
|
+
|
|
73
|
+
If `child(scope)` exists:
|
|
74
|
+
|
|
75
|
+
* scope must be from a **closed union** (request/job/component only)
|
|
76
|
+
* scope must be **structural identity**, not metadata
|
|
77
|
+
* no user-provided object blobs
|
|
78
|
+
* no per-step override
|
|
79
|
+
|
|
80
|
+
If this is not enforceable, `child()` is non-compliant.
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
<a id="section-3-canonical-step-record-compliance"></a>
|
|
85
|
+
## 3. Canonical Step Record Compliance (Hard Rules)
|
|
86
|
+
|
|
87
|
+
### 3.1 Record completeness
|
|
88
|
+
|
|
89
|
+
✅ Every emitted record must include:
|
|
90
|
+
|
|
91
|
+
* `record_version`
|
|
92
|
+
* `record_id`
|
|
93
|
+
* `sequence`
|
|
94
|
+
* `timestamp_utc`
|
|
95
|
+
* `monotonic_time`
|
|
96
|
+
* system ownership fields (`institution`, `system_name`, `system_type`, `environment`, `system_version`)
|
|
97
|
+
* `message`
|
|
98
|
+
* `context_hash`
|
|
99
|
+
* integrity fields (`record_hash`, `hash_algorithm`)
|
|
100
|
+
|
|
101
|
+
### 3.2 Immutability
|
|
102
|
+
|
|
103
|
+
✅ Record must be immutable at emission time.
|
|
104
|
+
FAIL if:
|
|
105
|
+
|
|
106
|
+
* any sink can mutate fields
|
|
107
|
+
* per-sink copies differ in content (other than transport metadata outside record)
|
|
108
|
+
|
|
109
|
+
### 3.3 Boundedness
|
|
110
|
+
|
|
111
|
+
✅ `message` must satisfy bounded rules:
|
|
112
|
+
|
|
113
|
+
* hard length limit (as configured but fixed per major version)
|
|
114
|
+
* must not contain embedded JSON objects/arrays
|
|
115
|
+
* must not contain base64-like blobs or raw payloads
|
|
116
|
+
|
|
117
|
+
### 3.4 Context discipline
|
|
118
|
+
|
|
119
|
+
✅ Context is **reference-only**.
|
|
120
|
+
FAIL if:
|
|
121
|
+
|
|
122
|
+
* context is embedded in record
|
|
123
|
+
* context can be changed after init
|
|
124
|
+
* per-step context exists in any form
|
|
125
|
+
|
|
126
|
+
### 3.5 Evidence references
|
|
127
|
+
|
|
128
|
+
✅ Evidence may appear only as `evidence_refs` (references).
|
|
129
|
+
FAIL if:
|
|
130
|
+
|
|
131
|
+
* raw evidence/payload is embedded
|
|
132
|
+
* `evidence_refs` contains inline data rather than references
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
<a id="section-4-sink-emitter-compliance"></a>
|
|
137
|
+
## 4. Sink / Emitter Compliance (Hard Rules)
|
|
138
|
+
|
|
139
|
+
### 4.1 Contract adherence
|
|
140
|
+
|
|
141
|
+
Each sink must support:
|
|
142
|
+
|
|
143
|
+
* `emit(record)` (required)
|
|
144
|
+
Optional:
|
|
145
|
+
* `flush()`, `close()`
|
|
146
|
+
|
|
147
|
+
FAIL if sink:
|
|
148
|
+
|
|
149
|
+
* requires mutating record
|
|
150
|
+
* requires additional record fields not in canonical schema
|
|
151
|
+
* rejects records based on semantics rather than transport
|
|
152
|
+
|
|
153
|
+
### 4.2 Non-mutation guarantee
|
|
154
|
+
|
|
155
|
+
FAIL if sink:
|
|
156
|
+
|
|
157
|
+
* adds labels/tags into record
|
|
158
|
+
* rewrites fields
|
|
159
|
+
* strips fields
|
|
160
|
+
* changes ordering within a single execution context
|
|
161
|
+
|
|
162
|
+
Transport-level enrichment (headers, labels outside record) is allowed.
|
|
163
|
+
|
|
164
|
+
### 4.3 Sink classification must be explicit
|
|
165
|
+
|
|
166
|
+
Every sink must be configured as one of:
|
|
167
|
+
|
|
168
|
+
* `authoritative`
|
|
169
|
+
* `observability`
|
|
170
|
+
|
|
171
|
+
FAIL if:
|
|
172
|
+
|
|
173
|
+
* sink class is inferred dynamically
|
|
174
|
+
* sink class is missing
|
|
175
|
+
|
|
176
|
+
### 4.4 Evidence continuity requirement (system config rule)
|
|
177
|
+
|
|
178
|
+
At runtime configuration level:
|
|
179
|
+
|
|
180
|
+
* at least one `authoritative` sink must exist
|
|
181
|
+
|
|
182
|
+
FAIL if:
|
|
183
|
+
|
|
184
|
+
* only observability sinks exist (e.g., Loki-only setup)
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
<a id="section-5-fan-out-semantics-compliance"></a>
|
|
189
|
+
## 5. Fan-Out Semantics Compliance (Hard Rules)
|
|
190
|
+
|
|
191
|
+
### 5.1 Emit once
|
|
192
|
+
|
|
193
|
+
FAIL if:
|
|
194
|
+
|
|
195
|
+
* multiple canonical records are generated for one `step()` call
|
|
196
|
+
* per-sink content differs
|
|
197
|
+
|
|
198
|
+
### 5.2 Deterministic order
|
|
199
|
+
|
|
200
|
+
PASS if:
|
|
201
|
+
|
|
202
|
+
* sinks are invoked in declared order (or an explicitly declared concurrent mode that preserves deterministic semantics)
|
|
203
|
+
|
|
204
|
+
FAIL if:
|
|
205
|
+
|
|
206
|
+
* sink invocation order varies run-to-run without explicit config
|
|
207
|
+
|
|
208
|
+
### 5.3 Failure classification
|
|
209
|
+
|
|
210
|
+
Must produce one of:
|
|
211
|
+
|
|
212
|
+
* `OK`
|
|
213
|
+
* `DEGRADED`
|
|
214
|
+
* `FAILED`
|
|
215
|
+
|
|
216
|
+
Rules:
|
|
217
|
+
|
|
218
|
+
* observability sink failure must not cause FAILED
|
|
219
|
+
* authoritative sink failure must not be silently ignored
|
|
220
|
+
|
|
221
|
+
### 5.4 Fail-open requires spool
|
|
222
|
+
|
|
223
|
+
If fail-open mode is enabled:
|
|
224
|
+
|
|
225
|
+
* emergency spool must exist
|
|
226
|
+
* spool must be append-only + bounded
|
|
227
|
+
* spool write must be acknowledged
|
|
228
|
+
|
|
229
|
+
FAIL if:
|
|
230
|
+
|
|
231
|
+
* fail-open occurs without spool
|
|
232
|
+
* authoritative failure is swallowed
|
|
233
|
+
|
|
234
|
+
### 5.5 Bounded resource behavior
|
|
235
|
+
|
|
236
|
+
FAIL if:
|
|
237
|
+
|
|
238
|
+
* unbounded buffering is possible
|
|
239
|
+
* memory can grow without a hard cap
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
<a id="section-6-compliance-artifacts"></a>
|
|
244
|
+
## 6. Compliance Artifacts (What CI Must Prove)
|
|
245
|
+
|
|
246
|
+
A compliant implementation must be able to generate these proofs:
|
|
247
|
+
|
|
248
|
+
1. **API surface report**
|
|
249
|
+
|
|
250
|
+
* lists exported methods and signatures
|
|
251
|
+
* asserts forbidden APIs absent
|
|
252
|
+
|
|
253
|
+
2. **Schema conformance report**
|
|
254
|
+
|
|
255
|
+
* validates emitted record against canonical schema
|
|
256
|
+
|
|
257
|
+
3. **Fan-out behavior report**
|
|
258
|
+
|
|
259
|
+
* demonstrates deterministic order
|
|
260
|
+
* demonstrates correct OK/DEGRADED/FAILED behavior
|
|
261
|
+
|
|
262
|
+
4. **Sink classification report**
|
|
263
|
+
|
|
264
|
+
* confirms at least one authoritative sink exists
|
|
265
|
+
|
|
266
|
+
5. **Negative tests**
|
|
267
|
+
|
|
268
|
+
* prove rejection of:
|
|
269
|
+
|
|
270
|
+
* payload-in-message
|
|
271
|
+
* JSON-in-message
|
|
272
|
+
* missing authoritative sink
|
|
273
|
+
* per-step context attempts
|
|
274
|
+
|
|
275
|
+
These artifacts enable downstream governance validators to PASS.
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
<a id="section-7-non-compliance-taxonomy"></a>
|
|
280
|
+
## 7. Non-Compliance Taxonomy (Standard Failure Reasons)
|
|
281
|
+
|
|
282
|
+
When validation fails, it must classify failures into one of these reasons:
|
|
283
|
+
|
|
284
|
+
* `API_SURFACE_VIOLATION`
|
|
285
|
+
* `CONTEXT_INJECTION_VIOLATION`
|
|
286
|
+
* `PAYLOAD_EMBEDDING_VIOLATION`
|
|
287
|
+
* `CANONICAL_SCHEMA_VIOLATION`
|
|
288
|
+
* `SINK_MUTATION_VIOLATION`
|
|
289
|
+
* `NO_AUTHORITATIVE_SINK`
|
|
290
|
+
* `FANOUT_NONDETERMINISM`
|
|
291
|
+
* `AUTHORITATIVE_FAILURE_SWALLOWED`
|
|
292
|
+
* `UNBOUNDED_BUFFER_RISK`
|
|
293
|
+
|
|
294
|
+
This taxonomy is required for traceability.
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
<a id="section-8-freeze-statement"></a>
|
|
299
|
+
## 8. Freeze Statement
|
|
300
|
+
|
|
301
|
+
**LogSDK Core Validation Rules v1.0 are now locked.**
|
|
302
|
+
|
|
303
|
+
Any change to:
|
|
304
|
+
|
|
305
|
+
* canonical record fields
|
|
306
|
+
* allowed API surface
|
|
307
|
+
* sink compliance rules
|
|
308
|
+
* fan-out failure semantics
|
|
309
|
+
|
|
310
|
+
requires a **major version bump**.
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
<a id="section-closure"></a>
|
|
315
|
+
## ✅ Closure
|
|
316
|
+
|
|
317
|
+
At this point, you have **fully defined v1.0** of:
|
|
318
|
+
|
|
319
|
+
1. Canonical Step Record
|
|
320
|
+
2. Sink / Emitter Contract
|
|
321
|
+
3. Fan-Out Semantics
|
|
322
|
+
4. Validation Rules
|
|
323
|
+
|
|
324
|
+
**You are now ready to implement LogSDK without rediscovery or design drift.**
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# LogSDK — Unified Execution Logging Framework for UnifyPlane
|
|
2
|
+
|
|
3
|
+
## Table of Contents
|
|
4
|
+
- [1. What LogSDK Is](#section-1-what-logsdk-is)
|
|
5
|
+
- [2. Why LogSDK Exists in UnifyPlane](#section-2-why-logsdk-exists-in-unifyplane)
|
|
6
|
+
- [3. Core Capabilities (Evidence-Based)](#section-3-core-capabilities-evidence-based)
|
|
7
|
+
- [4. LogSDK Usage Across the Repository](#section-4-logsdk-usage-across-the-repository)
|
|
8
|
+
- [5. Executable vs Non-Executable Surfaces](#section-5-executable-vs-non-executable-surfaces)
|
|
9
|
+
- [6. Execution Lifecycle and Logging Semantics](#section-6-execution-lifecycle-and-logging-semantics)
|
|
10
|
+
- [7. Relationship to Events and CIA](#section-7-relationship-to-events-and-cia)
|
|
11
|
+
- [8. Governance, Validation, and Evidence](#section-8-governance-validation-and-evidence)
|
|
12
|
+
- [9. Benefits of Leveraging LogSDK Across UnifyPlane](#section-9-benefits-of-leveraging-logsdk-across-unifyplane)
|
|
13
|
+
- [10. Future Considerations (Non-Binding)](#section-10-future-considerations-non-binding)
|
|
14
|
+
- [11. Non-Goals and Explicit Exclusions](#section-11-non-goals-and-explicit-exclusions)
|
|
15
|
+
|
|
16
|
+
## 1. What LogSDK Is
|
|
17
|
+
<a id="section-1-what-logsdk-is"></a>
|
|
18
|
+
- Precise definition: A TypeScript/Node library that produces immutable, canonical step records with integrity metadata and context capsule references, and delivers them to configured sinks with authoritative failure handling. Evidence: src/index.ts, src/core/record_builder.ts, src/core/fanout.ts, src/validate/schema_guard.ts.
|
|
19
|
+
- Explicit scope: Provides `initLogSDK()` returning a `LogApi` with `step(message)` and optional `flush()`, enforces message constraints and API surface policies, and supports sink fanout with emergency spooling on authoritative failure. Evidence: src/index.ts, src/core/message_constraints.ts, src/validate/api_surface_guard.ts, src/core/spool.ts.
|
|
20
|
+
- Explicit non-scope: No metrics/tracing collection, no external observability backends beyond provided file/stdout sinks, no per-step context injection, no arbitrary API exports beyond `step`, `flush`. Evidence: src/validate/api_surface_guard.ts, src/sinks/file_ndjson.ts, src/sinks/stdout_sink.ts, src/index.ts.
|
|
21
|
+
|
|
22
|
+
## 2. Why LogSDK Exists in UnifyPlane
|
|
23
|
+
<a id="section-2-why-logsdk-exists-in-unifyplane"></a>
|
|
24
|
+
- Relationship to UnifyPlane Law and Governance Stack: Enforces canonical record schema, message discipline, and authoritative emission requirements to produce governance-grade execution evidence. Evidence: src/validate/schema_guard.ts, src/core/message_constraints.ts, src/core/record_builder.ts, src/core/fanout.ts.
|
|
25
|
+
- Why execution logging is treated as governance evidence: Records include integrity fields (`record_hash`, `hash_algorithm`) over a canonicalized payload and a context capsule (`context_hash`, `context_version`), supporting auditability and tamper detection. Evidence: src/core/record_builder.ts, src/core/context.ts, src/core/types.ts.
|
|
26
|
+
|
|
27
|
+
## 3. Core Capabilities (Evidence-Based)
|
|
28
|
+
<a id="section-3-core-capabilities-evidence-based"></a>
|
|
29
|
+
- `initLogSDK(config)`: Initializes context (once per process) and returns `step(message)`/`flush()`. Evidence: src/index.ts, src/core/context.ts.
|
|
30
|
+
- Step record construction: `buildStepRecord()` enforces required fields, sets monotonic clocks, and computes a canonical hash over an ordered JSON representation. Evidence: src/core/record_builder.ts, src/core/clock.ts.
|
|
31
|
+
- Message validation: Rejects empty, too-long, JSON-shaped, and base64-like payloads. Evidence: src/core/message_constraints.ts.
|
|
32
|
+
- API surface validation: Only `step`, optional `flush`; forbids ambiguous exports and per-step context injection. Evidence: src/validate/api_surface_guard.ts.
|
|
33
|
+
- Sink fanout with authoritative requirement: Emits to sinks; requires at least one authoritative sink; writes to emergency spool on authoritative failure; reports `OK`/`DEGRADED`/`FAILED`. Evidence: src/core/fanout.ts, src/validate/schema_guard.ts, src/core/spool.ts, src/core/outcomes.ts.
|
|
34
|
+
- Provided sinks: NDJSON file sink (authoritative/observability variants) and stdout sink. Evidence: src/sinks/file_ndjson.ts, src/sinks/file_ndjson_sink.ts, src/sinks/stdout_sink.ts, src/index.ts.
|
|
35
|
+
- Id generation and sequencing: Deterministic sequence starting at 0 per instance; record IDs include time-derived and instance components. Evidence: src/core/ids.ts, validated in tests/sequence_monotonic.test.ts.
|
|
36
|
+
|
|
37
|
+
## 4. LogSDK Usage Across the Repository
|
|
38
|
+
<a id="section-4-logsdk-usage-across-the-repository"></a>
|
|
39
|
+
- Initialization site: External code calls `initLogSDK()` with `context`, `system`, and `sinks`. Tests demonstrate usage patterns. Evidence: src/index.ts, tests/step1_compliance.test.ts.
|
|
40
|
+
- Components using it: Library clients construct sinks (file NDJSON, stdout) and call `log.step("...")`, optionally `log.flush()`. Evidence: tests/step1_compliance.test.ts.
|
|
41
|
+
- Observed patterns:
|
|
42
|
+
- Authoritative sink enforced before emission. Evidence: src/validate/schema_guard.ts.
|
|
43
|
+
- Emergency spool path driven by `LOGSDK_EMERGENCY_SPOOL_PATH`. Evidence: src/core/spool.ts, tests/step1_compliance.test.ts.
|
|
44
|
+
- NDJSON line discipline (append-only). Evidence: src/sinks/file_ndjson.ts, src/sinks/file_ndjson_sink.ts.
|
|
45
|
+
|
|
46
|
+
## 5. Executable vs Non-Executable Surfaces
|
|
47
|
+
<a id="section-5-executable-vs-non-executable-surfaces"></a>
|
|
48
|
+
- Formal definition of execution surface: Any file directly invocable (CLI/job/script/tool), a deterministic entrypoint, or performing side-effect-capable logic (filesystem, process, env, network). Basis: Task requirements; mapped to repo evidence in Part B.
|
|
49
|
+
- Why this distinction exists: Governance mandates logging at operational boundaries and side-effect points to preserve execution evidence.
|
|
50
|
+
- Governance implications: Execution surfaces carry logging obligations; declarative/spec-only assets do not. Evidence: CI/tooling orchestrations in tools/test_results/run-tests-then-prebuild.js and validator in validators/bootstrap/validate-repo-structure.ts.
|
|
51
|
+
|
|
52
|
+
## 6. Execution Lifecycle and Logging Semantics
|
|
53
|
+
<a id="section-6-execution-lifecycle-and-logging-semantics"></a>
|
|
54
|
+
- Step-based logging: `log.step(message)` produces one immutable record per step; sequence increments monotonically. Evidence: src/index.ts, src/core/ids.ts.
|
|
55
|
+
- Started/completed/error semantics: Errors occur at validation or sink emission; authoritative failure triggers emergency spooling and can escalate to `FAILED`. Evidence: src/core/fanout.ts, tests/step1_compliance.test.ts.
|
|
56
|
+
- Bounded message discipline: 512-char max, no JSON-shaped or base64-like payloads; message is the sole human input. Evidence: src/core/message_constraints.ts, src/core/types.ts.
|
|
57
|
+
|
|
58
|
+
## 7. Relationship to Events and CIA
|
|
59
|
+
<a id="section-7-relationship-to-events-and-cia"></a>
|
|
60
|
+
- Logs vs Events: LogSDK emits canonical step records to sinks; it does not implement an event bus or downstream event processing. Evidence: absence of event frameworks; presence of sink-only interfaces in src/sinks/sink_types.ts.
|
|
61
|
+
- CIA readiness (Confidentiality, Integrity, Availability) without coupling:
|
|
62
|
+
- Integrity: Canonical hashing and immutability at emission. Evidence: src/core/record_builder.ts, src/validate/schema_guard.ts.
|
|
63
|
+
- Availability: Emergency spool on authoritative failure. Evidence: src/core/spool.ts, src/core/fanout.ts.
|
|
64
|
+
- Confidentiality: Not explicitly addressed in code; no encryption features observed.
|
|
65
|
+
|
|
66
|
+
## 8. Governance, Validation, and Evidence
|
|
67
|
+
<a id="section-8-governance-validation-and-evidence"></a>
|
|
68
|
+
- Validators (runtime/API):
|
|
69
|
+
- API surface guard prohibits non-compliant exports and per-step context injection. Evidence: src/validate/api_surface_guard.ts.
|
|
70
|
+
- Schema guard enforces canonical record fields and authoritative sink presence. Evidence: src/validate/schema_guard.ts.
|
|
71
|
+
- Noncompliance codes used for precise error signaling. Evidence: src/validate/noncompliance.ts.
|
|
72
|
+
- CI enforcement (tooling):
|
|
73
|
+
- Verification pipeline runs repo-structure validator, tests, normalization, and traceability generation. Evidence: tools/test_results/run-tests-then-prebuild.js.
|
|
74
|
+
- Auditability guarantees:
|
|
75
|
+
- NDJSON sinks produce append-only lines; emergency spool preserves authoritative failures; canonical hashing ensures record integrity. Evidence: src/sinks/file_ndjson.ts, src/sinks/file_ndjson_sink.ts, src/core/spool.ts, src/core/record_builder.ts.
|
|
76
|
+
|
|
77
|
+
## 9. Benefits of Leveraging LogSDK Across UnifyPlane
|
|
78
|
+
<a id="section-9-benefits-of-leveraging-logsdk-across-unifyplane"></a>
|
|
79
|
+
- Determinism: Sequence and monotonic clock, canonical hashing, immutable records. Evidence: src/core/ids.ts, src/core/clock.ts, src/core/record_builder.ts.
|
|
80
|
+
- Traceability: Context capsule references and consistent schema across steps. Evidence: src/core/context.ts, src/core/types.ts.
|
|
81
|
+
- Governance safety: Clear noncompliance paths, authoritative emission guarantees, and emergency spooling. Evidence: src/validate/noncompliance.ts, src/core/fanout.ts, src/core/spool.ts.
|
|
82
|
+
|
|
83
|
+
## 10. Future Considerations (Non-Binding)
|
|
84
|
+
<a id="section-10-future-considerations-non-binding"></a>
|
|
85
|
+
- External sink integrations (e.g., exporting NDJSON to external systems such as Grafana/Loki) could be added via new sink implementations; not present in repo. Evidence: Only file/stdout sinks exist today in src/sinks.
|
|
86
|
+
- Extended correlation (trace/span IDs) could be populated by callers; fields exist but no automatic propagation observed. Evidence: Optional fields in src/core/types.ts.
|
|
87
|
+
- Policy-driven retention or rotation for NDJSON files may be desirable for production; not implemented here.
|
|
88
|
+
|
|
89
|
+
## 11. Non-Goals and Explicit Exclusions
|
|
90
|
+
<a id="section-11-non-goals-and-explicit-exclusions"></a>
|
|
91
|
+
- No dynamic per-step context embedding; context is fixed at initialization and referenced by hash/version. Evidence: src/core/context.ts, src/validate/schema_guard.ts.
|
|
92
|
+
- No metrics, spans, tags, or arbitrary API exports; guarded explicitly. Evidence: src/validate/api_surface_guard.ts.
|
|
93
|
+
- No built-in network transports or databases for logs; sinks provided are file/stdout only. Evidence: src/sinks/file_ndjson.ts, src/sinks/stdout_sink.ts.
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# 🧪 LogSDK — Test Cases, Execution & Traceability (Plan + Templates)
|
|
2
|
+
|
|
3
|
+
**Status:** Proposed (Non-authoritative)
|
|
4
|
+
**Goal:** Define explicit **test cases**, execute existing tests against them, and produce **traceable results** suitable for audit and freeze-gate.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 1. Model Overview
|
|
9
|
+
|
|
10
|
+
We introduce a **3-layer traceability model** without changing runtime code:
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
Audit Objective
|
|
14
|
+
↓
|
|
15
|
+
Test Case (TC-*) — declarative intent
|
|
16
|
+
↓
|
|
17
|
+
Test Implementation (existing *.test.ts)
|
|
18
|
+
↓
|
|
19
|
+
Execution Result (CI output / JSON)
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
This keeps tests intact while making **intent, coverage, and results explicit**.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## 2. Test Case Definition (Authoritative for Testing Only)
|
|
27
|
+
|
|
28
|
+
Create a test-case registry:
|
|
29
|
+
|
|
30
|
+
**Path:** `tools/audit/test-cases.md`
|
|
31
|
+
|
|
32
|
+
### Test Case Schema (Human-Readable)
|
|
33
|
+
|
|
34
|
+
Each test case MUST include:
|
|
35
|
+
- **TC-ID** (stable)
|
|
36
|
+
- **Objective** (what is proven)
|
|
37
|
+
- **Preconditions** (if any)
|
|
38
|
+
- **Assertions** (observable guarantees)
|
|
39
|
+
- **Mapped Tests** (existing files / test names)
|
|
40
|
+
- **Audit Objective Mapping**
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 3. Canonical Test Cases (Initial Set)
|
|
45
|
+
|
|
46
|
+
### TC-SEQ-001 — Monotonic Sequence Start & Increment
|
|
47
|
+
- **Objective:** Verify sequence numbering starts at baseline and increments strictly.
|
|
48
|
+
- **Assertions:**
|
|
49
|
+
- First `step()` has sequence = 0
|
|
50
|
+
- Each subsequent `step()` increments by +1
|
|
51
|
+
- No duplicates or skips
|
|
52
|
+
- **Mapped Tests:**
|
|
53
|
+
- `tests/sequence_monotonic.test.ts`
|
|
54
|
+
- **Audit Mapping:** Determinism, Replay Safety
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
### TC-CLK-001 — Strict Monotonic Time
|
|
59
|
+
- **Objective:** Verify `monotonic_time` strictly increases across rapid calls.
|
|
60
|
+
- **Assertions:**
|
|
61
|
+
- `monotonic_time[n+1] > monotonic_time[n]`
|
|
62
|
+
- **Mapped Tests:**
|
|
63
|
+
- `tests/sequence_monotonic.test.ts`
|
|
64
|
+
- **Audit Mapping:** Determinism
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
### TC-REC-001 — Canonical Step Record Integrity
|
|
69
|
+
- **Objective:** Verify Step Record shape, fields, and immutability.
|
|
70
|
+
- **Assertions:**
|
|
71
|
+
- All required fields present
|
|
72
|
+
- No forbidden fields
|
|
73
|
+
- Record is immutable after creation
|
|
74
|
+
- **Mapped Tests:**
|
|
75
|
+
- `tests/record_builder.test.ts`
|
|
76
|
+
- `tests/step1_compliance.test.ts`
|
|
77
|
+
- **Audit Mapping:** Contract Fidelity
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
### TC-FAN-001 — Fan-out Isolation & Outcome Classification
|
|
82
|
+
- **Objective:** Verify sink fan-out does not mutate records and isolates failures.
|
|
83
|
+
- **Assertions:**
|
|
84
|
+
- All sinks receive identical records
|
|
85
|
+
- Secondary sink failure does not abort execution
|
|
86
|
+
- **Mapped Tests:**
|
|
87
|
+
- `tests/fanout.test.ts`
|
|
88
|
+
- **Audit Mapping:** Evidence Safety
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
### TC-SPL-001 — Degraded Mode & Emergency Spool
|
|
93
|
+
- **Objective:** Verify evidence preservation on authoritative sink failure.
|
|
94
|
+
- **Assertions:**
|
|
95
|
+
- Evidence is spooled
|
|
96
|
+
- Outcome = DEGRADED
|
|
97
|
+
- No silent loss
|
|
98
|
+
- **Mapped Tests:**
|
|
99
|
+
- `tests/fanout_spool.test.ts`
|
|
100
|
+
- **Audit Mapping:** Evidence Durability
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
### TC-MSG-001 — Message & Context Constraints
|
|
105
|
+
- **Objective:** Verify payload and context limits are enforced deterministically.
|
|
106
|
+
- **Assertions:**
|
|
107
|
+
- Oversized payloads rejected
|
|
108
|
+
- No implicit truncation
|
|
109
|
+
- **Mapped Tests:**
|
|
110
|
+
- `tests/message_constraints.test.ts`
|
|
111
|
+
- **Audit Mapping:** LLM Safety
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
### TC-SNK-001 — NDJSON Evidence Persistence
|
|
116
|
+
- **Objective:** Verify file sink writes valid NDJSON evidence.
|
|
117
|
+
- **Assertions:**
|
|
118
|
+
- One record per line
|
|
119
|
+
- No corruption across writes
|
|
120
|
+
- **Mapped Tests:**
|
|
121
|
+
- `tests/sinks_file_ndjson.test.ts`
|
|
122
|
+
- **Audit Mapping:** Evidence Storage
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## 4. Execution & Result Capture
|
|
127
|
+
|
|
128
|
+
### Command (example)
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
npm test -- --runInBand --json --outputFile=tools/audit/test-results.json
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Produces a **machine-readable execution artifact**.
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## 5. Traceability Matrix (Generated)
|
|
139
|
+
|
|
140
|
+
Create a generated file:
|
|
141
|
+
|
|
142
|
+
**Path:** `tools/audit/test-traceability.json`
|
|
143
|
+
|
|
144
|
+
### Example Structure
|
|
145
|
+
|
|
146
|
+
```json
|
|
147
|
+
{
|
|
148
|
+
"TC-SEQ-001": {
|
|
149
|
+
"tests": ["sequence_monotonic.test.ts"],
|
|
150
|
+
"status": "PASS",
|
|
151
|
+
"run_id": "2026-01-18T10:22:11Z"
|
|
152
|
+
},
|
|
153
|
+
"TC-SPL-001": {
|
|
154
|
+
"tests": ["fanout_spool.test.ts"],
|
|
155
|
+
"status": "PASS",
|
|
156
|
+
"run_id": "2026-01-18T10:22:11Z"
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
This can be produced by a **small parser** over the test runner JSON output.
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## 6. Audit-Grade Outputs
|
|
166
|
+
|
|
167
|
+
After execution, you have:
|
|
168
|
+
|
|
169
|
+
1. `test-cases.md` — declarative intent
|
|
170
|
+
2. `test-results.json` — raw execution evidence
|
|
171
|
+
3. `test-traceability.json` — TC → Result mapping
|
|
172
|
+
4. `test-coverage-report.md` — narrative coverage (already generated)
|
|
173
|
+
|
|
174
|
+
Together, these form a **complete, defensible test evidence bundle**.
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## 7. What This Enables
|
|
179
|
+
|
|
180
|
+
- Freeze-gate validation with proof
|
|
181
|
+
- Regression detection across runs
|
|
182
|
+
- CI enforcement (fail if any TC fails)
|
|
183
|
+
- External audit consumption
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## 8. Next Steps (Optional)
|
|
188
|
+
|
|
189
|
+
- Generate `test-cases.md` automatically from this doc
|
|
190
|
+
- Add CI job to publish traceability artifacts
|
|
191
|
+
- Extend model to validators/ tools
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
**Key Principle:**
|
|
196
|
+
> Tests already prove behavior. This layer proves **what** they prove, **when**, and **with what result**.
|
|
197
|
+
|