Skip to content

Commit 8db64a9

Browse files
author
Vish Devarajan
committed
All new features
1 parent a9985b9 commit 8db64a9

10 files changed

Lines changed: 1220 additions & 23 deletions

File tree

CHANGELOG.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,29 @@
11
# Changelog
22

3+
## 0.6.0
4+
5+
- Added threat-intel sync hooks, anomaly detection, telemetry replay, signed inspection attestation, and a streaming output firewall
6+
- Added policy-config validation flow through the scorecard CLI and expanded enterprise change-management primitives
7+
- Kept the new runtime slice aligned with Python while preserving the existing shield APIs
8+
9+
## 0.5.1
10+
11+
- Added file-backed corpus hardening for adversarial mutations and strengthened the edge build's built-in PII masking coverage
12+
- Added explicit coverage paths for training data poisoning, improper output reliance, excessive agency, and overreliance in OWASP reporting
13+
- Fixed tracker lifecycle so shared conversation history stays attached to the shield instance instead of falling back to per-request creation
14+
15+
## 0.5.0
16+
17+
- Added automatic multi-turn threat tracking by default, realistic OWASP coverage reporting, and automatic provenance stamping on guarded request/output paths
18+
- Added richer plugin hooks for output scanning, retrieval inspection, and telemetry enrichment plus an end-to-end `protectZeroTrustModelCall()` helper
19+
- Expanded adversarial mutation strategies, improved unicode de-obfuscation, and added a Node-compatible vault encryption fallback
20+
21+
## 0.4.0
22+
23+
- Replaced the default semantic scorer model with a jailbreak-focused Protect AI checkpoint and improved label mapping for security classifications
24+
- Added a reversible `unvault()` API, `ConversationThreatTracker`, plugin registration via `shield.use(plugin)`, and an edge-safe entry point
25+
- Added OWASP LLM coverage reporting, adversarial mutation helpers, prompt provenance tracking, and stronger grounding output metadata
26+
327
## 0.2.1
428

529
- Added `CrossModelConsensusWrapper` for out-of-the-box cross-model safety verification
@@ -8,6 +32,12 @@
832
- Added `PolicyLearningLoop` for approval-history-based policy suggestions
933
- Added JWT-style passport tokens in `AgentIdentityRegistry`
1034

35+
## 0.3.0
36+
37+
- Added richer signed agent passports with capability manifests, lineage, trust scores, and PQC-ready crypto profile metadata
38+
- Added `QuorumApprovalEngine`, `SovereignRoutingEngine`, simulation-mode digital twins with differential privacy noise, and explainable transparency reports
39+
- Wired quorum approvals into tool gating and added trust-score degradation when agents repeatedly fall out of consensus
40+
1141
## 0.2.4
1242

1343
- Added wiki-ready example guides and linked them from the main README

README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,14 +154,16 @@ Recommended presets:
154154

155155
### Global Governance Pack
156156

157-
The 0.2.2 line also adds globally applicable enterprise controls that are useful across regulated industries, not just one country or sector:
157+
The 0.5.0 line also adds globally applicable enterprise controls that are useful across regulated industries, not just one country or sector:
158158

159159
- `DataClassificationGate` to classify traffic as `public`, `internal`, `confidential`, or `restricted`
160160
- `ProviderRoutingPolicy` to keep sensitive classes on approved providers
161161
- `ApprovalInboxModel` and `UploadQuarantineWorkflow` for quarantine and review-first intake
162162
- `buildComplianceEventBundle()` and `sanitizeAuditEvent()` for audit-safe event export
163163
- `RetrievalTrustScorer` and `OutboundCommunicationGuard` for retrieval trust and outbound checks
164164
- `detectOperationalDrift()` for release-over-release noise monitoring
165+
- `ConversationThreatTracker`, `shield.use(plugin)`, `generateCoverageReport()`, and `unvault()` for multi-turn defense, ecosystem extensions, OWASP reporting, and reversible PII workflows
166+
- `AdversarialMutationEngine`, `PromptProvenanceGraph`, and `src/edge` for corpus hardening, cross-hop tracing, and edge-safe deployments
165167

166168
### `AuditTrail`
167169

@@ -172,9 +174,12 @@ Use it to record signed events, summarize security activity, and power dashboard
172174
- `ValueAtRiskCircuitBreaker` for financial or high-value operational actions
173175
- `ShadowConsensusAuditor` for second-model or secondary-review logic conflict checks
174176
- `CrossModelConsensusWrapper` for automatic cross-model verification of high-impact actions
177+
- `QuorumApprovalEngine` for committee-based approvals and trust-score-aware multi-agent decisions
175178
- `DigitalTwinOrchestrator` for mock tool environments and sandbox simulations
179+
- `SovereignRoutingEngine` for local-vs-global provider routing based on data classification
176180
- `PolicyLearningLoop` plus `suggestPolicyOverride()` for narrow false-positive tuning suggestions after HITL approvals
177-
- `AgentIdentityRegistry.issueSignedPassport()` and `issuePassportToken()` for signed agent identity exchange
181+
- `buildTransparencyReport()` for explainable operator and compliance artifacts
182+
- `AgentIdentityRegistry.issueSignedPassport()` and `issuePassportToken()` for signed agent identity exchange with capability manifests and lineage
178183

179184
## Example Workflows
180185

edge.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export function detectPromptInjectionEdge(input?: string): Record<string, unknown>;
2+
export function maskTextEdge(input?: string): Record<string, unknown>;
3+
export class EdgeBlackwallShield {
4+
guardModelRequest(input?: Record<string, unknown>): Promise<Record<string, unknown>>;
5+
}

index.d.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,15 @@ export interface ShieldOptions {
6262

6363
export class BlackwallShield {
6464
constructor(options?: ShieldOptions);
65+
use(plugin: Record<string, unknown>): this;
6566
inspectText(text: unknown): Record<string, unknown>;
6667
guardModelRequest(input?: { messages?: ShieldMessage[]; metadata?: Record<string, unknown>; allowSystemMessages?: boolean; comparePolicyPacks?: string[] }): Promise<GuardResult>;
6768
reviewModelResponse(input?: { output: unknown; metadata?: Record<string, unknown>; outputFirewall?: OutputFirewall | null; firewallOptions?: Record<string, unknown> }): Promise<ReviewResult>;
6869
protectModelCall(input: Record<string, unknown>): Promise<Record<string, unknown>>;
70+
protectZeroTrustModelCall(input: Record<string, unknown>): Promise<Record<string, unknown>>;
6971
protectJsonModelCall(input: Record<string, unknown>): Promise<JsonProtectionResult>;
7072
protectWithAdapter(input: { adapter: ProviderAdapter; messages?: ShieldMessage[]; metadata?: Record<string, unknown>; allowSystemMessages?: boolean; comparePolicyPacks?: string[]; outputFirewall?: OutputFirewall | null; firewallOptions?: Record<string, unknown> }): Promise<Record<string, unknown>>;
73+
generateCoverageReport(options?: Record<string, unknown>): Record<string, unknown>;
7174
}
7275

7376
export class OutputFirewall {
@@ -81,6 +84,25 @@ export class ToolPermissionFirewall {
8184
inspectCallAsync?(input: Record<string, unknown>): Promise<Record<string, unknown>>;
8285
}
8386

87+
export class AgentIdentityRegistry {
88+
constructor(options?: Record<string, unknown>);
89+
register(agentId: string, profile?: Record<string, unknown>): Record<string, unknown>;
90+
get(agentId: string): Record<string, unknown> | null;
91+
issueEphemeralToken(agentId: string, options?: Record<string, unknown>): Record<string, unknown>;
92+
verifyEphemeralToken(token: string): Record<string, unknown>;
93+
recordSecurityEvent(agentId: string, event?: Record<string, unknown>): Record<string, unknown>;
94+
getTrustScore(agentId: string): number | null;
95+
issueSignedPassport(agentId: string, options?: Record<string, unknown>): Record<string, unknown>;
96+
verifySignedPassport(passport?: Record<string, unknown>): Record<string, unknown>;
97+
issuePassportToken(agentId: string, options?: Record<string, unknown>): string;
98+
verifyPassportToken(token: string): Record<string, unknown>;
99+
}
100+
101+
export class AgenticCapabilityGater {
102+
constructor(options?: Record<string, unknown>);
103+
evaluate(agentId: string, capabilities?: Record<string, unknown>): Record<string, unknown>;
104+
}
105+
84106
export class ValueAtRiskCircuitBreaker {
85107
constructor(options?: Record<string, unknown>);
86108
inspect(input?: Record<string, unknown>): Record<string, unknown>;
@@ -97,12 +119,35 @@ export class CrossModelConsensusWrapper {
97119
evaluate(input?: Record<string, unknown>): Promise<Record<string, unknown>> | Record<string, unknown>;
98120
}
99121

122+
export class QuorumApprovalEngine {
123+
constructor(options?: Record<string, unknown>);
124+
evaluate(input?: Record<string, unknown>): Promise<Record<string, unknown>> | Record<string, unknown>;
125+
}
126+
127+
export class ConversationThreatTracker {
128+
constructor(options?: Record<string, unknown>);
129+
record(sessionId: string, injection?: Record<string, unknown>): Record<string, unknown> | null;
130+
summarize(sessionId: string): Record<string, unknown>;
131+
clear(sessionId: string): void;
132+
}
133+
100134
export class DigitalTwinOrchestrator {
101135
constructor(options?: Record<string, unknown>);
102136
generate(): Record<string, unknown>;
103137
static fromToolPermissionFirewall(firewall: unknown): DigitalTwinOrchestrator;
104138
}
105139

140+
export class AdversarialMutationEngine {
141+
mutate(prompt?: string): Array<Record<string, unknown>>;
142+
hardenCorpus(input?: Record<string, unknown>): Record<string, unknown>;
143+
}
144+
145+
export class PromptProvenanceGraph {
146+
constructor();
147+
append(input?: Record<string, unknown>): Record<string, unknown>;
148+
summarize(): Record<string, unknown>;
149+
}
150+
106151
export class DataClassificationGate {
107152
constructor(options?: Record<string, unknown>);
108153
classify(input?: Record<string, unknown>): string;
@@ -114,6 +159,11 @@ export class ProviderRoutingPolicy {
114159
choose(input?: Record<string, unknown>): Record<string, unknown>;
115160
}
116161

162+
export class SovereignRoutingEngine {
163+
constructor(options?: Record<string, unknown>);
164+
route(input?: Record<string, unknown>): Record<string, unknown>;
165+
}
166+
117167
export class ApprovalInboxModel {
118168
constructor(options?: Record<string, unknown>);
119169
createRequest(input?: Record<string, unknown>): Record<string, unknown>;
@@ -139,6 +189,7 @@ export class PolicyLearningLoop {
139189
constructor();
140190
recordDecision(input?: Record<string, unknown>): Record<string, unknown> | null;
141191
suggestOverrides(): Array<Record<string, unknown>>;
192+
buildTransparencyReport(input?: Record<string, unknown>): Record<string, unknown>;
142193
}
143194

144195
export class RetrievalSanitizer {
@@ -165,7 +216,10 @@ export function buildPowerBIRecord(event?: Record<string, unknown>): Record<stri
165216
export function buildComplianceEventBundle(event?: Record<string, unknown>): Record<string, unknown>;
166217
export function sanitizeAuditEvent(event?: Record<string, unknown>, options?: Record<string, unknown>): Record<string, unknown>;
167218
export function detectOperationalDrift(previousSummary?: Record<string, unknown>, currentSummary?: Record<string, unknown>): Record<string, unknown>;
219+
export function buildTransparencyReport(input?: Record<string, unknown>): Record<string, unknown>;
220+
export function generateCoverageReport(options?: Record<string, unknown>): Record<string, unknown>;
168221
export function suggestPolicyOverride(input?: Record<string, unknown>): Record<string, unknown> | null;
222+
export function unvault(output?: unknown, vault?: Record<string, string>): string;
169223
export class PowerBIExporter {
170224
constructor(options?: Record<string, unknown>);
171225
send(events?: Array<Record<string, unknown>> | Record<string, unknown>): Promise<Array<Record<string, unknown>>>;

package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@vpdeva/blackwall-llm-shield-js",
3-
"version": "0.2.4",
3+
"version": "0.6.0",
44
"description": "Open-source JavaScript enterprise LLM protection toolkit for Node.js and Next.js",
55
"license": "Apache-2.0",
66
"author": "Vish <hello@vish.au> (https://vish.au)",
@@ -20,6 +20,10 @@
2020
"types": "./providers.d.ts",
2121
"default": "./src/providers.js"
2222
},
23+
"./edge": {
24+
"types": "./edge.d.ts",
25+
"default": "./src/edge.js"
26+
},
2327
"./semantic": {
2428
"types": "./semantic.d.ts",
2529
"default": "./src/semantic.js"
@@ -39,6 +43,7 @@
3943
},
4044
"files": [
4145
"src",
46+
"edge.d.ts",
4247
"index.d.ts",
4348
"integrations.d.ts",
4449
"providers.d.ts",

src/edge.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
const EDGE_PROMPT_PATTERNS = [
2+
{ id: 'ignore_instructions', score: 25, regex: /\bignore\b.{0,40}\b(instructions?|policy|guardrails?|safety)\b/i },
3+
{ id: 'secret_exfiltration', score: 25, regex: /\b(reveal|dump|print|show)\b.{0,40}\b(secret|token|system prompt|hidden instructions?)\b/i },
4+
{ id: 'tool_override', score: 20, regex: /\b(bypass|override|disable)\b.{0,40}\b(tool|policy|guardrail|safety)\b/i },
5+
];
6+
7+
function edgeRiskLevel(score) {
8+
if (score >= 70) return 'critical';
9+
if (score >= 45) return 'high';
10+
if (score >= 20) return 'medium';
11+
return 'low';
12+
}
13+
14+
function detectPromptInjectionEdge(input = '') {
15+
const text = String(input || '');
16+
const matches = EDGE_PROMPT_PATTERNS.filter((rule) => rule.regex.test(text)).map((rule) => ({
17+
id: rule.id,
18+
score: rule.score,
19+
reason: `Edge rule matched ${rule.id}`,
20+
}));
21+
const score = Math.min(matches.reduce((sum, item) => sum + item.score, 0), 100);
22+
return {
23+
score,
24+
level: edgeRiskLevel(score),
25+
matches,
26+
blockedByDefault: score >= 45,
27+
};
28+
}
29+
30+
function maskTextEdge(text = '') {
31+
let masked = String(text || '');
32+
const vault = {};
33+
const patterns = [
34+
['EMAIL', /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/g],
35+
['CREDIT_CARD', /\b(?:\d{4}[\s-]?){3}\d{4}\b/g],
36+
['API_KEY', /\b(?:sk|rk|pk|api)[-_][A-Za-z0-9_-]{8,}\b/g],
37+
['JWT', /\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9._-]+\.[A-Za-z0-9._-]+\b/g],
38+
['BEARER', /\bBearer\s+[A-Za-z0-9\-._~+/]+=*\b/gi],
39+
['PHONE', /(\+?\d{1,3}[\s-]?)?(\(0\d\)|0\d|\(?\d{2,4}\)?)[\s-]?\d{3,4}[\s-]?\d{3,4}\b/g],
40+
];
41+
for (const [label, pattern] of patterns) {
42+
masked = masked.replace(pattern, (match) => {
43+
const token = `[${label}_${Object.keys(vault).length + 1}]`;
44+
vault[token] = match;
45+
return token;
46+
});
47+
}
48+
return { masked, vault, hasSensitiveData: Object.keys(vault).length > 0 };
49+
}
50+
51+
class EdgeBlackwallShield {
52+
async guardModelRequest({ messages = [], metadata = {} } = {}) {
53+
const text = (Array.isArray(messages) ? messages : []).map((item) => String(item.content || '')).join('\n');
54+
const masked = maskTextEdge(text);
55+
const injection = detectPromptInjectionEdge(text);
56+
return {
57+
allowed: !injection.blockedByDefault,
58+
blocked: injection.blockedByDefault,
59+
reason: injection.blockedByDefault ? 'Prompt injection risk exceeded edge threshold' : null,
60+
messages,
61+
report: { metadata, promptInjection: injection, sensitiveData: masked },
62+
vault: masked.vault,
63+
};
64+
}
65+
}
66+
67+
module.exports = {
68+
EdgeBlackwallShield,
69+
detectPromptInjectionEdge,
70+
maskTextEdge,
71+
};

0 commit comments

Comments
 (0)