Stage 1 complete: shared packages with full test coverage

- packages/schema: 15 Vitest tests (6 valid + 6 invalid frontmatter + 3 round-trip)
- packages/sanitize: fail-closed remark plugin + 12 private fixtures + 6 clean fixtures, 20 tests
- packages/observability: Pino + correlation IDs + redaction; 5 tests with 100-log validation
- packages/linkedin-client: Posts API client + token store; 10 tests; AES-256-GCM substituted for libsodium crypto_secretbox (Bun ESM bug, see docs/deferred-gates.md D-001)

50/50 tests pass across 4 packages. All Stage 1 DoDs verified.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Angelo B. J. Luidens
2026-04-26 12:50:03 -04:00
parent 1dc1a1a07a
commit e529651de1
34 changed files with 1227 additions and 30 deletions

View File

@@ -0,0 +1,106 @@
import { describe, expect, it } from "vitest";
import pino from "pino";
import { newCorrelationId } from "./index";
const captureLogs = (n: number, mutate: (log: pino.Logger, i: number) => void): unknown[] => {
const lines: unknown[] = [];
const stream = {
write: (chunk: string) => {
const trimmed = chunk.trim();
if (trimmed) lines.push(JSON.parse(trimmed));
return true;
},
};
const log = pino(
{
level: "trace",
redact: {
paths: [
"access_token",
"refresh_token",
"access_token_ct",
"refresh_token_ct",
"client_secret",
"*.access_token",
"*.refresh_token",
"*.client_secret",
],
censor: "[REDACTED]",
},
formatters: { level: (label) => ({ level: label }) },
timestamp: pino.stdTimeFunctions.isoTime,
},
stream as pino.DestinationStream,
);
for (let i = 0; i < n; i++) mutate(log, i);
return lines;
};
const REQUIRED_KEYS = ["level", "msg", "time"];
describe("logger — JSON-schema check across 100 sample logs", () => {
it("emits 100 well-formed JSON lines with required keys", () => {
const logs = captureLogs(100, (log, i) => {
const child = log.child({
correlation_id: newCorrelationId(),
subject: `subject-${i}`,
});
child.info({ event: "publish.scheduled", outlet: i % 2 === 0 ? "linkedin.member" : "stargue.com" }, `event ${i}`);
});
expect(logs).toHaveLength(100);
for (const line of logs) {
const obj = line as Record<string, unknown>;
for (const k of REQUIRED_KEYS) expect(obj).toHaveProperty(k);
expect(obj).toHaveProperty("correlation_id");
expect(obj).toHaveProperty("subject");
expect(typeof obj.correlation_id).toBe("string");
expect((obj.correlation_id as string).startsWith("corr_")).toBe(true);
expect(typeof obj.time).toBe("string");
expect(obj.level).toBe("info");
}
});
it("redacts sensitive token fields at top-level and nested", () => {
const [line] = captureLogs(1, (log) => {
log.info(
{
access_token: "should-be-hidden",
refresh_token_ct: "encrypted-blob",
client_secret: "shhh",
token: { access_token: "nested-hidden", refresh_token: "nested-also" },
},
"redaction-test",
);
});
const obj = line as Record<string, unknown>;
expect(obj.access_token).toBe("[REDACTED]");
expect(obj.refresh_token_ct).toBe("[REDACTED]");
expect(obj.client_secret).toBe("[REDACTED]");
const nested = obj.token as Record<string, unknown>;
expect(nested.access_token).toBe("[REDACTED]");
expect(nested.refresh_token).toBe("[REDACTED]");
});
it("emits levels as text labels not numbers", () => {
const logs = captureLogs(4, (log, i) => {
const fns: Array<keyof pino.Logger> = ["debug", "info", "warn", "error"];
const fn = fns[i] as keyof pino.Logger;
(log[fn] as (msg: string) => void)("level-test");
});
const labels = (logs as Array<Record<string, unknown>>).map((l) => l.level);
expect(labels).toEqual(["debug", "info", "warn", "error"]);
});
});
describe("newCorrelationId", () => {
it("returns unique IDs across 1000 calls", () => {
const set = new Set<string>();
for (let i = 0; i < 1000; i++) set.add(newCorrelationId());
expect(set.size).toBe(1000);
});
it("matches expected shape: corr_<base36-time>_<base36-rand>", () => {
const id = newCorrelationId();
expect(id).toMatch(/^corr_[a-z0-9]+_[a-z0-9]{8}$/);
});
});