@gebsecure01/sdk
v0.2.2
Published
Official TypeScript/JavaScript SDK for the GebSecure AI Agent Security & Governance Platform
Maintainers
Readme
@gebsecure01/sdk — GebSecure TypeScript / JavaScript SDK
Official client for the GebSecure AI Agent Security & Governance Platform: authorize agent actions, execute them through the secure runtime, handle human approvals and manage agents — with typed models, automatic authentication, retries and typed errors.
- Runs on Node.js ≥ 20, Deno, Bun, Cloudflare Workers and other runtimes with
fetch+ WebCrypto. - ESM and CommonJS builds with bundled type declarations; zero runtime dependencies.
- Behaviour is specified by the cross-SDK conformance plan and identical to the Python, Go, Java and .NET SDKs.
npm install @gebsecure01/sdkQuick start
import { GebSecure } from '@gebsecure01/sdk';
const gs = new GebSecure({ apiKey: process.env.GEBSECURE_API_KEY });
const { allowed, decision } = await gs.guard('refunds:create', 'stripe:charge/ch_123', { amount: 250 });
if (allowed) {
// perform the action
} else if (decision.decision === 'APPROVAL_REQUIRED') {
console.log('Needs approval:', decision.approval?.url);
} else {
console.log('Denied:', decision.reason);
}Configuration
| Option | Default | Notes |
| ------ | ------- | ----- |
| gatewayUrl | GEBSECURE_GATEWAY_URL or https://gateway.gebsecure.com | Data plane: authorize, execute, executions, approval polling |
| apiUrl | GEBSECURE_API_URL or https://api.gebsecure.com | Control plane and token endpoint |
| auth / apiKey | GEBSECURE_API_KEY, then GEBSECURE_CLIENT_SECRET | See below |
| maxRetries | 3 | 0 disables retries and automatic idempotency keys |
| timeoutMs | 30000 | Per attempt |
| baseDelayMs / maxDelayMs | 500 / 8000 | Equal-jitter exponential backoff |
| maxRetryAfterMs | 60000 | Longer Retry-After values are raised immediately |
| fetch, clock, random | globals | Injection points for tests and custom transports |
Every method takes RequestOptions: { signal, traceparent, timeoutMs, maxRetries, headers, idempotencyKey }.
Authentication
import { GebSecure, apiKey, clientSecret, privateKeyJwt, delegation, staticToken } from '@gebsecure01/sdk';
new GebSecure({ auth: apiKey('gsk_…') }); // server-side automation
new GebSecure({ auth: clientSecret({ clientSecret: 'gsa_…', scope: 'authorize execute' }) });
new GebSecure({ auth: privateKeyJwt({ credentialId: 'cred_…', privateKey: pemOrJwk }) }); // Ed25519, ES256, RS256
new GebSecure({ auth: delegation({ subjectToken: 'gsd_…', actor: clientSecret({ clientSecret: 'gsa_…' }) }) });
new GebSecure({ auth: staticToken(accessToken) });
new GebSecure({ auth: unauthenticated() }); // only login() / refreshSession()- OAuth tokens are cached and refreshed
min(60 s, expires_in/2)before expiry; concurrent calls share a single token request. A401with a cached token triggers one transparent re-authentication. private_key_jwtassertions (RFC 7523) are signed with WebCrypto:iss = sub = kid = credentialId,aud = {apiUrl}/v1/auth/token(override withaudience), 60 s lifetime (≤ 300), uniquejtiper attempt. Keys: PKCS#8 PEM, private JWK, aCryptoKey, or a customsigner(KMS/HSM).gs.withDelegation(gsdToken)returns a client that exchanges the delegation token using the current client's credentials as the actor.
User sessions (CLIs, CI)
const session = await new GebSecure({ auth: unauthenticated() }).login({ email, password });
// session.refreshToken is returned in the body (refreshTokenDelivery: 'body'); store it securely.
const gs = new GebSecure({ auth: staticToken(session.accessToken) });
const me = await gs.me();
const next = await new GebSecure({ auth: unauthenticated() }).refreshSession(session.refreshToken!); // rotates: store next.refreshToken
await gs.logout();refreshSession is never retried on 5xx/network errors (a replayed refresh token revokes the session
family). Passwords, refresh tokens and secret values are never logged or included in error messages.
Operations
| Method | Endpoint |
| ------ | -------- |
| authorize(req) / authorizeBatch(req) | POST {gateway}/v1/authorize[/batch] |
| guard(action, resource, context?) | authorize → { allowed, decision } |
| execute(req) | POST {gateway}/v1/execute → ExecuteResult (denied/failed are results) |
| getExecution(id) / listExecutions() / cancelExecution(id) | {gateway}/v1/executions… |
| getApproval(id) / waitForApproval(id, { timeoutMs, pollIntervalMs }) | GET {gateway}/v1/approvals/{id} |
| executeWithApproval(req, { timeoutMs, pollIntervalMs }) | execute → wait for approval → poll the execution the server resumes (never re-executes) |
| listAgents() / getAgent(id) / listPolicies() / listApprovals() | {api}/v1/… |
| createDelegation(req) | POST {api}/v1/delegations |
| getAccessToken() | current access token for APIs not wrapped by the SDK |
Runtime protection (agents)
| Method | Endpoint |
| ------ | -------- |
| inspect({ content, source, origin?, dlp? }) | POST {gateway}/v1/inspect → InspectResult: injection score/level/action/findings, sanitized content (null when blocked), inbound dlp |
| dlpScan({ content, direction, dryRun? }) | POST {gateway}/v1/dlp/scan → DlpScanResult (masked findings, transformed content) |
| reportSpans(spans) + buildSpan() / traceparentOf() | POST {gateway}/v1/traces/spans — agent spans joined to the platform trace |
| runSimulation(req) | POST {api}/v1/simulations/run → SimulationRun; failOnMismatch: true throws SimulationFailedError with run |
const traceparent = '00-<trace id>-<span id>-01'; // your current trace
const r = await gs.inspect({ content: webPage, source: 'web', origin: url }, { traceparent });
if (r.action === 'BLOCK') throw new Error(`injection ${r.injection.level}`);
const span = buildSpan('llm.plan', startedAt, Date.now(), { traceparent, attributes: { model: 'x' } });
await gs.authorize({ action, resource }, { traceparent: traceparentOf(span) }); // child of the agent span
await gs.reportSpans([span]);Management (control plane)
| Area | Methods |
| ---- | ------- |
| Session | login, refreshSession, logout, me |
| Policies | listPolicies, getPolicy, createPolicy, updatePolicy (PUT, new version), deletePolicy, validatePolicy, getPolicyVersion, diffPolicyVersions, listPolicyDeployments, deployPolicy (a 412 deploy report returns deployed: false), rollbackPolicy, addPolicyTest, replacePolicyTests (PUT), deletePolicyTest, runPolicyTests, simulatePolicies |
| Agents | createAgent, listAgents, getAgent, updateAgent, setAgentStatus, deleteAgent, listAgentCredentials, createAgentCredential, rotateCredential, revokeCredential |
| Secrets | createSecret, listSecrets, getSecret, updateSecret, rotateSecret, revokeSecret, deleteSecret — values are write-only |
| Connectors | listConnectors, getConnector, listConnections, getConnection, createConnection, updateConnection, deleteConnection, checkConnectionHealth, startConnectionOAuth, completeConnectionOAuth, installClientCredentials, installJwtBearer |
| Audit | searchAudit (afterSeq tails new events oldest-first), getAuditEvent, exportAudit (raw ndjson/csv/json), verifyAudit |
| Approvals | listApprovals, getApprovalDetails, decideApproval (with the reviewed snapshotHash) |
| Alerts | listAlerts, getAlert, updateAlert |
| Traces | searchTraces, getTrace, replaySession |
// Tail the audit log
let after = (await gs.searchAudit({ limit: 1 })).data[0]?.seq ?? 0;
for (;;) {
const page = await gs.searchAudit({ afterSeq: after, limit: 500 });
for (const e of page.data) console.log(e.seq, e.action, e.outcome);
after = page.data.at(-1)?.seq ?? after;
await new Promise((r) => setTimeout(r, 2000));
}Retries and idempotency
429is retried for every request (honouringRetry-After);502/503/504, network errors and timeouts are retried only for idempotent requests: GETs, PUTs and DELETEs (exceptupdatePolicy, which appends a version), token requests,dryRunauthorizations and DLP scans, span reports, cancels, evaluation-only calls (validate/simulate/test runs/audit verify/health checks), andexecutewith anidempotencyKey.- PATCH and other POSTs are retried on 5xx/network errors only when you pass
{ idempotencyKey }(sent as theIdempotency-Keyheader) — you assert the call is safe to repeat. - With retries enabled,
execute()adds anidempotencyKey(sdk-<uuid>) when you don't pass one, so a retried execution never runs twice.executeWithApproval()always uses one. - A
502/504whose body is anExecuteResult(the connector failed) is returned, not retried. - Cancel any call with an
AbortSignal; in-flight requests and backoff sleeps stop immediately.
Errors
All errors extend GebSecureError and expose status, code, detail, requestId, traceId,
details and type:
AuthenticationError, PermissionDeniedError, PolicyDeniedError, ApprovalRequiredError,
ValidationError, RateLimitError (retryAfterMs), NotFoundError, ConflictError, UpstreamError,
TimeoutError, UnavailableError, InternalError, ApiError (other codes), ConnectionError,
ApprovalTimeoutError, ApprovalNotGrantedError, SimulationFailedError (run), ConfigurationError.
Tracing
Each call sends a W3C traceparent; pass { traceparent } to join your current trace. Retries keep the
trace id. Errors carry the server's requestId and traceId. Agents report their own spans with
reportSpans(); buildSpan(name, start, end, { traceparent }) creates a child of the current span and
traceparentOf(span) propagates it to subsequent calls.
Examples
See examples/: authorize-then-act, execute with approval, private_key_jwt,
delegation exchange, inspect-and-trace (inspection + agent spans), policy-as-code (session login, tests,
simulation gate, deploy).
Development
npm install # from the repository root
npm run test -w @gebsecure01/sdk # unit + conformance tests (vitest)
npm run build -w @gebsecure01/sdk # dist/: ESM, CJS, .d.ts
GEBSECURE_LIVE_TEST=1 GEBSECURE_CLIENT_SECRET=gsa_… GEBSECURE_ENVIRONMENT_ID=env_… \
GEBSECURE_LIVE_EMAIL=… GEBSECURE_LIVE_PASSWORD=… npm run test -w @gebsecure01/sdk # optional live tests (conformance §9)
node sdks/scripts/generate-models.mjs # regenerate src/generated/models.ts from the OpenAPI specsVersioning and releases: see ../VERSIONING.md and CHANGELOG.md.
