shrike

package module
v1.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 10, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

README

Shrike Guard (Go)

Go Reference

Shrike Guard is the Go SDK for the Shrike platform — AI governance for every AI interaction. It wraps OpenAI, Anthropic (Claude), and Google Gemini clients to automatically evaluate every prompt against policy before it reaches the LLM. Whether you're governing a customer-facing chatbot, securing developer AI tools, or managing autonomous agent actions — the same 9-layer cognitive pipeline evaluates every interaction.

Features

  • Drop-in wrappers for the OpenAI, Anthropic, and Gemini Go clients
  • Automatic prompt scanning for:
    • Prompt injection attacks
    • PII / sensitive-data leakage
    • Jailbreak attempts
    • SQL injection
    • Path traversal
  • Fail-closed by default (Zero Trust posture); opt into fail-open explicitly when availability outranks enforcement
  • Per-provider subpackages: import .../openai, .../anthropic, or .../gemini and only that provider's dependency is pulled in
  • Client-side PII redaction: redact before the prompt leaves your process, rehydrate the model's response afterward
  • Idiomatic errors: errors.As against *shrike.BlockedError and *shrike.ScanError

What Shrike Detects

Shrike's 9-layer cognitive pipeline includes sensitive-data detection aligned to 5 major regulatory frameworks:

Framework Coverage
GDPR EU personal data — names, addresses, national IDs
HIPAA Protected health information (PHI)
ISO 27001 Information security — passwords, tokens, certificates
SOC 2 Secrets, credentials, API keys, cloud tokens
NIST AI risk management (IR 8596), cybersecurity framework (CSF 2.0)

Detection coverage is not a certification claim — see shrikesecurity.com/compliance for our current certification status. Plus built-in detection for prompt injection, jailbreaks, social engineering, and dangerous requests.

Tiers

Detection depth depends on your tier. All tiers get the same SDK wrappers — tiers control which backend layers run.

Anonymous Community Pro Enterprise
Detection Layers L1-L5 L1-L5 L1-L9 (full) L1-L9 (full)
API Key Not needed Free signup Paid Paid
Rate Limit — 10/min 100/min 1,000/min
Scans/month — 1,000 25,000 1,000,000

Anonymous (no API key): pattern-based detection (L1-L5). Community (free): same L1-L5 detection with a dashboard and higher limits; LLM-powered semantic analysis (L6-L9) is Pro+. Register at shrikesecurity.com/signup — instant, no credit card.

Installation

go get github.com/shrike-security/shrike-guard-go@latest

Requires Go 1.25+. Provider dependencies are pulled in only when you import the matching subpackage.

Quick Start

OpenAI
import (
	"github.com/sashabaranov/go-openai"
	shrikeopenai "github.com/shrike-security/shrike-guard-go/openai"
)

client, err := shrikeopenai.NewClient(shrikeopenai.ClientOptions{
	OpenAIAPIKey: "sk-...",     // your OpenAI API key
	ShrikeAPIKey: "shrike-...", // your Shrike API key
})
if err != nil {
	log.Fatal(err)
}

// Use it like the normal go-openai client — every prompt is scanned first.
resp, err := client.CreateChatCompletion(ctx, openai.ChatCompletionRequest{
	Model: openai.GPT4,
	Messages: []openai.ChatCompletionMessage{
		{Role: openai.ChatMessageRoleUser, Content: "Hello, how are you?"},
	},
})
Anthropic (Claude)
import (
	anthropicsdk "github.com/anthropics/anthropic-sdk-go"
	shrikeanthropic "github.com/shrike-security/shrike-guard-go/anthropic"
)

client, err := shrikeanthropic.NewClient(shrikeanthropic.ClientOptions{
	AnthropicAPIKey: "sk-ant-...",
	ShrikeAPIKey:    "shrike-...",
})
if err != nil {
	log.Fatal(err)
}

// Params are the underlying anthropic-sdk-go MessageNewParams; the user
// content is scanned before Messages.New is called.
msg, err := client.CreateMessage(ctx, anthropicsdk.MessageNewParams{
	Model:     anthropicsdk.ModelClaudeSonnet4_5,
	MaxTokens: 1024,
	Messages: []anthropicsdk.MessageParam{
		anthropicsdk.NewUserMessage(anthropicsdk.NewTextBlock("Hello!")),
	},
})
Google Gemini
import (
	"google.golang.org/genai"
	shrikegemini "github.com/shrike-security/shrike-guard-go/gemini"
)

client, err := shrikegemini.NewClient(ctx, shrikegemini.ClientOptions{
	GeminiAPIKey: "AIza...",
	ShrikeAPIKey: "shrike-...",
})
if err != nil {
	log.Fatal(err)
}

resp, err := client.GenerateContent(ctx, "gemini-2.0-flash",
	[]*genai.Content{genai.NewContentFromText("Hello!", genai.RoleUser)}, nil)

Streaming is supported too: CreateMessageStream and GenerateContentStream scan the user content before the first token is produced, returning a *shrike.BlockedError if the request is refused.

Configuration

Every wrapper's ClientOptions accepts the same Shrike knobs:

shrikeopenai.ClientOptions{
	OpenAIAPIKey:   "sk-...",
	ShrikeAPIKey:   "shrike-...",
	ShrikeEndpoint: "https://your-shrike-instance.com", // self-hosted / VPC (optional)
	FailMode:       shrike.FailModeClosed,              // default; see below
	ScanTimeout:    5000,                               // milliseconds (default 10000)
}
Local and self-hosted LLMs

Shrike governs the model you point it at — it does not have to be a hosted frontier API. Local runtimes like Ollama, vLLM, and LM Studio expose an OpenAI-compatible endpoint, so the OpenAI wrapper guards them via a custom OpenAIConfig:

cfg := openai.DefaultConfig("ollama")        // local servers ignore the token
cfg.BaseURL = "http://localhost:11434/v1"    // your local/self-hosted endpoint

client, err := shrikeopenai.NewClient(shrikeopenai.ClientOptions{
	OpenAIConfig: &cfg,
	ShrikeAPIKey: "shrike-...",               // governance still runs server-side
})

The Anthropic and Gemini wrappers take a BaseURL for compatible gateways (added in v1.1.0):

shrikeanthropic.ClientOptions{AnthropicAPIKey: "…", ShrikeAPIKey: "shrike-...", BaseURL: "https://anthropic-gateway.example"}
shrikegemini.ClientOptions{GeminiAPIKey: "…", ShrikeAPIKey: "shrike-...", BaseURL: "https://gemini-gateway.example"}

The prompt still leaves your process to reach the Shrike backend for scanning; the model call stays on your local/self-hosted endpoint.

Fail Modes

Choose how the SDK behaves when the scan itself fails (timeout, network error, backend 5xx):

  • shrike.FailModeClosed (default) — block the request and return a *shrike.ScanError. Best for production security workloads: if the Shrike backend is down, traffic does not flow through unguarded.
  • shrike.FailModeOpen — allow the request to proceed. Best for non-production experiments or internal tools where availability must outrank enforcement. Trades the guard's enforcement promise for uptime.
Sessions: one per unit of work, not one per process

Shrike correlates risk across a session. After a refusal, later actions in the same session are held until the session recovers. That is the multi-turn defence, and it means the session id has to mean one unit of work: one agent run, one conversation, one user's request.

By default the SDK scans under one id for the whole process. That suits a CLI, a worker, or a single agent. It does not suit a server that scans on behalf of many end users, because every user then shares one risk score, and one user's refusal counts against the next user's action.

Build one client at startup and derive a per-request view from it. The view shares the HTTP client, circuit breaker and cache, so it costs nothing to make one per request:

guard := scanner.NewClient(key)                        // once, at startup

func handle(w http.ResponseWriter, r *http.Request) {  // per request
    scoped := guard.ForSession(sessionIDFor(r))
    verdict, err := scoped.ScanCommand(r.Context(), cmd, "")
    if err != nil || verdict.RefuseTier != "allow" {
        ...
    }
}

Or pin the identity at construction when one client serves one unit of work:

client := scanner.NewClient(key, scanner.WithSession("job-42"), scanner.WithAgentID("ingest"))

WithAgentID is separate on purpose: it names which agent a scope is enforced against and who an incident is attributed to. Set it when one process drives several distinct agents.

The SDK logs once per process when it is scanning under the shared default. Set SHRIKE_SUPPRESS_SESSION_WARNING=1 to silence it once you have decided the default is what you want.

The content cache and sessions

Content-hash caching is off by default, so every scan reaches the backend and no verdict is reused. That is the right default for an enforcement point: a cache key built from content alone carries no session identity, so a cached verdict can outlive the session state that produced it, and an allow stored before a quarantine would be served after it.

Opt in where a stale allow is acceptable, such as a single-tenant advisory check or a batch pass over static content:

guard := scanner.NewClient(key, scanner.WithCache(5*time.Minute, 1000))

A non-positive TTL or size means "use the default", so WithCache(0, 0) enables a 5-minute cache rather than disabling one. WithoutCache() remains available to undo a WithCache passed earlier in the same option list.

SQL and File Scanning

Each provider wrapper also exposes standalone scanning:

sqlResult, err := client.ScanSQL(ctx, "SELECT * FROM users WHERE id = 1", "production_db", false)
if !sqlResult.Safe {
	log.Printf("SQL threat: %s", sqlResult.Reason)
}

fileResult, err := client.ScanFile(ctx, "/app/data/report.csv", "") // optional content arg

Client-Side PII Redaction

Redact PII before the prompt leaves your process, then rehydrate the model's response. Raw PII is never sent to Shrike or the downstream LLM.

import "github.com/shrike-security/shrike-guard-go/pii"

r := pii.Redact("Email john@acme.com about invoice 12345")
// r.RedactedText == "Email [EMAIL_1] about invoice 12345"

// ... send r.RedactedText to the LLM ...

final := pii.Rehydrate(llmOutput, r.Redactions) // tokens → original values

pii.SyncPatterns optionally pulls Shrike's canonical server-side pattern set to replace the bootstrap patterns; it never fails your request (returns (false, err) on a soft failure and keeps the current patterns).

Error Handling

import (
	"errors"
	shrike "github.com/shrike-security/shrike-guard-go"
)

resp, err := client.CreateChatCompletion(ctx, req)
if err != nil {
	var blocked *shrike.BlockedError
	if errors.As(err, &blocked) {
		log.Printf("blocked: %s (threat=%s, confidence=%s)",
			blocked.Message, blocked.ThreatType, blocked.Confidence)
		return
	}
	var scanErr *shrike.ScanError
	if errors.As(err, &scanErr) {
		// only returned under FailModeClosed when the scan couldn't complete
		log.Printf("scan error: %s", scanErr.Message)
		return
	}
	log.Fatal(err) // an underlying provider error
}

Confidence is a bucketed level (high / medium / low), not a raw score — the SDK never surfaces exact detection thresholds.

Low-Level Scan Client

For direct control, use the scanner client without a provider wrapper:

import "github.com/shrike-security/shrike-guard-go/scanner"

sc := scanner.NewClient("shrike-...")
res, err := sc.Scan(ctx, "Check this prompt for threats")
if scanner.IsBlocked(res) {
	log.Printf("threat detected: %s", res.Reason)
}

scanner.IsBlocked is the single proceed-vs-refuse decision helper: it honors the server action (allow/warn proceed, block/require_approval refuse) and fails closed on unknown verdicts.

Scanning agent actions (shell commands, SQL, web search, RAG, MCP tools)

Scanning the prompt protects the model. It does not protect the shell. An agent that was never told anything malicious can still be talked into running curl … | sh by a poisoned README, and the prompt scan has no view of that.

scanner.Client exposes a method per action channel. Call the one that matches what the agent is about to do, before it does it:

Channel Method Screens for
Shell command ScanCommand(ctx, cmd, cwd) destructive commands, data exfiltration, credential dumps, embedded SQL injection
SQL query ScanSQL(ctx, query, db, allowDestructive) SQL injection, unauthorized destructive statements
File path ScanFile(ctx, path, "") path traversal, writes outside the working tree
File content ScanFile(ctx, path, content) secrets, credentials, PII before they land on disk
Web search ScanWebSearch(ctx, query) searches that acquire attack tooling, credentials, or evasion tradecraft
RAG context ScanRagContext(ctx, chunks, query) indirect prompt injection in retrieved documents
Agent message ScanA2AMessage(ctx, msg, opts) instructions smuggled between agents
Agent card ScanAgentCard(ctx, card, verifySig) capability misrepresentation in A2A discovery
MCP tool schema ScanMCPSchema(ctx, name, desc, schema) tool poisoning in tools/list responses
client := scanner.NewClient(os.Getenv("SHRIKE_API_KEY"))

// Before shelling out
res, err := client.ScanCommand(ctx, `psql -c "SELECT * FROM users"`, "/srv/app")
if err != nil {
	log.Fatal(err) // fail closed
}
if scanner.IsBlocked(res) {
	return fmt.Errorf("refused: %s", res.Reason)
}

// Before searching the web
res, _ = client.ScanWebSearch(ctx, "sql injection prevention owasp")

// Screen an MCP tool before registering it — tool poisoning needs no execution
res, _ = client.ScanMCPSchema(ctx, tool.Name, tool.Description, tool.InputSchema)

A shell command is not one thing. ScanCommand sends it to a backend that decomposes it, so SQL passed to psql -c, mysql -e, or a heredoc is scanned as SQL rather than as an opaque string of shell text.

DeclareScope binds an agent to a declared operating scope, after which every scan for that agent_id is enforced against it server-side.

Who is answerable: ContentOrigin

Every verdict carries ContentOrigin, which says where the scanned content came from. It answers the question a verdict alone cannot: was that my prompt, or the agent acting on its own?

Value Meaning
human_prompt the operator typed it
agent_output the model generated it
agent_action the agent is about to do it (every act-plane channel)
third_party it arrived from outside: a tool result, a retrieved document, a peer agent
res, _ := client.ScanRagContext(ctx, chunks, userQuery)

if scanner.IsBlocked(res) {
	if scanner.AttributableToOperator(res.ContentOrigin) {
		showUser("Your request was blocked: " + res.Reason)
	} else {
		// The agent poisoned its own context. Telling the user "your request
		// was blocked" would be both wrong and unhelpful.
		log.Printf("agent-side refusal: %s", res.Reason)
	}
}

Unknown content types resolve to agent_action, never to human_prompt: attributing an unattributable action to the operator is the one error that is never safe to make by default.

System Prompt

Inject the canonical "Working with Shrike" guidance into your agent's system prompt — byte-for-byte identical across the Go, TypeScript, and Python SDKs:

prompt := shrike.SystemPrompt() // shrike.SystemPromptVersion identifies the block

Compatibility

  • Go: 1.25+
  • Provider SDKs:
    • OpenAI — github.com/sashabaranov/go-openai
    • Anthropic — github.com/anthropics/anthropic-sdk-go v1
    • Google Gemini — google.golang.org/genai v1 (the unified Google GenAI SDK)

Other Integration Surfaces

Shrike Guard is one of several ways to integrate with the Shrike platform:

  • MCP Server — npx shrike-mcp (GitHub)
  • TypeScript SDK — npm install shrike-guard (GitHub)
  • Python SDK — pip install shrike-guard (GitHub)
  • REST API — POST https://api.shrikesecurity.com/agent/scan
  • LLM Gateway — change one URL, scan everything
  • Dashboard — shrikesecurity.com

License

Apache 2.0 — see LICENSE.

Support

Documentation

Overview

Package shrike is the Go SDK for the Shrike platform — AI governance for every AI interaction.

Shrike evaluates every prompt against policy before it reaches the model, deciding in real time what is allowed, blocked, or escalated. The same backend cognitive pipeline that governs a customer-facing chatbot also governs autonomous, tool-using agents.

Drop-in provider wrappers

Wrap your existing LLM client and every prompt is scanned before it is sent. Each wrapper lives in its own subpackage so provider dependencies are only pulled in when you import the one you use:

  • github.com/shrike-security/shrike-guard-go/openai (ShrikeOpenAI)
  • github.com/shrike-security/shrike-guard-go/anthropic (ShrikeAnthropic)
  • github.com/shrike-security/shrike-guard-go/gemini (ShrikeGemini)

A minimal OpenAI example:

client, err := shrikeopenai.NewClient(shrikeopenai.ClientOptions{
    OpenAIAPIKey: os.Getenv("OPENAI_API_KEY"),
    ShrikeAPIKey: os.Getenv("SHRIKE_API_KEY"),
})
resp, err := client.CreateChatCompletion(ctx, req) // scanned before send

Fail-closed by default

When the Shrike backend cannot decide (timeout, network error, backend 5xx), the SDK blocks the request and returns a *ScanError — the Zero Trust posture. Opt into fail-open only when availability must outrank enforcement, via scanner.WithFailMode(shrike.FailModeOpen).

Other packages

  • scanner — the low-level scan client (Scan, ScanSQL, ScanFile, DeclareScope, ScanA2AMessage, ScanAgentCard) plus IsBlocked, the single proceed-vs-refuse decision helper.
  • pii — client-side PII redaction and rehydration; PII never leaves the caller's process.
  • api — the quota-free sandbox scan client.

SystemPrompt returns the canonical "Working with Shrike" system-prompt block, byte-for-byte identical across the Go, TypeScript, and Python SDKs.

Index

Constants

View Source
const (
	// DefaultCacheTTL is the default time-to-live for cached scan results.
	DefaultCacheTTL = 5 * time.Minute

	// DefaultCacheMaxSize is the default maximum number of cached entries.
	DefaultCacheMaxSize = 1000
)

Default cache configuration.

View Source
const (
	// DefaultScanTimeout is the default timeout for scan requests.
	DefaultScanTimeout = 10 * time.Second

	// DefaultEndpoint is the default Shrike API endpoint (uses load balancer for scalability).
	// Override with WithEndpoint() for VPC deployments.
	DefaultEndpoint = "https://api.shrikesecurity.com/agent"

	// SDKName identifies this SDK in API requests.
	SDKName = "go"

	// SDKUserAgent is the user agent string for this SDK.
	SDKUserAgent = "shrike-guard-go"
)

Default configuration values.

View Source
const DefaultSyncTimeout = 5 * time.Second

DefaultSyncTimeout is how long SyncPIIPatterns waits for the backend before keeping the fallback patterns.

View Source
const SystemPromptVersion = "1.0"

SystemPromptVersion is the version string for the canonical block. Integrators can pin behavior against this without pinning the whole SDK.

View Source
const Version = "1.2.0"

Version is the SDK version.

Variables

View Source
var (
	// ErrCircuitOpen is returned when the circuit breaker is in open state.
	ErrCircuitOpen = errors.New("shrike: circuit breaker is open")

	// ErrTooManyRequests is returned when too many requests are in-flight
	// during the half-open state.
	ErrTooManyRequests = errors.New("shrike: too many requests in half-open state")
)

Circuit breaker errors.

View Source
var DefaultFailMode = FailModeClosed

DefaultFailMode is the default fail mode. Set to FailModeClosed to match the Shrike platform's Zero Trust contract: when the scanner cannot decide, the request is blocked. Override at the call site with WithFailMode(FailModeOpen) if you need availability over enforcement.

Functions

func GetPIIPatternCount added in v1.2.0

func GetPIIPatternCount() int

GetPIIPatternCount returns the current number of active PII patterns.

func GetRedactionSummary added in v1.2.0

func GetRedactionSummary(redactions []RedactionEntry) map[string]int

GetRedactionSummary returns a count of redactions grouped by PII type (no raw PII values). Safe to log.

func HashContent

func HashContent(content string) string

HashContent computes a SHA256 hash of the content for use as a cache key.

func RehydratePII added in v1.2.0

func RehydratePII(text string, redactions []RedactionEntry) string

RehydratePII restores indexed tokens in text back to their original PII values using the redaction map returned by RedactPII. All occurrences of each token are replaced (LLMs may repeat tokens in their output).

restored := shrike.RehydratePII(llmOutput, redacted.Redactions)

func Retry

func Retry(ctx context.Context, cfg RetryConfig, fn func() error) error

Retry executes fn with exponential backoff retry. It respects context cancellation and does not retry circuit breaker errors.

func SyncPIIPatterns added in v1.2.0

func SyncPIIPatterns(ctx context.Context, opts SyncPIIPatternsOptions) error

SyncPIIPatterns fetches canonical PII patterns from the Shrike backend and applies them to the client-side redactor.

Never returns an error that blocks scans — pattern sync is a quality feature. The returned error is informational only; the redactor is guaranteed to remain in a usable state regardless of the outcome.

err := shrike.SyncPIIPatterns(ctx, shrike.SyncPIIPatternsOptions{
    Endpoint: "https://api.shrikesecurity.com",
    APIKey:   os.Getenv("SHRIKE_API_KEY"),
})

func SystemPrompt

func SystemPrompt() string

SystemPrompt returns the canonical "Working with Shrike" system-prompt block. Drop it into your agent's system prompt as the first non-role paragraph:

prompt := "You are a support agent for Acme Corp.\n\n" +
	shrike.SystemPrompt() +
	"\n\nWhen customers ask about refunds, first verify..."

func UpdatePIIPatterns added in v1.2.0

func UpdatePIIPatterns(patterns []PIIPattern)

UpdatePIIPatterns replaces the active PII pattern list (e.g. with a backend-fetched canonical set). Thread-safe.

Types

type BlockedError

type BlockedError struct {
	ShrikeError

	// ThreatType is the type of threat detected (e.g., 'prompt_injection', 'pii')
	ThreatType string

	// Confidence is the bucketed confidence level ("high"/"medium"/"low").
	// Buckets protect IP by not exposing exact detection thresholds.
	Confidence string

	// Violations is the sanitized list of specific violations detected.
	Violations []map[string]interface{}
}

BlockedError is returned when a prompt is blocked by Shrike security checks.

This error indicates that the prompt was scanned and determined to be unsafe.

func NewBlockedError

func NewBlockedError(message, threatType, confidence string, violations []map[string]interface{}) *BlockedError

NewBlockedError creates a new BlockedError.

func (*BlockedError) Error

func (e *BlockedError) Error() string

type CacheStats

type CacheStats struct {
	Hits    uint64
	Misses  uint64
	Size    int
	MaxSize int
	HitRate float64
}

CacheStats provides read-only cache statistics.

type CircuitBreaker

type CircuitBreaker struct {
	// contains filtered or unexported fields
}

CircuitBreaker implements the three-state circuit breaker pattern.

func NewCircuitBreaker

func NewCircuitBreaker(cfg CircuitBreakerConfig) *CircuitBreaker

NewCircuitBreaker creates a new circuit breaker with the given config.

func (*CircuitBreaker) Execute

func (cb *CircuitBreaker) Execute(fn func() error) error

Execute runs fn through the circuit breaker.

func (*CircuitBreaker) ExecuteWithContext

func (cb *CircuitBreaker) ExecuteWithContext(ctx context.Context, fn func(context.Context) error) error

ExecuteWithContext runs fn with context through the circuit breaker.

func (*CircuitBreaker) State

func (cb *CircuitBreaker) State() CircuitState

State returns the current circuit breaker state.

func (*CircuitBreaker) Stats

func (cb *CircuitBreaker) Stats() CircuitBreakerStats

Stats returns circuit breaker statistics.

type CircuitBreakerConfig

type CircuitBreakerConfig struct {
	// FailureThreshold is the number of consecutive failures before opening.
	// Default: 5
	FailureThreshold uint32

	// SuccessThreshold is the number of successes in half-open before closing.
	// Default: 2
	SuccessThreshold uint32

	// Timeout is the duration the circuit stays open before transitioning
	// to half-open. Default: 30s
	Timeout time.Duration

	// MaxHalfOpenRequests is the max concurrent requests allowed in half-open.
	// Default: 3
	MaxHalfOpenRequests uint32

	// OnStateChange is called when the circuit breaker state changes.
	OnStateChange func(from, to CircuitState)
}

CircuitBreakerConfig configures the circuit breaker.

func DefaultCircuitBreakerConfig

func DefaultCircuitBreakerConfig() CircuitBreakerConfig

DefaultCircuitBreakerConfig returns sensible defaults for SDK use.

type CircuitBreakerStats

type CircuitBreakerStats struct {
	State           CircuitState
	FailureCount    uint32
	SuccessCount    uint32
	LastStateChange time.Time
	LastFailureTime time.Time
}

CircuitBreakerStats provides read-only stats about the circuit breaker.

type CircuitState

type CircuitState int

CircuitState represents the state of the circuit breaker.

const (
	// CircuitClosed is the normal operating state.
	CircuitClosed CircuitState = iota
	// CircuitOpen is the failing state — requests are rejected.
	CircuitOpen
	// CircuitHalfOpen is the recovery testing state.
	CircuitHalfOpen
)

func (CircuitState) String

func (s CircuitState) String() string

type Config

type Config struct {
	// APIKey is the Shrike API key for authentication.
	APIKey string

	// Endpoint is the Shrike API endpoint URL.
	Endpoint string

	// FailMode defines behavior when scan operations fail.
	FailMode FailMode

	// ScanTimeout is the timeout for scan requests.
	ScanTimeout time.Duration
}

Config holds configuration for Shrike clients.

func DefaultConfig

func DefaultConfig(apiKey string) Config

DefaultConfig returns a configuration with default values.

type ConfigError

type ConfigError struct {
	ShrikeError
}

ConfigError is returned when there's a configuration error in the SDK.

func NewConfigError

func NewConfigError(message string) *ConfigError

NewConfigError creates a new ConfigError.

type ContentCache

type ContentCache struct {
	// contains filtered or unexported fields
}

ContentCache is a thread-safe LRU cache with TTL expiry. It uses SHA256 content hashes as keys to deduplicate scan requests.

func NewContentCache

func NewContentCache(ttl time.Duration, maxSize int) *ContentCache

NewContentCache creates a new content cache.

func (*ContentCache) Clear

func (c *ContentCache) Clear()

Clear removes all entries from the cache.

func (*ContentCache) Get

func (c *ContentCache) Get(contentHash string) (interface{}, bool)

Get retrieves a cached value by content hash. Returns nil, false if not found or expired.

func (*ContentCache) Set

func (c *ContentCache) Set(contentHash string, value interface{})

Set stores a value in the cache. Evicts the oldest entry if at capacity.

func (*ContentCache) Stats

func (c *ContentCache) Stats() CacheStats

Stats returns cache statistics.

type FailMode

type FailMode string

FailMode defines behavior when scan operations fail (timeout, network error, backend 5xx).

const (
	// FailModeOpen allows the request to proceed when the scanner cannot decide.
	// Use this when availability is strictly prioritized over enforcement
	// (e.g. non-production experiments, internal tools where outages must not
	// block users). Note: a fail-open SDK provides no guard during backend
	// outages, which is when adversarial pressure is highest.
	FailModeOpen FailMode = "open"

	// FailModeClosed blocks the request and returns an error when the scanner
	// cannot decide. This is the Zero Trust posture promised by the Shrike
	// platform — if the guard cannot evaluate the action, the action does not
	// proceed. This is the default (see DefaultFailMode).
	FailModeClosed FailMode = "closed"
)

type PIIPattern added in v1.2.0

type PIIPattern struct {
	Name   string         // e.g. "email"
	Regex  *regexp.Regexp // compiled detector
	Prefix string         // e.g. "EMAIL" → [EMAIL_1], [EMAIL_2]
}

PIIPattern is one PII detection rule.

type RedactionEntry added in v1.2.0

type RedactionEntry struct {
	Token    string // [EMAIL_1]
	Original string // john@acme.com
	Type     string // email
	Position int    // char offset in original text
}

RedactionEntry is one redacted span: token in redacted text + original PII value.

type RedactionResult added in v1.2.0

type RedactionResult struct {
	RedactedText   string
	Redactions     []RedactionEntry
	PIIDetected    bool
	RedactionCount int
}

RedactionResult is the outcome of RedactPII.

func RedactPII added in v1.2.0

func RedactPII(text string) RedactionResult

RedactPII redacts PII from text, replacing matches with indexed tokens ([EMAIL_1], [EMAIL_2], ...) and returning a reversible redaction map.

r := shrike.RedactPII("Email john@acme.com")
// r.RedactedText == "Email [EMAIL_1]"
// r.Redactions[0].Original == "john@acme.com"

type RetryConfig

type RetryConfig struct {
	// MaxAttempts is the maximum number of attempts (including the first).
	// Default: 3
	MaxAttempts int

	// InitialBackoff is the delay before the first retry.
	// Default: 200ms
	InitialBackoff time.Duration

	// MaxBackoff is the maximum delay between retries.
	// Default: 5s
	MaxBackoff time.Duration

	// Multiplier is the backoff multiplier between retries.
	// Default: 2.0
	Multiplier float64

	// IsRetryable determines whether an error should be retried.
	// Default: retries all errors except ErrCircuitOpen and ErrTooManyRequests
	IsRetryable func(error) bool
}

RetryConfig configures retry behavior with exponential backoff.

func DefaultRetryConfig

func DefaultRetryConfig() RetryConfig

DefaultRetryConfig returns sensible defaults.

type ScanError

type ScanError struct {
	ShrikeError
}

ScanError is returned when a scan operation fails and fail_mode is 'closed' (the default; fail-closed).

This error is returned when: - The Shrike API times out - A network error occurs - The API returns an unexpected error

When fail_mode is explicitly set to 'open', these errors are silently handled and the request is allowed to proceed (use this only when availability must outrank enforcement).

func NewScanError

func NewScanError(message string) *ScanError

NewScanError creates a new ScanError.

type ShrikeError

type ShrikeError struct {
	Message string
	Details map[string]interface{}
}

ShrikeError is the base error type for all Shrike SDK errors.

func (*ShrikeError) Error

func (e *ShrikeError) Error() string

type SyncPIIPatternsOptions added in v1.2.0

type SyncPIIPatternsOptions struct {
	// Endpoint is the Shrike backend base URL (e.g. https://api.shrikesecurity.com).
	// SyncPIIPatterns appends /api/pii/patterns.
	Endpoint string

	// APIKey is sent as "Authorization: Bearer <key>" when non-empty.
	// The endpoint is currently unauthenticated, but sending the key keeps
	// the client forward-compatible.
	APIKey string

	// Timeout is the HTTP timeout. Zero falls back to DefaultSyncTimeout.
	Timeout time.Duration

	// HTTPClient lets callers inject a custom *http.Client (for testing,
	// custom transports, instrumented round-trippers). Zero falls back to
	// a client with the configured Timeout.
	HTTPClient *http.Client
}

SyncPIIPatternsOptions configures a SyncPIIPatterns call.

Directories

Path Synopsis
Package anthropic provides a Shrike-protected Anthropic client wrapper.
Package anthropic provides a Shrike-protected Anthropic client wrapper.
Package api provides API clients for Shrike backend services.
Package api provides API clients for Shrike backend services.
examples
openai command
Example of using ShrikeOpenAI client.
Example of using ShrikeOpenAI client.
Package gemini provides a Shrike-protected Google Gemini client wrapper.
Package gemini provides a Shrike-protected Google Gemini client wrapper.
internal
testutil
Package testutil provides testing utilities for the Shrike SDK.
Package testutil provides testing utilities for the Shrike SDK.
Package openai provides a Shrike-protected OpenAI client wrapper.
Package openai provides a Shrike-protected OpenAI client wrapper.
Package pii provides client-side PII redaction and rehydration.
Package pii provides client-side PII redaction and rehydration.
Package scanner provides the HTTP client for the Shrike scan API.
Package scanner provides the HTTP client for the Shrike scan API.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL