@shivaedev/platform 0.19.0 → 0.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README.md +33 -8
  3. package/dist/server/RedactionPolicy.d.ts +4 -0
  4. package/dist/server/RedactionPolicy.d.ts.map +1 -0
  5. package/dist/server/RedactionPolicy.js +4 -0
  6. package/dist/server/RedactionPolicy.js.map +1 -0
  7. package/dist/server/appHostHttp.d.ts +3 -3
  8. package/dist/server/appHostHttp.d.ts.map +1 -1
  9. package/dist/server/appHostHttp.js +10 -5
  10. package/dist/server/appHostHttp.js.map +1 -1
  11. package/dist/server/hostOptions.d.ts +1 -0
  12. package/dist/server/hostOptions.d.ts.map +1 -1
  13. package/dist/server/otlpHttpClient.d.ts.map +1 -1
  14. package/dist/server/otlpHttpClient.js +3 -1
  15. package/dist/server/otlpHttpClient.js.map +1 -1
  16. package/dist/server/otlpTracing.d.ts.map +1 -1
  17. package/dist/server/otlpTracing.js +4 -1
  18. package/dist/server/otlpTracing.js.map +1 -1
  19. package/dist/server/redactingDiagnostics.d.ts +5 -0
  20. package/dist/server/redactingDiagnostics.d.ts.map +1 -0
  21. package/dist/server/redactingDiagnostics.js +25 -0
  22. package/dist/server/redactingDiagnostics.js.map +1 -0
  23. package/dist/server/redactingRpcSerialization.d.ts +4 -0
  24. package/dist/server/redactingRpcSerialization.d.ts.map +1 -0
  25. package/dist/server/redactingRpcSerialization.js +74 -0
  26. package/dist/server/redactingRpcSerialization.js.map +1 -0
  27. package/dist/server/redactingTracer.d.ts +4 -0
  28. package/dist/server/redactingTracer.d.ts.map +1 -0
  29. package/dist/server/redactingTracer.js +32 -0
  30. package/dist/server/redactingTracer.js.map +1 -0
  31. package/dist/server/rpc-server/local.d.ts.map +1 -1
  32. package/dist/server/rpc-server/local.js +10 -2
  33. package/dist/server/rpc-server/local.js.map +1 -1
  34. package/dist/server/rpc-server/redact.d.ts +2 -1
  35. package/dist/server/rpc-server/redact.d.ts.map +1 -1
  36. package/dist/server/rpc-server/redact.js +26 -18
  37. package/dist/server/rpc-server/redact.js.map +1 -1
  38. package/dist/server/rpc-server/redactCause.d.ts +2 -1
  39. package/dist/server/rpc-server/redactCause.d.ts.map +1 -1
  40. package/dist/server/rpc-server/redactCause.js +64 -8
  41. package/dist/server/rpc-server/redactCause.js.map +1 -1
  42. package/dist/server/rpc-server/sensitive.d.ts +2 -1
  43. package/dist/server/rpc-server/sensitive.d.ts.map +1 -1
  44. package/dist/server/rpc-server/sensitive.js +8 -2
  45. package/dist/server/rpc-server/sensitive.js.map +1 -1
  46. package/dist/server/rpc-server/tracing.d.ts +1 -1
  47. package/dist/server/rpc-server/tracing.d.ts.map +1 -1
  48. package/dist/server/rpc-server/tracing.js +9 -3
  49. package/dist/server/rpc-server/tracing.js.map +1 -1
  50. package/dist/server/safeOtlpSerialization.d.ts +2 -1
  51. package/dist/server/safeOtlpSerialization.d.ts.map +1 -1
  52. package/dist/server/safeOtlpSerialization.js +32 -21
  53. package/dist/server/safeOtlpSerialization.js.map +1 -1
  54. package/dist/server/schemaSensitiveKeys.d.ts +5 -0
  55. package/dist/server/schemaSensitiveKeys.d.ts.map +1 -0
  56. package/dist/server/schemaSensitiveKeys.js +143 -0
  57. package/dist/server/schemaSensitiveKeys.js.map +1 -0
  58. package/package.json +5 -5
  59. package/src/server/RedactionPolicy.ts +4 -0
  60. package/src/server/appHostHttp.ts +12 -5
  61. package/src/server/hostOptions.ts +1 -0
  62. package/src/server/otlpHttpClient.ts +3 -1
  63. package/src/server/otlpTracing.ts +4 -1
  64. package/src/server/redactingDiagnostics.ts +33 -0
  65. package/src/server/redactingRpcSerialization.ts +85 -0
  66. package/src/server/redactingTracer.ts +37 -0
  67. package/src/server/rpc-server/local.ts +11 -2
  68. package/src/server/rpc-server/redact.ts +26 -18
  69. package/src/server/rpc-server/redactCause.ts +73 -9
  70. package/src/server/rpc-server/sensitive.ts +8 -2
  71. package/src/server/rpc-server/tracing.ts +9 -4
  72. package/src/server/safeOtlpSerialization.ts +44 -34
  73. package/src/server/schemaSensitiveKeys.ts +148 -0
@@ -1 +1 @@
1
- {"version":3,"file":"tracing.js","sourceRoot":"","sources":["../../../src/server/rpc-server/tracing.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tracing.js","sourceRoot":"","sources":["../../../src/server/rpc-server/tracing.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { Layer } from "effect";
2
2
  import { OtlpSerialization } from "effect/observability";
3
- export declare function redactOtlpText(value: string, key?: string): string;
3
+ import { type SensitiveKey } from "#server/rpc-server/sensitive.ts";
4
+ export declare function redactOtlpText(value: string, key?: string, sensitive?: SensitiveKey): string;
4
5
  export declare const safeOtlpSerialization: Layer.Layer<OtlpSerialization.OtlpSerialization, never, OtlpSerialization.OtlpSerialization>;
5
6
  //# sourceMappingURL=safeOtlpSerialization.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"safeOtlpSerialization.d.ts","sourceRoot":"","sources":["../../src/server/safeOtlpSerialization.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,EAAE,MAAM,QAAQ,CAAC;AAEvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAOzD,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,SAAK,UAErD;AA2BD,eAAO,MAAM,qBAAqB,8FAwBjC,CAAC"}
1
+ {"version":3,"file":"safeOtlpSerialization.d.ts","sourceRoot":"","sources":["../../src/server/safeOtlpSerialization.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,EAAE,MAAM,QAAQ,CAAC;AAEvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAGzD,OAAO,EAAwC,KAAK,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAK1G,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,SAAK,EAAE,SAAS,GAAE,YAA6B,UAE/F;AAkDD,eAAO,MAAM,qBAAqB,8FAUjC,CAAC"}
@@ -1,25 +1,26 @@
1
1
  import { Effect, Layer } from "effect";
2
2
  import { OtlpSerialization } from "effect/observability";
3
+ import { RedactionPolicy } from "#server/RedactionPolicy.ts";
3
4
  import { redactOtlpUrl } from "#server/redactOtlpUrl.ts";
4
5
  import { isSensitiveKey, REDACTED, redactText } from "#server/rpc-server/sensitive.ts";
5
- function sensitive(key) {
6
- return isSensitiveKey(key) || ["db.user", "db.user.name", "db.connection_string"].includes(key.toLowerCase());
6
+ function otlpSensitive(sensitive) {
7
+ return (key) => sensitive(key) || ["db.user", "db.user.name", "db.connection_string"].includes(key.toLowerCase());
7
8
  }
8
- export function redactOtlpText(value, key = "") {
9
- return redactText(redactOtlpUrl(value, key), sensitive);
9
+ export function redactOtlpText(value, key = "", sensitive = isSensitiveKey) {
10
+ return redactText(redactOtlpUrl(value, key), otlpSensitive(sensitive));
10
11
  }
11
- function attributeValue(value, key) {
12
+ function attributeValue(value, key, sensitive) {
12
13
  return {
13
14
  ...value,
14
- ...(typeof value.stringValue === "string" ? { stringValue: redactOtlpText(value.stringValue, key) } : {}),
15
- ...(value.arrayValue ? { arrayValue: { values: value.arrayValue.values.map((item) => attributeValue(item, key)) } } : {}),
16
- ...(value.kvlistValue ? { kvlistValue: { values: attributes(value.kvlistValue.values) } } : {}),
15
+ ...(typeof value.stringValue === "string" ? { stringValue: redactOtlpText(value.stringValue, key, sensitive) } : {}),
16
+ ...(value.arrayValue ? { arrayValue: { values: value.arrayValue.values.map((item) => attributeValue(item, key, sensitive)) } } : {}),
17
+ ...(value.kvlistValue ? { kvlistValue: { values: attributes(value.kvlistValue.values, sensitive) } } : {}),
17
18
  };
18
19
  }
19
- function attributes(values) {
20
+ function attributes(values, sensitive) {
20
21
  return values.map(({ key, value }) => ({
21
22
  key,
22
- value: sensitive(key) ? { stringValue: REDACTED } : attributeValue(value, key),
23
+ value: sensitive(key) ? { stringValue: REDACTED } : attributeValue(value, key, sensitive),
23
24
  }));
24
25
  }
25
26
  function spanName(span) {
@@ -32,25 +33,35 @@ function spanName(span) {
32
33
  }
33
34
  return span.name;
34
35
  }
35
- export const safeOtlpSerialization = Layer.effect(OtlpSerialization.OtlpSerialization, Effect.map(OtlpSerialization.OtlpSerialization, (serialization) => ({
36
- ...serialization,
37
- traces: (data) => serialization.traces({
36
+ function redactTraces(data, sensitive) {
37
+ function text(value) {
38
+ return redactOtlpText(value, "", sensitive);
39
+ }
40
+ return {
38
41
  ...data,
39
42
  resourceSpans: data.resourceSpans.map((resource) => ({
40
43
  ...resource,
41
- resource: { ...resource.resource, attributes: attributes(resource.resource.attributes) },
44
+ resource: { ...resource.resource, attributes: attributes(resource.resource.attributes, sensitive) },
42
45
  scopeSpans: resource.scopeSpans.map((scope) => ({
43
46
  ...scope,
44
47
  spans: scope.spans.map((span) => ({
45
48
  ...span,
46
- attributes: attributes(span.attributes),
47
- events: span.events.map((event) => ({ ...event, attributes: attributes(event.attributes), name: redactOtlpText(event.name) })),
48
- links: span.links.map((link) => ({ ...link, attributes: attributes(link.attributes) })),
49
- name: redactOtlpText(spanName(span)),
50
- status: { ...span.status, ...(span.status.message === undefined ? {} : { message: redactOtlpText(span.status.message) }) },
49
+ attributes: attributes(span.attributes, sensitive),
50
+ events: span.events.map((event) => ({ ...event, attributes: attributes(event.attributes, sensitive), name: text(event.name) })),
51
+ links: span.links.map((link) => ({ ...link, attributes: attributes(link.attributes, sensitive) })),
52
+ name: text(spanName(span)),
53
+ status: { ...span.status, ...(span.status.message === undefined ? {} : { message: text(span.status.message) }) },
51
54
  })),
52
55
  })),
53
56
  })),
54
- }),
55
- })));
57
+ };
58
+ }
59
+ export const safeOtlpSerialization = Layer.effect(OtlpSerialization.OtlpSerialization, Effect.gen(function* () {
60
+ const serialization = yield* OtlpSerialization.OtlpSerialization;
61
+ const sensitive = otlpSensitive(yield* RedactionPolicy);
62
+ return OtlpSerialization.OtlpSerialization.of({
63
+ ...serialization,
64
+ traces: (data) => serialization.traces(redactTraces(data, sensitive)),
65
+ });
66
+ }));
56
67
  //# sourceMappingURL=safeOtlpSerialization.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"safeOtlpSerialization.js","sourceRoot":"","sources":["../../src/server/safeOtlpSerialization.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"safeOtlpSerialization.js","sourceRoot":"","sources":["../../src/server/safeOtlpSerialization.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { Rpc, type RpcGroup } from "effect/rpc";
2
+ export declare function schemaSensitiveKeys<R extends Rpc.Any>(group: RpcGroup.RpcGroup<R>, extra?: readonly string[]): ((key: string) => boolean) & {
3
+ maskFailure: (tag: string | undefined, reason: "Fail" | "Die") => boolean;
4
+ };
5
+ //# sourceMappingURL=schemaSensitiveKeys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemaSensitiveKeys.d.ts","sourceRoot":"","sources":["../../src/server/schemaSensitiveKeys.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAC;AA0GhD,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,GAAE,SAAS,MAAM,EAAO,UAoCrF,MAAM;uBACb,MAAM,GAAG,SAAS,UAAU,MAAM,GAAG,KAAK;EAG9D"}
@@ -0,0 +1,143 @@
1
+ import { Predicate } from "effect";
2
+ import { Rpc } from "effect/rpc";
3
+ import { isSensitiveKey } from "#server/rpc-server/sensitive.ts";
4
+ function children(ast) {
5
+ switch (ast._tag) {
6
+ case "Objects":
7
+ return [...ast.propertySignatures.map((property) => property.type), ...ast.indexSignatures.flatMap((index) => [index.parameter, index.type])];
8
+ case "Arrays":
9
+ return [...ast.elements, ...ast.rest];
10
+ case "Union":
11
+ return ast.types;
12
+ case "Declaration":
13
+ return ast.typeParameters;
14
+ case "Suspend":
15
+ return [ast.thunk()];
16
+ default:
17
+ return [];
18
+ }
19
+ }
20
+ function sensitiveCheck(check) {
21
+ return check.annotations?.sensitive === true || (check._tag === "FilterGroup" && check.checks.some(sensitiveCheck));
22
+ }
23
+ function marked(ast, seen = new Set()) {
24
+ if (seen.has(ast)) {
25
+ return false;
26
+ }
27
+ seen.add(ast);
28
+ if (ast.annotations?.sensitive === true
29
+ || ast.context?.annotations?.sensitive === true
30
+ || ast.checks?.some(sensitiveCheck)
31
+ || (Predicate.hasProperty(ast.annotations?.representation, "id") && ast.annotations.representation.id === "effect/schema/Redacted")) {
32
+ return true;
33
+ }
34
+ const nested = ast._tag === "Objects" ? ast.indexSignatures.map((index) => index.type) : children(ast);
35
+ return (ast.encoding?.some((link) => marked(link.to, seen)) ?? false) || nested.some((type) => marked(type, seen));
36
+ }
37
+ function containsSensitive(ast, keys) {
38
+ return (marked(ast)
39
+ || propertiesOf(ast).some((property) => typeof property.name === "string" && (keys.has(property.name) || isSensitiveKey(property.name))));
40
+ }
41
+ function collectEncodedKeys(ast, keys) {
42
+ let source = ast;
43
+ let sensitive = false;
44
+ for (const link of ast.encoding ?? []) {
45
+ sensitive ||= containsSensitive(source, keys);
46
+ if (sensitive) {
47
+ for (const property of propertiesOf(link.to)) {
48
+ if (typeof property.name === "string") {
49
+ keys.add(property.name);
50
+ }
51
+ }
52
+ }
53
+ source = link.to;
54
+ }
55
+ }
56
+ function fixedOutput(ast) {
57
+ if (ast._tag === "Union") {
58
+ return ast.types.every(fixedOutput);
59
+ }
60
+ return ast._tag === "Objects" && ast.indexSignatures.length === 0;
61
+ }
62
+ function maskedValue(ast, keys, seen = new Set()) {
63
+ if (seen.has(ast)) {
64
+ return false;
65
+ }
66
+ seen.add(ast);
67
+ if (marked(ast)) {
68
+ return true;
69
+ }
70
+ let source = ast;
71
+ let sensitive = false;
72
+ for (const link of ast.encoding ?? []) {
73
+ sensitive ||= containsSensitive(source, keys);
74
+ if (sensitive && !fixedOutput(link.to)) {
75
+ return true;
76
+ }
77
+ source = link.to;
78
+ }
79
+ const nested = ast._tag === "Objects" ? ast.indexSignatures.map((index) => index.type) : children(ast);
80
+ return nested.some((type) => maskedValue(type, keys, seen));
81
+ }
82
+ function collect(ast, nodes, encodings = true) {
83
+ if (nodes.has(ast)) {
84
+ return;
85
+ }
86
+ nodes.add(ast);
87
+ for (const child of [...children(ast), ...(encodings ? (ast.encoding?.map((link) => link.to) ?? []) : [])]) {
88
+ collect(child, nodes, encodings);
89
+ }
90
+ }
91
+ function propertiesOf(ast) {
92
+ const nodes = new Set();
93
+ collect(ast, nodes, false);
94
+ return [...nodes].flatMap((node) => (node._tag === "Objects" ? node.propertySignatures : []));
95
+ }
96
+ function collectFieldKeys(properties, keys, sensitive) {
97
+ for (const property of properties) {
98
+ if (typeof property.name === "string" && sensitive(property.type)) {
99
+ keys.add(property.name);
100
+ }
101
+ }
102
+ }
103
+ export function schemaSensitiveKeys(group, extra = []) {
104
+ const keys = new Set(extra);
105
+ const nodes = new Set();
106
+ const requests = [];
107
+ for (const rpc of group.requests.values()) {
108
+ if (Rpc.isRpc(rpc)) {
109
+ requests.push(rpc);
110
+ }
111
+ }
112
+ for (const rpc of requests) {
113
+ const schemas = [
114
+ rpc.payloadSchema,
115
+ rpc.successSchema,
116
+ rpc.errorSchema,
117
+ rpc.defectSchema,
118
+ ...[...rpc.middlewares].map((m) => m.error),
119
+ ];
120
+ for (const schema of schemas) {
121
+ collect(schema.ast, nodes);
122
+ }
123
+ }
124
+ const properties = [...nodes].flatMap((ast) => (ast._tag === "Objects" ? ast.propertySignatures : []));
125
+ collectFieldKeys(properties, keys, marked);
126
+ let previousSize;
127
+ do {
128
+ previousSize = keys.size;
129
+ collectFieldKeys(properties, keys, (ast) => maskedValue(ast, keys));
130
+ for (const ast of nodes) {
131
+ collectEncodedKeys(ast, keys);
132
+ }
133
+ } while (keys.size !== previousSize);
134
+ const roots = requests.map((rpc) => ({
135
+ die: maskedValue(rpc.defectSchema.ast, keys),
136
+ fail: [rpc.errorSchema, ...[...rpc.middlewares].map((m) => m.error)].some((schema) => maskedValue(schema.ast, keys)),
137
+ tag: rpc._tag,
138
+ }));
139
+ return Object.assign((key) => keys.has(key) || isSensitiveKey(key), {
140
+ maskFailure: (tag, reason) => roots.some((root) => (tag === undefined || tag === root.tag) && (reason === "Fail" ? root.fail : root.die)),
141
+ });
142
+ }
143
+ //# sourceMappingURL=schemaSensitiveKeys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemaSensitiveKeys.js","sourceRoot":"","sources":["../../src/server/schemaSensitiveKeys.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAA+B,MAAM,QAAQ,CAAC;AAChE,OAAO,EAAE,GAAG,EAAiB,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEjE,SAAS,QAAQ,CAAC,GAAkB;IACnC,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,SAAS;YACb,OAAO,CAAC,GAAG,GAAG,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,GAAG,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC/I,KAAK,QAAQ;YACZ,OAAO,CAAC,GAAG,GAAG,CAAC,QAAQ,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;QACvC,KAAK,OAAO;YACX,OAAO,GAAG,CAAC,KAAK,CAAC;QAClB,KAAK,aAAa;YACjB,OAAO,GAAG,CAAC,cAAc,CAAC;QAC3B,KAAK,SAAS;YACb,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC;QACtB;YACC,OAAO,EAAE,CAAC;IACZ,CAAC;AACF,CAAC;AACD,SAAS,cAAc,CAAC,KAA6B;IACpD,OAAO,KAAK,CAAC,WAAW,EAAE,SAAS,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,aAAa,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC;AACrH,CAAC;AACD,SAAS,MAAM,CAAC,GAAkB,EAAE,IAAI,GAAG,IAAI,GAAG,EAAiB;IAClE,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;QACnB,OAAO,KAAK,CAAC;IACd,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACd,IACC,GAAG,CAAC,WAAW,EAAE,SAAS,KAAK,IAAI;WAChC,GAAG,CAAC,OAAO,EAAE,WAAW,EAAE,SAAS,KAAK,IAAI;WAC5C,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,cAAc,CAAC;WAChC,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,WAAW,EAAE,cAAc,EAAE,IAAI,CAAC,IAAI,GAAG,CAAC,WAAW,CAAC,cAAc,CAAC,EAAE,KAAK,wBAAwB,CAAC,EAClI,CAAC;QACF,OAAO,IAAI,CAAC;IACb,CAAC;IACD,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IACvG,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;AACpH,CAAC;AACD,SAAS,iBAAiB,CAAC,GAAkB,EAAE,IAAyB;IACvE,OAAO,CACN,MAAM,CAAC,GAAG,CAAC;WACR,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,OAAO,QAAQ,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CACxI,CAAC;AACH,CAAC;AACD,SAAS,kBAAkB,CAAC,GAAkB,EAAE,IAAiB;IAChE,IAAI,MAAM,GAAG,GAAG,CAAC;IACjB,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;QACvC,SAAS,KAAK,iBAAiB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC9C,IAAI,SAAS,EAAE,CAAC;YACf,KAAK,MAAM,QAAQ,IAAI,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;gBAC9C,IAAI,OAAO,QAAQ,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBACvC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;gBACzB,CAAC;YACF,CAAC;QACF,CAAC;QACD,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;IAClB,CAAC;AACF,CAAC;AACD,SAAS,WAAW,CAAC,GAAkB;IACtC,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC1B,OAAO,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,GAAG,CAAC,eAAe,CAAC,MAAM,KAAK,CAAC,CAAC;AACnE,CAAC;AACD,SAAS,WAAW,CAAC,GAAkB,EAAE,IAAyB,EAAE,IAAI,GAAG,IAAI,GAAG,EAAiB;IAClG,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;QACnB,OAAO,KAAK,CAAC;IACd,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACd,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;QACjB,OAAO,IAAI,CAAC;IACb,CAAC;IACD,IAAI,MAAM,GAAG,GAAG,CAAC;IACjB,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;QACvC,SAAS,KAAK,iBAAiB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC9C,IAAI,SAAS,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YACxC,OAAO,IAAI,CAAC;QACb,CAAC;QACD,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;IAClB,CAAC;IACD,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IACvG,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;AAC7D,CAAC;AACD,SAAS,OAAO,CAAC,GAAkB,EAAE,KAAyB,EAAE,SAAS,GAAG,IAAI;IAC/E,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;QACpB,OAAO;IACR,CAAC;IACD,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACf,KAAK,MAAM,KAAK,IAAI,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QAC5G,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;IAClC,CAAC;AACF,CAAC;AACD,SAAS,YAAY,CAAC,GAAkB;IACvC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAiB,CAAC;IACvC,OAAO,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IAC3B,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAC/F,CAAC;AACD,SAAS,gBAAgB,CAAC,UAAmD,EAAE,IAAiB,EAAE,SAA0C;IAC3I,KAAK,MAAM,QAAQ,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,OAAO,QAAQ,CAAC,IAAI,KAAK,QAAQ,IAAI,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACnE,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACzB,CAAC;IACF,CAAC;AACF,CAAC;AACD,MAAM,UAAU,mBAAmB,CAAoB,KAA2B,EAAE,KAAK,GAAsB,EAAE;IAChH,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IAC5B,MAAM,KAAK,GAAG,IAAI,GAAG,EAAiB,CAAC;IACvC,MAAM,QAAQ,GAAuB,EAAE,CAAC;IACxC,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;QAC3C,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;YACpB,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC;IACF,CAAC;IACD,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAiB;YAC7B,GAAG,CAAC,aAAa;YACjB,GAAG,CAAC,aAAa;YACjB,GAAG,CAAC,WAAW;YACf,GAAG,CAAC,YAAY;YAChB,GAAG,CAAC,GAAG,GAAG,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;SAC3C,CAAC;QACF,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC9B,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC5B,CAAC;IACF,CAAC;IACD,MAAM,UAAU,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACvG,gBAAgB,CAAC,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IAC3C,IAAI,YAAoB,CAAC;IACzB,GAAG,CAAC;QACH,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC;QACzB,gBAAgB,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;QACpE,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;YACzB,kBAAkB,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC/B,CAAC;IACF,CAAC,QAAQ,IAAI,CAAC,IAAI,KAAK,YAAY,EAAE;IACrC,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACpC,GAAG,EAAE,WAAW,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC;QAC5C,IAAI,EAAE,CAAC,GAAG,CAAC,WAAW,EAAE,GAAG,CAAC,GAAG,GAAG,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACpH,GAAG,EAAE,GAAG,CAAC,IAAI;KACb,CAAC,CAAC,CAAC;IACJ,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,GAAW,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,cAAc,CAAC,GAAG,CAAC,EAAE;QAC3E,WAAW,EAAE,CAAC,GAAuB,EAAE,MAAsB,EAAE,EAAE,CAChE,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;KAC5G,CAAC,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shivaedev/platform",
3
- "version": "0.19.0",
3
+ "version": "0.20.1",
4
4
  "description": "Opinionated Effect application infrastructure for ShivaeDev services",
5
5
  "homepage": "https://github.com/ShivaeDev/platform/tree/main/packages/platform#readme",
6
6
  "bugs": {
@@ -41,7 +41,7 @@
41
41
  ],
42
42
  "dependencies": {
43
43
  "@shivaedev/effect-contract": "0.6.0",
44
- "@shivaedev/effect-sql": "0.7.0",
44
+ "@shivaedev/effect-sql": "0.8.0",
45
45
  "@shivaedev/types": "0.2.1"
46
46
  },
47
47
  "devDependencies": {
@@ -55,10 +55,10 @@
55
55
  "@prisma-next/sql-orm-client": "0.16.0",
56
56
  "@prisma-next/target-postgres": "0.16.0",
57
57
  "@shivaedev/effect-prisma": "0.10.2",
58
- "@shivaedev/effect-test-sql": "0.6.1",
58
+ "@shivaedev/effect-test-sql": "0.7.1",
59
59
  "@shivaedev/effect-trpc": "0.8.2",
60
- "@shivaedev/quality": "0.28.0",
61
- "@shivaedev/test-story": "0.12.0",
60
+ "@shivaedev/quality": "0.28.2",
61
+ "@shivaedev/test-story": "0.13.0",
62
62
  "@trpc/client": "11.19.0",
63
63
  "@trpc/server": "11.19.0",
64
64
  "@types/node": "24.19.2",
@@ -0,0 +1,4 @@
1
+ import { Context } from "effect";
2
+ import { isSensitiveKey, type SensitiveKey } from "#server/rpc-server/sensitive.ts";
3
+
4
+ export const RedactionPolicy = Context.Reference<SensitiveKey>("@shivaedev/platform/RedactionPolicy", { defaultValue: () => isSensitiveKey });
@@ -12,10 +12,14 @@ import { hostChanges } from "#server/hostChanges.ts";
12
12
  import type { HostOptions, HostPolicy } from "#server/hostOptions.ts";
13
13
  import type { MigrationOptions } from "#server/MigrationOptions.ts";
14
14
  import { otlpTracing } from "#server/otlpTracing.ts";
15
+ import { RedactionPolicy } from "#server/RedactionPolicy.ts";
16
+ import { redactingDiagnostics } from "#server/redactingDiagnostics.ts";
17
+ import { redactingRpcSerialization } from "#server/redactingRpcSerialization.ts";
15
18
  import { localRpcGuard } from "#server/rpc-server/local.ts";
16
19
  import { authenticatedLayer, maybeAuthenticatedLayer, type SessionShape } from "#server/rpc-server/session.ts";
17
20
  import { requestTracingLayer } from "#server/rpc-server/tracing.ts";
18
21
  import { TrustedProxy } from "#server/rpc-server/trustedProxy.ts";
22
+ import { schemaSensitiveKeys } from "#server/schemaSensitiveKeys.ts";
19
23
  import { tracedGroup } from "#server/tracedGroup.ts";
20
24
  export function appHostHttp<
21
25
  TRpcs extends Rpc.Any,
@@ -30,6 +34,7 @@ export function appHostHttp<
30
34
  options: HostOptions<TRpcs, THandlers, THandlerError, THandlerRequirements, TServices, TServiceError, TServiceRequirements> & HostPolicy<TSession>,
31
35
  changesService: typeof AppChanges,
32
36
  ) {
37
+ const sensitive = schemaSensitiveKeys(options.group, options.config?.sensitiveKeys);
33
38
  return Layer.unwrap(
34
39
  Effect.gen(function* () {
35
40
  const maxBodySize = options.config?.maxBodySize ?? (yield* Config.Int("MAX_BODY_SIZE").pipe(Config.withDefault(1024 * 1024)));
@@ -45,12 +50,14 @@ export function appHostHttp<
45
50
  }
46
51
  const middleware: Layer.Layer<RequestTracing> | Layer.Layer<Authenticated | MaybeAuthenticated | RequestTracing> =
47
52
  options.policy === "loopback"
48
- ? requestTracingLayer()
49
- : Layer.mergeAll(authenticatedLayer(options.sessions), maybeAuthenticatedLayer(options.sessions), requestTracingLayer());
53
+ ? requestTracingLayer({ sensitive })
54
+ : Layer.mergeAll(authenticatedLayer(options.sessions), maybeAuthenticatedLayer(options.sessions), requestTracingLayer({ sensitive }));
50
55
  const routes = HttpRouter.use((router) =>
51
56
  Effect.gen(function* () {
52
- const wire = yield* RpcSerialization.RpcSerialization;
53
- const handler = yield* RpcServer.toHttpEffect(tracedGroup(options.group));
57
+ const wire = redactingRpcSerialization(yield* RpcSerialization.RpcSerialization, sensitive, sensitive.maskFailure);
58
+ const handler = yield* RpcServer.toHttpEffect(tracedGroup(options.group)).pipe(
59
+ Effect.provideService(RpcSerialization.RpcSerialization, wire),
60
+ );
54
61
  const guarded = localRpcGuard(handler, trustedProxy);
55
62
  yield* router.add("POST", options.rpcPath ?? "/rpc", (request) =>
56
63
  guarded.pipe(
@@ -88,7 +95,7 @@ export function appHostHttp<
88
95
  Layer.provide(NodeServices.layer),
89
96
  );
90
97
  }),
91
- ).pipe(Layer.provide(otlpTracing));
98
+ ).pipe(Layer.provide(redactingDiagnostics(sensitive)), Layer.provide(otlpTracing), Layer.provide(Layer.succeed(RedactionPolicy, sensitive)));
92
99
  }
93
100
 
94
101
  export function migratedHost<
@@ -11,6 +11,7 @@ export type HostOptions<TRpcs extends Rpc.Any, THandlers, THandlerError, THandle
11
11
  readonly host?: string;
12
12
  readonly trustedProxy?: string;
13
13
  readonly maxBodySize?: number;
14
+ readonly sensitiveKeys?: readonly string[];
14
15
  readonly disablePreemptiveShutdown?: boolean;
15
16
  };
16
17
  readonly group: RpcGroup.RpcGroup<TRpcs>;
@@ -1,5 +1,6 @@
1
1
  import { Effect, Layer } from "effect";
2
2
  import { FetchHttpClient, HttpClient, HttpClientError, type HttpClientRequest } from "effect/http";
3
+ import { RedactionPolicy } from "#server/RedactionPolicy.ts";
3
4
  import { redactOtlpText } from "#server/safeOtlpSerialization.ts";
4
5
 
5
6
  function timeoutError(request: HttpClientRequest.HttpClientRequest) {
@@ -13,6 +14,7 @@ export function otlpHttpClient(timeout = 10_000) {
13
14
  HttpClient.HttpClient,
14
15
  Effect.gen(function* () {
15
16
  const client = yield* HttpClient.HttpClient;
17
+ const sensitive = yield* RedactionPolicy;
16
18
  let warned = false;
17
19
  function warnOnce(diagnostic: Effect.Effect<Record<string, unknown>>) {
18
20
  return Effect.suspend(() => {
@@ -41,7 +43,7 @@ export function otlpHttpClient(timeout = 10_000) {
41
43
  return warnOnce(
42
44
  response.text.pipe(
43
45
  Effect.orElseSucceed(() => "Unable to read collector response"),
44
- Effect.map((body) => ({ "otlp.response": redactOtlpText(body), "otlp.status": response.status })),
46
+ Effect.map((body) => ({ "otlp.response": redactOtlpText(body, "", sensitive), "otlp.status": response.status })),
45
47
  ),
46
48
  );
47
49
  }),
@@ -1,6 +1,8 @@
1
1
  import { Config, Effect, Layer, Schema } from "effect";
2
2
  import { OtlpSerialization, OtlpTracer } from "effect/observability";
3
3
  import { otlpHttpClient } from "#server/otlpHttpClient.ts";
4
+ import { RedactionPolicy } from "#server/RedactionPolicy.ts";
5
+ import { redactingTracer } from "#server/redactingTracer.ts";
4
6
  import { safeOtlpSerialization } from "#server/safeOtlpSerialization.ts";
5
7
 
6
8
  export const otlpTracing: Layer.Layer<never, Config.ConfigError> = Layer.unwrap(
@@ -41,7 +43,7 @@ export const otlpTracing: Layer.Layer<never, Config.ConfigError> = Layer.unwrap(
41
43
  const exportInterval = yield* Config.Int("OTEL_BSP_SCHEDULE_DELAY").pipe(Config.withDefault(5000));
42
44
  const maxBatchSize = yield* Config.Int("OTEL_BSP_MAX_EXPORT_BATCH_SIZE").pipe(Config.withDefault(1000));
43
45
  const exportTimeout = yield* Config.Int("OTEL_BSP_EXPORT_TIMEOUT").pipe(Config.withDefault(3000));
44
- return OtlpTracer.layer({
46
+ const tracer = OtlpTracer.layer({
45
47
  exportInterval,
46
48
  headers,
47
49
  maxBatchSize,
@@ -54,5 +56,6 @@ export const otlpTracing: Layer.Layer<never, Config.ConfigError> = Layer.unwrap(
54
56
  ),
55
57
  Layer.provide(otlpHttpClient(requestTimeout)),
56
58
  );
59
+ return redactingTracer(yield* RedactionPolicy).pipe(Layer.provideMerge(tracer));
57
60
  }),
58
61
  );
@@ -0,0 +1,33 @@
1
+ import { Context, Effect, ErrorReporter, Layer, Logger, References } from "effect";
2
+ import { redact } from "#server/rpc-server/redact.ts";
3
+ import { redactDiagnosticCause, redactingErrorReporter } from "#server/rpc-server/redactCause.ts";
4
+ import type { SensitiveKey } from "#server/rpc-server/sensitive.ts";
5
+
6
+ export function redactRecord(values: Readonly<Record<string, unknown>>, sensitive: SensitiveKey): Record<string, unknown> {
7
+ return Object.fromEntries(Object.entries(values).map(([key, value]) => [key, sensitive(key) ? "<redacted>" : redact(value, sensitive)]));
8
+ }
9
+ export function redactingDiagnostics(sensitive: SensitiveKey) {
10
+ return Layer.effectContext(
11
+ Effect.gen(function* () {
12
+ const loggers = yield* Logger.CurrentLoggers;
13
+ const reporters = yield* ErrorReporter.CurrentErrorReporters;
14
+ const safeLoggers = new Set(
15
+ [...loggers].map((logger) =>
16
+ Logger.make((options) => {
17
+ const context = options.fiber.context;
18
+ const annotations = redactRecord(options.fiber.getRef(References.CurrentLogAnnotations), sensitive);
19
+ options.fiber.setContext(Context.add(context, References.CurrentLogAnnotations, annotations));
20
+ try {
21
+ return logger.log({ ...options, cause: redactDiagnosticCause(options.cause, sensitive), message: redact(options.message, sensitive) });
22
+ } finally {
23
+ options.fiber.setContext(context);
24
+ }
25
+ }),
26
+ ),
27
+ );
28
+ return Context.make(Logger.CurrentLoggers, safeLoggers).pipe(
29
+ Context.add(ErrorReporter.CurrentErrorReporters, new Set([...reporters].map((reporter) => redactingErrorReporter(reporter, sensitive)))),
30
+ );
31
+ }),
32
+ );
33
+ }
@@ -0,0 +1,85 @@
1
+ import { Predicate } from "effect";
2
+ import type { RpcSerialization } from "effect/rpc";
3
+ import { redactWire } from "#server/rpc-server/redact.ts";
4
+ import { REDACTED, type SensitiveKey } from "#server/rpc-server/sensitive.ts";
5
+
6
+ function isRequestId(value: unknown): value is string | number {
7
+ return typeof value === "string" || typeof value === "number";
8
+ }
9
+ export function redactingRpcSerialization(
10
+ wire: RpcSerialization.RpcSerialization["Service"],
11
+ sensitive: SensitiveKey,
12
+ maskFailure: (tag: string | undefined, reason: "Fail" | "Die") => boolean = () => false,
13
+ ): typeof wire {
14
+ function reason(value: unknown, tag: string | undefined): unknown {
15
+ const redacted = redactWire(value, sensitive);
16
+ if (Predicate.isObjectOrArray(redacted)) {
17
+ if (Predicate.isTagged(value, "Fail") && maskFailure(tag, "Fail")) {
18
+ return { ...redacted, _tag: "Fail", error: REDACTED };
19
+ }
20
+ if (Predicate.isTagged(value, "Die") && maskFailure(tag, "Die")) {
21
+ return { ...redacted, _tag: "Die", defect: REDACTED };
22
+ }
23
+ }
24
+ if (
25
+ (Predicate.isTagged(value, "Fail") || Predicate.isTagged(value, "Die") || Predicate.isTagged(value, "Interrupt"))
26
+ && Predicate.isObjectOrArray(redacted)
27
+ ) {
28
+ return { ...redacted, _tag: value._tag };
29
+ }
30
+ return redacted;
31
+ }
32
+ function exit(value: unknown, tag: string | undefined): unknown {
33
+ if (Predicate.isTagged(value, "Failure") && Predicate.hasProperty(value, "cause")) {
34
+ const cause = Array.isArray(value.cause) ? value.cause.map((item) => reason(item, tag)) : redactWire(value.cause, sensitive);
35
+ return { ...value, cause };
36
+ }
37
+ return value;
38
+ }
39
+ return {
40
+ ...wire,
41
+ makeUnsafe: () => {
42
+ const parser = wire.makeUnsafe();
43
+ const requests = new Map<string | number, string>();
44
+ function response(value: unknown): unknown {
45
+ if (Array.isArray(value)) {
46
+ return value.map(response);
47
+ }
48
+ if (Predicate.isTagged(value, "Defect") && Predicate.hasProperty(value, "defect")) {
49
+ return { ...value, defect: maskFailure(undefined, "Die") ? REDACTED : redactWire(value.defect, sensitive) };
50
+ }
51
+ if (
52
+ Predicate.isTagged(value, "Exit")
53
+ && Predicate.hasProperty(value, "requestId")
54
+ && isRequestId(value.requestId)
55
+ && Predicate.hasProperty(value, "exit")
56
+ ) {
57
+ const tag = requests.get(value.requestId);
58
+ requests.delete(value.requestId);
59
+ return { ...value, exit: exit(value.exit, tag) };
60
+ }
61
+ return value;
62
+ }
63
+ return {
64
+ ...parser,
65
+ decode: (data) => {
66
+ const decoded = parser.decode(data);
67
+ for (const request of decoded) {
68
+ if (
69
+ Predicate.isTagged(request, "Request")
70
+ && Predicate.hasProperty(request, "id")
71
+ && isRequestId(request.id)
72
+ && Predicate.hasProperty(request, "tag")
73
+ && typeof request.tag === "string"
74
+ && !requests.has(request.id)
75
+ ) {
76
+ requests.set(request.id, request.tag);
77
+ }
78
+ }
79
+ return decoded;
80
+ },
81
+ encode: (value) => parser.encode(response(value)),
82
+ };
83
+ },
84
+ };
85
+ }
@@ -0,0 +1,37 @@
1
+ import { Effect, Exit, Layer, Tracer } from "effect";
2
+ import { redactRecord } from "#server/redactingDiagnostics.ts";
3
+ import { redact } from "#server/rpc-server/redact.ts";
4
+ import { redactDiagnosticCause } from "#server/rpc-server/redactCause.ts";
5
+ import { REDACTED, type SensitiveKey } from "#server/rpc-server/sensitive.ts";
6
+
7
+ function redactLinks(values: readonly Tracer.SpanLink[], sensitive: SensitiveKey) {
8
+ return values.map((link) => ({ ...link, attributes: redactRecord(link.attributes, sensitive) }));
9
+ }
10
+ function redactSpan(span: Tracer.Span, sensitive: SensitiveKey) {
11
+ const end = span.end.bind(span);
12
+ const attribute = span.attribute.bind(span);
13
+ const event = span.event.bind(span);
14
+ const addLinks = span.addLinks.bind(span);
15
+ return Object.assign(span, {
16
+ addLinks: (values: readonly Tracer.SpanLink[]) => addLinks(redactLinks(values, sensitive)),
17
+ attribute: (key: string, value: unknown) => attribute(key, sensitive(key) ? REDACTED : redact(value, sensitive)),
18
+ end: (time: bigint, exit: Exit.Exit<unknown, unknown>) => {
19
+ for (const [key, value] of span.attributes) {
20
+ attribute(key, sensitive(key) ? REDACTED : redact(value, sensitive));
21
+ }
22
+ end(time, Exit.isFailure(exit) ? Exit.failCause(redactDiagnosticCause(exit.cause, sensitive)) : exit);
23
+ },
24
+ event: (name: string, time: bigint, attributes?: Record<string, unknown>) => event(name, time, attributes && redactRecord(attributes, sensitive)),
25
+ });
26
+ }
27
+ export function redactingTracer(sensitive: SensitiveKey) {
28
+ return Layer.effect(
29
+ Tracer.Tracer,
30
+ Effect.map(Tracer.Tracer, (tracer) =>
31
+ Tracer.make({
32
+ ...tracer,
33
+ span: (options) => redactSpan(tracer.span({ ...options, links: redactLinks(options.links, sensitive) }), sensitive),
34
+ }),
35
+ ),
36
+ );
37
+ }
@@ -1,5 +1,5 @@
1
1
  import { Effect, Option } from "effect";
2
- import { HttpServerRequest, HttpServerResponse } from "effect/http";
2
+ import { HttpServerRequest, HttpServerResponse, HttpTraceContext } from "effect/http";
3
3
  import { RpcSerialization } from "effect/rpc";
4
4
  import { proxyAddresses, proxyMatches, proxyRanges } from "./trustedProxy.ts";
5
5
 
@@ -72,7 +72,16 @@ export function localRpcGuard<E, R>(effect: Effect.Effect<HttpServerResponse.Htt
72
72
  const local = loopbackHost(request.headers.host) && Option.exists(request.remoteAddress, loopbackAddress);
73
73
  const contentType = request.headers["content-type"]?.split(";")[0]?.trim().toLowerCase();
74
74
  return ((local && sameOrigin(request)) || proxyOrigin(request, isTrustedProxy)) && contentType === serialization.contentType
75
- ? yield* effect
75
+ ? yield* continueHttpTrace(effect, request)
76
76
  : HttpServerResponse.text("Local same-origin requests only", { status: 403 });
77
77
  });
78
78
  }
79
+
80
+ const continueHttpTrace = Effect.fnUntraced(function* <A, E, R>(effect: Effect.Effect<A, E, R>, request: HttpServerRequest.HttpServerRequest) {
81
+ const incoming = HttpTraceContext.w3c(request.headers);
82
+ if (Option.isNone(incoming)) {
83
+ return yield* effect;
84
+ }
85
+ const parent = Option.getOrElse(yield* Effect.option(Effect.currentParentSpan), () => incoming.value);
86
+ return yield* Effect.withParentSpan(effect, parent);
87
+ });