scopeblind
v1.3.0
Published
Machine access control middleware with signed decision receipts. Configurable identity disclosure — Private, Scoped, or Named. Ed25519-signed, independently verifiable.
Downloads
67
Maintainers
Keywords
Readme
ScopeBlind
Signed receipts for machine decisions. You choose what identity goes in.
- Signed decision receipts — Ed25519-signed, independently verifiable, exportable
- Three disclosure modes — Private (unlinkable), Scoped (pseudonymous), Named (attributed)
- No PII stored — cryptographic proofs, not fingerprinting
- ~20ms latency — runs at the edge on Cloudflare
- AI agent compatible — works with browsers, AI agents, and MCP servers
For MCP servers: Use protect-mcp instead — trust-tier gating, credential vault, signed receipts, per-tool policies.
npx protect-mcp -- node your-server.js
When to Use ScopeBlind
Use ScopeBlind if your project needs:
- Signed evidence of machine access decisions (who was allowed, denied, challenged)
- Configurable identity disclosure (from fully private to fully named)
- Agent-compatible access control without CAPTCHAs
- Protection for API endpoints, MCP tool servers, or AI agent-facing services
- Audit-ready exports with independently verifiable signatures
Quick Start
npm install scopeblind1. Get a slug
curl -X POST https://api.scopeblind.com/provision \
-H "Content-Type: application/json" \
-d '{"target_url": "https://yourapp.com/api/signup", "email": "[email protected]"}'Or programmatically:
import { provision } from 'scopeblind';
const tenant = await provision({
targetUrl: 'https://yourapp.com/api/signup',
email: '[email protected]',
});
console.log(tenant.slug); // 'a1b2c3d4e5f6'
console.log(tenant.scriptTag); // '<script async src="https://api.scopeblind.com/sb/a1b2c3d4e5f6.js"></script>'
console.log(tenant.dashboardUrl); // 'https://scopeblind.com/t/a1b2c3d4e5f6'Save the mgmtToken — it's shown only once.
2. Add the client script
Add this to your HTML <head>:
<script async src="https://api.scopeblind.com/sb/{slug}.js"></script>The script runs silently — no UI, no popup, no CAPTCHA.
3. Add the middleware
import express from 'express';
import { scopeblind } from 'scopeblind';
const app = express();
// Block unverified devices on signup
app.post('/api/signup', scopeblind(), (req, res) => {
// req.scopeblind.verified === true
// req.scopeblind.deviceId === unique non-PII device hash
res.json({ ok: true });
});
// Flag but allow (for monitoring before enforcement)
app.post('/api/action', scopeblind({ onFail: 'flag' }), (req, res) => {
if (!req.scopeblind.verified) {
console.log('Unverified device detected');
}
res.json({ ok: true });
});API
scopeblind(options?)
Express middleware for device verification.
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| onFail | 'block' \| 'flag' \| 'allow' | 'block' | What to do when verification fails |
| cookieName | string | 'sb_pass' | Cookie name for the JWT |
| headerName | string | 'x-scopeblind-token' | Header name fallback |
| jwksUrl | string | ScopeBlind production | Custom JWKS endpoint |
| errorBody | object | { error: 'device_not_verified' } | Custom 403 response body |
After verification, req.scopeblind contains:
{
verified: boolean; // Whether the device proof is valid
deviceId: string | null; // Unique non-PII device hash
payload: JWTPayload; // Full JWT claims
}verify(token, options?)
Standalone JWT verification (non-Express):
import { verify } from 'scopeblind';
const result = await verify(tokenString);
if (result.verified) {
console.log('Device:', result.deviceId);
}provision(options)
Create a new tenant programmatically:
import { provision } from 'scopeblind';
const tenant = await provision({
targetUrl: 'https://yourapp.com/api/signup',
email: '[email protected]',
});Next.js
// app/api/signup/route.ts
import { verify } from 'scopeblind';
import { cookies } from 'next/headers';
export async function POST(request: Request) {
const cookieStore = await cookies();
const token = cookieStore.get('sb_pass')?.value;
if (!token) {
return Response.json({ error: 'device_not_verified' }, { status: 403 });
}
const result = await verify(token);
if (!result.verified) {
return Response.json({ error: 'invalid_proof' }, { status: 403 });
}
// result.deviceId = unique device hash (not PII)
// ... handle the signup
}How It Works
- Client completes a privacy-preserving proof (RFC 9497) — invisible to the user
- ScopeBlind's edge verifier issues a signed JWT and decision receipt
- Your backend verifies the JWT using this package — every decision is independently verifiable
- Enforcement decisions produce signed receipts with configurable identity disclosure
Dashboard
After deploying, visit https://scopeblind.com/t/{slug} to see:
- Unique visitors vs. repeat abusers
- Abuse rate percentage
- Estimated wasted compute costs
- One-click enforcement toggle
ScopeBlind starts in observe mode (observe only). Enable enforcement when ready.
Links
Related
- protect-mcp — If you're securing an MCP tool server (not a web API), use protect-mcp instead. Wraps any stdio MCP server with per-tool policies, rate limiting, and structured decision logs. Zero dependencies, no account required.
- scopeblind-agent — DPoP-based cryptographic identity for AI agents and CLIs.
License
MIT
