@gebsecure01/sdk 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,64 @@
1
+ # Changelog — @gebsecure01/sdk
2
+
3
+ All notable changes to the TypeScript SDK. Format: [Keep a Changelog](https://keepachangelog.com/);
4
+ versioning: [SemVer](https://semver.org/) as described in [`../VERSIONING.md`](../VERSIONING.md).
5
+
6
+ ## [Unreleased]
7
+
8
+ ## [0.2.1] - 2026-10-01
9
+
10
+ Compatible with GebSecure API `v1` (gateway/api OpenAPI 0.1.0), same servers as 0.2.0. Conformance suite:
11
+ fixtures v1 incl. `verbs.json`, `runtime.json`, `admin.json` (110 scenarios; `execute.json` APPR-004…APPR-010).
12
+
13
+ ### Fixed
14
+ - `executeWithApproval()` no longer races the server. After the approval was granted it executed a second time with the
15
+ approval id, while the platform worker (`execution-resume`) resumes the stored execution itself and consumes
16
+ the single-use approval, so the helper failed nondeterministically (`ApprovalNotGranted` with status
17
+ `consumed`, `conflict` "Approval has already been used", or 400 "Request violates a data constraint"). It
18
+ now waits for the approval and then polls `getExecution` until the execution is terminal, and returns that
19
+ result (`replayed` set, approval and risk from the first response); it never executes twice. A `consumed`
20
+ approval counts as granted. Rejected, expired and cancelled approvals raise `ApprovalNotGrantedError`; an approved
21
+ execution that has not finished by the deadline raises `TimeoutError` (code `timeout`, status 0); a resumed
22
+ execution that fails is returned with `status: 'failed'`. The signature is unchanged.
23
+
24
+ ## [0.2.0] - 2026-09-30
25
+
26
+ Compatible with GebSecure API `v1` (gateway/api OpenAPI 0.1.0, including `/v1/inspect`, `/v1/dlp/scan`,
27
+ `/v1/traces/spans` and `/v1/simulations/run`). Conformance suite: fixtures v1 + `verbs`, `runtime`, `admin`.
28
+
29
+ ### Added
30
+ - HTTP verbs `PUT`, `PATCH`, `DELETE`; per-call `idempotencyKey` option (sent as `Idempotency-Key`,
31
+ makes the call retryable); `204` responses resolve to `undefined`.
32
+ - Runtime: `inspect`, `dlpScan`, `reportSpans`, `buildSpan`, `traceparentOf`, `runSimulation` with
33
+ `SimulationFailedError` (carries the typed run) for `failOnMismatch`.
34
+ - Session auth for CLIs: `login` (refresh token in the body), `refreshSession`, `logout`, `me`, and the
35
+ `unauthenticated()` provider.
36
+ - Management wrappers: policies (versions, diff, tests incl. `PUT` replace, deploy with 412 deploy
37
+ reports returned as results, rollback, simulate), agents and credentials, secrets (write-only values),
38
+ connectors and connections (OAuth, client-credentials and JWT-bearer installs, health), audit
39
+ (search with `afterSeq` tailing, export, verify), approvals (details, decide with snapshot hash),
40
+ alerts, traces and session replay.
41
+ - Typed models for all of the above (generated from the OpenAPI documents + `sdks/spec/overlay.json`).
42
+ - Examples: `inspect-and-trace.ts`, `policy-as-code.ts`.
43
+
44
+ ### Changed
45
+ - Retry classification follows the HTTP method: `PUT`/`DELETE` are idempotent (except `updatePolicy`,
46
+ which appends a version); `PATCH` and other `POST`s retry on 5xx/network errors only with an
47
+ idempotency key.
48
+
49
+ ## [0.1.0] - 2026-09-30
50
+
51
+ Compatible with GebSecure API `v1` (gateway/api OpenAPI 0.1.0). Conformance suite: fixtures v1.
52
+
53
+ ### Added
54
+ - `GebSecure` client: `authorize`, `authorizeBatch`, `guard`, `execute`, `getExecution`,
55
+ `listExecutions`, `cancelExecution`, `getApproval`, `waitForApproval`, `executeWithApproval`,
56
+ `listAgents`, `getAgent`, `listPolicies`, `listApprovals`, `createDelegation`, `withDelegation`,
57
+ `getAccessToken`.
58
+ - Authentication: API keys, static tokens, client secret, `private_key_jwt` (EdDSA/ES256/RS256 via
59
+ WebCrypto; PEM, JWK, CryptoKey or custom signer), delegation token exchange; cached single-flight
60
+ tokens with early refresh and one-shot 401 re-authentication.
61
+ - Retries with equal-jitter exponential backoff, `Retry-After`, idempotency rules and automatic
62
+ idempotency keys for `execute`; AbortSignal cancellation; per-attempt timeouts.
63
+ - Typed errors mapped from RFC 9457 problem+json; W3C `traceparent` propagation.
64
+ - Models generated from `docs/openapi` + `sdks/spec/overlay.json`.
package/README.md ADDED
@@ -0,0 +1,188 @@
1
+ # @gebsecure01/sdk — GebSecure TypeScript / JavaScript SDK
2
+
3
+ Official client for the GebSecure AI Agent Security & Governance Platform: authorize agent actions,
4
+ execute them through the secure runtime, handle human approvals and manage agents — with typed models,
5
+ automatic authentication, retries and typed errors.
6
+
7
+ - Runs on Node.js ≥ 20, Deno, Bun, Cloudflare Workers and other runtimes with `fetch` + WebCrypto.
8
+ - ESM and CommonJS builds with bundled type declarations; zero runtime dependencies.
9
+ - Behaviour is specified by the cross-SDK [conformance plan](../conformance/README.md) and identical to
10
+ the Python, Go, Java and .NET SDKs.
11
+
12
+ ```sh
13
+ npm install @gebsecure01/sdk
14
+ ```
15
+
16
+ ## Quick start
17
+
18
+ ```ts
19
+ import { GebSecure } from '@gebsecure01/sdk';
20
+
21
+ const gs = new GebSecure({ apiKey: process.env.GEBSECURE_API_KEY });
22
+
23
+ const { allowed, decision } = await gs.guard('refunds:create', 'stripe:charge/ch_123', { amount: 250 });
24
+ if (allowed) {
25
+ // perform the action
26
+ } else if (decision.decision === 'APPROVAL_REQUIRED') {
27
+ console.log('Needs approval:', decision.approval?.url);
28
+ } else {
29
+ console.log('Denied:', decision.reason);
30
+ }
31
+ ```
32
+
33
+ ## Configuration
34
+
35
+ | Option | Default | Notes |
36
+ | ------ | ------- | ----- |
37
+ | `gatewayUrl` | `GEBSECURE_GATEWAY_URL` or `https://gateway.gebsecure.dev` | Data plane: authorize, execute, executions, approval polling |
38
+ | `apiUrl` | `GEBSECURE_API_URL` or `https://api.gebsecure.dev` | Control plane and token endpoint |
39
+ | `auth` / `apiKey` | `GEBSECURE_API_KEY`, then `GEBSECURE_CLIENT_SECRET` | See below |
40
+ | `maxRetries` | `3` | `0` disables retries and automatic idempotency keys |
41
+ | `timeoutMs` | `30000` | Per attempt |
42
+ | `baseDelayMs` / `maxDelayMs` | `500` / `8000` | Equal-jitter exponential backoff |
43
+ | `maxRetryAfterMs` | `60000` | Longer `Retry-After` values are raised immediately |
44
+ | `fetch`, `clock`, `random` | globals | Injection points for tests and custom transports |
45
+
46
+ Every method takes `RequestOptions`: `{ signal, traceparent, timeoutMs, maxRetries, headers, idempotencyKey }`.
47
+
48
+ ## Authentication
49
+
50
+ ```ts
51
+ import { GebSecure, apiKey, clientSecret, privateKeyJwt, delegation, staticToken } from '@gebsecure01/sdk';
52
+
53
+ new GebSecure({ auth: apiKey('gsk_…') }); // server-side automation
54
+ new GebSecure({ auth: clientSecret({ clientSecret: 'gsa_…', scope: 'authorize execute' }) });
55
+ new GebSecure({ auth: privateKeyJwt({ credentialId: 'cred_…', privateKey: pemOrJwk }) }); // Ed25519, ES256, RS256
56
+ new GebSecure({ auth: delegation({ subjectToken: 'gsd_…', actor: clientSecret({ clientSecret: 'gsa_…' }) }) });
57
+ new GebSecure({ auth: staticToken(accessToken) });
58
+ new GebSecure({ auth: unauthenticated() }); // only login() / refreshSession()
59
+ ```
60
+
61
+ - OAuth tokens are cached and refreshed `min(60 s, expires_in/2)` before expiry; concurrent calls share a
62
+ single token request. A `401` with a cached token triggers one transparent re-authentication.
63
+ - `private_key_jwt` assertions (RFC 7523) are signed with WebCrypto: `iss = sub = kid = credentialId`,
64
+ `aud = {apiUrl}/v1/auth/token` (override with `audience`), 60 s lifetime (≤ 300), unique `jti` per
65
+ attempt. Keys: PKCS#8 PEM, private JWK, a `CryptoKey`, or a custom `signer` (KMS/HSM).
66
+ - `gs.withDelegation(gsdToken)` returns a client that exchanges the delegation token using the current
67
+ client's credentials as the actor.
68
+
69
+ ### User sessions (CLIs, CI)
70
+
71
+ ```ts
72
+ const session = await new GebSecure({ auth: unauthenticated() }).login({ email, password });
73
+ // session.refreshToken is returned in the body (refreshTokenDelivery: 'body'); store it securely.
74
+ const gs = new GebSecure({ auth: staticToken(session.accessToken) });
75
+ const me = await gs.me();
76
+ const next = await new GebSecure({ auth: unauthenticated() }).refreshSession(session.refreshToken!); // rotates: store next.refreshToken
77
+ await gs.logout();
78
+ ```
79
+
80
+ `refreshSession` is never retried on 5xx/network errors (a replayed refresh token revokes the session
81
+ family). Passwords, refresh tokens and secret values are never logged or included in error messages.
82
+
83
+ ## Operations
84
+
85
+ | Method | Endpoint |
86
+ | ------ | -------- |
87
+ | `authorize(req)` / `authorizeBatch(req)` | `POST {gateway}/v1/authorize[/batch]` |
88
+ | `guard(action, resource, context?)` | `authorize` → `{ allowed, decision }` |
89
+ | `execute(req)` | `POST {gateway}/v1/execute` → `ExecuteResult` (denied/failed are results) |
90
+ | `getExecution(id)` / `listExecutions()` / `cancelExecution(id)` | `{gateway}/v1/executions…` |
91
+ | `getApproval(id)` / `waitForApproval(id, { timeoutMs, pollIntervalMs })` | `GET {gateway}/v1/approvals/{id}` |
92
+ | `executeWithApproval(req, { timeoutMs, pollIntervalMs })` | execute → wait for approval → poll the execution the server resumes (never re-executes) |
93
+ | `listAgents()` / `getAgent(id)` / `listPolicies()` / `listApprovals()` | `{api}/v1/…` |
94
+ | `createDelegation(req)` | `POST {api}/v1/delegations` |
95
+ | `getAccessToken()` | current access token for APIs not wrapped by the SDK |
96
+
97
+ ### Runtime protection (agents)
98
+
99
+ | Method | Endpoint |
100
+ | ------ | -------- |
101
+ | `inspect({ content, source, origin?, dlp? })` | `POST {gateway}/v1/inspect` → `InspectResult`: injection `score`/`level`/`action`/`findings`, sanitized `content` (null when blocked), inbound `dlp` |
102
+ | `dlpScan({ content, direction, dryRun? })` | `POST {gateway}/v1/dlp/scan` → `DlpScanResult` (masked findings, transformed content) |
103
+ | `reportSpans(spans)` + `buildSpan()` / `traceparentOf()` | `POST {gateway}/v1/traces/spans` — agent spans joined to the platform trace |
104
+ | `runSimulation(req)` | `POST {api}/v1/simulations/run` → `SimulationRun`; `failOnMismatch: true` throws `SimulationFailedError` with `run` |
105
+
106
+ ```ts
107
+ const traceparent = '00-<trace id>-<span id>-01'; // your current trace
108
+ const r = await gs.inspect({ content: webPage, source: 'web', origin: url }, { traceparent });
109
+ if (r.action === 'BLOCK') throw new Error(`injection ${r.injection.level}`);
110
+ const span = buildSpan('llm.plan', startedAt, Date.now(), { traceparent, attributes: { model: 'x' } });
111
+ await gs.authorize({ action, resource }, { traceparent: traceparentOf(span) }); // child of the agent span
112
+ await gs.reportSpans([span]);
113
+ ```
114
+
115
+ ### Management (control plane)
116
+
117
+ | Area | Methods |
118
+ | ---- | ------- |
119
+ | Session | `login`, `refreshSession`, `logout`, `me` |
120
+ | 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` |
121
+ | Agents | `createAgent`, `listAgents`, `getAgent`, `updateAgent`, `setAgentStatus`, `deleteAgent`, `listAgentCredentials`, `createAgentCredential`, `rotateCredential`, `revokeCredential` |
122
+ | Secrets | `createSecret`, `listSecrets`, `getSecret`, `updateSecret`, `rotateSecret`, `revokeSecret`, `deleteSecret` — values are write-only |
123
+ | Connectors | `listConnectors`, `getConnector`, `listConnections`, `getConnection`, `createConnection`, `updateConnection`, `deleteConnection`, `checkConnectionHealth`, `startConnectionOAuth`, `completeConnectionOAuth`, `installClientCredentials`, `installJwtBearer` |
124
+ | Audit | `searchAudit` (`afterSeq` tails new events oldest-first), `getAuditEvent`, `exportAudit` (raw ndjson/csv/json), `verifyAudit` |
125
+ | Approvals | `listApprovals`, `getApprovalDetails`, `decideApproval` (with the reviewed `snapshotHash`) |
126
+ | Alerts | `listAlerts`, `getAlert`, `updateAlert` |
127
+ | Traces | `searchTraces`, `getTrace`, `replaySession` |
128
+
129
+ ```ts
130
+ // Tail the audit log
131
+ let after = (await gs.searchAudit({ limit: 1 })).data[0]?.seq ?? 0;
132
+ for (;;) {
133
+ const page = await gs.searchAudit({ afterSeq: after, limit: 500 });
134
+ for (const e of page.data) console.log(e.seq, e.action, e.outcome);
135
+ after = page.data.at(-1)?.seq ?? after;
136
+ await new Promise((r) => setTimeout(r, 2000));
137
+ }
138
+ ```
139
+
140
+ ## Retries and idempotency
141
+
142
+ - `429` is retried for every request (honouring `Retry-After`); `502/503/504`, network errors and
143
+ timeouts are retried only for idempotent requests: GETs, PUTs and DELETEs (except `updatePolicy`, which
144
+ appends a version), token requests, `dryRun` authorizations and DLP scans, span reports, cancels,
145
+ evaluation-only calls (validate/simulate/test runs/audit verify/health checks), and `execute` with an
146
+ `idempotencyKey`.
147
+ - PATCH and other POSTs are retried on 5xx/network errors only when you pass
148
+ `{ idempotencyKey }` (sent as the `Idempotency-Key` header) — you assert the call is safe to repeat.
149
+ - With retries enabled, `execute()` adds an `idempotencyKey` (`sdk-<uuid>`) when you don't pass one, so
150
+ a retried execution never runs twice. `executeWithApproval()` always uses one.
151
+ - A `502/504` whose body is an `ExecuteResult` (the connector failed) is returned, not retried.
152
+ - Cancel any call with an `AbortSignal`; in-flight requests and backoff sleeps stop immediately.
153
+
154
+ ## Errors
155
+
156
+ All errors extend `GebSecureError` and expose `status`, `code`, `detail`, `requestId`, `traceId`,
157
+ `details` and `type`:
158
+
159
+ `AuthenticationError`, `PermissionDeniedError`, `PolicyDeniedError`, `ApprovalRequiredError`,
160
+ `ValidationError`, `RateLimitError` (`retryAfterMs`), `NotFoundError`, `ConflictError`, `UpstreamError`,
161
+ `TimeoutError`, `UnavailableError`, `InternalError`, `ApiError` (other codes), `ConnectionError`,
162
+ `ApprovalTimeoutError`, `ApprovalNotGrantedError`, `SimulationFailedError` (`run`), `ConfigurationError`.
163
+
164
+ ## Tracing
165
+
166
+ Each call sends a W3C `traceparent`; pass `{ traceparent }` to join your current trace. Retries keep the
167
+ trace id. Errors carry the server's `requestId` and `traceId`. Agents report their own spans with
168
+ `reportSpans()`; `buildSpan(name, start, end, { traceparent })` creates a child of the current span and
169
+ `traceparentOf(span)` propagates it to subsequent calls.
170
+
171
+ ## Examples
172
+
173
+ See [`examples/`](./examples): authorize-then-act, execute with approval, private_key_jwt,
174
+ delegation exchange, inspect-and-trace (inspection + agent spans), policy-as-code (session login, tests,
175
+ simulation gate, deploy).
176
+
177
+ ## Development
178
+
179
+ ```sh
180
+ npm install # from the repository root
181
+ npm run test -w @gebsecure01/sdk # unit + conformance tests (vitest)
182
+ npm run build -w @gebsecure01/sdk # dist/: ESM, CJS, .d.ts
183
+ GEBSECURE_LIVE_TEST=1 GEBSECURE_CLIENT_SECRET=gsa_… GEBSECURE_ENVIRONMENT_ID=env_… \
184
+ GEBSECURE_LIVE_EMAIL=… GEBSECURE_LIVE_PASSWORD=… npm run test -w @gebsecure01/sdk # optional live tests (conformance §9)
185
+ node sdks/scripts/generate-models.mjs # regenerate src/generated/models.ts from the OpenAPI specs
186
+ ```
187
+
188
+ Versioning and releases: see [`../VERSIONING.md`](../VERSIONING.md) and [`CHANGELOG.md`](./CHANGELOG.md).