@nebutra/ecosystem-safety 0.1.2 → 0.1.4
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/CHANGELOG.md +7 -0
- package/package.json +16 -5
- package/.turbo/turbo-build.log +0 -17
- package/.turbo/turbo-test.log +0 -14
- package/.turbo/turbo-typecheck.log +0 -4
- package/src/index.test.ts +0 -32
- package/src/index.ts +0 -65
- package/tsconfig.json +0 -9
- package/tsup.config.ts +0 -9
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nebutra/ecosystem-safety",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Shared public-disclosure safety primitives for ecosystem publishing surfaces",
|
|
5
5
|
"private": false,
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"nebutra": {
|
|
9
|
+
"graph": "labs",
|
|
9
10
|
"status": "wip",
|
|
10
11
|
"productionReady": false,
|
|
11
12
|
"surface": "support-contract",
|
|
@@ -21,13 +22,17 @@
|
|
|
21
22
|
"category": "ai",
|
|
22
23
|
"summary": "Single shared owner for public-disclosure sensitive-field scanning"
|
|
23
24
|
},
|
|
24
|
-
"main": "./
|
|
25
|
-
"types": "./
|
|
25
|
+
"main": "./dist/index.js",
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
26
27
|
"exports": {
|
|
27
|
-
".":
|
|
28
|
+
".": {
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"import": "./dist/index.js",
|
|
31
|
+
"default": "./dist/index.js"
|
|
32
|
+
}
|
|
28
33
|
},
|
|
29
34
|
"dependencies": {
|
|
30
|
-
"@nebutra/errors": "0.
|
|
35
|
+
"@nebutra/errors": "2.0.0"
|
|
31
36
|
},
|
|
32
37
|
"devDependencies": {
|
|
33
38
|
"@types/node": "^25.9.1",
|
|
@@ -47,6 +52,12 @@
|
|
|
47
52
|
"publishConfig": {
|
|
48
53
|
"access": "public"
|
|
49
54
|
},
|
|
55
|
+
"files": [
|
|
56
|
+
"dist",
|
|
57
|
+
"README.md",
|
|
58
|
+
"LICENSE",
|
|
59
|
+
"CHANGELOG.md"
|
|
60
|
+
],
|
|
50
61
|
"scripts": {
|
|
51
62
|
"build": "tsup",
|
|
52
63
|
"test": "vitest run",
|
package/.turbo/turbo-build.log
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
> @nebutra/ecosystem-safety@0.1.2 build /Users/tseka_luk/Documents/Nebutra-SaaS-Lab/Nebutra-Sailor/packages/ai/ecosystem-safety
|
|
3
|
-
> tsup
|
|
4
|
-
|
|
5
|
-
CLI Building entry: src/index.ts
|
|
6
|
-
CLI Using tsconfig: tsconfig.json
|
|
7
|
-
CLI tsup v8.5.1
|
|
8
|
-
CLI Using tsup config: /Users/tseka_luk/Documents/Nebutra-SaaS-Lab/Nebutra-Sailor/packages/ai/ecosystem-safety/tsup.config.ts
|
|
9
|
-
CLI Target: es2022
|
|
10
|
-
CLI Cleaning output folder
|
|
11
|
-
ESM Build start
|
|
12
|
-
ESM dist/index.js 1.60 KB
|
|
13
|
-
ESM dist/index.js.map 3.27 KB
|
|
14
|
-
ESM ⚡️ Build success in 9ms
|
|
15
|
-
DTS Build start
|
|
16
|
-
DTS ⚡️ Build success in 1574ms
|
|
17
|
-
DTS dist/index.d.ts 662.00 B
|
package/.turbo/turbo-test.log
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
> @nebutra/ecosystem-safety@0.1.1 test /Users/tseka_luk/Documents/Nebutra-SaaS-Lab/Nebutra-Sailor/packages/ai/ecosystem-safety
|
|
3
|
-
> vitest run
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
RUN v4.1.4 /Users/tseka_luk/Documents/Nebutra-SaaS-Lab/Nebutra-Sailor/packages/ai/ecosystem-safety
|
|
7
|
-
|
|
8
|
-
✓ src/index.test.ts (3 tests) 4ms
|
|
9
|
-
|
|
10
|
-
Test Files 1 passed (1)
|
|
11
|
-
Tests 3 passed (3)
|
|
12
|
-
Start at 09:38:31
|
|
13
|
-
Duration 248ms (transform 43ms, setup 0ms, import 56ms, tests 4ms, environment 0ms)
|
|
14
|
-
|
package/src/index.test.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { assertPublicDisclosureSafe, scanForSensitiveFields } from "./index";
|
|
3
|
-
|
|
4
|
-
describe("ecosystem-safety", () => {
|
|
5
|
-
it("detects emails and token-like secrets deterministically", () => {
|
|
6
|
-
expect(
|
|
7
|
-
scanForSensitiveFields("Contact alice@example.com with api key sk-test-1234567890."),
|
|
8
|
-
).toEqual([
|
|
9
|
-
{ kind: "email", value: "alice@example.com" },
|
|
10
|
-
{ kind: "secret", value: "sk-test-1234567890" },
|
|
11
|
-
]);
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
it("rejects public disclosure when sensitive fields have no explicit redaction", () => {
|
|
15
|
-
expect(() =>
|
|
16
|
-
assertPublicDisclosureSafe({
|
|
17
|
-
capability: "idea-plaza",
|
|
18
|
-
content: "customer bob@example.com uses token-api-12345678",
|
|
19
|
-
}),
|
|
20
|
-
).toThrow(expect.objectContaining({ capability: "idea-plaza" }));
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it("returns detected fields when the caller provides explicit redaction intent", () => {
|
|
24
|
-
expect(
|
|
25
|
-
assertPublicDisclosureSafe({
|
|
26
|
-
capability: "founder-cemetery",
|
|
27
|
-
content: "customer bob@example.com",
|
|
28
|
-
redactions: ["customers"],
|
|
29
|
-
}),
|
|
30
|
-
).toEqual([{ kind: "email", value: "bob@example.com" }]);
|
|
31
|
-
});
|
|
32
|
-
});
|
package/src/index.ts
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { CapabilityError } from "@nebutra/errors";
|
|
2
|
-
|
|
3
|
-
export type SensitiveFieldKind = "email" | "secret";
|
|
4
|
-
|
|
5
|
-
export interface SensitiveField {
|
|
6
|
-
readonly kind: SensitiveFieldKind;
|
|
7
|
-
readonly value: string;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export interface PublicDisclosureSafetyRequest {
|
|
11
|
-
readonly capability: string;
|
|
12
|
-
readonly content: string;
|
|
13
|
-
readonly redactions?: readonly string[];
|
|
14
|
-
readonly suggestion?: string;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const EMAIL_RE = /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi;
|
|
18
|
-
const SECRET_RE = /\b(?:sk|pk|api|key|token)[-_][A-Za-z0-9][A-Za-z0-9_-]{7,}\b/g;
|
|
19
|
-
|
|
20
|
-
function hasExplicitRedaction(redactions: readonly string[] | undefined): boolean {
|
|
21
|
-
return Boolean(redactions?.some((item) => item.trim().length > 0));
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function uniqueFields(fields: readonly SensitiveField[]): SensitiveField[] {
|
|
25
|
-
const seen = new Set<string>();
|
|
26
|
-
const unique: SensitiveField[] = [];
|
|
27
|
-
for (const field of fields) {
|
|
28
|
-
const key = `${field.kind}:${field.value.toLowerCase()}`;
|
|
29
|
-
if (seen.has(key)) continue;
|
|
30
|
-
seen.add(key);
|
|
31
|
-
unique.push(field);
|
|
32
|
-
}
|
|
33
|
-
return unique;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export function scanForSensitiveFields(content: string): SensitiveField[] {
|
|
37
|
-
const emails = [...content.matchAll(EMAIL_RE)].map((match) => ({
|
|
38
|
-
kind: "email" as const,
|
|
39
|
-
value: match[0],
|
|
40
|
-
}));
|
|
41
|
-
const secrets = [...content.matchAll(SECRET_RE)].map((match) => ({
|
|
42
|
-
kind: "secret" as const,
|
|
43
|
-
value: match[0],
|
|
44
|
-
}));
|
|
45
|
-
return uniqueFields([...emails, ...secrets]);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export function assertPublicDisclosureSafe(
|
|
49
|
-
request: PublicDisclosureSafetyRequest,
|
|
50
|
-
): readonly SensitiveField[] {
|
|
51
|
-
const sensitive = scanForSensitiveFields(request.content);
|
|
52
|
-
if (sensitive.length > 0 && !hasExplicitRedaction(request.redactions)) {
|
|
53
|
-
throw new CapabilityError(request.capability, "Sensitive fields require explicit redaction", {
|
|
54
|
-
suggestion:
|
|
55
|
-
request.suggestion ??
|
|
56
|
-
"Review detected private values and pass explicit redactions before publishing.",
|
|
57
|
-
metadata: {
|
|
58
|
-
sensitiveKinds: [...new Set(sensitive.map((item) => item.kind))],
|
|
59
|
-
sensitiveCount: sensitive.length,
|
|
60
|
-
},
|
|
61
|
-
statusCode: 400,
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
return sensitive;
|
|
65
|
-
}
|
package/tsconfig.json
DELETED