
Security News
Lovable’s OJ Rewrites Vite’s Dev Server in Rust as AI Lowers the Cost of Forking Open Source
Lovable’s OJ rewrites Vite’s dev server in Rust, reducing memory use and preview times as AI lowers the cost of open source reimplementation.
@fidacy/sdk
Advanced tools
Thin, typed client for the public Fidacy API. Bundles @fidacy/verify so you can check every signed verdict yourself.
A thin, typed client for the public Fidacy API. It ships @fidacy/verify alongside it, so the verdict you get back is one call away from being independently verified.
Fidacy returns a signed verdict for an agent payment. The point of the SDK is not to make you trust that verdict: it is to get it, and hand you the tool to check the signature yourself.
npm i @fidacy/sdk
import { Fidacy } from '@fidacy/sdk';
const fidacy = new Fidacy({ apiKey: process.env.FIDACY_API_KEY! }); // fky_test_… or fky_live_…
const result = await fidacy.assess({
mandate: {
vct: 'mandate.payment.1',
payee: { id: 'merchant_demo', name: 'Demo Store' },
payment_amount: { amount: 4299, currency: 'EUR' },
payment_instrument: { id: 'pi_demo', type: 'card' },
},
});
console.log(result.decision); // 'approve' | 'review' | 'deny'
console.log(result.score); // 0..100
// Don't trust the response object — verify the signed payload yourself.
const verified = await fidacy.verify(result.riskPayloadJws);
console.log('signature valid:', verified.valid);
console.log('decisions match:', verified.claims.decision === result.decision);
fidacy.verify is @fidacy/verify's verifyRiskPayload, bundled so you don't add a second dependency. The assess call itself does no verification: it returns the API's response as-is, and you decide whether to trust it by checking the signature against Fidacy's public JWKS.
The verdict is action-generic. kind (default 'ap2_payment') accepts every action the engine assesses: 'ap2_payment' | 'message_send' | 'voice_call' | 'claim_document' | 'custom' (the exported AssessKind type). An agent sending a customer message, for example:
const verdict = await fidacy.assess({
kind: 'message_send',
mandate: {
kind: 'message_send',
actor_agent: 'did:web:agents.example.com:support-1',
principal: 'org:example',
channel: 'email', // 'whatsapp' | 'email' | 'sms'
recipient_ref: 'cust_8f31', // pseudonymized ref — never a raw address
content_hash: 'sha256-9b2f…', // hash only — the message never leaves you
requested_at: Math.floor(Date.now() / 1000), // epoch seconds
},
});
// verdict.riskPayloadJws is the signed, independently verifiable record
// that this send was assessed before it happened.
Each kind validates against its public JSON schema on the engine side; the payment path (ap2_payment) is unchanged and remains the default.
assess returnsinterface AssessResult {
decision: 'approve' | 'review' | 'deny';
score: number; // 0..100
assessmentId: string;
riskPayloadJws: string; // the signed verdict — pass to fidacy.verify
signingKeyId: string;
signals: Record<string, unknown>;
outcome: Record<string, unknown>;
spend_guard?: Record<string, unknown>;
a2a?: { recommended_task_state: string; task_metadata: Record<string, unknown> };
}
Webhook events are verified for you. constructEvent checks the signature before returning, and throws if it does not hold.
const event = await fidacy.webhooks.constructEvent(
rawBody,
req.headers['x-fidacy-signature'],
);
// event.type, event.data — only reached on a valid signature.
const status = await fidacy.billing.get();
const { url } = await fidacy.billing.checkout({ tier: 'growth' });
A non-2xx response throws FidacyError. The message is static and never includes your key or the request body.
import { FidacyError } from '@fidacy/sdk';
try {
await fidacy.assess({ mandate });
} catch (err) {
if (err instanceof FidacyError) {
console.error(err.type, err.status, err.rejection_reasons);
} else {
throw err;
}
}
new Fidacy({
apiKey, // required, sent as a Bearer token
baseUrl, // default 'https://api.fidacy.com'
timeoutMs, // per-request, default 10000
maxRetries, // idempotent calls only, default 2
fetch, // inject a fetch implementation
});
Retries apply only when you pass an idempotencyKey to assess, so a retried call can never double-charge or duplicate.
assess produces a signed risk verdict. actionMandates is the stricter path
for an action that changes the world: it creates bounded authority, then issues
a short-lived grant for one exact request. The executor keeps the business data
and credential; Fidacy receives only the action, resource, and a SHA-256 hash of
the local context.
import { Fidacy, hashActionContext } from '@fidacy/sdk';
const fidacy = new Fidacy({ apiKey: process.env.FIDACY_API_KEY! });
const mandate = await fidacy.actionMandates.create({
subject: 'support-refund-agent',
version: 'fidacy.action-mandate.v1',
allow: {
actions: ['stripe.refund.create'],
resources: ['stripe:payment_intent:pi_123'],
maxActions: 1,
maxDelegationDepth: 0,
},
window: {
notBefore: new Date().toISOString(),
notAfter: new Date(Date.now() + 15 * 60_000).toISOString(),
},
});
const localRefund = { paymentIntentId: 'pi_123', amount: 1234 };
const contextHash = await hashActionContext(localRefund);
const result = await fidacy.actionMandates.decide(mandate.id, {
action: 'stripe.refund.create',
resource: 'stripe:payment_intent:pi_123',
contextHash,
});
if (!result.grant) throw new Error(`Refund refused: ${result.violated_rule}`);
// Give result.grant to a Fidacy-enforcing executor. It must verify the grant,
// redeem it once, then and only then call Stripe.
Both ALLOW and DENY return a signed receipt. Operators can list decisions through
fidacy.actionDecisions.list() and export independently verifiable evidence with
fidacy.actionDecisions.incidentPack(decisionId).
Apache-2.0. Part of fidacy-open.
FAQs
Thin, typed client for the public Fidacy API. Bundles @fidacy/verify so you can check every signed verdict yourself.
The npm package @fidacy/sdk receives a total of 17 weekly downloads. As such, @fidacy/sdk popularity was classified as not popular.
We found that @fidacy/sdk demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Security News
Lovable’s OJ rewrites Vite’s dev server in Rust, reducing memory use and preview times as AI lowers the cost of open source reimplementation.

Security News
It has been one year since Shai-Hulud made its first appearance on npm.

Research
/Security News
Operators behind PolinRider used a compromised GitHub account to plant malware in four development versions of a Packagist package with 700,000+ downloads.